]>
Commit | Line | Data |
---|---|---|
fb41f5a7 | 1 | /* DVB USB library compliant Linux driver for the WideView/ Yakumo/ Hama/ |
d3c35acf | 2 | * Typhoon/ Yuan/ Miglia DVB-T USB2.0 receiver. |
776338e1 | 3 | * |
99e44da7 | 4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) |
776338e1 | 5 | * |
d590f9c2 PB |
6 | * Thanks to Steve Chang from WideView for providing support for the WT-220U. |
7 | * | |
776338e1 JS |
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 */ | |
17 | int dvb_usb_dtt200u_debug; | |
18 | module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644); | |
19 | MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS); | |
20 | ||
78e92006 JG |
21 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
22 | ||
ab883e2d MCC |
23 | struct dtt200u_state { |
24 | unsigned char data[80]; | |
25 | struct mutex data_mutex; | |
26 | }; | |
27 | ||
d590f9c2 PB |
28 | static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff) |
29 | { | |
ab883e2d MCC |
30 | struct dtt200u_state *st = d->priv; |
31 | ||
32 | mutex_lock(&st->data_mutex); | |
33 | ||
34 | st->data[0] = SET_INIT; | |
d590f9c2 PB |
35 | |
36 | if (onoff) | |
ab883e2d | 37 | dvb_usb_generic_write(d, st->data, 2); |
d590f9c2 | 38 | |
ab883e2d | 39 | mutex_unlock(&st->data_mutex); |
d590f9c2 PB |
40 | return 0; |
41 | } | |
42 | ||
4d43e13f | 43 | static int dtt200u_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) |
776338e1 | 44 | { |
ab883e2d MCC |
45 | struct dtt200u_state *st = adap->dev->priv; |
46 | ||
47 | mutex_lock(&st->data_mutex); | |
48 | st->data[0] = SET_STREAMING; | |
49 | st->data[1] = onoff; | |
776338e1 | 50 | |
ab883e2d MCC |
51 | dvb_usb_generic_write(adap->dev, st->data, 2); |
52 | ||
53 | if (onoff) | |
54 | return 0; | |
55 | ||
56 | st->data[0] = RESET_PID_FILTER; | |
57 | dvb_usb_generic_write(adap->dev, st->data, 1); | |
58 | ||
59 | mutex_unlock(&st->data_mutex); | |
776338e1 | 60 | |
776338e1 JS |
61 | return 0; |
62 | } | |
63 | ||
4d43e13f | 64 | static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) |
776338e1 | 65 | { |
ab883e2d MCC |
66 | struct dtt200u_state *st = adap->dev->priv; |
67 | int ret; | |
68 | ||
776338e1 JS |
69 | pid = onoff ? pid : 0; |
70 | ||
ab883e2d MCC |
71 | mutex_lock(&st->data_mutex); |
72 | st->data[0] = SET_PID_FILTER; | |
73 | st->data[1] = index; | |
74 | st->data[2] = pid & 0xff; | |
75 | st->data[3] = (pid >> 8) & 0x1f; | |
776338e1 | 76 | |
ab883e2d MCC |
77 | ret = dvb_usb_generic_write(adap->dev, st->data, 4); |
78 | mutex_unlock(&st->data_mutex); | |
79 | ||
80 | return ret; | |
776338e1 JS |
81 | } |
82 | ||
a4d020e9 | 83 | static int dtt200u_rc_query(struct dvb_usb_device *d) |
776338e1 | 84 | { |
ab883e2d | 85 | struct dtt200u_state *st = d->priv; |
a4d020e9 JM |
86 | u32 scancode; |
87 | ||
ab883e2d MCC |
88 | mutex_lock(&st->data_mutex); |
89 | st->data[0] = GET_RC_CODE; | |
90 | ||
91 | dvb_usb_generic_rw(d, st->data, 1, st->data, 5, 0); | |
92 | if (st->data[0] == 1) { | |
2ceeca04 SY |
93 | enum rc_type proto = RC_TYPE_NEC; |
94 | ||
ab883e2d MCC |
95 | scancode = st->data[1]; |
96 | if ((u8) ~st->data[1] != st->data[2]) { | |
a4d020e9 JM |
97 | /* Extended NEC */ |
98 | scancode = scancode << 8; | |
ab883e2d | 99 | scancode |= st->data[2]; |
2ceeca04 | 100 | proto = RC_TYPE_NECX; |
a4d020e9 JM |
101 | } |
102 | scancode = scancode << 8; | |
ab883e2d | 103 | scancode |= st->data[3]; |
a4d020e9 JM |
104 | |
105 | /* Check command checksum is ok */ | |
ab883e2d | 106 | if ((u8) ~st->data[3] == st->data[4]) |
2ceeca04 | 107 | rc_keydown(d->rc_dev, proto, scancode, 0); |
a4d020e9 JM |
108 | else |
109 | rc_keyup(d->rc_dev); | |
ab883e2d | 110 | } else if (st->data[0] == 2) { |
a4d020e9 JM |
111 | rc_repeat(d->rc_dev); |
112 | } else { | |
113 | rc_keyup(d->rc_dev); | |
114 | } | |
115 | ||
ab883e2d MCC |
116 | if (st->data[0] != 0) |
117 | deb_info("st->data: %*ph\n", 5, st->data); | |
a4d020e9 | 118 | |
ab883e2d | 119 | mutex_unlock(&st->data_mutex); |
776338e1 JS |
120 | return 0; |
121 | } | |
122 | ||
4d43e13f | 123 | static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap) |
776338e1 | 124 | { |
77eed219 | 125 | adap->fe_adap[0].fe = dtt200u_fe_attach(adap->dev); |
776338e1 JS |
126 | return 0; |
127 | } | |
128 | ||
4d43e13f PB |
129 | static struct dvb_usb_device_properties dtt200u_properties; |
130 | static struct dvb_usb_device_properties wt220u_fc_properties; | |
131 | static struct dvb_usb_device_properties wt220u_properties; | |
132 | static struct dvb_usb_device_properties wt220u_zl0353_properties; | |
d3c35acf | 133 | static struct dvb_usb_device_properties wt220u_miglia_properties; |
776338e1 JS |
134 | |
135 | static int dtt200u_usb_probe(struct usb_interface *intf, | |
136 | const struct usb_device_id *id) | |
137 | { | |
ab883e2d MCC |
138 | struct dvb_usb_device *d; |
139 | struct dtt200u_state *st; | |
140 | ||
78e92006 | 141 | if (0 == dvb_usb_device_init(intf, &dtt200u_properties, |
ab883e2d | 142 | THIS_MODULE, &d, adapter_nr) || |
78e92006 | 143 | 0 == dvb_usb_device_init(intf, &wt220u_properties, |
ab883e2d | 144 | THIS_MODULE, &d, adapter_nr) || |
78e92006 | 145 | 0 == dvb_usb_device_init(intf, &wt220u_fc_properties, |
ab883e2d | 146 | THIS_MODULE, &d, adapter_nr) || |
78e92006 | 147 | 0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties, |
ab883e2d | 148 | THIS_MODULE, &d, adapter_nr) || |
78e92006 | 149 | 0 == dvb_usb_device_init(intf, &wt220u_miglia_properties, |
ab883e2d MCC |
150 | THIS_MODULE, &d, adapter_nr)) { |
151 | st = d->priv; | |
152 | mutex_init(&st->data_mutex); | |
153 | ||
d590f9c2 | 154 | return 0; |
ab883e2d | 155 | } |
d590f9c2 PB |
156 | |
157 | return -ENODEV; | |
776338e1 JS |
158 | } |
159 | ||
160 | static struct usb_device_id dtt200u_usb_table [] = { | |
62703b9d PB |
161 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_COLD) }, |
162 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_WARM) }, | |
163 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_COLD) }, | |
164 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM) }, | |
d46e6451 PB |
165 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_COLD) }, |
166 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_WARM) }, | |
19e22576 AT |
167 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_COLD) }, |
168 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_WARM) }, | |
ded38d28 | 169 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZAP250_COLD) }, |
d3c35acf | 170 | { USB_DEVICE(USB_VID_MIGLIA, USB_PID_WT220U_ZAP250_COLD) }, |
62703b9d | 171 | { 0 }, |
776338e1 JS |
172 | }; |
173 | MODULE_DEVICE_TABLE(usb, dtt200u_usb_table); | |
174 | ||
4d43e13f | 175 | static struct dvb_usb_device_properties dtt200u_properties = { |
776338e1 JS |
176 | .usb_ctrl = CYPRESS_FX2, |
177 | .firmware = "dvb-usb-dtt200u-01.fw", | |
178 | ||
ab883e2d MCC |
179 | .size_of_priv = sizeof(struct dtt200u_state), |
180 | ||
4d43e13f PB |
181 | .num_adapters = 1, |
182 | .adapter = { | |
183 | { | |
77eed219 MK |
184 | .num_frontends = 1, |
185 | .fe = {{ | |
4d43e13f PB |
186 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, |
187 | .pid_filter_count = 15, | |
188 | ||
776338e1 JS |
189 | .streaming_ctrl = dtt200u_streaming_ctrl, |
190 | .pid_filter = dtt200u_pid_filter, | |
191 | .frontend_attach = dtt200u_frontend_attach, | |
776338e1 | 192 | /* parameter for the MPEG2-data transfer */ |
4d43e13f PB |
193 | .stream = { |
194 | .type = USB_BULK, | |
776338e1 JS |
195 | .count = 7, |
196 | .endpoint = 0x02, | |
197 | .u = { | |
198 | .bulk = { | |
199 | .buffersize = 4096, | |
200 | } | |
201 | } | |
202 | }, | |
77eed219 | 203 | }}, |
4d43e13f PB |
204 | } |
205 | }, | |
206 | .power_ctrl = dtt200u_power_ctrl, | |
207 | ||
a4d020e9 | 208 | .rc.core = { |
f72a27b8 | 209 | .rc_interval = 300, |
a4d020e9 | 210 | .rc_codes = RC_MAP_DTT200U, |
f72a27b8 | 211 | .rc_query = dtt200u_rc_query, |
a4d020e9 | 212 | .allowed_protos = RC_BIT_NEC, |
f72a27b8 | 213 | }, |
4d43e13f PB |
214 | |
215 | .generic_bulk_ctrl_endpoint = 0x01, | |
776338e1 JS |
216 | |
217 | .num_device_descs = 1, | |
218 | .devices = { | |
d590f9c2 | 219 | { .name = "WideView/Yuan/Yakumo/Hama/Typhoon DVB-T USB2.0 (WT-200U)", |
fb41f5a7 | 220 | .cold_ids = { &dtt200u_usb_table[0], NULL }, |
776338e1 JS |
221 | .warm_ids = { &dtt200u_usb_table[1], NULL }, |
222 | }, | |
dad08dfc | 223 | { NULL }, |
776338e1 JS |
224 | } |
225 | }; | |
226 | ||
4d43e13f | 227 | static struct dvb_usb_device_properties wt220u_properties = { |
d590f9c2 | 228 | .usb_ctrl = CYPRESS_FX2, |
6ce17c57 | 229 | .firmware = "dvb-usb-wt220u-02.fw", |
d590f9c2 | 230 | |
ab883e2d MCC |
231 | .size_of_priv = sizeof(struct dtt200u_state), |
232 | ||
4d43e13f PB |
233 | .num_adapters = 1, |
234 | .adapter = { | |
235 | { | |
77eed219 MK |
236 | .num_frontends = 1, |
237 | .fe = {{ | |
4d43e13f PB |
238 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, |
239 | .pid_filter_count = 15, | |
240 | ||
d590f9c2 PB |
241 | .streaming_ctrl = dtt200u_streaming_ctrl, |
242 | .pid_filter = dtt200u_pid_filter, | |
243 | .frontend_attach = dtt200u_frontend_attach, | |
d590f9c2 | 244 | /* parameter for the MPEG2-data transfer */ |
4d43e13f PB |
245 | .stream = { |
246 | .type = USB_BULK, | |
d590f9c2 PB |
247 | .count = 7, |
248 | .endpoint = 0x02, | |
249 | .u = { | |
250 | .bulk = { | |
251 | .buffersize = 4096, | |
252 | } | |
253 | } | |
254 | }, | |
77eed219 | 255 | }}, |
4d43e13f PB |
256 | } |
257 | }, | |
258 | .power_ctrl = dtt200u_power_ctrl, | |
259 | ||
a4d020e9 | 260 | .rc.core = { |
f72a27b8 | 261 | .rc_interval = 300, |
a4d020e9 | 262 | .rc_codes = RC_MAP_DTT200U, |
f72a27b8 | 263 | .rc_query = dtt200u_rc_query, |
a4d020e9 | 264 | .allowed_protos = RC_BIT_NEC, |
f72a27b8 | 265 | }, |
4d43e13f PB |
266 | |
267 | .generic_bulk_ctrl_endpoint = 0x01, | |
d590f9c2 PB |
268 | |
269 | .num_device_descs = 1, | |
270 | .devices = { | |
62703b9d | 271 | { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)", |
ded38d28 | 272 | .cold_ids = { &dtt200u_usb_table[2], &dtt200u_usb_table[8], NULL }, |
d590f9c2 PB |
273 | .warm_ids = { &dtt200u_usb_table[3], NULL }, |
274 | }, | |
dad08dfc | 275 | { NULL }, |
d590f9c2 PB |
276 | } |
277 | }; | |
278 | ||
4d43e13f | 279 | static struct dvb_usb_device_properties wt220u_fc_properties = { |
19e22576 AT |
280 | .usb_ctrl = CYPRESS_FX2, |
281 | .firmware = "dvb-usb-wt220u-fc03.fw", | |
282 | ||
ab883e2d MCC |
283 | .size_of_priv = sizeof(struct dtt200u_state), |
284 | ||
4d43e13f PB |
285 | .num_adapters = 1, |
286 | .adapter = { | |
287 | { | |
77eed219 MK |
288 | .num_frontends = 1, |
289 | .fe = {{ | |
4d43e13f PB |
290 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, |
291 | .pid_filter_count = 15, | |
292 | ||
19e22576 AT |
293 | .streaming_ctrl = dtt200u_streaming_ctrl, |
294 | .pid_filter = dtt200u_pid_filter, | |
295 | .frontend_attach = dtt200u_frontend_attach, | |
19e22576 | 296 | /* parameter for the MPEG2-data transfer */ |
4d43e13f PB |
297 | .stream = { |
298 | .type = USB_BULK, | |
19e22576 | 299 | .count = 7, |
4d43e13f | 300 | .endpoint = 0x06, |
19e22576 AT |
301 | .u = { |
302 | .bulk = { | |
303 | .buffersize = 4096, | |
304 | } | |
305 | } | |
306 | }, | |
77eed219 | 307 | }}, |
4d43e13f PB |
308 | } |
309 | }, | |
310 | .power_ctrl = dtt200u_power_ctrl, | |
311 | ||
a4d020e9 | 312 | .rc.core = { |
f72a27b8 | 313 | .rc_interval = 300, |
a4d020e9 | 314 | .rc_codes = RC_MAP_DTT200U, |
f72a27b8 | 315 | .rc_query = dtt200u_rc_query, |
a4d020e9 | 316 | .allowed_protos = RC_BIT_NEC, |
f72a27b8 | 317 | }, |
4d43e13f PB |
318 | |
319 | .generic_bulk_ctrl_endpoint = 0x01, | |
19e22576 AT |
320 | |
321 | .num_device_descs = 1, | |
322 | .devices = { | |
323 | { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)", | |
324 | .cold_ids = { &dtt200u_usb_table[6], NULL }, | |
325 | .warm_ids = { &dtt200u_usb_table[7], NULL }, | |
326 | }, | |
327 | { NULL }, | |
328 | } | |
329 | }; | |
330 | ||
4d43e13f | 331 | static struct dvb_usb_device_properties wt220u_zl0353_properties = { |
d46e6451 PB |
332 | .usb_ctrl = CYPRESS_FX2, |
333 | .firmware = "dvb-usb-wt220u-zl0353-01.fw", | |
334 | ||
ab883e2d MCC |
335 | .size_of_priv = sizeof(struct dtt200u_state), |
336 | ||
4d43e13f PB |
337 | .num_adapters = 1, |
338 | .adapter = { | |
339 | { | |
77eed219 MK |
340 | .num_frontends = 1, |
341 | .fe = {{ | |
4d43e13f PB |
342 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, |
343 | .pid_filter_count = 15, | |
344 | ||
01451e72 PB |
345 | .streaming_ctrl = dtt200u_streaming_ctrl, |
346 | .pid_filter = dtt200u_pid_filter, | |
347 | .frontend_attach = dtt200u_frontend_attach, | |
348 | /* parameter for the MPEG2-data transfer */ | |
4d43e13f PB |
349 | .stream = { |
350 | .type = USB_BULK, | |
01451e72 PB |
351 | .count = 7, |
352 | .endpoint = 0x02, | |
353 | .u = { | |
354 | .bulk = { | |
355 | .buffersize = 4096, | |
356 | } | |
357 | } | |
358 | }, | |
77eed219 | 359 | }}, |
4d43e13f PB |
360 | } |
361 | }, | |
362 | .power_ctrl = dtt200u_power_ctrl, | |
363 | ||
a4d020e9 | 364 | .rc.core = { |
f72a27b8 | 365 | .rc_interval = 300, |
a4d020e9 | 366 | .rc_codes = RC_MAP_DTT200U, |
f72a27b8 | 367 | .rc_query = dtt200u_rc_query, |
a4d020e9 | 368 | .allowed_protos = RC_BIT_NEC, |
f72a27b8 | 369 | }, |
4d43e13f PB |
370 | |
371 | .generic_bulk_ctrl_endpoint = 0x01, | |
d46e6451 PB |
372 | |
373 | .num_device_descs = 1, | |
374 | .devices = { | |
375 | { .name = "WideView WT-220U PenType Receiver (based on ZL353)", | |
376 | .cold_ids = { &dtt200u_usb_table[4], NULL }, | |
377 | .warm_ids = { &dtt200u_usb_table[5], NULL }, | |
378 | }, | |
379 | { NULL }, | |
380 | } | |
381 | }; | |
382 | ||
d3c35acf RR |
383 | static struct dvb_usb_device_properties wt220u_miglia_properties = { |
384 | .usb_ctrl = CYPRESS_FX2, | |
385 | .firmware = "dvb-usb-wt220u-miglia-01.fw", | |
386 | ||
ab883e2d MCC |
387 | .size_of_priv = sizeof(struct dtt200u_state), |
388 | ||
d3c35acf RR |
389 | .num_adapters = 1, |
390 | .generic_bulk_ctrl_endpoint = 0x01, | |
391 | ||
392 | .num_device_descs = 1, | |
393 | .devices = { | |
394 | { .name = "WideView WT-220U PenType Receiver (Miglia)", | |
395 | .cold_ids = { &dtt200u_usb_table[9], NULL }, | |
396 | /* This device turns into WT220U_ZL0353_WARM when fw | |
397 | has been uploaded */ | |
398 | .warm_ids = { NULL }, | |
399 | }, | |
400 | { NULL }, | |
401 | } | |
402 | }; | |
403 | ||
776338e1 JS |
404 | /* usb specific object needed to register this driver with the usb subsystem */ |
405 | static struct usb_driver dtt200u_usb_driver = { | |
d590f9c2 | 406 | .name = "dvb_usb_dtt200u", |
62703b9d | 407 | .probe = dtt200u_usb_probe, |
776338e1 | 408 | .disconnect = dvb_usb_device_exit, |
62703b9d | 409 | .id_table = dtt200u_usb_table, |
776338e1 JS |
410 | }; |
411 | ||
ecb3b2b3 | 412 | module_usb_driver(dtt200u_usb_driver); |
776338e1 | 413 | |
99e44da7 | 414 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>"); |
d3c35acf | 415 | MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D/Miglia DVB-T USB2.0 devices"); |
776338e1 JS |
416 | MODULE_VERSION("1.0"); |
417 | MODULE_LICENSE("GPL"); |