diff options
Diffstat (limited to 'drivers/media/dvb/dvb-usb/dvb-usb-remote.c')
-rw-r--r-- | drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 198 |
1 files changed, 140 insertions, 58 deletions
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 852fe89539cf..b579fed3ab3f 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -8,29 +8,29 @@ #include "dvb-usb-common.h" #include <linux/usb/input.h> -static int dvb_usb_getkeycode(struct input_dev *dev, +static int legacy_dvb_usb_getkeycode(struct input_dev *dev, unsigned int scancode, unsigned int *keycode) { struct dvb_usb_device *d = input_get_drvdata(dev); - struct dvb_usb_rc_key *keymap = d->props.rc_key_map; + struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map; int i; /* See if we can match the raw key code. */ - for (i = 0; i < d->props.rc_key_map_size; i++) - if (keymap[i].scan == scancode) { - *keycode = keymap[i].event; + for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) + if (keymap[i].scancode == scancode) { + *keycode = keymap[i].keycode; return 0; } /* * If is there extra space, returns KEY_RESERVED, - * otherwise, input core won't let dvb_usb_setkeycode + * otherwise, input core won't let legacy_dvb_usb_setkeycode * to work */ - for (i = 0; i < d->props.rc_key_map_size; i++) - if (keymap[i].event == KEY_RESERVED || - keymap[i].event == KEY_UNKNOWN) { + for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) + if (keymap[i].keycode == KEY_RESERVED || + keymap[i].keycode == KEY_UNKNOWN) { *keycode = KEY_RESERVED; return 0; } @@ -38,27 +38,27 @@ static int dvb_usb_getkeycode(struct input_dev *dev, return -EINVAL; } -static int dvb_usb_setkeycode(struct input_dev *dev, +static int legacy_dvb_usb_setkeycode(struct input_dev *dev, unsigned int scancode, unsigned int keycode) { struct dvb_usb_device *d = input_get_drvdata(dev); - struct dvb_usb_rc_key *keymap = d->props.rc_key_map; + struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map; int i; /* Search if it is replacing an existing keycode */ - for (i = 0; i < d->props.rc_key_map_size; i++) - if (keymap[i].scan == scancode) { - keymap[i].event = keycode; + for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) + if (keymap[i].scancode == scancode) { + keymap[i].keycode = keycode; return 0; } /* Search if is there a clean entry. If so, use it */ - for (i = 0; i < d->props.rc_key_map_size; i++) - if (keymap[i].event == KEY_RESERVED || - keymap[i].event == KEY_UNKNOWN) { - keymap[i].scan = scancode; - keymap[i].event = keycode; + for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) + if (keymap[i].keycode == KEY_RESERVED || + keymap[i].keycode == KEY_UNKNOWN) { + keymap[i].scancode = scancode; + keymap[i].keycode = keycode; return 0; } @@ -78,7 +78,7 @@ static int dvb_usb_setkeycode(struct input_dev *dev, * * TODO: Fix the repeat rate of the input device. */ -static void dvb_usb_read_remote_control(struct work_struct *work) +static void legacy_dvb_usb_read_remote_control(struct work_struct *work) { struct dvb_usb_device *d = container_of(work, struct dvb_usb_device, rc_query_work.work); @@ -92,7 +92,7 @@ static void dvb_usb_read_remote_control(struct work_struct *work) if (dvb_usb_disable_rc_polling) return; - if (d->props.rc_query(d,&event,&state)) { + if (d->props.rc.legacy.rc_query(d,&event,&state)) { err("error while querying for an remote control event."); goto schedule; } @@ -151,18 +151,117 @@ static void dvb_usb_read_remote_control(struct work_struct *work) */ schedule: - schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval)); + schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval)); +} + +static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d, + struct input_dev *input_dev) +{ + int i, err, rc_interval; + + input_dev->getkeycode = legacy_dvb_usb_getkeycode; + input_dev->setkeycode = legacy_dvb_usb_setkeycode; + + /* set the bits for the keys */ + deb_rc("key map size: %d\n", d->props.rc.legacy.rc_key_map_size); + for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) { + deb_rc("setting bit for event %d item %d\n", + d->props.rc.legacy.rc_key_map[i].keycode, i); + set_bit(d->props.rc.legacy.rc_key_map[i].keycode, input_dev->keybit); + } + + /* setting these two values to non-zero, we have to manage key repeats */ + input_dev->rep[REP_PERIOD] = d->props.rc.legacy.rc_interval; + input_dev->rep[REP_DELAY] = d->props.rc.legacy.rc_interval + 150; + + input_set_drvdata(input_dev, d); + + err = input_register_device(input_dev); + if (err) + input_free_device(input_dev); + + rc_interval = d->props.rc.legacy.rc_interval; + + INIT_DELAYED_WORK(&d->rc_query_work, legacy_dvb_usb_read_remote_control); + + info("schedule remote query interval to %d msecs.", rc_interval); + schedule_delayed_work(&d->rc_query_work, + msecs_to_jiffies(rc_interval)); + + d->state |= DVB_USB_STATE_REMOTE; + + return err; +} + +/* 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(struct work_struct *work) +{ + struct dvb_usb_device *d = + container_of(work, struct dvb_usb_device, rc_query_work.work); + int err; + + /* TODO: need a lock here. We can simply skip checking for the remote control + if we're busy. */ + + /* when the parameter has been set to 1 via sysfs while the + * driver was running, or when bulk mode is enabled after IR init + */ + if (dvb_usb_disable_rc_polling || d->props.rc.core.bulk_mode) + return; + + err = d->props.rc.core.rc_query(d); + if (err) + err("error %d while querying for an remote control event.", err); + + schedule_delayed_work(&d->rc_query_work, + msecs_to_jiffies(d->props.rc.core.rc_interval)); +} + +static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d, + struct input_dev *input_dev) +{ + int err, rc_interval; + + d->props.rc.core.rc_props.priv = d; + err = ir_input_register(input_dev, + d->props.rc.core.rc_codes, + &d->props.rc.core.rc_props, + d->props.rc.core.module_name); + if (err < 0) + return err; + + if (!d->props.rc.core.rc_query || d->props.rc.core.bulk_mode) + return 0; + + /* Polling mode - initialize a work queue for handling it */ + INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); + + rc_interval = d->props.rc.core.rc_interval; + + info("schedule remote query interval to %d msecs.", rc_interval); + schedule_delayed_work(&d->rc_query_work, + msecs_to_jiffies(rc_interval)); + + return 0; } int dvb_usb_remote_init(struct dvb_usb_device *d) { struct input_dev *input_dev; - int i; int err; - if (d->props.rc_key_map == NULL || - d->props.rc_query == NULL || - dvb_usb_disable_rc_polling) + if (dvb_usb_disable_rc_polling) + return 0; + + if (d->props.rc.legacy.rc_key_map && d->props.rc.legacy.rc_query) + d->props.rc.mode = DVB_RC_LEGACY; + else if (d->props.rc.core.rc_codes) + d->props.rc.mode = DVB_RC_CORE; + else return 0; usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); @@ -177,39 +276,19 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) input_dev->phys = d->rc_phys; usb_to_input_id(d->udev, &input_dev->id); input_dev->dev.parent = &d->udev->dev; - input_dev->getkeycode = dvb_usb_getkeycode; - input_dev->setkeycode = dvb_usb_setkeycode; - - /* set the bits for the keys */ - deb_rc("key map size: %d\n", d->props.rc_key_map_size); - for (i = 0; i < d->props.rc_key_map_size; i++) { - deb_rc("setting bit for event %d item %d\n", - d->props.rc_key_map[i].event, i); - set_bit(d->props.rc_key_map[i].event, input_dev->keybit); - } /* Start the remote-control polling. */ - if (d->props.rc_interval < 40) - d->props.rc_interval = 100; /* default */ - - /* setting these two values to non-zero, we have to manage key repeats */ - input_dev->rep[REP_PERIOD] = d->props.rc_interval; - input_dev->rep[REP_DELAY] = d->props.rc_interval + 150; - - input_set_drvdata(input_dev, d); - - err = input_register_device(input_dev); - if (err) { - input_free_device(input_dev); - return err; - } + if (d->props.rc.legacy.rc_interval < 40) + d->props.rc.legacy.rc_interval = 100; /* default */ d->rc_input_dev = input_dev; - INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); - - 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)); + if (d->props.rc.mode == DVB_RC_LEGACY) + err = legacy_dvb_usb_remote_init(d, input_dev); + else + err = rc_core_dvb_usb_remote_init(d, input_dev); + if (err) + return err; d->state |= DVB_USB_STATE_REMOTE; @@ -221,7 +300,10 @@ int dvb_usb_remote_exit(struct dvb_usb_device *d) if (d->state & DVB_USB_STATE_REMOTE) { cancel_rearming_delayed_work(&d->rc_query_work); flush_scheduled_work(); - input_unregister_device(d->rc_input_dev); + if (d->props.rc.mode == DVB_RC_LEGACY) + input_unregister_device(d->rc_input_dev); + else + ir_input_unregister(d->rc_input_dev); } d->state &= ~DVB_USB_STATE_REMOTE; return 0; @@ -234,7 +316,7 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d, u8 keybuf[5], u32 *event, int *state) { int i; - struct dvb_usb_rc_key *keymap = d->props.rc_key_map; + struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map; *event = 0; *state = REMOTE_NO_KEY_PRESSED; switch (keybuf[0]) { @@ -247,10 +329,10 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d, break; } /* See if we can match the raw key code. */ - for (i = 0; i < d->props.rc_key_map_size; i++) + for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) if (rc5_custom(&keymap[i]) == keybuf[1] && rc5_data(&keymap[i]) == keybuf[3]) { - *event = keymap[i].event; + *event = keymap[i].keycode; *state = REMOTE_KEY_PRESSED; return 0; } |