summaryrefslogtreecommitdiff
path: root/firmware/usbstack
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/usbstack
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/usbstack')
-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
7 files changed, 265 insertions, 154 deletions
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}