1/* DVB USB library compliant Linux driver for the WideView/ Yakumo/ Hama/
2 * Typhoon/ Yuan DVB-T USB2.0 receiver.
3 *
4 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
5 *
6 * Thanks to Steve Chang from WideView for providing support for the WT-220U.
7 *
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
21static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff)
22{
23	u8 b = SET_INIT;
24
25	if (onoff)
26		dvb_usb_generic_write(d,&b,2);
27
28	return 0;
29}
30
31static int dtt200u_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
32{
33	u8 b_streaming[2] = { SET_STREAMING, onoff };
34	u8 b_rst_pid = RESET_PID_FILTER;
35
36	dvb_usb_generic_write(adap->dev, b_streaming, 2);
37
38	if (onoff == 0)
39		dvb_usb_generic_write(adap->dev, &b_rst_pid, 1);
40	return 0;
41}
42
43static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)
44{
45	u8 b_pid[4];
46	pid = onoff ? pid : 0;
47
48	b_pid[0] = SET_PID_FILTER;
49	b_pid[1] = index;
50	b_pid[2] = pid & 0xff;
51	b_pid[3] = (pid >> 8) & 0x1f;
52
53	return dvb_usb_generic_write(adap->dev, b_pid, 4);
54}
55
56/* remote control */
57/* key list for the tiny remote control (Yakumo, don't know about the others) */
58static struct dvb_usb_rc_key dtt200u_rc_keys[] = {
59	{ 0x80, 0x01, KEY_MUTE },
60	{ 0x80, 0x02, KEY_CHANNELDOWN },
61	{ 0x80, 0x03, KEY_VOLUMEDOWN },
62	{ 0x80, 0x04, KEY_1 },
63	{ 0x80, 0x05, KEY_2 },
64	{ 0x80, 0x06, KEY_3 },
65	{ 0x80, 0x07, KEY_4 },
66	{ 0x80, 0x08, KEY_5 },
67	{ 0x80, 0x09, KEY_6 },
68	{ 0x80, 0x0a, KEY_7 },
69	{ 0x80, 0x0c, KEY_ZOOM },
70	{ 0x80, 0x0d, KEY_0 },
71	{ 0x80, 0x0e, KEY_SELECT },
72	{ 0x80, 0x12, KEY_POWER },
73	{ 0x80, 0x1a, KEY_CHANNELUP },
74	{ 0x80, 0x1b, KEY_8 },
75	{ 0x80, 0x1e, KEY_VOLUMEUP },
76	{ 0x80, 0x1f, KEY_9 },
77};
78
79static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
80{
81	u8 key[5],cmd = GET_RC_CODE;
82	dvb_usb_generic_rw(d,&cmd,1,key,5,0);
83	dvb_usb_nec_rc_key_to_event(d,key,event,state);
84	if (key[0] != 0)
85		deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
86	return 0;
87}
88
89static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap)
90{
91	adap->fe = dtt200u_fe_attach(adap->dev);
92	return 0;
93}
94
95static struct dvb_usb_device_properties dtt200u_properties;
96static struct dvb_usb_device_properties wt220u_fc_properties;
97static struct dvb_usb_device_properties wt220u_properties;
98static struct dvb_usb_device_properties wt220u_zl0353_properties;
99
100static int dtt200u_usb_probe(struct usb_interface *intf,
101		const struct usb_device_id *id)
102{
103	if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
104		dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 ||
105		dvb_usb_device_init(intf,&wt220u_fc_properties,THIS_MODULE,NULL) == 0 ||
106		dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0)
107		return 0;
108
109	return -ENODEV;
110}
111
112static struct usb_device_id dtt200u_usb_table [] = {
113	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_COLD) },
114	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_WARM) },
115	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_COLD)  },
116	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM)  },
117	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_COLD)  },
118	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_WARM)  },
119	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_COLD)  },
120	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_WARM)  },
121	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZAP250_COLD)  },
122	{ 0 },
123};
124MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
125
126static struct dvb_usb_device_properties dtt200u_properties = {
127	.usb_ctrl = CYPRESS_FX2,
128	.firmware = "dvb-usb-dtt200u-01.fw",
129
130	.num_adapters = 1,
131	.adapter = {
132		{
133			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
134			.pid_filter_count = 15,
135
136	.streaming_ctrl  = dtt200u_streaming_ctrl,
137	.pid_filter      = dtt200u_pid_filter,
138	.frontend_attach = dtt200u_frontend_attach,
139	/* parameter for the MPEG2-data transfer */
140			.stream = {
141				.type = USB_BULK,
142		.count = 7,
143		.endpoint = 0x02,
144		.u = {
145			.bulk = {
146				.buffersize = 4096,
147			}
148		}
149	},
150		}
151	},
152	.power_ctrl      = dtt200u_power_ctrl,
153
154	.rc_interval     = 300,
155	.rc_key_map      = dtt200u_rc_keys,
156	.rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
157	.rc_query        = dtt200u_rc_query,
158
159	.generic_bulk_ctrl_endpoint = 0x01,
160
161	.num_device_descs = 1,
162	.devices = {
163		{ .name = "WideView/Yuan/Yakumo/Hama/Typhoon DVB-T USB2.0 (WT-200U)",
164		  .cold_ids = { &dtt200u_usb_table[0], NULL },
165		  .warm_ids = { &dtt200u_usb_table[1], NULL },
166		},
167		{ NULL },
168	}
169};
170
171static struct dvb_usb_device_properties wt220u_properties = {
172	.usb_ctrl = CYPRESS_FX2,
173	.firmware = "dvb-usb-wt220u-02.fw",
174
175	.num_adapters = 1,
176	.adapter = {
177		{
178			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
179			.pid_filter_count = 15,
180
181	.streaming_ctrl  = dtt200u_streaming_ctrl,
182	.pid_filter      = dtt200u_pid_filter,
183	.frontend_attach = dtt200u_frontend_attach,
184	/* parameter for the MPEG2-data transfer */
185			.stream = {
186				.type = USB_BULK,
187		.count = 7,
188		.endpoint = 0x02,
189		.u = {
190			.bulk = {
191				.buffersize = 4096,
192			}
193		}
194	},
195		}
196	},
197	.power_ctrl      = dtt200u_power_ctrl,
198
199	.rc_interval     = 300,
200	.rc_key_map      = dtt200u_rc_keys,
201	.rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
202	.rc_query        = dtt200u_rc_query,
203
204	.generic_bulk_ctrl_endpoint = 0x01,
205
206	.num_device_descs = 1,
207	.devices = {
208		{ .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
209		  .cold_ids = { &dtt200u_usb_table[2], &dtt200u_usb_table[8], NULL },
210		  .warm_ids = { &dtt200u_usb_table[3], NULL },
211		},
212		{ NULL },
213	}
214};
215
216static struct dvb_usb_device_properties wt220u_fc_properties = {
217	.usb_ctrl = CYPRESS_FX2,
218	.firmware = "dvb-usb-wt220u-fc03.fw",
219
220	.num_adapters = 1,
221	.adapter = {
222		{
223			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
224			.pid_filter_count = 15,
225
226	.streaming_ctrl  = dtt200u_streaming_ctrl,
227	.pid_filter      = dtt200u_pid_filter,
228	.frontend_attach = dtt200u_frontend_attach,
229	/* parameter for the MPEG2-data transfer */
230			.stream = {
231				.type = USB_BULK,
232		.count = 7,
233				.endpoint = 0x06,
234		.u = {
235			.bulk = {
236				.buffersize = 4096,
237			}
238		}
239	},
240		}
241	},
242	.power_ctrl      = dtt200u_power_ctrl,
243
244	.rc_interval     = 300,
245	.rc_key_map      = dtt200u_rc_keys,
246	.rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
247	.rc_query        = dtt200u_rc_query,
248
249	.generic_bulk_ctrl_endpoint = 0x01,
250
251	.num_device_descs = 1,
252	.devices = {
253		{ .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
254		  .cold_ids = { &dtt200u_usb_table[6], NULL },
255		  .warm_ids = { &dtt200u_usb_table[7], NULL },
256		},
257		{ NULL },
258	}
259};
260
261static struct dvb_usb_device_properties wt220u_zl0353_properties = {
262	.usb_ctrl = CYPRESS_FX2,
263	.firmware = "dvb-usb-wt220u-zl0353-01.fw",
264
265	.num_adapters = 1,
266	.adapter = {
267		{
268			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
269			.pid_filter_count = 15,
270
271			.streaming_ctrl  = dtt200u_streaming_ctrl,
272			.pid_filter      = dtt200u_pid_filter,
273			.frontend_attach = dtt200u_frontend_attach,
274			/* parameter for the MPEG2-data transfer */
275			.stream = {
276				.type = USB_BULK,
277				.count = 7,
278				.endpoint = 0x02,
279				.u = {
280					.bulk = {
281						.buffersize = 4096,
282					}
283				}
284			},
285		}
286	},
287	.power_ctrl      = dtt200u_power_ctrl,
288
289	.rc_interval     = 300,
290	.rc_key_map      = dtt200u_rc_keys,
291	.rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
292	.rc_query        = dtt200u_rc_query,
293
294	.generic_bulk_ctrl_endpoint = 0x01,
295
296	.num_device_descs = 1,
297	.devices = {
298		{ .name = "WideView WT-220U PenType Receiver (based on ZL353)",
299		  .cold_ids = { &dtt200u_usb_table[4], NULL },
300		  .warm_ids = { &dtt200u_usb_table[5], NULL },
301		},
302		{ NULL },
303	}
304};
305
306/* usb specific object needed to register this driver with the usb subsystem */
307static struct usb_driver dtt200u_usb_driver = {
308	.name		= "dvb_usb_dtt200u",
309	.probe		= dtt200u_usb_probe,
310	.disconnect = dvb_usb_device_exit,
311	.id_table	= dtt200u_usb_table,
312};
313
314/* module stuff */
315static int __init dtt200u_usb_module_init(void)
316{
317	int result;
318	if ((result = usb_register(&dtt200u_usb_driver))) {
319		err("usb_register failed. (%d)",result);
320		return result;
321	}
322
323	return 0;
324}
325
326static void __exit dtt200u_usb_module_exit(void)
327{
328	/* deregister this driver from the USB subsystem */
329	usb_deregister(&dtt200u_usb_driver);
330}
331
332module_init(dtt200u_usb_module_init);
333module_exit(dtt200u_usb_module_exit);
334
335MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
336MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D DVB-T USB2.0 devices");
337MODULE_VERSION("1.0");
338MODULE_LICENSE("GPL");
339