Mercurial > louis > kiibohd-controller
changeset 129:0bad1499ec19
Adding teensy-loader-cli so it's not required.
- This is a patched version to work with Teensy 3.1 (current version on the website doesn't work)
- "Should" work with OS's other than Linux, but hasn't been tested
author | Jacob Alexander <haata@kiibohd.com> |
---|---|
date | Sat, 12 Apr 2014 20:52:32 -0700 |
parents | f10966b3ea8a |
children | 033c3e01322f |
files | CMakeLists.txt LoadFile/CMakeLists.txt LoadFile/FindLibUSB.cmake LoadFile/bash LoadFile/load LoadFile/teensy_loader_cli.c arm.cmake setup.cmake |
diffstat | 8 files changed, 1249 insertions(+), 30 deletions(-) [+] |
line wrap: on
line diff
--- a/CMakeLists.txt Wed Apr 09 21:06:57 2014 -0700 +++ b/CMakeLists.txt Sat Apr 12 20:52:32 2014 -0700 @@ -25,8 +25,8 @@ #| "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}" ) @@ -142,7 +142,8 @@ #| After Changes Size Information #| TODO Do lookup on Flash and RAM sizes and do % used -add_custom_target( SizeAfter ALL ${SIZE} --target=${FORMAT} ${TARGET_HEX} ${TARGET_ELF} +add_custom_target( SizeAfter ALL + COMMAND ${SIZE} --target=${FORMAT} ${TARGET_HEX} ${TARGET_ELF} DEPENDS ${TARGET_ELF} COMMENT "Size after generation\n\tFlash Usage: data (hex)\n\t RAM Usage: data (elf)" ) @@ -150,17 +151,9 @@ ### -# Setup Loader Script +# Setup Loader Script and Program # #| Provides the user with the correct teensy-loader-cli command for the built .HEX file -#| teensy-loader-cli must be in the user's path -if( ${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" ) - configure_file( LoadFile/bash load ) -endif() +configure_file( LoadFile/load load ) -#| TODO Windows -if( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) - configure_file( LoadFile/bash load ) -endif() -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LoadFile/CMakeLists.txt Sat Apr 12 20:52:32 2014 -0700 @@ -0,0 +1,118 @@ +###| CMAKE teensy-loader-cli |### +# +# Jacob Alexander 2014 +# Written to replace the pjrc's kludey Makefiles +# (that require hand edits for different platforms) +# +# Released into the Public Domain +# +### + +#| Windows / Cygwin Compatibility options +set( CMAKE_LEGACY_CYGWIN_WIN32 0 ) +set( CMAKE_USE_RELATIVE_PATHS 1 ) + + + +### +# Project Description +# + +#| Project +project( teensy-loader-cli ) + +#| Target Name (output name) +set( TARGET teensy-loader-cli ) + +#| General Settings +cmake_minimum_required( VERSION 2.8 ) + + + +### +# Source Defines +# + +#| Sources +set( SRCS + teensy_loader_cli.c +) + + + +### +# Platform Setup +# +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 ) + + # Defines + set( DEFINES -s -DUSE_LIBUSB ) + + # Include directories + set( INCLUDE_DIRS ${LIBUSB_INCLUDE_DIRS} ) + + # Libraries + set( LIBS ${LIBUSB_LIBRARIES} ) + +#| Windows +elseif( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + message( AUTHOR_WARNING "Not Tested...") + + # Defines + set( DEFINES -s -DUSE_WIN32 ) + + # Libraries + set( LIBS hid setupapi ) + +#| Mac OS X +elseif( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" ) + message( AUTHOR_WARNING "Not Tested...") + + # Defines - XXX What is SDK? + set( DEFINES -DUSE_APPLE_IOKIT -isysroot ${SDK} -Wl,-syslibroot,${SDK} -framework IOKit -framework CoreFoundation ) + +#| BSD - NetBSD and OpenBSD +elseif( ${CMAKE_SYSTEM_NAME} MATCHES "BSD" ) + message( AUTHOR_WARNING "Not Tested...") + + # Defines + set( DEFINES -s -DUSE_UHID ) +endif() + + + +### +# Defines +# + +#| Default CFLAGS +set( CFLAGS -O2 -Wall ) + +add_definitions( ${CFLAGS} ${DEFINES} ) + + + +### +# Includes +# + +#| Linux +include_directories( ${INCLUDE_DIRS} ) + + + +### +# Build Targets +# + +#| Create the executable +add_executable( ${TARGET} ${SRCS} ) + +#| Link executable +target_link_libraries( ${TARGET} ${LIBS} ) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LoadFile/FindLibUSB.cmake Sat Apr 12 20:52:32 2014 -0700 @@ -0,0 +1,94 @@ +# Attempts to find libusb (not libusb-1.0) +# +# LIBUSB_FOUND - system has libusb +# LIBUSB_INCLUDE_DIRS - the libusb include directory +# LIBUSB_LIBRARIES - Link these to use libusb +# LIBUSB_DEFINITIONS - Compiler switches required for using libusb +# +# Adapted from cmake-modules Google Code project +# +# Copyright (c) 2006 Andreas Schneider <mail@cynapses.org> +# +# (Changes for libusb) Copyright (c) 2014 Jacob Alexander <haata@kiibohd.com> +# +# Redistribution and use is allowed according to the terms of the New BSD license. +# +# CMake-Modules Project New BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of the CMake-Modules Project nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + + +if ( LIBUSB_LIBRARIES AND LIBUSB_INCLUDE_DIRS ) + # in cache already + set( LIBUSB_FOUND TRUE ) +else () + find_path( LIBUSB_INCLUDE_DIR + NAMES + usb.h + PATHS + /usr/include + /usr/local/include + /opt/local/include + /sw/include + /include + ) + + find_library( LIBUSB_LIBRARY + NAMES + usb + PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /sw/lib + /lib + ) + + set( LIBUSB_INCLUDE_DIRS ${LIBUSB_INCLUDE_DIR} ) + set( LIBUSB_LIBRARIES ${LIBUSB_LIBRARY} ) + + if ( LIBUSB_INCLUDE_DIRS AND LIBUSB_LIBRARIES ) + set( LIBUSB_FOUND TRUE ) + endif () + + if ( LIBUSB_FOUND ) + if ( NOT LIBUSB_FIND_QUIETLY ) + message( STATUS "Found libusb:" ) + message( STATUS " - Includes: ${LIBUSB_INCLUDE_DIRS}" ) + message( STATUS " - Libraries: ${LIBUSB_LIBRARIES}" ) + endif () + else () + if ( LIBUSB_FIND_REQUIRED ) + message( FATAL_ERROR "Could not find libusb" ) + endif () + endif () + + # show the LIBUSB_INCLUDE_DIRS and LIBUSB_LIBRARIES variables only in the advanced view + mark_as_advanced( LIBUSB_INCLUDE_DIRS LIBUSB_LIBRARIES ) + +endif () +
--- a/LoadFile/bash Wed Apr 09 21:06:57 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -#!/bin/bash - -#| Loads the hex file onto the teensy - -sudo teensy-loader-cli -mmcu=@MCU@ -w @TARGET_HEX@ - -exit 0 -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LoadFile/load Sat Apr 12 20:52:32 2014 -0700 @@ -0,0 +1,16 @@ +#!/bin/bash + +#| First check to see teensy-loader-cli has been compiled +if [ ! -e teensy-loader-cli/teensy-loader-cli ]; then + # Compile teensy-loader-cli + mkdir -p teensy-loader-cli + cd teensy-loader-cli + cmake @CMAKE_SOURCE_DIR@/LoadFile + make +fi + +#| Loads the hex file onto the teensy +sudo teensy-loader-cli/teensy-loader-cli -mmcu=@MCU@ -w @TARGET_HEX@ + +exit 0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LoadFile/teensy_loader_cli.c Sat Apr 12 20:52:32 2014 -0700 @@ -0,0 +1,1009 @@ +/* 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 + * Modifications 2014, Jacob Alexander <haata@kiibohd.com> + * + * 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"); +#if defined(USE_LIBUSB) + fprintf(stderr, "\n<MCU> = atmega32u4 | at90usb162 | at90usb646 | at90usb1286 | mk20dx128 | mk20dx256\n"); +#else + fprintf(stderr, "\n<MCU> = atmega32u4 | at90usb162 | at90usb646 | at90usb1286\n"); +#endif + 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); +int memory_is_blank(int addr, int block_size); + +// 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[2048]; + int num, addr, r, write_size=block_size+2; + int 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, Kiibohd-Mods\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 (!first_block && !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; + } + if (!first_block && memory_is_blank(addr, block_size)) continue; + printf_verbose("."); + if (code_size < 0x10000) { + buf[0] = addr & 255; + buf[1] = (addr >> 8) & 255; + ihex_get_data(addr, block_size, buf + 2); + write_size = block_size + 2; + } else if (block_size == 256) { + buf[0] = (addr >> 8) & 255; + buf[1] = (addr >> 16) & 255; + ihex_get_data(addr, block_size, buf + 2); + write_size = block_size + 2; + } else if (block_size >= 1024) { + buf[0] = addr & 255; + buf[1] = (addr >> 8) & 255; + buf[2] = (addr >> 16) & 255; + memset(buf + 3, 0, 61); + ihex_get_data(addr, block_size, buf + 64); + write_size = block_size + 64; + } else { + die("Unknown code/block size\n"); + } + r = teensy_write(buf, write_size, 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; + buf[2] = 0xFF; + memset(buf + 3, 0, sizeof(buf) - 3); + teensy_write(buf, write_size, 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; + 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; +} + +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 0x40000 + +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, HEX 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++; + } +} + +int memory_is_blank(int addr, int block_size) +{ + if (addr < 0 || addr > MAX_MEMORY_SIZE) return 1; + + while (block_size && addr < MAX_MEMORY_SIZE) { + if (firmware_mask[addr] && firmware_image[addr] != 255) return 0; + addr++; + block_size--; + } + return 1; +} + + + + +/****************************************************************/ +/* */ +/* 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; +#if defined(USE_LIBUSB) + } else if (strcasecmp(arg+6, "mk20dx128") == 0) { + code_size = 131072; + block_size = 1024; + } else if (strcasecmp(arg+6, "mk20dx256") == 0) { + code_size = 262144; + block_size = 1024; +#endif + } else { + die("Unknown MCU type\n"); + } + } + } else { + filename = argv[i]; + } + } +} +
--- a/arm.cmake Wed Apr 09 21:06:57 2014 -0700 +++ b/arm.cmake Sat Apr 12 20:52:32 2014 -0700 @@ -35,8 +35,8 @@ #| #| "mk20dx128" # Teensy 3.0 #| "mk20dx256" # Teensy 3.1 -set( CHIP "mk20dx128" ) -#set( CHIP "mk20dx256" ) +#set( CHIP "mk20dx128" ) +set( CHIP "mk20dx256" ) message( STATUS "Chip Selected:" ) message( "${CHIP}" )
--- a/setup.cmake Wed Apr 09 21:06:57 2014 -0700 +++ b/setup.cmake Sat Apr 12 20:52:32 2014 -0700 @@ -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 "SKM67001" ) +set( ScanModule "ADCTest" ) ##| Provides the mapping functions for DefaultMap and handles any macro processing before sending to the OutputModule set( MacroModule "PartialMap" ) @@ -203,7 +203,6 @@ execute_process( COMMAND git show -s --format=%ci WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_VARIABLE Git_Date_INFO - RESULT_VARIABLE Git_RETURN ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE ) @@ -212,7 +211,6 @@ execute_process( COMMAND git show -s --format="%cn <%ce>" WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_VARIABLE Git_Commit_Author - RESULT_VARIABLE Git_RETURN ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE ) @@ -221,7 +219,6 @@ execute_process( COMMAND git show -s --format=%H WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_VARIABLE Git_Commit_Revision - RESULT_VARIABLE Git_RETURN ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE ) @@ -230,19 +227,19 @@ execute_process( COMMAND git config --get remote.origin.url WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_VARIABLE Git_Origin_URL - RESULT_VARIABLE Git_RETURN ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE ) #| Build Date execute_process( COMMAND "date" "+%Y-%m-%d %T %z" - OUTPUT_VARIABLE ${RESULT} + OUTPUT_VARIABLE Build_Date + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE ) #| Last Commit Date -set( GitLastCommitDate "${Git_Modified_Flag_INFO}${Git_Branch_INFO} - ${Git_Date_INFO}" ) +set( GitLastCommitDate "${Git_Modified_Status} ${Git_Branch_INFO} - ${Git_Date_INFO}" ) #| Uses CMake variables to include as defines #| Primarily for USB configuration