Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* DVB USB compliant linux driver for mobile DVB-T USB devices based on
0003  * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-B)
0004  *
0005  * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de)
0006  *
0007  * based on GPL code from DiBcom, which has
0008  * Copyright (C) 2004 Amaury Demol for DiBcom
0009  *
0010  * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
0011  */
0012 #include "dibusb.h"
0013 
0014 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
0015 
0016 static int dib3000mb_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
0017 {
0018     struct dvb_usb_adapter *adap = fe->dvb->priv;
0019     struct dibusb_state *st = adap->priv;
0020 
0021     return st->ops.tuner_pass_ctrl(fe, enable, st->tuner_addr);
0022 }
0023 
0024 static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_adapter *adap)
0025 {
0026     struct dib3000_config demod_cfg;
0027     struct dibusb_state *st = adap->priv;
0028 
0029     demod_cfg.demod_address = 0x8;
0030 
0031     adap->fe_adap[0].fe = dvb_attach(dib3000mb_attach, &demod_cfg,
0032                      &adap->dev->i2c_adap, &st->ops);
0033     if ((adap->fe_adap[0].fe) == NULL)
0034         return -ENODEV;
0035 
0036     adap->fe_adap[0].fe->ops.i2c_gate_ctrl = dib3000mb_i2c_gate_ctrl;
0037 
0038     return 0;
0039 }
0040 
0041 static int dibusb_thomson_tuner_attach(struct dvb_usb_adapter *adap)
0042 {
0043     struct dibusb_state *st = adap->priv;
0044 
0045     st->tuner_addr = 0x61;
0046 
0047     dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, &adap->dev->i2c_adap,
0048            DVB_PLL_TUA6010XS);
0049     return 0;
0050 }
0051 
0052 static int dibusb_panasonic_tuner_attach(struct dvb_usb_adapter *adap)
0053 {
0054     struct dibusb_state *st = adap->priv;
0055 
0056     st->tuner_addr = 0x60;
0057 
0058     dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap,
0059            DVB_PLL_TDA665X);
0060     return 0;
0061 }
0062 
0063 /* Some of the Artec 1.1 device aren't equipped with the default tuner
0064  * (Thomson Cable), but with a Panasonic ENV77H11D5.  This function figures
0065  * this out. */
0066 static int dibusb_tuner_probe_and_attach(struct dvb_usb_adapter *adap)
0067 {
0068     u8 b[2] = { 0,0 }, b2[1];
0069     int ret = 0;
0070     struct i2c_msg msg[2] = {
0071         { .flags = 0,        .buf = b,  .len = 2 },
0072         { .flags = I2C_M_RD, .buf = b2, .len = 1 },
0073     };
0074     struct dibusb_state *st = adap->priv;
0075 
0076     /* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */
0077     msg[0].addr = msg[1].addr = st->tuner_addr = 0x60;
0078 
0079     if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
0080         adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1);
0081 
0082     if (i2c_transfer(&adap->dev->i2c_adap, msg, 2) != 2) {
0083         err("tuner i2c write failed.");
0084         return -EREMOTEIO;
0085     }
0086 
0087     if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
0088         adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0);
0089 
0090     if (b2[0] == 0xfe) {
0091         info("This device has the Thomson Cable onboard. Which is default.");
0092         ret = dibusb_thomson_tuner_attach(adap);
0093     } else {
0094         info("This device has the Panasonic ENV77H11D5 onboard.");
0095         ret = dibusb_panasonic_tuner_attach(adap);
0096     }
0097 
0098     return ret;
0099 }
0100 
0101 /* USB Driver stuff */
0102 static struct dvb_usb_device_properties dibusb1_1_properties;
0103 static struct dvb_usb_device_properties dibusb1_1_an2235_properties;
0104 static struct dvb_usb_device_properties dibusb2_0b_properties;
0105 static struct dvb_usb_device_properties artec_t1_usb2_properties;
0106 
0107 static int dibusb_probe(struct usb_interface *intf,
0108         const struct usb_device_id *id)
0109 {
0110     if (0 == dvb_usb_device_init(intf, &dibusb1_1_properties,
0111                      THIS_MODULE, NULL, adapter_nr) ||
0112         0 == dvb_usb_device_init(intf, &dibusb1_1_an2235_properties,
0113                      THIS_MODULE, NULL, adapter_nr) ||
0114         0 == dvb_usb_device_init(intf, &dibusb2_0b_properties,
0115                      THIS_MODULE, NULL, adapter_nr) ||
0116         0 == dvb_usb_device_init(intf, &artec_t1_usb2_properties,
0117                      THIS_MODULE, NULL, adapter_nr))
0118         return 0;
0119 
0120     return -EINVAL;
0121 }
0122 
0123 /* do not change the order of the ID table */
0124 enum {
0125     WIDEVIEW_DVBT_USB_COLD,
0126     WIDEVIEW_DVBT_USB_WARM,
0127     COMPRO_DVBU2000_COLD,
0128     COMPRO_DVBU2000_WARM,
0129     COMPRO_DVBU2000_UNK_COLD,
0130     DIBCOM_MOD3000_COLD,
0131     DIBCOM_MOD3000_WARM,
0132     EMPIA_VSTREAM_COLD,
0133     EMPIA_VSTREAM_WARM,
0134     GRANDTEC_DVBT_USB_COLD,
0135     GRANDTEC_DVBT_USB_WARM,
0136     GRANDTEC_MOD3000_COLD,
0137     GRANDTEC_MOD3000_WARM,
0138     UNK_HYPER_PALTEK_COLD,
0139     UNK_HYPER_PALTEK_WARM,
0140     VISIONPLUS_VP7041_COLD,
0141     VISIONPLUS_VP7041_WARM,
0142     TWINHAN_VP7041_COLD,
0143     TWINHAN_VP7041_WARM,
0144     ULTIMA_TVBOX_COLD,
0145     ULTIMA_TVBOX_WARM,
0146     ULTIMA_TVBOX_AN2235_COLD,
0147     ULTIMA_TVBOX_AN2235_WARM,
0148     ADSTECH_USB2_COLD,
0149     ADSTECH_USB2_WARM,
0150     KYE_DVB_T_COLD,
0151     KYE_DVB_T_WARM,
0152     KWORLD_VSTREAM_COLD,
0153     ULTIMA_TVBOX_USB2_COLD,
0154     ULTIMA_TVBOX_USB2_WARM,
0155     ULTIMA_TVBOX_ANCHOR_COLD,
0156 };
0157 
0158 static struct usb_device_id dibusb_dib3000mb_table[] = {
0159     DVB_USB_DEV(WIDEVIEW, WIDEVIEW_DVBT_USB_COLD),
0160     DVB_USB_DEV(WIDEVIEW, WIDEVIEW_DVBT_USB_WARM),
0161     DVB_USB_DEV(COMPRO, COMPRO_DVBU2000_COLD),
0162     DVB_USB_DEV(COMPRO, COMPRO_DVBU2000_WARM),
0163     DVB_USB_DEV(COMPRO_UNK, COMPRO_DVBU2000_UNK_COLD),
0164     DVB_USB_DEV(DIBCOM, DIBCOM_MOD3000_COLD),
0165     DVB_USB_DEV(DIBCOM, DIBCOM_MOD3000_WARM),
0166     DVB_USB_DEV(EMPIA, EMPIA_VSTREAM_COLD),
0167     DVB_USB_DEV(EMPIA, EMPIA_VSTREAM_WARM),
0168     DVB_USB_DEV(GRANDTEC, GRANDTEC_DVBT_USB_COLD),
0169     DVB_USB_DEV(GRANDTEC, GRANDTEC_DVBT_USB_WARM),
0170     DVB_USB_DEV(GRANDTEC, GRANDTEC_MOD3000_COLD),
0171     DVB_USB_DEV(GRANDTEC, GRANDTEC_MOD3000_WARM),
0172     DVB_USB_DEV(HYPER_PALTEK, UNK_HYPER_PALTEK_COLD),
0173     DVB_USB_DEV(HYPER_PALTEK, UNK_HYPER_PALTEK_WARM),
0174     DVB_USB_DEV(VISIONPLUS, VISIONPLUS_VP7041_COLD),
0175     DVB_USB_DEV(VISIONPLUS, VISIONPLUS_VP7041_WARM),
0176     DVB_USB_DEV(TWINHAN, TWINHAN_VP7041_COLD),
0177     DVB_USB_DEV(TWINHAN, TWINHAN_VP7041_WARM),
0178     DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_COLD),
0179     DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_WARM),
0180     DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_AN2235_COLD),
0181     DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_AN2235_WARM),
0182     DVB_USB_DEV(ADSTECH, ADSTECH_USB2_COLD),
0183     DVB_USB_DEV(ADSTECH, ADSTECH_USB2_WARM),
0184     DVB_USB_DEV(KYE, KYE_DVB_T_COLD),
0185     DVB_USB_DEV(KYE, KYE_DVB_T_WARM),
0186     DVB_USB_DEV(KWORLD, KWORLD_VSTREAM_COLD),
0187     DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_USB2_COLD),
0188     DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_USB2_WARM),
0189 #ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
0190     DVB_USB_DEV(ANCHOR, ULTIMA_TVBOX_ANCHOR_COLD),
0191 #endif
0192     { }
0193 };
0194 
0195 MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table);
0196 
0197 static struct dvb_usb_device_properties dibusb1_1_properties = {
0198     .caps =  DVB_USB_IS_AN_I2C_ADAPTER,
0199 
0200     .usb_ctrl = CYPRESS_AN2135,
0201 
0202     .firmware = "dvb-usb-dibusb-5.0.0.11.fw",
0203 
0204     .num_adapters = 1,
0205     .adapter = {
0206         {
0207         .num_frontends = 1,
0208         .fe = {{
0209             .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
0210             .pid_filter_count = 16,
0211 
0212             .streaming_ctrl   = dibusb_streaming_ctrl,
0213             .pid_filter       = dibusb_pid_filter,
0214             .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
0215             .frontend_attach  = dibusb_dib3000mb_frontend_attach,
0216             .tuner_attach     = dibusb_tuner_probe_and_attach,
0217 
0218             /* parameter for the MPEG2-data transfer */
0219             .stream = {
0220                 .type = USB_BULK,
0221                 .count = 7,
0222                 .endpoint = 0x02,
0223                 .u = {
0224                     .bulk = {
0225                         .buffersize = 4096,
0226                     }
0227                 }
0228             },
0229         }},
0230             .size_of_priv     = sizeof(struct dibusb_state),
0231         }
0232     },
0233 
0234     .power_ctrl       = dibusb_power_ctrl,
0235 
0236     .rc.legacy = {
0237         .rc_interval      = DEFAULT_RC_INTERVAL,
0238         .rc_map_table     = rc_map_dibusb_table,
0239         .rc_map_size      = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
0240         .rc_query         = dibusb_rc_query,
0241     },
0242 
0243     .i2c_algo         = &dibusb_i2c_algo,
0244 
0245     .generic_bulk_ctrl_endpoint = 0x01,
0246 
0247     .num_device_descs = 9,
0248     .devices = {
0249         {   "AVerMedia AverTV DVBT USB1.1",
0250             { &dibusb_dib3000mb_table[WIDEVIEW_DVBT_USB_COLD],  NULL },
0251             { &dibusb_dib3000mb_table[WIDEVIEW_DVBT_USB_WARM],  NULL },
0252         },
0253         {   "Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)",
0254             { &dibusb_dib3000mb_table[COMPRO_DVBU2000_COLD], &dibusb_dib3000mb_table[COMPRO_DVBU2000_UNK_COLD], NULL},
0255             { &dibusb_dib3000mb_table[COMPRO_DVBU2000_WARM], NULL },
0256         },
0257         {   "DiBcom USB1.1 DVB-T reference design (MOD3000)",
0258             { &dibusb_dib3000mb_table[DIBCOM_MOD3000_COLD],  NULL },
0259             { &dibusb_dib3000mb_table[DIBCOM_MOD3000_WARM],  NULL },
0260         },
0261         {   "KWorld V-Stream XPERT DTV - DVB-T USB1.1",
0262             { &dibusb_dib3000mb_table[EMPIA_VSTREAM_COLD], NULL },
0263             { &dibusb_dib3000mb_table[EMPIA_VSTREAM_WARM], NULL },
0264         },
0265         {   "Grandtec USB1.1 DVB-T",
0266             { &dibusb_dib3000mb_table[GRANDTEC_DVBT_USB_COLD],  &dibusb_dib3000mb_table[GRANDTEC_MOD3000_COLD], NULL },
0267             { &dibusb_dib3000mb_table[GRANDTEC_DVBT_USB_WARM], &dibusb_dib3000mb_table[GRANDTEC_MOD3000_WARM], NULL },
0268         },
0269         {   "Unknown USB1.1 DVB-T device ???? please report the name to the author",
0270             { &dibusb_dib3000mb_table[UNK_HYPER_PALTEK_COLD], NULL },
0271             { &dibusb_dib3000mb_table[UNK_HYPER_PALTEK_WARM], NULL },
0272         },
0273         {   "TwinhanDTV USB-Ter USB1.1 / Magic Box I / HAMA USB1.1 DVB-T device",
0274             { &dibusb_dib3000mb_table[VISIONPLUS_VP7041_COLD], &dibusb_dib3000mb_table[TWINHAN_VP7041_COLD], NULL},
0275             { &dibusb_dib3000mb_table[VISIONPLUS_VP7041_WARM], &dibusb_dib3000mb_table[TWINHAN_VP7041_WARM], NULL},
0276         },
0277         {   "Artec T1 USB1.1 TVBOX with AN2135",
0278             { &dibusb_dib3000mb_table[ULTIMA_TVBOX_COLD], NULL },
0279             { &dibusb_dib3000mb_table[ULTIMA_TVBOX_WARM], NULL },
0280         },
0281         {   "VideoWalker DVB-T USB",
0282             { &dibusb_dib3000mb_table[KYE_DVB_T_COLD], NULL },
0283             { &dibusb_dib3000mb_table[KYE_DVB_T_WARM], NULL },
0284         },
0285     }
0286 };
0287 
0288 static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {
0289     .caps = DVB_USB_IS_AN_I2C_ADAPTER,
0290     .usb_ctrl = CYPRESS_AN2235,
0291 
0292     .firmware = "dvb-usb-dibusb-an2235-01.fw",
0293 
0294     .num_adapters = 1,
0295     .adapter = {
0296         {
0297         .num_frontends = 1,
0298         .fe = {{
0299             .caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER,
0300             .pid_filter_count = 16,
0301 
0302             .streaming_ctrl   = dibusb_streaming_ctrl,
0303             .pid_filter       = dibusb_pid_filter,
0304             .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
0305             .frontend_attach  = dibusb_dib3000mb_frontend_attach,
0306             .tuner_attach     = dibusb_tuner_probe_and_attach,
0307 
0308             /* parameter for the MPEG2-data transfer */
0309             .stream = {
0310                 .type = USB_BULK,
0311                 .count = 7,
0312                 .endpoint = 0x02,
0313                 .u = {
0314                     .bulk = {
0315                         .buffersize = 4096,
0316                     }
0317                 }
0318             },
0319         }},
0320             .size_of_priv     = sizeof(struct dibusb_state),
0321         },
0322     },
0323     .power_ctrl       = dibusb_power_ctrl,
0324 
0325     .rc.legacy = {
0326         .rc_interval      = DEFAULT_RC_INTERVAL,
0327         .rc_map_table     = rc_map_dibusb_table,
0328         .rc_map_size      = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
0329         .rc_query         = dibusb_rc_query,
0330     },
0331 
0332     .i2c_algo         = &dibusb_i2c_algo,
0333 
0334     .generic_bulk_ctrl_endpoint = 0x01,
0335 
0336 #ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
0337     .num_device_descs = 2,
0338 #else
0339     .num_device_descs = 1,
0340 #endif
0341     .devices = {
0342         {   "Artec T1 USB1.1 TVBOX with AN2235",
0343             { &dibusb_dib3000mb_table[ULTIMA_TVBOX_AN2235_COLD], NULL },
0344             { &dibusb_dib3000mb_table[ULTIMA_TVBOX_AN2235_WARM], NULL },
0345         },
0346 #ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
0347         {   "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)",
0348             { &dibusb_dib3000mb_table[ULTIMA_TVBOX_ANCHOR_COLD], NULL },
0349             { NULL },
0350         },
0351         { NULL },
0352 #endif
0353     }
0354 };
0355 
0356 static struct dvb_usb_device_properties dibusb2_0b_properties = {
0357     .caps = DVB_USB_IS_AN_I2C_ADAPTER,
0358 
0359     .usb_ctrl = CYPRESS_FX2,
0360 
0361     .firmware = "dvb-usb-adstech-usb2-02.fw",
0362 
0363     .num_adapters = 1,
0364     .adapter = {
0365         {
0366         .num_frontends = 1,
0367         .fe = {{
0368             .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
0369             .pid_filter_count = 16,
0370 
0371             .streaming_ctrl   = dibusb2_0_streaming_ctrl,
0372             .pid_filter       = dibusb_pid_filter,
0373             .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
0374             .frontend_attach  = dibusb_dib3000mb_frontend_attach,
0375             .tuner_attach     = dibusb_thomson_tuner_attach,
0376 
0377             /* parameter for the MPEG2-data transfer */
0378             .stream = {
0379                 .type = USB_BULK,
0380                 .count = 7,
0381                 .endpoint = 0x06,
0382                 .u = {
0383                     .bulk = {
0384                         .buffersize = 4096,
0385                     }
0386                 }
0387             },
0388         }},
0389             .size_of_priv     = sizeof(struct dibusb_state),
0390         }
0391     },
0392     .power_ctrl       = dibusb2_0_power_ctrl,
0393 
0394     .rc.legacy = {
0395         .rc_interval      = DEFAULT_RC_INTERVAL,
0396         .rc_map_table     = rc_map_dibusb_table,
0397         .rc_map_size      = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
0398         .rc_query         = dibusb_rc_query,
0399     },
0400 
0401     .i2c_algo         = &dibusb_i2c_algo,
0402 
0403     .generic_bulk_ctrl_endpoint = 0x01,
0404 
0405     .num_device_descs = 2,
0406     .devices = {
0407         {   "KWorld/ADSTech Instant DVB-T USB2.0",
0408             { &dibusb_dib3000mb_table[ADSTECH_USB2_COLD], NULL },
0409             { &dibusb_dib3000mb_table[ADSTECH_USB2_WARM], NULL },
0410         },
0411         {   "KWorld Xpert DVB-T USB2.0",
0412             { &dibusb_dib3000mb_table[KWORLD_VSTREAM_COLD], NULL },
0413             { NULL }
0414         },
0415         { NULL },
0416     }
0417 };
0418 
0419 static struct dvb_usb_device_properties artec_t1_usb2_properties = {
0420     .caps = DVB_USB_IS_AN_I2C_ADAPTER,
0421 
0422     .usb_ctrl = CYPRESS_FX2,
0423 
0424     .firmware = "dvb-usb-dibusb-6.0.0.8.fw",
0425 
0426     .num_adapters = 1,
0427     .adapter = {
0428         {
0429         .num_frontends = 1,
0430         .fe = {{
0431             .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
0432             .pid_filter_count = 16,
0433 
0434             .streaming_ctrl   = dibusb2_0_streaming_ctrl,
0435             .pid_filter       = dibusb_pid_filter,
0436             .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
0437             .frontend_attach  = dibusb_dib3000mb_frontend_attach,
0438             .tuner_attach     = dibusb_tuner_probe_and_attach,
0439             /* parameter for the MPEG2-data transfer */
0440             .stream = {
0441                 .type = USB_BULK,
0442                 .count = 7,
0443                 .endpoint = 0x06,
0444                 .u = {
0445                     .bulk = {
0446                         .buffersize = 4096,
0447                     }
0448                 }
0449             },
0450         }},
0451             .size_of_priv     = sizeof(struct dibusb_state),
0452         }
0453     },
0454     .power_ctrl       = dibusb2_0_power_ctrl,
0455 
0456     .rc.legacy = {
0457         .rc_interval      = DEFAULT_RC_INTERVAL,
0458         .rc_map_table     = rc_map_dibusb_table,
0459         .rc_map_size      = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
0460         .rc_query         = dibusb_rc_query,
0461     },
0462 
0463     .i2c_algo         = &dibusb_i2c_algo,
0464 
0465     .generic_bulk_ctrl_endpoint = 0x01,
0466 
0467     .num_device_descs = 1,
0468     .devices = {
0469         {   "Artec T1 USB2.0",
0470             { &dibusb_dib3000mb_table[ULTIMA_TVBOX_USB2_COLD], NULL },
0471             { &dibusb_dib3000mb_table[ULTIMA_TVBOX_USB2_WARM], NULL },
0472         },
0473         { NULL },
0474     }
0475 };
0476 
0477 static struct usb_driver dibusb_driver = {
0478     .name       = "dvb_usb_dibusb_mb",
0479     .probe      = dibusb_probe,
0480     .disconnect = dvb_usb_device_exit,
0481     .id_table   = dibusb_dib3000mb_table,
0482 };
0483 
0484 module_usb_driver(dibusb_driver);
0485 
0486 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
0487 MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)");
0488 MODULE_VERSION("1.0");
0489 MODULE_LICENSE("GPL");