]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/media/usb/dvb-usb/dtt200u.c
[media] dtt200u: don't do DMA on stack
[mirror_ubuntu-bionic-kernel.git] / drivers / media / usb / dvb-usb / dtt200u.c
CommitLineData
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 */
17int dvb_usb_dtt200u_debug;
18module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644);
19MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS);
20
78e92006
JG
21DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
22
ab883e2d
MCC
23struct dtt200u_state {
24 unsigned char data[80];
25 struct mutex data_mutex;
26};
27
d590f9c2
PB
28static 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 43static 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 64static 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 83static 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 123static 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
129static struct dvb_usb_device_properties dtt200u_properties;
130static struct dvb_usb_device_properties wt220u_fc_properties;
131static struct dvb_usb_device_properties wt220u_properties;
132static struct dvb_usb_device_properties wt220u_zl0353_properties;
d3c35acf 133static struct dvb_usb_device_properties wt220u_miglia_properties;
776338e1
JS
134
135static 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
160static 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};
173MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
174
4d43e13f 175static 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 227static 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 279static 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 331static 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
383static 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 */
405static 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 412module_usb_driver(dtt200u_usb_driver);
776338e1 413
99e44da7 414MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
d3c35acf 415MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D/Miglia DVB-T USB2.0 devices");
776338e1
JS
416MODULE_VERSION("1.0");
417MODULE_LICENSE("GPL");