Archived
1
0

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

- Currently only Linux tested.
This commit is contained in:
Jacob Alexander 2014-04-18 00:18:02 -07:00
parent a82d239efc
commit cc3f062875
6 changed files with 113 additions and 81 deletions

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

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

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

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

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.

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