Changes in uspace/lib/usbhid/src/hidparser.c [d861c22:160b75e] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbhid/src/hidparser.c
rd861c22 r160b75e 31 31 */ 32 32 /** @file 33 * USB HIDreport data parser implementation.33 * HID report descriptor and 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 48 //inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset); 49 49 int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data); 50 51 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, 52 int32_t value); 53 50 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value); 54 51 int usb_pow(int a, int b); 55 52 56 /*---------------------------------------------------------------------------*/57 53 58 54 // TODO: tohle ma bejt asi jinde … … 60 56 { 61 57 switch(b) { 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 100 /** Returns size of report of specified report id and type in bytes 101 * 102 * @param parser Opaque report parser structure 103 * @param report_id 104 * @param type 105 * @return Number of items in specified report 106 */ 107 size_t usb_hid_report_byte_size(usb_hid_report_t *report, uint8_t report_id, 108 usb_hid_report_type_t type) 109 { 110 usb_hid_report_description_t *report_des; 111 112 if(report == NULL) { 113 return 0; 114 } 115 116 report_des = usb_hid_report_find_description (report, report_id, type); 117 if(report_des == NULL){ 118 return 0; 119 } 120 else { 121 return ((report_des->bit_length + 7) / 8) ; 122 } 123 } 124 /*---------------------------------------------------------------------------*/ 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 125 72 126 73 /** Parse and act upon a HID report. … … 132 79 * @return Error code. 133 80 */ 134 int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data,135 81 int usb_hid_parse_report(const usb_hid_report_t *report, 82 const uint8_t *data, size_t size, uint8_t *report_id) 136 83 { 137 84 link_t *list_item; … … 140 87 usb_hid_report_description_t *report_des; 141 88 usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT; 142 89 143 90 if(report == NULL) { 144 91 return EINVAL; … … 154 101 155 102 report_des = usb_hid_report_find_description(report, *report_id, type); 156 if(report_des == NULL) {157 return EINVAL;158 }159 103 160 104 /* read data */ … … 162 106 while(list_item != &(report_des->report_items)) { 163 107 164 item = list_get_instance(list_item, usb_hid_report_field_t, 165 link); 108 item = list_get_instance(list_item, usb_hid_report_field_t, link); 166 109 167 110 if(USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) { … … 170 113 171 114 // array 172 item->value = 173 usb_hid_translate_data(item, data); 174 175 item->usage = USB_HID_EXTENDED_USAGE( 176 item->usages[item->value - item->physical_minimum]); 177 178 item->usage_page = USB_HID_EXTENDED_USAGE_PAGE( 179 item->usages[item->value - item->physical_minimum]); 180 181 usb_hid_report_set_last_item (item->collection_path, 182 USB_HID_TAG_CLASS_GLOBAL, item->usage_page); 183 184 usb_hid_report_set_last_item (item->collection_path, 185 USB_HID_TAG_CLASS_LOCAL, item->usage); 186 115 item->value = usb_hid_translate_data(item, data); 116 item->usage = (item->value - item->physical_minimum) + item->usage_minimum; 187 117 } 188 118 else { … … 193 123 list_item = list_item->next; 194 124 } 195 125 196 126 return EOK; 197 127 198 128 } 199 129 200 /*---------------------------------------------------------------------------*/201 130 /** 202 131 * Translate data from the report as specified in report descriptor item … … 204 133 * @param item Report descriptor item with definition of translation 205 134 * @param data Data to translate 135 * @param j Index of processed field in report descriptor item 206 136 * @return Translated data 207 137 */ … … 272 202 } 273 203 274 return (int)(((value - item->logical_minimum) / resolution) + 275 item->physical_minimum); 276 277 } 278 279 /*---------------------------------------------------------------------------*/ 280 /* OUTPUT API */ 204 return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum); 205 206 } 207 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 **/ 281 253 282 254 /** … … 288 260 * @return Returns allocated output buffer for specified output 289 261 */ 290 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, 291 uint8_t report_id) 262 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id) 292 263 { 293 264 if(report == NULL) { … … 299 270 usb_hid_report_description_t *report_des = NULL; 300 271 while(report_it != &report->reports) { 301 report_des = list_get_instance(report_it, 302 usb_hid_report_description_t, link); 303 304 if((report_des->report_id == report_id) && 305 (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){ 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)){ 306 274 break; 307 275 } … … 334 302 free (output); 335 303 } 304 } 305 306 /** Returns size of output for given usage path 307 * 308 * @param parser Opaque report parser structure 309 * @param path Usage path specified which items will be thought for the output 310 * @param flags Flags of usage path structure comparison 311 * @return Number of items matching the given usage path 312 */ 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 336 346 } 337 347 … … 345 355 * @return Error code 346 356 */ 347 int usb_hid_report_output_translate(usb_hid_report_t *report, 348 uint8_t report_id,uint8_t *buffer, size_t size)357 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id, 358 uint8_t *buffer, size_t size) 349 359 { 350 360 link_t *item; … … 362 372 } 363 373 374 usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0)); 375 364 376 usb_hid_report_description_t *report_des; 365 report_des = usb_hid_report_find_description (report, report_id, 366 USB_HID_REPORT_TYPE_OUTPUT); 367 377 report_des = usb_hid_report_find_description (report, report_id, USB_HID_REPORT_TYPE_OUTPUT); 368 378 if(report_des == NULL){ 369 379 return EINVAL; … … 375 385 report_item = list_get_instance(item, usb_hid_report_field_t, link); 376 386 377 if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) {387 if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) { 378 388 379 // array 380 value = usb_hid_translate_data_reverse(report_item, 381 report_item->value); 382 383 offset = report_item->offset; 384 length = report_item->size; 385 } 386 else { 387 // variable item 388 value = usb_hid_translate_data_reverse(report_item, 389 report_item->value); 390 391 offset = report_item->offset; 392 length = report_item->size; 393 } 394 395 usb_log_debug("\ttranslated value: %x\n", value); 396 397 if((offset/8) == ((offset+length-1)/8)) { 398 // je to v jednom bytu 399 if(((size_t)(offset/8) >= size) || 400 ((size_t)(offset+length-1)/8) >= size) { 401 break; // TODO ErrorCode 402 } 403 size_t shift = 8 - offset%8 - length; 404 value = value << shift; 405 value = value & (((1 << length)-1) << shift); 389 // array 390 value = usb_hid_translate_data_reverse(report_item, report_item->value); 391 offset = report_item->offset; 392 length = report_item->size; 393 } 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 405 } 406 407 size_t shift = 8 - offset%8 - length; 408 409 value = value << shift; 410 value = value & (((1 << length)-1) << shift); 406 411 407 uint8_t mask = 0; 408 mask = 0xff - (((1 << length) - 1) << shift); 409 buffer[offset/8] = (buffer[offset/8] & mask) | value; 410 } 411 else { 412 int i = 0; 413 uint8_t mask = 0; 414 for(i = (offset/8); i <= ((offset+length-1)/8); i++) { 415 if(i == (offset/8)) { 416 tmp_value = value; 417 tmp_value = tmp_value & 418 ((1 << (8-(offset%8)))-1); 419 420 tmp_value = tmp_value << (offset%8); 421 422 mask = ~(((1 << (8-(offset%8)))-1) << 423 (offset%8)); 424 425 buffer[i] = (buffer[i] & mask) | 426 tmp_value; 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 } 427 439 } 428 else if (i == ((offset + length -1)/8)) { 429 430 value = value >> (length - 431 ((offset + length) % 8)); 432 433 value = value & ((1 << (length - 434 ((offset + length) % 8))) - 1); 435 436 mask = (1 << (length - 437 ((offset + length) % 8))) - 1; 438 439 buffer[i] = (buffer[i] & mask) | value; 440 } 441 else { 442 buffer[i] = value & (0xFF << i); 443 } 444 } 445 } 440 } 441 446 442 447 443 // reset value … … 451 447 } 452 448 449 usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0)); 450 453 451 return EOK; 454 452 } 455 453 456 /*---------------------------------------------------------------------------*/457 454 /** 458 455 * Translate given data for putting them into the outoput report … … 461 458 * @return ranslated value 462 459 */ 463 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, 464 int value) 460 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int value) 465 461 { 466 462 int ret=0; … … 476 472 } 477 473 478 // variable item 479 if(item->physical_maximum == item->physical_minimum){ 480 resolution = 1; 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; 481 488 } 482 489 else { 483 resolution = (item->logical_maximum - item->logical_minimum) / 484 ((item->physical_maximum - item->physical_minimum) * 485 (usb_pow(10,(item->unit_exponent)))); 486 } 487 488 ret = ((value - item->physical_minimum) * resolution) + 489 item->logical_minimum; 490 491 usb_log_debug("\tvalue(%x), resolution(%x), phymin(%x) logmin(%x), \ 492 ret(%x)\n", value, resolution, item->physical_minimum, 493 item->logical_minimum, ret); 494 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 495 500 if((item->logical_minimum < 0) || (item->logical_maximum < 0)){ 496 501 return USB_HID_INT32_TO_UINT32(ret, item->size); 497 502 } 498 return (int32_t)0 + ret; 499 } 500 501 /*---------------------------------------------------------------------------*/ 502 /** 503 * Clones given state table 504 * 505 * @param item State table to clone 506 * @return Pointer to the cloned item 507 */ 508 usb_hid_report_item_t *usb_hid_report_item_clone( 509 const usb_hid_report_item_t *item) 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) 510 507 { 511 508 usb_hid_report_item_t *new_report_item; … … 520 517 } 521 518 522 /*---------------------------------------------------------------------------*/ 523 /** 524 * Function for sequence walking through the report. Returns next field in the 525 * report or the first one when no field is given. 526 * 527 * @param report Searched report structure 528 * @param field Current field. If NULL is given, the first one in the report 529 * is returned. Otherwise the next one i nthe list is returned. 530 * @param path Usage path specifying which fields wa are interested in. 531 * @param flags Flags defining mode of usage paths comparison 532 * @param type Type of report we search. 533 * @retval NULL if no field is founded 534 * @retval Pointer to the founded report structure when founded 535 */ 519 536 520 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, 537 usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, 538 usb_hid_report_type_t type) 539 { 540 usb_hid_report_description_t *report_des = 541 usb_hid_report_find_description(report, path->report_id, type); 542 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); 543 526 link_t *field_it; 544 527 … … 548 531 549 532 if(field == NULL){ 533 // vezmu prvni co mathuje podle path!! 550 534 field_it = report_des->report_items.next; 551 535 } … … 555 539 556 540 while(field_it != &report_des->report_items) { 557 field = list_get_instance(field_it, usb_hid_report_field_t, 558 link); 541 field = list_get_instance(field_it, usb_hid_report_field_t, link); 559 542 560 543 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) { 561 usb_hid_report_path_append_item ( 562 field->collection_path, field->usage_page, 563 field->usage); 564 565 if(usb_hid_report_compare_usage_path( 566 field->collection_path, path, flags) == EOK){ 567 568 usb_hid_report_remove_last_item( 569 field->collection_path); 570 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); 571 547 return field; 572 548 } 573 usb_hid_report_remove_last_item ( 574 field->collection_path); 549 usb_hid_report_remove_last_item (field->collection_path); 575 550 } 576 551 field_it = field_it->next; … … 580 555 } 581 556 582 /*---------------------------------------------------------------------------*/ 583 /** 584 * Returns next report_id of report of specified type. If zero is given than 585 * first report_id of specified type is returned (0 is not legal value for 586 * repotr_id) 587 * 588 * @param report_id Current report_id, 0 if there is no current report_id 589 * @param type Type of searched report 590 * @param report Report structure inwhich we search 591 * @retval 0 if report structure is null or there is no specified report 592 * @retval report_id otherwise 593 */ 594 uint8_t usb_hid_get_next_report_id(usb_hid_report_t *report, 595 uint8_t report_id, usb_hid_report_type_t type) 557 uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type) 596 558 { 597 559 if(report == NULL){ … … 602 564 link_t *report_it; 603 565 604 if(report_id > 0) { 605 report_it = usb_hid_report_find_description(report, report_id, 606 type)->link.next; 566 if(report_id == 0) { 567 report_it = usb_hid_report_find_description (report, report_id, type)->link.next; 607 568 } 608 569 else { … … 611 572 612 573 while(report_it != &report->reports) { 613 report_des = list_get_instance(report_it, 614 usb_hid_report_description_t, link); 615 574 report_des = list_get_instance(report_it, usb_hid_report_description_t, link); 616 575 if(report_des->type == type){ 617 576 return report_des->report_id; … … 622 581 } 623 582 624 /*---------------------------------------------------------------------------*/625 /**626 * Reset all local items in given state table627 *628 * @param report_item State table containing current state of report629 * descriptor parsing630 *631 * @return void632 */633 583 void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item) 634 584 {
Note:
See TracChangeset
for help on using the changeset viewer.