=== ukbd.c ================================================================== --- ukbd.c (revision 223581) +++ ukbd.c (local) @@ -108,9 +108,10 @@ #define UKBD_IN_BUF_SIZE (2*(UKBD_NMOD + (2*UKBD_NKEYCODE))) /* bytes */ #define UKBD_IN_BUF_FULL (UKBD_IN_BUF_SIZE / 2) /* bytes */ #define UKBD_NFKEY (sizeof(fkey_tab)/sizeof(fkey_tab[0])) /* units */ +#define UKBD_OUT_BUF_SIZE 16 /* bytes */ struct ukbd_data { - uint8_t modifiers; + uint16_t modifiers; #define MOD_CONTROL_L 0x01 #define MOD_CONTROL_R 0x10 #define MOD_SHIFT_L 0x02 @@ -119,9 +120,10 @@ #define MOD_ALT_R 0x40 #define MOD_WIN_L 0x08 #define MOD_WIN_R 0x80 - uint8_t reserved; +/* internal */ +#define MOD_EJECT 0x0100 +#define MOD_FN 0x0200 uint8_t keycode[UKBD_NKEYCODE]; - uint8_t exten[8]; }; enum { @@ -137,6 +139,18 @@ fkeytab_t sc_fkeymap[UKBD_NFKEY]; struct hid_location sc_loc_apple_eject; struct hid_location sc_loc_apple_fn; + struct hid_location sc_loc_ctrl_l; + struct hid_location sc_loc_ctrl_r; + struct hid_location sc_loc_shift_l; + struct hid_location sc_loc_shift_r; + struct hid_location sc_loc_alt_l; + struct hid_location sc_loc_alt_r; + struct hid_location sc_loc_win_l; + struct hid_location sc_loc_win_r; + struct hid_location sc_loc_events; + struct hid_location sc_loc_numlock; + struct hid_location sc_loc_capslock; + struct hid_location sc_loc_scrolllock; struct usb_callout sc_callout; struct ukbd_data sc_ndata; struct ukbd_data sc_odata; @@ -155,30 +169,60 @@ uint32_t sc_buffered_char[2]; #endif uint32_t sc_flags; /* flags */ -#define UKBD_FLAG_COMPOSE 0x0001 -#define UKBD_FLAG_POLLING 0x0002 -#define UKBD_FLAG_SET_LEDS 0x0004 -#define UKBD_FLAG_ATTACHED 0x0010 -#define UKBD_FLAG_GONE 0x0020 -#define UKBD_FLAG_APPLE_EJECT 0x0040 -#define UKBD_FLAG_APPLE_FN 0x0080 -#define UKBD_FLAG_APPLE_SWAP 0x0100 -#define UKBD_FLAG_TIMER_RUNNING 0x0200 +#define UKBD_FLAG_COMPOSE 0x00000001 +#define UKBD_FLAG_POLLING 0x00000002 +#define UKBD_FLAG_SET_LEDS 0x00000004 +#define UKBD_FLAG_ATTACHED 0x00000010 +#define UKBD_FLAG_GONE 0x00000020 +#define UKBD_FLAG_APPLE_EJECT 0x00000040 +#define UKBD_FLAG_APPLE_FN 0x00000080 +#define UKBD_FLAG_APPLE_SWAP 0x00000100 +#define UKBD_FLAG_TIMER_RUNNING 0x00000200 +#define UKBD_FLAG_CTRL_L 0x00000400 +#define UKBD_FLAG_CTRL_R 0x00000800 +#define UKBD_FLAG_SHIFT_L 0x00001000 +#define UKBD_FLAG_SHIFT_R 0x00002000 +#define UKBD_FLAG_ALT_L 0x00004000 +#define UKBD_FLAG_ALT_R 0x00008000 +#define UKBD_FLAG_WIN_L 0x00010000 +#define UKBD_FLAG_WIN_R 0x00020000 +#define UKBD_FLAG_EVENTS 0x00040000 +#define UKBD_FLAG_NUMLOCK 0x00080000 +#define UKBD_FLAG_CAPSLOCK 0x00100000 +#define UKBD_FLAG_SCROLLLOCK 0x00200000 int sc_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */ int sc_state; /* shift/lock key state */ int sc_accents; /* accent key index (> 0) */ int sc_poll_tick_last; + int sc_led_size; + int sc_kbd_size; uint16_t sc_inputs; uint16_t sc_inputhead; uint16_t sc_inputtail; + uint16_t sc_modifiers; uint8_t sc_leds; /* store for async led requests */ uint8_t sc_iface_index; uint8_t sc_iface_no; + uint8_t sc_id_apple_eject; + uint8_t sc_id_apple_fn; + uint8_t sc_id_ctrl_l; + uint8_t sc_id_ctrl_r; + uint8_t sc_id_shift_l; + uint8_t sc_id_shift_r; + uint8_t sc_id_alt_l; + uint8_t sc_id_alt_r; + uint8_t sc_id_win_l; + uint8_t sc_id_win_r; + uint8_t sc_id_event; + uint8_t sc_id_numlock; + uint8_t sc_id_capslock; + uint8_t sc_id_scrolllock; + uint8_t sc_id_events; uint8_t sc_kbd_id; - uint8_t sc_led_id; + uint8_t sc_poll_detected; }; @@ -558,11 +602,10 @@ { struct ukbd_softc *sc = usbd_xfer_softc(xfer); struct usb_page_cache *pc; + uint8_t buffer[32]; uint8_t i; uint8_t offset; uint8_t id; - uint8_t apple_fn; - uint8_t apple_eject; int len; usbd_xfer_status(xfer, &len, NULL, NULL, NULL); @@ -580,73 +623,145 @@ if (sc->sc_kbd_id != 0) { /* check and remove HID ID byte */ usbd_copy_out(pc, 0, &id, 1); - if (id != sc->sc_kbd_id) { - DPRINTF("wrong HID ID\n"); + offset = 1; + len--; + if (len == 0) { + DPRINTF("zero length data\n"); goto tr_setup; } - offset = 1; - len--; } else { offset = 0; + id = 0; } - if (len > sizeof(sc->sc_ndata)) { - len = sizeof(sc->sc_ndata); - } + if (len > sizeof(buffer)) + len = sizeof(buffer); - if (len) { - memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata)); - usbd_copy_out(pc, offset, &sc->sc_ndata, len); + /* get data */ + usbd_copy_out(pc, offset, buffer, len); - if ((sc->sc_flags & UKBD_FLAG_APPLE_EJECT) && - hid_get_data((uint8_t *)&sc->sc_ndata, - len, &sc->sc_loc_apple_eject)) - apple_eject = 1; - else - apple_eject = 0; + /* clear temporary storage */ + memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata)); - if ((sc->sc_flags & UKBD_FLAG_APPLE_FN) && - hid_get_data((uint8_t *)&sc->sc_ndata, - len, &sc->sc_loc_apple_fn)) - apple_fn = 1; + /* scan through HID data */ + if ((sc->sc_flags & UKBD_FLAG_APPLE_EJECT) && + (id == sc->sc_id_apple_eject)) { + if (hid_get_data(buffer, len, &sc->sc_loc_apple_eject)) + sc->sc_modifiers |= MOD_EJECT; else - apple_fn = 0; -#ifdef USB_DEBUG - DPRINTF("apple_eject=%u apple_fn=%u\n", - apple_eject, apple_fn); + sc->sc_modifiers &= ~MOD_EJECT; + } + if ((sc->sc_flags & UKBD_FLAG_APPLE_FN) && + (id == sc->sc_id_apple_fn)) { + if (hid_get_data(buffer, len, &sc->sc_loc_apple_fn)) + sc->sc_modifiers |= MOD_FN; + else + sc->sc_modifiers &= ~MOD_FN; + } + if ((sc->sc_flags & UKBD_FLAG_CTRL_L) && + (id == sc->sc_id_ctrl_l)) { + if (hid_get_data(buffer, len, &sc->sc_loc_ctrl_l)) + sc-> sc_modifiers |= MOD_CONTROL_L; + else + sc-> sc_modifiers &= ~MOD_CONTROL_L; + } + if ((sc->sc_flags & UKBD_FLAG_CTRL_R) && + (id == sc->sc_id_ctrl_r)) { + if (hid_get_data(buffer, len, &sc->sc_loc_ctrl_r)) + sc->sc_modifiers |= MOD_CONTROL_R; + else + sc->sc_modifiers &= ~MOD_CONTROL_R; + } + if ((sc->sc_flags & UKBD_FLAG_SHIFT_L) && + (id == sc->sc_id_shift_l)) { + if (hid_get_data(buffer, len, &sc->sc_loc_shift_l)) + sc->sc_modifiers |= MOD_SHIFT_L; + else + sc->sc_modifiers &= ~MOD_SHIFT_L; + } + if ((sc->sc_flags & UKBD_FLAG_SHIFT_R) && + (id == sc->sc_id_shift_r)) { + if (hid_get_data(buffer, len, &sc->sc_loc_shift_r)) + sc->sc_modifiers |= MOD_SHIFT_R; + else + sc->sc_modifiers &= ~MOD_SHIFT_R; + } + if ((sc->sc_flags & UKBD_FLAG_ALT_L) && + (id == sc->sc_id_alt_l)) { + if (hid_get_data(buffer, len, &sc->sc_loc_alt_l)) + sc->sc_modifiers |= MOD_ALT_L; + else + sc->sc_modifiers &= ~MOD_ALT_L; + } + if ((sc->sc_flags & UKBD_FLAG_ALT_R) && + (id == sc->sc_id_alt_r)) { + if (hid_get_data(buffer, len, &sc->sc_loc_alt_r)) + sc->sc_modifiers |= MOD_ALT_R; + else + sc->sc_modifiers &= ~MOD_ALT_R; + } + if ((sc->sc_flags & UKBD_FLAG_WIN_L) && + (id == sc->sc_id_win_l)) { + if (hid_get_data(buffer, len, &sc->sc_loc_win_l)) + sc->sc_modifiers |= MOD_WIN_L; + else + sc->sc_modifiers &= ~MOD_WIN_L; + } + if ((sc->sc_flags & UKBD_FLAG_WIN_R) && + (id == sc->sc_id_win_r)) { + if (hid_get_data(buffer, len, &sc->sc_loc_win_r)) + sc->sc_modifiers |= MOD_WIN_R; + else + sc->sc_modifiers &= ~MOD_WIN_R; + } - if (sc->sc_ndata.modifiers) { - DPRINTF("mod: 0x%04x\n", sc->sc_ndata.modifiers); + sc->sc_ndata.modifiers = sc->sc_modifiers; + + if ((sc->sc_flags & UKBD_FLAG_EVENTS) && + (id == sc->sc_id_events)) { + i = sc->sc_loc_events.count; + if (i > UKBD_NKEYCODE) + i = UKBD_NKEYCODE; + if (i > len) + i = len; + while (i--) { + sc->sc_ndata.keycode[i] = + hid_get_data(buffer + i, len - i, + &sc->sc_loc_events); } + } + +#ifdef USB_DEBUG + DPRINTF("modifiers = 0x%04x\n", (int)sc->sc_modifiers); + for (i = 0; i < UKBD_NKEYCODE; i++) { + if (sc->sc_ndata.keycode[i]) { + DPRINTF("[%d] = 0x%02x\n", + (int)i, (int)sc->sc_ndata.keycode[i]); + } + } +#endif + if (sc->sc_modifiers & MOD_FN) { for (i = 0; i < UKBD_NKEYCODE; i++) { - if (sc->sc_ndata.keycode[i]) { - DPRINTF("[%d] = %d\n", i, sc->sc_ndata.keycode[i]); - } + sc->sc_ndata.keycode[i] = + ukbd_apple_fn(sc->sc_ndata.keycode[i]); } -#endif /* USB_DEBUG */ + } - if (apple_fn) { - for (i = 0; i < UKBD_NKEYCODE; i++) { - sc->sc_ndata.keycode[i] = - ukbd_apple_fn(sc->sc_ndata.keycode[i]); - } + if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) { + for (i = 0; i < UKBD_NKEYCODE; i++) { + sc->sc_ndata.keycode[i] = + ukbd_apple_swap(sc->sc_ndata.keycode[i]); } + } - if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) { - for (i = 0; i < UKBD_NKEYCODE; i++) { - sc->sc_ndata.keycode[i] = - ukbd_apple_swap(sc->sc_ndata.keycode[i]); - } - } + ukbd_interrupt(sc); - ukbd_interrupt(sc); - - if (!(sc->sc_flags & UKBD_FLAG_TIMER_RUNNING)) { - if (ukbd_any_key_pressed(sc)) { - ukbd_start_timer(sc); - } + if (!(sc->sc_flags & UKBD_FLAG_TIMER_RUNNING)) { + if (ukbd_any_key_pressed(sc)) { + ukbd_start_timer(sc); } } + case USB_ST_SETUP: tr_setup: if (sc->sc_inputs < UKBD_IN_BUF_FULL) { @@ -674,7 +789,10 @@ { struct usb_device_request req; struct usb_page_cache *pc; - uint8_t buf[2]; + uint8_t buf[UKBD_OUT_BUF_SIZE]; + uint8_t id; + uint8_t any; + int len; struct ukbd_softc *sc = usbd_xfer_softc(xfer); #ifdef USB_DEBUG @@ -685,37 +803,84 @@ switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: case USB_ST_SETUP: - if (sc->sc_flags & UKBD_FLAG_SET_LEDS) { - sc->sc_flags &= ~UKBD_FLAG_SET_LEDS; + if (!(sc->sc_flags & UKBD_FLAG_SET_LEDS)) + break; + sc->sc_flags &= ~UKBD_FLAG_SET_LEDS; - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UR_SET_REPORT; - USETW2(req.wValue, UHID_OUTPUT_REPORT, 0); - req.wIndex[0] = sc->sc_iface_no; - req.wIndex[1] = 0; - req.wLength[1] = 0; + req.bmRequestType = UT_WRITE_CLASS_INTERFACE; + req.bRequest = UR_SET_REPORT; + USETW2(req.wValue, UHID_OUTPUT_REPORT, 0); + req.wIndex[0] = sc->sc_iface_no; + req.wIndex[1] = 0; + req.wLength[1] = 0; - /* check if we need to prefix an ID byte */ - if (sc->sc_led_id != 0) { - req.wLength[0] = 2; - buf[0] = sc->sc_led_id; - buf[1] = sc->sc_leds; - } else { - req.wLength[0] = 1; - buf[0] = sc->sc_leds; - buf[1] = 0; + memset(buf, 0, sizeof(buf)); + + id = 0; + any = 0; + + /* Assumption: All led bits must be in the same ID. */ + + if (sc->sc_flags & UKBD_FLAG_NUMLOCK) { + if (sc->sc_leds & NLKED) { + hid_put_data_unsigned(buf + 1, sizeof(buf) - 1, + &sc->sc_loc_numlock, 1); } + id = sc->sc_id_numlock; + any = 1; + } - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_in(pc, 0, &req, sizeof(req)); + if (sc->sc_flags & UKBD_FLAG_SCROLLLOCK) { + if (sc->sc_leds & SLKED) { + hid_put_data_unsigned(buf + 1, sizeof(buf) - 1, + &sc->sc_loc_scrolllock, 1); + } + id = sc->sc_id_scrolllock; + any = 1; + } + + if (sc->sc_flags & UKBD_FLAG_CAPSLOCK) { + if (sc->sc_leds & CLKED) { + hid_put_data_unsigned(buf + 1, sizeof(buf) - 1, + &sc->sc_loc_capslock, 1); + } + id = sc->sc_id_capslock; + any = 1; + } + + /* if no leds, nothing to do */ + if (!any) + break; + + /* range check output report length */ + len = sc->sc_led_size; + if (len > (UKBD_OUT_BUF_SIZE - 1)) + len = (UKBD_OUT_BUF_SIZE - 1); + + /* check if we need to prefix an ID byte */ + if (id != 0) { + req.wLength[0] = 1 + len; + buf[0] = id; pc = usbd_xfer_get_frame(xfer, 1); usbd_copy_in(pc, 0, buf, sizeof(buf)); + usbd_xfer_set_frame_len(xfer, 1, 1 + len); + } else { + req.wLength[0] = len; + pc = usbd_xfer_get_frame(xfer, 1); + usbd_copy_in(pc, 0, buf + 1, sizeof(buf) - 1); + usbd_xfer_set_frame_len(xfer, 1, len); + } - usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); - usbd_xfer_set_frame_len(xfer, 1, req.wLength[0]); - usbd_xfer_set_frames(xfer, 2); - usbd_transfer_submit(xfer); - } + DPRINTF("len=%d, id=%d\n", len, id); + + /* setup control request last */ + pc = usbd_xfer_get_frame(xfer, 0); + usbd_copy_in(pc, 0, &req, sizeof(req)); + usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); + + /* start data transfer */ + usbd_xfer_set_frames(xfer, 2); + usbd_transfer_submit(xfer); break; default: /* Error */ @@ -739,7 +904,7 @@ .type = UE_CONTROL, .endpoint = 0x00, /* Control pipe */ .direction = UE_DIR_ANY, - .bufsize = sizeof(struct usb_device_request) + 8, + .bufsize = sizeof(struct usb_device_request) + UKBD_OUT_BUF_SIZE, .callback = &ukbd_set_leds_callback, .timeout = 1000, /* 1 second */ }, @@ -880,43 +1045,131 @@ err = usbd_req_get_hid_desc(uaa->device, NULL, &hid_ptr, &hid_len, M_TEMP, uaa->info.bIfaceIndex); if (err == 0) { - uint8_t apple_keys = 0; - uint8_t temp_id; + /* check if there is an ID byte */ + sc->sc_kbd_size = hid_report_size(hid_ptr, hid_len, + hid_input, &sc->sc_kbd_id); + /* investigate if this is an Apple Keyboard */ if (hid_locate(hid_ptr, hid_len, HID_USAGE2(HUP_CONSUMER, HUG_APPLE_EJECT), hid_input, 0, &sc->sc_loc_apple_eject, &flags, - &temp_id)) { + &sc->sc_id_apple_eject)) { if (flags & HIO_VARIABLE) sc->sc_flags |= UKBD_FLAG_APPLE_EJECT | UKBD_FLAG_APPLE_SWAP; DPRINTFN(1, "Found Apple eject-key\n"); - apple_keys = 1; - sc->sc_kbd_id = temp_id; } if (hid_locate(hid_ptr, hid_len, HID_USAGE2(0xFFFF, 0x0003), hid_input, 0, &sc->sc_loc_apple_fn, &flags, - &temp_id)) { + &sc->sc_id_apple_fn)) { if (flags & HIO_VARIABLE) sc->sc_flags |= UKBD_FLAG_APPLE_FN; DPRINTFN(1, "Found Apple FN-key\n"); - apple_keys = 1; - sc->sc_kbd_id = temp_id; } - if (apple_keys == 0) { - /* - * Assume the first HID ID contains the - * keyboard data - */ - hid_report_size(hid_ptr, hid_len, - hid_input, &sc->sc_kbd_id); + /* figure out some keys */ + if (hid_locate(hid_ptr, hid_len, + HID_USAGE2(HUP_KEYBOARD, 0xE0), + hid_input, 0, &sc->sc_loc_ctrl_l, &flags, + &sc->sc_id_ctrl_l)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_CTRL_L; + DPRINTFN(1, "Found left control\n"); } + if (hid_locate(hid_ptr, hid_len, + HID_USAGE2(HUP_KEYBOARD, 0xE4), + hid_input, 0, &sc->sc_loc_ctrl_r, &flags, + &sc->sc_id_ctrl_r)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_CTRL_R; + DPRINTFN(1, "Found right control\n"); + } + if (hid_locate(hid_ptr, hid_len, + HID_USAGE2(HUP_KEYBOARD, 0xE1), + hid_input, 0, &sc->sc_loc_shift_l, &flags, + &sc->sc_id_shift_l)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_SHIFT_L; + DPRINTFN(1, "Found left shift\n"); + } + if (hid_locate(hid_ptr, hid_len, + HID_USAGE2(HUP_KEYBOARD, 0xE5), + hid_input, 0, &sc->sc_loc_shift_r, &flags, + &sc->sc_id_shift_r)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_SHIFT_R; + DPRINTFN(1, "Found right shift\n"); + } + if (hid_locate(hid_ptr, hid_len, + HID_USAGE2(HUP_KEYBOARD, 0xE2), + hid_input, 0, &sc->sc_loc_alt_l, &flags, + &sc->sc_id_alt_l)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_ALT_L; + DPRINTFN(1, "Found left alt\n"); + } + if (hid_locate(hid_ptr, hid_len, + HID_USAGE2(HUP_KEYBOARD, 0xE6), + hid_input, 0, &sc->sc_loc_alt_r, &flags, + &sc->sc_id_alt_r)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_ALT_R; + DPRINTFN(1, "Found right alt\n"); + } + if (hid_locate(hid_ptr, hid_len, + HID_USAGE2(HUP_KEYBOARD, 0xE3), + hid_input, 0, &sc->sc_loc_win_l, &flags, + &sc->sc_id_win_l)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_WIN_L; + DPRINTFN(1, "Found left GUI\n"); + } + if (hid_locate(hid_ptr, hid_len, + HID_USAGE2(HUP_KEYBOARD, 0xE7), + hid_input, 0, &sc->sc_loc_win_r, &flags, + &sc->sc_id_win_r)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_WIN_R; + DPRINTFN(1, "Found right GUI\n"); + } + /* figure out event buffer */ + if (hid_locate(hid_ptr, hid_len, + HID_USAGE2(HUP_KEYBOARD, 0x00), + hid_input, 0, &sc->sc_loc_events, &flags, + &sc->sc_id_events)) { + sc->sc_flags |= UKBD_FLAG_EVENTS; + DPRINTFN(1, "Found keyboard events\n"); + } - /* investigate if we need an ID-byte for the leds */ - hid_report_size(hid_ptr, hid_len, hid_output, &sc->sc_led_id); + /* figure out leds on keyboard */ + sc->sc_led_size = hid_report_size(hid_ptr, hid_len, + hid_output, NULL); + if (hid_locate(hid_ptr, hid_len, + HID_USAGE2(HUP_LEDS, 0x01), + hid_output, 0, &sc->sc_loc_numlock, &flags, + &sc->sc_id_numlock)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_NUMLOCK; + DPRINTFN(1, "Found keyboard numlock\n"); + } + if (hid_locate(hid_ptr, hid_len, + HID_USAGE2(HUP_LEDS, 0x02), + hid_output, 0, &sc->sc_loc_capslock, &flags, + &sc->sc_id_capslock)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_CAPSLOCK; + DPRINTFN(1, "Found keyboard capslock\n"); + } + if (hid_locate(hid_ptr, hid_len, + HID_USAGE2(HUP_LEDS, 0x03), + hid_output, 0, &sc->sc_loc_scrolllock, &flags, + &sc->sc_id_scrolllock)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_SCROLLLOCK; + DPRINTFN(1, "Found keyboard scrolllock\n"); + } free(hid_ptr, M_TEMP); } @@ -1468,10 +1721,6 @@ static int ukbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) { - /* translate LED_XXX bits into the device specific bits */ - static const uint8_t ledmap[8] = { - 0, 2, 1, 3, 4, 6, 5, 7, - }; struct ukbd_softc *sc = kbd->kb_data; int i; @@ -1547,10 +1796,11 @@ #endif case KDSETLED: /* set keyboard LED */ /* NOTE: lock key state in "sc_state" won't be changed */ - if (*(int *)arg & ~LOCK_MASK) { + if (*(int *)arg & ~LOCK_MASK) return (EINVAL); - } + i = *(int *)arg; + /* replace CAPS LED with ALTGR LED for ALTGR keyboards */ if (sc->sc_mode == K_XLATE && kbd->kb_keymap->n_keys > ALTGR_OFFSET) { @@ -1559,9 +1809,9 @@ else i &= ~CLKED; } - if (KBD_HAS_DEVICE(kbd)) { - ukbd_set_leds(sc, ledmap[i & LED_MASK]); - } + if (KBD_HAS_DEVICE(kbd)) + ukbd_set_leds(sc, i); + KBD_LED_VAL(kbd) = *(int *)arg; break; case KDGKBSTATE: /* get lock key state */