Changes in / [59e01689:e93e319] in mainline
- Location:
- uspace
- Files:
-
- 1 deleted
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhid/hiddev.c
r59e01689 re93e319 158 158 } 159 159 160 hid_dev->report_desc_size = length;161 162 160 usb_log_debug("Done.\n"); 163 161 … … 264 262 265 263 if (rc != EOK) { 266 usb_log_warning("Problem with getting Report descriptor: %s.\n",264 usb_log_warning("Problem with parsing Report descriptor: %s.\n", 267 265 str_error(rc)); 268 266 return rc; 269 267 } 270 271 rc = usb_hid_parse_report_descriptor(hid_dev->parser,272 hid_dev->report_desc, hid_dev->report_desc_size);273 if (rc != EOK) {274 usb_log_warning("Problem parsing Report descriptor: %s.\n",275 str_error(rc));276 return rc;277 }278 279 usb_hid_descriptor_print(hid_dev->parser);280 268 281 269 return EOK; … … 301 289 302 290 memset(dev, 0, sizeof(usbhid_dev_t)); 303 304 dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(305 usb_hid_report_parser_t)));306 if (dev->parser == NULL) {307 usb_log_fatal("No memory!\n");308 free(dev);309 return NULL;310 }311 291 312 292 dev->initialized = 0; … … 419 399 420 400 /* 421 * Initialize the report parser.422 */423 rc = usb_hid_parser_init(hid_dev->parser);424 if (rc != EOK) {425 usb_log_error("Failed to initialize report parser.\n");426 return rc;427 }428 429 /*430 401 * Get descriptors, parse descriptors and save endpoints. 431 402 */ … … 440 411 if (rc != EOK) { 441 412 /* TODO: end session?? */ 442 usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);443 413 usb_log_error("Failed to process descriptors: %s.\n", 444 414 str_error(rc)); -
uspace/drv/usbhid/hiddev.h
r59e01689 re93e319 32 32 /** @file 33 33 * Generic USB HID device structure and API. 34 *35 * @todo Add function for parsing report - this is generic HID function, not36 * keyboard-specific, as the report parser is also generic.37 * @todo Add function for polling as that is also a generic HID process.38 * @todo Add interrupt in pipe to the structure.39 34 */ 40 35 … … 80 75 /** Report descriptor. */ 81 76 uint8_t *report_desc; 82 83 size_t report_desc_size;84 85 77 /** HID Report parser. */ 86 78 usb_hid_report_parser_t *parser; -
uspace/drv/usbhid/kbddev.c
r59e01689 re93e319 51 51 #include <usb/classes/hidparser.h> 52 52 #include <usb/classes/classes.h> 53 #include <usb/classes/hidut.h>54 53 55 54 #include "kbddev.h" … … 94 93 .flags = 0 95 94 }; 96 97 typedef enum usbhid_kbd_flags {98 USBHID_KBD_STATUS_UNINITIALIZED = 0,99 USBHID_KBD_STATUS_INITIALIZED = 1,100 USBHID_KBD_STATUS_TO_DESTROY = -1101 } usbhid_kbd_flags;102 95 103 96 /*----------------------------------------------------------------------------*/ … … 131 124 }; 132 125 133 typedef enum usbhid_lock_code {134 USBHID_LOCK_NUM = 0x53,135 USBHID_LOCK_CAPS = 0x39,136 USBHID_LOCK_SCROLL = 0x47,137 USBHID_LOCK_COUNT = 3138 } usbhid_lock_code;139 140 static const usbhid_lock_code usbhid_lock_codes[USBHID_LOCK_COUNT] = {141 USBHID_LOCK_NUM,142 USBHID_LOCK_CAPS,143 USBHID_LOCK_SCROLL144 };145 146 126 /*----------------------------------------------------------------------------*/ 147 127 /* IPC method handler */ … … 238 218 239 219 assert(kbd_dev->hid_dev != NULL); 240 assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);220 assert(kbd_dev->hid_dev->initialized); 241 221 usbhid_req_set_report(kbd_dev->hid_dev, USB_HID_REPORT_TYPE_OUTPUT, 242 222 buffer, BOOTP_BUFFER_OUT_SIZE); … … 366 346 * @sa usbhid_kbd_push_ev() 367 347 */ 368 //static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev, 369 // const uint8_t *key_codes, size_t count) 370 //{ 371 // /* 372 // * TODO: why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK 373 // * both as modifiers and as keyUSB_HID_LOCK_COUNTs with their own scancodes??? 374 // * 375 // * modifiers should be sent as normal keys to usbhid_parse_scancode()!! 376 // * so maybe it would be better if I received it from report parser in 377 // * that way 378 // */ 379 380 // int i; 381 // for (i = 0; i < count; ++i) { 382 // if ((modifiers & usb_hid_modifiers_consts[i]) && 383 // !(kbd_dev->modifiers & usb_hid_modifiers_consts[i])) { 384 // // modifier pressed 385 // if (usbhid_modifiers_keycodes[i] != 0) { 386 // usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, 387 // usbhid_modifiers_keycodes[i]); 388 // } 389 // } else if (!(modifiers & usb_hid_modifiers_consts[i]) && 390 // (kbd_dev->modifiers & usb_hid_modifiers_consts[i])) { 391 // // modifier released 392 // if (usbhid_modifiers_keycodes[i] != 0) { 393 // usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, 394 // usbhid_modifiers_keycodes[i]); 395 // } 396 // } // no change 397 // } 398 399 // kbd_dev->modifiers = modifiers; 400 //} 401 402 /*----------------------------------------------------------------------------*/ 403 404 static inline int usbhid_kbd_is_lock(unsigned int key_code) 405 { 406 return (key_code == KC_NUM_LOCK 407 || key_code == KC_SCROLL_LOCK 408 || key_code == KC_CAPS_LOCK); 348 static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev, 349 uint8_t modifiers) 350 { 351 /* 352 * TODO: why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK 353 * both as modifiers and as keys with their own scancodes??? 354 * 355 * modifiers should be sent as normal keys to usbhid_parse_scancode()!! 356 * so maybe it would be better if I received it from report parser in 357 * that way 358 */ 359 360 int i; 361 for (i = 0; i < USB_HID_MOD_COUNT; ++i) { 362 if ((modifiers & usb_hid_modifiers_consts[i]) && 363 !(kbd_dev->modifiers & usb_hid_modifiers_consts[i])) { 364 // modifier pressed 365 if (usbhid_modifiers_keycodes[i] != 0) { 366 usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, 367 usbhid_modifiers_keycodes[i]); 368 } 369 } else if (!(modifiers & usb_hid_modifiers_consts[i]) && 370 (kbd_dev->modifiers & usb_hid_modifiers_consts[i])) { 371 // modifier released 372 if (usbhid_modifiers_keycodes[i] != 0) { 373 usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, 374 usbhid_modifiers_keycodes[i]); 375 } 376 } // no change 377 } 378 379 kbd_dev->modifiers = modifiers; 409 380 } 410 381 … … 433 404 /* 434 405 * First of all, check if the kbd have reported phantom state. 435 *436 * TODO: this must be changed as we don't know which keys are modifiers437 * and which are regular keys.438 406 */ 439 407 i = 0; … … 466 434 // not found, i.e. the key was released 467 435 key = usbhid_parse_scancode(kbd_dev->keys[j]); 468 if (!usbhid_kbd_is_lock(key)) { 469 usbhid_kbd_repeat_stop(kbd_dev, key); 470 } 436 usbhid_kbd_repeat_stop(kbd_dev, key); 471 437 usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key); 472 438 usb_log_debug2("Key released: %d\n", key); … … 492 458 key_codes[i]); 493 459 usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key); 494 if (!usbhid_kbd_is_lock(key)) { 495 usbhid_kbd_repeat_start(kbd_dev, key); 496 } 460 usbhid_kbd_repeat_start(kbd_dev, key); 497 461 } else { 498 462 // found, nothing happens … … 538 502 539 503 usb_log_debug("Got keys from parser: %s\n", 540 usb_debug_str_buffer(key_codes, count, 0));504 usb_debug_str_buffer(key_codes, kbd_dev->key_count, 0)); 541 505 542 506 if (count != kbd_dev->key_count) { … … 546 510 } 547 511 548 ///usbhid_kbd_check_modifier_changes(kbd_dev, key_codes, count);512 usbhid_kbd_check_modifier_changes(kbd_dev, modifiers); 549 513 usbhid_kbd_check_key_changes(kbd_dev, key_codes, count); 550 514 } … … 571 535 uint8_t *buffer, size_t actual_size) 572 536 { 573 assert(kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);574 assert(kbd_dev->hid_dev->parser != NULL);575 576 537 usb_hid_report_in_callbacks_t *callbacks = 577 538 (usb_hid_report_in_callbacks_t *)malloc( … … 580 541 callbacks->keyboard = usbhid_kbd_process_keycodes; 581 542 582 usb_log_debug("Calling usb_hid_ parse_report() with "543 usb_log_debug("Calling usb_hid_boot_keyboard_input_report() with " 583 544 "buffer %s\n", usb_debug_str_buffer(buffer, actual_size, 0)); 584 545 585 // int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size, 586 // callbacks, kbd_dev); 587 int rc = usb_hid_parse_report(kbd_dev->hid_dev->parser, buffer, 588 actual_size, callbacks, kbd_dev); 546 int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size, 547 callbacks, kbd_dev); 589 548 590 549 if (rc != EOK) { … … 625 584 626 585 kbd_dev->console_phone = -1; 627 kbd_dev->initialized = USBHID_KBD_STATUS_UNINITIALIZED;586 kbd_dev->initialized = 0; 628 587 629 588 return kbd_dev; … … 631 590 632 591 /*----------------------------------------------------------------------------*/ 633 634 static void usbhid_kbd_mark_unusable(usbhid_kbd_t *kbd_dev) 635 { 636 kbd_dev->initialized = USBHID_KBD_STATUS_TO_DESTROY; 592 /** 593 * Properly destroys the USB/HID keyboard structure. 594 * 595 * @param kbd_dev Pointer to the structure to be destroyed. 596 */ 597 static void usbhid_kbd_free(usbhid_kbd_t **kbd_dev) 598 { 599 if (kbd_dev == NULL || *kbd_dev == NULL) { 600 return; 601 } 602 603 // hangup phone to the console 604 async_hangup((*kbd_dev)->console_phone); 605 606 if ((*kbd_dev)->hid_dev != NULL) { 607 usbhid_dev_free(&(*kbd_dev)->hid_dev); 608 assert((*kbd_dev)->hid_dev == NULL); 609 } 610 611 if ((*kbd_dev)->repeat_mtx != NULL) { 612 /* TODO: replace by some check and wait */ 613 assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx)); 614 free((*kbd_dev)->repeat_mtx); 615 } 616 617 free(*kbd_dev); 618 *kbd_dev = NULL; 637 619 } 638 620 … … 676 658 } 677 659 678 if (kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED) {660 if (kbd_dev->initialized) { 679 661 usb_log_warning("Keyboard structure already initialized.\n"); 680 662 return EINVAL; … … 689 671 } 690 672 691 assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);673 assert(kbd_dev->hid_dev->initialized); 692 674 693 675 // save the size of the report (boot protocol report by default) 694 // kbd_dev->key_count = BOOTP_REPORT_SIZE; 695 696 usb_hid_report_path_t path; 697 path.usage_page = USB_HIDUT_PAGE_KEYBOARD; 698 kbd_dev->key_count = usb_hid_report_input_length( 699 kbd_dev->hid_dev->parser, &path); 700 701 usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count); 702 676 kbd_dev->key_count = BOOTP_REPORT_SIZE; 703 677 kbd_dev->keys = (uint8_t *)calloc( 704 678 kbd_dev->key_count, sizeof(uint8_t)); … … 735 709 assert(kbd_dev->hid_dev != NULL); 736 710 assert(kbd_dev->hid_dev->initialized); 737 //usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);711 usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT); 738 712 739 713 usbhid_kbd_set_led(kbd_dev); … … 741 715 usbhid_req_set_idle(kbd_dev->hid_dev, IDLE_RATE); 742 716 743 kbd_dev->initialized = USBHID_KBD_STATUS_INITIALIZED;717 kbd_dev->initialized = 1; 744 718 usb_log_info("HID/KBD device structure initialized.\n"); 745 719 … … 855 829 usbhid_kbd_poll(kbd_dev); 856 830 857 // as there is another fibril using this device, so we must leave the858 // structure to it, but mark it for destroying.859 usbhid_kbd_mark_unusable(kbd_dev);860 831 // at the end, properly destroy the KBD structure 861 //usbhid_kbd_free(&kbd_dev);862 //assert(kbd_dev == NULL);832 usbhid_kbd_free(&kbd_dev); 833 assert(kbd_dev == NULL); 863 834 864 835 return EOK; … … 982 953 } 983 954 984 /*----------------------------------------------------------------------------*/985 986 int usbhid_kbd_is_usable(const usbhid_kbd_t *kbd_dev)987 {988 return (kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);989 }990 991 /*----------------------------------------------------------------------------*/992 /**993 * Properly destroys the USB/HID keyboard structure.994 *995 * @param kbd_dev Pointer to the structure to be destroyed.996 */997 void usbhid_kbd_free(usbhid_kbd_t **kbd_dev)998 {999 if (kbd_dev == NULL || *kbd_dev == NULL) {1000 return;1001 }1002 1003 // hangup phone to the console1004 async_hangup((*kbd_dev)->console_phone);1005 1006 if ((*kbd_dev)->hid_dev != NULL) {1007 usbhid_dev_free(&(*kbd_dev)->hid_dev);1008 assert((*kbd_dev)->hid_dev == NULL);1009 }1010 1011 if ((*kbd_dev)->repeat_mtx != NULL) {1012 /* TODO: replace by some check and wait */1013 assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));1014 free((*kbd_dev)->repeat_mtx);1015 }1016 1017 free(*kbd_dev);1018 *kbd_dev = NULL;1019 }1020 1021 955 /** 1022 956 * @} -
uspace/drv/usbhid/kbddev.h
r59e01689 re93e319 42 42 43 43 #include <usb/classes/hid.h> 44 #include <usb/classes/hidparser.h>45 44 #include <ddf/driver.h> 46 45 #include <usb/pipes.h> … … 101 100 fibril_mutex_t *repeat_mtx; 102 101 103 /** State of the structure (for checking before use). 104 * 105 * 0 - not initialized 106 * 1 - initialized 107 * -1 - ready for destroying 108 */ 102 /** State of the structure (for checking before use). */ 109 103 int initialized; 110 104 } usbhid_kbd_t; … … 113 107 114 108 int usbhid_kbd_try_add_device(ddf_dev_t *dev); 115 116 int usbhid_kbd_is_usable(const usbhid_kbd_t *kbd_dev);117 118 void usbhid_kbd_free(usbhid_kbd_t **kbd_dev);119 109 120 110 void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key); -
uspace/drv/usbhid/kbdrepeat.c
r59e01689 re93e319 77 77 78 78 while (true) { 79 // check if the kbd structure is usable80 if (!usbhid_kbd_is_usable(kbd)) {81 usbhid_kbd_free(&kbd);82 assert(kbd == NULL);83 return;84 }85 86 79 fibril_mutex_lock(kbd->repeat_mtx); 87 80 -
uspace/drv/usbmouse/init.c
r59e01689 re93e319 124 124 goto leave; 125 125 } 126 127 /* Open the control pipe. */128 rc = usb_endpoint_pipe_start_session(&dev->ctrl_pipe);129 if (rc != EOK) {130 goto leave;131 }132 133 /* Set the boot protocol. */134 rc = usb_control_request_set(&dev->ctrl_pipe,135 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,136 USB_HIDREQ_SET_PROTOCOL, USB_HID_PROTOCOL_BOOT, dev->interface_no,137 NULL, 0);138 if (rc != EOK) {139 goto leave;140 }141 142 /* Close the control pipe (ignore errors). */143 usb_endpoint_pipe_end_session(&dev->ctrl_pipe);144 145 126 146 127 /* Everything allright. */ -
uspace/lib/usb/include/usb/classes/hidparser.h
r59e01689 re93e319 37 37 38 38 #include <stdint.h> 39 #include <adt/list.h>40 #include <usb/classes/hid_report_items.h>41 42 /**43 * Item prefix44 */45 #define USB_HID_ITEM_SIZE(data) ((uint8_t)(data & 0x3))46 #define USB_HID_ITEM_TAG(data) ((uint8_t)((data & 0xF0) >> 4))47 #define USB_HID_ITEM_TAG_CLASS(data) ((uint8_t)((data & 0xC) >> 2))48 #define USB_HID_ITEM_IS_LONG(data) (data == 0xFE)49 50 51 /**52 * Input/Output/Feature Item flags53 */54 /** Constant (1) / Variable (0) */55 #define USB_HID_ITEM_FLAG_CONSTANT(flags) ((flags & 0x1) == 0x1)56 /** Variable (1) / Array (0) */57 #define USB_HID_ITEM_FLAG_VARIABLE(flags) ((flags & 0x2) == 0x2)58 /** Absolute / Relative*/59 #define USB_HID_ITEM_FLAG_RELATIVE(flags) ((flags & 0x4) == 0x4)60 /** Wrap / No Wrap */61 #define USB_HID_ITEM_FLAG_WRAP(flags) ((flags & 0x8) == 0x8)62 #define USB_HID_ITEM_FLAG_LINEAR(flags) ((flags & 0x10) == 0x10)63 #define USB_HID_ITEM_FLAG_PREFERRED(flags) ((flags & 0x20) == 0x20)64 #define USB_HID_ITEM_FLAG_POSITION(flags) ((flags & 0x40) == 0x40)65 #define USB_HID_ITEM_FLAG_VOLATILE(flags) ((flags & 0x80) == 0x80)66 #define USB_HID_ITEM_FLAG_BUFFERED(flags) ((flags & 0x100) == 0x100)67 68 69 /**70 * Description of path of usage pages and usages in report descriptor71 */72 typedef struct {73 int32_t usage_page;74 } usb_hid_report_path_t;75 39 76 40 /** … … 78 42 */ 79 43 typedef struct { 80 int32_t id;81 int32_t usage_page;82 int32_t usage;83 int32_t usage_minimum;84 int32_t usage_maximum;85 int32_t logical_minimum;86 int32_t logical_maximum;87 int32_t size;88 int32_t count;89 size_t offset;90 int32_t delimiter;91 44 92 int32_t unit_exponent; 93 int32_t unit; 45 uint8_t usage_min; 46 uint8_t usage_max; 47 uint8_t logical_min; 48 uint8_t logical_max; 49 uint8_t size; 50 uint8_t count; 51 uint8_t offset; 94 52 95 /*96 * some not yet used fields97 */98 int32_t string_index;99 int32_t string_minimum;100 int32_t string_maximum;101 int32_t designator_index;102 int32_t designator_minimum;103 int32_t designator_maximum;104 int32_t physical_minimum;105 int32_t physical_maximum;106 107 uint8_t item_flags;108 109 link_t link;110 53 } usb_hid_report_item_t; 111 54 112 55 113 56 /** HID report parser structure. */ 114 typedef struct { 115 link_t input; 116 link_t output; 117 link_t feature; 118 } usb_hid_report_parser_t; 119 57 typedef struct { 58 } usb_hid_report_parser_t; 120 59 121 60 … … 188 127 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size); 189 128 190 int usb_hid_parser_init(usb_hid_report_parser_t *parser);191 129 int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser, 192 130 const uint8_t *data, size_t size); … … 196 134 const usb_hid_report_in_callbacks_t *callbacks, void *arg); 197 135 198 int usb_hid_report_input_length(const usb_hid_report_parser_t *parser,199 const usb_hid_report_path_t *path);200 136 201 202 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser); 203 204 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser); 137 int usb_hid_free_report_parser(usb_hid_report_parser_t *parser); 205 138 206 139 #endif -
uspace/lib/usb/include/usb/devdrv.h
r59e01689 re93e319 47 47 */ 48 48 usb_endpoint_mapping_t *pipes; 49 /** Current interface.50 * Usually, drivers operate on single interface only.51 * This item contains the value of the interface or -1 for any.52 */53 int interface_no;54 49 /** Generic DDF device backing this one. */ 55 50 ddf_dev_t *ddf_dev; -
uspace/lib/usb/src/devdrv.c
r59e01689 re93e319 109 109 { 110 110 int rc; 111 dev->interface_no= usb_device_get_assigned_interface(dev->ddf_dev);111 int my_interface = usb_device_get_assigned_interface(dev->ddf_dev); 112 112 113 113 size_t pipe_count = count_other_pipes(drv); … … 134 134 135 135 dev->pipes[i].description = drv->endpoints[i]; 136 dev->pipes[i].interface_no = dev->interface_no;136 dev->pipes[i].interface_no = my_interface; 137 137 } 138 138 -
uspace/lib/usb/src/hidparser.c
r59e01689 re93e319 36 36 #include <errno.h> 37 37 #include <stdio.h> 38 #include <malloc.h>39 #include <mem.h>40 #include <usb/debug.h>41 42 #define USB_HID_NEW_REPORT_ITEM 143 #define USB_HID_NO_ACTION 244 #define USB_HID_UNKNOWN_TAG -9945 46 #define BAD_HACK_USAGE_PAGE 0x0747 48 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,49 usb_hid_report_item_t *report_item);50 int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,51 usb_hid_report_item_t *report_item);52 int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size,53 usb_hid_report_item_t *report_item);54 int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size,55 usb_hid_report_item_t *report_item);56 57 void usb_hid_descriptor_print_list(link_t *head);58 int usb_hid_report_reset_local_items();59 void usb_hid_free_report_list(link_t *head);60 int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size);61 inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset);62 int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j);63 int usb_pow(int a, int b);64 65 int usb_pow(int a, int b)66 {67 switch(b) {68 case 0:69 return 1;70 break;71 case 1:72 return a;73 break;74 default:75 return a * usb_pow(a, b-1);76 break;77 }78 }79 80 /**81 *82 */83 int usb_hid_parser_init(usb_hid_report_parser_t *parser)84 {85 if(parser == NULL) {86 return -1;87 }88 89 list_initialize(&(parser->input));90 list_initialize(&(parser->output));91 list_initialize(&(parser->feature));92 93 return EOK;94 }95 96 38 97 39 /** Parse HID report descriptor. … … 104 46 const uint8_t *data, size_t size) 105 47 { 106 size_t i=0; 107 uint8_t tag=0; 108 uint8_t item_size=0; 109 int class=0; 110 int ret; 111 usb_hid_report_item_t *report_item=0; 112 usb_hid_report_item_t *new_report_item; 48 return ENOTSUP; 49 } 113 50 114 size_t offset_input=0; 115 size_t offset_output=0; 116 size_t offset_feature=0; 51 /** Parse and act upon a HID report. 52 * 53 * @see usb_hid_parse_report_descriptor 54 * 55 * @param parser Opaque HID report parser structure. 56 * @param data Data for the report. 57 * @param callbacks Callbacks for report actions. 58 * @param arg Custom argument (passed through to the callbacks). 59 * @return Error code. 60 */ 61 int usb_hid_parse_report(const usb_hid_report_parser_t *parser, 62 const uint8_t *data, size_t size, 63 const usb_hid_report_in_callbacks_t *callbacks, void *arg) 64 { 65 int i; 117 66 118 119 if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){ 120 return ENOMEM; 121 } 122 memset(report_item, 0, sizeof(usb_hid_report_item_t)); 123 124 link_initialize(&(report_item->link)); 125 126 while(i<size){ 127 if(!USB_HID_ITEM_IS_LONG(data[i])){ 128 129 if((i+USB_HID_ITEM_SIZE(data[i]))>= size){ 130 return -1; // TODO ERROR CODE 131 } 132 133 tag = USB_HID_ITEM_TAG(data[i]); 134 item_size = USB_HID_ITEM_SIZE(data[i]); 135 class = USB_HID_ITEM_TAG_CLASS(data[i]); 136 137 usb_log_debug2( 138 "i(%u) data(%X) value(%X): TAG %u, class %u, size %u - ", i, 139 data[i], usb_hid_report_tag_data_int32(data+i+1,item_size), 140 tag, class, item_size); 141 142 ret = usb_hid_report_parse_tag(tag,class,data+i+1, 143 item_size,report_item); 144 usb_log_debug2("ret: %u\n", ret); 145 switch(ret){ 146 case USB_HID_NEW_REPORT_ITEM: 147 // store report item to report and create the new one 148 usb_log_debug("\nNEW REPORT ITEM: %X",tag); 149 150 switch(tag) { 151 case USB_HID_REPORT_TAG_INPUT: 152 report_item->offset = offset_input; 153 offset_input += report_item->count * report_item->size; 154 usb_log_debug(" - INPUT\n"); 155 list_append(&(report_item->link), &(parser->input)); 156 break; 157 case USB_HID_REPORT_TAG_OUTPUT: 158 report_item->offset = offset_output; 159 offset_output += report_item->count * report_item->size; 160 usb_log_debug(" - OUTPUT\n"); 161 list_append(&(report_item->link), &(parser->output)); 162 163 break; 164 case USB_HID_REPORT_TAG_FEATURE: 165 report_item->offset = offset_feature; 166 offset_feature += report_item->count * report_item->size; 167 usb_log_debug(" - FEATURE\n"); 168 list_append(&(report_item->link), &(parser->feature)); 169 break; 170 default: 171 usb_log_debug("\tjump over - tag %X\n", tag); 172 break; 173 } 174 175 /* clone current state table to the new item */ 176 if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) { 177 return ENOMEM; 178 } 179 memcpy(new_report_item,report_item, sizeof(usb_hid_report_item_t)); 180 /* reset local items */ 181 new_report_item->usage_minimum = 0; 182 new_report_item->usage_maximum = 0; 183 184 link_initialize(&(new_report_item->link)); 185 report_item = new_report_item; 186 187 break; 188 case USB_HID_REPORT_TAG_PUSH: 189 // push current state to stack 190 // not yet implemented 191 break; 192 case USB_HID_REPORT_TAG_POP: 193 // restore current state from stack 194 // not yet implemented 195 break; 196 197 default: 198 // nothing special to do 199 break; 200 } 201 202 /* jump over the processed block */ 203 i += 1 + USB_HID_ITEM_SIZE(data[i]); 204 } 205 else{ 206 // TBD 207 i += 3 + USB_HID_ITEM_SIZE(data[i+1]); 208 } 209 210 67 /* main parsing loop */ 68 while(0){ 211 69 } 212 70 71 72 uint8_t keys[6]; 73 74 for (i = 0; i < 6; ++i) { 75 keys[i] = data[i]; 76 } 77 78 callbacks->keyboard(keys, 6, 0, arg); 79 80 return EOK; 81 } 82 83 /** Free the HID report parser structure 84 * 85 * @param parser Opaque HID report parser structure 86 * @return Error code 87 */ 88 int usb_hid_free_report_parser(usb_hid_report_parser_t *parser) 89 { 90 213 91 return EOK; 214 92 } … … 238 116 item.size = 8; 239 117 item.count = 6; 240 item.usage_min imum= 0;241 item.usage_max imum= 255;242 item.logical_min imum= 0;243 item.logical_max imum= 255;118 item.usage_min = 0; 119 item.usage_max = 255; 120 item.logical_min = 0; 121 item.logical_max = 255; 244 122 245 123 if (size != 8) { 246 return -1; //ERANGE;124 return ERANGE; 247 125 } 248 126 … … 266 144 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size) 267 145 { 268 if (size !=1){146 if (size < 1){ 269 147 return -1; 270 148 } 271 149 272 /* used only first five bits, others are only padding*/ 273 *data = leds; 150 data[0] = leds; 274 151 return EOK; 275 152 } 276 153 277 154 /** 278 *279 * @param Tag to parse280 * @param Report descriptor buffer281 * @param Size of data belongs to this tag282 * @param Current report item structe283 * @return Code of action to be done next284 */285 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,286 usb_hid_report_item_t *report_item)287 {288 int ret;289 290 switch(class){291 case USB_HID_TAG_CLASS_MAIN:292 293 if((ret=usb_hid_report_parse_main_tag(tag,data,item_size,report_item)) == EOK) {294 return USB_HID_NEW_REPORT_ITEM;295 }296 else {297 /*TODO process the error */298 return ret;299 }300 break;301 302 case USB_HID_TAG_CLASS_GLOBAL:303 return usb_hid_report_parse_global_tag(tag,data,item_size,report_item);304 break;305 306 case USB_HID_TAG_CLASS_LOCAL:307 return usb_hid_report_parse_local_tag(tag,data,item_size,report_item);308 break;309 default:310 return USB_HID_NO_ACTION;311 }312 }313 314 /**315 * Parse main tags of report descriptor316 *317 * @param Tag identifier318 * @param Data buffer319 * @param Length of data buffer320 * @param Current state table321 * @return Error code322 */323 324 int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,325 usb_hid_report_item_t *report_item)326 {327 switch(tag)328 {329 case USB_HID_REPORT_TAG_INPUT:330 case USB_HID_REPORT_TAG_OUTPUT:331 case USB_HID_REPORT_TAG_FEATURE:332 report_item->item_flags = *data;333 return EOK;334 break;335 336 case USB_HID_REPORT_TAG_COLLECTION:337 // TODO338 return USB_HID_NO_ACTION;339 break;340 341 case USB_HID_REPORT_TAG_END_COLLECTION:342 /* should be ignored */343 return USB_HID_NO_ACTION;344 break;345 default:346 return USB_HID_NO_ACTION;347 }348 349 return EOK;350 }351 352 /**353 * Parse global tags of report descriptor354 *355 * @param Tag identifier356 * @param Data buffer357 * @param Length of data buffer358 * @param Current state table359 * @return Error code360 */361 362 int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size,363 usb_hid_report_item_t *report_item)364 {365 // TODO take care about the bit length of data366 switch(tag)367 {368 case USB_HID_REPORT_TAG_USAGE_PAGE:369 report_item->usage_page = usb_hid_report_tag_data_int32(data,item_size);370 break;371 case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:372 report_item->logical_minimum = usb_hid_report_tag_data_int32(data,item_size);373 break;374 case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM:375 report_item->logical_maximum = usb_hid_report_tag_data_int32(data,item_size);376 break;377 case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM:378 report_item->physical_minimum = usb_hid_report_tag_data_int32(data,item_size);379 break;380 case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM:381 report_item->physical_maximum = usb_hid_report_tag_data_int32(data,item_size);382 break;383 case USB_HID_REPORT_TAG_UNIT_EXPONENT:384 report_item->unit_exponent = usb_hid_report_tag_data_int32(data,item_size);385 break;386 case USB_HID_REPORT_TAG_UNIT:387 report_item->unit = usb_hid_report_tag_data_int32(data,item_size);388 break;389 case USB_HID_REPORT_TAG_REPORT_SIZE:390 report_item->size = usb_hid_report_tag_data_int32(data,item_size);391 break;392 case USB_HID_REPORT_TAG_REPORT_COUNT:393 report_item->count = usb_hid_report_tag_data_int32(data,item_size);394 break;395 case USB_HID_REPORT_TAG_REPORT_ID:396 report_item->id = usb_hid_report_tag_data_int32(data,item_size);397 break;398 case USB_HID_REPORT_TAG_PUSH:399 case USB_HID_REPORT_TAG_POP:400 return tag;401 break;402 403 default:404 return USB_HID_NO_ACTION;405 }406 407 return EOK;408 }409 410 /**411 * Parse local tags of report descriptor412 *413 * @param Tag identifier414 * @param Data buffer415 * @param Length of data buffer416 * @param Current state table417 * @return Error code418 */419 int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size,420 usb_hid_report_item_t *report_item)421 {422 switch(tag)423 {424 case USB_HID_REPORT_TAG_USAGE:425 report_item->usage = usb_hid_report_tag_data_int32(data,item_size);426 break;427 case USB_HID_REPORT_TAG_USAGE_MINIMUM:428 report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);429 break;430 case USB_HID_REPORT_TAG_USAGE_MAXIMUM:431 report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);432 break;433 case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:434 report_item->designator_index = usb_hid_report_tag_data_int32(data,item_size);435 break;436 case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM:437 report_item->designator_minimum = usb_hid_report_tag_data_int32(data,item_size);438 break;439 case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM:440 report_item->designator_maximum = usb_hid_report_tag_data_int32(data,item_size);441 break;442 case USB_HID_REPORT_TAG_STRING_INDEX:443 report_item->string_index = usb_hid_report_tag_data_int32(data,item_size);444 break;445 case USB_HID_REPORT_TAG_STRING_MINIMUM:446 report_item->string_minimum = usb_hid_report_tag_data_int32(data,item_size);447 break;448 case USB_HID_REPORT_TAG_STRING_MAXIMUM:449 report_item->string_maximum = usb_hid_report_tag_data_int32(data,item_size);450 break;451 case USB_HID_REPORT_TAG_DELIMITER:452 report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);453 break;454 455 default:456 return USB_HID_NO_ACTION;457 }458 459 return EOK;460 }461 462 /**463 * Converts raw data to int32 (thats the maximum length of short item data)464 *465 * @param Data buffer466 * @param Size of buffer467 * @return Converted int32 number468 */469 int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size)470 {471 unsigned int i;472 int32_t result;473 474 result = 0;475 for(i=0; i<size; i++) {476 result = (result | (data[i]) << (i*8));477 }478 479 return result;480 }481 482 483 484 /**485 * Prints content of given list of report items.486 *487 * @param List of report items488 * @return void489 */490 void usb_hid_descriptor_print_list(link_t *head)491 {492 usb_hid_report_item_t *report_item;493 link_t *item;494 495 if(head == NULL || list_empty(head)) {496 usb_log_debug("\tempty\n");497 return;498 }499 500 for(item = head->next; item != head; item = item->next) {501 502 report_item = list_get_instance(item, usb_hid_report_item_t, link);503 504 usb_log_debug("\tOFFSET: %X\n", report_item->offset);505 usb_log_debug("\tCOUNT: %X\n", report_item->count);506 usb_log_debug("\tSIZE: %X\n", report_item->size);507 usb_log_debug("\tCONSTANT/VAR: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags));508 usb_log_debug("\tVARIABLE/ARRAY: %X\n", USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags));509 usb_log_debug("\tUSAGE: %X\n", report_item->usage);510 usb_log_debug("\tUSAGE PAGE: %X\n", report_item->usage_page);511 usb_log_debug("\tLOGMIN: %X\n", report_item->logical_minimum);512 usb_log_debug("\tLOGMAX: %X\n", report_item->logical_maximum);513 usb_log_debug("\tPHYMIN: %X\n", report_item->physical_minimum);514 usb_log_debug("\tPHYMAX: %X\n", report_item->physical_maximum);515 usb_log_debug("\tUSAGEMIN: %X\n", report_item->usage_minimum);516 usb_log_debug("\tUSAGEMAX: %X\n", report_item->usage_maximum);517 518 usb_log_debug("\n");519 520 }521 522 523 }524 /**525 * Prints content of given descriptor in human readable format.526 *527 * @param Parsed descriptor to print528 * @return void529 */530 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser)531 {532 usb_log_debug("INPUT:\n");533 usb_hid_descriptor_print_list(&parser->input);534 535 usb_log_debug("OUTPUT: \n");536 usb_hid_descriptor_print_list(&parser->output);537 538 usb_log_debug("FEATURE:\n");539 usb_hid_descriptor_print_list(&parser->feature);540 541 }542 543 /**544 * Releases whole linked list of report items545 *546 *547 */548 void usb_hid_free_report_list(link_t *head)549 {550 return;551 552 usb_hid_report_item_t *report_item;553 link_t *next;554 555 if(head == NULL || list_empty(head)) {556 return;557 }558 559 next = head->next;560 while(next != head) {561 562 report_item = list_get_instance(next, usb_hid_report_item_t, link);563 next = next->next;564 565 free(report_item);566 }567 568 return;569 570 }571 572 /** Free the HID report parser structure573 *574 * @param parser Opaque HID report parser structure575 * @return Error code576 */577 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser)578 {579 if(parser == NULL){580 return;581 }582 583 usb_hid_free_report_list(&parser->input);584 usb_hid_free_report_list(&parser->output);585 usb_hid_free_report_list(&parser->feature);586 587 return;588 }589 590 /** Parse and act upon a HID report.591 *592 * @see usb_hid_parse_report_descriptor593 *594 * @param parser Opaque HID report parser structure.595 * @param data Data for the report.596 * @param callbacks Callbacks for report actions.597 * @param arg Custom argument (passed through to the callbacks).598 * @return Error code.599 */600 int usb_hid_parse_report(const usb_hid_report_parser_t *parser,601 const uint8_t *data, size_t size,602 const usb_hid_report_in_callbacks_t *callbacks, void *arg)603 {604 /*605 *606 * only key codes (usage page 0x07) will be processed607 * other usages will be ignored608 */609 link_t *list_item;610 usb_hid_report_item_t *item;611 uint8_t *keys;612 uint8_t item_value;613 size_t key_count=0;614 size_t i=0;615 size_t j=0;616 617 // get the size of result keycodes array618 usb_hid_report_path_t path;619 path.usage_page = BAD_HACK_USAGE_PAGE;620 key_count = usb_hid_report_input_length(parser, &path);621 622 if(!(keys = malloc(sizeof(uint8_t) * key_count))){623 return ENOMEM;624 }625 626 // read data627 list_item = parser->input.next;628 while(list_item != &(parser->input)) {629 630 item = list_get_instance(list_item, usb_hid_report_item_t, link);631 if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) &&632 (item->usage_page == path.usage_page)) {633 for(j=0; j<(size_t)(item->count); j++) {634 if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) ||635 ((item->usage_minimum == 0) && (item->usage_maximum == 0))) {636 // variable item637 keys[i++] = usb_hid_translate_data(item, data,j);638 }639 else {640 // bitmapa641 if((item_value = usb_hid_translate_data(item, data, j)) != 0) {642 keys[i++] = j + item->usage_minimum;643 }644 else {645 keys[i++] = 0;646 }647 }648 }649 }650 list_item = list_item->next;651 }652 653 callbacks->keyboard(keys, key_count, 0, arg);654 655 free(keys);656 return EOK;657 658 }659 660 661 int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j)662 {663 int resolution;664 int offset;665 int part_size;666 667 int32_t value;668 int32_t mask;669 const uint8_t *foo;670 671 // now only common numbers llowed672 if(item->size > 32) {673 return 0;674 }675 676 if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {677 item->physical_minimum = item->logical_minimum;678 item->physical_maximum = item->logical_maximum;679 }680 681 if(item->physical_maximum == item->physical_minimum){682 resolution = 1;683 }684 else {685 resolution = (item->logical_maximum - item->logical_minimum) /686 ((item->physical_maximum - item->physical_minimum) *687 (usb_pow(10,(item->unit_exponent))));688 }689 offset = item->offset + (j * item->size);690 691 // FIXME692 if((offset/8) != ((offset+item->size)/8)) {693 usb_log_debug2("offset %d\n", offset);694 695 part_size = ((offset+item->size)%8);696 usb_log_debug2("part size %d\n",part_size);697 698 // the higher one699 foo = data+(offset/8);700 mask = ((1 << (item->size-part_size))-1);701 value = (*foo & mask) << part_size;702 703 usb_log_debug2("hfoo %x\n", *foo);704 usb_log_debug2("hmaska %x\n", mask);705 usb_log_debug2("hval %d\n", value);706 707 // the lower one708 foo = data+((offset+item->size)/8);709 mask = ((1 << part_size)-1) << (8-part_size);710 value += ((*foo & mask) >> (8-part_size));711 712 usb_log_debug2("lfoo %x\n", *foo);713 usb_log_debug2("lmaska %x\n", mask);714 usb_log_debug2("lval %d\n", ((*foo & mask) >> (8-(item->size-part_size))));715 usb_log_debug2("val %d\n", value);716 717 718 }719 else {720 foo = data+(offset/8);721 mask = ((1 << item->size)-1) << (8-((offset%8)+item->size));722 value = (*foo & mask) >> (8-((offset%8)+item->size));723 724 usb_log_debug2("offset %d\n", offset);725 726 usb_log_debug2("foo %x\n", *foo);727 usb_log_debug2("maska %x\n", mask);728 usb_log_debug2("val %d\n", value);729 }730 731 usb_log_debug2("---\n\n");732 733 return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum);734 735 }736 737 int usb_hid_report_input_length(const usb_hid_report_parser_t *parser,738 const usb_hid_report_path_t *path)739 {740 int ret = 0;741 link_t *item;742 usb_hid_report_item_t *report_item;743 744 item = (&parser->input)->next;745 while(&parser->input != item) {746 report_item = list_get_instance(item, usb_hid_report_item_t, link);747 if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) &&748 (report_item->usage_page == path->usage_page)) {749 ret += report_item->count;750 }751 752 item = item->next;753 }754 755 return ret;756 }757 758 759 760 /**761 155 * @} 762 156 */
Note:
See TracChangeset
for help on using the changeset viewer.