diff options
-rw-r--r-- | drivers/input/misc/cm109.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c index 9365535ba7f1..ee1bedd7c54c 100644 --- a/drivers/input/misc/cm109.c +++ b/drivers/input/misc/cm109.c @@ -76,8 +76,8 @@ enum { BUZZER_ON = 1 << 5, - /* up to 256 normal keys, up to 16 special keys */ - KEYMAP_SIZE = 256 + 16, + /* up to 256 normal keys, up to 15 special key combinations */ + KEYMAP_SIZE = 256 + 15, }; /* CM109 protocol packet */ @@ -139,7 +139,7 @@ static unsigned short special_keymap(int code) { if (code > 0xff) { switch (code - 0xff) { - case RECORD_MUTE: return KEY_MUTE; + case RECORD_MUTE: return KEY_MICMUTE; case PLAYBACK_MUTE: return KEY_MUTE; case VOLUME_DOWN: return KEY_VOLUMEDOWN; case VOLUME_UP: return KEY_VOLUMEUP; @@ -312,6 +312,32 @@ static void report_key(struct cm109_dev *dev, int key) input_sync(idev); } +/* + * Converts data of special key presses (volume, mute) into events + * for the input subsystem, sends press-n-release for mute keys. + */ +static void cm109_report_special(struct cm109_dev *dev) +{ + static const u8 autorelease = RECORD_MUTE | PLAYBACK_MUTE; + struct input_dev *idev = dev->idev; + u8 data = dev->irq_data->byte[HID_IR0]; + unsigned short keycode; + int i; + + for (i = 0; i < 4; i++) { + keycode = dev->keymap[0xff + BIT(i)]; + if (keycode == KEY_RESERVED) + continue; + + input_report_key(idev, keycode, data & BIT(i)); + if (data & autorelease & BIT(i)) { + input_sync(idev); + input_report_key(idev, keycode, 0); + } + } + input_sync(idev); +} + /****************************************************************************** * CM109 usb communication interface *****************************************************************************/ @@ -357,10 +383,7 @@ static void cm109_urb_irq_callback(struct urb *urb) } /* Special keys */ - if (dev->irq_data->byte[HID_IR0] & 0x0f) { - const int code = (dev->irq_data->byte[HID_IR0] & 0x0f); - report_key(dev, dev->keymap[0xff + code]); - } + cm109_report_special(dev); /* Scan key column */ if (dev->keybit == 0xf) { |