1 /* 2 * Linux driver for Technisat DVB-S/S2 USB 2.0 device 3 * 4 * Copyright (C) 2010 Patrick Boettcher, 5 * Kernel Labs Inc. PO Box 745, St James, NY 11780 6 * 7 * Development was sponsored by Technisat Digital UK Limited, whose 8 * registered office is Witan Gate House 500 - 600 Witan Gate West, 9 * Milton Keynes, MK9 1SH 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation; either version 2 of the 14 * License, or (at your option) any later version. 15 * 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * 21 * THIS PROGRAM IS PROVIDED "AS IS" AND BOTH THE COPYRIGHT HOLDER AND 22 * TECHNISAT DIGITAL UK LTD DISCLAIM ALL WARRANTIES WITH REGARD TO 23 * THIS PROGRAM INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY OR 24 * FITNESS FOR A PARTICULAR PURPOSE. NEITHER THE COPYRIGHT HOLDER 25 * NOR TECHNISAT DIGITAL UK LIMITED SHALL BE LIABLE FOR ANY SPECIAL, 26 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 27 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 28 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 29 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS PROGRAM. See the 30 * GNU General Public License for more details. 31 */ 32 33 #define DVB_USB_LOG_PREFIX "technisat-usb2" 34 #include "dvb-usb.h" 35 36 #include "stv6110x.h" 37 #include "stv090x.h" 38 39 /* module parameters */ 40 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 41 42 static int debug; 43 module_param(debug, int, 0644); 44 MODULE_PARM_DESC(debug, 45 "set debugging level (bit-mask: 1=info,2=eeprom,4=i2c,8=rc)." \ 46 DVB_USB_DEBUG_STATUS); 47 48 /* disables all LED control command and 49 * also does not start the signal polling thread */ 50 static int disable_led_control; 51 module_param(disable_led_control, int, 0444); 52 MODULE_PARM_DESC(disable_led_control, 53 "disable LED control of the device " 54 "(default: 0 - LED control is active)."); 55 56 /* device private data */ 57 struct technisat_usb2_state { 58 struct dvb_usb_device *dev; 59 struct delayed_work green_led_work; 60 u8 power_state; 61 62 u16 last_scan_code; 63 64 u8 buf[64]; 65 }; 66 67 /* debug print helpers */ 68 #define deb_info(args...) dprintk(debug, 0x01, args) 69 #define deb_eeprom(args...) dprintk(debug, 0x02, args) 70 #define deb_i2c(args...) dprintk(debug, 0x04, args) 71 #define deb_rc(args...) dprintk(debug, 0x08, args) 72 73 /* vendor requests */ 74 #define SET_IFCLK_TO_EXTERNAL_TSCLK_VENDOR_REQUEST 0xB3 75 #define SET_FRONT_END_RESET_VENDOR_REQUEST 0xB4 76 #define GET_VERSION_INFO_VENDOR_REQUEST 0xB5 77 #define SET_GREEN_LED_VENDOR_REQUEST 0xB6 78 #define SET_RED_LED_VENDOR_REQUEST 0xB7 79 #define GET_IR_DATA_VENDOR_REQUEST 0xB8 80 #define SET_LED_TIMER_DIVIDER_VENDOR_REQUEST 0xB9 81 #define SET_USB_REENUMERATION 0xBA 82 83 /* i2c-access methods */ 84 #define I2C_SPEED_100KHZ_BIT 0x40 85 86 #define I2C_STATUS_NAK 7 87 #define I2C_STATUS_OK 8 88 89 static int technisat_usb2_i2c_access(struct usb_device *udev, 90 u8 device_addr, u8 *tx, u8 txlen, u8 *rx, u8 rxlen) 91 { 92 u8 b[64]; 93 int ret, actual_length; 94 95 deb_i2c("i2c-access: %02x, tx: ", device_addr); 96 debug_dump(tx, txlen, deb_i2c); 97 deb_i2c(" "); 98 99 if (txlen > 62) { 100 err("i2c TX buffer can't exceed 62 bytes (dev 0x%02x)", 101 device_addr); 102 txlen = 62; 103 } 104 if (rxlen > 62) { 105 err("i2c RX buffer can't exceed 62 bytes (dev 0x%02x)", 106 device_addr); 107 rxlen = 62; 108 } 109 110 b[0] = I2C_SPEED_100KHZ_BIT; 111 b[1] = device_addr << 1; 112 113 if (rx != NULL) { 114 b[0] |= rxlen; 115 b[1] |= 1; 116 } 117 118 memcpy(&b[2], tx, txlen); 119 ret = usb_bulk_msg(udev, 120 usb_sndbulkpipe(udev, 0x01), 121 b, 2 + txlen, 122 NULL, 1000); 123 124 if (ret < 0) { 125 err("i2c-error: out failed %02x = %d", device_addr, ret); 126 return -ENODEV; 127 } 128 129 ret = usb_bulk_msg(udev, 130 usb_rcvbulkpipe(udev, 0x01), 131 b, 64, &actual_length, 1000); 132 if (ret < 0) { 133 err("i2c-error: in failed %02x = %d", device_addr, ret); 134 return -ENODEV; 135 } 136 137 if (b[0] != I2C_STATUS_OK) { 138 err("i2c-error: %02x = %d", device_addr, b[0]); 139 /* handle tuner-i2c-nak */ 140 if (!(b[0] == I2C_STATUS_NAK && 141 device_addr == 0x60 142 /* && device_is_technisat_usb2 */)) 143 return -ENODEV; 144 } 145 146 deb_i2c("status: %d, ", b[0]); 147 148 if (rx != NULL) { 149 memcpy(rx, &b[2], rxlen); 150 151 deb_i2c("rx (%d): ", rxlen); 152 debug_dump(rx, rxlen, deb_i2c); 153 } 154 155 deb_i2c("\n"); 156 157 return 0; 158 } 159 160 static int technisat_usb2_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, 161 int num) 162 { 163 int ret = 0, i; 164 struct dvb_usb_device *d = i2c_get_adapdata(adap); 165 166 /* Ensure nobody else hits the i2c bus while we're sending our 167 sequence of messages, (such as the remote control thread) */ 168 if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 169 return -EAGAIN; 170 171 for (i = 0; i < num; i++) { 172 if (i+1 < num && msg[i+1].flags & I2C_M_RD) { 173 ret = technisat_usb2_i2c_access(d->udev, msg[i+1].addr, 174 msg[i].buf, msg[i].len, 175 msg[i+1].buf, msg[i+1].len); 176 if (ret != 0) 177 break; 178 i++; 179 } else { 180 ret = technisat_usb2_i2c_access(d->udev, msg[i].addr, 181 msg[i].buf, msg[i].len, 182 NULL, 0); 183 if (ret != 0) 184 break; 185 } 186 } 187 188 if (ret == 0) 189 ret = i; 190 191 mutex_unlock(&d->i2c_mutex); 192 193 return ret; 194 } 195 196 static u32 technisat_usb2_i2c_func(struct i2c_adapter *adapter) 197 { 198 return I2C_FUNC_I2C; 199 } 200 201 static struct i2c_algorithm technisat_usb2_i2c_algo = { 202 .master_xfer = technisat_usb2_i2c_xfer, 203 .functionality = technisat_usb2_i2c_func, 204 }; 205 206 #if 0 207 static void technisat_usb2_frontend_reset(struct usb_device *udev) 208 { 209 usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 210 SET_FRONT_END_RESET_VENDOR_REQUEST, 211 USB_TYPE_VENDOR | USB_DIR_OUT, 212 10, 0, 213 NULL, 0, 500); 214 } 215 #endif 216 217 /* LED control */ 218 enum technisat_usb2_led_state { 219 TECH_LED_OFF, 220 TECH_LED_BLINK, 221 TECH_LED_ON, 222 TECH_LED_UNDEFINED 223 }; 224 225 static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, 226 enum technisat_usb2_led_state st) 227 { 228 struct technisat_usb2_state *state = d->priv; 229 u8 *led = state->buf; 230 int ret; 231 232 led[0] = red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST; 233 234 if (disable_led_control && st != TECH_LED_OFF) 235 return 0; 236 237 switch (st) { 238 case TECH_LED_ON: 239 led[1] = 0x82; 240 break; 241 case TECH_LED_BLINK: 242 led[1] = 0x82; 243 if (red) { 244 led[2] = 0x02; 245 led[3] = 10; 246 led[4] = 10; 247 } else { 248 led[2] = 0xff; 249 led[3] = 50; 250 led[4] = 50; 251 } 252 led[5] = 1; 253 break; 254 255 default: 256 case TECH_LED_OFF: 257 led[1] = 0x80; 258 break; 259 } 260 261 if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 262 return -EAGAIN; 263 264 ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), 265 red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST, 266 USB_TYPE_VENDOR | USB_DIR_OUT, 267 0, 0, 268 led, 8, 500); 269 270 mutex_unlock(&d->i2c_mutex); 271 return ret; 272 } 273 274 static int technisat_usb2_set_led_timer(struct dvb_usb_device *d, u8 red, u8 green) 275 { 276 struct technisat_usb2_state *state = d->priv; 277 u8 *b = state->buf; 278 int ret; 279 280 b[0] = 0; 281 282 if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 283 return -EAGAIN; 284 285 ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), 286 SET_LED_TIMER_DIVIDER_VENDOR_REQUEST, 287 USB_TYPE_VENDOR | USB_DIR_OUT, 288 (red << 8) | green, 0, 289 b, 1, 500); 290 291 mutex_unlock(&d->i2c_mutex); 292 293 return ret; 294 } 295 296 static void technisat_usb2_green_led_control(struct work_struct *work) 297 { 298 struct technisat_usb2_state *state = 299 container_of(work, struct technisat_usb2_state, green_led_work.work); 300 struct dvb_frontend *fe = state->dev->adapter[0].fe_adap[0].fe; 301 302 if (state->power_state == 0) 303 goto schedule; 304 305 if (fe != NULL) { 306 enum fe_status status; 307 308 if (fe->ops.read_status(fe, &status) != 0) 309 goto schedule; 310 311 if (status & FE_HAS_LOCK) { 312 u32 ber; 313 314 if (fe->ops.read_ber(fe, &ber) != 0) 315 goto schedule; 316 317 if (ber > 1000) 318 technisat_usb2_set_led(state->dev, 0, TECH_LED_BLINK); 319 else 320 technisat_usb2_set_led(state->dev, 0, TECH_LED_ON); 321 } else 322 technisat_usb2_set_led(state->dev, 0, TECH_LED_OFF); 323 } 324 325 schedule: 326 schedule_delayed_work(&state->green_led_work, 327 msecs_to_jiffies(500)); 328 } 329 330 /* method to find out whether the firmware has to be downloaded or not */ 331 static int technisat_usb2_identify_state(struct usb_device *udev, 332 struct dvb_usb_device_properties *props, 333 struct dvb_usb_device_description **desc, int *cold) 334 { 335 int ret; 336 u8 *version; 337 338 version = kmalloc(3, GFP_KERNEL); 339 if (!version) 340 return -ENOMEM; 341 342 /* first select the interface */ 343 if (usb_set_interface(udev, 0, 1) != 0) 344 err("could not set alternate setting to 0"); 345 else 346 info("set alternate setting"); 347 348 *cold = 0; /* by default do not download a firmware - just in case something is wrong */ 349 350 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 351 GET_VERSION_INFO_VENDOR_REQUEST, 352 USB_TYPE_VENDOR | USB_DIR_IN, 353 0, 0, 354 version, 3, 500); 355 356 if (ret < 0) 357 *cold = 1; 358 else { 359 info("firmware version: %d.%d", version[1], version[2]); 360 *cold = 0; 361 } 362 363 kfree(version); 364 365 return 0; 366 } 367 368 /* power control */ 369 static int technisat_usb2_power_ctrl(struct dvb_usb_device *d, int level) 370 { 371 struct technisat_usb2_state *state = d->priv; 372 373 state->power_state = level; 374 375 if (disable_led_control) 376 return 0; 377 378 /* green led is turned off in any case - will be turned on when tuning */ 379 technisat_usb2_set_led(d, 0, TECH_LED_OFF); 380 /* red led is turned on all the time */ 381 technisat_usb2_set_led(d, 1, TECH_LED_ON); 382 return 0; 383 } 384 385 /* mac address reading - from the eeprom */ 386 #if 0 387 static void technisat_usb2_eeprom_dump(struct dvb_usb_device *d) 388 { 389 u8 reg; 390 u8 b[16]; 391 int i, j; 392 393 /* full EEPROM dump */ 394 for (j = 0; j < 256 * 4; j += 16) { 395 reg = j; 396 if (technisat_usb2_i2c_access(d->udev, 0x50 + j / 256, ®, 1, b, 16) != 0) 397 break; 398 399 deb_eeprom("EEPROM: %01x%02x: ", j / 256, reg); 400 for (i = 0; i < 16; i++) 401 deb_eeprom("%02x ", b[i]); 402 deb_eeprom("\n"); 403 } 404 } 405 #endif 406 407 static u8 technisat_usb2_calc_lrc(const u8 *b, u16 length) 408 { 409 u8 lrc = 0; 410 while (--length) 411 lrc ^= *b++; 412 return lrc; 413 } 414 415 static int technisat_usb2_eeprom_lrc_read(struct dvb_usb_device *d, 416 u16 offset, u8 *b, u16 length, u8 tries) 417 { 418 u8 bo = offset & 0xff; 419 struct i2c_msg msg[] = { 420 { 421 .addr = 0x50 | ((offset >> 8) & 0x3), 422 .buf = &bo, 423 .len = 1 424 }, { 425 .addr = 0x50 | ((offset >> 8) & 0x3), 426 .flags = I2C_M_RD, 427 .buf = b, 428 .len = length 429 } 430 }; 431 432 while (tries--) { 433 int status; 434 435 if (i2c_transfer(&d->i2c_adap, msg, 2) != 2) 436 break; 437 438 status = 439 technisat_usb2_calc_lrc(b, length - 1) == b[length - 1]; 440 441 if (status) 442 return 0; 443 } 444 445 return -EREMOTEIO; 446 } 447 448 #define EEPROM_MAC_START 0x3f8 449 #define EEPROM_MAC_TOTAL 8 450 static int technisat_usb2_read_mac_address(struct dvb_usb_device *d, 451 u8 mac[]) 452 { 453 u8 buf[EEPROM_MAC_TOTAL]; 454 455 if (technisat_usb2_eeprom_lrc_read(d, EEPROM_MAC_START, 456 buf, EEPROM_MAC_TOTAL, 4) != 0) 457 return -ENODEV; 458 459 memcpy(mac, buf, 6); 460 return 0; 461 } 462 463 static struct stv090x_config technisat_usb2_stv090x_config; 464 465 /* frontend attach */ 466 static int technisat_usb2_set_voltage(struct dvb_frontend *fe, 467 enum fe_sec_voltage voltage) 468 { 469 int i; 470 u8 gpio[3] = { 0 }; /* 0 = 2, 1 = 3, 2 = 4 */ 471 472 gpio[2] = 1; /* high - voltage ? */ 473 474 switch (voltage) { 475 case SEC_VOLTAGE_13: 476 gpio[0] = 1; 477 break; 478 case SEC_VOLTAGE_18: 479 gpio[0] = 1; 480 gpio[1] = 1; 481 break; 482 default: 483 case SEC_VOLTAGE_OFF: 484 break; 485 } 486 487 for (i = 0; i < 3; i++) 488 if (technisat_usb2_stv090x_config.set_gpio(fe, i+2, 0, 489 gpio[i], 0) != 0) 490 return -EREMOTEIO; 491 return 0; 492 } 493 494 static struct stv090x_config technisat_usb2_stv090x_config = { 495 .device = STV0903, 496 .demod_mode = STV090x_SINGLE, 497 .clk_mode = STV090x_CLK_EXT, 498 499 .xtal = 8000000, 500 .address = 0x68, 501 502 .ts1_mode = STV090x_TSMODE_DVBCI, 503 .ts1_clk = 13400000, 504 .ts1_tei = 1, 505 506 .repeater_level = STV090x_RPTLEVEL_64, 507 508 .tuner_bbgain = 6, 509 }; 510 511 static struct stv6110x_config technisat_usb2_stv6110x_config = { 512 .addr = 0x60, 513 .refclk = 16000000, 514 .clk_div = 2, 515 }; 516 517 static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a) 518 { 519 struct usb_device *udev = a->dev->udev; 520 int ret; 521 522 a->fe_adap[0].fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config, 523 &a->dev->i2c_adap, STV090x_DEMODULATOR_0); 524 525 if (a->fe_adap[0].fe) { 526 const struct stv6110x_devctl *ctl; 527 528 ctl = dvb_attach(stv6110x_attach, 529 a->fe_adap[0].fe, 530 &technisat_usb2_stv6110x_config, 531 &a->dev->i2c_adap); 532 533 if (ctl) { 534 technisat_usb2_stv090x_config.tuner_init = ctl->tuner_init; 535 technisat_usb2_stv090x_config.tuner_sleep = ctl->tuner_sleep; 536 technisat_usb2_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; 537 technisat_usb2_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; 538 technisat_usb2_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; 539 technisat_usb2_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; 540 technisat_usb2_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; 541 technisat_usb2_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; 542 technisat_usb2_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; 543 technisat_usb2_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; 544 technisat_usb2_stv090x_config.tuner_get_status = ctl->tuner_get_status; 545 546 /* call the init function once to initialize 547 tuner's clock output divider and demod's 548 master clock */ 549 if (a->fe_adap[0].fe->ops.init) 550 a->fe_adap[0].fe->ops.init(a->fe_adap[0].fe); 551 552 if (mutex_lock_interruptible(&a->dev->i2c_mutex) < 0) 553 return -EAGAIN; 554 555 ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 556 SET_IFCLK_TO_EXTERNAL_TSCLK_VENDOR_REQUEST, 557 USB_TYPE_VENDOR | USB_DIR_OUT, 558 0, 0, 559 NULL, 0, 500); 560 mutex_unlock(&a->dev->i2c_mutex); 561 562 if (ret != 0) 563 err("could not set IF_CLK to external"); 564 565 a->fe_adap[0].fe->ops.set_voltage = technisat_usb2_set_voltage; 566 567 /* if everything was successful assign a nice name to the frontend */ 568 strlcpy(a->fe_adap[0].fe->ops.info.name, a->dev->desc->name, 569 sizeof(a->fe_adap[0].fe->ops.info.name)); 570 } else { 571 dvb_frontend_detach(a->fe_adap[0].fe); 572 a->fe_adap[0].fe = NULL; 573 } 574 } 575 576 technisat_usb2_set_led_timer(a->dev, 1, 1); 577 578 return a->fe_adap[0].fe == NULL ? -ENODEV : 0; 579 } 580 581 /* Remote control */ 582 583 /* the device is giving providing raw IR-signals to the host mapping 584 * it only to one remote control is just the default implementation 585 */ 586 #define NOMINAL_IR_BIT_TRANSITION_TIME_US 889 587 #define NOMINAL_IR_BIT_TIME_US (2 * NOMINAL_IR_BIT_TRANSITION_TIME_US) 588 589 #define FIRMWARE_CLOCK_TICK 83333 590 #define FIRMWARE_CLOCK_DIVISOR 256 591 592 #define IR_PERCENT_TOLERANCE 15 593 594 #define NOMINAL_IR_BIT_TRANSITION_TICKS ((NOMINAL_IR_BIT_TRANSITION_TIME_US * 1000 * 1000) / FIRMWARE_CLOCK_TICK) 595 #define NOMINAL_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICKS / FIRMWARE_CLOCK_DIVISOR) 596 597 #define NOMINAL_IR_BIT_TIME_TICKS ((NOMINAL_IR_BIT_TIME_US * 1000 * 1000) / FIRMWARE_CLOCK_TICK) 598 #define NOMINAL_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICKS / FIRMWARE_CLOCK_DIVISOR) 599 600 #define MINIMUM_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICK_COUNT - ((NOMINAL_IR_BIT_TRANSITION_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100)) 601 #define MAXIMUM_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICK_COUNT + ((NOMINAL_IR_BIT_TRANSITION_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100)) 602 603 #define MINIMUM_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICK_COUNT - ((NOMINAL_IR_BIT_TIME_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100)) 604 #define MAXIMUM_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICK_COUNT + ((NOMINAL_IR_BIT_TIME_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100)) 605 606 static int technisat_usb2_get_ir(struct dvb_usb_device *d) 607 { 608 struct technisat_usb2_state *state = d->priv; 609 u8 *buf = state->buf; 610 u8 *b; 611 int ret; 612 struct ir_raw_event ev; 613 614 buf[0] = GET_IR_DATA_VENDOR_REQUEST; 615 buf[1] = 0x08; 616 buf[2] = 0x8f; 617 buf[3] = MINIMUM_IR_BIT_TRANSITION_TICK_COUNT; 618 buf[4] = MAXIMUM_IR_BIT_TIME_TICK_COUNT; 619 620 if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 621 return -EAGAIN; 622 ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), 623 GET_IR_DATA_VENDOR_REQUEST, 624 USB_TYPE_VENDOR | USB_DIR_OUT, 625 0, 0, 626 buf, 5, 500); 627 if (ret < 0) 628 goto unlock; 629 630 buf[1] = 0; 631 buf[2] = 0; 632 ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), 633 GET_IR_DATA_VENDOR_REQUEST, 634 USB_TYPE_VENDOR | USB_DIR_IN, 635 0x8080, 0, 636 buf, 62, 500); 637 638 unlock: 639 mutex_unlock(&d->i2c_mutex); 640 641 if (ret < 0) 642 return ret; 643 644 if (ret == 1) 645 return 0; /* no key pressed */ 646 647 /* decoding */ 648 b = buf+1; 649 650 #if 0 651 deb_rc("RC: %d ", ret); 652 debug_dump(b, ret, deb_rc); 653 #endif 654 655 ev.pulse = 0; 656 while (1) { 657 ev.pulse = !ev.pulse; 658 ev.duration = (*b * FIRMWARE_CLOCK_DIVISOR * FIRMWARE_CLOCK_TICK) / 1000; 659 ir_raw_event_store(d->rc_dev, &ev); 660 661 b++; 662 if (*b == 0xff) { 663 ev.pulse = 0; 664 ev.duration = 888888*2; 665 ir_raw_event_store(d->rc_dev, &ev); 666 break; 667 } 668 } 669 670 ir_raw_event_handle(d->rc_dev); 671 672 return 1; 673 } 674 675 static int technisat_usb2_rc_query(struct dvb_usb_device *d) 676 { 677 int ret = technisat_usb2_get_ir(d); 678 679 if (ret < 0) 680 return ret; 681 682 if (ret == 0) 683 return 0; 684 685 if (!disable_led_control) 686 technisat_usb2_set_led(d, 1, TECH_LED_BLINK); 687 688 return 0; 689 } 690 691 /* DVB-USB and USB stuff follows */ 692 static struct usb_device_id technisat_usb2_id_table[] = { 693 { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_DVB_S2) }, 694 { 0 } /* Terminating entry */ 695 }; 696 MODULE_DEVICE_TABLE(usb, technisat_usb2_id_table); 697 698 /* device description */ 699 static struct dvb_usb_device_properties technisat_usb2_devices = { 700 .caps = DVB_USB_IS_AN_I2C_ADAPTER, 701 702 .usb_ctrl = CYPRESS_FX2, 703 704 .identify_state = technisat_usb2_identify_state, 705 .firmware = "dvb-usb-SkyStar_USB_HD_FW_v17_63.HEX.fw", 706 707 .size_of_priv = sizeof(struct technisat_usb2_state), 708 709 .i2c_algo = &technisat_usb2_i2c_algo, 710 711 .power_ctrl = technisat_usb2_power_ctrl, 712 .read_mac_address = technisat_usb2_read_mac_address, 713 714 .num_adapters = 1, 715 .adapter = { 716 { 717 .num_frontends = 1, 718 .fe = {{ 719 .frontend_attach = technisat_usb2_frontend_attach, 720 721 .stream = { 722 .type = USB_ISOC, 723 .count = 4, 724 .endpoint = 0x2, 725 .u = { 726 .isoc = { 727 .framesperurb = 32, 728 .framesize = 2048, 729 .interval = 1, 730 } 731 } 732 }, 733 }}, 734 .size_of_priv = 0, 735 }, 736 }, 737 738 .num_device_descs = 1, 739 .devices = { 740 { "Technisat SkyStar USB HD (DVB-S/S2)", 741 { &technisat_usb2_id_table[0], NULL }, 742 { NULL }, 743 }, 744 }, 745 746 .rc.core = { 747 .rc_interval = 100, 748 .rc_codes = RC_MAP_TECHNISAT_USB2, 749 .module_name = "technisat-usb2", 750 .rc_query = technisat_usb2_rc_query, 751 .allowed_protos = RC_BIT_ALL, 752 .driver_type = RC_DRIVER_IR_RAW, 753 } 754 }; 755 756 static int technisat_usb2_probe(struct usb_interface *intf, 757 const struct usb_device_id *id) 758 { 759 struct dvb_usb_device *dev; 760 761 if (dvb_usb_device_init(intf, &technisat_usb2_devices, THIS_MODULE, 762 &dev, adapter_nr) != 0) 763 return -ENODEV; 764 765 if (dev) { 766 struct technisat_usb2_state *state = dev->priv; 767 state->dev = dev; 768 769 if (!disable_led_control) { 770 INIT_DELAYED_WORK(&state->green_led_work, 771 technisat_usb2_green_led_control); 772 schedule_delayed_work(&state->green_led_work, 773 msecs_to_jiffies(500)); 774 } 775 } 776 777 return 0; 778 } 779 780 static void technisat_usb2_disconnect(struct usb_interface *intf) 781 { 782 struct dvb_usb_device *dev = usb_get_intfdata(intf); 783 784 /* work and stuff was only created when the device is is hot-state */ 785 if (dev != NULL) { 786 struct technisat_usb2_state *state = dev->priv; 787 if (state != NULL) 788 cancel_delayed_work_sync(&state->green_led_work); 789 } 790 791 dvb_usb_device_exit(intf); 792 } 793 794 static struct usb_driver technisat_usb2_driver = { 795 .name = "dvb_usb_technisat_usb2", 796 .probe = technisat_usb2_probe, 797 .disconnect = technisat_usb2_disconnect, 798 .id_table = technisat_usb2_id_table, 799 }; 800 801 module_usb_driver(technisat_usb2_driver); 802 803 MODULE_AUTHOR("Patrick Boettcher <pboettcher@kernellabs.com>"); 804 MODULE_DESCRIPTION("Driver for Technisat DVB-S/S2 USB 2.0 device"); 805 MODULE_VERSION("1.0"); 806 MODULE_LICENSE("GPL"); 807