V4L/DVB (9639): Make dib0700 remote control support work with firmware v1.20

The format for reading the IR controller changed in firmware 1.20. It now
provides the events on bulk endpoint 1 instead of using a control request.

Support the new format, providing backward compatibility for users who might
be using older firmware.

Thanks to Patrick Boettcher <patrick.boettcher@desy.de> for providing the
required information on how the version 1.20 firmware works.

Signed-off-by: Devin Heitmueller <devin.heitmueller@gmail.com>
Signed-off-by: Patrick Boettcher <pb@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

authored by Devin Heitmueller and committed by Mauro Carvalho Chehab 99afb989 deaf53e3

+158 -2
+4 -1
drivers/media/dvb/dvb-usb/dib0700.h
··· 22 22 23 23 #define REQUEST_I2C_READ 0x2 24 24 #define REQUEST_I2C_WRITE 0x3 25 - #define REQUEST_POLL_RC 0x4 25 + #define REQUEST_POLL_RC 0x4 /* deprecated in firmware v1.20 */ 26 26 #define REQUEST_JUMPRAM 0x8 27 27 #define REQUEST_SET_CLOCK 0xB 28 28 #define REQUEST_SET_GPIO 0xC ··· 40 40 u16 mt2060_if1[2]; 41 41 u8 rc_toggle; 42 42 u8 rc_counter; 43 + u8 rc_func_version; 43 44 u8 is_dib7000pc; 44 45 u8 fw_use_new_i2c_api; 45 46 u8 disable_streaming_master_mode; 46 47 }; 47 48 49 + extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, 50 + u32 *romversion, u32 *ramversion, u32 *fwtype); 48 51 extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); 49 52 extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3); 50 53 extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen);
+16
drivers/media/dvb/dvb-usb/dib0700_core.c
··· 19 19 20 20 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 21 21 22 + 23 + int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, 24 + u32 *romversion, u32 *ramversion, u32 *fwtype) 25 + { 26 + u8 b[16]; 27 + int ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), 28 + REQUEST_GET_VERSION, 29 + USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, 30 + b, sizeof(b), USB_CTRL_GET_TIMEOUT); 31 + *hwversion = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; 32 + *romversion = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | b[7]; 33 + *ramversion = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11]; 34 + *fwtype = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15]; 35 + return ret; 36 + } 37 + 22 38 /* expecting rx buffer: request data[0] data[1] ... data[2] */ 23 39 static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen) 24 40 {
+138 -1
drivers/media/dvb/dvb-usb/dib0700_devices.c
··· 38 38 } 39 39 }; 40 40 41 + 41 42 static struct dibx000_agc_config bristol_dib3000p_mt2060_agc_config = { 42 43 .band_caps = BAND_VHF | BAND_UHF, 43 44 .setup = (1 << 8) | (5 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (2 << 0), ··· 452 451 453 452 /* Number of keypresses to ignore before start repeating */ 454 453 #define RC_REPEAT_DELAY 2 454 + #define RC_REPEAT_DELAY_V1_20 5 455 455 456 - static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) 456 + 457 + 458 + /* Used by firmware versions < 1.20 (deprecated) */ 459 + static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event, 460 + int *state) 457 461 { 458 462 u8 key[4]; 459 463 int i; ··· 533 527 err("Unknown remote controller key: %2X %2X %2X %2X", (int) key[3-2], (int) key[3-3], (int) key[3-1], (int) key[3]); 534 528 d->last_event = 0; 535 529 return 0; 530 + } 531 + 532 + /* This is the structure of the RC response packet starting in firmware 1.20 */ 533 + struct dib0700_rc_response { 534 + u8 report_id; 535 + u8 data_state; 536 + u8 system_msb; 537 + u8 system_lsb; 538 + u8 data; 539 + u8 not_data; 540 + }; 541 + 542 + /* This supports the new IR response format for firmware v1.20 */ 543 + static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event, 544 + int *state) 545 + { 546 + struct dvb_usb_rc_key *keymap = d->props.rc_key_map; 547 + struct dib0700_state *st = d->priv; 548 + struct dib0700_rc_response poll_reply; 549 + u8 buf[6]; 550 + int i; 551 + int status; 552 + int actlen; 553 + int found = 0; 554 + 555 + /* Set initial results in case we exit the function early */ 556 + *event = 0; 557 + *state = REMOTE_NO_KEY_PRESSED; 558 + 559 + /* Firmware v1.20 provides RC data via bulk endpoint 1 */ 560 + status = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, 1), buf, 561 + sizeof(buf), &actlen, 50); 562 + if (status < 0) { 563 + /* No data available (meaning no key press) */ 564 + return 0; 565 + } 566 + 567 + if (actlen != sizeof(buf)) { 568 + /* We didn't get back the 6 byte message we expected */ 569 + err("Unexpected RC response size [%d]", actlen); 570 + return -1; 571 + } 572 + 573 + poll_reply.report_id = buf[0]; 574 + poll_reply.data_state = buf[1]; 575 + poll_reply.system_msb = buf[2]; 576 + poll_reply.system_lsb = buf[3]; 577 + poll_reply.data = buf[4]; 578 + poll_reply.not_data = buf[5]; 579 + 580 + /* 581 + info("rid=%02x ds=%02x sm=%02x sl=%02x d=%02x nd=%02x\n", 582 + poll_reply.report_id, poll_reply.data_state, 583 + poll_reply.system_msb, poll_reply.system_lsb, 584 + poll_reply.data, poll_reply.not_data); 585 + */ 586 + 587 + if ((poll_reply.data + poll_reply.not_data) != 0xff) { 588 + /* Key failed integrity check */ 589 + err("key failed integrity check: %02x %02x %02x %02x", 590 + poll_reply.system_msb, poll_reply.system_lsb, 591 + poll_reply.data, poll_reply.not_data); 592 + return -1; 593 + } 594 + 595 + /* Find the key in the map */ 596 + for (i = 0; i < d->props.rc_key_map_size; i++) { 597 + if (keymap[i].custom == poll_reply.system_lsb && 598 + keymap[i].data == poll_reply.data) { 599 + *event = keymap[i].event; 600 + found = 1; 601 + break; 602 + } 603 + } 604 + 605 + if (found == 0) { 606 + err("Unknown remote controller key: %02x %02x %02x %02x", 607 + poll_reply.system_msb, poll_reply.system_lsb, 608 + poll_reply.data, poll_reply.not_data); 609 + d->last_event = 0; 610 + return 0; 611 + } 612 + 613 + if (poll_reply.data_state == 1) { 614 + /* New key hit */ 615 + st->rc_counter = 0; 616 + *event = keymap[i].event; 617 + *state = REMOTE_KEY_PRESSED; 618 + d->last_event = keymap[i].event; 619 + } else if (poll_reply.data_state == 2) { 620 + /* Key repeated */ 621 + st->rc_counter++; 622 + 623 + /* prevents unwanted double hits */ 624 + if (st->rc_counter > RC_REPEAT_DELAY_V1_20) { 625 + *event = d->last_event; 626 + *state = REMOTE_KEY_PRESSED; 627 + st->rc_counter = RC_REPEAT_DELAY_V1_20; 628 + } 629 + } else { 630 + err("Unknown data state [%d]", poll_reply.data_state); 631 + } 632 + 633 + return 0; 634 + } 635 + 636 + static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) 637 + { 638 + struct dib0700_state *st = d->priv; 639 + 640 + /* Because some people may have improperly named firmware files, 641 + let's figure out whether to use the new firmware call or the legacy 642 + call based on the firmware version embedded in the file */ 643 + if (st->rc_func_version == 0) { 644 + u32 hwver, romver, ramver, fwtype; 645 + int ret = dib0700_get_version(d, &hwver, &romver, &ramver, 646 + &fwtype); 647 + if (ret < 0) { 648 + err("Could not determine version info"); 649 + return -1; 650 + } 651 + if (ramver < 0x10200) 652 + st->rc_func_version = 1; 653 + else 654 + st->rc_func_version = 2; 655 + } 656 + 657 + if (st->rc_func_version == 2) 658 + return dib0700_rc_query_v1_20(d, event, state); 659 + else 660 + return dib0700_rc_query_legacy(d, event, state); 536 661 } 537 662 538 663 static struct dvb_usb_rc_key dib0700_rc_keys[] = {