Package: release.debian.org
Severity: normal
User: release.debian....@packages.debian.org
Usertags: unblock

Please unblock package hdmi2usb-fx2-firmware.

I screwed up a bit with hdmi2usb-fx2-firmware, and the version in
unstable/testing doesn't actually work with the Numato Opsis board.
Debian's boards are at IRILL in Paris, and I didn't have one to hand at
the time.

There is no minimal diff to get us to a working image, because what we
currently have is some random snapshot from before they worked. Yes,
this is shitty, but that's what you get with small community hardware
projects. (Once upstream found something that worked, they lobbed that
firmware blob around a lot.)

This is obviously a very leaf package, the risk of changing it is
negligible.
(include/attach the debdiff against the package in testing)

unblock hdmi2usb-fx2-firmware/0.0.0~git20151225-1
diff --git a/.travis-push-docs.sh b/.travis-push-docs.sh
new file mode 100755
index 0000000..630605e
--- /dev/null
+++ b/.travis-push-docs.sh
@@ -0,0 +1,103 @@
+#!/bin/bash
+
+set -e
+
+if [ "$TRAVIS" = true -a "$TRAVIS_SECURE_ENV_VARS" = false ]; then
+	echo "No environment variables found, skipping (probably a pull request)."
+	exit 0
+fi
+
+if [ "$TRAVIS" = true -a "$TRAVIS_BRANCH" != "master" ]; then
+	echo "No master branch, skipping."
+	exit 0
+fi
+
+if [ -z "$TRAVIS_REPO_SLUG" ]; then
+	echo "No TRAVIS_REPO_SLUG value found."
+	echo "Please set this if running outside Travis."
+	exit 0
+fi
+
+# FIXME: Replace this with a deploy key, so you don't end up with tokens which
+# potentially give people *a lot* of access to your GitHub repos.
+if [ -z "$GH_TOKEN" ]; then
+	echo "No GH_TOKEN value found."
+	echo
+	echo "Generate a GitHub token at https://github.com/settings/tokens/new";
+	echo "with *only* the public_repo option."
+	echo "Then go to https://travis-ci.org/$TRAVIS_REPO_SLUG/settings and"
+	echo "add an 'Environment Variables' with the following;"
+	echo " * Name == GH_TOKEN"
+	echo " * Value == your token value from above"
+	echo " * Display value in build log == OFF"
+	echo
+	echo "It is important that you protect this token, as it has full push"
+	echo "access to your repos!"
+	exit 1
+fi
+
+if [ -z "$GIT_NAME" ]; then
+	echo "No GIT_NAME value found."
+	echo
+	echo "Then go to https://travis-ci.org/$TRAVIS_REPO_SLUG/settings and"
+	echo "add an 'Environment Variables' with the following;"
+	echo " * Name == GIT_NAME"
+	echo " * Value == Human readable name for the commit author."
+	echo "       Something like \"Tim Ansell's Robot\" is a good choice."
+	echo " * Display value in build log == ON"
+	exit 1
+fi
+
+if [ -z "$GIT_EMAIL" ]; then
+	echo "No GIT_EMAIL value found."
+	echo
+	echo "Then go to https://travis-ci.org/$TRAVIS_REPO_SLUG/settings and"
+	echo "add an 'Environment Variables' with the following;"
+	echo " * Name == GIT_EMAIL"
+	echo " * Value == Email address the commit author."
+	echo "       Set up an email address, or use your own."
+	echo " * Display value in build log == ON"
+	exit 1
+fi
+
+TMPDIR=$(mktemp --directory)
+
+if ! git describe > /dev/null 2>&1; then
+	echo "- Fetching non shallow to get git version"
+	git fetch --unshallow && git fetch --tags
+fi
+ORIG_GIT_REVISION=`git describe`
+ORIG_COMMITTER_NAME=$(git log -1 --pretty=%an)
+ORIG_COMMITTER_EMAIL=$(git log -1 --pretty=%ae)
+
+echo "- Setting up the output"
+cp -aRf docs/html/* $TMPDIR/
+cp docs/intro/intro.pdf $TMPDIR/
+find $TMPDIR | sort
+
+echo "- Switching to the gh-pages branch"
+git remote set-branches --add origin gh-pages
+git fetch origin gh-pages
+git checkout origin/gh-pages -b gh-pages
+
+echo "- Updating the README"
+sed -e"s-github.com/[^/]\+/[^/ ]\+-github.com/$TRAVIS_REPO_SLUG-" README.md > $TMPDIR/README.md
+cat $TMPDIR/README.md
+
+echo "- Adding the newly generated content"
+rm -rf *
+cp -aRf $TMPDIR/* .
+git add -v -A .
+
+echo "- Committing"
+export GIT_AUTHOR_EMAIL="$ORIG_COMMITTER_EMAIL"
+export GIT_AUTHOR_NAME="$ORIG_COMMITTER_NAME"
+export GIT_COMMITTER_EMAIL="$GIT_NAME"
+export GIT_COMMITTER_NAME="$GIT_EMAIL"
+unset GIT_NAME
+unset GIT_EMAIL
+git commit -a -m "Travis build #$TRAVIS_BUILD_NUMBER of $ORIG_GIT_REVISION"
+
+echo "- Pushing"
+git remote set-url origin https://$gh_to...@github.com/$TRAVIS_REPO_SLUG.git > /dev/null 2>&1
+git push origin gh-pages > /dev/null 2>&1
diff --git a/.travis.yml b/.travis.yml
index e5c96c9..5d5960c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,6 +10,12 @@ install:
   - # Install sdcc
   - sudo apt-get install --force-yes -y sdcc
   - sdcc --version
+  - # doxygen & rubber are needed for generating the documentation
+  - sudo apt-get install -y doxygen rubber
 
 script:
   - make
+  - make docs
+
+after_success:
+  - ./.travis-push-docs.sh
diff --git a/debian/changelog b/debian/changelog
index 3541a3a..82797f3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,12 @@
-hdmi2usb-fx2-firmware (0.0.0~git20151018-1) unstable; urgency=low
+hdmi2usb-fx2-firmware (0.0.0~git20151225-1) UNRELEASED; urgency=low
+
+  * New upstream release (different git branch)
+    - Should actually build a working uart firmware for the opsis.
+      (Closes: #855548)
+
+ -- Stefano Rivera <stefa...@debian.org>  Mon, 28 Nov 2016 23:35:19 -0800
+
+hdmi2usb-fx2-firmware (0.0.0~git20151128-1) unstable; urgency=low
 
   * Initial upload. (Closes: #796769)
 
diff --git a/debian/rules b/debian/rules
index c4f2158..152525d 100755
--- a/debian/rules
+++ b/debian/rules
@@ -4,12 +4,13 @@
 	dh $@
 
 VER=$(shell dpkg-parsechangelog | sed -rne 's/^Version: (.+)-.*/\1/p')
+BRANCH=opsis-uart-with-eeprom-serialno
 get-packaged-orig-source:
-	git clone https://github.com/mithro/fx2lib -b cdc-usb-serialno-from-eeprom
+	git clone https://github.com/mithro/fx2lib -b $(BRANCH)
 	set -xe; \
 		GIT_DATE=$$(dpkg-parsechangelog | sed -rne 's/^Version: .*\~git(....)(..)(..)-.*/\1-\2-\3 00:00:00 UTC/p'); \
 		cd fx2lib; \
-		GIT_COMMIT=$$(git rev-list -n1 --until="$$GIT_DATE" cdc-usb-serialno-from-eeprom); \
+		GIT_COMMIT=$$(git rev-list -n1 --until="$$GIT_DATE" $(BRANCH)); \
 		git archive $$GIT_COMMIT --prefix=hdmi2usb-fx2-firmware_$(VER).orig/ \
 			-o ../hdmi2usb-fx2-firmware_$(VER).orig.tar
 	xz -f hdmi2usb-fx2-firmware_$(VER).orig.tar
diff --git a/examples/cdc/Makefile b/examples/cdc/Makefile
index 57cb825..e9b579c 100644
--- a/examples/cdc/Makefile
+++ b/examples/cdc/Makefile
@@ -1,4 +1,4 @@
-DIRS=to-uart
+DIRS=loopback to-uart
      
 .PHONY: dirs $(DIRS) clean
      
diff --git a/examples/cdc/common/dscr.a51 b/examples/cdc/common/dscr.a51
index 285d9f9..533d5ec 100644
--- a/examples/cdc/common/dscr.a51
+++ b/examples/cdc/common/dscr.a51
@@ -42,7 +42,8 @@ ENDPOINT_TYPE_ISO=1
 ENDPOINT_TYPE_BULK=2
 ENDPOINT_TYPE_INT=3
 
-    .globl	_dev_dscr, _dev_qual_dscr, _highspd_dscr, _fullspd_dscr, _dev_strings, _dev_strings_end, _dev_serial
+    .globl	_dev_dscr, _dev_qual_dscr, _highspd_dscr, _fullspd_dscr, _dev_strings, _dev_strings_end
+    .globl	_dev_serial
 ; These need to be in code memory.  If
 ; they aren't you'll have to manully copy them somewhere
 ; in code memory otherwise SUDPTRH:L don't work right
@@ -57,9 +58,9 @@ _dev_dscr:
 	.db 0x00                      ; 5 bDeviceSubclass 1 Subclass code
 	.db 0x00                      ; 6 bDeviceProtocol 1 Protocol Code
 	.db 64                        ; 7 bMaxPacketSize0 1 Maximum packet size for endpoint zero
-	.dw 0xB404                    ; 8 idVendor 2 Vendor ID
-	.dw 0x0410                    ; 10 idProduct 2 Product ID
-	.dw 0x0100                    ; 12 bcdDevice 2 Device release number (BCD)
+	.dw 0x192A                    ; 8 idVendor 2 Vendor ID
+	.dw 0x4154                    ; 10 idProduct 2 Product ID
+	.dw 0x0300                    ; 12 bcdDevice 2 Device release number (BCD)
 	.db 1                         ; 14 iManufacturer 1 Index of string descriptor for the manufacturer
 	.db 2                         ; 15 iProduct 1 Index of string descriptor for the product
 	.db 3                         ; 16 iSerialNumber 1 Index of string descriptor for the serial number
@@ -107,7 +108,7 @@ highspd_dscr_end:
 	.db 0x02                         ; Interface class
 	.db 0x02                         ; Interface sub class
 	.db 0x01                         ; Interface protocol code class
-	.db 0x00                         ; Interface descriptor string index
+	.db 0                            ; Interface descriptor string index
 
 	;; CDC Header Functional Descriptor
 	.db 0x05                         ; Descriptor Size in Bytes (5)
@@ -154,7 +155,7 @@ highspd_dscr_end:
 	.db 0x0A                         ; Interface class
 	.db 0x00                         ; Interface sub class
 	.db 0x00                         ; Interface protocol code class
-	.db 0x00                         ; Interface descriptor string index
+	.db 0                            ; Interface descriptor string index
 
 ; endpoint 2 out
 	.db DSCR_ENDPOINT_LEN            ; Descriptor length
@@ -195,15 +196,15 @@ fullspd_dscr_end:
 ; NOTE the default TRM actually has more alt interfaces
 ; but you can add them back in if you need them.
 ; here, we just use the default alt setting 1 from the trm
-	.db	DSCR_INTERFACE_LEN
-	.db	DSCR_INTERFACE_TYPE
-	.db	0				 ; index
-	.db	0				 ; alt setting idx
-	.db	2				 ; n endpoints
-	.db	0x2			 ; class
-	.db	0x2
-	.db	0x1
-	.db	3	             ; string index
+	.db DSCR_INTERFACE_LEN
+	.db DSCR_INTERFACE_TYPE
+	.db 0                            ; index
+	.db 0                            ; alt setting idx
+	.db 2                            ; n endpoints
+	.db 0x2                          ; class
+	.db 0x2
+	.db 0x1
+	.db 3                            ; string index
 
 	;; CDC Header Functional Descriptor
 	.db 0x05                         ; Descriptor Size in Bytes (5)
@@ -242,15 +243,15 @@ fullspd_dscr_end:
 
 	;; CDC Virtual COM Port Data Interface Descriptor
 	; data endpoints
-	.db	DSCR_INTERFACE_LEN
-	.db	DSCR_INTERFACE_TYPE
-	.db	0x01				; index
-	.db	0x00				; alt setting idx
-	.db	0x02				; n endpoints
-	.db	0x0a				; class
-	.db	0x00
-	.db	0x00
-	.db	0x00				; string index
+	.db DSCR_INTERFACE_LEN
+	.db DSCR_INTERFACE_TYPE
+	.db 0x01                         ; index
+	.db 0x00                         ; alt setting idx
+	.db 0x02                         ; n endpoints
+	.db 0x0a                         ; class
+	.db 0x00
+	.db 0x00
+	.db 0x00                         ; string index
 
 ; endpoint 2 out
 	.db DSCR_ENDPOINT_LEN            ; Descriptor length
@@ -276,72 +277,118 @@ fullspd_dscr_realend:
 _dev_strings:
 ; sample string
 _string0:
-	.db	string0end-_string0 ; len
-	.db	DSCR_STRING_TYPE
-	.db 0x09, 0x04     ; who knows
+	.db string0end-_string0 ; len
+	.db DSCR_STRING_TYPE
+	.db 0x09, 0x04     ; 0x0409 is the language code for English. 
 string0end:
 ; add more strings here
 
+; Manufacture String - Numato
 _string1:
 	.db string1end-_string1
 	.db DSCR_STRING_TYPE
-	.ascii 'H'
+	.ascii 'N'
 	.db 0
-	.ascii 'i'
+	.ascii 'u'
+	.db 0
+	.ascii 'm'
+	.db 0
+	.ascii 'a'
+	.db 0
+	.ascii 't'
+	.db 0
+	.ascii 'o'
 	.db 0
 string1end:
 
+; Product String - Opsis (CDC Serial Mode)
 _string2:
 	.db string2end-_string2
 	.db DSCR_STRING_TYPE
-	.ascii 'T'
+	.ascii 'O'
+	.db 0
+	.ascii 'p'
+	.db 0
+	.ascii 's'
+	.db 0
+	.ascii 'i'
+	.db 0
+	.ascii 's'
 	.db 0
-	.ascii 'h'
+	.ascii ' '
+	.db 0
+	.ascii '('
+	.db 0
+	.ascii 'C'
+	.db 0
+	.ascii 'D'
+	.db 0
+	.ascii 'C'
+	.db 0
+	.ascii ' '
+	.db 0
+	.ascii 'S'
 	.db 0
 	.ascii 'e'
 	.db 0
 	.ascii 'r'
 	.db 0
+	.ascii 'i'
+	.db 0
+	.ascii 'a'
+	.db 0
+	.ascii 'l'
+	.db 0
+	.ascii ' '
+	.db 0
+	.ascii 'M'
+	.db 0
+	.ascii 'o'
+	.db 0
+	.ascii 'd'
+	.db 0
 	.ascii 'e'
 	.db 0
+	.ascii ')'
+	.db 0
 string2end:
 
 _string3:
-    .db string3end-_string3
-    .db DSCR_STRING_TYPE
+	.db string3end-_string3
+	.db DSCR_STRING_TYPE
 _dev_serial:
-    .ascii '0'
-    .db 0
-    .ascii '1'
-    .db 0
-    .ascii '2'
-    .db 0
-    .ascii '3'
-    .db 0
-    .ascii '4'
-    .db 0
-    .ascii '5'
-    .db 0
-    .ascii '6'
-    .db 0
-    .ascii '7'
-    .db 0
-    .ascii '8'
-    .db 0
-    .ascii '9'
-    .db 0
-    .ascii 'a'
-    .db 0
-    .ascii 'b'
-    .db 0
-    .ascii 'c'
-    .db 0
-    .ascii 'd'
-    .db 0
-    .ascii 'e'
-    .db 0
-    .ascii 'f'
-    .db 0
+	.ascii '0'
+	.db 0
+	.ascii '1'
+	.db 0
+	.ascii '2'
+	.db 0
+	.ascii '3'
+	.db 0
+	.ascii '4'
+	.db 0
+	.ascii '5'
+	.db 0
+	.ascii '6'
+	.db 0
+	.ascii '7'
+	.db 0
+	.ascii '8'
+	.db 0
+	.ascii '9'
+	.db 0
+	.ascii 'a'
+	.db 0
+	.ascii 'b'
+	.db 0
+	.ascii 'c'
+	.db 0
+	.ascii 'd'
+	.db 0
+	.ascii 'e'
+	.db 0
+	.ascii 'f'
+	.db 0
 string3end:
 
 _dev_strings_end:
diff --git a/examples/cdc/to-uart/to-uart.c b/examples/cdc/common/main.c
similarity index 73%
rename from examples/cdc/to-uart/to-uart.c
rename to examples/cdc/common/main.c
index 37c0836..50e2bb6 100644
--- a/examples/cdc/to-uart/to-uart.c
+++ b/examples/cdc/common/main.c
@@ -33,40 +33,7 @@
 
 // -----------------------------------------------------------------------
 
-BOOL cdcuser_set_line_rate(DWORD baud_rate) {
-        if (baud_rate > 115200 || baud_rate < 2400)
-            baud_rate = 115200;
-	sio0_init(baud_rate);
-	return TRUE;
-}
-
-void cdcuser_receive_data(BYTE* data, WORD length) {
-        WORD i;
-        for (i=0; i < length ; ++i) {
-		SBUF0 = data[i];
-		while(TI);
-	}
-}
-
-void ISR_USART0(void) __interrupt 4 __critical {
-	if (RI) {
-		RI=0;
-		if (!cdc_can_send()) {
-			// Mark overflow
-		} else {
-			cdc_queue_data(SBUF0);
-		}
-		// FIXME: Should use a timer, rather then sending one byte at a
-		// time.
-		cdc_send_queued_data();
-	}
-	if (TI) {
-		TI=0;
-//		transmit();
-	}
-}
-
-// -----------------------------------------------------------------------
+#include "main-custom.c"
 
 volatile WORD bytes;
 volatile __bit gotbuf;
@@ -87,13 +54,33 @@ char hex(BYTE value) {
 }
 
 extern __xdata char dev_serial[];
-void patch_serial(BYTE index, BYTE value) {
+void _patch_serial_byte(BYTE index, BYTE value) {
 	dev_serial[index*4] = hex(value >> 4);
 	dev_serial[index*4+2] = hex(value & 0xf);
 }
 
-void main() {
+void patch_serial() {
 	BYTE tempbyte = 0;
+	dev_serial[0] = 'f';
+	eeprom_read(0x51, 0xf8, 1, &tempbyte);
+	_patch_serial_byte(0, tempbyte);
+	eeprom_read(0x51, 0xf8+1, 1, &tempbyte);
+	_patch_serial_byte(1, tempbyte);
+	eeprom_read(0x51, 0xf8+2, 1, &tempbyte);
+	_patch_serial_byte(2, tempbyte);
+	eeprom_read(0x51, 0xf8+3, 1, &tempbyte);
+	_patch_serial_byte(3, tempbyte);
+	eeprom_read(0x51, 0xf8+4, 1, &tempbyte);
+	_patch_serial_byte(4, tempbyte);
+	eeprom_read(0x51, 0xf8+5, 1, &tempbyte);
+	_patch_serial_byte(5, tempbyte);
+	eeprom_read(0x51, 0xf8+6, 1, &tempbyte);
+	_patch_serial_byte(6, tempbyte);
+	eeprom_read(0x51, 0xf8+7, 1, &tempbyte);
+	_patch_serial_byte(7, tempbyte);
+}
+
+void main() {
 	REVCTL=0; // not using advanced endpoint controls
 
 	on=0;
@@ -108,32 +95,14 @@ void main() {
  
 	SETCPUFREQ(CLK_48M);
 	SETIF48MHZ();
+
+	patch_serial();
  
 	USE_USB_INTS(); 
 	ENABLE_SUDAV();
 	ENABLE_SOF();
 	ENABLE_HISPEED();
 	ENABLE_USBRESET();
-
-	dev_serial[0] = 'f';
-	//pSerial[2] = ((WORD)'e') << 8;
-
-        eeprom_read(0x51, 0xf8, 1, &tempbyte);
-	patch_serial(0, tempbyte);
-        eeprom_read(0x51, 0xf8+1, 1, &tempbyte);
-	patch_serial(1, tempbyte);
-        eeprom_read(0x51, 0xf8+2, 1, &tempbyte);
-	patch_serial(2, tempbyte);
-        eeprom_read(0x51, 0xf8+3, 1, &tempbyte);
-	patch_serial(3, tempbyte);
-        eeprom_read(0x51, 0xf8+4, 1, &tempbyte);
-	patch_serial(4, tempbyte);
-        eeprom_read(0x51, 0xf8+5, 1, &tempbyte);
-	patch_serial(5, tempbyte);
-        eeprom_read(0x51, 0xf8+6, 1, &tempbyte);
-	patch_serial(6, tempbyte);
-        eeprom_read(0x51, 0xf8+7, 1, &tempbyte);
-	patch_serial(7, tempbyte);
  
 	// only valid endpoints are 2/6
 	// Activate, OUT Direction, BULK Type, 512  bytes Size, Double buffered
@@ -249,15 +218,15 @@ void sudav_isr() __interrupt SUDAV_ISR {
 	CLEAR_SUDAV();
 }
 
-//__bit on5;
-//__xdata WORD sofct=0;
+__bit on5;
+__xdata WORD sofct=0;
 void sof_isr () __interrupt SOF_ISR __using 1 {
-//	++sofct;
-//	if(sofct==8000) { // about 8000 sof interrupts per second at high speed
-//		on5=!on5;
-//		if (on5) {d5on();} else {d5off();}
-//		sofct=0;
-//	}
+	++sofct;
+	if(sofct==8000) { // about 8000 sof interrupts per second at high speed
+		on5=!on5;
+		if (on5) {d5on();} else {d5off();}
+		sofct=0;
+	}
 	CLEAR_SOF();
 }
 
diff --git a/examples/cdc/loopback/Makefile b/examples/cdc/loopback/Makefile
new file mode 100644
index 0000000..da996ca
--- /dev/null
+++ b/examples/cdc/loopback/Makefile
@@ -0,0 +1,9 @@
+FX2LIBDIR=../../../
+BASENAME = cdc-acm-loopback
+SOURCES=../common/main.c ../common/cdc.c
+DEPS=../common/cdc.h ../common/cdc-config.h main-custom.c
+INCLUDES=../common -I ./
+A51_SOURCES=../common/dscr.a51
+PID=0x1004
+
+include $(FX2LIBDIR)lib/fx2.mk
diff --git a/examples/cdc/loopback/main-custom.c b/examples/cdc/loopback/main-custom.c
new file mode 100644
index 0000000..5bbbb43
--- /dev/null
+++ b/examples/cdc/loopback/main-custom.c
@@ -0,0 +1,14 @@
+// This file is included from ../common/main.c
+// -----------------------------------------------------------------------
+
+BOOL cdcuser_set_line_rate(DWORD baud_rate) {
+	return TRUE;
+}
+
+void cdcuser_receive_data(BYTE* data, WORD length) {
+        WORD i;
+        for (i=0; i < length ; ++i) {
+		cdc_queue_data(data[i]);
+	}
+	cdc_send_queued_data();
+}
diff --git a/examples/cdc/to-uart/Makefile b/examples/cdc/to-uart/Makefile
index 90969eb..7fa4e8f 100644
--- a/examples/cdc/to-uart/Makefile
+++ b/examples/cdc/to-uart/Makefile
@@ -1,9 +1,11 @@
 FX2LIBDIR=../../../
 BASENAME = cdc-acm-to-uart
-SOURCES=to-uart.c ../common/cdc.c
-DEPS=../common/cdc.h ../common/cdc-config.h
-INCLUDES=../common
+SOURCES=../common/main.c ../common/cdc.c
+DEPS=../common/cdc.h ../common/cdc-config.h main-custom.c
+INCLUDES=../common -I ./
 A51_SOURCES=../common/dscr.a51
 PID=0x1004
 
+DSCR_AREA=-Wl"-b DSCR_AREA=0x1e00"
+
 include $(FX2LIBDIR)lib/fx2.mk
diff --git a/examples/cdc/to-uart/main-custom.c b/examples/cdc/to-uart/main-custom.c
new file mode 100644
index 0000000..af8304b
--- /dev/null
+++ b/examples/cdc/to-uart/main-custom.c
@@ -0,0 +1,44 @@
+// This file is included from ../common/main.c
+// -----------------------------------------------------------------------
+
+#include <fx2ints.h>
+
+BOOL cdcuser_set_line_rate(DWORD baud_rate) {
+        if (baud_rate > 115200 || baud_rate < 2400)
+            baud_rate = 115200;
+	sio0_init(baud_rate);
+	return TRUE;
+}
+
+
+volatile __bit byte_sending = TRUE;
+void cdcuser_receive_data(BYTE* data, WORD length) {
+        WORD i;
+        for (i=0; i < length ; ++i) {
+		// Wait for any previous byte to send. byte_sending is cleared
+		// in the USART0 ISR.
+		while(byte_sending);
+		byte_sending = TRUE;
+		SBUF0 = data[i];
+	}
+}
+
+// Serial port 0 transmit or receive interrupt
+// *MUST* Clear TI and RI bits.
+void ISR_USART0(void) __interrupt TI_0_ISR {
+	if (RI) {
+		RI=0;
+		if (!cdc_can_send()) {
+			// Mark overflow
+		} else {
+			cdc_queue_data(SBUF0);
+		}
+		// FIXME: Should use a timer, rather then sending one byte at a
+		// time.
+		cdc_send_queued_data();
+	}
+	if (TI) {
+		TI=0;
+		byte_sending = FALSE;
+	}
+}
diff --git a/examples/eeprom/client.py b/examples/eeprom/client.py
index 80d630f..b87e34e 100644
--- a/examples/eeprom/client.py
+++ b/examples/eeprom/client.py
@@ -88,5 +88,6 @@ def set_eeprom(prom):
 
 if __name__=='__main__':
 
-   openfx2(0x04b4,0x0083) # vid/pid of eeprom firmware 
+   openfx2(0x2A19,0x5441) # vid/pid of eeprom firmware 
+   print(repr(fetch_eeprom()))
 
diff --git a/examples/eeprom/firmware/dscr.a51 b/examples/eeprom/firmware/dscr.a51
index 03871a9..8cd1168 100644
--- a/examples/eeprom/firmware/dscr.a51
+++ b/examples/eeprom/firmware/dscr.a51
@@ -43,6 +43,7 @@ ENDPOINT_TYPE_BULK=2
 ENDPOINT_TYPE_INT=3
 
     .globl	_dev_dscr, _dev_qual_dscr, _highspd_dscr, _fullspd_dscr, _dev_strings, _dev_strings_end
+    .globl      _dev_serial
 ; These need to be in code memory.  If
 ; they aren't you'll have to manully copy them somewhere
 ; in code memory otherwise SUDPTRH:L don't work right
@@ -56,12 +57,12 @@ _dev_dscr:
 	.db	0xff					  ; subclass (vendor specific)
 	.db	0xff					  ; protocol (vendor specific)
 	.db	64						  ; packet size (ep0)
-	.dw	0xb404			      ; vendor id 
-	.dw	0x8300					  ; product id
-	.dw	0x0100					  ; version id
-	.db	0		                  ; manufacturure str idx				
-	.db	1				          ; product str idx	
-	.db	0				          ; serial str idx 
+	.dw	0x192A			      ; vendor id 
+	.dw	0x4154					  ; product id
+	.dw	0x0200					  ; version id
+	.db	1		                  ; manufacturure str idx				
+	.db	2				          ; product str idx	
+	.db	3				          ; serial str idx 
 	.db	1			              ; n configurations
 dev_dscr_end:
 
@@ -251,27 +252,106 @@ _string0:
 string0end:
 ; add more strings here
 
-string1:
-    .db string1end-string1
-    .db DSCR_STRING_TYPE
-    .ascii 'U'
-    .db 0
-    .ascii 's'
-    .db 0
-    .ascii 'b'
-    .db 0
-    .ascii ' '
-    .db 0
-    .ascii 'T'
-    .db 0
-    .ascii 'e'
-    .db 0
-    .ascii 'r'
-    .db 0
-    .ascii 'm'
-    .db 0
+; Manufacture String - Numato
+_string1:
+	.db string1end-_string1
+	.db DSCR_STRING_TYPE
+	.ascii 'N'
+	.db 0
+	.ascii 'u'
+	.db 0
+	.ascii 'm'
+	.db 0
+	.ascii 'a'
+	.db 0
+	.ascii 't'
+	.db 0
+	.ascii 'o'
+	.db 0
 string1end:
 
+; Product String - Opsis (EEPROM Mode)
+_string2:
+	.db string2end-_string2
+	.db DSCR_STRING_TYPE
+	.ascii 'O'
+	.db 0
+	.ascii 'p'
+	.db 0
+	.ascii 's'
+	.db 0
+	.ascii 'i'
+	.db 0
+	.ascii 's'
+	.db 0
+	.ascii ' '
+	.db 0
+	.ascii '('
+	.db 0
+	.ascii 'E'
+	.db 0
+	.ascii 'E'
+	.db 0
+	.ascii 'P'
+	.db 0
+	.ascii 'R'
+	.db 0
+	.ascii 'O'
+	.db 0
+	.ascii 'M'
+	.db 0
+	.ascii ' '
+	.db 0
+	.ascii 'M'
+	.db 0
+	.ascii 'o'
+	.db 0
+	.ascii 'd'
+	.db 0
+	.ascii 'e'
+	.db 0
+	.ascii ')'
+	.db 0
+string2end:
+
+_string3:
+	.db string3end-_string3
+	.db DSCR_STRING_TYPE
+_dev_serial:
+	.ascii '0'
+	.db 0
+	.ascii '1'
+	.db 0
+	.ascii '2'
+	.db 0
+	.ascii '3'
+	.db 0
+	.ascii '4'
+	.db 0
+	.ascii '5'
+	.db 0
+	.ascii '6'
+	.db 0
+	.ascii '7'
+	.db 0
+	.ascii '8'
+	.db 0
+	.ascii '9'
+	.db 0
+	.ascii 'a'
+	.db 0
+	.ascii 'b'
+	.db 0
+	.ascii 'c'
+	.db 0
+	.ascii 'd'
+	.db 0
+	.ascii 'e'
+	.db 0
+	.ascii 'f'
+	.db 0
+string3end:
+
 _dev_strings_end:
     .dw 0x0000
 ; in case you wanted to look at memory between _dev_strings and _dev_strings_end
diff --git a/examples/eeprom/firmware/eeprom.c b/examples/eeprom/firmware/eeprom.c
index 83afae4..6f2992c 100644
--- a/examples/eeprom/firmware/eeprom.c
+++ b/examples/eeprom/firmware/eeprom.c
@@ -35,9 +35,44 @@ volatile __bit dosud;
 __bit on;
 WORD count;
 
+char hex(BYTE value) {
+	if (value > 0x0f) {
+		return '?';
+	} else if (value > 0x09) {
+		return 'a'+(value-0x0a);
+	} else {
+		return '0'+value;
+	}
+}
 
-void main() {
+extern __xdata char dev_serial[];
+void _patch_serial_byte(BYTE index, BYTE value) {
+	dev_serial[index*4] = hex(value >> 4);
+	dev_serial[index*4+2] = hex(value & 0xf);
+}
+
+void patch_serial() {
+	BYTE tempbyte = 0;
+	dev_serial[0] = 'f';
+	eeprom_read(0x51, 0xf8, 1, &tempbyte);
+	_patch_serial_byte(0, tempbyte);
+	eeprom_read(0x51, 0xf8+1, 1, &tempbyte);
+	_patch_serial_byte(1, tempbyte);
+	eeprom_read(0x51, 0xf8+2, 1, &tempbyte);
+	_patch_serial_byte(2, tempbyte);
+	eeprom_read(0x51, 0xf8+3, 1, &tempbyte);
+	_patch_serial_byte(3, tempbyte);
+	eeprom_read(0x51, 0xf8+4, 1, &tempbyte);
+	_patch_serial_byte(4, tempbyte);
+	eeprom_read(0x51, 0xf8+5, 1, &tempbyte);
+	_patch_serial_byte(5, tempbyte);
+	eeprom_read(0x51, 0xf8+6, 1, &tempbyte);
+	_patch_serial_byte(6, tempbyte);
+	eeprom_read(0x51, 0xf8+7, 1, &tempbyte);
+	_patch_serial_byte(7, tempbyte);
+}
 
+void main() {
  REVCTL = 0; // not using advanced endpoint controls
 
  dosud=FALSE;
@@ -50,6 +85,7 @@ void main() {
 
  SETCPUFREQ(CLK_48M);
  sio0_init(57600); // needed for printf on sio0 
+ patch_serial();
  
  
  USE_USB_INTS();
@@ -81,9 +117,16 @@ BOOL handle_get_descriptor() {
 #define VC_EEPROM 0xb1
         
 BOOL handle_vendorcommand(BYTE cmd) {
+ BYTE prom_addr=0;
  WORD addr=SETUP_VALUE(),len=SETUP_LENGTH();
  printf ( "Handle Vendor Command %02x, addr %d, len %d\n" , cmd, addr, len );
+ if (EEPROM_TWO_BYTE) {
+     prom_addr=0x51;
+ } else {
+     prom_addr=0x50;
+ }
  switch (cmd) {
+
     case VC_EEPROM:
         {            
             // wait for ep0 not busy
@@ -92,7 +135,7 @@ BOOL handle_vendorcommand(BYTE cmd) {
                  while (len) { // still have bytes to read
                     BYTE cur_read = len > 64 ? 64 : len; // can't read more than 64 bytes at a time
                     while (EP0CS&bmEPBUSY); // can't do this until EP0 is ready                
-                    eeprom_read(0x51, addr, cur_read, EP0BUF );
+                    eeprom_read(prom_addr, addr, cur_read, EP0BUF );
                     EP0BCH=0;
                     SYNCDELAY;
                     EP0BCL=cur_read;
@@ -108,7 +151,7 @@ BOOL handle_vendorcommand(BYTE cmd) {
                    while(EP0CS & bmEPBUSY); // wait
                    cur_write=EP0BCL;
 //                   printf ( "Writing %d Bytes to %d..\n", cur_write, addr );
-                   if ( !eeprom_write(0x51, addr, cur_write, EP0BUF ) ) return FALSE;
+                   if ( !eeprom_write(prom_addr, addr, cur_write, EP0BUF ) ) return FALSE;
                    addr += cur_write;
                    len -= cur_write;
                 }
diff --git a/fw/fw.c b/fw/fw.c
index df630c5..6e09431 100644
--- a/fw/fw.c
+++ b/fw/fw.c
@@ -29,8 +29,7 @@
 #define printf(...)
 #endif
 
-
-
+#define SUSPEND_ENABLED
 
 volatile __bit dosud=FALSE;
 volatile __bit dosuspend=FALSE;
diff --git a/include/autovector.h b/include/autovector.h
index 372ba61..c58677c 100644
--- a/include/autovector.h
+++ b/include/autovector.h
@@ -38,11 +38,6 @@
 #include "fx2regs.h"
 
 
-
-// this causes usbjt to be included from the lib
-// not used for anything
-extern volatile BYTE INT2JT;
-extern volatile BYTE INT4JT;
 /**
  * Enable all interrupts (EA=1) separate from this macro.
  * This macro causes the autovector assembly for int2 interrupts
@@ -55,8 +50,7 @@ extern volatile BYTE INT4JT;
  *   sdcc <files> -Wl"-b INT2JT = 0xaddr"
  * \endcode
  **/
-#define USE_USB_INTS() {BYTE dummy=INT2JT;\
-                        EUSB=1;\
+#define USE_USB_INTS() {EUSB=1;\
                         INTSETUP|=bmAV2EN;}
 /** This macro causes the autovector assemby for int4 to be overlayed
  * at 0x53.  Don't use this if you want external pin generated int4 interrupts
@@ -65,12 +59,10 @@ extern volatile BYTE INT4JT;
  * interrupts require the USB jump table.  (You can't USE your own usb interrupt
  * handler if you want to enable GPIF interrupts.)
  **/
-#define USE_GPIF_INTS() {BYTE dummy=INT4JT;\
-                        EIEX4=1;\
+#define USE_GPIF_INTS() {EIEX4=1;\
                         INTSETUP|=bmAV4EN|INT4IN;}
              
 
-
 #define CLEAR_USBINT() EXIF &= ~0x10
 #define CLEAR_GPIF() EXIF &= ~0x40
 
@@ -185,49 +177,51 @@ typedef enum {
 // you must include the predef of these in the file with your main
 // so lets just define them here
 
-void sudav_isr() __interrupt SUDAV_ISR;
-void sof_isr() __interrupt SOF_ISR;
-void sutok_isr() __interrupt SUTOK_ISR;
-void suspend_isr() __interrupt SUSPEND_ISR;
-void usbreset_isr() __interrupt USBRESET_ISR;
-void hispeed_isr() __interrupt HISPEED_ISR;
-void ep0ack_isr() __interrupt EP0ACK_ISR;
-void ep0in_isr() __interrupt EP0IN_ISR;
-void ep0out_isr() __interrupt EP0OUT_ISR;
-void ep1in_isr() __interrupt EP1IN_ISR;
-void ep1out_isr() __interrupt EP1OUT_ISR;
-void ep2_isr() __interrupt EP2_ISR;
-void ep4_isr() __interrupt EP4_ISR;
-void ep6_isr() __interrupt EP6_ISR;
-void ep8_isr() __interrupt EP8_ISR;
-void ibn_isr() __interrupt IBN_ISR;
-void ep0ping_isr() __interrupt EP0PING_ISR;
-void ep1ping_isr() __interrupt EP1PING_ISR;
-void ep2ping_isr() __interrupt EP2PING_ISR;
-void ep4ping_isr() __interrupt EP4PING_ISR;
-void ep6ping_isr() __interrupt EP6PING_ISR;
-void ep8ping_isr() __interrupt EP8PING_ISR;
-void errlimit_isr() __interrupt ERRLIMIT_ISR;
-void ep2isoerr_isr() __interrupt EP2ISOERR_ISR;
-void ep4isoerr_isr() __interrupt EP4ISOERR_ISR;
-void ep6isoerr_isr() __interrupt EP6ISOERR_ISR;
-void ep8isoerr_isr() __interrupt EP8ISOERR_ISR;
-void spare_isr() __interrupt RESERVED_ISR; // not used
+void usb_isr(void) __interrupt (8);
+void sudav_isr() __interrupt;
+void sof_isr() __interrupt;
+void sutok_isr() __interrupt;
+void suspend_isr() __interrupt;
+void usbreset_isr() __interrupt;
+void hispeed_isr() __interrupt;
+void ep0ack_isr() __interrupt;
+void ep0in_isr() __interrupt;
+void ep0out_isr() __interrupt;
+void ep1in_isr() __interrupt;
+void ep1out_isr() __interrupt;
+void ep2_isr() __interrupt;
+void ep4_isr() __interrupt;
+void ep6_isr() __interrupt;
+void ep8_isr() __interrupt;
+void ibn_isr() __interrupt;
+void ep0ping_isr() __interrupt;
+void ep1ping_isr() __interrupt;
+void ep2ping_isr() __interrupt;
+void ep4ping_isr() __interrupt;
+void ep6ping_isr() __interrupt;
+void ep8ping_isr() __interrupt;
+void errlimit_isr() __interrupt;
+void ep2isoerr_isr() __interrupt;
+void ep4isoerr_isr() __interrupt;
+void ep6isoerr_isr() __interrupt;
+void ep8isoerr_isr() __interrupt;
+void spare_isr() __interrupt; // not used
 // gpif ints
-void ep2pf_isr() __interrupt EP2PF_ISR;
-void ep4pf_isr() __interrupt EP4PF_ISR;
-void ep6pf_isr() __interrupt EP6PF_ISR;
-void ep8pf_isr() __interrupt EP8PF_ISR;
-void ep2ef_isr() __interrupt EP2EF_ISR;
-void ep4ef_isr() __interrupt EP4EF_ISR;
-void ep6ef_isr() __interrupt EP6EF_ISR;
-void ep8ef_isr() __interrupt EP8EF_ISR;
-void ep2ff_isr() __interrupt EP2FF_ISR;
-void ep4ff_isr() __interrupt EP4FF_ISR;
-void ep6ff_isr() __interrupt EP6FF_ISR;
-void ep8ff_isr() __interrupt EP8FF_ISR;
-void gpifdone_isr() __interrupt GPIFDONE_ISR;
-void gpifwf_isr() __interrupt GPIFWF_ISR;
+void gpif_isr(void) __interrupt (10);
+void ep2pf_isr() __interrupt;
+void ep4pf_isr() __interrupt;
+void ep6pf_isr() __interrupt;
+void ep8pf_isr() __interrupt;
+void ep2ef_isr() __interrupt;
+void ep4ef_isr() __interrupt;
+void ep6ef_isr() __interrupt;
+void ep8ef_isr() __interrupt;
+void ep2ff_isr() __interrupt;
+void ep4ff_isr() __interrupt;
+void ep6ff_isr() __interrupt;
+void ep8ff_isr() __interrupt;
+void gpifdone_isr() __interrupt;
+void gpifwf_isr() __interrupt;
 
 #endif
 
diff --git a/include/eputils.h b/include/eputils.h
index 9a0b1e6..50968ed 100644
--- a/include/eputils.h
+++ b/include/eputils.h
@@ -21,7 +21,10 @@
 #ifndef EPUTILS_H
 #define EPUTILS_H
 
+#include <assert.h>
+
 #include "fx2types.h"
+#include "fx2macros.h"
 
 /**
  * NOTE you can't use these unless you define SYNCDELAY 
@@ -47,7 +50,13 @@
  * \brief Reset the toggle on an endpoint.
  * To use this, the endpoint needs bit 8 to be IN=1,OUT=0
  **/
-#define RESETTOGGLE(ep) TOGCTL = (ep&0x0F) + ((ep&0x80)>>3); TOGCTL |= bmRESETTOGGLE
+#define RESETTOGGLE(ep) do {\
+	BYTE x = ep; \
+	if (x&0x80) { x |= 0x10; } \
+	x &= 0x1F; \
+	TOGCTL = x; \
+	TOGCTL = x | bmRESETTOGGLE; \
+} while (0)
 
 
 /**
@@ -74,13 +83,61 @@
  **/
 void readep0( BYTE* dst, WORD len );
 
-
 /**
  * Write bytes from src to ep0, allowing host to transfer data
  * between 64 byte blocks.
  **/
-void writeep0 ( BYTE* src, WORD len );
+void writeep0( BYTE* src, WORD len );
+
+// The Setup Data Pointer can access data in either of two RAM spaces:
+//  - On-chip Main RAM (8 KB at 0x0000-0x1FFF)
+//  - On-chip Scratch RAM (512 bytes at 0xE000-0xE1FF)
+// The base address of SUDPTRH:L must be word-aligned.
+#define ep0_load_sudptr(src) \
+	assert( \
+		(((WORD)src) <= 0x3FFF) || \
+		(((WORD)src) >= 0xE000 && ((WORD)src) <= 0xE1FF)); \
+	assert(!(LSB(src) & bmBIT0)); \
+	LOADWORD(SUDPTR, src);
+
+// For manual mode, SUDPTRCTL must be in "auto read length mode".
+//
+// |  Data Read  | Data Length | SUDPTRCTL |
+// |-------------|-------------|-----------|
+// | Auto   (0)  | Manual (0)  |  0|0 = 0  | SUDPTR->EP0BC
+// | Manual (1)  | Manual (0)  |  1|0 = 1  | EP0BUF->EP0BC
+// | Auto   (0)  | Auto   (1)  |  0|1 = 1  | SUDPTR
+// | Manual (1)  | Auto   (1)  |  Invalid  | NA
+enum ep0_mode_data {
+	EP0_DATA_AUTO    = 0,
+	EP0_DATA_MANUAL  = 1,
+};
+enum ep0_mode_length {
+	EP0_LENGTH_AUTO   = 1,
+	EP0_LENGTH_MANUAL = 0,
+};
+
+#define ep0_mode(mode_data, mode_length) \
+	assert(!(mode_data & mode_length)); \
+	SUDPTRCTL = mode_data | mode_length;
+
+#define ep0_busywait() \
+	while (EP0CS & bmEPBUSY) printf("w\n");
+
+#define ep0_load_length(len) \
+	LOADWORD(EP0BC, len);
+
+#define ep0_arm() \
+	ep0_load_length(0);
+
+// ep0 can only receive 64 bytes
+#define ep0_get_length() \
+	EP0BCL
 
+void ep0_send_auto(__xdata BYTE* src, WORD len);
+void ep0_send_byte(BYTE data);
+void ep0_send_word(WORD data);
 
+BYTE ep0_recv();
 
 #endif
diff --git a/include/fx2ints.h b/include/fx2ints.h
index 45ae71e..75bd685 100644
--- a/include/fx2ints.h
+++ b/include/fx2ints.h
@@ -15,7 +15,7 @@
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
 /*! \file 
- *  Define the standard fx2 interrupts.  For int2 and int4 autovector
+ *  Define the standard FX2 interrupts.  For INT2 and INT4 autovector
  *  interrupts see \ref autovector.h
  *
  *  To enable an interrupt, simply define an interrupt handler function
@@ -38,8 +38,7 @@
 
 
 /**
- * \brief interrupt numbers for standard fx2 interrupts
-
+ * \brief Interrupt numbers for standard FX2 interrupts.
  **/
 typedef enum {
  IE0_ISR=0, ///< External interrupt 0
@@ -50,29 +49,66 @@ typedef enum {
  TF2_ISR, ///< Timer 2 interrupt
  RESUME_ISR, ///< Resume interrupt
  TI_1_ISR, ///< Serial port 1 transmit or receive interrupt
- USBINT_ISR, ///< Usb Interrupt.  An interrupt handler for this should only be used if not using auto vectored interrupts with int2
+ USBINT_ISR, ///< USB Interrupt.  An interrupt handler for this should only be used if not using auto vectored interrupts with INT2
  I2CINT_ISR, ///< I2C Bus interrupt
- IE4_ISR, ///< External interrupt 4.  An interrupt handler for this should only be used if not using auto vectored interrupts with int4
+ IE4_ISR, ///< External interrupt 4.  An interrupt handler for this should only be used if not using auto vectored interrupts with INT4
  IE5_ISR, ///< External interrupt 5
  IE6_ISR, ///< External interrupt 6
+ // Better names for the USART interrupts
+ USART0_ISR = TI_0_ISR, ///< Better name for USART0 interrupt
+ USART1_ISR = TI_1_ISR, ///< Better name for USART1 interrupt
 } FX2_ISR;
 
+/**
+ * \brief Interrupt high priority.
+ **/
+#define INTERRUPT_HIGH_PRIO	1
+/**
+ * \brief Interrupt low priority.
+ **/
+#define INTERRUPT_LOW_PRIO	0
+
+
+// TIMER0
+// =======================================================================
 
 /**
  * \brief Enable the timer 0 interrupt.
  *
- * There is not CLEAR_TIMER0 because the timer interrupt flag 
- * is automatically cleared when the isr is called.
+ * CLEAR_TIMER0() is a NOP because the timer interrupt flag is automatically
+ * cleared when the ISR is called.
  **/
 #define ENABLE_TIMER0() ET0=1
 
 /**
+ * \brief Clear timer 0 interrupt
+ *
+ * CLEAR_TIMER0() is a NOP because the timer interrupt flag is automatically
+ * cleared when the ISR is called.
+ **/
+#define CLEAR_TIMER0()
+
+// TIMER1
+// =======================================================================
+
+/**
  * \brief Enable timer 1 interrupt
- * There is no CLEAR_TIMER1 because the timer interrupt flag
- * is automatically cleared when the isr is called.
+ *
+ * CLEAR_TIMER1() is a NOP because the timer interrupt flag is automatically
+ * cleared when the ISR is called.
  **/
 #define ENABLE_TIMER1() ET1=1
 
+/**
+ * \brief Clear timer 1 interrupt
+ *
+ * CLEAR_TIMER1() is a NOP because the timer interrupt flag is automatically
+ * cleared when the ISR is called.
+ **/
+#define CLEAR_TIMER1()
+
+// TIMER2 and external EXF2 interrupt
+// =======================================================================
 
 /**
  * \brief Enable timer 2 interrupt
@@ -82,12 +118,18 @@ typedef enum {
  **/
 #define ENABLE_TIMER2() ET2=1
 /**
- *  \brief Clear timer 2 interrupt
+ * \brief Clear timer 2 interrupt
  *
- *  Clears both the TF2 AND EXF2 flag
+ * Clears both the TF2 AND EXF2 flag
  **/
 #define CLEAR_TIMER2() TF2=0;EXF2=0;
 
+// Resume interrupt
+// =======================================================================
+// After the FX2 has entered its idle state, it responds to an external signal
+// on its WAKEUP/WU2 pins or resumption of USB bus activity by restarting its
+// oscillator and resuming firmware execution.
+
 /**
  * \brief Enable the Resume Interrupt.  Requires EA=1 separately.
  **/
@@ -99,18 +141,138 @@ typedef enum {
  **/
 #define CLEAR_RESUME() RESI=0
 
+// Interrupt 4 - Autovectored FIFO / GPIF or External interrupt 4
+// =======================================================================
 
-#define ENABLE_INT4() 
+//#define ENABLE_INT4()
+
+// External Interrupt 5
+// =======================================================================
 
 /**
  * \brief 
- * Enable external interupt for int5#
+ * Enable external interrupt for INT5#
  **/
 #define ENABLE_INT5() EIEX5=1 
 
 /**
  * \brief 
- * Clear int5# interrupt
+ * Clear INT5# interrupt
+ **/
+#define CLEAR_INT5() \
+	EXIF &= ~bmIE5
+
+// USART0
+// =======================================================================
+
+/**
+ * \brief Set the USART 0 interrupt priority.
+ *
+ * Does *not* enable the interrupt.
+ *
+ * \code
+ *  SET_USART0_ISR_PRIO(INTERRUPT_HIGH_PRIO); // Set USART0 to high priority
+ *  SET_USART0_ISR_PRIO(INTERRUPT_LOW_PRIO);  // Set USART0 to low priority
+ * \endcode
+ **/
+#define SET_USART0_ISR_PRIORITY(p) \
+	PS0 = p
+/**
+ * \brief Enable the USART 0 interrupt.
+ *
+ * Requires enabling global interrupts (EA=1) separately.
+ *
+ * The USART interrupt fires for both *receive* (RX) and *transmit* (TX)
+ * completing, the interrupt must clear *both*.
+ **/
+#define ENABLE_USART0() \
+	ES0 = 1;
+/**
+ * \brief Clear USART 0 RX bit.
  **/
-#define CLEAR_INT5() EXIF &= ~0x80
+#define CLEAR_USART0_RX() \
+	RI = 0;
+/**
+ * \brief Clear USART 0 TX bit.
+ **/
+#define CLEAR_USART0_TX() \
+	TI = 0;
+/**
+ * \brief Clear USART 0 both TX & RX bit.
+ **/
+#define CLEAR_USART0() \
+	CLEAR_USART0_RX(); \
+	CLEAR_USART0_TX();
 
+// USART1
+// =======================================================================
+
+/**
+ * \brief Set the USART 1 interrupt priority.
+ *
+ * Does *not* enable the interrupt.
+ *
+ * \code
+ * SET_USART1_ISR_PRIO(INTERRUPT_HIGH_PRIO); // Set USART1 to high priority
+ * SET_USART1_ISR_PRIO(INTERRUPT_LOW_PRIO);  // Set USART1 to low priority
+ * \endcode
+ **/
+#define SET_USART1_ISR_PRIORITY(p) \
+	PS1 = p
+/**
+ * \brief Enable the USART 1 interrupt.
+ *
+ * Requires enabling global interrupts (EA=1) separately.
+ *
+ * The USART interrupt fires for both *receive* (RX) and *transmit* (TX)
+ * completing, the interrupt must clear *both*.
+ **/
+#define ENABLE_USART1() \
+	ES1 = 1;
+/**
+ * \brief Clear USART 1 receive (RI1) bit.
+ **/
+#define CLEAR_USART1_RX() \
+	RI1 = 0;
+/**
+ * \brief Clear USART 1 transmit (TI1) bit.
+ **/
+#define CLEAR_USART1_TX() \
+	TI1 = 0;
+/**
+ * \brief Clear USART 1 both TX & RX bits.
+ **/
+#define CLEAR_USART1() \
+	CLEAR_USART1_RX(); \
+	CLEAR_USART1_TX();
+
+// I2C Interrupt
+// =======================================================================
+
+/**
+ * \brief Set the I2C interrupt priority.
+ *
+ * Does *not* enable the interrupt.
+ *
+ * \code
+ *  SET_I2C_ISR_PRIO(INTERRUPT_HIGH_PRIO) // Set I2C to high priority
+ *  SET_I2C_ISR_PRIO(INTERRUPT_LOW_PRIO)  // Set I2C to low priority
+ * \endcode
+ **/
+#define SET_I2C_ISR_PRIORITY(p) \
+	PI2C = p
+/**
+ * \brief Enable the I2C interrupt.
+ *
+ * Requires enabling global interrupts (EA=1) separately.
+ *
+ * The USART interrupt fires for both *receive* (RX) and *transmit* (TX)
+ * completing, the interrupt must clear *both*.
+ **/
+#define ENABLE_I2C() \
+	EI2C = 1;
+/**
+ * \brief Clear I2C interrupt.
+ **/
+#define CLEAR_I2C() \
+	EXIF &= ~bmI2CINT;
diff --git a/include/fx2macros.h b/include/fx2macros.h
index f59139c..c7f367d 100644
--- a/include/fx2macros.h
+++ b/include/fx2macros.h
@@ -32,6 +32,13 @@
 #define LSW(dword) (WORD)(dword & 0xffff)
 #define MAKEDWORD(msw,lsw) (((DWORD)msw << 16) | lsw)
 
+/**
+ * Load a word register (such as the data pointers), high byte then low byte.
+ */
+#define LOADWORD(reg, value) \
+    reg ## H = MSB(value); \
+    reg ## L = LSB(value);
+
 // clock stuff
 
 /**
diff --git a/include/fx2regs.h b/include/fx2regs.h
index 3e5da48..aa6392e 100644
--- a/include/fx2regs.h
+++ b/include/fx2regs.h
@@ -635,4 +635,10 @@ __sfr __at 0xF8 EIP; // EIP Bit Values differ from Reg320
 #define bmEP1OUTBSY     bmBIT1
 #define bmEP0BSY        bmBIT0
 
+/* EXIF - External interrupt flags */
+#define bmIE5           bmBIT7
+#define bmIE4           bmBIT6
+#define bmI2CINT        bmBIT5
+#define bmUSBNT         bmBIT4
+
 #endif   /* FX2REGS_H */
diff --git a/include/setupdat.h b/include/setupdat.h
index 0027845..f3c1928 100644
--- a/include/setupdat.h
+++ b/include/setupdat.h
@@ -138,36 +138,90 @@ typedef enum {
 
 
 /**
- * returns the control/status register for an end point
- * (bit 7=1 for IN, 0 for out
+ * \brief Get pointer to an endpoint's control/status register.
+ *
+ * \param Endpoint number (lower bits) and direction (bit 7).
  **/
 __xdata BYTE* ep_addr(BYTE ep);
 
 /*
- You can call this function directly if you are polling
- for setup data in your main loop.
- You can also use the usbjt and enable the sudav isr
- and call the function from withing the sudav isr routine
-*/
+ * \brief Handle the "setup data" USB requests.
+ *
+ * This function should *not* be called inside an ISR (as it calls
+ * non-reentrant functions). Instead you should set a flag inside the ISR and
+ * then call this function ASAP as part of your main loop.
+ *
+ * \code
+ * volatile __bit dosud=FALSE;
+ * void sudav_isr() __interrupt SUDAV_ISR {
+ *     CLEAR_SUDAV();
+ *     if(dosud) {
+ *         // Indicate error
+ *     }
+ *     dosud=TRUE;
+ * }
+ *
+ * void main() {
+ *     // Other init code
+ *     ENABLE_SUDAV();
+ *     EA=1; // Enable interrupts
+ *
+ *     while(TRUE) {
+ *         if(dosud) { // Check flag
+ *             handle_setupdata();
+ *             dosud=FALSE;
+ *         }
+ *         // Other loop code
+ *     }
+ * }
+ * \endcode
+ */
 void handle_setupdata();
 
 
 /**
-    For devices to properly handle usb hispeed
-    (This is if your descriptor has high speed and full speed versions
-     and it should since the fx2lp is a high speed capable device
-    )
-    enable both USBRESET and HISPEED interrupts and
-    call this function to switch the descriptors.  This function uses
-    a __critical section to switch the descriptors and is safe to call
-    from the hispeed or reset interrupt.  See \ref fw.c
-
-    \param highspeed Call the function with highspeed = TRUE if 
-        calling because the highspeed interrupt was received.
-        If calling from usbreset, call with highspeed=false
-**/
+ * \brief Switch the descriptor pointer to right descriptor version.
+ *
+ * This function switches the descriptor pointer between the high speed and
+ * full speed descriptor versions. To use this function;
+ *  \li Your descriptors should have both versions.
+ *  \li Enable both USBRESET and HISPEED interrupts.
+ *  \li In your ISR for these functions call this method;
+ *    \li  * highspeed = FALSE for USBRESET
+ *    \li  * highspeed = TRUE for HISPEED
+ *
+ * This function is safe to call both inside an ISR and outside because it
+ * disable interrupts while operating (__critical).
+ *
+ * \code
+ * void usbreset_isr() __interrupt USBRESET_ISR {
+ *     handle_hispeed(FALSE);
+ *     CLEAR_USBRESET();
+ * }
+ * void hispeed_isr() __interrupt HISPEED_ISR {
+ *     handle_hispeed(TRUE);
+ *     CLEAR_HISPEED();
+ * }
+ *
+ * void main() {
+ *     ENABLE_USBRESET();
+ *     ENABLE_HISPEED();
+ * }
+ * \endcode
+ *
+ * See \ref fw.c for full example.
+ *
+ * \param highspeed Use high speed descriptor?
+ *     \li TRUE, use high speed descriptor.
+ *     \li FALSE, use full speed descriptor.
+ **/
 void handle_hispeed( BOOL highspeed );
 
+/* Descriptor header */
+typedef struct {
+    BYTE dsc_len;
+    BYTE dsc_type;
+} HEADER_DSCR;
 
 /* descriptor types */
 #define DSCR_DEVICE_TYPE 1
@@ -177,13 +231,10 @@ void handle_hispeed( BOOL highspeed );
 #define DSCR_OTHERSPD_TYPE 7
 #define DSCR_DEBUG_TYPE 10
 
-/* usb spec 2 */
-#define DSCR_BCD 2
-
-
-/* device descriptor */
-#define DSCR_DEVICE_LEN 18
+/* USB version 2.0 */
+#define DSCR_BCD 0x0200
 
+/* Device descriptor */
 typedef struct {
     BYTE dsc_len; // descriptor length (18 for this )
     BYTE dsc_type; // dscr type
@@ -199,26 +250,18 @@ typedef struct {
     BYTE idx_devstr; // product string index
     BYTE idx_serstr; // serial number index
     BYTE num_configs; // number of configurations
-        
 } DEVICE_DSCR;
+#define DSCR_DEVICE_LEN 18
 
-
-/* config descriptor */
+/* Config descriptor  */
 #define DSCR_CONFIG_LEN 9
-typedef struct {
-    BYTE dsc_len; // 9 for this one
-    BYTE dsc_type; // dscr type
-    
-} CONFIG_DSCR;
+#define CONFIG_DSCR DSCR_HEAD
 
-/* string descriptor */
+/* String descriptor */
 typedef struct {
     BYTE dsc_len;
     BYTE dsc_type;
     BYTE pstr;
 } STRING_DSCR;
 
-
-
-
 #endif
diff --git a/lib/Makefile b/lib/Makefile
index f7ecf14..42eb04d 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -18,7 +18,7 @@ SHELL := /bin/bash
 
 AS8051?=sdas8051
 SOURCES = serial.c i2c.c delay.c setupdat.c gpif.c eputils.c $(wildcard interrupts/*.c)
-FX2_OBJS = $(patsubst %.c,%.rel, $(SOURCES)) usbav.rel int4av.rel
+FX2_OBJS = $(patsubst %.c,%.rel, $(SOURCES)) usbav.rel
 INCLUDES = -I../include
 SDCC = sdcc -mmcs51 $(SDCCFLAGS)
 LIBS = fx2.lib
@@ -31,9 +31,6 @@ $(LIBS): $(FX2_OBJS)
 usbav.rel: usbav.a51
 	$(AS8051) -logs usbav.a51
 
-int4av.rel: int4av.a51
-	$(AS8051) -logs int4av.a51
-
 %.rel: %.c
 	$(SDCC) $(INCLUDES) -c $< -o $@
 
diff --git a/lib/eputils.c b/lib/eputils.c
index e459aee..d482350 100644
--- a/lib/eputils.c
+++ b/lib/eputils.c
@@ -16,9 +16,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  **/
 
-
-
-
 #include <eputils.h>
 
 #include <fx2regs.h>
@@ -33,11 +30,7 @@ void readep0( BYTE* dst, WORD len) {
     WORD read = 0; // n bytes read
     BYTE c,avail;
     while (read < len) {
-        EP0BCH = 0;
-        // NOTE need syncdelay?
-        EP0BCL = 0; // re-arm ep so host can send more
-        while (EP0CS & bmEPBUSY);
-        avail = EP0BCL; // max size fits in one byte (64 bytes)
+        avail = ep0_recv();
         for (c=0;c<avail;++c)
             dst[read+c] = EP0BUF[c];
         read += avail;
@@ -49,12 +42,46 @@ void writeep0( BYTE* src, WORD len) {
     WORD written = 0;
     BYTE c;
     while ( written < len ) {
-        while ( EP0CS & bmEPBUSY ); // wait
+        ep0_busywait();
         for (c=0;c<64 && written<len;++c ) {
             EP0BUF[c] = src[written++];
         }
-        EP0BCH = 0;
-        EP0BCL= c;
-        printf ( "Write %d bytes\n", c );
+        ep0_load_length(c);
+        printf("Write %d bytes\n", c);
     }
 }
+
+void ep0_send_descriptor(__xdata BYTE* src) {
+    // The ep0_load_length will be read out of the descriptor.
+    ep0_mode(EP0_DATA_AUTO, EP0_LENGTH_AUTO);
+    ep0_load_sudptr(src);
+}
+
+void ep0_send_auto(__xdata BYTE* src, WORD len) {
+    ep0_mode(EP0_DATA_AUTO, EP0_LENGTH_MANUAL);
+    ep0_load_length(len);
+    ep0_load_sudptr(src);
+}
+
+void ep0_send_byte(BYTE data) {
+    ep0_mode(EP0_DATA_MANUAL, EP0_LENGTH_MANUAL);
+    EP0BUF[0] = data;
+    ep0_load_length(sizeof(data));
+}
+
+void ep0_send_word(WORD data) {
+    ep0_mode(EP0_DATA_MANUAL, EP0_LENGTH_MANUAL);
+    EP0BUF[0] = MSB(data);
+    EP0BUF[1] = LSB(data);
+    ep0_load_length(sizeof(data));
+}
+
+BYTE ep0_recv() {
+    BYTE len = 0;
+    ep0_mode(EP0_DATA_MANUAL, EP0_LENGTH_MANUAL);
+    ep0_arm(); //ep0_load_length(len);
+    ep0_busywait();
+    len = ep0_get_length();
+    // EP0BUF now has the requested data
+    return len;
+}
diff --git a/lib/int4av.a51 b/lib/int4av.a51
deleted file mode 100644
index 85bce78..0000000
--- a/lib/int4av.a51
+++ /dev/null
@@ -1,28 +0,0 @@
-; Copyright (C) 2010 Ubixum, Inc. 
-;
-; This library is free software; you can redistribute it and/or
-; modify it under the terms of the GNU Lesser General Public
-; License as published by the Free Software Foundation; either
-; version 2.1 of the License, or (at your option) any later version.
-; 
-; This library 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
-; Lesser General Public License for more details.
-; 
-; You should have received a copy of the GNU Lesser General Public
-; License along with this library; if not, write to the Free Software
-; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-.module INT4AV ; jump table for int4AV (GPIF & endpoint interrupts)
-
-.globl _INT4JT
-
-.area INT4AV (ABS,OVR)
-.org    0x53 ; where INT4 jumps to 
-_INT4AV = #. + 2
-    ljmp _INT2JT ; the addr gets replaced so this really goes to int4jt locations
-
-
-.area INT4JT ( CODE )
-_INT4JT: ; doesn't do anything but forces this module to be linked in if gpif macro used.
diff --git a/lib/interrupts/ep0ack_isr.c b/lib/interrupts/ep0ack_isr.c
index 3ea4b1e..3fb2085 100644
--- a/lib/interrupts/ep0ack_isr.c
+++ b/lib/interrupts/ep0ack_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep0ack_isr() __interrupt EP0ACK_ISR {}
+void ep0ack_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep0in_isr.c b/lib/interrupts/ep0in_isr.c
index d0ebc22..76256a9 100644
--- a/lib/interrupts/ep0in_isr.c
+++ b/lib/interrupts/ep0in_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep0in_isr() __interrupt EP0IN_ISR {}
+void ep0in_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep0out_isr.c b/lib/interrupts/ep0out_isr.c
index 5c76574..2bea93a 100644
--- a/lib/interrupts/ep0out_isr.c
+++ b/lib/interrupts/ep0out_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep0out_isr() __interrupt EP0OUT_ISR {}
+void ep0out_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep0ping_isr.c b/lib/interrupts/ep0ping_isr.c
index 85716c9..af07fbf 100644
--- a/lib/interrupts/ep0ping_isr.c
+++ b/lib/interrupts/ep0ping_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep0ping_isr() __interrupt EP0PING_ISR {}
+void ep0ping_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep1in_isr.c b/lib/interrupts/ep1in_isr.c
index afc8841..cf89ba3 100644
--- a/lib/interrupts/ep1in_isr.c
+++ b/lib/interrupts/ep1in_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep1in_isr() __interrupt EP1IN_ISR {}
+void ep1in_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep1out_isr.c b/lib/interrupts/ep1out_isr.c
index 51f5b5c..af2c0e9 100644
--- a/lib/interrupts/ep1out_isr.c
+++ b/lib/interrupts/ep1out_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep1out_isr() __interrupt EP1OUT_ISR {}
+void ep1out_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep1ping_isr.c b/lib/interrupts/ep1ping_isr.c
index fa77349..22bad45 100644
--- a/lib/interrupts/ep1ping_isr.c
+++ b/lib/interrupts/ep1ping_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep1ping_isr() __interrupt EP1PING_ISR {}
+void ep1ping_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep2_isr.c b/lib/interrupts/ep2_isr.c
index d91764e..9699247 100644
--- a/lib/interrupts/ep2_isr.c
+++ b/lib/interrupts/ep2_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep2_isr() __interrupt EP2_ISR {}
+void ep2_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep2ef_isr.c b/lib/interrupts/ep2ef_isr.c
index d1509a7..387f52c 100644
--- a/lib/interrupts/ep2ef_isr.c
+++ b/lib/interrupts/ep2ef_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep2ef_isr() __interrupt EP2EF_ISR{}
+void ep2ef_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep2ff_isr.c b/lib/interrupts/ep2ff_isr.c
index ebfa8f1..3520bb5 100644
--- a/lib/interrupts/ep2ff_isr.c
+++ b/lib/interrupts/ep2ff_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep2ff_isr() __interrupt EP2FF_ISR{}
+void ep2ff_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep2isoerr_isr.c b/lib/interrupts/ep2isoerr_isr.c
index 1bd1a72..f6d8194 100644
--- a/lib/interrupts/ep2isoerr_isr.c
+++ b/lib/interrupts/ep2isoerr_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep2isoerr_isr() __interrupt EP2ISOERR_ISR {}
+void ep2isoerr_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep2pf_isr.c b/lib/interrupts/ep2pf_isr.c
index f12c5ba..1228cdc 100644
--- a/lib/interrupts/ep2pf_isr.c
+++ b/lib/interrupts/ep2pf_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep2pf_isr() __interrupt EP2PF_ISR{}
+void ep2pf_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep2ping_isr.c b/lib/interrupts/ep2ping_isr.c
index e292648..b9d424a 100644
--- a/lib/interrupts/ep2ping_isr.c
+++ b/lib/interrupts/ep2ping_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep2ping_isr() __interrupt EP2PING_ISR {}
+void ep2ping_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep4_isr.c b/lib/interrupts/ep4_isr.c
index 249162e..a71aa49 100644
--- a/lib/interrupts/ep4_isr.c
+++ b/lib/interrupts/ep4_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep4_isr() __interrupt EP4_ISR {}
+void ep4_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep4ef_isr.c b/lib/interrupts/ep4ef_isr.c
index 3e6f102..275d49c 100644
--- a/lib/interrupts/ep4ef_isr.c
+++ b/lib/interrupts/ep4ef_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep4ef_isr() __interrupt EP4EF_ISR{}
+void ep4ef_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep4ff_isr.c b/lib/interrupts/ep4ff_isr.c
index eb15bdb..15edd6c 100644
--- a/lib/interrupts/ep4ff_isr.c
+++ b/lib/interrupts/ep4ff_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep4ff_isr() __interrupt EP4FF_ISR{}
+void ep4ff_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep4isoerr_isr.c b/lib/interrupts/ep4isoerr_isr.c
index bd874c5..9fdb4fa 100644
--- a/lib/interrupts/ep4isoerr_isr.c
+++ b/lib/interrupts/ep4isoerr_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep4isoerr_isr() __interrupt EP4ISOERR_ISR {}
+void ep4isoerr_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep4pf_isr.c b/lib/interrupts/ep4pf_isr.c
index a8d3f08..c2d0258 100644
--- a/lib/interrupts/ep4pf_isr.c
+++ b/lib/interrupts/ep4pf_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep4pf_isr() __interrupt EP4PF_ISR{}
+void ep4pf_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep4ping_isr.c b/lib/interrupts/ep4ping_isr.c
index 14b39cc..254b38c 100644
--- a/lib/interrupts/ep4ping_isr.c
+++ b/lib/interrupts/ep4ping_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep4ping_isr() __interrupt EP4PING_ISR {}
+void ep4ping_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep6_isr.c b/lib/interrupts/ep6_isr.c
index dc6551e..f0edc9c 100644
--- a/lib/interrupts/ep6_isr.c
+++ b/lib/interrupts/ep6_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep6_isr() __interrupt EP6_ISR {}
+void ep6_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep6ef_isr.c b/lib/interrupts/ep6ef_isr.c
index cf29ba7..4eb75ed 100644
--- a/lib/interrupts/ep6ef_isr.c
+++ b/lib/interrupts/ep6ef_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep6ef_isr() __interrupt EP6EF_ISR{}
+void ep6ef_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep6ff_isr.c b/lib/interrupts/ep6ff_isr.c
index 3777f6e..cb73645 100644
--- a/lib/interrupts/ep6ff_isr.c
+++ b/lib/interrupts/ep6ff_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep6ff_isr() __interrupt EP6FF_ISR{}
+void ep6ff_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep6isoerr_isr.c b/lib/interrupts/ep6isoerr_isr.c
index f660858..3d720a8 100644
--- a/lib/interrupts/ep6isoerr_isr.c
+++ b/lib/interrupts/ep6isoerr_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep6isoerr_isr() __interrupt EP6ISOERR_ISR {}
+void ep6isoerr_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep6pf_isr.c b/lib/interrupts/ep6pf_isr.c
index bc1ae7b..59fbc6d 100644
--- a/lib/interrupts/ep6pf_isr.c
+++ b/lib/interrupts/ep6pf_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep6pf_isr() __interrupt EP6PF_ISR{}
+void ep6pf_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep6ping_isr.c b/lib/interrupts/ep6ping_isr.c
index eaabbbc..2e4dd6a 100644
--- a/lib/interrupts/ep6ping_isr.c
+++ b/lib/interrupts/ep6ping_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep6ping_isr() __interrupt EP6PING_ISR {}
+void ep6ping_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep8_isr.c b/lib/interrupts/ep8_isr.c
index a82eef0..473f255 100644
--- a/lib/interrupts/ep8_isr.c
+++ b/lib/interrupts/ep8_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep8_isr() __interrupt EP8_ISR {}
+void ep8_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep8ef_isr.c b/lib/interrupts/ep8ef_isr.c
index deca21e..542bbec 100644
--- a/lib/interrupts/ep8ef_isr.c
+++ b/lib/interrupts/ep8ef_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep8ef_isr() __interrupt EP8EF_ISR{}
+void ep8ef_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep8ff_isr.c b/lib/interrupts/ep8ff_isr.c
index 6fcb0c1..32541af 100644
--- a/lib/interrupts/ep8ff_isr.c
+++ b/lib/interrupts/ep8ff_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep8ff_isr() __interrupt EP8FF_ISR{}
+void ep8ff_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep8isoerr_isr.c b/lib/interrupts/ep8isoerr_isr.c
index 0d75ff4..e103ab7 100644
--- a/lib/interrupts/ep8isoerr_isr.c
+++ b/lib/interrupts/ep8isoerr_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep8isoerr_isr() __interrupt EP8ISOERR_ISR {}
+void ep8isoerr_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep8pf_isr.c b/lib/interrupts/ep8pf_isr.c
index f3a329c..4ef7ba1 100644
--- a/lib/interrupts/ep8pf_isr.c
+++ b/lib/interrupts/ep8pf_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep8pf_isr() __interrupt EP8PF_ISR{}
+void ep8pf_isr() __interrupt {}
 
diff --git a/lib/interrupts/ep8ping_isr.c b/lib/interrupts/ep8ping_isr.c
index 0bc4abf..642221a 100644
--- a/lib/interrupts/ep8ping_isr.c
+++ b/lib/interrupts/ep8ping_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ep8ping_isr() __interrupt EP8PING_ISR {}
+void ep8ping_isr() __interrupt {}
 
diff --git a/lib/interrupts/errlimit_isr.c b/lib/interrupts/errlimit_isr.c
index 115418d..07608bb 100644
--- a/lib/interrupts/errlimit_isr.c
+++ b/lib/interrupts/errlimit_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void errlimit_isr() __interrupt ERRLIMIT_ISR {}
+void errlimit_isr() __interrupt {}
 
diff --git a/lib/interrupts/gpifdone_isr.c b/lib/interrupts/gpifdone_isr.c
index 6b8b48d..ccda60a 100644
--- a/lib/interrupts/gpifdone_isr.c
+++ b/lib/interrupts/gpifdone_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void gpifdone_isr() __interrupt GPIFDONE_ISR{}
+void gpifdone_isr() __interrupt {}
 
diff --git a/lib/interrupts/gpifwf_isr.c b/lib/interrupts/gpifwf_isr.c
index de0ab4d..417f4a1 100644
--- a/lib/interrupts/gpifwf_isr.c
+++ b/lib/interrupts/gpifwf_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void gpifwf_isr() __interrupt GPIFWF_ISR{}
+void gpifwf_isr() __interrupt {}
 
diff --git a/lib/interrupts/hispeed_isr.c b/lib/interrupts/hispeed_isr.c
index 14f440a..ca05990 100644
--- a/lib/interrupts/hispeed_isr.c
+++ b/lib/interrupts/hispeed_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void hispeed_isr() __interrupt HISPEED_ISR {}
+void hispeed_isr()__interrupt {}
 
diff --git a/lib/interrupts/ibn_isr.c b/lib/interrupts/ibn_isr.c
index 4f54937..0c196fd 100644
--- a/lib/interrupts/ibn_isr.c
+++ b/lib/interrupts/ibn_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void ibn_isr() __interrupt IBN_ISR {}
+void ibn_isr() __interrupt {}
 
diff --git a/lib/interrupts/sof_isr.c b/lib/interrupts/sof_isr.c
index 15349c8..ea34f60 100644
--- a/lib/interrupts/sof_isr.c
+++ b/lib/interrupts/sof_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void sof_isr() __interrupt SOF_ISR {}
+void sof_isr() __interrupt {}
 
diff --git a/lib/interrupts/spare_isr.c b/lib/interrupts/spare_isr.c
index fa84995..06cc7f1 100644
--- a/lib/interrupts/spare_isr.c
+++ b/lib/interrupts/spare_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void spare_isr() __interrupt RESERVED_ISR {}
+void spare_isr() __interrupt {}
 
diff --git a/lib/interrupts/sudav_isr.c b/lib/interrupts/sudav_isr.c
index e72a1a1..13e69da 100644
--- a/lib/interrupts/sudav_isr.c
+++ b/lib/interrupts/sudav_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void sudav_isr() __interrupt SUDAV_ISR {}
+void sudav_isr() __interrupt {}
 
diff --git a/lib/interrupts/suspend_isr.c b/lib/interrupts/suspend_isr.c
index ef56b9c..98cadbb 100644
--- a/lib/interrupts/suspend_isr.c
+++ b/lib/interrupts/suspend_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void suspend_isr() __interrupt SUSPEND_ISR {}
+void suspend_isr() __interrupt {}
 
diff --git a/lib/interrupts/sutok_isr.c b/lib/interrupts/sutok_isr.c
index d857eb7..5f141ce 100644
--- a/lib/interrupts/sutok_isr.c
+++ b/lib/interrupts/sutok_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void sutok_isr() __interrupt SUTOK_ISR {}
+void sutok_isr() __interrupt {}
 
diff --git a/lib/interrupts/usbreset_isr.c b/lib/interrupts/usbreset_isr.c
index cf0bc47..b8d3bfb 100644
--- a/lib/interrupts/usbreset_isr.c
+++ b/lib/interrupts/usbreset_isr.c
@@ -18,5 +18,5 @@
 
 #include <autovector.h>
 
-void usbreset_isr() __interrupt USBRESET_ISR {}
+void usbreset_isr() __interrupt {}
 
diff --git a/lib/setupdat.c b/lib/setupdat.c
index 848305b..961eb27 100644
--- a/lib/setupdat.c
+++ b/lib/setupdat.c
@@ -35,12 +35,12 @@ extern BOOL handle_get_descriptor();
 extern BOOL handle_vendorcommand(BYTE cmd);
 extern BOOL handle_set_configuration(BYTE cfg);
 extern BOOL handle_get_interface(BYTE ifc, BYTE* alt_ifc);
-extern BOOL handle_set_interface(BYTE ifc,BYTE alt_ifc);
+extern BOOL handle_set_interface(BYTE ifc, BYTE alt_ifc);
 extern BYTE handle_get_configuration();
 extern void handle_reset_ep(BYTE ep);
 
 /**
- * Predefs for handlers
+ * Forward declaration for handlers
  **/
 
 
@@ -52,7 +52,7 @@ BOOL handle_clear_feature();
 //  SET_FEATURE=0x03,
 BOOL handle_set_feature();
   // 0x04 is reserved
-//  SET_ADDRESS=0x05, // this is handled by EZ-USB core unless RENUM=0
+//  SET_ADDRESS=0x05, // SET_ADDRESS is *always* handled by EZ-USB core.
 //  GET_DESCRIPTOR,
 void _handle_get_descriptor();
 //  SET_DESCRIPTOR,
@@ -70,10 +70,9 @@ void _handle_get_descriptor();
 */
 
 void handle_setupdata() {
-    //printf ( "Handle setupdat: %02x\n", SETUPDAT[1] );
+    printf("Handle setupdat: 0x%02x\n", SETUPDAT[1]);
 
     switch ( SETUPDAT[1] ) {
-
         case GET_STATUS:
             if (!handle_get_status())
                 STALLEP0();
@@ -99,7 +98,7 @@ void handle_setupdata() {
             break;
         case SET_CONFIGURATION:
             // user callback
-            if( !handle_set_configuration(SETUPDAT[2])) {
+            if(!handle_set_configuration(SETUPDAT[2])) {
                 STALLEP0();
             }
             break;
@@ -109,43 +108,41 @@ void handle_setupdata() {
                 if (!handle_get_interface(SETUPDAT[4],&alt_ifc)) {
                     STALLEP0();
                 } else {
-                 EP0BUF[0] = alt_ifc;
-                 EP0BCH=0;
-                 EP0BCL=1;
+                    EP0BUF[0] = alt_ifc;
+                    EP0BCH=0;
+                    EP0BCL=1;
                 }
             }
             break;
         case SET_INTERFACE:
             // user callback
-            if ( !handle_set_interface(SETUPDAT[4],SETUPDAT[2])) {
+            if (!handle_set_interface(SETUPDAT[4],SETUPDAT[2])) {
                 STALLEP0();
             }
             break;
         default:
-         if (!handle_vendorcommand(SETUPDAT[1])) {
-            printf ( "Unhandled Vendor Command: %02x\n" , SETUPDAT[1] );
-            STALLEP0();
-         }
-        
-        
+            if (!handle_vendorcommand(SETUPDAT[1])) {
+                printf("Unhandled Vendor Command: 0x%02x\n" , SETUPDAT[1]);
+                STALLEP0();
+            }
     }
     
     // do the handshake
     EP0CS |= bmHSNAK;
-    
 }
 
-__xdata BYTE* ep_addr(BYTE ep) { // bit 8 of ep_num is the direction
- BYTE ep_num = ep&~0x80; // mask the direction
- switch (ep_num) {
-  case 0: return &EP0CS;
-  case 1: return ep&0x80? &EP1INCS : &EP1OUTCS;
-  case 2: return &EP2CS;
-  case 4: return &EP4CS;
-  case 6: return &EP6CS;
-  case 8: return &EP8CS;
-  default: return NULL;
- }
+__xdata BYTE* ep_addr(BYTE ep) {
+    // Bit 8 of ep_num is the direction (In or Out) of the endpoint.
+    BYTE ep_num = ep & ~bmBIT7;
+    switch (ep_num) {
+        case 0: return &EP0CS;
+        case 1: return (ep&0x80) ? &EP1INCS : &EP1OUTCS;
+        case 2: return &EP2CS;
+        case 4: return &EP4CS;
+        case 6: return &EP6CS;
+        case 8: return &EP8CS;
+        default: return NULL;
+    }
 }
 
 
@@ -161,8 +158,8 @@ volatile BOOL remote_wakeup_allowed=FALSE;
 BOOL handle_get_status() {
     
     switch ( SETUPDAT[0] ) {
-
 //        case 0: // sometimes we get a 0 status too
+
         case GS_INTERFACE: 
             EP0BUF[0] = 0;
             EP0BUF[1] = 0;
@@ -191,10 +188,8 @@ BOOL handle_get_status() {
             }
             break;
         default:
-            printf ( "Unexpected Get Status: %02x\n", SETUPDAT[0] );
+            printf("Unexpected Get Status: 0x%02x\n", SETUPDAT[0]);
             return FALSE;
-            
-                        
     }
     return TRUE;
 }
@@ -204,77 +199,83 @@ BOOL handle_get_status() {
 #define GF_ENDPOINT 2
 
 BOOL handle_clear_feature() {
- //printf ( "Clear Feature\n" );
- switch ( SETUPDAT[0] ) {
-   case GF_DEVICE:
-    if (SETUPDAT[2] == 1) {
-        remote_wakeup_allowed=FALSE;
-        break;
-    }
+    printf("Clear Feature 0x%02x\n", SETUPDAT[0]);
 
-    if (SETUPDAT[2] == 6) // debug feature
-	break;
-    return FALSE;
-   case GF_ENDPOINT:
-    if (SETUPDAT[2] == 0) { // ep stall feature
-        __xdata BYTE* pep=ep_addr(SETUPDAT[4]);
-        printf ( "unstall endpoint %02X\n" , SETUPDAT[4] );
-        *pep &= ~bmEPSTALL;        
-	RESETTOGGLE(SETUPDAT[4]);
-    } else {
-        printf ( "unsupported ep feature %02x", SETUPDAT[2] );
-        return FALSE;
-    }
+    switch ( SETUPDAT[0] ) {
+        case GF_DEVICE:
+            if (SETUPDAT[2] == 1) {
+                remote_wakeup_allowed=FALSE;
+                break;
+            }
+
+            if (SETUPDAT[2] == 6) // debug feature
+                break;
 
-    break;
-   default:
-    return handle_vendorcommand(SETUPDAT[1]);
- }
- return TRUE;
+            return FALSE;
+        case GF_ENDPOINT:
+            if (SETUPDAT[2] == 0) { // ep stall feature
+                __xdata BYTE* pep=ep_addr(SETUPDAT[4]);
+                printf("unstall endpoint 0x%02x\n" , SETUPDAT[4]);
+                *pep &= ~bmEPSTALL;
+                RESETTOGGLE(SETUPDAT[4]);
+            } else {
+                printf("unsupported ep feature 0x%02x\n", SETUPDAT[2]);
+                return FALSE;
+            }
+            break;
+        default:
+            return handle_vendorcommand(SETUPDAT[1]);
+    }
+    return TRUE;
 }
 
 BOOL handle_set_feature() {
- printf ( "Set Feature %02x\n", SETUPDAT[0] );
- switch ( SETUPDAT[0] ) {
-  case GF_DEVICE:
-    if (SETUPDAT[2] == 2) break; // this is TEST_MODE and we simply need to return the handshake
-    if (SETUPDAT[2] == 1) {
-       remote_wakeup_allowed=TRUE; 
-       break;
-    }
-    if (SETUPDAT[2] == 6) // debug feature
-	break;
-    return FALSE;
-  case GF_ENDPOINT:
-    if ( SETUPDAT[2] == 0 ) { // ep stall feature
-        // set TRM 2.3.2
-        // stall and endpoint
-        __xdata BYTE* pep = ep_addr(SETUPDAT[4]);
-        printf ( "Stall ep %d\n", SETUPDAT[4] );
-        if (!pep) {            
+    printf("Set Feature 0x%02x\n", SETUPDAT[0]);
+
+    switch ( SETUPDAT[0] ) {
+        case GF_DEVICE:
+            // this is TEST_MODE and we simply need to return the handshake
+            if (SETUPDAT[2] == 2)
+                break;
+
+            if (SETUPDAT[2] == 1) {
+                remote_wakeup_allowed=TRUE;
+                break;
+            }
+            // debug feature
+            if (SETUPDAT[2] == 6)
+                break;
+
             return FALSE;
-        }
-        
-        *pep |= bmEPSTALL;
-        // should now reset data toggles
-        // write ep+dir to TOGCTL
-        RESETTOGGLE(SETUPDAT[4]);
-        // restore stalled ep to default condition
-        // NOTE
-        //handle_reset_ep(SETUPDAT[4]);
+        case GF_ENDPOINT:
+            if ( SETUPDAT[2] == 0 ) { // ep stall feature
+                // set TRM 2.3.2
+                // stall and endpoint
+                __xdata BYTE* pep = ep_addr(SETUPDAT[4]);
+                printf("Stall ep 0x%02x\n", SETUPDAT[4]);
+                if (!pep) {
+                    return FALSE;
+                }
         
-    } else {
-        printf ( "unsupported ep feature %02x\n", SETUPDAT[2] );
-        return FALSE;
-    }  
-   break;
-   default:
-    return handle_vendorcommand(SETUPDAT[1]);
- }
- return TRUE;
+                *pep |= bmEPSTALL;
+                // should now reset data toggles
+                // write ep+dir to TOGCTL
+                RESETTOGGLE(SETUPDAT[4]);
+                // restore stalled ep to default condition
+                // NOTE
+                //handle_reset_ep(SETUPDAT[4]);
+            } else {
+                printf("unsupported ep feature 0x%02x\n", SETUPDAT[2]);
+                return FALSE;
+            }
+            break;
+        default:
+            return handle_vendorcommand(SETUPDAT[1]);
+    }
+    return TRUE;
 }
 
-/* these are devined in dscr.asm
+/* these are defined in dscr.asm
    and need to be customized then
    linked in by the firmware manually */
 extern __code WORD dev_dscr;
@@ -283,20 +284,28 @@ extern __code WORD highspd_dscr;
 extern __code WORD fullspd_dscr;
 extern __code WORD dev_strings;
 
+/**
+ * \brief Pointer to the active descriptor.
+ **/
 WORD pDevConfig = (WORD)&fullspd_dscr;
+/**
+ * \brief Pointer to the inactive descriptor.
+ **/
 WORD pOtherConfig = (WORD)&highspd_dscr;
 
-void handle_hispeed(BOOL highspeed) {
- __critical { 
-     printf ( "Hi Speed or reset Interrupt\n" );
-     if (highspeed) {
-         pDevConfig=(WORD)&highspd_dscr;
-         pOtherConfig=(WORD)&fullspd_dscr;
-     } else {
+/**
+ * This function is called inside ISR functions, so must *not* call any
+ * non-reentrant functions.
+ * (This *includes* things like printf provided by SDCC.)
+ **/
+void handle_hispeed(BOOL highspeed) __critical {
+    if (highspeed) {
+        pDevConfig=(WORD)&highspd_dscr;
+        pOtherConfig=(WORD)&fullspd_dscr;
+    } else {
         pDevConfig=(WORD)&fullspd_dscr;
         pOtherConfig=(WORD)&highspd_dscr;
-     }
- }
+    }
 }
 
 /**
@@ -308,25 +317,25 @@ void handle_hispeed(BOOL highspeed) {
  *  Other-Speed
  **/
 void _handle_get_descriptor() {
-    //printf ( "Get Descriptor\n" );
+    printf("Get Descriptor ");
 
     // Sets to "Setup Data Pointer Auto Mode" see Appendix C - 29 of TRM
     SUDPTRCTL = 0x01;
 
     switch ( SETUPDAT[3] ) {
         case DSCR_DEVICE_TYPE:
-            printf ( "Get Device Config\n" );
+            printf("Device\n");
             SUDPTRH = MSB((WORD)&dev_dscr);
             SUDPTRL = LSB((WORD)&dev_dscr);
             break;
         case DSCR_CONFIG_TYPE:
             // get the config descriptor
-            printf ( "Get Config Descriptor\n");
+            printf("Config\n");
             SUDPTRH = MSB(pDevConfig);
             SUDPTRL = LSB(pDevConfig);
             break;        
         case DSCR_STRING_TYPE:
-            //printf ( "Get String Descriptor idx: %d\n", SETUPDAT[2] );
+            printf("String idx: %d\n", SETUPDAT[2]);
             {
                 STRING_DSCR* pStr = (STRING_DSCR*)&dev_strings;
                 // pStr points to string 0
@@ -334,20 +343,20 @@ void _handle_get_descriptor() {
                 BYTE cur=0; // current check
                 do {
                     if (idx==cur++) break;
-                    //printf ( "Length of pStr: %d\n", pStr->dsc_len );
-                    //printf ( "pstr: %04x to ", pStr );
+                    //printf("Length of pStr: %d\n", pStr->dsc_len);
+                    //printf("pstr: 0x%04x to ", pStr);
                     pStr = (STRING_DSCR*)((BYTE*)pStr + pStr->dsc_len);
-                    //printf ( "%04x\n" , pStr );
+                    //printf("%04x\n", pStr);
                     if (pStr->dsc_type != DSCR_STRING_TYPE) pStr=NULL;
                 } while ( pStr && cur<=idx);
                 
                 if (pStr) {
-                    /* BYTE i;
-                    //printf ( "found str: '");
-                    for (i=0;i<pStr->dsc_len-2;++i) {
-                       printf ( i%2==0?"%c":"%02x", *((BYTE*)(&pStr->pstr)+i));
-                    } printf ( "\n"); */
-                    
+                    //BYTE i;
+                    //printf("found str: '");
+                    //for (i=0;i<pStr->dsc_len-2;++i) {
+                    //    printf(i%2==0?"%c":"%02x", *((BYTE*)(&pStr->pstr)+i));
+                    //} printf("\n");
+
                     SUDPTRH = MSB((WORD)pStr);
                     SUDPTRL = LSB((WORD)pStr);
                     //SUDPTRH = MSB((WORD)&dev_strings);
@@ -358,20 +367,18 @@ void _handle_get_descriptor() {
             
             break;
         case DSCR_DEVQUAL_TYPE:
-            printf ( "Get Device Qualifier Descriptor\n");
+            printf("Device Qualifier\n");
             // assumes this is a high speed capable device
             SUDPTRH = MSB((WORD)&dev_qual_dscr);
             SUDPTRL = LSB((WORD)&dev_qual_dscr);
             break;
         case DSCR_OTHERSPD_TYPE:
-            printf ( "Other Speed Descriptor\n");
+            printf("Other Speed\n");
             SUDPTRH = MSB(pOtherConfig);
             SUDPTRL = LSB(pOtherConfig);
             break;
         default:
-            printf ( "Unhandled Get Descriptor: %02x\n", SETUPDAT[3]);
+            printf("Unknown: %02x\n", SETUPDAT[3]);
             STALLEP0();
     }
-    
 }
-
diff --git a/lib/usbav.a51 b/lib/usbav.a51
index ce956d9..a73dc9f 100644
--- a/lib/usbav.a51
+++ b/lib/usbav.a51
@@ -16,19 +16,15 @@
 
 .module INT2AV ; jump table for usb auto vector
 
-.globl _INT2JT ; defined as global so this assembly gets included in project 
-
-.area INT2AV (ABS,OVR)
-.org    0x43 ; this is where USBINT ( interrupt 8 ) jumps to
-_INT2AV = #. + 2 ; two bytes for ljmp (auto set by INT2IVEC)
-    ljmp _INT2JT
-
 ; INT2 Jump Table
+.globl _usb_isr  ; define jump target for interrupt 8 (USB)
+.globl _gpif_isr ; define jump target for interrupt 10 (GPIF)
 
 .area INT2JT ( CODE )
 ;.org    0x1A00 ; needs to be on a page boundary
 
-_INT2JT:
+_gpif_isr:
+_usb_isr:
     ljmp _sudav_isr
     .db 0
     ljmp _sof_isr

Reply via email to