summaryrefslogtreecommitdiffstats
path: root/src/usb-device.c
diff options
context:
space:
mode:
authorPali Rohár <pali.rohar@gmail.com>2012-08-09 16:13:43 +0200
committerPali Rohár <pali.rohar@gmail.com>2012-08-09 16:13:43 +0200
commit01239ea839548a71b3313d51b5890a6050cb64ec (patch)
tree13022613b155a647aa601590bc33b233ef9a903b /src/usb-device.c
parentb4cbab6774acf47bb6173911a865dfb4d4ce869c (diff)
download0xFFFF-01239ea839548a71b3313d51b5890a6050cb64ec.tar.bz2
Rename usb_device to usb-device, fix includes
Diffstat (limited to 'src/usb-device.c')
-rw-r--r--src/usb-device.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/src/usb-device.c b/src/usb-device.c
new file mode 100644
index 0000000..9fc8d91
--- /dev/null
+++ b/src/usb-device.c
@@ -0,0 +1,221 @@
+/*
+ 0xFFFF - Open Free Fiasco Firmware Flasher
+ Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
+
+ 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include <usb.h>
+
+#include "device.h"
+#include "usb-device.h"
+
+static struct usb_flash_device usb_devices[] = {
+ { 0x0421, 0x0105, 2, 1, -1, FLASH_NOLO, { DEVICE_SU_18, DEVICE_RX_44, DEVICE_RX_48, DEVICE_RX_51, 0 } },
+ { 0x0421, 0x0106, 0, -1, -1, FLASH_COLD, { DEVICE_RX_51, 0 } },
+ { 0x0421, 0x01c7, 0, -1, -1, FLASH_DISK, { DEVICE_RX_51, 0 } },
+ { 0x0421, 0x01c8, -1, -1, -1, FLASH_MKII, { DEVICE_RX_51, 0 } },
+ { 0x0421, 0x0431, 0, -1, -1, FLASH_DISK, { DEVICE_SU_18, DEVICE_RX_34, 0 } },
+ { 0x0421, 0x3f00, 2, 1, -1, FLASH_NOLO, { DEVICE_RX_34, 0 } },
+ { 0, 0, -1, -1, -1, 0, {} }
+};
+
+static const char * usb_flash_protocols[] = {
+ [FLASH_NOLO] = "NOLO",
+ [FLASH_COLD] = "Cold flashing",
+ [FLASH_MKII] = "Mkii protcol",
+ [FLASH_DISK] = "RAW disk",
+};
+
+const char * usb_flash_protocol_to_string(enum usb_flash_protocol protocol) {
+
+ if ( protocol > sizeof(usb_flash_protocols) )
+ return NULL;
+
+ return usb_flash_protocols[protocol];
+
+}
+
+static void usb_device_info_print(const struct usb_flash_device * dev) {
+
+ int i;
+
+ printf("USB device %s", device_to_string(dev->devices[0]));
+
+ for ( i = 1; dev->devices[i]; ++i )
+ printf("/%s", device_to_string(dev->devices[i]));
+
+ printf(" (%#04x:%#04x) in %s mode", dev->vendor, dev->product, usb_flash_protocol_to_string(dev->protocol));
+
+}
+
+static struct usb_device_info * usb_device_is_valid(struct usb_device * dev) {
+
+ int i;
+ struct usb_device_info * ret = NULL;
+
+ for ( i = 0; usb_devices[i].vendor; ++i ) {
+
+ if ( dev->descriptor.idVendor == usb_devices[i].vendor && dev->descriptor.idProduct == usb_devices[i].product ) {
+
+ printf("\nFound ");
+ usb_device_info_print(&usb_devices[i]);
+ printf("\n");
+
+ printf("\rOpening USB..."); fflush(stdout);
+ usb_dev_handle * udev = usb_open(dev);
+ if ( ! udev ) {
+ fprintf(stderr, "usb_open failed: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ if ( usb_devices[i].interface < 0 ) {
+ fprintf(stderr, "no interface specified\n");
+ usb_close(udev);
+ return NULL;
+ }
+
+#if defined(LIBUSB_HAS_GET_DRIVER_NP) && defined(LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP)
+ /* Detach kernel from usb interface */
+ printf("\rDetaching kernel from USB interface..."); fflush(stdout);
+ usb_detach_kernel_driver_np(udev, usb_devices[i].interface);
+#endif
+
+ printf("\rClaiming USB interface..."); fflush(stdout);
+ if ( usb_claim_interface(udev, usb_devices[i].interface) < 0 ) {
+ fprintf(stderr, "usb_claim_interface failed: %s\n", strerror(errno));
+ usb_close(udev);
+ return NULL;
+ }
+
+ if ( usb_devices[i].alternate >= 0 ) {
+ printf("\rSetting alternate USB interface..."); fflush(stdout);
+ if ( usb_set_altinterface(udev, usb_devices[i].alternate) < 0 ) {
+ fprintf(stderr, "usb_claim_interface failed: %s\n", strerror(errno));
+ usb_close(udev);
+ return NULL;
+ }
+ }
+
+ if ( usb_devices[i].configuration >= 0 ) {
+ printf("\rSetting USB configuration..."); fflush(stdout);
+ if ( usb_set_configuration(udev, usb_devices[i].configuration) < 0 ) {
+ fprintf(stderr, "usb_set_configuration failed: %s\n", strerror(errno));
+ usb_close(udev);
+ return NULL;
+ }
+ }
+
+ ret = malloc(sizeof(struct usb_device_info));
+ if ( ! ret ) {
+ usb_close(udev);
+ return NULL;
+ }
+
+ ret->dev = udev;
+ ret->info = &usb_devices[i];
+ break;
+ }
+ }
+
+ return ret;
+
+}
+
+static struct usb_device_info * usb_search_device(struct usb_device * dev, int level) {
+
+ int i;
+ struct usb_device_info * ret = NULL;
+
+ if ( ! dev )
+ return NULL;
+
+ ret = usb_device_is_valid(dev);
+ if ( ret )
+ return ret;
+
+ for ( i = 0; i < dev->num_children; i++ ) {
+ ret = usb_search_device(dev->children[i], level + 1);
+ if ( ret )
+ break;
+ }
+
+ return ret;
+
+}
+
+struct usb_device_info * usb_wait_for_device(void) {
+
+ struct usb_bus * bus;
+ struct usb_device_info * ret = NULL;
+ int i = 0;
+ static char progress[] = {'/','-','\\', '|'};
+
+ usb_init();
+ usb_find_busses();
+
+ while ( 1 ) {
+
+ printf("\rWaiting for USB device... %c", progress[++i%sizeof(progress)]);
+ fflush(stdout);
+
+ usb_find_devices();
+
+ for ( bus = usb_get_busses(); bus; bus = bus->next ) {
+
+ if ( bus->root_dev )
+ ret = usb_search_device(bus->root_dev, 0);
+ else {
+ struct usb_device *dev;
+ for ( dev = bus->devices; dev; dev = dev->next ) {
+ ret = usb_search_device(dev, 0);
+ if ( ret )
+ break;
+ }
+ }
+
+ if ( ret )
+ break;
+
+ }
+
+ if ( ret )
+ break;
+
+ usleep(0xc350); // 0.5s
+
+ }
+
+ printf("\r \r");
+
+ if ( ! ret )
+ return NULL;
+
+ return ret;
+
+}
+
+void usb_close_device(struct usb_device_info * dev) {
+
+ free(dev->dev);
+ free(dev);
+
+}