1 /* HM-CFG-USB libusb-driver
3 * Copyright (c) 2013 Michael Gernoth <michael@gernoth.net>
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
32 #include <libusb-1.0/libusb.h>
37 #define USB_TIMEOUT 10000
39 #define ID_VENDOR 0x1b1f
40 #define ID_PRODUCT 0xc00f
43 #define ASYNC_SIZE 0x0040
44 #define ASYNC_INTERVAL 32
54 /* Not in all libusb-1.0 versions, so we have to roll our own :-( */
55 static char * usb_strerror(int e
)
57 static char unknerr
[256];
63 return "Input/output error";
64 case LIBUSB_ERROR_INVALID_PARAM
:
65 return "Invalid parameter";
66 case LIBUSB_ERROR_ACCESS
:
67 return "Access denied (insufficient permissions)";
68 case LIBUSB_ERROR_NO_DEVICE
:
69 return "No such device (it may have been disconnected)";
70 case LIBUSB_ERROR_NOT_FOUND
:
71 return "Entity not found";
72 case LIBUSB_ERROR_BUSY
:
73 return "Resource busy";
74 case LIBUSB_ERROR_TIMEOUT
:
75 return "Operation timed out";
76 case LIBUSB_ERROR_OVERFLOW
:
78 case LIBUSB_ERROR_PIPE
:
80 case LIBUSB_ERROR_INTERRUPTED
:
81 return "System call interrupted (perhaps due to signal)";
82 case LIBUSB_ERROR_NO_MEM
:
83 return "Insufficient memory";
84 case LIBUSB_ERROR_NOT_SUPPORTED
:
85 return "Operation not supported or unimplemented on this platform";
86 case LIBUSB_ERROR_OTHER
:
89 snprintf(unknerr
, sizeof(unknerr
), "Unknown error code %d / 0x%02x", e
, e
);
93 static libusb_device_handle
*hmcfgusb_find() {
94 libusb_device_handle
*devh
= NULL
;
100 cnt
= libusb_get_device_list(NULL
, &list
);
102 fprintf(stderr
, "Can't get USB device list: %d\n", (int)cnt
);
106 for (i
= 0; i
< cnt
; i
++){
107 struct libusb_device_descriptor desc
;
109 err
= libusb_get_device_descriptor(list
[i
], &desc
);
113 if ((desc
.idVendor
== ID_VENDOR
) && (desc
.idProduct
== ID_PRODUCT
)) {
114 libusb_device
*dev
= list
[i
];
116 err
= libusb_open(dev
, &devh
);
118 fprintf(stderr
, "Can't open device: %s\n", usb_strerror(err
));
122 err
= libusb_detach_kernel_driver(devh
, INTERFACE
);
123 if ((err
!= 0) && (err
!= LIBUSB_ERROR_NOT_FOUND
)) {
124 fprintf(stderr
, "Can't detach kernel driver: %s\n", usb_strerror(err
));
128 err
= libusb_claim_interface(devh
, INTERFACE
);
130 fprintf(stderr
, "Can't claim interface: %s\n", usb_strerror(err
));
142 int hmcfgusb_send(struct hmcfgusb_dev
*usbdev
, unsigned char* send_data
, int len
, int done
)
148 hexdump(send_data
, len
, "USB < ");
149 err
= libusb_interrupt_transfer(usbdev
->usb_devh
, EP_OUT
, send_data
, len
, &cnt
, USB_TIMEOUT
);
151 fprintf(stderr
, "Can't send data: %s\n", usb_strerror(err
));
156 err
= libusb_interrupt_transfer(usbdev
->usb_devh
, EP_OUT
, send_data
, 0, &cnt
, USB_TIMEOUT
);
158 fprintf(stderr
, "Can't send data: %s\n", usb_strerror(err
));
166 static struct libusb_transfer
*hmcfgusb_prepare_int(libusb_device_handle
*devh
, libusb_transfer_cb_fn cb
, void *data
)
168 unsigned char *data_buf
;
169 struct libusb_transfer
*transfer
;
172 data_buf
= malloc(ASYNC_SIZE
);
174 fprintf(stderr
, "Can't allocate memory for data-buffer!\n");
178 transfer
= libusb_alloc_transfer(0);
180 fprintf(stderr
, "Can't allocate memory for usb-transfer!\n");
185 libusb_fill_interrupt_transfer(transfer
, devh
, EP_IN
,
186 data_buf
, ASYNC_SIZE
, cb
, data
, USB_TIMEOUT
);
188 transfer
->flags
= LIBUSB_TRANSFER_SHORT_NOT_OK
| LIBUSB_TRANSFER_FREE_BUFFER
;
190 err
= libusb_submit_transfer(transfer
);
192 fprintf(stderr
, "Can't submit transfer: %s\n", usb_strerror(err
));
193 libusb_free_transfer(transfer
);
200 struct hmcfgusb_cb_data
{
201 struct hmcfgusb_dev
*dev
;
206 static void LIBUSB_CALL
hmcfgusb_interrupt(struct libusb_transfer
*transfer
)
209 struct hmcfgusb_cb_data
*cb_data
;
211 cb_data
= transfer
->user_data
;
213 if (transfer
->status
!= LIBUSB_TRANSFER_COMPLETED
) {
214 if (transfer
->status
!= LIBUSB_TRANSFER_TIMED_OUT
) {
215 fprintf(stderr
, "Interrupt transfer not completed: %d!\n", transfer
->status
);
218 if (cb_data
&& cb_data
->dev
&& cb_data
->dev
->transfer
) {
219 libusb_free_transfer(cb_data
->dev
->transfer
);
220 cb_data
->dev
->transfer
= NULL
;
225 if (cb_data
&& cb_data
->cb
) {
227 hexdump(transfer
->buffer
, transfer
->actual_length
, "USB > ");
228 cb_data
->cb(transfer
->buffer
, transfer
->actual_length
, cb_data
->data
);
230 hexdump(transfer
->buffer
, transfer
->actual_length
, "> ");
234 err
= libusb_submit_transfer(transfer
);
236 fprintf(stderr
, "Can't re-submit transfer: %s\n", usb_strerror(err
));
237 libusb_free_transfer(transfer
);
241 struct hmcfgusb_dev
*hmcfgusb_init(hmcfgusb_cb_fn cb
, void *data
)
243 libusb_device_handle
*devh
= NULL
;
244 const struct libusb_pollfd
**usb_pfd
= NULL
;
245 struct hmcfgusb_dev
*dev
= NULL
;
246 struct hmcfgusb_cb_data
*cb_data
= NULL
;
250 err
= libusb_init(NULL
);
252 fprintf(stderr
, "Can't initialize libusb: %s\n", usb_strerror(err
));
256 devh
= hmcfgusb_find();
258 fprintf(stderr
, "Can't find/open hmcfgusb!\n");
262 dev
= malloc(sizeof(struct hmcfgusb_dev
));
264 perror("Can't allocate memory for hmcfgusb_dev");
268 memset(dev
, 0, sizeof(struct hmcfgusb_dev
));
269 dev
->usb_devh
= devh
;
271 cb_data
= malloc(sizeof(struct hmcfgusb_cb_data
));
273 perror("Can't allocate memory for hmcfgusb_cb_data");
277 memset(cb_data
, 0, sizeof(struct hmcfgusb_cb_data
));
281 cb_data
->data
= data
;
283 dev
->transfer
= hmcfgusb_prepare_int(devh
, hmcfgusb_interrupt
, cb_data
);
284 if (!dev
->transfer
) {
285 fprintf(stderr
, "Can't prepare async device io!\n");
289 usb_pfd
= libusb_get_pollfds(NULL
);
291 fprintf(stderr
, "Can't get FDset from libusb!\n");
297 for(i
= 0; usb_pfd
[i
]; i
++)
300 dev
->pfd
= malloc(dev
->n_usb_pfd
* sizeof(struct pollfd
));
302 perror("Can't allocate memory for poll-fds");
306 memset(dev
->pfd
, 0, dev
->n_usb_pfd
* sizeof(struct pollfd
));
308 for (i
= 0; i
< dev
->n_usb_pfd
; i
++) {
309 dev
->pfd
[i
].fd
= usb_pfd
[i
]->fd
;
310 dev
->pfd
[i
].events
= usb_pfd
[i
]->events
;
311 dev
->pfd
[i
].revents
= 0;
316 dev
->n_pfd
= dev
->n_usb_pfd
;
323 int hmcfgusb_add_pfd(struct hmcfgusb_dev
*dev
, int fd
, short events
)
326 dev
->pfd
= realloc(dev
->pfd
, dev
->n_pfd
* sizeof(struct pollfd
));
328 perror("Can't realloc poll-fds");
332 dev
->pfd
[dev
->n_pfd
-1].fd
= fd
;
333 dev
->pfd
[dev
->n_pfd
-1].events
= events
;
334 dev
->pfd
[dev
->n_pfd
-1].revents
= 0;
339 int hmcfgusb_poll(struct hmcfgusb_dev
*dev
, int timeout
)
350 memset(&tv
, 0, sizeof(tv
));
351 err
= libusb_get_next_timeout(NULL
, &tv
);
353 fprintf(stderr
, "libusb_get_next_timeout: %s\n", usb_strerror(err
));
356 } else if (err
== 0) {
357 /* No pending timeout or a sane platform */
360 if ((tv
.tv_sec
== 0) && (tv
.tv_usec
== 0)) {
366 for (i
= 0; i
< dev
->n_pfd
; i
++) {
367 dev
->pfd
[i
].revents
= 0;
370 n
= poll(dev
->pfd
, dev
->n_pfd
, tv
.tv_sec
* 1000);
378 for (fd_n
= 0; fd_n
< dev
->n_pfd
; fd_n
++) {
379 if (dev
->pfd
[fd_n
].revents
) {
380 if (fd_n
< dev
->n_usb_pfd
) {
385 return dev
->pfd
[fd_n
].fd
;
393 memset(&tv
, 0, sizeof(tv
));
394 err
= libusb_handle_events_timeout_completed(NULL
, &tv
, NULL
);
396 fprintf(stderr
, "libusb_handle_events_timeout_completed: %s\n", usb_strerror(err
));
404 fprintf(stderr
, "closing device-connection due to error %d\n", quit
);
411 void hmcfgusb_close(struct hmcfgusb_dev
*dev
)
416 libusb_cancel_transfer(dev
->transfer
);
419 err
= libusb_release_interface(dev
->usb_devh
, INTERFACE
);
421 fprintf(stderr
, "Can't release interface: %s\n", usb_strerror(err
));
424 libusb_close(dev
->usb_devh
);
431 void hmcfgusb_set_debug(int d
)