From: tmk <nobody@nowhere>
Date: Sat, 17 Sep 2011 13:39:50 +0000 (+0900)
Subject: Added Bulegiga iWRAP support into HHKB.(Bluetooth)
X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=e67c988824f5ec0c965beb412f8ee5953dfd3c8c;p=tmk_firmware.git

Added Bulegiga iWRAP support into HHKB.(Bluetooth)
---

diff --git a/Makefile.common b/Makefile.common
deleted file mode 100644
index 1922def..0000000
--- a/Makefile.common
+++ /dev/null
@@ -1,35 +0,0 @@
-SRC +=	host.c \
-	keyboard.c \
-	command.c \
-	layer.c \
-	timer.c \
-	print.c \
-	util.c
-
-
-# Option modules
-ifdef MOUSEKEY_ENABLE
-    SRC += mousekey.c
-    OPT_DEFS += -DMOUSEKEY_ENABLE
-endif
-
-ifdef PS2_MOUSE_ENABLE
-    SRC += ps2.c \
-	   ps2_mouse.c
-    OPT_DEFS += -DPS2_MOUSE_ENABLE
-endif
-
-ifdef USB_EXTRA_ENABLE
-    OPT_DEFS += -DUSB_EXTRA_ENABLE
-endif
-
-ifdef USB_NKRO_ENABLE
-    OPT_DEFS += -DUSB_NKRO_ENABLE
-endif
-
-ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE)
-    OPT_DEFS += -DUSB_MOUSE_ENABLE
-endif
-
-
-include $(COMMON_DIR)/Makefile.rules
diff --git a/Makefile.pjrc b/Makefile.pjrc
deleted file mode 100644
index 894d4dc..0000000
--- a/Makefile.pjrc
+++ /dev/null
@@ -1,21 +0,0 @@
-OPT_DEFS += -DHOST_PJRC
-
-SRC =	usb_keyboard.c \
-	usb_debug.c \
-	usb.c \
-	jump_bootloader.c
-SRC +=	$(TARGET_SRC)
-
-
-# C source file search path
-VPATH = $(TARGET_DIR):$(COMMON_DIR):$(COMMON_DIR)/pjrc
-
-
-# Option modules
-ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE)
-    SRC += usb_mouse.c
-endif
-
-ifdef USB_EXTRA_ENABLE
-    SRC += usb_extra.c
-endif
diff --git a/Makefile.rules b/Makefile.rules
deleted file mode 100644
index f1d0a30..0000000
--- a/Makefile.rules
+++ /dev/null
@@ -1,547 +0,0 @@
-# Hey Emacs, this is a -*- makefile -*-
-#----------------------------------------------------------------------------
-# WinAVR Makefile Template written by Eric B. Weddington, Jg Wunsch, et al.
-#
-# Released to the Public Domain
-#
-# Additional material for this makefile was written by:
-# Peter Fleury
-# Tim Henigan
-# Colin O'Flynn
-# Reiner Patommel
-# Markus Pfaff
-# Sander Pool
-# Frederik Rouleau
-# Carlos Lamas
-#
-#----------------------------------------------------------------------------
-# On command line:
-#
-# make all = Make software.
-#
-# make clean = Clean out built project files.
-#
-# make coff = Convert ELF to AVR COFF.
-#
-# make extcoff = Convert ELF to AVR Extended COFF.
-#
-# make program = Download the hex file to the device, using avrdude.
-#                Please customize the avrdude settings below first!
-#
-# make debug = Start either simulavr or avarice as specified for debugging, 
-#              with avr-gdb or avr-insight as the front end for debugging.
-#
-# make filename.s = Just compile filename.c into the assembler code only.
-#
-# make filename.i = Create a preprocessed source file for use in submitting
-#                   bug reports to the GCC project.
-#
-# To rebuild project do "make clean" then "make all".
-#----------------------------------------------------------------------------
-
-
-# Output format. (can be srec, ihex, binary)
-FORMAT = ihex
-
-
-# Object files directory
-#     To put object files in current directory, use a dot (.), do NOT make
-#     this an empty or blank macro!
-OBJDIR = obj_$(TARGET)
-
-
-# Optimization level, can be [0, 1, 2, 3, s]. 
-#     0 = turn off optimization. s = optimize for size.
-#     (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
-OPT = s
-
-
-# Debugging format.
-#     Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
-#     AVR Studio 4.10 requires dwarf-2.
-#     AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
-DEBUG = dwarf-2
-
-
-# List any extra directories to look for include files here.
-#     Each directory must be seperated by a space.
-#     Use forward slashes for directory separators.
-#     For a directory that has spaces, enclose it in quotes.
-EXTRAINCDIRS = $(subst :, ,$(VPATH))
-
-
-# Compiler flag to set the C Standard level.
-#     c89   = "ANSI" C
-#     gnu89 = c89 plus GCC extensions
-#     c99   = ISO C99 standard (not yet fully implemented)
-#     gnu99 = c99 plus GCC extensions
-CSTANDARD = -std=gnu99
-
-
-# Place -D or -U options here for C sources
-CDEFS = -DF_CPU=$(F_CPU)UL
-CDEFS += $(OPT_DEFS)
-
-
-# Place -D or -U options here for ASM sources
-ADEFS = -DF_CPU=$(F_CPU)
-ADEFS += $(OPT_DEFS)
-
-
-# Place -D or -U options here for C++ sources
-CPPDEFS = -DF_CPU=$(F_CPU)UL
-#CPPDEFS += -D__STDC_LIMIT_MACROS
-#CPPDEFS += -D__STDC_CONSTANT_MACROS
-CPPDEFS += $(OPT_DEFS)
-
-
-
-#---------------- Compiler Options C ----------------
-#  -g*:          generate debugging information
-#  -O*:          optimization level
-#  -f...:        tuning, see GCC manual and avr-libc documentation
-#  -Wall...:     warning level
-#  -Wa,...:      tell GCC to pass this to the assembler.
-#    -adhlns...: create assembler listing
-CFLAGS = -g$(DEBUG)
-CFLAGS += $(CDEFS)
-CFLAGS += -O$(OPT)
-CFLAGS += -funsigned-char
-CFLAGS += -funsigned-bitfields
-CFLAGS += -ffunction-sections
-CFLAGS += -fpack-struct
-CFLAGS += -fshort-enums
-CFLAGS += -Wall
-CFLAGS += -Wstrict-prototypes
-#CFLAGS += -mshort-calls
-#CFLAGS += -fno-unit-at-a-time
-#CFLAGS += -Wundef
-#CFLAGS += -Wunreachable-code
-#CFLAGS += -Wsign-compare
-CFLAGS += -Wa,-adhlns=$(@:%.o=%.lst)
-CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
-CFLAGS += $(CSTANDARD)
-CFLAGS += -include $(CONFIG_H)
-
-
-#---------------- Compiler Options C++ ----------------
-#  -g*:          generate debugging information
-#  -O*:          optimization level
-#  -f...:        tuning, see GCC manual and avr-libc documentation
-#  -Wall...:     warning level
-#  -Wa,...:      tell GCC to pass this to the assembler.
-#    -adhlns...: create assembler listing
-CPPFLAGS = -g$(DEBUG)
-CPPFLAGS += $(CPPDEFS)
-CPPFLAGS += -O$(OPT)
-CPPFLAGS += -funsigned-char
-CPPFLAGS += -funsigned-bitfields
-CPPFLAGS += -fpack-struct
-CPPFLAGS += -fshort-enums
-CPPFLAGS += -fno-exceptions
-CPPFLAGS += -Wall
-CPPFLAGS += -Wundef
-#CPPFLAGS += -mshort-calls
-#CPPFLAGS += -fno-unit-at-a-time
-#CPPFLAGS += -Wstrict-prototypes
-#CPPFLAGS += -Wunreachable-code
-#CPPFLAGS += -Wsign-compare
-CPPFLAGS += -Wa,-adhlns=$(@:%.o=%.lst)
-CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
-#CPPFLAGS += $(CSTANDARD)
-CPPFLAGS += -include $(CONFIG_H)
-
-
-#---------------- Assembler Options ----------------
-#  -Wa,...:   tell GCC to pass this to the assembler.
-#  -adhlns:   create listing
-#  -gstabs:   have the assembler create line number information; note that
-#             for use in COFF files, additional information about filenames
-#             and function names needs to be present in the assembler source
-#             files -- see avr-libc docs [FIXME: not yet described there]
-#  -listing-cont-lines: Sets the maximum number of continuation lines of hex 
-#       dump that will be displayed for a given single line of source input.
-ASFLAGS = $(ADEFS) -Wa,-adhlns=$(@:%.o=%.lst),-gstabs,--listing-cont-lines=100
-ASFLAGS += -include $(CONFIG_H)
-
-
-#---------------- Library Options ----------------
-# Minimalistic printf version
-PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
-
-# Floating point printf version (requires MATH_LIB = -lm below)
-PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
-
-# If this is left blank, then it will use the Standard printf version.
-PRINTF_LIB = 
-#PRINTF_LIB = $(PRINTF_LIB_MIN)
-#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
-
-
-# Minimalistic scanf version
-SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
-
-# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
-SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
-
-# If this is left blank, then it will use the Standard scanf version.
-SCANF_LIB = 
-#SCANF_LIB = $(SCANF_LIB_MIN)
-#SCANF_LIB = $(SCANF_LIB_FLOAT)
-
-
-MATH_LIB = -lm
-
-
-# List any extra directories to look for libraries here.
-#     Each directory must be seperated by a space.
-#     Use forward slashes for directory separators.
-#     For a directory that has spaces, enclose it in quotes.
-EXTRALIBDIRS = 
-
-
-
-#---------------- External Memory Options ----------------
-
-# 64 KB of external RAM, starting after internal RAM (ATmega128!),
-# used for variables (.data/.bss) and heap (malloc()).
-#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
-
-# 64 KB of external RAM, starting after internal RAM (ATmega128!),
-# only used for heap (malloc()).
-#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
-
-EXTMEMOPTS =
-
-
-
-#---------------- Linker Options ----------------
-#  -Wl,...:     tell GCC to pass this to linker.
-#    -Map:      create map file
-#    --cref:    add cross reference to  map file
-#
-# Comennt out "--relax" option to avoid a error such:
-# 	(.vectors+0x30): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_12'
-#
-LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
-LDFLAGS += -Wl,--relax
-LDFLAGS += -Wl,--gc-sections
-LDFLAGS += $(EXTMEMOPTS)
-LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
-LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
-#LDFLAGS += -T linker_script.x
-
-
-
-#---------------- Debugging Options ----------------
-
-# For simulavr only - target MCU frequency.
-DEBUG_MFREQ = $(F_CPU)
-
-# Set the DEBUG_UI to either gdb or insight.
-# DEBUG_UI = gdb
-DEBUG_UI = insight
-
-# Set the debugging back-end to either avarice, simulavr.
-DEBUG_BACKEND = avarice
-#DEBUG_BACKEND = simulavr
-
-# GDB Init Filename.
-GDBINIT_FILE = __avr_gdbinit
-
-# When using avarice settings for the JTAG
-JTAG_DEV = /dev/com1
-
-# Debugging port used to communicate between GDB / avarice / simulavr.
-DEBUG_PORT = 4242
-
-# Debugging host used to communicate between GDB / avarice / simulavr, normally
-#     just set to localhost unless doing some sort of crazy debugging when 
-#     avarice is running on a different computer.
-DEBUG_HOST = localhost
-
-
-
-#============================================================================
-
-
-# Define programs and commands.
-SHELL = sh
-CC = avr-gcc
-OBJCOPY = avr-objcopy
-OBJDUMP = avr-objdump
-SIZE = avr-size
-AR = avr-ar rcs
-NM = avr-nm
-REMOVE = rm -f
-REMOVEDIR = rmdir
-COPY = cp
-WINSHELL = cmd
-
-
-# Define Messages
-# English
-MSG_ERRORS_NONE = Errors: none
-MSG_BEGIN = -------- begin --------
-MSG_END = --------  end  --------
-MSG_SIZE_BEFORE = Size before: 
-MSG_SIZE_AFTER = Size after:
-MSG_COFF = Converting to AVR COFF:
-MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
-MSG_FLASH = Creating load file for Flash:
-MSG_EEPROM = Creating load file for EEPROM:
-MSG_EXTENDED_LISTING = Creating Extended Listing:
-MSG_SYMBOL_TABLE = Creating Symbol Table:
-MSG_LINKING = Linking:
-MSG_COMPILING = Compiling C:
-MSG_COMPILING_CPP = Compiling C++:
-MSG_ASSEMBLING = Assembling:
-MSG_CLEANING = Cleaning project:
-MSG_CREATING_LIBRARY = Creating library:
-
-
-
-
-# Define all object files.
-OBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(patsubst %.cpp,$(OBJDIR)/%.o,$(patsubst %.S,$(OBJDIR)/%.o,$(SRC))))
-
-# Define all listing files.
-LST = $(patsubst %.c,$(OBJDIR)/%.lst,$(patsubst %.cpp,$(OBJDIR)/%.lst,$(patsubst %.S,$(OBJDIR)/%.lst,$(SRC))))
-
-
-# Compiler flags to generate dependency files.
-GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
-
-
-# Combine all necessary flags and optional flags.
-# Add target processor to flags.
-ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
-ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS)
-ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
-
-
-
-
-
-# Default target.
-all: begin gccversion sizebefore build sizeafter end
-
-# Change the build target to build a HEX file or a library.
-build: elf hex eep lss sym
-#build: lib
-
-
-elf: $(TARGET).elf
-hex: $(TARGET).hex
-eep: $(TARGET).eep
-lss: $(TARGET).lss
-sym: $(TARGET).sym
-LIBNAME=lib$(TARGET).a
-lib: $(LIBNAME)
-
-
-
-# Eye candy.
-# AVR Studio 3.x does not check make's exit code but relies on
-# the following magic strings to be generated by the compile job.
-begin:
-	@echo
-	@echo $(MSG_BEGIN)
-
-end:
-	@echo $(MSG_END)
-	@echo
-
-
-# Display size of file.
-HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
-#ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf
-ELFSIZE = $(SIZE) $(TARGET).elf
-
-sizebefore:
-	@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
-	2>/dev/null; echo; fi
-
-sizeafter:
-	@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
-	2>/dev/null; echo; fi
-
-
-
-# Display compiler version information.
-gccversion : 
-	@$(CC) --version
-
-
-
-# Program the device.  
-program: $(TARGET).hex $(TARGET).eep
-	$(PROGRAM_CMD)
-
-
-# Generate avr-gdb config/init file which does the following:
-#     define the reset signal, load the target file, connect to target, and set 
-#     a breakpoint at main().
-gdb-config: 
-	@$(REMOVE) $(GDBINIT_FILE)
-	@echo define reset >> $(GDBINIT_FILE)
-	@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
-	@echo end >> $(GDBINIT_FILE)
-	@echo file $(TARGET).elf >> $(GDBINIT_FILE)
-	@echo target remote $(DEBUG_HOST):$(DEBUG_PORT)  >> $(GDBINIT_FILE)
-ifeq ($(DEBUG_BACKEND),simulavr)
-	@echo load  >> $(GDBINIT_FILE)
-endif
-	@echo break main >> $(GDBINIT_FILE)
-
-debug: gdb-config $(TARGET).elf
-ifeq ($(DEBUG_BACKEND), avarice)
-	@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
-	@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
-	$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
-	@$(WINSHELL) /c pause
-
-else
-	@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
-	$(DEBUG_MFREQ) --port $(DEBUG_PORT)
-endif
-	@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
-
-
-
-
-# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
-COFFCONVERT = $(OBJCOPY) --debugging
-COFFCONVERT += --change-section-address .data-0x800000
-COFFCONVERT += --change-section-address .bss-0x800000
-COFFCONVERT += --change-section-address .noinit-0x800000
-COFFCONVERT += --change-section-address .eeprom-0x810000
-
-
-
-coff: $(TARGET).elf
-	@echo
-	@echo $(MSG_COFF) $(TARGET).cof
-	$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
-
-
-extcoff: $(TARGET).elf
-	@echo
-	@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
-	$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
-
-
-
-# Create final output files (.hex, .eep) from ELF output file.
-%.hex: %.elf
-	@echo
-	@echo $(MSG_FLASH) $@
-	$(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock -R .signature $< $@
-
-%.eep: %.elf
-	@echo
-	@echo $(MSG_EEPROM) $@
-	-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
-	--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0
-
-# Create extended listing file from ELF output file.
-%.lss: %.elf
-	@echo
-	@echo $(MSG_EXTENDED_LISTING) $@
-	$(OBJDUMP) -h -S -z $< > $@
-
-# Create a symbol table from ELF output file.
-%.sym: %.elf
-	@echo
-	@echo $(MSG_SYMBOL_TABLE) $@
-	$(NM) -n $< > $@
-
-
-
-# Create library from object files.
-.SECONDARY : $(TARGET).a
-.PRECIOUS : $(OBJ)
-%.a: $(OBJ)
-	@echo
-	@echo $(MSG_CREATING_LIBRARY) $@
-	$(AR) $@ $(OBJ)
-
-
-# Link: create ELF output file from object files.
-.SECONDARY : $(TARGET).elf
-.PRECIOUS : $(OBJ)
-%.elf: $(OBJ)
-	@echo
-	@echo $(MSG_LINKING) $@
-	$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
-
-
-# Compile: create object files from C source files.
-$(OBJDIR)/%.o : %.c
-	@echo
-	@echo $(MSG_COMPILING) $<
-	$(CC) -c $(ALL_CFLAGS) $< -o $@ 
-
-
-# Compile: create object files from C++ source files.
-$(OBJDIR)/%.o : %.cpp
-	@echo
-	@echo $(MSG_COMPILING_CPP) $<
-	$(CC) -c $(ALL_CPPFLAGS) $< -o $@ 
-
-
-# Compile: create assembler files from C source files.
-%.s : %.c
-	$(CC) -S $(ALL_CFLAGS) $< -o $@
-
-
-# Compile: create assembler files from C++ source files.
-%.s : %.cpp
-	$(CC) -S $(ALL_CPPFLAGS) $< -o $@
-
-
-# Assemble: create object files from assembler source files.
-$(OBJDIR)/%.o : %.S
-	@echo
-	@echo $(MSG_ASSEMBLING) $<
-	$(CC) -c $(ALL_ASFLAGS) $< -o $@
-
-
-# Create preprocessed source for use in sending a bug report.
-%.i : %.c
-	$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ 
-
-
-# Target: clean project.
-clean: begin clean_list end
-
-clean_list :
-	@echo
-	$(REMOVE) $(TARGET).hex
-	$(REMOVE) $(TARGET).eep
-	$(REMOVE) $(TARGET).cof
-	$(REMOVE) $(TARGET).elf
-	$(REMOVE) $(TARGET).map
-	$(REMOVE) $(TARGET).sym
-	$(REMOVE) $(TARGET).lss
-	$(REMOVE) $(OBJ)
-	$(REMOVE) $(LST)
-	$(REMOVE) $(OBJ:.o=.s)
-	$(REMOVE) $(OBJ:.o=.i)
-	$(REMOVE) -r .dep
-	$(REMOVEDIR) $(OBJDIR)
-
-
-# Create object files directory
-$(shell mkdir $(OBJDIR) 2>/dev/null)
-
-
-# Include the dependency files.
--include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
-
-
-# Listing of phony targets.
-.PHONY : all begin finish end sizebefore sizeafter gccversion \
-build elf hex eep lss sym coff extcoff \
-clean clean_list program debug gdb-config
-
diff --git a/Makefile.vusb b/Makefile.vusb
deleted file mode 100644
index b8e71a8..0000000
--- a/Makefile.vusb
+++ /dev/null
@@ -1,11 +0,0 @@
-OPT_DEFS += -DHOST_VUSB
-
-SRC =	usbdrv.c \
-	usbdrvasm.S \
-	oddebug.c \
-	sendchar_usart.c
-SRC +=	$(TARGET_SRC)
-
-
-# C source file search path
-VPATH = $(TARGET_DIR):$(COMMON_DIR):$(COMMON_DIR)/vusb:$(COMMON_DIR)/vusb/usbdrv
diff --git a/POWER.txt b/POWER.txt
new file mode 100644
index 0000000..0abbbe4
--- /dev/null
+++ b/POWER.txt
@@ -0,0 +1,62 @@
+Time to Sleep
+=============
+USB suspend     no activity on USB line for  3ms
+No Interaction  no user interaction
+    matrix has no change
+    matrix has no switch on
+
+
+AVR Power Management
+====================
+
+V-USB suspend
+    USB suspend
+    http://vusb.wikidot.com/examples
+
+MCUSR   MCU Status Register
+    WDRF    Watchdog Reset Flag
+    BORF
+    EXTRF
+    PORF    Power-on Reset Flag
+
+SMCR    Sleep Mode Control Register
+    SE      Sleep Enable
+    SM2:0   
+        #define set_sleep_mode(mode) \
+        #define SLEEP_MODE_IDLE         (0)
+        #define SLEEP_MODE_ADC          _BV(SM0)
+        #define SLEEP_MODE_PWR_DOWN     _BV(SM1)
+        #define SLEEP_MODE_PWR_SAVE     (_BV(SM0) | _BV(SM1))
+        #define SLEEP_MODE_STANDBY      (_BV(SM1) | _BV(SM2))
+        #define SLEEP_MODE_EXT_STANDBY  (_BV(SM0) | _BV(SM1) | _BV(SM2))
+
+
+ACSR    Analog Comparator Control and Status Register
+    To disable Analog Comparator
+    ACSR = 0x80;
+    or
+    ACSR &= ~_BV(ACIE);
+    ACSR |= _BV(ACD);
+
+    ACD: Analog Comparator Disable
+        When this bit is written logic one, the power to the Analog Comparator is
+        switched off. This bit can be set at any time to turn off the Analog
+        Comparator. This will reduce power consumption in Active and Idle mode.
+        When changing the ACD bit, the Analog Comparator Interrupt must be disabled
+        by clearing the ACIE bit in ACSR. Otherwise an interrupt can occur when
+        the bit is changed.
+
+DIDR1   Digital Input Disable Register 1
+    AIN1D
+    AIN0D
+        When this bit is written logic one, the digital input buffer on the AIN1/0 pin is disabled. The corresponding PIN Register bit will always read as zero when this bit is set. When an analog signal is applied to the AIN1/0 pin and the digital input from this pin is not needed, this bit should be written logic one to reduce power consumption in the digital input buffer.
+
+
+PRR     Power Reduction Register
+    PRTWI
+    PRTIM2
+    PRTIM0
+    PRTIM1
+    PRSPI
+    PRUSART0
+    PRADC
diff --git a/README b/README
index 2aa0106..d85f512 100644
--- a/README
+++ b/README
@@ -96,8 +96,8 @@ Build Options
 3. Choose optional modules as needed. Comment out to disable optional modules.
      MOUSEKEY_ENABLE = yes	# Mouse keys
      PS2_MOUSE_ENABLE = yes	# PS/2 mouse(TrackPoint) support
-     USB_EXTRA_ENABLE = yes	# Enhanced feature for Windows(Audio control and System control)
-     USB_NKRO_ENABLE = yes	# USB Nkey Rollover
+     EXTRAKEY_ENABLE = yes	# Enhanced feature for Windows(Audio control and System control)
+     NKRO_ENABLE = yes		# USB Nkey Rollover
 
 <target>/config.h:
 1. USB vendor/product ID and device description
diff --git a/adb_usb/Makefile b/adb_usb/Makefile
index 802b424..56b342d 100644
--- a/adb_usb/Makefile
+++ b/adb_usb/Makefile
@@ -8,11 +8,11 @@ COMMON_DIR = ..
 TARGET_DIR = .
 
 # keyboard dependent files
-TARGET_SRC =	main_pjrc.c \
-		keymap.c \
-  	        matrix.c \
-		led.c \
-		adb.c
+SRC =	main.c \
+	keymap.c \
+	matrix.c \
+	led.c \
+	adb.c
 
 CONFIG_H = config.h
 
@@ -36,10 +36,10 @@ F_CPU = 16000000
 # Build Options
 #   comment out to disable the options.
 #
-MOUSEKEY_ENABLE = yes	# Mouse keys
+#MOUSEKEY_ENABLE = yes	# Mouse keys
 #PS2_MOUSE_ENABLE = yes	# PS/2 mouse(TrackPoint) support
-USB_EXTRA_ENABLE = yes	# Audio control and System control
-#USB_NKRO_ENABLE = yes	# USB Nkey Rollover
+#EXTRAKEY_ENABLE = yes	# Audio control and System control
+#NKRO_ENABLE = yes	# USB Nkey Rollover
 
 
 
@@ -48,5 +48,5 @@ PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex
 
 
 
-include $(COMMON_DIR)/Makefile.pjrc
-include $(COMMON_DIR)/Makefile.common
+include $(COMMON_DIR)/pjrc.mk
+include $(COMMON_DIR)/common.mk
diff --git a/adb_usb/README b/adb_usb/README
index b4bd35b..5d0e1bc 100644
--- a/adb_usb/README
+++ b/adb_usb/README
@@ -59,4 +59,12 @@ effort at this time.
     ),
 
 
+Notes
+-----
+Many ADB keyboards has no discrimination between right modifier and left one,
+you will always see left control even if you press right control key.
+Apple Extended Keyboard and Apple Extended Keyboard II are the examples.
+Though ADB protocol itsef has the ability of distinction between right and left.
+And most ADB keyboard has no NKRO functionality, though ADB protocol itsef has that. 
+
 EOF
diff --git a/adb_usb/config.h b/adb_usb/config.h
index 27f31ca..6431ede 100644
--- a/adb_usb/config.h
+++ b/adb_usb/config.h
@@ -37,8 +37,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 /* key combination for command */
 #define IS_COMMAND() ( \
-    keyboard_report->mods == (BIT_LSHIFT | BIT_LCTRL | BIT_LALT | BIT_LGUI) || \
-    keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT) \
+    keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_LCTRL) | MOD_BIT(KB_LALT) | MOD_BIT(KB_LGUI)) || \
+    keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) \
 )
 
 
diff --git a/command.c b/command.c
index 0a07aeb..22f25e9 100644
--- a/command.c
+++ b/command.c
@@ -30,24 +30,49 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifdef HOST_PJRC
 #   include "jump_bootloader.h"
 #   include "usb_keyboard.h"
-#   ifdef USB_EXTRA_ENABLE
+#   ifdef EXTRAKEY_ENABLE
 #       include "usb_extra.h"
 #   endif
 #endif
 
+#ifdef HOST_VUSB
+#   include "usbdrv.h"
+#endif
+
 
+static uint8_t command_common(void);
 static void help(void);
 static void switch_layer(uint8_t layer);
 
+static bool last_print_enable;
 
 uint8_t command_proc(void)
 {
+    uint8_t processed = 0;
+    last_print_enable = print_enable;
+
     if (!IS_COMMAND())
         return 0;
 
-    uint8_t processed = 1;
-    bool last_print_enable = print_enable;
     print_enable = true;
+    if (command_extra() || command_common()) {
+        processed = 1;
+        _delay_ms(500);
+    }
+    print_enable = last_print_enable;
+    return processed;
+}
+
+/* This allows to define extra commands. return 0 when not processed. */
+uint8_t command_extra(void) __attribute__ ((weak));
+uint8_t command_extra(void)
+{
+    return 0;
+}
+
+
+static uint8_t command_common(void)
+{
     switch (host_get_first_key()) {
         case KB_H:
             help();
@@ -122,21 +147,27 @@ uint8_t command_proc(void)
             print("usb_keyboard_protocol: "); phex(usb_keyboard_protocol); print("\n");
             print("usb_keyboard_idle_config:"); phex(usb_keyboard_idle_config); print("\n");
             print("usb_keyboard_idle_count:"); phex(usb_keyboard_idle_count); print("\n");
+#endif
+
+#ifdef HOST_VUSB
+#   if USB_COUNT_SOF
+            print("usbSofCount: "); phex(usbSofCount); print("\n");
+#   endif
 #endif
             break;
-#ifdef USB_NKRO_ENABLE
+#ifdef NKRO_ENABLE
         case KB_N:
             // send empty report before change
             host_clear_keyboard_report();
             host_send_keyboard_report();
             keyboard_nkro = !keyboard_nkro;
             if (keyboard_nkro)
-                print("USB_NKRO: enabled\n");
+                print("NKRO: enabled\n");
             else
-                print("USB_NKRO: disabled\n");
+                print("NKRO: disabled\n");
             break;
 #endif
-#ifdef USB_EXTRA_ENABLE
+#ifdef EXTRAKEY_ENABLE
         case KB_ESC:
             host_clear_keyboard_report();
             host_send_keyboard_report();
@@ -175,12 +206,9 @@ uint8_t command_proc(void)
             switch_layer(4);
             break;
         default:
-            processed = 0;
+            return 0;
     }
-    if (processed)
-        _delay_ms(500);
-    print_enable = last_print_enable;
-    return processed;
+    return 1;
 }
 
 static void help(void)
@@ -194,8 +222,8 @@ static void help(void)
     print("v: print version\n");
     print("t: print timer count\n");
     print("s: print status\n");
-#ifdef USB_NKRO_ENABLE
-    print("n: toggle USB_NKRO\n");
+#ifdef NKRO_ENABLE
+    print("n: toggle NKRO\n");
 #endif
     print("Backspace: clear matrix\n");
     print("ESC: power down/wake up\n");
diff --git a/command.h b/command.h
index dca6da4..4888f5e 100644
--- a/command.h
+++ b/command.h
@@ -19,5 +19,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define COMMAND
 
 uint8_t command_proc(void);
+/* This allows to extend commands. Return 0 when command is not processed. */
+uint8_t command_extra(void);
 
 #endif
diff --git a/common.mk b/common.mk
new file mode 100644
index 0000000..17c6816
--- /dev/null
+++ b/common.mk
@@ -0,0 +1,38 @@
+SRC +=	host.c \
+	keyboard.c \
+	command.c \
+	layer.c \
+	timer.c \
+	print.c \
+	util.c
+
+
+# Option modules
+ifdef MOUSEKEY_ENABLE
+    SRC += mousekey.c
+    OPT_DEFS += -DMOUSEKEY_ENABLE
+endif
+
+ifdef PS2_MOUSE_ENABLE
+    SRC += ps2.c \
+	   ps2_mouse.c
+    OPT_DEFS += -DPS2_MOUSE_ENABLE
+endif
+
+ifdef EXTRAKEY_ENABLE
+    OPT_DEFS += -DEXTRAKEY_ENABLE
+endif
+
+ifdef NKRO_ENABLE
+    OPT_DEFS += -DNKRO_ENABLE
+endif
+
+ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE)
+    OPT_DEFS += -DMOUSE_ENABLE
+endif
+
+# Search Path
+VPATH += $(COMMON_DIR)
+
+
+include $(COMMON_DIR)/rules.mk
diff --git a/hhkb/FUSE.txt b/hhkb/FUSE.txt
new file mode 100644
index 0000000..40055e5
--- /dev/null
+++ b/hhkb/FUSE.txt
@@ -0,0 +1,40 @@
+ATMega168P Fuse/Lock Bits
+=========================
+This configuration is from usbasploader's Makefile.
+
+    HFUSE   0xD6
+    LFUSE   0xDF
+    EFUSE   0x00
+    LOCK    0x3F(intact)
+
+#---------------------------------------------------------------------
+# ATMega168P
+#---------------------------------------------------------------------
+# Fuse extended byte:
+# 0x00 = 0 0 0 0   0 0 0 0 <-- BOOTRST (boot reset vector at 0x1800)
+#                    \+/
+#                     +------- BOOTSZ (00 = 2k bytes)
+# Fuse high byte:
+# 0xd6 = 1 1 0 1   0 1 1 0
+#        ^ ^ ^ ^   ^ \-+-/
+#        | | | |   |   +------ BODLEVEL 0..2 (110 = 1.8 V)
+#        | | | |   + --------- EESAVE (preserve EEPROM over chip erase)
+#        | | | +-------------- WDTON (if 0: watchdog always on)
+#        | | +---------------- SPIEN (allow serial programming)
+#        | +------------------ DWEN (debug wire enable)
+#        +-------------------- RSTDISBL (reset pin is enabled)
+# Fuse low byte:
+# 0xdf = 1 1 0 1   1 1 1 1
+#        ^ ^ \ /   \--+--/
+#        | |  |       +------- CKSEL 3..0 (external >8M crystal)
+#        | |  +--------------- SUT 1..0 (crystal osc, BOD enabled)
+#        | +------------------ CKOUT (if 0: Clock output enabled)
+#        +-------------------- CKDIV8 (if 0: divide by 8)
+
+
+# Lock Bits
+# 0x3f = - - 1 1   1 1 1 1
+#            \ /   \-/ \-/
+#             |     |   +----- LB 2..1 (No memory lock features enabled)
+#             |     +--------- BLB0 2..1 (No restrictions for SPM or LPM accessing the Application section)
+#             +--------------- BLB1 2..1 (No restrictions for SPM or LPM accessing the Boot Loader section)
diff --git a/hhkb/Makefile b/hhkb/Makefile
deleted file mode 100644
index e1cc2f2..0000000
--- a/hhkb/Makefile
+++ /dev/null
@@ -1,55 +0,0 @@
-#
-# Makefile for PJRC Teensy
-#
-
-
-# Target file name (without extension).
-TARGET = hhkb_pjrc
-
-# Directory common source filess exist
-COMMON_DIR = ..
-
-# Directory keyboard dependent files exist
-TARGET_DIR = .
-
-# keyboard dependent files
-TARGET_SRC =	main_pjrc.c \
-		keymap.c \
-  	        matrix.c \
-		led.c
-
-CONFIG_H = config_pjrc.h
-
-
-# MCU name, you MUST set this to match the board you are using
-# type "make clean" after changing this, so all files will be rebuilt
-#MCU = at90usb162       # Teensy 1.0
-#MCU = atmega32u4       # Teensy 2.0
-#MCU = at90usb646       # Teensy++ 1.0
-MCU = at90usb1286      # Teensy++ 2.0
-
-
-# Processor frequency.
-#   Normally the first thing your program should do is set the clock prescaler,
-#   so your program will run at the correct speed.  You should also set this
-#   variable to same clock speed.  The _delay_ms() macro uses this, and many
-#   examples use this variable to calculate timings.  Do not add a "UL" here.
-F_CPU = 16000000
-
-
-# Build Options
-#   comment out to disable the options.
-MOUSEKEY_ENABLE = yes	# Mouse keys
-#PS2_MOUSE_ENABLE = yes	# PS/2 mouse(TrackPoint) support
-USB_EXTRA_ENABLE = yes	# Audio control and System control
-USB_NKRO_ENABLE = yes	# USB Nkey Rollover
-
-
-
-#---------------- Programming Options --------------------------
-PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex
-
-
-
-include $(COMMON_DIR)/Makefile.pjrc
-include $(COMMON_DIR)/Makefile.common
diff --git a/hhkb/Makefile.iwrap b/hhkb/Makefile.iwrap
new file mode 100644
index 0000000..cf020b9
--- /dev/null
+++ b/hhkb/Makefile.iwrap
@@ -0,0 +1,91 @@
+#
+# Makefile for iWRAP
+#
+
+
+# Target file name (without extension).
+TARGET = hhkb_iwrap
+
+# Directory common source filess exist
+COMMON_DIR = ..
+
+# Directory keyboard dependent files exist
+TARGET_DIR = .
+
+# keyboard dependent files
+SRC =	main.c \
+	keymap.c \
+	matrix.c \
+	led.c
+
+CONFIG_H = config_iwrap.h
+
+
+# V-USB debug level: To use ps2_usart.c level must be 0
+# ps2_usart.c requires USART to receive PS/2 signal.
+OPT_DEFS = -DDEBUG_LEVEL=0
+
+
+# MCU name, you MUST set this to match the board you are using
+# type "make clean" after changing this, so all files will be rebuilt
+MCU = atmega168p
+# avrdude doesn't know atmega168p
+AVRDUDE_MCU = atmega168
+
+
+# Processor frequency.
+#   Normally the first thing your program should do is set the clock prescaler,
+#   so your program will run at the correct speed.  You should also set this
+#   variable to same clock speed.  The _delay_ms() macro uses this, and many
+#   examples use this variable to calculate timings.  Do not add a "UL" here.
+F_CPU = 12000000
+
+
+# Build Options
+#   comment out to disable the options.
+#
+MOUSEKEY_ENABLE = yes	# Mouse keys
+EXTRAKEY_ENABLE = yes	# Audio control and System control
+#NKRO_ENABLE = yes	# USB Nkey Rollover
+
+
+
+#---------------- Programming Options --------------------------
+AVRDUDE = avrdude
+# Type: avrdude -c ? to get a full listing.
+AVRDUDE_PROGRAMMER = usbasp
+AVRDUDE_PORT =
+AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
+#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
+
+# Uncomment the following if you want avrdude's erase cycle counter.
+# Note that this counter needs to be initialized first using -Yn,
+# see avrdude manual.
+#AVRDUDE_ERASE_COUNTER = -y
+
+# Uncomment the following if you do /not/ wish a verification to be
+# performed after programming the device.
+#AVRDUDE_NO_VERIFY = -V
+
+# Increase verbosity level.  Please use this when submitting bug
+# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude> 
+# to submit bug reports.
+#AVRDUDE_VERBOSE = -v -v
+
+#AVRDUDE_FLAGS = -p $(AVRDUDE_MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
+AVRDUDE_FLAGS = -p $(AVRDUDE_MCU) -c $(AVRDUDE_PROGRAMMER)
+AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
+AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
+AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
+
+PROGRAM_CMD = $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
+
+
+
+# Search Path
+VPATH = $(TARGET_DIR)
+
+include $(COMMON_DIR)/iwrap.mk
+# To be swatchable btween Bluetooth and USB. Comment out if you don't need USB.
+include $(COMMON_DIR)/vusb.mk
+include $(COMMON_DIR)/common.mk
diff --git a/hhkb/Makefile.pjrc b/hhkb/Makefile.pjrc
new file mode 100644
index 0000000..17aa865
--- /dev/null
+++ b/hhkb/Makefile.pjrc
@@ -0,0 +1,58 @@
+#
+# Makefile for PJRC Teensy
+#
+
+
+# Target file name (without extension).
+TARGET = hhkb_pjrc
+
+# Directory common source filess exist
+COMMON_DIR = ..
+
+# Directory keyboard dependent files exist
+TARGET_DIR = .
+
+# keyboard dependent files
+SRC =	main.c \
+	keymap.c \
+	matrix.c \
+	led.c
+
+CONFIG_H = config_pjrc.h
+
+
+# MCU name, you MUST set this to match the board you are using
+# type "make clean" after changing this, so all files will be rebuilt
+#MCU = at90usb162       # Teensy 1.0
+#MCU = atmega32u4       # Teensy 2.0
+#MCU = at90usb646       # Teensy++ 1.0
+MCU = at90usb1286      # Teensy++ 2.0
+
+
+# Processor frequency.
+#   Normally the first thing your program should do is set the clock prescaler,
+#   so your program will run at the correct speed.  You should also set this
+#   variable to same clock speed.  The _delay_ms() macro uses this, and many
+#   examples use this variable to calculate timings.  Do not add a "UL" here.
+F_CPU = 16000000
+
+
+# Build Options
+#   comment out to disable the options.
+MOUSEKEY_ENABLE = yes	# Mouse keys
+#PS2_MOUSE_ENABLE = yes	# PS/2 mouse(TrackPoint) support
+EXTRAKEY_ENABLE = yes	# Audio control and System control
+NKRO_ENABLE = yes	# USB Nkey Rollover
+
+
+
+#---------------- Programming Options --------------------------
+PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex
+
+
+
+# Search Path
+VPATH = $(TARGET_DIR)
+
+include $(COMMON_DIR)/pjrc.mk
+include $(COMMON_DIR)/common.mk
diff --git a/hhkb/Makefile.vusb b/hhkb/Makefile.vusb
index 77841b8..5bfc233 100644
--- a/hhkb/Makefile.vusb
+++ b/hhkb/Makefile.vusb
@@ -13,10 +13,10 @@ COMMON_DIR = ..
 TARGET_DIR = .
 
 # keyboard dependent files
-TARGET_SRC =	main_vusb.c \
-		keymap.c \
-		matrix.c \
-		led.c
+SRC =	main.c \
+	keymap.c \
+	matrix.c \
+	led.c
 
 CONFIG_H = config_vusb.h
 
@@ -28,7 +28,9 @@ OPT_DEFS = -DDEBUG_LEVEL=0
 
 # MCU name, you MUST set this to match the board you are using
 # type "make clean" after changing this, so all files will be rebuilt
-MCU = atmega168
+MCU = atmega168p
+# avrdude doesn't know atmega168p
+AVRDUDE_MCU = atmega168
 
 
 # Processor frequency.
@@ -36,15 +38,15 @@ MCU = atmega168
 #   so your program will run at the correct speed.  You should also set this
 #   variable to same clock speed.  The _delay_ms() macro uses this, and many
 #   examples use this variable to calculate timings.  Do not add a "UL" here.
-F_CPU = 20000000
+F_CPU = 12000000
 
 
 # Build Options
 #   comment out to disable the options.
 #
 MOUSEKEY_ENABLE = yes	# Mouse keys
-USB_EXTRA_ENABLE = yes	# Audio control and System control
-#USB_NKRO_ENABLE = yes	# USB Nkey Rollover
+EXTRAKEY_ENABLE = yes	# Audio control and System control
+#NKRO_ENABLE = yes	# USB Nkey Rollover
 
 
 
@@ -70,8 +72,8 @@ AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
 # to submit bug reports.
 #AVRDUDE_VERBOSE = -v -v
 
-#AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
-AVRDUDE_FLAGS = -p $(MCU) -c $(AVRDUDE_PROGRAMMER)
+#AVRDUDE_FLAGS = -p $(AVRDUDE_MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
+AVRDUDE_FLAGS = -p $(AVRDUDE_MCU) -c $(AVRDUDE_PROGRAMMER)
 AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
 AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
 AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
@@ -80,5 +82,8 @@ PROGRAM_CMD = $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE
 
 
 
-include $(COMMON_DIR)/Makefile.vusb
-include $(COMMON_DIR)/Makefile.common
+# Search Path
+VPATH = $(TARGET_DIR)
+
+include $(COMMON_DIR)/vusb.mk
+include $(COMMON_DIR)/common.mk
diff --git a/hhkb/README b/hhkb/README
index 2a44181..65f7dca 100644
--- a/hhkb/README
+++ b/hhkb/README
@@ -4,7 +4,7 @@ Alternative Controller for HHKB
 Feature
 -------
 - Mouse Keys
-- NKRO on USB
+- NKRO on USB(PJRC Tennsy only)
 - Keymap Layers
 
 
@@ -13,8 +13,11 @@ Customize Keymap
 see keymap.c.
 
 
-Build for Teensy
-----------------
+
+Build
+=====
+PJRC Teensy
+-----------
 0. Edit matrix.c.
     adjust scan code to your pin configuration.(see doc/HHKB.txt for pinouts)
 1. Define macros in config_pjrc.h.(Optional)
@@ -22,15 +25,15 @@ Build for Teensy
     IS_COMMAND
 2. Edit Makefile for MCU setting and build options.
     MCU, F_CPU
-    MOUSEKEY_ENABLE, USB_EXTRA_ENABLE, USB_NKRO_ENABLE
+    MOUSEKEY_ENABLE, EXTRAKEY_ENABLE, NKRO_ENABLE
 3. Build hex file.
-    $ make
+    $ make -f Makefile.pjrc
 4. Program MCU.
-    $  make program
+    $  make -f Makefile.pjrc program
 
 
-Build for V-USB
----------------
+V-USB
+-----
 0. Edit matrix.c and usbconfig.h.
     adjust scan code to your pin configuration.(see doc/HHKB.txt for pinouts)
     define macros for V-USB in usbconfig.h.
@@ -38,7 +41,7 @@ Build for V-USB
     IS_COMMAND
 2. Edit Makefile.vusb for MCU setting and build options.
     MCU, F_CPU
-    MOUSEKEY_ENABLE, USB_EXTRA_ENABLE, USB_NKRO_ENABLE
+    MOUSEKEY_ENABLE, EXTRAKEY_ENABLE
 3. Build hex file.
     $ make -f Makefile.vusb
 4. Program MCU.
@@ -52,21 +55,59 @@ Build for V-USB
     http://www.obdev.at/products/vusb/usbasploader.html
 
 
-V-USB Circuit
--------------
+iWRAP
+-----
+0. Edit matrix.c and usbconfig.h.
+    adjust scan code to your pin configuration.(see doc/HHKB.txt for pinouts)
+    define macros for V-USB in usbconfig.h.
+1. Define macros in config_iwrap.h.(Optional)
+    IS_COMMAND
+2. Edit Makefile.iwrap for MCU setting and build options.
+    MCU, F_CPU
+    MOUSEKEY_ENABLE, EXTRAKEY_ENABLE
+3. Build hex file.
+    $ make -f Makefile.iwrap
+4. Program MCU.
+    $  make -f Makefile.iwrap program
+
+
+
+Hardware
+========
+PJRC Teensy
+-----------
+                        +---------------+
+                        |   Teensy++    |
+                        |               |
+                        |               |        HHKB
+                        |               |        ~~~~
+                        |          PB0-2|------->ROW(6-8)
+                        |          PB3-5|------->COL(9-11)
+                        |            PB6|------->ENABLE(12)
+                        |            PE6|<-------KEY(4)
+                        |            PE7|------->PREV(5)
+                        |               |
+                        |               |
+                        |               |
+                        +---------------+
+
+
+V-USB
+-----
                 +---+   +---------------+
 USB            GND  |   |   ATmega168   |
-===                 C3  |               |
+~~~                 C3  |               |
 5V <-------+--------+---|Vcc,AVCC       |        HHKB
-           R1           |               |        ====
-D- <----+--+-----R2-----|INT1      PB0-2|------->ROW
-D+ <----|---+----R3-----|INT0      PB3-5|------->COL
-        Z1  Z2          |            PB6|------->ENABLE
-GND<----+---+--+--+-----|GND         PE6|------->KEY
-               |  |     |            PE7|------->PREV
-               |  C2-+--|XTAL1          |        (see doc/HHKB.txt for pinouts)
-               |     X1 |               |
-               +--C3-+--|XTAL2       RST|---SW--+GND
+           R1           |               |        ~~~~
+D- <----+--+-----R2-----|INT1      PB2-4|------->ROW(6-8)
+D+ <----|---+----R3-----|INT0      PC0-2|------->COL(9-11)
+        Z1  Z2          |            PC3|------->ENABLE(12)
+GND<----+---+-----------|GND         PB0|<-------KEY(4)
+                        |            PB1|------->PREV(5)
+                        |               |
+            GND+-C2--+--|XTAL1       RXD|------->Debug Console
+                     X1 |            TXD|<-------Debug Console
+            GND+-C3--+--|XTAL2       RST|---SW--+GND
                         +---------------+
 R1:     1.5K Ohm
 R2,R3:  68 Ohm
@@ -77,4 +118,34 @@ X1:     Crystal 20MHz(16MHz/12MHz)
 SW:     Push Switch(Optional for bootloader)
 
 
+iWRAP
+-----
+                        +---------------+        WT12
+              5V        |   ATmega168   | 5V/3.3V~~~~
+              +-----+---|Vcc,AVCC    PC4|---/--->iWRAP(RxD)
+USB           |     C3  |            PC5|<--/----iWRAP(TxD)
+~~~           |     +   |               | 
+5V <--BATT    +    GND  |               |        HHKB
+              R1        |               |        ~~~~
+D- <----+-----+--R2-----|INT1      PB2-4|------->ROW(6-8)
+D+ <----|---+----R3-----|INT0      PC0-2|------->COL(9-11)
+        Z1  Z2          |            PC3|------->ENABLE(12)
+GND<----+---+-----------|GND         PB0|<-------KEY(4)
+                        |            PB1|------->PREV(5)
+                        |               |
+            GND+-C2--+--|XTAL1       RXD|------->Debug Console
+                     X1 |            TXD|<-------Debug Console
+            GND+-C3--+--|XTAL2       RST|---SW--+GND
+                        +---------------+
+
+R1:     1.5K Ohm
+R2,R3:  68 Ohm
+Z1,Z2:  Zener 3.6V
+C1,C2:  22pF
+C3:     0.1uF
+X1:     Crystal 12MHz
+SW:     Push Switch(Optional)
+BATT:   Li-Po Battery, Battery Charger and Voltage Regulator(5V and 3.3V).
+
+
 EOF
diff --git a/hhkb/config_iwrap.h b/hhkb/config_iwrap.h
new file mode 100644
index 0000000..80ab643
--- /dev/null
+++ b/hhkb/config_iwrap.h
@@ -0,0 +1,55 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#define VENDOR_ID       0xFEED
+#define PRODUCT_ID      0xBEEA
+// TODO: share these strings with usbconfig.h
+// Edit usbconfig.h to change these.
+#define MANUFACTURER    t.m.k.
+#define PRODUCT         HHKB mod
+#define DESCRIPTION     t.m.k. keyboard firmware for HHKB mod
+
+
+/* matrix size */
+#define MATRIX_ROWS 8
+#define MATRIX_COLS 8
+
+
+/* key combination for command */
+#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT))) 
+
+/* mouse keys */
+#ifdef MOUSEKEY_ENABLE
+#   define MOUSEKEY_DELAY_TIME 255
+#endif
+
+/* pins for Software UART */
+#define SUART_IN_PIN    PINC
+#define SUART_IN_BIT    5
+#define SUART_OUT_PORT  PORTC
+#define SUART_OUT_BIT   4
+
+
+#define DEBUG_LED 1
+#define DEBUG_LED_CONFIG    (DDRD |= (1<<4))
+#define DEBUG_LED_OFF       (PORTD |= (1<<4))
+#define DEBUG_LED_ON        (PORTD &= ~(1<<4))
+
+#endif
diff --git a/hhkb/config_pjrc.h b/hhkb/config_pjrc.h
index ef2efe2..8379202 100644
--- a/hhkb/config_pjrc.h
+++ b/hhkb/config_pjrc.h
@@ -36,11 +36,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
 /* key combination for command */
-#define IS_COMMAND() ( \
-    keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT) || \
-    keyboard_report->mods == (BIT_LCTRL | BIT_RSHIFT) \
-)
-
+#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT))) 
 
 /* mouse keys */
 #ifdef MOUSEKEY_ENABLE
diff --git a/hhkb/config_vusb.h b/hhkb/config_vusb.h
index 115b73d..2686448 100644
--- a/hhkb/config_vusb.h
+++ b/hhkb/config_vusb.h
@@ -18,7 +18,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifndef CONFIG_H
 #define CONFIG_H
 
-
 #define VENDOR_ID       0xFEED
 #define PRODUCT_ID      0xC0FE
 // TODO: share these strings with usbconfig.h
@@ -34,11 +33,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
 /* key combination for command */
-#define IS_COMMAND() ( \
-    keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT) || \
-    keyboard_report->mods == (BIT_LCTRL | BIT_RSHIFT) \
-)
-
+#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT))) 
 
 /* mouse keys */
 #ifdef MOUSEKEY_ENABLE
@@ -46,4 +41,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #endif
 
 
+#define DEBUG_LED 1
+#define DEBUG_LED_CONFIG    (DDRD |= (1<<4))
+#define DEBUG_LED_OFF       (PORTD |= (1<<4))
+#define DEBUG_LED_ON        (PORTD &= ~(1<<4))
+
 #endif
diff --git a/hhkb/doc/Bluetooth.txt b/hhkb/doc/Bluetooth.txt
new file mode 100644
index 0000000..b27f197
--- /dev/null
+++ b/hhkb/doc/Bluetooth.txt
@@ -0,0 +1,4 @@
+HHKB Bluetooth mod
+==================
+See this article:
+http://geekhack.org/showwiki.php?title=Island:20851
diff --git a/hhkb/doc/Bluetooth_img/.picasa.ini b/hhkb/doc/Bluetooth_img/.picasa.ini
new file mode 100755
index 0000000..f6a4f60
--- /dev/null
+++ b/hhkb/doc/Bluetooth_img/.picasa.ini
@@ -0,0 +1,2 @@
+[Picasa]
+name=Bluetooth_img
diff --git a/hhkb/doc/Bluetooth_img/BT_circuit.jpg b/hhkb/doc/Bluetooth_img/BT_circuit.jpg
new file mode 100755
index 0000000..2e5a25e
Binary files /dev/null and b/hhkb/doc/Bluetooth_img/BT_circuit.jpg differ
diff --git a/hhkb/doc/HHKB_TP1684.jpg b/hhkb/doc/HHKB_TP1684.jpg
deleted file mode 100644
index 0a03164..0000000
Binary files a/hhkb/doc/HHKB_TP1684.jpg and /dev/null differ
diff --git a/hhkb/doc/HHKB_chart1.jpg b/hhkb/doc/HHKB_chart1.jpg
deleted file mode 100644
index 1f09bd1..0000000
Binary files a/hhkb/doc/HHKB_chart1.jpg and /dev/null differ
diff --git a/hhkb/doc/HHKB_chart2.jpg b/hhkb/doc/HHKB_chart2.jpg
deleted file mode 100644
index 45f5ada..0000000
Binary files a/hhkb/doc/HHKB_chart2.jpg and /dev/null differ
diff --git a/hhkb/doc/HHKB_connector.jpg b/hhkb/doc/HHKB_connector.jpg
deleted file mode 100644
index e8a09e9..0000000
Binary files a/hhkb/doc/HHKB_connector.jpg and /dev/null differ
diff --git a/hhkb/doc/HHKB_controller.jpg b/hhkb/doc/HHKB_controller.jpg
deleted file mode 100644
index e3dae8e..0000000
Binary files a/hhkb/doc/HHKB_controller.jpg and /dev/null differ
diff --git a/hhkb/doc/HHKB_img/HHKB_TP1684.jpg b/hhkb/doc/HHKB_img/HHKB_TP1684.jpg
new file mode 100644
index 0000000..0a03164
Binary files /dev/null and b/hhkb/doc/HHKB_img/HHKB_TP1684.jpg differ
diff --git a/hhkb/doc/HHKB_img/HHKB_chart1.jpg b/hhkb/doc/HHKB_img/HHKB_chart1.jpg
new file mode 100644
index 0000000..1f09bd1
Binary files /dev/null and b/hhkb/doc/HHKB_img/HHKB_chart1.jpg differ
diff --git a/hhkb/doc/HHKB_img/HHKB_chart2.jpg b/hhkb/doc/HHKB_img/HHKB_chart2.jpg
new file mode 100644
index 0000000..45f5ada
Binary files /dev/null and b/hhkb/doc/HHKB_img/HHKB_chart2.jpg differ
diff --git a/hhkb/doc/HHKB_img/HHKB_connector.jpg b/hhkb/doc/HHKB_img/HHKB_connector.jpg
new file mode 100644
index 0000000..e8a09e9
Binary files /dev/null and b/hhkb/doc/HHKB_img/HHKB_connector.jpg differ
diff --git a/hhkb/doc/HHKB_img/HHKB_controller.jpg b/hhkb/doc/HHKB_img/HHKB_controller.jpg
new file mode 100644
index 0000000..e3dae8e
Binary files /dev/null and b/hhkb/doc/HHKB_img/HHKB_controller.jpg differ
diff --git a/hhkb/doc/HHKB_img/HHKB_keyswitch.jpg b/hhkb/doc/HHKB_img/HHKB_keyswitch.jpg
new file mode 100644
index 0000000..3afc269
Binary files /dev/null and b/hhkb/doc/HHKB_img/HHKB_keyswitch.jpg differ
diff --git a/hhkb/doc/HHKB_img/connector_contact.jpg b/hhkb/doc/HHKB_img/connector_contact.jpg
new file mode 100644
index 0000000..5304bc8
Binary files /dev/null and b/hhkb/doc/HHKB_img/connector_contact.jpg differ
diff --git a/hhkb/doc/HHKB_img/logic_analyzer.jpg b/hhkb/doc/HHKB_img/logic_analyzer.jpg
new file mode 100644
index 0000000..f1b438a
Binary files /dev/null and b/hhkb/doc/HHKB_img/logic_analyzer.jpg differ
diff --git a/hhkb/doc/HHKB_img/probe_contact.jpg b/hhkb/doc/HHKB_img/probe_contact.jpg
new file mode 100644
index 0000000..dc79afa
Binary files /dev/null and b/hhkb/doc/HHKB_img/probe_contact.jpg differ
diff --git a/hhkb/doc/HHKB_img/teensy_install.jpg b/hhkb/doc/HHKB_img/teensy_install.jpg
new file mode 100644
index 0000000..873d988
Binary files /dev/null and b/hhkb/doc/HHKB_img/teensy_install.jpg differ
diff --git a/hhkb/doc/HHKB_img/teensy_wiring.jpg b/hhkb/doc/HHKB_img/teensy_wiring.jpg
new file mode 100644
index 0000000..1c4eb67
Binary files /dev/null and b/hhkb/doc/HHKB_img/teensy_wiring.jpg differ
diff --git a/hhkb/doc/HHKB_keyswitch.jpg b/hhkb/doc/HHKB_keyswitch.jpg
deleted file mode 100644
index 3afc269..0000000
Binary files a/hhkb/doc/HHKB_keyswitch.jpg and /dev/null differ
diff --git a/hhkb/doc/connector_contact.jpg b/hhkb/doc/connector_contact.jpg
deleted file mode 100644
index 5304bc8..0000000
Binary files a/hhkb/doc/connector_contact.jpg and /dev/null differ
diff --git a/hhkb/doc/logic_analyzer.jpg b/hhkb/doc/logic_analyzer.jpg
deleted file mode 100644
index f1b438a..0000000
Binary files a/hhkb/doc/logic_analyzer.jpg and /dev/null differ
diff --git a/hhkb/doc/probe_contact.jpg b/hhkb/doc/probe_contact.jpg
deleted file mode 100644
index dc79afa..0000000
Binary files a/hhkb/doc/probe_contact.jpg and /dev/null differ
diff --git a/hhkb/doc/teensy_install.jpg b/hhkb/doc/teensy_install.jpg
deleted file mode 100644
index 873d988..0000000
Binary files a/hhkb/doc/teensy_install.jpg and /dev/null differ
diff --git a/hhkb/doc/teensy_wiring.jpg b/hhkb/doc/teensy_wiring.jpg
deleted file mode 100644
index 1c4eb67..0000000
Binary files a/hhkb/doc/teensy_wiring.jpg and /dev/null differ
diff --git a/hhkb/keymap.c b/hhkb/keymap.c
index f539a06..85a7c31 100644
--- a/hhkb/keymap.c
+++ b/hhkb/keymap.c
@@ -32,21 +32,21 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // Convert physical keyboard layout to matrix array.
 // This is a macro to define keymap easily in keyboard layout form.
 #define KEYMAP( \
-    R3C1, R3C0, R0C0, R1C0, R1C1, R2C0, R2C1, R4C0, R4C1, R6C0, R6C1, R7C0, R7C1, R5C0, R5C1, \
-    R3C2, R0C1, R0C2, R1C3, R1C2, R2C3, R2C2, R4C2, R4C3, R6C2, R6C3, R7C3, R7C2, R5C2, \
-    R3C3, R0C4, R0C3, R1C4, R1C5, R2C4, R2C5, R4C5, R4C4, R6C5, R6C4, R7C4, R5C3, \
-    R3C4, R0C5, R0C6, R0C7, R1C6, R1C7, R2C6, R4C6, R6C6, R7C6, R7C5, R5C5, R5C4, \
-    R3C5, R3C6, R3C7, R5C7, R5C6 \
+    K31, K30, K00, K10, K11, K20, K21, K40, K41, K60, K61, K70, K71, K50, K51, \
+    K32, K01, K02, K13, K12, K23, K22, K42, K43, K62, K63, K73, K72, K52, \
+    K33, K04, K03, K14, K15, K24, K25, K45, K44, K65, K64, K74, K53, \
+    K34, K05, K06, K07, K16, K17, K26, K46, K66, K76, K75, K55, K54, \
+         K35, K36,           K37,                K57, K56 \
 ) \
 { \
-    { R0C0, R0C1, R0C2, R0C3, R0C4, R0C5, R0C6, R0C7 }, \
-    { R1C0, R1C1, R1C2, R1C3, R1C4, R1C5, R1C6, R1C7 }, \
-    { R2C0, R2C1, R2C2, R2C3, R2C4, R2C5, R2C6, KB_NO }, \
-    { R3C0, R3C1, R3C2, R3C3, R3C4, R3C5, R3C6, R3C7 }, \
-    { R4C0, R4C1, R4C2, R4C3, R4C4, R4C5, R4C6, KB_NO }, \
-    { R5C0, R5C1, R5C2, R5C3, R5C4, R5C5, R5C6, R5C7 }, \
-    { R6C0, R6C1, R6C2, R6C3, R6C4, R6C5, R6C6, KB_NO }, \
-    { R7C0, R7C1, R7C2, R7C3, R7C4, R7C5, R7C6, KB_NO } \
+    { KB_##K00, KB_##K01, KB_##K02, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \
+    { KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \
+    { KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_NO    }, \
+    { KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_##K37 }, \
+    { KB_##K40, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_NO    }, \
+    { KB_##K50, KB_##K51, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \
+    { KB_##K60, KB_##K61, KB_##K62, KB_##K63, KB_##K64, KB_##K65, KB_##K66, KB_NO    }, \
+    { KB_##K70, KB_##K71, KB_##K72, KB_##K73, KB_##K74, KB_##K75, KB_##K76, KB_NO    } \
 }
 
 #define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)]))
@@ -58,8 +58,8 @@ static const uint8_t PROGMEM fn_layer[] = {
     1,              // Fn1
     2,              // Fn2
     3,              // Fn3
-    4,              // Fn4
-    0,              // Fn5
+    3,              // Fn4
+    4,              // Fn5
     0,              // Fn6
     0               // Fn7
 };
@@ -71,8 +71,8 @@ static const uint8_t PROGMEM fn_keycode[] = {
     KB_NO,          // Fn1
     KB_SLSH,        // Fn2
     KB_SCLN,        // Fn3
-    KB_SPC,         // Fn4
-    KB_NO,          // Fn5
+    KB_NO,          // Fn4
+    KB_SPC,         // Fn5
     KB_NO,          // Fn6
     KB_NO           // Fn7
 };
@@ -91,11 +91,11 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
      *       |Gui|Alt  |Fn5                    |Alt  |Fn4|
      *       `-------------------------------------------'
      */
-    KEYMAP(KB_ESC, KB_1,   KB_2,   KB_3,   KB_4,   KB_5,   KB_6,   KB_7,   KB_8,   KB_9,   KB_0,   KB_MINS,KB_EQL, KB_BSLS,KB_GRV, \
-           KB_TAB, KB_Q,   KB_W,   KB_E,   KB_R,   KB_T,   KB_Y,   KB_U,   KB_I,   KB_O,   KB_P,   KB_LBRC,KB_RBRC,KB_BSPC, \
-           KB_LCTL,KB_A,   KB_S,   KB_D,   KB_F,   KB_G,   KB_H,   KB_J,   KB_K,   KB_L,   KB_FN3, KB_QUOT,KB_ENT, \
-           KB_LSFT,KB_Z,   KB_X,   KB_C,   KB_V,   KB_B,   KB_N,   KB_M,   KB_COMM,KB_DOT, KB_FN2, KB_RSFT,KB_FN1, \
-           KB_LGUI,KB_LALT,KB_FN4, KB_RALT,KB_RGUI),
+    KEYMAP(ESC, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, BSLS,GRV, \
+           TAB, Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC,BSPC, \
+           LCTL,A,   S,   D,   F,   G,   H,   J,   K,   L,   FN3, QUOT,ENT, \
+           LSFT,Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, FN2, RSFT,FN1, \
+                LGUI,LALT,          FN5,                RALT,FN4),
 
     /* Layer 1: HHKB mode (HHKB Fn)
      * ,-----------------------------------------------------------.
@@ -110,11 +110,11 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
      *      |Gui |Alt  |Space                  |Alt  |xxx|
      *      `--------------------------------------------'
      */ 
-    KEYMAP(KB_ESC, KB_F1,  KB_F2,  KB_F3,  KB_F4,  KB_F5,  KB_F6,  KB_F7,  KB_F8,  KB_F9,  KB_F10, KB_F11, KB_F12, KB_INS, KB_DEL, \
-           KB_CAPS,KB_NO,  KB_NO,  KB_NO,  KB_NO,  KB_NO,  KB_NO,  KB_NO,  KB_PSCR,KB_SLCK,KB_BRK, KB_UP,  KB_NO,  KB_BSPC, \
-           KB_LCTL,KB_VOLD,KB_VOLU,KB_MUTE,KB_NO,  KB_NO,  KB_PAST,KB_PSLS,KB_HOME,KB_PGUP,KB_LEFT,KB_RGHT,KB_ENT, \
-           KB_LSFT,KB_NO,  KB_NO,  KB_NO,  KB_NO,  KB_NO,  KB_PPLS,KB_PMNS,KB_END, KB_PGDN,KB_DOWN,KB_RSFT,KB_FN1, \
-           KB_LGUI,KB_LALT,KB_SPC, KB_RALT,KB_FN7),
+    KEYMAP(ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
+           CAPS,NO,  NO,  NO,  NO,  NO,  NO,  NO,  PSCR,SLCK,BRK, UP,  NO,  BSPC, \
+           LCTL,VOLD,VOLU,MUTE,NO,  NO,  PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \
+           LSFT,NO,  NO,  NO,  NO,  NO,  PPLS,PMNS,END, PGDN,DOWN,RSFT,FN1, \
+                LGUI,LALT,          SPC,                RALT,FN7),
 
     /* Layer 2: Vi mode (Slash)
      * ,-----------------------------------------------------------.
@@ -129,11 +129,11 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
      *       |Gui|Alt  |Space                  |Alt  |Gui|
      *       `-------------------------------------------'
      */
-    KEYMAP(KB_ESC, KB_F1,  KB_F2,  KB_F3,  KB_F4,  KB_F5,  KB_F6,  KB_F7,  KB_F8,  KB_F9,  KB_F10, KB_F11, KB_F12, KB_INS, KB_DEL, \
-           KB_TAB, KB_HOME,KB_PGDN,KB_UP,  KB_PGUP,KB_END, KB_HOME,KB_PGDN,KB_PGUP,KB_END, KB_NO,  KB_NO,  KB_NO,  KB_BSPC, \
-           KB_LCTL,KB_NO,  KB_LEFT,KB_DOWN,KB_RGHT,KB_NO,  KB_LEFT,KB_DOWN,KB_UP,  KB_RGHT,KB_NO,  KB_NO,  KB_ENT, \
-           KB_LSFT,KB_NO,  KB_NO,  KB_NO,  KB_NO,  KB_NO,  KB_HOME,KB_PGDN,KB_PGUP,KB_END, KB_FN2, KB_RSFT,KB_NO, \
-           KB_LGUI,KB_LALT,KB_SPC, KB_RALT,KB_RGUI),
+    KEYMAP(ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
+           TAB, HOME,PGDN,UP,  PGUP,END, HOME,PGDN,PGUP,END, NO,  NO,  NO,  BSPC, \
+           LCTL,NO,  LEFT,DOWN,RGHT,NO,  LEFT,DOWN,UP,  RGHT,NO,  NO,  ENT, \
+           LSFT,NO,  NO,  NO,  NO,  NO,  HOME,PGDN,PGUP,END, FN2, RSFT,NO, \
+                LGUI,LALT,          SPC,                RALT,RGUI),
 
     /* Layer 3: Mouse mode (Semicolon)
      * ,-----------------------------------------------------------.
@@ -149,11 +149,24 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
      *      `--------------------------------------------'
      * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel 
      */
-    KEYMAP(KB_ESC, KB_F1,  KB_F2,  KB_F3,  KB_F4,  KB_F5,  KB_F6,  KB_F7,  KB_F8,  KB_F9,  KB_F10, KB_F11, KB_F12, KB_INS, KB_DEL, \
-           KB_TAB, KB_WH_L,KB_WH_U,KB_MS_U,KB_WH_D,KB_WH_R,KB_WH_L,KB_WH_D,KB_WH_U,KB_WH_R,KB_NO,  KB_NO,  KB_NO,  KB_BSPC, \
-           KB_LCTL,KB_NO,  KB_MS_L,KB_MS_D,KB_MS_R,KB_NO,  KB_MS_L,KB_MS_D,KB_MS_U,KB_MS_R,KB_FN3, KB_NO,  KB_ENT, \
-           KB_LSFT,KB_BTN4,KB_BTN5,KB_BTN1,KB_BTN2,KB_BTN3,KB_BTN2,KB_BTN1,KB_BTN4,KB_BTN5,KB_NO,  KB_RSFT,KB_NO, \
-           KB_LGUI,KB_LALT,KB_BTN1,KB_RALT,KB_RGUI),
+#ifdef HOST_IWRAP
+// iWRAP does not support mouse wheel, use these keycodes to remap as wheel
+#define KB_KPPL KB_KP_PLUS
+#define KB_KPMI KB_KP_MINUS
+#define KB_KPAS KB_KP_ASTERISK
+#define KB_KPSL KB_KP_SLASH
+    KEYMAP(ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
+           TAB, KPAS,KPPL,MS_U,KPMI,KPSL,KPAS,KPPL,KPMI,KPSL,NO,  NO,  NO,  BSPC, \
+           LCTL,NO,  MS_L,MS_D,MS_R,NO,  MS_L,MS_D,MS_U,MS_R,FN3, NO,  ENT, \
+           LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,NO,  NO,  NO,  RSFT,NO, \
+                LGUI,LALT,          BTN1,               RALT,FN4),
+#else
+    KEYMAP(ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
+           TAB, WH_L,WH_U,MS_U,WH_D,WH_R,WH_L,WH_D,WH_U,WH_R,NO,  NO,  NO,  BSPC, \
+           LCTL,NO,  MS_L,MS_D,MS_R,NO,  MS_L,MS_D,MS_U,MS_R,FN3, NO,  ENT, \
+           LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,BTN4,BTN5,NO,  RSFT,NO, \
+                LGUI,LALT,          BTN1,               RALT,FN4),
+#endif
 
     /* Layer 4: Matias half keyboard style (Space)
      * ,-----------------------------------------------------------.
@@ -169,18 +182,26 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
      *      `--------------------------------------------'
      */
 /*
-    KEYMAP(KB_MINS,KB_0,   KB_9,   KB_8,   KB_7,   KB_6,   KB_5,   KB_4,   KB_3,   KB_2,   KB_1,   KB_NO,  KB_NO,  KB_NO,  KB_ESC, \
-           KB_BSPC,KB_P,   KB_O,   KB_I,   KB_U,   KB_Y,   KB_T,   KB_R,   KB_E,   KB_W,   KB_Q,   KB_NO,  KB_NO,  KB_TAB, \
-           KB_LCTL,KB_SCLN,KB_L,   KB_K,   KB_J,   KB_H,   KB_G,   KB_F,   KB_D,   KB_S,   KB_A,   KB_RCTL,KB_RCTL, \
-           KB_LSFT,KB_SLSH,KB_DOT, KB_COMM,KB_M,   KB_N,   KB_B,   KB_V,   KB_C,   KB_X,   KB_Z,   KB_RSFT,KB_NO, \
-           KB_LGUI,KB_LALT,KB_FN4, KB_RALT,KB_RGUI)
+    KEYMAP(MINS,0,   9,   8,   7,   6,   5,   4,   3,   2,   1,   NO,  NO,  NO,  ESC, \
+           BSPC,P,   O,   I,   U,   Y,   T,   R,   E,   W,   Q,   NO,  NO,  TAB, \
+           LCTL,SCLN,L,   K,   J,   H,   G,   F,   D,   S,   A,   RCTL,RCTL, \
+           LSFT,SLSH,DOT, COMM,M,   N,   B,   V,   C,   X,   Z,   RSFT,NO, \
+                LGUI,LALT,          FN5,                RALT,RGUI)
 */
     /* Mouse mode (Space) */
-    KEYMAP(KB_ESC, KB_F1,  KB_F2,  KB_F3,  KB_F4,  KB_F5,  KB_F6,  KB_F7,  KB_F8,  KB_F9,  KB_F10, KB_F11, KB_F12, KB_INS, KB_DEL, \
-           KB_TAB, KB_WH_L,KB_WH_U,KB_MS_U,KB_WH_D,KB_WH_R,KB_WH_L,KB_WH_D,KB_WH_U,KB_WH_R,KB_NO,  KB_NO,  KB_NO,  KB_BSPC, \
-           KB_LCTL,KB_NO,  KB_MS_L,KB_MS_D,KB_MS_R,KB_NO,  KB_MS_L,KB_MS_D,KB_MS_U,KB_MS_R,KB_FN3, KB_NO,  KB_ENT, \
-           KB_LSFT,KB_BTN4,KB_BTN5,KB_BTN1,KB_BTN2,KB_BTN3,KB_BTN2,KB_BTN1,KB_BTN4,KB_BTN5,KB_NO,  KB_RSFT,KB_NO, \
-           KB_LGUI,KB_LALT,KB_FN4, KB_RALT,KB_RGUI),
+#ifdef HOST_IWRAP
+    KEYMAP(ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
+           TAB, KPAS,KPPL,MS_U,KPMI,KPSL,KPAS,KPPL,KPMI,KPSL,NO,  NO,  NO,  BSPC, \
+           LCTL,NO,  MS_L,MS_D,MS_R,NO,  MS_L,MS_D,MS_U,MS_R,FN3, NO,  ENT, \
+           LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,BTN4,BTN5,NO,  RSFT,NO, \
+                LGUI,LALT,          FN5,                RALT,RGUI),
+#else
+    KEYMAP(ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
+           TAB, WH_L,WH_U,MS_U,WH_D,WH_R,WH_L,WH_D,WH_U,WH_R,NO,  NO,  NO,  BSPC, \
+           LCTL,NO,  MS_L,MS_D,MS_R,NO,  MS_L,MS_D,MS_U,MS_R,FN3, NO,  ENT, \
+           LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,BTN4,BTN5,NO,  RSFT,NO, \
+                LGUI,LALT,          FN5,                RALT,RGUI),
+#endif
 };
 
 
diff --git a/hhkb/matrix.c b/hhkb/matrix.c
index a77febb..350066b 100644
--- a/hhkb/matrix.c
+++ b/hhkb/matrix.c
@@ -25,9 +25,15 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <util/delay.h>
 #include "print.h"
 #include "util.h"
+#include "timer.h"
 #include "matrix.h"
 
 
+// Timer resolution check
+#if (1000000/TIMER_RAW_FREQ > 20)
+#   error "Timer resolution(>20us) is not enough for HHKB matrix scan tweak on V-USB."
+#endif
+
 #if (MATRIX_COLS > 16)
 #   error "MATRIX_COLS must not exceed 16"
 #endif
@@ -82,18 +88,22 @@ static bool matrix_has_ghost_in_row(uint8_t row);
 #define KEY_STATE()             (PINE & (1<<6))
 #define KEY_PREV_ON()           (PORTE |=  (1<<7))
 #define KEY_PREV_OFF()          (PORTE &= ~(1<<7))
-
+#define KEY_POWER_ON()
+#define KEY_POWER_OFF()
 #else
 // Ports for V-USB
 // key:     PB0(pull-uped)
 // prev:    PB1
 // row:     PB2-4
 // col:     PC0-2,3
+// power:   PB5(Low:on/Hi-z:off)
 #define KEY_INIT()              do {    \
-    DDRB |= 0x1E;                       \
-    DDRB &= ~(1<<0);                    \
-    PORTB |= (1<<0);                    \
-    DDRC |= 0x0F;                       \
+    DDRB  |= 0x3E;                      \
+    DDRB  &= ~(1<<0);                   \
+    PORTB |= 1<<0;                      \
+    DDRC  |= 0x0F;                      \
+    KEY_UNABLE();                       \
+    KEY_PREV_OFF();                     \
 } while (0)
 #define KEY_SELECT(ROW, COL)    do {    \
     PORTB = (PORTB & 0xE3) | ((ROW) & 0x07)<<2; \
@@ -104,6 +114,18 @@ static bool matrix_has_ghost_in_row(uint8_t row);
 #define KEY_STATE()             (PINB & (1<<0))
 #define KEY_PREV_ON()           (PORTB |=  (1<<1))
 #define KEY_PREV_OFF()          (PORTB &= ~(1<<1))
+// Power supply switching
+#define KEY_POWER_ON()          do {    \
+    KEY_INIT();                         \
+    PORTB &= ~(1<<5);                   \
+    _delay_us(200);                     \
+} while (0)
+#define KEY_POWER_OFF()         do {    \
+    DDRB  &= ~0x3F;                     \
+    PORTB &= ~0x3F;                     \
+    DDRC  &= ~0x0F;                     \
+    PORTC &= ~0x0F;                     \
+} while (0)
 #endif
 
 
@@ -138,36 +160,46 @@ uint8_t matrix_scan(void)
     matrix_prev = matrix;
     matrix = tmp;
 
+    KEY_POWER_ON();
     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
         for (uint8_t col = 0; col < MATRIX_COLS; col++) {
             KEY_SELECT(row, col);
-            _delay_us(40);  // from logic analyzer chart
+            _delay_us(40);
+
+            // Not sure this is needed. This just emulates HHKB controller's behaviour.
             if (matrix_prev[row] & (1<<col)) {
                 KEY_PREV_ON();
             }
-            _delay_us(7);  // from logic analyzer chart
+            _delay_us(7);
+
+            // NOTE: KEY_STATE is valid only in 20us after KEY_ENABLE.
+            // If V-USB interrupts in this section we could lose 40us or so
+            // and would read invalid value from KEY_STATE.
+            uint8_t last = TIMER_RAW;
 
-#if HOST_VUSB
-            // to avoid V-USB interrupt during read key state
-            uint8_t sreg = SREG;
-            cli();
-#endif
             KEY_ENABLE();
-            _delay_us(10);  // from logic analyzer chart
+            // Wait for KEY_STATE outputs its value.
+            // 1us was ok on one HHKB, but not worked on another.
+            _delay_us(10);
             if (KEY_STATE()) {
                 matrix[row] &= ~(1<<col);
             } else {
                 matrix[row] |= (1<<col);
             }
-#if HOST_VUSB
-            SREG = sreg;
-#endif
+
+            // Ignore if this code region execution time elapses more than 20us.
+            if (TIMER_DIFF_RAW(TIMER_RAW, last) > 20/(1000000/TIMER_RAW_FREQ)) {
+                matrix[row] = matrix_prev[row];
+            }
 
             KEY_PREV_OFF();
             KEY_UNABLE();
-            _delay_us(150);  // from logic analyzer chart
+            // NOTE: KEY_STATE keep its state in 20us after KEY_ENABLE.
+            // This takes 25us or more to make sure KEY_STATE returns to idle state.
+            _delay_us(150);
         }
     }
+    KEY_POWER_OFF();
     return 1;
 }
 
diff --git a/hhkb/usbconfig.h b/hhkb/usbconfig.h
index e828350..c3aad34 100644
--- a/hhkb/usbconfig.h
+++ b/hhkb/usbconfig.h
@@ -171,7 +171,7 @@ section at the end of this file).
 /* This macro (if defined) is executed when a USB SET_ADDRESS request was
  * received.
  */
-#define USB_COUNT_SOF                   0
+#define USB_COUNT_SOF                   1
 /* define this macro to 1 if you need the global variable "usbSofCount" which
  * counts SOF packets. This feature requires that the hardware interrupt is
  * connected to D- instead of D+.
@@ -352,8 +352,8 @@ section at the end of this file).
 #define USB_CFG_DESCR_PROPS_STRING_VENDOR           0
 #define USB_CFG_DESCR_PROPS_STRING_PRODUCT          0
 #define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER    0
-//#define USB_CFG_DESCR_PROPS_HID                     USB_PROP_IS_DYNAMIC
-#define USB_CFG_DESCR_PROPS_HID                     0
+#define USB_CFG_DESCR_PROPS_HID                     USB_PROP_IS_DYNAMIC
+//#define USB_CFG_DESCR_PROPS_HID                     0
 #define USB_CFG_DESCR_PROPS_HID_REPORT              USB_PROP_IS_DYNAMIC
 //#define USB_CFG_DESCR_PROPS_HID_REPORT              0
 #define USB_CFG_DESCR_PROPS_UNKNOWN                 0
@@ -375,4 +375,14 @@ section at the end of this file).
 /* #define USB_INTR_PENDING_BIT    INTF0 */
 /* #define USB_INTR_VECTOR         INT0_vect */
 
+/* Set INT1 for D- falling edge to count SOF */
+/* #define USB_INTR_CFG            EICRA */
+#define USB_INTR_CFG_SET        ((1 << ISC11) | (0 << ISC10))
+/* #define USB_INTR_CFG_CLR        0 */
+/* #define USB_INTR_ENABLE         EIMSK */
+#define USB_INTR_ENABLE_BIT     INT1
+/* #define USB_INTR_PENDING        EIFR */
+#define USB_INTR_PENDING_BIT    INTF1
+#define USB_INTR_VECTOR         INT1_vect
+
 #endif /* __usbconfig_h_included__ */
diff --git a/host.c b/host.c
new file mode 100644
index 0000000..65b5ddc
--- /dev/null
+++ b/host.c
@@ -0,0 +1,190 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include <avr/interrupt.h>
+#include "usb_keycodes.h"
+#include "host.h"
+#include "util.h"
+#include "debug.h"
+
+
+#ifdef NKRO_ENABLE
+bool keyboard_nkro = false;
+#endif
+
+static host_driver_t *driver;
+static report_keyboard_t report0;
+static report_keyboard_t report1;
+report_keyboard_t *keyboard_report = &report0;
+report_keyboard_t *keyboard_report_prev = &report1;
+
+
+static inline void add_key_byte(uint8_t code);
+static inline void add_key_bit(uint8_t code);
+
+
+void host_set_driver(host_driver_t *d)
+{
+    driver = d;
+}
+
+host_driver_t *host_get_driver(void)
+{
+    return driver;
+}
+
+uint8_t host_keyboard_leds(void)
+{
+    if (!driver) return 0;
+    return (*driver->keyboard_leds)();
+}
+
+/* keyboard report operations */
+void host_add_key(uint8_t key)
+{
+#ifdef NKRO_ENABLE
+    if (keyboard_nkro) {
+        add_key_bit(key);
+        return;
+    }
+#endif
+    add_key_byte(key);
+}
+
+void host_add_mod_bit(uint8_t mod)
+{
+    keyboard_report->mods |= mod;
+}
+
+void host_set_mods(uint8_t mods)
+{
+    keyboard_report->mods = mods;
+}
+
+void host_add_code(uint8_t code)
+{
+    if (IS_MOD(code)) {
+        host_add_mod_bit(MOD_BIT(code));
+    } else {
+        host_add_key(code);
+    }
+}
+
+void host_swap_keyboard_report(void)
+{
+    uint8_t sreg = SREG;
+    cli();
+    report_keyboard_t *tmp = keyboard_report_prev;
+    keyboard_report_prev = keyboard_report;
+    keyboard_report = tmp;
+    SREG = sreg;
+}
+
+void host_clear_keyboard_report(void)
+{
+    keyboard_report->mods = 0;
+    for (int8_t i = 0; i < REPORT_KEYS; i++) {
+        keyboard_report->keys[i] = 0;
+    }
+}
+
+uint8_t host_has_anykey(void)
+{
+    uint8_t cnt = 0;
+    for (int i = 0; i < REPORT_KEYS; i++) {
+        if (keyboard_report->keys[i])
+            cnt++;
+    }
+    return cnt;
+}
+
+uint8_t host_get_first_key(void)
+{
+#ifdef NKRO_ENABLE
+    if (keyboard_nkro) {
+        uint8_t i = 0;
+        for (; i < REPORT_KEYS && !keyboard_report->keys[i]; i++)
+            ;
+        return i<<3 | biton(keyboard_report->keys[i]);
+    }
+#endif
+    return keyboard_report->keys[0];
+}
+
+
+void host_send_keyboard_report(void)
+{
+    if (!driver) return;
+    (*driver->send_keyboard)(keyboard_report);
+}
+
+void host_mouse_send(report_mouse_t *report)
+{
+    if (!driver) return;
+    (*driver->send_mouse)(report);
+}
+
+void host_system_send(uint16_t data)
+{
+    if (!driver) return;
+    (*driver->send_consumer)(data);
+}
+
+void host_consumer_send(uint16_t data)
+{
+    // TODO: this is needed?
+    static uint16_t last_data = 0;
+    if (data == last_data) return;
+    last_data = data;
+
+    if (!driver) return;
+    (*driver->send_consumer)(data);
+}
+
+
+static inline void add_key_byte(uint8_t code)
+{
+    // TODO: fix ugly code
+    int8_t i = 0;
+    int8_t empty = -1;
+    for (; i < REPORT_KEYS; i++) {
+        if (keyboard_report_prev->keys[i] == code) {
+            keyboard_report->keys[i] = code;
+            break;
+        }
+        if (empty == -1 &&
+                keyboard_report_prev->keys[i] == 0 &&
+                keyboard_report->keys[i] == 0) {
+            empty = i;
+        }
+    }
+    if (i == REPORT_KEYS) {
+        if (empty != -1) {
+            keyboard_report->keys[empty] = code;
+        }
+    }
+}
+
+static inline void add_key_bit(uint8_t code)
+{
+    if ((code>>3) < REPORT_KEYS) {
+        keyboard_report->keys[code>>3] |= 1<<(code&7);
+    } else {
+        debug("add_key_bit: can't add: "); phex(code); debug("\n");
+    }
+}
diff --git a/host.h b/host.h
index bdbd7db..06f1311 100644
--- a/host.h
+++ b/host.h
@@ -19,88 +19,11 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define HOST_H
 
 #include <stdint.h>
+#include "report.h"
+#include "host_driver.h"
 
 
-/* report id */
-#define REPORT_ID_MOUSE     1
-#define REPORT_ID_SYSTEM    2
-#define REPORT_ID_CONSUMER  3
-
-/* keyboard Modifiers in boot protocol report */
-#define BIT_LCTRL   (1<<0)
-#define BIT_LSHIFT  (1<<1)
-#define BIT_LALT    (1<<2)
-#define BIT_LGUI    (1<<3)
-#define BIT_RCTRL   (1<<4)
-#define BIT_RSHIFT  (1<<5)
-#define BIT_RALT    (1<<6)
-#define BIT_RGUI    (1<<7)
-#define BIT_LCTL BIT_LCTRL
-#define BIT_RCTL BIT_RCTRL
-#define BIT_LSFT BIT_LSHIFT
-#define BIT_RSFT BIT_RSHIFT
-
-/* mouse buttons */
-#define MOUSE_BTN1 (1<<0)
-#define MOUSE_BTN2 (1<<1)
-#define MOUSE_BTN3 (1<<2)
-#define MOUSE_BTN4 (1<<3)
-#define MOUSE_BTN5 (1<<4)
-
-// Consumer Page(0x0C)
-#define AUDIO_MUTE              0x00E2
-#define AUDIO_VOL_UP            0x00E9
-#define AUDIO_VOL_DOWN          0x00EA
-#define TRANSPORT_NEXT_TRACK    0x00B5
-#define TRANSPORT_PREV_TRACK    0x00B6
-#define TRANSPORT_STOP          0x00B7
-#define TRANSPORT_PLAY_PAUSE    0x00CD
-#define AL_CC_CONFIG            0x0183
-#define AL_EMAIL                0x018A
-#define AL_CALCULATOR           0x0192
-#define AL_LOCAL_BROWSER        0x0194
-#define AC_SEARCH               0x0221
-#define AC_HOME                 0x0223
-#define AC_BACK                 0x0224
-#define AC_FORWARD              0x0225
-#define AC_STOP                 0x0226
-#define AC_REFRESH              0x0227
-#define AC_BOOKMARKS            0x022A
-
-// Generic Desktop Page(0x01)
-#define SYSTEM_POWER_DOWN       0x0081
-#define SYSTEM_SLEEP            0x0082
-#define SYSTEM_WAKE_UP          0x0083
-
-
-#if defined(HOST_PJRC)
-#   include "usb.h"
-#   if defined(KBD2_REPORT_KEYS) && KBD2_REPORT_KEYS > KBD_REPORT_KEYS
-#       define REPORT_KEYS KBD2_REPORT_KEYS
-#   else
-#       define REPORT_KEYS KBD_REPORT_KEYS
-#   endif
-#elif defined(HOST_VUSB)
-#   define REPORT_KEYS 6
-#endif
-
-typedef struct {
-    uint8_t mods;
-    uint8_t rserved;
-    uint8_t keys[REPORT_KEYS];
-} report_keyboard_t;
-
-typedef struct {
-    uint8_t report_id;
-    uint8_t buttons;
-    int8_t x;
-    int8_t y;
-    int8_t v;
-    int8_t h;
-} report_mouse_t;
-
-
-#ifdef USB_NKRO_ENABLE
+#ifdef NKRO_ENABLE
 extern bool keyboard_nkro;
 #endif
 
@@ -108,6 +31,8 @@ extern report_keyboard_t *keyboard_report;
 extern report_keyboard_t *keyboard_report_prev;
 
 
+void host_set_driver(host_driver_t *driver);
+host_driver_t *host_get_driver(void);
 uint8_t host_keyboard_leds(void);
 
 /* keyboard report operations */
@@ -122,12 +47,8 @@ uint8_t host_get_first_key(void);
 
 
 void host_send_keyboard_report(void);
-#if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE)
 void host_mouse_send(report_mouse_t *report);
-#endif
-#ifdef USB_EXTRA_ENABLE
 void host_system_send(uint16_t data);
 void host_consumer_send(uint16_t data);
-#endif
 
 #endif
diff --git a/host_driver.h b/host_driver.h
new file mode 100644
index 0000000..edb9e5d
--- /dev/null
+++ b/host_driver.h
@@ -0,0 +1,33 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef HOST_DRIVER_H
+#define HOST_DRIVER_H
+
+#include <stdint.h>
+#include "report.h"
+
+
+typedef struct {
+    uint8_t (*keyboard_leds)(void);
+    void (*send_keyboard)(report_keyboard_t *);
+    void (*send_mouse)(report_mouse_t *);
+    void (*send_system)(uint16_t);
+    void (*send_consumer)(uint16_t);
+} host_driver_t;
+
+#endif
diff --git a/iwrap.mk b/iwrap.mk
new file mode 100644
index 0000000..ea4a6e9
--- /dev/null
+++ b/iwrap.mk
@@ -0,0 +1,10 @@
+OPT_DEFS += -DHOST_IWRAP
+
+SRC +=	iwrap.c \
+	suart.S \
+	sendchar_uart.c \
+	uart.c
+
+
+# Search Path
+VPATH += $(COMMON_DIR)/iwrap
diff --git a/iwrap/iWRAP.txt b/iwrap/iWRAP.txt
new file mode 100644
index 0000000..2a062d9
--- /dev/null
+++ b/iwrap/iWRAP.txt
@@ -0,0 +1,376 @@
+Bulegiga WT12
+=============
+WT12 is a bluetooth module from Bluegiga. http://www.bluegiga.com/
+
+iWRAP
+    higher layer interface for bluetooth firmware
+    communicate with UART
+
+iWRAP HID
+default setting
+    115200  8bit/n/1/n
+
+
+TODO
+----
+KiCAD circuit/PCB design
+power saving
+    AVR sleep(15ms by watch dog timer)
+    WT12 sleep
+    measuring current consumption
+    measuring battery life of normal usage/idle/intensive usage
+software reset/bootloarder
+LED indicator(chaging/paring/connecting)
+license confirmation of suart.c
+consumer page is not working
+authenticate method/SSP
+SPP keyboard support
+SPP debug console support
+mouse wheel feature request to Bluegiga
+
+
+Problems
+--------
+power consumption
+no consumer page support(bug?)
+no mouse wheel support
+no paring management
+no interactive auth method
+
+
+UART hardware flow control
+--------------------------
+(iWRAP4 User Guide 9.5)
+Hardware flow control is enabled by default and it should not be disabled unless mandatory, because without the hardware flow control the data transmission may not be reliable.
+If the hardware flow control is enabled from PS-keys, but no flow control is used, the following steps should be implemented in the hardware design:
+- CTS pin must be grounded
+- RTS pin must be left floating
+
+
+Power Saving
+------------
+power consume
+    without opimization: 4hr to shutdown(310mAh)
+    2011/08/25: 9hr(310mAh) SNIFF MASTER sleep/WDTO_120MS
+
+measure current consumption
+    HHKB keyswitch matrix board
+        idle
+        scanning
+    Bluegiga WT12 module
+        SLEEP command
+        deep sleep on/off in config bits
+
+HHKB keyswich
+    how to power off
+        I/O pin configuration when sleeping
+        FET switch for 5V regulator
+
+Bluetooth module
+    power off when in USB mode
+    power off by FET switch
+
+AVR configuration
+    unused pins
+    ADC
+    
+
+
+SET CONTROL CONFIG
+------------------
+    SET CONTROL CONFIG 4810
+    SET CONTROL CONFIG LIST
+    SET CONTROL CONFIG 0000 0000 4910 DEEP_SLEEP KLUDGE INTERACTIVE_PIN UART_LATENCY
+
+    Bit14   UART low latency
+    Bit11   Interactive pairing mode
+    Bit04   Deep sleep
+
+
+Reconnection
+------------
+SET CONTROL AUTOCALL 1124 5000 HID
+    1124    HID service class
+    5000    interval ms
+
+HID profile
+-----------
+This is needed to configure only once.
+    SET PROFILE HID ON
+    RESET
+
+HID class
+---------
+    SET BT CLASS 005C0  // keyboard/mouse combined devie
+
+Pairing Security
+----------------
+Secure Simple Pairing(SSP)
+    SET BT SSP 2 0  // Enables SSP for keyboard and Man-in-the-middle protection
+    SET BT SSP 3 0  // Enables SSP just works mode
+
+for keyboard with SSP
+    SET BT AUTH * 0000
+    SET BT SSP 2 0
+    SET CONTROL CONFIG 800
+    RESET
+
+for keyboard without SSP
+    SET BT AUTH * 0000
+    SET CONTROL CONFIG 800
+    RESET
+
+AUTH
+    AUTH xx:xx:xx:xx:xx:xx?         // Pairing request event
+    AUTH xx:xx:xx:xx:xx:xx  0000
+
+    SSP PASSKEY 78:dd:08:b7:e4:a2 ?
+    SSP PASSKEY 78:dd:08:b7:e4:a2 xxxxx
+    (SSP COMPLETE 78:dd:08:b7:e4:a2 HCI_ERROR_AUTH_FAIL     // failed)
+    RING 0 78:dd:08:b7:e4:a2 11 HID
+
+Connecton
+    RING xx:xx:xx:xx:xx:xx xx HID   // connection event
+
+    KILL xx:xx:xx:xx:xx:xx
+
+Mode
+----
+Command mode
+Data mode
+    Raw mode
+    (Simple mode         not for a real keyboard)
+
+Raw mode
+    Keyboard:
+    0x9f, length(10), 0xa1, 0x01, mods, 0x00, key1, key2, key3, key4, key5, key6
+
+    Mouse:
+    0x9f, length(5), 0xa1, 0x02, buttons, X, Y
+
+    Consumer page:
+    0x9f, length(5), 0xa1, 0x03, bitfield1, bitfield2, bitfield3
+
+    consumer page suage
+    Bitfield 1:
+        0x01 Volume Increment
+        0x02 Volume Decrement
+        0x04 Mute
+        0x08 Play/Pause
+        0x10 Scan Next Track
+        0x20 Scan Previous Track
+        0x40 Stop
+        0x80 Eject
+    Bitfield 2:
+        0x01 Email Reader
+        0x02 Application Control Search
+        0x04 AC Bookmarks
+        0x08 AC Home
+        0x10 AC Back
+        0x20 AC Forward
+        0x40 AC Stop
+        0x80 AC Refresh
+    Bitfield 3:
+        0x01 Application Launch Generic Consumer Control
+        0x02 AL Internet Browser
+        0x04 AL Calculator
+        0x08 AL Terminal Lock / Screensaver
+        0x10 AL Local Machine Browser
+        0x20 AC Minimize
+        0x40 Record
+        0x80 Rewind
+
+
+
+
+
+2011/07/13
+set
+SET BT BDADDR 00:07:80:47:22:14
+SET BT NAME HHKB pro BT
+SET BT CLASS 0005c0
+SET BT AUTH * 0000
+SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP
+SET BT LAP 9e8b33
+SET BT PAGEMODE 4 2000 1
+SET BT PAIR 78:dd:08:b7:e4:a2 a191189cd7e51030ad6a07848ce879bb
+SET BT POWER 3 3 3
+SET BT ROLE 0 f 7d00
+SET BT SNIFF 0 20 1 8
+SET BT SSP 2 1
+SET BT MTU 667
+SET CONTROL AUTOCALL 1124 3000 HID
+SET CONTROL BAUD 38400,8n1
+SET CONTROL CD 00 0
+SET CONTROL ECHO 7
+SET CONTROL ESCAPE 43 00 1
+SET CONTROL GAIN 0 5
+SET CONTROL INIT SET CONTROL MUX 0
+SET CONTROL MSC DTE 00 00 00 00 00 00
+SET CONTROL MUX 1
+SET CONTROL PIO 00 00
+SET CONTROL READY 00
+SET PROFILE HID f HID
+SET
+
+info config
+
+!!! THIS IS BETA RELEASE AND MAY BE USED FOR EVALUATION PURPOSES ONLY !!!
+
+WRAP THOR AI (4.1.0 build 435)
+Copyright (c) 2003-2011 Bluegiga Technologies Inc.
+Compiled on Jun 28 2011 17:19:51, running on WT12-A module, psr v31
+        AVRCP BGIO FTP HFP HFP_AG HID HID_CONSUMER_PAGE HSP LEDS MAP OTA PBAP PIO=0x00fc SSP SUBRATE TEST VOLUME
+        - BOCK3 version 435 (Jun 28 2011 17:19:37) (max acl/sco 7/1)
+        - Bluetooth version 2.1, Power class 2
+        - Loader 4279, firmware 6297 (56-bit encryption), native execution mode
+        - up 0 days, 06:23, 2 connections (pool 2)
+        - User configuration:
+&028a = 0001 0000 0000 0011 0024 0000 0000 0010 0000 0080 0000 0000 0080 005f 009b 0034 00fb 0006
+&028b = 0000 0bb8
+&028d = 0001
+&0295 = 0000 0005 000b 0000 0003 0000 0000 0000 0000 0000 0000
+&0298 = a006
+&0299 = 0000 0000
+&02a3 = 0030 0030 0030 0030
+&02a4 = 009d 0000
+&02a5 = 0053 0045 0054 0020 0043 004f 004e 0054 0052 004f 004c 0020 004d 0055 0058 0020 0030
+&02a7 = 0000 05c0
+&02a8 = 4910 0000 0000
+&02aa = 0004 2000 0001 0033 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+&02ac = 0000 0000 002b 0000 0000 0000 0000 0000 0000 0000 0002 0000 0000 0000 0010 0000 0000 0000 0000 029b 0000 0000 0000 0000
+&02ad = 4848 424b 7020 6f72 4220 0054
+&02b3 = 0005 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003
+&02b7 = 000f 4948 0044
+&02bb = 8000
+READY.
+
+
+
+
+2011/07/07 settings:
+set
+SET BT BDADDR 00:07:80:47:22:14
+SET BT NAME HHKB Pro BT
+SET BT CLASS 0005c0
+SET BT AUTH * 000
+SET BT IDENT BT:47 f000 4.0.0 Bluegiga iWRAP
+SET BT LAP 9e8b33
+SET BT PAGEMODE 4 2000 1
+SET BT PAIR 78:dd:08:b7:e4:a2 9e54d0aabb1b4d73cfccddb1ea4ef2d6
+SET BT POWER 3 3 3
+SET BT ROLE 0 f 7d00
+SET BT SNIFF 0 20 1 8
+SET BT SSP 3 0
+SET BT MTU 667
+SET CONTROL BAUD 38400,8n1
+SET CONTROL CD 00 0
+SET CONTROL ECHO 7
+SET CONTROL ESCAPE 255 00 1
+SET CONTROL GAIN 0 5
+SET CONTROL INIT set control mux 0
+SET CONTROL MSC DTE 00 00 00 00 00 00
+SET CONTROL PREAMP 1 1
+SET CONTROL READY 00
+SET PROFILE HID HID
+SET PROFILE SPP Bluetooth Serial Port
+SET
+
+info config
+WRAP THOR AI (4.0.0 build 317)
+Copyright (c) 2003-2010 Bluegiga Technologies Inc.
+Compiled on Apr 20 2010 16:44:28, running on WT12-A module, psr v31
+        AVRCP FTP PBAP PIO=0x00fc SSP SUBRATE VOLUME
+        - BOCK3 version 317 (Apr 20 2010 16:44:21) (max acl/sco 7/1)
+        - Bluetooth version 2.1, Power class 2
+        - Loader 4279, firmware 6297 (56-bit encryption), native execution mode
+        - up 0 days, 00:00, 0 connections (pool 1)
+        - User configuration:
+&028c = 0001 0020 0000 0001 0008 0000
+&028d = 0000
+&0296 = 0047 0001 f000 0400 6c42 6575 6967 6167 6920 5257 5041
+&0298 = c006
+&02a3 = 0030 0030 0030
+&02a4 = 009d 0000
+&02a5 = 0073 0065 0074 0020 0063 006f 006e 0074 0072 006f 006c 0020 006d 0075 0078 0020 0030
+&02a7 = 0000 05c0
+&02a8 = 0800 0000 0000
+&02ac = 0000 0000 00ff 0000 0000 0000 0000 0000 0000 0000 0002 0000 0000 0000 0010 0000 0000 0000 0000 029b 0000 0000 0000 0000
+&02ad = 4848 424b 5020 6f72 4220 0054
+&02b3 = 0004 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003
+&02b7 = 0000
+&02bb = 6c42 6575 6f74 746f 2068 6553 6972 6c61 5020 726f 0074
+READY.
+
+
+
+2011/08/23:
+SET BT BDADDR 00:07:80:47:22:14
+SET BT NAME HHKB pro BT
+SET BT CLASS 0005c0
+SET BT AUTH * 0000
+SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP
+SET BT LAP 9e8b33
+SET BT PAGEMODE 4 2000 1
+SET BT PAIRCOUNT 4
+SET BT POWER 3 3 3
+SET BT ROLE 1 f 12c0
+SET BT SNIFF 10 2 1 8
+SET BT SSP 3 0
+SET BT MTU 667
+SET CONTROL BAUD 38400,8n1
+SET CONTROL CD 00 0
+SET CONTROL ECHO 7
+SET CONTROL ESCAPE 43 00 1
+SET CONTROL GAIN 0 5
+SET CONTROL INIT SET CONTROL MUX 0
+SET CONTROL MSC DTE 00 00 00 00 00 00
+SET CONTROL MUX 1
+SET CONTROL PIO 00 00
+SET CONTROL READY 00
+SET PROFILE HID 7 HIDKeyboardMouse
+SET
+
+SET CONTROL CONFIG 0000 0004 481e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE DEEP_SLEEP INTERACTIVE_PIN UART_LATENCY 23D_NOKLUDGE
+
+
+
+2011/08/25:
+SET BT BDADDR 00:07:80:47:22:14
+SET BT NAME HHKB pro BT
+SET BT CLASS 0005c0
+
+SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP
+SET BT LAP 9e8b33
+SET BT PAGEMODE 4 2000 1
+SET BT PAIRCOUNT 4
+SET BT PAIR 78:dd:08:b7:e4:a2 0be83335a03fed8ededae42e99554e28
+SET BT POWER 3 3 3
+SET BT ROLE 1 f 12c0
+SET BT SNIFF 100 20 1 8
+SET BT SSP 3 0
+SET BT MTU 667
+SET CONTROL BAUD 38400,8n1
+SET CONTROL CD 00 0
+SET CONTROL ECHO 7
+SET CONTROL ESCAPE - 20 1
+SET CONTROL GAIN 0 5
+SET CONTROL INIT SET CONTROL MUX 0
+SET CONTROL MSC DTE 00 00 00 00 00 00
+SET CONTROL MUX 1
+SET CONTROL PIO 00 00
+SET CONTROL READY 00
+SET PROFILE HID f HIDKeyboardMouse
+SET
+
+
+SET CONTROL CONFIG 0000 0000 490e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE KLUDGE INTERACTIVE_PIN UART_LATENCY
+
+
+2011/09/08:
+SET CONTROL CONFIG 0000 0000 410e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE KLUDGE UART_LATENCY
+
+    Removed INTERACTIVE_PIN to avoid interactive auth and use SET BT AUTH pin(0000).
+
+
+EOF
diff --git a/iwrap/iwrap.c b/iwrap/iwrap.c
new file mode 100644
index 0000000..9c68761
--- /dev/null
+++ b/iwrap/iwrap.c
@@ -0,0 +1,467 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* host driver for Bulegiga iWRAP */
+/* Bluegiga BT12
+ * Connections
+ *    Hardware UART       Software UART            BlueTooth
+ * PC=====UART=======AVR=====SUART====iWRAP(BT12)-----------PC
+ *
+ * - Hardware UART for Debug Console to communicate iWRAP
+ * - Software UART for iWRAP control to send keyboard/mouse data
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "usb_keycodes.h"
+#include "suart.h"
+#include "uart.h"
+#include "report.h"
+#include "host_driver.h"
+#include "iwrap.h"
+#include "print.h"
+
+
+/* iWRAP MUX mode utils. 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf) */
+#define MUX_HEADER(LINK, LENGTH) do { \
+    xmit(0xbf);     /* SOF    */ \
+    xmit(LINK);     /* Link   */ \
+    xmit(0x00);     /* Flags  */ \
+    xmit(LENGTH);   /* Length */ \
+} while (0)
+#define MUX_FOOTER(LINK) xmit(LINK^0xff)
+
+
+static uint8_t connected = 0;
+//static uint8_t channel = 1;
+
+/* iWRAP buffer */
+#define MUX_BUF_SIZE 64
+static char buf[MUX_BUF_SIZE];
+static uint8_t snd_pos = 0;
+
+#define MUX_RCV_BUF_SIZE 256
+static char rcv_buf[MUX_RCV_BUF_SIZE];
+static uint8_t rcv_head = 0;
+static uint8_t rcv_tail = 0;
+
+
+/* receive buffer */
+static void rcv_enq(char c)
+{
+    uint8_t next = (rcv_head + 1) % MUX_RCV_BUF_SIZE;
+    if (next != rcv_tail) {
+        rcv_buf[rcv_head] = c;
+        rcv_head = next;
+    }
+}
+
+static char rcv_deq(void)
+{
+    char c = 0;
+    if (rcv_head != rcv_tail) {
+        c = rcv_buf[rcv_tail++];
+        rcv_tail %= MUX_RCV_BUF_SIZE;
+    }
+    return c;
+}
+
+/*
+static char rcv_peek(void)
+{
+    if (rcv_head == rcv_tail)
+        return 0;
+    return rcv_buf[rcv_tail];
+}
+*/
+
+static void rcv_clear(void)
+{
+    rcv_tail = rcv_head = 0;
+}
+
+/* iWRAP response */
+ISR(PCINT1_vect, ISR_BLOCK) // recv() runs away in case of ISR_NOBLOCK
+{
+    if ((SUART_IN_PIN & (1<<SUART_IN_BIT)))
+        return;
+
+    static volatile uint8_t mux_state = 0xff;
+    static volatile uint8_t mux_link = 0xff;
+    uint8_t c = recv();
+    switch (mux_state) {
+        case 0xff: // SOF
+            if (c == 0xbf)
+                mux_state--;
+            break;
+        case 0xfe: // Link
+            mux_state--;
+            mux_link = c;
+            break;
+        case 0xfd: // Flags
+            mux_state--;
+            break;
+        case 0xfc: // Length
+            mux_state = c;
+            break;
+        case 0x00:
+            mux_state = 0xff;
+            mux_link = 0xff;
+            break;
+        default:
+            if (mux_state--) {
+                uart_putchar(c);
+                rcv_enq(c);
+            }
+    }
+}
+
+
+/*------------------------------------------------------------------*
+ * iWRAP communication
+ *------------------------------------------------------------------*/
+void iwrap_init(void)
+{
+    // reset iWRAP if in already MUX mode after AVR software-reset
+    iwrap_send("RESET");
+    iwrap_mux_send("RESET");
+    _delay_ms(3000);
+    iwrap_send("\r\nSET CONTROL MUX 1\r\n");
+    _delay_ms(500);
+    iwrap_check_connection();
+}
+
+void iwrap_mux_send(const char *s)
+{
+    rcv_clear();
+    MUX_HEADER(0xff, strlen((char *)s));
+    iwrap_send(s);
+    MUX_FOOTER(0xff);
+}
+
+void iwrap_send(const char *s)
+{
+    while (*s)
+        xmit(*s++);
+}
+
+/* send buffer */
+void iwrap_buf_add(uint8_t c)
+{
+    // need space for '\0'
+    if (snd_pos < MUX_BUF_SIZE-1)
+        buf[snd_pos++] = c;
+}
+
+void iwrap_buf_del(void)
+{
+    if (snd_pos)
+        snd_pos--;
+}
+
+void iwrap_buf_send(void)
+{
+    buf[snd_pos] = '\0';
+    snd_pos = 0;
+    iwrap_mux_send(buf);
+}
+
+void iwrap_call(void)
+{
+    char *p;
+
+    iwrap_mux_send("SET BT PAIR");
+    _delay_ms(500);
+
+    p = rcv_buf + rcv_tail;
+    while (!strncmp(p, "SET BT PAIR", 11)) {
+        p += 7;
+        strncpy(p, "CALL", 4);
+        strncpy(p+22, " 11 HID\n\0", 9);
+        print_S(p);
+        iwrap_mux_send(p);
+        // TODO: skip to next line
+        p += 57;
+
+        DEBUG_LED_CONFIG;
+        DEBUG_LED_ON;
+        _delay_ms(500);
+        DEBUG_LED_OFF;
+        _delay_ms(500);
+        DEBUG_LED_ON;
+        _delay_ms(500);
+        DEBUG_LED_OFF;
+        _delay_ms(500);
+        DEBUG_LED_ON;
+        _delay_ms(500);
+        DEBUG_LED_OFF;
+        _delay_ms(500);
+        DEBUG_LED_ON;
+        _delay_ms(500);
+        DEBUG_LED_OFF;
+        _delay_ms(500);
+        DEBUG_LED_ON;
+        _delay_ms(500);
+        DEBUG_LED_OFF;
+        _delay_ms(500);
+    }
+    iwrap_check_connection();
+}
+
+void iwrap_kill(void)
+{
+    char c;
+    iwrap_mux_send("LIST");
+    _delay_ms(500);
+
+    while ((c = rcv_deq()) && c != '\n') ;
+    if (strncmp(rcv_buf + rcv_tail, "LIST ", 5)) {
+        print("no connection to kill.\n");
+        return;
+    }
+    // skip 10 'space' chars
+    for (uint8_t i = 10; i; i--)
+        while ((c = rcv_deq()) && c != ' ') ;
+
+    char *p = rcv_buf + rcv_tail - 5;
+    strncpy(p, "KILL ", 5);
+    strncpy(p + 22, "\n\0", 2);
+    print_S(p);
+    iwrap_mux_send(p);
+    _delay_ms(500);
+
+    iwrap_check_connection();
+}
+
+void iwrap_unpair(void)
+{
+    iwrap_mux_send("SET BT PAIR");
+    _delay_ms(500);
+
+    char *p = rcv_buf + rcv_tail;
+    if (!strncmp(p, "SET BT PAIR", 11)) {
+        strncpy(p+29, "\n\0", 2);
+        print_S(p);
+        iwrap_mux_send(p);
+    }
+}
+
+void iwrap_sleep(void)
+{
+    iwrap_mux_send("SLEEP");
+}
+
+void iwrap_sniff(void)
+{
+}
+
+void iwrap_subrate(void)
+{
+}
+
+bool iwrap_failed(void)
+{
+    if (strncmp(rcv_buf, "SYNTAX ERROR", 12))
+        return true;
+    else
+        return false;
+}
+
+uint8_t iwrap_connected(void)
+{
+    return connected;
+}
+
+uint8_t iwrap_check_connection(void)
+{
+    iwrap_mux_send("LIST");
+    _delay_ms(100);
+
+    if (strncmp(rcv_buf, "LIST ", 5) || !strncmp(rcv_buf, "LIST 0", 6))
+        connected = 0;
+    else
+        connected = 1;
+    return connected;
+}
+
+
+/*------------------------------------------------------------------*
+ * Host driver
+ *------------------------------------------------------------------*/
+static uint8_t keyboard_leds(void);
+static void send_keyboard(report_keyboard_t *report);
+static void send_mouse(report_mouse_t *report);
+static void send_system(uint16_t data);
+static void send_consumer(uint16_t data);
+
+static host_driver_t driver = {
+        keyboard_leds,
+        send_keyboard,
+        send_mouse,
+        send_system,
+        send_consumer
+};
+
+host_driver_t *iwrap_driver(void)
+{
+    return &driver;
+}
+
+static uint8_t keyboard_leds(void) {
+    return 0;
+}
+
+static void send_keyboard(report_keyboard_t *report)
+{
+    if (!iwrap_connected() && !iwrap_check_connection()) return;
+    MUX_HEADER(0x01, 0x0c);
+    // HID raw mode header
+    xmit(0x9f);
+    xmit(0x0a); // Length
+    xmit(0xa1); // keyboard report
+    xmit(0x01);
+    xmit(report->mods);
+    xmit(0x00); // reserved byte(always 0)
+    xmit(report->keys[0]);
+    xmit(report->keys[1]);
+    xmit(report->keys[2]);
+    xmit(report->keys[3]);
+    xmit(report->keys[4]);
+    xmit(report->keys[5]);
+    MUX_FOOTER(0x01);
+}
+
+static void send_mouse(report_mouse_t *report)
+{
+#if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE)
+    if (!iwrap_connected() && !iwrap_check_connection()) return;
+    MUX_HEADER(0x01, 0x07);
+    // HID raw mode header
+    xmit(0x9f);
+    xmit(0x05); // Length
+    xmit(0xa1); // mouse report
+    xmit(0x02);
+    xmit(report->buttons);
+    xmit(report->x);
+    xmit(report->y);
+    MUX_FOOTER(0x01);
+#endif
+}
+
+static void send_system(uint16_t data)
+{
+    /* not supported */
+}
+
+static void send_consumer(uint16_t data)
+{
+#ifdef EXTRAKEY_ENABLE
+    static uint16_t last_data = 0;
+    uint8_t bits1 = 0;
+    uint8_t bits2 = 0;
+    uint8_t bits3 = 0;
+
+    if (!iwrap_connected() && !iwrap_check_connection()) return;
+    if (data == last_data) return;
+    last_data = data;
+
+    // 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf)
+    switch (data) {
+        case AUDIO_VOL_UP:
+            bits1 = 0x01;
+            break;
+        case AUDIO_VOL_DOWN:
+            bits1 = 0x02;
+            break;
+        case AUDIO_MUTE:
+            bits1 = 0x04;
+            break;
+        case TRANSPORT_PLAY_PAUSE:
+            bits1 = 0x08;
+            break;
+        case TRANSPORT_NEXT_TRACK:
+            bits1 = 0x10;
+            break;
+        case TRANSPORT_PREV_TRACK:
+            bits1 = 0x20;
+            break;
+        case TRANSPORT_STOP:
+            bits1 = 0x40;
+            break;
+        case TRANSPORT_EJECT:
+            bits1 = 0x80;
+            break;
+        case AL_EMAIL:
+            bits2 = 0x01;
+            break;
+        case AC_SEARCH:
+            bits2 = 0x02;
+            break;
+        case AC_BOOKMARKS:
+            bits2 = 0x04;
+            break;
+        case AC_HOME:
+            bits2 = 0x08;
+            break;
+        case AC_BACK:
+            bits2 = 0x10;
+            break;
+        case AC_FORWARD:
+            bits2 = 0x20;
+            break;
+        case AC_STOP:
+            bits2 = 0x40;
+            break;
+        case AC_REFRESH:
+            bits2 = 0x80;
+            break;
+        case AL_CC_CONFIG:
+            bits3 = 0x01;
+            break;
+        case AL_CALCULATOR:
+            bits3 = 0x04;
+            break;
+        case AL_LOCK:
+            bits3 = 0x08;
+            break;
+        case AL_LOCAL_BROWSER:
+            bits3 = 0x10;
+            break;
+        case AC_MINIMIZE:
+            bits3 = 0x20;
+            break;
+        case TRANSPORT_RECORD:
+            bits3 = 0x40;
+            break;
+        case TRANSPORT_REWIND:
+            bits3 = 0x80;
+            break;
+    }
+
+    MUX_HEADER(0x01, 0x07);
+    xmit(0x9f);
+    xmit(0x05); // Length
+    xmit(0xa1); // consumer report
+    xmit(0x03);
+    xmit(bits1);
+    xmit(bits2);
+    xmit(bits3);
+    MUX_FOOTER(0x01);
+#endif
+}
diff --git a/iwrap/iwrap.h b/iwrap/iwrap.h
new file mode 100644
index 0000000..ffaad93
--- /dev/null
+++ b/iwrap/iwrap.h
@@ -0,0 +1,49 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef IWRAP_H
+#define IWRAP_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "host_driver.h"
+
+
+/* enable iWRAP MUX mode */
+#define MUX_MODE
+
+
+host_driver_t *iwrap_driver(void);
+
+void iwrap_init(void);
+void iwrap_send(const char *s);
+void iwrap_mux_send(const char *s);
+void iwrap_buf_send(void);
+void iwrap_buf_add(uint8_t c);
+void iwrap_buf_del(void);
+
+void iwrap_call(void);
+void iwrap_kill(void);
+void iwrap_unpair(void);
+void iwrap_sleep(void);
+void iwrap_sniff(void);
+void iwrap_subrate(void);
+bool iwrap_failed(void);
+uint8_t iwrap_connected(void);
+uint8_t iwrap_check_connection(void);
+
+#endif
diff --git a/iwrap/main.c b/iwrap/main.c
new file mode 100644
index 0000000..a552afb
--- /dev/null
+++ b/iwrap/main.c
@@ -0,0 +1,378 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <stdint.h>
+#include <avr/interrupt.h>
+#include <avr/io.h>
+//#include <avr/wdt.h>
+#include "wd.h" // in order to use watchdog in interrupt mode
+#include <avr/sleep.h>
+#include <util/delay.h>
+#include <avr/power.h>
+#include "keyboard.h"
+#include "matrix.h"
+#include "host.h"
+#include "iwrap.h"
+#ifdef HOST_VUSB
+#   include "vusb.h"
+#   include "usbdrv.h"
+#endif
+#include "uart.h"
+#include "suart.h"
+#include "timer.h"
+#include "debug.h"
+#include "usb_keycodes.h"
+#include "command.h"
+
+
+static void sleep(uint8_t term);
+static bool console(void);
+static uint8_t console_command(uint8_t c);
+static uint8_t key2asc(uint8_t key);
+
+
+/*
+static void set_prr(void)
+{
+    power_adc_disable();
+    power_spi_disable();
+    power_twi_disable();
+#ifndef TIMER_H
+    //power_timer0_disable(); // used in timer.c
+#endif
+    power_timer1_disable();
+    power_timer2_disable();
+}
+*/
+
+/*
+static void pullup_pins(void)
+{
+    // DDRs are set to 0(input) by default.
+#ifdef PORTA
+    PORTA = 0xFF;
+#endif
+    PORTB = 0xFF;
+    PORTC = 0xFF;
+    PORTD = 0xFF;
+#ifdef PORTE
+    PORTE = 0xFF;
+#endif
+#ifdef PORTE
+    PORTF = 0xFF;
+#endif
+}
+*/
+
+
+#ifdef HOST_VUSB
+static void disable_vusb(void)
+{
+    // disable interrupt & disconnect to prevent host from enumerating
+    USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT);
+    usbDeviceDisconnect();
+}
+
+static void enable_vusb(void)
+{
+    USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);
+    usbDeviceConnect();
+}
+
+static void init_vusb(void)
+{
+    uint8_t i = 0;
+
+    usbInit();
+    disable_vusb();
+    /* fake USB disconnect for > 250 ms */
+    while(--i){
+        _delay_ms(1);
+    }
+    enable_vusb();
+}
+#endif
+
+void change_driver(host_driver_t *driver)
+{
+    host_clear_keyboard_report();
+    host_swap_keyboard_report();
+    host_clear_keyboard_report();
+    host_send_keyboard_report();
+    _delay_ms(1000);
+    host_set_driver(driver);
+}
+
+
+static bool sleeping = false;
+static bool insomniac = false;   // TODO: should be false for power saving
+static uint16_t last_timer = 0;
+
+int main(void)
+{
+    MCUSR = 0;
+    clock_prescale_set(clock_div_1);
+    WD_SET(WD_OFF);
+
+    // power saving: the result is worse than nothing... why?
+    //pullup_pins();
+    //set_prr();
+
+    print_enable = true;
+    debug_enable = false;
+
+#ifdef HOST_VUSB
+    disable_vusb();
+#endif
+    uart_init(115200);
+    keyboard_init();
+    print("\nSend BREAK for UART Console Commands.\n");
+
+    // TODO: move to iWRAP/suart file
+    print("suart init\n");
+    // suart init
+    // PC4: Tx Output IDLE(Hi)
+    PORTC |= (1<<4);
+    DDRC  |= (1<<4);
+    // PC5: Rx Input(pull-up)
+    PORTC |= (1<<5);
+    DDRC  &= ~(1<<5);
+    // suart receive interrut(PC5/PCINT13)
+    PCMSK1 = 0b00100000;
+    PCICR  = 0b00000010;
+
+    host_set_driver(iwrap_driver());
+
+    print("iwrap_init()\n");
+    iwrap_init();
+    iwrap_call();
+
+    last_timer = timer_read();
+    while (true) {
+#ifdef HOST_VUSB
+        if (host_get_driver() == vusb_driver())
+            usbPoll();
+#endif
+        keyboard_proc();
+#ifdef HOST_VUSB
+        if (host_get_driver() == vusb_driver())
+            vusb_transfer_keyboard();
+#endif
+        if (matrix_is_modified() || console()) {
+            last_timer = timer_read();
+            sleeping = false;
+        } else if (!sleeping && timer_elapsed(last_timer) > 4000) {
+            sleeping = true;
+            iwrap_check_connection();
+        }
+
+        if (host_get_driver() == iwrap_driver()) {
+            if (sleeping && !insomniac) {
+                _delay_ms(1);   // wait for UART to send
+                iwrap_sleep();
+                sleep(WDTO_60MS);
+            }
+        }
+    }
+}
+
+static void sleep(uint8_t term)
+{
+    WD_SET(WD_IRQ, term);
+
+    cli();
+    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
+    sleep_enable();
+    sleep_bod_disable();
+    sei();
+    sleep_cpu();
+    sleep_disable();
+
+    WD_SET(WD_OFF);
+}
+
+ISR(WDT_vect)
+{
+    // wake up
+}
+
+static bool console(void)
+{
+        // Send to Bluetoot module WT12
+        static bool breaked = false;
+        if (!uart_available())
+            return false;
+        else {
+            uint8_t c;
+            c = uart_getchar();
+            uart_putchar(c);
+            switch (c) {
+                case 0x00: // BREAK signal
+                    if (!breaked) {
+                        print("break(? for help): ");
+                        breaked = true;
+                    }
+                    break;
+                case '\r':
+                    uart_putchar('\n');
+                    iwrap_buf_send();
+                    break;
+                case '\b':
+                    iwrap_buf_del();
+                    break;
+                default:
+                    if (breaked) {
+                        print("\n");
+                        console_command(c);
+                        breaked = false;
+                    } else {
+                        iwrap_buf_add(c);
+                    }
+                    break;
+            }
+            return true;
+        }
+}
+
+uint8_t command_extra()
+{
+    return console_command(key2asc(host_get_first_key()));
+}
+
+static uint8_t console_command(uint8_t c)
+{
+    switch (c) {
+        case 'h':
+        case '?':
+            print("\nCommands for Bluetooth(WT12/iWRAP):\n");
+            print("r: reset. software reset by watchdog\n");
+            print("i: insomniac. prevent KB from sleeping\n");
+            print("c: iwrap_call. CALL for BT connection.\n");
+#ifdef HOST_VUSB
+            print("u: USB mode. switch to USB.\n");
+            print("w: BT mode. switch to Bluetooth.\n");
+#endif
+            print("k: kill first connection.\n");
+            print("Del: unpair first pairing.\n");
+            print("\n");
+            return 0;
+        case 'r':
+            print("reset\n");
+            WD_AVR_RESET();
+            return 1;
+        case 'i':
+            insomniac = !insomniac;
+            if (insomniac)
+                print("insomniac\n");
+            else
+                print("not insomniac\n");
+            return 1;
+        case 'c':
+            print("iwrap_call()\n");
+            iwrap_call();
+            return 1;
+#ifdef HOST_VUSB
+        case 'u':
+            print("USB mode\n");
+            init_vusb();
+            change_driver(vusb_driver());
+            //iwrap_kill();
+            //iwrap_sleep();
+            // disable suart receive interrut(PC5/PCINT13)
+            PCMSK1 &= ~(0b00100000);
+            PCICR  &= ~(0b00000010);
+            return 1;
+        case 'w':
+            print("iWRAP mode\n");
+            change_driver(iwrap_driver());
+            disable_vusb();
+            // enable suart receive interrut(PC5/PCINT13)
+            PCMSK1 |= 0b00100000;
+            PCICR  |= 0b00000010;
+            return 1;
+#endif
+        case 'k':
+            print("kill\n");
+            iwrap_kill();
+            return 1;
+        case 0x7F:  // DELETE
+            print("unpair\n");
+            iwrap_unpair();
+            return 1;
+    }
+    return 0;
+}
+
+// convert keycode into ascii charactor
+static uint8_t key2asc(uint8_t key)
+{
+    switch (key) {
+        case KB_A: return 'a';
+        case KB_B: return 'b';
+        case KB_C: return 'c';
+        case KB_D: return 'd';
+        case KB_E: return 'e';
+        case KB_F: return 'f';
+        case KB_G: return 'g';
+        case KB_H: return 'h';
+        case KB_I: return 'i';
+        case KB_J: return 'j';
+        case KB_K: return 'k';
+        case KB_L: return 'l';
+        case KB_M: return 'm';
+        case KB_N: return 'n';
+        case KB_O: return 'o';
+        case KB_P: return 'p';
+        case KB_Q: return 'q';
+        case KB_R: return 'r';
+        case KB_S: return 's';
+        case KB_T: return 't';
+        case KB_U: return 'u';
+        case KB_V: return 'v';
+        case KB_W: return 'w';
+        case KB_X: return 'x';
+        case KB_Y: return 'y';
+        case KB_Z: return 'z';
+        case KB_1: return '1';
+        case KB_2: return '2';
+        case KB_3: return '3';
+        case KB_4: return '4';
+        case KB_5: return '5';
+        case KB_6: return '6';
+        case KB_7: return '7';
+        case KB_8: return '8';
+        case KB_9: return '9';
+        case KB_0: return '0';
+        case KB_ENTER: return '\n';
+        case KB_ESCAPE: return 0x1B;
+        case KB_BSPACE: return '\b';
+        case KB_TAB: return '\t';
+        case KB_SPACE: return ' ';
+        case KB_MINUS: return '-';
+        case KB_EQUAL: return '=';
+        case KB_LBRACKET: return '[';
+        case KB_RBRACKET: return ']';
+        case KB_BSLASH: return '\\';
+        case KB_NONUS_HASH: return '\\';
+        case KB_SCOLON: return ';';
+        case KB_QUOTE: return '\'';
+        case KB_GRAVE: return '`';
+        case KB_COMMA: return ',';
+        case KB_DOT: return '.';
+        case KB_SLASH: return '/';
+        default: return 0x00;
+    }
+}
diff --git a/iwrap/suart.S b/iwrap/suart.S
new file mode 100644
index 0000000..1b02909
--- /dev/null
+++ b/iwrap/suart.S
@@ -0,0 +1,156 @@
+;---------------------------------------------------------------------------;
+; Software implemented UART module                                          ;
+; (C)ChaN, 2005 (http://elm-chan.org/)                                      ;
+;---------------------------------------------------------------------------;
+; Bit rate settings:
+;
+;            1MHz  2MHz  4MHz  6MHz  8MHz  10MHz  12MHz  16MHz  20MHz
+;   2.4kbps   138     -     -     -     -      -      -      -      -
+;   4.8kbps    68   138     -     -     -      -      -      -      -
+;   9.6kbps    33    68   138   208     -      -      -      -      -
+;  19.2kbps     -    33    68   102   138    173    208      -      -
+;  38.4kbps     -     -    33    50    68     85    102    138    172
+;  57.6kbps     -     -    21    33    44     56     68     91    114
+; 115.2kbps     -     -     -     -    21     27     33     44     56
+
+.nolist
+#include <avr/io.h>
+.list
+
+#define	BPS	102 	/* Bit delay. (see above table) */
+#define	BIDIR	0	/* 0:Separated Tx/Rx, 1:Shared Tx/Rx */
+
+#define	OUT_1		sbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT	/* Output 1 */
+#define	OUT_0		cbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT	/* Output 0 */
+#define	SKIP_IN_1	sbis _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT	/* Skip if 1 */
+#define	SKIP_IN_0	sbic _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT	/* Skip if 0 */
+
+
+
+#ifdef SPM_PAGESIZE
+.macro	_LPMI	reg
+	lpm	\reg, Z+
+.endm
+.macro	_MOVW	dh,dl, sh,sl
+	movw	\dl, \sl
+.endm
+#else
+.macro	_LPMI	reg
+	lpm
+	mov	\reg, r0
+	adiw	ZL, 1
+.endm
+.macro	_MOVW	dh,dl, sh,sl
+	mov	\dl, \sl
+	mov	\dh, \sh
+.endm
+#endif
+
+
+
+;---------------------------------------------------------------------------;
+; Transmit a byte in serial format of N81
+;
+;Prototype: void xmit (uint8_t data);
+;Size: 16 words
+
+.global xmit
+.func xmit
+xmit:
+#if BIDIR
+	ldi	r23, BPS-1	;Pre-idle time for bidirectional data line
+5:	dec	r23     	;
+	brne	5b		;/
+#endif
+	in	r0, _SFR_IO_ADDR(SREG)	;Save flags
+
+	com	r24		;C = start bit
+	ldi	r25, 10		;Bit counter
+	cli			;Start critical section
+
+1:	ldi	r23, BPS-1	;----- Bit transferring loop 
+2:	dec	r23     	;Wait for a bit time
+	brne	2b		;/
+	brcs	3f		;MISO = bit to be sent
+	OUT_1			;
+3:	brcc	4f		;
+	OUT_0			;/
+4:	lsr	r24     	;Get next bit into C
+	dec	r25     	;All bits sent?
+	brne	1b	     	;  no, coutinue
+
+	out	_SFR_IO_ADDR(SREG), r0	;End of critical section
+	ret
+.endfunc
+
+
+
+;---------------------------------------------------------------------------;
+; Receive a byte
+;
+;Prototype: uint8_t rcvr (void);
+;Size: 19 words
+
+.global rcvr
+.func rcvr
+rcvr:
+	in	r0, _SFR_IO_ADDR(SREG)	;Save flags
+
+	ldi	r24, 0x80	;Receiving shift reg
+	cli			;Start critical section
+
+1:	SKIP_IN_1		;Wait for idle
+	rjmp	1b
+2:	SKIP_IN_0		;Wait for start bit
+	rjmp	2b
+	ldi	r25, BPS/2	;Wait for half bit time
+3:	dec	r25
+	brne	3b
+
+4:	ldi	r25, BPS	;----- Bit receiving loop
+5:	dec	r25     	;Wait for a bit time
+	brne	5b		;/
+	lsr	r24     	;Next bit
+	SKIP_IN_0		;Get a data bit into r24.7
+	ori	r24, 0x80
+	brcc	4b	     	;All bits received?  no, continue
+
+	out	_SFR_IO_ADDR(SREG), r0	;End of critical section
+	ret
+.endfunc
+
+
+; Not wait for start bit. This should be called after detecting start bit.
+.global recv
+.func recv
+recv:
+	in	r0, _SFR_IO_ADDR(SREG)	;Save flags
+
+	ldi	r24, 0x80	;Receiving shift reg
+	cli			;Start critical section
+
+;1:	SKIP_IN_1		;Wait for idle
+;	rjmp	1b
+;2:	SKIP_IN_0		;Wait for start bit
+;	rjmp	2b
+	ldi	r25, BPS/2	;Wait for half bit time
+3:	dec	r25
+	brne	3b
+
+4:	ldi	r25, BPS	;----- Bit receiving loop
+5:	dec	r25     	;Wait for a bit time
+	brne	5b		;/
+	lsr	r24     	;Next bit
+	SKIP_IN_0		;Get a data bit into r24.7
+	ori	r24, 0x80
+	brcc	4b	     	;All bits received?  no, continue
+
+	ldi	r25, BPS/2	;Wait for half bit time
+6:	dec	r25
+	brne	6b
+7:	SKIP_IN_1		;Wait for stop bit
+	rjmp	7b
+
+	out	_SFR_IO_ADDR(SREG), r0	;End of critical section
+	ret
+.endfunc
diff --git a/iwrap/suart.h b/iwrap/suart.h
new file mode 100644
index 0000000..72725b9
--- /dev/null
+++ b/iwrap/suart.h
@@ -0,0 +1,8 @@
+#ifndef SUART
+#define SUART
+
+void xmit(uint8_t);
+uint8_t rcvr(void);
+uint8_t recv(void);
+
+#endif	/* SUART */
diff --git a/iwrap/wd.h b/iwrap/wd.h
new file mode 100644
index 0000000..99058f0
--- /dev/null
+++ b/iwrap/wd.h
@@ -0,0 +1,159 @@
+/* This is from http://www.mtcnet.net/~henryvm/wdt/ */
+#ifndef _AVR_WD_H_
+#define _AVR_WD_H_
+
+#include <avr/io.h>
+
+/*
+Copyright (c) 2009, Curt Van Maanen
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+include usage-
+    #include "wd.h"             //if in same directory as project
+    #include <avr/wd.h>         //if wd.h is in avr directory
+
+set watchdog modes and prescale
+
+usage-
+    WD_SET(mode,[timeout]);     //prescale always set
+
+modes-
+    WD_OFF                      disabled
+    WD_RST                      normal reset mode
+    WD_IRQ                      interrupt only mode (if supported)
+    WD_RST_IRQ                  interrupt+reset mode (if supported)
+
+timeout-
+    WDTO_15MS                   default if no timeout provided
+    WDTO_30MS
+    WDTO_60MS
+    WDTO_120MS
+    WDTO_250MS
+    WDTO_500MS
+    WDTO_1S
+    WDTO_2S
+    WDTO_4S                     (if supported)
+    WDTO_8S                     (if supported)
+
+examples-
+    WD_SET(WD_RST,WDTO_1S);     //reset mode, 1s timeout
+    WD_SET(WD_OFF);             //watchdog disabled (if not fused on)
+    WD_SET(WD_RST);             //reset mode, 15ms (default timeout)
+    WD_SET(WD_IRQ,WDTO_120MS);  //interrupt only mode, 120ms timeout
+    WD_SET(WD_RST_IRQ,WDTO_2S); //interrupt+reset mode, 2S timeout
+
+
+for enhanced watchdogs, if the watchdog is not being used WDRF should be
+cleared on every power up or reset, along with disabling the watchdog-
+    WD_DISABLE();               //clear WDRF, then turn off watchdog
+
+*/
+
+//reset registers to the same name (MCUCSR)
+#if !defined(MCUCSR)
+#define MCUCSR                  MCUSR
+#endif
+
+//watchdog registers to the same name (WDTCSR)
+#if !defined(WDTCSR)
+#define WDTCSR                  WDTCR
+#endif
+
+//if enhanced watchdog, define irq values, create disable macro
+#if defined(WDIF)
+#define WD_IRQ                  0xC0
+#define WD_RST_IRQ              0xC8
+#define WD_DISABLE()            do{                       \
+                                    MCUCSR &= ~(1<<WDRF); \
+                                    WD_SET(WD_OFF);       \
+                                }while(0)
+#endif
+
+//all watchdogs
+#define WD_RST                  8
+#define WD_OFF                  0
+
+//prescale values
+#define WDTO_15MS               0
+#define WDTO_30MS               1
+#define WDTO_60MS               2
+#define WDTO_120MS              3
+#define WDTO_250MS              4
+#define WDTO_500MS              5
+#define WDTO_1S                 6
+#define WDTO_2S                 7
+
+//prescale values for avrs with WDP3
+#if defined(WDP3)
+#define WDTO_4S                 0x20
+#define WDTO_8S                 0x21
+#endif
+
+//watchdog reset
+#define WDR()                   __asm__ __volatile__("wdr")
+
+//avr reset using watchdog
+#define WD_AVR_RESET()          do{                              \
+                                    __asm__ __volatile__("cli"); \
+                                    WD_SET_UNSAFE(WD_RST);       \
+                                    while(1);                    \
+                                }while(0)
+
+/*set the watchdog-
+1. save SREG
+2. turn off irq's
+3. reset watchdog timer
+4. enable watchdog change
+5. write watchdog value
+6. restore SREG (restoring irq status)
+*/
+#define WD_SET(val,...)                                 \
+    __asm__ __volatile__(                               \
+        "in __tmp_reg__,__SREG__"           "\n\t"      \
+        "cli"                               "\n\t"      \
+        "wdr"                               "\n\t"      \
+        "sts %[wdreg],%[wden]"              "\n\t"      \
+        "sts %[wdreg],%[wdval]"             "\n\t"      \
+        "out __SREG__,__tmp_reg__"          "\n\t"      \
+        :                                               \
+        : [wdreg] "M" (&WDTCSR),                        \
+          [wden]  "r" ((uint8_t)(0x18)),                \
+          [wdval] "r" ((uint8_t)(val|(__VA_ARGS__+0)))  \
+        : "r0"                                          \
+)
+
+/*set the watchdog when I bit in SREG known to be clear-
+1. reset watchdog timer
+2. enable watchdog change
+5. write watchdog value
+*/
+#define WD_SET_UNSAFE(val,...)                          \
+    __asm__ __volatile__(                               \
+        "wdr"                               "\n\t"      \
+        "sts %[wdreg],%[wden]"              "\n\t"      \
+        "sts %[wdreg],%[wdval]"             "\n\t"      \
+        :                                               \
+        : [wdreg] "M" (&WDTCSR),                        \
+          [wden]  "r" ((uint8_t)(0x18)),                \
+          [wdval] "r" ((uint8_t)(val|(__VA_ARGS__+0)))  \
+)
+
+
+//for compatibility with avr/wdt.h
+#define wdt_enable(val) WD_SET(WD_RST,val)
+#define wdt_disable()   WD_SET(WD_OFF)
+
+
+#endif /* _AVR_WD_H_ */
diff --git a/keyboard.c b/keyboard.c
index 9bba409..5c2643c 100644
--- a/keyboard.c
+++ b/keyboard.c
@@ -27,7 +27,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifdef MOUSEKEY_ENABLE
 #include "mousekey.h"
 #endif
-#ifdef USB_EXTRA_ENABLE
+#ifdef EXTRAKEY_ENABLE
 #include <util/delay.h>
 #endif
 
@@ -47,7 +47,7 @@ void keyboard_init(void)
 void keyboard_proc(void)
 {
     uint8_t fn_bits = 0;
-#ifdef USB_EXTRA_ENABLE
+#ifdef EXTRAKEY_ENABLE
     uint16_t consumer_code = 0;
 #endif
 
@@ -82,7 +82,8 @@ void keyboard_proc(void)
             } else if (IS_FN(code)) {
                 fn_bits |= FN_BIT(code);
             }
-#ifdef USB_EXTRA_ENABLE
+// TODO: use table or something
+#ifdef EXTRAKEY_ENABLE
             // System Control
             else if (code == KB_SYSTEM_POWER) {
 #ifdef HOST_PJRC
@@ -170,7 +171,7 @@ void keyboard_proc(void)
     // TODO: should send only when changed from last report
     if (matrix_is_modified()) {
         host_send_keyboard_report();
-#ifdef USB_EXTRA_ENABLE
+#ifdef EXTRAKEY_ENABLE
         host_consumer_send(consumer_code);
 #endif
 #ifdef DEBUG_LED
diff --git a/layer.c b/layer.c
index 8c16485..3f9e55a 100755
--- a/layer.c
+++ b/layer.c
@@ -69,10 +69,10 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 // LAYER_ENTER_DELAY: prevent from moving new layer
-#define LAYER_ENTER_DELAY 10
+#define LAYER_ENTER_DELAY 150
 
 // LAYER_SEND_FN_TERM: send keycode if release key in this term
-#define LAYER_SEND_FN_TERM 40
+#define LAYER_SEND_FN_TERM 500
 
 
 uint8_t default_layer = 0;
diff --git a/macway/Makefile b/macway/Makefile
index 6e7fa7f..b8b0a85 100644
--- a/macway/Makefile
+++ b/macway/Makefile
@@ -8,10 +8,10 @@ COMMON_DIR = ..
 TARGET_DIR = .
 
 # keyboard dependent files
-TARGET_SRC =	main_pjrc.c \
-		keymap.c \
-  	        matrix.c \
-		led.c
+SRC =	main.c \
+	keymap.c \
+	matrix.c \
+	led.c
 
 CONFIG_H = config.h
 
@@ -37,8 +37,8 @@ F_CPU = 16000000
 #
 MOUSEKEY_ENABLE = yes	# Mouse keys
 #PS2_MOUSE_ENABLE = yes	# PS/2 mouse(TrackPoint) support
-USB_EXTRA_ENABLE = yes	# Audio control and System control
-#USB_NKRO_ENABLE = yes	# USB Nkey Rollover
+EXTRAKEY_ENABLE = yes	# Audio control and System control
+#NKRO_ENABLE = yes	# USB Nkey Rollover
 
 
 
@@ -47,5 +47,5 @@ PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex
 
 
 
-include $(COMMON_DIR)/Makefile.pjrc
-include $(COMMON_DIR)/Makefile.common
+include $(COMMON_DIR)/pjrc.mk
+include $(COMMON_DIR)/common.mk
diff --git a/macway/config.h b/macway/config.h
index ff62bfd..546067b 100644
--- a/macway/config.h
+++ b/macway/config.h
@@ -37,8 +37,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 /* key combination for command */
 #define IS_COMMAND() ( \
-    keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT) || \
-    keyboard_report->mods == (BIT_LCTRL | BIT_RSHIFT) \
+    keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_LCTRL) | MOD_BIT(KB_LALT) | MOD_BIT(KB_LGUI)) || \
+    keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) \
 )
 
 
diff --git a/macway/doc/back.jpg b/macway/doc/back.jpg
old mode 100755
new mode 100644
diff --git a/macway/doc/case.jpg b/macway/doc/case.jpg
old mode 100755
new mode 100644
diff --git a/macway/doc/keys.jpg b/macway/doc/keys.jpg
old mode 100755
new mode 100644
diff --git a/macway/doc/side.jpg b/macway/doc/side.jpg
old mode 100755
new mode 100644
diff --git a/macway/doc/switch.jpg b/macway/doc/switch.jpg
old mode 100755
new mode 100644
diff --git a/macway/doc/teensy.jpg b/macway/doc/teensy.jpg
old mode 100755
new mode 100644
diff --git a/macway/doc/wiring.jpg b/macway/doc/wiring.jpg
old mode 100755
new mode 100644
diff --git a/macway/doc/withHHKB.jpg b/macway/doc/withHHKB.jpg
old mode 100755
new mode 100644
diff --git a/macway/doc/withThinkPad.jpg b/macway/doc/withThinkPad.jpg
old mode 100755
new mode 100644
diff --git a/main_pjrc.c b/main_pjrc.c
deleted file mode 100644
index 6ba6204..0000000
--- a/main_pjrc.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/* Keyboard example with debug channel, for Teensy USB Development Board
- * http://www.pjrc.com/teensy/usb_keyboard.html
- * Copyright (c) 2008 PJRC.COM, LLC
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include <stdbool.h>
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include <util/delay.h>
-#include "keyboard.h"
-#include "usb.h"
-#include "matrix.h"
-#include "print.h"
-#include "debug.h"
-#include "util.h"
-#include "jump_bootloader.h"
-#ifdef PS2_MOUSE_ENABLE
-#   include "ps2_mouse.h"
-#endif
-
-
-#define CPU_PRESCALE(n)    (CLKPR = 0x80, CLKPR = (n))
-
-
-bool debug_enable = false;
-bool debug_matrix = false;
-bool debug_keyboard = false;
-bool debug_mouse = false;
-
-
-int main(void)
-{
-    DEBUG_LED_CONFIG;
-    DEBUG_LED_OFF;
-
-    // set for 16 MHz clock
-    CPU_PRESCALE(0);
-
-    // Initialize the USB, and then wait for the host to set configuration.
-    // If the Teensy is powered without a PC connected to the USB port,
-    // this will wait forever.
-    usb_init();
-    while (!usb_configured()) /* wait */ ;
-
-    keyboard_init();
-    matrix_scan();
-    if (matrix_key_count() >= 3) {
-#ifdef DEBUG_LED
-        for (int i = 0; i < 6; i++) {
-            DEBUG_LED_CONFIG;
-            DEBUG_LED_ON;
-            _delay_ms(500);
-            DEBUG_LED_OFF;
-            _delay_ms(500);
-        }
-#else
-        _delay_ms(5000);
-#endif
-        print_enable = true;
-        debug_enable = true;
-        debug_matrix = true;
-        debug_keyboard = true;
-        debug_mouse = true;
-        print("debug enabled.\n");
-    }
-    if (matrix_key_count() >= 4) {
-        print("jump to bootloader...\n");
-        _delay_ms(1000);
-        jump_bootloader(); // not return
-    }
-
-
-    while (1) {
-       keyboard_proc(); 
-    }
-}
diff --git a/main_vusb.c b/main_vusb.c
deleted file mode 100644
index 017888e..0000000
--- a/main_vusb.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Name: main.c
- * Project: hid-mouse, a very simple HID example
- * Author: Christian Starkjohann
- * Creation Date: 2008-04-07
- * Tabsize: 4
- * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
- * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
- * This Revision: $Id: main.c 790 2010-05-30 21:00:26Z cs $
- */
-#include <stdint.h>
-#include <avr/wdt.h>
-#include <avr/interrupt.h>
-#include <util/delay.h>
-#include "usbdrv.h"
-#include "oddebug.h"
-#include "host_vusb.h"
-#include "keyboard.h"
-
-
-#if 0
-#define DEBUGP_INIT() do { DDRC = 0xFF; } while (0)
-#define DEBUGP(x) do { PORTC = x; } while (0)
-#else
-#define DEBUGP_INIT()
-#define DEBUGP(x)
-#endif
-
-
-int main(void)
-{
-    DEBUGP_INIT();
-    wdt_enable(WDTO_1S);
-    odDebugInit();
-    usbInit();
-
-    /* enforce re-enumeration, do this while interrupts are disabled! */
-    usbDeviceDisconnect();
-    uint8_t i = 0;
-    /* fake USB disconnect for > 250 ms */
-    while(--i){
-        wdt_reset();
-        _delay_ms(1);
-    }
-    usbDeviceConnect();
-
-    keyboard_init();
-
-    sei();
-    while (1) {
-        DEBUGP(0x1);
-        wdt_reset();
-        usbPoll();
-        DEBUGP(0x2);
-        keyboard_proc();
-        DEBUGP(0x3);
-        host_vusb_keyboard_send();
-    }
-}
diff --git a/mousekey.c b/mousekey.c
old mode 100644
new mode 100755
index 69b7524..76bd0fd
--- a/mousekey.c
+++ b/mousekey.c
@@ -63,10 +63,10 @@ void mousekey_decode(uint8_t code)
     else if (code == KB_MS_BTN3)    report.buttons |= MOUSE_BTN3;
     else if (code == KB_MS_BTN4)    report.buttons |= MOUSE_BTN4;
     else if (code == KB_MS_BTN5)    report.buttons |= MOUSE_BTN5;
-    else if (code == KB_MS_WH_UP)   report.v += 1;
-    else if (code == KB_MS_WH_DOWN) report.v -= 1;
-    else if (code == KB_MS_WH_LEFT) report.h -= 1;
-    else if (code == KB_MS_WH_RIGHT)report.h += 1;
+    else if (code == KB_MS_WH_UP)   report.v += move_unit()/4;
+    else if (code == KB_MS_WH_DOWN) report.v -= move_unit()/4;
+    else if (code == KB_MS_WH_LEFT) report.h -= move_unit()/4;
+    else if (code == KB_MS_WH_RIGHT)report.h += move_unit()/4;
 }
 
 bool mousekey_changed(void)
@@ -87,7 +87,7 @@ void mousekey_send(void)
 
     // send immediately when buttun state is changed
     if (report.buttons == report_prev.buttons) {
-        if (timer_elapsed(last_timer) < 5) {
+        if (timer_elapsed(last_timer) < 100) {
             mousekey_clear_report();
             return;
         }
diff --git a/pjrc.mk b/pjrc.mk
new file mode 100644
index 0000000..0bc47ac
--- /dev/null
+++ b/pjrc.mk
@@ -0,0 +1,21 @@
+OPT_DEFS += -DHOST_PJRC
+
+SRC +=	pjrc.c \
+	usb_keyboard.c \
+	usb_debug.c \
+	usb.c \
+	jump_bootloader.c
+
+
+# Search Path
+VPATH += $(COMMON_DIR):$(COMMON_DIR)/pjrc
+
+
+# Option modules
+ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE)
+    SRC += usb_mouse.c
+endif
+
+ifdef EXTRAKEY_ENABLE
+    SRC += usb_extra.c
+endif
diff --git a/pjrc/host.c b/pjrc/host.c
index 35d59de..fcf71d5 100644
--- a/pjrc/host.c
+++ b/pjrc/host.c
@@ -22,7 +22,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE)
 #include "usb_mouse.h"
 #endif
-#ifdef USB_EXTRA_ENABLE
+#ifdef EXTRAKEY_ENABLE
 #include "usb_extra.h"
 #endif
 #include "debug.h"
@@ -30,7 +30,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "util.h"
 
 
-#ifdef USB_NKRO_ENABLE
+#ifdef NKRO_ENABLE
 bool keyboard_nkro = false;
 #endif
 
@@ -51,7 +51,7 @@ uint8_t host_keyboard_leds(void)
 /* keyboard report operations */
 void host_add_key(uint8_t key)
 {
-#ifdef USB_NKRO_ENABLE
+#ifdef NKRO_ENABLE
     if (keyboard_nkro) {
         add_key_bit(key);
         return;
@@ -109,7 +109,7 @@ uint8_t host_has_anykey(void)
 
 uint8_t host_get_first_key(void)
 {
-#ifdef USB_NKRO_ENABLE
+#ifdef NKRO_ENABLE
     if (keyboard_nkro) {
         uint8_t i = 0;
         for (; i < REPORT_KEYS && !keyboard_report->keys[i]; i++)
@@ -133,7 +133,7 @@ void host_mouse_send(report_mouse_t *report)
 }
 #endif
 
-#ifdef USB_EXTRA_ENABLE
+#ifdef EXTRAKEY_ENABLE
 void host_system_send(uint16_t data)
 {
     usb_extra_system_send(data);
diff --git a/pjrc/main.c b/pjrc/main.c
new file mode 100644
index 0000000..f84925d
--- /dev/null
+++ b/pjrc/main.c
@@ -0,0 +1,97 @@
+/* Keyboard example with debug channel, for Teensy USB Development Board
+ * http://www.pjrc.com/teensy/usb_keyboard.html
+ * Copyright (c) 2008 PJRC.COM, LLC
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdbool.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "keyboard.h"
+#include "usb.h"
+#include "matrix.h"
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "jump_bootloader.h"
+#ifdef PS2_MOUSE_ENABLE
+#   include "ps2_mouse.h"
+#endif
+#include "host.h"
+#include "pjrc.h"
+
+
+#define CPU_PRESCALE(n)    (CLKPR = 0x80, CLKPR = (n))
+
+
+bool debug_enable = false;
+bool debug_matrix = false;
+bool debug_keyboard = false;
+bool debug_mouse = false;
+
+
+int main(void)
+{
+    DEBUG_LED_CONFIG;
+    DEBUG_LED_OFF;
+
+    // set for 16 MHz clock
+    CPU_PRESCALE(0);
+
+    // Initialize the USB, and then wait for the host to set configuration.
+    // If the Teensy is powered without a PC connected to the USB port,
+    // this will wait forever.
+    usb_init();
+    while (!usb_configured()) /* wait */ ;
+
+    keyboard_init();
+    matrix_scan();
+    if (matrix_key_count() >= 3) {
+#ifdef DEBUG_LED
+        for (int i = 0; i < 6; i++) {
+            DEBUG_LED_CONFIG;
+            DEBUG_LED_ON;
+            _delay_ms(500);
+            DEBUG_LED_OFF;
+            _delay_ms(500);
+        }
+#else
+        _delay_ms(5000);
+#endif
+        print_enable = true;
+        debug_enable = true;
+        debug_matrix = true;
+        debug_keyboard = true;
+        debug_mouse = true;
+        print("debug enabled.\n");
+    }
+    if (matrix_key_count() >= 4) {
+        print("jump to bootloader...\n");
+        _delay_ms(1000);
+        jump_bootloader(); // not return
+    }
+
+
+    host_set_driver(pjrc_driver());
+    while (1) {
+       keyboard_proc(); 
+    }
+}
diff --git a/pjrc/pjrc.c b/pjrc/pjrc.c
new file mode 100644
index 0000000..0562a12
--- /dev/null
+++ b/pjrc/pjrc.c
@@ -0,0 +1,76 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include "usb_keyboard.h"
+#include "usb_mouse.h"
+#include "usb_extra.h"
+#include "host_driver.h"
+#include "pjrc.h"
+
+
+/*------------------------------------------------------------------*
+ * Host driver
+ *------------------------------------------------------------------*/
+static uint8_t keyboard_leds(void);
+static void send_keyboard(report_keyboard_t *report);
+static void send_mouse(report_mouse_t *report);
+static void send_system(uint16_t data);
+static void send_consumer(uint16_t data);
+
+static host_driver_t driver = {
+        keyboard_leds,
+        send_keyboard,
+        send_mouse,
+        send_system,
+        send_consumer
+};
+
+host_driver_t *pjrc_driver(void)
+{
+    return &driver;
+}
+
+static uint8_t keyboard_leds(void) {
+    return usb_keyboard_leds;
+}
+
+static void send_keyboard(report_keyboard_t *report)
+{
+    usb_keyboard_send_report(report);
+}
+
+static void send_mouse(report_mouse_t *report)
+{
+#ifdef MOUSE_ENABLE
+    usb_mouse_send(report->x, report->y, report->v, report->h, report->buttons);
+#endif
+}
+
+static void send_system(uint16_t data)
+{
+#ifdef EXTRAKEY_ENABLE
+    usb_extra_system_send(data);
+#endif
+}
+
+static void send_consumer(uint16_t data)
+{
+#ifdef EXTRAKEY_ENABLE
+    usb_extra_consumer_send(data);
+#endif
+}
diff --git a/pjrc/pjrc.h b/pjrc/pjrc.h
new file mode 100644
index 0000000..06e7962
--- /dev/null
+++ b/pjrc/pjrc.h
@@ -0,0 +1,26 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PJRC_H
+#define PJRC_H
+
+#include "host_driver.h"
+
+
+host_driver_t *pjrc_driver(void);
+
+#endif
diff --git a/pjrc/usb.c b/pjrc/usb.c
index ea2e71b..9989a4b 100644
--- a/pjrc/usb.c
+++ b/pjrc/usb.c
@@ -91,18 +91,18 @@ bool suspend = false;
 static const uint8_t PROGMEM endpoint_config_table[] = {
 	// enable, UECFG0X(type, direction), UECFG1X(size, bank, allocation)
 	1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(KBD_SIZE)      | KBD_BUFFER,      // 1
-#ifdef USB_MOUSE_ENABLE
+#ifdef MOUSE_ENABLE
 	1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(MOUSE_SIZE)    | MOUSE_BUFFER,    // 2
 #else
         0,                                                                  // 2
 #endif
 	1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, // 3
-#ifdef USB_EXTRA_ENABLE
+#ifdef EXTRAKEY_ENABLE
 	1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(EXTRA_SIZE)    | EXTRA_BUFFER,    // 4
 #else
         0,                                                                  // 4
 #endif
-#ifdef USB_NKRO_ENABLE
+#ifdef NKRO_ENABLE
 	1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(KBD2_SIZE)     | KBD2_BUFFER,     // 5
 #else
         0,                                                                  // 5
@@ -176,7 +176,7 @@ static uint8_t PROGMEM keyboard_hid_report_desc[] = {
         0x81, 0x00,          //   Input (Data, Array),
         0xc0                 // End Collection
 };
-#ifdef USB_NKRO_ENABLE
+#ifdef NKRO_ENABLE
 static uint8_t PROGMEM keyboard2_hid_report_desc[] = {
         0x05, 0x01,                     // Usage Page (Generic Desktop),
         0x09, 0x06,                     // Usage (Keyboard),
@@ -213,7 +213,7 @@ static uint8_t PROGMEM keyboard2_hid_report_desc[] = {
 };
 #endif
 
-#ifdef USB_MOUSE_ENABLE
+#ifdef MOUSE_ENABLE
 // Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
 // http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521
 // http://www.keil.com/forum/15671/
@@ -282,7 +282,7 @@ static uint8_t PROGMEM debug_hid_report_desc[] = {
 	0xC0					// end collection
 };
 
-#ifdef USB_EXTRA_ENABLE
+#ifdef EXTRAKEY_ENABLE
 // audio controls & system controls
 // http://www.microsoft.com/whdc/archive/w2kbd.mspx
 static uint8_t PROGMEM extra_hid_report_desc[] = {
@@ -318,7 +318,7 @@ static uint8_t PROGMEM extra_hid_report_desc[] = {
 #define KBD_HID_DESC_NUM                0
 #define KBD_HID_DESC_OFFSET             (9+(9+9+7)*KBD_HID_DESC_NUM+9)
 
-#ifdef USB_MOUSE_ENABLE
+#ifdef MOUSE_ENABLE
 #   define MOUSE_HID_DESC_NUM           (KBD_HID_DESC_NUM + 1)
 #   define MOUSE_HID_DESC_OFFSET        (9+(9+9+7)*MOUSE_HID_DESC_NUM+9)
 #else
@@ -328,14 +328,14 @@ static uint8_t PROGMEM extra_hid_report_desc[] = {
 #define DEBUG_HID_DESC_NUM              (MOUSE_HID_DESC_NUM + 1)
 #define DEBUG_HID_DESC_OFFSET           (9+(9+9+7)*DEBUG_HID_DESC_NUM+9)
 
-#ifdef USB_EXTRA_ENABLE
+#ifdef EXTRAKEY_ENABLE
 #   define EXTRA_HID_DESC_NUM           (DEBUG_HID_DESC_NUM + 1)
 #   define EXTRA_HID_DESC_OFFSET        (9+(9+9+7)*EXTRA_HID_DESC_NUM+9)
 #else
 #   define EXTRA_HID_DESC_NUM           (DEBUG_HID_DESC_NUM + 0)
 #endif
 
-#ifdef USB_NKRO_ENABLE
+#ifdef NKRO_ENABLE
 #   define KBD2_HID_DESC_NUM            (EXTRA_HID_DESC_NUM + 1)
 #   define KBD2_HID_DESC_OFFSET         (9+(9+9+7)*EXTRA_HID_DESC_NUM+9)
 #else
@@ -383,7 +383,7 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
 	KBD_SIZE, 0,				// wMaxPacketSize
 	10,					// bInterval
 
-#ifdef USB_MOUSE_ENABLE
+#ifdef MOUSE_ENABLE
 	// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
 	9,					// bLength
 	4,					// bDescriptorType
@@ -444,7 +444,7 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
 	DEBUG_TX_SIZE, 0,			// wMaxPacketSize
 	1,					// bInterval
 
-#ifdef USB_EXTRA_ENABLE
+#ifdef EXTRAKEY_ENABLE
 	// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
 	9,					// bLength
 	4,					// bDescriptorType
@@ -473,7 +473,7 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
 	10,					// bInterval
 #endif
 
-#ifdef USB_NKRO_ENABLE
+#ifdef NKRO_ENABLE
 	// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
 	9,					// bLength
 	4,					// bDescriptorType
@@ -542,17 +542,17 @@ static struct descriptor_list_struct {
         // HID/REPORT descriptors
 	{0x2100, KBD_INTERFACE, config1_descriptor+KBD_HID_DESC_OFFSET, 9},
 	{0x2200, KBD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
-#ifdef USB_MOUSE_ENABLE
+#ifdef MOUSE_ENABLE
 	{0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9},
 	{0x2200, MOUSE_INTERFACE, mouse_hid_report_desc, sizeof(mouse_hid_report_desc)},
 #endif
 	{0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
 	{0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
-#ifdef USB_EXTRA_ENABLE
+#ifdef EXTRAKEY_ENABLE
 	{0x2100, EXTRA_INTERFACE, config1_descriptor+EXTRA_HID_DESC_OFFSET, 9},
 	{0x2200, EXTRA_INTERFACE, extra_hid_report_desc, sizeof(extra_hid_report_desc)},
 #endif
-#ifdef USB_NKRO_ENABLE
+#ifdef NKRO_ENABLE
 	{0x2100, KBD2_INTERFACE, config1_descriptor+KBD2_HID_DESC_OFFSET, 9},
 	{0x2200, KBD2_INTERFACE, keyboard2_hid_report_desc, sizeof(keyboard2_hid_report_desc)},
 #endif
@@ -653,7 +653,7 @@ ISR(USB_GEN_vect)
 			}
 		}
                 /* TODO: should keep IDLE rate on each keyboard interface */
-#ifdef USB_NKRO_ENABLE
+#ifdef NKRO_ENABLE
 		if (!keyboard_nkro && usb_keyboard_idle_config && (++div4 & 3) == 0) {
 #else
 		if (usb_keyboard_idle_config && (++div4 & 3) == 0) {
@@ -894,7 +894,7 @@ ISR(USB_COM_vect)
 				}
 			}
 		}
-#ifdef USB_MOUSE_ENABLE
+#ifdef MOUSE_ENABLE
 		if (wIndex == MOUSE_INTERFACE) {
 			if (bmRequestType == 0xA1) {
 				if (bRequest == HID_GET_REPORT) {
diff --git a/pjrc/usb.h b/pjrc/usb.h
index a4e40bd..82e18f1 100644
--- a/pjrc/usb.h
+++ b/pjrc/usb.h
@@ -120,7 +120,7 @@ void usb_remote_wakeup(void);
 #define KBD_REPORT_KEYS		(KBD_SIZE - 2)
 
 // secondary keyboard
-#ifdef USB_NKRO_ENABLE
+#ifdef NKRO_ENABLE
 #define KBD2_INTERFACE		4
 #define KBD2_ENDPOINT		5
 #define KBD2_SIZE		16
diff --git a/pjrc/usb_keyboard.c b/pjrc/usb_keyboard.c
index 34e9d49..e057c77 100644
--- a/pjrc/usb_keyboard.c
+++ b/pjrc/usb_keyboard.c
@@ -55,7 +55,7 @@ int8_t usb_keyboard_send_report(report_keyboard_t *report)
 {
     int8_t result = 0;
 
-#ifdef USB_NKRO_ENABLE
+#ifdef NKRO_ENABLE
     if (keyboard_nkro)
         result = send_report(report, KBD2_ENDPOINT, 0, KBD2_REPORT_KEYS);
     else
@@ -105,7 +105,7 @@ static inline int8_t send_report(report_keyboard_t *report, uint8_t endpoint, ui
             UENUM = endpoint;
     }
     UEDATX = report->mods;
-#ifdef USB_NKRO_ENABLE
+#ifdef NKRO_ENABLE
     if (!keyboard_nkro)
         UEDATX = 0;
 #else
diff --git a/print.c b/print.c
index d915297..558181e 100644
--- a/print.c
+++ b/print.c
@@ -29,6 +29,19 @@
 
 bool print_enable = false;
 
+void print_S(const char *s)
+{
+	if (!print_enable) return;
+	char c;
+
+	while (1) {
+		c = *s++;
+		if (!c) break;
+		if (c == '\n') sendchar('\r');
+		sendchar(c);
+	}
+}
+
 void print_P(const char *s)
 {
 	if (!print_enable) return;
diff --git a/print.h b/print.h
index edc540f..686fa89 100644
--- a/print.h
+++ b/print.h
@@ -24,6 +24,7 @@
 #ifndef PRINT_H__
 #define PRINT_H__ 1
 
+#include <stdint.h>
 #include <stdbool.h>
 #include <avr/pgmspace.h>
 
@@ -34,6 +35,7 @@ extern bool print_enable;
 // the string is automatically placed into flash memory :)
 #define print(s) print_P(PSTR(s))
 
+void print_S(const char *s);
 void print_P(const char *s);
 void phex(unsigned char c);
 void phex16(unsigned int i);
diff --git a/ps2_usb/Makefile b/ps2_usb/Makefile
index a548b56..7352f6b 100644
--- a/ps2_usb/Makefile
+++ b/ps2_usb/Makefile
@@ -13,11 +13,11 @@ COMMON_DIR = ..
 TARGET_DIR = .
 
 # keyboard dependent files
-TARGET_SRC =	main_pjrc.c \
-		keymap.c \
-		matrix.c \
-		led.c \
-		ps2.c
+SRC =	main.c \
+	keymap.c \
+	matrix.c \
+	led.c \
+	ps2.c
 
 CONFIG_H = config_pjrc.h
 
@@ -42,8 +42,8 @@ F_CPU = 16000000
 #   comment out to disable the options.
 #
 MOUSEKEY_ENABLE = yes	# Mouse keys
-USB_EXTRA_ENABLE = yes	# Audio control and System control
-USB_NKRO_ENABLE = yes	# USB Nkey Rollover
+EXTRAKEY_ENABLE = yes	# Audio control and System control
+NKRO_ENABLE = yes	# USB Nkey Rollover
 
 
 
@@ -52,5 +52,5 @@ PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex
 
 
 
-include $(COMMON_DIR)/Makefile.pjrc
-include $(COMMON_DIR)/Makefile.common
+include $(COMMON_DIR)/pjrc.mk
+include $(COMMON_DIR)/common.mk
diff --git a/ps2_usb/Makefile.vusb b/ps2_usb/Makefile.vusb
index ff86d79..5b6978f 100644
--- a/ps2_usb/Makefile.vusb
+++ b/ps2_usb/Makefile.vusb
@@ -13,11 +13,11 @@ COMMON_DIR = ..
 TARGET_DIR = .
 
 # keyboard dependent files
-TARGET_SRC =	main_vusb.c \
-		keymap.c \
-		matrix.c \
-		led.c \
-		ps2_usart.c
+SRC =	main.c \
+	keymap.c \
+	matrix.c \
+	led.c \
+	ps2_usart.c
 
 CONFIG_H = config_vusb.h
 
@@ -48,8 +48,9 @@ F_CPU = 20000000
 #   comment out to disable the options.
 #
 MOUSEKEY_ENABLE = yes	# Mouse keys
-USB_EXTRA_ENABLE = yes	# Audio control and System control
-#USB_NKRO_ENABLE = yes	# USB Nkey Rollover
+EXTRAKEY_ENABLE = yes	# Audio control and System control
+#NKRO_ENABLE = yes	# USB Nkey Rollover
+NO_UART = yes		# UART is unavailable
 
 
 
@@ -85,5 +86,5 @@ PROGRAM_CMD = $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE
 
 
 
-include $(COMMON_DIR)/Makefile.vusb
-include $(COMMON_DIR)/Makefile.common
+include $(COMMON_DIR)/vusb.mk
+include $(COMMON_DIR)/common.mk
diff --git a/ps2_usb/config_pjrc.h b/ps2_usb/config_pjrc.h
index 56917be..883ffab 100644
--- a/ps2_usb/config_pjrc.h
+++ b/ps2_usb/config_pjrc.h
@@ -35,8 +35,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 /* key combination for command */
 #define IS_COMMAND() ( \
-    keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT) || \
-    keyboard_report->mods == (BIT_LCTRL | BIT_RSHIFT) \
+    keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) || \
+    keyboard_report->mods == (MOD_BIT(KB_LCTRL) | MOD_BIT(KB_RSHIFT)) \
 )
 
 
diff --git a/ps2_usb/config_vusb.h b/ps2_usb/config_vusb.h
index 426bb61..afd2f79 100644
--- a/ps2_usb/config_vusb.h
+++ b/ps2_usb/config_vusb.h
@@ -35,8 +35,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 /* key combination for command */
 #define IS_COMMAND() ( \
-    keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT) || \
-    keyboard_report->mods == (BIT_LCTRL | BIT_RSHIFT) \
+    keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) || \
+    keyboard_report->mods == (MOD_BIT(KB_LCTRL) | MOD_BIT(KB_RSHIFT)) \
 )
 
 
diff --git a/ps2_usb/keymap.c b/ps2_usb/keymap.c
index ef11daa..e84e8c2 100644
--- a/ps2_usb/keymap.c
+++ b/ps2_usb/keymap.c
@@ -124,7 +124,7 @@ static const uint8_t PROGMEM fn_layer[] = {
 static const uint8_t PROGMEM fn_keycode[] = {
     KB_SCLN,        // Fn0
     KB_SLSH,        // Fn1
-    KB_A,           // Fn2
+    KB_NO,          // Fn2
     KB_NO,          // Fn3
     KB_NO,          // Fn4
     KB_NO,          // Fn5
@@ -154,7 +154,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
     ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12,           PSCR,SLCK,BRK,
     GRV, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, BSPC,     INS, HOME,PGUP,    NLCK,PSLS,PAST,PMNS,
     TAB, Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC,BSLS,     DEL, END, PGDN,    P7,  P8,  P9,
-    CAPS,FN2, S,   D,   F,   G,   H,   J,   K,   L,   FN0, QUOT,     ENT,                         P4,  P5,  P6,  PPLS,
+    CAPS,A,   S,   D,   F,   G,   H,   J,   K,   L,   FN0, QUOT,     ENT,                         P4,  P5,  P6,  PPLS,
     LSFT,Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, FN1,           RSFT,          UP,           P1,  P2,  P3,
     LCTL,LGUI,LALT,          SPC,                     RALT,RGUI,APP, RCTL,     LEFT,DOWN,RGHT,    P0,       PDOT,PENT
     ),
@@ -204,7 +204,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
     ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12,           PSCR,SLCK,BRK,
     ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F8,  F10, F11, F12, BSPC,     INS, HOME,PGUP,    NLCK,PSLS,PAST,PMNS,
     TAB, WH_L,WH_D,MS_U,WH_U,WH_R,WH_L,WH_D,WH_U,WH_R,NO,  NO,  NO,  BSLS,     DEL, END, PGDN,    P7,  P8,  P9,
-    CAPS,FN2, MS_L,MS_D,MS_R,NO,  MS_L,MS_D,MS_U,MS_R,FN0, NO,       ENT,                         P4,  P5,  P6,  PPLS,
+    CAPS,NO,  MS_L,MS_D,MS_R,NO,  MS_L,MS_D,MS_U,MS_R,FN0, NO,       ENT,                         P4,  P5,  P6,  PPLS,
     LSFT,VOLD,VOLU,MUTE,BTN2,BTN3,BTN2,BTN1,VOLD,VOLU,MUTE,          RSFT,          UP,           P1,  P2,  P3,
     LCTL,LGUI,LALT,          BTN1,                    RALT,RGUI,APP, RCTL,     LEFT,DOWN,RGHT,    P0,       PDOT,PENT
     ),
diff --git a/ps2_usb/matrix.c b/ps2_usb/matrix.c
index 5d73cc2..1aac3f8 100644
--- a/ps2_usb/matrix.c
+++ b/ps2_usb/matrix.c
@@ -349,6 +349,7 @@ uint8_t matrix_scan(void)
             default:
                 state = INIT;
         }
+        phex(code);
     }
     return 1;
 }
diff --git a/report.h b/report.h
new file mode 100644
index 0000000..b85b86c
--- /dev/null
+++ b/report.h
@@ -0,0 +1,96 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef REPORT_H
+#define REPORT_H
+
+#include <stdint.h>
+
+
+/* report id */
+#define REPORT_ID_MOUSE     1
+#define REPORT_ID_SYSTEM    2
+#define REPORT_ID_CONSUMER  3
+
+/* mouse buttons */
+#define MOUSE_BTN1 (1<<0)
+#define MOUSE_BTN2 (1<<1)
+#define MOUSE_BTN3 (1<<2)
+#define MOUSE_BTN4 (1<<3)
+#define MOUSE_BTN5 (1<<4)
+
+// Consumer Page(0x0C)
+// following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx
+#define AUDIO_MUTE              0x00E2
+#define AUDIO_VOL_UP            0x00E9
+#define AUDIO_VOL_DOWN          0x00EA
+#define TRANSPORT_NEXT_TRACK    0x00B5
+#define TRANSPORT_PREV_TRACK    0x00B6
+#define TRANSPORT_STOP          0x00B7
+#define TRANSPORT_PLAY_PAUSE    0x00CD
+#define AL_CC_CONFIG            0x0183
+#define AL_EMAIL                0x018A
+#define AL_CALCULATOR           0x0192
+#define AL_LOCAL_BROWSER        0x0194
+#define AC_SEARCH               0x0221
+#define AC_HOME                 0x0223
+#define AC_BACK                 0x0224
+#define AC_FORWARD              0x0225
+#define AC_STOP                 0x0226
+#define AC_REFRESH              0x0227
+#define AC_BOOKMARKS            0x022A
+// supplement for Bluegiga iWRAP HID(not supported by Windows?)
+#define AL_LOCK                 0x019E
+#define TRANSPORT_RECORD        0x00B2
+#define TRANSPORT_REWIND        0x00B4
+#define TRANSPORT_EJECT         0x00B8
+#define AC_MINIMIZE             0x0206
+
+// Generic Desktop Page(0x01)
+#define SYSTEM_POWER_DOWN       0x0081
+#define SYSTEM_SLEEP            0x0082
+#define SYSTEM_WAKE_UP          0x0083
+
+
+// key report size(NKRO or boot mode)
+#if defined(HOST_PJRC)
+#   include "usb.h"
+#   if defined(KBD2_REPORT_KEYS) && KBD2_REPORT_KEYS > KBD_REPORT_KEYS
+#       define REPORT_KEYS KBD2_REPORT_KEYS
+#   else
+#       define REPORT_KEYS KBD_REPORT_KEYS
+#   endif
+#else
+#   define REPORT_KEYS 6
+#endif
+
+typedef struct {
+    uint8_t mods;
+    uint8_t rserved;
+    uint8_t keys[REPORT_KEYS];
+} report_keyboard_t;
+
+typedef struct {
+    uint8_t report_id;
+    uint8_t buttons;
+    int8_t x;
+    int8_t y;
+    int8_t v;
+    int8_t h;
+} report_mouse_t;
+
+#endif
diff --git a/rules.mk b/rules.mk
new file mode 100644
index 0000000..f1d0a30
--- /dev/null
+++ b/rules.mk
@@ -0,0 +1,547 @@
+# Hey Emacs, this is a -*- makefile -*-
+#----------------------------------------------------------------------------
+# WinAVR Makefile Template written by Eric B. Weddington, Jg Wunsch, et al.
+#
+# Released to the Public Domain
+#
+# Additional material for this makefile was written by:
+# Peter Fleury
+# Tim Henigan
+# Colin O'Flynn
+# Reiner Patommel
+# Markus Pfaff
+# Sander Pool
+# Frederik Rouleau
+# Carlos Lamas
+#
+#----------------------------------------------------------------------------
+# On command line:
+#
+# make all = Make software.
+#
+# make clean = Clean out built project files.
+#
+# make coff = Convert ELF to AVR COFF.
+#
+# make extcoff = Convert ELF to AVR Extended COFF.
+#
+# make program = Download the hex file to the device, using avrdude.
+#                Please customize the avrdude settings below first!
+#
+# make debug = Start either simulavr or avarice as specified for debugging, 
+#              with avr-gdb or avr-insight as the front end for debugging.
+#
+# make filename.s = Just compile filename.c into the assembler code only.
+#
+# make filename.i = Create a preprocessed source file for use in submitting
+#                   bug reports to the GCC project.
+#
+# To rebuild project do "make clean" then "make all".
+#----------------------------------------------------------------------------
+
+
+# Output format. (can be srec, ihex, binary)
+FORMAT = ihex
+
+
+# Object files directory
+#     To put object files in current directory, use a dot (.), do NOT make
+#     this an empty or blank macro!
+OBJDIR = obj_$(TARGET)
+
+
+# Optimization level, can be [0, 1, 2, 3, s]. 
+#     0 = turn off optimization. s = optimize for size.
+#     (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
+OPT = s
+
+
+# Debugging format.
+#     Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
+#     AVR Studio 4.10 requires dwarf-2.
+#     AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
+DEBUG = dwarf-2
+
+
+# List any extra directories to look for include files here.
+#     Each directory must be seperated by a space.
+#     Use forward slashes for directory separators.
+#     For a directory that has spaces, enclose it in quotes.
+EXTRAINCDIRS = $(subst :, ,$(VPATH))
+
+
+# Compiler flag to set the C Standard level.
+#     c89   = "ANSI" C
+#     gnu89 = c89 plus GCC extensions
+#     c99   = ISO C99 standard (not yet fully implemented)
+#     gnu99 = c99 plus GCC extensions
+CSTANDARD = -std=gnu99
+
+
+# Place -D or -U options here for C sources
+CDEFS = -DF_CPU=$(F_CPU)UL
+CDEFS += $(OPT_DEFS)
+
+
+# Place -D or -U options here for ASM sources
+ADEFS = -DF_CPU=$(F_CPU)
+ADEFS += $(OPT_DEFS)
+
+
+# Place -D or -U options here for C++ sources
+CPPDEFS = -DF_CPU=$(F_CPU)UL
+#CPPDEFS += -D__STDC_LIMIT_MACROS
+#CPPDEFS += -D__STDC_CONSTANT_MACROS
+CPPDEFS += $(OPT_DEFS)
+
+
+
+#---------------- Compiler Options C ----------------
+#  -g*:          generate debugging information
+#  -O*:          optimization level
+#  -f...:        tuning, see GCC manual and avr-libc documentation
+#  -Wall...:     warning level
+#  -Wa,...:      tell GCC to pass this to the assembler.
+#    -adhlns...: create assembler listing
+CFLAGS = -g$(DEBUG)
+CFLAGS += $(CDEFS)
+CFLAGS += -O$(OPT)
+CFLAGS += -funsigned-char
+CFLAGS += -funsigned-bitfields
+CFLAGS += -ffunction-sections
+CFLAGS += -fpack-struct
+CFLAGS += -fshort-enums
+CFLAGS += -Wall
+CFLAGS += -Wstrict-prototypes
+#CFLAGS += -mshort-calls
+#CFLAGS += -fno-unit-at-a-time
+#CFLAGS += -Wundef
+#CFLAGS += -Wunreachable-code
+#CFLAGS += -Wsign-compare
+CFLAGS += -Wa,-adhlns=$(@:%.o=%.lst)
+CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
+CFLAGS += $(CSTANDARD)
+CFLAGS += -include $(CONFIG_H)
+
+
+#---------------- Compiler Options C++ ----------------
+#  -g*:          generate debugging information
+#  -O*:          optimization level
+#  -f...:        tuning, see GCC manual and avr-libc documentation
+#  -Wall...:     warning level
+#  -Wa,...:      tell GCC to pass this to the assembler.
+#    -adhlns...: create assembler listing
+CPPFLAGS = -g$(DEBUG)
+CPPFLAGS += $(CPPDEFS)
+CPPFLAGS += -O$(OPT)
+CPPFLAGS += -funsigned-char
+CPPFLAGS += -funsigned-bitfields
+CPPFLAGS += -fpack-struct
+CPPFLAGS += -fshort-enums
+CPPFLAGS += -fno-exceptions
+CPPFLAGS += -Wall
+CPPFLAGS += -Wundef
+#CPPFLAGS += -mshort-calls
+#CPPFLAGS += -fno-unit-at-a-time
+#CPPFLAGS += -Wstrict-prototypes
+#CPPFLAGS += -Wunreachable-code
+#CPPFLAGS += -Wsign-compare
+CPPFLAGS += -Wa,-adhlns=$(@:%.o=%.lst)
+CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
+#CPPFLAGS += $(CSTANDARD)
+CPPFLAGS += -include $(CONFIG_H)
+
+
+#---------------- Assembler Options ----------------
+#  -Wa,...:   tell GCC to pass this to the assembler.
+#  -adhlns:   create listing
+#  -gstabs:   have the assembler create line number information; note that
+#             for use in COFF files, additional information about filenames
+#             and function names needs to be present in the assembler source
+#             files -- see avr-libc docs [FIXME: not yet described there]
+#  -listing-cont-lines: Sets the maximum number of continuation lines of hex 
+#       dump that will be displayed for a given single line of source input.
+ASFLAGS = $(ADEFS) -Wa,-adhlns=$(@:%.o=%.lst),-gstabs,--listing-cont-lines=100
+ASFLAGS += -include $(CONFIG_H)
+
+
+#---------------- Library Options ----------------
+# Minimalistic printf version
+PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
+
+# Floating point printf version (requires MATH_LIB = -lm below)
+PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
+
+# If this is left blank, then it will use the Standard printf version.
+PRINTF_LIB = 
+#PRINTF_LIB = $(PRINTF_LIB_MIN)
+#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
+
+
+# Minimalistic scanf version
+SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
+
+# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
+SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
+
+# If this is left blank, then it will use the Standard scanf version.
+SCANF_LIB = 
+#SCANF_LIB = $(SCANF_LIB_MIN)
+#SCANF_LIB = $(SCANF_LIB_FLOAT)
+
+
+MATH_LIB = -lm
+
+
+# List any extra directories to look for libraries here.
+#     Each directory must be seperated by a space.
+#     Use forward slashes for directory separators.
+#     For a directory that has spaces, enclose it in quotes.
+EXTRALIBDIRS = 
+
+
+
+#---------------- External Memory Options ----------------
+
+# 64 KB of external RAM, starting after internal RAM (ATmega128!),
+# used for variables (.data/.bss) and heap (malloc()).
+#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
+
+# 64 KB of external RAM, starting after internal RAM (ATmega128!),
+# only used for heap (malloc()).
+#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
+
+EXTMEMOPTS =
+
+
+
+#---------------- Linker Options ----------------
+#  -Wl,...:     tell GCC to pass this to linker.
+#    -Map:      create map file
+#    --cref:    add cross reference to  map file
+#
+# Comennt out "--relax" option to avoid a error such:
+# 	(.vectors+0x30): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_12'
+#
+LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
+LDFLAGS += -Wl,--relax
+LDFLAGS += -Wl,--gc-sections
+LDFLAGS += $(EXTMEMOPTS)
+LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
+LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
+#LDFLAGS += -T linker_script.x
+
+
+
+#---------------- Debugging Options ----------------
+
+# For simulavr only - target MCU frequency.
+DEBUG_MFREQ = $(F_CPU)
+
+# Set the DEBUG_UI to either gdb or insight.
+# DEBUG_UI = gdb
+DEBUG_UI = insight
+
+# Set the debugging back-end to either avarice, simulavr.
+DEBUG_BACKEND = avarice
+#DEBUG_BACKEND = simulavr
+
+# GDB Init Filename.
+GDBINIT_FILE = __avr_gdbinit
+
+# When using avarice settings for the JTAG
+JTAG_DEV = /dev/com1
+
+# Debugging port used to communicate between GDB / avarice / simulavr.
+DEBUG_PORT = 4242
+
+# Debugging host used to communicate between GDB / avarice / simulavr, normally
+#     just set to localhost unless doing some sort of crazy debugging when 
+#     avarice is running on a different computer.
+DEBUG_HOST = localhost
+
+
+
+#============================================================================
+
+
+# Define programs and commands.
+SHELL = sh
+CC = avr-gcc
+OBJCOPY = avr-objcopy
+OBJDUMP = avr-objdump
+SIZE = avr-size
+AR = avr-ar rcs
+NM = avr-nm
+REMOVE = rm -f
+REMOVEDIR = rmdir
+COPY = cp
+WINSHELL = cmd
+
+
+# Define Messages
+# English
+MSG_ERRORS_NONE = Errors: none
+MSG_BEGIN = -------- begin --------
+MSG_END = --------  end  --------
+MSG_SIZE_BEFORE = Size before: 
+MSG_SIZE_AFTER = Size after:
+MSG_COFF = Converting to AVR COFF:
+MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
+MSG_FLASH = Creating load file for Flash:
+MSG_EEPROM = Creating load file for EEPROM:
+MSG_EXTENDED_LISTING = Creating Extended Listing:
+MSG_SYMBOL_TABLE = Creating Symbol Table:
+MSG_LINKING = Linking:
+MSG_COMPILING = Compiling C:
+MSG_COMPILING_CPP = Compiling C++:
+MSG_ASSEMBLING = Assembling:
+MSG_CLEANING = Cleaning project:
+MSG_CREATING_LIBRARY = Creating library:
+
+
+
+
+# Define all object files.
+OBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(patsubst %.cpp,$(OBJDIR)/%.o,$(patsubst %.S,$(OBJDIR)/%.o,$(SRC))))
+
+# Define all listing files.
+LST = $(patsubst %.c,$(OBJDIR)/%.lst,$(patsubst %.cpp,$(OBJDIR)/%.lst,$(patsubst %.S,$(OBJDIR)/%.lst,$(SRC))))
+
+
+# Compiler flags to generate dependency files.
+GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
+
+
+# Combine all necessary flags and optional flags.
+# Add target processor to flags.
+ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
+ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS)
+ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
+
+
+
+
+
+# Default target.
+all: begin gccversion sizebefore build sizeafter end
+
+# Change the build target to build a HEX file or a library.
+build: elf hex eep lss sym
+#build: lib
+
+
+elf: $(TARGET).elf
+hex: $(TARGET).hex
+eep: $(TARGET).eep
+lss: $(TARGET).lss
+sym: $(TARGET).sym
+LIBNAME=lib$(TARGET).a
+lib: $(LIBNAME)
+
+
+
+# Eye candy.
+# AVR Studio 3.x does not check make's exit code but relies on
+# the following magic strings to be generated by the compile job.
+begin:
+	@echo
+	@echo $(MSG_BEGIN)
+
+end:
+	@echo $(MSG_END)
+	@echo
+
+
+# Display size of file.
+HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
+#ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf
+ELFSIZE = $(SIZE) $(TARGET).elf
+
+sizebefore:
+	@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
+	2>/dev/null; echo; fi
+
+sizeafter:
+	@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
+	2>/dev/null; echo; fi
+
+
+
+# Display compiler version information.
+gccversion : 
+	@$(CC) --version
+
+
+
+# Program the device.  
+program: $(TARGET).hex $(TARGET).eep
+	$(PROGRAM_CMD)
+
+
+# Generate avr-gdb config/init file which does the following:
+#     define the reset signal, load the target file, connect to target, and set 
+#     a breakpoint at main().
+gdb-config: 
+	@$(REMOVE) $(GDBINIT_FILE)
+	@echo define reset >> $(GDBINIT_FILE)
+	@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
+	@echo end >> $(GDBINIT_FILE)
+	@echo file $(TARGET).elf >> $(GDBINIT_FILE)
+	@echo target remote $(DEBUG_HOST):$(DEBUG_PORT)  >> $(GDBINIT_FILE)
+ifeq ($(DEBUG_BACKEND),simulavr)
+	@echo load  >> $(GDBINIT_FILE)
+endif
+	@echo break main >> $(GDBINIT_FILE)
+
+debug: gdb-config $(TARGET).elf
+ifeq ($(DEBUG_BACKEND), avarice)
+	@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
+	@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
+	$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
+	@$(WINSHELL) /c pause
+
+else
+	@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
+	$(DEBUG_MFREQ) --port $(DEBUG_PORT)
+endif
+	@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
+
+
+
+
+# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
+COFFCONVERT = $(OBJCOPY) --debugging
+COFFCONVERT += --change-section-address .data-0x800000
+COFFCONVERT += --change-section-address .bss-0x800000
+COFFCONVERT += --change-section-address .noinit-0x800000
+COFFCONVERT += --change-section-address .eeprom-0x810000
+
+
+
+coff: $(TARGET).elf
+	@echo
+	@echo $(MSG_COFF) $(TARGET).cof
+	$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
+
+
+extcoff: $(TARGET).elf
+	@echo
+	@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
+	$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
+
+
+
+# Create final output files (.hex, .eep) from ELF output file.
+%.hex: %.elf
+	@echo
+	@echo $(MSG_FLASH) $@
+	$(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock -R .signature $< $@
+
+%.eep: %.elf
+	@echo
+	@echo $(MSG_EEPROM) $@
+	-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
+	--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0
+
+# Create extended listing file from ELF output file.
+%.lss: %.elf
+	@echo
+	@echo $(MSG_EXTENDED_LISTING) $@
+	$(OBJDUMP) -h -S -z $< > $@
+
+# Create a symbol table from ELF output file.
+%.sym: %.elf
+	@echo
+	@echo $(MSG_SYMBOL_TABLE) $@
+	$(NM) -n $< > $@
+
+
+
+# Create library from object files.
+.SECONDARY : $(TARGET).a
+.PRECIOUS : $(OBJ)
+%.a: $(OBJ)
+	@echo
+	@echo $(MSG_CREATING_LIBRARY) $@
+	$(AR) $@ $(OBJ)
+
+
+# Link: create ELF output file from object files.
+.SECONDARY : $(TARGET).elf
+.PRECIOUS : $(OBJ)
+%.elf: $(OBJ)
+	@echo
+	@echo $(MSG_LINKING) $@
+	$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
+
+
+# Compile: create object files from C source files.
+$(OBJDIR)/%.o : %.c
+	@echo
+	@echo $(MSG_COMPILING) $<
+	$(CC) -c $(ALL_CFLAGS) $< -o $@ 
+
+
+# Compile: create object files from C++ source files.
+$(OBJDIR)/%.o : %.cpp
+	@echo
+	@echo $(MSG_COMPILING_CPP) $<
+	$(CC) -c $(ALL_CPPFLAGS) $< -o $@ 
+
+
+# Compile: create assembler files from C source files.
+%.s : %.c
+	$(CC) -S $(ALL_CFLAGS) $< -o $@
+
+
+# Compile: create assembler files from C++ source files.
+%.s : %.cpp
+	$(CC) -S $(ALL_CPPFLAGS) $< -o $@
+
+
+# Assemble: create object files from assembler source files.
+$(OBJDIR)/%.o : %.S
+	@echo
+	@echo $(MSG_ASSEMBLING) $<
+	$(CC) -c $(ALL_ASFLAGS) $< -o $@
+
+
+# Create preprocessed source for use in sending a bug report.
+%.i : %.c
+	$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ 
+
+
+# Target: clean project.
+clean: begin clean_list end
+
+clean_list :
+	@echo
+	$(REMOVE) $(TARGET).hex
+	$(REMOVE) $(TARGET).eep
+	$(REMOVE) $(TARGET).cof
+	$(REMOVE) $(TARGET).elf
+	$(REMOVE) $(TARGET).map
+	$(REMOVE) $(TARGET).sym
+	$(REMOVE) $(TARGET).lss
+	$(REMOVE) $(OBJ)
+	$(REMOVE) $(LST)
+	$(REMOVE) $(OBJ:.o=.s)
+	$(REMOVE) $(OBJ:.o=.i)
+	$(REMOVE) -r .dep
+	$(REMOVEDIR) $(OBJDIR)
+
+
+# Create object files directory
+$(shell mkdir $(OBJDIR) 2>/dev/null)
+
+
+# Include the dependency files.
+-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
+
+
+# Listing of phony targets.
+.PHONY : all begin finish end sizebefore sizeafter gccversion \
+build elf hex eep lss sym coff extcoff \
+clean clean_list program debug gdb-config
+
diff --git a/sendchar.h b/sendchar.h
index b316654..7c81303 100644
--- a/sendchar.h
+++ b/sendchar.h
@@ -18,8 +18,10 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifndef SENDCHAR_H
 #define SENDCHAR_H
 
+#include <stdint.h>
+
+
 /* transmit a character.  return 0 on success, -1 on error. */
 int8_t sendchar(uint8_t c);
 
 #endif
-
diff --git a/sendchar_null.c b/sendchar_null.c
new file mode 100644
index 0000000..2933306
--- /dev/null
+++ b/sendchar_null.c
@@ -0,0 +1,23 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "sendchar.h"
+
+
+int8_t sendchar(uint8_t c)
+{
+    return 0;
+}
diff --git a/sendchar_uart.c b/sendchar_uart.c
new file mode 100644
index 0000000..0241859
--- /dev/null
+++ b/sendchar_uart.c
@@ -0,0 +1,25 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "uart.h"
+#include "sendchar.h"
+
+
+int8_t sendchar(uint8_t c)
+{
+    uart_putchar(c);
+    return 0;
+}
diff --git a/timer.c b/timer.c
index edbb440..48a38c9 100644
--- a/timer.c
+++ b/timer.c
@@ -20,17 +20,31 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <stdint.h>
 #include "timer.h"
 
+
+// counter resolution 1ms
 volatile uint16_t timer_count = 0;
 
-// Configure timer 0 to generate a timer overflow interrupt every
-// 256*1024 clock cycles, or approx 61 Hz when using 16 MHz clock
-// This demonstrates how to use interrupts to implement a simple
-// inactivity timeout.
 void timer_init(void)
 {
-    TCCR0A = 0x00;
+    // Timer0 CTC mode
+    TCCR0A = 0x02;
+
+#if TIMER_PRESCALER == 1
+    TCCR0B = 0x01;
+#elif TIMER_PRESCALER == 8
+    TCCR0B = 0x02;
+#elif TIMER_PRESCALER == 64
+    TCCR0B = 0x03;
+#elif TIMER_PRESCALER == 256
+    TCCR0B = 0x04;
+#elif TIMER_PRESCALER == 1024
     TCCR0B = 0x05;
-    TIMSK0 = (1<<TOIE0);
+#else
+#   error "Timer prescaler value is NOT vaild."
+#endif
+
+    OCR0A = TIMER_RAW_TOP;
+    TIMSK0 = (1<<OCIE0A);
 }
 
 inline
@@ -65,14 +79,11 @@ uint16_t timer_elapsed(uint16_t last)
     t = timer_count;
     SREG = sreg;
 
-    return TIMER_DIFF(t, last);
+    return TIMER_DIFF_MS(t, last);
 }
 
-// This interrupt routine is run approx 61 times per second.
-// A very simple inactivity timeout is implemented, where we
-// will send a space character and print a message to the
-// hid_listen debug message window.
-ISR(TIMER0_OVF_vect)
+// excecuted once per 1ms.(excess for just timer count?)
+ISR(TIMER0_COMPA_vect)
 {
     timer_count++;
 }
diff --git a/timer.h b/timer.h
index 402d4ac..f9e8181 100644
--- a/timer.h
+++ b/timer.h
@@ -20,7 +20,26 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include <stdint.h>
 
-#define TIMER_DIFF(a, b) ((a) >= (b) ?  (a) - (b) : UINT16_MAX - (b) + (a))
+#ifndef TIMER_PRESCALER
+#   if F_CPU > 16000000
+#       define TIMER_PRESCALER      256
+#   elif F_CPU >= 4000000
+#       define TIMER_PRESCALER      64
+#   else
+#       define TIMER_PRESCALER      8
+#   endif
+#endif
+#define TIMER_RAW_FREQ      (F_CPU/TIMER_PRESCALER)
+#define TIMER_RAW           TCNT0
+#define TIMER_RAW_TOP       (TIMER_RAW_FREQ/1000)
+
+#if (TIMER_RAW_TOP > 255)
+#   error "Timer0 can't count 1ms at this clock freq. Use larger prescaler."
+#endif
+
+#define TIMER_DIFF(a, b, max)   ((a) >= (b) ?  (a) - (b) : (max) - (b) + (a))
+#define TIMER_DIFF_RAW(a, b)    TIMER_DIFF(a, b, UINT8_MAX)
+#define TIMER_DIFF_MS(a, b)     TIMER_DIFF(a, b, UINT16_MAX)
 
 
 extern volatile uint16_t timer_count;
diff --git a/uart.c b/uart.c
new file mode 100644
index 0000000..c17649b
--- /dev/null
+++ b/uart.c
@@ -0,0 +1,129 @@
+// TODO: Teensy support(ATMega32u4/AT90USB128)
+// Fixed for Arduino Duemilanove ATmega168p by Jun Wako
+/* UART Example for Teensy USB Development Board
+ * http://www.pjrc.com/teensy/
+ * Copyright (c) 2009 PJRC.COM, LLC
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+// Version 1.0: Initial Release
+// Version 1.1: Add support for Teensy 2.0, minor optimizations
+
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+
+#include "uart.h"
+
+// These buffers may be any size from 2 to 256 bytes.
+#define RX_BUFFER_SIZE 64
+#define TX_BUFFER_SIZE 40
+
+static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
+static volatile uint8_t tx_buffer_head;
+static volatile uint8_t tx_buffer_tail;
+static volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
+static volatile uint8_t rx_buffer_head;
+static volatile uint8_t rx_buffer_tail;
+
+// Initialize the UART
+void uart_init(uint32_t baud)
+{
+	cli();
+	UBRR0 = (F_CPU / 4 / baud - 1) / 2;
+	UCSR0A = (1<<U2X0);
+	UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
+	UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
+	tx_buffer_head = tx_buffer_tail = 0;
+	rx_buffer_head = rx_buffer_tail = 0;
+	sei();
+}
+
+// Transmit a byte
+void uart_putchar(uint8_t c)
+{
+	uint8_t i;
+
+	i = tx_buffer_head + 1;
+	if (i >= TX_BUFFER_SIZE) i = 0;
+	while (tx_buffer_tail == i) ; // wait until space in buffer
+	//cli();
+	tx_buffer[i] = c;
+	tx_buffer_head = i;
+	UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0) | (1<<UDRIE0);
+	//sei();
+}
+
+// Receive a byte
+uint8_t uart_getchar(void)
+{
+        uint8_t c, i;
+
+	while (rx_buffer_head == rx_buffer_tail) ; // wait for character
+        i = rx_buffer_tail + 1;
+        if (i >= RX_BUFFER_SIZE) i = 0;
+        c = rx_buffer[i];
+        rx_buffer_tail = i;
+        return c;
+}
+
+// Return the number of bytes waiting in the receive buffer.
+// Call this before uart_getchar() to check if it will need
+// to wait for a byte to arrive.
+uint8_t uart_available(void)
+{
+	uint8_t head, tail;
+
+	head = rx_buffer_head;
+	tail = rx_buffer_tail;
+	if (head >= tail) return head - tail;
+	return RX_BUFFER_SIZE + head - tail;
+}
+
+// Transmit Interrupt
+ISR(USART_UDRE_vect)
+{
+	uint8_t i;
+
+	if (tx_buffer_head == tx_buffer_tail) {
+		// buffer is empty, disable transmit interrupt
+		UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
+	} else {
+		i = tx_buffer_tail + 1;
+		if (i >= TX_BUFFER_SIZE) i = 0;
+		UDR0 = tx_buffer[i];
+		tx_buffer_tail = i;
+	}
+}
+
+// Receive Interrupt
+ISR(USART_RX_vect)
+{
+	uint8_t c, i;
+
+	c = UDR0;
+	i = rx_buffer_head + 1;
+	if (i >= RX_BUFFER_SIZE) i = 0;
+	if (i != rx_buffer_tail) {
+		rx_buffer[i] = c;
+		rx_buffer_head = i;
+	}
+}
+
diff --git a/uart.h b/uart.h
new file mode 100644
index 0000000..41136a3
--- /dev/null
+++ b/uart.h
@@ -0,0 +1,11 @@
+#ifndef _uart_included_h_
+#define _uart_included_h_
+
+#include <stdint.h>
+
+void uart_init(uint32_t baud);
+void uart_putchar(uint8_t c);
+uint8_t uart_getchar(void);
+uint8_t uart_available(void);
+
+#endif
diff --git a/usb_keycodes.h b/usb_keycodes.h
index 8b8d4d3..391d21f 100644
--- a/usb_keycodes.h
+++ b/usb_keycodes.h
@@ -16,7 +16,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 /* 
- * Key codes from HID Keyboard/Keypad Page
+ * Key codes: HID Keyboard/Keypad Page(0x07)
  * http://www.usb.org/developers/devclass_docs/Hut1_12.pdf
  */
 #ifndef USB_KEYCODES_H
@@ -353,7 +353,8 @@ enum keycodes {
     KB_CRSEL,
     KB_EXSEL,
 
-    /* NOTE: uses 0xB0-DF for special keycodes */
+    /* NOTE: 0xB0-DF are used as special_keycodes */
+#if 0
     KB_KP_00 = 0xB0,
     KB_KP_000,
     KB_THOUSANDS_SEPARATOR,
@@ -400,6 +401,7 @@ enum keycodes {
     KB_KP_OCTAL,
     KB_KP_DECIMAL,
     KB_KP_HEXADECIMAL,
+#endif
 
     /* Modifiers */
     KB_LCTRL = 0xE0,
@@ -411,7 +413,7 @@ enum keycodes {
     KB_RALT,
     KB_RGUI,
 
-    /* NOTE: uses 0xE8-FF for special keycodes */
+    /* NOTE: 0xE8-FF are used as special_keycodes */
 };
 
 #endif /* USB_KEYCODES_H */
diff --git a/vusb.mk b/vusb.mk
new file mode 100644
index 0000000..7fd5dc0
--- /dev/null
+++ b/vusb.mk
@@ -0,0 +1,17 @@
+OPT_DEFS += -DHOST_VUSB
+
+SRC +=	vusb.c \
+	usbdrv.c \
+	usbdrvasm.S \
+	oddebug.c
+
+ifdef NO_UART
+SRC +=	sendchar_null.c
+else
+SRC +=	sendchar_uart.c \
+	uart.c
+endif
+
+
+# Search Path
+VPATH += $(COMMON_DIR)/vusb:$(COMMON_DIR)/vusb/usbdrv
diff --git a/vusb/host.c b/vusb/host.c
deleted file mode 100644
index 8cd38d0..0000000
--- a/vusb/host.c
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
-Copyright 2011 Jun Wako <wakojun@gmail.com>
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <stdint.h>
-#include <avr/interrupt.h>
-#include "usbdrv.h"
-#include "usbconfig.h"
-#include "print.h"
-#include "usb_keycodes.h"
-#include "host.h"
-#include "host_vusb.h"
-#include "debug.h"
-
-
-static report_keyboard_t report0;
-static report_keyboard_t report1;
-report_keyboard_t *keyboard_report = &report0;
-report_keyboard_t *keyboard_report_prev = &report1;
-
-static uint8_t keyboard_leds = 0;
-static uchar   idleRate = 0;
-
-uint8_t host_keyboard_leds(void)
-{
-    return keyboard_leds;
-}
-
-
-/*------------------------------------------------------------------*
- * Keyboard report operations
- *------------------------------------------------------------------*/
-void host_add_key(uint8_t code)
-{
-    int8_t i = 0;
-    int8_t empty = -1;
-    for (; i < REPORT_KEYS; i++) {
-        if (keyboard_report_prev->keys[i] == code) {
-            keyboard_report->keys[i] = code;
-            break;
-        }
-        if (empty == -1 && keyboard_report_prev->keys[i] == KB_NO && keyboard_report->keys[i] == KB_NO) {
-            empty = i;
-        }
-    }
-    if (i == REPORT_KEYS && empty != -1) {
-        keyboard_report->keys[empty] = code;
-    }
-}
-
-void host_add_mod_bit(uint8_t mod)
-{
-    keyboard_report->mods |= mod;
-}
-
-void host_set_mods(uint8_t mods)
-{
-    keyboard_report->mods = mods;
-}
-
-void host_add_code(uint8_t code)
-{
-    if (IS_MOD(code)) {
-        host_add_mod_bit(MOD_BIT(code));
-    } else {
-        host_add_key(code);
-    }
-}
-
-void host_swap_keyboard_report(void)
-{
-    uint8_t sreg = SREG;
-    cli();
-    report_keyboard_t *tmp = keyboard_report_prev;
-    keyboard_report_prev = keyboard_report;
-    keyboard_report = tmp;
-    SREG = sreg;
-}
-
-void host_clear_keyboard_report(void)
-{
-    keyboard_report->mods = 0;
-    for (int8_t i = 0; i < REPORT_KEYS; i++) {
-        keyboard_report->keys[i] = 0;
-    }
-}
-
-uint8_t host_has_anykey(void)
-{
-    uint8_t cnt = 0;
-    for (int i = 0; i < REPORT_KEYS; i++) {
-        if (keyboard_report->keys[i])
-            cnt++;
-    }
-    return cnt;
-}
-
-uint8_t host_get_first_key(void)
-{
-#ifdef USB_NKRO_ENABLE
-    if (keyboard_nkro) {
-        uint8_t i = 0;
-        for (; i < REPORT_KEYS && !keyboard_report->keys[i]; i++)
-            ;
-        return i<<3 | biton(keyboard_report->keys[i]);
-    }
-#endif
-    return keyboard_report->keys[0];
-}
-
-
-/*------------------------------------------------------------------*
- * Keyboard report send buffer
- *------------------------------------------------------------------*/
-#define KBUF_SIZE 16
-static report_keyboard_t kbuf[KBUF_SIZE];
-static uint8_t kbuf_head = 0;
-static uint8_t kbuf_tail = 0;
-
-void host_vusb_keyboard_send(void)
-{
-    if (usbInterruptIsReady() && kbuf_head != kbuf_tail) {
-        usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t));
-        kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE;
-    }
-}
-
-void host_send_keyboard_report(void)
-{
-    uint8_t next = (kbuf_head + 1) % KBUF_SIZE;
-    if (next != kbuf_tail) {
-        kbuf[kbuf_head] = *keyboard_report;
-        kbuf_head = next;
-    } else {
-        debug("kbuf: full\n");
-    }
-}
-
-
-#if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE)
-void host_mouse_send(report_mouse_t *report)
-{
-    report->report_id = REPORT_ID_MOUSE;
-    if (usbInterruptIsReady3()) {
-        usbSetInterrupt3((void *)report, sizeof(*report));
-    } else {
-        debug("Int3 not ready\n");
-    }
-}
-#endif
-
-#ifdef USB_EXTRA_ENABLE
-void host_system_send(uint16_t data)
-{
-    // Not need static?
-    static uint8_t report[] = { REPORT_ID_SYSTEM, 0, 0 };
-    report[1] = data&0xFF;
-    report[2] = (data>>8)&0xFF;
-    if (usbInterruptIsReady3()) {
-        usbSetInterrupt3((void *)&report, sizeof(report));
-    } else {
-        debug("Int3 not ready\n");
-    }
-}
-
-void host_consumer_send(uint16_t data)
-{
-    static uint16_t last_data = 0;
-    if (data == last_data) return;
-    last_data = data;
-
-    // Not need static?
-    static uint8_t report[] = { REPORT_ID_CONSUMER, 0, 0 };
-    report[1] = data&0xFF;
-    report[2] = (data>>8)&0xFF;
-    if (usbInterruptIsReady3()) {
-        usbSetInterrupt3((void *)&report, sizeof(report));
-    } else {
-        debug("Int3 not ready\n");
-    }
-}
-#endif
-
-
-
-/*------------------------------------------------------------------*
- * Request from host                                                *
- *------------------------------------------------------------------*/
-static struct {
-    uint16_t        len;
-    enum {
-        NONE,
-        SET_LED
-    }               kind;
-} last_req;
-
-usbMsgLen_t usbFunctionSetup(uchar data[8])
-{
-usbRequest_t    *rq = (void *)data;
-
-    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){    /* class request type */
-        if(rq->bRequest == USBRQ_HID_GET_REPORT){
-            debug(" GET_REPORT");
-            /* we only have one report type, so don't look at wValue */
-            usbMsgPtr = (void *)keyboard_report_prev;
-            return sizeof(*keyboard_report_prev);
-        }else if(rq->bRequest == USBRQ_HID_GET_IDLE){
-            debug(" GET_IDLE: ");
-            debug_hex(idleRate);
-            usbMsgPtr = &idleRate;
-            return 1;
-        }else if(rq->bRequest == USBRQ_HID_SET_IDLE){
-            idleRate = rq->wValue.bytes[1];
-            debug(" SET_IDLE: ");
-            debug_hex(idleRate);
-        }else if(rq->bRequest == USBRQ_HID_SET_REPORT){
-            //debug(" SET_REPORT: ");
-            if (rq->wValue.word == 0x0200 && rq->wIndex.word == 0) {
-                last_req.kind = SET_LED;
-                last_req.len = rq->wLength.word;
-            }
-            return USB_NO_MSG; // to get data in usbFunctionWrite
-        }
-        debug("\n");
-    }else{
-        debug("VENDOR\n");
-        /* no vendor specific requests implemented */
-    }
-    return 0;   /* default for not implemented requests: return no data back to host */
-}
-
-uchar usbFunctionWrite(uchar *data, uchar len)
-{
-    if (last_req.len == 0) {
-        return -1;
-    }
-    switch (last_req.kind) {
-        case SET_LED:
-            //debug("SET_LED\n");
-            keyboard_leds = data[0];
-            last_req.len = 0;
-            return 1;
-            break;
-        case NONE:
-        default:
-            return -1;
-            break;
-    }
-    return 1;
-}
-
-
-
-/*------------------------------------------------------------------*
- * Descriptors                                                      *
- *------------------------------------------------------------------*/
-
-/*
- * Report Descriptor for keyboard
- *
- * from an example in HID spec appendix
- */
-PROGMEM uchar keyboard_hid_report[] = {
-    0x05, 0x01,          // Usage Page (Generic Desktop),
-    0x09, 0x06,          // Usage (Keyboard),
-    0xA1, 0x01,          // Collection (Application),
-    0x75, 0x01,          //   Report Size (1),
-    0x95, 0x08,          //   Report Count (8),
-    0x05, 0x07,          //   Usage Page (Key Codes),
-    0x19, 0xE0,          //   Usage Minimum (224),
-    0x29, 0xE7,          //   Usage Maximum (231),
-    0x15, 0x00,          //   Logical Minimum (0),
-    0x25, 0x01,          //   Logical Maximum (1),
-    0x81, 0x02,          //   Input (Data, Variable, Absolute), ;Modifier byte
-    0x95, 0x01,          //   Report Count (1),
-    0x75, 0x08,          //   Report Size (8),
-    0x81, 0x03,          //   Input (Constant),                 ;Reserved byte
-    0x95, 0x05,          //   Report Count (5),
-    0x75, 0x01,          //   Report Size (1),
-    0x05, 0x08,          //   Usage Page (LEDs),
-    0x19, 0x01,          //   Usage Minimum (1),
-    0x29, 0x05,          //   Usage Maximum (5),
-    0x91, 0x02,          //   Output (Data, Variable, Absolute), ;LED report
-    0x95, 0x01,          //   Report Count (1),
-    0x75, 0x03,          //   Report Size (3),
-    0x91, 0x03,          //   Output (Constant),                 ;LED report padding
-    0x95, 0x06,          //   Report Count (6),
-    0x75, 0x08,          //   Report Size (8),
-    0x15, 0x00,          //   Logical Minimum (0),
-    0x25, 0xFF,          //   Logical Maximum(255),
-    0x05, 0x07,          //   Usage Page (Key Codes),
-    0x19, 0x00,          //   Usage Minimum (0),
-    0x29, 0xFF,          //   Usage Maximum (255),
-    0x81, 0x00,          //   Input (Data, Array),
-    0xc0                 // End Collection
-};
-
-/*
- * Report Descriptor for mouse
- *
- * Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
- * http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521
- * http://www.keil.com/forum/15671/
- * http://www.microsoft.com/whdc/device/input/wheel.mspx
- */
-PROGMEM uchar mouse_hid_report[] = {
-    /* mouse */
-    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
-    0x09, 0x02,                    // USAGE (Mouse)
-    0xa1, 0x01,                    // COLLECTION (Application)
-    0x85, REPORT_ID_MOUSE,         //   REPORT_ID (1)
-    0x09, 0x01,                    //   USAGE (Pointer)
-    0xa1, 0x00,                    //   COLLECTION (Physical)
-                                   // ----------------------------  Buttons
-    0x05, 0x09,                    //     USAGE_PAGE (Button)
-    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
-    0x29, 0x05,                    //     USAGE_MAXIMUM (Button 5)
-    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
-    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
-    0x75, 0x01,                    //     REPORT_SIZE (1)
-    0x95, 0x05,                    //     REPORT_COUNT (5)
-    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
-    0x75, 0x03,                    //     REPORT_SIZE (3)
-    0x95, 0x01,                    //     REPORT_COUNT (1)
-    0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
-                                   // ----------------------------  X,Y position
-    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
-    0x09, 0x30,                    //     USAGE (X)
-    0x09, 0x31,                    //     USAGE (Y)
-    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
-    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
-    0x75, 0x08,                    //     REPORT_SIZE (8)
-    0x95, 0x02,                    //     REPORT_COUNT (2)
-    0x81, 0x06,                    //     INPUT (Data,Var,Rel)
-                                   // ----------------------------  Vertical wheel
-    0x09, 0x38,                    //     USAGE (Wheel)
-    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
-    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
-    0x35, 0x00,                    //     PHYSICAL_MINIMUM (0)        - reset physical
-    0x45, 0x00,                    //     PHYSICAL_MAXIMUM (0)
-    0x75, 0x08,                    //     REPORT_SIZE (8)
-    0x95, 0x01,                    //     REPORT_COUNT (1)
-    0x81, 0x06,                    //     INPUT (Data,Var,Rel)
-                                   // ----------------------------  Horizontal wheel
-    0x05, 0x0c,                    //     USAGE_PAGE (Consumer Devices)
-    0x0a, 0x38, 0x02,              //     USAGE (AC Pan)
-    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
-    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
-    0x75, 0x08,                    //     REPORT_SIZE (8)
-    0x95, 0x01,                    //     REPORT_COUNT (1)
-    0x81, 0x06,                    //     INPUT (Data,Var,Rel)
-    0xc0,                          //   END_COLLECTION
-    0xc0,                          // END_COLLECTION
-    /* system control */
-    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
-    0x09, 0x80,                    // USAGE (System Control)
-    0xa1, 0x01,                    // COLLECTION (Application)
-    0x85, REPORT_ID_SYSTEM,        //   REPORT_ID (2)
-    0x15, 0x01,                    //   LOGICAL_MINIMUM (0x1)
-    0x25, 0xb7,                    //   LOGICAL_MAXIMUM (0xb7)
-    0x19, 0x01,                    //   USAGE_MINIMUM (0x1)
-    0x29, 0xb7,                    //   USAGE_MAXIMUM (0xb7)
-    0x75, 0x10,                    //   REPORT_SIZE (16)
-    0x95, 0x01,                    //   REPORT_COUNT (1)
-    0x81, 0x00,                    //   INPUT (Data,Array,Abs)
-    0xc0,                          // END_COLLECTION
-    /* consumer */
-    0x05, 0x0c,                    // USAGE_PAGE (Consumer Devices)
-    0x09, 0x01,                    // USAGE (Consumer Control)
-    0xa1, 0x01,                    // COLLECTION (Application)
-    0x85, REPORT_ID_CONSUMER,      //   REPORT_ID (3)
-    0x15, 0x01,                    //   LOGICAL_MINIMUM (0x1)
-    0x26, 0x9c, 0x02,              //   LOGICAL_MAXIMUM (0x29c)
-    0x19, 0x01,                    //   USAGE_MINIMUM (0x1)
-    0x2a, 0x9c, 0x02,              //   USAGE_MAXIMUM (0x29c)
-    0x75, 0x10,                    //   REPORT_SIZE (16)
-    0x95, 0x01,                    //   REPORT_COUNT (1)
-    0x81, 0x00,                    //   INPUT (Data,Array,Abs)
-    0xc0,                          // END_COLLECTION
-};
-
-
-/* 
- * Descriptor for compite device: Keyboard + Mouse
- * 
- * contains: device, interface, HID and endpoint descriptors
- */
-#if USB_CFG_DESCR_PROPS_CONFIGURATION
-PROGMEM char usbDescriptorConfiguration[] = {    /* USB configuration descriptor */
-    9,          /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
-    USBDESCR_CONFIG,    /* descriptor type */
-    9 + (9 + 9 + 7) + (9 + 9 + 7), 0,
-    //18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 + 9, 0,
-                /* total length of data returned (including inlined descriptors) */
-    2,          /* number of interfaces in this configuration */
-    1,          /* index of this configuration */
-    0,          /* configuration name string index */
-#if USB_CFG_IS_SELF_POWERED
-    (1 << 7) | USBATTR_SELFPOWER,       /* attributes */
-#else
-    (1 << 7),                           /* attributes */
-#endif
-    USB_CFG_MAX_BUS_POWER/2,            /* max USB current in 2mA units */
-
-    /*
-     * Keyboard interface
-     */
-    /* Interface descriptor */
-    9,          /* sizeof(usbDescrInterface): length of descriptor in bytes */
-    USBDESCR_INTERFACE, /* descriptor type */
-    0,          /* index of this interface */
-    0,          /* alternate setting for this interface */
-    USB_CFG_HAVE_INTRIN_ENDPOINT, /* endpoints excl 0: number of endpoint descriptors to follow */
-    USB_CFG_INTERFACE_CLASS,
-    USB_CFG_INTERFACE_SUBCLASS,
-    USB_CFG_INTERFACE_PROTOCOL,
-    0,          /* string index for interface */
-    /* HID descriptor */
-    9,          /* sizeof(usbDescrHID): length of descriptor in bytes */
-    USBDESCR_HID,   /* descriptor type: HID */
-    0x01, 0x01, /* BCD representation of HID version */
-    0x00,       /* target country code */
-    0x01,       /* number of HID Report (or other HID class) Descriptor infos to follow */
-    0x22,       /* descriptor type: report */
-    sizeof(keyboard_hid_report), 0,  /* total length of report descriptor */
-    /* Endpoint descriptor */
-#if USB_CFG_HAVE_INTRIN_ENDPOINT    /* endpoint descriptor for endpoint 1 */
-    7,          /* sizeof(usbDescrEndpoint) */
-    USBDESCR_ENDPOINT,  /* descriptor type = endpoint */
-    (char)0x81, /* IN endpoint number 1 */
-    0x03,       /* attrib: Interrupt endpoint */
-    8, 0,       /* maximum packet size */
-    USB_CFG_INTR_POLL_INTERVAL, /* in ms */
-#endif
-
-    /*
-     * Mouse interface
-     */
-    /* Interface descriptor */
-    9,          /* sizeof(usbDescrInterface): length of descriptor in bytes */
-    USBDESCR_INTERFACE, /* descriptor type */
-    1,          /* index of this interface */
-    0,          /* alternate setting for this interface */
-    USB_CFG_HAVE_INTRIN_ENDPOINT3, /* endpoints excl 0: number of endpoint descriptors to follow */
-    0x03,       /* CLASS: HID */
-    0,          /* SUBCLASS: none */
-    0,          /* PROTOCOL: none */
-    0,          /* string index for interface */
-    /* HID descriptor */
-    9,          /* sizeof(usbDescrHID): length of descriptor in bytes */
-    USBDESCR_HID,   /* descriptor type: HID */
-    0x01, 0x01, /* BCD representation of HID version */
-    0x00,       /* target country code */
-    0x01,       /* number of HID Report (or other HID class) Descriptor infos to follow */
-    0x22,       /* descriptor type: report */
-    sizeof(mouse_hid_report), 0,  /* total length of report descriptor */
-#if USB_CFG_HAVE_INTRIN_ENDPOINT3   /* endpoint descriptor for endpoint 3 */
-    /* Endpoint descriptor */
-    7,          /* sizeof(usbDescrEndpoint) */
-    USBDESCR_ENDPOINT,  /* descriptor type = endpoint */
-    (char)(0x80 | USB_CFG_EP3_NUMBER), /* IN endpoint number 3 */
-    0x03,       /* attrib: Interrupt endpoint */
-    8, 0,       /* maximum packet size */
-    USB_CFG_INTR_POLL_INTERVAL, /* in ms */
-#endif
-};
-#endif
-
-
-USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq)
-{
-    usbMsgLen_t len = 0;
-
-    debug("usbFunctionDescriptor: ");
-    debug_hex(rq->bmRequestType); debug(" ");
-    debug_hex(rq->bRequest); debug(" ");
-    debug_hex16(rq->wValue.word); debug(" ");
-    debug_hex16(rq->wIndex.word); debug(" ");
-    debug_hex16(rq->wLength.word); debug("\n");
-
-    switch (rq->wValue.bytes[1]) {
-#if USB_CFG_DESCR_PROPS_CONFIGURATION
-        case USBDESCR_CONFIG:
-            usbMsgPtr = (unsigned char *)usbDescriptorConfiguration;
-            len = sizeof(usbDescriptorConfiguration);
-            break;
-#endif
-        case USBDESCR_HID:
-            usbMsgPtr = (unsigned char *)(usbDescriptorConfiguration + 18);
-            len = 9;
-            break;
-        case USBDESCR_HID_REPORT:
-            /* interface index */
-            switch (rq->wIndex.word) {
-                case 0:
-                    usbMsgPtr = keyboard_hid_report;
-                    len = sizeof(keyboard_hid_report);
-                    break;
-                case 1:
-                    usbMsgPtr = mouse_hid_report;
-                    len = sizeof(mouse_hid_report);
-                    break;
-            }
-            break;
-    }
-    debug("desc len: "); debug_hex(len); debug("\n");
-    return len;
-}
diff --git a/vusb/host_vusb.h b/vusb/host_vusb.h
deleted file mode 100644
index be9886e..0000000
--- a/vusb/host_vusb.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-Copyright 2011 Jun Wako <wakojun@gmail.com>
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef HOST_VUSB_H
-#define HOST_VUSB_H
-
-void host_vusb_keyboard_send(void);
-
-#endif
diff --git a/vusb/main.c b/vusb/main.c
new file mode 100644
index 0000000..1bf9035
--- /dev/null
+++ b/vusb/main.c
@@ -0,0 +1,99 @@
+/* Name: main.c
+ * Project: hid-mouse, a very simple HID example
+ * Author: Christian Starkjohann
+ * Creation Date: 2008-04-07
+ * Tabsize: 4
+ * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * This Revision: $Id: main.c 790 2010-05-30 21:00:26Z cs $
+ */
+#include <stdint.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+#include <avr/sleep.h>
+#include <util/delay.h>
+#include "usbdrv.h"
+#include "oddebug.h"
+#include "vusb.h"
+#include "keyboard.h"
+#include "host.h"
+#include "timer.h"
+#include "uart.h"
+#include "debug.h"
+
+
+#define UART_BAUD_RATE 115200
+
+
+/* This is from main.c of USBaspLoader */
+static void initForUsbConnectivity(void)
+{
+    uint8_t i = 0;
+
+    usbInit();
+    /* enforce USB re-enumerate: */
+    usbDeviceDisconnect();  /* do this while interrupts are disabled */
+    while(--i){         /* fake USB disconnect for > 250 ms */
+        wdt_reset();
+        _delay_ms(1);
+    }
+    usbDeviceConnect();
+    sei();
+}
+
+int main(void)
+{
+    bool suspended = false;
+#if USB_COUNT_SOF
+    uint16_t last_timer = timer_read();
+#endif
+
+    CLKPR = 0x80, CLKPR = 0;
+#ifndef PS2_USE_USART
+    uart_init(UART_BAUD_RATE);
+#endif
+
+    debug_enable = true;
+    print_enable = true;
+
+    debug("keyboard_init()\n");
+    keyboard_init();
+    host_set_driver(vusb_driver());
+
+    debug("initForUsbConnectivity()\n");
+    initForUsbConnectivity();
+
+    debug("main loop\n");
+    while (1) {
+#if USB_COUNT_SOF
+        if (usbSofCount != 0) {
+            suspended = false;
+            usbSofCount = 0;
+            last_timer = timer_read();
+        } else {
+            // Suspend when no SOF in 3ms-10ms(7.1.7.4 Suspending of USB1.1)
+            if (timer_elapsed(last_timer) > 5) {
+                suspended = true;
+/*
+                uart_putchar('S');
+                _delay_ms(1);
+                cli();
+                set_sleep_mode(SLEEP_MODE_PWR_DOWN);
+                sleep_enable();
+                sleep_bod_disable();
+                sei();
+                sleep_cpu();
+                sleep_disable();
+                _delay_ms(10);
+                uart_putchar('W');
+*/
+            }
+        }
+#endif
+        if (!suspended)
+            usbPoll();
+        keyboard_proc();
+        if (!suspended)
+            vusb_transfer_keyboard();
+    }
+}
diff --git a/vusb/vusb.c b/vusb/vusb.c
new file mode 100644
index 0000000..638611f
--- /dev/null
+++ b/vusb/vusb.c
@@ -0,0 +1,462 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include "usbdrv.h"
+#include "usbconfig.h"
+#include "host.h"
+#include "report.h"
+#include "print.h"
+#include "debug.h"
+#include "host_driver.h"
+#include "vusb.h"
+
+
+static uint8_t vusb_keyboard_leds = 0;
+static uint8_t vusb_idle_rate = 0;
+
+/* Keyboard report send buffer */
+#define KBUF_SIZE 16
+static report_keyboard_t kbuf[KBUF_SIZE];
+static uint8_t kbuf_head = 0;
+static uint8_t kbuf_tail = 0;
+
+
+/* transfer keyboard report from buffer */
+void vusb_transfer_keyboard(void)
+{
+    if (usbInterruptIsReady()) {
+       if (kbuf_head != kbuf_tail) {
+            usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t));
+            kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE;
+       }
+    }
+}
+
+
+/*------------------------------------------------------------------*
+ * Host driver
+ *------------------------------------------------------------------*/
+static uint8_t keyboard_leds(void);
+static void send_keyboard(report_keyboard_t *report);
+static void send_mouse(report_mouse_t *report);
+static void send_system(uint16_t data);
+static void send_consumer(uint16_t data);
+
+static host_driver_t driver = {
+        keyboard_leds,
+        send_keyboard,
+        send_mouse,
+        send_system,
+        send_consumer
+};
+
+host_driver_t *vusb_driver(void)
+{
+    return &driver;
+}
+
+static uint8_t keyboard_leds(void) {
+    return vusb_keyboard_leds;
+}
+
+static void send_keyboard(report_keyboard_t *report)
+{
+    uint8_t next = (kbuf_head + 1) % KBUF_SIZE;
+    if (next != kbuf_tail) {
+        kbuf[kbuf_head] = *report;
+        kbuf_head = next;
+    } else {
+        debug("kbuf: full\n");
+    }
+}
+
+
+static void send_mouse(report_mouse_t *report)
+{
+    report->report_id = REPORT_ID_MOUSE;
+    if (usbInterruptIsReady3()) {
+        usbSetInterrupt3((void *)report, sizeof(*report));
+    }
+}
+
+static void send_system(uint16_t data)
+{
+    // Not need static?
+    static uint8_t report[] = { REPORT_ID_SYSTEM, 0, 0 };
+    report[1] = data&0xFF;
+    report[2] = (data>>8)&0xFF;
+    if (usbInterruptIsReady3()) {
+        usbSetInterrupt3((void *)&report, sizeof(report));
+    }
+}
+
+static void send_consumer(uint16_t data)
+{
+    static uint16_t last_data = 0;
+    if (data == last_data) return;
+    last_data = data;
+
+    // Not need static?
+    static uint8_t report[] = { REPORT_ID_CONSUMER, 0, 0 };
+    report[1] = data&0xFF;
+    report[2] = (data>>8)&0xFF;
+    if (usbInterruptIsReady3()) {
+        usbSetInterrupt3((void *)&report, sizeof(report));
+    }
+}
+
+
+
+/*------------------------------------------------------------------*
+ * Request from host                                                *
+ *------------------------------------------------------------------*/
+static struct {
+    uint16_t        len;
+    enum {
+        NONE,
+        SET_LED
+    }               kind;
+} last_req;
+
+usbMsgLen_t usbFunctionSetup(uchar data[8])
+{
+usbRequest_t    *rq = (void *)data;
+
+    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){    /* class request type */
+        if(rq->bRequest == USBRQ_HID_GET_REPORT){
+            debug("GET_REPORT:");
+            /* we only have one report type, so don't look at wValue */
+            usbMsgPtr = (void *)keyboard_report_prev;
+            return sizeof(*keyboard_report_prev);
+        }else if(rq->bRequest == USBRQ_HID_GET_IDLE){
+            debug("GET_IDLE: ");
+            //debug_hex(vusb_idle_rate);
+            usbMsgPtr = &vusb_idle_rate;
+            return 1;
+        }else if(rq->bRequest == USBRQ_HID_SET_IDLE){
+            vusb_idle_rate = rq->wValue.bytes[1];
+            debug("SET_IDLE: ");
+            debug_hex(vusb_idle_rate);
+        }else if(rq->bRequest == USBRQ_HID_SET_REPORT){
+            debug("SET_REPORT: ");
+            // Report Type: 0x02(Out)/ReportID: 0x00(none) && Interface: 0(keyboard)
+            if (rq->wValue.word == 0x0200 && rq->wIndex.word == 0) {
+                debug("SET_LED: ");
+                last_req.kind = SET_LED;
+                last_req.len = rq->wLength.word;
+            }
+            return USB_NO_MSG; // to get data in usbFunctionWrite
+        } else {
+            debug("UNKNOWN:");
+        }
+    }else{
+        debug("VENDOR:");
+        /* no vendor specific requests implemented */
+    }
+    debug("\n");
+    return 0;   /* default for not implemented requests: return no data back to host */
+}
+
+uchar usbFunctionWrite(uchar *data, uchar len)
+{
+    if (last_req.len == 0) {
+        return -1;
+    }
+    switch (last_req.kind) {
+        case SET_LED:
+            debug("SET_LED: ");
+            debug_hex(data[0]);
+            debug("\n");
+            vusb_keyboard_leds = data[0];
+            last_req.len = 0;
+            return 1;
+            break;
+        case NONE:
+        default:
+            return -1;
+            break;
+    }
+    return 1;
+}
+
+
+
+/*------------------------------------------------------------------*
+ * Descriptors                                                      *
+ *------------------------------------------------------------------*/
+
+/*
+ * Report Descriptor for keyboard
+ *
+ * from an example in HID spec appendix
+ */
+PROGMEM uchar keyboard_hid_report[] = {
+    0x05, 0x01,          // Usage Page (Generic Desktop),
+    0x09, 0x06,          // Usage (Keyboard),
+    0xA1, 0x01,          // Collection (Application),
+    0x75, 0x01,          //   Report Size (1),
+    0x95, 0x08,          //   Report Count (8),
+    0x05, 0x07,          //   Usage Page (Key Codes),
+    0x19, 0xE0,          //   Usage Minimum (224),
+    0x29, 0xE7,          //   Usage Maximum (231),
+    0x15, 0x00,          //   Logical Minimum (0),
+    0x25, 0x01,          //   Logical Maximum (1),
+    0x81, 0x02,          //   Input (Data, Variable, Absolute), ;Modifier byte
+    0x95, 0x01,          //   Report Count (1),
+    0x75, 0x08,          //   Report Size (8),
+    0x81, 0x03,          //   Input (Constant),                 ;Reserved byte
+    0x95, 0x05,          //   Report Count (5),
+    0x75, 0x01,          //   Report Size (1),
+    0x05, 0x08,          //   Usage Page (LEDs),
+    0x19, 0x01,          //   Usage Minimum (1),
+    0x29, 0x05,          //   Usage Maximum (5),
+    0x91, 0x02,          //   Output (Data, Variable, Absolute), ;LED report
+    0x95, 0x01,          //   Report Count (1),
+    0x75, 0x03,          //   Report Size (3),
+    0x91, 0x03,          //   Output (Constant),                 ;LED report padding
+    0x95, 0x06,          //   Report Count (6),
+    0x75, 0x08,          //   Report Size (8),
+    0x15, 0x00,          //   Logical Minimum (0),
+    0x25, 0xFF,          //   Logical Maximum(255),
+    0x05, 0x07,          //   Usage Page (Key Codes),
+    0x19, 0x00,          //   Usage Minimum (0),
+    0x29, 0xFF,          //   Usage Maximum (255),
+    0x81, 0x00,          //   Input (Data, Array),
+    0xc0                 // End Collection
+};
+
+/*
+ * Report Descriptor for mouse
+ *
+ * Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
+ * http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521
+ * http://www.keil.com/forum/15671/
+ * http://www.microsoft.com/whdc/device/input/wheel.mspx
+ */
+PROGMEM uchar mouse_hid_report[] = {
+    /* mouse */
+    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
+    0x09, 0x02,                    // USAGE (Mouse)
+    0xa1, 0x01,                    // COLLECTION (Application)
+    0x85, REPORT_ID_MOUSE,         //   REPORT_ID (1)
+    0x09, 0x01,                    //   USAGE (Pointer)
+    0xa1, 0x00,                    //   COLLECTION (Physical)
+                                   // ----------------------------  Buttons
+    0x05, 0x09,                    //     USAGE_PAGE (Button)
+    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
+    0x29, 0x05,                    //     USAGE_MAXIMUM (Button 5)
+    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
+    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
+    0x75, 0x01,                    //     REPORT_SIZE (1)
+    0x95, 0x05,                    //     REPORT_COUNT (5)
+    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
+    0x75, 0x03,                    //     REPORT_SIZE (3)
+    0x95, 0x01,                    //     REPORT_COUNT (1)
+    0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
+                                   // ----------------------------  X,Y position
+    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
+    0x09, 0x30,                    //     USAGE (X)
+    0x09, 0x31,                    //     USAGE (Y)
+    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
+    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
+    0x75, 0x08,                    //     REPORT_SIZE (8)
+    0x95, 0x02,                    //     REPORT_COUNT (2)
+    0x81, 0x06,                    //     INPUT (Data,Var,Rel)
+                                   // ----------------------------  Vertical wheel
+    0x09, 0x38,                    //     USAGE (Wheel)
+    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
+    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
+    0x35, 0x00,                    //     PHYSICAL_MINIMUM (0)        - reset physical
+    0x45, 0x00,                    //     PHYSICAL_MAXIMUM (0)
+    0x75, 0x08,                    //     REPORT_SIZE (8)
+    0x95, 0x01,                    //     REPORT_COUNT (1)
+    0x81, 0x06,                    //     INPUT (Data,Var,Rel)
+                                   // ----------------------------  Horizontal wheel
+    0x05, 0x0c,                    //     USAGE_PAGE (Consumer Devices)
+    0x0a, 0x38, 0x02,              //     USAGE (AC Pan)
+    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
+    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
+    0x75, 0x08,                    //     REPORT_SIZE (8)
+    0x95, 0x01,                    //     REPORT_COUNT (1)
+    0x81, 0x06,                    //     INPUT (Data,Var,Rel)
+    0xc0,                          //   END_COLLECTION
+    0xc0,                          // END_COLLECTION
+    /* system control */
+    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
+    0x09, 0x80,                    // USAGE (System Control)
+    0xa1, 0x01,                    // COLLECTION (Application)
+    0x85, REPORT_ID_SYSTEM,        //   REPORT_ID (2)
+    0x15, 0x01,                    //   LOGICAL_MINIMUM (0x1)
+    0x25, 0xb7,                    //   LOGICAL_MAXIMUM (0xb7)
+    0x19, 0x01,                    //   USAGE_MINIMUM (0x1)
+    0x29, 0xb7,                    //   USAGE_MAXIMUM (0xb7)
+    0x75, 0x10,                    //   REPORT_SIZE (16)
+    0x95, 0x01,                    //   REPORT_COUNT (1)
+    0x81, 0x00,                    //   INPUT (Data,Array,Abs)
+    0xc0,                          // END_COLLECTION
+    /* consumer */
+    0x05, 0x0c,                    // USAGE_PAGE (Consumer Devices)
+    0x09, 0x01,                    // USAGE (Consumer Control)
+    0xa1, 0x01,                    // COLLECTION (Application)
+    0x85, REPORT_ID_CONSUMER,      //   REPORT_ID (3)
+    0x15, 0x01,                    //   LOGICAL_MINIMUM (0x1)
+    0x26, 0x9c, 0x02,              //   LOGICAL_MAXIMUM (0x29c)
+    0x19, 0x01,                    //   USAGE_MINIMUM (0x1)
+    0x2a, 0x9c, 0x02,              //   USAGE_MAXIMUM (0x29c)
+    0x75, 0x10,                    //   REPORT_SIZE (16)
+    0x95, 0x01,                    //   REPORT_COUNT (1)
+    0x81, 0x00,                    //   INPUT (Data,Array,Abs)
+    0xc0,                          // END_COLLECTION
+};
+
+
+/* 
+ * Descriptor for compite device: Keyboard + Mouse
+ * 
+ * contains: device, interface, HID and endpoint descriptors
+ */
+#if USB_CFG_DESCR_PROPS_CONFIGURATION
+PROGMEM char usbDescriptorConfiguration[] = {    /* USB configuration descriptor */
+    9,          /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
+    USBDESCR_CONFIG,    /* descriptor type */
+    9 + (9 + 9 + 7) + (9 + 9 + 7), 0,
+    //18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 + 9, 0,
+                /* total length of data returned (including inlined descriptors) */
+    2,          /* number of interfaces in this configuration */
+    1,          /* index of this configuration */
+    0,          /* configuration name string index */
+#if USB_CFG_IS_SELF_POWERED
+    (1 << 7) | USBATTR_SELFPOWER,       /* attributes */
+#else
+    (1 << 7),                           /* attributes */
+#endif
+    USB_CFG_MAX_BUS_POWER/2,            /* max USB current in 2mA units */
+
+    /*
+     * Keyboard interface
+     */
+    /* Interface descriptor */
+    9,          /* sizeof(usbDescrInterface): length of descriptor in bytes */
+    USBDESCR_INTERFACE, /* descriptor type */
+    0,          /* index of this interface */
+    0,          /* alternate setting for this interface */
+    USB_CFG_HAVE_INTRIN_ENDPOINT, /* endpoints excl 0: number of endpoint descriptors to follow */
+    USB_CFG_INTERFACE_CLASS,
+    USB_CFG_INTERFACE_SUBCLASS,
+    USB_CFG_INTERFACE_PROTOCOL,
+    0,          /* string index for interface */
+    /* HID descriptor */
+    9,          /* sizeof(usbDescrHID): length of descriptor in bytes */
+    USBDESCR_HID,   /* descriptor type: HID */
+    0x01, 0x01, /* BCD representation of HID version */
+    0x00,       /* target country code */
+    0x01,       /* number of HID Report (or other HID class) Descriptor infos to follow */
+    0x22,       /* descriptor type: report */
+    sizeof(keyboard_hid_report), 0,  /* total length of report descriptor */
+    /* Endpoint descriptor */
+#if USB_CFG_HAVE_INTRIN_ENDPOINT    /* endpoint descriptor for endpoint 1 */
+    7,          /* sizeof(usbDescrEndpoint) */
+    USBDESCR_ENDPOINT,  /* descriptor type = endpoint */
+    (char)0x81, /* IN endpoint number 1 */
+    0x03,       /* attrib: Interrupt endpoint */
+    8, 0,       /* maximum packet size */
+    USB_CFG_INTR_POLL_INTERVAL, /* in ms */
+#endif
+
+    /*
+     * Mouse interface
+     */
+    /* Interface descriptor */
+    9,          /* sizeof(usbDescrInterface): length of descriptor in bytes */
+    USBDESCR_INTERFACE, /* descriptor type */
+    1,          /* index of this interface */
+    0,          /* alternate setting for this interface */
+    USB_CFG_HAVE_INTRIN_ENDPOINT3, /* endpoints excl 0: number of endpoint descriptors to follow */
+    0x03,       /* CLASS: HID */
+    0,          /* SUBCLASS: none */
+    0,          /* PROTOCOL: none */
+    0,          /* string index for interface */
+    /* HID descriptor */
+    9,          /* sizeof(usbDescrHID): length of descriptor in bytes */
+    USBDESCR_HID,   /* descriptor type: HID */
+    0x01, 0x01, /* BCD representation of HID version */
+    0x00,       /* target country code */
+    0x01,       /* number of HID Report (or other HID class) Descriptor infos to follow */
+    0x22,       /* descriptor type: report */
+    sizeof(mouse_hid_report), 0,  /* total length of report descriptor */
+#if USB_CFG_HAVE_INTRIN_ENDPOINT3   /* endpoint descriptor for endpoint 3 */
+    /* Endpoint descriptor */
+    7,          /* sizeof(usbDescrEndpoint) */
+    USBDESCR_ENDPOINT,  /* descriptor type = endpoint */
+    (char)(0x80 | USB_CFG_EP3_NUMBER), /* IN endpoint number 3 */
+    0x03,       /* attrib: Interrupt endpoint */
+    8, 0,       /* maximum packet size */
+    USB_CFG_INTR_POLL_INTERVAL, /* in ms */
+#endif
+};
+#endif
+
+
+USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq)
+{
+    usbMsgLen_t len = 0;
+
+/*
+    debug("usbFunctionDescriptor: ");
+    debug_hex(rq->bmRequestType); debug(" ");
+    debug_hex(rq->bRequest); debug(" ");
+    debug_hex16(rq->wValue.word); debug(" ");
+    debug_hex16(rq->wIndex.word); debug(" ");
+    debug_hex16(rq->wLength.word); debug("\n");
+*/
+    switch (rq->wValue.bytes[1]) {
+#if USB_CFG_DESCR_PROPS_CONFIGURATION
+        case USBDESCR_CONFIG:
+            usbMsgPtr = (unsigned char *)usbDescriptorConfiguration;
+            len = sizeof(usbDescriptorConfiguration);
+            break;
+#endif
+        case USBDESCR_HID:
+            switch (rq->wValue.bytes[0]) {
+                case 0:
+                    usbMsgPtr = (unsigned char *)(usbDescriptorConfiguration + 9 + 9);
+                    len = 9;
+                    break;
+                case 1:
+                    usbMsgPtr = (unsigned char *)(usbDescriptorConfiguration + 9 + (9 + 9 + 7) + 9);
+                    len = 9;
+                    break;
+            }
+            break;
+        case USBDESCR_HID_REPORT:
+            /* interface index */
+            switch (rq->wIndex.word) {
+                case 0:
+                    usbMsgPtr = keyboard_hid_report;
+                    len = sizeof(keyboard_hid_report);
+                    break;
+                case 1:
+                    usbMsgPtr = mouse_hid_report;
+                    len = sizeof(mouse_hid_report);
+                    break;
+            }
+            break;
+    }
+    //debug("desc len: "); debug_hex(len); debug("\n");
+    return len;
+}
diff --git a/vusb/vusb.h b/vusb/vusb.h
new file mode 100644
index 0000000..5accf23
--- /dev/null
+++ b/vusb/vusb.h
@@ -0,0 +1,27 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef VUSB_H
+#define VUSB_H
+
+#include "host_driver.h"
+
+
+host_driver_t *vusb_driver(void);
+void vusb_transfer_keyboard(void);
+
+#endif