Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* DVB USB library compliant Linux driver for the WideView/ Yakumo/ Hama/
0003  * Typhoon/ Yuan/ Miglia DVB-T USB2.0 receiver.
0004  *
0005  * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de)
0006  *
0007  * Thanks to Steve Chang from WideView for providing support for the WT-220U.
0008  *
0009  * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
0010  */
0011 #include "dtt200u.h"
0012 
0013 /* debug */
0014 int dvb_usb_dtt200u_debug;
0015 module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644);
0016 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS);
0017 
0018 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
0019 
0020 struct dtt200u_state {
0021     unsigned char data[80];
0022 };
0023 
0024 static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff)
0025 {
0026     struct dtt200u_state *st = d->priv;
0027     int ret = 0;
0028 
0029     mutex_lock(&d->data_mutex);
0030 
0031     st->data[0] = SET_INIT;
0032 
0033     if (onoff)
0034         ret = dvb_usb_generic_write(d, st->data, 2);
0035 
0036     mutex_unlock(&d->data_mutex);
0037     return ret;
0038 }
0039 
0040 static int dtt200u_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
0041 {
0042     struct dvb_usb_device *d = adap->dev;
0043     struct dtt200u_state *st = d->priv;
0044     int ret;
0045 
0046     mutex_lock(&d->data_mutex);
0047     st->data[0] = SET_STREAMING;
0048     st->data[1] = onoff;
0049 
0050     ret = dvb_usb_generic_write(adap->dev, st->data, 2);
0051     if (ret < 0)
0052         goto ret;
0053 
0054     if (onoff)
0055         goto ret;
0056 
0057     st->data[0] = RESET_PID_FILTER;
0058     ret = dvb_usb_generic_write(adap->dev, st->data, 1);
0059 
0060 ret:
0061     mutex_unlock(&d->data_mutex);
0062 
0063     return ret;
0064 }
0065 
0066 static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)
0067 {
0068     struct dvb_usb_device *d = adap->dev;
0069     struct dtt200u_state *st = d->priv;
0070     int ret;
0071 
0072     pid = onoff ? pid : 0;
0073 
0074     mutex_lock(&d->data_mutex);
0075     st->data[0] = SET_PID_FILTER;
0076     st->data[1] = index;
0077     st->data[2] = pid & 0xff;
0078     st->data[3] = (pid >> 8) & 0x1f;
0079 
0080     ret = dvb_usb_generic_write(adap->dev, st->data, 4);
0081     mutex_unlock(&d->data_mutex);
0082 
0083     return ret;
0084 }
0085 
0086 static int dtt200u_rc_query(struct dvb_usb_device *d)
0087 {
0088     struct dtt200u_state *st = d->priv;
0089     u32 scancode;
0090     int ret;
0091 
0092     mutex_lock(&d->data_mutex);
0093     st->data[0] = GET_RC_CODE;
0094 
0095     ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 5, 0);
0096     if (ret < 0)
0097         goto ret;
0098 
0099     if (st->data[0] == 1) {
0100         enum rc_proto proto = RC_PROTO_NEC;
0101 
0102         scancode = st->data[1];
0103         if ((u8) ~st->data[1] != st->data[2]) {
0104             /* Extended NEC */
0105             scancode = scancode << 8;
0106             scancode |= st->data[2];
0107             proto = RC_PROTO_NECX;
0108         }
0109         scancode = scancode << 8;
0110         scancode |= st->data[3];
0111 
0112         /* Check command checksum is ok */
0113         if ((u8) ~st->data[3] == st->data[4])
0114             rc_keydown(d->rc_dev, proto, scancode, 0);
0115         else
0116             rc_keyup(d->rc_dev);
0117     } else if (st->data[0] == 2) {
0118         rc_repeat(d->rc_dev);
0119     } else {
0120         rc_keyup(d->rc_dev);
0121     }
0122 
0123     if (st->data[0] != 0)
0124         deb_info("st->data: %*ph\n", 5, st->data);
0125 
0126 ret:
0127     mutex_unlock(&d->data_mutex);
0128     return ret;
0129 }
0130 
0131 static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap)
0132 {
0133     adap->fe_adap[0].fe = dtt200u_fe_attach(adap->dev);
0134     return 0;
0135 }
0136 
0137 static struct dvb_usb_device_properties dtt200u_properties;
0138 static struct dvb_usb_device_properties wt220u_fc_properties;
0139 static struct dvb_usb_device_properties wt220u_properties;
0140 static struct dvb_usb_device_properties wt220u_zl0353_properties;
0141 static struct dvb_usb_device_properties wt220u_miglia_properties;
0142 
0143 static int dtt200u_usb_probe(struct usb_interface *intf,
0144         const struct usb_device_id *id)
0145 {
0146     if (0 == dvb_usb_device_init(intf, &dtt200u_properties,
0147                      THIS_MODULE, NULL, adapter_nr) ||
0148         0 == dvb_usb_device_init(intf, &wt220u_properties,
0149                      THIS_MODULE, NULL, adapter_nr) ||
0150         0 == dvb_usb_device_init(intf, &wt220u_fc_properties,
0151                      THIS_MODULE, NULL, adapter_nr) ||
0152         0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties,
0153                      THIS_MODULE, NULL, adapter_nr) ||
0154         0 == dvb_usb_device_init(intf, &wt220u_miglia_properties,
0155                      THIS_MODULE, NULL, adapter_nr))
0156         return 0;
0157 
0158     return -ENODEV;
0159 }
0160 
0161 enum {
0162     WIDEVIEW_DTT200U_COLD,
0163     WIDEVIEW_DTT200U_WARM,
0164     WIDEVIEW_WT220U_COLD,
0165     WIDEVIEW_WT220U_WARM,
0166     WIDEVIEW_WT220U_ZL0353_COLD,
0167     WIDEVIEW_WT220U_ZL0353_WARM,
0168     WIDEVIEW_WT220U_FC_COLD,
0169     WIDEVIEW_WT220U_FC_WARM,
0170     WIDEVIEW_WT220U_ZAP250_COLD,
0171     MIGLIA_WT220U_ZAP250_COLD,
0172 };
0173 
0174 static struct usb_device_id dtt200u_usb_table[] = {
0175     DVB_USB_DEV(WIDEVIEW, WIDEVIEW_DTT200U_COLD),
0176     DVB_USB_DEV(WIDEVIEW, WIDEVIEW_DTT200U_WARM),
0177     DVB_USB_DEV(WIDEVIEW, WIDEVIEW_WT220U_COLD),
0178     DVB_USB_DEV(WIDEVIEW, WIDEVIEW_WT220U_WARM),
0179     DVB_USB_DEV(WIDEVIEW, WIDEVIEW_WT220U_ZL0353_COLD),
0180     DVB_USB_DEV(WIDEVIEW, WIDEVIEW_WT220U_ZL0353_WARM),
0181     DVB_USB_DEV(WIDEVIEW, WIDEVIEW_WT220U_FC_COLD),
0182     DVB_USB_DEV(WIDEVIEW, WIDEVIEW_WT220U_FC_WARM),
0183     DVB_USB_DEV(WIDEVIEW, WIDEVIEW_WT220U_ZAP250_COLD),
0184     DVB_USB_DEV(MIGLIA, MIGLIA_WT220U_ZAP250_COLD),
0185     { }
0186 };
0187 
0188 MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
0189 
0190 static struct dvb_usb_device_properties dtt200u_properties = {
0191     .usb_ctrl = CYPRESS_FX2,
0192     .firmware = "dvb-usb-dtt200u-01.fw",
0193 
0194     .size_of_priv     = sizeof(struct dtt200u_state),
0195 
0196     .num_adapters = 1,
0197     .adapter = {
0198         {
0199         .num_frontends = 1,
0200         .fe = {{
0201             .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
0202             .pid_filter_count = 15,
0203 
0204     .streaming_ctrl  = dtt200u_streaming_ctrl,
0205     .pid_filter      = dtt200u_pid_filter,
0206     .frontend_attach = dtt200u_frontend_attach,
0207     /* parameter for the MPEG2-data transfer */
0208             .stream = {
0209                 .type = USB_BULK,
0210         .count = 7,
0211         .endpoint = 0x02,
0212         .u = {
0213             .bulk = {
0214                 .buffersize = 4096,
0215             }
0216         }
0217     },
0218         }},
0219         }
0220     },
0221     .power_ctrl      = dtt200u_power_ctrl,
0222 
0223     .rc.core = {
0224         .rc_interval     = 300,
0225         .rc_codes        = RC_MAP_DTT200U,
0226         .rc_query        = dtt200u_rc_query,
0227         .allowed_protos  = RC_PROTO_BIT_NEC,
0228     },
0229 
0230     .generic_bulk_ctrl_endpoint = 0x01,
0231 
0232     .num_device_descs = 1,
0233     .devices = {
0234         { .name = "WideView/Yuan/Yakumo/Hama/Typhoon DVB-T USB2.0 (WT-200U)",
0235           .cold_ids = { &dtt200u_usb_table[WIDEVIEW_DTT200U_COLD], NULL },
0236           .warm_ids = { &dtt200u_usb_table[WIDEVIEW_DTT200U_WARM], NULL },
0237         },
0238         { NULL },
0239     }
0240 };
0241 
0242 static struct dvb_usb_device_properties wt220u_properties = {
0243     .usb_ctrl = CYPRESS_FX2,
0244     .firmware = "dvb-usb-wt220u-02.fw",
0245 
0246     .size_of_priv     = sizeof(struct dtt200u_state),
0247 
0248     .num_adapters = 1,
0249     .adapter = {
0250         {
0251         .num_frontends = 1,
0252         .fe = {{
0253             .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
0254             .pid_filter_count = 15,
0255 
0256     .streaming_ctrl  = dtt200u_streaming_ctrl,
0257     .pid_filter      = dtt200u_pid_filter,
0258     .frontend_attach = dtt200u_frontend_attach,
0259     /* parameter for the MPEG2-data transfer */
0260             .stream = {
0261                 .type = USB_BULK,
0262         .count = 7,
0263         .endpoint = 0x02,
0264         .u = {
0265             .bulk = {
0266                 .buffersize = 4096,
0267             }
0268         }
0269     },
0270         }},
0271         }
0272     },
0273     .power_ctrl      = dtt200u_power_ctrl,
0274 
0275     .rc.core = {
0276         .rc_interval     = 300,
0277         .rc_codes        = RC_MAP_DTT200U,
0278         .rc_query        = dtt200u_rc_query,
0279         .allowed_protos  = RC_PROTO_BIT_NEC,
0280     },
0281 
0282     .generic_bulk_ctrl_endpoint = 0x01,
0283 
0284     .num_device_descs = 1,
0285     .devices = {
0286         { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
0287           .cold_ids = { &dtt200u_usb_table[WIDEVIEW_WT220U_COLD], &dtt200u_usb_table[WIDEVIEW_WT220U_ZAP250_COLD], NULL },
0288           .warm_ids = { &dtt200u_usb_table[WIDEVIEW_WT220U_WARM], NULL },
0289         },
0290         { NULL },
0291     }
0292 };
0293 
0294 static struct dvb_usb_device_properties wt220u_fc_properties = {
0295     .usb_ctrl = CYPRESS_FX2,
0296     .firmware = "dvb-usb-wt220u-fc03.fw",
0297 
0298     .size_of_priv     = sizeof(struct dtt200u_state),
0299 
0300     .num_adapters = 1,
0301     .adapter = {
0302         {
0303         .num_frontends = 1,
0304         .fe = {{
0305             .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
0306             .pid_filter_count = 15,
0307 
0308     .streaming_ctrl  = dtt200u_streaming_ctrl,
0309     .pid_filter      = dtt200u_pid_filter,
0310     .frontend_attach = dtt200u_frontend_attach,
0311     /* parameter for the MPEG2-data transfer */
0312             .stream = {
0313                 .type = USB_BULK,
0314         .count = 7,
0315                 .endpoint = 0x06,
0316         .u = {
0317             .bulk = {
0318                 .buffersize = 4096,
0319             }
0320         }
0321     },
0322         }},
0323         }
0324     },
0325     .power_ctrl      = dtt200u_power_ctrl,
0326 
0327     .rc.core = {
0328         .rc_interval     = 300,
0329         .rc_codes        = RC_MAP_DTT200U,
0330         .rc_query        = dtt200u_rc_query,
0331         .allowed_protos  = RC_PROTO_BIT_NEC,
0332     },
0333 
0334     .generic_bulk_ctrl_endpoint = 0x01,
0335 
0336     .num_device_descs = 1,
0337     .devices = {
0338         { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
0339           .cold_ids = { &dtt200u_usb_table[WIDEVIEW_WT220U_FC_COLD], NULL },
0340           .warm_ids = { &dtt200u_usb_table[WIDEVIEW_WT220U_FC_WARM], NULL },
0341         },
0342         { NULL },
0343     }
0344 };
0345 
0346 static struct dvb_usb_device_properties wt220u_zl0353_properties = {
0347     .usb_ctrl = CYPRESS_FX2,
0348     .firmware = "dvb-usb-wt220u-zl0353-01.fw",
0349 
0350     .size_of_priv     = sizeof(struct dtt200u_state),
0351 
0352     .num_adapters = 1,
0353     .adapter = {
0354         {
0355         .num_frontends = 1,
0356         .fe = {{
0357             .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
0358             .pid_filter_count = 15,
0359 
0360             .streaming_ctrl  = dtt200u_streaming_ctrl,
0361             .pid_filter      = dtt200u_pid_filter,
0362             .frontend_attach = dtt200u_frontend_attach,
0363             /* parameter for the MPEG2-data transfer */
0364             .stream = {
0365                 .type = USB_BULK,
0366                 .count = 7,
0367                 .endpoint = 0x02,
0368                 .u = {
0369                     .bulk = {
0370                         .buffersize = 4096,
0371                     }
0372                 }
0373             },
0374         }},
0375         }
0376     },
0377     .power_ctrl      = dtt200u_power_ctrl,
0378 
0379     .rc.core = {
0380         .rc_interval     = 300,
0381         .rc_codes        = RC_MAP_DTT200U,
0382         .rc_query        = dtt200u_rc_query,
0383         .allowed_protos  = RC_PROTO_BIT_NEC,
0384     },
0385 
0386     .generic_bulk_ctrl_endpoint = 0x01,
0387 
0388     .num_device_descs = 1,
0389     .devices = {
0390         { .name = "WideView WT-220U PenType Receiver (based on ZL353)",
0391           .cold_ids = { &dtt200u_usb_table[WIDEVIEW_WT220U_ZL0353_COLD], NULL },
0392           .warm_ids = { &dtt200u_usb_table[WIDEVIEW_WT220U_ZL0353_WARM], NULL },
0393         },
0394         { NULL },
0395     }
0396 };
0397 
0398 static struct dvb_usb_device_properties wt220u_miglia_properties = {
0399     .usb_ctrl = CYPRESS_FX2,
0400     .firmware = "dvb-usb-wt220u-miglia-01.fw",
0401 
0402     .size_of_priv     = sizeof(struct dtt200u_state),
0403 
0404     .num_adapters = 1,
0405     .generic_bulk_ctrl_endpoint = 0x01,
0406 
0407     .num_device_descs = 1,
0408     .devices = {
0409         { .name = "WideView WT-220U PenType Receiver (Miglia)",
0410           .cold_ids = { &dtt200u_usb_table[MIGLIA_WT220U_ZAP250_COLD], NULL },
0411           /* This device turns into WT220U_ZL0353_WARM when fw
0412              has been uploaded */
0413           .warm_ids = { NULL },
0414         },
0415         { NULL },
0416     }
0417 };
0418 
0419 /* usb specific object needed to register this driver with the usb subsystem */
0420 static struct usb_driver dtt200u_usb_driver = {
0421     .name       = "dvb_usb_dtt200u",
0422     .probe      = dtt200u_usb_probe,
0423     .disconnect = dvb_usb_device_exit,
0424     .id_table   = dtt200u_usb_table,
0425 };
0426 
0427 module_usb_driver(dtt200u_usb_driver);
0428 
0429 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
0430 MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D/Miglia DVB-T USB2.0 devices");
0431 MODULE_VERSION("1.0");
0432 MODULE_LICENSE("GPL");