Changes in / [c40f385:89128f3] in mainline
- Location:
- uspace
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/usbinfo/info.c
rc40f385 r89128f3 287 287 void dump_strings(usbinfo_device_t *dev) 288 288 { 289 /* Find used indexes. Devices with more than 64 strings are very rare.*/ 290 uint64_t str_mask = 0; 291 find_string_indexes_callback((uint8_t *)&dev->device_descriptor, 0, 292 &str_mask); 293 usb_dp_walk_simple(dev->full_configuration_descriptor, 294 dev->full_configuration_descriptor_size, 295 usb_dp_standard_descriptor_nesting, 296 find_string_indexes_callback, 297 &str_mask); 298 299 if (str_mask == 0) { 300 printf("Device does not support string descriptors.\n"); 301 return; 302 } 303 289 304 /* Get supported languages. */ 290 305 l18_win_locales_t *langs; … … 305 320 } 306 321 printf(".\n"); 307 308 /* Find used indexes. Device with more than 64 strings are very rare.309 */310 uint64_t str_mask = 0;311 find_string_indexes_callback((uint8_t *)&dev->device_descriptor, 0,312 &str_mask);313 usb_dp_walk_simple(dev->full_configuration_descriptor,314 dev->full_configuration_descriptor_size,315 usb_dp_standard_descriptor_nesting,316 find_string_indexes_callback,317 &str_mask);318 322 319 323 /* Get all strings and dump them. */ -
uspace/drv/bus/usb/ohci/hc.c
rc40f385 r89128f3 137 137 return ret; 138 138 } 139 usb_device_manager_bind_address(&instance->generic.dev_manager,140 instance->rh.address, hub_fun->handle);141 139 142 140 #define CHECK_RET_UNREG_RETURN(ret, message...) \ … … 166 164 "Failed to bind root hub function: %s.\n", str_error(ret)); 167 165 166 ret = usb_device_manager_bind_address(&instance->generic.dev_manager, 167 instance->rh.address, hub_fun->handle); 168 if (ret != EOK) 169 usb_log_warning("Failed to bind root hub address: %s.\n", 170 str_error(ret)); 171 168 172 return EOK; 169 173 #undef CHECK_RET_RELEASE -
uspace/drv/bus/usb/ohci/ohci_batch.c
rc40f385 r89128f3 34 34 #include <errno.h> 35 35 #include <str_error.h> 36 #include <macros.h> 36 37 37 38 #include <usb/usb.h> … … 53 54 return; 54 55 if (ohci_batch->tds) { 56 const ohci_endpoint_t *ohci_ep = 57 ohci_endpoint_get(ohci_batch->usb_batch->ep); 58 assert(ohci_ep); 55 59 for (unsigned i = 0; i < ohci_batch->td_count; ++i) { 56 if ( i != ohci_batch->leave_td)60 if (ohci_batch->tds[i] != ohci_ep->td) 57 61 free32(ohci_batch->tds[i]); 58 62 } … … 64 68 } 65 69 /*----------------------------------------------------------------------------*/ 70 /** Finishes usb_transfer_batch and destroys the structure. 71 * 72 * @param[in] uhci_batch Instance to finish and destroy. 73 */ 66 74 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *ohci_batch) 67 75 { … … 69 77 assert(ohci_batch->usb_batch); 70 78 usb_transfer_batch_finish(ohci_batch->usb_batch, 71 ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size, 72 ohci_batch->usb_batch->buffer_size); 79 ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size); 73 80 ohci_transfer_batch_dispose(ohci_batch); 74 81 } 75 82 /*----------------------------------------------------------------------------*/ 83 /** Allocate memory and initialize internal data structure. 84 * 85 * @param[in] usb_batch Pointer to generic USB batch structure. 86 * @return Valid pointer if all structures were successfully created, 87 * NULL otherwise. 88 * 89 * Determines the number of needed transfer descriptors (TDs). 90 * Prepares a transport buffer (that is accessible by the hardware). 91 * Initializes parameters needed for the transfer and callback. 92 */ 76 93 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *usb_batch) 77 94 { … … 105 122 ohci_batch->ed = ohci_endpoint_get(usb_batch->ep)->ed; 106 123 ohci_batch->tds[0] = ohci_endpoint_get(usb_batch->ep)->td; 107 ohci_batch->leave_td = 0;108 124 109 125 for (unsigned i = 1; i <= ohci_batch->td_count; ++i) { … … 152 168 * completes with the last TD. 153 169 */ 154 bool ohci_transfer_batch_is_complete( ohci_transfer_batch_t *ohci_batch)170 bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *ohci_batch) 155 171 { 156 172 assert(ohci_batch); … … 174 190 175 191 /* Assume we will leave the last(unused) TD behind */ 176 ohci_batch->leave_td = ohci_batch->td_count;192 unsigned leave_td = ohci_batch->td_count; 177 193 178 194 /* Check all TDs */ … … 212 228 * It will be the one TD we leave behind. 213 229 */ 214 ohci_batch->leave_td = i + 1;230 leave_td = i + 1; 215 231 216 232 /* Check TD assumption */ 217 const uint32_t pa = addr_to_phys(218 ohci_batch->tds[ohci_batch->leave_td]);219 assert((ohci_batch->ed->td_head & ED_TD TAIL_PTR_MASK)233 const uint32_t pa = 234 addr_to_phys(ohci_batch->tds[leave_td]); 235 assert((ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK) 220 236 == pa); 221 237 222 238 ed_set_tail_td(ohci_batch->ed, 223 ohci_batch->tds[ ohci_batch->leave_td]);239 ohci_batch->tds[leave_td]); 224 240 225 241 /* Clear possible ED HALT */ … … 234 250 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->usb_batch->ep); 235 251 assert(ohci_ep); 236 ohci_ep->td = ohci_batch->tds[ ohci_batch->leave_td];252 ohci_ep->td = ohci_batch->tds[leave_td]; 237 253 238 254 /* Make sure that we are leaving the right TD behind */ … … 248 264 * @param[in] ohci_batch Batch structure to use 249 265 */ 250 void ohci_transfer_batch_commit( ohci_transfer_batch_t *ohci_batch)266 void ohci_transfer_batch_commit(const ohci_transfer_batch_t *ohci_batch) 251 267 { 252 268 assert(ohci_batch); … … 295 311 while (remain_size > 0) { 296 312 const size_t transfer_size = 297 remain_size > OHCI_TD_MAX_TRANSFER ? 298 OHCI_TD_MAX_TRANSFER : remain_size; 313 min(remain_size, OHCI_TD_MAX_TRANSFER); 299 314 toggle = 1 - toggle; 300 315 … … 378 393 } 379 394 /*----------------------------------------------------------------------------*/ 395 /** Transfer setup table. */ 380 396 static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t) = 381 397 { -
uspace/drv/bus/usb/ohci/ohci_batch.h
rc40f385 r89128f3 53 53 /** Number of TDs used by the transfer */ 54 54 size_t td_count; 55 /** Dummy TD to be left at the ED and used by the next transfer */56 size_t leave_td;57 55 /** Data buffer, must be accessible by the OHCI hw. */ 58 56 char *device_buffer; … … 62 60 63 61 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *batch); 64 bool ohci_transfer_batch_is_complete( ohci_transfer_batch_t *batch);65 void ohci_transfer_batch_commit( ohci_transfer_batch_t *batch);62 bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *batch); 63 void ohci_transfer_batch_commit(const ohci_transfer_batch_t *batch); 66 64 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *batch); 67 65 /*----------------------------------------------------------------------------*/ -
uspace/drv/bus/usb/ohci/root_hub.c
rc40f385 r89128f3 100 100 .attributes = USB_TRANSFER_INTERRUPT, 101 101 .descriptor_type = USB_DESCTYPE_ENDPOINT, 102 .endpoint_address = 1 +(1 << 7),102 .endpoint_address = 1 | (1 << 7), 103 103 .length = sizeof(usb_standard_endpoint_descriptor_t), 104 104 .max_packet_size = 2, … … 109 109 static void rh_init_descriptors(rh_t *instance); 110 110 static uint16_t create_interrupt_mask(const rh_t *instance); 111 static intget_status(const rh_t *instance, usb_transfer_batch_t *request);112 static intget_descriptor(const rh_t *instance, usb_transfer_batch_t *request);113 static intset_feature(const rh_t *instance, usb_transfer_batch_t *request);114 static intclear_feature(const rh_t *instance, usb_transfer_batch_t *request);111 static void get_status(const rh_t *instance, usb_transfer_batch_t *request); 112 static void get_descriptor(const rh_t *instance, usb_transfer_batch_t *request); 113 static void set_feature(const rh_t *instance, usb_transfer_batch_t *request); 114 static void clear_feature(const rh_t *instance, usb_transfer_batch_t *request); 115 115 static int set_feature_port( 116 116 const rh_t *instance, uint16_t feature, uint16_t port); 117 117 static int clear_feature_port( 118 118 const rh_t *instance, uint16_t feature, uint16_t port); 119 static intcontrol_request(rh_t *instance, usb_transfer_batch_t *request);119 static void control_request(rh_t *instance, usb_transfer_batch_t *request); 120 120 static inline void interrupt_request( 121 121 usb_transfer_batch_t *request, uint16_t mask, size_t size) 122 122 { 123 123 assert(request); 124 125 request->transfered_size = size;126 124 usb_transfer_batch_finish_error(request, &mask, size, EOK); 127 } 128 129 #define TRANSFER_OK(bytes) \ 125 usb_transfer_batch_destroy(request); 126 } 127 128 #define TRANSFER_END_DATA(request, data, bytes) \ 130 129 do { \ 131 request->transfered_size = bytes; \ 132 return EOK; \ 130 usb_transfer_batch_finish_error(request, data, bytes, EOK); \ 131 usb_transfer_batch_destroy(request); \ 132 return; \ 133 } while (0) 134 135 #define TRANSFER_END(request, error) \ 136 do { \ 137 usb_transfer_batch_finish_error(request, NULL, 0, error); \ 138 usb_transfer_batch_destroy(request); \ 139 return; \ 133 140 } while (0) 134 141 … … 212 219 case USB_TRANSFER_CONTROL: 213 220 usb_log_debug("Root hub got CONTROL packet\n"); 214 const int ret = control_request(instance, request); 215 usb_transfer_batch_finish_error(request, NULL, 0, ret); 221 control_request(instance, request); 216 222 break; 223 217 224 case USB_TRANSFER_INTERRUPT: 218 225 usb_log_debug("Root hub got INTERRUPT packet\n"); … … 221 228 const uint16_t mask = create_interrupt_mask(instance); 222 229 if (mask == 0) { 223 usb_log_debug("No changes.. \n");230 usb_log_debug("No changes...\n"); 224 231 instance->unfinished_interrupt_transfer = request; 225 fibril_mutex_unlock(&instance->guard); 226 return; 232 } else { 233 usb_log_debug("Processing changes...\n"); 234 interrupt_request( 235 request, mask, instance->interrupt_mask_size); 227 236 } 228 usb_log_debug("Processing changes...\n");229 interrupt_request(request, mask, instance->interrupt_mask_size);230 237 fibril_mutex_unlock(&instance->guard); 231 238 break; … … 233 240 default: 234 241 usb_log_error("Root hub got unsupported request.\n"); 235 usb_transfer_batch_finish_error(request, NULL, 0, EINVAL); 236 } 237 usb_transfer_batch_destroy(request); 242 TRANSFER_END(request, ENOTSUP); 243 } 238 244 } 239 245 /*----------------------------------------------------------------------------*/ … … 254 260 interrupt_request(instance->unfinished_interrupt_transfer, 255 261 mask, instance->interrupt_mask_size); 256 usb_transfer_batch_destroy(257 instance->unfinished_interrupt_transfer);258 262 instance->unfinished_interrupt_transfer = NULL; 259 263 } … … 384 388 * @return error code 385 389 */ 386 intget_status(const rh_t *instance, usb_transfer_batch_t *request)390 void get_status(const rh_t *instance, usb_transfer_batch_t *request) 387 391 { 388 392 assert(instance); 389 393 assert(request); 394 390 395 391 396 const usb_device_request_setup_packet_t *request_packet = 392 397 (usb_device_request_setup_packet_t*)request->setup_buffer; 393 398 394 if (request->buffer_size < 4) { 395 usb_log_error("Buffer too small for get status request.\n"); 396 return EOVERFLOW; 397 } 398 399 switch (request_packet->request_type) 400 { 401 case USB_HUB_REQ_TYPE_GET_HUB_STATUS: 399 402 /* Hub status: just filter relevant info from rh_status reg */ 400 if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) { 401 const uint32_t data = instance->registers->rh_status & 402 (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG); 403 memcpy(request->buffer, &data, sizeof(data)); 404 TRANSFER_OK(sizeof(data)); 405 } 403 if (request->buffer_size < 4) { 404 usb_log_error("Buffer(%zu) too small for hub get " 405 "status request.\n", request->buffer_size); 406 TRANSFER_END(request, EOVERFLOW); 407 } else { 408 const uint32_t data = instance->registers->rh_status & 409 (RHS_LPS_FLAG | RHS_LPSC_FLAG 410 | RHS_OCI_FLAG | RHS_OCIC_FLAG); 411 TRANSFER_END_DATA(request, &data, sizeof(data)); 412 } 406 413 407 414 /* Copy appropriate rh_port_status register, OHCI designers were 408 415 * kind enough to make those bit values match USB specification */ 409 if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) { 410 const unsigned port = request_packet->index; 411 if (port < 1 || port > instance->port_count) 412 return EINVAL; 413 414 const uint32_t data = 415 instance->registers->rh_port_status[port - 1]; 416 memcpy(request->buffer, &data, sizeof(data)); 417 TRANSFER_OK(sizeof(data)); 418 } 419 420 return ENOTSUP; 416 case USB_HUB_REQ_TYPE_GET_PORT_STATUS: 417 if (request->buffer_size < 4) { 418 usb_log_error("Buffer(%zu) too small for hub get " 419 "status request.\n", request->buffer_size); 420 TRANSFER_END(request, EOVERFLOW); 421 } else { 422 const unsigned port = request_packet->index; 423 if (port < 1 || port > instance->port_count) 424 TRANSFER_END(request, EINVAL); 425 426 const uint32_t data = 427 instance->registers->rh_port_status[port - 1]; 428 TRANSFER_END_DATA(request, &data, sizeof(data)); 429 } 430 case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE): 431 if (request->buffer_size < 2) { 432 usb_log_error("Buffer(%zu) too small for hub generic " 433 "get status request.\n", request->buffer_size); 434 TRANSFER_END(request, EOVERFLOW); 435 } else { 436 static const uint16_t data = 437 uint16_host2usb(USB_DEVICE_STATUS_SELF_POWERED); 438 TRANSFER_END_DATA(request, &data, sizeof(data)); 439 } 440 441 case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE): 442 /* Hubs are allowed to have only one interface */ 443 if (request_packet->index != 0) 444 TRANSFER_END(request, EINVAL); 445 /* Fall through, as the answer will be the same: 0x0000 */ 446 case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT): 447 /* Endpoint 0 (default control) and 1 (interrupt) */ 448 if (request_packet->index >= 2) 449 TRANSFER_END(request, EINVAL); 450 451 if (request->buffer_size < 2) { 452 usb_log_error("Buffer(%zu) too small for hub generic " 453 "get status request.\n", request->buffer_size); 454 TRANSFER_END(request, EOVERFLOW); 455 } else { 456 /* Endpoints are OK. (We don't halt) */ 457 static const uint16_t data = 0; 458 TRANSFER_END_DATA(request, &data, sizeof(data)); 459 } 460 461 default: 462 usb_log_error("Unsupported GET_STATUS request.\n"); 463 TRANSFER_END(request, ENOTSUP); 464 } 465 421 466 } 422 467 /*----------------------------------------------------------------------------*/ … … 430 475 * @return Error code 431 476 */ 432 intget_descriptor(const rh_t *instance, usb_transfer_batch_t *request)477 void get_descriptor(const rh_t *instance, usb_transfer_batch_t *request) 433 478 { 434 479 assert(instance); … … 437 482 const usb_device_request_setup_packet_t *setup_request = 438 483 (usb_device_request_setup_packet_t *) request->setup_buffer; 439 size_t size;440 const void *descriptor = NULL;441 484 const uint16_t setup_request_value = setup_request->value_high; 442 //(setup_request->value_low << 8);443 485 switch (setup_request_value) 444 486 { 445 487 case USB_DESCTYPE_HUB: 446 488 usb_log_debug2("USB_DESCTYPE_HUB\n"); 447 /* Hub descriptor was generated locally */448 descriptor = instance->descriptors.hub;449 size = instance->hub_descriptor_size;450 break;489 /* Hub descriptor was generated locally. 490 * Class specific request. */ 491 TRANSFER_END_DATA(request, instance->descriptors.hub, 492 instance->hub_descriptor_size); 451 493 452 494 case USB_DESCTYPE_DEVICE: 453 495 usb_log_debug2("USB_DESCTYPE_DEVICE\n"); 454 /* Device descriptor is shared (No one should ask for it)*/ 455 descriptor = &ohci_rh_device_descriptor; 456 size = sizeof(ohci_rh_device_descriptor); 457 break; 496 /* Device descriptor is shared 497 * (No one should ask for it, as the device is already setup) 498 * Standard USB device request. */ 499 TRANSFER_END_DATA(request, &ohci_rh_device_descriptor, 500 sizeof(ohci_rh_device_descriptor)); 458 501 459 502 case USB_DESCTYPE_CONFIGURATION: 460 503 usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n"); 461 504 /* Start with configuration and add others depending on 462 * request size */ 463 descriptor = &instance->descriptors; 464 size = instance->descriptors.configuration.total_length; 465 break; 505 * request size. Standard USB request. */ 506 TRANSFER_END_DATA(request, &instance->descriptors, 507 instance->descriptors.configuration.total_length); 466 508 467 509 case USB_DESCTYPE_INTERFACE: 468 510 usb_log_debug2("USB_DESCTYPE_INTERFACE\n"); 469 511 /* Use local interface descriptor. There is one and it 470 * might be modified */471 descriptor = &instance->descriptors.interface;472 size = sizeof(instance->descriptors.interface);473 break;512 * might be modified. Hub driver should not ask or this 513 * descriptor as it is not part of standard requests set. */ 514 TRANSFER_END_DATA(request, &instance->descriptors.interface, 515 sizeof(instance->descriptors.interface)); 474 516 475 517 case USB_DESCTYPE_ENDPOINT: 476 518 /* Use local endpoint descriptor. There is one 477 * it might have max_packet_size field modified*/ 519 * it might have max_packet_size field modified. Hub driver 520 * should not ask for this descriptor as it is not part 521 * of standard requests set. */ 478 522 usb_log_debug2("USB_DESCTYPE_ENDPOINT\n"); 479 descriptor = &instance->descriptors.endpoint; 480 size = sizeof(instance->descriptors.endpoint); 481 break; 523 TRANSFER_END_DATA(request, &instance->descriptors.endpoint, 524 sizeof(instance->descriptors.endpoint)); 482 525 483 526 default: … … 489 532 setup_request_value, setup_request->index, 490 533 setup_request->length); 491 return EINVAL; 492 } 493 if (request->buffer_size < size) { 494 size = request->buffer_size; 495 } 496 497 memcpy(request->buffer, descriptor, size); 498 TRANSFER_OK(size); 534 TRANSFER_END(request, EINVAL); 535 } 536 537 TRANSFER_END(request, ENOTSUP); 499 538 } 500 539 /*----------------------------------------------------------------------------*/ … … 604 643 * @return error code 605 644 */ 606 intset_feature(const rh_t *instance, usb_transfer_batch_t *request)645 void set_feature(const rh_t *instance, usb_transfer_batch_t *request) 607 646 { 608 647 assert(instance); … … 615 654 case USB_HUB_REQ_TYPE_SET_PORT_FEATURE: 616 655 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 617 returnset_feature_port(instance,656 const int ret = set_feature_port(instance, 618 657 setup_request->value, setup_request->index); 658 TRANSFER_END(request, ret); 619 659 620 660 case USB_HUB_REQ_TYPE_SET_HUB_FEATURE: … … 623 663 * features. It makes no sense to SET either. */ 624 664 usb_log_error("Invalid HUB set feature request.\n"); 625 return ENOTSUP; 665 TRANSFER_END(request, ENOTSUP); 666 //TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL 626 667 default: 627 668 usb_log_error("Invalid set feature request type: %d\n", 628 669 setup_request->request_type); 629 return EINVAL;670 TRANSFER_END(request, ENOTSUP); 630 671 } 631 672 } … … 640 681 * @return error code 641 682 */ 642 intclear_feature(const rh_t *instance, usb_transfer_batch_t *request)683 void clear_feature(const rh_t *instance, usb_transfer_batch_t *request) 643 684 { 644 685 assert(instance); … … 647 688 const usb_device_request_setup_packet_t *setup_request = 648 689 (usb_device_request_setup_packet_t *) request->setup_buffer; 649 650 request->transfered_size = 0;651 690 652 691 switch (setup_request->request_type) … … 654 693 case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE: 655 694 usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n"); 656 returnclear_feature_port(instance,695 const int ret = clear_feature_port(instance, 657 696 setup_request->value, setup_request->index); 697 TRANSFER_END(request, ret); 658 698 659 699 case USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE: … … 668 708 if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) { 669 709 instance->registers->rh_status = RHS_OCIC_FLAG; 670 TRANSFER_ OK(0);710 TRANSFER_END(request, EOK); 671 711 } 712 //TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL 672 713 default: 673 714 usb_log_error("Invalid clear feature request type: %d\n", 674 715 setup_request->request_type); 675 return EINVAL;716 TRANSFER_END(request, ENOTSUP); 676 717 } 677 718 } … … 695 736 * @return error code 696 737 */ 697 intcontrol_request(rh_t *instance, usb_transfer_batch_t *request)738 void control_request(rh_t *instance, usb_transfer_batch_t *request) 698 739 { 699 740 assert(instance); … … 702 743 if (!request->setup_buffer) { 703 744 usb_log_error("Root hub received empty transaction!"); 704 return EINVAL;745 TRANSFER_END(request, EBADMEM); 705 746 } 706 747 707 748 if (sizeof(usb_device_request_setup_packet_t) > request->setup_size) { 708 749 usb_log_error("Setup packet too small\n"); 709 return EOVERFLOW;750 TRANSFER_END(request, EOVERFLOW); 710 751 } 711 752 … … 718 759 case USB_DEVREQ_GET_STATUS: 719 760 usb_log_debug("USB_DEVREQ_GET_STATUS\n"); 720 return get_status(instance, request); 761 get_status(instance, request); 762 break; 721 763 722 764 case USB_DEVREQ_GET_DESCRIPTOR: 723 765 usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n"); 724 return get_descriptor(instance, request); 766 get_descriptor(instance, request); 767 break; 725 768 726 769 case USB_DEVREQ_GET_CONFIGURATION: 727 770 usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n"); 728 if (request->buffer_size != 1)729 return EINVAL;730 request->buffer[0]= 1;731 TRANSFER_ OK(1);771 if (request->buffer_size == 0) 772 TRANSFER_END(request, EOVERFLOW); 773 static const uint8_t config = 1; 774 TRANSFER_END_DATA(request, &config, sizeof(config)); 732 775 733 776 case USB_DEVREQ_CLEAR_FEATURE: 734 usb_log_debug2(" Processing request without "735 "additional data\n");736 return clear_feature(instance, request);777 usb_log_debug2("USB_DEVREQ_CLEAR_FEATURE\n"); 778 clear_feature(instance, request); 779 break; 737 780 738 781 case USB_DEVREQ_SET_FEATURE: 739 usb_log_debug2(" Processing request without "740 "additional data\n");741 return set_feature(instance, request);782 usb_log_debug2("USB_DEVREQ_SET_FEATURE\n"); 783 set_feature(instance, request); 784 break; 742 785 743 786 case USB_DEVREQ_SET_ADDRESS: 744 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n"); 787 usb_log_debug("USB_DEVREQ_SET_ADDRESS: %u\n", 788 setup_request->value); 789 if (uint16_usb2host(setup_request->value) > 127) 790 TRANSFER_END(request, EINVAL); 791 745 792 instance->address = setup_request->value; 746 TRANSFER_ OK(0);793 TRANSFER_END(request, EOK); 747 794 748 795 case USB_DEVREQ_SET_CONFIGURATION: 749 usb_log_debug("USB_DEVREQ_SET_CONFIGURATION\n"); 750 /* We don't need to do anything */ 751 TRANSFER_OK(0); 752 753 case USB_DEVREQ_SET_DESCRIPTOR: /* Not supported by OHCI RH */ 796 usb_log_debug("USB_DEVREQ_SET_CONFIGURATION: %u\n", 797 setup_request->value); 798 /* We have only one configuration, it's number is 1 */ 799 if (uint16_usb2host(setup_request->value) != 1) 800 TRANSFER_END(request, EINVAL); 801 TRANSFER_END(request, EOK); 802 803 /* Both class specific and std is optional for hubs */ 804 case USB_DEVREQ_SET_DESCRIPTOR: 805 /* Hubs have only one interface GET/SET is not supported */ 806 case USB_DEVREQ_GET_INTERFACE: 807 case USB_DEVREQ_SET_INTERFACE: 754 808 default: 809 /* Hub class GET_STATE(2) falls in here too. */ 755 810 usb_log_error("Received unsupported request: %d.\n", 756 811 setup_request->request); 757 return ENOTSUP; 758 } 759 } 760 812 TRANSFER_END(request, ENOTSUP); 813 } 814 } 761 815 /** 762 816 * @} -
uspace/drv/bus/usb/uhci/hc.c
rc40f385 r89128f3 130 130 uhci_transfer_batch_t *batch = 131 131 uhci_transfer_batch_from_link(item); 132 uhci_transfer_batch_ call_dispose(batch);132 uhci_transfer_batch_finish_dispose(batch); 133 133 } 134 134 } -
uspace/drv/bus/usb/uhci/transfer_list.c
rc40f385 r89128f3 184 184 uhci_transfer_batch_from_link(current); 185 185 transfer_list_remove_batch(instance, batch); 186 batch->usb_batch->error = EINTR; 187 uhci_transfer_batch_call_dispose(batch); 186 uhci_transfer_batch_abort(batch); 188 187 } 189 188 fibril_mutex_unlock(&instance->guard); -
uspace/drv/bus/usb/uhci/uhci_batch.c
rc40f385 r89128f3 34 34 #include <errno.h> 35 35 #include <str_error.h> 36 #include <macros.h> 36 37 37 38 #include <usb/usb.h> … … 45 46 #define DEFAULT_ERROR_COUNT 3 46 47 48 /** Safely destructs uhci_transfer_batch_t structure. 49 * 50 * @param[in] uhci_batch Instance to destroy. 51 */ 47 52 static void uhci_transfer_batch_dispose(uhci_transfer_batch_t *uhci_batch) 48 53 { … … 54 59 } 55 60 /*----------------------------------------------------------------------------*/ 56 /** Safely destructs uhci_transfer_batch_t structure57 * 58 * @param[in] uhci_batch Instance to destroy.59 */ 60 void uhci_transfer_batch_ call_dispose(uhci_transfer_batch_t *uhci_batch)61 /** Finishes usb_transfer_batch and destroys the structure. 62 * 63 * @param[in] uhci_batch Instance to finish and destroy. 64 */ 65 void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch) 61 66 { 62 67 assert(uhci_batch); 63 68 assert(uhci_batch->usb_batch); 64 69 usb_transfer_batch_finish(uhci_batch->usb_batch, 65 uhci_transfer_batch_data_buffer(uhci_batch), 66 uhci_batch->usb_batch->buffer_size); 70 uhci_transfer_batch_data_buffer(uhci_batch)); 67 71 uhci_transfer_batch_dispose(uhci_batch); 68 72 } 69 73 /*----------------------------------------------------------------------------*/ 74 /** Transfer batch setup table. */ 70 75 static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t); 71 76 /*----------------------------------------------------------------------------*/ 72 77 /** Allocate memory and initialize internal data structure. 73 78 * 74 * @param[in] fun DDF function to pass to callback. 75 * @param[in] ep Communication target 76 * @param[in] buffer Data source/destination. 77 * @param[in] buffer_size Size of the buffer. 78 * @param[in] setup_buffer Setup data source (if not NULL) 79 * @param[in] setup_size Size of setup_buffer (should be always 8) 80 * @param[in] func_in function to call on inbound transfer completion 81 * @param[in] func_out function to call on outbound transfer completion 82 * @param[in] arg additional parameter to func_in or func_out 79 * @param[in] usb_batch Pointer to generic USB batch structure. 83 80 * @return Valid pointer if all structures were successfully created, 84 81 * NULL otherwise. … … 156 153 * is reached. 157 154 */ 158 bool uhci_transfer_batch_is_complete( uhci_transfer_batch_t *uhci_batch)155 bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch) 159 156 { 160 157 assert(uhci_batch); … … 200 197 } 201 198 /*----------------------------------------------------------------------------*/ 199 /** Direction to pid conversion table */ 202 200 static const usb_packet_id direction_pids[] = { 203 201 [USB_DIRECTION_IN] = USB_PID_IN, … … 237 235 238 236 while (remain_size > 0) { 239 const size_t packet_size = 240 (remain_size < mps) ? remain_size : mps; 237 const size_t packet_size = min(remain_size, mps); 241 238 242 239 const td_t *next_td = (td + 1 < uhci_batch->td_count) … … 309 306 310 307 while (remain_size > 0) { 311 const size_t packet_size = 312 (remain_size < mps) ? remain_size : mps; 308 const size_t packet_size = min(remain_size, mps); 313 309 314 310 td_init( -
uspace/drv/bus/usb/uhci/uhci_batch.h
rc40f385 r89128f3 61 61 62 62 uhci_transfer_batch_t * uhci_transfer_batch_get(usb_transfer_batch_t *batch); 63 void uhci_transfer_batch_ call_dispose(uhci_transfer_batch_t *uhci_batch);64 bool uhci_transfer_batch_is_complete( uhci_transfer_batch_t *uhci_batch);63 void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch); 64 bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch); 65 65 66 /** Get offset to setup buffer accessible to the HC hw. 67 * @param uhci_batch UHCI batch structure. 68 * @return Pointer to the setup buffer. 69 */ 66 70 static inline void * uhci_transfer_batch_setup_buffer( 67 71 const uhci_transfer_batch_t *uhci_batch) … … 73 77 } 74 78 /*----------------------------------------------------------------------------*/ 79 /** Get offset to data buffer accessible to the HC hw. 80 * @param uhci_batch UHCI batch structure. 81 * @return Pointer to the data buffer. 82 */ 75 83 static inline void * uhci_transfer_batch_data_buffer( 76 84 const uhci_transfer_batch_t *uhci_batch) … … 82 90 } 83 91 /*----------------------------------------------------------------------------*/ 92 /** Aborts the batch. 93 * Sets error to EINTR and size off transferd data to 0, before finishing the 94 * batch. 95 * @param uhci_batch Batch to abort. 96 */ 97 static inline void uhci_transfer_batch_abort(uhci_transfer_batch_t *uhci_batch) 98 { 99 assert(uhci_batch); 100 assert(uhci_batch->usb_batch); 101 uhci_batch->usb_batch->error = EINTR; 102 uhci_batch->usb_batch->transfered_size = 0; 103 uhci_transfer_batch_finish_dispose(uhci_batch); 104 } 105 /*----------------------------------------------------------------------------*/ 106 /** Linked list conversion wrapper. 107 * @param l Linked list link. 108 * @return Pointer to the uhci batch structure. 109 */ 84 110 static inline uhci_transfer_batch_t *uhci_transfer_batch_from_link(link_t *l) 85 111 { -
uspace/lib/usb/include/usb/classes/hub.h
rc40f385 r89128f3 84 84 85 85 /** 86 * @brief usb hub descriptor 87 * 88 * For more information see Universal Serial Bus Specification Revision 1.1 chapter 11.16.2 86 * @brief usb hub descriptor 87 * 88 * For more information see Universal Serial Bus Specification Revision 1.1 89 * chapter 11.16.2 89 90 */ 90 91 typedef struct usb_hub_descriptor_type { -
uspace/lib/usb/src/usb.c
rc40f385 r89128f3 39 39 40 40 static const char *str_speed[] = { 41 "low",42 "full",43 "high"41 [USB_SPEED_LOW] = "low", 42 [USB_SPEED_FULL] = "full", 43 [USB_SPEED_HIGH] = "high", 44 44 }; 45 45 46 46 static const char *str_transfer_type[] = { 47 "control",48 "isochronous",49 "bulk",50 "interrupt"47 [USB_TRANSFER_CONTROL] = "control", 48 [USB_TRANSFER_ISOCHRONOUS] = "isochronous", 49 [USB_TRANSFER_BULK] = "bulk", 50 [USB_TRANSFER_INTERRUPT] = "interrupt", 51 51 }; 52 52 53 53 static const char *str_transfer_type_short[] = { 54 "ctrl",55 "iso",56 "bulk",57 "intr"54 [USB_TRANSFER_CONTROL] = "ctrl", 55 [USB_TRANSFER_ISOCHRONOUS] = "iso", 56 [USB_TRANSFER_BULK] = "bulk", 57 [USB_TRANSFER_INTERRUPT] = "intr", 58 58 }; 59 59 60 60 static const char *str_direction[] = { 61 "in",62 "out",63 "both"61 [USB_DIRECTION_IN] = "in", 62 [USB_DIRECTION_OUT] = "out", 63 [USB_DIRECTION_BOTH] = "both", 64 64 }; 65 65 -
uspace/lib/usbdev/include/usb/dev/request.h
rc40f385 r89128f3 83 83 uint8_t request_type; 84 84 #define SETUP_REQUEST_TYPE_DEVICE_TO_HOST (1 << 7) 85 #define SETUP_REQUEST_TYPE_GET_TYPE(rt) ((rt >> 5) & 0x3) 86 #define SETUP_REQUEST_TYPE_GET_RECIPIENT(rec) (rec & 0x1f) 87 #define SETUP_REQUEST_TO_HOST(type, recipient) \ 88 (uint8_t)((1 << 7) | ((type & 0x3) << 5) | (recipient & 0x1f)) 89 #define SETUP_REQUEST_TO_DEVICE(type, recipient) \ 90 (uint8_t)(((type & 0x3) << 5) | (recipient & 0x1f)) 85 91 86 92 /** Request identification. */ -
uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h
rc40f385 r89128f3 106 106 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance); 107 107 108 void usb_transfer_batch_finish (const usb_transfer_batch_t *instance,109 const void* data, size_t size );108 void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance, 109 const void* data, size_t size, int error); 110 110 /*----------------------------------------------------------------------------*/ 111 /** Override error value and finishes transfer.111 /** Finish batch using stored error value. 112 112 * 113 113 * @param[in] instance Batch structure to use. 114 114 * @param[in] data Data to copy to the output buffer. 115 115 * @param[in] size Size of @p data. 116 * @param[in] error Set batch status to this error value.117 116 */ 118 static inline void usb_transfer_batch_finish _error(119 usb_transfer_batch_t *instance, const void* data, size_t size, int error)117 static inline void usb_transfer_batch_finish( 118 const usb_transfer_batch_t *instance, const void* data) 120 119 { 121 120 assert(instance); 122 instance->error = error;123 usb_transfer_batch_finish(instance, data, size);121 usb_transfer_batch_finish_error( 122 instance, data, instance->transfered_size, instance->error); 124 123 } 125 124 /*----------------------------------------------------------------------------*/ -
uspace/lib/usbhost/src/usb_transfer_batch.c
rc40f385 r89128f3 33 33 */ 34 34 #include <errno.h> 35 #include < str_error.h>35 #include <macros.h> 36 36 37 37 #include <usb/usb.h> … … 121 121 * @param[in] data Data to copy to the output buffer. 122 122 * @param[in] size Size of @p data. 123 * @param[in] error Error value to use. 123 124 */ 124 void usb_transfer_batch_finish (125 const usb_transfer_batch_t *instance, const void *data, size_t size)125 void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance, 126 const void *data, size_t size, int error) 126 127 { 127 128 assert(instance); … … 133 134 /* Check for commands that reset toggle bit */ 134 135 if (instance->ep->transfer_type == USB_TRANSFER_CONTROL 135 && instance->error == EOK) {136 && error == EOK) { 136 137 const usb_target_t target = 137 138 {{ instance->ep->address, instance->ep->endpoint }}; … … 139 140 instance->setup_buffer); 140 141 } 141 instance->callback_out(instance->fun, 142 instance->error, instance->arg); 142 instance->callback_out(instance->fun, error, instance->arg); 143 143 } 144 144 145 145 if (instance->callback_in) { 146 146 /* We care about the data and there are some to copy */ 147 const size_t safe_size = min(size, instance->buffer_size); 147 148 if (data) { 148 const size_t min_size = size < instance->buffer_size 149 ? size : instance->buffer_size; 150 memcpy(instance->buffer, data, min_size); 149 memcpy(instance->buffer, data, safe_size); 151 150 } 152 instance->callback_in(instance->fun, instance->error,153 instance->transfered_size, instance->arg);151 instance->callback_in(instance->fun, error, 152 safe_size, instance->arg); 154 153 } 155 154 }
Note:
See TracChangeset
for help on using the changeset viewer.