vserver 2.0 rc7
[linux-2.6.git] / drivers / media / dvb / dibusb / dvb-dibusb-core.c
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");