summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorFrank Gevaerts <frank@gevaerts.be>2009-05-16 15:30:09 +0000
committerFrank Gevaerts <frank@gevaerts.be>2009-05-16 15:30:09 +0000
commit69a4117c1d15d91836de91abe5f8f93b868ec808 (patch)
treea3d47f51a0998506ef7b0f5332ddecae3e2106d2 /firmware
parente435e4d976757f8436484a5b4d158ab7545fcdb6 (diff)
downloadrockbox-69a4117c1d15d91836de91abe5f8f93b868ec808.tar.gz
rockbox-69a4117c1d15d91836de91abe5f8f93b868ec808.zip
Add working USB HID driver, by Tomer Shalev (part of his GSoC work).
This needs support for usb interrupt transfers, so there are some changes in various USB drivers as well (only usb-drv-arc supports it at this point, others won't have working HID yet). HID is disabled for now, as the apps/ part is not included yet. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20962 a1c6a512-1295-4272-9138-f99709370657
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}