• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/media/dvb/dvb-usb/
1/* DVB USB compliant Linux driver for the TwinhanDTV StarBox USB2.0 DVB-S
2 * receiver.
3 *
4 * Copyright (C) 2005 Ralph Metzler <rjkm@metzlerbros.de>
5 *                    Metzler Brothers Systementwicklung GbR
6 *
7 * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
8 *
9 * Thanks to Twinhan who kindly provided hardware and information.
10 *
11 *	This program is free software; you can redistribute it and/or modify it
12 *	under the terms of the GNU General Public License as published by the Free
13 *	Software Foundation, version 2.
14 *
15 * see Documentation/dvb/README.dvb-usb for more information
16 */
17#include "vp702x.h"
18
19/* debug */
20int dvb_usb_vp702x_debug;
21module_param_named(debug,dvb_usb_vp702x_debug, int, 0644);
22MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
23
24DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
25
26struct vp702x_state {
27	int pid_filter_count;
28	int pid_filter_can_bypass;
29	u8  pid_filter_state;
30};
31
32struct vp702x_device_state {
33	u8 power_state;
34};
35
36int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
37{
38	int ret = -1;
39
40		ret = usb_control_msg(d->udev,
41			usb_rcvctrlpipe(d->udev,0),
42			req,
43			USB_TYPE_VENDOR | USB_DIR_IN,
44			value,index,b,blen,
45			2000);
46
47	if (ret < 0) {
48		warn("usb in operation failed. (%d)", ret);
49		ret = -EIO;
50	} else
51		ret = 0;
52
53
54	deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index);
55	debug_dump(b,blen,deb_xfer);
56
57	return ret;
58}
59
60static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
61			     u16 index, u8 *b, int blen)
62{
63	int ret;
64	deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index);
65	debug_dump(b,blen,deb_xfer);
66
67	if ((ret = usb_control_msg(d->udev,
68			usb_sndctrlpipe(d->udev,0),
69			req,
70			USB_TYPE_VENDOR | USB_DIR_OUT,
71			value,index,b,blen,
72			2000)) != blen) {
73		warn("usb out operation failed. (%d)",ret);
74		return -EIO;
75	} else
76		return 0;
77}
78
79int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec)
80{
81	int ret;
82
83	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
84		return ret;
85
86	ret = vp702x_usb_out_op(d,REQUEST_OUT,0,0,o,olen);
87	msleep(msec);
88	ret = vp702x_usb_in_op(d,REQUEST_IN,0,0,i,ilen);
89
90	mutex_unlock(&d->usb_mutex);
91
92	return ret;
93}
94
95static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o,
96				int olen, u8 *i, int ilen, int msec)
97{
98	u8 bout[olen+2];
99	u8 bin[ilen+1];
100	int ret = 0;
101
102	bout[0] = 0x00;
103	bout[1] = cmd;
104	memcpy(&bout[2],o,olen);
105
106	ret = vp702x_usb_inout_op(d, bout, olen+2, bin, ilen+1,msec);
107
108	if (ret == 0)
109		memcpy(i,&bin[1],ilen);
110
111	return ret;
112}
113
114static int vp702x_set_pld_mode(struct dvb_usb_adapter *adap, u8 bypass)
115{
116	u8 buf[16] = { 0 };
117	return vp702x_usb_in_op(adap->dev, 0xe0, (bypass << 8) | 0x0e, 0, buf, 16);
118}
119
120static int vp702x_set_pld_state(struct dvb_usb_adapter *adap, u8 state)
121{
122	u8 buf[16] = { 0 };
123	return vp702x_usb_in_op(adap->dev, 0xe0, (state << 8) | 0x0f, 0, buf, 16);
124}
125
126static int vp702x_set_pid(struct dvb_usb_adapter *adap, u16 pid, u8 id, int onoff)
127{
128	struct vp702x_state *st = adap->priv;
129	u8 buf[16] = { 0 };
130
131	if (onoff)
132		st->pid_filter_state |=  (1 << id);
133	else {
134		st->pid_filter_state &= ~(1 << id);
135		pid = 0xffff;
136	}
137
138	id = 0x10 + id*2;
139
140	vp702x_set_pld_state(adap, st->pid_filter_state);
141	vp702x_usb_in_op(adap->dev, 0xe0, (((pid >> 8) & 0xff) << 8) | (id), 0, buf, 16);
142	vp702x_usb_in_op(adap->dev, 0xe0, (((pid     ) & 0xff) << 8) | (id+1), 0, buf, 16);
143	return 0;
144}
145
146
147static int vp702x_init_pid_filter(struct dvb_usb_adapter *adap)
148{
149	struct vp702x_state *st = adap->priv;
150	int i;
151	u8 b[10] = { 0 };
152
153	st->pid_filter_count = 8;
154	st->pid_filter_can_bypass = 1;
155	st->pid_filter_state = 0x00;
156
157	vp702x_set_pld_mode(adap, 1); // bypass
158
159	for (i = 0; i < st->pid_filter_count; i++)
160		vp702x_set_pid(adap, 0xffff, i, 1);
161
162	vp702x_usb_in_op(adap->dev, 0xb5, 3, 0, b, 10);
163	vp702x_usb_in_op(adap->dev, 0xb5, 0, 0, b, 10);
164	vp702x_usb_in_op(adap->dev, 0xb5, 1, 0, b, 10);
165
166	//vp702x_set_pld_mode(d, 0); // filter
167	return 0;
168}
169
170static int vp702x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
171{
172	return 0;
173}
174
175/* keys for the enclosed remote control */
176static struct ir_scancode ir_codes_vp702x_table[] = {
177	{ 0x0001, KEY_1 },
178	{ 0x0002, KEY_2 },
179};
180
181/* remote control stuff (does not work with my box) */
182static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
183{
184	u8 key[10];
185	int i;
186
187/* remove the following return to enabled remote querying */
188	return 0;
189
190	vp702x_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10);
191
192	deb_rc("remote query key: %x %d\n",key[1],key[1]);
193
194	if (key[1] == 0x44) {
195		*state = REMOTE_NO_KEY_PRESSED;
196		return 0;
197	}
198
199	for (i = 0; i < ARRAY_SIZE(ir_codes_vp702x_table); i++)
200		if (rc5_custom(&ir_codes_vp702x_table[i]) == key[1]) {
201			*state = REMOTE_KEY_PRESSED;
202			*event = ir_codes_vp702x_table[i].keycode;
203			break;
204		}
205	return 0;
206}
207
208
209static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
210{
211	u8 i;
212	for (i = 6; i < 12; i++)
213		vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &mac[i - 6], 1);
214	return 0;
215}
216
217static int vp702x_frontend_attach(struct dvb_usb_adapter *adap)
218{
219	u8 buf[10] = { 0 };
220
221	vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 0, 7, NULL, 0);
222
223	if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0, buf, 10, 10))
224		return -EIO;
225
226	buf[9] = '\0';
227	info("system string: %s",&buf[1]);
228
229	vp702x_init_pid_filter(adap);
230
231	adap->fe = vp702x_fe_attach(adap->dev);
232	vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 1, 7, NULL, 0);
233
234	return 0;
235}
236
237static struct dvb_usb_device_properties vp702x_properties;
238
239static int vp702x_usb_probe(struct usb_interface *intf,
240		const struct usb_device_id *id)
241{
242	return dvb_usb_device_init(intf, &vp702x_properties,
243				   THIS_MODULE, NULL, adapter_nr);
244}
245
246static struct usb_device_id vp702x_usb_table [] = {
247	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7021_COLD) },
248//	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_COLD) },
249//	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_WARM) },
250	    { 0 },
251};
252MODULE_DEVICE_TABLE(usb, vp702x_usb_table);
253
254static struct dvb_usb_device_properties vp702x_properties = {
255	.usb_ctrl = CYPRESS_FX2,
256	.firmware            = "dvb-usb-vp702x-02.fw",
257	.no_reconnect        = 1,
258
259	.size_of_priv     = sizeof(struct vp702x_device_state),
260
261	.num_adapters = 1,
262	.adapter = {
263		{
264			.caps             = DVB_USB_ADAP_RECEIVES_204_BYTE_TS,
265
266			.streaming_ctrl   = vp702x_streaming_ctrl,
267			.frontend_attach  = vp702x_frontend_attach,
268
269			/* parameter for the MPEG2-data transfer */
270			.stream = {
271				.type = USB_BULK,
272				.count = 10,
273				.endpoint = 0x02,
274				.u = {
275					.bulk = {
276						.buffersize = 4096,
277					}
278				}
279			},
280			.size_of_priv     = sizeof(struct vp702x_state),
281		}
282	},
283	.read_mac_address = vp702x_read_mac_addr,
284
285	.rc.legacy = {
286		.rc_key_map       = ir_codes_vp702x_table,
287		.rc_key_map_size  = ARRAY_SIZE(ir_codes_vp702x_table),
288		.rc_interval      = 400,
289		.rc_query         = vp702x_rc_query,
290	},
291
292	.num_device_descs = 1,
293	.devices = {
294		{ .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7021)",
295		  .cold_ids = { &vp702x_usb_table[0], NULL },
296		  .warm_ids = { NULL },
297		},
298/*		{ .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7020)",
299		  .cold_ids = { &vp702x_usb_table[2], NULL },
300		  .warm_ids = { &vp702x_usb_table[3], NULL },
301		},
302*/		{ NULL },
303	}
304};
305
306/* usb specific object needed to register this driver with the usb subsystem */
307static struct usb_driver vp702x_usb_driver = {
308	.name		= "dvb_usb_vp702x",
309	.probe 		= vp702x_usb_probe,
310	.disconnect = dvb_usb_device_exit,
311	.id_table 	= vp702x_usb_table,
312};
313
314/* module stuff */
315static int __init vp702x_usb_module_init(void)
316{
317	int result;
318	if ((result = usb_register(&vp702x_usb_driver))) {
319		err("usb_register failed. (%d)",result);
320		return result;
321	}
322
323	return 0;
324}
325
326static void __exit vp702x_usb_module_exit(void)
327{
328	/* deregister this driver from the USB subsystem */
329	usb_deregister(&vp702x_usb_driver);
330}
331
332module_init(vp702x_usb_module_init);
333module_exit(vp702x_usb_module_exit);
334
335MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
336MODULE_DESCRIPTION("Driver for Twinhan StarBox DVB-S USB2.0 and clones");
337MODULE_VERSION("1.0");
338MODULE_LICENSE("GPL");
339