diff options
author | Frank Gevaerts <frank@gevaerts.be> | 2009-04-19 19:53:32 +0000 |
---|---|---|
committer | Frank Gevaerts <frank@gevaerts.be> | 2009-04-19 19:53:32 +0000 |
commit | 08b04cc5870bc78e653a9093d186999a5d263407 (patch) | |
tree | 4e84f765ef9c6903a0dbfe82380bd6bc9c71bcbf | |
parent | b71aad65f5b69e2c3212a3efdd3abca29516c450 (diff) | |
download | rockbox-08b04cc5870bc78e653a9093d186999a5d263407.tar.gz rockbox-08b04cc5870bc78e653a9093d186999a5d263407.zip |
reorganise usb_core.c a bit, to make the code more readable and more maintainable (FS#10150 by Tomer Shalev))
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20748 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/export/usb_ch9.h | 18 | ||||
-rw-r--r-- | firmware/export/usb_core.h | 8 | ||||
-rw-r--r-- | firmware/usbstack/usb_core.c | 519 |
3 files changed, 299 insertions, 246 deletions
diff --git a/firmware/export/usb_ch9.h b/firmware/export/usb_ch9.h index 560a737354..f05dbd3265 100644 --- a/firmware/export/usb_ch9.h +++ b/firmware/export/usb_ch9.h | |||
@@ -109,6 +109,24 @@ | |||
109 | #define USB_REQ_GET_INTERFACE 0x0A | 109 | #define USB_REQ_GET_INTERFACE 0x0A |
110 | #define USB_REQ_SET_INTERFACE 0x0B | 110 | #define USB_REQ_SET_INTERFACE 0x0B |
111 | #define USB_REQ_SYNCH_FRAME 0x0C | 111 | #define USB_REQ_SYNCH_FRAME 0x0C |
112 | /* | ||
113 | * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and | ||
114 | * are read as a bit array returned by USB_REQ_GET_STATUS. (So there | ||
115 | * are at most sixteen features of each type.) Hubs may also support a | ||
116 | * new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend. | ||
117 | */ | ||
118 | #define USB_DEVICE_SELF_POWERED 0 /* (read only) */ | ||
119 | #define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */ | ||
120 | #define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */ | ||
121 | #define USB_DEVICE_BATTERY 2 /* (wireless) */ | ||
122 | #define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */ | ||
123 | #define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/ | ||
124 | #define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */ | ||
125 | #define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */ | ||
126 | #define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */ | ||
127 | |||
128 | #define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ | ||
129 | |||
112 | 130 | ||
113 | /** | 131 | /** |
114 | * struct usb_ctrlrequest - SETUP data for a USB device control request | 132 | * struct usb_ctrlrequest - SETUP data for a USB device control request |
diff --git a/firmware/export/usb_core.h b/firmware/export/usb_core.h index ba2820b1ad..aac84756f5 100644 --- a/firmware/export/usb_core.h +++ b/firmware/export/usb_core.h | |||
@@ -42,16 +42,16 @@ struct usb_class_driver; | |||
42 | void usb_core_init(void); | 42 | void usb_core_init(void); |
43 | void usb_core_exit(void); | 43 | void usb_core_exit(void); |
44 | void usb_core_control_request(struct usb_ctrlrequest* req); | 44 | void usb_core_control_request(struct usb_ctrlrequest* req); |
45 | void usb_core_transfer_complete(int endpoint, int dir, int status, int length); | 45 | void usb_core_transfer_complete(int endpoint,int dir,int status,int length); |
46 | void usb_core_bus_reset(void); | 46 | void usb_core_bus_reset(void); |
47 | bool usb_core_any_exclusive_storage(void); | 47 | bool usb_core_any_exclusive_storage(void); |
48 | void usb_core_enable_driver(int driver,bool enabled); | 48 | void usb_core_enable_driver(int driver,bool enabled); |
49 | bool usb_core_driver_enabled (int driver); | 49 | bool usb_core_driver_enabled(int driver); |
50 | void usb_core_handle_transfer_completion( | 50 | void usb_core_handle_transfer_completion( |
51 | struct usb_transfer_completion_event_data* event); | 51 | struct usb_transfer_completion_event_data* event); |
52 | int usb_core_ack_control(struct usb_ctrlrequest* req); | 52 | int usb_core_ack_control(struct usb_ctrlrequest* req); |
53 | 53 | ||
54 | int usb_core_request_endpoint(int dir, struct usb_class_driver *drv); | 54 | int usb_core_request_endpoint(int dir,struct usb_class_driver* drv); |
55 | void usb_core_release_endpoint(int dir); | 55 | void usb_core_release_endpoint(int dir); |
56 | 56 | ||
57 | #ifdef HAVE_HOTSWAP | 57 | #ifdef HAVE_HOTSWAP |
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c index f6373b8945..8c235723ad 100644 --- a/firmware/usbstack/usb_core.c +++ b/firmware/usbstack/usb_core.c | |||
@@ -167,7 +167,7 @@ static enum { DEFAULT, ADDRESS, CONFIGURED } usb_state; | |||
167 | static int usb_core_num_interfaces; | 167 | static int usb_core_num_interfaces; |
168 | 168 | ||
169 | typedef void (*completion_handler_t)(int ep,int dir, int status, int length); | 169 | typedef void (*completion_handler_t)(int ep,int dir, int status, int length); |
170 | typedef bool (*control_handler_t)(struct usb_ctrlrequest* req, unsigned char *dest); | 170 | typedef bool (*control_handler_t)(struct usb_ctrlrequest* req, unsigned char* dest); |
171 | 171 | ||
172 | static struct | 172 | static struct |
173 | { | 173 | { |
@@ -435,13 +435,13 @@ static void usb_core_set_serial_function_id(void) | |||
435 | usb_string_iSerial.wString[0] = hex[id]; | 435 | usb_string_iSerial.wString[0] = hex[id]; |
436 | } | 436 | } |
437 | 437 | ||
438 | int usb_core_request_endpoint(int dir, struct usb_class_driver *drv) | 438 | int usb_core_request_endpoint(int dir, struct usb_class_driver* drv) |
439 | { | 439 | { |
440 | int ret, ep; | 440 | int ret, ep; |
441 | 441 | ||
442 | ret = usb_drv_request_endpoint(dir); | 442 | ret = usb_drv_request_endpoint(dir); |
443 | 443 | ||
444 | if (ret == -1) | 444 | if (ret==-1) |
445 | return -1; | 445 | return -1; |
446 | 446 | ||
447 | ep = ret & 0x7f; | 447 | ep = ret & 0x7f; |
@@ -494,270 +494,305 @@ static void allocate_interfaces_and_endpoints(void) | |||
494 | usb_core_num_interfaces = interface; | 494 | usb_core_num_interfaces = interface; |
495 | } | 495 | } |
496 | 496 | ||
497 | static void usb_core_control_request_handler(struct usb_ctrlrequest* req) | 497 | static void control_request_handler_drivers(struct usb_ctrlrequest* req) |
498 | { | 498 | { |
499 | int i; | 499 | int i; |
500 | if(usb_state == DEFAULT) { | 500 | bool handled=false; |
501 | set_serial_descriptor(); | 501 | for(i=0;i<USB_NUM_DRIVERS;i++) { |
502 | usb_core_set_serial_function_id(); | 502 | if(drivers[i].enabled && |
503 | 503 | drivers[i].control_request && | |
504 | allocate_interfaces_and_endpoints(); | 504 | drivers[i].first_interface <= (req->wIndex) && |
505 | drivers[i].last_interface > (req->wIndex)) | ||
506 | { | ||
507 | handled = drivers[i].control_request(req, response_data); | ||
508 | if(handled) | ||
509 | break; | ||
510 | } | ||
505 | } | 511 | } |
512 | if(!handled) { | ||
513 | /* nope. flag error */ | ||
514 | logf("bad req:desc %d:%d", req->bRequest, req->wValue>>8); | ||
515 | usb_drv_stall(EP_CONTROL, true,true); | ||
516 | usb_core_ack_control(req); | ||
517 | } | ||
518 | } | ||
506 | 519 | ||
507 | switch(req->bRequestType & 0x1f) { | 520 | static void request_handler_device_get_descriptor(struct usb_ctrlrequest* req) |
508 | case 0: /* Device */ | 521 | { |
509 | switch (req->bRequest) { | 522 | int size; |
510 | case USB_REQ_GET_CONFIGURATION: { | 523 | bool handled = true; |
511 | logf("usb_core: GET_CONFIG"); | 524 | const void* ptr = NULL; |
512 | if (usb_state == ADDRESS) | 525 | int length = req->wLength; |
513 | response_data[0] = 0; | 526 | int index = req->wValue & 0xff; |
514 | else | 527 | |
515 | response_data[0] = 1; | 528 | switch(req->wValue>>8) { /* type */ |
516 | if(usb_drv_send(EP_CONTROL, response_data, 1)!= 0) | 529 | case USB_DT_DEVICE: |
517 | break; | 530 | ptr = &device_descriptor; |
518 | usb_core_ack_control(req); | 531 | size = sizeof(struct usb_device_descriptor); |
519 | break; | 532 | break; |
520 | } | 533 | |
521 | case USB_REQ_SET_CONFIGURATION: { | 534 | case USB_DT_OTHER_SPEED_CONFIG: |
522 | logf("usb_core: SET_CONFIG"); | 535 | case USB_DT_CONFIG: { |
523 | usb_drv_cancel_all_transfers(); | 536 | int i, max_packet_size; |
524 | if (req->wValue) { | 537 | |
525 | usb_state = CONFIGURED; | 538 | if(req->wValue>>8==USB_DT_CONFIG) { |
526 | for(i=0;i<USB_NUM_DRIVERS;i++) { | 539 | max_packet_size=(usb_drv_port_speed() ? 512 : 64); |
527 | if(drivers[i].enabled && | 540 | config_descriptor.bDescriptorType=USB_DT_CONFIG; |
528 | drivers[i].init_connection!=NULL) | ||
529 | { | ||
530 | drivers[i].init_connection(); | ||
531 | } | ||
532 | } | ||
533 | } | ||
534 | else { | ||
535 | usb_state = ADDRESS; | ||
536 | } | ||
537 | usb_core_ack_control(req); | ||
538 | break; | ||
539 | } | 541 | } |
540 | case USB_REQ_SET_ADDRESS: { | 542 | else { |
541 | unsigned char address = req->wValue; | 543 | max_packet_size=(usb_drv_port_speed() ? 64 : 512); |
542 | logf("usb_core: SET_ADR %d", address); | 544 | config_descriptor.bDescriptorType = |
543 | if(usb_core_ack_control(req)!=0) | 545 | USB_DT_OTHER_SPEED_CONFIG; |
544 | break; | ||
545 | usb_drv_cancel_all_transfers(); | ||
546 | usb_address = address; | ||
547 | usb_drv_set_address(usb_address); | ||
548 | usb_state = ADDRESS; | ||
549 | break; | ||
550 | } | 546 | } |
551 | case USB_REQ_GET_DESCRIPTOR: { | 547 | size = sizeof(struct usb_config_descriptor); |
552 | int index = req->wValue & 0xff; | ||
553 | int length = req->wLength; | ||
554 | int size; | ||
555 | const void* ptr = NULL; | ||
556 | logf("usb_core: GET_DESC %d", req->wValue >> 8); | ||
557 | |||
558 | switch (req->wValue >> 8) { /* type */ | ||
559 | case USB_DT_DEVICE: | ||
560 | ptr = &device_descriptor; | ||
561 | size = sizeof(struct usb_device_descriptor); | ||
562 | break; | ||
563 | |||
564 | case USB_DT_OTHER_SPEED_CONFIG: | ||
565 | case USB_DT_CONFIG: { | ||
566 | int max_packet_size; | ||
567 | |||
568 | if(req->wValue >> 8 == USB_DT_CONFIG) { | ||
569 | if(usb_drv_port_speed()) | ||
570 | max_packet_size=512; | ||
571 | else | ||
572 | max_packet_size=64; | ||
573 | config_descriptor.bDescriptorType=USB_DT_CONFIG; | ||
574 | } | ||
575 | else { | ||
576 | if(usb_drv_port_speed()) | ||
577 | max_packet_size=64; | ||
578 | else | ||
579 | max_packet_size=512; | ||
580 | config_descriptor.bDescriptorType = | ||
581 | USB_DT_OTHER_SPEED_CONFIG; | ||
582 | } | ||
583 | size = sizeof(struct usb_config_descriptor); | ||
584 | |||
585 | for(i=0;i<USB_NUM_DRIVERS;i++) { | ||
586 | if(drivers[i].enabled && | ||
587 | drivers[i].get_config_descriptor) | ||
588 | { | ||
589 | size+=drivers[i].get_config_descriptor( | ||
590 | &response_data[size], | ||
591 | max_packet_size); | ||
592 | } | ||
593 | } | ||
594 | config_descriptor.bNumInterfaces = | ||
595 | usb_core_num_interfaces; | ||
596 | config_descriptor.wTotalLength = size; | ||
597 | memcpy(&response_data[0],&config_descriptor, | ||
598 | sizeof(struct usb_config_descriptor)); | ||
599 | |||
600 | ptr = response_data; | ||
601 | break; | ||
602 | } | ||
603 | |||
604 | case USB_DT_STRING: | ||
605 | logf("STRING %d",index); | ||
606 | if ((unsigned)index < (sizeof(usb_strings)/ | ||
607 | sizeof(struct usb_string_descriptor*))) | ||
608 | { | ||
609 | size = usb_strings[index]->bLength; | ||
610 | ptr = usb_strings[index]; | ||
611 | } | ||
612 | else { | ||
613 | logf("bad string id %d", index); | ||
614 | usb_drv_stall(EP_CONTROL, true,true); | ||
615 | } | ||
616 | break; | ||
617 | |||
618 | case USB_DT_DEVICE_QUALIFIER: | ||
619 | ptr = &qualifier_descriptor; | ||
620 | size = sizeof (struct usb_qualifier_descriptor); | ||
621 | break; | ||
622 | |||
623 | default: | ||
624 | logf("bad desc %d", req->wValue >> 8); | ||
625 | usb_drv_stall(EP_CONTROL, true,true); | ||
626 | break; | ||
627 | } | ||
628 | 548 | ||
629 | if (ptr) { | 549 | for(i=0;i<USB_NUM_DRIVERS;i++) { |
630 | length = MIN(size, length); | 550 | if(drivers[i].enabled && drivers[i].get_config_descriptor) { |
551 | size+=drivers[i].get_config_descriptor( | ||
552 | &response_data[size],max_packet_size); | ||
553 | } | ||
554 | } | ||
555 | config_descriptor.bNumInterfaces = usb_core_num_interfaces; | ||
556 | config_descriptor.wTotalLength = size; | ||
557 | memcpy(&response_data[0],&config_descriptor, | ||
558 | sizeof(struct usb_config_descriptor)); | ||
631 | 559 | ||
632 | if (ptr != response_data) { | 560 | ptr = response_data; |
633 | memcpy(response_data, ptr, length); | 561 | break; |
634 | } | 562 | } |
635 | 563 | ||
636 | if(usb_drv_send(EP_CONTROL, response_data, length)!=0) | 564 | case USB_DT_STRING: |
637 | break; | 565 | logf("STRING %d",index); |
638 | } | 566 | if ((unsigned)index < (sizeof(usb_strings)/ |
639 | usb_core_ack_control(req); | 567 | sizeof(struct usb_string_descriptor*))) { |
640 | break; | 568 | size = usb_strings[index]->bLength; |
641 | } /* USB_REQ_GET_DESCRIPTOR */ | 569 | ptr = usb_strings[index]; |
642 | case USB_REQ_CLEAR_FEATURE: | 570 | } |
643 | break; | 571 | else { |
644 | case USB_REQ_SET_FEATURE: | 572 | logf("bad string id %d",index); |
645 | if(req->wValue == 2) { /* TEST_MODE */ | 573 | usb_drv_stall(EP_CONTROL,true,true); |
646 | int mode=req->wIndex>>8; | ||
647 | usb_core_ack_control(req); | ||
648 | usb_drv_set_test_mode(mode); | ||
649 | } | ||
650 | break; | ||
651 | case USB_REQ_GET_STATUS: | ||
652 | response_data[0]= 0; | ||
653 | response_data[1]= 0; | ||
654 | if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) | ||
655 | break; | ||
656 | usb_core_ack_control(req); | ||
657 | break; | ||
658 | default: | ||
659 | break; | ||
660 | } | 574 | } |
661 | break; | 575 | break; |
662 | case 1: /* Interface */ | ||
663 | switch (req->bRequest) { | ||
664 | case USB_REQ_SET_INTERFACE: | ||
665 | logf("usb_core: SET_INTERFACE"); | ||
666 | usb_core_ack_control(req); | ||
667 | break; | ||
668 | 576 | ||
669 | case USB_REQ_GET_INTERFACE: | 577 | case USB_DT_DEVICE_QUALIFIER: |
670 | logf("usb_core: GET_INTERFACE"); | 578 | ptr = &qualifier_descriptor; |
671 | response_data[0] = 0; | 579 | size = sizeof(struct usb_qualifier_descriptor); |
672 | if(usb_drv_send(EP_CONTROL, response_data, 1)!=0) | 580 | break; |
673 | break; | 581 | |
674 | usb_core_ack_control(req); | 582 | default: |
675 | break; | 583 | logf("ctrl desc."); |
676 | case USB_REQ_CLEAR_FEATURE: | 584 | handled = false; |
677 | break; | 585 | control_request_handler_drivers(req); |
678 | case USB_REQ_SET_FEATURE: | 586 | break; |
679 | break; | 587 | } |
680 | case USB_REQ_GET_STATUS: | 588 | |
681 | response_data[0]= 0; | 589 | if (ptr) { |
682 | response_data[1]= 0; | 590 | logf("data %d (%d)",size,length); |
683 | if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) | 591 | length = MIN(size,length); |
684 | break; | 592 | |
593 | if (ptr != response_data) { | ||
594 | memcpy(response_data,ptr,length); | ||
595 | } | ||
596 | |||
597 | if(usb_drv_send(EP_CONTROL,response_data,length)) | ||
598 | return; | ||
599 | } | ||
600 | if (handled) | ||
601 | usb_core_ack_control(req); | ||
602 | } | ||
603 | |||
604 | static void request_handler_device(struct usb_ctrlrequest* req) | ||
605 | { | ||
606 | int i; | ||
607 | |||
608 | switch(req->bRequest) { | ||
609 | case USB_REQ_GET_CONFIGURATION: { | ||
610 | logf("usb_core: GET_CONFIG"); | ||
611 | response_data[0] = (usb_state == ADDRESS ? 0 : 1); | ||
612 | if(!usb_drv_send(EP_CONTROL, response_data, 1)) | ||
685 | usb_core_ack_control(req); | 613 | usb_core_ack_control(req); |
686 | break; | 614 | break; |
687 | default: { | 615 | } |
688 | bool handled=false; | 616 | case USB_REQ_SET_CONFIGURATION: { |
617 | logf("usb_core: SET_CONFIG"); | ||
618 | usb_drv_cancel_all_transfers(); | ||
619 | if(req->wValue) { | ||
620 | usb_state = CONFIGURED; | ||
689 | for(i=0;i<USB_NUM_DRIVERS;i++) { | 621 | for(i=0;i<USB_NUM_DRIVERS;i++) { |
690 | if(drivers[i].enabled && | 622 | if(drivers[i].enabled && drivers[i].init_connection) |
691 | drivers[i].control_request && | 623 | drivers[i].init_connection(); |
692 | drivers[i].first_interface <= (req->wIndex) && | ||
693 | drivers[i].last_interface > (req->wIndex)) | ||
694 | { | ||
695 | handled = drivers[i].control_request(req, response_data); | ||
696 | } | ||
697 | } | ||
698 | if(!handled) { | ||
699 | /* nope. flag error */ | ||
700 | logf("usb bad req %d", req->bRequest); | ||
701 | usb_drv_stall(EP_CONTROL, true,true); | ||
702 | usb_core_ack_control(req); | ||
703 | } | 624 | } |
704 | break; | ||
705 | } | 625 | } |
626 | else { | ||
627 | usb_state = ADDRESS; | ||
628 | } | ||
629 | usb_core_ack_control(req); | ||
630 | break; | ||
706 | } | 631 | } |
707 | break; | 632 | case USB_REQ_SET_ADDRESS: { |
708 | case 2: /* Endpoint */ | 633 | unsigned char address = req->wValue; |
709 | switch (req->bRequest) { | 634 | logf("usb_core: SET_ADR %d", address); |
710 | case USB_REQ_CLEAR_FEATURE: | 635 | if(usb_core_ack_control(req)) |
711 | if (req->wValue == 0 ) /* ENDPOINT_HALT */ | ||
712 | usb_drv_stall(req->wIndex & 0xf, false, | ||
713 | (req->wIndex & 0x80) !=0); | ||
714 | usb_core_ack_control(req); | ||
715 | break; | 636 | break; |
716 | case USB_REQ_SET_FEATURE: | 637 | usb_drv_cancel_all_transfers(); |
717 | if (req->wValue == 0 ) /* ENDPOINT_HALT */ | 638 | usb_address = address; |
718 | usb_drv_stall(req->wIndex & 0xf, true, | 639 | usb_drv_set_address(usb_address); |
719 | (req->wIndex & 0x80) !=0); | 640 | usb_state = ADDRESS; |
720 | usb_core_ack_control(req); | 641 | break; |
642 | } | ||
643 | case USB_REQ_GET_DESCRIPTOR: | ||
644 | logf("usb_core: GET_DESC %d", req->wValue>>8); | ||
645 | request_handler_device_get_descriptor(req); | ||
646 | break; | ||
647 | case USB_REQ_CLEAR_FEATURE: | ||
648 | break; | ||
649 | case USB_REQ_SET_FEATURE: | ||
650 | if(req->wValue==USB_DEVICE_TEST_MODE) { | ||
651 | int mode=req->wIndex>>8; | ||
652 | usb_core_ack_control(req); | ||
653 | usb_drv_set_test_mode(mode); | ||
654 | } | ||
655 | break; | ||
656 | case USB_REQ_GET_STATUS: | ||
657 | response_data[0]= 0; | ||
658 | response_data[1]= 0; | ||
659 | if(!usb_drv_send(EP_CONTROL, response_data, 2)) | ||
660 | usb_core_ack_control(req); | ||
661 | break; | ||
662 | default: | ||
663 | break; | ||
664 | } | ||
665 | } | ||
666 | |||
667 | static void request_handler_interface_standard(struct usb_ctrlrequest* req) | ||
668 | { | ||
669 | switch (req->bRequest) | ||
670 | { | ||
671 | case USB_REQ_SET_INTERFACE: | ||
672 | logf("usb_core: SET_INTERFACE"); | ||
673 | usb_core_ack_control(req); | ||
674 | break; | ||
675 | |||
676 | case USB_REQ_GET_INTERFACE: | ||
677 | logf("usb_core: GET_INTERFACE"); | ||
678 | response_data[0]=0; | ||
679 | if(!usb_drv_send(EP_CONTROL,response_data,1)) | ||
680 | usb_core_ack_control(req); | ||
681 | break; | ||
682 | case USB_REQ_CLEAR_FEATURE: | ||
683 | break; | ||
684 | case USB_REQ_SET_FEATURE: | ||
685 | break; | ||
686 | case USB_REQ_GET_STATUS: | ||
687 | response_data[0]=0; | ||
688 | response_data[1]=0; | ||
689 | if(!usb_drv_send(EP_CONTROL, response_data, 2)) | ||
690 | usb_core_ack_control(req); | ||
691 | break; | ||
692 | default: | ||
693 | control_request_handler_drivers(req); | ||
694 | break; | ||
695 | } | ||
696 | } | ||
697 | |||
698 | static void request_handler_interface(struct usb_ctrlrequest* req) | ||
699 | { | ||
700 | switch(req->bRequestType & USB_TYPE_MASK) { | ||
701 | case USB_TYPE_STANDARD: | ||
702 | request_handler_interface_standard(req); | ||
703 | break; | ||
704 | case USB_TYPE_CLASS: | ||
705 | control_request_handler_drivers(req); | ||
706 | break; | ||
707 | case USB_TYPE_VENDOR: | ||
708 | break; | ||
709 | } | ||
710 | } | ||
711 | |||
712 | static void request_handler_endpoint(struct usb_ctrlrequest* req) | ||
713 | { | ||
714 | switch (req->bRequest) { | ||
715 | case USB_REQ_CLEAR_FEATURE: | ||
716 | if (req->wValue==USB_ENDPOINT_HALT) { | ||
717 | usb_drv_stall(req->wIndex & 0xf, false, | ||
718 | (req->wIndex & USB_DIR_IN)!=0); | ||
719 | } | ||
720 | usb_core_ack_control(req); | ||
721 | break; | ||
722 | case USB_REQ_SET_FEATURE: | ||
723 | if (req->wValue==USB_ENDPOINT_HALT) { | ||
724 | usb_drv_stall(req->wIndex & 0xf,true, | ||
725 | (req->wIndex & USB_DIR_IN)!=0); | ||
726 | } | ||
727 | usb_core_ack_control(req); | ||
728 | break; | ||
729 | case USB_REQ_GET_STATUS: | ||
730 | response_data[0]=0; | ||
731 | response_data[1]=0; | ||
732 | logf("usb_core: GET_STATUS"); | ||
733 | if(req->wIndex>0) { | ||
734 | response_data[0]=usb_drv_stalled(req->wIndex & 0xf, | ||
735 | (req->wIndex & USB_DIR_IN)!=0); | ||
736 | } | ||
737 | if(!usb_drv_send(EP_CONTROL,response_data,2)) | ||
738 | usb_core_ack_control(req); | ||
739 | break; | ||
740 | default: { | ||
741 | bool handled; | ||
742 | control_handler_t control_handler; | ||
743 | |||
744 | control_handler=ep_data[req->wIndex & 0xf].control_handler[0]; | ||
745 | if (!control_handler) | ||
721 | break; | 746 | break; |
722 | case USB_REQ_GET_STATUS: | 747 | |
723 | response_data[0]= 0; | 748 | handled=control_handler(req, response_data); |
724 | response_data[1]= 0; | 749 | if (!handled) { |
725 | logf("usb_core: GET_STATUS"); | 750 | /* nope. flag error */ |
726 | if(req->wIndex>0) | 751 | logf("usb bad req %d",req->bRequest); |
727 | response_data[0] = usb_drv_stalled(req->wIndex&0xf, | 752 | usb_drv_stall(EP_CONTROL,true,true); |
728 | (req->wIndex&0x80)!=0); | ||
729 | if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) | ||
730 | break; | ||
731 | usb_core_ack_control(req); | 753 | usb_core_ack_control(req); |
732 | break; | ||
733 | default: { | ||
734 | bool handled=false; | ||
735 | if(ep_data[req->wIndex & 0xf].control_handler[0] != NULL) { | ||
736 | handled = ep_data[req->wIndex & 0xf].control_handler[0](req, | ||
737 | response_data); | ||
738 | } | ||
739 | if(!handled) { | ||
740 | /* nope. flag error */ | ||
741 | logf("usb bad req %d", req->bRequest); | ||
742 | usb_drv_stall(EP_CONTROL, true,true); | ||
743 | usb_core_ack_control(req); | ||
744 | } | ||
745 | break; | ||
746 | } | 754 | } |
755 | break; | ||
747 | } | 756 | } |
748 | } | 757 | } |
749 | logf("control handled"); | 758 | } |
759 | |||
760 | /* Handling USB requests starts here */ | ||
761 | static void usb_core_control_request_handler(struct usb_ctrlrequest* req) | ||
762 | { | ||
763 | if (usb_state==DEFAULT) { | ||
764 | set_serial_descriptor(); | ||
765 | usb_core_set_serial_function_id(); | ||
766 | |||
767 | allocate_interfaces_and_endpoints(); | ||
768 | } | ||
769 | |||
770 | switch(req->bRequestType & USB_RECIP_MASK) { | ||
771 | case USB_RECIP_DEVICE: | ||
772 | request_handler_device(req); | ||
773 | break; | ||
774 | case USB_RECIP_INTERFACE: | ||
775 | request_handler_interface(req); | ||
776 | break; | ||
777 | case USB_RECIP_ENDPOINT: | ||
778 | request_handler_endpoint(req); | ||
779 | break; | ||
780 | case USB_RECIP_OTHER: | ||
781 | logf("unsupported recipient"); | ||
782 | break; | ||
783 | } | ||
784 | //logf("control handled"); | ||
750 | } | 785 | } |
751 | 786 | ||
752 | /* called by usb_drv_int() */ | 787 | /* called by usb_drv_int() */ |
753 | void usb_core_bus_reset(void) | 788 | void usb_core_bus_reset(void) |
754 | { | 789 | { |
755 | usb_address = 0; | 790 | usb_address=0; |
756 | usb_state = DEFAULT; | 791 | usb_state=DEFAULT; |
757 | } | 792 | } |
758 | 793 | ||
759 | /* called by usb_drv_transfer_completed() */ | 794 | /* called by usb_drv_transfer_completed() */ |
760 | void usb_core_transfer_complete(int endpoint, int dir, int status,int length) | 795 | void usb_core_transfer_complete(int endpoint,int dir,int status,int length) |
761 | { | 796 | { |
762 | struct usb_transfer_completion_event_data *completion_event; | 797 | struct usb_transfer_completion_event_data *completion_event; |
763 | 798 | ||
@@ -767,7 +802,7 @@ void usb_core_transfer_complete(int endpoint, int dir, int status,int length) | |||
767 | break; | 802 | break; |
768 | 803 | ||
769 | default: | 804 | default: |
770 | completion_event = &ep_data[endpoint].completion_event; | 805 | completion_event=&ep_data[endpoint].completion_event; |
771 | 806 | ||
772 | completion_event->endpoint=endpoint; | 807 | completion_event->endpoint=endpoint; |
773 | completion_event->dir=dir; | 808 | completion_event->dir=dir; |
@@ -783,12 +818,12 @@ void usb_core_transfer_complete(int endpoint, int dir, int status,int length) | |||
783 | /* called by usb_drv_int() */ | 818 | /* called by usb_drv_int() */ |
784 | void usb_core_control_request(struct usb_ctrlrequest* req) | 819 | void usb_core_control_request(struct usb_ctrlrequest* req) |
785 | { | 820 | { |
786 | struct usb_transfer_completion_event_data *completion_event = | 821 | struct usb_transfer_completion_event_data* completion_event = |
787 | &ep_data[0].completion_event; | 822 | &ep_data[0].completion_event; |
788 | 823 | ||
789 | completion_event->endpoint=0; | 824 | completion_event->endpoint=0; |
790 | completion_event->dir=0; | 825 | completion_event->dir=0; |
791 | completion_event->data=(void *)req; | 826 | completion_event->data=(void*)req; |
792 | completion_event->status=0; | 827 | completion_event->status=0; |
793 | completion_event->length=0; | 828 | completion_event->length=0; |
794 | logf("ctrl received %ld",current_tick); | 829 | logf("ctrl received %ld",current_tick); |
@@ -798,14 +833,14 @@ void usb_core_control_request(struct usb_ctrlrequest* req) | |||
798 | int usb_core_ack_control(struct usb_ctrlrequest* req) | 833 | int usb_core_ack_control(struct usb_ctrlrequest* req) |
799 | { | 834 | { |
800 | if (req->bRequestType & USB_DIR_IN) | 835 | if (req->bRequestType & USB_DIR_IN) |
801 | return usb_drv_recv(EP_CONTROL, NULL, 0); | 836 | return usb_drv_recv(EP_CONTROL,NULL,0); |
802 | else | 837 | else |
803 | return usb_drv_send(EP_CONTROL, NULL, 0); | 838 | return usb_drv_send(EP_CONTROL,NULL,0); |
804 | } | 839 | } |
805 | 840 | ||
806 | #ifdef HAVE_USB_POWER | 841 | #ifdef HAVE_USB_POWER |
807 | unsigned short usb_allowed_current() | 842 | unsigned short usb_allowed_current() |
808 | { | 843 | { |
809 | return (usb_state == CONFIGURED) ? MAX(USB_MAX_CURRENT, 100) : 100; | 844 | return (usb_state==CONFIGURED) ? MAX(USB_MAX_CURRENT, 100) : 100; |
810 | } | 845 | } |
811 | #endif | 846 | #endif |