Neale Pickett
·
2024-02-24
usb.c
1#include <libusb.h>
2#include <stdio.h>
3#include <poll.h>
4#include <stdint.h>
5#include <string.h>
6#include <sys/select.h>
7#include "usb.h"
8#include "alsa.h"
9#include "log.h"
10#include "dump.h"
11
12#define MAX_PFDS 20
13
14struct device {
15 uint16_t product_id;
16 uint8_t interface_number;
17 uint8_t ep_in;
18 uint8_t ep_out;
19 uint8_t ep_in2;
20 uint8_t interface_number2;
21};
22const struct device devices[] = {
23 { 0xb102, 1, 0x83, 0x04, 0x0, 0 }, // Steel
24 { 0xb105, 1, 0x81, 0x03, 0x0, 0 }, // MP3e2
25 { 0xb120, 1, 0x82, 0x03, 0x0, 0 }, // Hercules MP3 LE / Glow
26 { 0xb107, 5, 0x83, 0x03, 0x0, 0 }, // Hercules Mk4
27 { 0xb100, 1, 0x86, 0x06, 0x0, 0 }, // Hercules Mk2
28 { 0xb109, 5, 0x83, 0x03, 0x84, 0}, // 4-Mx
29 { 0xb10c, 5, 0x83, 0x03, 0x84, 0}, // Hercules DJ 4Set
30 { 0xb10d, 5, 0x83, 0x03, 0x84, 0}, // Hercules DJ 4Set, second variant(?)
31 { 0, 0, 0, 0 }
32};
33
34static const int MANUFACTURER_HERCULES = 0x6f8;
35static libusb_context *context = NULL;
36static struct libusb_device_handle *usb_dev = NULL;
37static const struct device *dev_info;
38const struct libusb_pollfd **usb_fds = NULL;
39struct libusb_transfer *xfer_in;
40struct libusb_transfer *xfer_in2;
41
42static int writes_pending = 0;
43static int reads_pending = 0;
44
45void
46usb_debug_msg(char *action, int ep, uint8_t data[], size_t datalen)
47{
48#ifdef DEBUG
49 fprintf(stderr, "%s on ep%02x:", action, ep);
50 for (int i = 0; i < datalen; i += 1) {
51 fprintf(stderr, " %02x", data[i]);
52 }
53 fprintf(stderr, "\n");
54#endif
55}
56
57void usb_xfer_done(struct libusb_transfer *xfer);
58void usb_xfer_done_additional(struct libusb_transfer *xfer);
59
60void
61usb_interrupting()
62{
63 libusb_cancel_transfer(xfer_in);
64 if (dev_info->ep_in2 != 0x0) {
65 libusb_cancel_transfer(xfer_in2);
66 }
67}
68static void
69usb_initiate_transfer()
70{
71 static const int buffsize = 256;
72 unsigned char *buf;
73
74 buf = (unsigned char *)malloc(buffsize);
75
76 // Tell libusb we want to know about bulk transfers
77 xfer_in = libusb_alloc_transfer(0);
78 //timeout if in 1000 milliseconds it hasn't been sent
79 xfer_in->timeout=1000;
80 xfer_in->flags |=LIBUSB_TRANSFER_ADD_ZERO_PACKET;
81 libusb_fill_bulk_transfer(xfer_in, usb_dev, dev_info->ep_in, buf, buffsize, usb_xfer_done, NULL, 0);
82 libusb_submit_transfer(xfer_in);
83 reads_pending += 1;
84}
85
86static void
87usb_initiate_transfer_additional()
88{
89 static const int buffsize = 256;
90 unsigned char *buf;
91
92 buf = (unsigned char *)malloc(buffsize);
93
94 // Tell libusb we want to know about bulk transfers
95 xfer_in2 = libusb_alloc_transfer(0);
96 //timeout if in 1000 milliseconds it hasn't been sent
97 xfer_in2->timeout=1000;
98 xfer_in2->flags |=LIBUSB_TRANSFER_ADD_ZERO_PACKET;
99 libusb_fill_bulk_transfer(xfer_in2, usb_dev, dev_info->ep_in2, buf, buffsize, usb_xfer_done_additional, NULL, 0);
100 libusb_submit_transfer(xfer_in2);
101}
102
103void LIBUSB_CALL
104usb_xfer_done(struct libusb_transfer *xfer)
105{
106 uint8_t *data = xfer->buffer;
107 int datalen = xfer->actual_length;
108 reads_pending -= 1;
109 if ( xfer->status == LIBUSB_TRANSFER_COMPLETED ) {
110 usb_debug_msg("Receiving", dev_info->ep_in, data, datalen);
111 alsa_write(data, datalen);
112 }
113 if ( xfer->status == LIBUSB_TRANSFER_COMPLETED ) {
114 usb_initiate_transfer();
115 } else if ( xfer->status != LIBUSB_TRANSFER_CANCELLED ) {
116 fatal("Stopping EP_IN, because of status %d.\nSoftware needs restarting", xfer->status);
117 }
118
119 free(data);
120 libusb_free_transfer(xfer);
121}
122void LIBUSB_CALL
123usb_xfer_done_additional(struct libusb_transfer *xfer)
124{
125 if ( xfer->status == LIBUSB_TRANSFER_COMPLETED ) {
126 // We don't need to use the information of this call, but it is needed that we
127 // poll this, or else it hangs and doesn't receive more data.
128 usb_debug_msg("Receiving", dev_info->ep_in2, xfer->buffer, xfer->actual_length);
129 }
130
131 if ( xfer->status == LIBUSB_TRANSFER_COMPLETED ) {
132 usb_initiate_transfer_additional();
133 } else if ( xfer->status != LIBUSB_TRANSFER_CANCELLED ) {
134 fatal("Stopping EP_IN2, because of status %d\nSoftware needs restarting", xfer->status);
135 }
136
137 free(xfer->buffer);
138 libusb_free_transfer(xfer);
139}
140
141int
142usb_setup(char *name, size_t namelen)
143{
144 int ret;
145 ret=libusb_init(&context);
146 if (ret < 0) {
147 fatal("ERROR: %s\n%s", libusb_error_name(ret), libusb_strerror(ret));
148 return -1;
149 }
150 //----------------------------------------------------------------------------
151 // Enable debug
152 //----------------------------------------------------------------------------
153#ifdef DEBUG
154 libusb_set_debug(context, LIBUSB_LOG_LEVEL_WARNING);
155#endif
156
157 if (libusb_pollfds_handle_timeouts(context) == 0) {
158 fatal("I'm too dumb to handle events on such an old system.");
159 return -1;
160 }
161 //----------------------------------------------------------------------------
162 // Get device list
163 //----------------------------------------------------------------------------
164 struct libusb_device_descriptor founddesc = {0};
165 {
166 libusb_device **devs;
167 ssize_t count; //holding number of devices in list
168 printf("Locating Hercules USB devices...\n(You can also use the lsusb command to locate this information)\n");
169 count = libusb_get_device_list(context, &devs);
170 if ( count < 0) {
171 fatal("Error getting the device list: %s\n%s", libusb_error_name(count), libusb_strerror(count));
172 return -1;
173 } else if (count == 0) {
174 warn("Seems that the USB device list is empty. Is the controller connected? ");
175 }
176 size_t idx;
177 for (idx = 0; idx < count; idx+=1) {
178 libusb_device *device = devs[idx];
179 struct libusb_device_descriptor listdesc = {0};
180
181 ret = libusb_get_device_descriptor(device, &listdesc);
182 if ( ret != 0) {
183 warn("Could not get descriptor for device index %ld: %s\n%s",
184 (long int)idx, libusb_error_name(count), libusb_strerror(count));
185 } else if (listdesc.idVendor == MANUFACTURER_HERCULES) {
186 printf("Vendor:Device = %04x:%04x\n", listdesc.idVendor, listdesc.idProduct);
187 founddesc = listdesc;
188 }
189 }
190
191 libusb_free_device_list(devs, 1); //free the list, unref the devices in it
192 //----------------------------------------------------------------------------
193 }
194 for (dev_info = devices; dev_info->product_id; dev_info += 1) {
195 usb_dev = libusb_open_device_with_vid_pid(context, MANUFACTURER_HERCULES, dev_info->product_id);
196 if (usb_dev) {
197 break;
198 } else if (dev_info->product_id == founddesc.idProduct) {
199 fatal("The controller %04x:%04x could not be opened.\n"
200 "Check that you have enough permissions over /dev/bus/usb/ subfolder elements.\n."
201 "You might need to create an udev rule at /etc/udev/rules.d/", founddesc.idVendor,founddesc.idProduct);
202 }
203 }
204 if (! usb_dev) {
205 if (founddesc.idVendor != MANUFACTURER_HERCULES) {
206 fatal("Couldn't find a Hercules controller.");
207 }
208 else {
209 fatal("The controller %04x:%04x is not supported.", founddesc.idVendor,founddesc.idProduct);
210 }
211 return -1;
212 }
213
214 // Figure out what it's called
215 {
216 struct libusb_device_descriptor ddesc;
217 name[0]='\0';
218 libusb_get_device_descriptor(libusb_get_device(usb_dev), &ddesc);
219 ret = libusb_get_string_descriptor_ascii(usb_dev, ddesc.iManufacturer, (unsigned char *)name, namelen);
220 if (ret > 0) {
221 char *p = name + ret;
222
223 *p = ' ';
224 p += 1;
225 ret = libusb_get_string_descriptor_ascii(usb_dev, ddesc.iProduct, (unsigned char *)p, namelen - ret - 1);
226 }
227 if (ret < 0) {
228 warn("I can't figure out what to call this thing.");
229 }
230 printf("Opened [%s]\n", name);
231 }
232
233 ret = libusb_claim_interface(usb_dev, dev_info->interface_number);
234 if (ret == 0 ) {
235 if (dev_info->ep_in2 != 0x0) {
236 libusb_claim_interface(usb_dev, dev_info->interface_number2);
237 usb_initiate_transfer_additional();
238 }
239 usb_initiate_transfer();
240 return 0;
241 } else {
242 if (ret == LIBUSB_ERROR_BUSY) {
243 fatal("Couldn't claim interface %d. Already in use?", dev_info->interface_number);
244 } else {
245 fatal("Couldn't claim interface %d. %s\n%s", dev_info->interface_number,
246 libusb_error_name(ret), libusb_strerror(ret));
247 }
248 return -1;
249 }
250}
251
252void
253usb_finish() {
254 int ret;
255 if (usb_dev) {
256 ret = libusb_release_interface(usb_dev, dev_info->interface_number);
257 if (ret != 0 && ret != LIBUSB_ERROR_NOT_FOUND) {
258 warn("Couldn't release interface %d. %s\n%s", dev_info->interface_number,
259 libusb_error_name(ret), libusb_strerror(ret));
260 }
261 libusb_close(usb_dev);
262 usb_dev=NULL;
263 }
264 libusb_exit(context);
265}
266
267void
268usb_fd_setup(int *nfds, fd_set *rfds, fd_set *wfds)
269{
270 usb_fds = libusb_get_pollfds(context);
271 if (usb_fds == NULL) {
272 warn("could not get the filedescriptors! This is unexpected");
273 }
274
275 int i;
276 for (i = 0; usb_fds[i]; i += 1) {
277 const struct libusb_pollfd *ufd = usb_fds[i];
278
279 if (ufd->fd > *nfds) {
280 *nfds = ufd->fd;
281 }
282 if (ufd->events & POLLIN) {
283 FD_SET(ufd->fd, rfds);
284 }
285 if (ufd->events & POLLOUT) {
286 FD_SET(ufd->fd, wfds);
287 }
288 }
289
290 if (reads_pending + writes_pending > 100) {
291 warn("%d(r)+%d(w) = %d outstanding USB transactions!", reads_pending, writes_pending, reads_pending + writes_pending);
292 }
293}
294
295void
296usb_check_fds(fd_set *rfds, fd_set *wfds)
297{
298 if (usb_fds == NULL) {
299 return;
300 }
301
302 int i;
303 for (i = 0; usb_fds[i]; i += 1) {
304 int fd = usb_fds[i]->fd;
305
306 if (FD_ISSET(fd, rfds) || FD_ISSET(fd, wfds)) {
307 libusb_handle_events(context);
308 return;
309 }
310 }
311
312#if LIBUSB_API_VERSION >= 0x01000104
313 libusb_free_pollfds(usb_fds);
314 usb_fds = NULL;
315#endif // LIBUSB_API_VERSION >= 0x01000104
316}
317
318
319void LIBUSB_CALL
320usb_write_done(struct libusb_transfer *xfer)
321{
322 if ( xfer->status == LIBUSB_TRANSFER_TIMED_OUT ) {
323 warn("Send timed out");
324 } else if ( xfer->status && xfer->status != LIBUSB_TRANSFER_CANCELLED) {
325 warn("USB Write status %d", xfer->status);
326 }
327 writes_pending -= 1;
328 usb_debug_msg("Sent", dev_info->ep_out, xfer->buffer, xfer->actual_length);
329 free(xfer->buffer);
330 libusb_free_transfer(xfer);
331}
332
333void
334usb_write(uint8_t *data, size_t datalen)
335{
336 struct libusb_transfer *xfer;
337 unsigned char *buf;
338
339 writes_pending += 1;
340 xfer = libusb_alloc_transfer(0);
341 //timeout if in 1000 milliseconds it hasn't been sent
342 xfer->timeout=1000;
343 buf = (unsigned char *)malloc(datalen);
344 memcpy(buf, data, datalen);
345 libusb_fill_bulk_transfer(xfer, usb_dev, dev_info->ep_out, buf, datalen, usb_write_done, NULL, 0);
346 libusb_submit_transfer(xfer);
347
348 usb_debug_msg("Preparing to send", dev_info->ep_out, data, datalen);
349}