summaryrefslogtreecommitdiff
path: root/firmware/usbstack/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/usbstack/drivers')
-rw-r--r--firmware/usbstack/drivers/device/usb_serial.c300
-rw-r--r--firmware/usbstack/drivers/device/usb_serial.h32
-rw-r--r--firmware/usbstack/drivers/device/usb_storage.c269
-rw-r--r--firmware/usbstack/drivers/device/usb_storage.h31
4 files changed, 632 insertions, 0 deletions
diff --git a/firmware/usbstack/drivers/device/usb_serial.c b/firmware/usbstack/drivers/device/usb_serial.c
new file mode 100644
index 0000000000..fe1e52f25a
--- /dev/null
+++ b/firmware/usbstack/drivers/device/usb_serial.c
@@ -0,0 +1,300 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2007 by Christian Gmeiner
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "usb_serial.h"
21#include <string.h>
22
23static struct usb_dcd_controller_ops* ops;
24
25struct usb_device_driver usb_serial_driver = {
26 .name = "serial",
27 .bind = usb_serial_driver_bind,
28 .unbind = NULL,
29 .request = usb_serial_driver_request,
30 .suspend = NULL,
31 .resume = NULL,
32 .speed = usb_serial_driver_speed,
33};
34
35/*-------------------------------------------------------------------------*/
36/* usb descriptors */
37
38/* TODO: implement strings */
39#define GS_MANUFACTURER_STR_ID 0
40#define GS_PRODUCT_STR_ID 0
41#define GS_SERIAL_STR_ID 0
42#define GS_BULK_CONFIG_STR_ID 0
43#define GS_DATA_STR_ID 0
44
45#define GS_BULK_CONFIG_ID 1
46
47static struct usb_device_descriptor serial_device_desc = {
48 .bLength = USB_DT_DEVICE_SIZE,
49 .bDescriptorType = USB_DT_DEVICE,
50 .bcdUSB = 0x0200,
51 .bDeviceClass = USB_CLASS_COMM,
52 .bDeviceSubClass = 0,
53 .bDeviceProtocol = 0,
54 .idVendor = 0x0525,
55 .idProduct = 0xa4a6,
56 .iManufacturer = GS_MANUFACTURER_STR_ID,
57 .iProduct = GS_PRODUCT_STR_ID,
58 .iSerialNumber = GS_SERIAL_STR_ID,
59 .bNumConfigurations = 1,
60};
61
62static struct usb_config_descriptor serial_bulk_config_desc = {
63 .bLength = USB_DT_CONFIG_SIZE,
64 .bDescriptorType = USB_DT_CONFIG,
65
66 .bNumInterfaces = 1,
67 .bConfigurationValue = GS_BULK_CONFIG_ID,
68 .iConfiguration = GS_BULK_CONFIG_STR_ID,
69 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
70 .bMaxPower = 1,
71};
72
73static struct usb_interface_descriptor serial_bulk_interface_desc = {
74 .bLength = USB_DT_INTERFACE_SIZE,
75 .bDescriptorType = USB_DT_INTERFACE,
76 .bInterfaceNumber = 0,
77 .bNumEndpoints = 2,
78 .bInterfaceClass = USB_CLASS_CDC_DATA,
79 .bInterfaceSubClass = 0,
80 .bInterfaceProtocol = 0,
81 .iInterface = GS_DATA_STR_ID,
82};
83
84static struct usb_endpoint_descriptor serial_fullspeed_in_desc = {
85 .bLength = USB_DT_ENDPOINT_SIZE,
86 .bDescriptorType = USB_DT_ENDPOINT,
87 .bEndpointAddress = USB_DIR_IN,
88 .bmAttributes = USB_ENDPOINT_XFER_BULK,
89 .wMaxPacketSize = 8,
90};
91
92static struct usb_endpoint_descriptor serial_fullspeed_out_desc = {
93 .bLength = USB_DT_ENDPOINT_SIZE,
94 .bDescriptorType = USB_DT_ENDPOINT,
95 .bEndpointAddress = USB_DIR_OUT,
96 .bmAttributes = USB_ENDPOINT_XFER_BULK,
97 .wMaxPacketSize = 8,
98};
99
100static struct usb_debug_descriptor serial_debug_desc = {
101 .bLength = sizeof(struct usb_debug_descriptor),
102 .bDescriptorType = USB_DT_DEBUG,
103};
104
105static struct usb_qualifier_descriptor serial_qualifier_desc = {
106 .bLength = sizeof(struct usb_qualifier_descriptor),
107 .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
108 .bcdUSB = 0x0200,
109 .bDeviceClass = USB_CLASS_COMM,
110 .bNumConfigurations = 1,
111};
112
113struct usb_descriptor_header *serial_bulk_fullspeed_function[] = {
114 (struct usb_descriptor_header *) &serial_bulk_interface_desc,
115 (struct usb_descriptor_header *) &serial_fullspeed_in_desc,
116 (struct usb_descriptor_header *) &serial_fullspeed_out_desc,
117 NULL,
118};
119
120#define BUFFER_SIZE 100
121uint8_t buf[BUFFER_SIZE];
122
123struct usb_response res;
124
125/* helper functions */
126static int config_buf(uint8_t *buf, uint8_t type, unsigned index);
127static int set_config(int config);
128
129
130struct device {
131 struct usb_ep* in;
132 struct usb_ep* out;
133 uint32_t used_config;
134};
135
136static struct device dev;
137
138/*-------------------------------------------------------------------------*/
139
140void usb_serial_driver_init(void) {
141
142 logf("usb serial: register");
143 usb_device_driver_register(&usb_serial_driver);
144}
145
146/*-------------------------------------------------------------------------*/
147
148void usb_serial_driver_bind(void* controler_ops) {
149
150 logf("usb serial: bind");
151 ops = controler_ops;
152
153 /* serach and asign endpoints */
154 usb_ep_autoconfig_reset();
155
156 dev.in = usb_ep_autoconfig(&serial_fullspeed_in_desc);
157 if (!dev.in) {
158 goto autoconf_fail;
159 }
160 dev.in->claimed = true;
161 logf("usb serial: in: %s", dev.in->name);
162
163 dev.out = usb_ep_autoconfig(&serial_fullspeed_out_desc);
164 if (!dev.out) {
165 goto autoconf_fail;
166 }
167 dev.out->claimed = true;
168 logf("usb serial: out: %s", dev.out->name);
169
170 /* update device decsriptor */
171 serial_device_desc.bMaxPacketSize0 = ops->ep0->maxpacket;
172
173 /* update qualifie descriptor */
174 serial_qualifier_desc.bMaxPacketSize0 = ops->ep0->maxpacket;
175
176 /* update debug descriptor */
177 serial_debug_desc.bDebugInEndpoint = dev.in->ep_num;
178 serial_debug_desc.bDebugOutEndpoint = dev.out->ep_num;
179
180 return;
181
182autoconf_fail:
183 logf("failed to find endpoiunts");
184}
185
186int usb_serial_driver_request(struct usb_ctrlrequest* request) {
187
188 int ret = -EOPNOTSUPP;
189 logf("usb serial: request");
190
191 res.length = 0;
192 res.buf = NULL;
193
194 switch (request->bRequestType & USB_TYPE_MASK) {
195 case USB_TYPE_STANDARD:
196
197 switch (request->bRequest) {
198 case USB_REQ_GET_DESCRIPTOR:
199
200 switch (request->wValue >> 8) {
201 case USB_DT_DEVICE:
202 logf("usb serial: sending device desc");
203 ret = MIN(sizeof(struct usb_device_descriptor), request->wLength);
204 res.buf = &serial_device_desc;
205 break;
206
207 case USB_DT_DEVICE_QUALIFIER:
208 logf("usb serial: sending qualifier dec");
209 ret = MIN(sizeof(struct usb_qualifier_descriptor), request->wLength);
210 res.buf = &serial_qualifier_desc;
211
212 case USB_DT_CONFIG:
213 logf("usb serial: sending config desc");
214
215 ret = config_buf(buf, request->wValue >> 8, request->wValue & 0xff);
216 if (ret >= 0) {
217 logf("%d, vs %d", request->wLength, ret);
218 ret = MIN(request->wLength, (uint16_t)ret);
219 }
220 res.buf = buf;
221 break;
222
223 case USB_DT_DEBUG:
224 logf("usb serial: sending debug desc");
225 ret = MIN(sizeof(struct usb_debug_descriptor), request->wLength);
226 res.buf = &serial_debug_desc;
227 break;
228 }
229 break;
230
231 case USB_REQ_SET_CONFIGURATION:
232 logf("usb serial: set configuration %d", request->wValue);
233 ret = set_config(request->wValue);
234 break;
235
236 case USB_REQ_GET_CONFIGURATION:
237 logf("usb serial: get configuration");
238 ret = 1;
239 res.buf = &dev.used_config;
240 break;
241 }
242 }
243
244 if (ret >= 0) {
245 res.length = ret;
246 ret = ops->send(NULL, &res);
247 }
248
249 return ret;
250}
251
252void usb_serial_driver_speed(enum usb_device_speed speed) {
253
254 switch (speed) {
255 case USB_SPEED_LOW:
256 case USB_SPEED_FULL:
257 logf("usb serial: using fullspeed");
258 break;
259 case USB_SPEED_HIGH:
260 logf("usb serial: using highspeed");
261 break;
262 default:
263 logf("speed: hmm");
264 break;
265 }
266}
267
268/*-------------------------------------------------------------------------*/
269/* helper functions */
270
271static int config_buf(uint8_t *buf, uint8_t type, unsigned index) {
272
273 int len;
274
275 /* TODO check index*/
276
277 len = usb_stack_configdesc(&serial_bulk_config_desc, buf, BUFFER_SIZE, serial_bulk_fullspeed_function);
278 if (len < 0) {
279 return len;
280 }
281 ((struct usb_config_descriptor *)buf)->bDescriptorType = type;
282 return len;
283}
284
285static int set_config(int config) {
286
287 /* TODO check config*/
288
289 /* enable endpoints */
290 logf("setup %s", dev.in->name);
291 ops->enable(dev.in);
292 logf("setup %s", dev.out->name);
293 ops->enable(dev.out);
294
295 /* store config */
296 logf("using config %d", config);
297 dev.used_config = config;
298
299 return 0;
300}
diff --git a/firmware/usbstack/drivers/device/usb_serial.h b/firmware/usbstack/drivers/device/usb_serial.h
new file mode 100644
index 0000000000..808eaa16e3
--- /dev/null
+++ b/firmware/usbstack/drivers/device/usb_serial.h
@@ -0,0 +1,32 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2007 by Christian Gmeiner
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef _SERIAL_H_
21#define _SERIAL_H_
22
23#include "usbstack/core.h"
24
25/* register serial driver in usb stack */
26void usb_serial_driver_init(void);
27
28void usb_serial_driver_bind(void* controller_ops);
29int usb_serial_driver_request(struct usb_ctrlrequest* req);
30void usb_serial_driver_speed(enum usb_device_speed speed);
31
32#endif /*_SERIAL_H_*/
diff --git a/firmware/usbstack/drivers/device/usb_storage.c b/firmware/usbstack/drivers/device/usb_storage.c
new file mode 100644
index 0000000000..0cb1f108b5
--- /dev/null
+++ b/firmware/usbstack/drivers/device/usb_storage.c
@@ -0,0 +1,269 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2007 by Christian Gmeiner
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "usb_storage.h"
21#include <string.h>
22
23/*-------------------------------------------------------------------------*/
24
25static struct usb_dcd_controller_ops* ops;
26
27struct usb_device_driver usb_storage_driver = {
28 .name = "storage",
29 .bind = usb_storage_driver_bind,
30 .unbind = NULL,
31 .request = usb_storage_driver_request,
32 .suspend = NULL,
33 .resume = NULL,
34 .speed = NULL,
35};
36
37struct device {
38 struct usb_ep* in;
39 struct usb_ep* out;
40 struct usb_ep* intr;
41};
42
43static struct device dev;
44
45/*-------------------------------------------------------------------------*/
46
47#define PROTO_BULK 0x50 // Bulk only
48#define SUBCL_SCSI 0x06 // Transparent SCSI
49
50/* Bulk-only class specific requests */
51#define USB_BULK_RESET_REQUEST 0xff
52#define USB_BULK_GET_MAX_LUN_REQUEST 0xfe
53
54/*-------------------------------------------------------------------------*/
55/* usb descriptors */
56
57static struct usb_device_descriptor storage_device_desc = {
58 .bLength = USB_DT_DEVICE_SIZE,
59 .bDescriptorType = USB_DT_DEVICE,
60 .bcdUSB = 0x0200,
61 .bDeviceClass = 0,
62 .bDeviceSubClass = 0,
63 .bDeviceProtocol = 0,
64 .bMaxPacketSize0 = 64,
65 .idVendor = 0xffff,
66 .idProduct = 0x0001,
67 .iManufacturer = 0,
68 .iProduct = 0,
69 .iSerialNumber = 0,
70 .bNumConfigurations = 1,
71};
72
73static struct usb_config_descriptor storage_config_desc = {
74 .bLength = USB_DT_CONFIG_SIZE,
75 .bDescriptorType = USB_DT_CONFIG,
76
77 .bNumInterfaces = 1,
78 .bConfigurationValue = 1,
79 .iConfiguration = 0,
80 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
81 .bMaxPower = 1,
82};
83
84static struct usb_interface_descriptor storage_interface_desc = {
85 .bLength = USB_DT_INTERFACE_SIZE,
86 .bDescriptorType = USB_DT_INTERFACE,
87 .bInterfaceNumber = 0,
88 .bNumEndpoints = 3,
89 .bInterfaceClass = USB_CLASS_MASS_STORAGE,
90 .bInterfaceSubClass = SUBCL_SCSI,
91 .bInterfaceProtocol = PROTO_BULK,
92 .iInterface = 0,
93};
94
95/* endpoint I -> bulk in */
96static struct usb_endpoint_descriptor storage_bulk_in_desc = {
97 .bLength = USB_DT_ENDPOINT_SIZE,
98 .bDescriptorType = USB_DT_ENDPOINT,
99 .bEndpointAddress = USB_DIR_IN,
100 .bmAttributes = USB_ENDPOINT_XFER_BULK,
101 .wMaxPacketSize = 512,
102};
103
104/* endpoint II -> bulk out */
105static struct usb_endpoint_descriptor storage_bulk_out_desc = {
106 .bLength = USB_DT_ENDPOINT_SIZE,
107 .bDescriptorType = USB_DT_ENDPOINT,
108 .bEndpointAddress = USB_DIR_OUT,
109 .bmAttributes = USB_ENDPOINT_XFER_BULK,
110 .wMaxPacketSize = 512,
111};
112
113struct usb_descriptor_header *storage_fullspeed_function[] = {
114 (struct usb_descriptor_header *) &storage_interface_desc,
115 (struct usb_descriptor_header *) &storage_bulk_in_desc,
116 (struct usb_descriptor_header *) &storage_bulk_out_desc,
117 NULL,
118};
119
120#define BUFFER_SIZE 100
121uint8_t buf[BUFFER_SIZE];
122
123struct usb_response res;
124
125/* helper functions */
126static int config_buf(uint8_t *buf, uint8_t type, unsigned index);
127static int set_config(int config);
128
129/*-------------------------------------------------------------------------*/
130
131void usb_storage_driver_init(void) {
132
133 logf("usb storage: register");
134 usb_device_driver_register(&usb_storage_driver);
135}
136
137/*-------------------------------------------------------------------------*/
138/* device driver ops */
139
140void usb_storage_driver_bind(void* controler_ops) {
141
142 ops = controler_ops;
143
144 /* serach and asign endpoints */
145 usb_ep_autoconfig_reset();
146
147 dev.in = usb_ep_autoconfig(&storage_bulk_in_desc);
148 if (!dev.in) {
149 goto autoconf_fail;
150 }
151 dev.in->claimed = true;
152 logf("usb storage: in: %s", dev.in->name);
153
154 dev.out = usb_ep_autoconfig(&storage_bulk_out_desc);
155 if (!dev.out) {
156 goto autoconf_fail;
157 }
158 dev.out->claimed = true;
159 logf("usb storage: out: %s", dev.out->name);
160
161 return;
162
163autoconf_fail:
164 logf("failed to find endpoints");
165}
166
167int usb_storage_driver_request(struct usb_ctrlrequest* request) {
168
169 int ret = -EOPNOTSUPP;
170 logf("usb storage: request");
171
172 res.length = 0;
173 res.buf = NULL;
174
175 switch (request->bRequestType & USB_TYPE_MASK) {
176 case USB_TYPE_STANDARD:
177
178 switch (request->bRequest) {
179 case USB_REQ_GET_DESCRIPTOR:
180
181 switch (request->wValue >> 8) {
182 case USB_DT_DEVICE:
183 logf("usb storage: sending device desc");
184 ret = MIN(sizeof(struct usb_device_descriptor), request->wLength);
185 res.buf = &storage_device_desc;
186 break;
187
188 case USB_DT_CONFIG:
189 logf("usb storage: sending config desc");
190
191 ret = config_buf(buf, request->wValue >> 8, request->wValue & 0xff);
192 if (ret >= 0) {
193 logf("%d, vs %d", request->wLength, ret);
194 ret = MIN(request->wLength, (uint16_t)ret);
195 }
196 res.buf = buf;
197 break;
198 }
199 break;
200
201 case USB_REQ_SET_CONFIGURATION:
202 logf("usb storage: set configuration %d", request->wValue);
203 ret = set_config(request->wValue);
204 break;
205
206 case USB_REQ_SET_INTERFACE:
207 logf("usb storage: set interface");
208 ret = 0;
209 break;
210 }
211
212 case USB_TYPE_CLASS:
213
214 switch (request->bRequest) {
215 case USB_BULK_RESET_REQUEST:
216 logf("usb storage: bulk reset");
217 break;
218
219 case USB_BULK_GET_MAX_LUN_REQUEST:
220 logf("usb storage: get max lun");
221 /* we support no LUNs (Logical Unit Number) */
222 buf[0] = 0;
223 ret = 1;
224 break;
225 }
226 break;
227 }
228
229 if (ret >= 0) {
230 res.length = ret;
231 ret = ops->send(NULL, &res);
232 }
233
234 return ret;
235}
236
237/*-------------------------------------------------------------------------*/
238/* S/GET CONFIGURATION helpers */
239
240static int config_buf(uint8_t *buf, uint8_t type, unsigned index) {
241
242 int len;
243
244 /* only one configuration */
245 if (index != 0) {
246 return -EINVAL;
247 }
248
249 len = usb_stack_configdesc(&storage_config_desc, buf, BUFFER_SIZE, storage_fullspeed_function);
250 if (len < 0) {
251 return len;
252 }
253 ((struct usb_config_descriptor *)buf)->bDescriptorType = type;
254 return len;
255}
256
257static int set_config(int config) {
258
259 /* enable endpoints */
260 logf("setup %s", dev.in->name);
261 ops->enable(dev.in);
262 logf("setup %s", dev.out->name);
263 ops->enable(dev.out);
264
265 /* setup buffers */
266
267 return 0;
268}
269
diff --git a/firmware/usbstack/drivers/device/usb_storage.h b/firmware/usbstack/drivers/device/usb_storage.h
new file mode 100644
index 0000000000..9494aa76ff
--- /dev/null
+++ b/firmware/usbstack/drivers/device/usb_storage.h
@@ -0,0 +1,31 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2007 by Christian Gmeiner
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef _STORGAGE_H_
21#define _STORGAGE_H_
22
23#include "usbstack/core.h"
24
25/* register serial driver in usb stack */
26void usb_storage_driver_init(void);
27
28void usb_storage_driver_bind(void* controller_ops);
29int usb_storage_driver_request(struct usb_ctrlrequest* req);
30
31#endif /*_STORGAGE_H_*/