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
))
161 static struct usb_device_id dtt200u_usb_table
[] = {
162 { USB_DEVICE(USB_VID_WIDEVIEW
, USB_PID_DTT200U_COLD
) },
163 { USB_DEVICE(USB_VID_WIDEVIEW
, USB_PID_DTT200U_WARM
) },
164 { USB_DEVICE(USB_VID_WIDEVIEW
, USB_PID_WT220U_COLD
) },
165 { USB_DEVICE(USB_VID_WIDEVIEW
, USB_PID_WT220U_WARM
) },
166 { USB_DEVICE(USB_VID_WIDEVIEW
, USB_PID_WT220U_ZL0353_COLD
) },
167 { USB_DEVICE(USB_VID_WIDEVIEW
, USB_PID_WT220U_ZL0353_WARM
) },
168 { USB_DEVICE(USB_VID_WIDEVIEW
, USB_PID_WT220U_FC_COLD
) },
169 { USB_DEVICE(USB_VID_WIDEVIEW
, USB_PID_WT220U_FC_WARM
) },
170 { USB_DEVICE(USB_VID_WIDEVIEW
, USB_PID_WT220U_ZAP250_COLD
) },
171 { USB_DEVICE(USB_VID_MIGLIA
, USB_PID_WT220U_ZAP250_COLD
) },
174 MODULE_DEVICE_TABLE(usb
, dtt200u_usb_table
);
176 static struct dvb_usb_device_properties dtt200u_properties
= {
177 .usb_ctrl
= CYPRESS_FX2
,
178 .firmware
= "dvb-usb-dtt200u-01.fw",
180 .size_of_priv
= sizeof(struct dtt200u_state
),
187 .caps
= DVB_USB_ADAP_HAS_PID_FILTER
| DVB_USB_ADAP_NEED_PID_FILTERING
,
188 .pid_filter_count
= 15,
190 .streaming_ctrl
= dtt200u_streaming_ctrl
,
191 .pid_filter
= dtt200u_pid_filter
,
192 .frontend_attach
= dtt200u_frontend_attach
,
193 /* parameter for the MPEG2-data transfer */
207 .power_ctrl
= dtt200u_power_ctrl
,
211 .rc_codes
= RC_MAP_DTT200U
,
212 .rc_query
= dtt200u_rc_query
,
213 .allowed_protos
= RC_PROTO_BIT_NEC
,
216 .generic_bulk_ctrl_endpoint
= 0x01,
218 .num_device_descs
= 1,
220 { .name
= "WideView/Yuan/Yakumo/Hama/Typhoon DVB-T USB2.0 (WT-200U)",
221 .cold_ids
= { &dtt200u_usb_table
[0], NULL
},
222 .warm_ids
= { &dtt200u_usb_table
[1], NULL
},
228 static struct dvb_usb_device_properties wt220u_properties
= {
229 .usb_ctrl
= CYPRESS_FX2
,
230 .firmware
= "dvb-usb-wt220u-02.fw",
232 .size_of_priv
= sizeof(struct dtt200u_state
),
239 .caps
= DVB_USB_ADAP_HAS_PID_FILTER
| DVB_USB_ADAP_NEED_PID_FILTERING
,
240 .pid_filter_count
= 15,
242 .streaming_ctrl
= dtt200u_streaming_ctrl
,
243 .pid_filter
= dtt200u_pid_filter
,
244 .frontend_attach
= dtt200u_frontend_attach
,
245 /* parameter for the MPEG2-data transfer */
259 .power_ctrl
= dtt200u_power_ctrl
,
263 .rc_codes
= RC_MAP_DTT200U
,
264 .rc_query
= dtt200u_rc_query
,
265 .allowed_protos
= RC_PROTO_BIT_NEC
,
268 .generic_bulk_ctrl_endpoint
= 0x01,
270 .num_device_descs
= 1,
272 { .name
= "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
273 .cold_ids
= { &dtt200u_usb_table
[2], &dtt200u_usb_table
[8], NULL
},
274 .warm_ids
= { &dtt200u_usb_table
[3], NULL
},
280 static struct dvb_usb_device_properties wt220u_fc_properties
= {
281 .usb_ctrl
= CYPRESS_FX2
,
282 .firmware
= "dvb-usb-wt220u-fc03.fw",
284 .size_of_priv
= sizeof(struct dtt200u_state
),
291 .caps
= DVB_USB_ADAP_HAS_PID_FILTER
| DVB_USB_ADAP_NEED_PID_FILTERING
,
292 .pid_filter_count
= 15,
294 .streaming_ctrl
= dtt200u_streaming_ctrl
,
295 .pid_filter
= dtt200u_pid_filter
,
296 .frontend_attach
= dtt200u_frontend_attach
,
297 /* parameter for the MPEG2-data transfer */
311 .power_ctrl
= dtt200u_power_ctrl
,
315 .rc_codes
= RC_MAP_DTT200U
,
316 .rc_query
= dtt200u_rc_query
,
317 .allowed_protos
= RC_PROTO_BIT_NEC
,
320 .generic_bulk_ctrl_endpoint
= 0x01,
322 .num_device_descs
= 1,
324 { .name
= "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
325 .cold_ids
= { &dtt200u_usb_table
[6], NULL
},
326 .warm_ids
= { &dtt200u_usb_table
[7], NULL
},
332 static struct dvb_usb_device_properties wt220u_zl0353_properties
= {
333 .usb_ctrl
= CYPRESS_FX2
,
334 .firmware
= "dvb-usb-wt220u-zl0353-01.fw",
336 .size_of_priv
= sizeof(struct dtt200u_state
),
343 .caps
= DVB_USB_ADAP_HAS_PID_FILTER
| DVB_USB_ADAP_NEED_PID_FILTERING
,
344 .pid_filter_count
= 15,
346 .streaming_ctrl
= dtt200u_streaming_ctrl
,
347 .pid_filter
= dtt200u_pid_filter
,
348 .frontend_attach
= dtt200u_frontend_attach
,
349 /* parameter for the MPEG2-data transfer */
363 .power_ctrl
= dtt200u_power_ctrl
,
367 .rc_codes
= RC_MAP_DTT200U
,
368 .rc_query
= dtt200u_rc_query
,
369 .allowed_protos
= RC_PROTO_BIT_NEC
,
372 .generic_bulk_ctrl_endpoint
= 0x01,
374 .num_device_descs
= 1,
376 { .name
= "WideView WT-220U PenType Receiver (based on ZL353)",
377 .cold_ids
= { &dtt200u_usb_table
[4], NULL
},
378 .warm_ids
= { &dtt200u_usb_table
[5], NULL
},
384 static struct dvb_usb_device_properties wt220u_miglia_properties
= {
385 .usb_ctrl
= CYPRESS_FX2
,
386 .firmware
= "dvb-usb-wt220u-miglia-01.fw",
388 .size_of_priv
= sizeof(struct dtt200u_state
),
391 .generic_bulk_ctrl_endpoint
= 0x01,
393 .num_device_descs
= 1,
395 { .name
= "WideView WT-220U PenType Receiver (Miglia)",
396 .cold_ids
= { &dtt200u_usb_table
[9], NULL
},
397 /* This device turns into WT220U_ZL0353_WARM when fw
399 .warm_ids
= { NULL
},
405 /* usb specific object needed to register this driver with the usb subsystem */
406 static struct usb_driver dtt200u_usb_driver
= {
407 .name
= "dvb_usb_dtt200u",
408 .probe
= dtt200u_usb_probe
,
409 .disconnect
= dvb_usb_device_exit
,
410 .id_table
= dtt200u_usb_table
,
413 module_usb_driver(dtt200u_usb_driver
);
415 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
416 MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D/Miglia DVB-T USB2.0 devices");
417 MODULE_VERSION("1.0");
418 MODULE_LICENSE("GPL");