The patch below makes full-speed USB work for my HHKB Pro. At least
to the point of F1 and Esc producing the usual result when rendering.

The elements in there:

- Navre progmem set to 4 kB, because I didn't get the 8 kB
  SoC+BIOS+etc. to work yet. Also commented out most of the debug
  output, so that the Navre firmware still fits.

- port A disabled. I use it to signal sending of SETUP instead, so
  that I can trigger on it. (Trying to wade through all the SOFs
  would be hopeless.)

- send all the ACKs as early as possible. Unfortunately, this means
  I have to send them even before checking whether the data is any
  good. (I tried to do it after the check, but I still missed the
  16 bit times deadline sometimes.)

- prepare the DATA0 packet in a SETUP transfer before sending the
  SETUP. This to reduce the time between SETUP and DATA0, which
  apparently also runs against a timeout. (The USB spec is not very
  clear about it.)

While it may be possible to meet timing requirements by shifting
things around a bit more, the only proper solution will be to
generate the ACK in hardware.

The good news is that timing seems to be the only major obstacle
for full-speed USB. At least as far as my HHKB is concerned ;-)

- Werner

diff --git a/softusb-input/main.c b/softusb-input/main.c
index 40f877e..3c538be 100644
--- a/softusb-input/main.c
+++ b/softusb-input/main.c
@@ -26,6 +26,9 @@
 #include "host.h"
 #include "crc.h"
 
+#define        print_string(s) (void) (s)
+#define        dump_hex(x, y)  (void) (x)
+
 enum {
        USB_PID_OUT     = 0xe1,
        USB_PID_IN      = 0x69,
@@ -94,6 +97,16 @@ static void usb_tx(unsigned char *buf, unsigned char len)
        while(rio8(SIE_TX_BUSY));
 }
 
+static void usb_ack(void)
+{
+       wio8(SIE_TX_DATA, 0x80); /* send SYNC */
+       while(rio8(SIE_TX_PENDING));
+       wio8(SIE_TX_DATA, USB_PID_ACK); /* send ACK */
+       while(rio8(SIE_TX_PENDING));
+       wio8(SIE_TX_VALID, 0);
+       while(rio8(SIE_TX_BUSY));
+}
+
 static const char transfer_start[] PROGMEM = "Transfer start: ";
 static const char timeout_error[] PROGMEM = "RX timeout error\n";
 static const char bitstuff_error[] PROGMEM = "RX bitstuff error\n";
@@ -163,6 +176,7 @@ static const char out_reply[] PROGMEM = "IN reply:\n";
 
 static char control_transfer(unsigned char addr, struct setup_packet *p, char 
out, unsigned char *payload, int maxlen)
 {
+       unsigned char usb_token[3];
        unsigned char usb_buffer[11];
        char toggle;
        char rxlen;
@@ -172,13 +186,15 @@ static char control_transfer(unsigned char addr, struct 
setup_packet *p, char ou
        toggle = 0;
 
        /* send SETUP token */
-       make_usb_token(USB_PID_SETUP, addr, usb_buffer);
-       usb_tx(usb_buffer, 3);
+       make_usb_token(USB_PID_SETUP, addr, usb_token);
        /* send setup packet */
        usb_buffer[0] = get_data_token(&toggle);
        memcpy(&usb_buffer[1], p, 8);
        usb_crc16(&usb_buffer[1], 8, &usb_buffer[9]);
+wio8(SIE_SEL_TX, 3);
+       usb_tx(usb_token, 3);
        usb_tx(usb_buffer, 11);
+wio8(SIE_SEL_TX, 2);
        /* get ACK token from device */
        rxlen = usb_rx(usb_buffer, 11);
        if((rxlen != 1) || (usb_buffer[0] != USB_PID_ACK)) {
@@ -230,6 +246,8 @@ static char control_transfer(unsigned char addr, struct 
setup_packet *p, char ou
                        usb_tx(usb_buffer, 3);
                        /* get DATAx packet */
                        rxlen = usb_rx(usb_buffer, 11);
+                       if (rxlen >= 3)
+                               usb_ack();      /* @@@ */
                        if((rxlen < 3) || ((usb_buffer[0] != USB_PID_DATA0) &&
                            (usb_buffer[0] != USB_PID_DATA1))) {
                                if((rxlen > 0) &&
@@ -240,15 +258,15 @@ static char control_transfer(unsigned char addr, struct 
setup_packet *p, char ou
                                dump_hex(usb_buffer, rxlen);
                                return -1;
                        }
+
+                       /* send ACK token */
+               //      usb_ack();
+
                        chunklen = rxlen - 3; /* strip token and CRC */
                        if(chunklen > (maxlen - transferred))
                                chunklen = maxlen - transferred;
                        memcpy(payload, &usb_buffer[1], chunklen);
 
-                       /* send ACK token */
-                       usb_buffer[0] = USB_PID_ACK;
-                       usb_tx(usb_buffer, 1);
-
                        transferred += chunklen;
                        payload += chunklen;
                        if(chunklen < 8)
@@ -263,6 +281,8 @@ retry:
        if(out) {
                /* get DATAx packet */
                rxlen = usb_rx(usb_buffer, 11);
+               if (rxlen == 3)
+                       usb_ack();      /* @@@ */
                if((rxlen != 3) || ((usb_buffer[0] != USB_PID_DATA0) &&
                    (usb_buffer[0] != USB_PID_DATA1))) {
                        if((rxlen > 0) && (usb_buffer[0] == USB_PID_NAK))
@@ -274,8 +294,7 @@ retry:
                        return -1;
                }
                /* send ACK token */
-               usb_buffer[0] = USB_PID_ACK;
-               usb_tx(usb_buffer, 1);
+//             usb_ack();
        } else {
                /* send DATAx packet */
                usb_buffer[0] = get_data_token(&toggle);
@@ -312,19 +331,18 @@ static void poll(struct ep_status *ep, char keyboard)
        len = usb_rx(usb_buffer, 11);
        if(len < 6)
                return;
+       usb_ack(); /* @@@ */
        if(usb_buffer[0] != ep->expected_data) {
                if((usb_buffer[0] == USB_PID_DATA0) ||
                    (usb_buffer[0] == USB_PID_DATA1)) {
                        /* ACK */
-                       usb_buffer[0] = USB_PID_ACK;
-                       usb_tx(usb_buffer, 1);
+//                     usb_ack();
                        print_string(datax_mismatch);
                }
                return; /* drop */
        }
        /* ACK */
-       usb_buffer[0] = USB_PID_ACK;
-       usb_tx(usb_buffer, 1);
+//     usb_ack();
        if(ep->expected_data == USB_PID_DATA0)
                ep->expected_data = USB_PID_DATA1;
        else
@@ -619,8 +637,8 @@ static void sof()
        unsigned char usb_buffer[3];
        
        mask = 0;
-       if(port_a.full_speed && (port_a.state > PORT_STATE_BUS_RESET))
-               mask |= 0x01;
+//     if(port_a.full_speed && (port_a.state > PORT_STATE_BUS_RESET))
+//             mask |= 0x01;
        if(port_b.full_speed && (port_b.state > PORT_STATE_BUS_RESET))
                mask |= 0x02;
        if(mask != 0) {
@@ -636,8 +654,8 @@ static void keepalive()
        unsigned char mask;
        
        mask = 0;
-       if(!port_a.full_speed && (port_a.state == PORT_STATE_RESET_WAIT))
-               mask |= 0x01;
+//     if(!port_a.full_speed && (port_a.state == PORT_STATE_RESET_WAIT))
+//             mask |= 0x01;
        if(!port_b.full_speed && (port_b.state == PORT_STATE_RESET_WAIT))
                mask |= 0x02;
        if(mask != 0) {
@@ -681,13 +699,17 @@ int main()
                for(i=0;i<128;i++)
                        asm("nop");
                
+#if 0
                wio8(SIE_SEL_RX, 0);
                wio8(SIE_SEL_TX, 0x01);
                port_service(&port_a, 'A');
+#endif
 
+#if 1
                wio8(SIE_SEL_RX, 1);
                wio8(SIE_SEL_TX, 0x02);
                port_service(&port_b, 'B');
+#endif
                
                /* set RX speed for new detected devices */
                set_rx_speed();
diff --git a/softusb-input/navre.ld b/softusb-input/navre.ld
index 652f554..4ec1578 100644
--- a/softusb-input/navre.ld
+++ b/softusb-input/navre.ld
@@ -3,7 +3,7 @@ OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
 OUTPUT_ARCH(avr:2)
 MEMORY
 {
-  text   (rx)   : ORIGIN = 0, LENGTH = 8K
+  text   (rx)   : ORIGIN = 0, LENGTH = 4K
   data   (rw!x) : ORIGIN = 0, LENGTH = 32K
 }
 SECTIONS
_______________________________________________
http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org
IRC: #milkymist@Freenode

Reply via email to