summaryrefslogtreecommitdiff
path: root/utils/hwstub/lib/hwstub.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/hwstub/lib/hwstub.c')
-rw-r--r--utils/hwstub/lib/hwstub.c125
1 files changed, 94 insertions, 31 deletions
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}