Changes in / [d8e61b0d:11ac272] in mainline
- Location:
- uspace
- Files:
-
- 1 deleted
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhid/hiddev.c
rd8e61b0d r11ac272 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 */ -
uspace/drv/usbhid/hiddev.h
rd8e61b0d r11ac272 75 75 /** Report descriptor. */ 76 76 uint8_t *report_desc; 77 78 size_t report_desc_size;79 80 77 /** HID Report parser. */ 81 78 usb_hid_report_parser_t *parser; -
uspace/drv/usbhid/kbddev.c
rd8e61b0d r11ac272 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" … … 123 122 KC_RALT, /* USB_HID_MOD_RALT */ 124 123 0, /* USB_HID_MOD_RGUI */ 125 };126 127 typedef enum usbhid_lock_code {128 USBHID_LOCK_NUM = 0x53,129 USBHID_LOCK_CAPS = 0x39,130 USBHID_LOCK_SCROLL = 0x47,131 USBHID_LOCK_COUNT = 3132 } usbhid_lock_code;133 134 static const usbhid_lock_code usbhid_lock_codes[USBHID_LOCK_COUNT] = {135 USBHID_LOCK_NUM,136 USBHID_LOCK_CAPS,137 USBHID_LOCK_SCROLL138 124 }; 139 125 … … 360 346 * @sa usbhid_kbd_push_ev() 361 347 */ 362 //static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev, 363 // const uint8_t *key_codes, size_t count) 364 //{ 365 // /* 366 // * TODO: why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK 367 // * both as modifiers and as keyUSB_HID_LOCK_COUNTs with their own scancodes??? 368 // * 369 // * modifiers should be sent as normal keys to usbhid_parse_scancode()!! 370 // * so maybe it would be better if I received it from report parser in 371 // * that way 372 // */ 373 374 // int i; 375 // for (i = 0; i < count; ++i) { 376 // if ((modifiers & usb_hid_modifiers_consts[i]) && 377 // !(kbd_dev->modifiers & usb_hid_modifiers_consts[i])) { 378 // // modifier pressed 379 // if (usbhid_modifiers_keycodes[i] != 0) { 380 // usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, 381 // usbhid_modifiers_keycodes[i]); 382 // } 383 // } else if (!(modifiers & usb_hid_modifiers_consts[i]) && 384 // (kbd_dev->modifiers & usb_hid_modifiers_consts[i])) { 385 // // modifier released 386 // if (usbhid_modifiers_keycodes[i] != 0) { 387 // usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, 388 // usbhid_modifiers_keycodes[i]); 389 // } 390 // } // no change 391 // } 392 393 // kbd_dev->modifiers = modifiers; 394 //} 395 396 /*----------------------------------------------------------------------------*/ 397 398 static inline int usbhid_kbd_is_lock(unsigned int key_code) 399 { 400 return (key_code == KC_NUM_LOCK 401 || key_code == KC_SCROLL_LOCK 402 || 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; 403 380 } 404 381 … … 427 404 /* 428 405 * First of all, check if the kbd have reported phantom state. 429 *430 * TODO: this must be changed as we don't know which keys are modifiers431 * and which are regular keys.432 406 */ 433 407 i = 0; … … 460 434 // not found, i.e. the key was released 461 435 key = usbhid_parse_scancode(kbd_dev->keys[j]); 462 if (!usbhid_kbd_is_lock(key)) { 463 usbhid_kbd_repeat_stop(kbd_dev, key); 464 } 436 usbhid_kbd_repeat_stop(kbd_dev, key); 465 437 usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key); 466 438 usb_log_debug2("Key released: %d\n", key); … … 486 458 key_codes[i]); 487 459 usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key); 488 if (!usbhid_kbd_is_lock(key)) { 489 usbhid_kbd_repeat_start(kbd_dev, key); 490 } 460 usbhid_kbd_repeat_start(kbd_dev, key); 491 461 } else { 492 462 // found, nothing happens … … 532 502 533 503 usb_log_debug("Got keys from parser: %s\n", 534 usb_debug_str_buffer(key_codes, count, 0));504 usb_debug_str_buffer(key_codes, kbd_dev->key_count, 0)); 535 505 536 506 if (count != kbd_dev->key_count) { … … 540 510 } 541 511 542 ///usbhid_kbd_check_modifier_changes(kbd_dev, key_codes, count);512 usbhid_kbd_check_modifier_changes(kbd_dev, modifiers); 543 513 usbhid_kbd_check_key_changes(kbd_dev, key_codes, count); 544 514 } … … 565 535 uint8_t *buffer, size_t actual_size) 566 536 { 567 assert(kbd_dev->initialized);568 assert(kbd_dev->hid_dev->parser != NULL);569 570 537 usb_hid_report_in_callbacks_t *callbacks = 571 538 (usb_hid_report_in_callbacks_t *)malloc( … … 574 541 callbacks->keyboard = usbhid_kbd_process_keycodes; 575 542 576 usb_log_debug("Calling usb_hid_ parse_report() with "543 usb_log_debug("Calling usb_hid_boot_keyboard_input_report() with " 577 544 "buffer %s\n", usb_debug_str_buffer(buffer, actual_size, 0)); 578 545 579 // int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size, 580 // callbacks, kbd_dev); 581 int rc = usb_hid_parse_report(kbd_dev->hid_dev->parser, buffer, 582 actual_size, callbacks, kbd_dev); 546 int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size, 547 callbacks, kbd_dev); 583 548 584 549 if (rc != EOK) { … … 649 614 free((*kbd_dev)->repeat_mtx); 650 615 } 651 616 652 617 free(*kbd_dev); 653 618 *kbd_dev = NULL; … … 709 674 710 675 // save the size of the report (boot protocol report by default) 711 // kbd_dev->key_count = BOOTP_REPORT_SIZE; 712 713 usb_hid_report_path_t path; 714 path.usage_page = USB_HIDUT_PAGE_KEYBOARD; 715 kbd_dev->key_count = usb_hid_report_input_length( 716 kbd_dev->hid_dev->parser, &path); 717 718 usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count); 719 676 kbd_dev->key_count = BOOTP_REPORT_SIZE; 720 677 kbd_dev->keys = (uint8_t *)calloc( 721 678 kbd_dev->key_count, sizeof(uint8_t)); … … 752 709 assert(kbd_dev->hid_dev != NULL); 753 710 assert(kbd_dev->hid_dev->initialized); 754 //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); 755 712 756 713 usbhid_kbd_set_led(kbd_dev); -
uspace/drv/usbhid/kbddev.h
rd8e61b0d r11ac272 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> -
uspace/lib/usb/include/usb/classes/hidparser.h
rd8e61b0d r11ac272 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/src/hidparser.c
rd8e61b0d r11ac272 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.