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 rc_map_table rc_map_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: %*ph\n", 5, key); 88 return 0; 89} 90 91static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap) 92{ 93 adap->fe_adap[0].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 .num_frontends = 1, 144 .fe = {{ 145 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, 146 .pid_filter_count = 15, 147 148 .streaming_ctrl = dtt200u_streaming_ctrl, 149 .pid_filter = dtt200u_pid_filter, 150 .frontend_attach = dtt200u_frontend_attach, 151 /* parameter for the MPEG2-data transfer */ 152 .stream = { 153 .type = USB_BULK, 154 .count = 7, 155 .endpoint = 0x02, 156 .u = { 157 .bulk = { 158 .buffersize = 4096, 159 } 160 } 161 }, 162 }}, 163 } 164 }, 165 .power_ctrl = dtt200u_power_ctrl, 166 167 .rc.legacy = { 168 .rc_interval = 300, 169 .rc_map_table = rc_map_dtt200u_table, 170 .rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table), 171 .rc_query = dtt200u_rc_query, 172 }, 173 174 .generic_bulk_ctrl_endpoint = 0x01, 175 176 .num_device_descs = 1, 177 .devices = { 178 { .name = "WideView/Yuan/Yakumo/Hama/Typhoon DVB-T USB2.0 (WT-200U)", 179 .cold_ids = { &dtt200u_usb_table[0], NULL }, 180 .warm_ids = { &dtt200u_usb_table[1], NULL }, 181 }, 182 { NULL }, 183 } 184}; 185 186static struct dvb_usb_device_properties wt220u_properties = { 187 .usb_ctrl = CYPRESS_FX2, 188 .firmware = "dvb-usb-wt220u-02.fw", 189 190 .num_adapters = 1, 191 .adapter = { 192 { 193 .num_frontends = 1, 194 .fe = {{ 195 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, 196 .pid_filter_count = 15, 197 198 .streaming_ctrl = dtt200u_streaming_ctrl, 199 .pid_filter = dtt200u_pid_filter, 200 .frontend_attach = dtt200u_frontend_attach, 201 /* parameter for the MPEG2-data transfer */ 202 .stream = { 203 .type = USB_BULK, 204 .count = 7, 205 .endpoint = 0x02, 206 .u = { 207 .bulk = { 208 .buffersize = 4096, 209 } 210 } 211 }, 212 }}, 213 } 214 }, 215 .power_ctrl = dtt200u_power_ctrl, 216 217 .rc.legacy = { 218 .rc_interval = 300, 219 .rc_map_table = rc_map_dtt200u_table, 220 .rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table), 221 .rc_query = dtt200u_rc_query, 222 }, 223 224 .generic_bulk_ctrl_endpoint = 0x01, 225 226 .num_device_descs = 1, 227 .devices = { 228 { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)", 229 .cold_ids = { &dtt200u_usb_table[2], &dtt200u_usb_table[8], NULL }, 230 .warm_ids = { &dtt200u_usb_table[3], NULL }, 231 }, 232 { NULL }, 233 } 234}; 235 236static struct dvb_usb_device_properties wt220u_fc_properties = { 237 .usb_ctrl = CYPRESS_FX2, 238 .firmware = "dvb-usb-wt220u-fc03.fw", 239 240 .num_adapters = 1, 241 .adapter = { 242 { 243 .num_frontends = 1, 244 .fe = {{ 245 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, 246 .pid_filter_count = 15, 247 248 .streaming_ctrl = dtt200u_streaming_ctrl, 249 .pid_filter = dtt200u_pid_filter, 250 .frontend_attach = dtt200u_frontend_attach, 251 /* parameter for the MPEG2-data transfer */ 252 .stream = { 253 .type = USB_BULK, 254 .count = 7, 255 .endpoint = 0x06, 256 .u = { 257 .bulk = { 258 .buffersize = 4096, 259 } 260 } 261 }, 262 }}, 263 } 264 }, 265 .power_ctrl = dtt200u_power_ctrl, 266 267 .rc.legacy = { 268 .rc_interval = 300, 269 .rc_map_table = rc_map_dtt200u_table, 270 .rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table), 271 .rc_query = dtt200u_rc_query, 272 }, 273 274 .generic_bulk_ctrl_endpoint = 0x01, 275 276 .num_device_descs = 1, 277 .devices = { 278 { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)", 279 .cold_ids = { &dtt200u_usb_table[6], NULL }, 280 .warm_ids = { &dtt200u_usb_table[7], NULL }, 281 }, 282 { NULL }, 283 } 284}; 285 286static struct dvb_usb_device_properties wt220u_zl0353_properties = { 287 .usb_ctrl = CYPRESS_FX2, 288 .firmware = "dvb-usb-wt220u-zl0353-01.fw", 289 290 .num_adapters = 1, 291 .adapter = { 292 { 293 .num_frontends = 1, 294 .fe = {{ 295 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, 296 .pid_filter_count = 15, 297 298 .streaming_ctrl = dtt200u_streaming_ctrl, 299 .pid_filter = dtt200u_pid_filter, 300 .frontend_attach = dtt200u_frontend_attach, 301 /* parameter for the MPEG2-data transfer */ 302 .stream = { 303 .type = USB_BULK, 304 .count = 7, 305 .endpoint = 0x02, 306 .u = { 307 .bulk = { 308 .buffersize = 4096, 309 } 310 } 311 }, 312 }}, 313 } 314 }, 315 .power_ctrl = dtt200u_power_ctrl, 316 317 .rc.legacy = { 318 .rc_interval = 300, 319 .rc_map_table = rc_map_dtt200u_table, 320 .rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table), 321 .rc_query = dtt200u_rc_query, 322 }, 323 324 .generic_bulk_ctrl_endpoint = 0x01, 325 326 .num_device_descs = 1, 327 .devices = { 328 { .name = "WideView WT-220U PenType Receiver (based on ZL353)", 329 .cold_ids = { &dtt200u_usb_table[4], NULL }, 330 .warm_ids = { &dtt200u_usb_table[5], NULL }, 331 }, 332 { NULL }, 333 } 334}; 335 336static struct dvb_usb_device_properties wt220u_miglia_properties = { 337 .usb_ctrl = CYPRESS_FX2, 338 .firmware = "dvb-usb-wt220u-miglia-01.fw", 339 340 .num_adapters = 1, 341 .generic_bulk_ctrl_endpoint = 0x01, 342 343 .num_device_descs = 1, 344 .devices = { 345 { .name = "WideView WT-220U PenType Receiver (Miglia)", 346 .cold_ids = { &dtt200u_usb_table[9], NULL }, 347 /* This device turns into WT220U_ZL0353_WARM when fw 348 has been uploaded */ 349 .warm_ids = { NULL }, 350 }, 351 { NULL }, 352 } 353}; 354 355/* usb specific object needed to register this driver with the usb subsystem */ 356static struct usb_driver dtt200u_usb_driver = { 357 .name = "dvb_usb_dtt200u", 358 .probe = dtt200u_usb_probe, 359 .disconnect = dvb_usb_device_exit, 360 .id_table = dtt200u_usb_table, 361}; 362 363module_usb_driver(dtt200u_usb_driver); 364 365MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); 366MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D/Miglia DVB-T USB2.0 devices"); 367MODULE_VERSION("1.0"); 368MODULE_LICENSE("GPL"); 369