Changeset df6ded8 in mainline for uspace/lib/usbhid/src/hidparser.c
- Timestamp:
- 2018-02-28T16:37:50Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1b20da0
- Parents:
- f5e5f73 (diff), b2dca8de (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - git-author:
- Jakub Jermar <jakub@…> (2018-02-28 16:06:42)
- git-committer:
- Jakub Jermar <jakub@…> (2018-02-28 16:37:50)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbhid/src/hidparser.c
rf5e5f73 rdf6ded8 1 1 /* 2 2 * Copyright (c) 2011 Matej Klonfar 3 * Copyright (c) 2018 Ondrej Hlavaty 3 4 * All rights reserved. 4 5 * … … 40 41 #include <usb/debug.h> 41 42 #include <assert.h> 43 #include <bitops.h> 44 #include <macros.h> 42 45 43 46 … … 49 52 int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data); 50 53 51 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, 52 54 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, 55 int32_t value); 53 56 54 57 … … 73 76 * 74 77 * @param parser Opaque report parser structure 75 * @param report_id 78 * @param report_id 76 79 * @param type 77 80 * @return Number of items in specified report 78 81 */ 79 size_t usb_hid_report_size(usb_hid_report_t *report, uint8_t report_id, 82 size_t usb_hid_report_size(usb_hid_report_t *report, uint8_t report_id, 80 83 usb_hid_report_type_t type) 81 84 { … … 97 100 * 98 101 * @param parser Opaque report parser structure 99 * @param report_id 102 * @param report_id 100 103 * @param type 101 104 * @return Number of items in specified report 102 105 */ 103 size_t usb_hid_report_byte_size(usb_hid_report_t *report, uint8_t report_id, 106 size_t usb_hid_report_byte_size(usb_hid_report_t *report, uint8_t report_id, 104 107 usb_hid_report_type_t type) 105 108 { … … 114 117 return 0; 115 118 } else { 116 return ((report_des->bit_length + 7) / 8) 119 return ((report_des->bit_length + 7) / 8); 117 120 } 118 121 } … … 126 129 * @param data Data for the report. 127 130 * @return Error code. 128 */ 129 errno_t usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, 131 */ 132 errno_t usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, 130 133 size_t size, uint8_t *report_id) 131 134 { 132 135 usb_hid_report_description_t *report_des; 133 136 usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT; 134 137 135 138 if (report == NULL) { 136 139 return EINVAL; … … 143 146 } 144 147 145 report_des = usb_hid_report_find_description(report, *report_id, 148 report_des = usb_hid_report_find_description(report, *report_id, 146 149 type); 147 150 … … 155 158 156 159 if (USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) { 157 160 158 161 if (USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) { 159 162 /* array */ 160 item->value = 161 162 163 item->value = 164 usb_hid_translate_data(item, data); 165 163 166 item->usage = USB_HID_EXTENDED_USAGE( 164 167 item->usages[item->value - 165 168 item->physical_minimum]); 166 169 167 item->usage_page = 170 item->usage_page = 168 171 USB_HID_EXTENDED_USAGE_PAGE( 169 172 item->usages[item->value - … … 171 174 172 175 usb_hid_report_set_last_item( 173 item->collection_path, 174 USB_HID_TAG_CLASS_GLOBAL, 176 item->collection_path, 177 USB_HID_TAG_CLASS_GLOBAL, 175 178 item->usage_page); 176 179 177 180 usb_hid_report_set_last_item( 178 item->collection_path, 181 item->collection_path, 179 182 USB_HID_TAG_CLASS_LOCAL, item->usage); 180 183 } else { 181 184 /* variable item */ 182 item->value = usb_hid_translate_data(item, 185 item->value = usb_hid_translate_data(item, 183 186 data); 184 187 } 185 188 } 186 189 } 187 190 188 191 return EOK; 189 192 } … … 199 202 int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data) 200 203 { 201 int resolution;202 int offset;203 int part_size;204 205 int32_t value = 0;206 int32_t mask = 0;207 const uint8_t *foo = 0;208 209 204 /* now only short tags are allowed */ 210 205 if (item->size > 32) { … … 214 209 if ((item->physical_minimum == 0) && (item->physical_maximum == 0)) { 215 210 item->physical_minimum = item->logical_minimum; 216 item->physical_maximum = item->logical_maximum; 217 } 218 219 211 item->physical_maximum = item->logical_maximum; 212 } 213 214 int resolution; 220 215 if (item->physical_maximum == item->physical_minimum) { 221 resolution = 1; 222 } else { 223 resolution = (item->logical_maximum - item->logical_minimum) / 224 ((item->physical_maximum - item->physical_minimum) * 225 (usb_pow(10, (item->unit_exponent)))); 226 } 227 228 offset = item->offset; 229 // FIXME 230 if ((size_t) (offset / 8) != (size_t) ((offset+item->size - 1) / 8)) { 231 232 part_size = 0; 233 234 size_t i = 0; 235 for (i = (size_t) (offset / 8); 236 i <= (size_t) (offset + item->size - 1) / 8; i++) { 237 if (i == (size_t) (offset / 8)) { 238 /* the higher one */ 239 part_size = 8 - (offset % 8); 240 foo = data + i; 241 mask = ((1 << (item->size - part_size)) - 1); 242 value = (*foo & mask); 243 } else if (i == ((offset + item->size - 1) / 8)) { 244 /* the lower one */ 245 foo = data + i; 246 mask = ((1 << (item->size - part_size)) - 1) << 247 (8 - (item->size - part_size)); 248 249 value = (((*foo & mask) >> (8 - 250 (item->size - part_size))) << part_size) + 251 value; 252 } else { 253 value = (*(data + 1) << (part_size + 8)) + 254 value; 255 part_size += 8; 256 } 257 } 258 } else { 259 foo = data + (offset / 8); 260 mask = ((1 << item->size) - 1) << 261 (8 - ((offset % 8) + item->size)); 262 value = (*foo & mask) >> (8 - ((offset % 8) + item->size)); 216 resolution = 1; 217 } else { 218 resolution = (item->logical_maximum - item->logical_minimum) / 219 ((item->physical_maximum - item->physical_minimum) * 220 (usb_pow(10, (item->unit_exponent)))); 221 } 222 223 int32_t value = 0; 224 225 /* First, skip all bytes we don't care */ 226 data += item->offset / 8; 227 228 int bits = item->size; 229 int taken = 0; 230 231 /* Than we take the higher bits from the LSB */ 232 const unsigned bit_offset = item->offset % 8; 233 const int lsb_bits = min(bits, 8); 234 235 value |= (*data >> bit_offset) & BIT_RRANGE(uint8_t, lsb_bits); 236 bits -= lsb_bits; 237 taken += lsb_bits; 238 data++; 239 240 /* Then there may be bytes, which we take as a whole. */ 241 while (bits > 8) { 242 value |= *data << taken; 243 taken += 8; 244 bits -= 8; 245 data++; 246 } 247 248 /* And, finally, lower bits from HSB. */ 249 if (bits > 0) { 250 value |= (*data & BIT_RRANGE(uint8_t, bits)) << taken; 263 251 } 264 252 … … 267 255 } 268 256 269 return (int) (((value - item->logical_minimum) / resolution) + 257 return (int) (((value - item->logical_minimum) / resolution) + 270 258 item->physical_minimum); 271 259 } … … 274 262 /* OUTPUT API */ 275 263 276 /** 264 /** 277 265 * Allocates output report buffer for output report 278 266 * … … 282 270 * @return Returns allocated output buffer for specified output 283 271 */ 284 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, 272 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, 285 273 uint8_t report_id) 286 274 { … … 334 322 * @return Error code 335 323 */ 336 errno_t usb_hid_report_output_translate(usb_hid_report_t *report, 324 errno_t usb_hid_report_output_translate(usb_hid_report_t *report, 337 325 uint8_t report_id, uint8_t *buffer, size_t size) 338 326 { … … 341 329 int length; 342 330 int32_t tmp_value; 343 331 344 332 if (report == NULL) { 345 333 return EINVAL; … … 351 339 352 340 usb_hid_report_description_t *report_des; 353 report_des = usb_hid_report_find_description(report, report_id, 341 report_des = usb_hid_report_find_description(report, report_id, 354 342 USB_HID_REPORT_TYPE_OUTPUT); 355 343 356 344 if (report_des == NULL) { 357 345 return EINVAL; … … 360 348 list_foreach(report_des->report_items, ritems_link, 361 349 usb_hid_report_field_t, report_item) { 362 value = usb_hid_translate_data_reverse(report_item, 350 value = usb_hid_translate_data_reverse(report_item, 363 351 report_item->value); 364 352 365 353 offset = report_des->bit_length - report_item->offset - 1; 366 354 length = report_item->size; 367 368 usb_log_debug("\ttranslated value: %x \n", value);355 356 usb_log_debug("\ttranslated value: %x", value); 369 357 370 358 if ((offset / 8) == ((offset + length - 1) / 8)) { 371 if (((size_t) (offset / 8) >= size) || 359 if (((size_t) (offset / 8) >= size) || 372 360 ((size_t) (offset + length - 1) / 8) >= size) { 373 361 break; // TODO ErrorCode … … 376 364 value = value << shift; 377 365 value = value & (((1 << length) - 1) << shift); 378 366 379 367 uint8_t mask = 0; 380 368 mask = 0xff - (((1 << length) - 1) << shift); … … 388 376 if (i == (offset / 8)) { 389 377 tmp_value = value; 390 tmp_value = tmp_value & 378 tmp_value = tmp_value & 391 379 ((1 << (8 - (offset % 8))) - 1); 392 380 393 381 tmp_value = tmp_value << (offset % 8); 394 382 395 383 mask = ~(((1 << (8 - (offset % 8))) - 1) 396 384 << (offset % 8)); 397 385 398 buffer[i] = (buffer[i] & mask) | 386 buffer[i] = (buffer[i] & mask) | 399 387 tmp_value; 400 388 } else if (i == ((offset + length - 1) / 8)) { 401 402 value = value >> (length - 389 390 value = value >> (length - 403 391 ((offset + length) % 8)); 404 392 405 value = value & ((1 << (length - 393 value = value & ((1 << (length - 406 394 ((offset + length) % 8))) - 1); 407 408 mask = (1 << (length - 395 396 mask = (1 << (length - 409 397 ((offset + length) % 8))) - 1; 410 398 … … 419 407 report_item->value = 0; 420 408 } 421 409 422 410 return EOK; 423 411 } … … 430 418 * @return ranslated value 431 419 */ 432 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, 420 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, 433 421 int value) 434 422 { … … 437 425 438 426 if (USB_HID_ITEM_FLAG_CONSTANT(item->item_flags)) { 439 ret =item->logical_minimum;427 return item->logical_minimum; 440 428 } 441 429 442 430 if ((item->physical_minimum == 0) && (item->physical_maximum == 0)) { 443 431 item->physical_minimum = item->logical_minimum; 444 item->physical_maximum = item->logical_maximum; 445 } 446 432 item->physical_maximum = item->logical_maximum; 433 } 434 447 435 /* variable item */ 448 436 if (item->physical_maximum == item->physical_minimum) { 449 450 } else { 451 452 ((item->physical_maximum - item->physical_minimum) *453 (usb_pow(10, (item->unit_exponent))));454 } 455 456 ret = ((value - item->physical_minimum) * resolution) + 437 resolution = 1; 438 } else { 439 resolution = (item->logical_maximum - item->logical_minimum) / 440 ((item->physical_maximum - item->physical_minimum) * 441 (usb_pow(10, (item->unit_exponent)))); 442 } 443 444 ret = ((value - item->physical_minimum) * resolution) + 457 445 item->logical_minimum; 458 446 459 447 usb_log_debug("\tvalue(%x), resolution(%x), phymin(%x) logmin(%x), " 460 "ret(%x)\n", value, resolution, item->physical_minimum, 448 "ret(%x)\n", value, resolution, item->physical_minimum, 461 449 item->logical_minimum, ret); 462 450 463 451 if ((item->logical_minimum < 0) || (item->logical_maximum < 0)) { 464 452 return USB_HID_INT32_TO_UINT32(ret, item->size); … … 479 467 { 480 468 usb_hid_report_item_t *new_report_item; 481 469 482 470 if (!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) { 483 471 return NULL; 484 } 472 } 485 473 memcpy(new_report_item,item, sizeof(usb_hid_report_item_t)); 486 474 link_initialize(&(new_report_item->link)); … … 497 485 * @param field Current field. If NULL is given, the first one in the report 498 486 * is returned. Otherwise the next one i nthe list is returned. 499 * @param path Usage path specifying which fields wa are interested in. 487 * @param path Usage path specifying which fields wa are interested in. 500 488 * @param flags Flags defining mode of usage paths comparison 501 489 * @param type Type of report we search. … … 503 491 * @retval Pointer to the founded report structure when founded 504 492 */ 505 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, 506 usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, 493 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, 494 usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, 507 495 usb_hid_report_type_t type) 508 496 { 509 usb_hid_report_description_t *report_des = 497 usb_hid_report_description_t *report_des = 510 498 usb_hid_report_find_description(report, path->report_id, type); 511 499 512 500 link_t *field_it; 513 501 514 502 if (report_des == NULL) { 515 503 return NULL; … … 523 511 524 512 while (field_it != &report_des->report_items.head) { 525 field = list_get_instance(field_it, usb_hid_report_field_t, 513 field = list_get_instance(field_it, usb_hid_report_field_t, 526 514 ritems_link); 527 515 … … 565 553 usb_hid_report_description_t *report_des; 566 554 link_t *report_it; 567 555 568 556 if (report_id > 0) { 569 report_des = usb_hid_report_find_description(report, report_id, 557 report_des = usb_hid_report_find_description(report, report_id, 570 558 type); 571 559 if (report_des == NULL) { … … 573 561 } else { 574 562 report_it = report_des->reports_link.next; 575 } 563 } 576 564 } else { 577 565 report_it = report->reports.head.next; … … 579 567 580 568 while (report_it != &report->reports.head) { 581 report_des = list_get_instance(report_it, 569 report_des = list_get_instance(report_it, 582 570 usb_hid_report_description_t, reports_link); 583 571 … … 606 594 return; 607 595 } 608 596 609 597 report_item->usages_count = 0; 610 598 memset(report_item->usages, 0, USB_HID_MAX_USAGES); 611 599 612 600 report_item->extended_usage_page = 0; 613 601 report_item->usage_minimum = 0;
Note:
See TracChangeset
for help on using the changeset viewer.