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 void print_win32_err(void)
403 err
= GetLastError();
404 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
, NULL
, err
,
405 0, buf
, sizeof(buf
), NULL
);
406 printf("err %ld: %s\n", err
, buf
);
409 static HANDLE win32_teensy_handle
= NULL
;
411 int teensy_open(void)
414 win32_teensy_handle
= open_usb_device(0x16C0, 0x0478);
416 if (!win32_teensy_handle
)
417 win32_teensy_handle
= open_usb_device(0x03eb, 0x2067);
419 if (!win32_teensy_handle
) return 0;
423 int teensy_write(void *buf
, int len
, double timeout
)
426 if (!win32_teensy_handle
) return 0;
427 r
= write_usb_device(win32_teensy_handle
, buf
, len
, (int)(timeout
* 1000.0));
431 void teensy_close(void)
433 if (!win32_teensy_handle
) return;
434 CloseHandle(win32_teensy_handle
);
435 win32_teensy_handle
= NULL
;
438 int hard_reboot(void)
443 rebootor
= open_usb_device(0x16C0, 0x0477);
446 rebootor
= open_usb_device(0x03eb, 0x2067);
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);
601 if (!iokit_teensy_reference
)
602 iokit_teensy_reference
= open_usb_device(0x03eb, 0x2067);
604 if (!iokit_teensy_reference
) return 0;
608 int teensy_write(void *buf
, int len
, double timeout
)
612 // timeouts do not work on OS-X
613 // IOHIDDeviceSetReportWithCallback is not implemented
614 // even though Apple documents it with a code example!
615 // submitted to Apple on 22-sep-2009, problem ID 7245050
616 if (!iokit_teensy_reference
) return 0;
617 ret
= IOHIDDeviceSetReport(iokit_teensy_reference
,
618 kIOHIDReportTypeOutput
, 0, buf
, len
);
619 if (ret
== kIOReturnSuccess
) return 1;
623 void teensy_close(void)
625 if (!iokit_teensy_reference
) return;
626 close_usb_device(iokit_teensy_reference
);
627 iokit_teensy_reference
= NULL
;
630 int hard_reboot(void)
632 IOHIDDeviceRef rebootor
;
635 rebootor
= open_usb_device(0x16C0, 0x0477);
638 rebootor
= open_usb_device(0x03eb, 0x2067);
640 if (!rebootor
) return 0;
641 ret
= IOHIDDeviceSetReport(rebootor
,
642 kIOHIDReportTypeOutput
, 0, (uint8_t *)("reboot"), 6);
643 close_usb_device(rebootor
);
644 if (ret
== kIOReturnSuccess
) return 1;
652 /****************************************************************/
654 /* USB Access - BSD's UHID driver */
656 /****************************************************************/
658 #if defined(USE_UHID)
660 // Thanks to Todd T Fries for help getting this working on OpenBSD
661 // and to Chris Kuethe for the initial patch to use UHID.
663 #include <sys/ioctl.h>
666 #include <dev/usb/usb.h>
667 #ifndef USB_GET_DEVICEINFO
668 #include <dev/usb/usb_ioctl.h>
671 int open_usb_device(int vid
, int pid
)
676 struct usb_device_info info
;
679 dir
= opendir("/dev");
681 while ((d
= readdir(dir
)) != NULL
) {
682 if (strncmp(d
->d_name
, "uhid", 4) != 0) continue;
683 snprintf(buf
, sizeof(buf
), "/dev/%s", d
->d_name
);
684 fd
= open(buf
, O_RDWR
);
685 if (fd
< 0) continue;
686 r
= ioctl(fd
, USB_GET_DEVICEINFO
, &info
);
688 // NetBSD: added in 2004
689 // OpenBSD: added November 23, 2009
690 // FreeBSD: missing (FreeBSD 8.0) - USE_LIBUSB works!
691 die("Error: your uhid driver does not support"
692 " USB_GET_DEVICEINFO, please upgrade!\n");
697 //printf("%s: v=%d, p=%d\n", buf, info.udi_vendorNo, info.udi_productNo);
698 if (info
.udi_vendorNo
== vid
&& info
.udi_productNo
== pid
) {
708 static int uhid_teensy_fd
= -1;
710 int teensy_open(void)
713 uhid_teensy_fd
= open_usb_device(0x16C0, 0x0478);
715 if (uhid_teensy_fd
< 0)
716 uhid_teensy_fd
= open_usb_device(0x03eb, 0x2067);
718 if (uhid_teensy_fd
< 0) return 0;
722 int teensy_write(void *buf
, int len
, double timeout
)
726 // TODO: imeplement timeout... how??
727 r
= write(uhid_teensy_fd
, buf
, len
);
728 if (r
== len
) return 1;
732 void teensy_close(void)
734 if (uhid_teensy_fd
>= 0) {
735 close(uhid_teensy_fd
);
740 int hard_reboot(void)
744 rebootor_fd
= open_usb_device(0x16C0, 0x0477);
747 rebootor_fd
= open_usb_device(0x03eb, 0x2067);
749 if (rebootor_fd
< 0) return 0;
750 r
= write(rebootor_fd
, "reboot", 6);
753 if (r
== 6) return 1;
761 /****************************************************************/
763 /* Read Intel Hex File */
765 /****************************************************************/
767 // the maximum flash image size we can support
768 // chips with larger memory may be used, but only this
769 // much intel-hex data can be loaded into memory!
770 #define MAX_MEMORY_SIZE 0x10000
772 static unsigned char firmware_image
[MAX_MEMORY_SIZE
];
773 static unsigned char firmware_mask
[MAX_MEMORY_SIZE
];
774 static int end_record_seen
=0;
775 static int byte_count
;
776 static unsigned int extended_addr
= 0;
777 static int parse_hex_line(char *line
);
779 int read_intel_hex(const char *filename
)
787 for (i
=0; i
<MAX_MEMORY_SIZE
; i
++) {
788 firmware_image
[i
] = 0xFF;
789 firmware_mask
[i
] = 0;
793 fp
= fopen(filename
, "r");
795 //printf("Unable to read file %s\n", filename);
800 if (!fgets(buf
, sizeof(buf
), fp
)) break;
803 if (parse_hex_line(buf
) == 0) {
804 //printf("Warning, parse error line %d\n", lineno);
809 if (end_record_seen
) break;
810 if (feof(stdin
)) break;
817 /* from ihex.c, at http://www.pjrc.com/tech/8051/pm2_docs/intel-hex.html */
819 /* parses a line of intel hex code, stores the data in bytes[] */
820 /* and the beginning address in addr, and returns a 1 if the */
821 /* line was valid, or a 0 if an error occured. The variable */
822 /* num gets the number of bytes that were stored into bytes[] */
826 parse_hex_line(char *line
)
829 int sum
, len
, cksum
, i
;
833 if (line
[0] != ':') return 0;
834 if (strlen(line
) < 11) return 0;
836 if (!sscanf(ptr
, "%02x", &len
)) return 0;
838 if ((int)strlen(line
) < (11 + (len
* 2)) ) return 0;
839 if (!sscanf(ptr
, "%04x", &addr
)) return 0;
841 /* printf("Line: length=%d Addr=%d\n", len, addr); */
842 if (!sscanf(ptr
, "%02x", &code
)) return 0;
843 if (addr
+ extended_addr
+ len
>= MAX_MEMORY_SIZE
) return 0;
845 sum
= (len
& 255) + ((addr
>> 8) & 255) + (addr
& 255) + (code
& 255);
851 if (code
== 2 && len
== 2) {
852 if (!sscanf(ptr
, "%04x", &i
)) return 1;
854 sum
+= ((i
>> 8) & 255) + (i
& 255);
855 if (!sscanf(ptr
, "%02x", &cksum
)) return 1;
856 if (((sum
& 255) + (cksum
& 255)) & 255) return 1;
857 extended_addr
= i
<< 4;
858 //printf("ext addr = %05X\n", extended_addr);
860 if (code
== 4 && len
== 2) {
861 if (!sscanf(ptr
, "%04x", &i
)) return 1;
863 sum
+= ((i
>> 8) & 255) + (i
& 255);
864 if (!sscanf(ptr
, "%02x", &cksum
)) return 1;
865 if (((sum
& 255) + (cksum
& 255)) & 255) return 1;
866 extended_addr
= i
<< 16;
867 //printf("ext addr = %08X\n", extended_addr);
869 return 1; // non-data line
873 if (sscanf(ptr
, "%02x", &i
) != 1) return 0;
875 firmware_image
[addr
+ extended_addr
+ num
] = i
;
876 firmware_mask
[addr
+ extended_addr
+ num
] = 1;
880 if (num
>= 256) return 0;
882 if (!sscanf(ptr
, "%02x", &cksum
)) return 0;
883 if (((sum
& 255) + (cksum
& 255)) & 255) return 0; /* checksum error */
887 int ihex_bytes_within_range(int begin
, int end
)
891 if (begin
< 0 || begin
>= MAX_MEMORY_SIZE
||
892 end
< 0 || end
>= MAX_MEMORY_SIZE
) {
895 for (i
=begin
; i
<=end
; i
++) {
896 if (firmware_mask
[i
]) return 1;
901 void ihex_get_data(int addr
, int len
, unsigned char *bytes
)
905 if (addr
< 0 || len
< 0 || addr
+ len
>= MAX_MEMORY_SIZE
) {
906 for (i
=0; i
<len
; i
++) {
911 for (i
=0; i
<len
; i
++) {
912 if (firmware_mask
[addr
]) {
913 bytes
[i
] = firmware_image
[addr
];
921 /****************************************************************/
925 /****************************************************************/
927 int printf_verbose(const char *format
, ...)
932 va_start(ap
, format
);
934 r
= vprintf(format
, ap
);
941 void delay(double seconds
)
944 Sleep(seconds
* 1000.0);
946 usleep(seconds
* 1000000.0);
950 void die(const char *str
, ...)
955 vfprintf(stderr
, str
, ap
);
956 fprintf(stderr
, "\n");
961 #define strcasecmp stricmp
964 void parse_options(int argc
, char **argv
)
969 for (i
=1; i
<argc
; i
++) {
973 if (strcmp(arg
, "-w") == 0) {
974 wait_for_device_to_appear
= 1;
975 } else if (strcmp(arg
, "-r") == 0) {
976 hard_reboot_device
= 1;
977 } else if (strcmp(arg
, "-n") == 0) {
978 reboot_after_programming
= 0;
979 } else if (strcmp(arg
, "-v") == 0) {
981 } else if (strncmp(arg
, "-mmcu=", 6) == 0) {
984 uint8_t valid_prefix
= 0;
986 if (strncmp(arg
, "at90usb", 7) == 0) {
989 } else if (strncmp(arg
, "atmega", 6) == 0) {
993 die("Unknown MCU type\n");
996 if (strncmp(arg
, "128", 3) == 0) {
997 code_size
= 128 * 1024;
999 } else if (strncmp(arg
, "64", 2) == 0) {
1000 code_size
= 64 * 1024;
1002 } else if (strncmp(arg
, "32", 2) == 0) {
1003 code_size
= 32 * 1024;
1005 } else if (strncmp(arg
, "16", 2) == 0) {
1006 code_size
= 16 * 1024;
1008 } else if (strncmp(arg
, "8", 1) == 0) {
1009 code_size
= 8 * 1024;
1012 die("Unknown MCU type\n");