Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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