summaryrefslogtreecommitdiff
path: root/utils/hwstub/stub/main.c
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2014-05-25 16:06:31 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2014-09-07 17:45:10 +0200
commit12ce7fc2cce5531723ea7d141df80142891989d7 (patch)
treedc4e3320f8ed0932265b3c917448a83f7dcecafe /utils/hwstub/stub/main.c
parent1dc1a9310e8a078a633dd90def13103f80e01ce7 (diff)
downloadrockbox-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/main.c')
-rw-r--r--utils/hwstub/stub/main.c219
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
48static struct usb_device_descriptor __attribute__((aligned(2))) 48static 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
69static struct usb_config_descriptor __attribute__((aligned(2))) 68static 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
82static const struct usb_string_descriptor __attribute__((aligned(2))) 80#define USB_HWSTUB_INTF 0
83 usb_string_iManufacturer = 81
82static 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
95static 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
90static const struct usb_string_descriptor __attribute__((aligned(2))) 102static 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
111static 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 */
101static const struct usb_string_descriptor __attribute__((aligned(2))) 119static 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
109static struct hwstub_version_desc_t __attribute__((aligned(2))) 126static 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
119static struct hwstub_layout_desc_t __attribute__((aligned(2))) 135static 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
136uint8_t *usb_buffer = oc_bufferstart; 152uint8_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
280static 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
320static 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
274static void handle_std_req(struct usb_ctrlrequest *req) 336static 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
294static void handle_rw_mem(struct usb_ctrlrequest *req) 358static 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
320static void handle_call_jump(struct usb_ctrlrequest *req) 387static 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
399static 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
334static void handle_class_dev_req(struct usb_ctrlrequest *req) 419static 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 }