1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* DVB USB compliant linux driver for mobile DVB-T USB devices based on |
3 | * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-B) |
4 | * |
5 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) |
6 | * |
7 | * based on GPL code from DiBcom, which has |
8 | * Copyright (C) 2004 Amaury Demol for DiBcom |
9 | * |
10 | * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information |
11 | */ |
12 | #include "dibusb.h" |
13 | |
14 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
15 | |
16 | static int dib3000mb_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) |
17 | { |
18 | struct dvb_usb_adapter *adap = fe->dvb->priv; |
19 | struct dibusb_state *st = adap->priv; |
20 | |
21 | return st->ops.tuner_pass_ctrl(fe, enable, st->tuner_addr); |
22 | } |
23 | |
24 | static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_adapter *adap) |
25 | { |
26 | struct dib3000_config demod_cfg; |
27 | struct dibusb_state *st = adap->priv; |
28 | |
29 | demod_cfg.demod_address = 0x8; |
30 | |
31 | adap->fe_adap[0].fe = dvb_attach(dib3000mb_attach, &demod_cfg, |
32 | &adap->dev->i2c_adap, &st->ops); |
33 | if ((adap->fe_adap[0].fe) == NULL) |
34 | return -ENODEV; |
35 | |
36 | adap->fe_adap[0].fe->ops.i2c_gate_ctrl = dib3000mb_i2c_gate_ctrl; |
37 | |
38 | return 0; |
39 | } |
40 | |
41 | static int dibusb_thomson_tuner_attach(struct dvb_usb_adapter *adap) |
42 | { |
43 | struct dibusb_state *st = adap->priv; |
44 | |
45 | st->tuner_addr = 0x61; |
46 | |
47 | dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, &adap->dev->i2c_adap, |
48 | DVB_PLL_TUA6010XS); |
49 | return 0; |
50 | } |
51 | |
52 | static int dibusb_panasonic_tuner_attach(struct dvb_usb_adapter *adap) |
53 | { |
54 | struct dibusb_state *st = adap->priv; |
55 | |
56 | st->tuner_addr = 0x60; |
57 | |
58 | dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, |
59 | DVB_PLL_TDA665X); |
60 | return 0; |
61 | } |
62 | |
63 | /* Some of the Artec 1.1 device aren't equipped with the default tuner |
64 | * (Thomson Cable), but with a Panasonic ENV77H11D5. This function figures |
65 | * this out. */ |
66 | static int dibusb_tuner_probe_and_attach(struct dvb_usb_adapter *adap) |
67 | { |
68 | u8 b[2] = { 0,0 }, b2[1]; |
69 | int ret = 0; |
70 | struct i2c_msg msg[2] = { |
71 | { .flags = 0, .buf = b, .len = 2 }, |
72 | { .flags = I2C_M_RD, .buf = b2, .len = 1 }, |
73 | }; |
74 | struct dibusb_state *st = adap->priv; |
75 | |
76 | /* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */ |
77 | msg[0].addr = msg[1].addr = st->tuner_addr = 0x60; |
78 | |
79 | if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) |
80 | adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1); |
81 | |
82 | if (i2c_transfer(adap: &adap->dev->i2c_adap, msgs: msg, num: 2) != 2) { |
83 | err("tuner i2c write failed." ); |
84 | return -EREMOTEIO; |
85 | } |
86 | |
87 | if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) |
88 | adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0); |
89 | |
90 | if (b2[0] == 0xfe) { |
91 | info("This device has the Thomson Cable onboard. Which is default." ); |
92 | ret = dibusb_thomson_tuner_attach(adap); |
93 | } else { |
94 | info("This device has the Panasonic ENV77H11D5 onboard." ); |
95 | ret = dibusb_panasonic_tuner_attach(adap); |
96 | } |
97 | |
98 | return ret; |
99 | } |
100 | |
101 | /* USB Driver stuff */ |
102 | static struct dvb_usb_device_properties dibusb1_1_properties; |
103 | static struct dvb_usb_device_properties dibusb1_1_an2235_properties; |
104 | static struct dvb_usb_device_properties dibusb2_0b_properties; |
105 | static struct dvb_usb_device_properties artec_t1_usb2_properties; |
106 | |
107 | static int dibusb_probe(struct usb_interface *intf, |
108 | const struct usb_device_id *id) |
109 | { |
110 | if (0 == dvb_usb_device_init(intf, &dibusb1_1_properties, |
111 | THIS_MODULE, NULL, adapter_nums: adapter_nr) || |
112 | 0 == dvb_usb_device_init(intf, &dibusb1_1_an2235_properties, |
113 | THIS_MODULE, NULL, adapter_nums: adapter_nr) || |
114 | 0 == dvb_usb_device_init(intf, &dibusb2_0b_properties, |
115 | THIS_MODULE, NULL, adapter_nums: adapter_nr) || |
116 | 0 == dvb_usb_device_init(intf, &artec_t1_usb2_properties, |
117 | THIS_MODULE, NULL, adapter_nums: adapter_nr)) |
118 | return 0; |
119 | |
120 | return -EINVAL; |
121 | } |
122 | |
123 | /* do not change the order of the ID table */ |
124 | enum { |
125 | WIDEVIEW_DVBT_USB_COLD, |
126 | WIDEVIEW_DVBT_USB_WARM, |
127 | COMPRO_DVBU2000_COLD, |
128 | COMPRO_DVBU2000_WARM, |
129 | COMPRO_DVBU2000_UNK_COLD, |
130 | DIBCOM_MOD3000_COLD, |
131 | DIBCOM_MOD3000_WARM, |
132 | EMPIA_VSTREAM_COLD, |
133 | EMPIA_VSTREAM_WARM, |
134 | GRANDTEC_DVBT_USB_COLD, |
135 | GRANDTEC_DVBT_USB_WARM, |
136 | GRANDTEC_MOD3000_COLD, |
137 | GRANDTEC_MOD3000_WARM, |
138 | UNK_HYPER_PALTEK_COLD, |
139 | UNK_HYPER_PALTEK_WARM, |
140 | VISIONPLUS_VP7041_COLD, |
141 | VISIONPLUS_VP7041_WARM, |
142 | TWINHAN_VP7041_COLD, |
143 | TWINHAN_VP7041_WARM, |
144 | ULTIMA_TVBOX_COLD, |
145 | ULTIMA_TVBOX_WARM, |
146 | ULTIMA_TVBOX_AN2235_COLD, |
147 | ULTIMA_TVBOX_AN2235_WARM, |
148 | ADSTECH_USB2_COLD, |
149 | ADSTECH_USB2_WARM, |
150 | KYE_DVB_T_COLD, |
151 | KYE_DVB_T_WARM, |
152 | KWORLD_VSTREAM_COLD, |
153 | ULTIMA_TVBOX_USB2_COLD, |
154 | ULTIMA_TVBOX_USB2_WARM, |
155 | ULTIMA_TVBOX_ANCHOR_COLD, |
156 | }; |
157 | |
158 | static struct usb_device_id dibusb_dib3000mb_table[] = { |
159 | DVB_USB_DEV(WIDEVIEW, WIDEVIEW_DVBT_USB_COLD), |
160 | DVB_USB_DEV(WIDEVIEW, WIDEVIEW_DVBT_USB_WARM), |
161 | DVB_USB_DEV(COMPRO, COMPRO_DVBU2000_COLD), |
162 | DVB_USB_DEV(COMPRO, COMPRO_DVBU2000_WARM), |
163 | DVB_USB_DEV(COMPRO_UNK, COMPRO_DVBU2000_UNK_COLD), |
164 | DVB_USB_DEV(DIBCOM, DIBCOM_MOD3000_COLD), |
165 | DVB_USB_DEV(DIBCOM, DIBCOM_MOD3000_WARM), |
166 | DVB_USB_DEV(EMPIA, EMPIA_VSTREAM_COLD), |
167 | DVB_USB_DEV(EMPIA, EMPIA_VSTREAM_WARM), |
168 | DVB_USB_DEV(GRANDTEC, GRANDTEC_DVBT_USB_COLD), |
169 | DVB_USB_DEV(GRANDTEC, GRANDTEC_DVBT_USB_WARM), |
170 | DVB_USB_DEV(GRANDTEC, GRANDTEC_MOD3000_COLD), |
171 | DVB_USB_DEV(GRANDTEC, GRANDTEC_MOD3000_WARM), |
172 | DVB_USB_DEV(HYPER_PALTEK, UNK_HYPER_PALTEK_COLD), |
173 | DVB_USB_DEV(HYPER_PALTEK, UNK_HYPER_PALTEK_WARM), |
174 | DVB_USB_DEV(VISIONPLUS, VISIONPLUS_VP7041_COLD), |
175 | DVB_USB_DEV(VISIONPLUS, VISIONPLUS_VP7041_WARM), |
176 | DVB_USB_DEV(TWINHAN, TWINHAN_VP7041_COLD), |
177 | DVB_USB_DEV(TWINHAN, TWINHAN_VP7041_WARM), |
178 | DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_COLD), |
179 | DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_WARM), |
180 | DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_AN2235_COLD), |
181 | DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_AN2235_WARM), |
182 | DVB_USB_DEV(ADSTECH, ADSTECH_USB2_COLD), |
183 | DVB_USB_DEV(ADSTECH, ADSTECH_USB2_WARM), |
184 | DVB_USB_DEV(KYE, KYE_DVB_T_COLD), |
185 | DVB_USB_DEV(KYE, KYE_DVB_T_WARM), |
186 | DVB_USB_DEV(KWORLD, KWORLD_VSTREAM_COLD), |
187 | DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_USB2_COLD), |
188 | DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_USB2_WARM), |
189 | #ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY |
190 | DVB_USB_DEV(ANCHOR, ULTIMA_TVBOX_ANCHOR_COLD), |
191 | #endif |
192 | { } |
193 | }; |
194 | |
195 | MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table); |
196 | |
197 | static struct dvb_usb_device_properties dibusb1_1_properties = { |
198 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, |
199 | |
200 | .usb_ctrl = CYPRESS_AN2135, |
201 | |
202 | .firmware = "dvb-usb-dibusb-5.0.0.11.fw" , |
203 | |
204 | .num_adapters = 1, |
205 | .adapter = { |
206 | { |
207 | .num_frontends = 1, |
208 | .fe = {{ |
209 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
210 | .pid_filter_count = 16, |
211 | |
212 | .streaming_ctrl = dibusb_streaming_ctrl, |
213 | .pid_filter = dibusb_pid_filter, |
214 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
215 | .frontend_attach = dibusb_dib3000mb_frontend_attach, |
216 | .tuner_attach = dibusb_tuner_probe_and_attach, |
217 | |
218 | /* parameter for the MPEG2-data transfer */ |
219 | .stream = { |
220 | .type = USB_BULK, |
221 | .count = 7, |
222 | .endpoint = 0x02, |
223 | .u = { |
224 | .bulk = { |
225 | .buffersize = 4096, |
226 | } |
227 | } |
228 | }, |
229 | }}, |
230 | .size_of_priv = sizeof(struct dibusb_state), |
231 | } |
232 | }, |
233 | |
234 | .power_ctrl = dibusb_power_ctrl, |
235 | |
236 | .rc.legacy = { |
237 | .rc_interval = DEFAULT_RC_INTERVAL, |
238 | .rc_map_table = rc_map_dibusb_table, |
239 | .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ |
240 | .rc_query = dibusb_rc_query, |
241 | }, |
242 | |
243 | .i2c_algo = &dibusb_i2c_algo, |
244 | |
245 | .generic_bulk_ctrl_endpoint = 0x01, |
246 | |
247 | .num_device_descs = 9, |
248 | .devices = { |
249 | { "AVerMedia AverTV DVBT USB1.1" , |
250 | { &dibusb_dib3000mb_table[WIDEVIEW_DVBT_USB_COLD], NULL }, |
251 | { &dibusb_dib3000mb_table[WIDEVIEW_DVBT_USB_WARM], NULL }, |
252 | }, |
253 | { "Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)" , |
254 | { &dibusb_dib3000mb_table[COMPRO_DVBU2000_COLD], &dibusb_dib3000mb_table[COMPRO_DVBU2000_UNK_COLD], NULL}, |
255 | { &dibusb_dib3000mb_table[COMPRO_DVBU2000_WARM], NULL }, |
256 | }, |
257 | { "DiBcom USB1.1 DVB-T reference design (MOD3000)" , |
258 | { &dibusb_dib3000mb_table[DIBCOM_MOD3000_COLD], NULL }, |
259 | { &dibusb_dib3000mb_table[DIBCOM_MOD3000_WARM], NULL }, |
260 | }, |
261 | { "KWorld V-Stream XPERT DTV - DVB-T USB1.1" , |
262 | { &dibusb_dib3000mb_table[EMPIA_VSTREAM_COLD], NULL }, |
263 | { &dibusb_dib3000mb_table[EMPIA_VSTREAM_WARM], NULL }, |
264 | }, |
265 | { "Grandtec USB1.1 DVB-T" , |
266 | { &dibusb_dib3000mb_table[GRANDTEC_DVBT_USB_COLD], &dibusb_dib3000mb_table[GRANDTEC_MOD3000_COLD], NULL }, |
267 | { &dibusb_dib3000mb_table[GRANDTEC_DVBT_USB_WARM], &dibusb_dib3000mb_table[GRANDTEC_MOD3000_WARM], NULL }, |
268 | }, |
269 | { "Unknown USB1.1 DVB-T device ???? please report the name to the author" , |
270 | { &dibusb_dib3000mb_table[UNK_HYPER_PALTEK_COLD], NULL }, |
271 | { &dibusb_dib3000mb_table[UNK_HYPER_PALTEK_WARM], NULL }, |
272 | }, |
273 | { "TwinhanDTV USB-Ter USB1.1 / Magic Box I / HAMA USB1.1 DVB-T device" , |
274 | { &dibusb_dib3000mb_table[VISIONPLUS_VP7041_COLD], &dibusb_dib3000mb_table[TWINHAN_VP7041_COLD], NULL}, |
275 | { &dibusb_dib3000mb_table[VISIONPLUS_VP7041_WARM], &dibusb_dib3000mb_table[TWINHAN_VP7041_WARM], NULL}, |
276 | }, |
277 | { "Artec T1 USB1.1 TVBOX with AN2135" , |
278 | { &dibusb_dib3000mb_table[ULTIMA_TVBOX_COLD], NULL }, |
279 | { &dibusb_dib3000mb_table[ULTIMA_TVBOX_WARM], NULL }, |
280 | }, |
281 | { "VideoWalker DVB-T USB" , |
282 | { &dibusb_dib3000mb_table[KYE_DVB_T_COLD], NULL }, |
283 | { &dibusb_dib3000mb_table[KYE_DVB_T_WARM], NULL }, |
284 | }, |
285 | } |
286 | }; |
287 | |
288 | static struct dvb_usb_device_properties dibusb1_1_an2235_properties = { |
289 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, |
290 | .usb_ctrl = CYPRESS_AN2235, |
291 | |
292 | .firmware = "dvb-usb-dibusb-an2235-01.fw" , |
293 | |
294 | .num_adapters = 1, |
295 | .adapter = { |
296 | { |
297 | .num_frontends = 1, |
298 | .fe = {{ |
299 | .caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER, |
300 | .pid_filter_count = 16, |
301 | |
302 | .streaming_ctrl = dibusb_streaming_ctrl, |
303 | .pid_filter = dibusb_pid_filter, |
304 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
305 | .frontend_attach = dibusb_dib3000mb_frontend_attach, |
306 | .tuner_attach = dibusb_tuner_probe_and_attach, |
307 | |
308 | /* parameter for the MPEG2-data transfer */ |
309 | .stream = { |
310 | .type = USB_BULK, |
311 | .count = 7, |
312 | .endpoint = 0x02, |
313 | .u = { |
314 | .bulk = { |
315 | .buffersize = 4096, |
316 | } |
317 | } |
318 | }, |
319 | }}, |
320 | .size_of_priv = sizeof(struct dibusb_state), |
321 | }, |
322 | }, |
323 | .power_ctrl = dibusb_power_ctrl, |
324 | |
325 | .rc.legacy = { |
326 | .rc_interval = DEFAULT_RC_INTERVAL, |
327 | .rc_map_table = rc_map_dibusb_table, |
328 | .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ |
329 | .rc_query = dibusb_rc_query, |
330 | }, |
331 | |
332 | .i2c_algo = &dibusb_i2c_algo, |
333 | |
334 | .generic_bulk_ctrl_endpoint = 0x01, |
335 | |
336 | #ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY |
337 | .num_device_descs = 2, |
338 | #else |
339 | .num_device_descs = 1, |
340 | #endif |
341 | .devices = { |
342 | { "Artec T1 USB1.1 TVBOX with AN2235" , |
343 | { &dibusb_dib3000mb_table[ULTIMA_TVBOX_AN2235_COLD], NULL }, |
344 | { &dibusb_dib3000mb_table[ULTIMA_TVBOX_AN2235_WARM], NULL }, |
345 | }, |
346 | #ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY |
347 | { "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)" , |
348 | { &dibusb_dib3000mb_table[ULTIMA_TVBOX_ANCHOR_COLD], NULL }, |
349 | { NULL }, |
350 | }, |
351 | { NULL }, |
352 | #endif |
353 | } |
354 | }; |
355 | |
356 | static struct dvb_usb_device_properties dibusb2_0b_properties = { |
357 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, |
358 | |
359 | .usb_ctrl = CYPRESS_FX2, |
360 | |
361 | .firmware = "dvb-usb-adstech-usb2-02.fw" , |
362 | |
363 | .num_adapters = 1, |
364 | .adapter = { |
365 | { |
366 | .num_frontends = 1, |
367 | .fe = {{ |
368 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
369 | .pid_filter_count = 16, |
370 | |
371 | .streaming_ctrl = dibusb2_0_streaming_ctrl, |
372 | .pid_filter = dibusb_pid_filter, |
373 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
374 | .frontend_attach = dibusb_dib3000mb_frontend_attach, |
375 | .tuner_attach = dibusb_thomson_tuner_attach, |
376 | |
377 | /* parameter for the MPEG2-data transfer */ |
378 | .stream = { |
379 | .type = USB_BULK, |
380 | .count = 7, |
381 | .endpoint = 0x06, |
382 | .u = { |
383 | .bulk = { |
384 | .buffersize = 4096, |
385 | } |
386 | } |
387 | }, |
388 | }}, |
389 | .size_of_priv = sizeof(struct dibusb_state), |
390 | } |
391 | }, |
392 | .power_ctrl = dibusb2_0_power_ctrl, |
393 | |
394 | .rc.legacy = { |
395 | .rc_interval = DEFAULT_RC_INTERVAL, |
396 | .rc_map_table = rc_map_dibusb_table, |
397 | .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ |
398 | .rc_query = dibusb_rc_query, |
399 | }, |
400 | |
401 | .i2c_algo = &dibusb_i2c_algo, |
402 | |
403 | .generic_bulk_ctrl_endpoint = 0x01, |
404 | |
405 | .num_device_descs = 2, |
406 | .devices = { |
407 | { "KWorld/ADSTech Instant DVB-T USB2.0" , |
408 | { &dibusb_dib3000mb_table[ADSTECH_USB2_COLD], NULL }, |
409 | { &dibusb_dib3000mb_table[ADSTECH_USB2_WARM], NULL }, |
410 | }, |
411 | { "KWorld Xpert DVB-T USB2.0" , |
412 | { &dibusb_dib3000mb_table[KWORLD_VSTREAM_COLD], NULL }, |
413 | { NULL } |
414 | }, |
415 | { NULL }, |
416 | } |
417 | }; |
418 | |
419 | static struct dvb_usb_device_properties artec_t1_usb2_properties = { |
420 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, |
421 | |
422 | .usb_ctrl = CYPRESS_FX2, |
423 | |
424 | .firmware = "dvb-usb-dibusb-6.0.0.8.fw" , |
425 | |
426 | .num_adapters = 1, |
427 | .adapter = { |
428 | { |
429 | .num_frontends = 1, |
430 | .fe = {{ |
431 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
432 | .pid_filter_count = 16, |
433 | |
434 | .streaming_ctrl = dibusb2_0_streaming_ctrl, |
435 | .pid_filter = dibusb_pid_filter, |
436 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
437 | .frontend_attach = dibusb_dib3000mb_frontend_attach, |
438 | .tuner_attach = dibusb_tuner_probe_and_attach, |
439 | /* parameter for the MPEG2-data transfer */ |
440 | .stream = { |
441 | .type = USB_BULK, |
442 | .count = 7, |
443 | .endpoint = 0x06, |
444 | .u = { |
445 | .bulk = { |
446 | .buffersize = 4096, |
447 | } |
448 | } |
449 | }, |
450 | }}, |
451 | .size_of_priv = sizeof(struct dibusb_state), |
452 | } |
453 | }, |
454 | .power_ctrl = dibusb2_0_power_ctrl, |
455 | |
456 | .rc.legacy = { |
457 | .rc_interval = DEFAULT_RC_INTERVAL, |
458 | .rc_map_table = rc_map_dibusb_table, |
459 | .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ |
460 | .rc_query = dibusb_rc_query, |
461 | }, |
462 | |
463 | .i2c_algo = &dibusb_i2c_algo, |
464 | |
465 | .generic_bulk_ctrl_endpoint = 0x01, |
466 | |
467 | .num_device_descs = 1, |
468 | .devices = { |
469 | { "Artec T1 USB2.0" , |
470 | { &dibusb_dib3000mb_table[ULTIMA_TVBOX_USB2_COLD], NULL }, |
471 | { &dibusb_dib3000mb_table[ULTIMA_TVBOX_USB2_WARM], NULL }, |
472 | }, |
473 | { NULL }, |
474 | } |
475 | }; |
476 | |
477 | static struct usb_driver dibusb_driver = { |
478 | .name = "dvb_usb_dibusb_mb" , |
479 | .probe = dibusb_probe, |
480 | .disconnect = dvb_usb_device_exit, |
481 | .id_table = dibusb_dib3000mb_table, |
482 | }; |
483 | |
484 | module_usb_driver(dibusb_driver); |
485 | |
486 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>" ); |
487 | MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)" ); |
488 | MODULE_VERSION("1.0" ); |
489 | MODULE_LICENSE("GPL" ); |
490 | |