0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include "vp702x.h"
0015 #include <linux/mutex.h>
0016
0017
0018 int dvb_usb_vp702x_debug;
0019 module_param_named(debug,dvb_usb_vp702x_debug, int, 0644);
0020 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
0021
0022 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
0023
0024 struct vp702x_adapter_state {
0025 int pid_filter_count;
0026 int pid_filter_can_bypass;
0027 u8 pid_filter_state;
0028 };
0029
0030 static int vp702x_usb_in_op_unlocked(struct dvb_usb_device *d, u8 req,
0031 u16 value, u16 index, u8 *b, int blen)
0032 {
0033 int ret;
0034
0035 ret = usb_control_msg(d->udev,
0036 usb_rcvctrlpipe(d->udev, 0),
0037 req,
0038 USB_TYPE_VENDOR | USB_DIR_IN,
0039 value, index, b, blen,
0040 2000);
0041
0042 if (ret < 0) {
0043 warn("usb in operation failed. (%d)", ret);
0044 ret = -EIO;
0045 } else
0046 ret = 0;
0047
0048
0049 deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index);
0050 debug_dump(b,blen,deb_xfer);
0051
0052 return ret;
0053 }
0054
0055 int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value,
0056 u16 index, u8 *b, int blen)
0057 {
0058 int ret;
0059
0060 mutex_lock(&d->usb_mutex);
0061 ret = vp702x_usb_in_op_unlocked(d, req, value, index, b, blen);
0062 mutex_unlock(&d->usb_mutex);
0063
0064 return ret;
0065 }
0066
0067 static int vp702x_usb_out_op_unlocked(struct dvb_usb_device *d, u8 req,
0068 u16 value, u16 index, u8 *b, int blen)
0069 {
0070 int ret;
0071 deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index);
0072 debug_dump(b,blen,deb_xfer);
0073
0074 if ((ret = usb_control_msg(d->udev,
0075 usb_sndctrlpipe(d->udev,0),
0076 req,
0077 USB_TYPE_VENDOR | USB_DIR_OUT,
0078 value,index,b,blen,
0079 2000)) != blen) {
0080 warn("usb out operation failed. (%d)",ret);
0081 return -EIO;
0082 } else
0083 return 0;
0084 }
0085
0086 static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
0087 u16 index, u8 *b, int blen)
0088 {
0089 int ret;
0090
0091 mutex_lock(&d->usb_mutex);
0092 ret = vp702x_usb_out_op_unlocked(d, req, value, index, b, blen);
0093 mutex_unlock(&d->usb_mutex);
0094
0095 return ret;
0096 }
0097
0098 int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec)
0099 {
0100 int ret;
0101
0102 if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
0103 return ret;
0104
0105 ret = vp702x_usb_out_op_unlocked(d, REQUEST_OUT, 0, 0, o, olen);
0106 msleep(msec);
0107 ret = vp702x_usb_in_op_unlocked(d, REQUEST_IN, 0, 0, i, ilen);
0108
0109 mutex_unlock(&d->usb_mutex);
0110 return ret;
0111 }
0112
0113 static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o,
0114 int olen, u8 *i, int ilen, int msec)
0115 {
0116 struct vp702x_device_state *st = d->priv;
0117 int ret = 0;
0118 u8 *buf;
0119 int buflen = max(olen + 2, ilen + 1);
0120
0121 ret = mutex_lock_interruptible(&st->buf_mutex);
0122 if (ret < 0)
0123 return ret;
0124
0125 if (buflen > st->buf_len) {
0126 buf = kmalloc(buflen, GFP_KERNEL);
0127 if (!buf) {
0128 mutex_unlock(&st->buf_mutex);
0129 return -ENOMEM;
0130 }
0131 info("successfully reallocated a bigger buffer");
0132 kfree(st->buf);
0133 st->buf = buf;
0134 st->buf_len = buflen;
0135 } else {
0136 buf = st->buf;
0137 }
0138
0139 buf[0] = 0x00;
0140 buf[1] = cmd;
0141 memcpy(&buf[2], o, olen);
0142
0143 ret = vp702x_usb_inout_op(d, buf, olen+2, buf, ilen+1, msec);
0144
0145 if (ret == 0)
0146 memcpy(i, &buf[1], ilen);
0147 mutex_unlock(&st->buf_mutex);
0148
0149 return ret;
0150 }
0151
0152 static int vp702x_set_pld_mode(struct dvb_usb_adapter *adap, u8 bypass)
0153 {
0154 int ret;
0155 struct vp702x_device_state *st = adap->dev->priv;
0156 u8 *buf;
0157
0158 mutex_lock(&st->buf_mutex);
0159
0160 buf = st->buf;
0161 memset(buf, 0, 16);
0162
0163 ret = vp702x_usb_in_op(adap->dev, 0xe0, (bypass << 8) | 0x0e,
0164 0, buf, 16);
0165 mutex_unlock(&st->buf_mutex);
0166 return ret;
0167 }
0168
0169 static int vp702x_set_pld_state(struct dvb_usb_adapter *adap, u8 state)
0170 {
0171 int ret;
0172 struct vp702x_device_state *st = adap->dev->priv;
0173 u8 *buf;
0174
0175 mutex_lock(&st->buf_mutex);
0176
0177 buf = st->buf;
0178 memset(buf, 0, 16);
0179 ret = vp702x_usb_in_op(adap->dev, 0xe0, (state << 8) | 0x0f,
0180 0, buf, 16);
0181
0182 mutex_unlock(&st->buf_mutex);
0183
0184 return ret;
0185 }
0186
0187 static int vp702x_set_pid(struct dvb_usb_adapter *adap, u16 pid, u8 id, int onoff)
0188 {
0189 struct vp702x_adapter_state *st = adap->priv;
0190 struct vp702x_device_state *dst = adap->dev->priv;
0191 u8 *buf;
0192
0193 if (onoff)
0194 st->pid_filter_state |= (1 << id);
0195 else {
0196 st->pid_filter_state &= ~(1 << id);
0197 pid = 0xffff;
0198 }
0199
0200 id = 0x10 + id*2;
0201
0202 vp702x_set_pld_state(adap, st->pid_filter_state);
0203
0204 mutex_lock(&dst->buf_mutex);
0205
0206 buf = dst->buf;
0207 memset(buf, 0, 16);
0208 vp702x_usb_in_op(adap->dev, 0xe0, (((pid >> 8) & 0xff) << 8) | (id), 0, buf, 16);
0209 vp702x_usb_in_op(adap->dev, 0xe0, (((pid ) & 0xff) << 8) | (id+1), 0, buf, 16);
0210
0211 mutex_unlock(&dst->buf_mutex);
0212
0213 return 0;
0214 }
0215
0216
0217 static int vp702x_init_pid_filter(struct dvb_usb_adapter *adap)
0218 {
0219 struct vp702x_adapter_state *st = adap->priv;
0220 struct vp702x_device_state *dst = adap->dev->priv;
0221 int i;
0222 u8 *b;
0223
0224 st->pid_filter_count = 8;
0225 st->pid_filter_can_bypass = 1;
0226 st->pid_filter_state = 0x00;
0227
0228 vp702x_set_pld_mode(adap, 1);
0229
0230 for (i = 0; i < st->pid_filter_count; i++)
0231 vp702x_set_pid(adap, 0xffff, i, 1);
0232
0233 mutex_lock(&dst->buf_mutex);
0234 b = dst->buf;
0235 memset(b, 0, 10);
0236 vp702x_usb_in_op(adap->dev, 0xb5, 3, 0, b, 10);
0237 vp702x_usb_in_op(adap->dev, 0xb5, 0, 0, b, 10);
0238 vp702x_usb_in_op(adap->dev, 0xb5, 1, 0, b, 10);
0239 mutex_unlock(&dst->buf_mutex);
0240
0241
0242 return 0;
0243 }
0244
0245 static int vp702x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
0246 {
0247 return 0;
0248 }
0249
0250
0251 static struct rc_map_table rc_map_vp702x_table[] = {
0252 { 0x0001, KEY_1 },
0253 { 0x0002, KEY_2 },
0254 };
0255
0256
0257 static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
0258 {
0259
0260 #if 0
0261 u8 *key;
0262 int i;
0263
0264 key = kmalloc(10, GFP_KERNEL);
0265 if (!key)
0266 return -ENOMEM;
0267
0268 vp702x_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10);
0269
0270 deb_rc("remote query key: %x %d\n",key[1],key[1]);
0271
0272 if (key[1] == 0x44) {
0273 *state = REMOTE_NO_KEY_PRESSED;
0274 kfree(key);
0275 return 0;
0276 }
0277
0278 for (i = 0; i < ARRAY_SIZE(rc_map_vp702x_table); i++)
0279 if (rc5_custom(&rc_map_vp702x_table[i]) == key[1]) {
0280 *state = REMOTE_KEY_PRESSED;
0281 *event = rc_map_vp702x_table[i].keycode;
0282 break;
0283 }
0284 kfree(key);
0285 #endif
0286
0287 return 0;
0288 }
0289
0290
0291 static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
0292 {
0293 u8 i, *buf;
0294 int ret;
0295 struct vp702x_device_state *st = d->priv;
0296
0297 mutex_lock(&st->buf_mutex);
0298 buf = st->buf;
0299 for (i = 6; i < 12; i++) {
0300 ret = vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1,
0301 &buf[i - 6], 1);
0302 if (ret < 0)
0303 goto err;
0304 }
0305
0306 memcpy(mac, buf, 6);
0307 err:
0308 mutex_unlock(&st->buf_mutex);
0309 return ret;
0310 }
0311
0312 static int vp702x_frontend_attach(struct dvb_usb_adapter *adap)
0313 {
0314 u8 buf[10] = { 0 };
0315
0316 vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 0, 7, NULL, 0);
0317
0318 if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0,
0319 buf, 10, 10))
0320 return -EIO;
0321
0322 buf[9] = '\0';
0323 info("system string: %s",&buf[1]);
0324
0325 vp702x_init_pid_filter(adap);
0326
0327 adap->fe_adap[0].fe = vp702x_fe_attach(adap->dev);
0328 vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 1, 7, NULL, 0);
0329
0330 return 0;
0331 }
0332
0333 static struct dvb_usb_device_properties vp702x_properties;
0334
0335 static int vp702x_usb_probe(struct usb_interface *intf,
0336 const struct usb_device_id *id)
0337 {
0338 struct dvb_usb_device *d;
0339 struct vp702x_device_state *st;
0340 int ret;
0341
0342 ret = dvb_usb_device_init(intf, &vp702x_properties,
0343 THIS_MODULE, &d, adapter_nr);
0344 if (ret)
0345 goto out;
0346
0347 st = d->priv;
0348 st->buf_len = 16;
0349 st->buf = kmalloc(st->buf_len, GFP_KERNEL);
0350 if (!st->buf) {
0351 ret = -ENOMEM;
0352 dvb_usb_device_exit(intf);
0353 goto out;
0354 }
0355 mutex_init(&st->buf_mutex);
0356
0357 out:
0358 return ret;
0359
0360 }
0361
0362 static void vp702x_usb_disconnect(struct usb_interface *intf)
0363 {
0364 struct dvb_usb_device *d = usb_get_intfdata(intf);
0365 struct vp702x_device_state *st = d->priv;
0366 mutex_lock(&st->buf_mutex);
0367 kfree(st->buf);
0368 mutex_unlock(&st->buf_mutex);
0369 dvb_usb_device_exit(intf);
0370 }
0371
0372 enum {
0373 VISIONPLUS_VP7021_COLD,
0374 VISIONPLUS_VP7020_COLD,
0375 VISIONPLUS_VP7020_WARM,
0376 };
0377
0378 static struct usb_device_id vp702x_usb_table[] = {
0379 DVB_USB_DEV(VISIONPLUS, VISIONPLUS_VP7021_COLD),
0380
0381
0382 { }
0383 };
0384
0385 MODULE_DEVICE_TABLE(usb, vp702x_usb_table);
0386
0387 static struct dvb_usb_device_properties vp702x_properties = {
0388 .usb_ctrl = CYPRESS_FX2,
0389 .firmware = "dvb-usb-vp702x-02.fw",
0390 .no_reconnect = 1,
0391
0392 .size_of_priv = sizeof(struct vp702x_device_state),
0393
0394 .num_adapters = 1,
0395 .adapter = {
0396 {
0397 .num_frontends = 1,
0398 .fe = {{
0399 .caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS,
0400
0401 .streaming_ctrl = vp702x_streaming_ctrl,
0402 .frontend_attach = vp702x_frontend_attach,
0403
0404
0405 .stream = {
0406 .type = USB_BULK,
0407 .count = 10,
0408 .endpoint = 0x02,
0409 .u = {
0410 .bulk = {
0411 .buffersize = 4096,
0412 }
0413 }
0414 },
0415 }},
0416 .size_of_priv = sizeof(struct vp702x_adapter_state),
0417 }
0418 },
0419 .read_mac_address = vp702x_read_mac_addr,
0420
0421 .rc.legacy = {
0422 .rc_map_table = rc_map_vp702x_table,
0423 .rc_map_size = ARRAY_SIZE(rc_map_vp702x_table),
0424 .rc_interval = 400,
0425 .rc_query = vp702x_rc_query,
0426 },
0427
0428 .num_device_descs = 1,
0429 .devices = {
0430 { .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7021)",
0431 .cold_ids = { &vp702x_usb_table[VISIONPLUS_VP7021_COLD], NULL },
0432 .warm_ids = { NULL },
0433 },
0434
0435
0436
0437
0438 { NULL },
0439 }
0440 };
0441
0442
0443 static struct usb_driver vp702x_usb_driver = {
0444 .name = "dvb_usb_vp702x",
0445 .probe = vp702x_usb_probe,
0446 .disconnect = vp702x_usb_disconnect,
0447 .id_table = vp702x_usb_table,
0448 };
0449
0450 module_usb_driver(vp702x_usb_driver);
0451
0452 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
0453 MODULE_DESCRIPTION("Driver for Twinhan StarBox DVB-S USB2.0 and clones");
0454 MODULE_VERSION("1.0");
0455 MODULE_LICENSE("GPL");