Changeset e9e58ea3 in mainline for uspace/lib/usb/src/request.c
- Timestamp:
- 2011-02-25T15:03:29Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 6cbe7dad
- Parents:
- 233e68d (diff), 3b0fb049 (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/request.c
r233e68d re9e58ea3 230 230 } 231 231 232 /** Retrieve USB descriptor, allocate space for it. 233 * 234 * @param[in] pipe Control endpoint pipe (session must be already started). 235 * @param[in] request_type Request type (standard/class/vendor). 236 * @param[in] descriptor_type Descriptor type (device/configuration/HID/...). 237 * @param[in] descriptor_index Descriptor index. 238 * @param[in] language Language index. 239 * @param[out] buffer_ptr Where to store pointer to allocated buffer. 240 * @param[out] buffer_size Where to store the size of the descriptor. 241 * @return 242 */ 243 int usb_request_get_descriptor_alloc(usb_endpoint_pipe_t * pipe, 244 usb_request_type_t request_type, 245 uint8_t descriptor_type, uint8_t descriptor_index, 246 uint16_t language, 247 void **buffer_ptr, size_t *buffer_size) 248 { 249 if (buffer_ptr == NULL) { 250 return EBADMEM; 251 } 252 253 int rc; 254 255 /* 256 * Get only first byte to retrieve descriptor length. 257 */ 258 uint8_t tmp_buffer[1]; 259 size_t bytes_transfered; 260 rc = usb_request_get_descriptor(pipe, request_type, 261 descriptor_type, descriptor_index, language, 262 &tmp_buffer, 1, &bytes_transfered); 263 if (rc != EOK) { 264 return rc; 265 } 266 if (bytes_transfered != 1) { 267 /* FIXME: some better error code? */ 268 return ESTALL; 269 } 270 271 size_t size = tmp_buffer[0]; 272 if (size == 0) { 273 /* FIXME: some better error code? */ 274 return ESTALL; 275 } 276 277 /* 278 * Allocate buffer and get the descriptor again. 279 */ 280 void *buffer = malloc(size); 281 if (buffer == NULL) { 282 return ENOMEM; 283 } 284 285 rc = usb_request_get_descriptor(pipe, request_type, 286 descriptor_type, descriptor_index, language, 287 buffer, size, &bytes_transfered); 288 if (rc != EOK) { 289 free(buffer); 290 return rc; 291 } 292 if (bytes_transfered != size) { 293 free(buffer); 294 /* FIXME: some better error code? */ 295 return ESTALL; 296 } 297 298 *buffer_ptr = buffer; 299 if (buffer_size != NULL) { 300 *buffer_size = size; 301 } 302 303 return EOK; 304 } 305 232 306 /** Retrieve standard device descriptor of a USB device. 233 307 * … … 355 429 } 356 430 431 /** Get list of supported languages by USB device. 432 * 433 * @param[in] pipe Control endpoint pipe (session must be already started). 434 * @param[out] languages_ptr Where to store pointer to allocated array of 435 * supported languages. 436 * @param[out] languages_count Number of supported languages. 437 * @return Error code. 438 */ 439 int usb_request_get_supported_languages(usb_endpoint_pipe_t *pipe, 440 l18_win_locales_t **languages_ptr, size_t *languages_count) 441 { 442 int rc; 443 444 if (languages_ptr == NULL) { 445 return EBADMEM; 446 } 447 if (languages_count == NULL) { 448 return EBADMEM; 449 } 450 451 uint8_t *string_descriptor = NULL; 452 size_t string_descriptor_size = 0; 453 rc = usb_request_get_descriptor_alloc(pipe, 454 USB_REQUEST_TYPE_STANDARD, USB_DESCTYPE_STRING, 0, 0, 455 (void **) &string_descriptor, &string_descriptor_size); 456 if (rc != EOK) { 457 return rc; 458 } 459 if (string_descriptor_size <= 2) { 460 free(string_descriptor); 461 return EEMPTY; 462 } 463 /* Substract first 2 bytes (length and descriptor type). */ 464 string_descriptor_size -= 2; 465 466 /* Odd number of bytes - descriptor is broken? */ 467 if ((string_descriptor_size % 2) != 0) { 468 /* FIXME: shall we return with error or silently ignore? */ 469 free(string_descriptor); 470 return ESTALL; 471 } 472 473 size_t langs_count = string_descriptor_size / 2; 474 l18_win_locales_t *langs 475 = malloc(sizeof(l18_win_locales_t) * langs_count); 476 if (langs == NULL) { 477 free(string_descriptor); 478 return ENOMEM; 479 } 480 481 size_t i; 482 for (i = 0; i < langs_count; i++) { 483 /* Language code from the descriptor is in USB endianess. */ 484 /* FIXME: is this really correct? */ 485 uint16_t lang_code = (string_descriptor[2 + 2 * i + 1] << 8) 486 + string_descriptor[2 + 2 * i]; 487 langs[i] = uint16_usb2host(lang_code); 488 } 489 490 free(string_descriptor); 491 492 *languages_ptr = langs; 493 *languages_count =langs_count; 494 495 return EOK; 496 } 497 498 /** Get string (descriptor) from USB device. 499 * 500 * The string is returned in native encoding of the operating system. 501 * For HelenOS, that is UTF-8. 502 * 503 * @param[in] pipe Control endpoint pipe (session must be already started). 504 * @param[in] index String index (in native endianess). 505 * @param[in] lang String language (in native endianess). 506 * @param[out] string_ptr Where to store allocated string in native encoding. 507 * @return Error code. 508 */ 509 int usb_request_get_string(usb_endpoint_pipe_t *pipe, 510 size_t index, l18_win_locales_t lang, char **string_ptr) 511 { 512 if (string_ptr == NULL) { 513 return EBADMEM; 514 } 515 /* Index is actually one byte value. */ 516 if (index > 0xFF) { 517 return ERANGE; 518 } 519 /* Language is actually two byte value. */ 520 if (lang > 0xFFFF) { 521 return ERANGE; 522 } 523 524 int rc; 525 526 /* Prepare dynamically allocated variables. */ 527 uint8_t *string = NULL; 528 wchar_t *string_chars = NULL; 529 530 /* Get the actual descriptor. */ 531 size_t string_size; 532 rc = usb_request_get_descriptor_alloc(pipe, 533 USB_REQUEST_TYPE_STANDARD, USB_DESCTYPE_STRING, 534 index, uint16_host2usb(lang), 535 (void **) &string, &string_size); 536 if (rc != EOK) { 537 goto leave; 538 } 539 540 if (string_size <= 2) { 541 rc = EEMPTY; 542 goto leave; 543 } 544 /* Substract first 2 bytes (length and descriptor type). */ 545 string_size -= 2; 546 547 /* Odd number of bytes - descriptor is broken? */ 548 if ((string_size % 2) != 0) { 549 /* FIXME: shall we return with error or silently ignore? */ 550 rc = ESTALL; 551 goto leave; 552 } 553 554 size_t string_char_count = string_size / 2; 555 string_chars = malloc(sizeof(wchar_t) * (string_char_count + 1)); 556 if (string_chars == NULL) { 557 rc = ENOMEM; 558 goto leave; 559 } 560 561 /* 562 * Build a wide string. 563 * And do not forget to set NULL terminator (string descriptors 564 * do not have them). 565 */ 566 size_t i; 567 for (i = 0; i < string_char_count; i++) { 568 uint16_t uni_char = (string[2 + 2 * i + 1] << 8) 569 + string[2 + 2 * i]; 570 string_chars[i] = uni_char; 571 } 572 string_chars[string_char_count] = 0; 573 574 575 /* Convert to normal string. */ 576 char *str = wstr_to_astr(string_chars); 577 if (str == NULL) { 578 rc = ENOMEM; 579 goto leave; 580 } 581 582 *string_ptr = str; 583 rc = EOK; 584 585 leave: 586 if (string != NULL) { 587 free(string); 588 } 589 if (string_chars != NULL) { 590 free(string_chars); 591 } 592 593 return rc; 594 } 595 357 596 /** 358 597 * @}
Note:
See TracChangeset
for help on using the changeset viewer.