X-Git-Url: https://git.ao2.it/libam7xxx.git/blobdiff_plain/9929ba27d2c28ef364ecdd7b27120f0fe7000a8c..2f9894ec66b5b4d67db7670dcd8bd721a16b4e43:/examples/am7xxx-modeswitch.c?ds=sidebyside diff --git a/examples/am7xxx-modeswitch.c b/examples/am7xxx-modeswitch.c index 9942d81..c304515 100644 --- a/examples/am7xxx-modeswitch.c +++ b/examples/am7xxx-modeswitch.c @@ -1,10 +1,10 @@ /* am7xxx-modeswitch - a simple usb-modeswitch for am7xxx devices * - * Copyright (C) 2012 Antonio Ospite + * Copyright (C) 2012-2014 Antonio Ospite * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or + * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -17,6 +17,7 @@ */ #include +#include #include #include @@ -28,53 +29,86 @@ static unsigned char switch_command[] = "\x55\x53\x42\x43\x08\x70\x52\x89\x00\x00\x00\x00\x00\x00" - "\x0c\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; + "\x10\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; int main(void) { int ret; - int transferred; - libusb_device_handle *usb_device = NULL; - + libusb_device_handle *usb_device; + int current_configuration; unsigned int len; + int transferred; ret = libusb_init(NULL); - if (ret < 0) + if (ret < 0) { + fprintf(stderr, "libusb_init failed: %s\n", + libusb_error_name(ret)); goto out; + } - libusb_set_debug(NULL, 3); + libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_INFO); usb_device = libusb_open_device_with_vid_pid(NULL, AM7XXX_STORAGE_VID, AM7XXX_STORAGE_PID); if (usb_device == NULL) { - fprintf(stderr, "cannot open the device: %d.\n", errno); + fprintf(stderr, "libusb_open failed: %s\n", strerror(errno)); ret = -errno; goto out; } - if (libusb_kernel_driver_active(usb_device, AM7XXX_STORAGE_INTERFACE)) { - ret = libusb_detach_kernel_driver(usb_device, - AM7XXX_STORAGE_INTERFACE); - if (ret < 0) - fprintf(stderr, "Warning: cannot detach kernel driver.\n"); - } else { - fprintf(stderr, "kernel driver not active.\n"); - } - - ret = libusb_set_configuration(usb_device, AM7XXX_STORAGE_CONFIGURATION); + current_configuration = -1; + ret = libusb_get_configuration(usb_device, ¤t_configuration); if (ret < 0) { - fprintf(stderr, "cannot set configuration.\n"); + fprintf(stderr, "libusb_get_configuration failed: %s\n", + libusb_error_name(ret)); goto out_libusb_close; } + if (current_configuration != AM7XXX_STORAGE_CONFIGURATION) { + ret = libusb_set_configuration(usb_device, + AM7XXX_STORAGE_CONFIGURATION); + if (ret < 0) { + fprintf(stderr, "libusb_set_configuration failed: %s\n", + libusb_error_name(ret)); + fprintf(stderr, "Cannot set configuration %d\n", + AM7XXX_STORAGE_CONFIGURATION); + goto out_libusb_close; + } + } + + libusb_set_auto_detach_kernel_driver(usb_device, 1); + ret = libusb_claim_interface(usb_device, AM7XXX_STORAGE_INTERFACE); if (ret < 0) { - fprintf(stderr, "cannot claim interface.\n"); + fprintf(stderr, "libusb_claim_interface failed: %s\n", + libusb_error_name(ret)); + fprintf(stderr, "Cannot claim interface %d\n", + AM7XXX_STORAGE_INTERFACE); goto out_libusb_close; } + /* + * Checking that the configuration has not changed, as suggested in + * http://libusb.sourceforge.net/api-1.0/caveats.html + */ + current_configuration = -1; + ret = libusb_get_configuration(usb_device, ¤t_configuration); + if (ret < 0) { + fprintf(stderr, "libusb_get_configuration after claim failed: %s\n", + libusb_error_name(ret)); + goto out_libusb_release_interface; + } + + if (current_configuration != AM7XXX_STORAGE_CONFIGURATION) { + fprintf(stderr, "libusb configuration changed (expected: %d, current: %d)\n", + AM7XXX_STORAGE_CONFIGURATION, current_configuration); + ret = -EINVAL; + goto out_libusb_release_interface; + } + len = sizeof(switch_command); + transferred = 0; ret = libusb_bulk_transfer(usb_device, AM7XXX_STORAGE_OUT_EP, switch_command, len, &transferred, 0);