1 /* HM-CFG-USB libusb-driver
3 * Copyright (c) 2013-16 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
33 #include <libusb-1.0/libusb.h>
35 /* Workaround for old libusb-1.0 */
38 #define libusb_handle_events_timeout_completed(ctx, tv, x) libusb_handle_events_timeout(ctx, tv)
44 #define USB_TIMEOUT 10000
46 #define ID_VENDOR 0x1b1f
47 #define ID_PRODUCT 0xc00f
48 #define ID_PRODUCT_BL 0xc010
51 #define ASYNC_SIZE 0x0040
52 #define ASYNC_INTERVAL 32
61 static int libusb_initialized
= 0;
63 /* Not in all libusb-1.0 versions, so we have to roll our own :-( */
64 static char * usb_strerror(int e
)
66 static char unknerr
[256];
72 return "Input/output error";
73 case LIBUSB_ERROR_INVALID_PARAM
:
74 return "Invalid parameter";
75 case LIBUSB_ERROR_ACCESS
:
76 return "Access denied (insufficient permissions)";
77 case LIBUSB_ERROR_NO_DEVICE
:
78 return "No such device (it may have been disconnected)";
79 case LIBUSB_ERROR_NOT_FOUND
:
80 return "Entity not found";
81 case LIBUSB_ERROR_BUSY
:
82 return "Resource busy";
83 case LIBUSB_ERROR_TIMEOUT
:
84 return "Operation timed out";
85 case LIBUSB_ERROR_OVERFLOW
:
87 case LIBUSB_ERROR_PIPE
:
89 case LIBUSB_ERROR_INTERRUPTED
:
90 return "System call interrupted (perhaps due to signal)";
91 case LIBUSB_ERROR_NO_MEM
:
92 return "Insufficient memory";
93 case LIBUSB_ERROR_NOT_SUPPORTED
:
94 return "Operation not supported or unimplemented on this platform";
95 case LIBUSB_ERROR_OTHER
:
98 snprintf(unknerr
, sizeof(unknerr
), "Unknown error code %d / 0x%02x", e
, e
);
102 static char * usb_str_transfer_status(int e
)
104 static char unknerr
[256];
107 case LIBUSB_TRANSFER_COMPLETED
:
108 return "Transfer completed";
109 case LIBUSB_TRANSFER_ERROR
:
110 return "Transfer error";
111 case LIBUSB_TRANSFER_TIMED_OUT
:
112 return "Transfer timed out";
113 case LIBUSB_TRANSFER_CANCELLED
:
114 return "Transfer cancelled";
115 case LIBUSB_TRANSFER_STALL
:
117 case LIBUSB_TRANSFER_OVERFLOW
:
118 return "Transfer overflow";
120 snprintf(unknerr
, sizeof(unknerr
), "Unknown transfer status %d / 0x%02x", e
, e
);
124 static libusb_device_handle
*hmcfgusb_find(int vid
, int pid
, char *serial
) {
125 libusb_device_handle
*devh
= NULL
;
126 libusb_device
**list
;
131 cnt
= libusb_get_device_list(NULL
, &list
);
133 fprintf(stderr
, "Can't get USB device list: %d\n", (int)cnt
);
137 for (i
= 0; i
< cnt
; i
++){
138 struct libusb_device_descriptor desc
;
140 err
= libusb_get_device_descriptor(list
[i
], &desc
);
144 if ((desc
.idVendor
== vid
) && (desc
.idProduct
== pid
)) {
145 libusb_device
*dev
= list
[i
];
147 err
= libusb_open(dev
, &devh
);
149 fprintf(stderr
, "Can't open device: %s\n", usb_strerror(err
));
150 libusb_free_device_list(list
, 1);
155 if (desc
.iSerialNumber
> 0) {
156 uint8_t devSerial
[256];
157 err
= libusb_get_string_descriptor_ascii(devh
, desc
.iSerialNumber
, devSerial
, sizeof(devSerial
));
159 fprintf(stderr
, "Can't read serial-number: %s\n", usb_strerror(err
));
161 libusb_free_device_list(list
, 1);
164 if (strcmp((char*)devSerial
, (char*)serial
)) {
174 err
= libusb_detach_kernel_driver(devh
, INTERFACE
);
175 if ((err
!= 0) && (err
!= LIBUSB_ERROR_NOT_FOUND
)) {
176 fprintf(stderr
, "Can't detach kernel driver: %s\n", usb_strerror(err
));
178 libusb_free_device_list(list
, 1);
182 err
= libusb_claim_interface(devh
, INTERFACE
);
184 fprintf(stderr
, "Can't claim interface: %s\n", usb_strerror(err
));
186 libusb_free_device_list(list
, 1);
190 libusb_free_device_list(list
, 0);
196 libusb_free_device_list(list
, 1);
200 int hmcfgusb_send_null_frame(struct hmcfgusb_dev
*usbdev
, int silent
)
204 unsigned char out
[0x40];
206 memset(out
, 0, sizeof(out
));
208 err
= libusb_interrupt_transfer(usbdev
->usb_devh
, EP_OUT
, out
, 0, &cnt
, USB_TIMEOUT
);
209 if (err
&& (!silent
)) {
210 fprintf(stderr
, "Can't send null frame: %s\n", usb_strerror(err
));
217 int hmcfgusb_send(struct hmcfgusb_dev
*usbdev
, unsigned char* send_data
, int len
, int done
)
221 struct timeval tv_start
, tv_end
;
225 hexdump(send_data
, len
, "USB < ");
228 gettimeofday(&tv_start
, NULL
);
230 err
= libusb_interrupt_transfer(usbdev
->usb_devh
, EP_OUT
, send_data
, len
, &cnt
, USB_TIMEOUT
);
232 fprintf(stderr
, "Can't send data: %s\n", usb_strerror(err
));
237 if (!hmcfgusb_send_null_frame(usbdev
, 0)) {
242 gettimeofday(&tv_end
, NULL
);
243 msec
= ((tv_end
.tv_sec
-tv_start
.tv_sec
)*1000)+((tv_end
.tv_usec
-tv_start
.tv_usec
)/1000);
246 fprintf(stderr
, "usb-transfer took more than 100ms (%dms), this may lead to timing problems!\n", msec
);
248 fprintf(stderr
, "usb-transfer took %dms!\n", msec
);
254 static struct libusb_transfer
*hmcfgusb_prepare_int(libusb_device_handle
*devh
, libusb_transfer_cb_fn cb
, void *data
, int in_size
)
256 unsigned char *data_buf
;
257 struct libusb_transfer
*transfer
;
260 data_buf
= malloc(in_size
);
262 fprintf(stderr
, "Can't allocate memory for data-buffer!\n");
266 transfer
= libusb_alloc_transfer(0);
268 fprintf(stderr
, "Can't allocate memory for usb-transfer!\n");
273 libusb_fill_interrupt_transfer(transfer
, devh
, EP_IN
,
274 data_buf
, in_size
, cb
, data
, USB_TIMEOUT
);
276 transfer
->flags
= LIBUSB_TRANSFER_FREE_BUFFER
;
278 err
= libusb_submit_transfer(transfer
);
280 fprintf(stderr
, "Can't submit transfer: %s\n", usb_strerror(err
));
281 libusb_free_transfer(transfer
);
288 struct hmcfgusb_cb_data
{
289 struct hmcfgusb_dev
*dev
;
294 static void LIBUSB_CALL
hmcfgusb_interrupt(struct libusb_transfer
*transfer
)
297 struct hmcfgusb_cb_data
*cb_data
;
299 cb_data
= transfer
->user_data
;
301 if (transfer
->status
!= LIBUSB_TRANSFER_COMPLETED
) {
302 if (transfer
->status
!= LIBUSB_TRANSFER_TIMED_OUT
) {
303 if (transfer
->status
!= LIBUSB_TRANSFER_CANCELLED
)
304 fprintf(stderr
, "Interrupt transfer not completed: %s!\n", usb_str_transfer_status(transfer
->status
));
310 if (cb_data
&& cb_data
->cb
) {
312 hexdump(transfer
->buffer
, transfer
->actual_length
, "USB > ");
314 if (!cb_data
->cb(transfer
->buffer
, transfer
->actual_length
, cb_data
->data
)) {
319 hexdump(transfer
->buffer
, transfer
->actual_length
, "> ");
323 err
= libusb_submit_transfer(transfer
);
325 fprintf(stderr
, "Can't re-submit transfer: %s\n", usb_strerror(err
));
332 libusb_free_transfer(transfer
);
334 if (cb_data
->dev
&& cb_data
->dev
->transfer
) {
335 cb_data
->dev
->transfer
= NULL
;
341 struct hmcfgusb_dev
*hmcfgusb_init(hmcfgusb_cb_fn cb
, void *data
, char *serial
)
343 libusb_device_handle
*devh
= NULL
;
344 const struct libusb_pollfd
**usb_pfd
= NULL
;
345 struct hmcfgusb_dev
*dev
= NULL
;
346 struct hmcfgusb_cb_data
*cb_data
= NULL
;
351 if (!libusb_initialized
) {
352 err
= libusb_init(NULL
);
354 fprintf(stderr
, "Can't initialize libusb: %s\n", usb_strerror(err
));
358 libusb_initialized
= 1;
360 devh
= hmcfgusb_find(ID_VENDOR
, ID_PRODUCT
, serial
);
362 devh
= hmcfgusb_find(ID_VENDOR
, ID_PRODUCT_BL
, serial
);
365 fprintf(stderr
, "Can't find/open HM-CFG-USB with serial %s!\n", serial
);
367 fprintf(stderr
, "Can't find/open HM-CFG-USB!\n");
369 #ifdef NEED_LIBUSB_EXIT
377 dev
= malloc(sizeof(struct hmcfgusb_dev
));
379 perror("Can't allocate memory for hmcfgusb_dev");
381 #ifdef NEED_LIBUSB_EXIT
387 memset(dev
, 0, sizeof(struct hmcfgusb_dev
));
388 dev
->usb_devh
= devh
;
389 dev
->bootloader
= bootloader
;
390 dev
->opened_at
= time(NULL
);
392 cb_data
= malloc(sizeof(struct hmcfgusb_cb_data
));
394 perror("Can't allocate memory for hmcfgusb_cb_data");
397 #ifdef NEED_LIBUSB_EXIT
403 memset(cb_data
, 0, sizeof(struct hmcfgusb_cb_data
));
407 cb_data
->data
= data
;
409 dev
->transfer
= hmcfgusb_prepare_int(devh
, hmcfgusb_interrupt
, cb_data
, ASYNC_SIZE
);
411 if (!dev
->transfer
) {
412 fprintf(stderr
, "Can't prepare async device io!\n");
416 #ifdef NEED_LIBUSB_EXIT
422 usb_pfd
= libusb_get_pollfds(NULL
);
424 fprintf(stderr
, "Can't get FDset from libusb!\n");
425 libusb_cancel_transfer(dev
->transfer
);
426 libusb_handle_events(NULL
);
430 #ifdef NEED_LIBUSB_EXIT
437 for(i
= 0; usb_pfd
[i
]; i
++)
440 dev
->pfd
= malloc(dev
->n_usb_pfd
* sizeof(struct pollfd
));
442 perror("Can't allocate memory for poll-fds");
443 libusb_cancel_transfer(dev
->transfer
);
444 libusb_handle_events(NULL
);
448 #ifdef NEED_LIBUSB_EXIT
454 memset(dev
->pfd
, 0, dev
->n_usb_pfd
* sizeof(struct pollfd
));
456 for (i
= 0; i
< dev
->n_usb_pfd
; i
++) {
457 dev
->pfd
[i
].fd
= usb_pfd
[i
]->fd
;
458 dev
->pfd
[i
].events
= usb_pfd
[i
]->events
;
459 dev
->pfd
[i
].revents
= 0;
464 dev
->n_pfd
= dev
->n_usb_pfd
;
471 int hmcfgusb_add_pfd(struct hmcfgusb_dev
*dev
, int fd
, short events
)
474 dev
->pfd
= realloc(dev
->pfd
, dev
->n_pfd
* sizeof(struct pollfd
));
476 perror("Can't realloc poll-fds");
480 dev
->pfd
[dev
->n_pfd
-1].fd
= fd
;
481 dev
->pfd
[dev
->n_pfd
-1].events
= events
;
482 dev
->pfd
[dev
->n_pfd
-1].revents
= 0;
487 int hmcfgusb_poll(struct hmcfgusb_dev
*dev
, int timeout
)
499 memset(&tv
, 0, sizeof(tv
));
500 err
= libusb_get_next_timeout(NULL
, &tv
);
502 fprintf(stderr
, "libusb_get_next_timeout: %s\n", usb_strerror(err
));
505 } else if (err
== 0) {
506 /* No pending timeout or a sane platform */
508 if ((tv
.tv_sec
== 0) && (tv
.tv_usec
== 0)) {
510 } else if ((tv
.tv_sec
* 1000) < timeout
) {
511 timeout
= tv
.tv_sec
* 1000;
516 for (i
= 0; i
< dev
->n_pfd
; i
++) {
517 dev
->pfd
[i
].revents
= 0;
520 n
= poll(dev
->pfd
, dev
->n_pfd
, timeout
);
529 for (fd_n
= 0; fd_n
< dev
->n_pfd
; fd_n
++) {
530 if (dev
->pfd
[fd_n
].revents
) {
531 if (fd_n
< dev
->n_usb_pfd
) {
536 return dev
->pfd
[fd_n
].fd
;
544 memset(&tv
, 0, sizeof(tv
));
545 err
= libusb_handle_events_timeout_completed(NULL
, &tv
, NULL
);
547 fprintf(stderr
, "libusb_handle_events_timeout_completed: %s\n", usb_strerror(err
));
555 fprintf(stderr
, "closing device-connection due to error %d\n", quit
);
565 void hmcfgusb_enter_bootloader(struct hmcfgusb_dev
*dev
)
567 uint8_t out
[ASYNC_SIZE
];
569 if (dev
->bootloader
) {
570 fprintf(stderr
, "request for bootloader mode, but device already in bootloader!\n");
574 memset(out
, 0, sizeof(out
));
576 hmcfgusb_send(dev
, out
, sizeof(out
), 1);
581 void hmcfgusb_leave_bootloader(struct hmcfgusb_dev
*dev
)
583 uint8_t out
[ASYNC_SIZE
];
585 if (!dev
->bootloader
) {
586 fprintf(stderr
, "request for leaving bootloader mode, but device already in normal mode!\n");
590 memset(out
, 0, sizeof(out
));
592 hmcfgusb_send(dev
, out
, sizeof(out
), 1);
597 void hmcfgusb_close(struct hmcfgusb_dev
*dev
)
602 libusb_cancel_transfer(dev
->transfer
);
603 libusb_handle_events(NULL
);
606 err
= libusb_release_interface(dev
->usb_devh
, INTERFACE
);
608 fprintf(stderr
, "Can't release interface: %s\n", usb_strerror(err
));
611 libusb_close(dev
->usb_devh
);
612 #ifdef NEED_LIBUSB_EXIT
619 void hmcfgusb_exit(void)
621 if (libusb_initialized
) {
623 libusb_initialized
= 0;
627 void hmcfgusb_set_debug(int d
)