diff --git a/converter/ibm4704_usb/README.md b/converter/ibm4704_usb/README.md
index 25b72ba671..15c826ab8b 100644
--- a/converter/ibm4704_usb/README.md
+++ b/converter/ibm4704_usb/README.md
@@ -8,6 +8,7 @@ Keyboard initialization process takes a few seconds at start up. During that you
 Update
 ------
 2015/05/05  Added keymaps for 107-key, 77-key and 50-key. Thanks, orihalcon @ geekhack!
+2015/05/19  Fixed a protocol handling bug.
 
 
 
diff --git a/converter/ibm4704_usb/config.h b/converter/ibm4704_usb/config.h
index 4f267b3b7a..2fee10fd61 100644
--- a/converter/ibm4704_usb/config.h
+++ b/converter/ibm4704_usb/config.h
@@ -51,9 +51,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define IBM4704_DATA_DDR    DDRD
 #define IBM4704_DATA_BIT    0
 
-/* Pin interrupt on  rising edge */
-#define IBM4704_INT_INIT()  do { EICRA |= ((1<<ISC11)|(0<<ISC10)); } while (0)
-#define IBM4704_INT_ON()    do { EIMSK |=  (1<<INT1); } while (0)
+/* Pin interrupt on rising edge of clock */
+#define IBM4704_INT_INIT()  do { EICRA |= ((1<<ISC11)|(1<<ISC10)); } while (0)
+#define IBM4704_INT_ON()    do { EIFR |= (1<<INTF1); EIMSK |= (1<<INT1); } while (0)
 #define IBM4704_INT_OFF()   do { EIMSK &= ~(1<<INT1); } while (0)
 #define IBM4704_INT_VECT    INT1_vect
 
diff --git a/converter/ibm4704_usb/ibm4704.txt b/converter/ibm4704_usb/ibm4704.txt
index 9c4895d922..e2d42f08fd 100644
--- a/converter/ibm4704_usb/ibm4704.txt
+++ b/converter/ibm4704_usb/ibm4704.txt
@@ -57,15 +57,15 @@ Keyboard to Host
 ----------------
 Data bits are LSB first and Pairty is odd. Clock has around 60us high and 30us low part.
 
-            ____      __   __   __   __   __   __   __   __   __   ________
-    Clock       \____/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/
+            ____       __   __   __   __   __   __   __   __   __   _______
+    Clock       \_____/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/
                  ____ ____ ____ ____ ____ ____ ____ ____ ____ ____    
     Data    ____/    X____X____X____X____X____X____X____X____X____X________
                 Start   0    1    2    3    4    5    6    7    P  Stop
 
 Start bit:  can be long as 300-350us.
 Inhibit:    Pull Data line down to inhibit keyboard to send.
-Timing:     Host reads bit while Clock is hi.
+Timing:     Host reads bit while Clock is hi.(rising edge)
 Stop bit:   Keyboard pulls down Data line to lo after 9th clock.
 
 
@@ -166,13 +166,14 @@ Data sent from host:
          |   `-----`--- scan code
          `------------- enable bit(0: enable repeat, 1: enable break)
 
-    00-77   Enable repeat(78-7F: invalid scancode)
-    80-F7   Enable break(F8-FF: invalid scancode)
+    00-79   Enable repeat
+    80-F9   Enable break(FA-FF are used as other commands, see above.)
     FE      Resend(011ah) no need to use
     FF      End(0114h) exits FC command mode.
 
 Response from keyboard:
     FD      Out of bound - Invalid scancode
+    --      OK - No response means that command is accepted.
 
 Examples:
     To enable break code of all keys.
diff --git a/converter/ibm4704_usb/matrix.c b/converter/ibm4704_usb/matrix.c
index 5f928d716f..155df9c38f 100644
--- a/converter/ibm4704_usb/matrix.c
+++ b/converter/ibm4704_usb/matrix.c
@@ -67,35 +67,31 @@ uint8_t matrix_cols(void)
 
 static void enable_break(void)
 {
-    uint8_t ret;
     print("Enable break: ");
     // valid scancode: 00-79h
     for (uint8_t code = 0; code < 0x7A; code++) {
-        while (ibm4704_send(0x80|code)) _delay_ms(1);
-        // get none when ok, get FD when out of bound
-        _delay_ms(5);
-        if ((ret = ibm4704_recv()) != 0xff) {
-            xprintf("c%02X:r%02X ", code, ret);
-        }
-        _delay_ms(1);
+        while (ibm4704_send(0x80|code)) _delay_ms(10);
+        _delay_ms(5);   // wait for response
+        // No response(FF) when ok, FD when out of bound
+        xprintf("s%02X:r%02X ", code, ibm4704_recv());
     }
-    _delay_us(1000);
-    while (ibm4704_send(0xFF)) { _delay_ms(1); } // End
+    while (ibm4704_send(0xFF)) { _delay_ms(10); } // End
     print("End\n");
 }
 
+
+void matrix_setup(void)
+{
+    ibm4704_init();
+}
+
 void matrix_init(void)
 {
     debug_enable = true;
 
-    ibm4704_init();
-    matrix_clear();
-
-    _delay_ms(2000);    // wait for starting up debug console
-
     print("IBM 4704 converter\n");
-    while (ibm4704_send(0xFE)) _delay_ms(1);    // resend
-    _delay_ms(5);
+    matrix_clear();
+    _delay_ms(2000);    // wait for keyboard starting up
     xprintf("Keyboard ID: %02X\n", ibm4704_recv());
     enable_break();
 }
diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c
index 80243f02bc..af99f52b5e 100644
--- a/tmk_core/common/avr/suspend.c
+++ b/tmk_core/common/avr/suspend.c
@@ -85,6 +85,8 @@ void suspend_power_down(void)
     power_down(WDTO_15MS);
 }
 
+__attribute__ ((weak)) void matrix_power_up(void) {}
+__attribute__ ((weak)) void matrix_power_down(void) {}
 bool suspend_wakeup_condition(void)
 {
     matrix_power_up();
diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c
index b03b124d76..eb7b096bed 100644
--- a/tmk_core/common/keyboard.c
+++ b/tmk_core/common/keyboard.c
@@ -62,6 +62,12 @@ static bool has_ghost_in_row(uint8_t row)
 #endif
 
 
+__attribute__ ((weak)) void matrix_setup(void) {}
+void keyboard_setup(void)
+{
+    matrix_setup();
+}
+
 void keyboard_init(void)
 {
     timer_init();
diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h
index 6442716fc7..7738251b64 100644
--- a/tmk_core/common/keyboard.h
+++ b/tmk_core/common/keyboard.h
@@ -58,13 +58,15 @@ static inline bool IS_RELEASED(keyevent_t event) { return (!IS_NOEVENT(event) &&
 }
 
 
+/* it runs once at early stage of startup before keyboard_init. */
+void keyboard_setup(void);
+/* it runs once after initializing host side protocol, debug and MCU peripherals. */
 void keyboard_init(void);
+/* it runs repeatedly in main loop */
 void keyboard_task(void);
+/* it runs when host LED status is updated */
 void keyboard_set_leds(uint8_t leds);
 
-__attribute__ ((weak)) void matrix_power_up(void) {}
-__attribute__ ((weak)) void matrix_power_down(void) {}
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/tmk_core/common/matrix.h b/tmk_core/common/matrix.h
index 107ee72653..ec6f8cd431 100644
--- a/tmk_core/common/matrix.h
+++ b/tmk_core/common/matrix.h
@@ -43,7 +43,9 @@ extern "C" {
 uint8_t matrix_rows(void);
 /* number of matrix columns */
 uint8_t matrix_cols(void);
-/* intialize matrix for scaning. should be called once. */
+/* should be called at early stage of startup before matrix_init.(optional) */
+void matrix_setup(void);
+/* intialize matrix for scaning. */
 void matrix_init(void);
 /* scan all key states on matrix */
 uint8_t matrix_scan(void);
diff --git a/tmk_core/protocol/ibm4704.c b/tmk_core/protocol/ibm4704.c
index a10a5e74d9..6a03cd4419 100644
--- a/tmk_core/protocol/ibm4704.c
+++ b/tmk_core/protocol/ibm4704.c
@@ -21,9 +21,10 @@ uint8_t ibm4704_error = 0;
 
 void ibm4704_init(void)
 {
+    inhibit();  // keep keyboard from sending
     IBM4704_INT_INIT();
     IBM4704_INT_ON();
-    idle();
+    idle();     // allow keyboard sending
 }
 
 /*
@@ -104,22 +105,6 @@ uint8_t ibm4704_recv_response(void)
     return rbuf_dequeue();
 }
 
-/*
-Keyboard to Host
-----------------
-Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part.
-
-        ____      __   __   __   __   __   __   __   __   __   ________
-Clock       \____/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/
-             ____ ____ ____ ____ ____ ____ ____ ____ ____ ____    
-Data    ____/    X____X____X____X____X____X____X____X____X____X________
-            Start   0    1    2    3    4    5    6    7    P  Stop
-
-Start bit:  can be long as 300-350us.
-Inhibit:    Pull Data line down to inhibit keyboard to send.
-Timing:     Host reads bit while Clock is hi.
-Stop bit:   Keyboard pulls down Data line to lo after 9th clock.
-*/
 uint8_t ibm4704_recv(void)
 {
     if (rbuf_has_data()) {
@@ -129,26 +114,35 @@ uint8_t ibm4704_recv(void)
     }
 }
 
+/*
+Keyboard to Host
+----------------
+Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part.
+
+        ____       __   __   __   __   __   __   __   __   __   _______
+Clock       \_____/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/
+             ____ ____ ____ ____ ____ ____ ____ ____ ____ ____    
+Data    ____/    X____X____X____X____X____X____X____X____X____X________
+            Start   0    1    2    3    4    5    6    7    P  Stop
+
+Start bit:  can be long as 300-350us.
+Inhibit:    Pull Data line down to inhibit keyboard to send.
+Timing:     Host reads bit while Clock is hi.(rising edge)
+Stop bit:   Keyboard pulls down Data line to lo after 9th clock.
+*/
 ISR(IBM4704_INT_VECT)
 {
     static enum {
-        INIT, START, BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, PARITY,
-    } state = INIT;
+        BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, PARITY, STOP
+    } state = BIT0;
     // LSB first
     static uint8_t data = 0;
     // Odd parity
     static uint8_t parity = false;
 
     ibm4704_error = 0;
-    // return unless falling edge
-    if (clock_in()) { goto RETURN; }    // why this occurs?
 
-    state++;
     switch (state) {
-        case START:
-            // Data:Low
-            WAIT(data_hi, 10, state);
-            break;
         case BIT0:
         case BIT1:
         case BIT2:
@@ -169,6 +163,10 @@ ISR(IBM4704_INT_VECT)
             }
             if (!parity)
                 goto ERROR;
+            break;
+        case STOP:
+            // Data:Low
+            WAIT(data_lo, 100, state);
             rbuf_enqueue(data);
             ibm4704_error = IBM4704_ERR_NONE;
             goto DONE;
@@ -176,13 +174,14 @@ ISR(IBM4704_INT_VECT)
         default:
             goto ERROR;
     }
+    state++;
     goto RETURN;
 ERROR:
     ibm4704_error = state;
     while (ibm4704_send(0xFE)) _delay_ms(1); // resend
     xprintf("R:%02X%02X\n", state, data);
 DONE:
-    state = INIT;
+    state = BIT0;
     data = 0;
     parity = false;
 RETURN:
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c
index cdfc7bc6ad..391064c9b2 100644
--- a/tmk_core/protocol/lufa/lufa.c
+++ b/tmk_core/protocol/lufa/lufa.c
@@ -544,7 +544,7 @@ int8_t sendchar(uint8_t c)
 /*******************************************************************************
  * main
  ******************************************************************************/
-static void SetupHardware(void)
+static void setup_mcu(void)
 {
     /* Disable watchdog if enabled by bootloader/fuses */
     MCUSR &= ~(1 << WDRF);
@@ -552,7 +552,10 @@ static void SetupHardware(void)
 
     /* Disable clock division */
     clock_prescale_set(clock_div_1);
+}
 
+static void setup_usb(void)
+{
     // Leonardo needs. Without this USB device is not recognized.
     USB_Disable();
 
@@ -566,7 +569,9 @@ static void SetupHardware(void)
 int main(void)  __attribute__ ((weak));
 int main(void)
 {
-    SetupHardware();
+    setup_mcu();
+    keyboard_setup();
+    setup_usb();
     sei();
 
     /* wait for USB startup & debug output */
diff --git a/tmk_core/protocol/pjrc/main.c b/tmk_core/protocol/pjrc/main.c
index e7bdcc059a..45eb17d4cd 100644
--- a/tmk_core/protocol/pjrc/main.c
+++ b/tmk_core/protocol/pjrc/main.c
@@ -46,6 +46,8 @@ int main(void)
     // set for 16 MHz clock
     CPU_PRESCALE(0);
 
+    keyboard_setup();
+
     // Initialize the USB, and then wait for the host to set configuration.
     // If the Teensy is powered without a PC connected to the USB port,
     // this will wait forever.