1 // SPDX-License-Identifier: GPL-2.0-only
2 /* DVB USB library compliant Linux driver for the WideView/ Yakumo/ Hama/
3 * Typhoon/ Yuan/ Miglia DVB-T USB2.0 receiver.
5 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de)
7 * Thanks to Steve Chang from WideView for providing support for the WT-220U.
9 * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
14 int dvb_usb_dtt200u_debug
;
15 module_param_named(debug
,dvb_usb_dtt200u_debug
, int, 0644);
16 MODULE_PARM_DESC(debug
, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS
);
18 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr
);
20 struct dtt200u_state
{
21 unsigned char data
[80];
24 static int dtt200u_power_ctrl(struct dvb_usb_device
*d
, int onoff
)
26 struct dtt200u_state
*st
= d
->priv
;
29 mutex_lock(&d
->data_mutex
);
31 st
->data
[0] = SET_INIT
;
34 ret
= dvb_usb_generic_write(d
, st
->data
, 2);
36 mutex_unlock(&d
->data_mutex
);
40 static int dtt200u_streaming_ctrl(struct dvb_usb_adapter
*adap
, int onoff
)
42 struct dvb_usb_device
*d
= adap
->dev
;
43 struct dtt200u_state
*st
= d
->priv
;
46 mutex_lock(&d
->data_mutex
);
47 st
->data
[0] = SET_STREAMING
;
50 ret
= dvb_usb_generic_write(adap
->dev
, st
->data
, 2);
57 st
->data
[0] = RESET_PID_FILTER
;
58 ret
= dvb_usb_generic_write(adap
->dev
, st
->data
, 1);
61 mutex_unlock(&d
->data_mutex
);
66 static int dtt200u_pid_filter(struct dvb_usb_adapter
*adap
, int index
, u16 pid
, int onoff
)
68 struct dvb_usb_device
*d
= adap
->dev
;
69 struct dtt200u_state
*st
= d
->priv
;
72 pid
= onoff
? pid
: 0;
74 mutex_lock(&d
->data_mutex
);
75 st
->data
[0] = SET_PID_FILTER
;
77 st
->data
[2] = pid
& 0xff;
78 st
->data
[3] = (pid
>> 8) & 0x1f;
80 ret
= dvb_usb_generic_write(adap
->dev
, st
->data
, 4);
81 mutex_unlock(&d
->data_mutex
);
86 static int dtt200u_rc_query(struct dvb_usb_device
*d
)
88 struct dtt200u_state
*st
= d
->priv
;
92 mutex_lock(&d
->data_mutex
);
93 st
->data
[0] = GET_RC_CODE
;
95 ret
= dvb_usb_generic_rw(d
, st
->data
, 1, st
->data
, 5, 0);
99 if (st
->data
[0] == 1) {
100 enum rc_proto proto
= RC_PROTO_NEC
;
102 scancode
= st
->data
[1];
103 if ((u8
) ~st
->data
[1] != st
->data
[2]) {
105 scancode
= scancode
<< 8;
106 scancode
|= st
->data
[2];
107 proto
= RC_PROTO_NECX
;
109 scancode
= scancode
<< 8;
110 scancode
|= st
->data
[3];
112 /* Check command checksum is ok */
113 if ((u8
) ~st
->data
[3] == st
->data
[4])
114 rc_keydown(d
->rc_dev
, proto
, scancode
, 0);
117 } else if (st
->data
[0] == 2) {
118 rc_repeat(d
->rc_dev
);
123 if (st
->data
[0] != 0)
124 deb_info("st->data: %*ph\n", 5, st
->data
);
127 mutex_unlock(&d
->data_mutex
);
131 static int dtt200u_frontend_attach(struct dvb_usb_adapter
*adap
)
133 adap
->fe_adap
[0].fe
= dtt200u_fe_attach(adap
->dev
);
137 static struct dvb_usb_device_properties dtt200u_properties
;
138 static struct dvb_usb_device_properties wt220u_fc_properties
;
139 static struct dvb_usb_device_properties wt220u_properties
;
140 static struct dvb_usb_device_properties wt220u_zl0353_properties
;
141 static struct dvb_usb_device_properties wt220u_miglia_properties
;
143 static int dtt200u_usb_probe(struct usb_interface
*intf
,
144 const struct usb_device_id
*id
)
146 if (0 == dvb_usb_device_init(intf
, &dtt200u_properties
,
147 THIS_MODULE
, NULL
, adapter_nr
) ||
148 0 == dvb_usb_device_init(intf
, &wt220u_properties
,
149 THIS_MODULE
, NULL
, adapter_nr
) ||
150 0 == dvb_usb_device_init(intf
, &wt220u_fc_properties
,
151 THIS_MODULE
, NULL
, adapter_nr
) ||
152 0 == dvb_usb_device_init(intf
, &wt220u_zl0353_properties
,
153 THIS_MODULE
, NULL
, adapter_nr
) ||
154 0 == dvb_usb_device_init(intf
, &wt220u_miglia_properties
,
155 THIS_MODULE
, NULL
, adapter_nr
))
162 WIDEVIEW_DTT200U_COLD
,
163 WIDEVIEW_DTT200U_WARM
,
164 WIDEVIEW_WT220U_COLD
,
165 WIDEVIEW_WT220U_WARM
,
166 WIDEVIEW_WT220U_ZL0353_COLD
,
167 WIDEVIEW_WT220U_ZL0353_WARM
,
168 WIDEVIEW_WT220U_FC_COLD
,
169 WIDEVIEW_WT220U_FC_WARM
,
170 WIDEVIEW_WT220U_ZAP250_COLD
,
171 MIGLIA_WT220U_ZAP250_COLD
,
174 static struct usb_device_id dtt200u_usb_table
[] = {
175 DVB_USB_DEV(WIDEVIEW
, WIDEVIEW_DTT200U_COLD
),
176 DVB_USB_DEV(WIDEVIEW
, WIDEVIEW_DTT200U_WARM
),
177 DVB_USB_DEV(WIDEVIEW
, WIDEVIEW_WT220U_COLD
),
178 DVB_USB_DEV(WIDEVIEW
, WIDEVIEW_WT220U_WARM
),
179 DVB_USB_DEV(WIDEVIEW
, WIDEVIEW_WT220U_ZL0353_COLD
),
180 DVB_USB_DEV(WIDEVIEW
, WIDEVIEW_WT220U_ZL0353_WARM
),
181 DVB_USB_DEV(WIDEVIEW
, WIDEVIEW_WT220U_FC_COLD
),
182 DVB_USB_DEV(WIDEVIEW
, WIDEVIEW_WT220U_FC_WARM
),
183 DVB_USB_DEV(WIDEVIEW
, WIDEVIEW_WT220U_ZAP250_COLD
),
184 DVB_USB_DEV(MIGLIA
, MIGLIA_WT220U_ZAP250_COLD
),
188 MODULE_DEVICE_TABLE(usb
, dtt200u_usb_table
);
190 static struct dvb_usb_device_properties dtt200u_properties
= {
191 .usb_ctrl
= CYPRESS_FX2
,
192 .firmware
= "dvb-usb-dtt200u-01.fw",
194 .size_of_priv
= sizeof(struct dtt200u_state
),
201 .caps
= DVB_USB_ADAP_HAS_PID_FILTER
| DVB_USB_ADAP_NEED_PID_FILTERING
,
202 .pid_filter_count
= 15,
204 .streaming_ctrl
= dtt200u_streaming_ctrl
,
205 .pid_filter
= dtt200u_pid_filter
,
206 .frontend_attach
= dtt200u_frontend_attach
,
207 /* parameter for the MPEG2-data transfer */
221 .power_ctrl
= dtt200u_power_ctrl
,
225 .rc_codes
= RC_MAP_DTT200U
,
226 .rc_query
= dtt200u_rc_query
,
227 .allowed_protos
= RC_PROTO_BIT_NEC
,
230 .generic_bulk_ctrl_endpoint
= 0x01,
232 .num_device_descs
= 1,
234 { .name
= "WideView/Yuan/Yakumo/Hama/Typhoon DVB-T USB2.0 (WT-200U)",
235 .cold_ids
= { &dtt200u_usb_table
[WIDEVIEW_DTT200U_COLD
], NULL
},
236 .warm_ids
= { &dtt200u_usb_table
[WIDEVIEW_DTT200U_WARM
], NULL
},
242 static struct dvb_usb_device_properties wt220u_properties
= {
243 .usb_ctrl
= CYPRESS_FX2
,
244 .firmware
= "dvb-usb-wt220u-02.fw",
246 .size_of_priv
= sizeof(struct dtt200u_state
),
253 .caps
= DVB_USB_ADAP_HAS_PID_FILTER
| DVB_USB_ADAP_NEED_PID_FILTERING
,
254 .pid_filter_count
= 15,
256 .streaming_ctrl
= dtt200u_streaming_ctrl
,
257 .pid_filter
= dtt200u_pid_filter
,
258 .frontend_attach
= dtt200u_frontend_attach
,
259 /* parameter for the MPEG2-data transfer */
273 .power_ctrl
= dtt200u_power_ctrl
,
277 .rc_codes
= RC_MAP_DTT200U
,
278 .rc_query
= dtt200u_rc_query
,
279 .allowed_protos
= RC_PROTO_BIT_NEC
,
282 .generic_bulk_ctrl_endpoint
= 0x01,
284 .num_device_descs
= 1,
286 { .name
= "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
287 .cold_ids
= { &dtt200u_usb_table
[WIDEVIEW_WT220U_COLD
], &dtt200u_usb_table
[WIDEVIEW_WT220U_ZAP250_COLD
], NULL
},
288 .warm_ids
= { &dtt200u_usb_table
[WIDEVIEW_WT220U_WARM
], NULL
},
294 static struct dvb_usb_device_properties wt220u_fc_properties
= {
295 .usb_ctrl
= CYPRESS_FX2
,
296 .firmware
= "dvb-usb-wt220u-fc03.fw",
298 .size_of_priv
= sizeof(struct dtt200u_state
),
305 .caps
= DVB_USB_ADAP_HAS_PID_FILTER
| DVB_USB_ADAP_NEED_PID_FILTERING
,
306 .pid_filter_count
= 15,
308 .streaming_ctrl
= dtt200u_streaming_ctrl
,
309 .pid_filter
= dtt200u_pid_filter
,
310 .frontend_attach
= dtt200u_frontend_attach
,
311 /* parameter for the MPEG2-data transfer */
325 .power_ctrl
= dtt200u_power_ctrl
,
329 .rc_codes
= RC_MAP_DTT200U
,
330 .rc_query
= dtt200u_rc_query
,
331 .allowed_protos
= RC_PROTO_BIT_NEC
,
334 .generic_bulk_ctrl_endpoint
= 0x01,
336 .num_device_descs
= 1,
338 { .name
= "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
339 .cold_ids
= { &dtt200u_usb_table
[WIDEVIEW_WT220U_FC_COLD
], NULL
},
340 .warm_ids
= { &dtt200u_usb_table
[WIDEVIEW_WT220U_FC_WARM
], NULL
},
346 static struct dvb_usb_device_properties wt220u_zl0353_properties
= {
347 .usb_ctrl
= CYPRESS_FX2
,
348 .firmware
= "dvb-usb-wt220u-zl0353-01.fw",
350 .size_of_priv
= sizeof(struct dtt200u_state
),
357 .caps
= DVB_USB_ADAP_HAS_PID_FILTER
| DVB_USB_ADAP_NEED_PID_FILTERING
,
358 .pid_filter_count
= 15,
360 .streaming_ctrl
= dtt200u_streaming_ctrl
,
361 .pid_filter
= dtt200u_pid_filter
,
362 .frontend_attach
= dtt200u_frontend_attach
,
363 /* parameter for the MPEG2-data transfer */
377 .power_ctrl
= dtt200u_power_ctrl
,
381 .rc_codes
= RC_MAP_DTT200U
,
382 .rc_query
= dtt200u_rc_query
,
383 .allowed_protos
= RC_PROTO_BIT_NEC
,
386 .generic_bulk_ctrl_endpoint
= 0x01,
388 .num_device_descs
= 1,
390 { .name
= "WideView WT-220U PenType Receiver (based on ZL353)",
391 .cold_ids
= { &dtt200u_usb_table
[WIDEVIEW_WT220U_ZL0353_COLD
], NULL
},
392 .warm_ids
= { &dtt200u_usb_table
[WIDEVIEW_WT220U_ZL0353_WARM
], NULL
},
398 static struct dvb_usb_device_properties wt220u_miglia_properties
= {
399 .usb_ctrl
= CYPRESS_FX2
,
400 .firmware
= "dvb-usb-wt220u-miglia-01.fw",
402 .size_of_priv
= sizeof(struct dtt200u_state
),
405 .generic_bulk_ctrl_endpoint
= 0x01,
407 .num_device_descs
= 1,
409 { .name
= "WideView WT-220U PenType Receiver (Miglia)",
410 .cold_ids
= { &dtt200u_usb_table
[MIGLIA_WT220U_ZAP250_COLD
], NULL
},
411 /* This device turns into WT220U_ZL0353_WARM when fw
413 .warm_ids
= { NULL
},
419 /* usb specific object needed to register this driver with the usb subsystem */
420 static struct usb_driver dtt200u_usb_driver
= {
421 .name
= "dvb_usb_dtt200u",
422 .probe
= dtt200u_usb_probe
,
423 .disconnect
= dvb_usb_device_exit
,
424 .id_table
= dtt200u_usb_table
,
427 module_usb_driver(dtt200u_usb_driver
);
429 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
430 MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D/Miglia DVB-T USB2.0 devices");
431 MODULE_VERSION("1.0");
432 MODULE_LICENSE("GPL");