From cc3f062875ad3ced6ba577bb09a7c29909ba2937 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Fri, 18 Apr 2014 00:18:02 -0700 Subject: [PATCH] Porting teensy-loader-cli to use libusb-1.0 (from 0.1). - Currently only Linux tested. --- CMakeLists.txt | 4 +- LoadFile/CMakeLists.txt | 4 +- ...{FindLibUSB.cmake => FindLibUSB-1.0.cmake} | 10 +- LoadFile/teensy_loader_cli.c | 173 +++++++++++------- README | 1 - setup.cmake | 2 +- 6 files changed, 113 insertions(+), 81 deletions(-) rename LoadFile/{FindLibUSB.cmake => FindLibUSB-1.0.cmake} (95%) diff --git a/CMakeLists.txt b/CMakeLists.txt index f9078ab..2c27c01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,8 +25,8 @@ set( CMAKE_USE_RELATIVE_PATHS 1 ) #| "avr" # Teensy++ 2.0 #| "arm" # Teensy 3.0 #| "arm" # Teensy 3.1 -set( COMPILER_FAMILY "arm" ) -#set( COMPILER_FAMILY "avr" ) +#set( COMPILER_FAMILY "arm" ) +set( COMPILER_FAMILY "avr" ) message( STATUS "Compiler Family:" ) message( "${COMPILER_FAMILY}" ) diff --git a/LoadFile/CMakeLists.txt b/LoadFile/CMakeLists.txt index 4b4c249..5baea82 100644 --- a/LoadFile/CMakeLists.txt +++ b/LoadFile/CMakeLists.txt @@ -48,7 +48,7 @@ list( APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR} ) # Use local find scripts #| Linux - libusb if( CMAKE_SYSTEM_NAME MATCHES "Linux" ) # Find libusb (not 1.0) - find_package( LibUSB REQUIRED ) + find_package( LibUSB-1.0 REQUIRED ) # Defines set( DEFINES -s -DUSE_LIBUSB ) @@ -94,7 +94,7 @@ endif() # #| Default CFLAGS -set( CFLAGS -O2 -Wall ) +set( CFLAGS -O2 -Wall -std=gnu99 ) add_definitions( ${CFLAGS} ${DEFINES} ) diff --git a/LoadFile/FindLibUSB.cmake b/LoadFile/FindLibUSB-1.0.cmake similarity index 95% rename from LoadFile/FindLibUSB.cmake rename to LoadFile/FindLibUSB-1.0.cmake index 9f7b264..2e8e522 100644 --- a/LoadFile/FindLibUSB.cmake +++ b/LoadFile/FindLibUSB-1.0.cmake @@ -1,4 +1,4 @@ -# Attempts to find libusb (not libusb-1.0) +# Attempts to find libusb-1.0 # # LIBUSB_FOUND - system has libusb # LIBUSB_INCLUDE_DIRS - the libusb include directory @@ -48,18 +48,20 @@ if ( LIBUSB_LIBRARIES AND LIBUSB_INCLUDE_DIRS ) else () find_path( LIBUSB_INCLUDE_DIR NAMES - usb.h + libusb.h PATHS /usr/include /usr/local/include /opt/local/include /sw/include /include + PATH_SUFFIXES + libusb-1.0 ) find_library( LIBUSB_LIBRARY NAMES - usb + usb-1.0 PATHS /usr/lib /usr/local/lib @@ -83,7 +85,7 @@ else () endif () else () if ( LIBUSB_FIND_REQUIRED ) - message( FATAL_ERROR "Could not find libusb" ) + message( FATAL_ERROR "Could not find libusb-1.0" ) endif () endif () diff --git a/LoadFile/teensy_loader_cli.c b/LoadFile/teensy_loader_cli.c index dfe31c1..8c6ba60 100644 --- a/LoadFile/teensy_loader_cli.c +++ b/LoadFile/teensy_loader_cli.c @@ -198,106 +198,137 @@ int main(int argc, char **argv) #if defined(USE_LIBUSB) -// http://libusb.sourceforge.net/doc/index.html -#include +#include -usb_dev_handle * open_usb_device(int vid, int pid) +struct libusb_device_handle *open_usb_device( int vid, int pid ) { - struct usb_bus *bus; - struct usb_device *dev; - usb_dev_handle *h; - char buf[128]; - int r; + libusb_device **devs; + struct libusb_device_handle *handle = NULL; + struct libusb_device_handle *ret = NULL; - usb_init(); - usb_find_busses(); - usb_find_devices(); - //printf_verbose("\nSearching for USB device:\n"); - for (bus = usb_get_busses(); bus; bus = bus->next) { - for (dev = bus->devices; dev; dev = dev->next) { - //printf_verbose("bus \"%s\", device \"%s\" vid=%04X, pid=%04X\n", - // bus->dirname, dev->filename, - // dev->descriptor.idVendor, - // dev->descriptor.idProduct - //); - if (dev->descriptor.idVendor != vid) continue; - if (dev->descriptor.idProduct != pid) continue; - h = usb_open(dev); - if (!h) { - printf_verbose("Found device but unable to open"); - continue; - } - #ifdef LIBUSB_HAS_GET_DRIVER_NP - r = usb_get_driver_np(h, 0, buf, sizeof(buf)); - if (r >= 0) { - r = usb_detach_kernel_driver_np(h, 0); - if (r < 0) { - usb_close(h); - printf_verbose("Device is in use by \"%s\" driver", buf); - continue; - } - } - #endif - // Mac OS-X - removing this call to usb_claim_interface() might allow - // this to work, even though it is a clear misuse of the libusb API. - // normally Apple's IOKit should be used on Mac OS-X - r = usb_claim_interface(h, 0); - if (r < 0) { - usb_close(h); - printf_verbose("Unable to claim interface, check USB permissions"); - continue; - } - return h; + if ( libusb_init( NULL ) != 0 ) + fprintf( stderr, "libusb_init failed.\n" ); + + size_t count = libusb_get_device_list( NULL, &devs ); + if ( count < 0 ) + fprintf( stderr, "libusb_get_device_list failed.\n" ); + + for ( size_t c = 0; c < count; c++ ) + { + struct libusb_device_descriptor desc; + libusb_device *dev = devs[c]; + + if ( libusb_get_device_descriptor( dev, &desc ) < 0 ) + fprintf( stderr, "libusb_get_device_descriptor failed.\n" ); + + //printf("ID: %04x Product: %04x\n", desc.idVendor, desc.idProduct ); + // Not correct device + if ( desc.idVendor != vid || desc.idProduct != pid ) + continue; + + // Attempt to open the device + if ( libusb_open( dev, &handle ) != 0 ) + { + fprintf( stderr, "Found device but unable to open\n" ); + continue; } + + // Only required on Linux, other platforms will just ignore this call + libusb_detach_kernel_driver( handle, 0 ); + + // Mac OS-X - removing this call to usb_claim_interface() might allow + // this to work, even though it is a clear misuse of the libusb API. + // normally Apple's IOKit should be used on Mac OS-X + // XXX Is this still valid with libusb-1.0? + + // Attempt to claim interface + int err = libusb_claim_interface( handle, 0 ); + if ( err < 0 ) + { + libusb_close( handle ); + fprintf( stderr, "Unable to claim interface, check USB permissions: %d\n", err ); + continue; + } + + ret = handle; + break; } - return NULL; + + libusb_free_device_list( devs, 1 ); + + return ret; } -static usb_dev_handle *libusb_teensy_handle = NULL; +static struct libusb_device_handle *libusb_teensy_handle = NULL; -int teensy_open(void) +int teensy_open() { teensy_close(); - libusb_teensy_handle = open_usb_device(0x16C0, 0x0478); - if (libusb_teensy_handle) return 1; + + libusb_teensy_handle = open_usb_device( 0x16C0, 0x0478 ); + + if ( libusb_teensy_handle ) + return 1; + return 0; } -int teensy_write(void *buf, int len, double timeout) +int teensy_write( void *buf, int len, double timeout ) { int r; - if (!libusb_teensy_handle) return 0; - while (timeout > 0) { - r = usb_control_msg(libusb_teensy_handle, 0x21, 9, 0x0200, 0, - (char *)buf, len, (int)(timeout * 1000.0)); - if (r >= 0) return 1; + if ( !libusb_teensy_handle ) + return 0; + + while ( timeout > 0 ) { + r = libusb_control_transfer( libusb_teensy_handle, + 0x21, 9, 0x0200, 0, + (unsigned char *)buf, len, + (int)(timeout * 1000.0) ); + + if ( r >= 0 ) + return 1; + //printf("teensy_write, r=%d\n", r); - usleep(10000); + usleep( 10000 ); timeout -= 0.01; // TODO: subtract actual elapsed time } + return 0; } -void teensy_close(void) +void teensy_close() { - if (!libusb_teensy_handle) return; - usb_release_interface(libusb_teensy_handle, 0); - usb_close(libusb_teensy_handle); + if ( !libusb_teensy_handle) + return; + + libusb_release_interface( libusb_teensy_handle, 0 ); + libusb_close( libusb_teensy_handle ); + libusb_teensy_handle = NULL; } -int hard_reboot(void) +int hard_reboot() { - usb_dev_handle *rebootor; + struct libusb_device_handle *rebootor; int r; - rebootor = open_usb_device(0x16C0, 0x0477); - if (!rebootor) return 0; - r = usb_control_msg(rebootor, 0x21, 9, 0x0200, 0, "reboot", 6, 100); - usb_release_interface(rebootor, 0); - usb_close(rebootor); - if (r < 0) return 0; + rebootor = open_usb_device( 0x16C0, 0x0477 ); + + if (!rebootor) + return 0; + + r = libusb_control_transfer( rebootor, + 0x21, 9, 0x0200, 0, + (unsigned char*)"reboot", 6, + 100 ); + + libusb_release_interface( rebootor, 0 ); + libusb_close( rebootor ); + + if (r < 0) + return 0; + return 1; } diff --git a/README b/README index 93a7866..1c44501 100644 --- a/README +++ b/README @@ -45,7 +45,6 @@ First make sure Cygwin is installed - http://www.cygwin.com/ - 32bit or 64bit is - git (needed for some compilation info) - cmake - gcc-core -- gcc-g++ or gcc-c++ And make sure CMake is *NOT* installed through Cygwin. This is extremely important. If this is not possible, you'll have to play with your paths in Cygwin to prioritize the Windows version of CMake. diff --git a/setup.cmake b/setup.cmake index 93b372e..4324b0f 100644 --- a/setup.cmake +++ b/setup.cmake @@ -20,7 +20,7 @@ #| Please look at the {Scan,Macro,USB,Debug}/module.txt for information on the modules and how to create new ones ##| Deals with acquiring the keypress information and turning it into a key index -set( ScanModule "ADCTest" ) +set( ScanModule "DPH" ) ##| Provides the mapping functions for DefaultMap and handles any macro processing before sending to the OutputModule set( MacroModule "PartialMap" ) -- 2.39.2