Changes in / [494eaf7:cc44f7e] in mainline
- Location:
- uspace/drv/usbhid
- Files:
-
- 1 added
- 6 deleted
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhid/Makefile
r494eaf7 rcc44f7e 40 40 main.c \ 41 41 conv.c \ 42 hidreq.c \43 kbddev.c \44 hiddev.c \45 42 $(STOLEN_LAYOUT_SOURCES) 46 43 -
uspace/drv/usbhid/conv.c
r494eaf7 rcc44f7e 163 163 }; 164 164 165 unsigned int usb hid_parse_scancode(int scancode)165 unsigned int usbkbd_parse_scancode(int scancode) 166 166 { 167 // console_ev_type_t type; 167 168 unsigned int key; 168 169 int *map = scanmap_simple; 169 170 size_t map_length = sizeof(scanmap_simple) / sizeof(int); 170 171 172 /* 173 * ACK/NAK are returned as response to us sending a command. 174 * We are not interested in them. 175 */ 176 // if (scancode == SC_ACK || scancode == SC_NAK) 177 // return; 178 179 // if (scancode == 0xe0) { 180 // ds = ds_e; 181 // return; 182 // } 183 184 // switch (ds) { 185 // case ds_s: 186 // map = scanmap_simple; 187 // map_length = sizeof(scanmap_simple) / sizeof(int); 188 // break; 189 // case ds_e: 190 // map = scanmap_e0; 191 // map_length = sizeof(scanmap_e0) / sizeof(int); 192 // break; 193 // default: 194 // map = NULL; 195 // map_length = 0; 196 // } 197 198 // ds = ds_s; 199 200 // if (scancode & 0x80) { 201 // scancode &= ~0x80; 202 // type = KEY_RELEASE; 203 // } else { 204 // type = KEY_PRESS; 205 // } 206 171 207 if ((scancode < 0) || ((size_t) scancode >= map_length)) 172 208 return -1; … … 174 210 key = map[scancode]; 175 211 212 if (scancode == 0x53) { 213 usb_log_debug("\n\nWe have a NUM LOCK!, sending key %u\n\n", key); 214 } 215 216 if (scancode == 0x47) { 217 usb_log_debug("\n\nWe have a SCROLL LOCK!, sending key %u\n\n", key); 218 } 219 220 if (scancode == 0x39) { 221 usb_log_debug("\n\nWe have a CAPS LOCK!, sending key %u\n\n", key); 222 } 223 224 // if (key != 0) 225 // kbd_push_ev(type, key); 176 226 return key; 177 227 } -
uspace/drv/usbhid/conv.h
r494eaf7 rcc44f7e 37 37 #define USBHID_CONV_H_ 38 38 39 unsigned int usb hid_parse_scancode(int scancode);39 unsigned int usbkbd_parse_scancode(int scancode); 40 40 41 #endif /* USBHID_CONV_H_ */41 #endif 42 42 43 43 /** -
uspace/drv/usbhid/descdump.h
r494eaf7 rcc44f7e 37 37 #define USBHID_DESCDUMP_H_ 38 38 39 #include <usb/descriptor.h> 40 #include <usb/classes/hid.h> 39 #include "hid.h" 41 40 42 41 void dump_standard_configuration_descriptor( -
uspace/drv/usbhid/main.c
r494eaf7 rcc44f7e 37 37 38 38 #include <ddf/driver.h> 39 #include <ipc/driver.h> 40 #include <ipc/kbd.h> 41 #include <io/keycode.h> 42 #include <io/console.h> 43 #include <errno.h> 44 #include <str_error.h> 45 #include <fibril.h> 39 46 #include <usb/debug.h> 40 #include <errno.h> 41 42 #include "kbddev.h" 43 44 /*----------------------------------------------------------------------------*/ 45 47 #include <usb/classes/classes.h> 48 #include <usb/classes/hid.h> 49 #include <usb/classes/hidparser.h> 50 #include <usb/request.h> 51 #include <usb/descriptor.h> 52 #include <io/console.h> 53 #include <stdint.h> 54 #include <usb/dp.h> 55 #include "hid.h" 56 #include "conv.h" 57 #include "layout.h" 58 59 #define BUFFER_SIZE 8 60 #define BUFFER_OUT_SIZE 1 46 61 #define NAME "usbhid" 47 62 48 /*----------------------------------------------------------------------------*/ 49 50 static int usbhid_add_device(ddf_dev_t *dev) 51 { 52 usb_log_debug("usbhid_add_device()\n"); 53 54 int rc = usbhid_kbd_try_add_device(dev); 55 56 if (rc != EOK) { 57 usb_log_info("Device is not a supported keyboard.\n"); 58 usb_log_error("Failed to add HID device.\n"); 63 //#define GUESSED_POLL_ENDPOINT 1 64 #define BOOTP_REPORT_SIZE 6 65 66 static unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK; 67 68 /** Keyboard polling endpoint description for boot protocol class. */ 69 static usb_endpoint_description_t poll_endpoint_description = { 70 .transfer_type = USB_TRANSFER_INTERRUPT, 71 .direction = USB_DIRECTION_IN, 72 .interface_class = USB_CLASS_HID, 73 .interface_subclass = USB_HID_SUBCLASS_BOOT, 74 .interface_protocol = USB_HID_PROTOCOL_KEYBOARD, 75 .flags = 0 76 }; 77 78 static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *); 79 static ddf_dev_ops_t keyboard_ops = { 80 .default_handler = default_connection_handler 81 }; 82 83 static int console_callback_phone = -1; 84 85 /** Default handler for IPC methods not handled by DDF. 86 * 87 * @param dev Device handling the call. 88 * @param icallid Call id. 89 * @param icall Call data. 90 */ 91 void default_connection_handler(ddf_fun_t *fun, 92 ipc_callid_t icallid, ipc_call_t *icall) 93 { 94 sysarg_t method = IPC_GET_IMETHOD(*icall); 95 96 if (method == IPC_M_CONNECT_TO_ME) { 97 int callback = IPC_GET_ARG5(*icall); 98 99 if (console_callback_phone != -1) { 100 async_answer_0(icallid, ELIMIT); 101 return; 102 } 103 104 console_callback_phone = callback; 105 async_answer_0(icallid, EOK); 106 return; 107 } 108 109 async_answer_0(icallid, EINVAL); 110 } 111 112 #if 0 113 static void send_key(int key, int type, wchar_t c) { 114 async_msg_4(console_callback_phone, KBD_EVENT, type, key, 115 KM_NUM_LOCK, c); 116 } 117 #endif 118 119 /* 120 * TODO: Move somewhere else 121 */ 122 /* 123 #define BYTES_PER_LINE 12 124 125 static void dump_buffer(const char *msg, const uint8_t *buffer, size_t length) 126 {uint8_t buffer[BUFFER_SIZE]; 127 printf("%s\n", msg); 128 129 size_t i; 130 for (i = 0; i < length; i++) { 131 printf(" 0x%02X", buffer[i]); 132 if (((i > 0) && (((i+1) % BYTES_PER_LINE) == 0)) 133 || (i + 1 == length)) { 134 printf("\n"); 135 } 136 } 137 } 138 */ 139 /* 140 * Copy-paste from srv/hid/kbd/generic/kbd.c 141 */ 142 143 /** Currently active modifiers (locks is probably better word). 144 * 145 * TODO: put to device? 146 */ 147 //static unsigned mods = KM_NUM_LOCK; 148 149 /** Currently pressed lock keys. We track these to tackle autorepeat. 150 * 151 * TODO: put to device? 152 */ 153 //static unsigned lock_keys; 154 155 #define NUM_LAYOUTS 3 156 157 static layout_op_t *layout[NUM_LAYOUTS] = { 158 &us_qwerty_op, 159 &us_dvorak_op, 160 &cz_op 161 }; 162 163 static int active_layout = 0; 164 165 static void usbkbd_req_set_report(usb_hid_dev_kbd_t *kbd_dev, uint16_t iface, 166 usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size) 167 { 168 int rc, sess_rc; 169 170 sess_rc = usb_endpoint_pipe_start_session(&kbd_dev->ctrl_pipe); 171 if (sess_rc != EOK) { 172 usb_log_warning("Failed to start a session: %s.\n", 173 str_error(sess_rc)); 174 return; 175 } 176 177 usb_log_debug("Sending Set_Report request to the device.\n"); 178 179 rc = usb_control_request_set(&kbd_dev->ctrl_pipe, 180 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 181 USB_HIDREQ_SET_REPORT, type, iface, buffer, buf_size); 182 183 sess_rc = usb_endpoint_pipe_end_session(&kbd_dev->ctrl_pipe); 184 185 if (rc != EOK) { 186 usb_log_warning("Error sending output report to the keyboard: " 187 "%s.\n", str_error(rc)); 188 return; 189 } 190 191 if (sess_rc != EOK) { 192 usb_log_warning("Error closing session: %s.\n", 193 str_error(sess_rc)); 194 return; 195 } 196 } 197 198 static void usbkbd_req_set_protocol(usb_hid_dev_kbd_t *kbd_dev, 199 usb_hid_protocol_t protocol) 200 { 201 int rc, sess_rc; 202 203 sess_rc = usb_endpoint_pipe_start_session(&kbd_dev->ctrl_pipe); 204 if (sess_rc != EOK) { 205 usb_log_warning("Failed to start a session: %s.\n", 206 str_error(sess_rc)); 207 return; 208 } 209 210 usb_log_debug("Sending Set_Protocol request to the device (" 211 "protocol: %d, iface: %d).\n", protocol, kbd_dev->iface); 212 213 rc = usb_control_request_set(&kbd_dev->ctrl_pipe, 214 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 215 USB_HIDREQ_SET_PROTOCOL, protocol, kbd_dev->iface, NULL, 0); 216 217 sess_rc = usb_endpoint_pipe_end_session(&kbd_dev->ctrl_pipe); 218 219 if (rc != EOK) { 220 usb_log_warning("Error sending output report to the keyboard: " 221 "%s.\n", str_error(rc)); 222 return; 223 } 224 225 if (sess_rc != EOK) { 226 usb_log_warning("Error closing session: %s.\n", 227 str_error(sess_rc)); 228 return; 229 } 230 } 231 232 static void usbkbd_set_led(usb_hid_dev_kbd_t *kbd_dev) 233 { 234 uint8_t buffer[BUFFER_OUT_SIZE]; 235 int rc= 0, i; 236 237 memset(buffer, 0, BUFFER_OUT_SIZE); 238 uint8_t leds = 0; 239 240 if (kbd_dev->mods & KM_NUM_LOCK) { 241 leds |= USB_HID_LED_NUM_LOCK; 242 } 243 244 if (kbd_dev->mods & KM_CAPS_LOCK) { 245 leds |= USB_HID_LED_CAPS_LOCK; 246 } 247 248 if (kbd_dev->mods & KM_SCROLL_LOCK) { 249 leds |= USB_HID_LED_SCROLL_LOCK; 250 } 251 252 // TODO: COMPOSE and KANA 253 254 usb_log_debug("Creating output report.\n"); 255 usb_log_debug("Leds: 0x%x\n", leds); 256 if ((rc = usb_hid_boot_keyboard_output_report( 257 leds, buffer, BUFFER_OUT_SIZE)) != EOK) { 258 usb_log_warning("Error composing output report to the keyboard:" 259 "%s.\n", str_error(rc)); 260 return; 261 } 262 263 usb_log_debug("Output report buffer: "); 264 for (i = 0; i < BUFFER_OUT_SIZE; ++i) { 265 usb_log_debug("0x%x ", buffer[i]); 266 } 267 usb_log_debug("\n"); 268 269 uint16_t value = 0; 270 value |= (USB_HID_REPORT_TYPE_OUTPUT << 8); 271 272 usbkbd_req_set_report(kbd_dev, kbd_dev->iface, value, buffer, 273 BUFFER_OUT_SIZE); 274 } 275 276 static void kbd_push_ev(int type, unsigned int key, usb_hid_dev_kbd_t *kbd_dev) 277 { 278 console_event_t ev; 279 unsigned mod_mask; 280 281 // TODO: replace by our own parsing?? or are the key codes identical?? 282 switch (key) { 283 case KC_LCTRL: mod_mask = KM_LCTRL; break; 284 case KC_RCTRL: mod_mask = KM_RCTRL; break; 285 case KC_LSHIFT: mod_mask = KM_LSHIFT; break; 286 case KC_RSHIFT: mod_mask = KM_RSHIFT; break; 287 case KC_LALT: mod_mask = KM_LALT; break; 288 case KC_RALT: mod_mask = KM_RALT; break; 289 default: mod_mask = 0; break; 290 } 291 292 if (mod_mask != 0) { 293 if (type == KEY_PRESS) 294 kbd_dev->mods = kbd_dev->mods | mod_mask; 295 else 296 kbd_dev->mods = kbd_dev->mods & ~mod_mask; 297 } 298 299 switch (key) { 300 case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; usb_log_debug2("\n\nPushing CAPS LOCK! (mask: %u)\n\n", mod_mask); break; 301 case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; usb_log_debug2("\n\nPushing NUM LOCK! (mask: %u)\n\n", mod_mask); break; 302 case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; usb_log_debug2("\n\nPushing SCROLL LOCK! (mask: %u)\n\n", mod_mask); break; 303 default: mod_mask = 0; break; 304 } 305 306 if (mod_mask != 0) { 307 usb_log_debug2("\n\nChanging mods and lock keys\n"); 308 usb_log_debug2("\nmods before: 0x%x\n", kbd_dev->mods); 309 usb_log_debug2("\nLock keys before:0x%x\n\n", kbd_dev->lock_keys); 310 311 if (type == KEY_PRESS) { 312 usb_log_debug2("\nKey pressed.\n"); 313 /* 314 * Only change lock state on transition from released 315 * to pressed. This prevents autorepeat from messing 316 * up the lock state. 317 */ 318 kbd_dev->mods = 319 kbd_dev->mods ^ (mod_mask & ~kbd_dev->lock_keys); 320 kbd_dev->lock_keys = kbd_dev->lock_keys | mod_mask; 321 322 /* Update keyboard lock indicator lights. */ 323 usbkbd_set_led(kbd_dev); 324 } else { 325 usb_log_debug2("\nKey released.\n"); 326 kbd_dev->lock_keys = kbd_dev->lock_keys & ~mod_mask; 327 } 328 } 329 330 usb_log_debug2("\n\nmods after: 0x%x\n", kbd_dev->mods); 331 usb_log_debug2("\nLock keys after: 0x%x\n\n", kbd_dev->lock_keys); 332 333 if (type == KEY_PRESS && (kbd_dev->mods & KM_LCTRL) && key == KC_F1) { 334 active_layout = 0; 335 layout[active_layout]->reset(); 336 return; 337 } 338 339 if (type == KEY_PRESS && (kbd_dev->mods & KM_LCTRL) && key == KC_F2) { 340 active_layout = 1; 341 layout[active_layout]->reset(); 342 return; 343 } 344 345 if (type == KEY_PRESS && (kbd_dev->mods & KM_LCTRL) && key == KC_F3) { 346 active_layout = 2; 347 layout[active_layout]->reset(); 348 return; 349 } 350 351 ev.type = type; 352 ev.key = key; 353 ev.mods = kbd_dev->mods; 354 355 if (ev.mods & KM_NUM_LOCK) { 356 usb_log_debug("\n\nNum Lock turned on.\n\n"); 357 } 358 359 ev.c = layout[active_layout]->parse_ev(&ev); 360 361 usb_log_debug2("Sending key %d to the console\n", ev.key); 362 assert(console_callback_phone != -1); 363 async_msg_4(console_callback_phone, KBD_EVENT, ev.type, ev.key, 364 ev.mods, ev.c); 365 } 366 /* 367 * End of copy-paste 368 */ 369 370 /* 371 * TODO: 372 * 1) key press / key release - how does the keyboard notify about 373 * release? 374 * 2) layouts (use the already defined), not important now 375 * 3) 376 */ 377 378 static const keycode_t usb_hid_modifiers_keycodes[USB_HID_MOD_COUNT] = { 379 KC_LCTRL, /* USB_HID_MOD_LCTRL */ 380 KC_LSHIFT, /* USB_HID_MOD_LSHIFT */ 381 KC_LALT, /* USB_HID_MOD_LALT */ 382 0, /* USB_HID_MOD_LGUI */ 383 KC_RCTRL, /* USB_HID_MOD_RCTRL */ 384 KC_RSHIFT, /* USB_HID_MOD_RSHIFT */ 385 KC_RALT, /* USB_HID_MOD_RALT */ 386 0, /* USB_HID_MOD_RGUI */ 387 }; 388 389 static void usbkbd_check_modifier_changes(usb_hid_dev_kbd_t *kbd_dev, 390 uint8_t modifiers) 391 { 392 /* 393 * TODO: why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK 394 * both as modifiers and as keys with their own scancodes??? 395 * 396 * modifiers should be sent as normal keys to usbkbd_parse_scancode()!! 397 * so maybe it would be better if I received it from report parser in 398 * that way 399 */ 400 401 int i; 402 for (i = 0; i < USB_HID_MOD_COUNT; ++i) { 403 if ((modifiers & usb_hid_modifiers_consts[i]) && 404 !(kbd_dev->modifiers & usb_hid_modifiers_consts[i])) { 405 // modifier pressed 406 if (usb_hid_modifiers_keycodes[i] != 0) { 407 kbd_push_ev(KEY_PRESS, 408 usb_hid_modifiers_keycodes[i], kbd_dev); 409 } 410 } else if (!(modifiers & usb_hid_modifiers_consts[i]) && 411 (kbd_dev->modifiers & usb_hid_modifiers_consts[i])) { 412 // modifier released 413 if (usb_hid_modifiers_keycodes[i] != 0) { 414 kbd_push_ev(KEY_RELEASE, 415 usb_hid_modifiers_keycodes[i], kbd_dev); 416 } 417 } // no change 418 } 419 420 kbd_dev->modifiers = modifiers; 421 } 422 423 static void usbkbd_check_key_changes(usb_hid_dev_kbd_t *kbd_dev, 424 const uint8_t *key_codes) 425 { 426 // TODO: phantom state!! 427 428 unsigned int key; 429 unsigned int i, j; 430 431 // TODO: quite dummy right now, think of better implementation 432 433 // key releases 434 for (j = 0; j < kbd_dev->keycode_count; ++j) { 435 // try to find the old key in the new key list 436 i = 0; 437 while (i < kbd_dev->keycode_count 438 && key_codes[i] != kbd_dev->keycodes[j]) { 439 ++i; 440 } 441 442 if (i == kbd_dev->keycode_count) { 443 // not found, i.e. the key was released 444 key = usbkbd_parse_scancode(kbd_dev->keycodes[j]); 445 kbd_push_ev(KEY_RELEASE, key, kbd_dev); 446 usb_log_debug2("\nKey released: %d\n", key); 447 } else { 448 // found, nothing happens 449 } 450 } 451 452 // key presses 453 for (i = 0; i < kbd_dev->keycode_count; ++i) { 454 // try to find the new key in the old key list 455 j = 0; 456 while (j < kbd_dev->keycode_count 457 && kbd_dev->keycodes[j] != key_codes[i]) { 458 ++j; 459 } 460 461 if (j == kbd_dev->keycode_count) { 462 // not found, i.e. new key pressed 463 key = usbkbd_parse_scancode(key_codes[i]); 464 usb_log_debug2("\nKey pressed: %d (keycode: %d)\n", key, 465 key_codes[i]); 466 kbd_push_ev(KEY_PRESS, key, kbd_dev); 467 } else { 468 // found, nothing happens 469 } 470 } 471 472 memcpy(kbd_dev->keycodes, key_codes, kbd_dev->keycode_count); 473 474 usb_log_debug2("\nNew stored keycodes: "); 475 for (i = 0; i < kbd_dev->keycode_count; ++i) { 476 usb_log_debug2("%d ", kbd_dev->keycodes[i]); 477 } 478 } 479 480 /* 481 * Callbacks for parser 482 */ 483 static void usbkbd_process_keycodes(const uint8_t *key_codes, size_t count, 484 uint8_t modifiers, void *arg) 485 { 486 if (arg == NULL) { 487 usb_log_warning("Missing argument in callback " 488 "usbkbd_process_keycodes().\n"); 489 return; 490 } 491 492 usb_log_debug2("Got keys from parser: "); 493 unsigned i; 494 for (i = 0; i < count; ++i) { 495 usb_log_debug2("%d ", key_codes[i]); 496 } 497 usb_log_debug2("\n"); 498 499 usb_hid_dev_kbd_t *kbd_dev = (usb_hid_dev_kbd_t *)arg; 500 501 if (count != kbd_dev->keycode_count) { 502 usb_log_warning("Number of received keycodes (%d) differs from" 503 " expected number (%d).\n", count, kbd_dev->keycode_count); 504 return; 505 } 506 507 usbkbd_check_modifier_changes(kbd_dev, modifiers); 508 usbkbd_check_key_changes(kbd_dev, key_codes); 509 } 510 511 /* 512 * Kbd functions 513 */ 514 //static int usbkbd_get_report_descriptor(usb_hid_dev_kbd_t *kbd_dev) 515 //{ 516 // // iterate over all configurations and interfaces 517 // // TODO: more configurations!! 518 // unsigned i; 519 // for (i = 0; i < kbd_dev->conf->config_descriptor.interface_count; ++i) { 520 // // TODO: endianness 521 // uint16_t length = kbd_dev->conf->interfaces[i].hid_desc. 522 // report_desc_info.length; 523 // size_t actual_size = 0; 524 525 // // allocate space for the report descriptor 526 // kbd_dev->conf->interfaces[i].report_desc = 527 // (uint8_t *)malloc(length); 528 529 // // get the descriptor from the device 530 // int rc = usb_request_get_descriptor(&kbd_dev->ctrl_pipe, 531 // USB_REQUEST_TYPE_CLASS, USB_DESCTYPE_HID_REPORT, 532 // i, 0, 533 // kbd_dev->conf->interfaces[i].report_desc, length, 534 // &actual_size); 535 536 // if (rc != EOK) { 537 // return rc; 538 // } 539 540 // assert(actual_size == length); 541 542 // //dump_hid_class_descriptor(0, USB_DESCTYPE_HID_REPORT, 543 // // kbd_dev->conf->interfaces[i].report_desc, length); 544 // } 545 546 // return EOK; 547 //} 548 549 static int usbkbd_get_report_descriptor(usb_hid_dev_kbd_t *kbd_dev, 550 uint8_t *config_desc, size_t config_desc_size, uint8_t *iface_desc) 551 { 552 assert(kbd_dev != NULL); 553 assert(config_desc != NULL); 554 assert(config_desc_size != 0); 555 assert(iface_desc != NULL); 556 557 usb_dp_parser_t parser = { 558 .nesting = usb_dp_standard_descriptor_nesting 559 }; 560 561 usb_dp_parser_data_t parser_data = { 562 .data = config_desc, 563 .size = config_desc_size, 564 .arg = NULL 565 }; 566 567 /* 568 * First nested descriptor of interface descriptor. 569 */ 570 uint8_t *d = 571 usb_dp_get_nested_descriptor(&parser, &parser_data, iface_desc); 572 573 /* 574 * Search through siblings until the HID descriptor is found. 575 */ 576 while (d != NULL && *(d + 1) != USB_DESCTYPE_HID) { 577 d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 578 iface_desc, d); 579 } 580 581 if (d == NULL) { 582 usb_log_fatal("No HID descriptor found!\n"); 583 return ENOENT; 584 } 585 586 if (*d != sizeof(usb_standard_hid_descriptor_t)) { 587 usb_log_fatal("HID descriptor hass wrong size (%u, expected %u" 588 ")\n", *d, sizeof(usb_standard_hid_descriptor_t)); 589 return EINVAL; 590 } 591 592 usb_standard_hid_descriptor_t *hid_desc = 593 (usb_standard_hid_descriptor_t *)d; 594 595 uint16_t length = hid_desc->report_desc_info.length; 596 size_t actual_size = 0; 597 598 /* 599 * Allocate space for the report descriptor. 600 */ 601 kbd_dev->report_desc = (uint8_t *)malloc(length); 602 if (kbd_dev->report_desc == NULL) { 603 usb_log_fatal("Failed to allocate space for Report descriptor." 604 "\n"); 605 return ENOMEM; 606 } 607 608 usb_log_debug("Getting Report descriptor, expected size: %u\n", length); 609 610 /* 611 * Get the descriptor from the device. 612 */ 613 int rc = usb_request_get_descriptor(&kbd_dev->ctrl_pipe, 614 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE, 615 USB_DESCTYPE_HID_REPORT, 0, 616 kbd_dev->iface, kbd_dev->report_desc, length, &actual_size); 617 618 if (rc != EOK) { 619 return rc; 620 } 621 622 if (actual_size != length) { 623 free(kbd_dev->report_desc); 624 kbd_dev->report_desc = NULL; 625 usb_log_fatal("Report descriptor has wrong size (%u, expected " 626 "%u)\n", actual_size, length); 627 return EINVAL; 628 } 629 630 usb_log_debug("Done.\n"); 631 632 return EOK; 633 } 634 635 static int usbkbd_process_descriptors(usb_hid_dev_kbd_t *kbd_dev) 636 { 637 // get the first configuration descriptor (TODO: parse also other!) 638 usb_standard_configuration_descriptor_t config_desc; 639 640 int rc; 641 rc = usb_request_get_bare_configuration_descriptor(&kbd_dev->ctrl_pipe, 642 0, &config_desc); 643 644 if (rc != EOK) { 645 return rc; 646 } 647 648 // prepare space for all underlying descriptors 649 uint8_t *descriptors = (uint8_t *)malloc(config_desc.total_length); 650 if (descriptors == NULL) { 651 return ENOMEM; 652 } 653 654 size_t transferred = 0; 655 // get full configuration descriptor 656 rc = usb_request_get_full_configuration_descriptor(&kbd_dev->ctrl_pipe, 657 0, descriptors, 658 config_desc.total_length, &transferred); 659 660 if (rc != EOK) { 661 return rc; 662 } 663 if (transferred != config_desc.total_length) { 664 return ELIMIT; 665 } 666 667 /* 668 * Initialize the interrupt in endpoint. 669 */ 670 usb_endpoint_mapping_t endpoint_mapping[1] = { 671 { 672 .pipe = &kbd_dev->poll_pipe, 673 .description = &poll_endpoint_description, 674 .interface_no = 675 usb_device_get_assigned_interface(kbd_dev->device) 676 } 677 }; 678 rc = usb_endpoint_pipe_initialize_from_configuration( 679 endpoint_mapping, 1, 680 descriptors, config_desc.total_length, 681 &kbd_dev->wire); 682 683 if (rc != EOK) { 684 usb_log_error("Failed to initialize poll pipe: %s.\n", 685 str_error(rc)); 686 free(descriptors); 687 return rc; 688 } 689 690 if (!endpoint_mapping[0].present) { 691 usb_log_warning("Not accepting device, " \ 692 "not boot-protocol keyboard.\n"); 693 free(descriptors); 59 694 return EREFUSED; 60 695 } 61 696 697 usb_log_debug("Accepted device. Saving interface, and getting Report" 698 " descriptor.\n"); 699 700 /* 701 * Save assigned interface number. 702 */ 703 if (endpoint_mapping[0].interface_no < 0) { 704 usb_log_error("Bad interface number.\n"); 705 free(descriptors); 706 return EINVAL; 707 } 708 709 kbd_dev->iface = endpoint_mapping[0].interface_no; 710 711 assert(endpoint_mapping[0].interface != NULL); 712 713 rc = usbkbd_get_report_descriptor(kbd_dev, descriptors, transferred, 714 (uint8_t *)endpoint_mapping[0].interface); 715 716 free(descriptors); 717 718 if (rc != EOK) { 719 usb_log_warning("Problem with parsing REPORT descriptor.\n"); 720 return rc; 721 } 722 723 usb_log_debug("Done parsing descriptors.\n"); 724 62 725 return EOK; 63 726 } 64 727 65 /*----------------------------------------------------------------------------*/ 728 static usb_hid_dev_kbd_t *usbkbd_init_device(ddf_dev_t *dev) 729 { 730 int rc; 731 732 usb_hid_dev_kbd_t *kbd_dev = (usb_hid_dev_kbd_t *)calloc(1, 733 sizeof(usb_hid_dev_kbd_t)); 734 735 if (kbd_dev == NULL) { 736 usb_log_fatal("No memory!\n"); 737 return NULL; 738 } 739 740 kbd_dev->device = dev; 741 742 /* 743 * Initialize the backing connection to the host controller. 744 */ 745 rc = usb_device_connection_initialize_from_device(&kbd_dev->wire, dev); 746 if (rc != EOK) { 747 printf("Problem initializing connection to device: %s.\n", 748 str_error(rc)); 749 goto error_leave; 750 } 751 752 /* 753 * Initialize device pipes. 754 */ 755 rc = usb_endpoint_pipe_initialize_default_control(&kbd_dev->ctrl_pipe, 756 &kbd_dev->wire); 757 if (rc != EOK) { 758 printf("Failed to initialize default control pipe: %s.\n", 759 str_error(rc)); 760 goto error_leave; 761 } 762 763 /* 764 * Get descriptors, parse descriptors and save endpoints. 765 */ 766 usb_endpoint_pipe_start_session(&kbd_dev->ctrl_pipe); 767 768 rc = usbkbd_process_descriptors(kbd_dev); 769 770 usb_endpoint_pipe_end_session(&kbd_dev->ctrl_pipe); 771 if (rc != EOK) { 772 goto error_leave; 773 } 774 775 // save the size of the report (boot protocol report by default) 776 kbd_dev->keycode_count = BOOTP_REPORT_SIZE; 777 kbd_dev->keycodes = (uint8_t *)calloc( 778 kbd_dev->keycode_count, sizeof(uint8_t)); 779 780 if (kbd_dev->keycodes == NULL) { 781 usb_log_fatal("No memory!\n"); 782 goto error_leave; 783 } 784 785 kbd_dev->modifiers = 0; 786 kbd_dev->mods = DEFAULT_ACTIVE_MODS; 787 kbd_dev->lock_keys = 0; 788 789 // set boot protocol 790 usbkbd_req_set_protocol(kbd_dev, USB_HID_PROTOCOL_BOOT); 791 792 // set LEDs according to internal setup (NUM LOCK enabled) 793 usbkbd_set_led(kbd_dev); 794 795 return kbd_dev; 796 797 error_leave: 798 free(kbd_dev); 799 return NULL; 800 } 801 802 static void usbkbd_process_interrupt_in(usb_hid_dev_kbd_t *kbd_dev, 803 uint8_t *buffer, size_t actual_size) 804 { 805 usb_hid_report_in_callbacks_t *callbacks = 806 (usb_hid_report_in_callbacks_t *)malloc( 807 sizeof(usb_hid_report_in_callbacks_t)); 808 callbacks->keyboard = usbkbd_process_keycodes; 809 810 //usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, callbacks, 811 // NULL); 812 /*usb_log_debug2("Calling usb_hid_boot_keyboard_input_report() with size" 813 " %zu\n", actual_size);*/ 814 //dump_buffer("bufffer: ", buffer, actual_size); 815 int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size, 816 callbacks, kbd_dev); 817 818 if (rc != EOK) { 819 usb_log_warning("Error in usb_hid_boot_keyboard_input_report():" 820 "%s\n", str_error(rc)); 821 } 822 } 823 824 static void usbkbd_poll_keyboard(usb_hid_dev_kbd_t *kbd_dev) 825 { 826 int rc, sess_rc; 827 uint8_t buffer[BUFFER_SIZE]; 828 size_t actual_size; 829 830 usb_log_info("Polling keyboard...\n"); 831 832 while (true) { 833 async_usleep(1000 * 10); 834 835 sess_rc = usb_endpoint_pipe_start_session(&kbd_dev->poll_pipe); 836 if (sess_rc != EOK) { 837 usb_log_warning("Failed to start a session: %s.\n", 838 str_error(sess_rc)); 839 continue; 840 } 841 842 rc = usb_endpoint_pipe_read(&kbd_dev->poll_pipe, buffer, 843 BUFFER_SIZE, &actual_size); 844 sess_rc = usb_endpoint_pipe_end_session(&kbd_dev->poll_pipe); 845 846 if (rc != EOK) { 847 usb_log_warning("Error polling the keyboard: %s.\n", 848 str_error(rc)); 849 continue; 850 } 851 852 if (sess_rc != EOK) { 853 usb_log_warning("Error closing session: %s.\n", 854 str_error(sess_rc)); 855 continue; 856 } 857 858 /* 859 * If the keyboard answered with NAK, it returned no data. 860 * This implies that no change happened since last query. 861 */ 862 if (actual_size == 0) { 863 usb_log_debug("Keyboard returned NAK\n"); 864 continue; 865 } 866 867 /* 868 * TODO: Process pressed keys. 869 */ 870 usb_log_debug("Calling usbkbd_process_interrupt_in()\n"); 871 usbkbd_process_interrupt_in(kbd_dev, buffer, actual_size); 872 } 873 874 // not reached 875 assert(0); 876 } 877 878 static int usbkbd_fibril_device(void *arg) 879 { 880 if (arg == NULL) { 881 usb_log_error("No device!\n"); 882 return -1; 883 } 884 885 usb_hid_dev_kbd_t *kbd_dev = (usb_hid_dev_kbd_t *)arg; 886 887 usbkbd_poll_keyboard(kbd_dev); 888 889 return EOK; 890 } 891 892 static int usbkbd_add_device(ddf_dev_t *dev) 893 { 894 /* 895 * Create default function. 896 */ 897 // FIXME - check for errors 898 ddf_fun_t *kbd_fun = ddf_fun_create(dev, fun_exposed, "keyboard"); 899 assert(kbd_fun != NULL); 900 kbd_fun->ops = &keyboard_ops; 901 902 int rc = ddf_fun_bind(kbd_fun); 903 assert(rc == EOK); 904 rc = ddf_fun_add_to_class(kbd_fun, "keyboard"); 905 assert(rc == EOK); 906 907 /* 908 * Initialize device (get and process descriptors, get address, etc.) 909 */ 910 usb_hid_dev_kbd_t *kbd_dev = usbkbd_init_device(dev); 911 if (kbd_dev == NULL) { 912 usb_log_error("Error while initializing device.\n"); 913 return -1; 914 } 915 916 usb_log_info("Device initialized.\n"); 917 918 /* 919 * Create new fibril for handling this keyboard 920 */ 921 fid_t fid = fibril_create(usbkbd_fibril_device, kbd_dev); 922 if (fid == 0) { 923 usb_log_error("Failed to start fibril for HID device\n"); 924 return ENOMEM; 925 } 926 fibril_add_ready(fid); 927 928 //dev->ops = &keyboard_ops; 929 (void)keyboard_ops; 930 931 //add_device_to_class(dev, "keyboard"); 932 933 /* 934 * Hurrah, device is initialized. 935 */ 936 return EOK; 937 } 66 938 67 939 static driver_ops_t kbd_driver_ops = { 68 .add_device = usb hid_add_device,940 .add_device = usbkbd_add_device, 69 941 }; 70 71 /*----------------------------------------------------------------------------*/72 942 73 943 static driver_t kbd_driver = { … … 76 946 }; 77 947 78 /*----------------------------------------------------------------------------*/79 80 948 int main(int argc, char *argv[]) 81 949 {
Note:
See TracChangeset
for help on using the changeset viewer.