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