diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2014-05-25 16:06:31 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2014-09-07 17:45:10 +0200 |
commit | 12ce7fc2cce5531723ea7d141df80142891989d7 (patch) | |
tree | dc4e3320f8ed0932265b3c917448a83f7dcecafe /utils/hwstub/stub | |
parent | 1dc1a9310e8a078a633dd90def13103f80e01ce7 (diff) | |
download | rockbox-12ce7fc2cce5531723ea7d141df80142891989d7.tar.gz rockbox-12ce7fc2cce5531723ea7d141df80142891989d7.zip |
hwstub: remove protocol to make it use its own interface
This way, hwstub can be implemented along with other usb features/interfaces.
Change-Id: I7148cab845049cc0a8b8e740fa0d52d3a385eaed
Diffstat (limited to 'utils/hwstub/stub')
-rw-r--r-- | utils/hwstub/stub/main.c | 219 |
1 files changed, 154 insertions, 65 deletions
diff --git a/utils/hwstub/stub/main.c b/utils/hwstub/stub/main.c index c831de0196..a8d99fc863 100644 --- a/utils/hwstub/stub/main.c +++ b/utils/hwstub/stub/main.c | |||
@@ -45,15 +45,14 @@ static bool g_exit = false; | |||
45 | * | 45 | * |
46 | */ | 46 | */ |
47 | 47 | ||
48 | static struct usb_device_descriptor __attribute__((aligned(2))) | 48 | static struct usb_device_descriptor device_descriptor= |
49 | device_descriptor= | ||
50 | { | 49 | { |
51 | .bLength = sizeof(struct usb_device_descriptor), | 50 | .bLength = sizeof(struct usb_device_descriptor), |
52 | .bDescriptorType = USB_DT_DEVICE, | 51 | .bDescriptorType = USB_DT_DEVICE, |
53 | .bcdUSB = 0x0200, | 52 | .bcdUSB = 0x0200, |
54 | .bDeviceClass = HWSTUB_CLASS, | 53 | .bDeviceClass = USB_CLASS_PER_INTERFACE, |
55 | .bDeviceSubClass = HWSTUB_SUBCLASS, | 54 | .bDeviceSubClass = 0, |
56 | .bDeviceProtocol = HWSTUB_PROTOCOL, | 55 | .bDeviceProtocol = 0, |
57 | .bMaxPacketSize0 = 64, | 56 | .bMaxPacketSize0 = 64, |
58 | .idVendor = HWSTUB_USB_VID, | 57 | .idVendor = HWSTUB_USB_VID, |
59 | .idProduct = HWSTUB_USB_PID, | 58 | .idProduct = HWSTUB_USB_PID, |
@@ -66,29 +65,41 @@ static struct usb_device_descriptor __attribute__((aligned(2))) | |||
66 | 65 | ||
67 | #define USB_MAX_CURRENT 200 | 66 | #define USB_MAX_CURRENT 200 |
68 | 67 | ||
69 | static struct usb_config_descriptor __attribute__((aligned(2))) | 68 | static struct usb_config_descriptor config_descriptor = |
70 | config_descriptor = | ||
71 | { | 69 | { |
72 | .bLength = sizeof(struct usb_config_descriptor), | 70 | .bLength = sizeof(struct usb_config_descriptor), |
73 | .bDescriptorType = USB_DT_CONFIG, | 71 | .bDescriptorType = USB_DT_CONFIG, |
74 | .wTotalLength = 0, /* will be filled in later */ | 72 | .wTotalLength = 0, /* will be filled in later */ |
75 | .bNumInterfaces = 0, | 73 | .bNumInterfaces = 1, |
76 | .bConfigurationValue = 1, | 74 | .bConfigurationValue = 1, |
77 | .iConfiguration = 0, | 75 | .iConfiguration = 0, |
78 | .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, | 76 | .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, |
79 | .bMaxPower = (USB_MAX_CURRENT + 1) / 2, /* In 2mA units */ | 77 | .bMaxPower = (USB_MAX_CURRENT + 1) / 2, /* In 2mA units */ |
80 | }; | 78 | }; |
81 | 79 | ||
82 | static const struct usb_string_descriptor __attribute__((aligned(2))) | 80 | #define USB_HWSTUB_INTF 0 |
83 | usb_string_iManufacturer = | 81 | |
82 | static struct usb_interface_descriptor interface_descriptor = | ||
83 | { | ||
84 | .bLength = sizeof(struct usb_interface_descriptor), | ||
85 | .bDescriptorType = USB_DT_INTERFACE, | ||
86 | .bInterfaceNumber = USB_HWSTUB_INTF, | ||
87 | .bAlternateSetting = 0, | ||
88 | .bNumEndpoints = 0, | ||
89 | .bInterfaceClass = HWSTUB_CLASS, | ||
90 | .bInterfaceSubClass = HWSTUB_SUBCLASS, | ||
91 | .bInterfaceProtocol = HWSTUB_PROTOCOL, | ||
92 | .iInterface = 3 | ||
93 | }; | ||
94 | |||
95 | static const struct usb_string_descriptor usb_string_iManufacturer = | ||
84 | { | 96 | { |
85 | 24, | 97 | 24, |
86 | USB_DT_STRING, | 98 | USB_DT_STRING, |
87 | {'R', 'o', 'c', 'k', 'b', 'o', 'x', '.', 'o', 'r', 'g'} | 99 | {'R', 'o', 'c', 'k', 'b', 'o', 'x', '.', 'o', 'r', 'g'} |
88 | }; | 100 | }; |
89 | 101 | ||
90 | static const struct usb_string_descriptor __attribute__((aligned(2))) | 102 | static const struct usb_string_descriptor usb_string_iProduct = |
91 | usb_string_iProduct = | ||
92 | { | 103 | { |
93 | 44, | 104 | 44, |
94 | USB_DT_STRING, | 105 | USB_DT_STRING, |
@@ -97,17 +108,22 @@ static const struct usb_string_descriptor __attribute__((aligned(2))) | |||
97 | 's', 't', 'u', 'b'} | 108 | 's', 't', 'u', 'b'} |
98 | }; | 109 | }; |
99 | 110 | ||
111 | static const struct usb_string_descriptor usb_string_iInterface = | ||
112 | { | ||
113 | 14, | ||
114 | USB_DT_STRING, | ||
115 | {'H', 'W', 'S', 't', 'u', 'b'} | ||
116 | }; | ||
117 | |||
100 | /* this is stringid #0: languages supported */ | 118 | /* this is stringid #0: languages supported */ |
101 | static const struct usb_string_descriptor __attribute__((aligned(2))) | 119 | static const struct usb_string_descriptor lang_descriptor = |
102 | lang_descriptor = | ||
103 | { | 120 | { |
104 | 4, | 121 | 4, |
105 | USB_DT_STRING, | 122 | USB_DT_STRING, |
106 | {0x0409} /* LANGID US English */ | 123 | {0x0409} /* LANGID US English */ |
107 | }; | 124 | }; |
108 | 125 | ||
109 | static struct hwstub_version_desc_t __attribute__((aligned(2))) | 126 | static struct hwstub_version_desc_t version_descriptor = |
110 | version_descriptor = | ||
111 | { | 127 | { |
112 | sizeof(struct hwstub_version_desc_t), | 128 | sizeof(struct hwstub_version_desc_t), |
113 | HWSTUB_DT_VERSION, | 129 | HWSTUB_DT_VERSION, |
@@ -116,8 +132,7 @@ static struct hwstub_version_desc_t __attribute__((aligned(2))) | |||
116 | HWSTUB_VERSION_REV | 132 | HWSTUB_VERSION_REV |
117 | }; | 133 | }; |
118 | 134 | ||
119 | static struct hwstub_layout_desc_t __attribute__((aligned(2))) | 135 | static struct hwstub_layout_desc_t layout_descriptor = |
120 | layout_descriptor = | ||
121 | { | 136 | { |
122 | sizeof(struct hwstub_layout_desc_t), | 137 | sizeof(struct hwstub_layout_desc_t), |
123 | HWSTUB_DT_LAYOUT, | 138 | HWSTUB_DT_LAYOUT, |
@@ -131,6 +146,7 @@ static const struct usb_string_descriptor* const usb_strings[USB_NUM_STRINGS] = | |||
131 | &lang_descriptor, | 146 | &lang_descriptor, |
132 | &usb_string_iManufacturer, | 147 | &usb_string_iManufacturer, |
133 | &usb_string_iProduct, | 148 | &usb_string_iProduct, |
149 | &usb_string_iInterface | ||
134 | }; | 150 | }; |
135 | 151 | ||
136 | uint8_t *usb_buffer = oc_bufferstart; | 152 | uint8_t *usb_buffer = oc_bufferstart; |
@@ -176,6 +192,10 @@ static void handle_std_dev_desc(struct usb_ctrlrequest *req) | |||
176 | } | 192 | } |
177 | size = sizeof(struct usb_config_descriptor); | 193 | size = sizeof(struct usb_config_descriptor); |
178 | 194 | ||
195 | /* interface desc */ | ||
196 | memcpy(usb_buffer + size, (void *)&interface_descriptor, | ||
197 | sizeof(interface_descriptor)); | ||
198 | size += sizeof(interface_descriptor); | ||
179 | /* hwstub version */ | 199 | /* hwstub version */ |
180 | memcpy(usb_buffer + size, (void *)&version_descriptor, | 200 | memcpy(usb_buffer + size, (void *)&version_descriptor, |
181 | sizeof(version_descriptor)); | 201 | sizeof(version_descriptor)); |
@@ -194,7 +214,8 @@ static void handle_std_dev_desc(struct usb_ctrlrequest *req) | |||
194 | target_get_config_desc(usb_buffer + size, &size); | 214 | target_get_config_desc(usb_buffer + size, &size); |
195 | /* fix config descriptor */ | 215 | /* fix config descriptor */ |
196 | config_descriptor.wTotalLength = size; | 216 | config_descriptor.wTotalLength = size; |
197 | memcpy(usb_buffer, (void *)&config_descriptor, sizeof(config_descriptor)); | 217 | memcpy(usb_buffer, (void *)&config_descriptor, |
218 | sizeof(config_descriptor)); | ||
198 | 219 | ||
199 | ptr = usb_buffer; | 220 | ptr = usb_buffer; |
200 | break; | 221 | break; |
@@ -208,22 +229,7 @@ static void handle_std_dev_desc(struct usb_ctrlrequest *req) | |||
208 | else | 229 | else |
209 | usb_drv_stall(EP_CONTROL, true, true); | 230 | usb_drv_stall(EP_CONTROL, true, true); |
210 | break; | 231 | break; |
211 | case HWSTUB_DT_VERSION: | ||
212 | ptr = &version_descriptor; | ||
213 | size = sizeof(version_descriptor); | ||
214 | break; | ||
215 | case HWSTUB_DT_LAYOUT: | ||
216 | ptr = &layout_descriptor; | ||
217 | size = sizeof(layout_descriptor); | ||
218 | break; | ||
219 | case HWSTUB_DT_TARGET: | ||
220 | ptr = &target_descriptor; | ||
221 | size = sizeof(target_descriptor); | ||
222 | break; | ||
223 | default: | 232 | default: |
224 | target_get_desc(req->wValue >> 8, &ptr); | ||
225 | if(ptr != 0) | ||
226 | size = ((struct usb_descriptor_header *)ptr)->bLength; | ||
227 | break; | 233 | break; |
228 | } | 234 | } |
229 | 235 | ||
@@ -271,12 +277,70 @@ static void handle_std_dev_req(struct usb_ctrlrequest *req) | |||
271 | } | 277 | } |
272 | } | 278 | } |
273 | 279 | ||
280 | static void handle_std_intf_desc(struct usb_ctrlrequest *req) | ||
281 | { | ||
282 | int size; | ||
283 | void* ptr = NULL; | ||
284 | |||
285 | switch(req->wValue >> 8) | ||
286 | { | ||
287 | case HWSTUB_DT_VERSION: | ||
288 | ptr = &version_descriptor; | ||
289 | size = sizeof(version_descriptor); | ||
290 | break; | ||
291 | case HWSTUB_DT_LAYOUT: | ||
292 | ptr = &layout_descriptor; | ||
293 | size = sizeof(layout_descriptor); | ||
294 | break; | ||
295 | case HWSTUB_DT_TARGET: | ||
296 | ptr = &target_descriptor; | ||
297 | size = sizeof(target_descriptor); | ||
298 | break; | ||
299 | default: | ||
300 | target_get_desc(req->wValue >> 8, &ptr); | ||
301 | if(ptr != 0) | ||
302 | size = ((struct usb_descriptor_header *)ptr)->bLength; | ||
303 | break; | ||
304 | } | ||
305 | |||
306 | if(ptr) | ||
307 | { | ||
308 | int length = MIN(size, req->wLength); | ||
309 | |||
310 | if(ptr != usb_buffer) | ||
311 | memcpy(usb_buffer, ptr, length); | ||
312 | |||
313 | usb_drv_send(EP_CONTROL, usb_buffer, length); | ||
314 | usb_drv_recv(EP_CONTROL, NULL, 0); | ||
315 | } | ||
316 | else | ||
317 | usb_drv_stall(EP_CONTROL, true, true); | ||
318 | } | ||
319 | |||
320 | static void handle_std_intf_req(struct usb_ctrlrequest *req) | ||
321 | { | ||
322 | unsigned intf = req->wIndex & 0xff; | ||
323 | if(intf != USB_HWSTUB_INTF) | ||
324 | return usb_drv_stall(EP_CONTROL, true, true); | ||
325 | |||
326 | switch(req->bRequest) | ||
327 | { | ||
328 | case USB_REQ_GET_DESCRIPTOR: | ||
329 | handle_std_intf_desc(req); | ||
330 | break; | ||
331 | default: | ||
332 | usb_drv_stall(EP_CONTROL, true, true); | ||
333 | } | ||
334 | } | ||
335 | |||
274 | static void handle_std_req(struct usb_ctrlrequest *req) | 336 | static void handle_std_req(struct usb_ctrlrequest *req) |
275 | { | 337 | { |
276 | switch(req->bRequestType & USB_RECIP_MASK) | 338 | switch(req->bRequestType & USB_RECIP_MASK) |
277 | { | 339 | { |
278 | case USB_RECIP_DEVICE: | 340 | case USB_RECIP_DEVICE: |
279 | return handle_std_dev_req(req); | 341 | return handle_std_dev_req(req); |
342 | case USB_RECIP_INTERFACE: | ||
343 | return handle_std_intf_req(req); | ||
280 | default: | 344 | default: |
281 | usb_drv_stall(EP_CONTROL, true, true); | 345 | usb_drv_stall(EP_CONTROL, true, true); |
282 | } | 346 | } |
@@ -291,36 +355,56 @@ static void handle_get_log(struct usb_ctrlrequest *req) | |||
291 | enable_logf(true); | 355 | enable_logf(true); |
292 | } | 356 | } |
293 | 357 | ||
294 | static void handle_rw_mem(struct usb_ctrlrequest *req) | 358 | static void handle_read(struct usb_ctrlrequest *req) |
295 | { | 359 | { |
296 | uint32_t addr = req->wValue | req->wIndex << 16; | 360 | static uint32_t last_addr = 0; |
297 | uint16_t length = req->wLength; | 361 | static uint16_t last_id = 0xffff; |
298 | 362 | uint16_t id = req->wValue; | |
299 | if(req->bRequestType & USB_DIR_IN) | 363 | |
364 | if(req->bRequest == HWSTUB_READ) | ||
300 | { | 365 | { |
301 | memcpy(usb_buffer, (void *)addr, length); | 366 | int size = usb_drv_recv(EP_CONTROL, usb_buffer, req->wLength); |
367 | if(size != sizeof(struct hwstub_read_req_t)) | ||
368 | return usb_drv_stall(EP_CONTROL, true, true); | ||
302 | asm volatile("nop" : : : "memory"); | 369 | asm volatile("nop" : : : "memory"); |
303 | usb_drv_send(EP_CONTROL, usb_buffer, length); | 370 | struct hwstub_read_req_t *read = (void *)usb_buffer; |
304 | usb_drv_recv(EP_CONTROL, NULL, 0); | 371 | last_addr = read->dAddress; |
372 | last_id = id; | ||
373 | usb_drv_send(EP_CONTROL, NULL, 0); | ||
305 | } | 374 | } |
306 | else | 375 | else |
307 | { | 376 | { |
308 | int size = usb_drv_recv(EP_CONTROL, usb_buffer, length); | 377 | if(id != last_id) |
378 | return usb_drv_stall(EP_CONTROL, true, true); | ||
379 | memcpy((void *)last_addr, usb_buffer, req->wLength); | ||
380 | memcpy(usb_buffer, (void *)last_addr, req->wLength); | ||
309 | asm volatile("nop" : : : "memory"); | 381 | asm volatile("nop" : : : "memory"); |
310 | if(size != length) | 382 | usb_drv_send(EP_CONTROL, usb_buffer, req->wLength); |
311 | usb_drv_stall(EP_CONTROL, true, true); | 383 | usb_drv_recv(EP_CONTROL, NULL, 0); |
312 | else | ||
313 | { | ||
314 | memcpy((void *)addr, usb_buffer, length); | ||
315 | usb_drv_send(EP_CONTROL, NULL, 0); | ||
316 | } | ||
317 | } | 384 | } |
318 | } | 385 | }; |
319 | 386 | ||
320 | static void handle_call_jump(struct usb_ctrlrequest *req) | 387 | static void handle_write(struct usb_ctrlrequest *req) |
321 | { | 388 | { |
322 | uint32_t addr = req->wValue | req->wIndex << 16; | 389 | int size = usb_drv_recv(EP_CONTROL, usb_buffer, req->wLength); |
390 | asm volatile("nop" : : : "memory"); | ||
391 | struct hwstub_write_req_t *write = (void *)usb_buffer; | ||
392 | int sz_hdr = sizeof(struct hwstub_write_req_t); | ||
393 | if(size < sz_hdr) | ||
394 | return usb_drv_stall(EP_CONTROL, true, true); | ||
395 | memcpy((void *)write->dAddress, usb_buffer + sz_hdr, req->wLength - sz_hdr); | ||
396 | usb_drv_send(EP_CONTROL, NULL, 0); | ||
397 | } | ||
323 | 398 | ||
399 | static void handle_exec(struct usb_ctrlrequest *req) | ||
400 | { | ||
401 | int size = usb_drv_recv(EP_CONTROL, usb_buffer, req->wLength); | ||
402 | asm volatile("nop" : : : "memory"); | ||
403 | struct hwstub_exec_req_t *exec = (void *)usb_buffer; | ||
404 | if(size != sizeof(struct hwstub_exec_req_t)) | ||
405 | return usb_drv_stall(EP_CONTROL, true, true); | ||
406 | usb_drv_send(EP_CONTROL, NULL, 0); | ||
407 | #if 0 | ||
324 | if(req->bRequest == HWSTUB_CALL) | 408 | if(req->bRequest == HWSTUB_CALL) |
325 | ((void (*)(void))addr)(); | 409 | ((void (*)(void))addr)(); |
326 | else | 410 | else |
@@ -329,23 +413,26 @@ static void handle_call_jump(struct usb_ctrlrequest *req) | |||
329 | usb_drv_exit(); | 413 | usb_drv_exit(); |
330 | asm volatile("bx %0\n" : : "r" (addr) : "memory"); | 414 | asm volatile("bx %0\n" : : "r" (addr) : "memory"); |
331 | } | 415 | } |
416 | #endif | ||
332 | } | 417 | } |
333 | 418 | ||
334 | static void handle_class_dev_req(struct usb_ctrlrequest *req) | 419 | static void handle_class_intf_req(struct usb_ctrlrequest *req) |
335 | { | 420 | { |
421 | unsigned intf = req->wIndex & 0xff; | ||
422 | if(intf != USB_HWSTUB_INTF) | ||
423 | return usb_drv_stall(EP_CONTROL, true, true); | ||
424 | |||
336 | switch(req->bRequest) | 425 | switch(req->bRequest) |
337 | { | 426 | { |
338 | case HWSTUB_GET_LOG: | 427 | case HWSTUB_GET_LOG: |
339 | handle_get_log(req); | 428 | return handle_get_log(req); |
340 | break; | 429 | case HWSTUB_READ: |
341 | case HWSTUB_RW_MEM: | 430 | case HWSTUB_READ2: |
342 | handle_rw_mem(req); | 431 | return handle_read(req); |
343 | break; | 432 | case HWSTUB_WRITE: |
344 | case HWSTUB_CALL: | 433 | return handle_write(req); |
345 | case HWSTUB_JUMP: | 434 | case HWSTUB_EXEC: |
346 | handle_call_jump(req); | 435 | return handle_exec(req); |
347 | break; | ||
348 | break; | ||
349 | default: | 436 | default: |
350 | usb_drv_stall(EP_CONTROL, true, true); | 437 | usb_drv_stall(EP_CONTROL, true, true); |
351 | } | 438 | } |
@@ -355,8 +442,10 @@ static void handle_class_req(struct usb_ctrlrequest *req) | |||
355 | { | 442 | { |
356 | switch(req->bRequestType & USB_RECIP_MASK) | 443 | switch(req->bRequestType & USB_RECIP_MASK) |
357 | { | 444 | { |
445 | case USB_RECIP_INTERFACE: | ||
446 | return handle_class_intf_req(req); | ||
358 | case USB_RECIP_DEVICE: | 447 | case USB_RECIP_DEVICE: |
359 | return handle_class_dev_req(req); | 448 | //return handle_class_dev_req(req); |
360 | default: | 449 | default: |
361 | usb_drv_stall(EP_CONTROL, true, true); | 450 | usb_drv_stall(EP_CONTROL, true, true); |
362 | } | 451 | } |