Update HID bootloader loader application to support the VID/PID used by the bootloader.
[pub/lufa.git] / Bootloaders / HID / HostLoaderApp / teensy_loader_cli.c
diff --git a/Bootloaders/HID/HostLoaderApp/teensy_loader_cli.c b/Bootloaders/HID/HostLoaderApp/teensy_loader_cli.c
deleted file mode 100644 (file)
index 3d9dbca..0000000
+++ /dev/null
@@ -1,960 +0,0 @@
-/* Teensy Loader, Command Line Interface
- * Program and Reboot Teensy Board with HalfKay Bootloader
- * http://www.pjrc.com/teensy/loader_cli.html
- * Copyright 2008-2010, PJRC.COM, LLC
- *
- * You may redistribute this program and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software
- * Foundation, version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see http://www.gnu.org/licenses/
- */
-
-/* Want to incorporate this code into a proprietary application??
- * Just email paul@pjrc.com to ask.  Usually it's not a problem,
- * but you do need to ask to use this code in any way other than
- * those permitted by the GNU General Public License, version 3  */
-
-/* For non-root permissions on ubuntu or similar udev-based linux
- * http://www.pjrc.com/teensy/49-teensy.rules
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <string.h>
-#include <unistd.h>
-
-void usage(void)
-{
-       fprintf(stderr, "Usage: teensy_loader_cli -mmcu=<MCU> [-w] [-h] [-n] [-v] <file.hex>\n");
-       fprintf(stderr, "\t-w : Wait for device to appear\n");
-       fprintf(stderr, "\t-r : Use hard reboot if device not online\n");
-       fprintf(stderr, "\t-n : No reboot after programming\n");
-       fprintf(stderr, "\t-v : Verbose output\n");
-       fprintf(stderr, "\n<MCU> = atmega32u4 | at90usb162 | at90usb646 | at90usb1286\n");
-       fprintf(stderr, "\nFor more information, please visit:\n");
-       fprintf(stderr, "http://www.pjrc.com/teensy/loader_cli.html\n");
-       exit(1);
-}
-
-// USB Access Functions
-int teensy_open(void);
-int teensy_write(void *buf, int len, double timeout);
-void teensy_close(void);
-int hard_reboot(void);
-
-// Intel Hex File Functions
-int read_intel_hex(const char *filename);
-int ihex_bytes_within_range(int begin, int end);
-void ihex_get_data(int addr, int len, unsigned char *bytes);
-
-// Misc stuff
-int printf_verbose(const char *format, ...);
-void delay(double seconds);
-void die(const char *str, ...);
-void parse_options(int argc, char **argv);
-
-// options (from user via command line args)
-int wait_for_device_to_appear = 0;
-int hard_reboot_device = 0;
-int reboot_after_programming = 1;
-int verbose = 0;
-int code_size = 0, block_size = 0;
-const char *filename=NULL;
-
-
-/****************************************************************/
-/*                                                              */
-/*                       Main Program                           */
-/*                                                              */
-/****************************************************************/
-
-int main(int argc, char **argv)
-{
-       unsigned char buf[260];
-       int num, addr, r, first_block=1, waited=0;
-
-       // parse command line arguments
-       parse_options(argc, argv);
-       if (!filename) {
-               fprintf(stderr, "Filename must be specified\n\n");
-               usage();
-       }
-       if (!code_size) {
-               fprintf(stderr, "MCU type must be specified\n\n");
-               usage();
-       }
-       printf_verbose("Teensy Loader, Command Line, Version 2.0\n");
-
-       // read the intel hex file
-       // this is done first so any error is reported before using USB
-       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);
-
-       // open the USB device
-       while (1) {
-               if (teensy_open()) break;
-               if (hard_reboot_device) {
-                       if (!hard_reboot()) die("Unable to find rebootor\n");
-                       printf_verbose("Hard Reboot performed\n");
-                       hard_reboot_device = 0; // only hard reboot once
-                       wait_for_device_to_appear = 1;
-               }
-               if (!wait_for_device_to_appear) die("Unable to open device\n");
-               if (!waited) {
-                       printf_verbose("Waiting for Teensy device...\n");
-                       printf_verbose(" (hint: press the reset button)\n");
-                       waited = 1;
-               }
-               delay(0.25);
-       }
-       printf_verbose("Found HalfKay Bootloader\n");
-
-       // if we waited for the device, read the hex file again
-       // perhaps it changed while we were waiting?
-       if (waited) {
-               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);
-       }
-
-       // program the data
-       printf_verbose("Programming");
-       fflush(stdout);
-       for (addr = 0; addr < code_size; addr += block_size) {
-               if (addr > 0 && !ihex_bytes_within_range(addr, addr + block_size - 1)) {
-                       // don't waste time on blocks that are unused,
-                       // but always do the first one to erase the chip
-                       continue;
-               }
-               printf_verbose(".");
-               if (code_size < 0x10000) {
-                       buf[0] = addr & 255;
-                       buf[1] = (addr >> 8) & 255;
-               } else {
-                       buf[0] = (addr >> 8) & 255;
-                       buf[1] = (addr >> 16) & 255;
-               }
-               ihex_get_data(addr, block_size, buf + 2);
-               r = teensy_write(buf, block_size + 2, first_block ? 3.0 : 0.25);
-               if (!r) die("error writing to Teensy\n");
-               first_block = 0;
-       }
-       printf_verbose("\n");
-
-       // reboot to the user's new code
-       if (reboot_after_programming) {
-               printf_verbose("Booting\n");
-               buf[0] = 0xFF;
-               buf[1] = 0xFF;
-               memset(buf + 2, 0, sizeof(buf) - 2);
-               teensy_write(buf, block_size + 2, 0.25);
-       }
-       teensy_close();
-       return 0;
-}
-
-
-
-
-/****************************************************************/
-/*                                                              */
-/*             USB Access - libusb (Linux & FreeBSD)            */
-/*                                                              */
-/****************************************************************/
-
-#if defined(USE_LIBUSB)
-
-// http://libusb.sourceforge.net/doc/index.html
-#include <usb.h>
-
-usb_dev_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;
-       r = usb_control_msg(libusb_teensy_handle, 0x21, 9, 0x0200, 0, (char *)buf,
-               len, (int)(timeout * 1000.0));
-       if (r < 0) return 0;
-       return 1;
-}
-
-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;
-}
-
-int hard_reboot(void)
-{
-       usb_dev_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;
-       return 1;
-}
-
-#endif
-
-
-/****************************************************************/
-/*                                                              */
-/*               USB Access - Microsoft WIN32                   */
-/*                                                              */
-/****************************************************************/
-
-#if defined(USE_WIN32)
-
-// http://msdn.microsoft.com/en-us/library/ms790932.aspx
-#include <windows.h>
-#include <setupapi.h>
-#include <ddk/hidsdi.h>
-#include <ddk/hidclass.h>
-
-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);
-                       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;
-       }
-       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;
-
-        err = GetLastError();
-        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
-                0, buf, sizeof(buf), NULL);
-        printf("err %ld: %s\n", err, buf);
-}
-
-static HANDLE win32_teensy_handle = NULL;
-
-int teensy_open(void)
-{
-       teensy_close();
-       win32_teensy_handle = open_usb_device(0x16C0, 0x0478);
-       if (win32_teensy_handle) return 1;
-       return 0;
-}
-
-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;
-}
-
-void teensy_close(void)
-{
-       if (!win32_teensy_handle) return;
-       CloseHandle(win32_teensy_handle);
-       win32_teensy_handle = NULL;
-}
-
-int hard_reboot(void)
-{
-       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;
-}
-
-#endif
-
-
-
-/****************************************************************/
-/*                                                              */
-/*             USB Access - Apple's IOKit, Mac OS-X             */
-/*                                                              */
-/****************************************************************/
-
-#if defined(USE_APPLE_IOKIT)
-
-// http://developer.apple.com/technotes/tn2007/tn2187.html
-#include <IOKit/IOKitLib.h>
-#include <IOKit/hid/IOHIDLib.h>
-#include <IOKit/hid/IOHIDDevice.h>
-
-struct usb_list_struct {
-       IOHIDDeviceRef ref;
-       int pid;
-       int vid;
-       struct usb_list_struct *next;
-};
-
-static struct usb_list_struct *usb_list=NULL;
-static IOHIDManagerRef hid_manager=NULL;
-
-void attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev)
-{
-       CFTypeRef type;
-       struct usb_list_struct *n, *p;
-       int32_t pid, vid;
-
-       if (!dev) return;
-       type = IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDVendorIDKey));
-       if (!type || CFGetTypeID(type) != CFNumberGetTypeID()) return;
-       if (!CFNumberGetValue((CFNumberRef)type, kCFNumberSInt32Type, &vid)) return;
-       type = IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDProductIDKey));
-       if (!type || CFGetTypeID(type) != CFNumberGetTypeID()) return;
-       if (!CFNumberGetValue((CFNumberRef)type, kCFNumberSInt32Type, &pid)) return;
-       n = (struct usb_list_struct *)malloc(sizeof(struct usb_list_struct));
-       if (!n) return;
-       //printf("attach callback: vid=%04X, pid=%04X\n", vid, pid);
-       n->ref = dev;
-       n->vid = vid;
-       n->pid = pid;
-       n->next = NULL;
-       if (usb_list == NULL) {
-               usb_list = n;
-       } else {
-               for (p = usb_list; p->next; p = p->next) ;
-               p->next = n;
-       }
-}
-
-void detach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev)
-{
-       struct usb_list_struct *p, *tmp, *prev=NULL;
-
-       p = usb_list;
-       while (p) {
-               if (p->ref == dev) {
-                       if (prev) {
-                               prev->next = p->next;
-                       } else {
-                               usb_list = p->next;
-                       }
-                       tmp = p;
-                       p = p->next;
-                       free(tmp);
-               } else {
-                       prev = p;
-                       p = p->next;
-               }
-       }
-}
-
-void init_hid_manager(void)
-{
-       CFMutableDictionaryRef dict;
-       IOReturn ret;
-
-       if (hid_manager) return;
-       hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
-       if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) {
-               if (hid_manager) CFRelease(hid_manager);
-               printf_verbose("no HID Manager - maybe this is a pre-Leopard (10.5) system?\n");
-               return;
-       }
-       dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
-               &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-       if (!dict) return;
-       IOHIDManagerSetDeviceMatching(hid_manager, dict);
-       CFRelease(dict);
-       IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
-       IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, attach_callback, NULL);
-       IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, detach_callback, NULL);
-       ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone);
-       if (ret != kIOReturnSuccess) {
-               IOHIDManagerUnscheduleFromRunLoop(hid_manager,
-                       CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
-               CFRelease(hid_manager);
-               printf_verbose("Error opening HID Manager");
-       }
-}
-
-static void do_run_loop(void)
-{
-       while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == kCFRunLoopRunHandledSource) ;
-}
-
-IOHIDDeviceRef open_usb_device(int vid, int pid)
-{
-       struct usb_list_struct *p;
-       IOReturn ret;
-
-       init_hid_manager();
-       do_run_loop();
-       for (p = usb_list; p; p = p->next) {
-               if (p->vid == vid && p->pid == pid) {
-                       ret = IOHIDDeviceOpen(p->ref, kIOHIDOptionsTypeNone);
-                       if (ret == kIOReturnSuccess) return p->ref;
-               }
-       }
-       return NULL;
-}
-
-void close_usb_device(IOHIDDeviceRef dev)
-{
-       struct usb_list_struct *p;
-
-       do_run_loop();
-       for (p = usb_list; p; p = p->next) {
-               if (p->ref == dev) {
-                       IOHIDDeviceClose(dev, kIOHIDOptionsTypeNone);
-                       return;
-               }
-       }
-}
-
-static IOHIDDeviceRef iokit_teensy_reference = NULL;
-
-int teensy_open(void)
-{
-       teensy_close();
-       iokit_teensy_reference = open_usb_device(0x16C0, 0x0478);
-       if (iokit_teensy_reference) return 1;
-       return 0;
-}
-
-int teensy_write(void *buf, int len, double timeout)
-{
-       IOReturn ret;
-
-       // timeouts do not work on OS-X
-       // IOHIDDeviceSetReportWithCallback is not implemented
-       // even though Apple documents it with a code example!
-       // submitted to Apple on 22-sep-2009, problem ID 7245050
-       if (!iokit_teensy_reference) return 0;
-       ret = IOHIDDeviceSetReport(iokit_teensy_reference,
-               kIOHIDReportTypeOutput, 0, buf, len);
-       if (ret == kIOReturnSuccess) return 1;
-       return 0;
-}
-
-void teensy_close(void)
-{
-       if (!iokit_teensy_reference) return;
-       close_usb_device(iokit_teensy_reference);
-       iokit_teensy_reference = NULL;
-}
-
-int hard_reboot(void)
-{
-       IOHIDDeviceRef rebootor;
-       IOReturn ret;
-
-       rebootor = open_usb_device(0x16C0, 0x0477);
-       if (!rebootor) return 0;
-       ret = IOHIDDeviceSetReport(rebootor,
-               kIOHIDReportTypeOutput, 0, (uint8_t *)("reboot"), 6);
-       close_usb_device(rebootor);
-       if (ret == kIOReturnSuccess) return 1;
-       return 0;
-}
-
-#endif
-
-
-
-/****************************************************************/
-/*                                                              */
-/*              USB Access - BSD's UHID driver                  */
-/*                                                              */
-/****************************************************************/
-
-#if defined(USE_UHID)
-
-// Thanks to Todd T Fries for help getting this working on OpenBSD
-// and to Chris Kuethe for the initial patch to use UHID.
-
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <dev/usb/usb.h>
-#ifndef USB_GET_DEVICEINFO
-#include <dev/usb/usb_ioctl.h>
-#endif
-
-int open_usb_device(int vid, int pid)
-{
-       int r, fd;
-       DIR *dir;
-       struct dirent *d;
-       struct usb_device_info info;
-       char buf[256];
-
-       dir = opendir("/dev");
-       if (!dir) return -1;
-       while ((d = readdir(dir)) != NULL) {
-               if (strncmp(d->d_name, "uhid", 4) != 0) continue;
-               snprintf(buf, sizeof(buf), "/dev/%s", d->d_name);
-               fd = open(buf, O_RDWR);
-               if (fd < 0) continue;
-               r = ioctl(fd, USB_GET_DEVICEINFO, &info);
-               if (r < 0) {
-                       // NetBSD: added in 2004
-                       // OpenBSD: added November 23, 2009
-                       // FreeBSD: missing (FreeBSD 8.0) - USE_LIBUSB works!
-                       die("Error: your uhid driver does not support"
-                         " USB_GET_DEVICEINFO, please upgrade!\n");
-                       close(fd);
-                       closedir(dir);
-                       exit(1);
-               }
-               //printf("%s: v=%d, p=%d\n", buf, info.udi_vendorNo, info.udi_productNo);
-               if (info.udi_vendorNo == vid && info.udi_productNo == pid) {
-                       closedir(dir);
-                       return fd;
-               }
-               close(fd);
-       }
-       closedir(dir);
-       return -1;
-}
-
-static int uhid_teensy_fd = -1;
-
-int teensy_open(void)
-{
-       teensy_close();
-       uhid_teensy_fd = open_usb_device(0x16C0, 0x0478);
-       if (uhid_teensy_fd < 0) return 0;
-       return 1;
-}
-
-int teensy_write(void *buf, int len, double timeout)
-{
-       int r;
-
-       // TODO: imeplement timeout... how??
-       r = write(uhid_teensy_fd, buf, len);
-       if (r == len) return 1;
-       return 0;
-}
-
-void teensy_close(void)
-{
-       if (uhid_teensy_fd >= 0) {
-               close(uhid_teensy_fd);
-               uhid_teensy_fd = -1;
-       }
-}
-
-int hard_reboot(void)
-{
-       int r, rebootor_fd;
-
-       rebootor_fd = open_usb_device(0x16C0, 0x0477);
-       if (rebootor_fd < 0) return 0;
-       r = write(rebootor_fd, "reboot", 6);
-       delay(0.1);
-       close(rebootor_fd);
-       if (r == 6) return 1;
-       return 0;
-}
-
-#endif
-
-
-
-/****************************************************************/
-/*                                                              */
-/*                     Read Intel Hex File                      */
-/*                                                              */
-/****************************************************************/
-
-// the maximum flash image size we can support
-// chips with larger memory may be used, but only this
-// much intel-hex data can be loaded into memory!
-#define MAX_MEMORY_SIZE 0x10000
-
-static unsigned char firmware_image[MAX_MEMORY_SIZE];
-static unsigned char firmware_mask[MAX_MEMORY_SIZE];
-static int end_record_seen=0;
-static int byte_count;
-static unsigned int extended_addr = 0;
-static int parse_hex_line(char *line);
-
-int read_intel_hex(const char *filename)
-{
-       FILE *fp;
-       int i, lineno=0;
-       char buf[1024];
-
-       byte_count = 0;
-       end_record_seen = 0;
-       for (i=0; i<MAX_MEMORY_SIZE; i++) {
-               firmware_image[i] = 0xFF;
-               firmware_mask[i] = 0;
-       }
-       extended_addr = 0;
-
-       fp = fopen(filename, "r");
-       if (fp == NULL) {
-               //printf("Unable to read file %s\n", filename);
-               return -1;
-       }
-       while (!feof(fp)) {
-               *buf = '\0';
-               if (!fgets(buf, sizeof(buf), fp)) break;
-               lineno++;
-               if (*buf) {
-                       if (parse_hex_line(buf) == 0) {
-                               //printf("Warning, parse error line %d\n", lineno);
-                               return -2;
-                       }
-               }
-               if (end_record_seen) break;
-               if (feof(stdin)) break;
-       }
-       fclose(fp);
-       return byte_count;
-}
-
-
-/* from ihex.c, at http://www.pjrc.com/tech/8051/pm2_docs/intel-hex.html */
-
-/* parses a line of intel hex code, stores the data in bytes[] */
-/* and the beginning address in addr, and returns a 1 if the */
-/* line was valid, or a 0 if an error occured.  The variable */
-/* num gets the number of bytes that were stored into bytes[] */
-
-
-int
-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;
-       if (addr + extended_addr + len >= MAX_MEMORY_SIZE) return 0;
-        ptr += 2;
-        sum = (len & 255) + ((addr >> 8) & 255) + (addr & 255) + (code & 255);
-       if (code != 0) {
-               if (code == 1) {
-                       end_record_seen = 1;
-                       return 1;
-               }
-               if (code == 2 && len == 2) {
-                       if (!sscanf(ptr, "%04x", &i)) return 1;
-                       ptr += 4;
-                       sum += ((i >> 8) & 255) + (i & 255);
-                       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 (code == 4 && len == 2) {
-                       if (!sscanf(ptr, "%04x", &i)) return 1;
-                       ptr += 4;
-                       sum += ((i >> 8) & 255) + (i & 255);
-                       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
-       }
-       byte_count += len;
-        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;
-}
-
-int ihex_bytes_within_range(int begin, int end)
-{
-       int i;
-
-       if (begin < 0 || begin >= MAX_MEMORY_SIZE ||
-          end < 0 || end >= MAX_MEMORY_SIZE) {
-               return 0;
-       }
-       for (i=begin; i<=end; i++) {
-               if (firmware_mask[i]) return 1;
-       }
-       return 0;
-}
-
-void ihex_get_data(int addr, int len, unsigned char *bytes)
-{
-       int i;
-
-       if (addr < 0 || len < 0 || addr + len >= MAX_MEMORY_SIZE) {
-               for (i=0; i<len; i++) {
-                       bytes[i] = 255;
-               }
-               return;
-       }
-       for (i=0; i<len; i++) {
-               if (firmware_mask[addr]) {
-                       bytes[i] = firmware_image[addr];
-               } else {
-                       bytes[i] = 255;
-               }
-               addr++;
-       }
-}
-
-/****************************************************************/
-/*                                                              */
-/*                       Misc Functions                         */
-/*                                                              */
-/****************************************************************/
-
-int printf_verbose(const char *format, ...)
-{
-       va_list ap;
-       int r;
-
-       va_start(ap, format);
-       if (verbose) {
-               r = vprintf(format, ap);
-               fflush(stdout);
-               return r;
-       }
-       return 0;
-}
-
-void delay(double seconds)
-{
-       #ifdef WIN32
-       Sleep(seconds * 1000.0);
-       #else
-       usleep(seconds * 1000000.0);
-       #endif
-}
-
-void die(const char *str, ...)
-{
-       va_list  ap;
-
-       va_start(ap, str);
-       vfprintf(stderr, str, ap);
-       fprintf(stderr, "\n");
-       exit(1);
-}
-
-#if defined(WIN32)
-#define strcasecmp stricmp
-#endif
-
-void parse_options(int argc, char **argv)
-{
-       int i;
-       const char *arg;
-
-       for (i=1; i<argc; i++) {
-               arg = argv[i];
-               //printf("arg: %s\n", arg);
-               if (*arg == '-') {
-                       if (strcmp(arg, "-w") == 0) {
-                               wait_for_device_to_appear = 1;
-                       } else if (strcmp(arg, "-r") == 0) {
-                               hard_reboot_device = 1;
-                       } else if (strcmp(arg, "-n") == 0) {
-                               reboot_after_programming = 0;
-                       } else if (strcmp(arg, "-v") == 0) {
-                               verbose = 1;
-                       } else if (strncmp(arg, "-mmcu=", 6) == 0) {
-                               if (strcasecmp(arg+6, "at90usb162") == 0) {
-                                       code_size = 15872;
-                                       block_size = 128;
-                               } else if (strcasecmp(arg+6, "atmega32u4") == 0) {
-                                       code_size = 32256;
-                                       block_size = 128;
-                               } else if (strcasecmp(arg+6, "at90usb646") == 0) {
-                                       code_size = 64512;
-                                       block_size = 256;
-                               } else if (strcasecmp(arg+6, "at90usb1286") == 0) {
-                                       code_size = 130048;
-                                       block_size = 256;
-                               } else {
-                                       die("Unknown MCU type\n");
-                               }
-                       }
-               } else {
-                       filename = argv[i];
-               }
-       }
-}
-