1 /* Teensy Loader, Command Line Interface
2 * Program and Reboot Teensy Board with HalfKay Bootloader
3 * http://www.pjrc.com/teensy/loader_cli.html
4 * Copyright 2008-2010, PJRC.COM, LLC
5 * Modifications 2014, Jacob Alexander <haata@kiibohd.com>
7 * You may redistribute this program and/or modify it under the terms
8 * of the GNU General Public License as published by the Free Software
9 * Foundation, version 3 of the License.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see http://www.gnu.org/licenses/
20 /* Want to incorporate this code into a proprietary application??
21 * Just email paul@pjrc.com to ask. Usually it's not a problem,
22 * but you do need to ask to use this code in any way other than
23 * those permitted by the GNU General Public License, version 3 */
25 /* For non-root permissions on ubuntu or similar udev-based linux
26 * http://www.pjrc.com/teensy/49-teensy.rules
39 fprintf(stderr, "Usage: teensy_loader_cli -mmcu=<MCU> [-w] [-h] [-n] [-v] <file.hex>\n");
40 fprintf(stderr, "\t-w : Wait for device to appear\n");
41 fprintf(stderr, "\t-r : Use hard reboot if device not online\n");
42 fprintf(stderr, "\t-n : No reboot after programming\n");
43 fprintf(stderr, "\t-v : Verbose output\n");
44 #if defined(USE_LIBUSB)
45 fprintf(stderr, "\n<MCU> = atmega32u4 | at90usb162 | at90usb646 | at90usb1286 | mk20dx128 | mk20dx256\n");
47 fprintf(stderr, "\n<MCU> = atmega32u4 | at90usb162 | at90usb646 | at90usb1286\n");
49 fprintf(stderr, "\nFor more information, please visit:\n");
50 fprintf(stderr, "http://www.pjrc.com/teensy/loader_cli.html\n");
54 // USB Access Functions
55 int teensy_open(void);
56 int teensy_write(void *buf, int len, double timeout);
57 void teensy_close(void);
58 int hard_reboot(void);
60 // Intel Hex File Functions
61 int read_intel_hex(const char *filename);
62 int ihex_bytes_within_range(int begin, int end);
63 void ihex_get_data(int addr, int len, unsigned char *bytes);
64 int memory_is_blank(int addr, int block_size);
67 int printf_verbose(const char *format, ...);
68 void delay(double seconds);
69 void die(const char *str, ...);
70 void parse_options(int argc, char **argv);
72 // options (from user via command line args)
73 int wait_for_device_to_appear = 0;
74 int hard_reboot_device = 0;
75 int reboot_after_programming = 1;
77 int code_size = 0, block_size = 0;
78 const char *filename=NULL;
81 /****************************************************************/
85 /****************************************************************/
87 int main(int argc, char **argv)
89 unsigned char buf[2048];
90 int num, addr, r, write_size=block_size+2;
91 int first_block=1, waited=0;
93 // parse command line arguments
94 parse_options(argc, argv);
96 fprintf(stderr, "Filename must be specified\n\n");
100 fprintf(stderr, "MCU type must be specified\n\n");
103 printf_verbose("Teensy Loader, Command Line, Version 2.0, Kiibohd-Mods\n");
105 // read the intel hex file
106 // this is done first so any error is reported before using USB
107 num = read_intel_hex(filename);
108 if (num < 0) die("error reading intel hex file \"%s\"", filename);
109 printf_verbose("Read \"%s\": %d bytes, %.1f%% usage\n",
110 filename, num, (double)num / (double)code_size * 100.0);
112 // open the USB device
114 if (teensy_open()) break;
115 if (hard_reboot_device) {
116 if (!hard_reboot()) die("Unable to find rebootor\n");
117 printf_verbose("Hard Reboot performed\n");
118 hard_reboot_device = 0; // only hard reboot once
119 wait_for_device_to_appear = 1;
121 if (!wait_for_device_to_appear) die("Unable to open device\n");
123 printf_verbose("Waiting for Teensy device...\n");
124 printf_verbose(" (hint: press the reset button)\n");
129 printf_verbose("Found HalfKay Bootloader\n");
131 // if we waited for the device, read the hex file again
132 // perhaps it changed while we were waiting?
134 num = read_intel_hex(filename);
135 if (num < 0) die("error reading intel hex file \"%s\"", filename);
136 printf_verbose("Read \"%s\": %d bytes, %.1f%% usage\n",
137 filename, num, (double)num / (double)code_size * 100.0);
141 printf_verbose("Programming");
143 for (addr = 0; addr < code_size; addr += block_size) {
144 if (!first_block && !ihex_bytes_within_range(addr, addr + block_size - 1)) {
145 // don't waste time on blocks that are unused,
146 // but always do the first one to erase the chip
149 if (!first_block && memory_is_blank(addr, block_size)) continue;
151 if (code_size < 0x10000) {
153 buf[1] = (addr >> 8) & 255;
154 ihex_get_data(addr, block_size, buf + 2);
155 write_size = block_size + 2;
156 } else if (block_size == 256) {
157 buf[0] = (addr >> 8) & 255;
158 buf[1] = (addr >> 16) & 255;
159 ihex_get_data(addr, block_size, buf + 2);
160 write_size = block_size + 2;
161 } else if (block_size >= 1024) {
163 buf[1] = (addr >> 8) & 255;
164 buf[2] = (addr >> 16) & 255;
165 memset(buf + 3, 0, 61);
166 ihex_get_data(addr, block_size, buf + 64);
167 write_size = block_size + 64;
169 die("Unknown code/block size\n");
171 r = teensy_write(buf, write_size, first_block ? 3.0 : 0.25);
172 if (!r) die("error writing to Teensy\n");
175 printf_verbose("\n");
177 // reboot to the user's new code
178 if (reboot_after_programming) {
179 printf_verbose("Booting\n");
183 memset(buf + 3, 0, sizeof(buf) - 3);
184 teensy_write(buf, write_size, 0.25);
193 /****************************************************************/
195 /* USB Access - libusb (Linux & FreeBSD) */
197 /****************************************************************/
199 #if defined(USE_LIBUSB)
201 // http://libusb.sourceforge.net/doc/index.html
204 usb_dev_handle * open_usb_device(int vid, int pid)
207 struct usb_device *dev;
215 //printf_verbose("\nSearching for USB device:\n");
216 for (bus = usb_get_busses(); bus; bus = bus->next) {
217 for (dev = bus->devices; dev; dev = dev->next) {
218 //printf_verbose("bus \"%s\", device \"%s\" vid=%04X, pid=%04X\n",
219 // bus->dirname, dev->filename,
220 // dev->descriptor.idVendor,
221 // dev->descriptor.idProduct
223 if (dev->descriptor.idVendor != vid) continue;
224 if (dev->descriptor.idProduct != pid) continue;
227 printf_verbose("Found device but unable to open");
230 #ifdef LIBUSB_HAS_GET_DRIVER_NP
231 r = usb_get_driver_np(h, 0, buf, sizeof(buf));
233 r = usb_detach_kernel_driver_np(h, 0);
236 printf_verbose("Device is in use by \"%s\" driver", buf);
241 // Mac OS-X - removing this call to usb_claim_interface() might allow
242 // this to work, even though it is a clear misuse of the libusb API.
243 // normally Apple's IOKit should be used on Mac OS-X
244 r = usb_claim_interface(h, 0);
247 printf_verbose("Unable to claim interface, check USB permissions");
256 static usb_dev_handle *libusb_teensy_handle = NULL;
258 int teensy_open(void)
261 libusb_teensy_handle = open_usb_device(0x16C0, 0x0478);
262 if (libusb_teensy_handle) return 1;
266 int teensy_write(void *buf, int len, double timeout)
270 if (!libusb_teensy_handle) return 0;
271 while (timeout > 0) {
272 r = usb_control_msg(libusb_teensy_handle, 0x21, 9, 0x0200, 0,
273 (char *)buf, len, (int)(timeout * 1000.0));
274 if (r >= 0) return 1;
275 //printf("teensy_write, r=%d\n", r);
277 timeout -= 0.01; // TODO: subtract actual elapsed time
282 void teensy_close(void)
284 if (!libusb_teensy_handle) return;
285 usb_release_interface(libusb_teensy_handle, 0);
286 usb_close(libusb_teensy_handle);
287 libusb_teensy_handle = NULL;
290 int hard_reboot(void)
292 usb_dev_handle *rebootor;
295 rebootor = open_usb_device(0x16C0, 0x0477);
296 if (!rebootor) return 0;
297 r = usb_control_msg(rebootor, 0x21, 9, 0x0200, 0, "reboot", 6, 100);
298 usb_release_interface(rebootor, 0);
307 /****************************************************************/
309 /* USB Access - Microsoft WIN32 */
311 /****************************************************************/
313 #if defined(USE_WIN32)
315 // http://msdn.microsoft.com/en-us/library/ms790932.aspx
317 #include <setupapi.h>
318 #include <ddk/hidsdi.h>
319 #include <ddk/hidclass.h>
321 HANDLE open_usb_device(int vid, int pid)
325 DWORD index, required_size;
326 SP_DEVICE_INTERFACE_DATA iface;
327 SP_DEVICE_INTERFACE_DETAIL_DATA *details;
328 HIDD_ATTRIBUTES attrib;
332 HidD_GetHidGuid(&guid);
333 info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
334 if (info == INVALID_HANDLE_VALUE) return NULL;
335 for (index=0; 1 ;index++) {
336 iface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
337 ret = SetupDiEnumDeviceInterfaces(info, NULL, &guid, index, &iface);
339 SetupDiDestroyDeviceInfoList(info);
342 SetupDiGetInterfaceDeviceDetail(info, &iface, NULL, 0, &required_size, NULL);
343 details = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(required_size);
344 if (details == NULL) continue;
345 memset(details, 0, required_size);
346 details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
347 ret = SetupDiGetDeviceInterfaceDetail(info, &iface, details,
348 required_size, NULL, NULL);
353 h = CreateFile(details->DevicePath, GENERIC_READ|GENERIC_WRITE,
354 FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
355 FILE_FLAG_OVERLAPPED, NULL);
357 if (h == INVALID_HANDLE_VALUE) continue;
358 attrib.Size = sizeof(HIDD_ATTRIBUTES);
359 ret = HidD_GetAttributes(h, &attrib);
364 if (attrib.VendorID != vid || attrib.ProductID != pid) {
368 SetupDiDestroyDeviceInfoList(info);
374 int write_usb_device(HANDLE h, void *buf, int len, int timeout)
376 static HANDLE event = NULL;
377 unsigned char tmpbuf[1040];
381 if (len > sizeof(tmpbuf) - 1) return 0;
383 event = CreateEvent(NULL, TRUE, TRUE, NULL);
384 if (!event) return 0;
387 memset(&ov, 0, sizeof(ov));
390 memcpy(tmpbuf + 1, buf, len);
391 if (!WriteFile(h, tmpbuf, len + 1, NULL, &ov)) {
392 if (GetLastError() != ERROR_IO_PENDING) return 0;
393 r = WaitForSingleObject(event, timeout);
394 if (r == WAIT_TIMEOUT) {
398 if (r != WAIT_OBJECT_0) return 0;
400 if (!GetOverlappedResult(h, &ov, &n, FALSE)) return 0;
401 if (n <= 0) return 0;
405 void print_win32_err(void)
410 err = GetLastError();
411 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
412 0, buf, sizeof(buf), NULL);
413 printf("err %ld: %s\n", err, buf);
416 static HANDLE win32_teensy_handle = NULL;
418 int teensy_open(void)
421 win32_teensy_handle = open_usb_device(0x16C0, 0x0478);
422 if (win32_teensy_handle) return 1;
426 int teensy_write(void *buf, int len, double timeout)
429 if (!win32_teensy_handle) return 0;
430 r = write_usb_device(win32_teensy_handle, buf, len, (int)(timeout * 1000.0));
431 //if (!r) print_win32_err();
435 void teensy_close(void)
437 if (!win32_teensy_handle) return;
438 CloseHandle(win32_teensy_handle);
439 win32_teensy_handle = NULL;
442 int hard_reboot(void)
447 rebootor = open_usb_device(0x16C0, 0x0477);
448 if (!rebootor) return 0;
449 r = write_usb_device(rebootor, "reboot", 6, 100);
450 CloseHandle(rebootor);
458 /****************************************************************/
460 /* USB Access - Apple's IOKit, Mac OS-X */
462 /****************************************************************/
464 #if defined(USE_APPLE_IOKIT)
466 // http://developer.apple.com/technotes/tn2007/tn2187.html
467 #include <IOKit/IOKitLib.h>
468 #include <IOKit/hid/IOHIDLib.h>
469 #include <IOKit/hid/IOHIDDevice.h>
471 struct usb_list_struct {
475 struct usb_list_struct *next;
478 static struct usb_list_struct *usb_list=NULL;
479 static IOHIDManagerRef hid_manager=NULL;
481 void attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev)
484 struct usb_list_struct *n, *p;
488 type = IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDVendorIDKey));
489 if (!type || CFGetTypeID(type) != CFNumberGetTypeID()) return;
490 if (!CFNumberGetValue((CFNumberRef)type, kCFNumberSInt32Type, &vid)) return;
491 type = IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDProductIDKey));
492 if (!type || CFGetTypeID(type) != CFNumberGetTypeID()) return;
493 if (!CFNumberGetValue((CFNumberRef)type, kCFNumberSInt32Type, &pid)) return;
494 n = (struct usb_list_struct *)malloc(sizeof(struct usb_list_struct));
496 //printf("attach callback: vid=%04X, pid=%04X\n", vid, pid);
501 if (usb_list == NULL) {
504 for (p = usb_list; p->next; p = p->next) ;
509 void detach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev)
511 struct usb_list_struct *p, *tmp, *prev=NULL;
517 prev->next = p->next;
531 void init_hid_manager(void)
533 CFMutableDictionaryRef dict;
536 if (hid_manager) return;
537 hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
538 if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) {
539 if (hid_manager) CFRelease(hid_manager);
540 printf_verbose("no HID Manager - maybe this is a pre-Leopard (10.5) system?\n");
543 dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
544 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
546 IOHIDManagerSetDeviceMatching(hid_manager, dict);
548 IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
549 IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, attach_callback, NULL);
550 IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, detach_callback, NULL);
551 ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone);
552 if (ret != kIOReturnSuccess) {
553 IOHIDManagerUnscheduleFromRunLoop(hid_manager,
554 CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
555 CFRelease(hid_manager);
556 printf_verbose("Error opening HID Manager");
560 static void do_run_loop(void)
562 while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == kCFRunLoopRunHandledSource) ;
565 IOHIDDeviceRef open_usb_device(int vid, int pid)
567 struct usb_list_struct *p;
572 for (p = usb_list; p; p = p->next) {
573 if (p->vid == vid && p->pid == pid) {
574 ret = IOHIDDeviceOpen(p->ref, kIOHIDOptionsTypeNone);
575 if (ret == kIOReturnSuccess) return p->ref;
581 void close_usb_device(IOHIDDeviceRef dev)
583 struct usb_list_struct *p;
586 for (p = usb_list; p; p = p->next) {
588 IOHIDDeviceClose(dev, kIOHIDOptionsTypeNone);
594 static IOHIDDeviceRef iokit_teensy_reference = NULL;
596 int teensy_open(void)
599 iokit_teensy_reference = open_usb_device(0x16C0, 0x0478);
600 if (iokit_teensy_reference) return 1;
604 int teensy_write(void *buf, int len, double timeout)
608 // timeouts do not work on OS-X
609 // IOHIDDeviceSetReportWithCallback is not implemented
610 // even though Apple documents it with a code example!
611 // submitted to Apple on 22-sep-2009, problem ID 7245050
612 if (!iokit_teensy_reference) return 0;
613 ret = IOHIDDeviceSetReport(iokit_teensy_reference,
614 kIOHIDReportTypeOutput, 0, buf, len);
615 if (ret == kIOReturnSuccess) return 1;
619 void teensy_close(void)
621 if (!iokit_teensy_reference) return;
622 close_usb_device(iokit_teensy_reference);
623 iokit_teensy_reference = NULL;
626 int hard_reboot(void)
628 IOHIDDeviceRef rebootor;
631 rebootor = open_usb_device(0x16C0, 0x0477);
632 if (!rebootor) return 0;
633 ret = IOHIDDeviceSetReport(rebootor,
634 kIOHIDReportTypeOutput, 0, (uint8_t *)("reboot"), 6);
635 close_usb_device(rebootor);
636 if (ret == kIOReturnSuccess) return 1;
644 /****************************************************************/
646 /* USB Access - BSD's UHID driver */
648 /****************************************************************/
650 #if defined(USE_UHID)
652 // Thanks to Todd T Fries for help getting this working on OpenBSD
653 // and to Chris Kuethe for the initial patch to use UHID.
655 #include <sys/ioctl.h>
658 #include <dev/usb/usb.h>
659 #ifndef USB_GET_DEVICEINFO
660 #include <dev/usb/usb_ioctl.h>
663 int open_usb_device(int vid, int pid)
668 struct usb_device_info info;
671 dir = opendir("/dev");
673 while ((d = readdir(dir)) != NULL) {
674 if (strncmp(d->d_name, "uhid", 4) != 0) continue;
675 snprintf(buf, sizeof(buf), "/dev/%s", d->d_name);
676 fd = open(buf, O_RDWR);
677 if (fd < 0) continue;
678 r = ioctl(fd, USB_GET_DEVICEINFO, &info);
680 // NetBSD: added in 2004
681 // OpenBSD: added November 23, 2009
682 // FreeBSD: missing (FreeBSD 8.0) - USE_LIBUSB works!
683 die("Error: your uhid driver does not support"
684 " USB_GET_DEVICEINFO, please upgrade!\n");
689 //printf("%s: v=%d, p=%d\n", buf, info.udi_vendorNo, info.udi_productNo);
690 if (info.udi_vendorNo == vid && info.udi_productNo == pid) {
700 static int uhid_teensy_fd = -1;
702 int teensy_open(void)
705 uhid_teensy_fd = open_usb_device(0x16C0, 0x0478);
706 if (uhid_teensy_fd < 0) return 0;
710 int teensy_write(void *buf, int len, double timeout)
714 // TODO: imeplement timeout... how??
715 r = write(uhid_teensy_fd, buf, len);
716 if (r == len) return 1;
720 void teensy_close(void)
722 if (uhid_teensy_fd >= 0) {
723 close(uhid_teensy_fd);
728 int hard_reboot(void)
732 rebootor_fd = open_usb_device(0x16C0, 0x0477);
733 if (rebootor_fd < 0) return 0;
734 r = write(rebootor_fd, "reboot", 6);
737 if (r == 6) return 1;
745 /****************************************************************/
747 /* Read Intel Hex File */
749 /****************************************************************/
751 // the maximum flash image size we can support
752 // chips with larger memory may be used, but only this
753 // much intel-hex data can be loaded into memory!
754 #define MAX_MEMORY_SIZE 0x40000
756 static unsigned char firmware_image[MAX_MEMORY_SIZE];
757 static unsigned char firmware_mask[MAX_MEMORY_SIZE];
758 static int end_record_seen=0;
759 static int byte_count;
760 static unsigned int extended_addr = 0;
761 static int parse_hex_line(char *line);
763 int read_intel_hex(const char *filename)
771 for (i=0; i<MAX_MEMORY_SIZE; i++) {
772 firmware_image[i] = 0xFF;
773 firmware_mask[i] = 0;
777 fp = fopen(filename, "r");
779 //printf("Unable to read file %s\n", filename);
784 if (!fgets(buf, sizeof(buf), fp)) break;
787 if (parse_hex_line(buf) == 0) {
788 printf("Warning, HEX parse error line %d\n", lineno);
792 if (end_record_seen) break;
793 if (feof(stdin)) break;
800 /* from ihex.c, at http://www.pjrc.com/tech/8051/pm2_docs/intel-hex.html */
802 /* parses a line of intel hex code, stores the data in bytes[] */
803 /* and the beginning address in addr, and returns a 1 if the */
804 /* line was valid, or a 0 if an error occured. The variable */
805 /* num gets the number of bytes that were stored into bytes[] */
809 parse_hex_line(char *line)
812 int sum, len, cksum, i;
816 if (line[0] != ':') return 0;
817 if (strlen(line) < 11) return 0;
819 if (!sscanf(ptr, "%02x", &len)) return 0;
821 if ((int)strlen(line) < (11 + (len * 2)) ) return 0;
822 if (!sscanf(ptr, "%04x", &addr)) return 0;
824 /* printf("Line: length=%d Addr=%d\n", len, addr); */
825 if (!sscanf(ptr, "%02x", &code)) return 0;
826 if (addr + extended_addr + len >= MAX_MEMORY_SIZE) return 0;
828 sum = (len & 255) + ((addr >> 8) & 255) + (addr & 255) + (code & 255);
834 if (code == 2 && len == 2) {
835 if (!sscanf(ptr, "%04x", &i)) return 1;
837 sum += ((i >> 8) & 255) + (i & 255);
838 if (!sscanf(ptr, "%02x", &cksum)) return 1;
839 if (((sum & 255) + (cksum & 255)) & 255) return 1;
840 extended_addr = i << 4;
841 //printf("ext addr = %05X\n", extended_addr);
843 if (code == 4 && len == 2) {
844 if (!sscanf(ptr, "%04x", &i)) return 1;
846 sum += ((i >> 8) & 255) + (i & 255);
847 if (!sscanf(ptr, "%02x", &cksum)) return 1;
848 if (((sum & 255) + (cksum & 255)) & 255) return 1;
849 extended_addr = i << 16;
850 //printf("ext addr = %08X\n", extended_addr);
852 return 1; // non-data line
856 if (sscanf(ptr, "%02x", &i) != 1) return 0;
858 firmware_image[addr + extended_addr + num] = i;
859 firmware_mask[addr + extended_addr + num] = 1;
863 if (num >= 256) return 0;
865 if (!sscanf(ptr, "%02x", &cksum)) return 0;
866 if (((sum & 255) + (cksum & 255)) & 255) return 0; /* checksum error */
870 int ihex_bytes_within_range(int begin, int end)
874 if (begin < 0 || begin >= MAX_MEMORY_SIZE ||
875 end < 0 || end >= MAX_MEMORY_SIZE) {
878 for (i=begin; i<=end; i++) {
879 if (firmware_mask[i]) return 1;
884 void ihex_get_data(int addr, int len, unsigned char *bytes)
888 if (addr < 0 || len < 0 || addr + len >= MAX_MEMORY_SIZE) {
889 for (i=0; i<len; i++) {
894 for (i=0; i<len; i++) {
895 if (firmware_mask[addr]) {
896 bytes[i] = firmware_image[addr];
904 int memory_is_blank(int addr, int block_size)
906 if (addr < 0 || addr > MAX_MEMORY_SIZE) return 1;
908 while (block_size && addr < MAX_MEMORY_SIZE) {
909 if (firmware_mask[addr] && firmware_image[addr] != 255) return 0;
919 /****************************************************************/
923 /****************************************************************/
925 int printf_verbose(const char *format, ...)
930 va_start(ap, format);
932 r = vprintf(format, ap);
939 void delay(double seconds)
942 Sleep(seconds * 1000.0);
944 usleep(seconds * 1000000.0);
948 void die(const char *str, ...)
953 vfprintf(stderr, str, ap);
954 fprintf(stderr, "\n");
959 #define strcasecmp stricmp
962 void parse_options(int argc, char **argv)
967 for (i=1; i<argc; i++) {
969 //printf("arg: %s\n", arg);
971 if (strcmp(arg, "-w") == 0) {
972 wait_for_device_to_appear = 1;
973 } else if (strcmp(arg, "-r") == 0) {
974 hard_reboot_device = 1;
975 } else if (strcmp(arg, "-n") == 0) {
976 reboot_after_programming = 0;
977 } else if (strcmp(arg, "-v") == 0) {
979 } else if (strncmp(arg, "-mmcu=", 6) == 0) {
980 if (strcasecmp(arg+6, "at90usb162") == 0) {
983 } else if (strcasecmp(arg+6, "atmega32u4") == 0) {
986 } else if (strcasecmp(arg+6, "at90usb646") == 0) {
989 } else if (strcasecmp(arg+6, "at90usb1286") == 0) {
992 #if defined(USE_LIBUSB)
993 } else if (strcasecmp(arg+6, "mk20dx128") == 0) {
996 } else if (strcasecmp(arg+6, "mk20dx256") == 0) {
1001 die("Unknown MCU type\n");