Changeset 7943c43 in mainline for uspace/drv/bus/usb/ohci/root_hub.c
- Timestamp:
- 2012-01-16T22:45:38Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 32817cc, 3fe58d3c
- Parents:
- 9117ef9b (diff), 3ea725e (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/drv/bus/usb/ohci/root_hub.c
r9117ef9b r7943c43 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"); 219 226 fibril_mutex_lock(&instance->guard); 220 227 assert(instance->unfinished_interrupt_transfer == NULL); 221 constuint16_t mask = create_interrupt_mask(instance);228 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 /*----------------------------------------------------------------------------*/ … … 251 257 if (instance->unfinished_interrupt_transfer) { 252 258 usb_log_debug("Finalizing interrupt transfer\n"); 253 constuint16_t mask = create_interrupt_mask(instance);259 uint16_t mask = create_interrupt_mask(instance); 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 } … … 274 278 275 279 /* 7 bytes + 2 port bit fields (port count + global bit) */ 276 constsize_t size = 7 + (instance->interrupt_mask_size * 2);280 size_t size = 7 + (instance->interrupt_mask_size * 2); 277 281 assert(size <= HUB_DESCRIPTOR_MAX_SIZE); 278 282 instance->hub_descriptor_size = size; 279 283 280 constuint32_t hub_desc = instance->registers->rh_desc_a;281 constuint32_t port_desc = instance->registers->rh_desc_b;284 uint32_t hub_desc = instance->registers->rh_desc_a; 285 uint32_t port_desc = instance->registers->rh_desc_b; 282 286 283 287 /* bDescLength */ … … 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); 390 394 391 const usb_device_request_setup_packet_t *request_packet = 395 396 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 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 unsigned port = request_packet->index; 423 if (port < 1 || port > instance->port_count) 424 TRANSFER_END(request, EINVAL); 425 426 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 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 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); 435 480 assert(request); 436 481 437 constusb_device_request_setup_packet_t *setup_request =482 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 const uint16_t setup_request_value = setup_request->value_high; 442 //(setup_request->value_low << 8); 484 uint16_t setup_request_value = setup_request->value_high; 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); 609 648 assert(request); 610 649 611 constusb_device_request_setup_packet_t *setup_request =650 usb_device_request_setup_packet_t *setup_request = 612 651 (usb_device_request_setup_packet_t *) request->setup_buffer; 613 652 switch (setup_request->request_type) … … 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 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); 645 686 assert(request); 646 687 647 constusb_device_request_setup_packet_t *setup_request =688 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 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 712 753 usb_log_debug2("CTRL packet: %s.\n", 713 754 usb_debug_str_buffer((uint8_t *) request->setup_buffer, 8, 8)); 714 constusb_device_request_setup_packet_t *setup_request =755 usb_device_request_setup_packet_t *setup_request = 715 756 (usb_device_request_setup_packet_t *) request->setup_buffer; 716 757 switch (setup_request->request) … … 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 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 * @}
Note:
See TracChangeset
for help on using the changeset viewer.