num = read_intel_hex(filename);
if (num < 0) die("error reading intel hex file \"%s\"", filename);
printf_verbose("Read \"%s\": %d bytes, %.1f%% usage\n",
- filename, num, (double)num / (double)code_size * 100.0);
+ filename, num, (double)num / (double)code_size * 100.0);
}
// program the data
/****************************************************************/
/* */
-/* USB Access - libusb (Linux & FreeBSD) */
+/* USB Access - libusb (Linux, Windows & FreeBSD) */
/* */
/****************************************************************/
#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;
-
- 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;
- }
- }
- return NULL;
-}
-
-static usb_dev_handle *libusb_teensy_handle = NULL;
-
-int teensy_open(void)
-{
- teensy_close();
- 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 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;
- //printf("teensy_write, r=%d\n", r);
- usleep(10000);
- timeout -= 0.01; // TODO: subtract actual elapsed time
- }
- return 0;
-}
+ libusb_device **devs;
+ struct libusb_device_handle *handle = NULL;
+ struct libusb_device_handle *ret = NULL;
-void teensy_close(void)
-{
- if (!libusb_teensy_handle) return;
- usb_release_interface(libusb_teensy_handle, 0);
- usb_close(libusb_teensy_handle);
- libusb_teensy_handle = NULL;
-}
+ if ( libusb_init( NULL ) != 0 )
+ fprintf( stderr, "libusb_init failed.\n" );
-int hard_reboot(void)
-{
- usb_dev_handle *rebootor;
- int r;
+ size_t count = libusb_get_device_list( NULL, &devs );
+ if ( count < 0 )
+ fprintf( stderr, "libusb_get_device_list failed.\n" );
- 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;
- return 1;
-}
+ for ( size_t c = 0; c < count; c++ )
+ {
+ struct libusb_device_descriptor desc;
+ libusb_device *dev = devs[c];
-#endif
+ 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;
-/****************************************************************/
-/* */
-/* USB Access - Microsoft WIN32 */
-/* */
-/****************************************************************/
+ // Attempt to open the device
+ if ( libusb_open( dev, &handle ) != 0 )
+ {
+ fprintf( stderr, "Found device but unable to open\n" );
+ continue;
+ }
-#if defined(USE_WIN32)
+ // Only required on Linux, other platforms will just ignore this call
+ libusb_detach_kernel_driver( handle, 0 );
-// http://msdn.microsoft.com/en-us/library/ms790932.aspx
-#include <windows.h>
-#include <setupapi.h>
-#include <ddk/hidsdi.h>
-#include <ddk/hidclass.h>
+ // 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?
-HANDLE open_usb_device(int vid, int pid)
-{
- GUID guid;
- HDEVINFO info;
- DWORD index, required_size;
- SP_DEVICE_INTERFACE_DATA iface;
- SP_DEVICE_INTERFACE_DETAIL_DATA *details;
- HIDD_ATTRIBUTES attrib;
- HANDLE h;
- BOOL ret;
-
- HidD_GetHidGuid(&guid);
- info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
- if (info == INVALID_HANDLE_VALUE) return NULL;
- for (index=0; 1 ;index++) {
- iface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
- ret = SetupDiEnumDeviceInterfaces(info, NULL, &guid, index, &iface);
- if (!ret) {
- SetupDiDestroyDeviceInfoList(info);
- break;
- }
- SetupDiGetInterfaceDeviceDetail(info, &iface, NULL, 0, &required_size, NULL);
- details = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(required_size);
- if (details == NULL) continue;
- memset(details, 0, required_size);
- details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
- ret = SetupDiGetDeviceInterfaceDetail(info, &iface, details,
- required_size, NULL, NULL);
- if (!ret) {
- free(details);
+ // 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;
}
- h = CreateFile(details->DevicePath, GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
- FILE_FLAG_OVERLAPPED, NULL);
- free(details);
- if (h == INVALID_HANDLE_VALUE) continue;
- attrib.Size = sizeof(HIDD_ATTRIBUTES);
- ret = HidD_GetAttributes(h, &attrib);
- if (!ret) {
- CloseHandle(h);
- continue;
- }
- if (attrib.VendorID != vid || attrib.ProductID != pid) {
- CloseHandle(h);
- continue;
- }
- SetupDiDestroyDeviceInfoList(info);
- return h;
- }
- return NULL;
-}
-int write_usb_device(HANDLE h, void *buf, int len, int timeout)
-{
- static HANDLE event = NULL;
- unsigned char tmpbuf[1040];
- OVERLAPPED ov;
- DWORD n, r;
-
- if (len > sizeof(tmpbuf) - 1) return 0;
- if (event == NULL) {
- event = CreateEvent(NULL, TRUE, TRUE, NULL);
- if (!event) return 0;
- }
- ResetEvent(&event);
- memset(&ov, 0, sizeof(ov));
- ov.hEvent = event;
- tmpbuf[0] = 0;
- memcpy(tmpbuf + 1, buf, len);
- if (!WriteFile(h, tmpbuf, len + 1, NULL, &ov)) {
- if (GetLastError() != ERROR_IO_PENDING) return 0;
- r = WaitForSingleObject(event, timeout);
- if (r == WAIT_TIMEOUT) {
- CancelIo(h);
- return 0;
- }
- if (r != WAIT_OBJECT_0) return 0;
+ ret = handle;
+ break;
}
- if (!GetOverlappedResult(h, &ov, &n, FALSE)) return 0;
- if (n <= 0) return 0;
- return 1;
-}
-void print_win32_err(void)
-{
- char buf[256];
- DWORD err;
+ libusb_free_device_list( devs, 1 );
- err = GetLastError();
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
- 0, buf, sizeof(buf), NULL);
- printf("err %ld: %s\n", err, buf);
+ return ret;
}
-static HANDLE win32_teensy_handle = NULL;
+static struct libusb_device_handle *libusb_teensy_handle = NULL;
-int teensy_open(void)
+int teensy_open()
{
teensy_close();
- win32_teensy_handle = open_usb_device(0x16C0, 0x0478);
- if (win32_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 (!win32_teensy_handle) return 0;
- r = write_usb_device(win32_teensy_handle, buf, len, (int)(timeout * 1000.0));
- //if (!r) print_win32_err();
- return r;
+
+ 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 );
+ timeout -= 0.01; // TODO: subtract actual elapsed time
+ }
+
+ return 0;
}
-void teensy_close(void)
+void teensy_close()
{
- if (!win32_teensy_handle) return;
- CloseHandle(win32_teensy_handle);
- win32_teensy_handle = NULL;
+ 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()
{
- HANDLE rebootor;
+ struct libusb_device_handle *rebootor;
int r;
- rebootor = open_usb_device(0x16C0, 0x0477);
- if (!rebootor) return 0;
- r = write_usb_device(rebootor, "reboot", 6, 100);
- CloseHandle(rebootor);
- return r;
+ 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;
}
#endif
parse_hex_line(char *line)
{
int addr, code, num;
- int sum, len, cksum, i;
- char *ptr;
-
- num = 0;
- if (line[0] != ':') return 0;
- if (strlen(line) < 11) return 0;
- ptr = line+1;
- if (!sscanf(ptr, "%02x", &len)) return 0;
- ptr += 2;
- if ((int)strlen(line) < (11 + (len * 2)) ) return 0;
- if (!sscanf(ptr, "%04x", &addr)) return 0;
- ptr += 4;
- /* printf("Line: length=%d Addr=%d\n", len, addr); */
- if (!sscanf(ptr, "%02x", &code)) return 0;
+ int sum, len, cksum, i;
+ char *ptr;
+
+ num = 0;
+ if (line[0] != ':') return 0;
+ if (strlen(line) < 11) return 0;
+ ptr = line+1;
+ if (!sscanf(ptr, "%02x", &len)) return 0;
+ ptr += 2;
+ if ((int)strlen(line) < (11 + (len * 2)) ) return 0;
+ if (!sscanf(ptr, "%04x", &addr)) return 0;
+ ptr += 4;
+ /* printf("Line: length=%d Addr=%d\n", len, addr); */
+ if (!sscanf(ptr, "%02x", &code)) return 0;
if (addr + extended_addr + len >= MAX_MEMORY_SIZE) return 0;
- ptr += 2;
- sum = (len & 255) + ((addr >> 8) & 255) + (addr & 255) + (code & 255);
+ ptr += 2;
+ sum = (len & 255) + ((addr >> 8) & 255) + (addr & 255) + (code & 255);
if (code != 0) {
if (code == 1) {
end_record_seen = 1;
if (!sscanf(ptr, "%04x", &i)) return 1;
ptr += 4;
sum += ((i >> 8) & 255) + (i & 255);
- if (!sscanf(ptr, "%02x", &cksum)) return 1;
+ if (!sscanf(ptr, "%02x", &cksum)) return 1;
if (((sum & 255) + (cksum & 255)) & 255) return 1;
extended_addr = i << 4;
//printf("ext addr = %05X\n", extended_addr);
if (!sscanf(ptr, "%04x", &i)) return 1;
ptr += 4;
sum += ((i >> 8) & 255) + (i & 255);
- if (!sscanf(ptr, "%02x", &cksum)) return 1;
+ if (!sscanf(ptr, "%02x", &cksum)) return 1;
if (((sum & 255) + (cksum & 255)) & 255) return 1;
extended_addr = i << 16;
//printf("ext addr = %08X\n", extended_addr);
}
- return 1; // non-data line
+ return 1; // non-data line
}
byte_count += len;
- while (num != len) {
- if (sscanf(ptr, "%02x", &i) != 1) return 0;
+ while (num != len) {
+ if (sscanf(ptr, "%02x", &i) != 1) return 0;
i &= 255;
firmware_image[addr + extended_addr + num] = i;
firmware_mask[addr + extended_addr + num] = 1;
- ptr += 2;
- sum += i;
- (num)++;
- if (num >= 256) return 0;
- }
- if (!sscanf(ptr, "%02x", &cksum)) return 0;
- if (((sum & 255) + (cksum & 255)) & 255) return 0; /* checksum error */
- return 1;
+ ptr += 2;
+ sum += i;
+ (num)++;
+ if (num >= 256) return 0;
+ }
+ if (!sscanf(ptr, "%02x", &cksum)) return 0;
+ if (((sum & 255) + (cksum & 255)) & 255) return 0; /* checksum error */
+ return 1;
}
int ihex_bytes_within_range(int begin, int end)