diff options
author | Frank Gevaerts <frank@gevaerts.be> | 2008-03-06 21:25:09 +0000 |
---|---|---|
committer | Frank Gevaerts <frank@gevaerts.be> | 2008-03-06 21:25:09 +0000 |
commit | f0b4a32d6f983b1bece0b8cb2f2da1fdd23b012e (patch) | |
tree | 90f36c9f421c174d0385268ea47f0013b0c8cd8c | |
parent | 5f83f0e4d2aaad77bda682cfd81a7ebb111a6024 (diff) | |
download | rockbox-f0b4a32d6f983b1bece0b8cb2f2da1fdd23b012e.tar.gz rockbox-f0b4a32d6f983b1bece0b8cb2f2da1fdd23b012e.zip |
reorganise the usb stack to provide a clean separation between core and class drivers
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16541 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/debug_menu.c | 11 | ||||
-rw-r--r-- | firmware/export/usb.h | 17 | ||||
-rw-r--r-- | firmware/export/usb_core.h | 23 | ||||
-rw-r--r-- | firmware/usb.c | 8 | ||||
-rw-r--r-- | firmware/usbstack/usb_class_driver.h | 59 | ||||
-rw-r--r-- | firmware/usbstack/usb_core.c | 750 | ||||
-rw-r--r-- | firmware/usbstack/usb_serial.c | 124 | ||||
-rw-r--r-- | firmware/usbstack/usb_serial.h | 5 | ||||
-rw-r--r-- | firmware/usbstack/usb_storage.c | 364 | ||||
-rw-r--r-- | firmware/usbstack/usb_storage.h | 3 |
10 files changed, 787 insertions, 577 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 3db6026901..3788631c81 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c | |||
@@ -102,6 +102,10 @@ | |||
102 | #include "as3514.h" | 102 | #include "as3514.h" |
103 | #endif | 103 | #endif |
104 | 104 | ||
105 | #if defined(HAVE_USBSTACK) && defined(ROCKBOX_HAS_LOGF) | ||
106 | #include "usb_core.h" | ||
107 | #endif | ||
108 | |||
105 | /*---------------------------------------------------*/ | 109 | /*---------------------------------------------------*/ |
106 | /* SPECIAL DEBUG STUFF */ | 110 | /* SPECIAL DEBUG STUFF */ |
107 | /*---------------------------------------------------*/ | 111 | /*---------------------------------------------------*/ |
@@ -2364,13 +2368,12 @@ static bool dbg_scrollwheel(void) | |||
2364 | #endif | 2368 | #endif |
2365 | 2369 | ||
2366 | #if defined(HAVE_USBSTACK) && defined(ROCKBOX_HAS_LOGF) | 2370 | #if defined(HAVE_USBSTACK) && defined(ROCKBOX_HAS_LOGF) |
2367 | extern bool usb_core_serial_enabled; | ||
2368 | |||
2369 | static bool logf_usb_serial(void) | 2371 | static bool logf_usb_serial(void) |
2370 | { | 2372 | { |
2371 | usb_core_serial_enabled = !usb_core_serial_enabled; | 2373 | bool serial_enabled = !usb_core_driver_enabled(USB_DRIVER_SERIAL); |
2374 | usb_core_enable_driver(USB_DRIVER_SERIAL,serial_enabled); | ||
2372 | gui_syncsplash(HZ, "USB logf %s", | 2375 | gui_syncsplash(HZ, "USB logf %s", |
2373 | usb_core_serial_enabled?"enabled":"disabled"); | 2376 | serial_enabled?"enabled":"disabled"); |
2374 | return false; | 2377 | return false; |
2375 | } | 2378 | } |
2376 | #endif | 2379 | #endif |
diff --git a/firmware/export/usb.h b/firmware/export/usb.h index 67793729c6..4dae7c2e68 100644 --- a/firmware/export/usb.h +++ b/firmware/export/usb.h | |||
@@ -24,13 +24,13 @@ | |||
24 | 24 | ||
25 | /* Messages from usb_tick and thread states */ | 25 | /* Messages from usb_tick and thread states */ |
26 | enum { | 26 | enum { |
27 | USB_INSERTED, | 27 | USB_INSERTED, |
28 | USB_EXTRACTED, | 28 | USB_EXTRACTED, |
29 | USB_REENABLE, | 29 | USB_REENABLE, |
30 | USB_POWERED, | 30 | USB_POWERED, |
31 | USB_TRANSFER_COMPLETION, | 31 | USB_TRANSFER_COMPLETION, |
32 | USB_REQUEST_DISK, | 32 | USB_REQUEST_DISK, |
33 | USB_REQUEST_REBOOT | 33 | USB_REQUEST_REBOOT |
34 | }; | 34 | }; |
35 | 35 | ||
36 | 36 | ||
@@ -69,7 +69,8 @@ enum { | |||
69 | enum { | 69 | enum { |
70 | USB_DRIVER_MASS_STORAGE, | 70 | USB_DRIVER_MASS_STORAGE, |
71 | USB_DRIVER_SERIAL, | 71 | USB_DRIVER_SERIAL, |
72 | USB_DRIVER_CHARGING_ONLY | 72 | USB_DRIVER_CHARGING_ONLY, |
73 | USB_NUM_DRIVERS | ||
73 | }; | 74 | }; |
74 | #endif | 75 | #endif |
75 | #ifdef HAVE_USBSTACK | 76 | #ifdef HAVE_USBSTACK |
diff --git a/firmware/export/usb_core.h b/firmware/export/usb_core.h index bb4ce6cedd..97712bca4d 100644 --- a/firmware/export/usb_core.h +++ b/firmware/export/usb_core.h | |||
@@ -21,7 +21,7 @@ | |||
21 | 21 | ||
22 | #ifndef BOOTLOADER | 22 | #ifndef BOOTLOADER |
23 | 23 | ||
24 | //#define USB_SERIAL | 24 | #define USB_SERIAL |
25 | #define USB_STORAGE | 25 | #define USB_STORAGE |
26 | #define USB_CHARGING_ONLY | 26 | #define USB_CHARGING_ONLY |
27 | #else /* BOOTLOADER */ | 27 | #else /* BOOTLOADER */ |
@@ -32,19 +32,8 @@ | |||
32 | #include "usb.h" | 32 | #include "usb.h" |
33 | 33 | ||
34 | /* endpoints */ | 34 | /* endpoints */ |
35 | enum { | 35 | #define EP_CONTROL 0 |
36 | EP_CONTROL = 0, | 36 | #define NUM_ENDPOINTS 3 |
37 | #ifdef USB_STORAGE | ||
38 | EP_MASS_STORAGE, | ||
39 | #endif | ||
40 | #ifdef USB_SERIAL | ||
41 | EP_SERIAL, | ||
42 | #endif | ||
43 | #ifdef USB_CHARGING_ONLY | ||
44 | EP_CHARGING_ONLY, | ||
45 | #endif | ||
46 | NUM_ENDPOINTS | ||
47 | }; | ||
48 | 37 | ||
49 | extern int usb_max_pkt_size; | 38 | extern int usb_max_pkt_size; |
50 | 39 | ||
@@ -54,7 +43,9 @@ void usb_core_control_request(struct usb_ctrlrequest* req); | |||
54 | void usb_core_transfer_complete(int endpoint, bool in, int status, int length); | 43 | void usb_core_transfer_complete(int endpoint, bool in, int status, int length); |
55 | void usb_core_bus_reset(void); | 44 | void usb_core_bus_reset(void); |
56 | bool usb_core_exclusive_connection(void); | 45 | bool usb_core_exclusive_connection(void); |
57 | void usb_core_enable_protocol(int driver,bool enabled); | 46 | void usb_core_enable_driver(int driver,bool enabled); |
58 | void usb_core_handle_transfer_completion(struct usb_transfer_completion_event_data* event); | 47 | bool usb_core_driver_enabled (int driver); |
48 | void usb_core_handle_transfer_completion( | ||
49 | struct usb_transfer_completion_event_data* event); | ||
59 | #endif | 50 | #endif |
60 | 51 | ||
diff --git a/firmware/usb.c b/firmware/usb.c index 529ecb773b..d59cbc3d15 100644 --- a/firmware/usb.c +++ b/firmware/usb.c | |||
@@ -191,8 +191,8 @@ static void usb_thread(void) | |||
191 | { | 191 | { |
192 | usb_state = USB_POWERED; | 192 | usb_state = USB_POWERED; |
193 | #ifdef HAVE_USBSTACK | 193 | #ifdef HAVE_USBSTACK |
194 | usb_core_enable_protocol(USB_DRIVER_MASS_STORAGE,false); | 194 | usb_core_enable_driver(USB_DRIVER_MASS_STORAGE,false); |
195 | usb_core_enable_protocol(USB_DRIVER_CHARGING_ONLY,true); | 195 | usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY,true); |
196 | usb_enable(true); | 196 | usb_enable(true); |
197 | #endif | 197 | #endif |
198 | } | 198 | } |
@@ -200,8 +200,8 @@ static void usb_thread(void) | |||
200 | #endif | 200 | #endif |
201 | { | 201 | { |
202 | #ifdef HAVE_USBSTACK | 202 | #ifdef HAVE_USBSTACK |
203 | usb_core_enable_protocol(USB_DRIVER_MASS_STORAGE,true); | 203 | usb_core_enable_driver(USB_DRIVER_MASS_STORAGE,true); |
204 | usb_core_enable_protocol(USB_DRIVER_CHARGING_ONLY,false); | 204 | usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY,false); |
205 | usb_enable(true); | 205 | usb_enable(true); |
206 | #else | 206 | #else |
207 | /* Tell all threads that they have to back off the ATA. | 207 | /* Tell all threads that they have to back off the ATA. |
diff --git a/firmware/usbstack/usb_class_driver.h b/firmware/usbstack/usb_class_driver.h new file mode 100644 index 0000000000..631d5a3bc1 --- /dev/null +++ b/firmware/usbstack/usb_class_driver.h | |||
@@ -0,0 +1,59 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: $ | ||
9 | * | ||
10 | * Copyright (C) 2008 Frank Gevaerts | ||
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 _USB_CLASS_DRIVER_H_ | ||
21 | #define _USB_CLASS_DRIVER_H_ | ||
22 | |||
23 | /* Common api, implemented by all class drivers */ | ||
24 | |||
25 | struct usb_class_driver { | ||
26 | bool enabled; | ||
27 | bool needs_exclusive_ata; | ||
28 | int usb_endpoint; | ||
29 | int usb_interface; | ||
30 | |||
31 | /* Asks the driver to put the interface descriptor and all other | ||
32 | needed descriptor for this driver at dest, for the given settings. | ||
33 | Returns the number of bytes taken by these descriptors. */ | ||
34 | int (*get_config_descriptor)(unsigned char *dest, | ||
35 | int max_packet_size, int interface_number, int endpoint); | ||
36 | |||
37 | /* Tells the driver that a usb connection has been set up and is now | ||
38 | ready to use. */ | ||
39 | void (*init_connection)(int interface,int endpoint); | ||
40 | |||
41 | /* Initialises the driver. This can be called multiple times, | ||
42 | and should not perform any action that can disturb other threads | ||
43 | (like getting the audio buffer) */ | ||
44 | void (*init)(void); | ||
45 | |||
46 | /* Tells the driver that the usb connection is no longer active */ | ||
47 | void (*disconnect)(void); | ||
48 | |||
49 | /* Tells the driver that a usb transfer has been completed. Note that "in" | ||
50 | is relative to the host */ | ||
51 | void (*transfer_complete)(bool in, int status, int length); | ||
52 | |||
53 | /* Tells the driver that a control request has come in. If the driver is | ||
54 | able to handle it, it should ack the request, and return true. Otherwise | ||
55 | it should return false. */ | ||
56 | bool (*control_request)(struct usb_ctrlrequest* req); | ||
57 | }; | ||
58 | |||
59 | #endif | ||
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c index 96a5994417..ff54e4269f 100644 --- a/firmware/usbstack/usb_core.c +++ b/firmware/usbstack/usb_core.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "usb_ch9.h" | 27 | #include "usb_ch9.h" |
28 | #include "usb_drv.h" | 28 | #include "usb_drv.h" |
29 | #include "usb_core.h" | 29 | #include "usb_core.h" |
30 | #include "usb_class_driver.h" | ||
30 | 31 | ||
31 | #if defined(USB_STORAGE) | 32 | #if defined(USB_STORAGE) |
32 | #include "usb_storage.h" | 33 | #include "usb_storage.h" |
@@ -36,7 +37,7 @@ | |||
36 | #include "usb_serial.h" | 37 | #include "usb_serial.h" |
37 | #endif | 38 | #endif |
38 | 39 | ||
39 | /* TODO: Move this target-specific stuff somewhere else (serial number reading) */ | 40 | /* TODO: Move target-specific stuff somewhere else (serial number reading) */ |
40 | 41 | ||
41 | #ifdef HAVE_AS3514 | 42 | #ifdef HAVE_AS3514 |
42 | #include "i2c-pp.h" | 43 | #include "i2c-pp.h" |
@@ -54,7 +55,9 @@ | |||
54 | #define USB_SC_SCSI 0x06 /* Transparent */ | 55 | #define USB_SC_SCSI 0x06 /* Transparent */ |
55 | #define USB_PROT_BULK 0x50 /* bulk only */ | 56 | #define USB_PROT_BULK 0x50 /* bulk only */ |
56 | 57 | ||
57 | static const struct usb_device_descriptor __attribute__((aligned(2))) device_descriptor= { | 58 | static const struct usb_device_descriptor __attribute__((aligned(2))) |
59 | device_descriptor= | ||
60 | { | ||
58 | .bLength = sizeof(struct usb_device_descriptor), | 61 | .bLength = sizeof(struct usb_device_descriptor), |
59 | .bDescriptorType = USB_DT_DEVICE, | 62 | .bDescriptorType = USB_DT_DEVICE, |
60 | #ifdef USE_HIGH_SPEED | 63 | #ifdef USE_HIGH_SPEED |
@@ -75,7 +78,8 @@ static const struct usb_device_descriptor __attribute__((aligned(2))) device_des | |||
75 | .bNumConfigurations = 1 | 78 | .bNumConfigurations = 1 |
76 | } ; | 79 | } ; |
77 | 80 | ||
78 | struct usb_config_descriptor __attribute__((aligned(2))) config_descriptor = | 81 | static struct usb_config_descriptor __attribute__((aligned(2))) |
82 | config_descriptor = | ||
79 | { | 83 | { |
80 | .bLength = sizeof(struct usb_config_descriptor), | 84 | .bLength = sizeof(struct usb_config_descriptor), |
81 | .bDescriptorType = USB_DT_CONFIG, | 85 | .bDescriptorType = USB_DT_CONFIG, |
@@ -89,7 +93,8 @@ struct usb_config_descriptor __attribute__((aligned(2))) config_descriptor = | |||
89 | 93 | ||
90 | #ifdef USB_CHARGING_ONLY | 94 | #ifdef USB_CHARGING_ONLY |
91 | /* dummy interface for charging-only */ | 95 | /* dummy interface for charging-only */ |
92 | struct usb_interface_descriptor __attribute__((aligned(2))) charging_interface_descriptor = | 96 | static struct usb_interface_descriptor __attribute__((aligned(2))) |
97 | charging_interface_descriptor = | ||
93 | { | 98 | { |
94 | .bLength = sizeof(struct usb_interface_descriptor), | 99 | .bLength = sizeof(struct usb_interface_descriptor), |
95 | .bDescriptorType = USB_DT_INTERFACE, | 100 | .bDescriptorType = USB_DT_INTERFACE, |
@@ -103,77 +108,8 @@ struct usb_interface_descriptor __attribute__((aligned(2))) charging_interface_d | |||
103 | }; | 108 | }; |
104 | #endif | 109 | #endif |
105 | 110 | ||
106 | #ifdef USB_STORAGE | 111 | static const struct usb_qualifier_descriptor __attribute__((aligned(2))) |
107 | /* storage interface */ | 112 | qualifier_descriptor = |
108 | struct usb_interface_descriptor __attribute__((aligned(2))) mass_storage_interface_descriptor = | ||
109 | { | ||
110 | .bLength = sizeof(struct usb_interface_descriptor), | ||
111 | .bDescriptorType = USB_DT_INTERFACE, | ||
112 | .bInterfaceNumber = 0, | ||
113 | .bAlternateSetting = 0, | ||
114 | .bNumEndpoints = 2, | ||
115 | .bInterfaceClass = USB_CLASS_MASS_STORAGE, | ||
116 | .bInterfaceSubClass = USB_SC_SCSI, | ||
117 | .bInterfaceProtocol = USB_PROT_BULK, | ||
118 | .iInterface = 0 | ||
119 | }; | ||
120 | |||
121 | struct usb_endpoint_descriptor __attribute__((aligned(2))) mass_storage_ep_in_descriptor = | ||
122 | { | ||
123 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
124 | .bDescriptorType = USB_DT_ENDPOINT, | ||
125 | .bEndpointAddress = EP_MASS_STORAGE | USB_DIR_IN, | ||
126 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
127 | .wMaxPacketSize = 16, | ||
128 | .bInterval = 0 | ||
129 | }; | ||
130 | struct usb_endpoint_descriptor __attribute__((aligned(2))) mass_storage_ep_out_descriptor = | ||
131 | { | ||
132 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
133 | .bDescriptorType = USB_DT_ENDPOINT, | ||
134 | .bEndpointAddress = EP_MASS_STORAGE | USB_DIR_OUT, | ||
135 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
136 | .wMaxPacketSize = 16, | ||
137 | .bInterval = 0 | ||
138 | }; | ||
139 | #endif | ||
140 | |||
141 | #ifdef USB_SERIAL | ||
142 | /* serial interface */ | ||
143 | struct usb_interface_descriptor __attribute__((aligned(2))) serial_interface_descriptor = | ||
144 | { | ||
145 | .bLength = sizeof(struct usb_interface_descriptor), | ||
146 | .bDescriptorType = USB_DT_INTERFACE, | ||
147 | .bInterfaceNumber = 0, | ||
148 | .bAlternateSetting = 0, | ||
149 | .bNumEndpoints = 2, | ||
150 | .bInterfaceClass = USB_CLASS_CDC_DATA, | ||
151 | .bInterfaceSubClass = 0, | ||
152 | .bInterfaceProtocol = 0, | ||
153 | .iInterface = 0 | ||
154 | }; | ||
155 | |||
156 | struct usb_endpoint_descriptor __attribute__((aligned(2))) serial_ep_in_descriptor = | ||
157 | { | ||
158 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
159 | .bDescriptorType = USB_DT_ENDPOINT, | ||
160 | .bEndpointAddress = EP_SERIAL | USB_DIR_IN, | ||
161 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
162 | .wMaxPacketSize = 16, | ||
163 | .bInterval = 0 | ||
164 | }; | ||
165 | struct usb_endpoint_descriptor __attribute__((aligned(2))) serial_ep_out_descriptor = | ||
166 | { | ||
167 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
168 | .bDescriptorType = USB_DT_ENDPOINT, | ||
169 | .bEndpointAddress = EP_SERIAL | USB_DIR_OUT, | ||
170 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
171 | .wMaxPacketSize = 16, | ||
172 | .bInterval = 0 | ||
173 | }; | ||
174 | #endif | ||
175 | |||
176 | static const struct usb_qualifier_descriptor __attribute__((aligned(2))) qualifier_descriptor = | ||
177 | { | 113 | { |
178 | .bLength = sizeof(struct usb_qualifier_descriptor), | 114 | .bLength = sizeof(struct usb_qualifier_descriptor), |
179 | .bDescriptorType = USB_DT_DEVICE_QUALIFIER, | 115 | .bDescriptorType = USB_DT_DEVICE_QUALIFIER, |
@@ -185,21 +121,26 @@ static const struct usb_qualifier_descriptor __attribute__((aligned(2))) qualifi | |||
185 | .bNumConfigurations = 1 | 121 | .bNumConfigurations = 1 |
186 | }; | 122 | }; |
187 | 123 | ||
188 | static struct usb_string_descriptor __attribute__((aligned(2))) usb_string_iManufacturer = | 124 | static struct usb_string_descriptor __attribute__((aligned(2))) |
125 | usb_string_iManufacturer = | ||
189 | { | 126 | { |
190 | 24, | 127 | 24, |
191 | USB_DT_STRING, | 128 | USB_DT_STRING, |
192 | {'R','o','c','k','b','o','x','.','o','r','g'} | 129 | {'R','o','c','k','b','o','x','.','o','r','g'} |
193 | }; | 130 | }; |
194 | 131 | ||
195 | static struct usb_string_descriptor __attribute__((aligned(2))) usb_string_iProduct = | 132 | static struct usb_string_descriptor __attribute__((aligned(2))) |
133 | usb_string_iProduct = | ||
196 | { | 134 | { |
197 | 42, | 135 | 42, |
198 | USB_DT_STRING, | 136 | USB_DT_STRING, |
199 | {'R','o','c','k','b','o','x',' ','m','e','d','i','a',' ','p','l','a','y','e','r'} | 137 | {'R','o','c','k','b','o','x',' ', |
138 | 'm','e','d','i','a',' ', | ||
139 | 'p','l','a','y','e','r'} | ||
200 | }; | 140 | }; |
201 | 141 | ||
202 | static struct usb_string_descriptor __attribute__((aligned(2))) usb_string_iSerial = | 142 | static struct usb_string_descriptor __attribute__((aligned(2))) |
143 | usb_string_iSerial = | ||
203 | { | 144 | { |
204 | 84, | 145 | 84, |
205 | USB_DT_STRING, | 146 | USB_DT_STRING, |
@@ -211,14 +152,16 @@ static struct usb_string_descriptor __attribute__((aligned(2))) usb_string_iSeri | |||
211 | /* Generic for all targets */ | 152 | /* Generic for all targets */ |
212 | 153 | ||
213 | /* this is stringid #0: languages supported */ | 154 | /* this is stringid #0: languages supported */ |
214 | static struct usb_string_descriptor __attribute__((aligned(2))) lang_descriptor = | 155 | static struct usb_string_descriptor __attribute__((aligned(2))) |
156 | lang_descriptor = | ||
215 | { | 157 | { |
216 | 4, | 158 | 4, |
217 | USB_DT_STRING, | 159 | USB_DT_STRING, |
218 | {0x0409} /* LANGID US English */ | 160 | {0x0409} /* LANGID US English */ |
219 | }; | 161 | }; |
220 | 162 | ||
221 | static struct usb_string_descriptor __attribute__((aligned(2))) usb_string_charging_only = | 163 | static struct usb_string_descriptor __attribute__((aligned(2))) |
164 | usb_string_charging_only = | ||
222 | { | 165 | { |
223 | 28, | 166 | 28, |
224 | USB_DT_STRING, | 167 | USB_DT_STRING, |
@@ -238,14 +181,56 @@ static int usb_address = 0; | |||
238 | static bool initialized = false; | 181 | static bool initialized = false; |
239 | static enum { DEFAULT, ADDRESS, CONFIGURED } usb_state; | 182 | static enum { DEFAULT, ADDRESS, CONFIGURED } usb_state; |
240 | 183 | ||
184 | static int usb_core_num_interfaces; | ||
185 | |||
186 | int usb_charging_get_config_descriptor(unsigned char *dest,int max_packet_size, | ||
187 | int interface_number,int endpoint); | ||
188 | |||
189 | struct usb_class_driver drivers[] = | ||
190 | { | ||
241 | #ifdef USB_STORAGE | 191 | #ifdef USB_STORAGE |
242 | static bool usb_core_storage_enabled = false; | 192 | [USB_DRIVER_MASS_STORAGE] = { |
193 | .enabled = false, | ||
194 | .needs_exclusive_ata = true, | ||
195 | .usb_endpoint = 0, | ||
196 | .usb_interface = 0, | ||
197 | .get_config_descriptor = usb_storage_get_config_descriptor, | ||
198 | .init_connection = usb_storage_init_connection, | ||
199 | .init = usb_storage_init, | ||
200 | .disconnect = NULL, | ||
201 | .transfer_complete = usb_storage_transfer_complete, | ||
202 | .control_request = usb_storage_control_request | ||
203 | }, | ||
204 | #endif | ||
205 | #ifdef USB_SERIAL | ||
206 | [USB_DRIVER_SERIAL] = { | ||
207 | .enabled = false, | ||
208 | .needs_exclusive_ata = false, | ||
209 | .usb_endpoint = 0, | ||
210 | .usb_interface = 0, | ||
211 | .get_config_descriptor = usb_serial_get_config_descriptor, | ||
212 | .init_connection = usb_serial_init_connection, | ||
213 | .init = usb_serial_init, | ||
214 | .disconnect = usb_serial_disconnect, | ||
215 | .transfer_complete = usb_serial_transfer_complete, | ||
216 | .control_request = usb_serial_control_request | ||
217 | }, | ||
243 | #endif | 218 | #endif |
244 | /* Next one is non-static, to enable setting it from the debug menu */ | ||
245 | bool usb_core_serial_enabled = false; | ||
246 | #ifdef USB_CHARGING_ONLY | 219 | #ifdef USB_CHARGING_ONLY |
247 | static bool usb_core_charging_enabled = false; | 220 | [USB_DRIVER_CHARGING_ONLY] = { |
221 | .enabled = false, | ||
222 | .needs_exclusive_ata = false, | ||
223 | .usb_endpoint = 0, | ||
224 | .usb_interface = 0, | ||
225 | .get_config_descriptor = usb_charging_get_config_descriptor, | ||
226 | .init_connection = NULL, | ||
227 | .init = NULL, | ||
228 | .disconnect = NULL, | ||
229 | .transfer_complete = NULL, | ||
230 | .control_request = NULL | ||
231 | }, | ||
248 | #endif | 232 | #endif |
233 | }; | ||
249 | 234 | ||
250 | static void usb_core_control_request_handler(struct usb_ctrlrequest* req); | 235 | static void usb_core_control_request_handler(struct usb_ctrlrequest* req); |
251 | static int ack_control(struct usb_ctrlrequest* req); | 236 | static int ack_control(struct usb_ctrlrequest* req); |
@@ -272,11 +257,9 @@ static void set_serial_descriptor(void) | |||
272 | uint32_t x; | 257 | uint32_t x; |
273 | int i,j; | 258 | int i,j; |
274 | 259 | ||
275 | for (i = 0; i < 2; i++) | 260 | for (i = 0; i < 2; i++) { |
276 | { | ||
277 | x = serial[i]; | 261 | x = serial[i]; |
278 | for (j=0;j<8;j++) | 262 | for (j=0;j<8;j++) { |
279 | { | ||
280 | *p-- = hex[x & 0xf]; | 263 | *p-- = hex[x & 0xf]; |
281 | x >>= 4; | 264 | x >>= 4; |
282 | } | 265 | } |
@@ -292,8 +275,7 @@ static void set_serial_descriptor(void) | |||
292 | int i; | 275 | int i; |
293 | 276 | ||
294 | i2c_readbytes(AS3514_I2C_ADDR, 0x30, 0x10, serial); | 277 | i2c_readbytes(AS3514_I2C_ADDR, 0x30, 0x10, serial); |
295 | for (i = 0; i < 16; i++) | 278 | for (i = 0; i < 16; i++) { |
296 | { | ||
297 | *p++ = hex[(serial[i] >> 4) & 0xF]; | 279 | *p++ = hex[(serial[i] >> 4) & 0xF]; |
298 | *p++ = hex[(serial[i] >> 0) & 0xF]; | 280 | *p++ = hex[(serial[i] >> 0) & 0xF]; |
299 | } | 281 | } |
@@ -309,8 +291,7 @@ static void set_serial_descriptor(void) | |||
309 | unsigned short x; | 291 | unsigned short x; |
310 | int i; | 292 | int i; |
311 | 293 | ||
312 | for (i = 10; i < 20; i++) | 294 | for (i = 10; i < 20; i++) { |
313 | { | ||
314 | x = identify[i]; | 295 | x = identify[i]; |
315 | *p++ = hex[(x >> 12) & 0xF]; | 296 | *p++ = hex[(x >> 12) & 0xF]; |
316 | *p++ = hex[(x >> 8) & 0xF]; | 297 | *p++ = hex[(x >> 8) & 0xF]; |
@@ -323,6 +304,7 @@ static void set_serial_descriptor(void) | |||
323 | 304 | ||
324 | void usb_core_init(void) | 305 | void usb_core_init(void) |
325 | { | 306 | { |
307 | int i; | ||
326 | if (initialized) | 308 | if (initialized) |
327 | return; | 309 | return; |
328 | 310 | ||
@@ -333,27 +315,34 @@ void usb_core_init(void) | |||
333 | /* class driver init functions should be safe to call even if the driver | 315 | /* class driver init functions should be safe to call even if the driver |
334 | * won't be used. This simplifies other logic (i.e. we don't need to know | 316 | * won't be used. This simplifies other logic (i.e. we don't need to know |
335 | * yet which drivers will be enabled */ | 317 | * yet which drivers will be enabled */ |
336 | #ifdef USB_STORAGE | 318 | for(i=0;i<USB_NUM_DRIVERS;i++) { |
337 | if(usb_core_storage_enabled) | 319 | if(drivers[i].enabled && drivers[i].init != NULL) |
338 | usb_storage_init(); | 320 | drivers[i].init(); |
339 | #endif | 321 | } |
340 | |||
341 | #ifdef USB_SERIAL | ||
342 | if(usb_core_serial_enabled) | ||
343 | usb_serial_init(); | ||
344 | #endif | ||
345 | 322 | ||
346 | initialized = true; | 323 | initialized = true; |
347 | usb_state = DEFAULT; | 324 | usb_state = DEFAULT; |
348 | logf("usb_core_init() finished"); | 325 | logf("usb_core_init() finished"); |
349 | } | 326 | } |
350 | 327 | ||
328 | int usb_charging_get_config_descriptor(unsigned char *dest,int max_packet_size, | ||
329 | int interface_number,int endpoint) | ||
330 | { | ||
331 | (void) max_packet_size; | ||
332 | (void) endpoint; | ||
333 | charging_interface_descriptor.bInterfaceNumber=interface_number; | ||
334 | memcpy(dest,&charging_interface_descriptor, | ||
335 | sizeof(struct usb_interface_descriptor)); | ||
336 | return sizeof(struct usb_interface_descriptor); | ||
337 | } | ||
338 | |||
351 | void usb_core_exit(void) | 339 | void usb_core_exit(void) |
352 | { | 340 | { |
353 | #ifdef USB_SERIAL | 341 | int i; |
354 | if(usb_core_serial_enabled) | 342 | for(i=0;i<USB_NUM_DRIVERS;i++) { |
355 | usb_serial_exit(); | 343 | if(drivers[i].enabled && drivers[i].disconnect != NULL) |
356 | #endif | 344 | drivers[i].disconnect (); |
345 | } | ||
357 | 346 | ||
358 | if (initialized) { | 347 | if (initialized) { |
359 | usb_drv_exit(); | 348 | usb_drv_exit(); |
@@ -362,321 +351,332 @@ void usb_core_exit(void) | |||
362 | logf("usb_core_exit() finished"); | 351 | logf("usb_core_exit() finished"); |
363 | } | 352 | } |
364 | 353 | ||
365 | void usb_core_handle_transfer_completion(struct usb_transfer_completion_event_data* event) | 354 | void usb_core_handle_transfer_completion( |
355 | struct usb_transfer_completion_event_data* event) | ||
366 | { | 356 | { |
357 | int i; | ||
367 | switch(event->endpoint) { | 358 | switch(event->endpoint) { |
368 | case EP_CONTROL: | 359 | case EP_CONTROL: |
369 | logf("ctrl handled %ld",current_tick); | 360 | logf("ctrl handled %ld",current_tick); |
370 | usb_core_control_request_handler((struct usb_ctrlrequest*)event->data); | 361 | usb_core_control_request_handler( |
371 | break; | 362 | (struct usb_ctrlrequest*)event->data); |
372 | #ifdef USB_STORAGE | ||
373 | case EP_MASS_STORAGE: | ||
374 | usb_storage_transfer_complete(event->in,event->status,event->length); | ||
375 | break; | 363 | break; |
376 | #endif | 364 | default: |
377 | #ifdef USB_SERIAL | 365 | for(i=0;i<USB_NUM_DRIVERS;i++) { |
378 | case EP_SERIAL: | 366 | if(drivers[i].enabled && |
379 | usb_serial_transfer_complete(event->in,event->status,event->length); | 367 | drivers[i].usb_endpoint == event->endpoint && |
380 | break; | 368 | drivers[i].transfer_complete != NULL) |
381 | #endif | 369 | { |
382 | #ifdef USB_CHARGING_ONLY | 370 | drivers[i].transfer_complete(event->in, |
383 | case EP_CHARGING_ONLY: | 371 | event->status,event->length); |
372 | break; | ||
373 | } | ||
374 | } | ||
384 | break; | 375 | break; |
385 | #endif | ||
386 | } | 376 | } |
387 | } | 377 | } |
388 | 378 | ||
389 | void usb_core_enable_protocol(int driver,bool enabled) | 379 | void usb_core_enable_driver(int driver,bool enabled) |
390 | { | 380 | { |
391 | switch(driver) { | 381 | drivers[driver].enabled = enabled; |
392 | #ifdef USB_STORAGE | 382 | } |
393 | case USB_DRIVER_MASS_STORAGE: | 383 | |
394 | usb_core_storage_enabled = enabled; | 384 | bool usb_core_driver_enabled(int driver) |
395 | break; | 385 | { |
396 | #endif | 386 | return drivers[driver].enabled; |
397 | #ifdef USB_SERIAL | 387 | } |
398 | case USB_DRIVER_SERIAL: | 388 | |
399 | usb_core_serial_enabled = enabled; | 389 | static void usb_core_set_serial_function_id(void) |
400 | break; | 390 | { |
401 | #endif | 391 | int id = 0; |
402 | #ifdef USB_CHARGING_ONLY | 392 | int i; |
403 | case USB_DRIVER_CHARGING_ONLY: | 393 | for(i=0;i<USB_NUM_DRIVERS;i++) { |
404 | usb_core_charging_enabled = enabled; | 394 | if(drivers[i].enabled) |
405 | break; | 395 | id |= 1<<i; |
406 | #endif | ||
407 | } | 396 | } |
397 | usb_string_iSerial.wString[0] = hex[id]; | ||
408 | } | 398 | } |
409 | 399 | ||
410 | static void usb_core_control_request_handler(struct usb_ctrlrequest* req) | 400 | static void allocate_interfaces_and_endpoints(void) |
411 | { | 401 | { |
412 | if(usb_state == DEFAULT) { | 402 | int i; |
413 | set_serial_descriptor(); | 403 | int interface=0; |
414 | 404 | int endpoint=1; | |
415 | int serial_function_id = 0; | 405 | for(i=0;i<USB_NUM_DRIVERS;i++) { |
416 | #ifdef USB_STORAGE | 406 | if(drivers[i].enabled) { |
417 | if(usb_core_storage_enabled) { | 407 | drivers[i].usb_endpoint = endpoint++; |
418 | usb_request_exclusive_ata(); | 408 | drivers[i].usb_interface = interface++; |
419 | serial_function_id |= 1; | 409 | } |
410 | if(endpoint>NUM_ENDPOINTS) { | ||
411 | drivers[i].enabled = false; | ||
420 | } | 412 | } |
421 | #endif | ||
422 | #ifdef USB_SERIAL | ||
423 | if(usb_core_serial_enabled) | ||
424 | serial_function_id |= 2; | ||
425 | #endif | ||
426 | usb_string_iSerial.wString[0] = hex[serial_function_id]; | ||
427 | } | 413 | } |
414 | usb_core_num_interfaces = interface; | ||
415 | } | ||
428 | 416 | ||
429 | switch (req->bRequest) { | 417 | static void usb_core_control_request_handler(struct usb_ctrlrequest* req) |
430 | case USB_REQ_SET_CONFIGURATION: | 418 | { |
431 | logf("usb_core: SET_CONFIG"); | 419 | int i; |
432 | usb_drv_cancel_all_transfers(); | 420 | if(usb_state == DEFAULT) { |
433 | if (req->wValue){ | 421 | set_serial_descriptor(); |
434 | usb_state = CONFIGURED; | 422 | usb_core_set_serial_function_id(); |
435 | #ifdef USB_STORAGE | ||
436 | if(usb_core_storage_enabled) | ||
437 | usb_storage_control_request(req); | ||
438 | #endif | ||
439 | 423 | ||
440 | #ifdef USB_SERIAL | 424 | allocate_interfaces_and_endpoints(); |
441 | if(usb_core_serial_enabled) | ||
442 | usb_serial_control_request(req); | ||
443 | #endif | ||
444 | } | ||
445 | else { | ||
446 | usb_state = ADDRESS; | ||
447 | } | ||
448 | ack_control(req); | ||
449 | break; | ||
450 | 425 | ||
451 | case USB_REQ_GET_CONFIGURATION: { | 426 | for(i=0;i<USB_NUM_DRIVERS;i++) { |
452 | logf("usb_core: GET_CONFIG"); | 427 | if(drivers[i].enabled && |
453 | if (usb_state == ADDRESS) | 428 | drivers[i].needs_exclusive_ata) { |
454 | response_data[0] = 0; | 429 | usb_request_exclusive_ata(); |
455 | else | ||
456 | response_data[0] = 1; | ||
457 | if(usb_drv_send(EP_CONTROL, response_data, 1)!= 0) | ||
458 | break; | 430 | break; |
459 | ack_control(req); | 431 | } |
460 | break; | ||
461 | } | 432 | } |
433 | } | ||
462 | 434 | ||
463 | case USB_REQ_SET_INTERFACE: | 435 | switch(req->bRequestType & 0x1f) { |
464 | logf("usb_core: SET_INTERFACE"); | 436 | case 0: /* Device */ |
465 | ack_control(req); | 437 | switch (req->bRequest) { |
466 | break; | 438 | case USB_REQ_GET_CONFIGURATION: { |
439 | logf("usb_core: GET_CONFIG"); | ||
440 | if (usb_state == ADDRESS) | ||
441 | response_data[0] = 0; | ||
442 | else | ||
443 | response_data[0] = 1; | ||
444 | if(usb_drv_send(EP_CONTROL, response_data, 1)!= 0) | ||
445 | break; | ||
446 | ack_control(req); | ||
447 | break; | ||
448 | case USB_REQ_SET_CONFIGURATION: | ||
449 | logf("usb_core: SET_CONFIG"); | ||
450 | usb_drv_cancel_all_transfers(); | ||
451 | if (req->wValue) { | ||
452 | usb_state = CONFIGURED; | ||
453 | for(i=0;i<USB_NUM_DRIVERS;i++) { | ||
454 | if(drivers[i].enabled && | ||
455 | drivers[i].init_connection!=NULL) | ||
456 | { | ||
457 | drivers[i].init_connection( | ||
458 | drivers[i].usb_interface, | ||
459 | drivers[i].usb_endpoint); | ||
460 | } | ||
461 | } | ||
462 | } | ||
463 | else { | ||
464 | usb_state = ADDRESS; | ||
465 | } | ||
466 | ack_control(req); | ||
467 | break; | ||
468 | } | ||
469 | case USB_REQ_SET_ADDRESS: { | ||
470 | unsigned char address = req->wValue; | ||
471 | logf("usb_core: SET_ADR %d", address); | ||
472 | if(ack_control(req)!=0) | ||
473 | break; | ||
474 | usb_drv_cancel_all_transfers(); | ||
475 | usb_address = address; | ||
476 | usb_drv_set_address(usb_address); | ||
477 | usb_state = ADDRESS; | ||
478 | break; | ||
479 | } | ||
480 | case USB_REQ_GET_DESCRIPTOR: { | ||
481 | int index = req->wValue & 0xff; | ||
482 | int length = req->wLength; | ||
483 | int size; | ||
484 | const void* ptr = NULL; | ||
485 | logf("usb_core: GET_DESC %d", req->wValue >> 8); | ||
486 | |||
487 | switch (req->wValue >> 8) { /* type */ | ||
488 | case USB_DT_DEVICE: | ||
489 | ptr = &device_descriptor; | ||
490 | size = sizeof(struct usb_device_descriptor); | ||
491 | break; | ||
492 | |||
493 | case USB_DT_OTHER_SPEED_CONFIG: | ||
494 | case USB_DT_CONFIG: { | ||
495 | int max_packet_size; | ||
496 | |||
497 | if(req->wValue >> 8 == USB_DT_CONFIG) { | ||
498 | if(usb_drv_port_speed()) | ||
499 | max_packet_size=512; | ||
500 | else | ||
501 | max_packet_size=64; | ||
502 | config_descriptor.bDescriptorType=USB_DT_CONFIG; | ||
503 | } | ||
504 | else { | ||
505 | if(usb_drv_port_speed()) | ||
506 | max_packet_size=64; | ||
507 | else | ||
508 | max_packet_size=512; | ||
509 | config_descriptor.bDescriptorType = | ||
510 | USB_DT_OTHER_SPEED_CONFIG; | ||
511 | } | ||
512 | size = sizeof(struct usb_config_descriptor); | ||
513 | |||
514 | for(i=0;i<USB_NUM_DRIVERS;i++) { | ||
515 | if(drivers[i].enabled && | ||
516 | drivers[i].get_config_descriptor) | ||
517 | { | ||
518 | size+=drivers[i].get_config_descriptor( | ||
519 | &response_data[size], | ||
520 | max_packet_size, | ||
521 | drivers[i].usb_interface, | ||
522 | drivers[i].usb_endpoint); | ||
523 | } | ||
524 | } | ||
525 | config_descriptor.bNumInterfaces = | ||
526 | usb_core_num_interfaces; | ||
527 | config_descriptor.wTotalLength = size; | ||
528 | memcpy(&response_data[0],&config_descriptor, | ||
529 | sizeof(struct usb_config_descriptor)); | ||
530 | |||
531 | ptr = response_data; | ||
532 | break; | ||
533 | } | ||
467 | 534 | ||
468 | case USB_REQ_GET_INTERFACE: | 535 | case USB_DT_STRING: |
469 | logf("usb_core: GET_INTERFACE"); | 536 | logf("STRING %d",index); |
470 | response_data[0] = 0; | 537 | if ((unsigned)index < (sizeof(usb_strings)/ |
471 | if(usb_drv_send(EP_CONTROL, response_data, 1)!=0) | 538 | sizeof(struct usb_string_descriptor*))) |
472 | break; | 539 | { |
473 | ack_control(req); | 540 | size = usb_strings[index]->bLength; |
474 | break; | 541 | memcpy(&response_data[0],usb_strings[index], |
475 | case USB_REQ_CLEAR_FEATURE: | 542 | size); |
476 | logf("usb_core: CLEAR_FEATURE"); | 543 | ptr = response_data; |
477 | if (req->wValue) | 544 | } |
478 | usb_drv_stall(req->wIndex & 0xf, false,(req->wIndex & 0x80) !=0); | 545 | else { |
479 | else | 546 | logf("bad string id %d", index); |
480 | usb_drv_stall(req->wIndex & 0xf, false,(req->wIndex & 0x80) !=0); | 547 | usb_drv_stall(EP_CONTROL, true,true); |
481 | ack_control(req); | 548 | } |
482 | break; | 549 | break; |
550 | |||
551 | case USB_DT_DEVICE_QUALIFIER: | ||
552 | ptr = &qualifier_descriptor; | ||
553 | size = sizeof (struct usb_qualifier_descriptor); | ||
554 | break; | ||
555 | |||
556 | default: | ||
557 | logf("bad desc %d", req->wValue >> 8); | ||
558 | usb_drv_stall(EP_CONTROL, true,true); | ||
559 | break; | ||
560 | } | ||
483 | 561 | ||
484 | case USB_REQ_SET_FEATURE: | 562 | if (ptr) { |
485 | logf("usb_core: SET_FEATURE"); | 563 | unsigned char *uncached = (void*)UNCACHED_ADDR(ptr); |
486 | switch(req->bRequestType & 0x0f){ | 564 | length = MIN(size, length); |
487 | case 0: /* Device */ | 565 | if(usb_drv_send(EP_CONTROL, uncached, length)!=0) |
566 | break; | ||
567 | } | ||
568 | ack_control(req); | ||
569 | break; | ||
570 | } /* USB_REQ_GET_DESCRIPTOR */ | ||
571 | case USB_REQ_CLEAR_FEATURE: | ||
572 | break; | ||
573 | case USB_REQ_SET_FEATURE: | ||
488 | if(req->wValue == 2) { /* TEST_MODE */ | 574 | if(req->wValue == 2) { /* TEST_MODE */ |
489 | int mode=req->wIndex>>8; | 575 | int mode=req->wIndex>>8; |
490 | ack_control(req); | 576 | ack_control(req); |
491 | usb_drv_set_test_mode(mode); | 577 | usb_drv_set_test_mode(mode); |
492 | } | 578 | } |
493 | break; | 579 | break; |
494 | case 2: /* Endpoint */ | 580 | case USB_REQ_GET_STATUS: |
495 | if (req->wValue) | 581 | response_data[0]= 0; |
496 | usb_drv_stall(req->wIndex & 0xf, true,(req->wIndex & 0x80) !=0); | 582 | response_data[1]= 0; |
497 | else | 583 | if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) |
498 | usb_drv_stall(req->wIndex & 0xf, false,(req->wIndex & 0x80) !=0); | 584 | break; |
499 | ack_control(req); | 585 | ack_control(req); |
500 | break; | 586 | break; |
501 | default: | 587 | default: |
502 | break; | 588 | break; |
503 | } | 589 | } |
504 | break; | 590 | break; |
505 | 591 | case 1: /* Interface */ | |
506 | case USB_REQ_SET_ADDRESS: { | 592 | switch (req->bRequest) { |
507 | unsigned char address = req->wValue; | 593 | case USB_REQ_SET_INTERFACE: |
508 | logf("usb_core: SET_ADR %d", address); | 594 | logf("usb_core: SET_INTERFACE"); |
509 | if(ack_control(req)!=0) | 595 | ack_control(req); |
510 | break; | ||
511 | usb_drv_cancel_all_transfers(); | ||
512 | usb_address = address; | ||
513 | usb_drv_set_address(usb_address); | ||
514 | usb_state = ADDRESS; | ||
515 | break; | ||
516 | } | ||
517 | |||
518 | case USB_REQ_GET_STATUS: { | ||
519 | response_data[0]= 0; | ||
520 | response_data[1]= 0; | ||
521 | logf("usb_core: GET_STATUS"); | ||
522 | if(req->wIndex>0) { | ||
523 | if(usb_drv_stalled(req->wIndex&0xf,(req->wIndex&0x80)!=0)) | ||
524 | response_data[0] = 1; | ||
525 | } | ||
526 | logf("usb_core: %X %X",response_data[0],response_data[1]); | ||
527 | if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) | ||
528 | break; | ||
529 | ack_control(req); | ||
530 | break; | ||
531 | } | ||
532 | |||
533 | case USB_REQ_GET_DESCRIPTOR: { | ||
534 | int index = req->wValue & 0xff; | ||
535 | int length = req->wLength; | ||
536 | int size; | ||
537 | const void* ptr = NULL; | ||
538 | logf("usb_core: GET_DESC %d", req->wValue >> 8); | ||
539 | |||
540 | switch (req->wValue >> 8) { /* type */ | ||
541 | case USB_DT_DEVICE: | ||
542 | ptr = &device_descriptor; | ||
543 | size = sizeof(struct usb_device_descriptor); | ||
544 | break; | 596 | break; |
545 | 597 | ||
546 | case USB_DT_OTHER_SPEED_CONFIG: | 598 | case USB_REQ_GET_INTERFACE: |
547 | case USB_DT_CONFIG: { | 599 | logf("usb_core: GET_INTERFACE"); |
548 | int max_packet_size; | 600 | response_data[0] = 0; |
549 | int interface_number=0; | 601 | if(usb_drv_send(EP_CONTROL, response_data, 1)!=0) |
550 | 602 | break; | |
551 | if(req->wValue >> 8 == USB_DT_CONFIG) { | 603 | ack_control(req); |
552 | if(usb_drv_port_speed()) { | ||
553 | max_packet_size=512; | ||
554 | } | ||
555 | else { | ||
556 | max_packet_size=64; | ||
557 | } | ||
558 | config_descriptor.bDescriptorType=USB_DT_CONFIG; | ||
559 | } | ||
560 | else { | ||
561 | if(usb_drv_port_speed()) { | ||
562 | max_packet_size=64; | ||
563 | } | ||
564 | else { | ||
565 | max_packet_size=512; | ||
566 | } | ||
567 | config_descriptor.bDescriptorType=USB_DT_OTHER_SPEED_CONFIG; | ||
568 | } | ||
569 | size = sizeof(struct usb_config_descriptor); | ||
570 | |||
571 | #ifdef USB_STORAGE | ||
572 | if(usb_core_storage_enabled){ | ||
573 | mass_storage_ep_in_descriptor.wMaxPacketSize=max_packet_size; | ||
574 | mass_storage_ep_out_descriptor.wMaxPacketSize=max_packet_size; | ||
575 | mass_storage_interface_descriptor.bInterfaceNumber=interface_number; | ||
576 | interface_number++; | ||
577 | |||
578 | memcpy(&response_data[size],&mass_storage_interface_descriptor,sizeof(struct usb_interface_descriptor)); | ||
579 | size += sizeof(struct usb_interface_descriptor); | ||
580 | memcpy(&response_data[size],&mass_storage_ep_in_descriptor,sizeof(struct usb_endpoint_descriptor)); | ||
581 | size += sizeof(struct usb_endpoint_descriptor); | ||
582 | memcpy(&response_data[size],&mass_storage_ep_out_descriptor,sizeof(struct usb_endpoint_descriptor)); | ||
583 | size += sizeof(struct usb_endpoint_descriptor); | ||
584 | } | ||
585 | #endif | ||
586 | #ifdef USB_SERIAL | ||
587 | if(usb_core_serial_enabled){ | ||
588 | serial_ep_in_descriptor.wMaxPacketSize=max_packet_size; | ||
589 | serial_ep_out_descriptor.wMaxPacketSize=max_packet_size; | ||
590 | serial_interface_descriptor.bInterfaceNumber=interface_number; | ||
591 | interface_number++; | ||
592 | |||
593 | memcpy(&response_data[size],&serial_interface_descriptor,sizeof(struct usb_interface_descriptor)); | ||
594 | size += sizeof(struct usb_interface_descriptor); | ||
595 | memcpy(&response_data[size],&serial_ep_in_descriptor,sizeof(struct usb_endpoint_descriptor)); | ||
596 | size += sizeof(struct usb_endpoint_descriptor); | ||
597 | memcpy(&response_data[size],&serial_ep_out_descriptor,sizeof(struct usb_endpoint_descriptor)); | ||
598 | size += sizeof(struct usb_endpoint_descriptor); | ||
599 | } | ||
600 | #endif | ||
601 | #ifdef USB_CHARGING_ONLY | ||
602 | if(usb_core_charging_enabled && interface_number == 0){ | ||
603 | charging_interface_descriptor.bInterfaceNumber=interface_number; | ||
604 | interface_number++; | ||
605 | memcpy(&response_data[size],&charging_interface_descriptor,sizeof(struct usb_interface_descriptor)); | ||
606 | size += sizeof(struct usb_interface_descriptor); | ||
607 | } | ||
608 | #endif | ||
609 | config_descriptor.bNumInterfaces=interface_number; | ||
610 | config_descriptor.wTotalLength = size; | ||
611 | memcpy(&response_data[0],&config_descriptor,sizeof(struct usb_config_descriptor)); | ||
612 | |||
613 | ptr = response_data; | ||
614 | break; | 604 | break; |
605 | case USB_REQ_CLEAR_FEATURE: | ||
606 | break; | ||
607 | case USB_REQ_SET_FEATURE: | ||
608 | break; | ||
609 | case USB_REQ_GET_STATUS: | ||
610 | response_data[0]= 0; | ||
611 | response_data[1]= 0; | ||
612 | if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) | ||
613 | break; | ||
614 | ack_control(req); | ||
615 | break; | ||
616 | default: { | ||
617 | bool handled=false; | ||
618 | for(i=0;i<USB_NUM_DRIVERS;i++) { | ||
619 | if(drivers[i].enabled && | ||
620 | drivers[i].control_request && | ||
621 | drivers[i].usb_interface == (req->wIndex)) | ||
622 | { | ||
623 | handled = drivers[i].control_request(req); | ||
624 | } | ||
615 | } | 625 | } |
616 | 626 | if(!handled) { | |
617 | case USB_DT_STRING: | 627 | /* nope. flag error */ |
618 | logf("STRING %d",index); | 628 | logf("usb bad req %d", req->bRequest); |
619 | if ((unsigned)index < (sizeof(usb_strings)/sizeof(struct usb_string_descriptor*))) { | ||
620 | size = usb_strings[index]->bLength; | ||
621 | memcpy(&response_data[0],usb_strings[index],size); | ||
622 | ptr = response_data; | ||
623 | } | ||
624 | else { | ||
625 | logf("bad string id %d", index); | ||
626 | usb_drv_stall(EP_CONTROL, true,true); | 629 | usb_drv_stall(EP_CONTROL, true,true); |
630 | ack_control(req); | ||
627 | } | 631 | } |
628 | break; | 632 | break; |
629 | 633 | } | |
630 | case USB_DT_DEVICE_QUALIFIER: | 634 | } |
631 | ptr = &qualifier_descriptor; | 635 | break; |
632 | size = sizeof (struct usb_qualifier_descriptor); | 636 | case 2: /* Endpoint */ |
637 | switch (req->bRequest) { | ||
638 | case USB_REQ_CLEAR_FEATURE: | ||
639 | if (req->wValue == 0 ) /* ENDPOINT_HALT */ | ||
640 | usb_drv_stall(req->wIndex & 0xf, false, | ||
641 | (req->wIndex & 0x80) !=0); | ||
642 | ack_control(req); | ||
633 | break; | 643 | break; |
634 | 644 | case USB_REQ_SET_FEATURE: | |
635 | default: | 645 | if (req->wValue == 0 ) /* ENDPOINT_HALT */ |
636 | logf("bad desc %d", req->wValue >> 8); | 646 | usb_drv_stall(req->wIndex & 0xf, true, |
637 | usb_drv_stall(EP_CONTROL, true,true); | 647 | (req->wIndex & 0x80) !=0); |
648 | ack_control(req); | ||
638 | break; | 649 | break; |
639 | } | 650 | case USB_REQ_GET_STATUS: |
640 | 651 | response_data[0]= 0; | |
641 | if (ptr) { | 652 | response_data[1]= 0; |
642 | length = MIN(size, length); | 653 | logf("usb_core: GET_STATUS"); |
643 | if(usb_drv_send(EP_CONTROL, (void*)UNCACHED_ADDR(ptr), length)!=0) | 654 | if(req->wIndex>0) |
655 | response_data[0] = usb_drv_stalled(req->wIndex&0xf, | ||
656 | (req->wIndex&0x80)!=0); | ||
657 | if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) | ||
658 | break; | ||
659 | ack_control(req); | ||
660 | break; | ||
661 | default: { | ||
662 | bool handled=false; | ||
663 | for(i=0;i<USB_NUM_DRIVERS;i++) { | ||
664 | if(drivers[i].enabled && | ||
665 | drivers[i].control_request && | ||
666 | drivers[i].usb_endpoint == (req->wIndex & 0xf)) | ||
667 | { | ||
668 | handled = drivers[i].control_request(req); | ||
669 | } | ||
670 | } | ||
671 | if(!handled) { | ||
672 | /* nope. flag error */ | ||
673 | logf("usb bad req %d", req->bRequest); | ||
674 | usb_drv_stall(EP_CONTROL, true,true); | ||
675 | ack_control(req); | ||
676 | } | ||
644 | break; | 677 | break; |
645 | } | ||
646 | ack_control(req); | ||
647 | break; | ||
648 | } /* USB_REQ_GET_DESCRIPTOR */ | ||
649 | |||
650 | default: { | ||
651 | bool handled=false; | ||
652 | if((req->bRequestType & 0x1f) == 1) /* Interface */ | ||
653 | { | ||
654 | #ifdef USB_STORAGE | ||
655 | /* does usb_storage know this request? */ | ||
656 | if(req->wIndex == mass_storage_interface_descriptor.bInterfaceNumber) | ||
657 | { | ||
658 | handled = usb_storage_control_request(req); | ||
659 | } | ||
660 | #endif | ||
661 | |||
662 | #ifdef USB_SERIAL | ||
663 | /* does usb_serial know this request? */ | ||
664 | if(req->wIndex == serial_interface_descriptor.bInterfaceNumber) | ||
665 | { | ||
666 | handled = usb_serial_control_request(req); | ||
667 | } | 678 | } |
668 | |||
669 | #endif | ||
670 | } | ||
671 | if(!handled) | ||
672 | { | ||
673 | /* nope. flag error */ | ||
674 | logf("usb bad req %d", req->bRequest); | ||
675 | usb_drv_stall(EP_CONTROL, true,true); | ||
676 | ack_control(req); | ||
677 | } | 679 | } |
678 | break; | ||
679 | } | ||
680 | } | 680 | } |
681 | logf("control handled"); | 681 | logf("control handled"); |
682 | } | 682 | } |
@@ -691,10 +691,6 @@ void usb_core_bus_reset(void) | |||
691 | /* called by usb_drv_transfer_completed() */ | 691 | /* called by usb_drv_transfer_completed() */ |
692 | void usb_core_transfer_complete(int endpoint, bool in, int status,int length) | 692 | void usb_core_transfer_complete(int endpoint, bool in, int status,int length) |
693 | { | 693 | { |
694 | #if defined(USB_CHARGING_ONLY) || defined(USB_STORAGE) | ||
695 | (void)in; | ||
696 | #endif | ||
697 | |||
698 | switch (endpoint) { | 694 | switch (endpoint) { |
699 | case EP_CONTROL: | 695 | case EP_CONTROL: |
700 | /* already handled */ | 696 | /* already handled */ |
diff --git a/firmware/usbstack/usb_serial.c b/firmware/usbstack/usb_serial.c index 8c86932a31..55b76adc69 100644 --- a/firmware/usbstack/usb_serial.c +++ b/firmware/usbstack/usb_serial.c | |||
@@ -27,6 +27,31 @@ | |||
27 | 27 | ||
28 | #ifdef USB_SERIAL | 28 | #ifdef USB_SERIAL |
29 | 29 | ||
30 | /* serial interface */ | ||
31 | struct usb_interface_descriptor __attribute__((aligned(2))) | ||
32 | interface_descriptor = | ||
33 | { | ||
34 | .bLength = sizeof(struct usb_interface_descriptor), | ||
35 | .bDescriptorType = USB_DT_INTERFACE, | ||
36 | .bInterfaceNumber = 0, | ||
37 | .bAlternateSetting = 0, | ||
38 | .bNumEndpoints = 2, | ||
39 | .bInterfaceClass = USB_CLASS_CDC_DATA, | ||
40 | .bInterfaceSubClass = 0, | ||
41 | .bInterfaceProtocol = 0, | ||
42 | .iInterface = 0 | ||
43 | }; | ||
44 | |||
45 | struct usb_endpoint_descriptor __attribute__((aligned(2))) endpoint_descriptor = | ||
46 | { | ||
47 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
48 | .bDescriptorType = USB_DT_ENDPOINT, | ||
49 | .bEndpointAddress = 0, | ||
50 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
51 | .wMaxPacketSize = 0, | ||
52 | .bInterval = 0 | ||
53 | }; | ||
54 | |||
30 | #define BUFFER_SIZE 512 /* Max 16k because of controller limitations */ | 55 | #define BUFFER_SIZE 512 /* Max 16k because of controller limitations */ |
31 | static unsigned char _send_buffer[BUFFER_SIZE] __attribute__((aligned(32))); | 56 | static unsigned char _send_buffer[BUFFER_SIZE] __attribute__((aligned(32))); |
32 | static unsigned char* send_buffer; | 57 | static unsigned char* send_buffer; |
@@ -38,8 +63,66 @@ static int buffer_start; | |||
38 | static int buffer_length; | 63 | static int buffer_length; |
39 | static bool active = false; | 64 | static bool active = false; |
40 | 65 | ||
66 | static int usb_endpoint; | ||
67 | static int usb_interface; | ||
68 | |||
41 | static struct mutex sendlock; | 69 | static struct mutex sendlock; |
42 | 70 | ||
71 | static void sendout(void) | ||
72 | { | ||
73 | if(buffer_start+buffer_length > BUFFER_SIZE) | ||
74 | { | ||
75 | /* Buffer wraps. Only send the first part */ | ||
76 | usb_drv_send_nonblocking(usb_endpoint, &send_buffer[buffer_start], | ||
77 | (BUFFER_SIZE - buffer_start)); | ||
78 | } | ||
79 | else | ||
80 | { | ||
81 | /* Send everything */ | ||
82 | usb_drv_send_nonblocking(usb_endpoint, &send_buffer[buffer_start], | ||
83 | buffer_length); | ||
84 | } | ||
85 | busy_sending=true; | ||
86 | } | ||
87 | |||
88 | int usb_serial_get_config_descriptor(unsigned char *dest,int max_packet_size, | ||
89 | int interface_number,int endpoint) | ||
90 | { | ||
91 | endpoint_descriptor.wMaxPacketSize=max_packet_size; | ||
92 | interface_descriptor.bInterfaceNumber=interface_number; | ||
93 | |||
94 | |||
95 | memcpy(dest,&interface_descriptor,sizeof(struct usb_interface_descriptor)); | ||
96 | dest+=sizeof(struct usb_interface_descriptor); | ||
97 | |||
98 | endpoint_descriptor.bEndpointAddress = endpoint | USB_DIR_IN, | ||
99 | memcpy(dest,&endpoint_descriptor,sizeof(struct usb_endpoint_descriptor)); | ||
100 | dest+=sizeof(struct usb_endpoint_descriptor); | ||
101 | |||
102 | endpoint_descriptor.bEndpointAddress = endpoint | USB_DIR_OUT, | ||
103 | memcpy(dest,&endpoint_descriptor,sizeof(struct usb_endpoint_descriptor)); | ||
104 | return sizeof(struct usb_interface_descriptor) + | ||
105 | 2 * sizeof(struct usb_endpoint_descriptor); | ||
106 | } | ||
107 | |||
108 | void usb_serial_init_connection(int interface,int endpoint) | ||
109 | { | ||
110 | usb_interface = interface; | ||
111 | usb_endpoint = endpoint; | ||
112 | |||
113 | /* prime rx endpoint */ | ||
114 | usb_drv_recv(usb_endpoint, receive_buffer, sizeof _receive_buffer); | ||
115 | |||
116 | /* we come here too after a bus reset, so reset some data */ | ||
117 | mutex_lock(&sendlock); | ||
118 | busy_sending = false; | ||
119 | if(buffer_length>0) | ||
120 | { | ||
121 | sendout(); | ||
122 | } | ||
123 | mutex_unlock(&sendlock); | ||
124 | } | ||
125 | |||
43 | /* called by usb_code_init() */ | 126 | /* called by usb_code_init() */ |
44 | void usb_serial_init(void) | 127 | void usb_serial_init(void) |
45 | { | 128 | { |
@@ -53,26 +136,11 @@ void usb_serial_init(void) | |||
53 | mutex_init(&sendlock); | 136 | mutex_init(&sendlock); |
54 | } | 137 | } |
55 | 138 | ||
56 | void usb_serial_exit(void) | 139 | void usb_serial_disconnect(void) |
57 | { | 140 | { |
58 | active = false; | 141 | active = false; |
59 | } | 142 | } |
60 | 143 | ||
61 | static void sendout(void) | ||
62 | { | ||
63 | if(buffer_start+buffer_length > BUFFER_SIZE) | ||
64 | { | ||
65 | /* Buffer wraps. Only send the first part */ | ||
66 | usb_drv_send_nonblocking(EP_SERIAL, &send_buffer[buffer_start],(BUFFER_SIZE - buffer_start)); | ||
67 | } | ||
68 | else | ||
69 | { | ||
70 | /* Send everything */ | ||
71 | usb_drv_send_nonblocking(EP_SERIAL, &send_buffer[buffer_start],buffer_length); | ||
72 | } | ||
73 | busy_sending=true; | ||
74 | } | ||
75 | |||
76 | void usb_serial_send(unsigned char *data,int length) | 144 | void usb_serial_send(unsigned char *data,int length) |
77 | { | 145 | { |
78 | if(!active) | 146 | if(!active) |
@@ -85,13 +153,14 @@ void usb_serial_send(unsigned char *data,int length) | |||
85 | /* current buffer wraps, so new data can't */ | 153 | /* current buffer wraps, so new data can't */ |
86 | int available_space = BUFFER_SIZE - buffer_length; | 154 | int available_space = BUFFER_SIZE - buffer_length; |
87 | length=MIN(length,available_space); | 155 | length=MIN(length,available_space); |
88 | memcpy(&send_buffer[(buffer_start+buffer_length)%BUFFER_SIZE],data,length); | 156 | memcpy(&send_buffer[(buffer_start+buffer_length)%BUFFER_SIZE], |
157 | data,length); | ||
89 | buffer_length+=length; | 158 | buffer_length+=length; |
90 | } | 159 | } |
91 | else | 160 | else |
92 | { | 161 | { |
93 | /* current buffer doesn't wrap, so new data might */ | 162 | /* current buffer doesn't wrap, so new data might */ |
94 | int available_end_space = (BUFFER_SIZE - (buffer_start + buffer_length)); | 163 | int available_end_space = (BUFFER_SIZE - (buffer_start+buffer_length)); |
95 | int first_chunk = MIN(length,available_end_space); | 164 | int first_chunk = MIN(length,available_end_space); |
96 | memcpy(&send_buffer[buffer_start + buffer_length],data,first_chunk); | 165 | memcpy(&send_buffer[buffer_start + buffer_length],data,first_chunk); |
97 | length-=first_chunk; | 166 | length-=first_chunk; |
@@ -121,7 +190,7 @@ void usb_serial_transfer_complete(bool in, int status, int length) | |||
121 | case false: | 190 | case false: |
122 | logf("serial: %s", receive_buffer); | 191 | logf("serial: %s", receive_buffer); |
123 | /* Data received. TODO : Do something with it ? */ | 192 | /* Data received. TODO : Do something with it ? */ |
124 | usb_drv_recv(EP_SERIAL, receive_buffer, sizeof _receive_buffer); | 193 | usb_drv_recv(usb_endpoint, receive_buffer, sizeof _receive_buffer); |
125 | break; | 194 | break; |
126 | 195 | ||
127 | case true: | 196 | case true: |
@@ -148,26 +217,9 @@ bool usb_serial_control_request(struct usb_ctrlrequest* req) | |||
148 | { | 217 | { |
149 | bool handled = false; | 218 | bool handled = false; |
150 | switch (req->bRequest) { | 219 | switch (req->bRequest) { |
151 | case USB_REQ_SET_CONFIGURATION: | ||
152 | logf("serial: set config"); | ||
153 | /* prime rx endpoint */ | ||
154 | usb_drv_recv(EP_SERIAL, receive_buffer, sizeof _receive_buffer); | ||
155 | handled = true; | ||
156 | |||
157 | /* we come here too after a bus reset, so reset some data */ | ||
158 | mutex_lock(&sendlock); | ||
159 | busy_sending = false; | ||
160 | if(buffer_length>0) | ||
161 | { | ||
162 | sendout(); | ||
163 | } | ||
164 | mutex_unlock(&sendlock); | ||
165 | break; | ||
166 | |||
167 | default: | 220 | default: |
168 | logf("serial: unhandeld req %d", req->bRequest); | 221 | logf("serial: unhandeld req %d", req->bRequest); |
169 | } | 222 | } |
170 | |||
171 | return handled; | 223 | return handled; |
172 | } | 224 | } |
173 | 225 | ||
diff --git a/firmware/usbstack/usb_serial.h b/firmware/usbstack/usb_serial.h index bcb0648af5..5d624137c3 100644 --- a/firmware/usbstack/usb_serial.h +++ b/firmware/usbstack/usb_serial.h | |||
@@ -21,8 +21,11 @@ | |||
21 | 21 | ||
22 | #include "usb_ch9.h" | 22 | #include "usb_ch9.h" |
23 | 23 | ||
24 | int usb_serial_get_config_descriptor(unsigned char *dest,int max_packet_size, | ||
25 | int interface_number, int endpoint); | ||
26 | void usb_serial_init_connection(int interface,int endpoint); | ||
24 | void usb_serial_init(void); | 27 | void usb_serial_init(void); |
25 | void usb_serial_exit(void); | 28 | void usb_serial_disconnect(void); |
26 | void usb_serial_transfer_complete(bool in, int status, int length); | 29 | void usb_serial_transfer_complete(bool in, int status, int length); |
27 | bool usb_serial_control_request(struct usb_ctrlrequest* req); | 30 | bool usb_serial_control_request(struct usb_ctrlrequest* req); |
28 | 31 | ||
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c index f1029c3c93..58578d958b 100644 --- a/firmware/usbstack/usb_storage.c +++ b/firmware/usbstack/usb_storage.c | |||
@@ -28,6 +28,7 @@ | |||
28 | /* Needed to get at the audio buffer */ | 28 | /* Needed to get at the audio buffer */ |
29 | #include "audio.h" | 29 | #include "audio.h" |
30 | 30 | ||
31 | |||
31 | #ifdef USB_STORAGE | 32 | #ifdef USB_STORAGE |
32 | 33 | ||
33 | /* Enable the following define to export only the SD card slot. This | 34 | /* Enable the following define to export only the SD card slot. This |
@@ -85,6 +86,35 @@ | |||
85 | 86 | ||
86 | #define SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA 0x02000000 | 87 | #define SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA 0x02000000 |
87 | 88 | ||
89 | /* storage interface */ | ||
90 | |||
91 | #define USB_SC_SCSI 0x06 /* Transparent */ | ||
92 | #define USB_PROT_BULK 0x50 /* bulk only */ | ||
93 | |||
94 | static struct usb_interface_descriptor __attribute__((aligned(2))) | ||
95 | interface_descriptor = | ||
96 | { | ||
97 | .bLength = sizeof(struct usb_interface_descriptor), | ||
98 | .bDescriptorType = USB_DT_INTERFACE, | ||
99 | .bInterfaceNumber = 0, | ||
100 | .bAlternateSetting = 0, | ||
101 | .bNumEndpoints = 2, | ||
102 | .bInterfaceClass = USB_CLASS_MASS_STORAGE, | ||
103 | .bInterfaceSubClass = USB_SC_SCSI, | ||
104 | .bInterfaceProtocol = USB_PROT_BULK, | ||
105 | .iInterface = 0 | ||
106 | }; | ||
107 | |||
108 | static struct usb_endpoint_descriptor __attribute__((aligned(2))) | ||
109 | endpoint_descriptor = | ||
110 | { | ||
111 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
112 | .bDescriptorType = USB_DT_ENDPOINT, | ||
113 | .bEndpointAddress = 0, | ||
114 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
115 | .wMaxPacketSize = 0, | ||
116 | .bInterval = 0 | ||
117 | }; | ||
88 | 118 | ||
89 | struct inquiry_data { | 119 | struct inquiry_data { |
90 | unsigned char DeviceType; | 120 | unsigned char DeviceType; |
@@ -111,7 +141,7 @@ struct report_lun_data { | |||
111 | struct sense_data { | 141 | struct sense_data { |
112 | unsigned char ResponseCode; | 142 | unsigned char ResponseCode; |
113 | unsigned char Obsolete; | 143 | unsigned char Obsolete; |
114 | unsigned char filemark_eom_ili_sensekey; | 144 | unsigned char fei_sensekey; |
115 | unsigned int Information; | 145 | unsigned int Information; |
116 | unsigned char AdditionalSenseLength; | 146 | unsigned char AdditionalSenseLength; |
117 | unsigned int CommandSpecificInformation; | 147 | unsigned int CommandSpecificInformation; |
@@ -122,15 +152,15 @@ struct sense_data { | |||
122 | unsigned short SenseKeySpecific; | 152 | unsigned short SenseKeySpecific; |
123 | } __attribute__ ((packed)); | 153 | } __attribute__ ((packed)); |
124 | 154 | ||
125 | struct mode_sense_block_descriptor_longlba { | 155 | struct mode_sense_bdesc_longlba { |
126 | unsigned char number_of_blocks[8]; | 156 | unsigned char num_blocks[8]; |
127 | unsigned char reserved[4]; | 157 | unsigned char reserved[4]; |
128 | unsigned char block_size[4]; | 158 | unsigned char block_size[4]; |
129 | } __attribute__ ((packed)); | 159 | } __attribute__ ((packed)); |
130 | 160 | ||
131 | struct mode_sense_block_descriptor_shortlba { | 161 | struct mode_sense_bdesc_shortlba { |
132 | unsigned char density_code; | 162 | unsigned char density_code; |
133 | unsigned char number_of_blocks[3]; | 163 | unsigned char num_blocks[3]; |
134 | unsigned char reserved; | 164 | unsigned char reserved; |
135 | unsigned char block_size[3]; | 165 | unsigned char block_size[3]; |
136 | } __attribute__ ((packed)); | 166 | } __attribute__ ((packed)); |
@@ -142,7 +172,7 @@ struct mode_sense_data_10 { | |||
142 | unsigned char longlba; | 172 | unsigned char longlba; |
143 | unsigned char reserved; | 173 | unsigned char reserved; |
144 | unsigned short block_descriptor_length; | 174 | unsigned short block_descriptor_length; |
145 | struct mode_sense_block_descriptor_longlba block_descriptor; | 175 | struct mode_sense_bdesc_longlba block_descriptor; |
146 | } __attribute__ ((packed)); | 176 | } __attribute__ ((packed)); |
147 | 177 | ||
148 | struct mode_sense_data_6 { | 178 | struct mode_sense_data_6 { |
@@ -150,7 +180,7 @@ struct mode_sense_data_6 { | |||
150 | unsigned char medium_type; | 180 | unsigned char medium_type; |
151 | unsigned char device_specific; | 181 | unsigned char device_specific; |
152 | unsigned char block_descriptor_length; | 182 | unsigned char block_descriptor_length; |
153 | struct mode_sense_block_descriptor_shortlba block_descriptor; | 183 | struct mode_sense_bdesc_shortlba block_descriptor; |
154 | } __attribute__ ((packed)); | 184 | } __attribute__ ((packed)); |
155 | 185 | ||
156 | struct command_block_wrapper { | 186 | struct command_block_wrapper { |
@@ -188,8 +218,8 @@ static union { | |||
188 | struct capacity* capacity_data; | 218 | struct capacity* capacity_data; |
189 | struct format_capacity* format_capacity_data; | 219 | struct format_capacity* format_capacity_data; |
190 | struct sense_data *sense_data; | 220 | struct sense_data *sense_data; |
191 | struct mode_sense_data_6 *mode_sense_data_6; | 221 | struct mode_sense_data_6 *ms_data_6; |
192 | struct mode_sense_data_10 *mode_sense_data_10; | 222 | struct mode_sense_data_10 *ms_data_10; |
193 | struct report_lun_data *lun_data; | 223 | struct report_lun_data *lun_data; |
194 | struct command_status_wrapper* csw; | 224 | struct command_status_wrapper* csw; |
195 | char *max_lun; | 225 | char *max_lun; |
@@ -203,7 +233,7 @@ static struct { | |||
203 | unsigned char *data[2]; | 233 | unsigned char *data[2]; |
204 | unsigned char data_select; | 234 | unsigned char data_select; |
205 | unsigned int last_result; | 235 | unsigned int last_result; |
206 | } current_cmd; | 236 | } cur_cmd; |
207 | 237 | ||
208 | static struct { | 238 | static struct { |
209 | unsigned char sense_key; | 239 | unsigned char sense_key; |
@@ -221,6 +251,9 @@ static void identify2inquiry(int lun); | |||
221 | static void send_and_read_next(void); | 251 | static void send_and_read_next(void); |
222 | static bool ejected[NUM_VOLUMES]; | 252 | static bool ejected[NUM_VOLUMES]; |
223 | 253 | ||
254 | static int usb_endpoint; | ||
255 | static int usb_interface; | ||
256 | |||
224 | static enum { | 257 | static enum { |
225 | WAITING_FOR_COMMAND, | 258 | WAITING_FOR_COMMAND, |
226 | SENDING_BLOCKS, | 259 | SENDING_BLOCKS, |
@@ -238,6 +271,49 @@ void usb_storage_init(void) | |||
238 | logf("usb_storage_init done"); | 271 | logf("usb_storage_init done"); |
239 | } | 272 | } |
240 | 273 | ||
274 | int usb_storage_get_config_descriptor(unsigned char *dest,int max_packet_size, | ||
275 | int interface_number,int endpoint) | ||
276 | { | ||
277 | endpoint_descriptor.wMaxPacketSize=max_packet_size; | ||
278 | interface_descriptor.bInterfaceNumber=interface_number; | ||
279 | |||
280 | |||
281 | memcpy(dest,&interface_descriptor, | ||
282 | sizeof(struct usb_interface_descriptor)); | ||
283 | dest+=sizeof(struct usb_interface_descriptor); | ||
284 | |||
285 | endpoint_descriptor.bEndpointAddress = endpoint | USB_DIR_IN, | ||
286 | memcpy(dest,&endpoint_descriptor, | ||
287 | sizeof(struct usb_endpoint_descriptor)); | ||
288 | dest+=sizeof(struct usb_endpoint_descriptor); | ||
289 | |||
290 | endpoint_descriptor.bEndpointAddress = endpoint | USB_DIR_OUT, | ||
291 | memcpy(dest,&endpoint_descriptor, | ||
292 | sizeof(struct usb_endpoint_descriptor)); | ||
293 | |||
294 | return sizeof(struct usb_interface_descriptor) + | ||
295 | 2*sizeof(struct usb_endpoint_descriptor); | ||
296 | } | ||
297 | |||
298 | void usb_storage_init_connection(int interface,int endpoint) | ||
299 | { | ||
300 | size_t bufsize; | ||
301 | unsigned char * audio_buffer; | ||
302 | |||
303 | usb_interface = interface; | ||
304 | usb_endpoint = endpoint; | ||
305 | |||
306 | logf("ums: set config"); | ||
307 | /* prime rx endpoint. We only need room for commands */ | ||
308 | state = WAITING_FOR_COMMAND; | ||
309 | |||
310 | /* TODO : check if bufsize is at least 32K ? */ | ||
311 | audio_buffer = audio_get_buffer(false,&bufsize); | ||
312 | tb.transfer_buffer = | ||
313 | (void *)UNCACHED_ADDR((unsigned int)(audio_buffer + 31) & 0xffffffe0); | ||
314 | usb_drv_recv(usb_endpoint, tb.transfer_buffer, 1024); | ||
315 | } | ||
316 | |||
241 | /* called by usb_core_transfer_complete() */ | 317 | /* called by usb_core_transfer_complete() */ |
242 | void usb_storage_transfer_complete(bool in,int status,int length) | 318 | void usb_storage_transfer_complete(bool in,int status,int length) |
243 | { | 319 | { |
@@ -249,26 +325,31 @@ void usb_storage_transfer_complete(bool in,int status,int length) | |||
249 | if(in==true) { | 325 | if(in==true) { |
250 | logf("IN received in RECEIVING"); | 326 | logf("IN received in RECEIVING"); |
251 | } | 327 | } |
252 | logf("scsi write %d %d", current_cmd.sector, current_cmd.count); | 328 | logf("scsi write %d %d", cur_cmd.sector, cur_cmd.count); |
253 | if(status==0) { | 329 | if(status==0) { |
254 | if((unsigned int)length!=(SECTOR_SIZE*current_cmd.count) | 330 | if((unsigned int)length!=(SECTOR_SIZE*cur_cmd.count) |
255 | && (unsigned int)length!=BUFFER_SIZE) { | 331 | && (unsigned int)length!=BUFFER_SIZE) { |
256 | logf("unexpected length :%d",length); | 332 | logf("unexpected length :%d",length); |
257 | } | 333 | } |
258 | 334 | ||
259 | unsigned int next_sector = current_cmd.sector + (BUFFER_SIZE/SECTOR_SIZE); | 335 | unsigned int next_sector = cur_cmd.sector + |
260 | unsigned int next_count = current_cmd.count - MIN(current_cmd.count,BUFFER_SIZE/SECTOR_SIZE); | 336 | (BUFFER_SIZE/SECTOR_SIZE); |
337 | unsigned int next_count = cur_cmd.count - | ||
338 | MIN(cur_cmd.count,BUFFER_SIZE/SECTOR_SIZE); | ||
261 | 339 | ||
262 | if(next_count!=0) { | 340 | if(next_count!=0) { |
263 | /* Ask the host to send more, to the other buffer */ | 341 | /* Ask the host to send more, to the other buffer */ |
264 | receive_block_data(current_cmd.data[!current_cmd.data_select], | 342 | receive_block_data(cur_cmd.data[!cur_cmd.data_select], |
265 | MIN(BUFFER_SIZE,next_count*SECTOR_SIZE)); | 343 | MIN(BUFFER_SIZE,next_count*SECTOR_SIZE)); |
266 | } | 344 | } |
267 | 345 | ||
268 | /* Now write the data that just came in, while the host is sending the next bit */ | 346 | /* Now write the data that just came in, while the host is |
269 | int result = ata_write_sectors(IF_MV2(current_cmd.lun,) | 347 | sending the next bit */ |
270 | current_cmd.sector, MIN(BUFFER_SIZE/SECTOR_SIZE,current_cmd.count), | 348 | int result = ata_write_sectors(IF_MV2(cur_cmd.lun,) |
271 | current_cmd.data[current_cmd.data_select]); | 349 | cur_cmd.sector, |
350 | MIN(BUFFER_SIZE/SECTOR_SIZE, | ||
351 | cur_cmd.count), | ||
352 | cur_cmd.data[cur_cmd.data_select]); | ||
272 | if(result != 0) { | 353 | if(result != 0) { |
273 | send_csw(UMS_STATUS_FAIL); | 354 | send_csw(UMS_STATUS_FAIL); |
274 | cur_sense_data.sense_key=SENSE_MEDIUM_ERROR; | 355 | cur_sense_data.sense_key=SENSE_MEDIUM_ERROR; |
@@ -282,10 +363,10 @@ void usb_storage_transfer_complete(bool in,int status,int length) | |||
282 | } | 363 | } |
283 | 364 | ||
284 | /* Switch buffers for the next one */ | 365 | /* Switch buffers for the next one */ |
285 | current_cmd.data_select=!current_cmd.data_select; | 366 | cur_cmd.data_select=!cur_cmd.data_select; |
286 | 367 | ||
287 | current_cmd.sector = next_sector; | 368 | cur_cmd.sector = next_sector; |
288 | current_cmd.count = next_count; | 369 | cur_cmd.count = next_count; |
289 | 370 | ||
290 | } | 371 | } |
291 | else { | 372 | else { |
@@ -307,8 +388,8 @@ void usb_storage_transfer_complete(bool in,int status,int length) | |||
307 | handle_scsi(cbw); | 388 | handle_scsi(cbw); |
308 | } | 389 | } |
309 | else { | 390 | else { |
310 | usb_drv_stall(EP_MASS_STORAGE, true,true); | 391 | usb_drv_stall(usb_endpoint, true,true); |
311 | usb_drv_stall(EP_MASS_STORAGE, true,false); | 392 | usb_drv_stall(usb_endpoint, true,false); |
312 | } | 393 | } |
313 | break; | 394 | break; |
314 | case SENDING_CSW: | 395 | case SENDING_CSW: |
@@ -317,7 +398,7 @@ void usb_storage_transfer_complete(bool in,int status,int length) | |||
317 | } | 398 | } |
318 | //logf("csw sent, now go back to idle"); | 399 | //logf("csw sent, now go back to idle"); |
319 | state = WAITING_FOR_COMMAND; | 400 | state = WAITING_FOR_COMMAND; |
320 | usb_drv_recv(EP_MASS_STORAGE, tb.transfer_buffer, 1024); | 401 | usb_drv_recv(usb_endpoint, tb.transfer_buffer, 1024); |
321 | break; | 402 | break; |
322 | case SENDING_RESULT: | 403 | case SENDING_RESULT: |
323 | if(in==false) { | 404 | if(in==false) { |
@@ -342,7 +423,7 @@ void usb_storage_transfer_complete(bool in,int status,int length) | |||
342 | logf("OUT received in SENDING"); | 423 | logf("OUT received in SENDING"); |
343 | } | 424 | } |
344 | if(status==0) { | 425 | if(status==0) { |
345 | if(current_cmd.count==0) { | 426 | if(cur_cmd.count==0) { |
346 | //logf("data sent, now send csw"); | 427 | //logf("data sent, now send csw"); |
347 | send_csw(UMS_STATUS_GOOD); | 428 | send_csw(UMS_STATUS_GOOD); |
348 | } | 429 | } |
@@ -368,6 +449,7 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req) | |||
368 | { | 449 | { |
369 | bool handled = false; | 450 | bool handled = false; |
370 | 451 | ||
452 | |||
371 | switch (req->bRequest) { | 453 | switch (req->bRequest) { |
372 | case USB_BULK_GET_MAX_LUN: { | 454 | case USB_BULK_GET_MAX_LUN: { |
373 | #ifdef ONLY_EXPOSE_CARD_SLOT | 455 | #ifdef ONLY_EXPOSE_CARD_SLOT |
@@ -386,31 +468,16 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req) | |||
386 | logf("ums: bulk reset"); | 468 | logf("ums: bulk reset"); |
387 | state = WAITING_FOR_COMMAND; | 469 | state = WAITING_FOR_COMMAND; |
388 | /* UMS BOT 3.1 says The device shall preserve the value of its bulk | 470 | /* UMS BOT 3.1 says The device shall preserve the value of its bulk |
389 | * data toggle bits and endpoint STALL conditions despite the Bulk-Only | 471 | data toggle bits and endpoint STALL conditions despite |
390 | * Mass Storage Reset. */ | 472 | the Bulk-Only Mass Storage Reset. */ |
391 | #if 0 | 473 | #if 0 |
392 | usb_drv_reset_endpoint(EP_MASS_STORAGE, false); | 474 | usb_drv_reset_endpoint(usb_endpoint, false); |
393 | usb_drv_reset_endpoint(EP_MASS_STORAGE, true); | 475 | usb_drv_reset_endpoint(usb_endpoint, true); |
394 | #endif | 476 | #endif |
395 | 477 | ||
396 | usb_drv_send(EP_CONTROL, NULL, 0); /* ack */ | 478 | usb_drv_send(EP_CONTROL, NULL, 0); /* ack */ |
397 | handled = true; | 479 | handled = true; |
398 | break; | 480 | break; |
399 | |||
400 | case USB_REQ_SET_CONFIGURATION: { | ||
401 | size_t bufsize; | ||
402 | unsigned char * audio_buffer; | ||
403 | logf("ums: set config"); | ||
404 | /* prime rx endpoint. We only need room for commands */ | ||
405 | state = WAITING_FOR_COMMAND; | ||
406 | |||
407 | /* TODO : check if bufsize is at least 32K ? */ | ||
408 | audio_buffer = audio_get_buffer(false,&bufsize); | ||
409 | tb.transfer_buffer = (void *)UNCACHED_ADDR((unsigned int)(audio_buffer + 31) & 0xffffffe0); | ||
410 | usb_drv_recv(EP_MASS_STORAGE, tb.transfer_buffer, 1024); | ||
411 | handled = true; | ||
412 | break; | ||
413 | } | ||
414 | } | 481 | } |
415 | 482 | ||
416 | return handled; | 483 | return handled; |
@@ -418,7 +485,7 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req) | |||
418 | 485 | ||
419 | static void send_and_read_next(void) | 486 | static void send_and_read_next(void) |
420 | { | 487 | { |
421 | if(current_cmd.last_result!=0) { | 488 | if(cur_cmd.last_result!=0) { |
422 | /* The last read failed. */ | 489 | /* The last read failed. */ |
423 | send_csw(UMS_STATUS_FAIL); | 490 | send_csw(UMS_STATUS_FAIL); |
424 | cur_sense_data.sense_key=SENSE_MEDIUM_ERROR; | 491 | cur_sense_data.sense_key=SENSE_MEDIUM_ERROR; |
@@ -426,21 +493,23 @@ static void send_and_read_next(void) | |||
426 | cur_sense_data.ascq=0; | 493 | cur_sense_data.ascq=0; |
427 | return; | 494 | return; |
428 | } | 495 | } |
429 | send_block_data(current_cmd.data[current_cmd.data_select], | 496 | send_block_data(cur_cmd.data[cur_cmd.data_select], |
430 | MIN(BUFFER_SIZE,current_cmd.count*SECTOR_SIZE)); | 497 | MIN(BUFFER_SIZE,cur_cmd.count*SECTOR_SIZE)); |
431 | 498 | ||
432 | /* Switch buffers for the next one */ | 499 | /* Switch buffers for the next one */ |
433 | current_cmd.data_select=!current_cmd.data_select; | 500 | cur_cmd.data_select=!cur_cmd.data_select; |
434 | 501 | ||
435 | current_cmd.sector+=(BUFFER_SIZE/SECTOR_SIZE); | 502 | cur_cmd.sector+=(BUFFER_SIZE/SECTOR_SIZE); |
436 | current_cmd.count-=MIN(current_cmd.count,BUFFER_SIZE/SECTOR_SIZE); | 503 | cur_cmd.count-=MIN(cur_cmd.count,BUFFER_SIZE/SECTOR_SIZE); |
437 | 504 | ||
438 | if(current_cmd.count!=0){ | 505 | if(cur_cmd.count!=0){ |
439 | /* already read the next bit, so we can send it out immediately when the | 506 | /* already read the next bit, so we can send it out immediately when the |
440 | * current transfer completes. */ | 507 | * current transfer completes. */ |
441 | current_cmd.last_result = ata_read_sectors(IF_MV2(current_cmd.lun,) current_cmd.sector, | 508 | cur_cmd.last_result = ata_read_sectors(IF_MV2(cur_cmd.lun,) |
442 | MIN(BUFFER_SIZE/SECTOR_SIZE,current_cmd.count), | 509 | cur_cmd.sector, |
443 | current_cmd.data[current_cmd.data_select]); | 510 | MIN(BUFFER_SIZE/SECTOR_SIZE, |
511 | cur_cmd.count), | ||
512 | cur_cmd.data[cur_cmd.data_select]); | ||
444 | } | 513 | } |
445 | } | 514 | } |
446 | /****************************************************************************/ | 515 | /****************************************************************************/ |
@@ -484,8 +553,8 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
484 | block_size_mult = disk_sector_multiplier; | 553 | block_size_mult = disk_sector_multiplier; |
485 | #endif | 554 | #endif |
486 | 555 | ||
487 | current_cmd.tag = cbw->tag; | 556 | cur_cmd.tag = cbw->tag; |
488 | current_cmd.lun = lun; | 557 | cur_cmd.lun = lun; |
489 | 558 | ||
490 | switch (cbw->command_block[0]) { | 559 | switch (cbw->command_block[0]) { |
491 | case SCSI_TEST_UNIT_READY: | 560 | case SCSI_TEST_UNIT_READY: |
@@ -524,7 +593,8 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
524 | #endif | 593 | #endif |
525 | tb.lun_data->lun0[1]=0; | 594 | tb.lun_data->lun0[1]=0; |
526 | 595 | ||
527 | send_command_result(tb.lun_data, MIN(sizeof(struct report_lun_data), length)); | 596 | send_command_result(tb.lun_data, |
597 | MIN(sizeof(struct report_lun_data), length)); | ||
528 | break; | 598 | break; |
529 | } | 599 | } |
530 | 600 | ||
@@ -532,12 +602,13 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
532 | logf("scsi inquiry %d",lun); | 602 | logf("scsi inquiry %d",lun); |
533 | identify2inquiry(lun); | 603 | identify2inquiry(lun); |
534 | length = MIN(length, cbw->command_block[4]); | 604 | length = MIN(length, cbw->command_block[4]); |
535 | send_command_result(tb.inquiry, MIN(sizeof(struct inquiry_data), length)); | 605 | send_command_result(tb.inquiry, |
606 | MIN(sizeof(struct inquiry_data), length)); | ||
536 | break; | 607 | break; |
537 | 608 | ||
538 | case SCSI_REQUEST_SENSE: { | 609 | case SCSI_REQUEST_SENSE: { |
539 | tb.sense_data->ResponseCode=0x70;/*current error*/ | 610 | tb.sense_data->ResponseCode=0x70;/*current error*/ |
540 | tb.sense_data->filemark_eom_ili_sensekey=cur_sense_data.sense_key&0x0f; | 611 | tb.sense_data->fei_sensekey=cur_sense_data.sense_key&0x0f; |
541 | tb.sense_data->Information=cur_sense_data.information; | 612 | tb.sense_data->Information=cur_sense_data.information; |
542 | tb.sense_data->AdditionalSenseLength=10; | 613 | tb.sense_data->AdditionalSenseLength=10; |
543 | tb.sense_data->CommandSpecificInformation=0; | 614 | tb.sense_data->CommandSpecificInformation=0; |
@@ -564,24 +635,36 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
564 | logf("scsi mode_sense_10 %d %X",lun,page_code); | 635 | logf("scsi mode_sense_10 %d %X",lun,page_code); |
565 | switch(page_code) { | 636 | switch(page_code) { |
566 | case 0x3f: | 637 | case 0x3f: |
567 | tb.mode_sense_data_10->mode_data_length=htobe16(sizeof(struct mode_sense_data_10)-2); | 638 | tb.ms_data_10->mode_data_length = |
568 | tb.mode_sense_data_10->medium_type=0; | 639 | htobe16(sizeof(struct mode_sense_data_10)-2); |
569 | tb.mode_sense_data_10->device_specific=0; | 640 | tb.ms_data_10->medium_type = 0; |
570 | tb.mode_sense_data_10->reserved=0; | 641 | tb.ms_data_10->device_specific = 0; |
571 | tb.mode_sense_data_10->longlba=1; | 642 | tb.ms_data_10->reserved = 0; |
572 | tb.mode_sense_data_10->block_descriptor_length=htobe16(sizeof(struct mode_sense_block_descriptor_longlba)); | 643 | tb.ms_data_10->longlba = 1; |
573 | memset(tb.mode_sense_data_10->block_descriptor.reserved,0,4); | 644 | tb.ms_data_10->block_descriptor_length = |
574 | memset(tb.mode_sense_data_10->block_descriptor.number_of_blocks,0,8); | 645 | htobe16(sizeof(struct mode_sense_bdesc_longlba)); |
575 | tb.mode_sense_data_10->block_descriptor.number_of_blocks[4]=((block_count/block_size_mult) & 0xff000000)>>24; | 646 | |
576 | tb.mode_sense_data_10->block_descriptor.number_of_blocks[5]=((block_count/block_size_mult) & 0x00ff0000)>>16; | 647 | memset(tb.ms_data_10->block_descriptor.reserved,0,4); |
577 | tb.mode_sense_data_10->block_descriptor.number_of_blocks[6]=((block_count/block_size_mult) & 0x0000ff00)>>8; | 648 | memset(tb.ms_data_10->block_descriptor.num_blocks,0,8); |
578 | tb.mode_sense_data_10->block_descriptor.number_of_blocks[7]=((block_count/block_size_mult) & 0x000000ff); | 649 | |
579 | 650 | tb.ms_data_10->block_descriptor.num_blocks[4] = | |
580 | tb.mode_sense_data_10->block_descriptor.block_size[0]=((block_size*block_size_mult) & 0xff000000)>>24; | 651 | ((block_count/block_size_mult) & 0xff000000)>>24; |
581 | tb.mode_sense_data_10->block_descriptor.block_size[1]=((block_size*block_size_mult) & 0x00ff0000)>>16; | 652 | tb.ms_data_10->block_descriptor.num_blocks[5] = |
582 | tb.mode_sense_data_10->block_descriptor.block_size[2]=((block_size*block_size_mult) & 0x0000ff00)>>8; | 653 | ((block_count/block_size_mult) & 0x00ff0000)>>16; |
583 | tb.mode_sense_data_10->block_descriptor.block_size[3]=((block_size*block_size_mult) & 0x000000ff); | 654 | tb.ms_data_10->block_descriptor.num_blocks[6] = |
584 | send_command_result(tb.mode_sense_data_10, | 655 | ((block_count/block_size_mult) & 0x0000ff00)>>8; |
656 | tb.ms_data_10->block_descriptor.num_blocks[7] = | ||
657 | ((block_count/block_size_mult) & 0x000000ff); | ||
658 | |||
659 | tb.ms_data_10->block_descriptor.block_size[0] = | ||
660 | ((block_size*block_size_mult) & 0xff000000)>>24; | ||
661 | tb.ms_data_10->block_descriptor.block_size[1] = | ||
662 | ((block_size*block_size_mult) & 0x00ff0000)>>16; | ||
663 | tb.ms_data_10->block_descriptor.block_size[2] = | ||
664 | ((block_size*block_size_mult) & 0x0000ff00)>>8; | ||
665 | tb.ms_data_10->block_descriptor.block_size[3] = | ||
666 | ((block_size*block_size_mult) & 0x000000ff); | ||
667 | send_command_result(tb.ms_data_10, | ||
585 | MIN(sizeof(struct mode_sense_data_10), length)); | 668 | MIN(sizeof(struct mode_sense_data_10), length)); |
586 | break; | 669 | break; |
587 | default: | 670 | default: |
@@ -606,27 +689,35 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
606 | logf("scsi mode_sense_6 %d %X",lun,page_code); | 689 | logf("scsi mode_sense_6 %d %X",lun,page_code); |
607 | switch(page_code) { | 690 | switch(page_code) { |
608 | case 0x3f: | 691 | case 0x3f: |
609 | /* All supported pages Since we support only one this is easy*/ | 692 | /* All supported pages. */ |
610 | tb.mode_sense_data_6->mode_data_length=sizeof(struct mode_sense_data_6)-1; | 693 | tb.ms_data_6->mode_data_length = |
611 | tb.mode_sense_data_6->medium_type=0; | 694 | sizeof(struct mode_sense_data_6)-1; |
612 | tb.mode_sense_data_6->device_specific=0; | 695 | tb.ms_data_6->medium_type = 0; |
613 | tb.mode_sense_data_6->block_descriptor_length=sizeof(struct mode_sense_block_descriptor_shortlba); | 696 | tb.ms_data_6->device_specific = 0; |
614 | tb.mode_sense_data_6->block_descriptor.density_code=0; | 697 | tb.ms_data_6->block_descriptor_length = |
615 | tb.mode_sense_data_6->block_descriptor.reserved=0; | 698 | sizeof(struct mode_sense_bdesc_shortlba); |
699 | tb.ms_data_6->block_descriptor.density_code = 0; | ||
700 | tb.ms_data_6->block_descriptor.reserved = 0; | ||
616 | if(block_count/block_size_mult > 0xffffff){ | 701 | if(block_count/block_size_mult > 0xffffff){ |
617 | tb.mode_sense_data_6->block_descriptor.number_of_blocks[0]=0xff; | 702 | tb.ms_data_6->block_descriptor.num_blocks[0] = 0xff; |
618 | tb.mode_sense_data_6->block_descriptor.number_of_blocks[1]=0xff; | 703 | tb.ms_data_6->block_descriptor.num_blocks[1] = 0xff; |
619 | tb.mode_sense_data_6->block_descriptor.number_of_blocks[2]=0xff; | 704 | tb.ms_data_6->block_descriptor.num_blocks[2] = 0xff; |
620 | } | 705 | } |
621 | else { | 706 | else { |
622 | tb.mode_sense_data_6->block_descriptor.number_of_blocks[0]=((block_count/block_size_mult) & 0xff0000)>>16; | 707 | tb.ms_data_6->block_descriptor.num_blocks[0] = |
623 | tb.mode_sense_data_6->block_descriptor.number_of_blocks[1]=((block_count/block_size_mult) & 0x00ff00)>>8; | 708 | ((block_count/block_size_mult) & 0xff0000)>>16; |
624 | tb.mode_sense_data_6->block_descriptor.number_of_blocks[2]=((block_count/block_size_mult) & 0x0000ff); | 709 | tb.ms_data_6->block_descriptor.num_blocks[1] = |
710 | ((block_count/block_size_mult) & 0x00ff00)>>8; | ||
711 | tb.ms_data_6->block_descriptor.num_blocks[2] = | ||
712 | ((block_count/block_size_mult) & 0x0000ff); | ||
625 | } | 713 | } |
626 | tb.mode_sense_data_6->block_descriptor.block_size[0]=((block_size*block_size_mult) & 0xff0000)>>16; | 714 | tb.ms_data_6->block_descriptor.block_size[0] = |
627 | tb.mode_sense_data_6->block_descriptor.block_size[1]=((block_size*block_size_mult) & 0x00ff00)>>8; | 715 | ((block_size*block_size_mult) & 0xff0000)>>16; |
628 | tb.mode_sense_data_6->block_descriptor.block_size[2]=((block_size*block_size_mult) & 0x0000ff); | 716 | tb.ms_data_6->block_descriptor.block_size[1] = |
629 | send_command_result(tb.mode_sense_data_6, | 717 | ((block_size*block_size_mult) & 0x00ff00)>>8; |
718 | tb.ms_data_6->block_descriptor.block_size[2] = | ||
719 | ((block_size*block_size_mult) & 0x0000ff); | ||
720 | send_command_result(tb.ms_data_6, | ||
630 | MIN(sizeof(struct mode_sense_data_6), length)); | 721 | MIN(sizeof(struct mode_sense_data_6), length)); |
631 | break; | 722 | break; |
632 | default: | 723 | default: |
@@ -641,8 +732,8 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
641 | 732 | ||
642 | case SCSI_START_STOP_UNIT: | 733 | case SCSI_START_STOP_UNIT: |
643 | logf("scsi start_stop unit %d",lun); | 734 | logf("scsi start_stop unit %d",lun); |
644 | if((cbw->command_block[4] & 0xf0) == 0) /* Process start and eject bits */ | 735 | if((cbw->command_block[4] & 0xf0) == 0) |
645 | { | 736 | { /* Process start and eject bits */ |
646 | if((cbw->command_block[4] & 0x01) == 0 && | 737 | if((cbw->command_block[4] & 0x01) == 0 && |
647 | (cbw->command_block[4] & 0x02) != 0) /* Stop and eject */ | 738 | (cbw->command_block[4] & 0x02) != 0) /* Stop and eject */ |
648 | { | 739 | { |
@@ -661,10 +752,13 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
661 | logf("scsi read_format_capacity %d",lun); | 752 | logf("scsi read_format_capacity %d",lun); |
662 | if(lun_present) { | 753 | if(lun_present) { |
663 | tb.format_capacity_data->following_length=htobe32(8); | 754 | tb.format_capacity_data->following_length=htobe32(8); |
664 | /* Careful: "block count" actually means "number of last block" */ | 755 | /* "block count" actually means "number of last block" */ |
665 | tb.format_capacity_data->block_count = htobe32(block_count/block_size_mult - 1); | 756 | tb.format_capacity_data->block_count = |
666 | tb.format_capacity_data->block_size = htobe32(block_size*block_size_mult); | 757 | htobe32(block_count/block_size_mult - 1); |
667 | tb.format_capacity_data->block_size |= SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA; | 758 | tb.format_capacity_data->block_size = |
759 | htobe32(block_size*block_size_mult); | ||
760 | tb.format_capacity_data->block_size |= | ||
761 | SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA; | ||
668 | 762 | ||
669 | send_command_result(tb.format_capacity_data, | 763 | send_command_result(tb.format_capacity_data, |
670 | MIN(sizeof(struct format_capacity), length)); | 764 | MIN(sizeof(struct format_capacity), length)); |
@@ -682,11 +776,14 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
682 | logf("scsi read_capacity %d",lun); | 776 | logf("scsi read_capacity %d",lun); |
683 | 777 | ||
684 | if(lun_present) { | 778 | if(lun_present) { |
685 | /* Careful: "block count" actually means "number of last block" */ | 779 | /* "block count" actually means "number of last block" */ |
686 | tb.capacity_data->block_count = htobe32(block_count/block_size_mult - 1); | 780 | tb.capacity_data->block_count = |
687 | tb.capacity_data->block_size = htobe32(block_size*block_size_mult); | 781 | htobe32(block_count/block_size_mult - 1); |
688 | 782 | tb.capacity_data->block_size = | |
689 | send_command_result(tb.capacity_data, MIN(sizeof(struct capacity), length)); | 783 | htobe32(block_size*block_size_mult); |
784 | |||
785 | send_command_result(tb.capacity_data, | ||
786 | MIN(sizeof(struct capacity), length)); | ||
690 | } | 787 | } |
691 | else | 788 | else |
692 | { | 789 | { |
@@ -707,30 +804,32 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
707 | cur_sense_data.ascq=0; | 804 | cur_sense_data.ascq=0; |
708 | break; | 805 | break; |
709 | } | 806 | } |
710 | current_cmd.data[0] = tb.transfer_buffer; | 807 | cur_cmd.data[0] = tb.transfer_buffer; |
711 | current_cmd.data[1] = &tb.transfer_buffer[BUFFER_SIZE]; | 808 | cur_cmd.data[1] = &tb.transfer_buffer[BUFFER_SIZE]; |
712 | current_cmd.data_select=0; | 809 | cur_cmd.data_select=0; |
713 | current_cmd.sector = block_size_mult * | 810 | cur_cmd.sector = block_size_mult * |
714 | (cbw->command_block[2] << 24 | | 811 | (cbw->command_block[2] << 24 | |
715 | cbw->command_block[3] << 16 | | 812 | cbw->command_block[3] << 16 | |
716 | cbw->command_block[4] << 8 | | 813 | cbw->command_block[4] << 8 | |
717 | cbw->command_block[5] ); | 814 | cbw->command_block[5] ); |
718 | current_cmd.count = block_size_mult * | 815 | cur_cmd.count = block_size_mult * |
719 | (cbw->command_block[7] << 8 | | 816 | (cbw->command_block[7] << 8 | |
720 | cbw->command_block[8]); | 817 | cbw->command_block[8]); |
721 | 818 | ||
722 | //logf("scsi read %d %d", current_cmd.sector, current_cmd.count); | 819 | //logf("scsi read %d %d", cur_cmd.sector, cur_cmd.count); |
723 | 820 | ||
724 | if((current_cmd.sector + current_cmd.count) > block_count) { | 821 | if((cur_cmd.sector + cur_cmd.count) > block_count) { |
725 | send_csw(UMS_STATUS_FAIL); | 822 | send_csw(UMS_STATUS_FAIL); |
726 | cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST; | 823 | cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST; |
727 | cur_sense_data.asc=ASC_LBA_OUT_OF_RANGE; | 824 | cur_sense_data.asc=ASC_LBA_OUT_OF_RANGE; |
728 | cur_sense_data.ascq=0; | 825 | cur_sense_data.ascq=0; |
729 | } | 826 | } |
730 | else { | 827 | else { |
731 | current_cmd.last_result = ata_read_sectors(IF_MV2(current_cmd.lun,) current_cmd.sector, | 828 | cur_cmd.last_result = ata_read_sectors(IF_MV2(cur_cmd.lun,) |
732 | MIN(BUFFER_SIZE/SECTOR_SIZE,current_cmd.count), | 829 | cur_cmd.sector, |
733 | current_cmd.data[current_cmd.data_select]); | 830 | MIN(BUFFER_SIZE/SECTOR_SIZE, |
831 | cur_cmd.count), | ||
832 | cur_cmd.data[cur_cmd.data_select]); | ||
734 | send_and_read_next(); | 833 | send_and_read_next(); |
735 | } | 834 | } |
736 | break; | 835 | break; |
@@ -744,34 +843,35 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
744 | cur_sense_data.ascq=0; | 843 | cur_sense_data.ascq=0; |
745 | break; | 844 | break; |
746 | } | 845 | } |
747 | current_cmd.data[0] = tb.transfer_buffer; | 846 | cur_cmd.data[0] = tb.transfer_buffer; |
748 | current_cmd.data[1] = &tb.transfer_buffer[BUFFER_SIZE]; | 847 | cur_cmd.data[1] = &tb.transfer_buffer[BUFFER_SIZE]; |
749 | current_cmd.data_select=0; | 848 | cur_cmd.data_select=0; |
750 | current_cmd.sector = block_size_mult * | 849 | cur_cmd.sector = block_size_mult * |
751 | (cbw->command_block[2] << 24 | | 850 | (cbw->command_block[2] << 24 | |
752 | cbw->command_block[3] << 16 | | 851 | cbw->command_block[3] << 16 | |
753 | cbw->command_block[4] << 8 | | 852 | cbw->command_block[4] << 8 | |
754 | cbw->command_block[5] ); | 853 | cbw->command_block[5] ); |
755 | current_cmd.count = block_size_mult * | 854 | cur_cmd.count = block_size_mult * |
756 | (cbw->command_block[7] << 8 | | 855 | (cbw->command_block[7] << 8 | |
757 | cbw->command_block[8]); | 856 | cbw->command_block[8]); |
758 | /* expect data */ | 857 | /* expect data */ |
759 | if((current_cmd.sector + current_cmd.count) > block_count) { | 858 | if((cur_cmd.sector + cur_cmd.count) > block_count) { |
760 | send_csw(UMS_STATUS_FAIL); | 859 | send_csw(UMS_STATUS_FAIL); |
761 | cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST; | 860 | cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST; |
762 | cur_sense_data.asc=ASC_LBA_OUT_OF_RANGE; | 861 | cur_sense_data.asc=ASC_LBA_OUT_OF_RANGE; |
763 | cur_sense_data.ascq=0; | 862 | cur_sense_data.ascq=0; |
764 | } | 863 | } |
765 | else { | 864 | else { |
766 | receive_block_data(current_cmd.data[0], | 865 | receive_block_data(cur_cmd.data[0], |
767 | MIN(BUFFER_SIZE,current_cmd.count*SECTOR_SIZE)); | 866 | MIN(BUFFER_SIZE, |
867 | cur_cmd.count*SECTOR_SIZE)); | ||
768 | } | 868 | } |
769 | 869 | ||
770 | break; | 870 | break; |
771 | 871 | ||
772 | default: | 872 | default: |
773 | logf("scsi unknown cmd %x",cbw->command_block[0x0]); | 873 | logf("scsi unknown cmd %x",cbw->command_block[0x0]); |
774 | usb_drv_stall(EP_MASS_STORAGE, true,true); | 874 | usb_drv_stall(usb_endpoint, true,true); |
775 | send_csw(UMS_STATUS_FAIL); | 875 | send_csw(UMS_STATUS_FAIL); |
776 | break; | 876 | break; |
777 | } | 877 | } |
@@ -779,30 +879,31 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
779 | 879 | ||
780 | static void send_block_data(void *data,int size) | 880 | static void send_block_data(void *data,int size) |
781 | { | 881 | { |
782 | usb_drv_send_nonblocking(EP_MASS_STORAGE, data,size); | 882 | usb_drv_send_nonblocking(usb_endpoint, data,size); |
783 | state = SENDING_BLOCKS; | 883 | state = SENDING_BLOCKS; |
784 | } | 884 | } |
785 | 885 | ||
786 | static void send_command_result(void *data,int size) | 886 | static void send_command_result(void *data,int size) |
787 | { | 887 | { |
788 | usb_drv_send_nonblocking(EP_MASS_STORAGE, data,size); | 888 | usb_drv_send_nonblocking(usb_endpoint, data,size); |
789 | state = SENDING_RESULT; | 889 | state = SENDING_RESULT; |
790 | } | 890 | } |
791 | 891 | ||
792 | static void receive_block_data(void *data,int size) | 892 | static void receive_block_data(void *data,int size) |
793 | { | 893 | { |
794 | usb_drv_recv(EP_MASS_STORAGE, data, size); | 894 | usb_drv_recv(usb_endpoint, data, size); |
795 | state = RECEIVING_BLOCKS; | 895 | state = RECEIVING_BLOCKS; |
796 | } | 896 | } |
797 | 897 | ||
798 | static void send_csw(int status) | 898 | static void send_csw(int status) |
799 | { | 899 | { |
800 | tb.csw->signature = htole32(CSW_SIGNATURE); | 900 | tb.csw->signature = htole32(CSW_SIGNATURE); |
801 | tb.csw->tag = current_cmd.tag; | 901 | tb.csw->tag = cur_cmd.tag; |
802 | tb.csw->data_residue = 0; | 902 | tb.csw->data_residue = 0; |
803 | tb.csw->status = status; | 903 | tb.csw->status = status; |
804 | 904 | ||
805 | usb_drv_send_nonblocking(EP_MASS_STORAGE, tb.csw, sizeof(struct command_status_wrapper)); | 905 | usb_drv_send_nonblocking(usb_endpoint, tb.csw, |
906 | sizeof(struct command_status_wrapper)); | ||
806 | state = SENDING_CSW; | 907 | state = SENDING_CSW; |
807 | //logf("CSW: %X",status); | 908 | //logf("CSW: %X",status); |
808 | 909 | ||
@@ -866,7 +967,8 @@ static void identify2inquiry(int lun) | |||
866 | tb.inquiry->DeviceTypeModifier = DEVICE_REMOVABLE; | 967 | tb.inquiry->DeviceTypeModifier = DEVICE_REMOVABLE; |
867 | #endif | 968 | #endif |
868 | #endif | 969 | #endif |
869 | /* Mac OSX 10.5 doesn't like this driver if DEVICE_REMOVABLE is not set */ | 970 | /* Mac OSX 10.5 doesn't like this driver if DEVICE_REMOVABLE is not set. |
971 | TODO : this can probably be solved by providing caching mode page */ | ||
870 | tb.inquiry->DeviceTypeModifier = DEVICE_REMOVABLE; | 972 | tb.inquiry->DeviceTypeModifier = DEVICE_REMOVABLE; |
871 | } | 973 | } |
872 | 974 | ||
diff --git a/firmware/usbstack/usb_storage.h b/firmware/usbstack/usb_storage.h index 23903a855a..34bc0144dd 100644 --- a/firmware/usbstack/usb_storage.h +++ b/firmware/usbstack/usb_storage.h | |||
@@ -21,6 +21,9 @@ | |||
21 | 21 | ||
22 | #include "usb_ch9.h" | 22 | #include "usb_ch9.h" |
23 | 23 | ||
24 | int usb_storage_get_config_descriptor(unsigned char *dest,int max_packet_size, | ||
25 | int interface_number,int endpoint); | ||
26 | void usb_storage_init_connection(int interface,int endpoint); | ||
24 | void usb_storage_init(void); | 27 | void usb_storage_init(void); |
25 | void usb_storage_transfer_complete(bool in,int state,int length); | 28 | void usb_storage_transfer_complete(bool in,int state,int length); |
26 | bool usb_storage_control_request(struct usb_ctrlrequest* req); | 29 | bool usb_storage_control_request(struct usb_ctrlrequest* req); |