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@desy.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 */ 17int dvb_usb_dtt200u_debug; 18module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644); 19MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS); 20 21DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 22 23static 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 33static 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 45static 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/* remote control */ 59/* key list for the tiny remote control (Yakumo, don't know about the others) */ 60static struct ir_scancode ir_codes_dtt200u_table[] = { 61 { 0x8001, KEY_MUTE }, 62 { 0x8002, KEY_CHANNELDOWN }, 63 { 0x8003, KEY_VOLUMEDOWN }, 64 { 0x8004, KEY_1 }, 65 { 0x8005, KEY_2 }, 66 { 0x8006, KEY_3 }, 67 { 0x8007, KEY_4 }, 68 { 0x8008, KEY_5 }, 69 { 0x8009, KEY_6 }, 70 { 0x800a, KEY_7 }, 71 { 0x800c, KEY_ZOOM }, 72 { 0x800d, KEY_0 }, 73 { 0x800e, KEY_SELECT }, 74 { 0x8012, KEY_POWER }, 75 { 0x801a, KEY_CHANNELUP }, 76 { 0x801b, KEY_8 }, 77 { 0x801e, KEY_VOLUMEUP }, 78 { 0x801f, KEY_9 }, 79}; 80 81static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state) 82{ 83 u8 key[5],cmd = GET_RC_CODE; 84 dvb_usb_generic_rw(d,&cmd,1,key,5,0); 85 dvb_usb_nec_rc_key_to_event(d,key,event,state); 86 if (key[0] != 0) 87 deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); 88 return 0; 89} 90 91static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap) 92{ 93 adap->fe = dtt200u_fe_attach(adap->dev); 94 return 0; 95} 96 97static struct dvb_usb_device_properties dtt200u_properties; 98static struct dvb_usb_device_properties wt220u_fc_properties; 99static struct dvb_usb_device_properties wt220u_properties; 100static struct dvb_usb_device_properties wt220u_zl0353_properties; 101static struct dvb_usb_device_properties wt220u_miglia_properties; 102 103static int dtt200u_usb_probe(struct usb_interface *intf, 104 const struct usb_device_id *id) 105{ 106 if (0 == dvb_usb_device_init(intf, &dtt200u_properties, 107 THIS_MODULE, NULL, adapter_nr) || 108 0 == dvb_usb_device_init(intf, &wt220u_properties, 109 THIS_MODULE, NULL, adapter_nr) || 110 0 == dvb_usb_device_init(intf, &wt220u_fc_properties, 111 THIS_MODULE, NULL, adapter_nr) || 112 0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties, 113 THIS_MODULE, NULL, adapter_nr) || 114 0 == dvb_usb_device_init(intf, &wt220u_miglia_properties, 115 THIS_MODULE, NULL, adapter_nr)) 116 return 0; 117 118 return -ENODEV; 119} 120 121static struct usb_device_id dtt200u_usb_table [] = { 122 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_COLD) }, 123 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_WARM) }, 124 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_COLD) }, 125 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM) }, 126 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_COLD) }, 127 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_WARM) }, 128 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_COLD) }, 129 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_WARM) }, 130 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZAP250_COLD) }, 131 { USB_DEVICE(USB_VID_MIGLIA, USB_PID_WT220U_ZAP250_COLD) }, 132 { 0 }, 133}; 134MODULE_DEVICE_TABLE(usb, dtt200u_usb_table); 135 136static struct dvb_usb_device_properties dtt200u_properties = { 137 .usb_ctrl = CYPRESS_FX2, 138 .firmware = "dvb-usb-dtt200u-01.fw", 139 140 .num_adapters = 1, 141 .adapter = { 142 { 143 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, 144 .pid_filter_count = 15, 145 146 .streaming_ctrl = dtt200u_streaming_ctrl, 147 .pid_filter = dtt200u_pid_filter, 148 .frontend_attach = dtt200u_frontend_attach, 149 /* parameter for the MPEG2-data transfer */ 150 .stream = { 151 .type = USB_BULK, 152 .count = 7, 153 .endpoint = 0x02, 154 .u = { 155 .bulk = { 156 .buffersize = 4096, 157 } 158 } 159 }, 160 } 161 }, 162 .power_ctrl = dtt200u_power_ctrl, 163 164 .rc.legacy = { 165 .rc_interval = 300, 166 .rc_key_map = ir_codes_dtt200u_table, 167 .rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table), 168 .rc_query = dtt200u_rc_query, 169 }, 170 171 .generic_bulk_ctrl_endpoint = 0x01, 172 173 .num_device_descs = 1, 174 .devices = { 175 { .name = "WideView/Yuan/Yakumo/Hama/Typhoon DVB-T USB2.0 (WT-200U)", 176 .cold_ids = { &dtt200u_usb_table[0], NULL }, 177 .warm_ids = { &dtt200u_usb_table[1], NULL }, 178 }, 179 { NULL }, 180 } 181}; 182 183static struct dvb_usb_device_properties wt220u_properties = { 184 .usb_ctrl = CYPRESS_FX2, 185 .firmware = "dvb-usb-wt220u-02.fw", 186 187 .num_adapters = 1, 188 .adapter = { 189 { 190 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, 191 .pid_filter_count = 15, 192 193 .streaming_ctrl = dtt200u_streaming_ctrl, 194 .pid_filter = dtt200u_pid_filter, 195 .frontend_attach = dtt200u_frontend_attach, 196 /* parameter for the MPEG2-data transfer */ 197 .stream = { 198 .type = USB_BULK, 199 .count = 7, 200 .endpoint = 0x02, 201 .u = { 202 .bulk = { 203 .buffersize = 4096, 204 } 205 } 206 }, 207 } 208 }, 209 .power_ctrl = dtt200u_power_ctrl, 210 211 .rc.legacy = { 212 .rc_interval = 300, 213 .rc_key_map = ir_codes_dtt200u_table, 214 .rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table), 215 .rc_query = dtt200u_rc_query, 216 }, 217 218 .generic_bulk_ctrl_endpoint = 0x01, 219 220 .num_device_descs = 1, 221 .devices = { 222 { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)", 223 .cold_ids = { &dtt200u_usb_table[2], &dtt200u_usb_table[8], NULL }, 224 .warm_ids = { &dtt200u_usb_table[3], NULL }, 225 }, 226 { NULL }, 227 } 228}; 229 230static struct dvb_usb_device_properties wt220u_fc_properties = { 231 .usb_ctrl = CYPRESS_FX2, 232 .firmware = "dvb-usb-wt220u-fc03.fw", 233 234 .num_adapters = 1, 235 .adapter = { 236 { 237 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, 238 .pid_filter_count = 15, 239 240 .streaming_ctrl = dtt200u_streaming_ctrl, 241 .pid_filter = dtt200u_pid_filter, 242 .frontend_attach = dtt200u_frontend_attach, 243 /* parameter for the MPEG2-data transfer */ 244 .stream = { 245 .type = USB_BULK, 246 .count = 7, 247 .endpoint = 0x06, 248 .u = { 249 .bulk = { 250 .buffersize = 4096, 251 } 252 } 253 }, 254 } 255 }, 256 .power_ctrl = dtt200u_power_ctrl, 257 258 .rc.legacy = { 259 .rc_interval = 300, 260 .rc_key_map = ir_codes_dtt200u_table, 261 .rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table), 262 .rc_query = dtt200u_rc_query, 263 }, 264 265 .generic_bulk_ctrl_endpoint = 0x01, 266 267 .num_device_descs = 1, 268 .devices = { 269 { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)", 270 .cold_ids = { &dtt200u_usb_table[6], NULL }, 271 .warm_ids = { &dtt200u_usb_table[7], NULL }, 272 }, 273 { NULL }, 274 } 275}; 276 277static struct dvb_usb_device_properties wt220u_zl0353_properties = { 278 .usb_ctrl = CYPRESS_FX2, 279 .firmware = "dvb-usb-wt220u-zl0353-01.fw", 280 281 .num_adapters = 1, 282 .adapter = { 283 { 284 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, 285 .pid_filter_count = 15, 286 287 .streaming_ctrl = dtt200u_streaming_ctrl, 288 .pid_filter = dtt200u_pid_filter, 289 .frontend_attach = dtt200u_frontend_attach, 290 /* parameter for the MPEG2-data transfer */ 291 .stream = { 292 .type = USB_BULK, 293 .count = 7, 294 .endpoint = 0x02, 295 .u = { 296 .bulk = { 297 .buffersize = 4096, 298 } 299 } 300 }, 301 } 302 }, 303 .power_ctrl = dtt200u_power_ctrl, 304 305 .rc.legacy = { 306 .rc_interval = 300, 307 .rc_key_map = ir_codes_dtt200u_table, 308 .rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table), 309 .rc_query = dtt200u_rc_query, 310 }, 311 312 .generic_bulk_ctrl_endpoint = 0x01, 313 314 .num_device_descs = 1, 315 .devices = { 316 { .name = "WideView WT-220U PenType Receiver (based on ZL353)", 317 .cold_ids = { &dtt200u_usb_table[4], NULL }, 318 .warm_ids = { &dtt200u_usb_table[5], NULL }, 319 }, 320 { NULL }, 321 } 322}; 323 324static struct dvb_usb_device_properties wt220u_miglia_properties = { 325 .usb_ctrl = CYPRESS_FX2, 326 .firmware = "dvb-usb-wt220u-miglia-01.fw", 327 328 .num_adapters = 1, 329 .generic_bulk_ctrl_endpoint = 0x01, 330 331 .num_device_descs = 1, 332 .devices = { 333 { .name = "WideView WT-220U PenType Receiver (Miglia)", 334 .cold_ids = { &dtt200u_usb_table[9], NULL }, 335 /* This device turns into WT220U_ZL0353_WARM when fw 336 has been uploaded */ 337 .warm_ids = { NULL }, 338 }, 339 { NULL }, 340 } 341}; 342 343/* usb specific object needed to register this driver with the usb subsystem */ 344static struct usb_driver dtt200u_usb_driver = { 345 .name = "dvb_usb_dtt200u", 346 .probe = dtt200u_usb_probe, 347 .disconnect = dvb_usb_device_exit, 348 .id_table = dtt200u_usb_table, 349}; 350 351/* module stuff */ 352static int __init dtt200u_usb_module_init(void) 353{ 354 int result; 355 if ((result = usb_register(&dtt200u_usb_driver))) { 356 err("usb_register failed. (%d)",result); 357 return result; 358 } 359 360 return 0; 361} 362 363static void __exit dtt200u_usb_module_exit(void) 364{ 365 /* deregister this driver from the USB subsystem */ 366 usb_deregister(&dtt200u_usb_driver); 367} 368 369module_init(dtt200u_usb_module_init); 370module_exit(dtt200u_usb_module_exit); 371 372MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); 373MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D/Miglia DVB-T USB2.0 devices"); 374MODULE_VERSION("1.0"); 375MODULE_LICENSE("GPL"); 376