diff options
| -rw-r--r-- | drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 152 | ||||
| -rw-r--r-- | drivers/media/dvb/dvb-usb/dvb-usb.h | 34 |
2 files changed, 149 insertions, 37 deletions
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 7951076e8e06..b579fed3ab3f 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include "dvb-usb-common.h" | 8 | #include "dvb-usb-common.h" |
| 9 | #include <linux/usb/input.h> | 9 | #include <linux/usb/input.h> |
| 10 | 10 | ||
| 11 | static int dvb_usb_getkeycode(struct input_dev *dev, | 11 | static int legacy_dvb_usb_getkeycode(struct input_dev *dev, |
| 12 | unsigned int scancode, unsigned int *keycode) | 12 | unsigned int scancode, unsigned int *keycode) |
| 13 | { | 13 | { |
| 14 | struct dvb_usb_device *d = input_get_drvdata(dev); | 14 | struct dvb_usb_device *d = input_get_drvdata(dev); |
| @@ -25,7 +25,7 @@ static int dvb_usb_getkeycode(struct input_dev *dev, | |||
| 25 | 25 | ||
| 26 | /* | 26 | /* |
| 27 | * If is there extra space, returns KEY_RESERVED, | 27 | * If is there extra space, returns KEY_RESERVED, |
| 28 | * otherwise, input core won't let dvb_usb_setkeycode | 28 | * otherwise, input core won't let legacy_dvb_usb_setkeycode |
| 29 | * to work | 29 | * to work |
| 30 | */ | 30 | */ |
| 31 | for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) | 31 | for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) |
| @@ -38,7 +38,7 @@ static int dvb_usb_getkeycode(struct input_dev *dev, | |||
| 38 | return -EINVAL; | 38 | return -EINVAL; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | static int dvb_usb_setkeycode(struct input_dev *dev, | 41 | static int legacy_dvb_usb_setkeycode(struct input_dev *dev, |
| 42 | unsigned int scancode, unsigned int keycode) | 42 | unsigned int scancode, unsigned int keycode) |
| 43 | { | 43 | { |
| 44 | struct dvb_usb_device *d = input_get_drvdata(dev); | 44 | struct dvb_usb_device *d = input_get_drvdata(dev); |
| @@ -78,7 +78,7 @@ static int dvb_usb_setkeycode(struct input_dev *dev, | |||
| 78 | * | 78 | * |
| 79 | * TODO: Fix the repeat rate of the input device. | 79 | * TODO: Fix the repeat rate of the input device. |
| 80 | */ | 80 | */ |
| 81 | static void dvb_usb_read_remote_control(struct work_struct *work) | 81 | static void legacy_dvb_usb_read_remote_control(struct work_struct *work) |
| 82 | { | 82 | { |
| 83 | struct dvb_usb_device *d = | 83 | struct dvb_usb_device *d = |
| 84 | container_of(work, struct dvb_usb_device, rc_query_work.work); | 84 | container_of(work, struct dvb_usb_device, rc_query_work.work); |
| @@ -154,15 +154,114 @@ schedule: | |||
| 154 | schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval)); | 154 | schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval)); |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d, | ||
| 158 | struct input_dev *input_dev) | ||
| 159 | { | ||
| 160 | int i, err, rc_interval; | ||
| 161 | |||
| 162 | input_dev->getkeycode = legacy_dvb_usb_getkeycode; | ||
| 163 | input_dev->setkeycode = legacy_dvb_usb_setkeycode; | ||
| 164 | |||
| 165 | /* set the bits for the keys */ | ||
| 166 | deb_rc("key map size: %d\n", d->props.rc.legacy.rc_key_map_size); | ||
| 167 | for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) { | ||
| 168 | deb_rc("setting bit for event %d item %d\n", | ||
| 169 | d->props.rc.legacy.rc_key_map[i].keycode, i); | ||
| 170 | set_bit(d->props.rc.legacy.rc_key_map[i].keycode, input_dev->keybit); | ||
| 171 | } | ||
| 172 | |||
| 173 | /* setting these two values to non-zero, we have to manage key repeats */ | ||
| 174 | input_dev->rep[REP_PERIOD] = d->props.rc.legacy.rc_interval; | ||
| 175 | input_dev->rep[REP_DELAY] = d->props.rc.legacy.rc_interval + 150; | ||
| 176 | |||
| 177 | input_set_drvdata(input_dev, d); | ||
| 178 | |||
| 179 | err = input_register_device(input_dev); | ||
| 180 | if (err) | ||
| 181 | input_free_device(input_dev); | ||
| 182 | |||
| 183 | rc_interval = d->props.rc.legacy.rc_interval; | ||
| 184 | |||
| 185 | INIT_DELAYED_WORK(&d->rc_query_work, legacy_dvb_usb_read_remote_control); | ||
| 186 | |||
| 187 | info("schedule remote query interval to %d msecs.", rc_interval); | ||
| 188 | schedule_delayed_work(&d->rc_query_work, | ||
| 189 | msecs_to_jiffies(rc_interval)); | ||
| 190 | |||
| 191 | d->state |= DVB_USB_STATE_REMOTE; | ||
| 192 | |||
| 193 | return err; | ||
| 194 | } | ||
| 195 | |||
| 196 | /* Remote-control poll function - called every dib->rc_query_interval ms to see | ||
| 197 | * whether the remote control has received anything. | ||
| 198 | * | ||
| 199 | * TODO: Fix the repeat rate of the input device. | ||
| 200 | */ | ||
| 201 | static void dvb_usb_read_remote_control(struct work_struct *work) | ||
| 202 | { | ||
| 203 | struct dvb_usb_device *d = | ||
| 204 | container_of(work, struct dvb_usb_device, rc_query_work.work); | ||
| 205 | int err; | ||
| 206 | |||
| 207 | /* TODO: need a lock here. We can simply skip checking for the remote control | ||
| 208 | if we're busy. */ | ||
| 209 | |||
| 210 | /* when the parameter has been set to 1 via sysfs while the | ||
| 211 | * driver was running, or when bulk mode is enabled after IR init | ||
| 212 | */ | ||
| 213 | if (dvb_usb_disable_rc_polling || d->props.rc.core.bulk_mode) | ||
| 214 | return; | ||
| 215 | |||
| 216 | err = d->props.rc.core.rc_query(d); | ||
| 217 | if (err) | ||
| 218 | err("error %d while querying for an remote control event.", err); | ||
| 219 | |||
| 220 | schedule_delayed_work(&d->rc_query_work, | ||
| 221 | msecs_to_jiffies(d->props.rc.core.rc_interval)); | ||
| 222 | } | ||
| 223 | |||
| 224 | static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d, | ||
| 225 | struct input_dev *input_dev) | ||
| 226 | { | ||
| 227 | int err, rc_interval; | ||
| 228 | |||
| 229 | d->props.rc.core.rc_props.priv = d; | ||
| 230 | err = ir_input_register(input_dev, | ||
| 231 | d->props.rc.core.rc_codes, | ||
| 232 | &d->props.rc.core.rc_props, | ||
| 233 | d->props.rc.core.module_name); | ||
| 234 | if (err < 0) | ||
| 235 | return err; | ||
| 236 | |||
| 237 | if (!d->props.rc.core.rc_query || d->props.rc.core.bulk_mode) | ||
| 238 | return 0; | ||
| 239 | |||
| 240 | /* Polling mode - initialize a work queue for handling it */ | ||
| 241 | INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); | ||
| 242 | |||
| 243 | rc_interval = d->props.rc.core.rc_interval; | ||
| 244 | |||
| 245 | info("schedule remote query interval to %d msecs.", rc_interval); | ||
| 246 | schedule_delayed_work(&d->rc_query_work, | ||
| 247 | msecs_to_jiffies(rc_interval)); | ||
| 248 | |||
| 249 | return 0; | ||
| 250 | } | ||
| 251 | |||
| 157 | int dvb_usb_remote_init(struct dvb_usb_device *d) | 252 | int dvb_usb_remote_init(struct dvb_usb_device *d) |
| 158 | { | 253 | { |
| 159 | struct input_dev *input_dev; | 254 | struct input_dev *input_dev; |
| 160 | int i; | ||
| 161 | int err; | 255 | int err; |
| 162 | 256 | ||
| 163 | if (d->props.rc.legacy.rc_key_map == NULL || | 257 | if (dvb_usb_disable_rc_polling) |
| 164 | d->props.rc.legacy.rc_query == NULL || | 258 | return 0; |
| 165 | dvb_usb_disable_rc_polling) | 259 | |
| 260 | if (d->props.rc.legacy.rc_key_map && d->props.rc.legacy.rc_query) | ||
| 261 | d->props.rc.mode = DVB_RC_LEGACY; | ||
| 262 | else if (d->props.rc.core.rc_codes) | ||
| 263 | d->props.rc.mode = DVB_RC_CORE; | ||
| 264 | else | ||
| 166 | return 0; | 265 | return 0; |
| 167 | 266 | ||
| 168 | usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); | 267 | 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) | |||
| 177 | input_dev->phys = d->rc_phys; | 276 | input_dev->phys = d->rc_phys; |
| 178 | usb_to_input_id(d->udev, &input_dev->id); | 277 | usb_to_input_id(d->udev, &input_dev->id); |
| 179 | input_dev->dev.parent = &d->udev->dev; | 278 | input_dev->dev.parent = &d->udev->dev; |
| 180 | input_dev->getkeycode = dvb_usb_getkeycode; | ||
| 181 | input_dev->setkeycode = dvb_usb_setkeycode; | ||
| 182 | |||
| 183 | /* set the bits for the keys */ | ||
| 184 | deb_rc("key map size: %d\n", d->props.rc.legacy.rc_key_map_size); | ||
| 185 | for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) { | ||
| 186 | deb_rc("setting bit for event %d item %d\n", | ||
| 187 | d->props.rc.legacy.rc_key_map[i].keycode, i); | ||
| 188 | set_bit(d->props.rc.legacy.rc_key_map[i].keycode, input_dev->keybit); | ||
| 189 | } | ||
| 190 | 279 | ||
| 191 | /* Start the remote-control polling. */ | 280 | /* Start the remote-control polling. */ |
| 192 | if (d->props.rc.legacy.rc_interval < 40) | 281 | if (d->props.rc.legacy.rc_interval < 40) |
| 193 | d->props.rc.legacy.rc_interval = 100; /* default */ | 282 | d->props.rc.legacy.rc_interval = 100; /* default */ |
| 194 | 283 | ||
| 195 | /* setting these two values to non-zero, we have to manage key repeats */ | ||
| 196 | input_dev->rep[REP_PERIOD] = d->props.rc.legacy.rc_interval; | ||
| 197 | input_dev->rep[REP_DELAY] = d->props.rc.legacy.rc_interval + 150; | ||
| 198 | |||
| 199 | input_set_drvdata(input_dev, d); | ||
| 200 | |||
| 201 | err = input_register_device(input_dev); | ||
| 202 | if (err) { | ||
| 203 | input_free_device(input_dev); | ||
| 204 | return err; | ||
| 205 | } | ||
| 206 | |||
| 207 | d->rc_input_dev = input_dev; | 284 | d->rc_input_dev = input_dev; |
| 208 | 285 | ||
| 209 | INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); | 286 | if (d->props.rc.mode == DVB_RC_LEGACY) |
| 210 | 287 | err = legacy_dvb_usb_remote_init(d, input_dev); | |
| 211 | info("schedule remote query interval to %d msecs.", d->props.rc.legacy.rc_interval); | 288 | else |
| 212 | schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval)); | 289 | err = rc_core_dvb_usb_remote_init(d, input_dev); |
| 290 | if (err) | ||
| 291 | return err; | ||
| 213 | 292 | ||
| 214 | d->state |= DVB_USB_STATE_REMOTE; | 293 | d->state |= DVB_USB_STATE_REMOTE; |
| 215 | 294 | ||
| @@ -221,7 +300,10 @@ int dvb_usb_remote_exit(struct dvb_usb_device *d) | |||
| 221 | if (d->state & DVB_USB_STATE_REMOTE) { | 300 | if (d->state & DVB_USB_STATE_REMOTE) { |
| 222 | cancel_rearming_delayed_work(&d->rc_query_work); | 301 | cancel_rearming_delayed_work(&d->rc_query_work); |
| 223 | flush_scheduled_work(); | 302 | flush_scheduled_work(); |
| 224 | input_unregister_device(d->rc_input_dev); | 303 | if (d->props.rc.mode == DVB_RC_LEGACY) |
| 304 | input_unregister_device(d->rc_input_dev); | ||
| 305 | else | ||
| 306 | ir_input_unregister(d->rc_input_dev); | ||
| 225 | } | 307 | } |
| 226 | d->state &= ~DVB_USB_STATE_REMOTE; | 308 | d->state &= ~DVB_USB_STATE_REMOTE; |
| 227 | return 0; | 309 | return 0; |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index 76f972493768..bcfbf9adc373 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | #include <linux/usb.h> | 14 | #include <linux/usb.h> |
| 15 | #include <linux/firmware.h> | 15 | #include <linux/firmware.h> |
| 16 | #include <linux/mutex.h> | 16 | #include <linux/mutex.h> |
| 17 | #include <media/rc-map.h> | 17 | #include <media/ir-core.h> |
| 18 | 18 | ||
| 19 | #include "dvb_frontend.h" | 19 | #include "dvb_frontend.h" |
| 20 | #include "dvb_demux.h" | 20 | #include "dvb_demux.h" |
| @@ -177,6 +177,34 @@ struct dvb_rc_legacy { | |||
| 177 | }; | 177 | }; |
| 178 | 178 | ||
| 179 | /** | 179 | /** |
| 180 | * struct dvb_rc properties of remote controller, using rc-core | ||
| 181 | * @rc_codes: name of rc codes table | ||
| 182 | * @rc_query: called to query an event event. | ||
| 183 | * @rc_interval: time in ms between two queries. | ||
| 184 | * @rc_props: remote controller properties | ||
| 185 | * @bulk_mode: device supports bulk mode for RC (disable polling mode) | ||
| 186 | */ | ||
| 187 | struct dvb_rc { | ||
| 188 | char *rc_codes; | ||
| 189 | char *module_name; | ||
| 190 | int (*rc_query) (struct dvb_usb_device *d); | ||
| 191 | int rc_interval; | ||
| 192 | struct ir_dev_props rc_props; | ||
| 193 | bool bulk_mode; /* uses bulk mode */ | ||
| 194 | }; | ||
| 195 | |||
| 196 | /** | ||
| 197 | * enum dvb_usb_mode - Specifies if it is using a legacy driver or a new one | ||
| 198 | * based on rc-core | ||
| 199 | * This is initialized/used only inside dvb-usb-remote.c. | ||
| 200 | * It shouldn't be set by the drivers. | ||
| 201 | */ | ||
| 202 | enum dvb_usb_mode { | ||
| 203 | DVB_RC_LEGACY, | ||
| 204 | DVB_RC_CORE, | ||
| 205 | }; | ||
| 206 | |||
| 207 | /** | ||
| 180 | * struct dvb_usb_device_properties - properties of a dvb-usb-device | 208 | * struct dvb_usb_device_properties - properties of a dvb-usb-device |
| 181 | * @usb_ctrl: which USB device-side controller is in use. Needed for firmware | 209 | * @usb_ctrl: which USB device-side controller is in use. Needed for firmware |
| 182 | * download. | 210 | * download. |
| @@ -238,8 +266,10 @@ struct dvb_usb_device_properties { | |||
| 238 | int (*identify_state) (struct usb_device *, struct dvb_usb_device_properties *, | 266 | int (*identify_state) (struct usb_device *, struct dvb_usb_device_properties *, |
| 239 | struct dvb_usb_device_description **, int *); | 267 | struct dvb_usb_device_description **, int *); |
| 240 | 268 | ||
| 241 | union { | 269 | struct { |
| 270 | enum dvb_usb_mode mode; /* Drivers shouldn't touch on it */ | ||
| 242 | struct dvb_rc_legacy legacy; | 271 | struct dvb_rc_legacy legacy; |
| 272 | struct dvb_rc core; | ||
| 243 | } rc; | 273 | } rc; |
| 244 | 274 | ||
| 245 | struct i2c_algorithm *i2c_algo; | 275 | struct i2c_algorithm *i2c_algo; |
