diff options
-rw-r--r-- | firmware/usbstack/core/utils.c | 51 | ||||
-rw-r--r-- | firmware/usbstack/drivers/device/usb_serial.c | 41 | ||||
-rw-r--r-- | firmware/usbstack/drivers/device/usb_storage.c | 32 |
3 files changed, 106 insertions, 18 deletions
diff --git a/firmware/usbstack/core/utils.c b/firmware/usbstack/core/utils.c index cd32fb3292..d43bd9290f 100644 --- a/firmware/usbstack/core/utils.c +++ b/firmware/usbstack/core/utils.c | |||
@@ -9,6 +9,9 @@ | |||
9 | * | 9 | * |
10 | * Copyright (C) 2007 by Christian Gmeiner | 10 | * Copyright (C) 2007 by Christian Gmeiner |
11 | * | 11 | * |
12 | * Based on linux/drivers/usb/gadget/usbstring.c | ||
13 | * Copyright (C) 2003 David Brownell | ||
14 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | 15 | * 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. | 16 | * See the file COPYING in the source tree root for full license agreement. |
14 | * | 17 | * |
@@ -123,3 +126,51 @@ void into_usb_ctrlrequest(struct usb_ctrlrequest* request) | |||
123 | logf(" -> e: %s", extra); | 126 | logf(" -> e: %s", extra); |
124 | } | 127 | } |
125 | } | 128 | } |
129 | |||
130 | int usb_stack_get_string(struct usb_string* strings, int id, uint8_t* buf) | ||
131 | { | ||
132 | struct usb_string* tmp; | ||
133 | char* sp, *dp; | ||
134 | int len; | ||
135 | |||
136 | /* if id is 0, then we need to send back all supported | ||
137 | * languages. In our case we only support one | ||
138 | * language: en-us (0x0409) */ | ||
139 | if (id == 0) { | ||
140 | buf [0] = 4; | ||
141 | buf [1] = USB_DT_STRING; | ||
142 | buf [2] = (uint8_t) 0x0409; | ||
143 | buf [3] = (uint8_t) (0x0409 >> 8); | ||
144 | return 4; | ||
145 | } | ||
146 | |||
147 | /* look for string */ | ||
148 | for (tmp = strings; tmp && tmp->s; tmp++) { | ||
149 | if (tmp->id == id) { | ||
150 | break; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | /* did we found it? */ | ||
155 | if (!tmp || !tmp->s) { | ||
156 | return -EINVAL; | ||
157 | } | ||
158 | |||
159 | len = MIN ((size_t) 126, strlen (tmp->s)); | ||
160 | memset(buf + 2, 0, 2 * len); | ||
161 | |||
162 | /* convert to utf-16le */ | ||
163 | sp = (char*)tmp->s; | ||
164 | dp = (char*)&buf[2]; | ||
165 | |||
166 | while (*sp) { | ||
167 | *dp++ = *sp++; | ||
168 | *dp++ = 0; | ||
169 | } | ||
170 | |||
171 | /* write len and tag */ | ||
172 | buf [0] = (len + 1) * 2; | ||
173 | buf [1] = USB_DT_STRING; | ||
174 | |||
175 | return buf[0]; | ||
176 | } | ||
diff --git a/firmware/usbstack/drivers/device/usb_serial.c b/firmware/usbstack/drivers/device/usb_serial.c index a37813b01c..0c66cf68fe 100644 --- a/firmware/usbstack/drivers/device/usb_serial.c +++ b/firmware/usbstack/drivers/device/usb_serial.c | |||
@@ -35,14 +35,22 @@ struct usb_device_driver usb_serial_driver = { | |||
35 | /*-------------------------------------------------------------------------*/ | 35 | /*-------------------------------------------------------------------------*/ |
36 | /* usb descriptors */ | 36 | /* usb descriptors */ |
37 | 37 | ||
38 | /* TODO: implement strings */ | 38 | #define MANUFACTURER_STR_ID 1 |
39 | #define GS_MANUFACTURER_STR_ID 0 | 39 | #define PRODUCT_STR_ID 2 |
40 | #define GS_PRODUCT_STR_ID 0 | 40 | #define SERIAL_STR_ID 3 |
41 | #define GS_SERIAL_STR_ID 0 | 41 | #define BULK_CONFIG_STR_ID 4 |
42 | #define GS_BULK_CONFIG_STR_ID 0 | 42 | #define DATA_STR_ID 5 |
43 | #define GS_DATA_STR_ID 0 | 43 | |
44 | /* static strings, in UTF-8 */ | ||
45 | static struct usb_string strings[] = { | ||
46 | { MANUFACTURER_STR_ID, "RockBox" }, | ||
47 | { PRODUCT_STR_ID, "RockBox Serial Driver" }, | ||
48 | { SERIAL_STR_ID, "0" }, | ||
49 | { BULK_CONFIG_STR_ID, "Serial Bulk" }, | ||
50 | { DATA_STR_ID, "Serial Data" }, | ||
51 | }; | ||
44 | 52 | ||
45 | #define GS_BULK_CONFIG_ID 1 | 53 | #define BULK_CONFIG_ID 1 |
46 | 54 | ||
47 | static struct usb_device_descriptor serial_device_desc = { | 55 | static struct usb_device_descriptor serial_device_desc = { |
48 | .bLength = USB_DT_DEVICE_SIZE, | 56 | .bLength = USB_DT_DEVICE_SIZE, |
@@ -53,9 +61,9 @@ static struct usb_device_descriptor serial_device_desc = { | |||
53 | .bDeviceProtocol = 0, | 61 | .bDeviceProtocol = 0, |
54 | .idVendor = 0x0525, | 62 | .idVendor = 0x0525, |
55 | .idProduct = 0xa4a6, | 63 | .idProduct = 0xa4a6, |
56 | .iManufacturer = GS_MANUFACTURER_STR_ID, | 64 | .iManufacturer = MANUFACTURER_STR_ID, |
57 | .iProduct = GS_PRODUCT_STR_ID, | 65 | .iProduct = PRODUCT_STR_ID, |
58 | .iSerialNumber = GS_SERIAL_STR_ID, | 66 | .iSerialNumber = SERIAL_STR_ID, |
59 | .bNumConfigurations = 1, | 67 | .bNumConfigurations = 1, |
60 | }; | 68 | }; |
61 | 69 | ||
@@ -64,8 +72,8 @@ static struct usb_config_descriptor serial_bulk_config_desc = { | |||
64 | .bDescriptorType = USB_DT_CONFIG, | 72 | .bDescriptorType = USB_DT_CONFIG, |
65 | 73 | ||
66 | .bNumInterfaces = 1, | 74 | .bNumInterfaces = 1, |
67 | .bConfigurationValue = GS_BULK_CONFIG_ID, | 75 | .bConfigurationValue = BULK_CONFIG_ID, |
68 | .iConfiguration = GS_BULK_CONFIG_STR_ID, | 76 | .iConfiguration = BULK_CONFIG_STR_ID, |
69 | .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, | 77 | .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, |
70 | .bMaxPower = 1, | 78 | .bMaxPower = 1, |
71 | }; | 79 | }; |
@@ -78,7 +86,7 @@ static struct usb_interface_descriptor serial_bulk_interface_desc = { | |||
78 | .bInterfaceClass = USB_CLASS_CDC_DATA, | 86 | .bInterfaceClass = USB_CLASS_CDC_DATA, |
79 | .bInterfaceSubClass = 0, | 87 | .bInterfaceSubClass = 0, |
80 | .bInterfaceProtocol = 0, | 88 | .bInterfaceProtocol = 0, |
81 | .iInterface = GS_DATA_STR_ID, | 89 | .iInterface = DATA_STR_ID, |
82 | }; | 90 | }; |
83 | 91 | ||
84 | static struct usb_endpoint_descriptor serial_fs_in_desc = { | 92 | static struct usb_endpoint_descriptor serial_fs_in_desc = { |
@@ -261,6 +269,13 @@ int usb_serial_driver_request(struct usb_ctrlrequest* request) | |||
261 | ret = MIN(sizeof(struct usb_debug_descriptor), request->wLength); | 269 | ret = MIN(sizeof(struct usb_debug_descriptor), request->wLength); |
262 | res.buf = &serial_debug_desc; | 270 | res.buf = &serial_debug_desc; |
263 | break; | 271 | break; |
272 | |||
273 | case USB_DT_STRING: | ||
274 | logf("usb serial: sending string desc"); | ||
275 | ret = usb_stack_get_string(strings, request->wValue & 0xff, buf); | ||
276 | ret = MIN(ret, request->wLength); | ||
277 | res.buf = buf; | ||
278 | break; | ||
264 | } | 279 | } |
265 | break; | 280 | break; |
266 | 281 | ||
diff --git a/firmware/usbstack/drivers/device/usb_storage.c b/firmware/usbstack/drivers/device/usb_storage.c index 49644e5805..45fd5c14b7 100644 --- a/firmware/usbstack/drivers/device/usb_storage.c +++ b/firmware/usbstack/drivers/device/usb_storage.c | |||
@@ -46,6 +46,21 @@ struct usb_device_driver usb_storage_driver = { | |||
46 | /*-------------------------------------------------------------------------*/ | 46 | /*-------------------------------------------------------------------------*/ |
47 | /* usb descriptors */ | 47 | /* usb descriptors */ |
48 | 48 | ||
49 | #define MANUFACTURER_STR_ID 1 | ||
50 | #define PRODUCT_STR_ID 2 | ||
51 | #define SERIAL_STR_ID 3 | ||
52 | #define CONFIG_STR_ID 4 | ||
53 | #define DATA_STR_ID 5 | ||
54 | |||
55 | /* static strings, in UTF-8 */ | ||
56 | static struct usb_string strings[] = { | ||
57 | { MANUFACTURER_STR_ID, "RockBox" }, | ||
58 | { PRODUCT_STR_ID, "RockBox Storage Driver" }, | ||
59 | { SERIAL_STR_ID, "0" }, | ||
60 | { CONFIG_STR_ID, "Storage Bulk" }, | ||
61 | { DATA_STR_ID, "Storage Data" }, | ||
62 | }; | ||
63 | |||
49 | static struct usb_device_descriptor storage_device_desc = { | 64 | static struct usb_device_descriptor storage_device_desc = { |
50 | .bLength = USB_DT_DEVICE_SIZE, | 65 | .bLength = USB_DT_DEVICE_SIZE, |
51 | .bDescriptorType = USB_DT_DEVICE, | 66 | .bDescriptorType = USB_DT_DEVICE, |
@@ -55,9 +70,9 @@ static struct usb_device_descriptor storage_device_desc = { | |||
55 | .bDeviceProtocol = 0, | 70 | .bDeviceProtocol = 0, |
56 | .idVendor = 0xffff, | 71 | .idVendor = 0xffff, |
57 | .idProduct = 0x0001, | 72 | .idProduct = 0x0001, |
58 | .iManufacturer = 0, | 73 | .iManufacturer = MANUFACTURER_STR_ID, |
59 | .iProduct = 0, | 74 | .iProduct = PRODUCT_STR_ID, |
60 | .iSerialNumber = 0, | 75 | .iSerialNumber = SERIAL_STR_ID, |
61 | .bNumConfigurations = 1, | 76 | .bNumConfigurations = 1, |
62 | }; | 77 | }; |
63 | 78 | ||
@@ -67,7 +82,7 @@ static struct usb_config_descriptor storage_config_desc = { | |||
67 | 82 | ||
68 | .bNumInterfaces = 1, | 83 | .bNumInterfaces = 1, |
69 | .bConfigurationValue = 1, | 84 | .bConfigurationValue = 1, |
70 | .iConfiguration = 0, | 85 | .iConfiguration = CONFIG_STR_ID, |
71 | .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, | 86 | .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, |
72 | .bMaxPower = 1, | 87 | .bMaxPower = 1, |
73 | }; | 88 | }; |
@@ -80,7 +95,7 @@ static struct usb_interface_descriptor storage_interface_desc = { | |||
80 | .bInterfaceClass = USB_CLASS_MASS_STORAGE, | 95 | .bInterfaceClass = USB_CLASS_MASS_STORAGE, |
81 | .bInterfaceSubClass = SUBCL_SCSI, | 96 | .bInterfaceSubClass = SUBCL_SCSI, |
82 | .bInterfaceProtocol = PROTO_BULK, | 97 | .bInterfaceProtocol = PROTO_BULK, |
83 | .iInterface = 0, | 98 | .iInterface = DATA_STR_ID, |
84 | }; | 99 | }; |
85 | 100 | ||
86 | static struct usb_endpoint_descriptor storage_fs_bulk_in_desc = { | 101 | static struct usb_endpoint_descriptor storage_fs_bulk_in_desc = { |
@@ -246,6 +261,13 @@ int usb_storage_driver_request(struct usb_ctrlrequest* request) | |||
246 | } | 261 | } |
247 | res.buf = buf; | 262 | res.buf = buf; |
248 | break; | 263 | break; |
264 | |||
265 | case USB_DT_STRING: | ||
266 | logf("usb storage: sending string desc"); | ||
267 | ret = usb_stack_get_string(strings, request->wValue & 0xff, buf); | ||
268 | ret = MIN(ret, request->wLength); | ||
269 | res.buf = buf; | ||
270 | break; | ||
249 | } | 271 | } |
250 | break; | 272 | break; |
251 | 273 | ||