summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-07-16 22:23:14 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-07-16 22:23:14 +0200
commit3c5ee9ac57cbac4050df1729a28ec39c60d303ff (patch)
treea404575003c20c30488965d783aee3d3d6212cd3
parente5de5e09c1ca6788d155393af0d906a9402ea7bc (diff)
downloadrockbox-3c5ee9ac57cbac4050df1729a28ec39c60d303ff.tar.gz
rockbox-3c5ee9ac57cbac4050df1729a28ec39c60d303ff.zip
hwstub: forgot file
Change-Id: Ib79f4ef89c734d7ba2fcbf648aadc346576e1c17
-rw-r--r--utils/hwstub/stub/main.c514
1 files changed, 514 insertions, 0 deletions
diff --git a/utils/hwstub/stub/main.c b/utils/hwstub/stub/main.c
new file mode 100644
index 0000000000..c3cc429949
--- /dev/null
+++ b/utils/hwstub/stub/main.c
@@ -0,0 +1,514 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2013 by Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "stddef.h"
22#include "protocol.h"
23#include "logf.h"
24#include "usb_ch9.h"
25#include "usb_drv.h"
26#include "memory.h"
27#include "target.h"
28
29extern unsigned char oc_codestart[];
30extern unsigned char oc_codeend[];
31extern unsigned char oc_stackstart[];
32extern unsigned char oc_stackend[];
33extern unsigned char oc_bufferstart[];
34extern unsigned char oc_bufferend[];
35
36#define oc_codesize ((size_t)(oc_codeend - oc_codestart))
37#define oc_stacksize ((size_t)(oc_stackend - oc_stackstart))
38#define oc_buffersize ((size_t)(oc_bufferend - oc_bufferstart))
39
40static bool g_exit = false;
41
42/**
43 *
44 * USB stack
45 *
46 */
47
48static struct usb_device_descriptor __attribute__((aligned(2)))
49 device_descriptor=
50{
51 .bLength = sizeof(struct usb_device_descriptor),
52 .bDescriptorType = USB_DT_DEVICE,
53 .bcdUSB = 0x0200,
54 .bDeviceClass = USB_CLASS_PER_INTERFACE,
55 .bDeviceSubClass = 0,
56 .bDeviceProtocol = 0,
57 .bMaxPacketSize0 = 64,
58 .idVendor = HWSTUB_USB_VID,
59 .idProduct = HWSTUB_USB_PID,
60 .bcdDevice = HWSTUB_VERSION_MAJOR << 8 | HWSTUB_VERSION_MINOR,
61 .iManufacturer = 1,
62 .iProduct = 2,
63 .iSerialNumber = 3,
64 .bNumConfigurations = 1
65};
66
67#define USB_MAX_CURRENT 200
68
69static struct usb_config_descriptor __attribute__((aligned(2)))
70 config_descriptor =
71{
72 .bLength = sizeof(struct usb_config_descriptor),
73 .bDescriptorType = USB_DT_CONFIG,
74 .wTotalLength = 0, /* will be filled in later */
75 .bNumInterfaces = 1,
76 .bConfigurationValue = 1,
77 .iConfiguration = 0,
78 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
79 .bMaxPower = (USB_MAX_CURRENT + 1) / 2, /* In 2mA units */
80};
81
82/* main interface */
83static struct usb_interface_descriptor __attribute__((aligned(2)))
84 interface_descriptor =
85{
86 .bLength = sizeof(struct usb_interface_descriptor),
87 .bDescriptorType = USB_DT_INTERFACE,
88 .bInterfaceNumber = 0,
89 .bAlternateSetting = 0,
90 .bNumEndpoints = 3,
91 .bInterfaceClass = HWSTUB_CLASS,
92 .bInterfaceSubClass = HWSTUB_SUBCLASS,
93 .bInterfaceProtocol = HWSTUB_PROTOCOL,
94 .iInterface = 4
95};
96
97
98static struct usb_endpoint_descriptor __attribute__((aligned(2)))
99 endpoint_descriptor =
100{
101 .bLength = sizeof(struct usb_endpoint_descriptor),
102 .bDescriptorType = USB_DT_ENDPOINT,
103 .bEndpointAddress = 0,
104 .bmAttributes = USB_ENDPOINT_XFER_BULK,
105 .wMaxPacketSize = 0,
106 .bInterval = 0
107};
108
109static const struct usb_string_descriptor __attribute__((aligned(2)))
110 usb_string_iManufacturer =
111{
112 24,
113 USB_DT_STRING,
114 {'R', 'o', 'c', 'k', 'b', 'o', 'x', '.', 'o', 'r', 'g'}
115};
116
117static const struct usb_string_descriptor __attribute__((aligned(2)))
118 usb_string_iProduct =
119{
120 52,
121 USB_DT_STRING,
122 {'R', 'o', 'c', 'k', 'b', 'o', 'x', ' ',
123 'h', 'a', 'r', 'd', 'w', 'a', 'r', 'e', ' ',
124 'e', 'm', 'u', 'l', 'a', 't', 'e', 'r'}
125};
126
127static struct usb_string_descriptor __attribute__((aligned(2)))
128 usb_string_iSerial =
129{
130 84,
131 USB_DT_STRING,
132 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
133 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
134 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
135 '0', '0', '0', '0', '0', '0', '0', '0'}
136};
137
138static struct usb_string_descriptor __attribute__((aligned(2)))
139 usb_string_iInterface =
140{
141 28,
142 USB_DT_STRING,
143 {'A', 'c', 'i', 'd', ' ',
144 '0' + (HWSTUB_VERSION_MAJOR >> 4), '0' + (HWSTUB_VERSION_MAJOR & 0xf), '.',
145 '0' + (HWSTUB_VERSION_MINOR >> 4), '0' + (HWSTUB_VERSION_MINOR & 0xf), '.',
146 '0' + (HWSTUB_VERSION_REV >> 4), '0' + (HWSTUB_VERSION_REV & 0xf) }
147};
148
149/* this is stringid #0: languages supported */
150static const struct usb_string_descriptor __attribute__((aligned(2)))
151 lang_descriptor =
152{
153 4,
154 USB_DT_STRING,
155 {0x0409} /* LANGID US English */
156};
157
158#define USB_NUM_STRINGS 5
159
160static const struct usb_string_descriptor* const usb_strings[USB_NUM_STRINGS] =
161{
162 &lang_descriptor,
163 &usb_string_iManufacturer,
164 &usb_string_iProduct,
165 &usb_string_iSerial,
166 &usb_string_iInterface
167};
168
169uint8_t *usb_buffer = oc_bufferstart;
170uint32_t usb_buffer_size = 0;
171
172#define EP_BULK 1
173#define EP_INT 2
174
175static void set_config(void)
176{
177 usb_drv_configure_endpoint(EP_BULK, USB_ENDPOINT_XFER_BULK);
178 usb_drv_configure_endpoint(EP_INT, USB_ENDPOINT_XFER_INT);
179}
180
181static void handle_std_dev_desc(struct usb_ctrlrequest *req)
182{
183 int size;
184 const void* ptr = NULL;
185 unsigned index = req->wValue & 0xff;
186
187 switch(req->wValue >> 8)
188 {
189 case USB_DT_DEVICE:
190 ptr = &device_descriptor;
191 size = sizeof(struct usb_device_descriptor);
192 break;
193 case USB_DT_OTHER_SPEED_CONFIG:
194 case USB_DT_CONFIG:
195 {
196 int max_packet_size;
197
198 /* config desc */
199 if((req->wValue >> 8) ==USB_DT_CONFIG)
200 {
201 max_packet_size = (usb_drv_port_speed() ? 512 : 64);
202 config_descriptor.bDescriptorType = USB_DT_CONFIG;
203 }
204 else
205 {
206 max_packet_size=(usb_drv_port_speed() ? 64 : 512);
207 config_descriptor.bDescriptorType = USB_DT_OTHER_SPEED_CONFIG;
208 }
209 size = sizeof(struct usb_config_descriptor);
210
211 /* interface */
212 memcpy(usb_buffer + size, (void *)&interface_descriptor,
213 sizeof(interface_descriptor));
214 size += sizeof(interface_descriptor);
215 /* endpoint 1: bulk out */
216 endpoint_descriptor.bEndpointAddress = EP_BULK | USB_DIR_OUT;
217 endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_BULK;
218 endpoint_descriptor.wMaxPacketSize = 512;
219 memcpy(usb_buffer + size, (void *)&endpoint_descriptor,
220 sizeof(endpoint_descriptor));
221 size += sizeof(endpoint_descriptor);
222 /* endpoint 2: bulk in */
223 endpoint_descriptor.bEndpointAddress = EP_BULK | USB_DIR_IN;
224 endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_BULK;
225 endpoint_descriptor.wMaxPacketSize = 512;
226 memcpy(usb_buffer + size, (void *)&endpoint_descriptor,
227 sizeof(endpoint_descriptor));
228 size += sizeof(endpoint_descriptor);
229 /* endpoint 3: int in */
230 endpoint_descriptor.bEndpointAddress = EP_INT | USB_DIR_IN;
231 endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_INT;
232 endpoint_descriptor.wMaxPacketSize = 1024;
233 memcpy(usb_buffer + size, (void *)&endpoint_descriptor,
234 sizeof(endpoint_descriptor));
235 size += sizeof(endpoint_descriptor);
236
237 /* fix config descriptor */
238 config_descriptor.bNumInterfaces = 1;
239 config_descriptor.wTotalLength = size;
240 memcpy(usb_buffer, (void *)&config_descriptor, sizeof(config_descriptor));
241
242 ptr = usb_buffer;
243 break;
244 }
245 case USB_DT_STRING:
246 if(index < USB_NUM_STRINGS)
247 {
248 size = usb_strings[index]->bLength;
249 ptr = usb_strings[index];
250 }
251 else
252 usb_drv_stall(EP_CONTROL, true, true);
253 break;
254 default:
255 break;
256 }
257
258 if(ptr)
259 {
260 int length = MIN(size, req->wLength);
261
262 if(ptr != usb_buffer)
263 memcpy(usb_buffer, ptr, length);
264
265 usb_drv_send(EP_CONTROL, usb_buffer, length);
266 usb_drv_recv(EP_CONTROL, NULL, 0);
267 }
268 else
269 usb_drv_stall(EP_CONTROL, true, true);
270}
271
272static void handle_std_dev_req(struct usb_ctrlrequest *req)
273{
274 switch(req->bRequest)
275 {
276 case USB_REQ_GET_CONFIGURATION:
277 usb_buffer[0] = 1;
278 usb_drv_send(EP_CONTROL, usb_buffer, 1);
279 usb_drv_recv(EP_CONTROL, NULL, 0);
280 break;
281 case USB_REQ_SET_CONFIGURATION:
282 usb_drv_send(EP_CONTROL, NULL, 0);
283 set_config();
284 break;
285 case USB_REQ_GET_DESCRIPTOR:
286 handle_std_dev_desc(req);
287 break;
288 case USB_REQ_SET_ADDRESS:
289 usb_drv_send(EP_CONTROL, NULL, 0);
290 usb_drv_set_address(req->wValue);
291 break;
292 case USB_REQ_GET_STATUS:
293 usb_buffer[0] = 0;
294 usb_buffer[1] = 0;
295 usb_drv_send(EP_CONTROL, usb_buffer, 2);
296 usb_drv_recv(EP_CONTROL, NULL, 0);
297 break;
298 default:
299 usb_drv_stall(EP_CONTROL, true, true);
300 }
301}
302
303static void handle_std_req(struct usb_ctrlrequest *req)
304{
305 switch(req->bRequestType & USB_RECIP_MASK)
306 {
307 case USB_RECIP_DEVICE:
308 return handle_std_dev_req(req);
309 default:
310 usb_drv_stall(EP_CONTROL, true, true);
311 }
312}
313
314struct usb_resp_info_version_t g_version =
315{
316 .major = HWSTUB_VERSION_MAJOR,
317 .minor = HWSTUB_VERSION_MINOR,
318 .revision = HWSTUB_VERSION_REV
319};
320
321struct usb_resp_info_layout_t g_layout;
322
323struct usb_resp_info_features_t g_features =
324{
325 .feature_mask = HWSTUB_FEATURE_LOG | HWSTUB_FEATURE_MEM |
326 HWSTUB_FEATURE_CALL | HWSTUB_FEATURE_JUMP
327};
328
329static void fill_layout_info(void)
330{
331 g_layout.oc_code_start = (uint32_t)oc_codestart;
332 g_layout.oc_code_size = oc_codesize;
333 g_layout.oc_stack_start = (uint32_t)oc_stackstart;
334 g_layout.oc_stack_size = oc_stacksize;
335 g_layout.oc_buffer_start = (uint32_t)oc_bufferstart;
336 g_layout.oc_buffer_size = oc_buffersize;
337}
338
339static void handle_get_info(struct usb_ctrlrequest *req)
340{
341 void *ptr = NULL;
342 int size = 0;
343 switch(req->wIndex)
344 {
345 case HWSTUB_INFO_VERSION:
346 ptr = &g_version;
347 size = sizeof(g_version);
348 break;
349 case HWSTUB_INFO_LAYOUT:
350 fill_layout_info();
351 ptr = &g_layout;
352 size = sizeof(g_layout);
353 break;
354 case HWSTUB_INFO_FEATURES:
355 ptr = &g_features;
356 size = sizeof(g_features);
357 break;
358 default:
359 size = target_get_info(req->wIndex, &ptr);
360 if(size < 0)
361 usb_drv_stall(EP_CONTROL, true, true);
362 }
363
364 if(ptr)
365 {
366 int length = MIN(size, req->wLength);
367
368 if(ptr != usb_buffer)
369 memcpy(usb_buffer, ptr, length);
370 usb_drv_send(EP_CONTROL, usb_buffer, length);
371 usb_drv_recv(EP_CONTROL, NULL, 0);
372 }
373}
374
375static void handle_get_log(struct usb_ctrlrequest *req)
376{
377 enable_logf(false);
378 int length = logf_readback(usb_buffer, MIN(req->wLength, usb_buffer_size));
379 usb_drv_send(EP_CONTROL, usb_buffer, length);
380 usb_drv_recv(EP_CONTROL, NULL, 0);
381 enable_logf(true);
382}
383
384static void handle_rw_mem(struct usb_ctrlrequest *req)
385{
386 uint32_t addr = req->wValue | req->wIndex << 16;
387 uint16_t length = req->wLength;
388
389 if(req->bRequestType & USB_DIR_IN)
390 {
391 memcpy(usb_buffer, (void *)addr, length);
392 asm volatile("nop" : : : "memory");
393 usb_drv_send(EP_CONTROL, usb_buffer, length);
394 usb_drv_recv(EP_CONTROL, NULL, 0);
395 }
396 else
397 {
398 int size = usb_drv_recv(EP_CONTROL, usb_buffer, length);
399 asm volatile("nop" : : : "memory");
400 if(size != length)
401 usb_drv_stall(EP_CONTROL, true, true);
402 else
403 {
404 memcpy((void *)addr, usb_buffer, length);
405 usb_drv_send(EP_CONTROL, NULL, 0);
406 }
407 }
408}
409
410static void handle_call_jump(struct usb_ctrlrequest *req)
411{
412 uint32_t addr = req->wValue | req->wIndex << 16;
413
414 if(req->bRequest == HWSTUB_CALL)
415 ((void (*)(void))addr)();
416 else
417 {
418 /* disconnect to make sure usb/dma won't interfere */
419 usb_drv_exit();
420 asm volatile("bx %0\n" : : "r" (addr) : "memory");
421 }
422}
423
424static void handle_atexit(struct usb_ctrlrequest *req)
425{
426 if(target_atexit(req->wIndex) < 0)
427 usb_drv_stall(EP_CONTROL, true, true);
428 else
429 usb_drv_send(EP_CONTROL, NULL, 0);
430}
431
432static void handle_exit(struct usb_ctrlrequest *req)
433{
434 (void)req;
435 usb_drv_send(EP_CONTROL, NULL, 0);
436 g_exit = true;
437}
438
439static void handle_class_dev_req(struct usb_ctrlrequest *req)
440{
441 switch(req->bRequest)
442 {
443 case HWSTUB_GET_INFO:
444 handle_get_info(req);
445 break;
446 case HWSTUB_GET_LOG:
447 handle_get_log(req);
448 break;
449 case HWSTUB_RW_MEM:
450 handle_rw_mem(req);
451 break;
452 case HWSTUB_CALL:
453 case HWSTUB_JUMP:
454 handle_call_jump(req);
455 break;
456 case HWSTUB_ATEXIT:
457 handle_atexit(req);
458 break;
459 case HWSTUB_EXIT:
460 handle_exit(req);
461 break;
462 default:
463 usb_drv_stall(EP_CONTROL, true, true);
464 }
465}
466
467static void handle_class_req(struct usb_ctrlrequest *req)
468{
469 switch(req->bRequestType & USB_RECIP_MASK)
470 {
471 case USB_RECIP_DEVICE:
472 return handle_class_dev_req(req);
473 default:
474 usb_drv_stall(EP_CONTROL, true, true);
475 }
476}
477
478/**
479 *
480 * Main
481 *
482 */
483
484void main(uint32_t arg)
485{
486 usb_buffer_size = oc_buffersize;
487
488 logf("hwstub %d.%d.%d\n", HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR,
489 HWSTUB_VERSION_REV);
490 logf("argument: 0x%08x\n", arg);
491
492 target_init();
493 usb_drv_init();
494
495 while(!g_exit)
496 {
497 struct usb_ctrlrequest req;
498 usb_drv_recv_setup(&req);
499
500 switch(req.bRequestType & USB_TYPE_MASK)
501 {
502 case USB_TYPE_STANDARD:
503 handle_std_req(&req);
504 break;
505 case USB_TYPE_CLASS:
506 handle_class_req(&req);
507 break;
508 default:
509 usb_drv_stall(EP_CONTROL, true, true);
510 }
511 }
512 usb_drv_exit();
513 target_exit();
514}