diff --git i/sys/dev/usb/input/ukbd.c w/sys/dev/usb/input/ukbd.c index 8e1eb23522a..0ffba5318db 100644 --- i/sys/dev/usb/input/ukbd.c +++ w/sys/dev/usb/input/ukbd.c @@ -158,6 +158,7 @@ struct ukbd_softc { struct hid_location sc_loc_numlock; struct hid_location sc_loc_capslock; struct hid_location sc_loc_scrolllock; + struct hid_location sc_loc_consumer_ctl; struct usb_callout sc_callout; struct ukbd_data sc_ndata; struct ukbd_data sc_odata; @@ -187,7 +188,7 @@ struct ukbd_softc { #define UKBD_FLAG_ATTACHED 0x00000010 #define UKBD_FLAG_GONE 0x00000020 -#define UKBD_FLAG_HID_MASK 0x003fffc0 +#define UKBD_FLAG_HID_MASK 0x007fffc0 #define UKBD_FLAG_APPLE_EJECT 0x00000040 #define UKBD_FLAG_APPLE_FN 0x00000080 #define UKBD_FLAG_APPLE_SWAP 0x00000100 @@ -203,6 +204,7 @@ struct ukbd_softc { #define UKBD_FLAG_NUMLOCK 0x00080000 #define UKBD_FLAG_CAPSLOCK 0x00100000 #define UKBD_FLAG_SCROLLLOCK 0x00200000 +#define UKBD_FLAG_CONSUMERCTL 0x00400000 int sc_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */ int sc_state; /* shift/lock key state */ @@ -234,6 +236,7 @@ struct ukbd_softc { uint8_t sc_id_capslock; uint8_t sc_id_scrolllock; uint8_t sc_id_events; + uint8_t sc_id_consumer_ctl; uint8_t sc_kbd_id; uint8_t sc_buffer[UKBD_BUFFER_SIZE]; @@ -834,6 +837,20 @@ ukbd_intr_callback(struct usb_xfer *xfer, usb_error_t error) } } + if ((sc->sc_flags & UKBD_FLAG_CONSUMERCTL) && + (id == sc->sc_id_consumer_ctl)) { + i = sc->sc_loc_consumer_ctl.count; + if (i > UKBD_NKEYCODE) + i = UKBD_NKEYCODE; + if (i > len) + i = len; + while (i--) { + sc->sc_ndata.keycode[i] = hid_consumerctl_to_scancode( + hid_get_data(sc->sc_buffer + i, len - i, + &sc->sc_loc_consumer_ctl)); + } + } + ukbd_interrupt(sc); if (ukbd_any_key_pressed(sc) != 0) { @@ -1198,6 +1215,15 @@ ukbd_parse_hid(struct ukbd_softc *sc, const uint8_t *ptr, uint32_t len) sc->sc_flags |= UKBD_FLAG_SCROLLLOCK; DPRINTFN(1, "Found keyboard scrolllock\n"); } + + /* figure out consumer control (multimedia keys) on keyboard */ + if (hid_locate(ptr, len, + HID_USAGE2(HUP_CONSUMER, 0x01), + hid_input, 0, &sc->sc_loc_consumer_ctl, &flags, + &sc->sc_id_consumer_ctl)) { + sc->sc_flags |= UKBD_FLAG_CONSUMERCTL; + DPRINTFN(1, "Found keyboard consumer control\n"); + } } static int diff --git i/sys/dev/usb/usbhid.h w/sys/dev/usb/usbhid.h index 31aa7ea4b2d..52a79351831 100644 --- i/sys/dev/usb/usbhid.h +++ w/sys/dev/usb/usbhid.h @@ -269,5 +269,24 @@ usb_error_t usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx, int32_t hid_item_resolution(struct hid_item *hi); int hid_is_mouse(const void *d_ptr, uint16_t d_len); int hid_is_keyboard(const void *d_ptr, uint16_t d_len); + +/* Converts a HID Consumer Control action into a keyboard scancode */ +static inline uint8_t +hid_consumerctl_to_scancode(int data) { + switch (data) { + case 0xcd: return 0xe8; // Play/Pause + case 0xb7: return 0xe9; // Stop (Music) + case 0xb6: return 0xea; // Previous Song + case 0xb5: return 0xeb; // Next Song + case 0xe9: return 0xed; // Volume Up + case 0xea: return 0xee; // Volume Down + case 0xe2: return 0xef; // Mute + case 0x224: return 0xf1; // Back + case 0x225: return 0xf2; // Forward + case 0x226: return 0xf3; // Stop (Browser) + default: return 0; + } +} + #endif /* _KERNEL */ #endif /* _USB_HID_H_ */