Index: teensy_loader_cli.c
===================================================================
RCS file: /home/CVS/avr-misc/teensy_loader_cli.c,v
retrieving revision 1.1
retrieving revision 1.8
diff -u -p -r1.1 -r1.8
--- teensy_loader_cli.c	12 Feb 2009 15:01:54 -0000	1.1
+++ teensy_loader_cli.c	20 Feb 2009 17:16:09 -0000	1.8
@@ -22,6 +22,8 @@
 /* Compile with:
  *
  *   gcc -O2 -Wall -o teensy_loader_cli teensy_loader_cli.c -lusb
+ *    - or -
+ *   gcc -DUSE_UHID -O2 -Wall -o teensy_loader_cli teensy_loader_cli.c
  *
  */
 
@@ -38,16 +40,30 @@
  * http://reactivated.net/writing_udev_rules.html
  */
 
+#include <sys/types.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
 #include <unistd.h>
+#ifdef USE_UHID
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#else
 #include <usb.h>
+#endif /* USE_UHID */
 
 void usage(void)
 {
-	fprintf(stderr, "usage: teensy_loader_cli [-w] [-n] [-v] <file.hex>\n");
+	fprintf(stderr, "teensy_loader_cli v1.03\n");
+	fprintf(stderr, "usage: teensy_loader_cli "
+#ifdef USE_UHID
+		"[-d <device>] "
+#endif /* USE_UHID */
+		"[-w] [-n] [-v] <file.hex>\n");
+#ifdef USE_UHID
+	fprintf(stderr, "\t-d : specify a uhid device node\n");
+#endif /* USE_UHID */
 	fprintf(stderr, "\t-w : Wait for device to appear\n");
 	fprintf(stderr, "\t-n : No reboot after programming\n");
 	fprintf(stderr, "\t-v : Verbose output\n");
@@ -61,7 +77,9 @@ void usage(void)
 #define CODE_SIZE	15872
 
 
+#ifndef USE_UHID
 usb_dev_handle * open_hid_device(int vid, int pid, int usage_page, int usage);
+#endif
 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);
@@ -70,21 +88,29 @@ void die(const char *str, ...);
 
 
 // options
-int wait=0, reboot=1, verbose=0;
+int wait_flag=0, reboot_flag=1, verbose=0;
 
 
 int main(int argc, char **argv)
 {
+#ifdef USE_UHID
+	int uhid_fd;
+	char *optstr = "wnvd:";
+	char *dev = "/dev/uhid0";
+#else
 	usb_dev_handle *handle;
+	char *optstr = "wnv";
+#endif
 	unsigned char buf[130];
 	int num, addr, r, first_block=1, waited=0;
 	int opt;
 
 	// parse optional command line arguments
-	while ((opt = getopt(argc, argv, "wnv")) != -1) {
+	while ((opt = getopt(argc, argv, optstr)) != -1) {
 		switch (opt) {
-			case 'w': wait = 1; break;
-			case 'n': reboot = 0; break;
+			case 'd': dev = strdup(optarg); break;
+			case 'w': wait_flag = 1; break;
+			case 'n': reboot_flag = 0; break;
 			case 'v': verbose = 1; break;
 			default: usage();
 		}
@@ -99,9 +125,15 @@ int main(int argc, char **argv)
 
 	// open the USB device
 	while (1) {
+#ifdef USE_UHID
+		uhid_fd = open(dev, O_RDWR, 0600);
+		if (uhid_fd != -1) break;
+		/* XXX maybe check the device id? */
+#else
 		handle = open_hid_device(VID, PID, USAGE_PAGE, USAGE);
 		if (handle) break;
-		if (!wait) die("Unable to open device\n");
+#endif
+		if (!wait_flag) die("Unable to open device\n");
 		sleep(1);
 		waited = 1;
 	}
@@ -113,7 +145,7 @@ int main(int argc, char **argv)
 		num = read_intel_hex(argv[optind]);
 		if (num < 0) die("error reading intel hex file \"%s\"", argv[optind]);
 		printf_verbose("Read \"%s\": %d bytes, %.1f%% usage\n",
-		 	argv[optind], num, (double)num / (double)CODE_SIZE * 100.0);
+			argv[optind], num, (double)num / (double)CODE_SIZE * 100.0);
 	}
 
 	// program the data
@@ -129,27 +161,45 @@ int main(int argc, char **argv)
 		buf[0] = addr & 255;
 		buf[1] = (addr >> 8) & 255;
 		ihex_get_data(addr, 128, buf + 2);
+#ifdef USE_UHID
+		r = (write(uhid_fd, buf, 130) == 130);
+		if (first_block)
+			sleep(3); /* wait 3s on first write for flash erase */
+		else
+			usleep(200000); /* 200ms per block thereafter */
+
+#else
 		r = usb_control_msg(handle, 0x21, 9, 0x0200, 0, (char *)buf, 130,
 			first_block ? 3000 : 200);
+#endif
 		if (r < 0) die("error writing, r = %d\n", r);
 		first_block = 0;
 	}
 	printf_verbose("\n");
 
 	// reboot to the user's new code
-	if (reboot) {
+	if (reboot_flag) {
 		printf_verbose("Booting\n");
 		buf[0] = 0xFF;
 		buf[1] = 0xFF;
 		memset(buf + 2, 0, sizeof(buf) - 2);
+#ifdef USE_UHID
+		write(uhid_fd, buf, 130);
+#else
 		usb_control_msg(handle, 0x21, 9, 0x0200, 0, (char *)buf, 130, 200);
+#endif
 	}
+#ifdef USE_UHID
+	close(uhid_fd);
+#else
 	usb_close(handle);
+#endif
 	return 0;
 }
 
 
 
+#ifndef USE_UHID
 // http://libusb.sourceforge.net/doc/index.html
 
 usb_dev_handle * open_hid_device(int vid, int pid, int usage_page, int usage)
@@ -202,6 +252,7 @@ usb_dev_handle * open_hid_device(int vid
 	printf_verbose("\n");
 	return NULL;
 }
+#endif
 
 
 
