From 813afd1296fd1ead02d4292705831e10dd3fcf5d Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Wed, 29 May 2013 16:21:55 +0200 Subject: [PATCH] cleanup on error/exit --- hmcfgusb.c | 39 ++++++++++++++++++++++++++++++++++----- hmcfgusb.h | 1 + hmland.c | 2 +- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/hmcfgusb.c b/hmcfgusb.c index 9b00c84..955a65b 100644 --- a/hmcfgusb.c +++ b/hmcfgusb.c @@ -34,7 +34,7 @@ #include "hexdump.h" #include "hmcfgusb.h" -#define USB_TIMEOUT 10000 +#define USB_TIMEOUT 10000 #define ID_VENDOR 0x1b1f #define ID_PRODUCT 0xc00f @@ -46,6 +46,8 @@ #define EP_OUT 0x02 #define EP_IN 0x83 +#define INTERFACE 0 + static int quit = 0; /* Not in all libusb-1.0 versions, so we have to roll our own :-( */ @@ -116,13 +118,13 @@ static libusb_device_handle *hmcfgusb_find() { return NULL; } - err = libusb_detach_kernel_driver(devh, 0); + err = libusb_detach_kernel_driver(devh, INTERFACE); if ((err != 0) && (err != LIBUSB_ERROR_NOT_FOUND)) { fprintf(stderr, "Can't detach kernel driver: %s\n", usb_strerror(err)); return NULL; } - err = libusb_claim_interface(devh, 0); + err = libusb_claim_interface(devh, INTERFACE); if ((err != 0)) { fprintf(stderr, "Can't claim interface: %s\n", usb_strerror(err)); return NULL; @@ -185,7 +187,7 @@ static struct libusb_transfer *hmcfgusb_prepare_int(libusb_device_handle *devh, libusb_fill_interrupt_transfer(transfer, devh, EP_IN, data_buf, ASYNC_SIZE, cb, data, USB_TIMEOUT); - transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK; + transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK | LIBUSB_TRANSFER_FREE_BUFFER; err = libusb_submit_transfer(transfer); if (err != 0) { @@ -199,6 +201,7 @@ static struct libusb_transfer *hmcfgusb_prepare_int(libusb_device_handle *devh, } struct hmcfgusb_cb_data { + struct hmcfgusb_dev *dev; hmcfgusb_cb_fn cb; void *data; }; @@ -208,14 +211,20 @@ static void LIBUSB_CALL hmcfgusb_interrupt(struct libusb_transfer *transfer) int err; struct hmcfgusb_cb_data *cb_data; + cb_data = transfer->user_data; + if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { if (transfer->status != LIBUSB_TRANSFER_TIMED_OUT) { fprintf(stderr, "Interrupt transfer not completed: %d!\n", transfer->status); quit = EIO; + + if (cb_data && cb_data->dev && cb_data->dev->transfer) { + libusb_free_transfer(cb_data->dev->transfer); + cb_data->dev->transfer = NULL; + } return; } } else { - cb_data = transfer->user_data; if (cb_data && cb_data->cb) { cb_data->cb(transfer->buffer, transfer->actual_length, cb_data->data); } else { @@ -269,6 +278,7 @@ struct hmcfgusb_dev *hmcfgusb_init(hmcfgusb_cb_fn cb, void *data) memset(cb_data, 0, sizeof(struct hmcfgusb_cb_data)); + cb_data->dev = dev; cb_data->cb = cb; cb_data->data = data; @@ -392,3 +402,22 @@ int hmcfgusb_poll(struct hmcfgusb_dev *dev, int timeout) return -1; } + +void hmcfgusb_close(struct hmcfgusb_dev *dev) +{ + int err; + + if (dev->transfer) { + libusb_cancel_transfer(dev->transfer); + } + + err = libusb_release_interface(dev->usb_devh, INTERFACE); + if ((err != 0)) { + fprintf(stderr, "Can't release interface: %s\n", usb_strerror(err)); + } + + libusb_close(dev->usb_devh); + free(dev); + + libusb_exit(NULL); +} diff --git a/hmcfgusb.h b/hmcfgusb.h index 98b5085..41e7e93 100644 --- a/hmcfgusb.h +++ b/hmcfgusb.h @@ -35,3 +35,4 @@ int hmcfgusb_send(struct hmcfgusb_dev *usbdev, unsigned char* send_data, int len struct hmcfgusb_dev *hmcfgusb_init(hmcfgusb_cb_fn cb, void *data); int hmcfgusb_add_pfd(struct hmcfgusb_dev *dev, int fd, short events); int hmcfgusb_poll(struct hmcfgusb_dev *dev, int timeout); +void hmcfgusb_close(struct hmcfgusb_dev *dev); diff --git a/hmland.c b/hmland.c index 75d4e14..3366c8b 100644 --- a/hmland.c +++ b/hmland.c @@ -216,7 +216,7 @@ int main(int argc, char **argv) } } - libusb_close(NULL); + hmcfgusb_close(dev); return EXIT_SUCCESS; } -- 2.39.2