diff options
Diffstat (limited to 'utils/hwstub/lib')
-rw-r--r-- | utils/hwstub/lib/hwstub.c | 125 | ||||
-rw-r--r-- | utils/hwstub/lib/hwstub.h | 8 |
2 files changed, 102 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 | ||
37 | int 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 | } | ||
59 | Lend: | ||
60 | if(config) | ||
61 | libusb_free_config_descriptor(config); | ||
62 | return ret; | ||
63 | } | ||
64 | |||
65 | ssize_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 | |||
38 | struct hwstub_device_t *hwstub_open(libusb_device_handle *handle) | 89 | struct 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 | ||
55 | Lerr: | 107 | Lerr: |
@@ -66,49 +118,60 @@ int hwstub_release(struct hwstub_device_t *dev) | |||
66 | int hwstub_get_desc(struct hwstub_device_t *dev, uint16_t desc, void *info, size_t sz) | 118 | int 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 | ||
73 | int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz) | 125 | int 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 | |||
132 | static 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 | |||
146 | int hwstub_write(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz) | ||
147 | { | ||
78 | } | 148 | } |
79 | 149 | ||
80 | int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz) | 150 | int 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 | ||
100 | int hwstub_call(struct hwstub_device_t *dev, uint32_t addr) | 155 | int 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 | ||
108 | int hwstub_jump(struct hwstub_device_t *dev, uint32_t addr) | 167 | int 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 | ||
37 | struct hwstub_device_t; | 37 | struct hwstub_device_t; |
38 | 38 | ||
39 | /* Returns hwstub interface, or -1 if none was found */ | ||
40 | int 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 */ | ||
44 | ssize_t hwstub_get_device_list(libusb_context *ctx, libusb_device ***list); | ||
39 | /* Returns NULL on error */ | 45 | /* Returns NULL on error */ |
40 | struct hwstub_device_t *hwstub_open(libusb_device_handle *handle); | 46 | struct 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 */ |
47 | int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz); | 53 | int 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 */ |
55 | int hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz); | ||
56 | int hwstub_write(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz); | ||
49 | int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz); | 57 | int 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 */ |
51 | int hwstub_call(struct hwstub_device_t *dev, uint32_t addr); | 59 | int hwstub_call(struct hwstub_device_t *dev, uint32_t addr); |