-
Notifications
You must be signed in to change notification settings - Fork 20
/
usb_requests.c
153 lines (131 loc) · 3.62 KB
/
usb_requests.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include "usb.h"
USB_SetupPacket usb_setup;
__attribute__((__aligned__(4))) uint8_t ep0_buf_in[USB_EP0_SIZE];
__attribute__((__aligned__(4))) uint8_t ep0_buf_out[USB_EP0_SIZE];
volatile uint8_t usb_configuration;
uint16_t usb_ep0_in_size;
const uint8_t* usb_ep0_in_ptr;
void usb_ep0_in_multi(void) {
uint16_t tsize = usb_ep0_in_size;
if (tsize > USB_EP0_SIZE) {
tsize = USB_EP0_SIZE;
}
memcpy(ep0_buf_in, usb_ep0_in_ptr, tsize);
usb_ep_start_in(0x80, ep0_buf_in, tsize, false);
if (tsize == 0) {
usb_ep0_out();
}
usb_ep0_in_size -= tsize;
usb_ep0_in_ptr += tsize;
}
void usb_handle_setup(void){
if ((usb_setup.bmRequestType & USB_REQTYPE_TYPE_MASK) == USB_REQTYPE_STANDARD){
switch (usb_setup.bRequest){
case USB_REQ_GetStatus:
ep0_buf_in[0] = 0;
ep0_buf_in[1] = 0;
usb_ep0_in(2);
return usb_ep0_out();
case USB_REQ_ClearFeature:
case USB_REQ_SetFeature:
usb_ep0_in(0);
return usb_ep0_out();
case USB_REQ_SetAddress:
usb_ep0_in(0);
return usb_ep0_out();
case USB_REQ_GetDescriptor: {
uint8_t type = (usb_setup.wValue >> 8);
uint8_t index = (usb_setup.wValue & 0xFF);
const uint8_t* descriptor = 0;
uint16_t size = usb_cb_get_descriptor(type, index, &descriptor);
if (size && descriptor){
if (size > usb_setup.wLength) {
size = usb_setup.wLength;
}
if (descriptor == ep0_buf_in) {
usb_ep0_in_size = 0;
usb_ep_start_in(0x80, ep0_buf_in, size, true);
} else {
usb_ep0_in_size = size;
usb_ep0_in_ptr = descriptor;
usb_ep0_in_multi();
}
return;
} else {
return usb_ep0_stall();
}
}
case USB_REQ_GetConfiguration:
ep0_buf_in[0] = usb_configuration;
usb_ep0_in(1);
return usb_ep0_out();
case USB_REQ_SetConfiguration:
if (usb_cb_set_configuration((uint8_t)usb_setup.wValue)) {
usb_ep0_in(0);
usb_configuration = (uint8_t)(usb_setup.wValue);
return usb_ep0_out();
} else {
return usb_ep0_stall();
}
case USB_REQ_SetInterface:
if (usb_cb_set_interface(usb_setup.wIndex, usb_setup.wValue)) {
usb_ep0_in(0);
return usb_ep0_out();
} else {
return usb_ep0_stall();
}
default:
return usb_ep0_stall();
}
}
usb_cb_control_setup();
}
void usb_handle_control_out_complete(void) {
if ((usb_setup.bmRequestType & USB_REQTYPE_TYPE_MASK) == USB_REQTYPE_STANDARD) {
// Let the status stage proceed
} else {
usb_cb_control_out_completion();
}
}
void usb_handle_control_in_complete(void) {
if ((usb_setup.bmRequestType & USB_REQTYPE_TYPE_MASK) == USB_REQTYPE_STANDARD) {
switch (usb_setup.bRequest){
case USB_REQ_SetAddress:
usb_set_address(usb_setup.wValue & 0x7F);
return;
case USB_REQ_GetDescriptor:
usb_ep0_in_multi();
return;
}
} else {
usb_cb_control_in_completion();
}
}
void usb_handle_msft_compatible(const USB_MicrosoftCompatibleDescriptor* msft_compatible) {
if (usb_setup.wIndex == 0x0004) {
uint16_t len = usb_setup.wLength;
if (len > msft_compatible->dwLength) {
len = msft_compatible->dwLength;
}
if (len > USB_EP0_SIZE) {
len = USB_EP0_SIZE;
}
memcpy(ep0_buf_in, msft_compatible, len);
usb_ep_start_in(0x80, ep0_buf_in, len, false);
return usb_ep0_out();
} else {
return usb_ep0_stall();
}
}
void* usb_string_to_descriptor(char* str) {
USB_StringDescriptor* desc = (((USB_StringDescriptor*)ep0_buf_in));
uint16_t len = strlen(str);
const uint16_t maxlen = (USB_EP0_SIZE - 2)/2;
if (len > maxlen) len = maxlen;
desc->bLength = USB_STRING_LEN(len);
desc->bDescriptorType = USB_DTYPE_String;
for (int i=0; i<len; i++) {
desc->bString[i] = str[i];
}
return desc;
}