Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame^] | 1 | /* |
| 2 | * Driver for mobile USB Budget DVB-T devices based on reference |
| 3 | * design made by DiBcom (http://www.dibcom.fr/) |
| 4 | * |
| 5 | * dvb-dibusb-core.c |
| 6 | * |
| 7 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) |
| 8 | * |
| 9 | * based on GPL code from DiBcom, which has |
| 10 | * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) |
| 11 | * |
| 12 | * Remote control code added by David Matthews (dm@prolingua.co.uk) |
| 13 | * |
| 14 | * This program is free software; you can redistribute it and/or |
| 15 | * modify it under the terms of the GNU General Public License as |
| 16 | * published by the Free Software Foundation, version 2. |
| 17 | * |
| 18 | * Acknowledgements |
| 19 | * |
| 20 | * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver |
| 21 | * sources, on which this driver (and the dib3000mb/mc/p frontends) are based. |
| 22 | * |
| 23 | * see Documentation/dvb/README.dibusb for more information |
| 24 | */ |
| 25 | #include "dvb-dibusb.h" |
| 26 | |
| 27 | #include <linux/moduleparam.h> |
| 28 | |
| 29 | /* debug */ |
| 30 | int dvb_dibusb_debug; |
| 31 | module_param_named(debug, dvb_dibusb_debug, int, 0644); |
| 32 | |
| 33 | #ifdef CONFIG_DVB_DIBCOM_DEBUG |
| 34 | #define DBSTATUS "" |
| 35 | #else |
| 36 | #define DBSTATUS " (debugging is not enabled)" |
| 37 | #endif |
| 38 | MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore,8=ts,16=err,32=rc (|-able))." DBSTATUS); |
| 39 | #undef DBSTATUS |
| 40 | |
| 41 | static int pid_parse; |
| 42 | module_param(pid_parse, int, 0644); |
| 43 | MODULE_PARM_DESC(pid_parse, "enable pid parsing (filtering) when running at USB2.0"); |
| 44 | |
| 45 | static int rc_query_interval = 100; |
| 46 | module_param(rc_query_interval, int, 0644); |
| 47 | MODULE_PARM_DESC(rc_query_interval, "interval in msecs for remote control query (default: 100; min: 40)"); |
| 48 | |
| 49 | static int rc_key_repeat_count = 2; |
| 50 | module_param(rc_key_repeat_count, int, 0644); |
| 51 | MODULE_PARM_DESC(rc_key_repeat_count, "how many key repeats will be dropped before passing the key event again (default: 2)"); |
| 52 | |
| 53 | /* Vendor IDs */ |
| 54 | #define USB_VID_ADSTECH 0x06e1 |
| 55 | #define USB_VID_ANCHOR 0x0547 |
| 56 | #define USB_VID_AVERMEDIA 0x14aa |
| 57 | #define USB_VID_COMPRO 0x185b |
| 58 | #define USB_VID_COMPRO_UNK 0x145f |
| 59 | #define USB_VID_CYPRESS 0x04b4 |
| 60 | #define USB_VID_DIBCOM 0x10b8 |
| 61 | #define USB_VID_EMPIA 0xeb1a |
| 62 | #define USB_VID_GRANDTEC 0x5032 |
| 63 | #define USB_VID_HANFTEK 0x15f4 |
| 64 | #define USB_VID_HAUPPAUGE 0x2040 |
| 65 | #define USB_VID_HYPER_PALTEK 0x1025 |
| 66 | #define USB_VID_IMC_NETWORKS 0x13d3 |
| 67 | #define USB_VID_TWINHAN 0x1822 |
| 68 | #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 |
| 69 | |
| 70 | /* Product IDs */ |
| 71 | #define USB_PID_ADSTECH_USB2_COLD 0xa333 |
| 72 | #define USB_PID_ADSTECH_USB2_WARM 0xa334 |
| 73 | #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 |
| 74 | #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 |
| 75 | #define USB_PID_COMPRO_DVBU2000_COLD 0xd000 |
| 76 | #define USB_PID_COMPRO_DVBU2000_WARM 0xd001 |
| 77 | #define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c |
| 78 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d |
| 79 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 |
| 80 | #define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9 |
| 81 | #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 |
| 82 | #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 |
| 83 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 |
| 84 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 |
| 85 | #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 |
| 86 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de |
| 87 | #define USB_PID_KWORLD_VSTREAM_WARM 0x17df |
| 88 | #define USB_PID_TWINHAN_VP7041_COLD 0x3201 |
| 89 | #define USB_PID_TWINHAN_VP7041_WARM 0x3202 |
| 90 | #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 |
| 91 | #define USB_PID_ULTIMA_TVBOX_WARM 0x8106 |
| 92 | #define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107 |
| 93 | #define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108 |
| 94 | #define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235 |
| 95 | #define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109 |
| 96 | #define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613 |
| 97 | #define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002 |
| 98 | #define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e |
| 99 | #define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f |
| 100 | #define USB_PID_HANFTEK_UMT_010_COLD 0x0001 |
| 101 | #define USB_PID_HANFTEK_UMT_010_WARM 0x0015 |
| 102 | #define USB_PID_YAKUMO_DTT200U_COLD 0x0201 |
| 103 | #define USB_PID_YAKUMO_DTT200U_WARM 0x0301 |
| 104 | #define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300 |
| 105 | #define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301 |
| 106 | |
| 107 | /* USB Driver stuff |
| 108 | * table of devices that this driver is working with |
| 109 | * |
| 110 | * ATTENTION: Never ever change the order of this table, the particular |
| 111 | * devices depend on this order |
| 112 | * |
| 113 | * Each entry is used as a reference in the device_struct. Currently this is |
| 114 | * the only non-redundant way of assigning USB ids to actual devices I'm aware |
| 115 | * of, because there is only one place in the code where the assignment of |
| 116 | * vendor and product id is done, here. |
| 117 | */ |
| 118 | static struct usb_device_id dib_table [] = { |
| 119 | /* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB_COLD)}, |
| 120 | /* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB_WARM)}, |
| 121 | /* 02 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_YAKUMO_DTT200U_COLD) }, |
| 122 | /* 03 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_YAKUMO_DTT200U_WARM) }, |
| 123 | |
| 124 | /* 04 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) }, |
| 125 | /* 05 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) }, |
| 126 | /* 06 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) }, |
| 127 | /* 07 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) }, |
| 128 | /* 08 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) }, |
| 129 | /* 09 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_COLD) }, |
| 130 | /* 10 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_WARM) }, |
| 131 | /* 11 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) }, |
| 132 | /* 12 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) }, |
| 133 | /* 13 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) }, |
| 134 | /* 14 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) }, |
| 135 | /* 15 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) }, |
| 136 | /* 16 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_WARM) }, |
| 137 | /* 17 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_COLD) }, |
| 138 | /* 18 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_WARM) }, |
| 139 | /* 19 */ { USB_DEVICE(USB_VID_IMC_NETWORKS, USB_PID_TWINHAN_VP7041_COLD) }, |
| 140 | /* 20 */ { USB_DEVICE(USB_VID_IMC_NETWORKS, USB_PID_TWINHAN_VP7041_WARM) }, |
| 141 | /* 21 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) }, |
| 142 | /* 22 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) }, |
| 143 | /* 23 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) }, |
| 144 | /* 24 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) }, |
| 145 | /* 25 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) }, |
| 146 | /* 26 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) }, |
| 147 | /* 27 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) }, |
| 148 | |
| 149 | /* 28 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_COLD) }, |
| 150 | /* 29 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_WARM) }, |
| 151 | |
| 152 | /* 30 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_COLD) }, |
| 153 | /* 31 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_WARM) }, |
| 154 | /* 32 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) }, |
| 155 | /* 33 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) }, |
| 156 | /* |
| 157 | * activate the following define when you have one of the devices and want to |
| 158 | * build it from build-2.6 in dvb-kernel |
| 159 | */ |
| 160 | // #define CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES |
| 161 | #ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES |
| 162 | /* 34 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) }, |
| 163 | /* 35 */ { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ULTIMA_TVBOX_USB2_FX_COLD) }, |
| 164 | /* 36 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_USB2_FX_WARM) }, |
| 165 | /* 37 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_DIBCOM_ANCHOR_2135_COLD) }, |
| 166 | #endif |
| 167 | { } /* Terminating entry */ |
| 168 | }; |
| 169 | |
| 170 | MODULE_DEVICE_TABLE (usb, dib_table); |
| 171 | |
| 172 | static struct dibusb_usb_controller dibusb_usb_ctrl[] = { |
| 173 | { .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 }, |
| 174 | { .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 }, |
| 175 | { .name = "Cypress FX2", .cpu_cs_register = 0xe600 }, |
| 176 | }; |
| 177 | |
| 178 | struct dibusb_tuner dibusb_tuner[] = { |
| 179 | { DIBUSB_TUNER_CABLE_THOMSON, |
| 180 | 0x61 |
| 181 | }, |
| 182 | { DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5, |
| 183 | 0x60 |
| 184 | }, |
| 185 | { DIBUSB_TUNER_CABLE_LG_TDTP_E102P, |
| 186 | 0x61 |
| 187 | }, |
| 188 | { DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5, |
| 189 | 0x60 |
| 190 | }, |
| 191 | }; |
| 192 | |
| 193 | static struct dibusb_demod dibusb_demod[] = { |
| 194 | { DIBUSB_DIB3000MB, |
| 195 | 16, |
| 196 | { 0x8, 0 }, |
| 197 | }, |
| 198 | { DIBUSB_DIB3000MC, |
| 199 | 32, |
| 200 | { 0x9, 0xa, 0xb, 0xc }, |
| 201 | }, |
| 202 | { DIBUSB_MT352, |
| 203 | 254, |
| 204 | { 0xf, 0 }, |
| 205 | }, |
| 206 | { DTT200U_FE, |
| 207 | 8, |
| 208 | { 0xff,0 }, /* there is no i2c bus in this device */ |
| 209 | } |
| 210 | }; |
| 211 | |
| 212 | static struct dibusb_device_class dibusb_device_classes[] = { |
| 213 | { .id = DIBUSB1_1, .usb_ctrl = &dibusb_usb_ctrl[0], |
| 214 | .firmware = "dvb-dibusb-5.0.0.11.fw", |
| 215 | .pipe_cmd = 0x01, .pipe_data = 0x02, |
| 216 | .urb_count = 7, .urb_buffer_size = 4096, |
| 217 | DIBUSB_RC_NEC_PROTOCOL, |
| 218 | &dibusb_demod[DIBUSB_DIB3000MB], |
| 219 | &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON], |
| 220 | }, |
| 221 | { DIBUSB1_1_AN2235, &dibusb_usb_ctrl[1], |
| 222 | "dvb-dibusb-an2235-1.fw", |
| 223 | 0x01, 0x02, |
| 224 | 7, 4096, |
| 225 | DIBUSB_RC_NEC_PROTOCOL, |
| 226 | &dibusb_demod[DIBUSB_DIB3000MB], |
| 227 | &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON], |
| 228 | }, |
| 229 | { DIBUSB2_0,&dibusb_usb_ctrl[2], |
| 230 | "dvb-dibusb-6.0.0.5.fw", |
| 231 | 0x01, 0x06, |
| 232 | 7, 4096, |
| 233 | DIBUSB_RC_NEC_PROTOCOL, |
| 234 | &dibusb_demod[DIBUSB_DIB3000MC], |
| 235 | &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5], |
| 236 | }, |
| 237 | { UMT2_0, &dibusb_usb_ctrl[2], |
| 238 | "dvb-dibusb-umt-2.fw", |
| 239 | 0x01, 0x06, |
| 240 | 20, 512, |
| 241 | DIBUSB_RC_NO, |
| 242 | &dibusb_demod[DIBUSB_MT352], |
| 243 | &dibusb_tuner[DIBUSB_TUNER_CABLE_LG_TDTP_E102P], |
| 244 | }, |
| 245 | { DIBUSB2_0B,&dibusb_usb_ctrl[2], |
| 246 | "dvb-dibusb-adstech-usb2-1.fw", |
| 247 | 0x01, 0x06, |
| 248 | 7, 4096, |
| 249 | DIBUSB_RC_NEC_PROTOCOL, |
| 250 | &dibusb_demod[DIBUSB_DIB3000MB], |
| 251 | &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON], |
| 252 | }, |
| 253 | { NOVAT_USB2,&dibusb_usb_ctrl[2], |
| 254 | "dvb-dibusb-nova-t-1.fw", |
| 255 | 0x01, 0x06, |
| 256 | 7, 4096, |
| 257 | DIBUSB_RC_HAUPPAUGE_PROTO, |
| 258 | &dibusb_demod[DIBUSB_DIB3000MC], |
| 259 | &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5], |
| 260 | }, |
| 261 | { DTT200U,&dibusb_usb_ctrl[2], |
| 262 | "dvb-dtt200u-1.fw", |
| 263 | 0x01, 0x02, |
| 264 | 7, 4096, |
| 265 | DIBUSB_RC_NO, |
| 266 | &dibusb_demod[DTT200U_FE], |
| 267 | NULL, /* no explicit tuner/pll-programming necessary (it has the ENV57H1XD5) */ |
| 268 | }, |
| 269 | }; |
| 270 | |
| 271 | static struct dibusb_usb_device dibusb_devices[] = { |
| 272 | { "TwinhanDTV USB1.1 / Magic Box / HAMA USB1.1 DVB-T device", |
| 273 | &dibusb_device_classes[DIBUSB1_1], |
| 274 | { &dib_table[19], &dib_table[21], NULL}, |
| 275 | { &dib_table[20], &dib_table[22], NULL}, |
| 276 | }, |
| 277 | { "KWorld V-Stream XPERT DTV - DVB-T USB1.1", |
| 278 | &dibusb_device_classes[DIBUSB1_1], |
| 279 | { &dib_table[11], NULL }, |
| 280 | { &dib_table[12], NULL }, |
| 281 | }, |
| 282 | { "Grandtec USB1.1 DVB-T", |
| 283 | &dibusb_device_classes[DIBUSB1_1], |
| 284 | { &dib_table[13], &dib_table[15], NULL }, |
| 285 | { &dib_table[14], &dib_table[16], NULL }, |
| 286 | }, |
| 287 | { "DiBcom USB1.1 DVB-T reference design (MOD3000)", |
| 288 | &dibusb_device_classes[DIBUSB1_1], |
| 289 | { &dib_table[7], NULL }, |
| 290 | { &dib_table[8], NULL }, |
| 291 | }, |
| 292 | { "Artec T1 USB1.1 TVBOX with AN2135", |
| 293 | &dibusb_device_classes[DIBUSB1_1], |
| 294 | { &dib_table[23], NULL }, |
| 295 | { &dib_table[24], NULL }, |
| 296 | }, |
| 297 | { "Artec T1 USB1.1 TVBOX with AN2235", |
| 298 | &dibusb_device_classes[DIBUSB1_1_AN2235], |
| 299 | { &dib_table[25], NULL }, |
| 300 | { &dib_table[26], NULL }, |
| 301 | }, |
| 302 | { "Avermedia AverTV DVBT USB1.1", |
| 303 | &dibusb_device_classes[DIBUSB1_1], |
| 304 | { &dib_table[0], NULL }, |
| 305 | { &dib_table[1], NULL }, |
| 306 | }, |
| 307 | { "Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)", |
| 308 | &dibusb_device_classes[DIBUSB1_1], |
| 309 | { &dib_table[4], &dib_table[6], NULL}, |
| 310 | { &dib_table[5], NULL }, |
| 311 | }, |
| 312 | { "Unkown USB1.1 DVB-T device ???? please report the name to the author", |
| 313 | &dibusb_device_classes[DIBUSB1_1], |
| 314 | { &dib_table[17], NULL }, |
| 315 | { &dib_table[18], NULL }, |
| 316 | }, |
| 317 | { "DiBcom USB2.0 DVB-T reference design (MOD3000P)", |
| 318 | &dibusb_device_classes[DIBUSB2_0], |
| 319 | { &dib_table[9], NULL }, |
| 320 | { &dib_table[10], NULL }, |
| 321 | }, |
| 322 | { "Artec T1 USB2.0 TVBOX (please report the warm ID)", |
| 323 | &dibusb_device_classes[DIBUSB2_0], |
| 324 | { &dib_table[27], NULL }, |
| 325 | { NULL }, |
| 326 | }, |
| 327 | { "Hauppauge WinTV NOVA-T USB2", |
| 328 | &dibusb_device_classes[NOVAT_USB2], |
| 329 | { &dib_table[30], NULL }, |
| 330 | { &dib_table[31], NULL }, |
| 331 | }, |
| 332 | { "DTT200U (Yakumo/Hama/Typhoon) DVB-T USB2.0", |
| 333 | &dibusb_device_classes[DTT200U], |
| 334 | { &dib_table[2], NULL }, |
| 335 | { &dib_table[3], NULL }, |
| 336 | }, |
| 337 | { "Hanftek UMT-010 DVB-T USB2.0", |
| 338 | &dibusb_device_classes[UMT2_0], |
| 339 | { &dib_table[28], NULL }, |
| 340 | { &dib_table[29], NULL }, |
| 341 | }, |
| 342 | { "KWorld/ADSTech Instant DVB-T USB 2.0", |
| 343 | &dibusb_device_classes[DIBUSB2_0B], |
| 344 | { &dib_table[32], NULL }, |
| 345 | { &dib_table[33], NULL }, /* device ID with default DIBUSB2_0-firmware */ |
| 346 | }, |
| 347 | #ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES |
| 348 | { "Artec T1 USB1.1 TVBOX with AN2235 (misdesigned)", |
| 349 | &dibusb_device_classes[DIBUSB1_1_AN2235], |
| 350 | { &dib_table[34], NULL }, |
| 351 | { NULL }, |
| 352 | }, |
| 353 | { "Artec T1 USB2.0 TVBOX with FX2 IDs (misdesigned, please report the warm ID)", |
| 354 | &dibusb_device_classes[DTT200U], |
| 355 | { &dib_table[35], NULL }, |
| 356 | { &dib_table[36], NULL }, /* undefined, it could be that the device will get another USB ID in warm state */ |
| 357 | }, |
| 358 | { "DiBcom USB1.1 DVB-T reference design (MOD3000) with AN2135 default IDs", |
| 359 | &dibusb_device_classes[DIBUSB1_1], |
| 360 | { &dib_table[37], NULL }, |
| 361 | { NULL }, |
| 362 | }, |
| 363 | #endif |
| 364 | }; |
| 365 | |
| 366 | static int dibusb_exit(struct usb_dibusb *dib) |
| 367 | { |
| 368 | deb_info("init_state before exiting everything: %x\n",dib->init_state); |
| 369 | dibusb_remote_exit(dib); |
| 370 | dibusb_fe_exit(dib); |
| 371 | dibusb_i2c_exit(dib); |
| 372 | dibusb_dvb_exit(dib); |
| 373 | dibusb_urb_exit(dib); |
| 374 | deb_info("init_state should be zero now: %x\n",dib->init_state); |
| 375 | dib->init_state = DIBUSB_STATE_INIT; |
| 376 | kfree(dib); |
| 377 | return 0; |
| 378 | } |
| 379 | |
| 380 | static int dibusb_init(struct usb_dibusb *dib) |
| 381 | { |
| 382 | int ret = 0; |
| 383 | sema_init(&dib->usb_sem, 1); |
| 384 | sema_init(&dib->i2c_sem, 1); |
| 385 | |
| 386 | dib->init_state = DIBUSB_STATE_INIT; |
| 387 | |
| 388 | if ((ret = dibusb_urb_init(dib)) || |
| 389 | (ret = dibusb_dvb_init(dib)) || |
| 390 | (ret = dibusb_i2c_init(dib))) { |
| 391 | dibusb_exit(dib); |
| 392 | return ret; |
| 393 | } |
| 394 | |
| 395 | if ((ret = dibusb_fe_init(dib))) |
| 396 | err("could not initialize a frontend."); |
| 397 | |
| 398 | if ((ret = dibusb_remote_init(dib))) |
| 399 | err("could not initialize remote control."); |
| 400 | |
| 401 | return 0; |
| 402 | } |
| 403 | |
| 404 | static struct dibusb_usb_device * dibusb_device_class_quirk(struct usb_device *udev, struct dibusb_usb_device *dev) |
| 405 | { |
| 406 | int i; |
| 407 | |
| 408 | /* Quirk for the Kworld/ADSTech Instant USB2.0 device. It has the same USB |
| 409 | * IDs like the USB1.1 KWorld after loading the firmware. Which is a bad |
| 410 | * idea and make this quirk necessary. |
| 411 | */ |
| 412 | if (dev->dev_cl->id == DIBUSB1_1 && udev->speed == USB_SPEED_HIGH) { |
| 413 | info("this seems to be the Kworld/ADSTech Instant USB2.0 device or equal."); |
| 414 | for (i = 0; i < sizeof(dibusb_devices)/sizeof(struct dibusb_usb_device); i++) { |
| 415 | if (dibusb_devices[i].dev_cl->id == DIBUSB2_0B) { |
| 416 | dev = &dibusb_devices[i]; |
| 417 | break; |
| 418 | } |
| 419 | } |
| 420 | } |
| 421 | |
| 422 | return dev; |
| 423 | } |
| 424 | |
| 425 | static struct dibusb_usb_device * dibusb_find_device (struct usb_device *udev,int *cold) |
| 426 | { |
| 427 | int i,j; |
| 428 | struct dibusb_usb_device *dev = NULL; |
| 429 | *cold = -1; |
| 430 | |
| 431 | for (i = 0; i < sizeof(dibusb_devices)/sizeof(struct dibusb_usb_device); i++) { |
| 432 | for (j = 0; j < DIBUSB_ID_MAX_NUM && dibusb_devices[i].cold_ids[j] != NULL; j++) { |
| 433 | deb_info("check for cold %x %x\n",dibusb_devices[i].cold_ids[j]->idVendor, dibusb_devices[i].cold_ids[j]->idProduct); |
| 434 | if (dibusb_devices[i].cold_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) && |
| 435 | dibusb_devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) { |
| 436 | *cold = 1; |
| 437 | dev = &dibusb_devices[i]; |
| 438 | break; |
| 439 | } |
| 440 | } |
| 441 | |
| 442 | if (dev != NULL) |
| 443 | break; |
| 444 | |
| 445 | for (j = 0; j < DIBUSB_ID_MAX_NUM && dibusb_devices[i].warm_ids[j] != NULL; j++) { |
| 446 | deb_info("check for warm %x %x\n",dibusb_devices[i].warm_ids[j]->idVendor, dibusb_devices[i].warm_ids[j]->idProduct); |
| 447 | if (dibusb_devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) && |
| 448 | dibusb_devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) { |
| 449 | *cold = 0; |
| 450 | dev = &dibusb_devices[i]; |
| 451 | break; |
| 452 | } |
| 453 | } |
| 454 | } |
| 455 | |
| 456 | if (dev != NULL) |
| 457 | dev = dibusb_device_class_quirk(udev,dev); |
| 458 | |
| 459 | return dev; |
| 460 | } |
| 461 | |
| 462 | /* |
| 463 | * USB |
| 464 | */ |
| 465 | static int dibusb_probe(struct usb_interface *intf, |
| 466 | const struct usb_device_id *id) |
| 467 | { |
| 468 | struct usb_device *udev = interface_to_usbdev(intf); |
| 469 | struct usb_dibusb *dib = NULL; |
| 470 | struct dibusb_usb_device *dibdev = NULL; |
| 471 | |
| 472 | int ret = -ENOMEM,cold=0; |
| 473 | |
| 474 | if ((dibdev = dibusb_find_device(udev,&cold)) == NULL) { |
| 475 | err("something went very wrong, " |
| 476 | "unknown product ID: %.4x",le16_to_cpu(udev->descriptor.idProduct)); |
| 477 | return -ENODEV; |
| 478 | } |
| 479 | |
| 480 | if (cold == 1) { |
| 481 | info("found a '%s' in cold state, will try to load a firmware",dibdev->name); |
| 482 | ret = dibusb_loadfirmware(udev,dibdev); |
| 483 | } else { |
| 484 | info("found a '%s' in warm state.",dibdev->name); |
| 485 | dib = kmalloc(sizeof(struct usb_dibusb),GFP_KERNEL); |
| 486 | if (dib == NULL) { |
| 487 | err("no memory"); |
| 488 | return ret; |
| 489 | } |
| 490 | memset(dib,0,sizeof(struct usb_dibusb)); |
| 491 | |
| 492 | dib->udev = udev; |
| 493 | dib->dibdev = dibdev; |
| 494 | |
| 495 | /* store parameters to structures */ |
| 496 | dib->rc_query_interval = rc_query_interval; |
| 497 | dib->pid_parse = pid_parse; |
| 498 | dib->rc_key_repeat_count = rc_key_repeat_count; |
| 499 | |
| 500 | usb_set_intfdata(intf, dib); |
| 501 | |
| 502 | ret = dibusb_init(dib); |
| 503 | } |
| 504 | |
| 505 | if (ret == 0) |
| 506 | info("%s successfully initialized and connected.",dibdev->name); |
| 507 | else |
| 508 | info("%s error while loading driver (%d)",dibdev->name,ret); |
| 509 | return ret; |
| 510 | } |
| 511 | |
| 512 | static void dibusb_disconnect(struct usb_interface *intf) |
| 513 | { |
| 514 | struct usb_dibusb *dib = usb_get_intfdata(intf); |
| 515 | const char *name = DRIVER_DESC; |
| 516 | |
| 517 | usb_set_intfdata(intf,NULL); |
| 518 | if (dib != NULL && dib->dibdev != NULL) { |
| 519 | name = dib->dibdev->name; |
| 520 | dibusb_exit(dib); |
| 521 | } |
| 522 | info("%s successfully deinitialized and disconnected.",name); |
| 523 | |
| 524 | } |
| 525 | |
| 526 | /* usb specific object needed to register this driver with the usb subsystem */ |
| 527 | static struct usb_driver dibusb_driver = { |
| 528 | .owner = THIS_MODULE, |
| 529 | .name = DRIVER_DESC, |
| 530 | .probe = dibusb_probe, |
| 531 | .disconnect = dibusb_disconnect, |
| 532 | .id_table = dib_table, |
| 533 | }; |
| 534 | |
| 535 | /* module stuff */ |
| 536 | static int __init usb_dibusb_init(void) |
| 537 | { |
| 538 | int result; |
| 539 | if ((result = usb_register(&dibusb_driver))) { |
| 540 | err("usb_register failed. Error number %d",result); |
| 541 | return result; |
| 542 | } |
| 543 | |
| 544 | return 0; |
| 545 | } |
| 546 | |
| 547 | static void __exit usb_dibusb_exit(void) |
| 548 | { |
| 549 | /* deregister this driver from the USB subsystem */ |
| 550 | usb_deregister(&dibusb_driver); |
| 551 | } |
| 552 | |
| 553 | module_init (usb_dibusb_init); |
| 554 | module_exit (usb_dibusb_exit); |
| 555 | |
| 556 | MODULE_AUTHOR(DRIVER_AUTHOR); |
| 557 | MODULE_DESCRIPTION(DRIVER_DESC); |
| 558 | MODULE_LICENSE("GPL"); |