summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/isp1583.c8
-rw-r--r--firmware/export/usb.h2
-rw-r--r--firmware/export/usb_core.h13
-rw-r--r--firmware/export/usb_drv.h2
-rw-r--r--firmware/ifp_usb_serial.c3
-rw-r--r--firmware/target/arm/usb-drv-arc.c185
-rw-r--r--firmware/target/arm/usb-tcc.c5
-rw-r--r--firmware/target/mips/ingenic_jz47xx/usb-jz4740.c7
-rw-r--r--firmware/usb.c6
-rw-r--r--firmware/usbstack/usb_charging_only.c2
-rw-r--r--firmware/usbstack/usb_class_driver.h6
-rw-r--r--firmware/usbstack/usb_core.c40
-rw-r--r--firmware/usbstack/usb_hid.c346
-rw-r--r--firmware/usbstack/usb_hid.h3
-rw-r--r--firmware/usbstack/usb_serial.c11
-rw-r--r--firmware/usbstack/usb_storage.c11
16 files changed, 416 insertions, 234 deletions
diff --git a/firmware/drivers/isp1583.c b/firmware/drivers/isp1583.c
index f373741586..fa97305b52 100644
--- a/firmware/drivers/isp1583.c
+++ b/firmware/drivers/isp1583.c
@@ -29,9 +29,6 @@
29#include "logf.h" 29#include "logf.h"
30#include "stdio.h" 30#include "stdio.h"
31 31
32#define DIR_RX 0
33#define DIR_TX 1
34
35struct usb_endpoint 32struct usb_endpoint
36{ 33{
37 unsigned char *out_buf; 34 unsigned char *out_buf;
@@ -602,9 +599,12 @@ void usb_drv_cancel_all_transfers(void)
602 endpoints[i].halt[0] = endpoints[i].halt[1] = 1; 599 endpoints[i].halt[0] = endpoints[i].halt[1] = 1;
603} 600}
604 601
605int usb_drv_request_endpoint(int dir) 602int usb_drv_request_endpoint(int type, int dir)
606{ 603{
607 int i, bit; 604 int i, bit;
605
606 if (type != USB_ENDPOINT_XFER_BULK)
607 return -1;
608 608
609 bit=(dir & USB_DIR_IN)? 2:1; 609 bit=(dir & USB_DIR_IN)? 2:1;
610 610
diff --git a/firmware/export/usb.h b/firmware/export/usb.h
index e1bacfffc7..42893c3468 100644
--- a/firmware/export/usb.h
+++ b/firmware/export/usb.h
@@ -105,7 +105,7 @@ struct usb_transfer_completion_event_data
105 int length; 105 int length;
106 void* data; 106 void* data;
107}; 107};
108#endif 108#endif /* HAVE_USBSTACK */
109 109
110void usb_init(void); 110void usb_init(void);
111void usb_enable(bool on); 111void usb_enable(bool on);
diff --git a/firmware/export/usb_core.h b/firmware/export/usb_core.h
index abf090ed9d..9c105fbc7c 100644
--- a/firmware/export/usb_core.h
+++ b/firmware/export/usb_core.h
@@ -36,6 +36,17 @@
36 36
37/* endpoints */ 37/* endpoints */
38#define EP_CONTROL 0 38#define EP_CONTROL 0
39
40#define DIR_OUT 0
41#define DIR_IN 1
42
43/* The USB core is a device, and OUT is RX from that P.O.V */
44#define DIR_RX DIR_OUT
45#define DIR_TX DIR_IN
46
47#define EP_DIR(ep) (((ep) & USB_ENDPOINT_DIR_MASK) ? DIR_IN : DIR_OUT)
48#define EP_NUM(ep) ((ep) & USB_ENDPOINT_NUMBER_MASK)
49
39extern int usb_max_pkt_size; 50extern int usb_max_pkt_size;
40 51
41struct usb_class_driver; 52struct usb_class_driver;
@@ -52,7 +63,7 @@ void usb_core_handle_transfer_completion(
52 struct usb_transfer_completion_event_data* event); 63 struct usb_transfer_completion_event_data* event);
53int usb_core_ack_control(struct usb_ctrlrequest* req); 64int usb_core_ack_control(struct usb_ctrlrequest* req);
54 65
55int usb_core_request_endpoint(int dir,struct usb_class_driver* drv); 66int usb_core_request_endpoint(int type, int dir,struct usb_class_driver* drv);
56void usb_core_release_endpoint(int dir); 67void usb_core_release_endpoint(int dir);
57 68
58#ifdef HAVE_HOTSWAP 69#ifdef HAVE_HOTSWAP
diff --git a/firmware/export/usb_drv.h b/firmware/export/usb_drv.h
index 0c99630b11..fad9c79c10 100644
--- a/firmware/export/usb_drv.h
+++ b/firmware/export/usb_drv.h
@@ -44,7 +44,7 @@ int usb_drv_port_speed(void);
44void usb_drv_cancel_all_transfers(void); 44void usb_drv_cancel_all_transfers(void);
45void usb_drv_set_test_mode(int mode); 45void usb_drv_set_test_mode(int mode);
46bool usb_drv_connected(void); 46bool usb_drv_connected(void);
47int usb_drv_request_endpoint(int dir); 47int usb_drv_request_endpoint(int type, int dir);
48void usb_drv_release_endpoint(int ep); 48void usb_drv_release_endpoint(int ep);
49 49
50#endif /* _USB_DRV_H */ 50#endif /* _USB_DRV_H */
diff --git a/firmware/ifp_usb_serial.c b/firmware/ifp_usb_serial.c
index e6c8dadfc5..06b286ab85 100644
--- a/firmware/ifp_usb_serial.c
+++ b/firmware/ifp_usb_serial.c
@@ -63,9 +63,6 @@
63 63
64#define ISP1582_UNLOCK_CODE 0xaa37 64#define ISP1582_UNLOCK_CODE 0xaa37
65 65
66#define DIR_RX 0
67#define DIR_TX 1
68
69#define TYPE_BULK 2 66#define TYPE_BULK 2
70 67
71#define STATE_DEFAULT 0 68#define STATE_DEFAULT 0
diff --git a/firmware/target/arm/usb-drv-arc.c b/firmware/target/arm/usb-drv-arc.c
index 200601eb24..8a10c5fbd6 100644
--- a/firmware/target/arm/usb-drv-arc.c
+++ b/firmware/target/arm/usb-drv-arc.c
@@ -248,10 +248,6 @@
248#define EPCTRL_RX_EP_STALL (0x00000001) 248#define EPCTRL_RX_EP_STALL (0x00000001)
249 249
250/* bit 19-18 and 3-2 are endpoint type */ 250/* bit 19-18 and 3-2 are endpoint type */
251#define EPCTRL_EP_TYPE_CONTROL (0)
252#define EPCTRL_EP_TYPE_ISO (1)
253#define EPCTRL_EP_TYPE_BULK (2)
254#define EPCTRL_EP_TYPE_INTERRUPT (3)
255#define EPCTRL_TX_EP_TYPE_SHIFT (18) 251#define EPCTRL_TX_EP_TYPE_SHIFT (18)
256#define EPCTRL_RX_EP_TYPE_SHIFT (2) 252#define EPCTRL_RX_EP_TYPE_SHIFT (2)
257 253
@@ -312,6 +308,14 @@
312 transfer size, so it seems like a good size */ 308 transfer size, so it seems like a good size */
313#define NUM_TDS_PER_EP 4 309#define NUM_TDS_PER_EP 4
314 310
311typedef struct usb_endpoint
312{
313 bool allocated[2];
314 short type[2];
315 short max_pkt_size[2];
316} usb_endpoint_t;
317static usb_endpoint_t endpoints[USB_NUM_ENDPOINTS];
318
315/* manual: 32.13.2 Endpoint Transfer Descriptor (dTD) */ 319/* manual: 32.13.2 Endpoint Transfer Descriptor (dTD) */
316struct transfer_descriptor { 320struct transfer_descriptor {
317 unsigned int next_td_ptr; /* Next TD pointer(31-5), T(0) set 321 unsigned int next_td_ptr; /* Next TD pointer(31-5), T(0) set
@@ -356,16 +360,12 @@ static const unsigned int pipe2mask[] = {
356 0x10, 0x100000, 360 0x10, 0x100000,
357}; 361};
358 362
359static char ep_allocation[USB_NUM_ENDPOINTS];
360
361/*-------------------------------------------------------------------------*/ 363/*-------------------------------------------------------------------------*/
362static void transfer_completed(void); 364static void transfer_completed(void);
363static void control_received(void); 365static void control_received(void);
364static int prime_transfer(int endpoint, void* ptr, 366static int prime_transfer(int ep_num, void* ptr, int len, bool send, bool wait);
365 int len, bool send, bool wait);
366static void prepare_td(struct transfer_descriptor* td, 367static void prepare_td(struct transfer_descriptor* td,
367 struct transfer_descriptor* previous_td, 368 struct transfer_descriptor* previous_td, void *ptr, int len,int pipe);
368 void *ptr, int len,int pipe);
369static void bus_reset(void); 369static void bus_reset(void);
370static void init_control_queue_heads(void); 370static void init_control_queue_heads(void);
371static void init_bulk_queue_heads(void); 371static void init_bulk_queue_heads(void);
@@ -394,7 +394,7 @@ void usb_drv_reset(void)
394 while (REG_USBCMD & USBCMD_CTRL_RESET); 394 while (REG_USBCMD & USBCMD_CTRL_RESET);
395 395
396#if CONFIG_CPU == PP5022 || CONFIG_CPU == PP5024 396#if CONFIG_CPU == PP5022 || CONFIG_CPU == PP5024
397 /* On a CPU which identifies as a PP5022, this 397 /* On a CPU which identifies as a PP5022, this
398 initialization must be done after USB is reset. 398 initialization must be done after USB is reset.
399 */ 399 */
400 outl(inl(0x70000060) | 0xF, 0x70000060); 400 outl(inl(0x70000060) | 0xF, 0x70000060);
@@ -475,6 +475,27 @@ static void _usb_drv_init(bool attach)
475 (void)attach; 475 (void)attach;
476} 476}
477 477
478#ifdef LOGF_ENABLE
479#define XFER_DIR_STR(dir) ((dir) ? "IN" : "OUT")
480#define XFER_TYPE_STR(type) \
481 ((type) == USB_ENDPOINT_XFER_CONTROL ? "CTRL" : \
482 ((type) == USB_ENDPOINT_XFER_ISOC ? "ISOC" : \
483 ((type) == USB_ENDPOINT_XFER_BULK ? "BULK" : \
484 ((type) == USB_ENDPOINT_XFER_INT ? "INTR" : "INVL"))))
485
486static void log_ep(int ep_num, int ep_dir, char* prefix)
487{
488 usb_endpoint_t* endpoint = &endpoints[ep_num];
489
490 logf("%s: ep%d %s %s %d", prefix, ep_num, XFER_DIR_STR(ep_dir),
491 XFER_TYPE_STR(endpoint->type[ep_dir]),
492 endpoint->max_pkt_size[ep_dir]);
493}
494#else
495#undef log_ep
496#define log_ep(...)
497#endif
498
478void usb_drv_init(void) 499void usb_drv_init(void)
479{ 500{
480 _usb_drv_init(false); 501 _usb_drv_init(false);
@@ -483,6 +504,7 @@ void usb_drv_init(void)
483/* fully enable driver */ 504/* fully enable driver */
484void usb_drv_attach(void) 505void usb_drv_attach(void)
485{ 506{
507 logf("usb_drv_attach");
486 sleep(HZ/10); 508 sleep(HZ/10);
487 _usb_drv_init(true); 509 _usb_drv_init(true);
488} 510}
@@ -555,49 +577,51 @@ void usb_drv_int(void)
555bool usb_drv_stalled(int endpoint,bool in) 577bool usb_drv_stalled(int endpoint,bool in)
556{ 578{
557 if(in) { 579 if(in) {
558 return ((REG_ENDPTCTRL(endpoint&0x7f) & EPCTRL_TX_EP_STALL)!=0); 580 return ((REG_ENDPTCTRL(EP_NUM(endpoint)) & EPCTRL_TX_EP_STALL)!=0);
559 } 581 }
560 else { 582 else {
561 return ((REG_ENDPTCTRL(endpoint&0x7f) & EPCTRL_RX_EP_STALL)!=0); 583 return ((REG_ENDPTCTRL(EP_NUM(endpoint)) & EPCTRL_RX_EP_STALL)!=0);
562 } 584 }
563 585
564} 586}
565void usb_drv_stall(int endpoint, bool stall,bool in) 587void usb_drv_stall(int endpoint, bool stall, bool in)
566{ 588{
567 logf("%sstall %d", stall?"":"un", endpoint&0x7f); 589 int ep_num = EP_NUM(endpoint);
590
591 logf("%sstall %d", stall ? "" : "un", ep_num);
568 592
569 if(in) { 593 if(in) {
570 if (stall) { 594 if (stall) {
571 REG_ENDPTCTRL(endpoint&0x7f) |= EPCTRL_TX_EP_STALL; 595 REG_ENDPTCTRL(ep_num) |= EPCTRL_TX_EP_STALL;
572 } 596 }
573 else { 597 else {
574 REG_ENDPTCTRL(endpoint&0x7f) &= ~EPCTRL_TX_EP_STALL; 598 REG_ENDPTCTRL(ep_num) &= ~EPCTRL_TX_EP_STALL;
575 } 599 }
576 } 600 }
577 else { 601 else {
578 if (stall) { 602 if (stall) {
579 REG_ENDPTCTRL(endpoint) |= EPCTRL_RX_EP_STALL; 603 REG_ENDPTCTRL(ep_num) |= EPCTRL_RX_EP_STALL;
580 } 604 }
581 else { 605 else {
582 REG_ENDPTCTRL(endpoint) &= ~EPCTRL_RX_EP_STALL; 606 REG_ENDPTCTRL(ep_num) &= ~EPCTRL_RX_EP_STALL;
583 } 607 }
584 } 608 }
585} 609}
586 610
587int usb_drv_send_nonblocking(int endpoint, void* ptr, int length) 611int usb_drv_send_nonblocking(int endpoint, void* ptr, int length)
588{ 612{
589 return prime_transfer(endpoint&0x7f, ptr, length, true, false); 613 return prime_transfer(EP_NUM(endpoint), ptr, length, true, false);
590} 614}
591 615
592int usb_drv_send(int endpoint, void* ptr, int length) 616int usb_drv_send(int endpoint, void* ptr, int length)
593{ 617{
594 return prime_transfer(endpoint&0x7f, ptr, length, true, true); 618 return prime_transfer(EP_NUM(endpoint), ptr, length, true, true);
595} 619}
596 620
597int usb_drv_recv(int endpoint, void* ptr, int length) 621int usb_drv_recv(int endpoint, void* ptr, int length)
598{ 622{
599 //logf("usbrecv(%x, %d)", ptr, length); 623 //logf("usbrecv(%x, %d)", ptr, length);
600 return prime_transfer(endpoint&0x7f, ptr, length, false, false); 624 return prime_transfer(EP_NUM(endpoint), ptr, length, false, false);
601} 625}
602 626
603int usb_drv_port_speed(void) 627int usb_drv_port_speed(void)
@@ -627,7 +651,7 @@ void usb_drv_set_address(int address)
627 651
628void usb_drv_reset_endpoint(int endpoint, bool send) 652void usb_drv_reset_endpoint(int endpoint, bool send)
629{ 653{
630 int pipe = (endpoint&0x7f) * 2 + (send ? 1 : 0); 654 int pipe = EP_NUM(endpoint) * 2 + (send ? 1 : 0);
631 unsigned int mask = pipe2mask[pipe]; 655 unsigned int mask = pipe2mask[pipe];
632 REG_ENDPTFLUSH = mask; 656 REG_ENDPTFLUSH = mask;
633 while (REG_ENDPTFLUSH & mask); 657 while (REG_ENDPTFLUSH & mask);
@@ -662,23 +686,23 @@ void usb_drv_set_test_mode(int mode)
662/*-------------------------------------------------------------------------*/ 686/*-------------------------------------------------------------------------*/
663 687
664/* manual: 32.14.5.2 */ 688/* manual: 32.14.5.2 */
665static int prime_transfer(int endpoint, void* ptr, int len, bool send, bool wait) 689static int prime_transfer(int ep_num, void* ptr, int len, bool send, bool wait)
666{ 690{
667 int rc = 0; 691 int rc = 0;
668 int pipe = endpoint * 2 + (send ? 1 : 0); 692 int pipe = ep_num * 2 + (send ? 1 : 0);
669 unsigned int mask = pipe2mask[pipe]; 693 unsigned int mask = pipe2mask[pipe];
670 struct queue_head* qh = &qh_array[pipe]; 694 struct queue_head* qh = &qh_array[pipe];
671 static long last_tick; 695 static long last_tick;
672 struct transfer_descriptor* new_td,*cur_td,*prev_td; 696 struct transfer_descriptor *new_td, *cur_td, *prev_td;
673 697
674 int oldlevel = disable_irq_save(); 698 int oldlevel = disable_irq_save();
675/* 699/*
676 if (send && endpoint > EP_CONTROL) { 700 if (send && ep_num > EP_CONTROL) {
677 logf("usb: sent %d bytes", len); 701 logf("usb: sent %d bytes", len);
678 } 702 }
679*/ 703*/
680 qh->status = 0; 704 qh->status = 0;
681 qh->wait = wait; 705 qh->wait = wait;
682 706
683 new_td=&td_array[pipe*NUM_TDS_PER_EP]; 707 new_td=&td_array[pipe*NUM_TDS_PER_EP];
684 cur_td=new_td; 708 cur_td=new_td;
@@ -694,15 +718,15 @@ static int prime_transfer(int endpoint, void* ptr, int len, bool send, bool wait
694 cur_td++; 718 cur_td++;
695 len-=tdlen; 719 len-=tdlen;
696 } 720 }
697 while(len>0 ); 721 while(len>0);
698 //logf("starting ep %d %s",endpoint,send?"send":"receive"); 722 //logf("starting ep %d %s",ep_num,send?"send":"receive");
699 723
700 qh->dtd.next_td_ptr = (unsigned int)new_td; 724 qh->dtd.next_td_ptr = (unsigned int)new_td;
701 qh->dtd.size_ioc_sts &= ~(QH_STATUS_HALT | QH_STATUS_ACTIVE); 725 qh->dtd.size_ioc_sts &= ~(QH_STATUS_HALT | QH_STATUS_ACTIVE);
702 726
703 REG_ENDPTPRIME |= mask; 727 REG_ENDPTPRIME |= mask;
704 728
705 if(endpoint == EP_CONTROL && (REG_ENDPTSETUPSTAT & EPSETUP_STATUS_EP0)) { 729 if(ep_num == EP_CONTROL && (REG_ENDPTSETUPSTAT & EPSETUP_STATUS_EP0)) {
706 /* 32.14.3.2.2 */ 730 /* 32.14.3.2.2 */
707 logf("new setup arrived"); 731 logf("new setup arrived");
708 rc = -4; 732 rc = -4;
@@ -724,11 +748,11 @@ static int prime_transfer(int endpoint, void* ptr, int len, bool send, bool wait
724 } 748 }
725 749
726 if (!(REG_ENDPTSTATUS & mask)) { 750 if (!(REG_ENDPTSTATUS & mask)) {
727 logf("no prime! %d %d %x", endpoint, pipe, qh->dtd.size_ioc_sts & 0xff ); 751 logf("no prime! %d %d %x", ep_num, pipe, qh->dtd.size_ioc_sts & 0xff);
728 rc = -3; 752 rc = -3;
729 goto pt_error; 753 goto pt_error;
730 } 754 }
731 if(endpoint == EP_CONTROL && (REG_ENDPTSETUPSTAT & EPSETUP_STATUS_EP0)) { 755 if(ep_num == EP_CONTROL && (REG_ENDPTSETUPSTAT & EPSETUP_STATUS_EP0)) {
732 /* 32.14.3.2.2 */ 756 /* 32.14.3.2.2 */
733 logf("new setup arrived"); 757 logf("new setup arrived");
734 rc = -4; 758 rc = -4;
@@ -780,17 +804,38 @@ void usb_drv_cancel_all_transfers(void)
780 } 804 }
781} 805}
782 806
783int usb_drv_request_endpoint(int dir) 807int usb_drv_request_endpoint(int type, int dir)
784{ 808{
785 int i, bit; 809 int ep_num, ep_dir;
810 short ep_type;
811
812 /* Safety */
813 ep_dir = EP_DIR(dir);
814 ep_type = type & USB_ENDPOINT_XFERTYPE_MASK;
786 815
787 bit=(dir & USB_DIR_IN)? 2:1; 816 logf("req: %s %s", XFER_DIR_STR(ep_dir), XFER_TYPE_STR(ep_type));
788 817
789 for (i=1; i < USB_NUM_ENDPOINTS; i++) { 818 /* Find an available ep/dir pair */
790 if((ep_allocation[i] & bit)!=0) 819 for (ep_num=1;ep_num<USB_NUM_ENDPOINTS;ep_num++) {
820 usb_endpoint_t* endpoint=&endpoints[ep_num];
821 int other_dir=(ep_dir ? 0:1);
822
823 if (endpoint->allocated[ep_dir])
791 continue; 824 continue;
792 ep_allocation[i] |= bit; 825
793 return i | dir; 826 if (endpoint->allocated[other_dir] &&
827 endpoint->type[other_dir] != ep_type) {
828 logf("ep of different type!");
829 return -1;
830 }
831
832 log_ep(ep_num, ep_dir, "add");
833
834 endpoint->allocated[ep_dir] = 1;
835 endpoint->type[ep_dir] = ep_type;
836
837 log_ep(ep_num, ep_dir, "got");
838 return (ep_num | (dir & USB_ENDPOINT_DIR_MASK));
794 } 839 }
795 840
796 return -1; 841 return -1;
@@ -798,8 +843,11 @@ int usb_drv_request_endpoint(int dir)
798 843
799void usb_drv_release_endpoint(int ep) 844void usb_drv_release_endpoint(int ep)
800{ 845{
801 int mask = (ep & USB_DIR_IN)? ~2:~1; 846 int ep_num = EP_NUM(ep);
802 ep_allocation[ep & 0x7f] &= mask; 847 int ep_dir = EP_DIR(ep);
848
849 log_ep(ep_num, ep_dir, "rel");
850 endpoints[ep_num].allocated[ep_dir] = 0;
803} 851}
804 852
805 853
@@ -870,11 +918,12 @@ static void transfer_completed(void)
870 struct transfer_descriptor* td=&td_array[pipe*NUM_TDS_PER_EP]; 918 struct transfer_descriptor* td=&td_array[pipe*NUM_TDS_PER_EP];
871 while(td!=(struct transfer_descriptor*)DTD_NEXT_TERMINATE && td!=0) 919 while(td!=(struct transfer_descriptor*)DTD_NEXT_TERMINATE && td!=0)
872 { 920 {
873 length += ((td->reserved & DTD_RESERVED_LENGTH_MASK) - 921 length += ((td->reserved & DTD_RESERVED_LENGTH_MASK) -
874 ((td->size_ioc_sts & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS)); 922 ((td->size_ioc_sts & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS));
875 td=(struct transfer_descriptor*) td->next_td_ptr; 923 td=(struct transfer_descriptor*) td->next_td_ptr;
876 } 924 }
877 usb_core_transfer_complete(ep, dir?USB_DIR_IN:USB_DIR_OUT, qh->status, length); 925 usb_core_transfer_complete(ep, dir?USB_DIR_IN:USB_DIR_OUT,
926 qh->status, length);
878 } 927 }
879 } 928 }
880 } 929 }
@@ -906,7 +955,7 @@ static void bus_reset(void)
906 } 955 }
907 956
908 usb_drv_cancel_all_transfers(); 957 usb_drv_cancel_all_transfers();
909 958
910 if (!(REG_PORTSC1 & PORTSCX_PORT_RESET)) { 959 if (!(REG_PORTSC1 & PORTSCX_PORT_RESET)) {
911 logf("usb: slow reset!"); 960 logf("usb: slow reset!");
912 } 961 }
@@ -926,39 +975,41 @@ static void init_control_queue_heads(void)
926/* manual: 32.14.4.1 Queue Head Initialization */ 975/* manual: 32.14.4.1 Queue Head Initialization */
927static void init_bulk_queue_heads(void) 976static void init_bulk_queue_heads(void)
928{ 977{
929 int tx_packetsize; 978 int packetsize = (usb_drv_port_speed() ? 512 : 64);
930 int rx_packetsize;
931 int i; 979 int i;
932 980
933 if (usb_drv_port_speed()) {
934 rx_packetsize = 512;
935 tx_packetsize = 512;
936 }
937 else {
938 rx_packetsize = 64;
939 tx_packetsize = 64;
940 }
941 /* TODO: this should take ep_allocation into account */ 981 /* TODO: this should take ep_allocation into account */
942 982 for (i=1;i<USB_NUM_ENDPOINTS;i++) {
943 /*** bulk ***/ 983 qh_array[i*2].max_pkt_length = packetsize << QH_MAX_PKT_LEN_POS |
944 for(i=1;i<USB_NUM_ENDPOINTS;i++) { 984 QH_ZLT_SEL;
945 qh_array[i*2].max_pkt_length = rx_packetsize << QH_MAX_PKT_LEN_POS | QH_ZLT_SEL;
946 qh_array[i*2].dtd.next_td_ptr = QH_NEXT_TERMINATE; 985 qh_array[i*2].dtd.next_td_ptr = QH_NEXT_TERMINATE;
947 qh_array[i*2+1].max_pkt_length = tx_packetsize << QH_MAX_PKT_LEN_POS | QH_ZLT_SEL; 986 qh_array[i*2+1].max_pkt_length = packetsize << QH_MAX_PKT_LEN_POS |
987 QH_ZLT_SEL;
948 qh_array[i*2+1].dtd.next_td_ptr = QH_NEXT_TERMINATE; 988 qh_array[i*2+1].dtd.next_td_ptr = QH_NEXT_TERMINATE;
949 } 989 }
950} 990}
951 991
952static void init_endpoints(void) 992static void init_endpoints(void)
953{ 993{
954 int i; 994 int ep_num;
955 /* TODO: this should take ep_allocation into account */ 995
956 /* bulk */ 996 logf("init_endpoints");
957 for(i=1;i<USB_NUM_ENDPOINTS;i++) { 997 /* RX/TX from the device POV: OUT/IN, respectively */
958 REG_ENDPTCTRL(i) = 998 for(ep_num=1;ep_num<USB_NUM_ENDPOINTS;ep_num++) {
999 usb_endpoint_t *endpoint = &endpoints[ep_num];
1000
1001 /* manual: 32.9.5.18 (Caution) */
1002 if (!endpoint->allocated[DIR_OUT]) {
1003 endpoint->type[DIR_OUT] = USB_ENDPOINT_XFER_BULK;
1004 }
1005 if (!endpoint->allocated[DIR_IN]) {
1006 endpoint->type[DIR_IN] = USB_ENDPOINT_XFER_BULK;
1007 }
1008
1009 REG_ENDPTCTRL(ep_num) =
959 EPCTRL_RX_DATA_TOGGLE_RST | EPCTRL_RX_ENABLE | 1010 EPCTRL_RX_DATA_TOGGLE_RST | EPCTRL_RX_ENABLE |
960 EPCTRL_TX_DATA_TOGGLE_RST | EPCTRL_TX_ENABLE | 1011 EPCTRL_TX_DATA_TOGGLE_RST | EPCTRL_TX_ENABLE |
961 (EPCTRL_EP_TYPE_BULK << EPCTRL_RX_EP_TYPE_SHIFT) | 1012 (endpoint->type[DIR_OUT] << EPCTRL_RX_EP_TYPE_SHIFT) |
962 (EPCTRL_EP_TYPE_BULK << EPCTRL_TX_EP_TYPE_SHIFT); 1013 (endpoint->type[DIR_IN] << EPCTRL_TX_EP_TYPE_SHIFT);
963 } 1014 }
964} 1015}
diff --git a/firmware/target/arm/usb-tcc.c b/firmware/target/arm/usb-tcc.c
index 611e4be195..2538efd12e 100644
--- a/firmware/target/arm/usb-tcc.c
+++ b/firmware/target/arm/usb-tcc.c
@@ -94,12 +94,15 @@ static struct tcc_ep tcc_endpoints[] = {
94static bool usb_drv_write_ep(struct tcc_ep *ep); 94static bool usb_drv_write_ep(struct tcc_ep *ep);
95static void usb_set_speed(int); 95static void usb_set_speed(int);
96 96
97int usb_drv_request_endpoint(int dir) 97int usb_drv_request_endpoint(int type, int dir)
98{ 98{
99 int flags = disable_irq_save(); 99 int flags = disable_irq_save();
100 size_t ep; 100 size_t ep;
101 int ret = 0; 101 int ret = 0;
102 102
103 if (type != USB_ENDPOINT_XFER_BULK)
104 return -1;
105
103 if (dir == USB_DIR_IN) 106 if (dir == USB_DIR_IN)
104 ep = 1; 107 ep = 1;
105 else 108 else
diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
index 14656eed5f..be245ede8c 100644
--- a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
@@ -852,10 +852,13 @@ void usb_drv_release_endpoint(int ep)
852 logf("usb_drv_release_endpoint(%d, %s)", (ep & 0x7F), (ep >> 7) ? "IN" : "OUT"); 852 logf("usb_drv_release_endpoint(%d, %s)", (ep & 0x7F), (ep >> 7) ? "IN" : "OUT");
853} 853}
854 854
855int usb_drv_request_endpoint(int dir) 855int usb_drv_request_endpoint(int type, int dir)
856{ 856{
857 logf("usb_drv_request_endpoint(%s)", (dir == USB_DIR_IN) ? "IN" : "OUT"); 857 logf("usb_drv_request_endpoint(%s)", (dir == USB_DIR_IN) ? "IN" : "OUT");
858 858
859 if (type != USB_ENDPOINT_XFER_BULK)
860 return -1;
861
859 /* There are only 3+2 endpoints, so hardcode this ... */ 862 /* There are only 3+2 endpoints, so hardcode this ... */
860 /* Currently only BULK endpoints ... */ 863 /* Currently only BULK endpoints ... */
861 if(dir == USB_DIR_OUT) 864 if(dir == USB_DIR_OUT)
diff --git a/firmware/usb.c b/firmware/usb.c
index 3d94ccfce7..bb00a1be5f 100644
--- a/firmware/usb.c
+++ b/firmware/usb.c
@@ -273,6 +273,9 @@ static void usb_thread(void)
273#ifdef USB_STORAGE 273#ifdef USB_STORAGE
274 usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, false); 274 usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, false);
275#endif 275#endif
276#ifdef USB_HID
277 usb_core_enable_driver(USB_DRIVER_HID, false);
278#endif
276#ifdef USB_CHARGING_ONLY 279#ifdef USB_CHARGING_ONLY
277 usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, true); 280 usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, true);
278#endif 281#endif
@@ -291,6 +294,9 @@ static void usb_thread(void)
291#ifdef USB_STORAGE 294#ifdef USB_STORAGE
292 usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, true); 295 usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, true);
293#endif 296#endif
297#ifdef USB_HID
298 usb_core_enable_driver(USB_DRIVER_HID, true);
299#endif
294#ifdef USB_CHARGING_ONLY 300#ifdef USB_CHARGING_ONLY
295 usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, false); 301 usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, false);
296#endif 302#endif
diff --git a/firmware/usbstack/usb_charging_only.c b/firmware/usbstack/usb_charging_only.c
index 3cbc4c3e96..fc6139c1ae 100644
--- a/firmware/usbstack/usb_charging_only.c
+++ b/firmware/usbstack/usb_charging_only.c
@@ -66,7 +66,7 @@ int usb_charging_only_get_config_descriptor(unsigned char *dest,int max_packet_s
66 unsigned char *orig_dest = dest; 66 unsigned char *orig_dest = dest;
67 67
68 interface_descriptor.bInterfaceNumber=usb_interface; 68 interface_descriptor.bInterfaceNumber=usb_interface;
69 PACK_DESCRIPTOR(dest, interface_descriptor); 69 PACK_DATA(dest, interface_descriptor);
70 70
71 return (dest-orig_dest); 71 return (dest-orig_dest);
72} 72}
diff --git a/firmware/usbstack/usb_class_driver.h b/firmware/usbstack/usb_class_driver.h
index 36f2ea9e3d..a9bc759a5b 100644
--- a/firmware/usbstack/usb_class_driver.h
+++ b/firmware/usbstack/usb_class_driver.h
@@ -85,10 +85,10 @@ struct usb_class_driver {
85#endif 85#endif
86}; 86};
87 87
88#define PACK_DESCRIPTOR(dest, descriptor) \ 88#define PACK_DATA(dest, data) \
89 do { \ 89 do { \
90 memcpy(dest, &(descriptor), sizeof(descriptor)); \ 90 memcpy(dest, &(data), sizeof(data)); \
91 dest += sizeof(descriptor); \ 91 dest += sizeof(data); \
92 } while (0) 92 } while (0)
93 93
94#endif 94#endif
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c
index 1e22ead63b..250544f202 100644
--- a/firmware/usbstack/usb_core.c
+++ b/firmware/usbstack/usb_core.c
@@ -397,7 +397,7 @@ void usb_core_handle_transfer_completion(
397 (struct usb_ctrlrequest*)event->data); 397 (struct usb_ctrlrequest*)event->data);
398 break; 398 break;
399 default: 399 default:
400 handler = ep_data[ep].completion_handler[event->dir>>7]; 400 handler = ep_data[ep].completion_handler[EP_DIR(event->dir)];
401 if(handler != NULL) 401 if(handler != NULL)
402 handler(ep,event->dir,event->status,event->length); 402 handler(ep,event->dir,event->status,event->length);
403 break; 403 break;
@@ -451,17 +451,17 @@ static void usb_core_set_serial_function_id(void)
451 usb_string_iSerial.wString[0] = hex[id]; 451 usb_string_iSerial.wString[0] = hex[id];
452} 452}
453 453
454int usb_core_request_endpoint(int dir, struct usb_class_driver* drv) 454int usb_core_request_endpoint(int type, int dir, struct usb_class_driver* drv)
455{ 455{
456 int ret, ep; 456 int ret, ep;
457 457
458 ret = usb_drv_request_endpoint(dir); 458 ret = usb_drv_request_endpoint(type, dir);
459 459
460 if (ret==-1) 460 if (ret==-1)
461 return -1; 461 return -1;
462 462
463 ep = ret & 0x7f; 463 dir = EP_DIR(ret);
464 dir = ret >> 7; 464 ep = EP_NUM(ret);
465 465
466 ep_data[ep].completion_handler[dir] = drv->transfer_complete; 466 ep_data[ep].completion_handler[dir] = drv->transfer_complete;
467 ep_data[ep].control_handler[dir] = drv->control_request; 467 ep_data[ep].control_handler[dir] = drv->control_request;
@@ -475,8 +475,8 @@ void usb_core_release_endpoint(int ep)
475 475
476 usb_drv_release_endpoint(ep); 476 usb_drv_release_endpoint(ep);
477 477
478 dir = ep >> 7; 478 dir = EP_DIR(ep);
479 ep &= 0x7f; 479 ep = EP_NUM(ep);
480 480
481 ep_data[ep].completion_handler[dir] = NULL; 481 ep_data[ep].completion_handler[dir] = NULL;
482 ep_data[ep].control_handler[dir] = NULL; 482 ep_data[ep].control_handler[dir] = NULL;
@@ -512,13 +512,14 @@ static void allocate_interfaces_and_endpoints(void)
512 512
513static void control_request_handler_drivers(struct usb_ctrlrequest* req) 513static void control_request_handler_drivers(struct usb_ctrlrequest* req)
514{ 514{
515 int i; 515 int i, interface = req->wIndex;
516 bool handled=false; 516 bool handled=false;
517
517 for(i=0;i<USB_NUM_DRIVERS;i++) { 518 for(i=0;i<USB_NUM_DRIVERS;i++) {
518 if(drivers[i].enabled && 519 if(drivers[i].enabled &&
519 drivers[i].control_request && 520 drivers[i].control_request &&
520 drivers[i].first_interface <= (req->wIndex) && 521 drivers[i].first_interface <= interface &&
521 drivers[i].last_interface > (req->wIndex)) 522 drivers[i].last_interface > interface)
522 { 523 {
523 handled = drivers[i].control_request(req, response_data); 524 handled = drivers[i].control_request(req, response_data);
524 if(handled) 525 if(handled)
@@ -528,7 +529,7 @@ static void control_request_handler_drivers(struct usb_ctrlrequest* req)
528 if(!handled) { 529 if(!handled) {
529 /* nope. flag error */ 530 /* nope. flag error */
530 logf("bad req:desc %d:%d", req->bRequest, req->wValue>>8); 531 logf("bad req:desc %d:%d", req->bRequest, req->wValue>>8);
531 usb_drv_stall(EP_CONTROL, true,true); 532 usb_drv_stall(EP_CONTROL, true, true);
532 usb_core_ack_control(req); 533 usb_core_ack_control(req);
533 } 534 }
534} 535}
@@ -730,15 +731,13 @@ static void request_handler_endpoint(struct usb_ctrlrequest* req)
730 switch (req->bRequest) { 731 switch (req->bRequest) {
731 case USB_REQ_CLEAR_FEATURE: 732 case USB_REQ_CLEAR_FEATURE:
732 if (req->wValue==USB_ENDPOINT_HALT) { 733 if (req->wValue==USB_ENDPOINT_HALT) {
733 usb_drv_stall(req->wIndex & 0xf, false, 734 usb_drv_stall(EP_NUM(req->wIndex), false, EP_DIR(req->wIndex));
734 (req->wIndex & USB_DIR_IN)!=0);
735 } 735 }
736 usb_core_ack_control(req); 736 usb_core_ack_control(req);
737 break; 737 break;
738 case USB_REQ_SET_FEATURE: 738 case USB_REQ_SET_FEATURE:
739 if (req->wValue==USB_ENDPOINT_HALT) { 739 if (req->wValue==USB_ENDPOINT_HALT) {
740 usb_drv_stall(req->wIndex & 0xf,true, 740 usb_drv_stall(EP_NUM(req->wIndex), true, EP_DIR(req->wIndex));
741 (req->wIndex & USB_DIR_IN)!=0);
742 } 741 }
743 usb_core_ack_control(req); 742 usb_core_ack_control(req);
744 break; 743 break;
@@ -747,8 +746,8 @@ static void request_handler_endpoint(struct usb_ctrlrequest* req)
747 response_data[1]=0; 746 response_data[1]=0;
748 logf("usb_core: GET_STATUS"); 747 logf("usb_core: GET_STATUS");
749 if(req->wIndex>0) { 748 if(req->wIndex>0) {
750 response_data[0]=usb_drv_stalled(req->wIndex & 0xf, 749 response_data[0]=usb_drv_stalled(EP_NUM(req->wIndex),
751 (req->wIndex & USB_DIR_IN)!=0); 750 EP_DIR(req->wIndex));
752 } 751 }
753 if(!usb_drv_send(EP_CONTROL,response_data,2)) 752 if(!usb_drv_send(EP_CONTROL,response_data,2))
754 usb_core_ack_control(req); 753 usb_core_ack_control(req);
@@ -757,7 +756,8 @@ static void request_handler_endpoint(struct usb_ctrlrequest* req)
757 bool handled; 756 bool handled;
758 control_handler_t control_handler; 757 control_handler_t control_handler;
759 758
760 control_handler=ep_data[req->wIndex & 0xf].control_handler[0]; 759 control_handler=
760 ep_data[EP_NUM(req->wIndex)].control_handler[EP_CONTROL];
761 if (!control_handler) 761 if (!control_handler)
762 break; 762 break;
763 763
@@ -835,9 +835,9 @@ void usb_core_transfer_complete(int endpoint,int dir,int status,int length)
835void usb_core_control_request(struct usb_ctrlrequest* req) 835void usb_core_control_request(struct usb_ctrlrequest* req)
836{ 836{
837 struct usb_transfer_completion_event_data* completion_event = 837 struct usb_transfer_completion_event_data* completion_event =
838 &ep_data[0].completion_event; 838 &ep_data[EP_CONTROL].completion_event;
839 839
840 completion_event->endpoint=0; 840 completion_event->endpoint=EP_CONTROL;
841 completion_event->dir=0; 841 completion_event->dir=0;
842 completion_event->data=(void*)req; 842 completion_event->data=(void*)req;
843 completion_event->status=0; 843 completion_event->status=0;
diff --git a/firmware/usbstack/usb_hid.c b/firmware/usbstack/usb_hid.c
index c3cd5d9a04..0c35da2acb 100644
--- a/firmware/usbstack/usb_hid.c
+++ b/firmware/usbstack/usb_hid.c
@@ -25,49 +25,66 @@
25#include "kernel.h" 25#include "kernel.h"
26#include "usb_hid.h" 26#include "usb_hid.h"
27#include "usb_class_driver.h" 27#include "usb_class_driver.h"
28#define LOGF_ENABLE 28//#define LOGF_ENABLE
29#include "logf.h" 29#include "logf.h"
30 30
31#ifdef USB_HID 31#ifdef USB_HID
32 32
33#define CONCAT(low, high) ((high << 8) | low) 33#define CONCAT(low, high) ((high << 8) | low)
34#define SIZE_VALUE 0x01 34#define PACK_VAL1(dest, val) *(dest)++ = (val) & 0xff
35#define PACK_VAL2(dest, val) PACK_VAL1((dest), (val)); \
36 PACK_VAL1((dest), (val >> 8))
37
38/* Documents avaiable here: http://www.usb.org/developers/devclass_docs/ */
39
40#define HID_VER 0x0110 /* 1.1 */
41/* Subclass Codes (HID1_11.pdf, page 18) */
42#define SUBCLASS_BOOT_INTERFACE 1
43/* Protocol Codes (HID1_11.pdf, page 19) */
44#define PROTOCOL_CODE_MOUSE 2
35/* HID main items (HID1_11.pdf, page 38) */ 45/* HID main items (HID1_11.pdf, page 38) */
36#define INPUT (0x80 | SIZE_VALUE) 46#define INPUT 0x80
37#define OUTPUT (0x90 | SIZE_VALUE) 47#define COLLECTION 0xa0
38#define FEATURE (0xb0 | SIZE_VALUE) 48#define COLLECTION_APPLICATION 0x01
39#define COLLECTION (0xa0 | SIZE_VALUE)
40#define COLLECTION_APPLICATION CONCAT(COLLECTION, 0x01)
41#define END_COLLECTION 0xc0 49#define END_COLLECTION 0xc0
50/* Parts (HID1_11.pdf, page 40) */
51#define PREFERERD (1 << 5)
52#define NULL_STATE (1 << 6)
42/* HID global items (HID1_11.pdf, page 45) */ 53/* HID global items (HID1_11.pdf, page 45) */
43#define USAGE_PAGE (0x04 | SIZE_VALUE) 54#define USAGE_PAGE 0x04
44#define LOGICAL_MINIMUM (0x14 | SIZE_VALUE) 55#define LOGICAL_MINIMUM 0x14
45#define LOGICAL_MAXIMUM (0x24 | SIZE_VALUE) 56#define LOGICAL_MAXIMUM 0x24
46#define PHYSICAL_MINIMUM (0x34 | SIZE_VALUE) 57#define REPORT_SIZE 0x74
47#define PHYSICAL_MAXIMUM (0x44 | SIZE_VALUE) 58#define REPORT_ID 0x84
48#define UNIT_EXPONENT (0x54 | SIZE_VALUE) 59#define REPORT_COUNT 0x94
49#define UNIT (0x64 | SIZE_VALUE) 60/* HID local items (HID1_11.pdf, page 50) */
50#define REPORT_SIZE (0x74 | SIZE_VALUE) 61#define USAGE_MINIMUM 0x18
51#define REPORT_ID (0x84 | SIZE_VALUE) 62#define USAGE_MAXIMUM 0x28
52#define REPORT_COUNT (0x94 | SIZE_VALUE) 63/* Types of class descriptors (HID1_11.pdf, page 59) */
53#define PUSH (0xa4 | SIZE_VALUE) 64#define USB_DT_HID 0x21
54#define POP (0xb4 | SIZE_VALUE) 65#define USB_DT_REPORT 0x22
55/* Hut1_12.pdf, Table 1, page 14 */ 66
56#define USAGE_PAGE_CONSUMER CONCAT(USAGE_PAGE, 0x0c) 67/* (Hut1_12.pdf, Table 1, page 14) */
57/* Hut1_12.pdf, Table 17, page 77 */ 68#define USAGE_PAGE_CONSUMER 0x0c
69
58#define CONSUMER_USAGE 0x09 70#define CONSUMER_USAGE 0x09
59#define CONSUMER_USAGE_CONTROL CONCAT(CONSUMER_USAGE, 0x01) 71
60#define CONSUMER_USAGE_MUTE CONCAT(CONSUMER_USAGE, 0xe2) 72/* HID-only class specific requests */
61#define CONSUMER_USAGE_VOLUME_INCREMENT CONCAT(CONSUMER_USAGE, 0xe9) 73#define USB_HID_GET_REPORT 0x01
62#define CONSUMER_USAGE_VOLUME_DECREMENT CONCAT(CONSUMER_USAGE, 0xea) 74#define USB_HID_GET_IDLE 0x02
63/* Hut1_12.pdf, Table 4, page 20 */ 75#define USB_HID_GET_PROTOCOL 0x03
64#define CONSUMER_CONTROL CONCAT(COLLECTION_APPLICATION, 0x01) 76#define USB_HID_SET_REPORT 0x09
65 77#define USB_HID_SET_IDLE 0x0a
66#define USB_DT_HID 0x21 78#define USB_HID_SET_PROTOCOL 0x0b
67#define USB_DT_REPORT 0x22 79
68#define USB_DT_PHYSICAL_DESCRIPTOR 0x23 80#define HID_BUF_SIZE_MSG 16
69 81#define HID_BUF_SIZE_CMD 5
70/* serial interface */ 82#define HID_BUG_SIZE_REPORT 32
83#define HID_NUM_BUFFERS 5
84
85#define HID_BUF_INC(i) do { (i) = ((i) + 1) % HID_NUM_BUFFERS; } while (0)
86
87/* hid interface */
71static struct usb_interface_descriptor __attribute__((aligned(2))) 88static struct usb_interface_descriptor __attribute__((aligned(2)))
72 interface_descriptor = 89 interface_descriptor =
73{ 90{
@@ -77,12 +94,11 @@ static struct usb_interface_descriptor __attribute__((aligned(2)))
77 .bAlternateSetting = 0, 94 .bAlternateSetting = 0,
78 .bNumEndpoints = 1, 95 .bNumEndpoints = 1,
79 .bInterfaceClass = USB_CLASS_HID, 96 .bInterfaceClass = USB_CLASS_HID,
80 .bInterfaceSubClass = 0, 97 .bInterfaceSubClass = SUBCLASS_BOOT_INTERFACE,
81 .bInterfaceProtocol = 0, 98 .bInterfaceProtocol = PROTOCOL_CODE_MOUSE,
82 .iInterface = 0 99 .iInterface = 0
83}; 100};
84 101
85/* USB_DT_HID: Endpoint descriptor */
86struct usb_hid_descriptor { 102struct usb_hid_descriptor {
87 uint8_t bLength; 103 uint8_t bLength;
88 uint8_t bDescriptorType; 104 uint8_t bDescriptorType;
@@ -93,19 +109,19 @@ struct usb_hid_descriptor {
93 uint16_t wDescriptorLength0; 109 uint16_t wDescriptorLength0;
94} __attribute__ ((packed)); 110} __attribute__ ((packed));
95 111
96/* USB_DT_REPORT: Endpoint descriptor */
97static struct usb_hid_descriptor __attribute__((aligned(2))) hid_descriptor = 112static struct usb_hid_descriptor __attribute__((aligned(2))) hid_descriptor =
98{ 113{
99 .bLength = sizeof(struct usb_hid_descriptor), 114 .bLength = sizeof(struct usb_hid_descriptor),
100 .bDescriptorType = USB_DT_HID, 115 .bDescriptorType = USB_DT_HID,
101 .wBcdHID = 0x0100, 116 .wBcdHID = HID_VER,
102 .bCountryCode = 0, 117 .bCountryCode = 0,
103 .bNumDescriptors = 1, 118 .bNumDescriptors = 1,
104 .bDescriptorType0 = 0x22, 119 .bDescriptorType0 = USB_DT_REPORT,
105 .wDescriptorLength0 = 0 120 .wDescriptorLength0 = 0
106}; 121};
107 122
108static struct usb_endpoint_descriptor __attribute__((aligned(2))) endpoint_descriptor = 123static struct usb_endpoint_descriptor __attribute__((aligned(2)))
124 endpoint_descriptor =
109{ 125{
110 .bLength = sizeof(struct usb_endpoint_descriptor), 126 .bLength = sizeof(struct usb_endpoint_descriptor),
111 .bDescriptorType = USB_DT_ENDPOINT, 127 .bDescriptorType = USB_DT_ENDPOINT,
@@ -115,43 +131,46 @@ static struct usb_endpoint_descriptor __attribute__((aligned(2))) endpoint_descr
115 .bInterval = 0 131 .bInterval = 0
116}; 132};
117 133
118/* USB_DT_REPORT: Endpoint descriptor */ 134static unsigned char report_descriptor[HID_BUG_SIZE_REPORT]
119struct usb_report_descriptor { 135 USB_DEVBSS_ATTR __attribute__((aligned(32)));
120 uint16_t wUsagePage;
121 uint16_t wUsage;
122 uint16_t wCollection;
123 uint16_t wCollectionItems[12];
124 uint8_t wEndCollection;
125} __attribute__ ((packed));
126 136
127static struct usb_report_descriptor __attribute__((aligned(2))) report_descriptor = 137static unsigned char send_buffer[HID_NUM_BUFFERS][HID_BUF_SIZE_MSG]
128{ 138 USB_DEVBSS_ATTR __attribute__((aligned(32)));
129 .wUsagePage = USAGE_PAGE_CONSUMER, 139size_t send_buffer_len[HID_NUM_BUFFERS];
130 .wUsage = CONSUMER_USAGE_CONTROL, 140static int cur_buf_prepare;
131 .wCollection = COLLECTION_APPLICATION, 141static int cur_buf_send;
132 .wCollectionItems = {
133 CONCAT(LOGICAL_MINIMUM, 0x0),
134 CONCAT(LOGICAL_MAXIMUM, 0x1),
135 USAGE_PAGE_CONSUMER,
136 CONSUMER_USAGE_MUTE,
137 CONSUMER_USAGE_VOLUME_INCREMENT,
138 CONSUMER_USAGE_VOLUME_DECREMENT,
139 CONCAT(REPORT_COUNT, 0x3),
140 CONCAT(REPORT_SIZE, 0x1),
141 CONCAT(INPUT, 0x42),
142 CONCAT(REPORT_COUNT, 0x5),
143 CONCAT(REPORT_SIZE, 0x1),
144 CONCAT(INPUT, 0x01)
145 },
146 .wEndCollection = END_COLLECTION
147};
148 142
143static uint16_t report_descriptor_len;
144static bool active = false;
149static int ep_in; 145static int ep_in;
150static int usb_interface; 146static int usb_interface;
147static uint32_t report_id;
148
149static void usb_hid_try_send_drv(void);
150
151static void pack_parameter(unsigned char **dest, uint8_t parameter,
152 uint32_t value)
153{
154 uint8_t size_value = 1; /* # of bytes */
155 uint32_t v = value;
156
157 while (v >>= 8)
158 size_value++;
159
160 **dest = parameter | size_value;
161 (*dest)++;
162
163 while (size_value--)
164 {
165 **dest = value & 0xff;
166 (*dest)++;
167 value >>= 8;
168 }
169}
151 170
152int usb_hid_request_endpoints(struct usb_class_driver *drv) 171int usb_hid_request_endpoints(struct usb_class_driver *drv)
153{ 172{
154 ep_in = usb_core_request_endpoint(USB_DIR_IN, drv); 173 ep_in = usb_core_request_endpoint(USB_ENDPOINT_XFER_INT, USB_DIR_IN, drv);
155 if (ep_in < 0) 174 if (ep_in < 0)
156 return -1; 175 return -1;
157 176
@@ -165,25 +184,46 @@ int usb_hid_set_first_interface(int interface)
165 return interface + 1; 184 return interface + 1;
166} 185}
167 186
168
169int usb_hid_get_config_descriptor(unsigned char *dest,int max_packet_size) 187int usb_hid_get_config_descriptor(unsigned char *dest,int max_packet_size)
170{ 188{
171 unsigned char *orig_dest = dest; 189 unsigned char *report, *orig_dest = dest;
172 190
173 logf("hid: config desc."); 191 logf("hid: config desc.");
174 interface_descriptor.bInterfaceNumber = usb_interface;
175 PACK_DESCRIPTOR(dest, interface_descriptor);
176
177 hid_descriptor.wDescriptorLength0 = sizeof(report_descriptor);
178 PACK_DESCRIPTOR(dest, hid_descriptor);
179 192
180 /* Ignore max_packet_size and set to 1 bytes long packet size */ 193 /* Ignore given max_packet_size */
181 (void)max_packet_size; 194 (void)max_packet_size;
182 endpoint_descriptor.wMaxPacketSize = 1; 195
196 /* TODO: Increment report_id for each report, and send command with
197 * appropriate report id */
198 report_id = 2;
199
200 /* Initialize report descriptor */
201 report = report_descriptor;
202 pack_parameter(&report, USAGE_PAGE, USAGE_PAGE_CONSUMER);
203 PACK_VAL2(report, CONCAT(CONSUMER_USAGE, CONSUMER_CONTROL));
204 pack_parameter(&report, COLLECTION, COLLECTION_APPLICATION);
205 pack_parameter(&report, REPORT_ID, report_id);
206 pack_parameter(&report, REPORT_SIZE, 16);
207 pack_parameter(&report, REPORT_COUNT, 2);
208 pack_parameter(&report, LOGICAL_MINIMUM, 1);
209 pack_parameter(&report, LOGICAL_MAXIMUM, 652);
210 pack_parameter(&report, USAGE_MINIMUM, CONSUMER_CONTROL);
211 pack_parameter(&report, USAGE_MAXIMUM, AC_SEND);
212 pack_parameter(&report, INPUT, PREFERERD | NULL_STATE);
213 PACK_VAL1(report, END_COLLECTION);
214 report_descriptor_len = (uint16_t)((uint32_t)report -
215 (uint32_t)report_descriptor);
216
217 interface_descriptor.bInterfaceNumber = usb_interface;
218 PACK_DATA(dest, interface_descriptor);
219 hid_descriptor.wDescriptorLength0 = report_descriptor_len;
220 PACK_DATA(dest, hid_descriptor);
221
222 endpoint_descriptor.wMaxPacketSize = 8;
183 endpoint_descriptor.bInterval = 8; 223 endpoint_descriptor.bInterval = 8;
184 224
185 endpoint_descriptor.bEndpointAddress = ep_in; 225 endpoint_descriptor.bEndpointAddress = ep_in;
186 PACK_DESCRIPTOR(dest, endpoint_descriptor); 226 PACK_DATA(dest, endpoint_descriptor);
187 227
188 return (dest - orig_dest); 228 return (dest - orig_dest);
189} 229}
@@ -191,38 +231,54 @@ int usb_hid_get_config_descriptor(unsigned char *dest,int max_packet_size)
191void usb_hid_init_connection(void) 231void usb_hid_init_connection(void)
192{ 232{
193 logf("hid: init connection"); 233 logf("hid: init connection");
234
235 active = true;
194} 236}
195 237
196/* called by usb_code_init() */ 238/* called by usb_core_init() */
197void usb_hid_init(void) 239void usb_hid_init(void)
198{ 240{
241 int i;
242
199 logf("hid: init"); 243 logf("hid: init");
244
245 for (i = 0; i < HID_NUM_BUFFERS; i++)
246 send_buffer_len[i] = 0;
247
248 cur_buf_prepare = 0;
249 cur_buf_send = 0;
250
251 active = true;
200} 252}
201 253
202void usb_hid_disconnect(void) 254void usb_hid_disconnect(void)
203{ 255{
204 logf("hid: disconnect"); 256 logf("hid: disconnect");
257 active = false;
205} 258}
206 259
207/* called by usb_core_transfer_complete() */ 260/* called by usb_core_transfer_complete() */
208void usb_hid_transfer_complete(int ep,int dir, int status, int length) 261void usb_hid_transfer_complete(int ep, int dir, int status, int length)
209{ 262{
210 (void)ep; 263 (void)ep;
211 (void)dir; 264 (void)dir;
212 (void)status; 265 (void)status;
213 (void)length; 266 (void)length;
214 267
215 logf("hid: transfer complete. ep %d, dir %d, status %d ,length %d", 268 switch (dir) {
216 ep, dir, status, length); 269 case USB_DIR_OUT:
217} 270 break;
271 case USB_DIR_IN: {
272 if (status)
273 break;
218 274
219/* HID-only class specific requests */ 275 send_buffer_len[cur_buf_send] = 0;
220#define USB_HID_GET_REPORT 0x01 276 HID_BUF_INC(cur_buf_send);
221#define USB_HID_GET_IDLE 0x02 277 usb_hid_try_send_drv();
222#define USB_HID_GET_PROTOCOL 0x03 278 break;
223#define USB_HID_SET_REPORT 0x09 279 }
224#define USB_HID_SET_IDLE 0x0a 280 }
225#define USB_HID_SET_PROTOCOL 0x0b 281}
226 282
227/* called by usb_core_control_request() */ 283/* called by usb_core_control_request() */
228bool usb_hid_control_request(struct usb_ctrlrequest* req, unsigned char* dest) 284bool usb_hid_control_request(struct usb_ctrlrequest* req, unsigned char* dest)
@@ -231,29 +287,32 @@ bool usb_hid_control_request(struct usb_ctrlrequest* req, unsigned char* dest)
231 287
232 switch(req->bRequestType & USB_TYPE_MASK) { 288 switch(req->bRequestType & USB_TYPE_MASK) {
233 case USB_TYPE_STANDARD: { 289 case USB_TYPE_STANDARD: {
234 switch(req->wValue>>8) { /* type */ 290 unsigned char *orig_dest = dest;
235 case USB_DT_REPORT: { 291
236 logf("hid: report"); 292 switch(req->wValue>>8) { /* type */
237 if (dest == NULL) { 293 case USB_DT_HID: {
238 logf("dest is NULL!"); 294 logf("hid: type hid");
239 } 295 hid_descriptor.wDescriptorLength0 = report_descriptor_len;
240 if (dest) { 296 PACK_DATA(dest, hid_descriptor);
241 unsigned char *orig_dest = dest; 297 break;
242 PACK_DESCRIPTOR(dest, report_descriptor);
243 if(usb_drv_send(EP_CONTROL, orig_dest, dest - orig_dest))
244 break;
245 usb_core_ack_control(req);
246
247 }
248 handled = true;
249 break;
250 }
251 default:
252 logf("hid: unsup. std. req");
253 break;
254 } 298 }
255 break; 299 case USB_DT_REPORT: {
300 logf("hid: type report");
301 memcpy(dest, &report_descriptor, report_descriptor_len);
302 dest += report_descriptor_len;
303 break;
304 }
305 default:
306 logf("hid: unsup. std. req");
307 break;
256 } 308 }
309 if (dest != orig_dest &&
310 !usb_drv_send(EP_CONTROL, orig_dest, dest - orig_dest)) {
311 usb_core_ack_control(req);
312 handled = true;
313 }
314 break;
315 }
257 316
258 case USB_TYPE_CLASS: { 317 case USB_TYPE_CLASS: {
259 switch (req->bRequest) { 318 switch (req->bRequest) {
@@ -263,7 +322,6 @@ bool usb_hid_control_request(struct usb_ctrlrequest* req, unsigned char* dest)
263 handled = true; 322 handled = true;
264 break; 323 break;
265 default: 324 default:
266 //logf("hid: unsup. cls. req");
267 logf("%d: unsup. cls. req", req->bRequest); 325 logf("%d: unsup. cls. req", req->bRequest);
268 break; 326 break;
269 } 327 }
@@ -277,12 +335,62 @@ bool usb_hid_control_request(struct usb_ctrlrequest* req, unsigned char* dest)
277 return handled; 335 return handled;
278} 336}
279 337
280void usb_hid_send(unsigned char *data, int length) 338static void usb_hid_try_send_drv(void)
281{ 339{
282 (void)data; 340 int rc;
283 (void)(length); 341 int length = send_buffer_len[cur_buf_send];
342
343 if (!length)
344 return;
345
346 rc = usb_drv_send_nonblocking(ep_in, send_buffer[cur_buf_send], length);
347 if (rc)
348 {
349 send_buffer_len[cur_buf_send] = 0;
350 return;
351 }
352}
353
354static void usb_hid_queue(unsigned char *data, int length)
355{
356 if (!active || length <= 0)
357 return;
358
359 /* Buffer overflow - item still in use */
360 if (send_buffer_len[cur_buf_prepare])
361 return;
362
363 /* Prepare buffer for sending */
364 if (length > HID_BUF_SIZE_MSG)
365 length = HID_BUF_SIZE_MSG;
366 memcpy(send_buffer[cur_buf_prepare], data, length);
367 send_buffer_len[cur_buf_prepare] = length;
368
369 HID_BUF_INC(cur_buf_prepare);
370}
371
372void usb_hid_send_consumer_usage(consumer_usage_page_t id)
373{
374 static unsigned char buf[HID_BUF_SIZE_CMD] USB_DEVBSS_ATTR
375 __attribute__((aligned(32)));
376 unsigned char *dest = buf;
377
378 memset(buf, 0, sizeof(buf));
379
380 logf("HID: Sending 0x%x", id);
381
382 pack_parameter(&dest, 0, id);
383 buf[0] = report_id;
384
385 /* Key pressed */
386 usb_hid_queue(buf, HID_BUF_SIZE_CMD);
387
388 /* Key released */
389 memset(buf, 0, sizeof(buf));
390 buf[0] = report_id;
391 usb_hid_queue(buf, HID_BUF_SIZE_CMD);
284 392
285 logf("hid: send %d bytes: \"%s\"", length, data); 393 usb_hid_try_send_drv();
286} 394}
287 395
288#endif /*USB_HID*/ 396#endif /*USB_HID*/
diff --git a/firmware/usbstack/usb_hid.h b/firmware/usbstack/usb_hid.h
index ff2a33dcbf..bce6943a4d 100644
--- a/firmware/usbstack/usb_hid.h
+++ b/firmware/usbstack/usb_hid.h
@@ -22,6 +22,7 @@
22#define USB_HID_H 22#define USB_HID_H
23 23
24#include "usb_ch9.h" 24#include "usb_ch9.h"
25#include "usb_hid_usage_tables.h"
25 26
26int usb_hid_request_endpoints(struct usb_class_driver *drv); 27int usb_hid_request_endpoints(struct usb_class_driver *drv);
27int usb_hid_set_first_interface(int interface); 28int usb_hid_set_first_interface(int interface);
@@ -32,7 +33,7 @@ void usb_hid_disconnect(void);
32void usb_hid_transfer_complete(int ep, int dir, int status, int length); 33void usb_hid_transfer_complete(int ep, int dir, int status, int length);
33bool usb_hid_control_request(struct usb_ctrlrequest* req, unsigned char* dest); 34bool usb_hid_control_request(struct usb_ctrlrequest* req, unsigned char* dest);
34 35
35void usb_hid_send(unsigned char *data,int length); 36void usb_hid_send_consumer_usage(consumer_usage_page_t id);
36 37
37#endif 38#endif
38 39
diff --git a/firmware/usbstack/usb_serial.c b/firmware/usbstack/usb_serial.c
index 370afcb7f1..246938a1ef 100644
--- a/firmware/usbstack/usb_serial.c
+++ b/firmware/usbstack/usb_serial.c
@@ -77,11 +77,12 @@ static int usb_interface;
77 77
78int usb_serial_request_endpoints(struct usb_class_driver *drv) 78int usb_serial_request_endpoints(struct usb_class_driver *drv)
79{ 79{
80 ep_in = usb_core_request_endpoint(USB_DIR_IN, drv); 80 ep_in = usb_core_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_IN, drv);
81 if (ep_in < 0) 81 if (ep_in < 0)
82 return -1; 82 return -1;
83 83
84 ep_out = usb_core_request_endpoint(USB_DIR_OUT, drv); 84 ep_out = usb_core_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_OUT,
85 drv);
85 if (ep_out < 0) { 86 if (ep_out < 0) {
86 usb_core_release_endpoint(ep_in); 87 usb_core_release_endpoint(ep_in);
87 return -1; 88 return -1;
@@ -101,15 +102,15 @@ int usb_serial_get_config_descriptor(unsigned char *dest, int max_packet_size)
101 unsigned char *orig_dest = dest; 102 unsigned char *orig_dest = dest;
102 103
103 interface_descriptor.bInterfaceNumber = usb_interface; 104 interface_descriptor.bInterfaceNumber = usb_interface;
104 PACK_DESCRIPTOR(dest, interface_descriptor); 105 PACK_DATA(dest, interface_descriptor);
105 106
106 endpoint_descriptor.wMaxPacketSize = max_packet_size; 107 endpoint_descriptor.wMaxPacketSize = max_packet_size;
107 108
108 endpoint_descriptor.bEndpointAddress = ep_in; 109 endpoint_descriptor.bEndpointAddress = ep_in;
109 PACK_DESCRIPTOR(dest, endpoint_descriptor); 110 PACK_DATA(dest, endpoint_descriptor);
110 111
111 endpoint_descriptor.bEndpointAddress = ep_out; 112 endpoint_descriptor.bEndpointAddress = ep_out;
112 PACK_DESCRIPTOR(dest, endpoint_descriptor); 113 PACK_DATA(dest, endpoint_descriptor);
113 114
114 return (dest - orig_dest); 115 return (dest - orig_dest);
115} 116}
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
index 464283551a..73176ee93e 100644
--- a/firmware/usbstack/usb_storage.c
+++ b/firmware/usbstack/usb_storage.c
@@ -349,12 +349,13 @@ void usb_storage_init(void)
349 349
350int usb_storage_request_endpoints(struct usb_class_driver *drv) 350int usb_storage_request_endpoints(struct usb_class_driver *drv)
351{ 351{
352 ep_in = usb_core_request_endpoint(USB_DIR_IN, drv); 352 ep_in = usb_core_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_IN, drv);
353 353
354 if(ep_in<0) 354 if(ep_in<0)
355 return -1; 355 return -1;
356 356
357 ep_out = usb_core_request_endpoint(USB_DIR_OUT, drv); 357 ep_out = usb_core_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_OUT,
358 drv);
358 359
359 if(ep_out<0) { 360 if(ep_out<0) {
360 usb_core_release_endpoint(ep_in); 361 usb_core_release_endpoint(ep_in);
@@ -375,15 +376,15 @@ int usb_storage_get_config_descriptor(unsigned char *dest,int max_packet_size)
375 unsigned char *orig_dest = dest; 376 unsigned char *orig_dest = dest;
376 377
377 interface_descriptor.bInterfaceNumber = usb_interface; 378 interface_descriptor.bInterfaceNumber = usb_interface;
378 PACK_DESCRIPTOR(dest, interface_descriptor); 379 PACK_DATA(dest, interface_descriptor);
379 380
380 endpoint_descriptor.wMaxPacketSize = max_packet_size; 381 endpoint_descriptor.wMaxPacketSize = max_packet_size;
381 382
382 endpoint_descriptor.bEndpointAddress = ep_in; 383 endpoint_descriptor.bEndpointAddress = ep_in;
383 PACK_DESCRIPTOR(dest, endpoint_descriptor); 384 PACK_DATA(dest, endpoint_descriptor);
384 385
385 endpoint_descriptor.bEndpointAddress = ep_out; 386 endpoint_descriptor.bEndpointAddress = ep_out;
386 PACK_DESCRIPTOR(dest, endpoint_descriptor); 387 PACK_DATA(dest, endpoint_descriptor);
387 388
388 return (dest - orig_dest); 389 return (dest - orig_dest);
389} 390}