/** Get data and parse scancodes. * @param arg Pointer to xt_kbd_t structure. * @return Never. */ int polling(void *arg) { assert(arg); const xt_kbd_t *kbd = arg; assert(kbd->parent_sess); async_exch_t *parent_exch = async_exchange_begin(kbd->parent_sess); while (1) { if (!parent_exch) parent_exch = async_exchange_begin(kbd->parent_sess); const int *map = scanmap_simple; size_t map_size = sizeof(scanmap_simple) / sizeof(int); uint8_t code = 0; ssize_t size = chardev_read(parent_exch, &code, 1); /** Ignore AT command reply */ if (code == KBD_ACK || code == KBD_RESEND) { continue; } if (code == KBD_SCANCODE_SET_EXTENDED) { map = scanmap_e0; map_size = sizeof(scanmap_e0) / sizeof(int); size = chardev_read(parent_exch, &code, 1); // TODO handle print screen } /* Invalid read. */ if (size != 1) { continue; } /* Bit 7 indicates press/release */ const kbd_event_type_t type = (code & 0x80) ? KEY_RELEASE : KEY_PRESS; code &= ~0x80; const unsigned key = (code < map_size) ? map[code] : 0; if (key != 0) { async_exch_t *exch = async_exchange_begin(kbd->client_sess); if (!exch) { ddf_msg(LVL_ERROR, "Failed creating exchange."); continue; } async_msg_4(exch, KBDEV_EVENT, type, key, 0, 0); async_exchange_end(exch); } else { ddf_msg(LVL_WARN, "Unknown scancode: %hhx", code); } } }
/** Get data and parse scancodes. * * @param arg Pointer to at_kbd_t structure. * * @return EIO on error. * */ static int polling(void *arg) { const at_kbd_t *kbd = arg; assert(kbd); assert(kbd->parent_sess); async_exch_t *parent_exch = async_exchange_begin(kbd->parent_sess); while (true) { if (!parent_exch) parent_exch = async_exchange_begin(kbd->parent_sess); uint8_t code = 0; ssize_t size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; const unsigned int *map; size_t map_size; if (code == KBD_SCANCODE_SET_EXTENDED) { map = scanmap_e0; map_size = sizeof(scanmap_e0) / sizeof(unsigned int); size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; } else if (code == KBD_SCANCODE_SET_EXTENDED_SPECIAL) { size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; if (code != 0x14) continue; size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; if (code != 0x77) continue; size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; if (code != 0xe1) continue; size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; if (code != 0xf0) continue; size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; if (code != 0x14) continue; size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; if (code != 0xf0) continue; size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; if (code == 0x77) push_event(kbd->client_sess, KEY_PRESS, KC_BREAK); continue; } else { map = scanmap_simple; map_size = sizeof(scanmap_simple) / sizeof(unsigned int); } kbd_event_type_t type; if (code == KBD_SCANCODE_KEY_RELEASE) { type = KEY_RELEASE; size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; } else { type = KEY_PRESS; } const unsigned int key = (code < map_size) ? map[code] : 0; if (key != 0) push_event(kbd->client_sess, type, key); else ddf_msg(LVL_WARN, "Unknown scancode: %hhx", code); } }
/** Get data and parse scancodes. * * @param arg Pointer to xt_kbd_t structure. * * @return EIO on error. * */ static int polling(void *arg) { const xt_kbd_t *kbd = arg; assert(kbd); assert(kbd->parent_sess); async_exch_t *parent_exch = async_exchange_begin(kbd->parent_sess); while (true) { if (!parent_exch) parent_exch = async_exchange_begin(kbd->parent_sess); const unsigned int *map = scanmap_simple; size_t map_size = sizeof(scanmap_simple) / sizeof(unsigned int); uint8_t code = 0; ssize_t size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; /* Ignore AT command reply */ if ((code == KBD_ACK) || (code == KBD_RESEND)) continue; /* Extended set */ if (code == KBD_SCANCODE_SET_EXTENDED) { map = scanmap_e0; map_size = sizeof(scanmap_e0) / sizeof(unsigned int); size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; /* Handle really special keys */ if (code == 0x2a) { /* Print Screen */ size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; if (code != 0xe0) continue; size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; if (code == 0x37) push_event(kbd->client_sess, KEY_PRESS, KC_PRTSCR); continue; } if (code == 0x46) { /* Break */ size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; if (code != 0xe0) continue; size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; if (code == 0xc6) push_event(kbd->client_sess, KEY_PRESS, KC_BREAK); continue; } } /* Extended special set */ if (code == KBD_SCANCODE_SET_EXTENDED_SPECIAL) { size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; if (code != 0x1d) continue; size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; if (code != 0x45) continue; size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; if (code != 0xe1) continue; size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; if (code != 0x9d) continue; size = chardev_read(parent_exch, &code, 1); if (size != 1) return EIO; if (code == 0xc5) push_event(kbd->client_sess, KEY_PRESS, KC_PAUSE); continue; } /* Bit 7 indicates press/release */ const kbd_event_type_t type = (code & 0x80) ? KEY_RELEASE : KEY_PRESS; code &= ~0x80; const unsigned int key = (code < map_size) ? map[code] : 0; if (key != 0) push_event(kbd->client_sess, type, key); else ddf_msg(LVL_WARN, "Unknown scancode: %hhx", code); } }