diff options
author | Patrick Boettcher <devnull@localhost> | 2005-04-02 14:42:56 +0000 |
---|---|---|
committer | Patrick Boettcher <devnull@localhost> | 2005-04-02 14:42:56 +0000 |
commit | 861784e76607eafbfb13c6ce1e3b87204b3978da (patch) | |
tree | 892e736a8c25848d2ccb0a3a8a46f6b92693ec56 /linux/drivers/media/dvb/dvb-usb | |
parent | 302481a5ffb8737f5fcb821ee79576637aa85055 (diff) | |
download | mediapointer-dvb-s2-861784e76607eafbfb13c6ce1e3b87204b3978da.tar.gz mediapointer-dvb-s2-861784e76607eafbfb13c6ce1e3b87204b3978da.tar.bz2 |
re-enabled and improved commonly used remote control code for dvb-usb
Diffstat (limited to 'linux/drivers/media/dvb/dvb-usb')
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/Makefile | 2 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/dtt200u.c | 30 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/dvb-usb-common.h | 15 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c | 6 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 374 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/dvb-usb.h | 36 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/vp7045.c | 56 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/vp7045.h | 1 |
8 files changed, 206 insertions, 314 deletions
diff --git a/linux/drivers/media/dvb/dvb-usb/Makefile b/linux/drivers/media/dvb/dvb-usb/Makefile index 76df16795..15c63d4f2 100644 --- a/linux/drivers/media/dvb/dvb-usb/Makefile +++ b/linux/drivers/media/dvb/dvb-usb/Makefile @@ -1,4 +1,4 @@ -dvb-usb-objs = dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o dvb-usb-dvb.o +dvb-usb-objs = dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o dvb-usb-dvb.o dvb-usb-remote.o obj-$(CONFIG_DVB_USB) += dvb-usb.o dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o diff --git a/linux/drivers/media/dvb/dvb-usb/dtt200u.c b/linux/drivers/media/dvb/dvb-usb/dtt200u.c index 28cb6863b..12abff048 100644 --- a/linux/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/linux/drivers/media/dvb/dvb-usb/dtt200u.c @@ -41,11 +41,29 @@ static int dtt200u_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int return dvb_usb_generic_write(d,b_pid,4); } -static int dtt200u_rc_query(struct dvb_usb_device *d, u8 *key_buf, int *state) +/* remote control */ + +struct dvb_usb_nec_rc_key dtt200u_rc_keys[] = { + { 0x00, 0xff, 0x03, KEY_1 }, + { 0x00, 0xff, 0x01, KEY_2 }, + { 0x00, 0xff, 0x06, KEY_3 }, +}; + +static int dtt200u_rc_init(struct dvb_usb_device *d) +{ + int i; + for (i = 0; i < sizeof(dtt200u_rc_keys)/sizeof(struct dvb_usb_nec_rc_key); i++) + set_bit(dtt200u_rc_keys[i].key, d->rc_input_dev.keybit); + return 0; +} + +static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { - deb_info("remote query\n"); - *state = REMOTE_KEY_NO; - return 0; //dtt200u_usb_op(d,RC_VAL_READ,&v,1,NULL,0,20); + u8 key[5],cmd = GET_RC_KEY; + dvb_usb_generic_rw(d,&cmd,1,key,5); + dvb_usb_nec_rc_key_to_event(d,dtt200u_rc_keys,sizeof(dtt200u_rc_keys)/sizeof(struct dvb_usb_nec_rc_key), + key,event,state); + return 0; } static int dtt200u_frontend_attach(struct dvb_usb_device *d) @@ -81,9 +99,9 @@ static struct dvb_usb_properties dtt200u_properties = { .power_ctrl = NULL, .frontend_attach = dtt200u_frontend_attach, - .rc_interval = 400, - .remote_protocol = USB_REMOTE_PROTO_NEC, + .rc_interval = 200, .query_rc = dtt200u_rc_query, + .init_rc = dtt200u_rc_init, .generic_bulk_ctrl_endpoint = 0x01, diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-common.h index e6e304851..2ea1f6ef7 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-common.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-common.h @@ -28,13 +28,16 @@ extern int dvb_usb_urb_kill(struct dvb_usb_device *); extern int dvb_usb_urb_init(struct dvb_usb_device *); extern int dvb_usb_urb_exit(struct dvb_usb_device *); -extern int dvb_usb_i2c_init(struct dvb_usb_device *d); -extern int dvb_usb_i2c_exit(struct dvb_usb_device *d); +extern int dvb_usb_i2c_init(struct dvb_usb_device *); +extern int dvb_usb_i2c_exit(struct dvb_usb_device *); -extern int dvb_usb_dvb_init(struct dvb_usb_device *d); -extern int dvb_usb_dvb_exit(struct dvb_usb_device *d); +extern int dvb_usb_dvb_init(struct dvb_usb_device *); +extern int dvb_usb_dvb_exit(struct dvb_usb_device *); -extern int dvb_usb_fe_init(struct dvb_usb_device *d); -extern int dvb_usb_fe_exit(struct dvb_usb_device *d); +extern int dvb_usb_fe_init(struct dvb_usb_device *); +extern int dvb_usb_fe_exit(struct dvb_usb_device *); + +extern int dvb_usb_remote_init(struct dvb_usb_device *); +extern int dvb_usb_remote_exit(struct dvb_usb_device *); #endif diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c index 204b591d3..d4cea6e30 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c @@ -22,7 +22,7 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,alot=4,ts=8,err=16,r int dvb_usb_exit(struct dvb_usb_device *d) { deb_info("init_state before exiting everything: %x\n",d->init_state); -// dvb_usb_remote_exit(d); + dvb_usb_remote_exit(d); dvb_usb_fe_exit(d); dvb_usb_i2c_exit(d); dvb_usb_dvb_exit(d); @@ -62,8 +62,8 @@ static int dvb_usb_init(struct dvb_usb_device *d) return ret; } -/* if ((ret = dvb_usb_remote_init(d))) - err("could not initialize remote control.");*/ + if ((ret = dvb_usb_remote_init(d))) + err("could not initialize remote control."); return 0; } diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index f461c30f1..811af315e 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -4,316 +4,146 @@ * see dvb-usb-init.c for copyright information. * * This file contains functions for initializing the the input-device and for handling remote-control-queries. - * - * TODO: this part is not compiling yet, some adaptions will be necessary. */ -#include "dvb-usb.h" +#include "dvb-usb-common.h" -/* Table to map raw key codes to key events. This should not be hard-wired - into the kernel. */ -static const struct { u8 c0, c1, c2; uint32_t key; } nec_rc_keys [] = +/* Remote-control poll function - called every dib->rc_query_interval ms to see + * whether the remote control has received anything. + * + * TODO: Fix the repeat rate of the input device. + */ +static void dvb_usb_read_remote_control(void *data) { - /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */ - { 0x00, 0xff, 0x16, KEY_POWER }, - { 0x00, 0xff, 0x10, KEY_MUTE }, - { 0x00, 0xff, 0x03, KEY_1 }, - { 0x00, 0xff, 0x01, KEY_2 }, - { 0x00, 0xff, 0x06, KEY_3 }, - { 0x00, 0xff, 0x09, KEY_4 }, - { 0x00, 0xff, 0x1d, KEY_5 }, - { 0x00, 0xff, 0x1f, KEY_6 }, - { 0x00, 0xff, 0x0d, KEY_7 }, - { 0x00, 0xff, 0x19, KEY_8 }, - { 0x00, 0xff, 0x1b, KEY_9 }, - { 0x00, 0xff, 0x15, KEY_0 }, - { 0x00, 0xff, 0x05, KEY_CHANNELUP }, - { 0x00, 0xff, 0x02, KEY_CHANNELDOWN }, - { 0x00, 0xff, 0x1e, KEY_VOLUMEUP }, - { 0x00, 0xff, 0x0a, KEY_VOLUMEDOWN }, - { 0x00, 0xff, 0x11, KEY_RECORD }, - { 0x00, 0xff, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */ - { 0x00, 0xff, 0x14, KEY_PLAY }, - { 0x00, 0xff, 0x1a, KEY_STOP }, - { 0x00, 0xff, 0x40, KEY_REWIND }, - { 0x00, 0xff, 0x12, KEY_FASTFORWARD }, - { 0x00, 0xff, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */ - { 0x00, 0xff, 0x4c, KEY_PAUSE }, - { 0x00, 0xff, 0x4d, KEY_SCREEN }, /* Full screen mode. */ - { 0x00, 0xff, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */ - /* additional keys TwinHan VisionPlus, the Artec appearantly not has */ - { 0x00, 0xff, 0x0c, KEY_CANCEL }, /* Cancel */ - { 0x00, 0xff, 0x1c, KEY_EPG }, /* EPG */ - { 0x00, 0xff, 0x00, KEY_TAB }, /* Tab */ - { 0x00, 0xff, 0x48, KEY_INFO }, /* Preview */ - { 0x00, 0xff, 0x04, KEY_LIST }, /* RecordList */ - { 0x00, 0xff, 0x0f, KEY_TEXT }, /* Teletext */ - /* Key codes for the KWorld/ADSTech/JetWay remote. */ - { 0x86, 0x6b, 0x12, KEY_POWER }, - { 0x86, 0x6b, 0x0f, KEY_SELECT }, /* source */ - { 0x86, 0x6b, 0x0c, KEY_UNKNOWN }, /* scan */ - { 0x86, 0x6b, 0x0b, KEY_EPG }, - { 0x86, 0x6b, 0x10, KEY_MUTE }, - { 0x86, 0x6b, 0x01, KEY_1 }, - { 0x86, 0x6b, 0x02, KEY_2 }, - { 0x86, 0x6b, 0x03, KEY_3 }, - { 0x86, 0x6b, 0x04, KEY_4 }, - { 0x86, 0x6b, 0x05, KEY_5 }, - { 0x86, 0x6b, 0x06, KEY_6 }, - { 0x86, 0x6b, 0x07, KEY_7 }, - { 0x86, 0x6b, 0x08, KEY_8 }, - { 0x86, 0x6b, 0x09, KEY_9 }, - { 0x86, 0x6b, 0x0a, KEY_0 }, - { 0x86, 0x6b, 0x18, KEY_ZOOM }, - { 0x86, 0x6b, 0x1c, KEY_UNKNOWN }, /* preview */ - { 0x86, 0x6b, 0x13, KEY_UNKNOWN }, /* snap */ - { 0x86, 0x6b, 0x00, KEY_UNDO }, - { 0x86, 0x6b, 0x1d, KEY_RECORD }, - { 0x86, 0x6b, 0x0d, KEY_STOP }, - { 0x86, 0x6b, 0x0e, KEY_PAUSE }, - { 0x86, 0x6b, 0x16, KEY_PLAY }, - { 0x86, 0x6b, 0x11, KEY_BACK }, - { 0x86, 0x6b, 0x19, KEY_FORWARD }, - { 0x86, 0x6b, 0x14, KEY_UNKNOWN }, /* pip */ - { 0x86, 0x6b, 0x15, KEY_ESC }, - { 0x86, 0x6b, 0x1a, KEY_UP }, - { 0x86, 0x6b, 0x1e, KEY_DOWN }, - { 0x86, 0x6b, 0x1f, KEY_LEFT }, - { 0x86, 0x6b, 0x1b, KEY_RIGHT }, -}; + struct dvb_usb_device *d = data; + u32 event; + int state; -/* Hauppauge NOVA-T USB2 keys */ -static const struct { u16 raw; uint32_t key; } haupp_rc_keys [] = { - { 0xddf, KEY_GOTO }, - { 0xdef, KEY_POWER }, - { 0xce7, KEY_TV }, - { 0xcc7, KEY_VIDEO }, - { 0xccf, KEY_AUDIO }, - { 0xcd7, KEY_MEDIA }, - { 0xcdf, KEY_EPG }, - { 0xca7, KEY_UP }, - { 0xc67, KEY_RADIO }, - { 0xcb7, KEY_LEFT }, - { 0xd2f, KEY_OK }, - { 0xcbf, KEY_RIGHT }, - { 0xcff, KEY_BACK }, - { 0xcaf, KEY_DOWN }, - { 0xc6f, KEY_MENU }, - { 0xc87, KEY_VOLUMEUP }, - { 0xc8f, KEY_VOLUMEDOWN }, - { 0xc97, KEY_CHANNEL }, - { 0xc7f, KEY_MUTE }, - { 0xd07, KEY_CHANNELUP }, - { 0xd0f, KEY_CHANNELDOWN }, - { 0xdbf, KEY_RECORD }, - { 0xdb7, KEY_STOP }, - { 0xd97, KEY_REWIND }, - { 0xdaf, KEY_PLAY }, - { 0xda7, KEY_FASTFORWARD }, - { 0xd27, KEY_LAST }, /* Skip backwards */ - { 0xd87, KEY_PAUSE }, - { 0xcf7, KEY_NEXT }, - { 0xc07, KEY_0 }, - { 0xc0f, KEY_1 }, - { 0xc17, KEY_2 }, - { 0xc1f, KEY_3 }, - { 0xc27, KEY_4 }, - { 0xc2f, KEY_5 }, - { 0xc37, KEY_6 }, - { 0xc3f, KEY_7 }, - { 0xc47, KEY_8 }, - { 0xc4f, KEY_9 }, - { 0xc57, KEY_KPASTERISK }, - { 0xc77, KEY_GRAVE }, /* # */ - { 0xc5f, KEY_RED }, - { 0xd77, KEY_GREEN }, - { 0xdc7, KEY_YELLOW }, - { 0xd4f, KEY_BLUE}, -}; + /* TODO: need a lock here. We can simply skip checking for the remote control + if we're busy. */ -#define DIBUSB_RC_NEC_EMPTY 0x00 -#define DIBUSB_RC_NEC_KEY_PRESSED 0x01 -#define DIBUSB_RC_NEC_KEY_REPEATED 0x02 -static int dvb_usb_key2event_dibusb_nec(struct dvb_usb *d,u8 rb[5]) -{ - int i; - switch (rb[0]) { - case DIBUSB_RC_NEC_KEY_PRESSED: - /* rb[1-3] is the actual key, rb[4] is a checksum */ - deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", - rb[1], rb[2], rb[3], rb[4]); + if (d->props.query_rc(d,&event,&state)) { + err("error while querying for an remote control event."); + goto schedule; + } - if ((0xff - rb[3]) != rb[4]) { - deb_rc("remote control checksum failed.\n"); - break; + switch (state) { + case REMOTE_NO_KEY_PRESSED: + deb_rc("NO KEY PRESSED\n"); + if (d->last_state != REMOTE_NO_KEY_PRESSED) { + deb_rc("releasing event %d\n",d->last_event); + input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0); + input_sync(&d->rc_input_dev); } + d->last_state = REMOTE_NO_KEY_PRESSED; + d->last_event = 0; + break; + case REMOTE_KEY_PRESSED: + deb_rc("KEY PRESSED\n"); + deb_rc("pressing event %d\n",event); - /* See if we can match the raw key code. */ - for (i = 0; i < sizeof(nec_rc_keys)/sizeof(nec_rc_keys[0]); i++) { - if (nec_rc_keys[i].c0 == rb[1] && - nec_rc_keys[i].c1 == rb[2] && - nec_rc_keys[i].c2 == rb[3]) { + input_event(&d->rc_input_dev, EV_KEY, event, 1); + input_sync(&d->rc_input_dev); - dib->last_event = nec_rc_keys[i].key; - return 1; - } - } + d->last_event = event; + d->last_state = REMOTE_KEY_PRESSED; break; - case DIBUSB_RC_NEC_KEY_REPEATED: - /* rb[1]..rb[4] are always zero.*/ - /* Repeats often seem to occur so for the moment just ignore this. */ - return 0; - case DIBUSB_RC_NEC_EMPTY: /* No (more) remote control keys. */ + case REMOTE_KEY_REPEAT: + deb_rc("KEY_REPEAT\n"); + if (d->last_state != REMOTE_NO_KEY_PRESSED) { + deb_rc("repeating event %d\n",d->last_event); + input_event(&d->rc_input_dev, EV_KEY, d->last_event, 2); + input_sync(&d->rc_input_dev); + d->last_state = REMOTE_KEY_REPEAT; + } default: break; } - return -1; + +schedule: + schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval)); } -/* additional status values for Hauppauge Remote Control Protocol */ -#define HAUPPAUGE_RC_KEY_PRESSED 0x01 -#define HAUPPAUGE_RC_KEY_EMPTY 0x03 -static int dibusb_key2event_hauppauge(struct usb_dibusb *dib,u8 rb[3]) +int dvb_usb_remote_init(struct dvb_usb_device *d) { - u16 raw; - int i,state; - switch (rb[0]) { - case HAUPPAUGE_RC_KEY_PRESSED: - raw = ((rb[1] & 0x0f) << 8) | rb[2]; + if (d->props.query_rc == NULL) + return 0; - state = !!(rb[1] & 0x40); + /* Initialise the remote-control structures.*/ + init_input_dev(&d->rc_input_dev); - deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to %04x state: %d\n",rb[1],rb[2],rb[3],raw,state); - for (i = 0; i < sizeof(haupp_rc_keys)/sizeof(haupp_rc_keys[0]); i++) { - if (haupp_rc_keys[i].raw == raw) { - if (dib->last_event == haupp_rc_keys[i].key && - dib->last_state == state) { - deb_rc("key repeat\n"); - return 0; - } else { - dib->last_event = haupp_rc_keys[i].key; - dib->last_state = state; - return 1; - } - } - } + d->rc_input_dev.evbit[0] = BIT(EV_KEY); + d->rc_input_dev.keycodesize = sizeof(unsigned char); + d->rc_input_dev.keycodemax = KEY_MAX; + d->rc_input_dev.name = "Remote control inside an USB DVB receiver"; - break; - case HAUPPAUGE_RC_KEY_EMPTY: - default: - break; - } - return -1; -} + /* set the bits for the keys */ + d->props.init_rc(d); -/* Read the remote control and feed the appropriate event. - * NEC protocol is used for remote controls - */ -static int dvb_usb_read_remote_control(struct usb_dibusb *dib) -{ - u8 b[1] = { DIBUSB_REQ_POLL_REMOTE }, rb[5]; - int ret,event = 0; + /* Start the remote-control polling. */ + if (d->props.rc_interval < 40) + d->props.rc_interval = 100; /* default */ - if ((ret = dibusb_readwrite_usb(dib,b,1,rb,5))) - return ret; + /* setting these two values to non-zero, we have to manage key repeats */ + d->rc_input_dev.rep[REP_PERIOD] = d->props.rc_interval; + d->rc_input_dev.rep[REP_DELAY] = d->props.rc_interval + 150; - switch (dib->dibdev->dev_cl->remote_type) { - case DIBUSB_RC_NEC_PROTOCOL: - event = dibusb_key2event_nec(dib,rb); - break; - case DIBUSB_RC_HAUPPAUGE_PROTO: - event = dibusb_key2event_hauppauge(dib,rb); - default: - break; - } + input_register_device(&d->rc_input_dev); - /* key repeat */ - if (event == 0) - if (++dib->repeat_key_count < dib->rc_key_repeat_count) { - deb_rc("key repeat dropped. (%d)\n",dib->repeat_key_count); - event = -1; /* skip this key repeat */ - } + INIT_WORK(&d->rc_query_work, dvb_usb_read_remote_control, d); - if (event == 1 || event == 0) { - deb_rc("Translated key 0x%04x\n",event); + info("schedule remote query interval to %d msecs.",d->props.rc_interval); + schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval)); - /* Signal down and up events for this key. */ - input_report_key(&dib->rc_input_dev, dib->last_event, 1); - input_report_key(&dib->rc_input_dev, dib->last_event, 0); - input_sync(&dib->rc_input_dev); + d->init_state |= DVB_USB_STATE_REMOTE; - if (event == 1) - dib->repeat_key_count = 0; - } return 0; } -/* Remote-control poll function - called every dib->rc_query_interval ms to see - whether the remote control has received anything. */ -static void dibusb_remote_query(void *data) +int dvb_usb_remote_exit(struct dvb_usb_device *d) { - struct usb_dibusb *dib = (struct usb_dibusb *) data; - /* TODO: need a lock here. We can simply skip checking for the remote control - if we're busy. */ - dibusb_read_remote_control(dib); - schedule_delayed_work(&dib->rc_query_work, - msecs_to_jiffies(dib->rc_query_interval)); + if (d->init_state & DVB_USB_STATE_REMOTE) { + cancel_delayed_work(&d->rc_query_work); + flush_scheduled_work(); + input_unregister_device(&d->rc_input_dev); + } + d->init_state &= ~DVB_USB_STATE_REMOTE; + return 0; } -int dibusb_remote_init(struct usb_dibusb *dib) +#define DVB_USB_RC_NEC_EMPTY 0x00 +#define DVB_USB_RC_NEC_KEY_PRESSED 0x01 +#define DVB_USB_RC_NEC_KEY_REPEATED 0x02 +int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d, struct dvb_usb_nec_rc_key keymap[],int key_count, u8 keybuf[5], u32 *event, int *state) { int i; - - if (dib->dibdev->dev_cl->remote_type == DIBUSB_RC_NO) - return 0; - - /* Initialise the remote-control structures.*/ - init_input_dev(&dib->rc_input_dev); - - dib->rc_input_dev.evbit[0] = BIT(EV_KEY); - dib->rc_input_dev.keycodesize = sizeof(unsigned char); - dib->rc_input_dev.keycodemax = KEY_MAX; - dib->rc_input_dev.name = DRIVER_DESC " remote control"; - - switch (dib->dibdev->dev_cl->remote_type) { - case DIBUSB_RC_NEC_PROTOCOL: - for (i=0; i<sizeof(nec_rc_keys)/sizeof(nec_rc_keys[0]); i++) - set_bit(nec_rc_keys[i].key, dib->rc_input_dev.keybit); + *event = 0; + *state = REMOTE_NO_KEY_PRESSED; + switch (keybuf[0]) { + case DVB_USB_RC_NEC_EMPTY: + break; + case DVB_USB_RC_NEC_KEY_PRESSED: + if ((0xff - keybuf[3]) != keybuf[4]) { + deb_err("remote control checksum failed.\n"); + break; + } + /* See if we can match the raw key code. */ + for (i = 0; i < key_count; i++) + if (keymap[i].c0 == keybuf[1] && + keymap[i].c1 == keybuf[2] && + keymap[i].c2 == keybuf[3]) { + *event = keymap[i].key; + *state = REMOTE_KEY_PRESSED; + break; + } + deb_err("key mapping failed - no appropriate key found in keymapping\n"); break; - case DIBUSB_RC_HAUPPAUGE_PROTO: - for (i=0; i<sizeof(haupp_rc_keys)/sizeof(haupp_rc_keys[0]); i++) - set_bit(haupp_rc_keys[i].key, dib->rc_input_dev.keybit); + case DVB_USB_RC_NEC_KEY_REPEATED: + *state = REMOTE_KEY_REPEAT; break; default: + deb_err("unkown type of remote status: %d\n",keybuf[0]); break; } - - - input_register_device(&dib->rc_input_dev); - - INIT_WORK(&dib->rc_query_work, dibusb_remote_query, dib); - - /* Start the remote-control polling. */ - if (dib->rc_query_interval < 40) - dib->rc_query_interval = 100; /* default */ - - info("schedule remote query interval to %d msecs.",dib->rc_query_interval); - schedule_delayed_work(&dib->rc_query_work,msecs_to_jiffies(dib->rc_query_interval)); - - dib->init_state |= DIBUSB_STATE_REMOTE; - - return 0; -} - -int dibusb_remote_exit(struct usb_dibusb *dib) -{ - if (dib->dibdev->dev_cl->remote_type == DIBUSB_RC_NO) - return 0; - - if (dib->init_state & DIBUSB_STATE_REMOTE) { - cancel_delayed_work(&dib->rc_query_work); - flush_scheduled_work(); - input_unregister_device(&dib->rc_input_dev); - } - dib->init_state &= ~DIBUSB_STATE_REMOTE; return 0; } +EXPORT_SYMBOL(dvb_usb_nec_rc_key_to_event); diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h index 7f08936ce..8fdafd2b3 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -88,17 +88,13 @@ struct dvb_usb_properties { struct dvb_usb_device_description * (*identify_desc_quirk) (void); /* the device is not distinuishable just by its USB IDs */ -#define USB_REMOTE_PROTO_NO 1 -#define USB_REMOTE_PROTO_NEC 2 -#define USB_REMOTE_PROTO_HAUPPAUGE 3 - int remote_protocol; /* does this device have an ir-receiver */ +#define REMOTE_NO_KEY_PRESSED 0x00 +#define REMOTE_KEY_PRESSED 0x01 +#define REMOTE_KEY_REPEAT 0x02 + int (*init_rc) (struct dvb_usb_device *); /* remote query callback - NULL no ir-receiver */ + int (*query_rc) (struct dvb_usb_device *, u32 *, int *); /* remote query callback - NULL no ir-receiver */ int rc_interval; -#define REMOTE_KEY_NO 0x01 -#define REMOTE_KEY_REPEAT 0x02 -#define REMOTE_KEY_PRESSED 0x03 - int (*query_rc) (struct dvb_usb_device *, u8 *, int *); /* remote query callback */ - /* i2c algorithm, if any */ struct i2c_algorithm i2c_algo; @@ -151,6 +147,7 @@ struct dvb_usb_device { int urbs_submitted; int feedcount; + int pid_filtering; /* locking */ struct semaphore usb_sem; @@ -170,15 +167,10 @@ struct dvb_usb_device { int (*fe_init) (struct dvb_frontend *); /* remote control */ -// struct input_dev rc_input_dev; -// struct work_struct rc_query_work; -// int last_event; -// int last_state; /* for Hauppauge RC protocol */ -// int repeat_key_count; -// int rc_key_repeat_count; /* module parameter */ - - int pid_filtering; -// int rc_query_interval; + struct input_dev rc_input_dev; + struct work_struct rc_query_work; + u32 last_event; + int last_state; void *priv; }; @@ -190,4 +182,12 @@ extern void dvb_usb_device_exit(struct usb_interface *); extern int dvb_usb_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16); extern int dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16); +/* common used remote control parsing */ +struct dvb_usb_nec_rc_key { + u8 c0,c1,c2; + u32 key; +}; + +extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, struct dvb_usb_nec_rc_key[],int, u8[], u32 *, int *); + #endif diff --git a/linux/drivers/media/dvb/dvb-usb/vp7045.c b/linux/drivers/media/dvb/dvb-usb/vp7045.c index 10945591b..d3d0b267d 100644 --- a/linux/drivers/media/dvb/dvb-usb/vp7045.c +++ b/linux/drivers/media/dvb/dvb-usb/vp7045.c @@ -16,7 +16,7 @@ /* debug */ int dvb_usb_vp7045_debug; module_param_named(debug,dvb_usb_vp7045_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS); +MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec) { @@ -85,16 +85,56 @@ u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg) static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff) { u8 v = onoff; - deb_info("power control: %s\n",onoff ? "on" : "off"); - return vp7045_usb_op(d,SET_TUNER_POWER,&v,1,NULL,0,150); } -static int vp7045_rc_query(struct dvb_usb_device *d, u8 *key_buf, int *state) +/* remote control stuff */ + +/* The keymapping struct. Somehow this should be loaded to the driver, but + * currently it is hardcoded. */ +struct { + u8 raw; + u32 key; +} vp7045_rc_key_mapping[] = { + + /* insert the keys like this. to make the raw keys visible, enable + * debug=0x04 when loading dvb-usb-vp7045. */ + + /* these keys are probably wrong. I don't have a working IR-receiver on my + * vp7045, so I can't test it. Patches are welcome. */ + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, +}; + +static int vp7045_rc_init(struct dvb_usb_device *d) { - deb_info("remote query\n"); - *state = REMOTE_KEY_NO; - return 0; //vp7045_usb_op(d,RC_VAL_READ,NULL,0,&v,1,20); + int i; + for (i = 0; i < sizeof(vp7045_rc_key_mapping)/sizeof(vp7045_rc_key_mapping[0]); i++) + set_bit(vp7045_rc_key_mapping[i].key, d->rc_input_dev.keybit); + + return 0; +} + +static int vp7045_rc_query(struct dvb_usb_device *d, u32 *key_buf, int *state) +{ + u8 key; + int i; + vp7045_usb_op(d,RC_VAL_READ,NULL,0,&key,1,20); + + deb_rc("remote query key: %x %d\n",key,key); + + if (key == 0x44) { + *state = REMOTE_NO_KEY_PRESSED; + return 0; + } + + for (i = 0; i < sizeof(vp7045_rc_key_mapping)/sizeof(vp7045_rc_key_mapping); i++) + if (vp7045_rc_key_mapping[i].raw == key) { + *state = REMOTE_KEY_PRESSED; + *key_buf = vp7045_rc_key_mapping[i].key; + break; + } + return 0; } static int vp7045_read_eeprom(struct dvb_usb_device *d,u8 *buf, int len, int offset) @@ -169,7 +209,7 @@ static struct dvb_usb_properties vp7045_properties = { .read_mac_address = vp7045_read_mac_addr, .rc_interval = 400, - .remote_protocol = USB_REMOTE_PROTO_NEC, + .init_rc = vp7045_rc_init, .query_rc = vp7045_rc_query, /* parameter for the MPEG2-data transfer */ diff --git a/linux/drivers/media/dvb/dvb-usb/vp7045.h b/linux/drivers/media/dvb/dvb-usb/vp7045.h index 0ff5e5dc6..9ce21a20f 100644 --- a/linux/drivers/media/dvb/dvb-usb/vp7045.h +++ b/linux/drivers/media/dvb/dvb-usb/vp7045.h @@ -20,6 +20,7 @@ extern int dvb_usb_vp7045_debug; #define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args) #define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args) +#define deb_rc(args...) dprintk(dvb_usb_vp7045_debug,0x04,args) /* vp7045 commands */ |