Porting teensy-loader-cli to use libusb-1.0 (from 0.1).
- Currently only Linux tested.
This commit is contained in:
		
							parent
							
								
									a82d239efc
								
							
						
					
					
						commit
						cc3f062875
					
				
					 6 changed files with 113 additions and 81 deletions
				
			
		|  | @ -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}" ) | ||||
|  |  | |||
|  | @ -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} ) | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 () | ||||
| 
 | ||||
|  | @ -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
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								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. | ||||
|  |  | |||
|  | @ -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" ) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jacob Alexander
						Jacob Alexander