Index: firmware/usb/usb.h
===================================================================
--- firmware/usb/usb.h	(revision 274)
+++ firmware/usb/usb.h	(revision 275)
@@ -5,6 +5,7 @@
 //#include <stdbool.h>
 
 #include "common/integer.h"
+#include "timer.h"
 
 /* NAK powers. To save space in endpoint data structure, amount of retries */
 /* before giving up and returning 0x4 is stored in bmNakPower as a power of 2.*/
@@ -70,15 +71,12 @@
     } __attribute__((packed));
   } __attribute__((packed)) ReqType_u;
   uint8_t    bRequest;		   //   1      Request
-  union {
-    uint16_t    wValue;            //   2/3    Depends on bRequest
-    struct {
-      uint8_t    wValueLo;
-      uint8_t    wValueHi;
-    } __attribute__((packed));
-  }  __attribute__((packed)) wVal_u;
-  uint16_t    wIndex;              //   4      Depends on bRequest
-  uint16_t    wLength;             //   6      Depends on bRequest
+  uint8_t    wValueL;
+  uint8_t    wValueH;
+  uint8_t    wIndexL;              //   4      Depends on bRequest
+  uint8_t    wIndexH;              //   5      Depends on bRequest
+  uint8_t    wLengthL;             //   6      Depends on bRequest
+  uint8_t    wLengthH;             //   7      Depends on bRequest
 } __attribute__((packed)) setup_pkt_t;
 
 // Additional Error Codes
@@ -106,6 +104,7 @@
   uint8_t parent;                          // parent device address
   uint8_t port;
   bool lowspeed;
+  char volatile * host_addr;
 
   union {
     usb_hub_info_t hub_info;
@@ -113,6 +112,14 @@
   };
 } usb_device_t;
 
+struct usb_host
+{
+	uint8_t usb_task_state;
+        unsigned char * addr;
+        msec_t poll;
+        msec_t delay;
+};
+
 #define USB_CLASS_USE_CLASS_INFO          0x00    // Use Class Info in the Interface Descriptors
 #define USB_CLASS_AUDIO                   0x01    // Audio
 #define USB_CLASS_COM_AND_CDC_CTRL        0x02    // Communications and CDC Control
@@ -143,14 +150,18 @@
 typedef struct {
   uint8_t  bLength;            // Length of this descriptor.
   uint8_t  bDescriptorType;    // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE).
-  uint16_t bcdUSB;	       // USB Spec Release Number (BCD).
+  uint8_t bcdUSBL;	       // USB Spec Release Number (BCD).
+  uint8_t bcdUSBH;	       // USB Spec Release Number (BCD).
   uint8_t  bDeviceClass;       // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
   uint8_t  bDeviceSubClass;    // Subclass code (assigned by the USB-IF).
   uint8_t  bDeviceProtocol;    // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
   uint8_t  bMaxPacketSize0;    // Maximum packet size for endpoint 0.
-  uint16_t idVendor;	       // Vendor ID (assigned by the USB-IF).
-  uint16_t idProduct;	       // Product ID (assigned by the manufacturer).
-  uint16_t bcdDevice;	       // Device release number (BCD).
+  uint8_t idVendorL;	       // Vendor ID (assigned by the USB-IF).
+  uint8_t idVendorH;	       // Vendor ID (assigned by the USB-IF).
+  uint8_t idProductL;	       // Product ID (assigned by the manufacturer).
+  uint8_t idProductH;	       // Product ID (assigned by the manufacturer).
+  uint8_t bcdDeviceL;	       // Device release number (BCD).
+  uint8_t bcdDeviceH;	       // Device release number (BCD).
   uint8_t  iManufacturer;      // Index of String Descriptor describing the manufacturer.
   uint8_t  iProduct;           // Index of String Descriptor describing the product.
   uint8_t  iSerialNumber;      // Index of String Descriptor with the device's serial number.
@@ -161,7 +172,8 @@
 typedef struct {
   uint8_t bLength;             // Length of this descriptor.
   uint8_t bDescriptorType;     // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION).
-  uint16_t wTotalLength;       // Total length of all descriptors for this configuration.
+  uint8_t wTotalLengthL;       // Total length of all descriptors for this configuration.
+  uint8_t wTotalLengthH;       // Total length of all descriptors for this configuration.
   uint8_t bNumInterfaces;      // Number of interfaces in this configuration.
   uint8_t bConfigurationValue; // Value of this configuration (1 based).
   uint8_t iConfiguration;      // Index of String Descriptor describing the configuration.
@@ -230,10 +242,8 @@
 #define USB_DESCRIPTOR_OTHER_SPEED      0x07    // bDescriptorType for a Other Speed Configuration.
 #define USB_DESCRIPTOR_INTERFACE_POWER  0x08    // bDescriptorType for Interface Power.
 
-void usb_init();
-void usb_poll();
-void usb_SetHubPreMask(void);
-void usb_ResetHubPreMask(void);
+void usb_init(struct usb_host * host, int portnumber);
+void usb_poll(struct usb_host * host);
 
 uint8_t usb_set_addr( usb_device_t *, uint8_t );
 uint8_t usb_ctrl_req( usb_device_t *, uint8_t bmReqType, 
Index: firmware/Makefile
===================================================================
--- firmware/Makefile	(revision 274)
+++ firmware/Makefile	(revision 275)
@@ -32,6 +32,7 @@
 DE1_5200_DIR = de1_5200
 CHAMELEON_DIR = chameleon
 MCC_DIR = mcc
+MCCTV_DIR = mcctv
 MIST_DIR = mist
 MIST_5200_DIR = mist_5200
 LINUXSIM_DIR = linux
@@ -42,6 +43,7 @@
 DE1_5200_BUILD_DIR = $(BUILD_DIR)/$(DE1_5200_DIR)
 CHAMELEON_BUILD_DIR = $(BUILD_DIR)/$(CHAMELEON_DIR)
 MCC_BUILD_DIR = $(BUILD_DIR)/$(MCC_DIR)
+MCCTV_BUILD_DIR = $(BUILD_DIR)/$(MCCTV_DIR)
 MIST_BUILD_DIR = $(BUILD_DIR)/$(MIST_DIR)
 MIST_5200_BUILD_DIR = $(BUILD_DIR)/$(MIST_5200_DIR)
 LINUXSIM_BUILD_DIR = $(BUILD_DIR)/$(LINUXSIM_DIR)
@@ -57,6 +59,7 @@
 A800_SRC = ${A800_SRC_LIGHT} a800/joystick.c libgcc_divmod.c
 5200_SRC_LIGHT = 5200/freeze.c  5200/mainmenu.c
 5200_SRC = ${5200_SRC_LIGHT} 5200/joystick.c
+USB_SRC = usb/hid.c  usb/hidparser.c  usb/hub.c usb/timer.c  usb/usb.c
 
 AEON_LITE_PRJ = AEON_LITE
 AEON_LITE_SRC = $(COMMON_SRC) $(SDCARD_SRC) $(A800_SRC) de1/dirs.c
@@ -75,9 +78,15 @@
 CHAMELEON_OBJ = $(patsubst %.c,$(CHAMELEON_BUILD_DIR)/%.o,$(CHAMELEON_SRC))
 
 MCC_PRJ = MCC216
-MCC_SRC = $(COMMON_SRC) $(SDCARD_SRC) $(A800_SRC) mcc/dirs.c
+MCC_SRC = $(COMMON_SRC) $(SDCARD_SRC) $(A800_SRC) $(USB_SRC) mcc/dirs.c
+#MCC_SRC = $(COMMON_SRC) $(SDCARD_SRC) $(A800_SRC) mcc/dirs.c
 MCC_OBJ = $(patsubst %.c,$(MCC_BUILD_DIR)/%.o,$(MCC_SRC))
 
+MCCTV_PRJ = MCCTV
+MCCTV_SRC = $(COMMON_SRC) $(SDCARD_SRC) $(A800_SRC) $(USB_SRC) mcc/dirs.c
+#MCCTV_SRC = $(COMMON_SRC) $(SDCARD_SRC) $(A800_SRC) mcc/dirs.c
+MCCTV_OBJ = $(patsubst %.c,$(MCCTV_BUILD_DIR)/%.o,$(MCCTV_SRC))
+
 MIST_PRJ = MIST
 MIST_SRC = $(COMMON_SRC) $(SDCARD_SRC) $(A800_SRC) mist/dirs.c
 MIST_OBJ = $(patsubst %.c,$(MIST_BUILD_DIR)/%.o,$(MIST_SRC))
@@ -87,11 +96,12 @@
 MIST_5200_OBJ = $(patsubst %.c,$(MIST_5200_BUILD_DIR)/%.o,$(MIST_5200_SRC))
 
 LINKMAP  = ./standalone_simple.ld
+LINKMAP_LARGE  = ./standalone_simple_large.ld
 
 LINUXSIM_EXE	= linuxsim
-LINUXSIM_SRC	= $(COMMON_SRC) $(A800_SRC_LIGHT) linux/main.c linux/mmc.c \
+LINUXSIM_SRC	= $(COMMON_SRC) $(A800_SRC_LIGHT) $(USB_SRC) linux/main.c linux/mmc.c \
 	sd_direct/diskio_mmc.c linux/dirs.c linux/linux_memory.c linux/curses_screen.c \
-	linux/linux_helper.c
+	linux/linux_helper.c linux/emulate_usb.c
 
 LINUXSIM_5200_EXE	= linuxsim_5200
 LINUXSIM_5200_SRC	= $(COMMON_SRC) $(5200_SRC_LIGHT) linux/main.c linux/mmc.c \
@@ -108,17 +118,19 @@
 ZPUOPTS =
 CFLAGS  = -I. -Isd_direct -Iprintf -Ifat -Icommon -Isdram_common -c -g -Os $(ZPUOPTS) -DDISABLE_UART_RX
 
-HOST_CFLAGS += -I. -Isd_direct -Iprintf -Ifat -Icommon -Isdram_common -DDISABLE_UART_RX
+HOST_CFLAGS += -I. -Isd_direct -Iprintf -Ifat -Icommon -Isdram_common -DDISABLE_UART_RX -DUSB -Iusb
 
 LFLAGS  = -nostartfiles -nostdlib -Wl,--relax -g -Os -Wl,-Map=out.map
 LFLAGS_5200  = -nostartfiles -Wl,--relax -g -Os -Wl,-Map=out.map
 #LFLAGS  = -nostartfiles -Os
 
+CFLAGS_USB = $(CFLAGS) -DUSB -Iusb
+CFLAGS_USB2 = $(CFLAGS) -DUSB -DUSB2 -Iusb
 CFLAGS_5200 = $(CFLAGS) -DFIRMWARE_5200
 HOST_CFLAGS_5200 = $(HOST_CFLAGS) -DFIRMWARE_5200
 
 # Our target.
-all: mcc mist de1 aeon_lite chameleon  de1_5200 mist_5200
+all: mcc mcctv mist de1 aeon_lite chameleon  de1_5200 mist_5200
 
 install:
 	cd ../common/romgen && ./createall && cd ../../firmware
@@ -133,6 +145,8 @@
 
 mcc: $(BUILD_DIR) $(MCC_PRJ).bin $(MCC_PRJ).rpt
 
+mcctv: $(BUILD_DIR) $(MCCTV_PRJ).bin $(MCCTV_PRJ).rpt
+
 mist: $(BUILD_DIR) $(MIST_PRJ).bin $(MIST_PRJ).rpt
 
 mist_5200: $(BUILD_DIR) $(MIST_5200_PRJ).bin $(MIST_5200_PRJ).rpt
@@ -175,8 +189,12 @@
 	$(LD) $(LFLAGS) -T $(LINKMAP) -o $@ $+ $(LIBS)
 
 $(MCC_PRJ).elf: $(MINSTARTUP_OBJ) $(MCC_OBJ)
-	$(LD) $(LFLAGS) -T $(LINKMAP) -o $@ $+ $(LIBS)
+	$(LD) $(LFLAGS) -T $(LINKMAP_LARGE) -o $@ $+ $(LIBS)
+#	$(LD) $(LFLAGS) -T $(LINKMAP) -o $@ $+ $(LIBS)
 
+$(MCCTV_PRJ).elf: $(MINSTARTUP_OBJ) $(MCCTV_OBJ)
+	$(LD) $(LFLAGS) -T $(LINKMAP_LARGE) -o $@ $+ $(LIBS)
+
 $(MIST_PRJ).elf: $(MINSTARTUP_OBJ) $(MIST_OBJ)
 	$(LD) $(LFLAGS) -T $(LINKMAP) -o $@ $+ $(LIBS)
 
@@ -207,8 +225,12 @@
 
 $(MCC_BUILD_DIR)/%.o: %.c Makefile
 	mkdir -p `dirname $@`
-	$(CC) -I$(MCC_DIR) $(CFLAGS)  -o $@ -c $<
+	$(CC) -I$(MCC_DIR) $(CFLAGS_USB)  -o $@ -c $<
 
+$(MCCTV_BUILD_DIR)/%.o: %.c Makefile
+	mkdir -p `dirname $@`
+	$(CC) -I$(MCCTV_DIR) $(CFLAGS_USB2)  -o $@ -c $<
+
 $(MIST_BUILD_DIR)/%.o: %.c Makefile
 	mkdir -p `dirname $@`
 	$(CC) -I$(MIST_DIR) $(CFLAGS)  -o $@ -c $<
Index: firmware/a800/joystick.c
===================================================================
--- firmware/a800/joystick.c	(revision 274)
+++ firmware/a800/joystick.c	(revision 275)
@@ -5,6 +5,17 @@
 
 //#include <stdio.h>
 
+#ifdef USB
+#include "usb.h"
+#endif
+
+#ifdef USB
+extern struct usb_host usb_porta;
+#endif
+#ifdef USB2
+extern struct usb_host usb_portb;
+#endif
+
 void joystick_poll(struct joystick_status * status)
 {
 	status->x_ = 0;
@@ -12,6 +23,13 @@
 	status->fire_ = 0;
 	status->escape_ = 0;
 
+#ifdef USB
+	usb_poll(&usb_porta);
+#endif
+#ifdef USB2
+	usb_poll(&usb_portb);
+#endif
+
 	unsigned char porta = *atari_porta;
 
 	int controls = get_controls();
Index: firmware/a800/mainmenu.c
===================================================================
--- firmware/a800/mainmenu.c	(revision 274)
+++ firmware/a800/mainmenu.c	(revision 275)
@@ -5,6 +5,10 @@
 
 unsigned char freezer_rom_present;
 
+#ifdef USB
+#include "usb.h"
+#endif
+
 void loadosrom()
 {
 	if (file_size(files[5]) == 0x4000)
@@ -17,9 +21,21 @@
 	}
 }
 
+#ifdef USB
+struct usb_host usb_porta;
+#endif
+#ifdef USB2
+struct usb_host usb_portb;
+#endif
 
 void mainmenu()
 {
+#ifdef USB
+	usb_init(&usb_porta,0);
+#endif
+#ifdef USB2
+	usb_init(&usb_portb,1);
+#endif
 	freezer_rom_present = 0;
 	if (SimpleFile_OK == dir_init((void *)DIR_INIT_MEM, DIR_INIT_MEMSIZE))
 	{
@@ -79,7 +95,7 @@
 		//printf("DIR init failed\n");
 	}
 	reboot(1);
-	for (;;) actions();
+	for (;;) actions(1);
 }
 
 char const * get_ram()
@@ -120,7 +136,7 @@
 int settings()
 {
 	struct joystick_status joy;
-	joy.x_ = joy.y_ = joy.fire_ = 0;
+	joy.x_ = joy.y_ = joy.fire_ = joy.escape_ = 0;
 
 	int row = 0;
 
@@ -274,13 +290,18 @@
 	return 0;
 }
 
-
-
 void actions()
 {
 #ifdef LINUX_BUILD
 	check_keys();
 #endif
+#ifdef USB
+	usb_poll(&usb_porta);
+#endif
+#ifdef USB2
+	usb_poll(&usb_portb);
+#endif
+
 	// Show some activity!
 	//*atari_colbk = *atari_random;
 	
@@ -311,9 +332,32 @@
 	}
 	else if (get_hotkey_fileselect())
 	{
+/*#ifdef USB
 		set_pause_6502(1);
 		set_freezer_enable(0);
 		freeze();
+
+		debug_pos = 0;	
+		printf("Hello USB");
+		debug_pos = 80;
+		usb_init();
+		while (1)
+		{
+			usb_poll();
+			if (debug_pos>1000)
+			{
+				debug_pos = 80;
+			}
+		}
+
+		debug_pos = -1;
+		restore();
+		set_freezer_enable(freezer_rom_present);
+		set_pause_6502(0);
+#else*/
+		set_pause_6502(1);
+		set_freezer_enable(0);
+		freeze();
 		filter = filter_disks;
 		file_selector(files[0]);
 		debug_pos = -1;
Index: firmware/aeon_lite/memory.h
===================================================================
--- firmware/aeon_lite/memory.h	(revision 274)
+++ firmware/aeon_lite/memory.h	(revision 275)
@@ -22,6 +22,7 @@
 
 #define atari_regbase  ((void*) 0x10000)
 #define atari_regmirror  ((void*) 0x20000)
-#define config_regbase ((void*) 0x40000)
+#define zpu_regbase ((void*) 0x40000)
+#define pokey_regbase ((void*) 0x40400)
 
 #endif
Index: firmware/atari_drive_emulator.c
===================================================================
--- firmware/atari_drive_emulator.c	(revision 274)
+++ firmware/atari_drive_emulator.c	(revision 275)
@@ -114,16 +114,13 @@
 
 	//printf("Waiting for command\n");
 	//USART_Data_Ready();
-	while (0 == USART_Command_Line());
+	while (0 == USART_Command_Line()) actions();
 	//printf("Init:");
 	//printf("%d",*zpu_sio);
 	USART_Init(speed+6);
 	//printf("%d",speed);
 	//printf("\n");
-	while (1 == USART_Command_Line())
-	{
-		actions();
-	}
+	while (1 == USART_Command_Line()) actions();
 	for (i=0;i!=5;++i)
 		((char *)cmd)[i] = USART_Receive_Byte();
 	/*cmd->deviceId = USART_Receive_Byte();
@@ -131,10 +128,7 @@
 	cmd->aux1 = USART_Receive_Byte();
 	cmd->aux2 = USART_Receive_Byte();
 	cmd->chksum = USART_Receive_Byte();*/
-	while (0 == USART_Command_Line())
-	{
-		actions();
-	}
+	while (0 == USART_Command_Line());
 	//printf("cmd:");
 	//printf("Gone high\n");
 	atari_sector_buffer[0] = cmd->deviceId;
Index: firmware/linux/curses_screen.c
===================================================================
--- firmware/linux/curses_screen.c	(revision 274)
+++ firmware/linux/curses_screen.c	(revision 275)
@@ -129,8 +129,8 @@
 		switch (ch) {
 		case KEY_F(12):
 			*zpu_in1 = 1<<11; return;
-		case 27: // ESCAPE:
-			longjmp(exit_jmp_buf, 1);
+		case KEY_F(11):
+			*zpu_in1 = 1<<10; return;
 		}
 	}
 }
@@ -143,6 +143,7 @@
 	status->x_ = 0;
 	status->y_ = 0;
 	status->fire_ = 0;
+	status->escape_ = 0;
 
 
 	switch (ch) {
@@ -154,7 +155,7 @@
 	case 13:
 		status->fire_ = 1; break;
 	case 27: // ESCAPE:
-		longjmp(exit_jmp_buf, 1);
+		status->escape_ = 1; break;
 	default: break;
 	}
 }
Index: firmware/linux/linux_helper.c
===================================================================
--- firmware/linux/linux_helper.c	(revision 274)
+++ firmware/linux/linux_helper.c	(revision 275)
@@ -1,5 +1,3 @@
 #include "linux_helper.h"
 
-jmp_buf exit_jmp_buf;
-
 char* sdcard_filename = 0;
Index: firmware/linux/linux_helper.h
===================================================================
--- firmware/linux/linux_helper.h	(revision 274)
+++ firmware/linux/linux_helper.h	(revision 275)
@@ -1,9 +1,6 @@
 #ifndef LINUX_HELPER_H
 #define LINUX_HELPER_H
-#include <setjmp.h>
 
-extern jmp_buf exit_jmp_buf;
-
 extern char* sdcard_filename;
 
 #endif
Index: firmware/linux/linux_memory.c
===================================================================
--- firmware/linux/linux_memory.c	(revision 274)
+++ firmware/linux/linux_memory.c	(revision 275)
@@ -8,7 +8,8 @@
 void* SDRAM_BASE;
 void* atari_regbase;
 void* atari_regmirror;
-void* config_regbase;
+void* zpu_regbase;
+void* pokey_regbase;
 void* CARTRIDGE_MEM;
 
 void* FREEZER_RAM_MEM;
@@ -47,7 +48,8 @@
 	SDRAM_BASE = sdram_memory;
 	atari_regbase = atari_memory;
 	atari_regmirror = atari_mirror_memory;
-	config_regbase = config_memory;
+	zpu_regbase = config_memory;
+	pokey_regbase = config_memory+0x100*4;
 	CARTRIDGE_MEM = cartridge_memory;
 	FREEZER_RAM_MEM = freezer_ram_memory;
 	FREEZER_ROM_MEM = freezer_rom_memory;
Index: firmware/linux/main.c
===================================================================
--- firmware/linux/main.c	(revision 274)
+++ firmware/linux/main.c	(revision 275)
@@ -20,10 +20,8 @@
 
 	init_memory();
 
-	if (setjmp(exit_jmp_buf) == 0) {
-		print_log("starting zpu_main\n");
-		zpu_main();
-	}
+	print_log("starting zpu_main\n");
+	zpu_main();
 
 	deinit_curses_screen();
 	return 0;
Index: firmware/linux/memory.h
===================================================================
--- firmware/linux/memory.h	(revision 274)
+++ firmware/linux/memory.h	(revision 275)
@@ -23,7 +23,8 @@
 
 extern void* atari_regbase;
 extern void* atari_regmirror;
-extern void* config_regbase;
+extern void* zpu_regbase;
+extern void* pokey_regbase;
 
 void init_memory(void);
 
Index: firmware/main.h
===================================================================
--- firmware/main.h	(revision 274)
+++ firmware/main.h	(revision 275)
@@ -94,6 +94,9 @@
 	// pause counter runs at pokey frequency - should be 1.79MHz
 	int unsigned cycles = (num*230)>>7;
 	*zpu_pause = cycles;
+#ifdef LINUX_BUILD
+	usleep(num);
+#endif
 }
 
 void memset8(void * address, int value, int length)
Index: firmware/native/joystick.c
===================================================================
--- firmware/native/joystick.c	(revision 274)
+++ firmware/native/joystick.c	(revision 275)
@@ -66,6 +66,7 @@
 	status->x_ = 0;
 	status->y_ = 0;
 	status->fire_ = 0;
+	status->escape_ = 0;
 
 	unsigned char porta = *atari_porta;
 	if (0==(porta&0x2)) // down
Index: firmware/regs.h
===================================================================
--- firmware/regs.h	(revision 274)
+++ firmware/regs.h	(revision 275)
@@ -4,42 +4,45 @@
 
 static const int screen_address = 11328;
 
-#define zpu_in1 ((int volatile *)(0*4+config_regbase))
-#define zpu_in2 ((int volatile *)(1*4+config_regbase))
-#define zpu_in3 ((int volatile *)(2*4+config_regbase))
-#define zpu_in4 ((int volatile *)(3*4+config_regbase))
+#define zpu_in1 ((int volatile *)(0*4+zpu_regbase))
+#define zpu_in2 ((int volatile *)(1*4+zpu_regbase))
+#define zpu_in3 ((int volatile *)(2*4+zpu_regbase))
+#define zpu_in4 ((int volatile *)(3*4+zpu_regbase))
 
-#define zpu_out1 ((int volatile *)(4*4+config_regbase))
-#define zpu_out2 ((int volatile *)(5*4+config_regbase))
-#define zpu_out3 ((int volatile *)(6*4+config_regbase))
-#define zpu_out4 ((int volatile *)(7*4+config_regbase))
+#define zpu_out1 ((int volatile *)(4*4+zpu_regbase))
+#define zpu_out2 ((int volatile *)(5*4+zpu_regbase))
+#define zpu_out3 ((int volatile *)(6*4+zpu_regbase))
+#define zpu_out4 ((int volatile *)(7*4+zpu_regbase))
+#define zpu_out5 ((int volatile *)(14*4+zpu_regbase))
+#define zpu_out6 ((int volatile *)(15*4+zpu_regbase))
 
-#define zpu_pause ((int volatile *)(8*4+config_regbase))
+#define zpu_pause ((int volatile *)(8*4+zpu_regbase))
+#define zpu_timer ((int volatile *)(8*4+zpu_regbase))
 
-#define zpu_spi_data ((int volatile *)(9*4+config_regbase))
-#define zpu_spi_state ((int volatile *)(10*4+config_regbase))
+#define zpu_spi_data ((int volatile *)(9*4+zpu_regbase))
+#define zpu_spi_state ((int volatile *)(10*4+zpu_regbase))
 
-#define zpu_sio ((int volatile *)(11*4+config_regbase))
+#define zpu_sio ((int volatile *)(11*4+zpu_regbase))
 
-#define zpu_board ((int volatile *)(12*4+config_regbase))
+#define zpu_board ((int volatile *)(12*4+zpu_regbase))
 
-#define zpu_spi_dma ((int volatile *)(13*4+config_regbase))
+#define zpu_spi_dma ((int volatile *)(13*4+zpu_regbase))
 
-#define zpu_pokey_audf0 ((unsigned char volatile *)(0x10*4+config_regbase))
-#define zpu_pokey_audc0 ((unsigned char volatile *)(0x11*4+config_regbase))
-#define zpu_pokey_audf1 ((unsigned char volatile *)(0x12*4+config_regbase))
-#define zpu_pokey_audc1 ((unsigned char volatile *)(0x13*4+config_regbase))
-#define zpu_pokey_audf2 ((unsigned char volatile *)(0x14*4+config_regbase))
-#define zpu_pokey_audc2 ((unsigned char volatile *)(0x15*4+config_regbase))
-#define zpu_pokey_audf3 ((unsigned char volatile *)(0x16*4+config_regbase))
-#define zpu_pokey_audc3 ((unsigned char volatile *)(0x17*4+config_regbase))
+#define zpu_pokey_audf0 ((unsigned char volatile *)(0x0*4+pokey_regbase))
+#define zpu_pokey_audc0 ((unsigned char volatile *)(0x1*4+pokey_regbase))
+#define zpu_pokey_audf1 ((unsigned char volatile *)(0x2*4+pokey_regbase))
+#define zpu_pokey_audc1 ((unsigned char volatile *)(0x3*4+pokey_regbase))
+#define zpu_pokey_audf2 ((unsigned char volatile *)(0x4*4+pokey_regbase))
+#define zpu_pokey_audc2 ((unsigned char volatile *)(0x5*4+pokey_regbase))
+#define zpu_pokey_audf3 ((unsigned char volatile *)(0x6*4+pokey_regbase))
+#define zpu_pokey_audc3 ((unsigned char volatile *)(0x7*4+pokey_regbase))
 
-#define zpu_pokey_audctl ((unsigned char volatile *)(0x18*4+config_regbase))
+#define zpu_pokey_audctl ((unsigned char volatile *)(0x8*4+pokey_regbase))
 
-#define zpu_pokey_skrest ((unsigned char volatile *)(0x1a*4+config_regbase))
-#define zpu_pokey_serout ((unsigned char volatile *)(0x1d*4+config_regbase))
-#define zpu_pokey_irqen ((unsigned char volatile *)(0x1e*4+config_regbase))
-#define zpu_pokey_skctl ((unsigned char volatile *)(0x1f*4+config_regbase))
+#define zpu_pokey_skrest ((unsigned char volatile *)(0xa*4+pokey_regbase))
+#define zpu_pokey_serout ((unsigned char volatile *)(0xd*4+pokey_regbase))
+#define zpu_pokey_irqen ((unsigned char volatile *)(0xe*4+pokey_regbase))
+#define zpu_pokey_skctl ((unsigned char volatile *)(0xf*4+pokey_regbase))
 
 #define atari_nmien ((unsigned char volatile *)(0xd40e + atari_regbase))
 #define atari_dlistl ((unsigned char volatile *)(0xd402 + atari_regbase))
Index: firmware/sdram_common/memory.h
===================================================================
--- firmware/sdram_common/memory.h	(revision 274)
+++ firmware/sdram_common/memory.h	(revision 275)
@@ -23,6 +23,7 @@
 
 #define atari_regbase  ((void*) 0x10000)
 #define atari_regmirror  ((void*) 0x20000)
-#define config_regbase ((void*) 0x40000)
+#define zpu_regbase ((void*) 0x40000)
+#define pokey_regbase ((void*) 0x40400)
 
 #endif
Index: firmware/usb/events.h
===================================================================
--- firmware/usb/events.h	(revision 274)
+++ firmware/usb/events.h	(revision 275)
@@ -1,25 +1,148 @@
-#include "printf.h"
+//#include "printf.h"
+#include "regs.h"
 
-void event_keyboard(uint8_t i, uint8_t buf[])
+#include "keycodes.h"
+
+extern int debug_pos;
+
+uint8_t kbbuf[6];
+uint32_t jmaps[4];
+
+int8_t analogx[4];
+int8_t analogy[4];
+
+void event_keyboard(uint8_t mod, uint8_t buf[])
 {
+	//printf("Event keyboard:%d\n", mod);
+	/*int changed = 0;
+
+	if (lastmod!=i)
+	{
+		lastmod = i;
+		changed = 1;
+	}
 	int j;
-	printf("Event keyboard:%d\n", i);
-        for (j=0;j!=6;++j)
+        for (j=0;j!=8;++j)
 	{
-		printf("Event keyboard:%d = %x\n", j, buf[j]);
+		//printf("Event keyboard:%d = %x\n", j, buf[j]);
+		if (buf[j] != kbbuf[j])
+		{
+			changed = 1;
+			kbbuf[j] = buf[j];
+		}
+	}*/
+
+  /* usb modifer bits: 
+        0     1     2    3    4     5     6    7
+      LCTRL LSHIFT LALT LGUI RCTRL RSHIFT RALT RGUI
+  */
+
+	// Convert changes into a serial of release/press notifications
+	int i=0;
+	for(i=0;i!=8;++i)
+	{
+		int bit = 1<<i;
+		uint32_t pressed = !!(bit&mod);
+		uint32_t ps2_key = ps2_modifier[i];
+		*zpu_out4 = (pressed<<16)|ps2_key;
 	}
+	
+	// unpress old keys that are no longer pressed
+	for (i=0;i!=6;++i)
+	{
+		if (kbbuf[i]==MISS) continue;
+
+		uint32_t oldkey = usb2ps2[kbbuf[i]];
+		int j=0;
+		int found = 0;
+		for (j=0;j!=6;++j)
+		{
+			uint32_t newkey = usb2ps2[buf[i]];
+			if (oldkey==newkey) {found=1;break;}
+		}
+
+		if (!found)
+		{
+			*zpu_out4 = oldkey; // unpress
+		}
+	}
+
+	// press/hold new keys
+	for (i=0;i!=6;++i)
+	{
+		if (buf[i]==MISS) continue;
+
+		uint32_t newkey = usb2ps2[buf[i]];
+
+		// press new one
+		*zpu_out4 = (1<<16)|newkey;
+	}
+
+	for (i=0;i!=6;++i)
+	{
+		kbbuf[i] = buf[i]; // store
+	}
+
+/*	if (changed)
+	{
+		debug_pos = 120;
+		printf("KB:");
+		printf("%02x ",kbi);
+		for (j=0;j!=8;++j)
+		{
+			printf("%04x ",usb2ps2[kbbuf[j]]);
+		}
+
+		// lctrl:1, lshift:2, lalt:4, lwin:8, rctrl:10, rshift:20, altgr:40
+		uint32_t mod = kbi;
+		uint32_t key1 = usb2ps2[kbbuf[0]];
+		//uint32_t key2 = usb2ps2[kbbuf[1]];
+		//uint32_t key3 = usb2ps2[kbbuf[2]];
+
+		uint32_t res = (key3<<24) | (key2<<16) || (key1<<8) || mod;
+		*zpu_out4 = res;
+	}*/
 }
 void event_mouse(uint8_t a, uint8_t b, uint8_t c)
 {
-	printf("Event mouse:%d %d %d\n",a,b,c);
+	//printf("Event mouse:%d %d %d\n",a,b,c);
 }
-void event_digital_joystick(uint8_t idx, uint8_t jmap)
+void event_digital_joystick(uint8_t idx, uint32_t jmap)
 {
-	printf("Event joystick:%d %x\n", idx,jmap);
+	//printf("Event joystick:%d %x\n", idx,jmap);
+	/*if (jmaps[idx] != jmap)
+	{
+		jmaps[idx] = jmap;
+		debug_pos = 200 + idx*40;
+		printf("JOY:%d:%08x ",idx,jmap);
+	}*/
+	if (idx == 0)
+	{
+		*zpu_out2 = jmap;
+	}
+	if (idx == 1)
+	{
+		*zpu_out3 = jmap;
+	}
 }
 void event_analog_joystick(uint8_t idx, int8_t x, int8_t y)
 {
-	printf("Event analog joystick:%d %d %d\n", idx,x,y);
+	//printf("Event analog joystick:%d %d %d\n", idx,x,y);
+	if (analogx[idx]!=x || analogy[idx]!=y)
+	{
+		analogx[idx] = x;
+		analogy[idx] = y;
+		//debug_pos = 360 + idx*40;
+		//printf("AJOY:%d:%d:%d ", idx,x,y);
+		
+		uint32_t x0 = (uint8_t)analogx[0];
+		uint32_t y0 = (uint8_t)analogy[0];
+		uint32_t x1 = (uint8_t)analogx[1];
+		uint32_t y1 = (uint8_t)analogy[1];
+
+		uint32_t comb = (y1<<24)|(x1<<16)|(y0<<8) |x0;
+		*zpu_out5 = comb;
+	}
 }
 
 #define JOY_RIGHT       0x01
Index: firmware/usb/hid.c
===================================================================
--- firmware/usb/hid.c	(revision 274)
+++ firmware/usb/hid.c	(revision 275)
@@ -6,10 +6,25 @@
 #include "events.h"
 #include "debug.h"
 #include "usbhostslave.h"
+#include "log.h"
 
-static unsigned char kbd_led_state = 0;  // default: all leds off
-static unsigned char joysticks = 0;      // number of detected usb joysticks
+/*#include "printf.h"
+extern unsigned char volatile * baseaddr;
+extern int debug_pos;*/
 
+unsigned char kbd_led_state;  // default: all leds off
+unsigned char joysticks;      // number of detected usb joysticks
+
+//#define hid_debugf printf
+
+uint16_t bs16(uint8_t * in)
+{
+	uint16_t low = *in;
+	uint16_t high = *(in+1);
+	uint16_t res = (high<<8) | low;
+	return res;
+}
+
 uint8_t hid_get_joysticks(void) {
   return joysticks;
 }
@@ -30,10 +45,17 @@
     // we got a report descriptor. Try to parse it
     if(parse_report_descriptor(buf, size, &(info->iface[i].conf))) {
       if(info->iface[i].conf.type == CONFIG_TYPE_JOYSTICK) {
+	//unsigned char * temp = baseaddr;
+	//baseaddr = (unsigned char volatile *)(40000 + atari_regbase);
+	//debug_pos=160;
+	//printf("Detected USB joystick #%d", joysticks);
 	hid_debugf("Detected USB joystick #%d", joysticks);
 
 	info->iface[i].device_type = HID_DEVICE_JOYSTICK;
 	info->iface[i].jindex = joysticks++;
+	//debug_pos=240;
+	//printf("assigned index #%d", info->iface[i].jindex);
+	//baseaddr = temp;
       }
     }
   }
@@ -84,7 +106,10 @@
 
   /* scan through all descriptors */
   p = &buf;
+  //LOG("LenX:%d\n", p->conf_desc.bLength);
   while(len > 0) {
+    //printf("L%02d %02d %02d ",len, p->conf_desc.bLength, p->conf_desc.bDescriptorType);
+
     switch(p->conf_desc.bDescriptorType) {
     case USB_DESCRIPTOR_CONFIGURATION:
       // hid_debugf("conf descriptor size %d", p->conf_desc.bLength);
@@ -182,6 +207,8 @@
     }
 
     // advance to next descriptor
+   //LOG("Len:%d\n", p->conf_desc.bLength);
+   //timer_delay_msec(1000);
     len -= p->conf_desc.bLength;
     p = (union buf_u*)(p->raw + p->conf_desc.bLength);
   }
@@ -201,6 +228,8 @@
   uint8_t i;
   uint16_t vid, pid;
 
+  kbd_led_state = 0;  // default: all leds off
+
   usb_hid_info_t *info = &(dev->hid_info);
   
   union {
@@ -225,8 +254,8 @@
     return rcode;
 
   // save vid/pid for automatic hack later
-  vid = buf.dev_desc.idVendor;
-  pid = buf.dev_desc.idProduct;
+  vid = bs16(&buf.dev_desc.idVendorL);
+  pid = bs16(&buf.dev_desc.idProductL);
 
   uint8_t num_of_conf = buf.dev_desc.bNumConfigurations;
   //  hid_debugf("number of configurations: %d", num_of_conf);
@@ -236,9 +265,11 @@
       return rcode;
     
     //    hid_debugf("conf descriptor %d has total size %d", i, buf.conf_desc.wTotalLength);
+    uint16_t wTotalLength = bs16(&buf.conf_desc.wTotalLengthL);
+    LOG("conf descriptor %d has total size %d", i, wTotalLength);
 
     // parse directly if it already fitted completely into the buffer
-    usb_hid_parse_conf(dev, i, buf.conf_desc.wTotalLength);
+    usb_hid_parse_conf(dev, i, wTotalLength);
   }
 
   // check if we found valid hid interfaces
@@ -254,9 +285,12 @@
   for(i=0; i<info->bNumIfaces; i++) {
     // no boot mode, try to parse HID report descriptor
     if(!info->iface[i].has_boot_mode) {
+ 
+      //printf("DESC ");
       rcode = hid_get_report_descr(dev, i, info->iface[i].report_desc_size);
       if(rcode) return rcode;
 
+      //printf("TYPE%02x ", info->iface[i].device_type);
       if(info->iface[i].device_type == CONFIG_TYPE_JOYSTICK) {
 	char k;
         
@@ -272,7 +306,7 @@
 		  info->iface[i].conf.joystick.axis[k].logical.min,
 		  info->iface[i].conf.joystick.axis[k].logical.max);
 	
-	for(k=0;k<4;k++)
+	for(k=0;k<24;k++)
 	  iprintf("Button%d: @%d/%d\n", k,
 		  info->iface[i].conf.joystick.button[k].byte_offset,
 		  info->iface[i].conf.joystick.button[k].bitmask);
@@ -308,12 +342,17 @@
 
     rcode = hid_set_idle(dev, info->iface[i].iface_idx, 0, 0);
     // MWW if (rcode && rcode != hrSTALL)
+    //printf("RCODE:%02x ",rcode);
     if (rcode && rcode != OHS900_STATMASK_STALL_RXED)
       return rcode;
 
+    //printf("BM ");
     // enable boot mode
     if(info->iface[i].has_boot_mode)
+    {
+      //printf("BM ");
       hid_set_protocol(dev, info->iface[i].iface_idx, HID_BOOT_PROTOCOL);
+    }
   }
   
   iprintf("HID configured\n");
@@ -321,7 +360,11 @@
   // update leds
   for(i=0;i<MAX_IFACES;i++)
     if(dev->hid_info.iface[i].device_type == HID_DEVICE_KEYBOARD)
-      hid_set_report(dev, dev->hid_info.iface[i].iface_idx, 2, 0, 1, &kbd_led_state);
+    {
+//      printf("LEDS ");
+      uint8_t res = hid_set_report(dev, dev->hid_info.iface[i].iface_idx, 2, 0, 1, &kbd_led_state);
+//      printf("LEDS res:%02x ", res);
+    }
 
   info->bPollEnable = true;
   return 0;
@@ -472,7 +515,7 @@
 	  if(iface->device_type == HID_DEVICE_JOYSTICK) {
 	    hid_config_t *conf = &iface->conf;
 	    if(read >= conf->report_size) {
-	      uint8_t jmap = 0;
+	      uint32_t jmap = 0;
 	      uint16_t a[2];
 	      uint8_t idx, i;
 	      
@@ -500,21 +543,23 @@
 	      
 	      //	      iprintf("JOY X:%d Y:%d\n", a[0], a[1]);
 	      
-	      // ... and four buttons
-	      for(i=0;i<4;i++)
+	      // ... and twenty-four buttons
+	      for(i=0;i<24;i++)
 		if(buf[conf->joystick.button[i].byte_offset] & 
 		   conf->joystick.button[i].bitmask) jmap |= (JOY_BTN1<<i);
 	      
 	      //	      iprintf("JOY D:%d\n", jmap);
 
-	      // swap joystick 0 and 1 since 1 is the one 
-	      // used primarily on most systems
 	      idx = iface->jindex;
-	      if(idx == 0)      idx = 1;
-	      else if(idx == 1) idx = 0;
 	      
 	      // check if joystick state has changed
 	      if(jmap != iface->jmap) {
+
+		//unsigned char * temp = baseaddr;
+		//baseaddr = (unsigned char volatile *)(40000 + atari_regbase);
+		//debug_pos=80;
+		//printf("jmap %d(%d) changed to %x\n", idx, iface->jindex,jmap);
+		//baseaddr = temp;
 		//	      iprintf("jmap %d changed to %x\n", idx, jmap);
 		
 		// and feed into joystick input system
Index: firmware/usb/hid.h
===================================================================
--- firmware/usb/hid.h	(revision 274)
+++ firmware/usb/hid.h	(revision 275)
@@ -51,13 +51,13 @@
   uint16_t report_desc_size;
 
   uint8_t device_type;
-  bool has_boot_mode: 1;     // device supports boot mode
-  bool is_5200daptor: 1;     // device is a 5200daptor with special key handling
+  uint8_t has_boot_mode;     // device supports boot mode
+  uint8_t is_5200daptor;     // device is a 5200daptor with special key handling
   uint16_t key_state;        // needed to detect key state changes in 5200daptor
   
   // additional info extracted from the report descriptor
   // (currently only used for joysticks) 
-  uint8_t jmap;           // last reported joystick state
+  uint32_t jmap;           // last reported joystick state
   uint8_t jindex;         // joystick index
   hid_config_t conf;
 
@@ -77,7 +77,8 @@
 typedef struct  {
   uint8_t         bLength;
   uint8_t         bDescriptorType;
-  uint16_t        bcdHID;                         // HID class specification release
+  uint8_t        bcdHIDL;                         // HID class specification release
+  uint8_t        bcdHIDH;                         // HID class specification release
   uint8_t         bCountryCode;
   uint8_t         bNumDescriptors;                // Number of additional class specific descriptors
   uint8_t         bDescrType;                     // Type of class descriptor
Index: firmware/usb/hidparser.c
===================================================================
--- firmware/usb/hidparser.c	(revision 274)
+++ firmware/usb/hidparser.c	(revision 275)
@@ -6,13 +6,17 @@
 
 #include "hidparser.h"
 #include "debug.h"
+//#include "printf.h"
+//#include <stdio.h>
 
-#if 1
+#if 0
 #define hidp_extreme_debugf(...) hidp_debugf(__VA_ARGS__)
 #else
 #define hidp_extreme_debugf(...)
 #endif
 
+//#define hidp_debugf printf
+
 typedef struct {
   uint8_t bSize: 2;
   uint8_t bType: 2;
@@ -70,6 +74,14 @@
   // that e.g. both axes and the button of a joystick are ready to be used
   uint8_t setup_complete = 0;
 
+  /*printf("PARSE:");
+  int j = 0;
+  for (j=0; j!=rep_size; ++j)
+  {
+    printf("%02x",rep[j]);
+  }
+  printf(" ");*/
+
   // joystick/mouse components
   int8_t axis[2]; // MWW = { -1, -1}; (this instantiates memcpy!)
   axis[0] = -1;
@@ -80,9 +92,19 @@
 
   while(rep_size) {
     // extract short item
-    uint8_t tag = ((item_t*)rep)->bTag;
+/*    uint8_t tag = ((item_t*)rep)->bTag;
     uint8_t type = ((item_t*)rep)->bType;
-    uint8_t size = ((item_t*)rep)->bSize;
+    uint8_t size = ((item_t*)rep)->bSize;*/
+/*typedef struct {
+  uint8_t bSize: 2;
+  uint8_t bType: 2;
+  uint8_t bTag: 4;
+} __attribute__((packed)) item_t;*/
+    // MWW - bitfields are not working
+    uint8_t tag = (rep[0]&0xf0)>>4;
+    uint8_t type = (rep[0]&0x0c)>>2;
+    uint8_t size = rep[0]&0x03;
+//    printf("WTF:%02x %02x %02x %02x\n",rep[0],tag,type,size);
 
     rep++;
     rep_size--;   // one byte consumed
@@ -140,9 +162,9 @@
 	  // 
 	  if(btns) {
 	    if(conf->type == CONFIG_TYPE_JOYSTICK) {
-	      // scan for up to four buttons
+	      // scan for up to 24 buttons
 	      char b;
-	      for(b=0;b<4;b++) {
+	      for(b=0;b<24;b++) {
 		if(report_count > b) {
 		  uint16_t this_bit = bit_count+b;
 
Index: firmware/usb/hidparser.h
===================================================================
--- firmware/usb/hidparser.h	(revision 274)
+++ firmware/usb/hidparser.h	(revision 275)
@@ -20,6 +20,10 @@
 	uint8_t byte_offset;
 	uint8_t size;          // 8 or 16 bits supported
 	struct {
+/*	  uint8_t minl;
+	  uint8_t minh;
+	  uint8_t maxl;
+	  uint8_t maxh;*/
 	  uint16_t min;
 	  uint16_t max;
 	} logical;
@@ -28,7 +32,7 @@
       struct {
 	uint8_t byte_offset;
 	uint8_t bitmask;
-      } button[4];             // 4 buttons
+      } button[24];             // 24 buttons
     } joystick;
   };
 } hid_config_t;
Index: firmware/usb/hub.c
===================================================================
--- firmware/usb/hub.c	(revision 274)
+++ firmware/usb/hub.c	(revision 275)
@@ -4,6 +4,22 @@
 #include "timer.h"
 #include "debug.h"
 
+//#include "printf.h"
+
+//#define iprintf printf
+
+uint16_t bs16(uint8_t * in);
+
+uint32_t bs32(uint8_t * in)
+{
+	uint32_t a = *in;
+	uint32_t b = *(in+1);
+	uint32_t c = *(in+2);
+	uint32_t d = *(in+3);
+	uint32_t res = (d<<24) | (c<<16) | (b<<8) | a;
+	return res;
+}
+
 static uint8_t usb_hub_clear_hub_feature(usb_device_t *dev, uint8_t fid )  {
   return( usb_ctrl_req( dev, USB_HUB_REQ_CLEAR_HUB_FEATURE, 
        USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, NULL));
@@ -29,8 +45,11 @@
 
 // Get Port Status
 static uint8_t usb_hub_get_port_status(usb_device_t *dev, uint8_t port, uint16_t nbytes, uint8_t* dataptr )  {
-  return( usb_ctrl_req( dev, USB_HUB_REQ_GET_PORT_STATUS, 
+  uint8_t res = ( usb_ctrl_req( dev, USB_HUB_REQ_GET_PORT_STATUS, 
        USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, dataptr));
+
+  iprintf("portstat:%d bytes:%d res:%02x ",port,nbytes,res);
+  return res;
 }
 
 static uint8_t usb_hub_init(usb_device_t *dev) {
@@ -86,6 +105,7 @@
   
   // Save number of ports for future use
   info->bNbrPorts = buf.hub_desc.bNbrPorts;
+  iprintf("ports:%d ",buf.hub_desc.bNbrPorts); // MWW
     
   // Read configuration Descriptor in Order To Obtain Proper Configuration Value
   rcode = usb_get_conf_descr(dev, sizeof(usb_configuration_descriptor_t), 0, &buf.conf_desc);
@@ -103,11 +123,12 @@
     
   // Power on all ports
   for (i=1; i<=info->bNbrPorts; i++)
-    usb_hub_set_port_feature(dev, HUB_FEATURE_PORT_POWER, i, 0);	// HubPortPowerOn(i);
+  {
+    rcode = usb_hub_set_port_feature(dev, HUB_FEATURE_PORT_POWER, i, 0);	// HubPortPowerOn(i);
+    iprintf("PWR:%d:%02x ",i,rcode);
+  }
     
-  if(!dev->parent)
-    usb_SetHubPreMask();
-
+  iprintf("HUB pollingOn "); // MWW
   info->bPollEnable = true;
 
   return 0;
@@ -116,10 +137,6 @@
 static uint8_t usb_hub_release(usb_device_t *dev) {
   iprintf("%s\n",__FUNCTION__);
 
-  // root hub unplugged
-  if(!dev->parent)
-    usb_ResetHubPreMask();
-
   return 0;
 }
 
@@ -148,12 +165,12 @@
 static uint8_t usb_hub_port_status_change(usb_device_t *dev, uint8_t port, hub_event_t evt) {
   usb_hub_info_t *info = &(dev->hub_info);
 
-  iprintf("status change on port %d, 0x%x\n", port, evt.bmEvent);
-  usb_hub_show_port_status(port, evt.bmStatus, evt.bmChange);
+  iprintf("status change on port %d, 0x%x\n", port, bs32(&evt.bmEventLL));
+  usb_hub_show_port_status(port, bs16(&evt.bmStatusL), bs16(&evt.bmChangeL));
 
   static bool bResetInitiated = false;
 
-  switch (evt.bmEvent) {
+  switch (bs32(&evt.bmEventLL)) {
     // Device connected event
   case USB_HUB_PORT_EVENT_CONNECT:
   case USB_HUB_PORT_EVENT_LS_CONNECT:
@@ -193,7 +210,7 @@
     usb_hub_clear_port_feature(dev, HUB_FEATURE_C_PORT_CONNECTION, port, 0);
     
     usb_configure(dev->bAddress, port, 
-	  (evt.bmStatus & USB_HUB_PORT_STATUS_PORT_LOW_SPEED)!=0 );
+	  (bs16(&evt.bmStatusL) & USB_HUB_PORT_STATUS_PORT_LOW_SPEED)!=0 );
 
     bResetInitiated = false;
     break;
@@ -209,17 +226,20 @@
   uint8_t	buf[8];
   uint16_t	read = 1;
 
-  //   iprintf("%s(addr=%x)\n", __FUNCTION__, dev->bAddress);
+  //iprintf("%s(addr=%x)\n", __FUNCTION__, dev->bAddress);
 
   rcode = usb_in_transfer(dev, &(info->ep), &read, buf);
   if(rcode)
+  {
+    //iprintf("RC:%02x ",rcode);
     return rcode;
+  }
 
   uint8_t port, mask;
   for(port=1,mask=0x02; port<8; mask<<=1, port++) {
     if (buf[0] & mask) {
       hub_event_t evt;
-      evt.bmEvent = 0;
+      evt.bmEventLL = evt.bmEventLL2 = evt.bmEventLL3 = evt.bmEventLL4 = 0;
 
       rcode = usb_hub_get_port_status(dev, port, sizeof(evt.evtBuff), evt.evtBuff);
       if (rcode)
@@ -237,17 +257,18 @@
   
   for (port=1; port<=ports; port++) {
     hub_event_t	evt;
-    evt.bmEvent = 0;
+    evt.bmEventLL = evt.bmEventLL2 = evt.bmEventLL3 = evt.bmEventLL4 = 0;
     
     rcode = usb_hub_get_port_status(dev, port, 4, evt.evtBuff);
     if (rcode)
       continue;
     
-    if ((evt.bmStatus & USB_HUB_PORT_STATE_CHECK_DISABLED) != USB_HUB_PORT_STATE_DISABLED)
+    if ((bs16(&evt.bmStatusL) & USB_HUB_PORT_STATE_CHECK_DISABLED) != USB_HUB_PORT_STATE_DISABLED)
       continue;
     
     // Emulate connection event for the port
-    evt.bmChange |= USB_HUB_PORT_STATUS_PORT_CONNECTION;
+    evt.bmChangeL |= 0xff&(USB_HUB_PORT_STATUS_PORT_CONNECTION);
+    evt.bmChangeH |= (USB_HUB_PORT_STATUS_PORT_CONNECTION)>>8;
     
     rcode = usb_hub_port_status_change(dev, port, evt);
     if (rcode == HUB_ERROR_PORT_HAS_BEEN_RESET)
@@ -269,7 +290,8 @@
   
   if (info->qNextPollTime <= timer_get_msec()) {
     rcode = usb_hub_check_hub_status(dev, info->bNbrPorts);
-    info->qNextPollTime = timer_get_msec() + 100;   // poll 10 times a second
+    //info->qNextPollTime = timer_get_msec() + 100;   // poll 10 times a second 
+    info->qNextPollTime = timer_get_msec() + 2000;   // poll every 2 seconds
   }
 
   return rcode;
Index: firmware/usb/hub.h
===================================================================
--- firmware/usb/hub.h	(revision 274)
+++ firmware/usb/hub.h	(revision 275)
@@ -80,7 +80,7 @@
   uint8_t bDescriptorType;	// descriptor type
   uint8_t bNbrPorts;		// number of ports a hub equiped with
   
-  struct {
+ /* struct {
     uint16_t LogPwrSwitchMode	     : 2;
     uint16_t CompoundDevice	     : 1;
     uint16_t OverCurrentProtectMode  : 2;
@@ -87,7 +87,9 @@
     uint16_t TTThinkTime	     : 2;
     uint16_t PortIndicatorsSupported : 1;
     uint16_t Reserved		     : 8;
-  } __attribute__((packed));
+  } __attribute__((packed));*/
+  uint8_t bCharacteristicsL;
+  uint8_t bCharacteristicsH;
   
   uint8_t bPwrOn2PwrGood;
   uint8_t bHubContrCurrent;
@@ -96,10 +98,15 @@
 typedef struct {
   union {
     struct {
-      uint16_t bmStatus;	// port status bits
-      uint16_t bmChange;	// port status change bits
+      uint8_t bmStatusL;	// port status bits
+      uint8_t bmStatusH;	// port status bits
+      uint8_t bmChangeL;	// port status change bits
+      uint8_t bmChangeH;	// port status change bits
     } __attribute__((packed));
-    uint32_t bmEvent;
+    uint8_t bmEventLL;
+    uint8_t bmEventLL2;
+    uint8_t bmEventLL3;
+    uint8_t bmEventLL4;
     uint8_t  evtBuff[4];
   } __attribute__((packed));
 }__attribute__((packed)) hub_event_t;
Index: firmware/usb/keycodes.h
===================================================================
--- firmware/usb/keycodes.h	(nonexistent)
+++ firmware/usb/keycodes.h	(revision 275)
@@ -0,0 +1,139 @@
+// http://wiki.amigaos.net/index.php/Keymap_Library
+// http://www.win.tue.nl/~aeb/linux/kbd/scancodes-14.html
+
+#define MISS  0xff
+#define KEYCODE_MAX (0x6f)
+
+// The original minimig had the keyboard connected to the FPGA. Thus all key events (even for OSD)
+// came from the FPGA core. The MIST has the keyboard attached to the arm controller. To be compatible
+// with the minimig core all keys (incl. OSD!) are forwarded to the FPGA and the OSD keys are returned.
+// These keys are tagged with the "OSD" flag
+// The atari/mist core does not forwards keys through the FPGA but queues them inside the arm controller.
+// These keys are tagged with the "OSD_LOC" flag. The keycodes itself used are identical between OSD
+// and OSD_LOC
+
+#define OSD               0x0100     // to be used by OSD, not the core itself
+#define OSD_LOC           0x0200     // OSD key not forwarded to core, but queued in arm controller
+#define CAPS_LOCK_TOGGLE  0x0400     // caps lock toggle behaviour
+#define NUM_LOCK_TOGGLE   0x0800
+#define EXT               0x1000     // extended PS/2 keycode
+
+const unsigned short ps2_modifier[] = 
+      { 0x14, 0x12, 0x11, EXT|0x1f, EXT|0x14, 0x59, EXT|0x11, EXT|0x27 };
+
+// keycode translation table for ps2 emulation
+const unsigned short usb2ps2[] = {
+  MISS,  // 00: NoEvent
+  MISS,  // 01: Overrun Error
+  MISS,  // 02: POST fail
+  MISS,  // 03: ErrorUndefined
+  0x1c,  // 04: a
+  0x32,  // 05: b
+  0x21,  // 06: c
+  0x23,  // 07: d
+  0x24,  // 08: e
+  0x2b,  // 09: f
+  0x34,  // 0a: g
+  0x33,  // 0b: h
+  0x43,  // 0c: i
+  0x3b,  // 0d: j
+  0x42,  // 0e: k
+  0x4b,  // 0f: l
+  0x3a,  // 10: m
+  0x31,  // 11: n
+  0x44,  // 12: o
+  0x4d,  // 13: p
+  0x15,  // 14: q
+  0x2d,  // 15: r
+  0x1b,  // 16: s
+  0x2c,  // 17: t
+  0x3c,  // 18: u
+  0x2a,  // 19: v
+  0x1d,  // 1a: w
+  0x22,  // 1b: x
+  0x35,  // 1c: y
+  0x1a,  // 1d: z
+  0x16,  // 1e: 1
+  0x1e,  // 1f: 2
+  0x26,  // 20: 3
+  0x25,  // 21: 4
+  0x2e,  // 22: 5
+  0x36,  // 23: 6
+  0x3d,  // 24: 7
+  0x3e,  // 25: 8
+  0x46,  // 26: 9
+  0x45,  // 27: 0
+  0x5a,  // 28: Return
+  0x76,  // 29: Escape
+  0x66,  // 2a: Backspace
+  0x0d,  // 2b: Tab
+  0x29,  // 2c: Space
+  0x4e,  // 2d: -
+  0x55,  // 2e: =
+  0x54,  // 2f: [
+  0x5b,  // 30: ]
+  0x5d,  // 31: backslash
+  0x5d,  // 32: Europe 1
+  0x4c,  // 33: ; 
+  0x52,  // 34: '
+  0x0e,  // 35: `
+  0x41,  // 36: ,
+  0x49,  // 37: .
+  0x4a,  // 38: /
+  0x58,  // 39: Caps Lock
+  0x05,  // 3a: F1
+  0x06,  // 3b: F2
+  0x04,  // 3c: F3
+  0x0c,  // 3d: F4
+  0x03,  // 3e: F5
+  0x0b,  // 3f: F6
+  0x83,  // 40: F7
+  0x0a,  // 41: F8
+  0x01,  // 42: F9
+  0x09,  // 43: F10
+  0x78,  // 44: F11
+  OSD_LOC | 0x07,  // 45: F12 (OSD)
+  EXT | 0x7c, // 46: Print Screen
+  NUM_LOCK_TOGGLE,  // 47: Scroll Lock
+  0x77,  // 48: Pause (special key handled inside user_io)
+  EXT | 0x70, // 49: Insert
+  EXT | 0x6c, // 4a: Home
+  EXT | 0x7d, // 4b: Page Up
+  EXT | 0x71, // 4c: Delete
+  EXT | 0x69, // 4d: End
+  EXT | 0x7a, // 4e: Page Down
+  EXT | 0x74, // 4f: Right Arrow
+  EXT | 0x6b, // 50: Left Arrow
+  EXT | 0x72, // 51: Down Arrow
+  EXT | 0x75, // 52: Up Arrow
+  NUM_LOCK_TOGGLE,  // 53: Num Lock
+  EXT | 0x4a, // 54: KP /
+  0x7c,  // 55: KP *
+  0x7b,  // 56: KP -
+  0x79,  // 57: KP +
+  EXT | 0x5a, // 58: KP Enter
+  0x69,  // 59: KP 1
+  0x72,  // 5a: KP 2
+  0x7a,  // 5b: KP 3
+  0x6b,  // 5c: KP 4
+  0x73,  // 5d: KP 5
+  0x74,  // 5e: KP 6
+  0x6c,  // 5f: KP 7
+  0x75,  // 60: KP 8
+  0x7d,  // 61: KP 9
+  0x70,  // 62: KP 0
+  0x71,  // 63: KP .
+  0x61,  // 64: Europe 2
+  EXT | 0x2f, // 65: App
+  EXT | 0x37, // 66: Power
+  0x0f,  // 67: KP =
+  0x08,  // 68: F13
+  0x10,  // 69: F14
+  0x18,  // 6a: F15
+  0x20,  // 6b: F16
+  0x28,  // 6c: F17
+  0x30,  // 6d: F18
+  0x38,  // 6e: F19
+  0x40   // 6f: F20
+};
+
Index: firmware/usb/timer.c
===================================================================
--- firmware/usb/timer.c	(revision 274)
+++ firmware/usb/timer.c	(revision 275)
@@ -1,4 +1,5 @@
 #include "timer.h"
+#include "regs.h"
 
 // this is a 32 bit counter which overflows after 2^32 milliseconds
 // -> after 46 days
@@ -6,12 +7,21 @@
 void wait_us(int unsigned num);
 
 void timer_init() {
-	// TODO - set zpu to 0...
 }
 
+#ifdef LINUX_BUILD
+#include <sys/time.h>
 msec_t timer_get_msec() {
-	return 0; // TODO - read from ZPU
+	struct timeval x;
+	gettimeofday(&x,0);
+	return (x.tv_sec*1000+(x.tv_usec/1000));
 }
+#else
+msec_t timer_get_msec() {
+	int res = *zpu_timer;
+	return res;
+}
+#endif
 
 void timer_delay_msec(msec_t t) {
 	int y = t;
Index: firmware/usb/usb.c
===================================================================
--- firmware/usb/usb.c	(revision 274)
+++ firmware/usb/usb.c	(revision 275)
@@ -4,11 +4,14 @@
 #include "usb.h"
 #include "usbhostslave.h"
 #include "debug.h"
+#include "memory.h"
+#include "printf.h"
+#include "log.h"
 
-static uint8_t usb_task_state;
-static uint8_t bmHubPre;
+extern unsigned char joysticks;      // number of detected usb joysticks
+usb_device_t devices[USB_NUMDEVICES];
 
-#define tokSETUP  0x10  // HS=0, ISO=0, OUTNIN=0, SETUP=1
+/*#define tokSETUP  0x10  // HS=0, ISO=0, OUTNIN=0, SETUP=1
 #define tokIN     0x00  // HS=0, ISO=0, OUTNIN=0, SETUP=0
 #define tokOUT    0x20  // HS=0, ISO=0, OUTNIN=1, SETUP=0
 #define tokINHS   0x80  // HS=1, ISO=0, OUTNIN=0, SETUP=0
@@ -15,40 +18,65 @@
 #define tokOUTHS  0xA0  // HS=1, ISO=0, OUTNIN=1, SETUP=0 
 #define tokISOIN  0x40  // HS=0, ISO=1, OUTNIN=0, SETUP=0
 #define tokISOOUT 0x60  // HS=0, ISO=1, OUTNIN=1, SETUP=0
+*/
 
+typedef enum {tokSETUP,tokIN,tokOUT,tokINHS,tokOUTHS,tokISOIN,tokISOOUT} TOKEN;
+
 static uint8_t outType;
 static uint8_t controlAdj;
+static uint8_t lineControlAdj;
 
-static usb_device_t dev[USB_NUMDEVICES];
+#ifdef LINUX_BUILD
+#define USBHOSTSLAVE_READ(ADDR) usbhostslave_read(ADDR)
+#define USBHOSTSLAVE_WRITE(ADDR,VALUE) usbhostslave_write(ADDR,VALUE)
+#else
+#define USBHOSTSLAVE_READ(ADDR) usbhostslave[ADDR]
+#define USBHOSTSLAVE_WRITE(ADDR,VALUE) usbhostslave[ADDR] = VALUE
+#endif
 
 void usb_reset_state() {
   iprintf("%s\n",__FUNCTION__);
-  bmHubPre	 = 0;
 }
 
 usb_device_t *usb_get_devices() {
-  return dev;
+  return devices;
 }
 
-void usb_init() {
+void usb_init(struct usb_host * host, int portnumber) {
   iprintf("%s\n",__FUNCTION__);
 
+  joysticks = 0;
+
   // MWW max3421e_init();   // init underlaying hardware layer
-  usbhostslave[OHS900_HOSTSLAVECTLREG] = OHS900_HSCTLREG_RESET_CORE;
+
+  if (portnumber == 0)
+  {
+      host->addr = zpu_regbase + 0x800;
+  }
+  if (portnumber == 1)
+  {
+      host->addr = zpu_regbase + 0xc00;
+  }
+  usbhostslave = host->addr;
+  host->poll = 0;
+  host->delay = 0;
+
+  USBHOSTSLAVE_WRITE(OHS900_HOSTSLAVECTLREG, OHS900_HSCTLREG_RESET_CORE);
   timer_delay_msec(1);
-  usbhostslave[OHS900_TXLINECTLREG] = 0;
-  usbhostslave[OHS900_HOSTSLAVECTLREG] = OHS900_HS_CTL_INIT;
-  usbhostslave[OHS900_SOFENREG] = 0;
-  usbhostslave[OHS900_IRQ_ENABLE] = 0;
+  USBHOSTSLAVE_WRITE(OHS900_TXLINECTLREG, 0);
+  USBHOSTSLAVE_WRITE(OHS900_HOSTSLAVECTLREG, OHS900_HS_CTL_INIT);
+  USBHOSTSLAVE_WRITE(OHS900_SOFENREG, 0);
+  USBHOSTSLAVE_WRITE(OHS900_IRQ_ENABLE, 0);
 
-  usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; 
+  host->usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; 
 
   outType = 0;
   controlAdj = 0;
+  lineControlAdj = 0;
 
   uint8_t i;
   for(i=0;i<USB_NUMDEVICES;i++)
-    dev[i].bAddress = 0;
+    devices[i].bAddress = 0;
 
   usb_reset_state();
 }
@@ -55,25 +83,19 @@
 
 uint8_t usb_set_address(usb_device_t *dev, ep_t *ep, 
 			uint16_t *nak_limit) {
-  //  iprintf("  %s(addr=%x, ep=%d)\n", __FUNCTION__, addr, ep);
+  //  printf("  %s(addr=%x, ep=%d)\n", __FUNCTION__, addr, ep);
   *nak_limit = (1UL << ( ( ep->bmNakPower > USB_NAK_MAX_POWER ) ? 
 			 USB_NAK_MAX_POWER : ep->bmNakPower) ) - 1;
   
   /*
-    iprintf("\nAddress: %x\n", addr);
-    iprintf(" EP: %d\n", ep);
-    iprintf(" NAK Power: %d\n",(*ppep)->bmNakPower);
-    iprintf(" NAK Limit: %d\n", nak_limit);
+    printf("\nAddress: %x\n", addr);
+    printf(" EP: %d\n", ep);
+    printf(" NAK Power: %d\n",(*ppep)->bmNakPower);
+    printf(" NAK Limit: %d\n", nak_limit);
   */
   
-  usbhostslave[OHS900_TXADDRREG] = dev->bAddress;
+  USBHOSTSLAVE_WRITE(OHS900_TXADDRREG, dev->bAddress);
 
-  controlAdj = 0;
-  if (bmHubPre)
-  {
-    controlAdj = OHS900_HCTLMASK_PREAMBLE_EN;
-  }
-  
   /* MWW (sets address and messes with mode - I plan to change mode on connect only...)
   max3421e_write_u08( MAX3421E_PERADDR, dev->bAddress); // set peripheral address
   uint8_t mode = max3421e_read_u08( MAX3421E_MODE );
@@ -84,6 +106,19 @@
 		      (dev->lowspeed) ? mode |   MAX3421E_LOWSPEED | bmHubPre : 
 		                      mode & ~(MAX3421E_HUBPRE | MAX3421E_LOWSPEED)); 
   */
+
+  controlAdj = 0;
+  lineControlAdj = 0;
+  if (dev->parent) // via hub
+  {
+    controlAdj = dev->lowspeed ? OHS900_HCTLMASK_PREAMBLE_EN : 0;
+    lineControlAdj = dev->lowspeed ? 0 : OHS900_TXLCTL_MASK_FS_RATE; 
+    lineControlAdj |= OHS900_TXLCTL_MASK_FS_POL; // hub always full speed polarity
+  }
+  else // direct
+  {
+    lineControlAdj = dev->lowspeed ? OHS900_TXLCTL_MASK_LSPD : OHS900_TXLCTL_MASK_FSPD;
+  }
   
   return 0;
 }
@@ -94,9 +129,10 @@
 /* If nak_limit == 0, do not count NAKs, exit after timeout */
 /* If bus timeout, re-sends up to USB_RETRY_LIMIT times */
 /* return codes 0x00-0x0f are HRSLT (0x00 being success), 0xff means timeout */
-uint8_t usb_dispatchPktWithData( uint8_t token, uint8_t ep, uint16_t nak_limit, uint8_t * data, uint16_t bytes_tosend, uint8_t * sndToggle) {
-  //  iprintf("  %s(token=%x, ep=%d, nak_limit=%d)\n", 
-  //	  __FUNCTION__, token, ep, nak_limit);
+uint8_t usb_dispatchPktWithData( TOKEN token, uint8_t ep, uint16_t nak_limit, uint8_t * data, uint16_t bytes_tosend, uint8_t * sndToggle) {
+ //   printf("  %s(token=%x, ep=%d, nak_limit=%d tosend:%d)\n", 
+ // 	  __FUNCTION__, token, ep, nak_limit, bytes_tosend);
+  iprintf("SEND%02d ", bytes_tosend);
   unsigned long timeout = timer_get_msec() + USB_XFER_TIMEOUT;
   uint8_t tmpdata;   
   uint8_t rcode = 0x00;
@@ -105,95 +141,140 @@
 	
   while( timeout > timer_get_msec() )  {
     //MWW max3421e_write_u08( MAX3421E_HXFR, ( token|ep )); //launch the transfer
-    usbhostslave[OHS900_TXENDPREG] = ep;
-    uint8_t control = OHS900_HCTLMASK_TRANS_REQ|OHS900_HCTLMASK_SOF_SYNC|controlAdj;
+    USBHOSTSLAVE_WRITE(OHS900_TXENDPREG, ep);
+    uint8_t control = OHS900_HCTLMASK_TRANS_REQ|controlAdj;
     uint8_t line_control = 0;
-    uint8_t out = 0;
+    uint8_t load_fifo = 0;
+    uint8_t wait_for_sof = OHS900_HCTLMASK_SOF_SYNC;
+    uint8_t expect_ack = 0;
     switch (token)
     {
     case tokSETUP:
-        usbhostslave[OHS900_TXTRANSTYPEREG] = OHS900_SETUP;
+        USBHOSTSLAVE_WRITE(OHS900_TXTRANSTYPEREG, OHS900_SETUP);
+	iprintf("S ");
+	load_fifo = 1;
+        expect_ack = 1;
         break;
     case tokIN:
-        usbhostslave[OHS900_TXTRANSTYPEREG] = OHS900_IN;
+        USBHOSTSLAVE_WRITE(OHS900_TXTRANSTYPEREG, OHS900_IN);
+	iprintf("I ");
         break;
     case tokOUT:
-        usbhostslave[OHS900_TXTRANSTYPEREG] = *sndToggle ? OHS900_OUT_DATA1 : OHS900_OUT_DATA0;
-        out = 1;
+        USBHOSTSLAVE_WRITE(OHS900_TXTRANSTYPEREG, *sndToggle ? OHS900_OUT_DATA1 : OHS900_OUT_DATA0);
+	iprintf(*sndToggle ? "Data1 ":"Data0 ");
+	load_fifo = 1;
+        expect_ack = 1;
         break;
     case tokINHS:
-        usbhostslave[OHS900_TXTRANSTYPEREG] = OHS900_IN;
-	line_control = OHS900_TXLCTL_MASK_FSPD;
+        USBHOSTSLAVE_WRITE(OHS900_TXTRANSTYPEREG, OHS900_IN);
+	iprintf("HI ");
+	//wait_for_sof = 0;
         break;
     case tokOUTHS:
-        usbhostslave[OHS900_TXTRANSTYPEREG] = *sndToggle ? OHS900_OUT_DATA1 : OHS900_OUT_DATA0;
-        out = 1;
-	line_control = OHS900_TXLCTL_MASK_FSPD;
+        USBHOSTSLAVE_WRITE(OHS900_TXTRANSTYPEREG, OHS900_OUT_DATA1);
+	iprintf("HO ");
+	load_fifo = 1;
+	//wait_for_sof = 0;
+        expect_ack = 1;
         break;
     case tokISOIN:
-        usbhostslave[OHS900_TXTRANSTYPEREG] = OHS900_IN;
+        USBHOSTSLAVE_WRITE(OHS900_TXTRANSTYPEREG, OHS900_IN);
         control |= OHS900_HCTLMASK_ISO_EN;
         break;
     case tokISOOUT:
-        usbhostslave[OHS900_TXTRANSTYPEREG] = *sndToggle ? OHS900_OUT_DATA1 : OHS900_OUT_DATA0;
-        out = 1;
+        USBHOSTSLAVE_WRITE(OHS900_TXTRANSTYPEREG, *sndToggle ? OHS900_OUT_DATA1 : OHS900_OUT_DATA0);
+      	*sndToggle = !*sndToggle; // No acks, toggle each time
+	load_fifo = 1;
         control |= OHS900_HCTLMASK_ISO_EN;
         break;
-    default:
-        return 0xff;
-        break;
     }
 
-    if (out)
+    line_control |= lineControlAdj;
+
+    USBHOSTSLAVE_WRITE(OHS900_TXFIFOCONTROLREG, OHS900_FIFO_FORCE_EMPTY);
+    USBHOSTSLAVE_WRITE(OHS900_RXFIFOCONTROLREG, OHS900_FIFO_FORCE_EMPTY);
+
+    if (load_fifo && data)
     {
-      //set toggle value
-      // MWW: max3421e_write_u08(MAX3421E_HCTL, 
-      //    (pep->bmSndToggle) ? MAX3421E_SNDTOG1 : MAX3421E_SNDTOG0 );
-      *sndToggle = !*sndToggle; // Correct place to flip Original code did this outside loop but that looks wrong - we should send 0/1/0/1 etc.
   
       //filling output FIFO
       //MWW max3421e_write( MAX3421E_SNDFIFO, bytes_tosend, data );
       uint16_t toSend = bytes_tosend;
       uint8_t * dataToSend = data;
-      while (--toSend)
+      iprintf("FIFO:");
+      while (toSend--)
       {
-        usbhostslave[OHS900_HOST_TXFIFO_DATA] = *dataToSend++;
+	iprintf("%02x", *dataToSend);
+        USBHOSTSLAVE_WRITE(OHS900_HOST_TXFIFO_DATA, *dataToSend++);
       }
+	iprintf(" ");
       
       //set number of bytes
       //MWW max3421e_write_u08( MAX3421E_SNDBC, bytes_tosend );
     }
 
-    usbhostslave[OHS900_TXLINECTLREG] = line_control;
-    usbhostslave[OHS900_HOST_TX_CTLREG] = control;
+	{
+	    rcode = USBHOSTSLAVE_READ(OHS900_HRXSTATREG);
+	   // printf("Pre transfer rcode:%02x line:%02x ctrl:%02x", rcode, line_control, control);
+	}
 
+    USBHOSTSLAVE_WRITE(OHS900_TXLINECTLREG, line_control);
+    //USBHOSTSLAVE_WRITE(OHS900_HOST_TX_CTLREG, control|wait_for_sof);
+    USBHOSTSLAVE_WRITE(OHS900_HOST_TX_CTLREG, control);
+
     rcode = USB_ERROR_TRANSFER_TIMEOUT;   
     
     // wait for transfer completion
+	//printf("Wait:%x %x ", timer_get_msec(), timeout);
     while( timer_get_msec() < timeout )	{
       //tmpdata = max3421e_read_u08( MAX3421E_HIRQ );
       // MWW
-      tmpdata = usbhostslave[OHS900_IRQ_STATUS];
+      tmpdata = USBHOSTSLAVE_READ(OHS900_IRQ_STATUS);
 
       if( tmpdata & OHS900_INTMASK_TRANS_DONE ) {
 	//clear the interrupt
 	//max3421e_write_u08( MAX3421E_HIRQ, MAX3421E_HXFRDNIRQ );
 	// MWW
-	usbhostslave[OHS900_IRQ_STATUS] = OHS900_INTMASK_TRANS_DONE;
+	USBHOSTSLAVE_WRITE(OHS900_IRQ_STATUS, OHS900_INTMASK_TRANS_DONE);
 	rcode = 0x00;
+
+	iprintf("OK ");
 	break;
       }
     }
 
     if( rcode != 0x00 )                 //exit if timeout
+	{
+		iprintf("TMOUT ");
       return( rcode );
+	}
 
     //analyze transfer result
     //rcode = ( max3421e_read_u08( MAX3421E_HRSL ) & 0x0f );
-    rcode = usbhostslave[OHS900_HRXSTATREG];
+    //rcode = 0x00;
+    rcode = USBHOSTSLAVE_READ(OHS900_HRXSTATREG);
+        
+    iprintf("R%02x ", rcode);
+    rcode &= ~OHS900_STATMASK_DATA_SEQ;
 
-    if (rcode&OHS900_STATMASK_NAK_RXED)
+    if (!expect_ack && rcode == 0x00)
     {
+        iprintf("EMPTY! ");
+        //rcode = USB_ERROR_TRANSFER_TIMEOUT;   
+        return rcode;
+    }
+
+    if (rcode&OHS900_STATMASK_ACK_RXED)
+    {
+        //set toggle value
+        // MWW: max3421e_write_u08(MAX3421E_HCTL, 
+        //    (pep->bmSndToggle) ? MAX3421E_SNDTOG1 : MAX3421E_SNDTOG0 );
+        *sndToggle = !*sndToggle; // Toggled on ack
+        iprintf("ACK ");
+        break;
+    }
+    else if (rcode&OHS900_STATMASK_NAK_RXED)
+    {
       nak_count++;
       if( nak_limit && ( nak_count == nak_limit ))
 	return( rcode );
@@ -201,6 +282,7 @@
     else if (rcode&OHS900_STATMASK_RX_TMOUT)
     {
       retry_count++;
+      iprintf("Retry ");
       if( retry_count == USB_RETRY_LIMIT )
 	return( rcode );
     }
@@ -210,7 +292,7 @@
     }
   }
 
-  return( rcode&~(OHS900_STATMASK_ACK_RXED|OHS900_STATMASK_DATA_SEQ));
+  return( rcode&~(OHS900_STATMASK_ACK_RXED));
 }
 
 uint8_t usb_dispatchPkt( uint8_t token, uint8_t ep, uint16_t nak_limit)
@@ -248,12 +330,17 @@
     /* toggle error occured. Need to add handling for that */
   // MWW if(( max3421e_read_u08( MAX3421E_HIRQ ) & MAX3421E_RCVDAVIRQ ) == 0 ) 
   //    return ( 0xf0 );                            //receive error
-    stat = usbhostslave[OHS900_HRXSTATREG];
+    stat = USBHOSTSLAVE_READ(OHS900_HRXSTATREG);
+    iprintf("rcv %02d stat %02d ", pep->bmRcvToggle, stat);
     if (pep->bmRcvToggle != (!!(stat&OHS900_STATMASK_DATA_SEQ))) // Check data0/data1
+    {
+        iprintf("DATA WRONG! rcv %02d stat %02d ", pep->bmRcvToggle, stat);
         return (0xf0);
+    }
     
     // MWW pktsize = max3421e_read_u08( MAX3421E_RCVBC ); // number of received bytes
-    pktsize = usbhostslave[OHS900_RXFIFOCNTLSBREG];
+    pktsize = USBHOSTSLAVE_READ(OHS900_RXFIFOCNTLSBREG);
+    iprintf("rd %02d ", pktsize);
         
     int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr);
 
@@ -263,11 +350,16 @@
     //MWW data = max3421e_read(MAX3421E_RCVFIFO, 
     //		 ((pktsize > mem_left) ? mem_left : pktsize), data );
     int16_t toRead = (pktsize > mem_left) ? mem_left : pktsize;
-    while (--toRead)
+    iprintf("rd2 %02d ",toRead);
+    LOG("DATA:%x:%d\n",data,toRead);
+    while (toRead--)
     {
-      *data++ = usbhostslave[OHS900_HOST_RXFIFO_DATA];
+      uint8_t val = USBHOSTSLAVE_READ(OHS900_HOST_RXFIFO_DATA);
+      iprintf ("%02x", val);
+      *data++ = val;
     }
-    
+    iprintf(" ");
+
     // Clear the IRQ & free the buffer
     //MWW - already done? max3421e_write_u08( MAX3421E_HIRQ, MAX3421E_RCVDAVIRQ );
     *nbytesptr += pktsize;							
@@ -276,13 +368,13 @@
     /* 1. The device sent a short packet (L.T. maxPacketSize)   */
     /* 2. 'nbytes' have been transferred.                       */
 
+    pep->bmRcvToggle = (!(stat&OHS900_STATMASK_DATA_SEQ)); // expect other way next time
+
     // have we transferred 'nbytes' bytes?
     if (( pktsize < maxpktsize ) || (*nbytesptr >= nbytes )) {     
       // Save toggle value
       //MWW pep->bmRcvToggle = (( max3421e_read_u08( MAX3421E_HRSL ) & 
 	//		    MAX3421E_RCVTOGRD )) ? 1 : 0;
-
-      pep->bmRcvToggle = (!(stat&OHS900_STATMASK_DATA_SEQ)); // expect other way next time
       
       return 0;
     }
@@ -305,7 +397,7 @@
 
 uint8_t usb_OutTransfer(ep_t *pep, uint16_t nak_limit, 
 			uint16_t nbytes, uint8_t *data) {
-  //  iprintf("%s(%d)\n", __FUNCTION__, nbytes);
+  //  printf("%s(%d)\n", __FUNCTION__, nbytes);
 
   uint8_t rcode = 0;
   uint16_t bytes_tosend;
@@ -399,8 +491,9 @@
 uint8_t usb_ctrl_req(usb_device_t *dev, uint8_t bmReqType, 
 		    uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, 
 		    uint16_t wInd, uint16_t nbytes, uint8_t* dataptr) {
-  //  iprintf("%s(addr=%x, len=%d, ptr=%p)\n", __FUNCTION__,
-  //	  dev->bAddress, nbytes, dataptr);
+//    printf("%s(addr=%x, len=%d, ptr=%p)\n", __FUNCTION__,
+//  	  dev->bAddress, nbytes, dataptr);
+iprintf("C%02X %02X %02x ",dev->bAddress,bRequest, nbytes);
   bool direction = false;     //request direction, IN or OUT
   uint8_t rcode;   
   setup_pkt_t setup_pkt;
@@ -408,7 +501,10 @@
   
   rcode = usb_set_address(dev, &(dev->ep0), &nak_limit);
   if (rcode)
+  {
+    iprintf("set_address failed ");
     return rcode;
+  }
   
   direction = (( bmReqType & 0x80 ) > 0);
 
@@ -415,10 +511,12 @@
   /* fill in setup packet */
   setup_pkt.ReqType_u.bmRequestType	= bmReqType;
   setup_pkt.bRequest			= bRequest;
-  setup_pkt.wVal_u.wValueLo		= wValLo;
-  setup_pkt.wVal_u.wValueHi		= wValHi;
-  setup_pkt.wIndex			= wInd;
-  setup_pkt.wLength			= nbytes;
+  setup_pkt.wValueL		= wValLo;
+  setup_pkt.wValueH		= wValHi;
+  setup_pkt.wIndexL			= wInd&0xFF;
+  setup_pkt.wIndexH			= wInd>>8;
+  setup_pkt.wLengthL			= nbytes&0xFF;
+  setup_pkt.wLengthH			= nbytes>>8;
   
   // transfer to setup packet FIFO
   /* MWW max3421e_write(MAX3421E_SUDFIFO, sizeof(setup_pkt_t), (uint8_t*)&setup_pkt );
@@ -428,7 +526,10 @@
   uint8_t dummy = 0;
   rcode = usb_dispatchPktWithData( tokSETUP, 0, nak_limit, (uint8_t*)&setup_pkt,  sizeof(setup_pkt_t), &dummy);
   if( rcode )		//return HRSLT if not zero
+  {
+    iprintf("setup failed:%02x ",rcode);
     return( rcode );
+  }
   
   // data stage, if present
   if( dataptr != NULL )	{
@@ -441,16 +542,25 @@
     }    
 
     //return error
-    if( rcode )	return( rcode );
+    if( rcode )	
+    {
+      iprintf("setupd failed:%02x ",rcode);
+      return( rcode );
+    }
   }
 
   // Status stage
   // GET if direction
-  return usb_dispatchPkt( (direction) ? tokOUTHS : tokINHS, 0, nak_limit );
+  rcode = usb_dispatchPkt( (direction) ? tokOUTHS : tokINHS, 0, nak_limit );
+  if (rcode)
+  {
+      iprintf("status failed:%02x ",rcode);
+  }
+  return rcode;
 }
 
 // list of supported device classes
-static const usb_device_class_config_t *class_list[] = {
+static const usb_device_class_config_t *class_list[]= {
   &usb_hub_class,
   &usb_hid_class,
   NULL
@@ -462,12 +572,12 @@
 
   // find an empty device entry
   uint8_t i;
-  for(i=0; i<USB_NUMDEVICES && dev[i].bAddress; i++);
+  for(i=0; i<USB_NUMDEVICES && devices[i].bAddress; i++);
 
   if(i < USB_NUMDEVICES) {
     iprintf("using free entry at %d\n", i);
 
-    usb_device_t *d = dev+i;
+    usb_device_t *d = devices+i;
 
     // setup generic info
     d->bAddress = 0;
@@ -475,6 +585,7 @@
     d->lowspeed = lowspeed;
     d->port = port;
     d->class = NULL;
+    d->host_addr = usbhostslave;
 
     // setup endpoint 0
     d->ep0.epAddr	= 0;
@@ -489,7 +600,7 @@
     iprintf("Setting addr %x\n", i+1);
     rcode = usb_set_addr(d, i+1);
     if(rcode) {
-      iprintf("failed to assign address\n");
+      iprintf("failed to assign address:%x\n", rcode);
       return rcode;
     }
 
@@ -511,91 +622,95 @@
       iprintf(" -> not accepted :-(\n");
     }
   } else
+  {
     iprintf("no more free entries\n");
+  }
 
   iprintf("unsupported device\n");
   return 0;
 }
 
-void usb_poll() {
-  static msec_t delay = 0;
+void usb_poll(struct usb_host * host) {
   bool lowspeed = false;
 
-  // poll underlaying hardware layer
-  //MWW tmpdata = max3421e_poll();
-  uint8_t conState = usbhostslave[OHS900_RXCONNSTATEREG];
-  switch(conState)
-  {
-  case OHS900_DISCONNECT_STATE:
-    if(( usb_task_state & USB_STATE_MASK ) != USB_STATE_DETACHED ) 
-      usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
-    break;
-  case OHS900_LS_CONN_STATE:
-    lowspeed = true;
-    // intentional fall-through ...
-  case OHS900_FS_CONN_STATE:
-    if(( usb_task_state & USB_STATE_MASK ) == USB_STATE_DETACHED ) {
-      delay = timer_get_msec() + USB_SETTLE_DELAY;
-      usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
-    }
-    break;
-  }
+  usbhostslave = host->addr;
 
-  /* modify USB task state if Vbus changed */
-/*  switch( tmpdata )  {
+  // max poll 1ms
+  if(timer_get_msec() > host->poll) {
+    host->poll = timer_get_msec()+1;
 
-    // illegal state
-  case MAX3421E_STATE_SE1:   
-    usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
-    lowspeed = false;
-    break;
-
-    // disconnected
-  case MAX3421E_STATE_SE0:
-    if(( usb_task_state & USB_STATE_MASK ) != USB_STATE_DETACHED ) 
-      usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
-    lowspeed = false;
-    break;
-
-    // attached
-  case MAX3421E_STATE_LSHOST:
-    lowspeed = true;
-    // intentional fall-through ...
-
-  case MAX3421E_STATE_FSHOST:
-    if(( usb_task_state & USB_STATE_MASK ) == USB_STATE_DETACHED ) {
-      delay = timer_get_msec() + USB_SETTLE_DELAY;
-      usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
+    // poll underlaying hardware layer
+    //MWW tmpdata = max3421e_poll();
+    uint8_t conState = USBHOSTSLAVE_READ(OHS900_RXCONNSTATEREG);
+    switch(conState)
+    {
+    case OHS900_DISCONNECT_STATE:
+      if(( host->usb_task_state & USB_STATE_MASK ) != USB_STATE_DETACHED ) 
+        host->usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
+      break;
+    case OHS900_LS_CONN_STATE:
+      lowspeed = true;
+      // intentional fall-through ...
+    case OHS900_FS_CONN_STATE:
+      if(( host->usb_task_state & USB_STATE_MASK ) == USB_STATE_DETACHED ) {
+        host->delay = timer_get_msec() + USB_SETTLE_DELAY;
+        host->usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
+      }
+      break;
     }
-    break;
-  }*/
+  
+    /* modify USB task state if Vbus changed */
+  /*  switch( tmpdata )  {
+  
+      // illegal state
+    case MAX3421E_STATE_SE1:   
+      host->usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
+      lowspeed = false;
+      break;
+  
+      // disconnected
+    case MAX3421E_STATE_SE0:
+      if(( host->usb_task_state & USB_STATE_MASK ) != USB_STATE_DETACHED ) 
+        host->usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
+      lowspeed = false;
+      break;
+  
+      // attached
+    case MAX3421E_STATE_LSHOST:
+      lowspeed = true;
+      // intentional fall-through ...
+  
+    case MAX3421E_STATE_FSHOST:
+      if(( host->usb_task_state & USB_STATE_MASK ) == USB_STATE_DETACHED ) {
+        delay = timer_get_msec() + USB_SETTLE_DELAY;
+        host->usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
+      }
+      break;
+    }*/
 
-  // max poll 1ms
-  static msec_t poll=0;
-  if(timer_get_msec() > poll) {
-    poll = timer_get_msec()+1;
-
     // poll all configured devices
     uint8_t i;
+    LOG("Poll\n");
+    //printf("Poll\n");
     for (i=0; i<USB_NUMDEVICES; i++)
-      if(dev[i].bAddress && dev[i].class && dev[i].class->poll)
-	dev[i].class->poll(dev+i);
-	// MWW (rcode unused error) rcode = dev[i].class->poll(dev+i);
+      if(devices[i].bAddress && devices[i].class && devices[i].class->poll && devices[i].host_addr == usbhostslave)
+	devices[i].class->poll(devices+i);
+	// MWW (rcode unused error) rcode = devices[i].class->poll(dev+i);
     
-    switch( usb_task_state ) {
+    switch( host->usb_task_state ) {
     case USB_DETACHED_SUBSTATE_INITIALIZE:
       usb_reset_state();
       
       // just remove everything ...
       for (i=0; i<USB_NUMDEVICES; i++) {
-	if(dev[i].bAddress && dev[i].class) {
-	  dev[i].class->release(dev+i);
-	  // MWW (rcode unused error) rcode = dev[i].class->release(dev+i);
-	  dev[i].bAddress = 0;
+	if(devices[i].bAddress && devices[i].class && devices[i].host_addr == usbhostslave) {
+	  devices[i].class->release(devices+i);
+	  // MWW (rcode unused error) rcode = devices[i].class->release(devices+i);
+	  devices[i].bAddress = 0;
 	}
       }
     
-      usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
+      host->usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
       break;
       
     case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE:
@@ -603,41 +718,41 @@
       break;
       
     case USB_ATTACHED_SUBSTATE_SETTLE:              //settle time for just attached device            
-      if( delay < timer_get_msec() ) 
-	usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
+      if( host->delay < timer_get_msec() ) 
+	host->usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
       break;
       
     case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
       // MWW max3421e_write_u08( MAX3421E_HCTL, MAX3421E_BUSRST );	             // issue bus reset
-      usbhostslave[OHS900_SOFENREG] = 0;
-      usbhostslave[OHS900_TXLINECTLREG] = OHS900_TXLCTL_MASK_SE0;
-      usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
-      delay = timer_get_msec() + 50; // send reset for 50msec
+      USBHOSTSLAVE_WRITE(OHS900_SOFENREG, 0);
+      USBHOSTSLAVE_WRITE(OHS900_TXLINECTLREG, OHS900_TXLCTL_MASK_SE0);
+      host->usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
+      host->delay = timer_get_msec() + 50; // send reset for 50msec
       break;
       
     case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
-      if( delay < timer_get_msec() )
+      if( host->delay < timer_get_msec() )
       {
-        usbhostslave[OHS900_SOFENREG] = OHS900_MASK_SOF_ENA;
-        usbhostslave[OHS900_TXLINECTLREG] = OHS900_TXLCTL_MASK_NORMAL;
-        usbhostslave[OHS900_IRQ_STATUS] = OHS900_INTMASK_SOFINTR;
+        USBHOSTSLAVE_WRITE(OHS900_SOFENREG, OHS900_MASK_SOF_ENA);
+        USBHOSTSLAVE_WRITE(OHS900_TXLINECTLREG, OHS900_TXLCTL_MASK_NORMAL);
+        USBHOSTSLAVE_WRITE(OHS900_IRQ_STATUS, OHS900_INTMASK_SOFINTR);
   
         /*if(( !max3421e_read_u08( MAX3421E_HCTL ) & MAX3421E_BUSRST ) ) {
   	tmpdata = max3421e_read_u08( MAX3421E_MODE ) | MAX3421E_SOFKAENAB;   // start SOF generation
   	max3421e_write_u08( MAX3421E_MODE, tmpdata );
         }*/
-        delay = timer_get_msec() + 20;                           //20ms wait after reset per USB spec
-        usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
+        host->delay = timer_get_msec() + 20;                           //20ms wait after reset per USB spec
+        host->usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
       }
       break;
       
     case USB_ATTACHED_SUBSTATE_WAIT_SOF:  //todo: change check order
       // MWW if( max3421e_read_u08( MAX3421E_HIRQ ) & MAX3421E_FRAMEIRQ ) { //when first SOF received we can continue
-      if (usbhostslave[OHS900_IRQ_STATUS]&OHS900_INTMASK_SOFINTR)
+      if (USBHOSTSLAVE_READ(OHS900_IRQ_STATUS)&OHS900_INTMASK_SOFINTR)
       {
-        usbhostslave[OHS900_IRQ_STATUS] = OHS900_INTMASK_SOFINTR;
-	if( delay < timer_get_msec() ) //20ms passed
-	  usb_task_state = USB_STATE_CONFIGURING;
+        USBHOSTSLAVE_WRITE(OHS900_IRQ_STATUS, OHS900_INTMASK_SOFINTR);
+	if( host->delay < timer_get_msec() ) //20ms passed
+	  host->usb_task_state = USB_STATE_CONFIGURING;
       }
       break;
       
@@ -644,7 +759,7 @@
     case USB_STATE_CONFIGURING:
       // configure root device
       usb_configure(0, 0, lowspeed);
-      usb_task_state = USB_STATE_RUNNING;
+      host->usb_task_state = USB_STATE_RUNNING;
     break;
     
     case USB_STATE_RUNNING:
@@ -651,14 +766,21 @@
       break;
     }
   }
+
+  if (USBHOSTSLAVE_READ(OHS900_IRQ_STATUS)&OHS900_INTMASK_SOFINTR)
+  {
+    USBHOSTSLAVE_WRITE(OHS900_IRQ_STATUS, OHS900_INTMASK_SOFINTR);
+  }
+
 }
 
 uint8_t usb_release_device(uint8_t parent, uint8_t port) {
   iprintf("%s(parent=%x, port=%d\n", __FUNCTION__, parent, port);
 
-  uint8_t i;
+
+  int i;
   for(i=0; i<USB_NUMDEVICES; i++) {
-    if(dev[i].bAddress && dev[i].parent == parent && dev[i].port == port) {
+    if(devices[i].bAddress && devices[i].parent == parent && devices[i].port == port) {
       iprintf("  -> device with address %x\n", dev[i].bAddress);
 
       // check if this is a hub (parent of some other device)
@@ -665,15 +787,15 @@
       // and release its kids first
       uint8_t j;
       for(j=0; j<USB_NUMDEVICES; j++) {
-	if(dev[j].parent == dev[i].bAddress)
-	  usb_release_device(dev[i].bAddress, dev[j].port);
+	if(devices[j].parent == devices[i].bAddress)
+	  usb_release_device(devices[i].bAddress, devices[j].port);
       }
       
       uint8_t rcode = 0;
-      if(dev[i].class)
-	rcode = dev[i].class->release(dev+i);
+      if(devices[i].class)
+	rcode = devices[i].class->release(devices+i);
 
-      dev[i].bAddress = 0;
+      devices[i].bAddress = 0;
       return rcode;	
     }
   }
@@ -690,6 +812,7 @@
 //get configuration descriptor  
 uint8_t usb_get_conf_descr( usb_device_t *dev, uint16_t nbytes, 
 			    uint8_t conf, usb_configuration_descriptor_t* p )  {
+  LOG("GET_CONF:%x\n",p);
   return( usb_ctrl_req( dev, USB_REQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 
 	       conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, (uint8_t*)p));
 }
@@ -709,10 +832,3 @@
 			conf_value, 0x00, 0x0000, 0x0000, NULL));
 }
 
-void usb_SetHubPreMask() { 
-  bmHubPre = 1; // MWW
-};
-
-void usb_ResetHubPreMask() { 
-  bmHubPre = 0; // MWW
-};
Index: firmware/usb/usbhostslave.h
===================================================================
--- firmware/usb/usbhostslave.h	(revision 274)
+++ firmware/usb/usbhostslave.h	(revision 275)
@@ -10,7 +10,7 @@
 // base address of OHS900 MWW TODO!!!
 //#define OHS900_BASE 0x80900c00
 
-char usbhostslave[0x100];
+char volatile * usbhostslave;
 
 /*
  * OHS900 has transfer registers, and control registers.  In host/master
@@ -20,7 +20,7 @@
 
 /* TRANSFER REGISTERS
  */
-#define OHS900_HOST_TX_CTLREG	0x00 
+#define OHS900_HOST_TX_CTLREG	(4*0x00) 
 #	define OHS900_HCTLMASK_TRANS_REQ		0x01 
 #	define OHS900_HCTLMASK_SOF_SYNC		0x02 
 #	define OHS900_HCTLMASK_PREAMBLE_EN	0x04 
@@ -27,7 +27,7 @@
 #	define OHS900_HCTLMASK_ISO_EN		0x08 
 
 
-#define OHS900_HRXSTATREG	0x0a	/* read */ 
+#define OHS900_HRXSTATREG	(4*0x0a)	/* read */ 
 #	define OHS900_STATMASK_CRC_ERROR		0x01 
 #	define OHS900_STATMASK_BS_ERROR		0x02 
 #	define OHS900_STATMASK_RX_OVF		0x04 
@@ -37,21 +37,21 @@
 #	define OHS900_STATMASK_ACK_RXED		0x40 
 #	define OHS900_STATMASK_DATA_SEQ		0x80 
 
-#define OHS900_TXTRANSTYPEREG		0x01	/* write */ 
+#define OHS900_TXTRANSTYPEREG		(4*0x01)	/* write */ 
 #	define	OHS900_SETUP	0x00 
 #	define	OHS900_IN	0x01 
 #	define	OHS900_OUT_DATA0	0x02 
 #	define	OHS900_OUT_DATA1	0x03 
 
-#define OHS900_TXADDRREG	0x04	
-#define OHS900_TXENDPREG	0x05	
+#define OHS900_TXADDRREG	(4*0x04)
+#define OHS900_TXENDPREG	(4*0x05)
 
 /* CONTROL REGISTERS:  
  */
-#define OHS900_SOFENREG		0x03 
+#define OHS900_SOFENREG		(4*0x03 )
 #	define OHS900_MASK_SOF_ENA	0x01 
 
-#define OHS900_TXLINECTLREG 0x02 
+#define OHS900_TXLINECTLREG (4*0x02)
 #	define OHS900_TXLCTL_MASK_FORCE	0x4 
 #	define OHS900_TXLCTL_MASK_LINE_CTRL_BITS 0x7
 #		define OHS900_TXLCTL_MASK_NORMAL	0x00 
@@ -64,29 +64,29 @@
 #	define OHS900_TXLCTL_MASK_FS_RATE 0x10 
 
 
-#define OHS900_IRQ_ENABLE	0x09             
+#define OHS900_IRQ_ENABLE	(4*0x09)             
 #	define OHS900_INTMASK_TRANS_DONE	0x01   
 #	define OHS900_INTMASK_SOFINTR	0x08   
 #	define OHS900_INTMASK_INSRMV	0x04   	
 #	define OHS900_INTMASK_RESUME_DET	0x02   
 		  
-#define OHS900_RXCONNSTATEREG 0x0e
+#define OHS900_RXCONNSTATEREG (4*0x0e)
 #define   OHS900_DISCONNECT_STATE 0x00
 #define   OHS900_LS_CONN_STATE 0x01
 #define   OHS900_FS_CONN_STATE 0x02
 
-#define OHS900_SLAVE_ADDRESS		0x54 
+#define OHS900_SLAVE_ADDRESS		(4*0x54)
 
 
 
-#define OHS900_IRQ_STATUS	0x08	/* write to ack */ 
-#define OHS900_HWREVREG		0xe1	/* read */ 
+#define OHS900_IRQ_STATUS	(4*0x08)	/* write to ack */ 
+#define OHS900_HWREVREG		(4*0xe1)	/* read */ 
 
-#define OHS900_SOFTMRREG		0x0F 
+#define OHS900_SOFTMRREG		(4*0x0F) 
 
 
 
-#define OHS900_HOSTSLAVECTLREG 			0xe0 
+#define OHS900_HOSTSLAVECTLREG 			(4*0xe0)
 #	define OHS900_HSCTLREG_HOST_EN_MASK	0x01 
 #	define OHS900_HSCTLREG_RESET_CORE	0x02 
 
@@ -98,16 +98,16 @@
  */
 #define H_MAXPACKET	64		/* bytes in fifos */
 
-#define OHS900_HOST_TXFIFO_DATA	0x30 
-#define OHS900_TXFIFOCNTMSBREG	0x32 
-#define OHS900_TXFIFOCNTLSBREG	0x33
-#define OHS900_TXFIFOCONTROLREG	0x34
-#define OHS900_HOST_RXFIFO_DATA	0x20 
-#define OHS900_RXFIFOCNTMSBREG	0x22 
-#define OHS900_RXFIFOCNTLSBREG	0x23
-#define OHS900_RXFIFOCONTROLREG	0x24
+#define OHS900_HOST_TXFIFO_DATA	(4*0x30) 
+#define OHS900_TXFIFOCNTMSBREG	(4*0x32) 
+#define OHS900_TXFIFOCNTLSBREG	(4*0x33)
+#define OHS900_TXFIFOCONTROLREG	(4*0x34)
+#define OHS900_HOST_RXFIFO_DATA	(4*0x20) 
+#define OHS900_RXFIFOCNTMSBREG	(4*0x22) 
+#define OHS900_RXFIFOCNTLSBREG	(4*0x23)
+#define OHS900_RXFIFOCONTROLREG	(4*0x24)
 #define		OHS900_FIFO_FORCE_EMPTY 0x01
 
 
-#define OHS900_IO_EXTENT 0x100
+#define OHS900_IO_EXTENT (4*0x100)
 
