diff options
author | Antti Palosaari <crope@iki.fi> | 2010-09-12 13:31:56 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-10-21 01:05:52 -0200 |
commit | d3bb73de97a9685bb150f81017d7e184fdb18451 (patch) | |
tree | d551bf4cd3710e678dabff7a19283fca0a9632a7 /drivers/media/dvb/dvb-usb/af9015.c | |
parent | 2ec01b41e3e06bd22d8f6c7f330605b554e9b121 (diff) |
V4L/DVB: af9015: reimplement remote controller
Remove HID and polling via firmware API. Implement direct access to remote codes via memory read and write.
HID and polling via firmware api never worked 100% well and there was also some limitations which tied used remote and device together.
After that it is possible to use upcoming kernel remote controller core.
Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/dvb-usb/af9015.c')
-rw-r--r-- | drivers/media/dvb/dvb-usb/af9015.c | 194 |
1 files changed, 84 insertions, 110 deletions
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index bf6ff2bb95c..f82f50d6acf 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -599,37 +599,6 @@ free: return ret; } -static int af9015_download_ir_table(struct dvb_usb_device *d) -{ - int i, packets = 0, ret; - u16 addr = 0x9a56; /* ir-table start address */ - struct req_t req = {WRITE_MEMORY, 0, 0, 0, 0, 1, NULL}; - u8 *data = NULL; - deb_info("%s:\n", __func__); - - data = af9015_config.ir_table; - packets = af9015_config.ir_table_size; - - /* no remote */ - if (!packets) - goto exit; - - /* load remote ir-table */ - for (i = 0; i < packets; i++) { - req.addr = addr + i; - req.data = &data[i]; - ret = af9015_ctrl_msg(d, &req); - if (ret) { - err("ir-table download failed at packet %d with " \ - "code %d", i, ret); - return ret; - } - } - -exit: - return 0; -} - static int af9015_init(struct dvb_usb_device *d) { int ret; @@ -639,10 +608,6 @@ static int af9015_init(struct dvb_usb_device *d) if (ret) goto error; - ret = af9015_download_ir_table(d); - if (ret) - goto error; - error: return ret; } @@ -739,8 +704,6 @@ struct af9015_setup { unsigned int id; struct ir_scancode *rc_key_map; unsigned int rc_key_map_size; - u8 *ir_table; - unsigned int ir_table_size; }; static const struct af9015_setup *af9015_setup_match(unsigned int id, @@ -753,57 +716,40 @@ static const struct af9015_setup *af9015_setup_match(unsigned int id, } static const struct af9015_setup af9015_setup_modparam[] = { - { AF9015_REMOTE_A_LINK_DTU_M, - ir_codes_af9015_table_a_link, ARRAY_SIZE(ir_codes_af9015_table_a_link), - af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) }, - { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, - ir_codes_af9015_table_msi, ARRAY_SIZE(ir_codes_af9015_table_msi), - af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) }, - { AF9015_REMOTE_MYGICTV_U718, - ir_codes_af9015_table_mygictv, ARRAY_SIZE(ir_codes_af9015_table_mygictv), - af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) }, - { AF9015_REMOTE_DIGITTRADE_DVB_T, - ir_codes_af9015_table_digittrade, ARRAY_SIZE(ir_codes_af9015_table_digittrade), - af9015_ir_table_digittrade, ARRAY_SIZE(af9015_ir_table_digittrade) }, - { AF9015_REMOTE_AVERMEDIA_KS, - ir_codes_af9015_table_avermedia, ARRAY_SIZE(ir_codes_af9015_table_avermedia), - af9015_ir_table_avermedia_ks, ARRAY_SIZE(af9015_ir_table_avermedia_ks) }, + { AF9015_REMOTE_A_LINK_DTU_M, af9015_rc_a_link, + ARRAY_SIZE(af9015_rc_a_link) }, + { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, af9015_rc_msi, + ARRAY_SIZE(af9015_rc_msi) }, + { AF9015_REMOTE_MYGICTV_U718, af9015_rc_mygictv, + ARRAY_SIZE(af9015_rc_mygictv) }, + { AF9015_REMOTE_DIGITTRADE_DVB_T, af9015_rc_digittrade, + ARRAY_SIZE(af9015_rc_digittrade) }, + { AF9015_REMOTE_AVERMEDIA_KS, af9015_rc_avermedia_ks, + ARRAY_SIZE(af9015_rc_avermedia_ks) }, { } }; /* don't add new entries here anymore, use hashes instead */ static const struct af9015_setup af9015_setup_usbids[] = { - { USB_VID_LEADTEK, - ir_codes_af9015_table_leadtek, ARRAY_SIZE(ir_codes_af9015_table_leadtek), - af9015_ir_table_leadtek, ARRAY_SIZE(af9015_ir_table_leadtek) }, - { USB_VID_VISIONPLUS, - ir_codes_af9015_table_twinhan, ARRAY_SIZE(ir_codes_af9015_table_twinhan), - af9015_ir_table_twinhan, ARRAY_SIZE(af9015_ir_table_twinhan) }, - { USB_VID_KWORLD_2, /* TODO: use correct rc keys */ - ir_codes_af9015_table_twinhan, ARRAY_SIZE(ir_codes_af9015_table_twinhan), - af9015_ir_table_kworld, ARRAY_SIZE(af9015_ir_table_kworld) }, - { USB_VID_AVERMEDIA, - ir_codes_af9015_table_avermedia, ARRAY_SIZE(ir_codes_af9015_table_avermedia), - af9015_ir_table_avermedia, ARRAY_SIZE(af9015_ir_table_avermedia) }, - { USB_VID_MSI_2, - ir_codes_af9015_table_msi_digivox_iii, ARRAY_SIZE(ir_codes_af9015_table_msi_digivox_iii), - af9015_ir_table_msi_digivox_iii, ARRAY_SIZE(af9015_ir_table_msi_digivox_iii) }, - { USB_VID_TERRATEC, - ir_codes_terratec, ARRAY_SIZE(ir_codes_terratec), - af9015_ir_terratec, ARRAY_SIZE(af9015_ir_terratec) }, + { USB_VID_LEADTEK, af9015_rc_leadtek, + ARRAY_SIZE(af9015_rc_leadtek) }, + { USB_VID_VISIONPLUS, af9015_rc_twinhan, + ARRAY_SIZE(af9015_rc_twinhan) }, + { USB_VID_KWORLD_2, af9015_rc_kworld, + ARRAY_SIZE(af9015_rc_kworld) }, + { USB_VID_AVERMEDIA, af9015_rc_avermedia, + ARRAY_SIZE(af9015_rc_avermedia) }, + { USB_VID_MSI_2, af9015_rc_msi_digivox_iii, + ARRAY_SIZE(af9015_rc_msi_digivox_iii) }, + { USB_VID_TERRATEC, af9015_rc_terratec, + ARRAY_SIZE(af9015_rc_terratec) }, { } }; static const struct af9015_setup af9015_setup_hashes[] = { - { 0xb8feb708, - ir_codes_af9015_table_msi, ARRAY_SIZE(ir_codes_af9015_table_msi), - af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) }, - { 0xa3703d00, - ir_codes_af9015_table_a_link, ARRAY_SIZE(ir_codes_af9015_table_a_link), - af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) }, - { 0x9b7dc64e, - ir_codes_af9015_table_mygictv, ARRAY_SIZE(ir_codes_af9015_table_mygictv), - af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) }, + { 0xb8feb708, af9015_rc_msi, ARRAY_SIZE(af9015_rc_msi) }, + { 0xa3703d00, af9015_rc_a_link, ARRAY_SIZE(af9015_rc_a_link) }, + { 0x9b7dc64e, af9015_rc_mygictv, ARRAY_SIZE(af9015_rc_mygictv) }, { } }; @@ -841,11 +787,8 @@ static void af9015_set_remote_config(struct usb_device *udev, } else if (udev->descriptor.idProduct == cpu_to_le16(USB_PID_TREKSTOR_DVBT)) { table = &(const struct af9015_setup){ 0, - ir_codes_af9015_table_trekstor, - ARRAY_SIZE(ir_codes_af9015_table_trekstor), - af9015_ir_table_trekstor, - ARRAY_SIZE(af9015_ir_table_trekstor) - }; + af9015_rc_trekstor, + ARRAY_SIZE(af9015_rc_trekstor) }; } } else if (!table) table = af9015_setup_match(vendor, af9015_setup_usbids); @@ -854,8 +797,6 @@ static void af9015_set_remote_config(struct usb_device *udev, if (table) { props->rc.legacy.rc_key_map = table->rc_key_map; props->rc.legacy.rc_key_map_size = table->rc_key_map_size; - af9015_config.ir_table = table->ir_table; - af9015_config.ir_table_size = table->ir_table_size; } } @@ -1065,34 +1006,66 @@ static int af9015_identify_state(struct usb_device *udev, static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { - u8 buf[8]; - struct req_t req = {GET_IR_CODE, 0, 0, 0, 0, sizeof(buf), buf}; - struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map; - int i, ret; + struct af9015_state *priv = d->priv; + int ret; + u8 ircode[5], repeat; - memset(buf, 0, sizeof(buf)); + /* read registers needed to detect remote controller code */ + ret = af9015_read_reg(d, 0x98df, &repeat); + if (ret) + goto error; - ret = af9015_ctrl_msg(d, &req); + ret = af9015_read_reg(d, 0x98e7, &ircode[3]); if (ret) - return ret; + goto error; + + ret = af9015_read_reg(d, 0x98e8, &ircode[4]); + if (ret) + goto error; - *event = 0; - *state = REMOTE_NO_KEY_PRESSED; + if (ircode[3] || ircode[4]) { + deb_rc("%s: key pressed\n", __func__); + ircode[0] = 1; /* DVB_USB_RC_NEC_KEY_PRESSED */ - for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) { - if (!buf[1] && rc5_custom(&keymap[i]) == buf[0] && - rc5_data(&keymap[i]) == buf[2]) { - *event = keymap[i].keycode; - *state = REMOTE_KEY_PRESSED; - break; - } + /* read 1st address byte */ + ret = af9015_read_reg(d, 0x98e5, &ircode[1]); + if (ret) + goto error; + + /* clean data bytes from mem */ + ret = af9015_write_reg(d, 0x98e7, 0); + if (ret) + goto error; + + ret = af9015_write_reg(d, 0x98e8, 0); + if (ret) + goto error; + + /* FIXME: Hack to pass checksum on the custom field for the + remote controllers using NEC extended address. + That must done since dvb_usb_nec_rc_key_to_event() + does not support NEC extended address format. */ + ircode[2] = ~ircode[1]; + } else if (priv->rc_repeat != repeat) { + deb_rc("%s: key repeated\n", __func__); + ircode[0] = 2; /* DVB_USB_RC_NEC_KEY_REPEATED */ + } else { + deb_rc("%s: no key press\n", __func__); + ircode[0] = 0; /* DVB_USB_RC_NEC_EMPTY */ } - if (!buf[1]) - deb_rc("%s: %02x %02x %02x %02x %02x %02x %02x %02x\n", - __func__, buf[0], buf[1], buf[2], buf[3], buf[4], - buf[5], buf[6], buf[7]); - return 0; + priv->rc_repeat = repeat; + + deb_rc("%s: ", __func__); + debug_dump(ircode, sizeof(ircode), deb_rc); + + dvb_usb_nec_rc_key_to_event(d, ircode, event, state); + +error: + if (ret) + err("%s: failed:%d", __func__, ret); + + return ret; } /* init 2nd I2C adapter */ @@ -1329,6 +1302,7 @@ static struct usb_device_id af9015_usb_table[] = { }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); +#define AF9015_RC_INTERVAL 500 static struct dvb_usb_device_properties af9015_properties[] = { { .caps = DVB_USB_IS_AN_I2C_ADAPTER, @@ -1381,7 +1355,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .rc.legacy = { .rc_query = af9015_rc_query, - .rc_interval = 150, + .rc_interval = AF9015_RC_INTERVAL, }, .i2c_algo = &af9015_i2c_algo, @@ -1500,7 +1474,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .rc.legacy = { .rc_query = af9015_rc_query, - .rc_interval = 150, + .rc_interval = AF9015_RC_INTERVAL, }, .i2c_algo = &af9015_i2c_algo, @@ -1609,7 +1583,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .rc.legacy = { .rc_query = af9015_rc_query, - .rc_interval = 150, + .rc_interval = AF9015_RC_INTERVAL, }, .i2c_algo = &af9015_i2c_algo, |