1 /* Modified for the LUFA HID Bootloader by Dean Camera
2 * http://www.lufa-lib.org
4 * THIS MODIFIED VERSION IS UNSUPPORTED BY PJRC.
7 /* Teensy Loader, Command Line Interface
8 * Program and Reboot Teensy Board with HalfKay Bootloader
9 * http://www.pjrc.com/teensy/loader_cli.html
10 * Copyright 2008-2010, PJRC.COM, LLC
13 * You may redistribute this program and/or modify it under the terms
14 * of the GNU General Public License as published by the Free Software
15 * Foundation, version 3 of the License.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see http://www.gnu.org/licenses/
26 /* Want to incorporate this code into a proprietary application??
27 * Just email paul@pjrc.com to ask. Usually it's not a problem,
28 * but you do need to ask to use this code in any way other than
29 * those permitted by the GNU General Public License, version 3 */
31 /* For non-root permissions on ubuntu or similar udev-based linux
32 * http://www.pjrc.com/teensy/49-teensy.rules
44 fprintf(stderr, "Usage: hid_bootloader_cli -mmcu=<MCU> [-w] [-h] [-n] [-v] <file.hex>\n");
45 fprintf(stderr, "\t-w : Wait for device to appear\n");
46 fprintf(stderr, "\t-r : Use hard reboot if device not online\n");
47 fprintf(stderr, "\t-n : No reboot after programming\n");
48 fprintf(stderr, "\t-v : Verbose output\n");
49 fprintf(stderr, "\n<MCU> = atmegaXXuY or at90usbXXXY");
51 fprintf(stderr, "\nFor support and more information, please visit:\n");
52 fprintf(stderr, "http://www.lufa-lib.org\n");
54 fprintf(stderr, "\nBased on the TeensyHID command line programmer software:\n");
55 fprintf(stderr, "http://www.pjrc.com/teensy/loader_cli.html\n");
59 // USB Access Functions
60 int teensy_open(void);
61 int teensy_write(void *buf, int len, double timeout);
62 void teensy_close(void);
63 int hard_reboot(void);
65 // Intel Hex File Functions
66 int read_intel_hex(const char *filename);
67 int ihex_bytes_within_range(int begin, int end);
68 void ihex_get_data(int addr, int len, unsigned char *bytes);
71 int printf_verbose(const char *format, ...);
72 void delay(double seconds);
73 void die(const char *str, ...);
74 void parse_options(int argc, char **argv);
76 // options (from user via command line args)
77 int wait_for_device_to_appear = 0;
78 int hard_reboot_device = 0;
79 int reboot_after_programming = 1;
81 int code_size = 0, block_size = 0;
82 const char *filename=NULL;
85 /****************************************************************/
89 /****************************************************************/
91 int main(int argc, char **argv)
93 unsigned char buf[260];
94 int num, addr, r, first_block=1, waited=0;
96 // parse command line arguments
97 parse_options(argc, argv);
99 fprintf(stderr, "Filename must be specified\n\n");
103 fprintf(stderr, "MCU type must be specified\n\n");
106 printf_verbose("Teensy Loader, Command Line, Version 2.0\n");
108 // read the intel hex file
109 // this is done first so any error is reported before using USB
110 num = read_intel_hex(filename);
111 if (num < 0) die("error reading intel hex file \"%s\"", filename);
112 printf_verbose("Read \"%s\": %d bytes, %.1f%% usage\n",
113 filename, num, (double)num / (double)code_size * 100.0);
115 // open the USB device
117 if (teensy_open()) break;
118 if (hard_reboot_device) {
119 if (!hard_reboot()) die("Unable to find rebootor\n");
120 printf_verbose("Hard Reboot performed\n");
121 hard_reboot_device = 0; // only hard reboot once
122 wait_for_device_to_appear = 1;
124 if (!wait_for_device_to_appear) die("Unable to open device\n");
126 printf_verbose("Waiting for Teensy device...\n");
127 printf_verbose(" (hint: press the reset button)\n");
132 printf_verbose("Found HalfKay Bootloader\n");
134 // if we waited for the device, read the hex file again
135 // perhaps it changed while we were waiting?
137 num = read_intel_hex(filename);
138 if (num < 0) die("error reading intel hex file \"%s\"", filename);
139 printf_verbose("Read \"%s\": %d bytes, %.1f%% usage\n",
140 filename, num, (double)num / (double)code_size * 100.0);
144 printf_verbose("Programming");
146 for (addr = 0; addr < code_size; addr += block_size) {
147 if (addr > 0 && !ihex_bytes_within_range(addr, addr + block_size - 1)) {
148 // don't waste time on blocks that are unused,
149 // but always do the first one to erase the chip
153 if (code_size < 0x10000) {
155 buf[1] = (addr >> 8) & 255;
157 buf[0] = (addr >> 8) & 255;
158 buf[1] = (addr >> 16) & 255;
160 ihex_get_data(addr, block_size, buf + 2);
161 r = teensy_write(buf, block_size + 2, first_block ? 3.0 : 0.25);
162 if (!r) die("error writing to Teensy\n");
165 printf_verbose("\n");
167 // reboot to the user's new code
168 if (reboot_after_programming) {
169 printf_verbose("Booting\n");
172 memset(buf + 2, 0, sizeof(buf) - 2);
173 teensy_write(buf, block_size + 2, 0.25);
182 /****************************************************************/
184 /* USB Access - libusb (Linux & FreeBSD) */
186 /****************************************************************/
188 #if defined(USE_LIBUSB)
190 // http://libusb.sourceforge.net/doc/index.html
193 usb_dev_handle * open_usb_device(int vid, int pid)
196 struct usb_device *dev;
198 #ifdef LIBUSB_HAS_GET_DRIVER_NP
206 //printf_verbose("\nSearching for USB device:\n");
207 for (bus = usb_get_busses(); bus; bus = bus->next) {
208 for (dev = bus->devices; dev; dev = dev->next) {
209 //printf_verbose("bus \"%s\", device \"%s\" vid=%04X, pid=%04X\n",
210 // bus->dirname, dev->filename,
211 // dev->descriptor.idVendor,
212 // dev->descriptor.idProduct
214 if (dev->descriptor.idVendor != vid) continue;
215 if (dev->descriptor.idProduct != pid) continue;
218 printf_verbose("Found device but unable to open");
221 #ifdef LIBUSB_HAS_GET_DRIVER_NP
222 r = usb_get_driver_np(h, 0, buf, sizeof(buf));
224 r = usb_detach_kernel_driver_np(h, 0);
227 printf_verbose("Device is in use by \"%s\" driver", buf);
232 // Mac OS-X - removing this call to usb_claim_interface() might allow
233 // this to work, even though it is a clear misuse of the libusb API.
234 // normally Apple's IOKit should be used on Mac OS-X
235 r = usb_claim_interface(h, 0);
238 printf_verbose("Unable to claim interface, check USB permissions");
247 static usb_dev_handle *libusb_teensy_handle = NULL;
249 int teensy_open(void)
252 libusb_teensy_handle = open_usb_device(0x16C0, 0x0478);
254 if (!libusb_teensy_handle)
255 libusb_teensy_handle = open_usb_device(0x03eb, 0x2067);
257 if (!libusb_teensy_handle) return 0;
261 int teensy_write(void *buf, int len, double timeout)
265 if (!libusb_teensy_handle) return 0;
266 r = usb_control_msg(libusb_teensy_handle, 0x21, 9, 0x0200, 0, (char *)buf,
267 len, (int)(timeout * 1000.0));
272 void teensy_close(void)
274 if (!libusb_teensy_handle) return;
275 usb_release_interface(libusb_teensy_handle, 0);
276 usb_close(libusb_teensy_handle);
277 libusb_teensy_handle = NULL;
280 int hard_reboot(void)
282 usb_dev_handle *rebootor;
285 rebootor = open_usb_device(0x16C0, 0x0477);
288 rebootor = open_usb_device(0x03eb, 0x2067);
290 if (!rebootor) return 0;
291 r = usb_control_msg(rebootor, 0x21, 9, 0x0200, 0, "reboot", 6, 100);
292 usb_release_interface(rebootor, 0);
301 /****************************************************************/
303 /* USB Access - Microsoft WIN32 */
305 /****************************************************************/
307 #if defined(USE_WIN32)
309 // http://msdn.microsoft.com/en-us/library/ms790932.aspx
311 #include <setupapi.h>
312 #include <ddk/hidsdi.h>
313 #include <ddk/hidclass.h>
315 HANDLE open_usb_device(int vid, int pid)
319 DWORD index, required_size;
320 SP_DEVICE_INTERFACE_DATA iface;
321 SP_DEVICE_INTERFACE_DETAIL_DATA *details;
322 HIDD_ATTRIBUTES attrib;
326 HidD_GetHidGuid(&guid);
327 info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
328 if (info == INVALID_HANDLE_VALUE) return NULL;
329 for (index=0; 1 ;index++) {
330 iface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
331 ret = SetupDiEnumDeviceInterfaces(info, NULL, &guid, index, &iface);
333 SetupDiDestroyDeviceInfoList(info);
336 SetupDiGetInterfaceDeviceDetail(info, &iface, NULL, 0, &required_size, NULL);
337 details = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(required_size);
338 if (details == NULL) continue;
339 memset(details, 0, required_size);
340 details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
341 ret = SetupDiGetDeviceInterfaceDetail(info, &iface, details,
342 required_size, NULL, NULL);
347 h = CreateFile(details->DevicePath, GENERIC_READ|GENERIC_WRITE,
348 FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
349 FILE_FLAG_OVERLAPPED, NULL);
351 if (h == INVALID_HANDLE_VALUE) continue;
352 attrib.Size = sizeof(HIDD_ATTRIBUTES);
353 ret = HidD_GetAttributes(h, &attrib);
358 if (attrib.VendorID != vid || attrib.ProductID != pid) {
362 SetupDiDestroyDeviceInfoList(info);
368 int write_usb_device(HANDLE h, void *buf, int len, int timeout)
370 static HANDLE event = NULL;
371 unsigned char tmpbuf[1040];
375 if (len > sizeof(tmpbuf) - 1) return 0;
377 event = CreateEvent(NULL, TRUE, TRUE, NULL);
378 if (!event) return 0;
381 memset(&ov, 0, sizeof(ov));
384 memcpy(tmpbuf + 1, buf, len);
385 if (!WriteFile(h, tmpbuf, len + 1, NULL, &ov)) {
386 if (GetLastError() != ERROR_IO_PENDING) return 0;
387 r = WaitForSingleObject(event, timeout);
388 if (r == WAIT_TIMEOUT) {
392 if (r != WAIT_OBJECT_0) return 0;
394 if (!GetOverlappedResult(h, &ov, &n, FALSE)) return 0;
398 static HANDLE win32_teensy_handle = NULL;
400 int teensy_open(void)
403 win32_teensy_handle = open_usb_device(0x16C0, 0x0478);
405 if (!win32_teensy_handle)
406 win32_teensy_handle = open_usb_device(0x03eb, 0x2067);
408 if (!win32_teensy_handle) return 0;
412 int teensy_write(void *buf, int len, double timeout)
415 if (!win32_teensy_handle) return 0;
416 r = write_usb_device(win32_teensy_handle, buf, len, (int)(timeout * 1000.0));
420 void teensy_close(void)
422 if (!win32_teensy_handle) return;
423 CloseHandle(win32_teensy_handle);
424 win32_teensy_handle = NULL;
427 int hard_reboot(void)
432 rebootor = open_usb_device(0x16C0, 0x0477);
435 rebootor = open_usb_device(0x03eb, 0x2067);
437 if (!rebootor) return 0;
438 r = write_usb_device(rebootor, "reboot", 6, 100);
439 CloseHandle(rebootor);
447 /****************************************************************/
449 /* USB Access - Apple's IOKit, Mac OS-X */
451 /****************************************************************/
453 #if defined(USE_APPLE_IOKIT)
455 // http://developer.apple.com/technotes/tn2007/tn2187.html
456 #include <IOKit/IOKitLib.h>
457 #include <IOKit/hid/IOHIDLib.h>
458 #include <IOKit/hid/IOHIDDevice.h>
460 struct usb_list_struct {
464 struct usb_list_struct *next;
467 static struct usb_list_struct *usb_list=NULL;
468 static IOHIDManagerRef hid_manager=NULL;
470 void attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev)
473 struct usb_list_struct *n, *p;
477 type = IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDVendorIDKey));
478 if (!type || CFGetTypeID(type) != CFNumberGetTypeID()) return;
479 if (!CFNumberGetValue((CFNumberRef)type, kCFNumberSInt32Type, &vid)) return;
480 type = IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDProductIDKey));
481 if (!type || CFGetTypeID(type) != CFNumberGetTypeID()) return;
482 if (!CFNumberGetValue((CFNumberRef)type, kCFNumberSInt32Type, &pid)) return;
483 n = (struct usb_list_struct *)malloc(sizeof(struct usb_list_struct));
485 //printf("attach callback: vid=%04X, pid=%04X\n", vid, pid);
490 if (usb_list == NULL) {
493 for (p = usb_list; p->next; p = p->next) ;
498 void detach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev)
500 struct usb_list_struct *p, *tmp, *prev=NULL;
506 prev->next = p->next;
520 void init_hid_manager(void)
522 CFMutableDictionaryRef dict;
525 if (hid_manager) return;
526 hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
527 if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) {
528 if (hid_manager) CFRelease(hid_manager);
529 printf_verbose("no HID Manager - maybe this is a pre-Leopard (10.5) system?\n");
532 dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
533 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
535 IOHIDManagerSetDeviceMatching(hid_manager, dict);
537 IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
538 IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, attach_callback, NULL);
539 IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, detach_callback, NULL);
540 ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone);
541 if (ret != kIOReturnSuccess) {
542 IOHIDManagerUnscheduleFromRunLoop(hid_manager,
543 CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
544 CFRelease(hid_manager);
545 printf_verbose("Error opening HID Manager");
549 static void do_run_loop(void)
551 while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == kCFRunLoopRunHandledSource) ;
554 IOHIDDeviceRef open_usb_device(int vid, int pid)
556 struct usb_list_struct *p;
561 for (p = usb_list; p; p = p->next) {
562 if (p->vid == vid && p->pid == pid) {
563 ret = IOHIDDeviceOpen(p->ref, kIOHIDOptionsTypeNone);
564 if (ret == kIOReturnSuccess) return p->ref;
570 void close_usb_device(IOHIDDeviceRef dev)
572 struct usb_list_struct *p;
575 for (p = usb_list; p; p = p->next) {
577 IOHIDDeviceClose(dev, kIOHIDOptionsTypeNone);
583 static IOHIDDeviceRef iokit_teensy_reference = NULL;
585 int teensy_open(void)
588 iokit_teensy_reference = open_usb_device(0x16C0, 0x0478);
590 if (!iokit_teensy_reference)
591 iokit_teensy_reference = open_usb_device(0x03eb, 0x2067);
593 if (!iokit_teensy_reference) return 0;
597 int teensy_write(void *buf, int len, double timeout)
601 // timeouts do not work on OS-X
602 // IOHIDDeviceSetReportWithCallback is not implemented
603 // even though Apple documents it with a code example!
604 // submitted to Apple on 22-sep-2009, problem ID 7245050
605 if (!iokit_teensy_reference) return 0;
606 ret = IOHIDDeviceSetReport(iokit_teensy_reference,
607 kIOHIDReportTypeOutput, 0, buf, len);
608 if (ret == kIOReturnSuccess) return 1;
612 void teensy_close(void)
614 if (!iokit_teensy_reference) return;
615 close_usb_device(iokit_teensy_reference);
616 iokit_teensy_reference = NULL;
619 int hard_reboot(void)
621 IOHIDDeviceRef rebootor;
624 rebootor = open_usb_device(0x16C0, 0x0477);
627 rebootor = open_usb_device(0x03eb, 0x2067);
629 if (!rebootor) return 0;
630 ret = IOHIDDeviceSetReport(rebootor,
631 kIOHIDReportTypeOutput, 0, (uint8_t *)("reboot"), 6);
632 close_usb_device(rebootor);
633 if (ret == kIOReturnSuccess) return 1;
641 /****************************************************************/
643 /* USB Access - BSD's UHID driver */
645 /****************************************************************/
647 #if defined(USE_UHID)
649 // Thanks to Todd T Fries for help getting this working on OpenBSD
650 // and to Chris Kuethe for the initial patch to use UHID.
652 #include <sys/ioctl.h>
655 #include <dev/usb/usb.h>
656 #ifndef USB_GET_DEVICEINFO
657 #include <dev/usb/usb_ioctl.h>
660 #ifndef USB_GET_DEVICEINFO
661 # define USB_GET_DEVICEINFO 0
662 # error The USB_GET_DEVICEINFO ioctl() value is not defined for your system.
665 int open_usb_device(int vid, int pid)
670 struct usb_device_info info;
673 dir = opendir("/dev");
675 while ((d = readdir(dir)) != NULL) {
676 if (strncmp(d->d_name, "uhid", 4) != 0) continue;
677 snprintf(buf, sizeof(buf), "/dev/%s", d->d_name);
678 fd = open(buf, O_RDWR);
679 if (fd < 0) continue;
680 r = ioctl(fd, USB_GET_DEVICEINFO, &info);
682 // NetBSD: added in 2004
683 // OpenBSD: added November 23, 2009
684 // FreeBSD: missing (FreeBSD 8.0) - USE_LIBUSB works!
685 die("Error: your uhid driver does not support"
686 " USB_GET_DEVICEINFO, please upgrade!\n");
691 //printf("%s: v=%d, p=%d\n", buf, info.udi_vendorNo, info.udi_productNo);
692 if (info.udi_vendorNo == vid && info.udi_productNo == pid) {
702 static int uhid_teensy_fd = -1;
704 int teensy_open(void)
707 uhid_teensy_fd = open_usb_device(0x16C0, 0x0478);
709 if (uhid_teensy_fd < 0)
710 uhid_teensy_fd = open_usb_device(0x03eb, 0x2067);
712 if (uhid_teensy_fd < 0) return 0;
716 int teensy_write(void *buf, int len, double timeout)
720 // TODO: implement timeout... how??
721 r = write(uhid_teensy_fd, buf, len);
722 if (r == len) return 1;
726 void teensy_close(void)
728 if (uhid_teensy_fd >= 0) {
729 close(uhid_teensy_fd);
734 int hard_reboot(void)
738 rebootor_fd = open_usb_device(0x16C0, 0x0477);
741 rebootor_fd = open_usb_device(0x03eb, 0x2067);
743 if (rebootor_fd < 0) return 0;
744 r = write(rebootor_fd, "reboot", 6);
747 if (r == 6) return 1;
755 /****************************************************************/
757 /* Read Intel Hex File */
759 /****************************************************************/
761 // the maximum flash image size we can support
762 // chips with larger memory may be used, but only this
763 // much intel-hex data can be loaded into memory!
764 #define MAX_MEMORY_SIZE 0x10000
766 static unsigned char firmware_image[MAX_MEMORY_SIZE];
767 static unsigned char firmware_mask[MAX_MEMORY_SIZE];
768 static int end_record_seen=0;
769 static int byte_count;
770 static unsigned int extended_addr = 0;
771 static int parse_hex_line(char *line);
773 int read_intel_hex(const char *filename)
781 for (i=0; i<MAX_MEMORY_SIZE; i++) {
782 firmware_image[i] = 0xFF;
783 firmware_mask[i] = 0;
787 fp = fopen(filename, "r");
789 //printf("Unable to read file %s\n", filename);
794 if (!fgets(buf, sizeof(buf), fp)) break;
797 if (parse_hex_line(buf) == 0) {
798 //printf("Warning, parse error line %d\n", lineno);
803 if (end_record_seen) break;
804 if (feof(stdin)) break;
811 /* from ihex.c, at http://www.pjrc.com/tech/8051/pm2_docs/intel-hex.html */
813 /* parses a line of intel hex code, stores the data in bytes[] */
814 /* and the beginning address in addr, and returns a 1 if the */
815 /* line was valid, or a 0 if an error occurred. The variable */
816 /* num gets the number of bytes that were stored into bytes[] */
820 parse_hex_line(char *line)
823 int sum, len, cksum, i;
827 if (line[0] != ':') return 0;
828 if (strlen(line) < 11) return 0;
830 if (!sscanf(ptr, "%02x", &len)) return 0;
832 if ((int)strlen(line) < (11 + (len * 2)) ) return 0;
833 if (!sscanf(ptr, "%04x", &addr)) return 0;
835 /* printf("Line: length=%d Addr=%d\n", len, addr); */
836 if (!sscanf(ptr, "%02x", &code)) return 0;
837 if (addr + extended_addr + len >= MAX_MEMORY_SIZE) return 0;
839 sum = (len & 255) + ((addr >> 8) & 255) + (addr & 255) + (code & 255);
845 if (code == 2 && len == 2) {
846 if (!sscanf(ptr, "%04x", &i)) return 1;
848 sum += ((i >> 8) & 255) + (i & 255);
849 if (!sscanf(ptr, "%02x", &cksum)) return 1;
850 if (((sum & 255) + (cksum & 255)) & 255) return 1;
851 extended_addr = i << 4;
852 //printf("ext addr = %05X\n", extended_addr);
854 if (code == 4 && len == 2) {
855 if (!sscanf(ptr, "%04x", &i)) return 1;
857 sum += ((i >> 8) & 255) + (i & 255);
858 if (!sscanf(ptr, "%02x", &cksum)) return 1;
859 if (((sum & 255) + (cksum & 255)) & 255) return 1;
860 extended_addr = i << 16;
861 //printf("ext addr = %08X\n", extended_addr);
863 return 1; // non-data line
867 if (sscanf(ptr, "%02x", &i) != 1) return 0;
869 firmware_image[addr + extended_addr + num] = i;
870 firmware_mask[addr + extended_addr + num] = 1;
874 if (num >= 256) return 0;
876 if (!sscanf(ptr, "%02x", &cksum)) return 0;
877 if (((sum & 255) + (cksum & 255)) & 255) return 0; /* checksum error */
881 int ihex_bytes_within_range(int begin, int end)
885 if (begin < 0 || begin >= MAX_MEMORY_SIZE ||
886 end < 0 || end >= MAX_MEMORY_SIZE) {
889 for (i=begin; i<=end; i++) {
890 if (firmware_mask[i]) return 1;
895 void ihex_get_data(int addr, int len, unsigned char *bytes)
899 if (addr < 0 || len < 0 || addr + len >= MAX_MEMORY_SIZE) {
900 for (i=0; i<len; i++) {
905 for (i=0; i<len; i++) {
906 if (firmware_mask[addr]) {
907 bytes[i] = firmware_image[addr];
915 /****************************************************************/
919 /****************************************************************/
921 int printf_verbose(const char *format, ...)
926 va_start(ap, format);
928 r = vprintf(format, ap);
936 void delay(double seconds)
939 sleep(seconds * 1000.0);
941 usleep(seconds * 1000000.0);
945 void die(const char *str, ...)
950 vfprintf(stderr, str, ap);
951 fprintf(stderr, "\n");
957 #if defined USE_WIN32
958 #define strcasecmp stricmp
961 void parse_options(int argc, char **argv)
966 for (i=1; i<argc; i++) {
970 if (strcmp(arg, "-w") == 0) {
971 wait_for_device_to_appear = 1;
972 } else if (strcmp(arg, "-r") == 0) {
973 hard_reboot_device = 1;
974 } else if (strcmp(arg, "-n") == 0) {
975 reboot_after_programming = 0;
976 } else if (strcmp(arg, "-v") == 0) {
978 } else if (strncmp(arg, "-mmcu=", 6) == 0) {
981 if (strncmp(arg, "at90usb", 7) == 0) {
983 } else if (strncmp(arg, "atmega", 6) == 0) {
986 die("Unknown MCU type\n");
989 if (strncmp(arg, "128", 3) == 0) {
990 code_size = 128 * 1024;
992 } else if (strncmp(arg, "64", 2) == 0) {
993 code_size = 64 * 1024;
995 } else if (strncmp(arg, "32", 2) == 0) {
996 code_size = 32 * 1024;
998 } else if (strncmp(arg, "16", 2) == 0) {
999 code_size = 16 * 1024;
1001 } else if (strncmp(arg, "8", 1) == 0) {
1002 code_size = 8 * 1024;
1005 die("Unknown MCU type\n");