Linux-2.6.12-rc2
[linux-2.6/next.git] / drivers / media / dvb / dibusb / dvb-dibusb-core.c
blob26235f9247e4588e25e20ea6b8c999ac14317713
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)
12 * Remote control code added by David Matthews (dm@prolingua.co.uk)
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.
18 * Acknowledgements
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.
23 * see Documentation/dvb/README.dibusb for more information
25 #include "dvb-dibusb.h"
27 #include <linux/moduleparam.h>
29 /* debug */
30 int dvb_dibusb_debug;
31 module_param_named(debug, dvb_dibusb_debug, int, 0644);
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
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");
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)");
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)");
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
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
107 /* USB Driver stuff
108 * table of devices that this driver is working with
110 * ATTENTION: Never ever change the order of this table, the particular
111 * devices depend on this order
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.
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) },
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) },
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) },
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) },
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
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 */
170 MODULE_DEVICE_TABLE (usb, dib_table);
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 },
178 struct dibusb_tuner dibusb_tuner[] = {
179 { DIBUSB_TUNER_CABLE_THOMSON,
180 0x61
182 { DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5,
183 0x60
185 { DIBUSB_TUNER_CABLE_LG_TDTP_E102P,
186 0x61
188 { DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5,
189 0x60
193 static struct dibusb_demod dibusb_demod[] = {
194 { DIBUSB_DIB3000MB,
196 { 0x8, 0 },
198 { DIBUSB_DIB3000MC,
200 { 0x9, 0xa, 0xb, 0xc },
202 { DIBUSB_MT352,
203 254,
204 { 0xf, 0 },
206 { DTT200U_FE,
208 { 0xff,0 }, /* there is no i2c bus in this device */
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],
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],
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],
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],
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],
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],
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) */
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},
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 },
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 },
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 },
292 { "Artec T1 USB1.1 TVBOX with AN2135",
293 &dibusb_device_classes[DIBUSB1_1],
294 { &dib_table[23], NULL },
295 { &dib_table[24], NULL },
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 },
302 { "Avermedia AverTV DVBT USB1.1",
303 &dibusb_device_classes[DIBUSB1_1],
304 { &dib_table[0], NULL },
305 { &dib_table[1], NULL },
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 },
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 },
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 },
322 { "Artec T1 USB2.0 TVBOX (please report the warm ID)",
323 &dibusb_device_classes[DIBUSB2_0],
324 { &dib_table[27], NULL },
325 { NULL },
327 { "Hauppauge WinTV NOVA-T USB2",
328 &dibusb_device_classes[NOVAT_USB2],
329 { &dib_table[30], NULL },
330 { &dib_table[31], NULL },
332 { "DTT200U (Yakumo/Hama/Typhoon) DVB-T USB2.0",
333 &dibusb_device_classes[DTT200U],
334 { &dib_table[2], NULL },
335 { &dib_table[3], NULL },
337 { "Hanftek UMT-010 DVB-T USB2.0",
338 &dibusb_device_classes[UMT2_0],
339 { &dib_table[28], NULL },
340 { &dib_table[29], NULL },
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 */
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 },
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 */
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 },
363 #endif
366 static int dibusb_exit(struct usb_dibusb *dib)
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;
380 static int dibusb_init(struct usb_dibusb *dib)
382 int ret = 0;
383 sema_init(&dib->usb_sem, 1);
384 sema_init(&dib->i2c_sem, 1);
386 dib->init_state = DIBUSB_STATE_INIT;
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;
395 if ((ret = dibusb_fe_init(dib)))
396 err("could not initialize a frontend.");
398 if ((ret = dibusb_remote_init(dib)))
399 err("could not initialize remote control.");
401 return 0;
404 static struct dibusb_usb_device * dibusb_device_class_quirk(struct usb_device *udev, struct dibusb_usb_device *dev)
406 int i;
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.
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;
422 return dev;
425 static struct dibusb_usb_device * dibusb_find_device (struct usb_device *udev,int *cold)
427 int i,j;
428 struct dibusb_usb_device *dev = NULL;
429 *cold = -1;
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;
442 if (dev != NULL)
443 break;
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;
456 if (dev != NULL)
457 dev = dibusb_device_class_quirk(udev,dev);
459 return dev;
463 * USB
465 static int dibusb_probe(struct usb_interface *intf,
466 const struct usb_device_id *id)
468 struct usb_device *udev = interface_to_usbdev(intf);
469 struct usb_dibusb *dib = NULL;
470 struct dibusb_usb_device *dibdev = NULL;
472 int ret = -ENOMEM,cold=0;
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;
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;
490 memset(dib,0,sizeof(struct usb_dibusb));
492 dib->udev = udev;
493 dib->dibdev = dibdev;
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;
500 usb_set_intfdata(intf, dib);
502 ret = dibusb_init(dib);
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;
512 static void dibusb_disconnect(struct usb_interface *intf)
514 struct usb_dibusb *dib = usb_get_intfdata(intf);
515 const char *name = DRIVER_DESC;
517 usb_set_intfdata(intf,NULL);
518 if (dib != NULL && dib->dibdev != NULL) {
519 name = dib->dibdev->name;
520 dibusb_exit(dib);
522 info("%s successfully deinitialized and disconnected.",name);
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,
535 /* module stuff */
536 static int __init usb_dibusb_init(void)
538 int result;
539 if ((result = usb_register(&dibusb_driver))) {
540 err("usb_register failed. Error number %d",result);
541 return result;
544 return 0;
547 static void __exit usb_dibusb_exit(void)
549 /* deregister this driver from the USB subsystem */
550 usb_deregister(&dibusb_driver);
553 module_init (usb_dibusb_init);
554 module_exit (usb_dibusb_exit);
556 MODULE_AUTHOR(DRIVER_AUTHOR);
557 MODULE_DESCRIPTION(DRIVER_DESC);
558 MODULE_LICENSE("GPL");