1 /* DVB USB library compliant Linux driver for the WideView/ Yakumo/ Hama/ 2 * Typhoon/ Yuan/ Miglia DVB-T USB2.0 receiver. 3 * 4 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) 5 * 6 * Thanks to Steve Chang from WideView for providing support for the WT-220U. 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the Free 10 * Software Foundation, version 2. 11 * 12 * see Documentation/dvb/README.dvb-usb for more information 13 */ 14 #include "dtt200u.h" 15 16 /* debug */ 17 int dvb_usb_dtt200u_debug; 18 module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644); 19 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS); 20 21 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 22 23 static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff) 24 { 25 u8 b = SET_INIT; 26 27 if (onoff) 28 dvb_usb_generic_write(d,&b,2); 29 30 return 0; 31 } 32 33 static int dtt200u_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) 34 { 35 u8 b_streaming[2] = { SET_STREAMING, onoff }; 36 u8 b_rst_pid = RESET_PID_FILTER; 37 38 dvb_usb_generic_write(adap->dev, b_streaming, 2); 39 40 if (onoff == 0) 41 dvb_usb_generic_write(adap->dev, &b_rst_pid, 1); 42 return 0; 43 } 44 45 static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) 46 { 47 u8 b_pid[4]; 48 pid = onoff ? pid : 0; 49 50 b_pid[0] = SET_PID_FILTER; 51 b_pid[1] = index; 52 b_pid[2] = pid & 0xff; 53 b_pid[3] = (pid >> 8) & 0x1f; 54 55 return dvb_usb_generic_write(adap->dev, b_pid, 4); 56 } 57 58 static int dtt200u_rc_query(struct dvb_usb_device *d) 59 { 60 u8 key[5],cmd = GET_RC_CODE; 61 u32 scancode; 62 63 dvb_usb_generic_rw(d,&cmd,1,key,5,0); 64 if (key[0] == 1) { 65 enum rc_type proto = RC_TYPE_NEC; 66 67 scancode = key[1]; 68 if ((u8) ~key[1] != key[2]) { 69 /* Extended NEC */ 70 scancode = scancode << 8; 71 scancode |= key[2]; 72 proto = RC_TYPE_NECX; 73 } 74 scancode = scancode << 8; 75 scancode |= key[3]; 76 77 /* Check command checksum is ok */ 78 if ((u8) ~key[3] == key[4]) 79 rc_keydown(d->rc_dev, proto, scancode, 0); 80 else 81 rc_keyup(d->rc_dev); 82 } else if (key[0] == 2) { 83 rc_repeat(d->rc_dev); 84 } else { 85 rc_keyup(d->rc_dev); 86 } 87 88 if (key[0] != 0) 89 deb_info("key: %*ph\n", 5, key); 90 91 return 0; 92 } 93 94 static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap) 95 { 96 adap->fe_adap[0].fe = dtt200u_fe_attach(adap->dev); 97 return 0; 98 } 99 100 static struct dvb_usb_device_properties dtt200u_properties; 101 static struct dvb_usb_device_properties wt220u_fc_properties; 102 static struct dvb_usb_device_properties wt220u_properties; 103 static struct dvb_usb_device_properties wt220u_zl0353_properties; 104 static struct dvb_usb_device_properties wt220u_miglia_properties; 105 106 static int dtt200u_usb_probe(struct usb_interface *intf, 107 const struct usb_device_id *id) 108 { 109 if (0 == dvb_usb_device_init(intf, &dtt200u_properties, 110 THIS_MODULE, NULL, adapter_nr) || 111 0 == dvb_usb_device_init(intf, &wt220u_properties, 112 THIS_MODULE, NULL, adapter_nr) || 113 0 == dvb_usb_device_init(intf, &wt220u_fc_properties, 114 THIS_MODULE, NULL, adapter_nr) || 115 0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties, 116 THIS_MODULE, NULL, adapter_nr) || 117 0 == dvb_usb_device_init(intf, &wt220u_miglia_properties, 118 THIS_MODULE, NULL, adapter_nr)) 119 return 0; 120 121 return -ENODEV; 122 } 123 124 static struct usb_device_id dtt200u_usb_table [] = { 125 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_COLD) }, 126 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_WARM) }, 127 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_COLD) }, 128 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM) }, 129 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_COLD) }, 130 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_WARM) }, 131 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_COLD) }, 132 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_WARM) }, 133 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZAP250_COLD) }, 134 { USB_DEVICE(USB_VID_MIGLIA, USB_PID_WT220U_ZAP250_COLD) }, 135 { 0 }, 136 }; 137 MODULE_DEVICE_TABLE(usb, dtt200u_usb_table); 138 139 static struct dvb_usb_device_properties dtt200u_properties = { 140 .usb_ctrl = CYPRESS_FX2, 141 .firmware = "dvb-usb-dtt200u-01.fw", 142 143 .num_adapters = 1, 144 .adapter = { 145 { 146 .num_frontends = 1, 147 .fe = {{ 148 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, 149 .pid_filter_count = 15, 150 151 .streaming_ctrl = dtt200u_streaming_ctrl, 152 .pid_filter = dtt200u_pid_filter, 153 .frontend_attach = dtt200u_frontend_attach, 154 /* parameter for the MPEG2-data transfer */ 155 .stream = { 156 .type = USB_BULK, 157 .count = 7, 158 .endpoint = 0x02, 159 .u = { 160 .bulk = { 161 .buffersize = 4096, 162 } 163 } 164 }, 165 }}, 166 } 167 }, 168 .power_ctrl = dtt200u_power_ctrl, 169 170 .rc.core = { 171 .rc_interval = 300, 172 .rc_codes = RC_MAP_DTT200U, 173 .rc_query = dtt200u_rc_query, 174 .allowed_protos = RC_BIT_NEC, 175 }, 176 177 .generic_bulk_ctrl_endpoint = 0x01, 178 179 .num_device_descs = 1, 180 .devices = { 181 { .name = "WideView/Yuan/Yakumo/Hama/Typhoon DVB-T USB2.0 (WT-200U)", 182 .cold_ids = { &dtt200u_usb_table[0], NULL }, 183 .warm_ids = { &dtt200u_usb_table[1], NULL }, 184 }, 185 { NULL }, 186 } 187 }; 188 189 static struct dvb_usb_device_properties wt220u_properties = { 190 .usb_ctrl = CYPRESS_FX2, 191 .firmware = "dvb-usb-wt220u-02.fw", 192 193 .num_adapters = 1, 194 .adapter = { 195 { 196 .num_frontends = 1, 197 .fe = {{ 198 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, 199 .pid_filter_count = 15, 200 201 .streaming_ctrl = dtt200u_streaming_ctrl, 202 .pid_filter = dtt200u_pid_filter, 203 .frontend_attach = dtt200u_frontend_attach, 204 /* parameter for the MPEG2-data transfer */ 205 .stream = { 206 .type = USB_BULK, 207 .count = 7, 208 .endpoint = 0x02, 209 .u = { 210 .bulk = { 211 .buffersize = 4096, 212 } 213 } 214 }, 215 }}, 216 } 217 }, 218 .power_ctrl = dtt200u_power_ctrl, 219 220 .rc.core = { 221 .rc_interval = 300, 222 .rc_codes = RC_MAP_DTT200U, 223 .rc_query = dtt200u_rc_query, 224 .allowed_protos = RC_BIT_NEC, 225 }, 226 227 .generic_bulk_ctrl_endpoint = 0x01, 228 229 .num_device_descs = 1, 230 .devices = { 231 { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)", 232 .cold_ids = { &dtt200u_usb_table[2], &dtt200u_usb_table[8], NULL }, 233 .warm_ids = { &dtt200u_usb_table[3], NULL }, 234 }, 235 { NULL }, 236 } 237 }; 238 239 static struct dvb_usb_device_properties wt220u_fc_properties = { 240 .usb_ctrl = CYPRESS_FX2, 241 .firmware = "dvb-usb-wt220u-fc03.fw", 242 243 .num_adapters = 1, 244 .adapter = { 245 { 246 .num_frontends = 1, 247 .fe = {{ 248 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, 249 .pid_filter_count = 15, 250 251 .streaming_ctrl = dtt200u_streaming_ctrl, 252 .pid_filter = dtt200u_pid_filter, 253 .frontend_attach = dtt200u_frontend_attach, 254 /* parameter for the MPEG2-data transfer */ 255 .stream = { 256 .type = USB_BULK, 257 .count = 7, 258 .endpoint = 0x06, 259 .u = { 260 .bulk = { 261 .buffersize = 4096, 262 } 263 } 264 }, 265 }}, 266 } 267 }, 268 .power_ctrl = dtt200u_power_ctrl, 269 270 .rc.core = { 271 .rc_interval = 300, 272 .rc_codes = RC_MAP_DTT200U, 273 .rc_query = dtt200u_rc_query, 274 .allowed_protos = RC_BIT_NEC, 275 }, 276 277 .generic_bulk_ctrl_endpoint = 0x01, 278 279 .num_device_descs = 1, 280 .devices = { 281 { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)", 282 .cold_ids = { &dtt200u_usb_table[6], NULL }, 283 .warm_ids = { &dtt200u_usb_table[7], NULL }, 284 }, 285 { NULL }, 286 } 287 }; 288 289 static struct dvb_usb_device_properties wt220u_zl0353_properties = { 290 .usb_ctrl = CYPRESS_FX2, 291 .firmware = "dvb-usb-wt220u-zl0353-01.fw", 292 293 .num_adapters = 1, 294 .adapter = { 295 { 296 .num_frontends = 1, 297 .fe = {{ 298 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, 299 .pid_filter_count = 15, 300 301 .streaming_ctrl = dtt200u_streaming_ctrl, 302 .pid_filter = dtt200u_pid_filter, 303 .frontend_attach = dtt200u_frontend_attach, 304 /* parameter for the MPEG2-data transfer */ 305 .stream = { 306 .type = USB_BULK, 307 .count = 7, 308 .endpoint = 0x02, 309 .u = { 310 .bulk = { 311 .buffersize = 4096, 312 } 313 } 314 }, 315 }}, 316 } 317 }, 318 .power_ctrl = dtt200u_power_ctrl, 319 320 .rc.core = { 321 .rc_interval = 300, 322 .rc_codes = RC_MAP_DTT200U, 323 .rc_query = dtt200u_rc_query, 324 .allowed_protos = RC_BIT_NEC, 325 }, 326 327 .generic_bulk_ctrl_endpoint = 0x01, 328 329 .num_device_descs = 1, 330 .devices = { 331 { .name = "WideView WT-220U PenType Receiver (based on ZL353)", 332 .cold_ids = { &dtt200u_usb_table[4], NULL }, 333 .warm_ids = { &dtt200u_usb_table[5], NULL }, 334 }, 335 { NULL }, 336 } 337 }; 338 339 static struct dvb_usb_device_properties wt220u_miglia_properties = { 340 .usb_ctrl = CYPRESS_FX2, 341 .firmware = "dvb-usb-wt220u-miglia-01.fw", 342 343 .num_adapters = 1, 344 .generic_bulk_ctrl_endpoint = 0x01, 345 346 .num_device_descs = 1, 347 .devices = { 348 { .name = "WideView WT-220U PenType Receiver (Miglia)", 349 .cold_ids = { &dtt200u_usb_table[9], NULL }, 350 /* This device turns into WT220U_ZL0353_WARM when fw 351 has been uploaded */ 352 .warm_ids = { NULL }, 353 }, 354 { NULL }, 355 } 356 }; 357 358 /* usb specific object needed to register this driver with the usb subsystem */ 359 static struct usb_driver dtt200u_usb_driver = { 360 .name = "dvb_usb_dtt200u", 361 .probe = dtt200u_usb_probe, 362 .disconnect = dvb_usb_device_exit, 363 .id_table = dtt200u_usb_table, 364 }; 365 366 module_usb_driver(dtt200u_usb_driver); 367 368 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>"); 369 MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D/Miglia DVB-T USB2.0 devices"); 370 MODULE_VERSION("1.0"); 371 MODULE_LICENSE("GPL"); 372