Browse Source

Porting teensy-loader-cli to use libusb-1.0 (from 0.1).

- Currently only Linux tested.
simple
Jacob Alexander 10 years ago
parent
commit
cc3f062875
6 changed files with 113 additions and 81 deletions
  1. 2
    2
      CMakeLists.txt
  2. 2
    2
      LoadFile/CMakeLists.txt
  3. 6
    4
      LoadFile/FindLibUSB-1.0.cmake
  4. 102
    71
      LoadFile/teensy_loader_cli.c
  5. 0
    1
      README
  6. 1
    1
      setup.cmake

+ 2
- 2
CMakeLists.txt View File

@@ -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}" )

+ 2
- 2
LoadFile/CMakeLists.txt View File

@@ -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} )


LoadFile/FindLibUSB.cmake → LoadFile/FindLibUSB-1.0.cmake View File

@@ -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 ()


+ 102
- 71
LoadFile/teensy_loader_cli.c View File

@@ -198,106 +198,137 @@ int main(int argc, char **argv)

#if defined(USE_LIBUSB)

// http://libusb.sourceforge.net/doc/index.html
#include <usb.h>
#include <libusb-1.0/libusb.h>

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;
}


+ 0
- 1
README View File

@@ -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.

+ 1
- 1
setup.cmake View File

@@ -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" )