]> git.donarmstrong.com Git - kiibohd-controller.git/blobdiff - LoadFile/teensy_loader_cli.c
Fixing CMake dependency checking for kll_defs.h
[kiibohd-controller.git] / LoadFile / teensy_loader_cli.c
index dfe31c1da6ea8a5232f5025bd22d7abe9f9c8ab8..3debc04820d0e7f2f38578018acf1b2860bb5f0a 100644 (file)
@@ -134,7 +134,7 @@ int main(int argc, char **argv)
                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
@@ -192,263 +192,144 @@ int main(int argc, char **argv)
 
 /****************************************************************/
 /*                                                              */
-/*             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
@@ -809,23 +690,23 @@ 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;
+       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;
@@ -835,7 +716,7 @@ parse_hex_line(char *line)
                        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);
@@ -844,27 +725,27 @@ parse_hex_line(char *line)
                        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)