summaryrefslogtreecommitdiff
path: root/utils/hwstub
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
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')
-rw-r--r--utils/hwstub/hwstub_protocol.h113
-rw-r--r--utils/hwstub/lib/hwstub.c125
-rw-r--r--utils/hwstub/lib/hwstub.h8
-rw-r--r--utils/hwstub/stub/main.c219
-rw-r--r--utils/hwstub/tools/hwstub_shell.cpp17
5 files changed, 347 insertions, 135 deletions
diff --git a/utils/hwstub/hwstub_protocol.h b/utils/hwstub/hwstub_protocol.h
index 2c11025b1e..02c065cbe0 100644
--- a/utils/hwstub/hwstub_protocol.h
+++ b/utils/hwstub/hwstub_protocol.h
@@ -21,46 +21,46 @@
21#ifndef __HWSTUB_PROTOCOL__ 21#ifndef __HWSTUB_PROTOCOL__
22#define __HWSTUB_PROTOCOL__ 22#define __HWSTUB_PROTOCOL__
23 23
24#define HWSTUB_CLASS 0xff 24/**
25#define HWSTUB_SUBCLASS 0xac 25 * HWStub protocol version
26#define HWSTUB_PROTOCOL 0x1d 26 */
27 27
28#define HWSTUB_VERSION_MAJOR 3 28#define HWSTUB_VERSION_MAJOR 4
29#define HWSTUB_VERSION_MINOR 0 29#define HWSTUB_VERSION_MINOR 0
30#define HWSTUB_VERSION_REV 1 30#define HWSTUB_VERSION_REV 0
31 31
32#define HWSTUB_VERSION__(maj,min,rev) #maj"."#min"."#rev 32#define HWSTUB_VERSION__(maj,min,rev) #maj"."#min"."#rev
33#define HWSTUB_VERSION_(maj,min,rev) HWSTUB_VERSION__(maj,min,rev) 33#define HWSTUB_VERSION_(maj,min,rev) HWSTUB_VERSION__(maj,min,rev)
34#define HWSTUB_VERSION HWSTUB_VERSION_(HWSTUB_VERSION_MAJOR,HWSTUB_VERSION_MINOR,HWSTUB_VERSION_REV) 34#define HWSTUB_VERSION HWSTUB_VERSION_(HWSTUB_VERSION_MAJOR,HWSTUB_VERSION_MINOR,HWSTUB_VERSION_REV)
35 35
36/**
37 * A device can use any VID:PID but in case hwstub is in full control of the
38 * device, the preferred VID:PID is the following.
39 */
40
36#define HWSTUB_USB_VID 0xfee1 41#define HWSTUB_USB_VID 0xfee1
37#define HWSTUB_USB_PID 0xdead 42#define HWSTUB_USB_PID 0xdead
38 43
39/** 44/**
40 * Control commands 45 * The device class should be per interface and the hwstub interface must use
41 * 46 * the following class, subclass and protocol.
42 * These commands are sent to the device, using the standard bRequest field
43 * of the SETUP packet. This is to take advantage of both wIndex and wValue
44 * although it would have been more correct to send them to the interface.
45 */ 47 */
46 48
47/* list of commands */ 49#define HWSTUB_CLASS 0xff
48#define HWSTUB_GET_LOG 0 /* optional */ 50#define HWSTUB_SUBCLASS 0x57
49#define HWSTUB_RW_MEM 1 /* optional */ 51#define HWSTUB_PROTOCOL 0x0b
50#define HWSTUB_CALL 2 /* optional */
51#define HWSTUB_JUMP 3 /* optional */
52 52
53/** 53/**
54 * Descriptors can be retrieve using configuration descriptor or individually 54 * Descriptors can be retrieved using configuration descriptor or individually
55 * using the standard GetDescriptor request on the interface. 55 * using the standard GetDescriptor request on the interface.
56 */ 56 */
57 57
58/* list of possible information */ 58#define HWSTUB_DT_VERSION 0x41 /* mandatory */
59#define HWSTUB_DT_VERSION 0x41 /* mandatory */ 59#define HWSTUB_DT_LAYOUT 0x42 /* mandatory */
60#define HWSTUB_DT_LAYOUT 0x42 /* mandatory */ 60#define HWSTUB_DT_TARGET 0x43 /* mandatory */
61#define HWSTUB_DT_TARGET 0x43 /* mandatory */ 61#define HWSTUB_DT_STMP 0x44 /* optional */
62#define HWSTUB_DT_STMP 0x44 /* optional */ 62#define HWSTUB_DT_PP 0x45 /* optional */
63#define HWSTUB_DT_PP 0x45 /* optional */ 63#define HWSTUB_DT_DEVICE 0x46 /* optional */
64 64
65struct hwstub_version_desc_t 65struct hwstub_version_desc_t
66{ 66{
@@ -120,25 +120,70 @@ struct hwstub_target_desc_t
120 char bName[58]; 120 char bName[58];
121} __attribute__((packed)); 121} __attribute__((packed));
122 122
123struct hwstub_device_desc_t
124{
125 uint8_t bLength;
126 uint8_t bDescriptorType;
127 /* Give the bRequest value for */
128} __attribute__((packed));
129
130/**
131 * Control commands
132 *
133 * These commands are sent to the interface, using the standard bRequest field
134 * of the SETUP packet. The wIndex contains the interface number. The wValue
135 * contains an ID which is used for requests requiring several transfers.
136 */
137
138#define HWSTUB_GET_LOG 0x40
139#define HWSTUB_READ 0x41
140#define HWSTUB_READ2 0x42
141#define HWSTUB_WRITE 0x43
142#define HWSTUB_EXEC 0x44
143
123/** 144/**
124 * HWSTUB_GET_LOG: 145 * HWSTUB_GET_LOG:
125 * The log is returned as part of the control transfer. 146 * The log is returned as part of the control transfer.
126 */ 147 */
127 148
128/** 149/**
129 * HWSTUB_RW_MEM: 150 * HWSTUB_READ and HWSTUB_READ2:
130 * The 32-bit address is split into two parts. 151 * Read a range of memory. The request works in two steps: first the host
131 * The low 16-bit are stored in wValue and the upper 152 * sends HWSTUB_READ with the parameters (address, length) and then
132 * 16-bit are stored in wIndex. Depending on the transfer direction, 153 * a HWSTUB_READ2 to retrieve the buffer. Both requests must use the same
133 * the transfer is either a read or a write. 154 * ID in wValue, otherwise the second request will be STALLed.
134 * The read/write on the device are guaranteed to be 16-bit/32-bit when 155 */
135 * possible, making it suitable to read/write registers. */ 156
157struct hwstub_read_req_t
158{
159 uint32_t dAddress;
160} __attribute__((packed));
161
162/**
163 * HWSTUB_WRITE
164 * Write a range of memory. The payload starts with the following header, everything
165 * which follows is data.
166 */
167struct hwstub_write_req_t
168{
169 uint32_t dAddress;
170} __attribute__((packed));
136 171
137/** 172/**
138 * HWSTUB_{CALL,JUMP}: 173 * HWSTUB_EXEC:
139 * The 32-bit address is split into two parts. 174 * Execute code at an address. Several options are available regarding ARM vs Thumb,
140 * The low 16-bit are stored in wValue and the upper 175 * jump vs call.
141 * 16-bit are stored in wIndex. Depending on the transfer direction, 176 */
142 * the transfer is either a read or a write. */ 177
178#define HWSTUB_EXEC_ARM (0 << 0) /* target code is ARM */
179#define HWSTUB_EXEC_THUMB (1 << 0) /* target code is Thumb */
180#define HWSTUB_EXEC_JUMP (0 << 1) /* branch, code will never turn */
181#define HWSTUB_EXEC_CALL (1 << 1) /* call and expect return */
182
183struct hwstub_exec_req_t
184{
185 uint32_t dAddress;
186 uint16_t bmFlags;
187};
143 188
144#endif /* __HWSTUB_PROTOCOL__ */ 189#endif /* __HWSTUB_PROTOCOL__ */
diff --git a/utils/hwstub/lib/hwstub.c b/utils/hwstub/lib/hwstub.c
index 67a797ddfe..9f46159026 100644
--- a/utils/hwstub/lib/hwstub.c
+++ b/utils/hwstub/lib/hwstub.c
@@ -30,26 +30,78 @@ struct hwstub_device_t
30{ 30{
31 libusb_device_handle *handle; 31 libusb_device_handle *handle;
32 int intf; 32 int intf;
33 int bulk_in; 33 unsigned buf_sz;
34 int bulk_out; 34 uint16_t id;
35 int int_in;
36}; 35};
37 36
37int hwstub_probe(libusb_device *dev)
38{
39 struct libusb_config_descriptor *config = NULL;
40 int ret = -1;
41 if(libusb_get_config_descriptor(dev, 0, &config) != 0)
42 goto Lend;
43 /* search hwstub interface */
44 for(unsigned i = 0; i < config->bNumInterfaces; i++)
45 {
46 /* hwstub interface has only one setting */
47 if(config->interface[i].num_altsetting != 1)
48 continue;
49 const struct libusb_interface_descriptor *intf = &config->interface[i].altsetting[0];
50 /* check class/subclass/protocol */
51 if(intf->bInterfaceClass != HWSTUB_CLASS ||
52 intf->bInterfaceSubClass != HWSTUB_SUBCLASS ||
53 intf->bInterfaceProtocol != HWSTUB_PROTOCOL)
54 continue;
55 /* found ! */
56 ret = i;
57 break;
58 }
59Lend:
60 if(config)
61 libusb_free_config_descriptor(config);
62 return ret;
63}
64
65ssize_t hwstub_get_device_list(libusb_context *ctx, libusb_device ***list)
66{
67 libusb_device **great_list;
68 ssize_t great_cnt = libusb_get_device_list(ctx, &great_list);
69 if(great_cnt < 0)
70 return great_cnt;
71 /* allocate a list (size at least one NULL entry at the end) */
72 libusb_device **mylist = malloc(sizeof(libusb_device *) * (great_cnt + 1));
73 memset(mylist, 0, sizeof(libusb_device *) * (great_cnt + 1));
74 /* list hwstub devices */
75 ssize_t cnt = 0;
76 for(int i = 0; i < great_cnt; i++)
77 if(hwstub_probe(great_list[i]) >= 0)
78 {
79 libusb_ref_device(great_list[i]);
80 mylist[cnt++] = great_list[i];
81 }
82 /* free old list */
83 libusb_free_device_list(great_list, 1);
84 /* return */
85 *list = mylist;
86 return cnt;
87}
88
38struct hwstub_device_t *hwstub_open(libusb_device_handle *handle) 89struct hwstub_device_t *hwstub_open(libusb_device_handle *handle)
39{ 90{
40 struct hwstub_device_t *dev = malloc(sizeof(struct hwstub_device_t)); 91 struct hwstub_device_t *dev = malloc(sizeof(struct hwstub_device_t));
41 memset(dev, 0, sizeof(struct hwstub_device_t)); 92 memset(dev, 0, sizeof(struct hwstub_device_t));
42 dev->handle = handle; 93 dev->handle = handle;
94 dev->intf = -1;
95 dev->buf_sz = 1024; /* default size */
43 libusb_device *mydev = libusb_get_device(dev->handle); 96 libusb_device *mydev = libusb_get_device(dev->handle);
44 97 dev->intf = hwstub_probe(mydev);
45 int config_id; 98 if(dev->intf == -1)
46 libusb_get_configuration(dev->handle, &config_id);
47 struct libusb_device_descriptor dev_desc;
48 libusb_get_device_descriptor(mydev, &dev_desc);
49 if(dev_desc.bDeviceClass != HWSTUB_CLASS ||
50 dev_desc.bDeviceSubClass != HWSTUB_SUBCLASS ||
51 dev_desc.bDeviceProtocol != HWSTUB_PROTOCOL)
52 goto Lerr; 99 goto Lerr;
100 /* try to get actual buffer size */
101 struct hwstub_layout_desc_t layout;
102 int sz = hwstub_get_desc(dev, HWSTUB_DT_LAYOUT, &layout, sizeof(layout));
103 if(sz == (int)sizeof(layout))
104 dev->buf_sz = layout->dBufferSize;
53 return dev; 105 return dev;
54 106
55Lerr: 107Lerr:
@@ -66,49 +118,60 @@ int hwstub_release(struct hwstub_device_t *dev)
66int hwstub_get_desc(struct hwstub_device_t *dev, uint16_t desc, void *info, size_t sz) 118int hwstub_get_desc(struct hwstub_device_t *dev, uint16_t desc, void *info, size_t sz)
67{ 119{
68 return libusb_control_transfer(dev->handle, 120 return libusb_control_transfer(dev->handle,
69 LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, 121 LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN,
70 LIBUSB_REQUEST_GET_DESCRIPTOR, desc << 8, 0, info, sz, 1000); 122 LIBUSB_REQUEST_GET_DESCRIPTOR, desc << 8, dev->intf, info, sz, 1000);
71} 123}
72 124
73int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz) 125int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz)
74{ 126{
75 return libusb_control_transfer(dev->handle, 127 return libusb_control_transfer(dev->handle,
76 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, 128 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN,
77 HWSTUB_GET_LOG, 0, 0, buf, sz, 1000); 129 HWSTUB_GET_LOG, 0, dev->intf, buf, sz, 1000);
130}
131
132static int _hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz)
133{
134 struct hwstub_read_req_t read;
135 read.dAddress = addr;
136 int size = libusb_control_transfer(dev->handle,
137 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
138 HWSTUB_READ, dev->id, dev->intf, &read, sizeof(read), 1000);
139 if(size != (int)sizeof(read))
140 return -1;
141 return libusb_control_transfer(dev->handle,
142 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN,
143 HWSTUB_READ2, dev->id++, dev->intf, &read, sizeof(read), 1000);
144}
145
146int hwstub_write(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz)
147{
78} 148}
79 149
80int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz) 150int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz)
81{ 151{
82 size_t tot_sz = 0; 152 return read ? hwstub_read(dev, addr, buf, sz) : hwstub_write(dev, addr, buf, sz);
83 while(sz)
84 {
85 uint16_t xfer = MIN(1 * 1024, sz);
86 int ret = libusb_control_transfer(dev->handle,
87 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
88 (read ? LIBUSB_ENDPOINT_IN : LIBUSB_ENDPOINT_OUT),
89 HWSTUB_RW_MEM, addr & 0xffff, addr >> 16, buf, xfer, 1000);
90 if(ret != xfer)
91 return ret;
92 sz -= xfer;
93 addr += xfer;
94 buf += xfer;
95 tot_sz += xfer;
96 }
97 return tot_sz;
98} 153}
99 154
100int hwstub_call(struct hwstub_device_t *dev, uint32_t addr) 155int hwstub_call(struct hwstub_device_t *dev, uint32_t addr)
101{ 156{
157#if 0
102 return libusb_control_transfer(dev->handle, 158 return libusb_control_transfer(dev->handle,
103 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | 159 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
104 LIBUSB_ENDPOINT_OUT, HWSTUB_CALL, addr & 0xffff, addr >> 16, NULL, 0, 160 LIBUSB_ENDPOINT_OUT, HWSTUB_CALL, addr & 0xffff, addr >> 16, NULL, 0,
105 1000); 161 1000);
162#else
163 return -1;
164#endif
106} 165}
107 166
108int hwstub_jump(struct hwstub_device_t *dev, uint32_t addr) 167int hwstub_jump(struct hwstub_device_t *dev, uint32_t addr)
109{ 168{
169#if 0
110 return libusb_control_transfer(dev->handle, 170 return libusb_control_transfer(dev->handle,
111 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | 171 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
112 LIBUSB_ENDPOINT_OUT, HWSTUB_JUMP, addr & 0xffff, addr >> 16, NULL, 0, 172 LIBUSB_ENDPOINT_OUT, HWSTUB_JUMP, addr & 0xffff, addr >> 16, NULL, 0,
113 1000); 173 1000);
174#else
175 return -1;
176#endif
114} 177}
diff --git a/utils/hwstub/lib/hwstub.h b/utils/hwstub/lib/hwstub.h
index 69fdc63988..1599f6508b 100644
--- a/utils/hwstub/lib/hwstub.h
+++ b/utils/hwstub/lib/hwstub.h
@@ -36,6 +36,12 @@ extern "C" {
36 36
37struct hwstub_device_t; 37struct hwstub_device_t;
38 38
39/* Returns hwstub interface, or -1 if none was found */
40int hwstub_probe(libusb_device *dev);
41/* Helper function which returns a list of all hwstub devices found. The caller
42 * must unref all of them when done, possibly using libusb_free_device_list().
43 * Return number of devices or <0 on error */
44ssize_t hwstub_get_device_list(libusb_context *ctx, libusb_device ***list);
39/* Returns NULL on error */ 45/* Returns NULL on error */
40struct hwstub_device_t *hwstub_open(libusb_device_handle *handle); 46struct hwstub_device_t *hwstub_open(libusb_device_handle *handle);
41/* Returns 0 on success. Does *NOT* close the usb handle */ 47/* Returns 0 on success. Does *NOT* close the usb handle */
@@ -46,6 +52,8 @@ int hwstub_get_desc(struct hwstub_device_t *dev, uint16_t desc, void *info, size
46/* Returns number of bytes filled */ 52/* Returns number of bytes filled */
47int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz); 53int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz);
48/* Returns number of bytes written/read or <0 on error */ 54/* Returns number of bytes written/read or <0 on error */
55int hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz);
56int hwstub_write(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz);
49int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz); 57int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz);
50/* Returns <0 on error */ 58/* Returns <0 on error */
51int hwstub_call(struct hwstub_device_t *dev, uint32_t addr); 59int hwstub_call(struct hwstub_device_t *dev, uint32_t addr);
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 }
diff --git a/utils/hwstub/tools/hwstub_shell.cpp b/utils/hwstub/tools/hwstub_shell.cpp
index d0fcdfabc2..a10a1dad4e 100644
--- a/utils/hwstub/tools/hwstub_shell.cpp
+++ b/utils/hwstub/tools/hwstub_shell.cpp
@@ -754,15 +754,22 @@ int main(int argc, char **argv)
754 754
755 // look for device 755 // look for device
756 if(!g_quiet) 756 if(!g_quiet)
757 printf("Looking for device %#04x:%#04x...\n", HWSTUB_USB_VID, HWSTUB_USB_PID); 757 printf("Looking for hwstub device ...\n");
758 758 // open first device
759 libusb_device_handle *handle = libusb_open_device_with_vid_pid(ctx, 759 libusb_device **list;
760 HWSTUB_USB_VID, HWSTUB_USB_PID); 760 ssize_t cnt = hwstub_get_device_list(ctx, &list);
761 if(handle == NULL) 761 if(cnt <= 0)
762 { 762 {
763 printf("No device found\n"); 763 printf("No device found\n");
764 return 1; 764 return 1;
765 } 765 }
766 libusb_device_handle *handle;
767 if(libusb_open(list[0], &handle) != 0)
768 {
769 printf("Cannot open device\n");
770 return 1;
771 }
772 libusb_free_device_list(list, 1);
766 773
767 // admin stuff 774 // admin stuff
768 libusb_device *mydev = libusb_get_device(handle); 775 libusb_device *mydev = libusb_get_device(handle);