Changes in uspace/lib/usbhid/src/hidparser.c [160b75e:5499a8b] in mainline
- File:
-
- 1 edited
-
uspace/lib/usbhid/src/hidparser.c (modified) (25 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbhid/src/hidparser.c
r160b75e r5499a8b 31 31 */ 32 32 /** @file 33 * HID report descriptor andreport data parser implementation.33 * USB HID report data parser implementation. 34 34 */ 35 35 #include <usb/hid/hidparser.h> … … 41 41 #include <assert.h> 42 42 43 43 /*---------------------------------------------------------------------------*/ 44 44 /* 45 45 * Data translation private functions 46 46 */ 47 47 uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size); 48 //inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset); 48 49 49 int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data); 50 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value); 50 51 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, 52 int32_t value); 53 51 54 int usb_pow(int a, int b); 52 55 56 /*---------------------------------------------------------------------------*/ 53 57 54 58 // TODO: tohle ma bejt asi jinde … … 56 60 { 57 61 switch(b) { 58 case 0: 59 return 1; 60 break; 61 case 1: 62 return a; 63 break; 64 default: 65 return a * usb_pow(a, b-1); 66 break; 67 } 68 } 69 70 71 62 case 0: 63 return 1; 64 break; 65 case 1: 66 return a; 67 break; 68 default: 69 return a * usb_pow(a, b-1); 70 break; 71 } 72 } 73 /*---------------------------------------------------------------------------*/ 74 75 /** Returns size of report of specified report id and type in items 76 * 77 * @param parser Opaque report parser structure 78 * @param report_id 79 * @param type 80 * @return Number of items in specified report 81 */ 82 size_t usb_hid_report_size(usb_hid_report_t *report, uint8_t report_id, 83 usb_hid_report_type_t type) 84 { 85 usb_hid_report_description_t *report_des; 86 87 if(report == NULL) { 88 return 0; 89 } 90 91 report_des = usb_hid_report_find_description (report, report_id, type); 92 if(report_des == NULL){ 93 return 0; 94 } 95 else { 96 return report_des->item_length; 97 } 98 } 99 /*---------------------------------------------------------------------------*/ 72 100 73 101 /** Parse and act upon a HID report. … … 79 107 * @return Error code. 80 108 */ 81 int usb_hid_parse_report(const usb_hid_report_t *report, 82 const uint8_t *data,size_t size, uint8_t *report_id)109 int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, 110 size_t size, uint8_t *report_id) 83 111 { 84 112 link_t *list_item; … … 87 115 usb_hid_report_description_t *report_des; 88 116 usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT; 89 117 90 118 if(report == NULL) { 91 119 return EINVAL; … … 114 142 // array 115 143 item->value = usb_hid_translate_data(item, data); 116 item->usage = (item->value - item->physical_minimum) + item->usage_minimum; 144 145 item->usage = USB_HID_EXTENDED_USAGE( 146 item->usages[item->value - item->physical_minimum]); 147 item->usage_page = USB_HID_EXTENDED_USAGE_PAGE( 148 item->usages[item->value - item->physical_minimum]); 149 150 usb_hid_report_set_last_item (item->collection_path, 151 USB_HID_TAG_CLASS_GLOBAL, item->usage_page); 152 usb_hid_report_set_last_item (item->collection_path, 153 USB_HID_TAG_CLASS_LOCAL, item->usage); 154 117 155 } 118 156 else { … … 123 161 list_item = list_item->next; 124 162 } 125 163 126 164 return EOK; 127 165 128 166 } 129 167 168 /*---------------------------------------------------------------------------*/ 130 169 /** 131 170 * Translate data from the report as specified in report descriptor item … … 133 172 * @param item Report descriptor item with definition of translation 134 173 * @param data Data to translate 135 * @param j Index of processed field in report descriptor item136 174 * @return Translated data 137 175 */ … … 206 244 } 207 245 208 /** 209 * Returns number of items in input report which are accessible by given usage path 210 * 211 * @param parser Opaque report descriptor structure 212 * @param path Usage path specification 213 * @param flags Usage path comparison flags 214 * @return Number of items in input report 215 */ 216 size_t usb_hid_report_input_length(const usb_hid_report_t *report, 217 usb_hid_report_path_t *path, int flags) 218 { 219 220 size_t ret = 0; 221 222 if(report == NULL) { 223 return 0; 224 } 225 226 usb_hid_report_description_t *report_des; 227 report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_INPUT); 228 if(report_des == NULL) { 229 return 0; 230 } 231 232 link_t *field_it = report_des->report_items.next; 233 usb_hid_report_field_t *field; 234 while(field_it != &report_des->report_items) { 235 236 field = list_get_instance(field_it, usb_hid_report_field_t, link); 237 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) { 238 239 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 240 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) { 241 ret++; 242 } 243 usb_hid_report_remove_last_item (field->collection_path); 244 } 245 246 field_it = field_it->next; 247 } 248 249 return ret; 250 } 251 252 /*** OUTPUT API **/ 246 /*---------------------------------------------------------------------------*/ 247 /* OUTPUT API */ 253 248 254 249 /** … … 260 255 * @return Returns allocated output buffer for specified output 261 256 */ 262 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id) 257 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, 258 uint8_t report_id) 263 259 { 264 260 if(report == NULL) { … … 270 266 usb_hid_report_description_t *report_des = NULL; 271 267 while(report_it != &report->reports) { 272 report_des = list_get_instance(report_it, usb_hid_report_description_t, link); 273 if((report_des->report_id == report_id) && (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){ 268 report_des = list_get_instance(report_it, 269 usb_hid_report_description_t, link); 270 271 if((report_des->report_id == report_id) && 272 (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){ 274 273 break; 275 274 } … … 302 301 free (output); 303 302 } 304 }305 306 /** Returns size of output for given usage path307 *308 * @param parser Opaque report parser structure309 * @param path Usage path specified which items will be thought for the output310 * @param flags Flags of usage path structure comparison311 * @return Number of items matching the given usage path312 */313 size_t usb_hid_report_output_size(usb_hid_report_t *report,314 usb_hid_report_path_t *path, int flags)315 {316 size_t ret = 0;317 usb_hid_report_description_t *report_des;318 319 if(report == NULL) {320 return 0;321 }322 323 report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_OUTPUT);324 if(report_des == NULL){325 return 0;326 }327 328 link_t *field_it = report_des->report_items.next;329 usb_hid_report_field_t *field;330 while(field_it != &report_des->report_items) {331 332 field = list_get_instance(field_it, usb_hid_report_field_t, link);333 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0){334 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);335 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {336 ret++;337 }338 usb_hid_report_remove_last_item (field->collection_path);339 }340 341 field_it = field_it->next;342 }343 344 return ret;345 346 303 } 347 304 … … 355 312 * @return Error code 356 313 */ 357 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id,358 uint8_t *buffer, size_t size)314 int usb_hid_report_output_translate(usb_hid_report_t *report, 315 uint8_t report_id, uint8_t *buffer, size_t size) 359 316 { 360 317 link_t *item; … … 372 329 } 373 330 374 usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));375 376 331 usb_hid_report_description_t *report_des; 377 report_des = usb_hid_report_find_description (report, report_id, USB_HID_REPORT_TYPE_OUTPUT); 332 report_des = usb_hid_report_find_description (report, report_id, 333 USB_HID_REPORT_TYPE_OUTPUT); 334 378 335 if(report_des == NULL){ 379 336 return EINVAL; … … 385 342 report_item = list_get_instance(item, usb_hid_report_field_t, link); 386 343 387 if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) {344 if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) { 388 345 389 // array 390 value = usb_hid_translate_data_reverse(report_item, report_item->value); 391 offset = report_item->offset; 392 length = report_item->size; 346 // array 347 value = usb_hid_translate_data_reverse(report_item, 348 report_item->value); 349 350 offset = report_item->offset; 351 length = report_item->size; 352 } 353 else { 354 // variable item 355 value = usb_hid_translate_data_reverse(report_item, 356 report_item->value); 357 358 offset = report_item->offset; 359 length = report_item->size; 360 } 361 362 usb_log_debug("\ttranslated value: %x\n", value); 363 364 if((offset/8) == ((offset+length-1)/8)) { 365 // je to v jednom bytu 366 if(((size_t)(offset/8) >= size) || 367 ((size_t)(offset+length-1)/8) >= size) { 368 break; // TODO ErrorCode 393 369 } 394 else { 395 // variable item 396 value = usb_hid_translate_data_reverse(report_item, report_item->value); 397 offset = report_item->offset; 398 length = report_item->size; 399 } 400 401 if((offset/8) == ((offset+length-1)/8)) { 402 // je to v jednom bytu 403 if(((size_t)(offset/8) >= size) || ((size_t)(offset+length-1)/8) >= size) { 404 break; // TODO ErrorCode 370 size_t shift = 8 - offset%8 - length; 371 value = value << shift; 372 value = value & (((1 << length)-1) << shift); 373 374 uint8_t mask = 0; 375 mask = 0xff - (((1 << length) - 1) << shift); 376 buffer[offset/8] = (buffer[offset/8] & mask) | value; 377 } 378 else { 379 int i = 0; 380 uint8_t mask = 0; 381 for(i = (offset/8); i <= ((offset+length-1)/8); i++) { 382 if(i == (offset/8)) { 383 tmp_value = value; 384 tmp_value = tmp_value & ((1 << (8-(offset%8)))-1); 385 tmp_value = tmp_value << (offset%8); 386 387 mask = ~(((1 << (8-(offset%8)))-1) << (offset%8)); 388 buffer[i] = (buffer[i] & mask) | tmp_value; 405 389 } 406 407 size_t shift = 8 - offset%8 - length;408 409 value = value << shift;410 value = value & (((1 << length)-1) << shift);390 else if (i == ((offset + length -1)/8)) { 391 392 value = value >> (length - ((offset + length) % 8)); 393 value = value & 394 ((1 << (length - ((offset + length) % 8))) - 1); 411 395 412 uint8_t mask = 0; 413 mask = 0xff - (((1 << length) - 1) << shift); 414 buffer[offset/8] = (buffer[offset/8] & mask) | value; 415 } 416 else { 417 int i = 0; 418 uint8_t mask = 0; 419 for(i = (offset/8); i <= ((offset+length-1)/8); i++) { 420 if(i == (offset/8)) { 421 tmp_value = value; 422 tmp_value = tmp_value & ((1 << (8-(offset%8)))-1); 423 tmp_value = tmp_value << (offset%8); 424 425 mask = ~(((1 << (8-(offset%8)))-1) << (offset%8)); 426 buffer[i] = (buffer[i] & mask) | tmp_value; 427 } 428 else if (i == ((offset + length -1)/8)) { 429 430 value = value >> (length - ((offset + length) % 8)); 431 value = value & ((1 << (length - ((offset + length) % 8))) - 1); 432 433 mask = (1 << (length - ((offset + length) % 8))) - 1; 434 buffer[i] = (buffer[i] & mask) | value; 435 } 436 else { 437 buffer[i] = value & (0xFF << i); 438 } 396 mask = (1 << (length - ((offset + length) % 8))) - 1; 397 buffer[i] = (buffer[i] & mask) | value; 398 } 399 else { 400 buffer[i] = value & (0xFF << i); 439 401 } 440 402 } 441 403 } 442 404 443 405 // reset value … … 447 409 } 448 410 449 usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));450 451 411 return EOK; 452 412 } 453 413 414 /*---------------------------------------------------------------------------*/ 454 415 /** 455 416 * Translate given data for putting them into the outoput report … … 458 419 * @return ranslated value 459 420 */ 460 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int value) 421 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, 422 int value) 461 423 { 462 424 int ret=0; … … 472 434 } 473 435 474 475 if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0)) { 476 477 // variable item 478 if(item->physical_maximum == item->physical_minimum){ 479 resolution = 1; 480 } 481 else { 482 resolution = (item->logical_maximum - item->logical_minimum) / 483 ((item->physical_maximum - item->physical_minimum) * 484 (usb_pow(10,(item->unit_exponent)))); 485 } 486 487 ret = ((value - item->physical_minimum) * resolution) + item->logical_minimum; 436 // variable item 437 if(item->physical_maximum == item->physical_minimum){ 438 resolution = 1; 488 439 } 489 440 else { 490 // bitmapa 491 if(value == 0) { 492 ret = 0; 493 } 494 else { 495 size_t bitmap_idx = (value - item->usage_minimum); 496 ret = 1 << bitmap_idx; 497 } 498 } 499 441 resolution = (item->logical_maximum - item->logical_minimum) / 442 ((item->physical_maximum - item->physical_minimum) * 443 (usb_pow(10,(item->unit_exponent)))); 444 } 445 446 ret = ((value - item->physical_minimum) * resolution) + 447 item->logical_minimum; 448 449 usb_log_debug("\tvalue(%x), resolution(%x), phymin(%x) logmin(%x), \ 450 ret(%x)\n", value, resolution, item->physical_minimum, 451 item->logical_minimum, ret); 452 500 453 if((item->logical_minimum < 0) || (item->logical_maximum < 0)){ 501 454 return USB_HID_INT32_TO_UINT32(ret, item->size); 502 455 } 503 return (int32_t)ret; 504 } 505 506 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item) 456 return (int32_t)0 + ret; 457 } 458 459 /*---------------------------------------------------------------------------*/ 460 /** 461 * Clones given state table 462 * 463 * @param item State table to clone 464 * @return Pointer to the cloned item 465 */ 466 usb_hid_report_item_t *usb_hid_report_item_clone( 467 const usb_hid_report_item_t *item) 507 468 { 508 469 usb_hid_report_item_t *new_report_item; … … 517 478 } 518 479 519 480 /*---------------------------------------------------------------------------*/ 481 /** 482 * Function for sequence walking through the report. Returns next field in the 483 * report or the first one when no field is given. 484 * 485 * @param report Searched report structure 486 * @param field Current field. If NULL is given, the first one in the report 487 * is returned. Otherwise the next one i nthe list is returned. 488 * @param path Usage path specifying which fields wa are interested in. 489 * @param flags Flags defining mode of usage paths comparison 490 * @param type Type of report we search. 491 * @retval NULL if no field is founded 492 * @retval Pointer to the founded report structure when founded 493 */ 520 494 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, 521 usb_hid_report_field_t *field, 522 usb_hid_report_path_t *path, int flags, 523 usb_hid_report_type_t type) 524 { 525 usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type); 495 usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, 496 usb_hid_report_type_t type) 497 { 498 usb_hid_report_description_t *report_des = usb_hid_report_find_description( 499 report, path->report_id, type); 500 526 501 link_t *field_it; 527 502 … … 531 506 532 507 if(field == NULL){ 533 // vezmu prvni co mathuje podle path!!534 508 field_it = report_des->report_items.next; 535 509 } … … 542 516 543 517 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) { 544 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 545 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){ 546 usb_hid_report_remove_last_item (field->collection_path); 518 usb_hid_report_path_append_item (field->collection_path, 519 field->usage_page, field->usage); 520 521 if(usb_hid_report_compare_usage_path(field->collection_path, path, 522 flags) == EOK){ 523 524 usb_hid_report_remove_last_item(field->collection_path); 547 525 return field; 548 526 } … … 555 533 } 556 534 557 uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type) 535 /*---------------------------------------------------------------------------*/ 536 /** 537 * Returns nonzero (report_id) number if there is report of given type and 538 * have the specified report_id in report structure 539 * 540 * @param report_id Searched report id 541 * @param type Type of searched report 542 * @param report Report structure inwhich we search 543 * @retval 0 if report structure is null or there is no specified report 544 * @retval report_id otherwise 545 */ 546 uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, 547 uint8_t report_id, usb_hid_report_type_t type) 558 548 { 559 549 if(report == NULL){ … … 565 555 566 556 if(report_id == 0) { 567 report_it = usb_hid_report_find_description (report, report_id, type)->link.next; 557 report_it = usb_hid_report_find_description(report, report_id, 558 type)->link.next; 568 559 } 569 560 else { … … 572 563 573 564 while(report_it != &report->reports) { 574 report_des = list_get_instance(report_it, usb_hid_report_description_t, link); 565 report_des = list_get_instance(report_it, usb_hid_report_description_t, 566 link); 567 575 568 if(report_des->type == type){ 576 569 return report_des->report_id; … … 581 574 } 582 575 576 /*---------------------------------------------------------------------------*/ 577 /** 578 * Reset all local items in given state table 579 * 580 * @param report_item State table containing current state of report 581 * descriptor parsing 582 * 583 * @return void 584 */ 583 585 void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item) 584 586 {
Note:
See TracChangeset
for help on using the changeset viewer.
