Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * TerraTec Cinergy T2/qanu USB2 DVB-T adapter.
0004  *
0005  * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi)
0006  *
0007  * Based on the dvb-usb-framework code and the
0008  * original Terratec Cinergy T2 driver by:
0009  *
0010  * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and
0011  *          Holger Waechtler <holger@qanu.de>
0012  *
0013  *  Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf
0014  */
0015 
0016 #include "cinergyT2.h"
0017 
0018 
0019 /* debug */
0020 int dvb_usb_cinergyt2_debug;
0021 
0022 module_param_named(debug, dvb_usb_cinergyt2_debug, int, 0644);
0023 MODULE_PARM_DESC(debug, "set debugging level (1=info, xfer=2, rc=4 (or-able)).");
0024 
0025 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
0026 
0027 struct cinergyt2_state {
0028     u8 rc_counter;
0029     unsigned char data[64];
0030 };
0031 
0032 /* Forward declaration */
0033 static const struct dvb_usb_device_properties cinergyt2_properties;
0034 
0035 static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable)
0036 {
0037     struct dvb_usb_device *d = adap->dev;
0038     struct cinergyt2_state *st = d->priv;
0039     int ret;
0040 
0041     mutex_lock(&d->data_mutex);
0042     st->data[0] = CINERGYT2_EP1_CONTROL_STREAM_TRANSFER;
0043     st->data[1] = enable ? 1 : 0;
0044 
0045     ret = dvb_usb_generic_rw(d, st->data, 2, st->data, 64, 0);
0046     mutex_unlock(&d->data_mutex);
0047 
0048     return ret;
0049 }
0050 
0051 static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable)
0052 {
0053     struct cinergyt2_state *st = d->priv;
0054     int ret;
0055 
0056     mutex_lock(&d->data_mutex);
0057     st->data[0] = CINERGYT2_EP1_SLEEP_MODE;
0058     st->data[1] = enable ? 0 : 1;
0059 
0060     ret = dvb_usb_generic_rw(d, st->data, 2, st->data, 3, 0);
0061     mutex_unlock(&d->data_mutex);
0062 
0063     return ret;
0064 }
0065 
0066 static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
0067 {
0068     struct dvb_usb_device *d = adap->dev;
0069     struct cinergyt2_state *st = d->priv;
0070     int ret;
0071 
0072     adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev);
0073 
0074     mutex_lock(&d->data_mutex);
0075     st->data[0] = CINERGYT2_EP1_GET_FIRMWARE_VERSION;
0076 
0077     ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 3, 0);
0078     if (ret < 0) {
0079         if (adap->fe_adap[0].fe)
0080             adap->fe_adap[0].fe->ops.release(adap->fe_adap[0].fe);
0081         deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep state info\n");
0082     }
0083     mutex_unlock(&d->data_mutex);
0084 
0085     return ret;
0086 }
0087 
0088 static struct rc_map_table rc_map_cinergyt2_table[] = {
0089     { 0x0401, KEY_POWER },
0090     { 0x0402, KEY_1 },
0091     { 0x0403, KEY_2 },
0092     { 0x0404, KEY_3 },
0093     { 0x0405, KEY_4 },
0094     { 0x0406, KEY_5 },
0095     { 0x0407, KEY_6 },
0096     { 0x0408, KEY_7 },
0097     { 0x0409, KEY_8 },
0098     { 0x040a, KEY_9 },
0099     { 0x040c, KEY_0 },
0100     { 0x040b, KEY_VIDEO },
0101     { 0x040d, KEY_REFRESH },
0102     { 0x040e, KEY_SELECT },
0103     { 0x040f, KEY_EPG },
0104     { 0x0410, KEY_UP },
0105     { 0x0414, KEY_DOWN },
0106     { 0x0411, KEY_LEFT },
0107     { 0x0413, KEY_RIGHT },
0108     { 0x0412, KEY_OK },
0109     { 0x0415, KEY_TEXT },
0110     { 0x0416, KEY_INFO },
0111     { 0x0417, KEY_RED },
0112     { 0x0418, KEY_GREEN },
0113     { 0x0419, KEY_YELLOW },
0114     { 0x041a, KEY_BLUE },
0115     { 0x041c, KEY_VOLUMEUP },
0116     { 0x041e, KEY_VOLUMEDOWN },
0117     { 0x041d, KEY_MUTE },
0118     { 0x041b, KEY_CHANNELUP },
0119     { 0x041f, KEY_CHANNELDOWN },
0120     { 0x0440, KEY_PAUSE },
0121     { 0x044c, KEY_PLAY },
0122     { 0x0458, KEY_RECORD },
0123     { 0x0454, KEY_PREVIOUS },
0124     { 0x0448, KEY_STOP },
0125     { 0x045c, KEY_NEXT }
0126 };
0127 
0128 /* Number of keypresses to ignore before detect repeating */
0129 #define RC_REPEAT_DELAY 3
0130 
0131 static int repeatable_keys[] = {
0132     KEY_UP,
0133     KEY_DOWN,
0134     KEY_LEFT,
0135     KEY_RIGHT,
0136     KEY_VOLUMEUP,
0137     KEY_VOLUMEDOWN,
0138     KEY_CHANNELUP,
0139     KEY_CHANNELDOWN
0140 };
0141 
0142 static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
0143 {
0144     struct cinergyt2_state *st = d->priv;
0145     int i, ret;
0146 
0147     *state = REMOTE_NO_KEY_PRESSED;
0148 
0149     mutex_lock(&d->data_mutex);
0150     st->data[0] = CINERGYT2_EP1_GET_RC_EVENTS;
0151 
0152     ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 5, 0);
0153     if (ret < 0)
0154         goto ret;
0155 
0156     if (st->data[4] == 0xff) {
0157         /* key repeat */
0158         st->rc_counter++;
0159         if (st->rc_counter > RC_REPEAT_DELAY) {
0160             for (i = 0; i < ARRAY_SIZE(repeatable_keys); i++) {
0161                 if (d->last_event == repeatable_keys[i]) {
0162                     *state = REMOTE_KEY_REPEAT;
0163                     *event = d->last_event;
0164                     deb_rc("repeat key, event %x\n",
0165                            *event);
0166                     goto ret;
0167                 }
0168             }
0169             deb_rc("repeated key (non repeatable)\n");
0170         }
0171         goto ret;
0172     }
0173 
0174     /* hack to pass checksum on the custom field */
0175     st->data[2] = ~st->data[1];
0176     dvb_usb_nec_rc_key_to_event(d, st->data, event, state);
0177     if (st->data[0] != 0) {
0178         if (*event != d->last_event)
0179             st->rc_counter = 0;
0180 
0181         deb_rc("key: %*ph\n", 5, st->data);
0182     }
0183 
0184 ret:
0185     mutex_unlock(&d->data_mutex);
0186     return ret;
0187 }
0188 
0189 static int cinergyt2_usb_probe(struct usb_interface *intf,
0190                 const struct usb_device_id *id)
0191 {
0192     return dvb_usb_device_init(intf, &cinergyt2_properties,
0193                    THIS_MODULE, NULL, adapter_nr);
0194 }
0195 
0196 enum {
0197     TERRATEC_CINERGY_T2,
0198 };
0199 
0200 static struct usb_device_id cinergyt2_usb_table[] = {
0201     DVB_USB_DEV(TERRATEC, TERRATEC_CINERGY_T2),
0202     { }
0203 };
0204 
0205 MODULE_DEVICE_TABLE(usb, cinergyt2_usb_table);
0206 
0207 static const struct dvb_usb_device_properties cinergyt2_properties = {
0208     .size_of_priv = sizeof(struct cinergyt2_state),
0209     .num_adapters = 1,
0210     .adapter = {
0211         {
0212         .num_frontends = 1,
0213         .fe = {{
0214             .streaming_ctrl   = cinergyt2_streaming_ctrl,
0215             .frontend_attach  = cinergyt2_frontend_attach,
0216 
0217             /* parameter for the MPEG2-data transfer */
0218             .stream = {
0219                 .type = USB_BULK,
0220                 .count = 5,
0221                 .endpoint = 0x02,
0222                 .u = {
0223                     .bulk = {
0224                         .buffersize = 512,
0225                     }
0226                 }
0227             },
0228         }},
0229         }
0230     },
0231 
0232     .power_ctrl       = cinergyt2_power_ctrl,
0233 
0234     .rc.legacy = {
0235         .rc_interval      = 50,
0236         .rc_map_table     = rc_map_cinergyt2_table,
0237         .rc_map_size      = ARRAY_SIZE(rc_map_cinergyt2_table),
0238         .rc_query         = cinergyt2_rc_query,
0239     },
0240 
0241     .generic_bulk_ctrl_endpoint = 1,
0242 
0243     .num_device_descs = 1,
0244     .devices = {
0245         { .name = "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver",
0246           .cold_ids = {NULL},
0247           .warm_ids = { &cinergyt2_usb_table[TERRATEC_CINERGY_T2], NULL },
0248         },
0249         { NULL },
0250     }
0251 };
0252 
0253 
0254 static struct usb_driver cinergyt2_driver = {
0255     .name       = "cinergyT2",
0256     .probe      = cinergyt2_usb_probe,
0257     .disconnect = dvb_usb_device_exit,
0258     .id_table   = cinergyt2_usb_table
0259 };
0260 
0261 module_usb_driver(cinergyt2_driver);
0262 
0263 MODULE_DESCRIPTION("Terratec Cinergy T2 DVB-T driver");
0264 MODULE_LICENSE("GPL");
0265 MODULE_AUTHOR("Tomi Orava");