소스 검색

Added Bulegiga iWRAP support into HHKB.(Bluetooth)

tmk 14 년 전
부모
커밋
e67c988824
81개의 변경된 파일3150개의 추가작업 그리고 537개의 파일을 삭제
  1. 0 11
      Makefile.vusb
  2. 62 0
      POWER.txt
  3. 2 2
      README
  4. 10 10
      adb_usb/Makefile
  5. 8 0
      adb_usb/README
  6. 2 2
      adb_usb/config.h
  7. 42 14
      command.c
  8. 2 0
      command.h
  9. 9 6
      common.mk
  10. 40 0
      hhkb/FUSE.txt
  11. 91 0
      hhkb/Makefile.iwrap
  12. 11 8
      hhkb/Makefile.pjrc
  13. 17 12
      hhkb/Makefile.vusb
  14. 92 21
      hhkb/README
  15. 55 0
      hhkb/config_iwrap.h
  16. 1 5
      hhkb/config_pjrc.h
  17. 6 6
      hhkb/config_vusb.h
  18. 4 0
      hhkb/doc/Bluetooth.txt
  19. 2 0
      hhkb/doc/Bluetooth_img/.picasa.ini
  20. BIN
      hhkb/doc/Bluetooth_img/BT_circuit.jpg
  21. 0 0
      hhkb/doc/HHKB_img/HHKB_TP1684.jpg
  22. 0 0
      hhkb/doc/HHKB_img/HHKB_chart1.jpg
  23. 0 0
      hhkb/doc/HHKB_img/HHKB_chart2.jpg
  24. 0 0
      hhkb/doc/HHKB_img/HHKB_connector.jpg
  25. 0 0
      hhkb/doc/HHKB_img/HHKB_controller.jpg
  26. 0 0
      hhkb/doc/HHKB_img/HHKB_keyswitch.jpg
  27. 0 0
      hhkb/doc/HHKB_img/connector_contact.jpg
  28. 0 0
      hhkb/doc/HHKB_img/logic_analyzer.jpg
  29. 0 0
      hhkb/doc/HHKB_img/probe_contact.jpg
  30. 0 0
      hhkb/doc/HHKB_img/teensy_install.jpg
  31. 0 0
      hhkb/doc/HHKB_img/teensy_wiring.jpg
  32. 68 47
      hhkb/keymap.c
  33. 49 17
      hhkb/matrix.c
  34. 13 3
      hhkb/usbconfig.h
  35. 190 0
      host.c
  36. 5 84
      host.h
  37. 33 0
      host_driver.h
  38. 10 0
      iwrap.mk
  39. 376 0
      iwrap/iWRAP.txt
  40. 467 0
      iwrap/iwrap.c
  41. 49 0
      iwrap/iwrap.h
  42. 378 0
      iwrap/main.c
  43. 156 0
      iwrap/suart.S
  44. 8 0
      iwrap/suart.h
  45. 159 0
      iwrap/wd.h
  46. 5 4
      keyboard.c
  47. 2 2
      layer.c
  48. 8 8
      macway/Makefile
  49. 2 2
      macway/config.h
  50. 0 58
      macway/doc/back.jpg
  51. 5 5
      mousekey.c
  52. 5 5
      pjrc.mk
  53. 5 5
      pjrc/host.c
  54. 3 0
      pjrc/main.c
  55. 76 0
      pjrc/pjrc.c
  56. 26 0
      pjrc/pjrc.h
  57. 17 17
      pjrc/usb.c
  58. 1 1
      pjrc/usb.h
  59. 2 2
      pjrc/usb_keyboard.c
  60. 13 0
      print.c
  61. 2 0
      print.h
  62. 9 9
      ps2_usb/Makefile
  63. 10 9
      ps2_usb/Makefile.vusb
  64. 2 2
      ps2_usb/config_pjrc.h
  65. 2 2
      ps2_usb/config_vusb.h
  66. 3 3
      ps2_usb/keymap.c
  67. 1 0
      ps2_usb/matrix.c
  68. 96 0
      report.h
  69. 0 0
      rules.mk
  70. 3 1
      sendchar.h
  71. 5 5
      sendchar_null.c
  72. 25 0
      sendchar_uart.c
  73. 23 12
      timer.c
  74. 20 1
      timer.h
  75. 129 0
      uart.c
  76. 11 0
      uart.h
  77. 5 3
      usb_keycodes.h
  78. 17 0
      vusb.mk
  79. 99 0
      vusb/main.c
  80. 74 133
      vusb/vusb.c
  81. 27 0
      vusb/vusb.h

+ 0 - 11
Makefile.vusb

@@ -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

+ 62 - 0
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

+ 2 - 2
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

+ 10 - 10
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

+ 8 - 0
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

+ 2 - 2
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)) \
 )
 
 

+ 42 - 14
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");

+ 2 - 0
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

+ 9 - 6
Makefile.common → common.mk

@@ -19,17 +19,20 @@ ifdef PS2_MOUSE_ENABLE
     OPT_DEFS += -DPS2_MOUSE_ENABLE
 endif
 
-ifdef USB_EXTRA_ENABLE
-    OPT_DEFS += -DUSB_EXTRA_ENABLE
+ifdef EXTRAKEY_ENABLE
+    OPT_DEFS += -DEXTRAKEY_ENABLE
 endif
 
-ifdef USB_NKRO_ENABLE
-    OPT_DEFS += -DUSB_NKRO_ENABLE
+ifdef NKRO_ENABLE
+    OPT_DEFS += -DNKRO_ENABLE
 endif
 
 ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE)
-    OPT_DEFS += -DUSB_MOUSE_ENABLE
+    OPT_DEFS += -DMOUSE_ENABLE
 endif
 
+# Search Path
+VPATH += $(COMMON_DIR)
 
-include $(COMMON_DIR)/Makefile.rules
+
+include $(COMMON_DIR)/rules.mk

+ 40 - 0
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)

+ 91 - 0
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

+ 11 - 8
hhkb/Makefile → hhkb/Makefile.pjrc

@@ -13,10 +13,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_pjrc.h
 
@@ -41,8 +41,8 @@ F_CPU = 16000000
 #   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
+EXTRAKEY_ENABLE = yes	# Audio control and System control
+NKRO_ENABLE = yes	# USB Nkey Rollover
 
 
 
@@ -51,5 +51,8 @@ PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex
 
 
 
-include $(COMMON_DIR)/Makefile.pjrc
-include $(COMMON_DIR)/Makefile.common
+# Search Path
+VPATH = $(TARGET_DIR)
+
+include $(COMMON_DIR)/pjrc.mk
+include $(COMMON_DIR)/common.mk

+ 17 - 12
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

+ 92 - 21
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

+ 55 - 0
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

+ 1 - 5
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

+ 6 - 6
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

+ 4 - 0
hhkb/doc/Bluetooth.txt

@@ -0,0 +1,4 @@
+HHKB Bluetooth mod
+==================
+See this article:
+http://geekhack.org/showwiki.php?title=Island:20851

+ 2 - 0
hhkb/doc/Bluetooth_img/.picasa.ini

@@ -0,0 +1,2 @@
+[Picasa]
+name=Bluetooth_img

BIN
hhkb/doc/Bluetooth_img/BT_circuit.jpg


+ 0 - 0
hhkb/doc/HHKB_TP1684.jpg → hhkb/doc/HHKB_img/HHKB_TP1684.jpg


+ 0 - 0
hhkb/doc/HHKB_chart1.jpg → hhkb/doc/HHKB_img/HHKB_chart1.jpg


+ 0 - 0
hhkb/doc/HHKB_chart2.jpg → hhkb/doc/HHKB_img/HHKB_chart2.jpg


+ 0 - 0
hhkb/doc/HHKB_connector.jpg → hhkb/doc/HHKB_img/HHKB_connector.jpg


+ 0 - 0
hhkb/doc/HHKB_controller.jpg → hhkb/doc/HHKB_img/HHKB_controller.jpg


+ 0 - 0
hhkb/doc/HHKB_keyswitch.jpg → hhkb/doc/HHKB_img/HHKB_keyswitch.jpg


+ 0 - 0
hhkb/doc/connector_contact.jpg → hhkb/doc/HHKB_img/connector_contact.jpg


+ 0 - 0
hhkb/doc/logic_analyzer.jpg → hhkb/doc/HHKB_img/logic_analyzer.jpg


+ 0 - 0
hhkb/doc/probe_contact.jpg → hhkb/doc/HHKB_img/probe_contact.jpg


+ 0 - 0
hhkb/doc/teensy_install.jpg → hhkb/doc/HHKB_img/teensy_install.jpg


+ 0 - 0
hhkb/doc/teensy_wiring.jpg → hhkb/doc/HHKB_img/teensy_wiring.jpg


+ 68 - 47
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
 };
 
 

+ 49 - 17
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;
 }
 

+ 13 - 3
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__ */

+ 190 - 0
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");
+    }
+}

+ 5 - 84
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

+ 33 - 0
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

+ 10 - 0
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

+ 376 - 0
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

+ 467 - 0
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
+}

+ 49 - 0
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

+ 378 - 0
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;
+    }
+}

+ 156 - 0
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

+ 8 - 0
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 */

+ 159 - 0
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_ */

+ 5 - 4
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

+ 2 - 2
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;

+ 8 - 8
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

+ 2 - 2
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)) \
 )
 
 

+ 0 - 58
macway/doc/back.jpg

@@ -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();
-    }
-}

+ 5 - 5
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;
         }

+ 5 - 5
Makefile.pjrc → pjrc.mk

@@ -1,14 +1,14 @@
 OPT_DEFS += -DHOST_PJRC
 
-SRC =	usb_keyboard.c \
+SRC +=	pjrc.c \
+	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
+# Search Path
+VPATH += $(COMMON_DIR):$(COMMON_DIR)/pjrc
 
 
 # Option modules
@@ -16,6 +16,6 @@ ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE)
     SRC += usb_mouse.c
 endif
 
-ifdef USB_EXTRA_ENABLE
+ifdef EXTRAKEY_ENABLE
     SRC += usb_extra.c
 endif

+ 5 - 5
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);

+ 3 - 0
main_pjrc.c → pjrc/main.c

@@ -35,6 +35,8 @@
 #ifdef PS2_MOUSE_ENABLE
 #   include "ps2_mouse.h"
 #endif
+#include "host.h"
+#include "pjrc.h"
 
 
 #define CPU_PRESCALE(n)    (CLKPR = 0x80, CLKPR = (n))
@@ -88,6 +90,7 @@ int main(void)
     }
 
 
+    host_set_driver(pjrc_driver());
     while (1) {
        keyboard_proc(); 
     }

+ 76 - 0
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
+}

+ 26 - 0
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

+ 17 - 17
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) {

+ 1 - 1
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

+ 2 - 2
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

+ 13 - 0
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;

+ 2 - 0
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);

+ 9 - 9
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

+ 10 - 9
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

+ 2 - 2
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)) \
 )
 
 

+ 2 - 2
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)) \
 )
 
 

+ 3 - 3
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
     ),

+ 1 - 0
ps2_usb/matrix.c

@@ -349,6 +349,7 @@ uint8_t matrix_scan(void)
             default:
                 state = INIT;
         }
+        phex(code);
     }
     return 1;
 }

+ 96 - 0
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

+ 0 - 0
Makefile.rules → rules.mk


+ 3 - 1
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
-

+ 5 - 5
vusb/host_vusb.h → sendchar_null.c

@@ -14,10 +14,10 @@ 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"
 
-#ifndef HOST_VUSB_H
-#define HOST_VUSB_H
 
-void host_vusb_keyboard_send(void);
-
-#endif
+int8_t sendchar(uint8_t c)
+{
+    return 0;
+}

+ 25 - 0
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;
+}

+ 23 - 12
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++;
 }

+ 20 - 1
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;

+ 129 - 0
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;
+	}
+}
+

+ 11 - 0
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

+ 5 - 3
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 */

+ 17 - 0
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

+ 99 - 0
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();
+    }
+}

+ 74 - 133
vusb/host.c → vusb/vusb.c

@@ -16,133 +16,69 @@ 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 "report.h"
+#include "print.h"
 #include "debug.h"
+#include "host_driver.h"
+#include "vusb.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;
-}
+static uint8_t vusb_keyboard_leds = 0;
+static uint8_t vusb_idle_rate = 0;
 
-void host_clear_keyboard_report(void)
-{
-    keyboard_report->mods = 0;
-    for (int8_t i = 0; i < REPORT_KEYS; i++) {
-        keyboard_report->keys[i] = 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;
 
-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)
+/* transfer keyboard report from buffer */
+void vusb_transfer_keyboard(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]);
+    if (usbInterruptIsReady()) {
+       if (kbuf_head != kbuf_tail) {
+            usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t));
+            kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE;
+       }
     }
-#endif
-    return keyboard_report->keys[0];
 }
 
 
 /*------------------------------------------------------------------*
- * Keyboard report send buffer
+ * Host driver
  *------------------------------------------------------------------*/
-#define KBUF_SIZE 16
-static report_keyboard_t kbuf[KBUF_SIZE];
-static uint8_t kbuf_head = 0;
-static uint8_t kbuf_tail = 0;
+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
+};
 
-void host_vusb_keyboard_send(void)
+host_driver_t *vusb_driver(void)
 {
-    if (usbInterruptIsReady() && kbuf_head != kbuf_tail) {
-        usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t));
-        kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE;
-    }
+    return &driver;
 }
 
-void host_send_keyboard_report(void)
+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] = *keyboard_report;
+        kbuf[kbuf_head] = *report;
         kbuf_head = next;
     } else {
         debug("kbuf: full\n");
@@ -150,20 +86,15 @@ void host_send_keyboard_report(void)
 }
 
 
-#if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE)
-void host_mouse_send(report_mouse_t *report)
+static void send_mouse(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)
+static void send_system(uint16_t data)
 {
     // Not need static?
     static uint8_t report[] = { REPORT_ID_SYSTEM, 0, 0 };
@@ -171,12 +102,10 @@ void host_system_send(uint16_t data)
     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 void send_consumer(uint16_t data)
 {
     static uint16_t last_data = 0;
     if (data == last_data) return;
@@ -188,11 +117,8 @@ void host_consumer_send(uint16_t data)
     report[2] = (data>>8)&0xFF;
     if (usbInterruptIsReady3()) {
         usbSetInterrupt3((void *)&report, sizeof(report));
-    } else {
-        debug("Int3 not ready\n");
     }
 }
-#endif
 
 
 
@@ -213,32 +139,36 @@ 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");
+            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;
+            debug("GET_IDLE: ");
+            //debug_hex(vusb_idle_rate);
+            usbMsgPtr = &vusb_idle_rate;
             return 1;
         }else if(rq->bRequest == USBRQ_HID_SET_IDLE){
-            idleRate = rq->wValue.bytes[1];
-            debug(" SET_IDLE: ");
-            debug_hex(idleRate);
+            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: ");
+            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:");
         }
-        debug("\n");
     }else{
-        debug("VENDOR\n");
+        debug("VENDOR:");
         /* no vendor specific requests implemented */
     }
+    debug("\n");
     return 0;   /* default for not implemented requests: return no data back to host */
 }
 
@@ -249,8 +179,10 @@ uchar usbFunctionWrite(uchar *data, uchar len)
     }
     switch (last_req.kind) {
         case SET_LED:
-            //debug("SET_LED\n");
-            keyboard_leds = data[0];
+            debug("SET_LED: ");
+            debug_hex(data[0]);
+            debug("\n");
+            vusb_keyboard_leds = data[0];
             last_req.len = 0;
             return 1;
             break;
@@ -484,13 +416,14 @@ 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:
@@ -499,8 +432,16 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq)
             break;
 #endif
         case USBDESCR_HID:
-            usbMsgPtr = (unsigned char *)(usbDescriptorConfiguration + 18);
-            len = 9;
+            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 */
@@ -516,6 +457,6 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq)
             }
             break;
     }
-    debug("desc len: "); debug_hex(len); debug("\n");
+    //debug("desc len: "); debug_hex(len); debug("\n");
     return len;
 }

+ 27 - 0
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