aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPatrick Boettcher <pb@linuxtv.org>2005-09-09 16:02:41 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-09 16:57:40 -0400
commit3706a4da2012679631da6d22e86c6a34cde7419a (patch)
tree45bf457db581f3b30d9ba49e1f4f1ad7f99f894c /drivers
parent80e27e20619902b11aa255081fd83eab10fc0839 (diff)
[PATCH] dvb: usb: add TwinhanDTV StarBox support
Add driver for the TwinhanDTV StarBox and clones. Thanks to Ralph Metzler for his initial work on this box and thanks to Twinhan for their support. Signed-off-by: Patrick Boettcher <pb@linuxtv.org> Signed-off-by: Johannes Stezenbach <js@linuxtv.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig23
-rw-r--r--drivers/media/dvb/dvb-usb/Makefile3
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h6
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x-fe.c339
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.c290
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.h109
6 files changed, 765 insertions, 5 deletions
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 612e5b087b1c..54e2b29076b1 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -93,13 +93,30 @@ config DVB_USB_DIGITV
93 Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver. 93 Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver.
94 94
95config DVB_USB_VP7045 95config DVB_USB_VP7045
96 tristate "TwinhanDTV Alpha/MagicBoxII and DNTV tinyUSB2 DVB-T USB2.0 support" 96 tristate "TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle USB2.0 support"
97 depends on DVB_USB 97 depends on DVB_USB
98 help 98 help
99 Say Y here to support the 99 Say Y here to support the
100
100 TwinhanDTV Alpha (stick) (VP-7045), 101 TwinhanDTV Alpha (stick) (VP-7045),
101 TwinhanDTV MagicBox II (VP-7046) and 102 TwinhanDTV MagicBox II (VP-7046),
102 DigitalNow TinyUSB 2 DVB-t DVB-T USB2.0 receivers. 103 DigitalNow TinyUSB 2 DVB-t,
104 DigitalRise USB 2.0 Ter (Beetle) and
105 TYPHOON DVB-T USB DRIVE
106
107 DVB-T USB2.0 receivers.
108
109config DVB_USB_VP702X
110 tristate "TwinhanDTV StarBox and clones DVB-S USB2.0 support"
111 depends on DVB_USB
112 help
113 Say Y here to support the
114
115 TwinhanDTV StarBox,
116 DigitalRise USB Starbox and
117 TYPHOON DVB-S USB 2.0 BOX
118
119 DVB-S USB2.0 receivers.
103 120
104config DVB_USB_NOVA_T_USB2 121config DVB_USB_NOVA_T_USB2
105 tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support" 122 tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index 746d87ed6f32..2dc9aad9681e 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -4,6 +4,9 @@ obj-$(CONFIG_DVB_USB) += dvb-usb.o
4dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o 4dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o
5obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o 5obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
6 6
7dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o
8obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o
9
7dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o 10dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
8obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o 11obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
9 12
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 794d513a8480..2b249c75fb02 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -52,12 +52,14 @@
52#define USB_PID_KWORLD_VSTREAM_WARM 0x17df 52#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
53#define USB_PID_TWINHAN_VP7041_COLD 0x3201 53#define USB_PID_TWINHAN_VP7041_COLD 0x3201
54#define USB_PID_TWINHAN_VP7041_WARM 0x3202 54#define USB_PID_TWINHAN_VP7041_WARM 0x3202
55#define USB_PID_TWINHAN_VP7020_COLD 0x3203
56#define USB_PID_TWINHAN_VP7020_WARM 0x3204
55#define USB_PID_TWINHAN_VP7045_COLD 0x3205 57#define USB_PID_TWINHAN_VP7045_COLD 0x3205
56#define USB_PID_TWINHAN_VP7045_WARM 0x3206 58#define USB_PID_TWINHAN_VP7045_WARM 0x3206
57#define USB_PID_DNTV_TINYUSB2_COLD 0x3223
58#define USB_PID_DNTV_TINYUSB2_WARM 0x3224
59#define USB_PID_TWINHAN_VP7021_COLD 0x3207 59#define USB_PID_TWINHAN_VP7021_COLD 0x3207
60#define USB_PID_TWINHAN_VP7021_WARM 0x3208 60#define USB_PID_TWINHAN_VP7021_WARM 0x3208
61#define USB_PID_DNTV_TINYUSB2_COLD 0x3223
62#define USB_PID_DNTV_TINYUSB2_WARM 0x3224
61#define USB_PID_ULTIMA_TVBOX_COLD 0x8105 63#define USB_PID_ULTIMA_TVBOX_COLD 0x8105
62#define USB_PID_ULTIMA_TVBOX_WARM 0x8106 64#define USB_PID_ULTIMA_TVBOX_WARM 0x8106
63#define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107 65#define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
new file mode 100644
index 000000000000..f20d8dbd0be8
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c
@@ -0,0 +1,339 @@
1/* DVB frontend part of the Linux driver for the TwinhanDTV StarBox USB2.0
2 * DVB-S 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 file can be removed soon, after the DST-driver is rewritten to provice
12 * the frontend-controlling separately.
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the Free
16 * Software Foundation, version 2.
17 *
18 * see Documentation/dvb/README.dvb-usb for more information
19 *
20 */
21#include "vp702x.h"
22
23struct vp702x_fe_state {
24 struct dvb_frontend fe;
25 struct dvb_usb_device *d;
26
27 fe_sec_voltage_t voltage;
28 fe_sec_tone_mode_t tone_mode;
29
30 u8 lnb_buf[8];
31
32 u8 lock;
33 u8 sig;
34 u8 snr;
35
36 unsigned long next_status_check;
37 unsigned long status_check_interval;
38};
39
40static int vp702x_fe_refresh_state(struct vp702x_fe_state *st)
41{
42 u8 buf[10];
43 if (time_after(jiffies,st->next_status_check)) {
44 vp702x_usb_in_op(st->d,READ_STATUS,0,0,buf,10);
45
46 st->lock = buf[4];
47 vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x11,0,&st->snr,1);
48 vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x15,0,&st->sig,1);
49
50 st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
51 }
52 return 0;
53}
54
55static u8 vp702x_chksum(u8 *buf,int f, int count)
56{
57 u8 s = 0;
58 int i;
59 for (i = f; i < f+count; i++)
60 s += buf[i];
61 return ~s+1;
62}
63
64static int vp702x_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
65{
66 struct vp702x_fe_state *st = fe->demodulator_priv;
67 vp702x_fe_refresh_state(st);
68 deb_fe("%s\n",__FUNCTION__);
69
70 if (st->lock == 0)
71 *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
72 else
73 *status = 0;
74
75 deb_fe("real state: %x\n",*status);
76 *status = 0x1f;
77
78 if (*status & FE_HAS_LOCK)
79 st->status_check_interval = 1000;
80 else
81 st->status_check_interval = 250;
82 return 0;
83}
84
85/* not supported by this Frontend */
86static int vp702x_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
87{
88 struct vp702x_fe_state *st = fe->demodulator_priv;
89 vp702x_fe_refresh_state(st);
90 *ber = 0;
91 return 0;
92}
93
94/* not supported by this Frontend */
95static int vp702x_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
96{
97 struct vp702x_fe_state *st = fe->demodulator_priv;
98 vp702x_fe_refresh_state(st);
99 *unc = 0;
100 return 0;
101}
102
103static int vp702x_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
104{
105 struct vp702x_fe_state *st = fe->demodulator_priv;
106 vp702x_fe_refresh_state(st);
107
108 *strength = (st->sig << 8) | st->sig;
109 return 0;
110}
111
112static int vp702x_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
113{
114 u8 _snr;
115 struct vp702x_fe_state *st = fe->demodulator_priv;
116 vp702x_fe_refresh_state(st);
117
118 _snr = (st->snr & 0x1f) * 0xff / 0x1f;
119 *snr = (_snr << 8) | _snr;
120 return 0;
121}
122
123static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
124{
125 deb_fe("%s\n",__FUNCTION__);
126 tune->min_delay_ms = 2000;
127 return 0;
128}
129
130static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
131 struct dvb_frontend_parameters *fep)
132{
133 struct vp702x_fe_state *st = fe->demodulator_priv;
134 u32 freq = fep->frequency/1000;
135 /*CalFrequency*/
136/* u16 frequencyRef[16] = { 2, 4, 8, 16, 32, 64, 128, 256, 24, 5, 10, 20, 40, 80, 160, 320 }; */
137 u64 sr;
138 u8 cmd[8] = { 0 },ibuf[10];
139
140 cmd[0] = (freq >> 8) & 0x7f;
141 cmd[1] = freq & 0xff;
142 cmd[2] = 1; /* divrate == 4 -> frequencyRef[1] -> 1 here */
143
144 sr = (u64) (fep->u.qpsk.symbol_rate/1000) << 20;
145 do_div(sr,88000);
146 cmd[3] = (sr >> 12) & 0xff;
147 cmd[4] = (sr >> 4) & 0xff;
148 cmd[5] = (sr << 4) & 0xf0;
149
150 deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %Lu (%Lx)\n",
151 fep->frequency,freq,freq, fep->u.qpsk.symbol_rate, sr, sr);
152
153/* if (fep->inversion == INVERSION_ON)
154 cmd[6] |= 0x80; */
155
156 if (st->voltage == SEC_VOLTAGE_18)
157 cmd[6] |= 0x40;
158
159/* if (fep->u.qpsk.symbol_rate > 8000000)
160 cmd[6] |= 0x20;
161
162 if (fep->frequency < 1531000)
163 cmd[6] |= 0x04;
164
165 if (st->tone_mode == SEC_TONE_ON)
166 cmd[6] |= 0x01;*/
167
168 cmd[7] = vp702x_chksum(cmd,0,7);
169
170 st->status_check_interval = 250;
171 st->next_status_check = jiffies;
172
173 vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0);
174 msleep(30);
175 vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
176
177 if (ibuf[2] == 0 && ibuf[3] == 0)
178 deb_fe("tuning failed.\n");
179 else
180 deb_fe("tuning succeeded.\n");
181
182 return 0;
183}
184
185static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
186 struct dvb_frontend_parameters *fep)
187{
188 deb_fe("%s\n",__FUNCTION__);
189 return 0;
190}
191
192static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
193 struct dvb_diseqc_master_cmd *m)
194{
195 struct vp702x_fe_state *st = fe->demodulator_priv;
196 u8 cmd[8],ibuf[10];
197 memset(cmd,0,8);
198
199 deb_fe("%s\n",__FUNCTION__);
200
201 if (m->msg_len > 4)
202 return -EINVAL;
203
204 cmd[1] = SET_DISEQC_CMD;
205 cmd[2] = m->msg_len;
206 memcpy(&cmd[3], m->msg, m->msg_len);
207 cmd[7] = vp702x_chksum(cmd,0,7);
208
209 vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
210
211 if (ibuf[2] == 0 && ibuf[3] == 0)
212 deb_fe("diseqc cmd failed.\n");
213 else
214 deb_fe("diseqc cmd succeeded.\n");
215
216 return 0;
217}
218
219static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
220{
221 deb_fe("%s\n",__FUNCTION__);
222 return 0;
223}
224
225static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
226{
227 struct vp702x_fe_state *st = fe->demodulator_priv;
228 u8 ibuf[10];
229 deb_fe("%s\n",__FUNCTION__);
230
231 st->tone_mode = tone;
232
233 if (tone == SEC_TONE_ON)
234 st->lnb_buf[2] = 0x02;
235 else
236 st->lnb_buf[2] = 0x00;
237
238 st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7);
239
240 vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100);
241 if (ibuf[2] == 0 && ibuf[3] == 0)
242 deb_fe("set_tone cmd failed.\n");
243 else
244 deb_fe("set_tone cmd succeeded.\n");
245
246 return 0;
247}
248
249static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
250 voltage)
251{
252 struct vp702x_fe_state *st = fe->demodulator_priv;
253 u8 ibuf[10];
254 deb_fe("%s\n",__FUNCTION__);
255
256 st->voltage = voltage;
257
258 if (voltage != SEC_VOLTAGE_OFF)
259 st->lnb_buf[4] = 0x01;
260 else
261 st->lnb_buf[4] = 0x00;
262
263 st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7);
264
265 vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100);
266 if (ibuf[2] == 0 && ibuf[3] == 0)
267 deb_fe("set_voltage cmd failed.\n");
268 else
269 deb_fe("set_voltage cmd succeeded.\n");
270
271 return 0;
272}
273
274static void vp702x_fe_release(struct dvb_frontend* fe)
275{
276 struct vp702x_fe_state *st = fe->demodulator_priv;
277 kfree(st);
278}
279
280static struct dvb_frontend_ops vp702x_fe_ops;
281
282struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d)
283{
284 struct vp702x_fe_state *s = kmalloc(sizeof(struct vp702x_fe_state), GFP_KERNEL);
285 if (s == NULL)
286 goto error;
287 memset(s,0,sizeof(struct vp702x_fe_state));
288
289 s->d = d;
290 s->fe.ops = &vp702x_fe_ops;
291 s->fe.demodulator_priv = s;
292
293 s->lnb_buf[1] = SET_LNB_POWER;
294 s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */
295
296 goto success;
297error:
298 return NULL;
299success:
300 return &s->fe;
301}
302
303
304static struct dvb_frontend_ops vp702x_fe_ops = {
305 .info = {
306 .name = "Twinhan DST-like frontend (VP7021/VP7020) DVB-S",
307 .type = FE_QPSK,
308 .frequency_min = 950000,
309 .frequency_max = 2150000,
310 .frequency_stepsize = 1000, /* kHz for QPSK frontends */
311 .frequency_tolerance = 0,
312 .symbol_rate_min = 1000000,
313 .symbol_rate_max = 45000000,
314 .symbol_rate_tolerance = 500, /* ppm */
315 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
316 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
317 FE_CAN_QPSK |
318 FE_CAN_FEC_AUTO
319 },
320 .release = vp702x_fe_release,
321
322 .init = NULL,
323 .sleep = NULL,
324
325 .set_frontend = vp702x_fe_set_frontend,
326 .get_frontend = vp702x_fe_get_frontend,
327 .get_tune_settings = vp702x_fe_get_tune_settings,
328
329 .read_status = vp702x_fe_read_status,
330 .read_ber = vp702x_fe_read_ber,
331 .read_signal_strength = vp702x_fe_read_signal_strength,
332 .read_snr = vp702x_fe_read_snr,
333 .read_ucblocks = vp702x_fe_read_unc_blocks,
334
335 .diseqc_send_master_cmd = vp702x_fe_send_diseqc_msg,
336 .diseqc_send_burst = vp702x_fe_send_diseqc_burst,
337 .set_tone = vp702x_fe_set_tone,
338 .set_voltage = vp702x_fe_set_voltage,
339};
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
new file mode 100644
index 000000000000..1f5034ca1152
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp702x.c
@@ -0,0 +1,290 @@
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
24struct vp702x_state {
25 u8 pid_table[17]; /* [16] controls the pid_table state */
26};
27
28/* check for mutex FIXME */
29int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
30{
31 int ret = 0,try = 0;
32
33 while (ret >= 0 && ret != blen && try < 3) {
34 ret = usb_control_msg(d->udev,
35 usb_rcvctrlpipe(d->udev,0),
36 req,
37 USB_TYPE_VENDOR | USB_DIR_IN,
38 value,index,b,blen,
39 2000);
40 deb_info("reading number %d (ret: %d)\n",try,ret);
41 try++;
42 }
43
44 if (ret < 0 || ret != blen) {
45 warn("usb in operation failed.");
46 ret = -EIO;
47 } else
48 ret = 0;
49
50 deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
51 debug_dump(b,blen,deb_xfer);
52
53 return ret;
54}
55
56int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
57{
58 deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
59 debug_dump(b,blen,deb_xfer);
60
61 if (usb_control_msg(d->udev,
62 usb_sndctrlpipe(d->udev,0),
63 req,
64 USB_TYPE_VENDOR | USB_DIR_OUT,
65 value,index,b,blen,
66 2000) != blen) {
67 warn("usb out operation failed.");
68 return -EIO;
69 } else
70 return 0;
71}
72
73int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec)
74{
75 int ret;
76
77 if ((ret = down_interruptible(&d->usb_sem)))
78 return ret;
79
80 if ((ret = vp702x_usb_out_op(d,REQUEST_OUT,0,0,o,olen)) < 0)
81 goto unlock;
82 msleep(msec);
83 ret = vp702x_usb_in_op(d,REQUEST_IN,0,0,i,ilen);
84
85unlock:
86 up(&d->usb_sem);
87
88 return ret;
89}
90
91int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec)
92{
93 u8 bout[olen+2];
94 u8 bin[ilen+1];
95 int ret = 0;
96
97 bout[0] = 0x00;
98 bout[1] = cmd;
99 memcpy(&bout[2],o,olen);
100
101 ret = vp702x_usb_inout_op(d, bout, olen+2, bin, ilen+1,msec);
102
103 if (ret == 0)
104 memcpy(i,&bin[1],ilen);
105
106 return ret;
107}
108
109static int vp702x_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff)
110{
111 struct vp702x_state *st = d->priv;
112 u8 buf[9];
113
114 if (onoff) {
115 st->pid_table[16] |= 1 << index;
116 st->pid_table[index*2] = (pid >> 8) & 0xff;
117 st->pid_table[index*2+1] = pid & 0xff;
118 } else {
119 st->pid_table[16] &= ~(1 << index);
120 st->pid_table[index*2] = st->pid_table[index*2+1] = 0;
121 }
122
123 return vp702x_usb_inout_cmd(d,SET_PID_FILTER,st->pid_table,17,buf,9,10);
124}
125
126static int vp702x_power_ctrl(struct dvb_usb_device *d, int onoff)
127{
128 vp702x_usb_in_op(d,RESET_TUNER,0,0,NULL,0);
129
130 vp702x_usb_in_op(d,SET_TUNER_POWER_REQ,0,onoff,NULL,0);
131 return vp702x_usb_in_op(d,SET_TUNER_POWER_REQ,0,onoff,NULL,0);
132}
133
134/* keys for the enclosed remote control */
135static struct dvb_usb_rc_key vp702x_rc_keys[] = {
136 { 0x00, 0x01, KEY_1 },
137 { 0x00, 0x02, KEY_2 },
138};
139
140/* remote control stuff (does not work with my box) */
141static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
142{
143 u8 key[10];
144 int i;
145
146/* remove the following return to enabled remote querying */
147 return 0;
148
149 vp702x_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10);
150
151 deb_rc("remote query key: %x %d\n",key[1],key[1]);
152
153 if (key[1] == 0x44) {
154 *state = REMOTE_NO_KEY_PRESSED;
155 return 0;
156 }
157
158 for (i = 0; i < ARRAY_SIZE(vp702x_rc_keys); i++)
159 if (vp702x_rc_keys[i].custom == key[1]) {
160 *state = REMOTE_KEY_PRESSED;
161 *event = vp702x_rc_keys[i].event;
162 break;
163 }
164 return 0;
165}
166
167static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
168{
169 u8 macb[9];
170 if (vp702x_usb_inout_cmd(d, GET_MAC_ADDRESS, NULL, 0, macb, 9, 10))
171 return -EIO;
172 memcpy(mac,&macb[3],6);
173 return 0;
174}
175
176static int vp702x_frontend_attach(struct dvb_usb_device *d)
177{
178 u8 buf[9] = { 0 };
179
180 if (vp702x_usb_inout_cmd(d, GET_SYSTEM_STRING, NULL, 0, buf, 9, 10))
181 return -EIO;
182
183 buf[8] = '\0';
184 info("system string: %s",&buf[1]);
185
186 d->fe = vp702x_fe_attach(d);
187 return 0;
188}
189
190static struct dvb_usb_properties vp702x_properties;
191
192static int vp702x_usb_probe(struct usb_interface *intf,
193 const struct usb_device_id *id)
194{
195 struct usb_device *udev = interface_to_usbdev(intf);
196
197 usb_clear_halt(udev,usb_sndctrlpipe(udev,0));
198 usb_clear_halt(udev,usb_rcvctrlpipe(udev,0));
199
200 return dvb_usb_device_init(intf,&vp702x_properties,THIS_MODULE);
201}
202
203static struct usb_device_id vp702x_usb_table [] = {
204 { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7021_COLD) },
205 { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7021_WARM) },
206 { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_COLD) },
207 { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_WARM) },
208 { 0 },
209};
210MODULE_DEVICE_TABLE(usb, vp702x_usb_table);
211
212static struct dvb_usb_properties vp702x_properties = {
213 .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
214 .pid_filter_count = 8, /* !!! */
215
216 .usb_ctrl = CYPRESS_FX2,
217 .firmware = "dvb-usb-vp702x-01.fw",
218
219 .pid_filter = vp702x_pid_filter,
220 .power_ctrl = vp702x_power_ctrl,
221 .frontend_attach = vp702x_frontend_attach,
222 .read_mac_address = vp702x_read_mac_addr,
223
224 .rc_key_map = vp702x_rc_keys,
225 .rc_key_map_size = ARRAY_SIZE(vp702x_rc_keys),
226 .rc_interval = 400,
227 .rc_query = vp702x_rc_query,
228
229 .size_of_priv = sizeof(struct vp702x_state),
230
231 /* parameter for the MPEG2-data transfer */
232 .urb = {
233 .type = DVB_USB_BULK,
234 .count = 7,
235 .endpoint = 0x02,
236 .u = {
237 .bulk = {
238 .buffersize = 4096,
239 }
240 }
241 },
242
243 .num_device_descs = 2,
244 .devices = {
245 { .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7021)",
246 .cold_ids = { &vp702x_usb_table[0], NULL },
247 .warm_ids = { &vp702x_usb_table[1], NULL },
248 },
249 { .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7020)",
250 .cold_ids = { &vp702x_usb_table[2], NULL },
251 .warm_ids = { &vp702x_usb_table[3], NULL },
252 },
253 { 0 },
254 }
255};
256
257/* usb specific object needed to register this driver with the usb subsystem */
258static struct usb_driver vp702x_usb_driver = {
259 .owner = THIS_MODULE,
260 .name = "dvb-usb-vp702x",
261 .probe = vp702x_usb_probe,
262 .disconnect = dvb_usb_device_exit,
263 .id_table = vp702x_usb_table,
264};
265
266/* module stuff */
267static int __init vp702x_usb_module_init(void)
268{
269 int result;
270 if ((result = usb_register(&vp702x_usb_driver))) {
271 err("usb_register failed. (%d)",result);
272 return result;
273 }
274
275 return 0;
276}
277
278static void __exit vp702x_usb_module_exit(void)
279{
280 /* deregister this driver from the USB subsystem */
281 usb_deregister(&vp702x_usb_driver);
282}
283
284module_init(vp702x_usb_module_init);
285module_exit(vp702x_usb_module_exit);
286
287MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
288MODULE_DESCRIPTION("Driver for Twinhan StarBox DVB-S USB2.0 and clones");
289MODULE_VERSION("1.0-alpha");
290MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h
new file mode 100644
index 000000000000..4a3e8c7eca2b
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp702x.h
@@ -0,0 +1,109 @@
1#ifndef _DVB_USB_VP7021_H_
2#define _DVB_USB_VP7021_H_
3
4#define DVB_USB_LOG_PREFIX "vp702x"
5#include "dvb-usb.h"
6
7extern int dvb_usb_vp702x_debug;
8#define deb_info(args...) dprintk(dvb_usb_vp702x_debug,0x01,args)
9#define deb_xfer(args...) dprintk(dvb_usb_vp702x_debug,0x02,args)
10#define deb_rc(args...) dprintk(dvb_usb_vp702x_debug,0x04,args)
11#define deb_fe(args...) dprintk(dvb_usb_vp702x_debug,0x08,args)
12
13/* commands are read and written with USB control messages */
14
15/* consecutive read/write operation */
16#define REQUEST_OUT 0xB2
17#define REQUEST_IN 0xB3
18
19/* the out-buffer of these consecutive operations contain sub-commands when b[0] = 0
20 * request: 0xB2; i: 0; v: 0; b[0] = 0, b[1] = subcmd, additional buffer
21 * the returning buffer looks as follows
22 * request: 0xB3; i: 0; v: 0; b[0] = 0xB3, additional buffer */
23
24#define GET_TUNER_STATUS 0x05
25/* additional in buffer:
26 * 0 1 2 3 4 5 6 7 8
27 * N/A N/A 0x05 signal-quality N/A N/A signal-strength lock==0 N/A */
28
29#define GET_SYSTEM_STRING 0x06
30/* additional in buffer:
31 * 0 1 2 3 4 5 6 7 8
32 * N/A 'U' 'S' 'B' '7' '0' '2' 'X' N/A */
33
34#define SET_DISEQC_CMD 0x08
35/* additional out buffer:
36 * 0 1 2 3 4
37 * len X1 X2 X3 X4
38 * additional in buffer:
39 * 0 1 2
40 * N/A 0 0 b[1] == b[2] == 0 -> success otherwise not */
41
42#define SET_LNB_POWER 0x09
43/* additional out buffer:
44 * 0 1 2
45 * 0x00 0xff 1 = on, 0 = off
46 * additional in buffer:
47 * 0 1 2
48 * N/A 0 0 b[1] == b[2] == 0 -> success otherwise not */
49
50#define GET_MAC_ADDRESS 0x0A
51/* #define GET_MAC_ADDRESS 0x0B */
52/* additional in buffer:
53 * 0 1 2 3 4 5 6 7 8
54 * N/A N/A 0x0A or 0x0B MAC0 MAC1 MAC2 MAC3 MAC4 MAC5 */
55
56#define SET_PID_FILTER 0x11
57/* additional in buffer:
58 * 0 1 ... 14 15 16
59 * PID0_MSB PID0_LSB ... PID7_MSB PID7_LSB PID_active (bits) */
60
61/* request: 0xB2; i: 0; v: 0;
62 * b[0] != 0 -> tune and lock a channel
63 * 0 1 2 3 4 5 6 7
64 * freq0 freq1 divstep srate0 srate1 srate2 flag chksum
65 */
66
67
68/* one direction requests */
69#define READ_REMOTE_REQ 0xB4
70/* IN i: 0; v: 0; b[0] == request, b[1] == key */
71
72#define READ_PID_NUMBER_REQ 0xB5
73/* IN i: 0; v: 0; b[0] == request, b[1] == 0, b[2] = pid number */
74
75#define WRITE_EEPROM_REQ 0xB6
76/* OUT i: offset; v: value to write; no extra buffer */
77
78#define READ_EEPROM_REQ 0xB7
79/* IN i: bufferlen; v: offset; buffer with bufferlen bytes */
80
81#define READ_STATUS 0xB8
82/* IN i: 0; v: 0; bufferlen 10 */
83
84#define READ_TUNER_REG_REQ 0xB9
85/* IN i: 0; v: register; b[0] = value */
86
87#define READ_FX2_REG_REQ 0xBA
88/* IN i: offset; v: 0; b[0] = value */
89
90#define WRITE_FX2_REG_REQ 0xBB
91/* OUT i: offset; v: value to write; 1 byte extra buffer */
92
93#define SET_TUNER_POWER_REQ 0xBC
94/* IN i: 0 = power off, 1 = power on */
95
96#define WRITE_TUNER_REG_REQ 0xBD
97/* IN i: register, v: value to write, no extra buffer */
98
99#define RESET_TUNER 0xBE
100/* IN i: 0, v: 0, no extra buffer */
101
102extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
103
104extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec);
105extern int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec);
106extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
107extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
108
109#endif