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

#| "avr" # Teensy++ 2.0 #| "avr" # Teensy++ 2.0
#| "arm" # Teensy 3.0 #| "arm" # Teensy 3.0
#| "arm" # Teensy 3.1 #| "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( STATUS "Compiler Family:" )
message( "${COMPILER_FAMILY}" ) message( "${COMPILER_FAMILY}" )

+ 2
- 2
LoadFile/CMakeLists.txt View File

#| Linux - libusb #| Linux - libusb
if( CMAKE_SYSTEM_NAME MATCHES "Linux" ) if( CMAKE_SYSTEM_NAME MATCHES "Linux" )
# Find libusb (not 1.0) # Find libusb (not 1.0)
find_package( LibUSB REQUIRED )
find_package( LibUSB-1.0 REQUIRED )


# Defines # Defines
set( DEFINES -s -DUSE_LIBUSB ) set( DEFINES -s -DUSE_LIBUSB )
# #


#| Default CFLAGS #| Default CFLAGS
set( CFLAGS -O2 -Wall )
set( CFLAGS -O2 -Wall -std=gnu99 )


add_definitions( ${CFLAGS} ${DEFINES} ) add_definitions( ${CFLAGS} ${DEFINES} )



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

# Attempts to find libusb (not libusb-1.0)
# Attempts to find libusb-1.0
# #
# LIBUSB_FOUND - system has libusb # LIBUSB_FOUND - system has libusb
# LIBUSB_INCLUDE_DIRS - the libusb include directory # LIBUSB_INCLUDE_DIRS - the libusb include directory
else () else ()
find_path( LIBUSB_INCLUDE_DIR find_path( LIBUSB_INCLUDE_DIR
NAMES NAMES
usb.h
libusb.h
PATHS PATHS
/usr/include /usr/include
/usr/local/include /usr/local/include
/opt/local/include /opt/local/include
/sw/include /sw/include
/include /include
PATH_SUFFIXES
libusb-1.0
) )


find_library( LIBUSB_LIBRARY find_library( LIBUSB_LIBRARY
NAMES NAMES
usb
usb-1.0
PATHS PATHS
/usr/lib /usr/lib
/usr/local/lib /usr/local/lib
endif () endif ()
else () else ()
if ( LIBUSB_FIND_REQUIRED ) if ( LIBUSB_FIND_REQUIRED )
message( FATAL_ERROR "Could not find libusb" )
message( FATAL_ERROR "Could not find libusb-1.0" )
endif () endif ()
endif () endif ()



+ 102
- 71
LoadFile/teensy_loader_cli.c View File



#if defined(USE_LIBUSB) #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(); 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; return 0;
} }


int teensy_write(void *buf, int len, double timeout)
int teensy_write( void *buf, int len, double timeout )
{ {
int r; 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); //printf("teensy_write, r=%d\n", r);
usleep(10000);
usleep( 10000 );
timeout -= 0.01; // TODO: subtract actual elapsed time timeout -= 0.01; // TODO: subtract actual elapsed time
} }

return 0; 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; libusb_teensy_handle = NULL;
} }


int hard_reboot(void)
int hard_reboot()
{ {
usb_dev_handle *rebootor;
struct libusb_device_handle *rebootor;
int r; 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; return 1;
} }



+ 0
- 1
README View File

- git (needed for some compilation info) - git (needed for some compilation info)
- cmake - cmake
- gcc-core - gcc-core
- gcc-g++ or gcc-c++


And make sure CMake is *NOT* installed through Cygwin. This is extremely important. 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. 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

#| Please look at the {Scan,Macro,USB,Debug}/module.txt for information on the modules and how to create new ones #| 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 ##| 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 ##| Provides the mapping functions for DefaultMap and handles any macro processing before sending to the OutputModule
set( MacroModule "PartialMap" ) set( MacroModule "PartialMap" )