diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2014-09-08 11:07:42 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2014-09-08 11:07:42 +0200 |
commit | d815c26e8fad1562e7c4d175bc4dec2567f0fe88 (patch) | |
tree | 20be1319e7e0f8856653a3c057d3ba78b9270411 | |
parent | 6cc057f180acfa90d673f03709801388ec415dee (diff) | |
download | rockbox-d815c26e8fad1562e7c4d175bc4dec2567f0fe88.tar.gz rockbox-d815c26e8fad1562e7c4d175bc4dec2567f0fe88.zip |
hwstub: implement jump/call in stub
Change-Id: I876fa012c5ae1509e57f5816a8ed31dc69d62ca0
-rw-r--r-- | utils/hwstub/stub/main.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/utils/hwstub/stub/main.c b/utils/hwstub/stub/main.c index e31c5d1b8b..8139615239 100644 --- a/utils/hwstub/stub/main.c +++ b/utils/hwstub/stub/main.c @@ -19,6 +19,7 @@ * ****************************************************************************/ #include "stddef.h" +#include "config.h" #include "protocol.h" #include "logf.h" #include "usb_ch9.h" @@ -402,17 +403,35 @@ static void handle_exec(struct usb_ctrlrequest *req) struct hwstub_exec_req_t *exec = (void *)usb_buffer; if(size != sizeof(struct hwstub_exec_req_t)) return usb_drv_stall(EP_CONTROL, true, true); - usb_drv_send(EP_CONTROL, NULL, 0); -#if 0 - if(req->bRequest == HWSTUB_CALL) - ((void (*)(void))addr)(); + uint32_t addr = exec->dAddress; + if(exec->bmFlags & HWSTUB_EXEC_THUMB) + addr |= 1; + else + addr &= ~1; + + if(exec->bmFlags & HWSTUB_EXEC_CALL) + { +#ifdef CPU_ARM + /* in case of call, respond after return */ + asm volatile("blx %0\n" : : "r"(addr) : "memory"); + usb_drv_send(EP_CONTROL, NULL, 0); +#else +#warning call is unsupported on this platform + usb_drv_stall(EP_CONTROL, true, true); +#endif + } else { - /* disconnect to make sure usb/dma won't interfere */ + /* in case of jump, respond immediately and disconnect usb */ + usb_drv_send(EP_CONTROL, NULL, 0); usb_drv_exit(); +#ifdef CPU_ARM asm volatile("bx %0\n" : : "r" (addr) : "memory"); - } +#else +#warning jump is unsupported on this platform + usb_drv_stall(EP_CONTROL, true, true); #endif + } } static void handle_class_intf_req(struct usb_ctrlrequest *req) |