Update USB and Chopstx
[gnuk/neug.git] / src / usb_stm32f103.c
index b75dfdb..80fbcc7 100644 (file)
@@ -1,9 +1,6 @@
 #include <stdint.h>
 #include <stdlib.h>
 
-#define TRUE  1
-#define FALSE 0
-
 #include "sys.h"
 #include "usb_lld.h"
 
@@ -49,33 +46,29 @@ enum FEATURE_SELECTOR
 
 struct DATA_INFO
 {
-  uint16_t len;
-  uint16_t offset;
   uint8_t *addr;
+  uint16_t len;
   uint8_t require_zlp;
 };
 
-struct CONTROL_INFO
-{
-  uint8_t bmRequestType;
-  uint8_t bRequest;
-  uint16_t wValue;
-  uint16_t wIndex;
-  uint16_t wLength;
-};
 
 struct DEVICE_INFO
 {
   uint8_t current_configuration;
   uint8_t current_feature;
   uint8_t state;
+  /**/
+  uint8_t bmRequestType;
+  uint8_t bRequest;
+  /**/
+  uint16_t value;
+  uint16_t index;
+  uint16_t len;
 };
 
-static struct CONTROL_INFO control_info;
 static struct DEVICE_INFO device_info;
 static struct DATA_INFO data_info;
 
-static struct CONTROL_INFO *const ctrl_p = &control_info;
 static struct DEVICE_INFO *const dev_p = &device_info;
 static struct DATA_INFO *const data_p = &data_info;
 
@@ -93,8 +86,8 @@ static struct DATA_INFO *const data_p = &data_info;
 /* Buffer Table address register */
 #define BTABLE  ((volatile uint16_t *)(REG_BASE + 0x50))
 
-#define ISTR_CTR    (0x8000) /* Correct TRansfer (clear-only bit) */
-#define ISTR_DOVR   (0x4000) /* DMA OVeR/underrun (clear-only bit) */
+#define ISTR_CTR    (0x8000) /* Correct TRansfer (read-only bit) */
+#define ISTR_OVR    (0x4000) /* OVeR/underrun (clear-only bit) */
 #define ISTR_ERR    (0x2000) /* ERRor (clear-only bit) */
 #define ISTR_WKUP   (0x1000) /* WaKe UP (clear-only bit) */
 #define ISTR_SUSP   (0x0800) /* SUSPend (clear-only bit) */
@@ -105,8 +98,7 @@ static struct DATA_INFO *const data_p = &data_info;
 #define ISTR_DIR    (0x0010)  /* DIRection of transaction (read-only bit)  */
 #define ISTR_EP_ID  (0x000F)  /* EndPoint IDentifier (read-only bit)  */
 
-#define CLR_CTR    (~ISTR_CTR)   /* clear Correct TRansfer bit */
-#define CLR_DOVR   (~ISTR_DOVR)  /* clear DMA OVeR/underrun bit*/
+#define CLR_OVR    (~ISTR_OVR)   /* clear OVeR/underrun bit*/
 #define CLR_ERR    (~ISTR_ERR)   /* clear ERRor bit */
 #define CLR_WKUP   (~ISTR_WKUP)  /* clear WaKe UP bit     */
 #define CLR_SUSP   (~ISTR_SUSP)  /* clear SUSPend bit     */
@@ -115,7 +107,7 @@ static struct DATA_INFO *const data_p = &data_info;
 #define CLR_ESOF   (~ISTR_ESOF)  /* clear Expected Start Of Frame bit */
 
 #define CNTR_CTRM   (0x8000) /* Correct TRansfer Mask */
-#define CNTR_DOVRM  (0x4000) /* DMA OVeR/underrun Mask */
+#define CNTR_OVRM   (0x4000) /* OVeR/underrun Mask */
 #define CNTR_ERRM   (0x2000) /* ERRor Mask */
 #define CNTR_WKUPM  (0x1000) /* WaKe UP Mask */
 #define CNTR_SUSPM  (0x0800) /* SUSPend Mask */
@@ -161,7 +153,7 @@ static struct DATA_INFO *const data_p = &data_info;
 #define EPRX_DTOG1     (0x1000) /* EndPoint RX Data TOGgle bit1 */
 #define EPRX_DTOG2     (0x2000) /* EndPoint RX Data TOGgle bit1 */
 
-static void usb_handle_transfer (void);
+static void usb_handle_transfer (uint16_t istr_value);
 
 static void st103_set_btable (void)
 {
@@ -363,7 +355,7 @@ void usb_lld_init (uint8_t feature)
   dev_p->state = IN_DATA;
 
   usb_lld_set_configuration (0);
-  usb_lld_set_feature (feature);
+  dev_p->current_feature = feature;
 
   /* Reset USB */
   st103_set_cntr (CNTR_FRES);
@@ -391,36 +383,36 @@ usb_interrupt_handler (void)
 {
   uint16_t istr_value = st103_get_istr ();
 
-  if (istr_value & ISTR_CTR)
-    usb_handle_transfer ();
-
-  if (istr_value & ISTR_RESET)
+  if ((istr_value & ISTR_RESET))
     {
       st103_set_istr (CLR_RESET);
       usb_cb_device_reset ();
     }
+  else
+    {
+      if ((istr_value & ISTR_OVR))
+       st103_set_istr (CLR_OVR);
 
-  if (istr_value & ISTR_DOVR)
-    st103_set_istr (CLR_DOVR);
+      if ((istr_value & ISTR_ERR))
+       st103_set_istr (CLR_ERR);
 
-  if (istr_value & ISTR_ERR)
-    st103_set_istr (CLR_ERR);
+      if ((istr_value & ISTR_CTR))
+       usb_handle_transfer (istr_value);
+    }
 }
 
 static void handle_datastage_out (void)
 {
   if (data_p->addr && data_p->len)
     {
-      uint8_t *buf;
       uint32_t len = st103_get_rx_count (ENDP0);
 
       if (len > data_p->len)
        len = data_p->len;
 
-      buf = data_p->addr + data_p->offset;
-      usb_lld_from_pmabuf (buf, st103_get_rx_addr (ENDP0), len);
+      usb_lld_from_pmabuf (data_p->addr, st103_get_rx_addr (ENDP0), len);
       data_p->len -= len;
-      data_p->offset += len;
+      data_p->addr += len;
     }
 
   if (data_p->len == 0)
@@ -439,13 +431,12 @@ static void handle_datastage_out (void)
 static void handle_datastage_in (void)
 {
   uint32_t len = USB_MAX_PACKET_SIZE;;
-  const uint8_t *buf;
 
   if ((data_p->len == 0) && (dev_p->state == LAST_IN_DATA))
     {
-      if (data_p->require_zlp == TRUE)
+      if (data_p->require_zlp)
        {
-         data_p->require_zlp = FALSE;
+         data_p->require_zlp = 0;
 
          /* No more data to send.  Send empty packet */
          st103_set_tx_count (ENDP0, 0);
@@ -466,40 +457,33 @@ static void handle_datastage_in (void)
   if (len > data_p->len)
     len = data_p->len;
 
-  buf = (const uint8_t *)data_p->addr + data_p->offset;
-  usb_lld_to_pmabuf (buf, st103_get_tx_addr (ENDP0), len);
+  usb_lld_to_pmabuf (data_p->addr, st103_get_tx_addr (ENDP0), len);
   data_p->len -= len;
-  data_p->offset += len;
+  data_p->addr += len;
   st103_set_tx_count (ENDP0, len);
   st103_ep_set_tx_status (ENDP0, EP_TX_VALID);
 }
 
-typedef int (*HANDLER) (uint8_t req,
-                       uint16_t value, uint16_t index, uint16_t length);
+typedef int (*HANDLER) (uint8_t req, struct req_args *arg);
 
-static int std_none (uint8_t req,
-                    uint16_t value, uint16_t index, uint16_t length)
+static int std_none (uint8_t req, struct req_args *arg)
 {
-  (void)req; (void)value; (void)index; (void)length;
+  (void)req; (void)arg;
   return USB_UNSUPPORT;
 }
 
-static int std_get_status (uint8_t req,
-                          uint16_t value, uint16_t index, uint16_t length)
+static int std_get_status (uint8_t req, struct req_args *arg)
 {
-  static uint16_t status_info;
   uint8_t rcp = req & RECIPIENT;
+  uint16_t status_info = 0;
 
-  status_info = 0;             /* Reset Status Information */
-  data_p->addr = (uint8_t *)&status_info;
-
-  if (value != 0 || length != 2 || (index >> 8) != 0
-      || (req & REQUEST_DIR) == 0)
+  if (arg->value != 0 || arg->len != 2 || (arg->index >> 8) != 0
+      || USB_SETUP_SET (req))
     return USB_UNSUPPORT;
 
   if (rcp == DEVICE_RECIPIENT)
     {
-      if (index == 0)
+      if (arg->index == 0)
        {
          /* Get Device Status */
          uint8_t feature = dev_p->current_feature;
@@ -516,8 +500,7 @@ static int std_get_status (uint8_t req,
          else /* Self-powered */
            status_info &= ~1;
 
-         data_p->len = 2;
-         return USB_SUCCESS;
+         return usb_lld_reply_request (&status_info, 2, arg);
        }
     }
   else if (rcp == INTERFACE_RECIPIENT)
@@ -527,22 +510,21 @@ static int std_get_status (uint8_t req,
       if (dev_p->current_configuration == 0)
        return USB_UNSUPPORT;
 
-      r = usb_cb_interface (USB_QUERY_INTERFACE, index, 0);
+      r = usb_cb_interface (USB_QUERY_INTERFACE, arg);
       if (r != USB_SUCCESS)
        return USB_UNSUPPORT;
 
-      data_p->len = 2;
-      return USB_SUCCESS;
+      return usb_lld_reply_request (&status_info, 2, arg);
     }
   else if (rcp == ENDPOINT_RECIPIENT)
     {
-      uint8_t endpoint = (index & 0x0f);
+      uint8_t endpoint = (arg->index & 0x0f);
       uint16_t status;
 
-      if ((index & 0x70) != 0 || endpoint == ENDP0)
+      if ((arg->index & 0x70) || endpoint == ENDP0)
        return USB_UNSUPPORT;
 
-      if ((index & 0x80))
+      if ((arg->index & 0x80))
        {
          status = st103_ep_get_tx_status (endpoint);
          if (status == 0)              /* Disabled */
@@ -559,27 +541,25 @@ static int std_get_status (uint8_t req,
            status_info |= 1; /* OUT Endpoint stalled */
        }
 
-       data_p->len = 2;
-       return USB_SUCCESS;
+      return usb_lld_reply_request (&status_info, 2, arg);
     }
 
   return USB_UNSUPPORT;
 }
 
-static int std_clear_feature (uint8_t req, uint16_t value,
-                             uint16_t index, uint16_t length)
+static int std_clear_feature (uint8_t req, struct req_args *arg)
 {
   uint8_t rcp = req & RECIPIENT;
 
-  if ((req & REQUEST_DIR) == 1)
+  if (USB_SETUP_GET (req))
     return USB_UNSUPPORT;
 
   if (rcp == DEVICE_RECIPIENT)
     {
-      if (length != 0 || index != 0)
+      if (arg->len != 0 || arg->index != 0)
        return USB_UNSUPPORT;
 
-      if (value == DEVICE_REMOTE_WAKEUP)
+      if (arg->value == DEVICE_REMOTE_WAKEUP)
        {
          dev_p->current_feature &= ~(1 << 5);
          return USB_SUCCESS;
@@ -587,17 +567,17 @@ static int std_clear_feature (uint8_t req, uint16_t value,
     }
   else if (rcp == ENDPOINT_RECIPIENT)
     {
-      uint8_t endpoint = (index & 0x0f);
+      uint8_t endpoint = (arg->index & 0x0f);
       uint16_t status;
 
       if (dev_p->current_configuration == 0)
        return USB_UNSUPPORT;
 
-      if (length != 0 || (index >> 8) != 0 || value != ENDPOINT_STALL
-         || endpoint == ENDP0)
+      if (arg->len != 0 || (arg->index >> 8) != 0
+         || arg->value != ENDPOINT_STALL || endpoint == ENDP0)
        return USB_UNSUPPORT;
 
-      if ((index & 0x80))
+      if ((arg->index & 0x80))
        status = st103_ep_get_tx_status (endpoint);
       else
        status = st103_ep_get_rx_status (endpoint);
@@ -605,7 +585,7 @@ static int std_clear_feature (uint8_t req, uint16_t value,
       if (status == 0)         /* Disabled */
        return USB_UNSUPPORT;
 
-      if (index & 0x80)                /* IN endpoint */
+      if (arg->index & 0x80)           /* IN endpoint */
        st103_ep_clear_dtog_tx (endpoint);
       else                     /* OUT endpoint */
        st103_ep_clear_dtog_rx (endpoint);
@@ -617,20 +597,19 @@ static int std_clear_feature (uint8_t req, uint16_t value,
   return USB_UNSUPPORT;
 }
 
-static int std_set_feature (uint8_t req, uint16_t value,
-                           uint16_t index, uint16_t length)
+static int std_set_feature (uint8_t req, struct req_args *arg)
 {
   uint8_t rcp = req & RECIPIENT;
 
-  if ((req & REQUEST_DIR) == 1)
+  if (USB_SETUP_GET (req))
     return USB_UNSUPPORT;
 
   if (rcp == DEVICE_RECIPIENT)
     {
-      if (length != 0 || index != 0)
+      if (arg->len != 0 || arg->index != 0)
        return USB_UNSUPPORT;
 
-      if (value == DEVICE_REMOTE_WAKEUP)
+      if (arg->value == DEVICE_REMOTE_WAKEUP)
        {
          dev_p->current_feature |= 1 << 5;
          // event??
@@ -639,16 +618,17 @@ static int std_set_feature (uint8_t req, uint16_t value,
     }
   else if (rcp == ENDPOINT_RECIPIENT)
     {
-      uint8_t endpoint = (index & 0x0f);
+      uint8_t endpoint = (arg->index & 0x0f);
       uint32_t status;
 
       if (dev_p->current_configuration == 0)
        return USB_UNSUPPORT;
 
-      if (length != 0 || (index >> 8) != 0 || value != 0 || endpoint == ENDP0)
+      if (arg->len != 0 || (arg->index >> 8) != 0
+         || arg->value != 0 || endpoint == ENDP0)
        return USB_UNSUPPORT;
 
-      if ((index & 0x80))
+      if ((arg->index & 0x80))
        status = st103_ep_get_tx_status (endpoint);
       else
        status = st103_ep_get_rx_status (endpoint);
@@ -656,7 +636,7 @@ static int std_set_feature (uint8_t req, uint16_t value,
       if (status == 0)         /* Disabled */
        return USB_UNSUPPORT;
 
-      if (index & 0x80)
+      if (arg->index & 0x80)
        /* IN endpoint */
        st103_ep_set_tx_status (endpoint, EP_TX_STALL);
       else
@@ -670,124 +650,88 @@ static int std_set_feature (uint8_t req, uint16_t value,
   return USB_UNSUPPORT;
 }
 
-static int std_set_address (uint8_t req, uint16_t value,
-                           uint16_t index, uint16_t length)
+static int std_set_address (uint8_t req, struct req_args *arg)
 {
   uint8_t rcp = req & RECIPIENT;
 
-  if ((req & REQUEST_DIR) == 1)
+  if (USB_SETUP_GET (req))
     return USB_UNSUPPORT;
 
-  if (rcp == DEVICE_RECIPIENT)
-    {
-      if (length == 0 && value <= 127 && index == 0
-         && dev_p->current_configuration == 0)
-       return USB_SUCCESS;
-    }
+  if (rcp == DEVICE_RECIPIENT && arg->len == 0 && arg->value <= 127
+      && arg->index == 0 && dev_p->current_configuration == 0)
+    return USB_SUCCESS;
 
   return USB_UNSUPPORT;
 }
 
-static int std_get_descriptor (uint8_t req, uint16_t value,
-                              uint16_t index, uint16_t length)
+static int std_get_descriptor (uint8_t req, struct req_args *arg)
 {
   uint8_t rcp = req & RECIPIENT;
 
-  if ((req & REQUEST_DIR) == 0)
+  if (USB_SETUP_SET (req))
     return USB_UNSUPPORT;
 
-  (void)length;
-  if (rcp == DEVICE_RECIPIENT)
-    return usb_cb_get_descriptor ((value >> 8), index, value);
-
-  return USB_UNSUPPORT;
+  return usb_cb_get_descriptor (rcp, (arg->value >> 8),
+                               (arg->value & 0xff), arg);
 }
 
-static int std_get_configuration (uint8_t req, uint16_t value,
-                                 uint16_t index, uint16_t length)
+static int std_get_configuration (uint8_t req,  struct req_args *arg)
 {
   uint8_t rcp = req & RECIPIENT;
 
-  if ((req & REQUEST_DIR) == 0)
+  if (USB_SETUP_SET (req))
     return USB_UNSUPPORT;
 
-  (void)value;  (void)index;  (void)length;
   if (rcp == DEVICE_RECIPIENT)
-    {
-      data_p->addr = &dev_p->current_configuration;
-      data_p->len = 1;
-      return USB_SUCCESS;
-    }
+    return usb_lld_reply_request (&dev_p->current_configuration, 1, arg);
 
   return USB_UNSUPPORT;
 }
 
-static int std_set_configuration (uint8_t req, uint16_t value,
-                                 uint16_t index, uint16_t length)
+static int std_set_configuration (uint8_t req, struct req_args *arg)
 {
   uint8_t rcp = req & RECIPIENT;
 
-  if ((req & REQUEST_DIR) == 1)
+  if (USB_SETUP_GET (req))
     return USB_UNSUPPORT;
 
-  if (rcp == DEVICE_RECIPIENT && index == 0 && length == 0)
-    {
-      int r;
-
-      r = usb_cb_handle_event (USB_EVENT_CONFIG, value);
-      if (r == USB_SUCCESS)
-       return USB_SUCCESS;
-    }
+  if (rcp == DEVICE_RECIPIENT && arg->index == 0 && arg->len == 0)
+    return usb_cb_handle_event (USB_EVENT_CONFIG, arg->value);
 
   return USB_UNSUPPORT;
 }
 
-static int std_get_interface (uint8_t req, uint16_t value,
-                             uint16_t index, uint16_t length)
+static int std_get_interface (uint8_t req, struct req_args *arg)
 {
   uint8_t rcp = req & RECIPIENT;
 
-  if ((req & REQUEST_DIR) == 0)
+  if (USB_SETUP_SET (req))
     return USB_UNSUPPORT;
 
   if (rcp == INTERFACE_RECIPIENT)
     {
-      if (value != 0 || (index >> 8) != 0 || length != 1)
+      if (arg->value != 0 || (arg->index >> 8) != 0 || arg->len != 1)
        return USB_UNSUPPORT;
 
       if (dev_p->current_configuration == 0)
        return USB_UNSUPPORT;
 
-      return usb_cb_interface (USB_GET_INTERFACE, index, 0);
+      return usb_cb_interface (USB_GET_INTERFACE, arg);
     }
 
   return USB_UNSUPPORT;
 }
 
-static int std_set_interface (uint8_t req, uint16_t value,
-                             uint16_t index, uint16_t length)
+static int std_set_interface (uint8_t req, struct req_args *arg)
 {
   uint8_t rcp = req & RECIPIENT;
 
-  if ((req & REQUEST_DIR) == 1)
+  if (USB_SETUP_GET (req) || rcp != INTERFACE_RECIPIENT
+      || arg->len != 0 || (arg->index >> 8) != 0
+      || (arg->value >> 8) != 0 || dev_p->current_configuration == 0)
     return USB_UNSUPPORT;
 
-  if (rcp == INTERFACE_RECIPIENT)
-    {
-      int r;
-
-      if (length != 0 || (index >> 8) != 0 || (value >> 8) != 0)
-       return  USB_UNSUPPORT;
-
-      if (dev_p->current_configuration != 0)
-       return USB_UNSUPPORT;
-
-      r = usb_cb_interface (USB_SET_INTERFACE, index, value);
-      if (r == USB_SUCCESS)
-       return USB_SUCCESS;
-    }
-
-  return USB_UNSUPPORT;
+  return usb_cb_interface (USB_SET_INTERFACE, arg);
 }
 
 
@@ -795,31 +739,31 @@ static void handle_setup0 (void)
 {
   const uint16_t *pw;
   uint16_t w;
-  uint8_t req;
+  uint8_t req_no;
   int r = USB_UNSUPPORT;
   HANDLER handler;
 
   pw = (uint16_t *)(PMA_ADDR + (uint8_t *)(st103_get_rx_addr (ENDP0) * 2));
   w = *pw++;
 
-  ctrl_p->bmRequestType = w & 0xff;
-  ctrl_p->bRequest = req = w >> 8;
+  dev_p->bmRequestType = w & 0xff;
+  dev_p->bRequest = req_no = w >> 8;
   pw++;
-  ctrl_p->wValue = *pw++;
+  dev_p->value = *pw++;
   pw++;
-  ctrl_p->wIndex  = *pw++;
+  dev_p->index = *pw++;
   pw++;
-  ctrl_p->wLength = *pw;
+  dev_p->len = *pw;
 
   data_p->addr = NULL;
   data_p->len = 0;
-  data_p->offset = 0;
+  data_p->require_zlp = 0;
 
-  if ((ctrl_p->bmRequestType & REQUEST_TYPE) == STANDARD_REQUEST)
+  if ((dev_p->bmRequestType & REQUEST_TYPE) == STANDARD_REQUEST)
     {
-      if (req < TOTAL_REQUEST)
+      if (req_no < TOTAL_REQUEST)
        {
-         switch (req)
+         switch (req_no)
            {
            case 0: handler = std_get_status;  break;
            case 1: handler = std_clear_feature;  break;
@@ -833,44 +777,31 @@ static void handle_setup0 (void)
            default: handler = std_none;  break;
            }
 
-         r = (*handler) (ctrl_p->bmRequestType,
-                         ctrl_p->wValue, ctrl_p->wIndex, ctrl_p->wLength);
+         r = (*handler) (dev_p->bmRequestType,
+                         (struct req_args *)&dev_p->value);
        }
     }
   else
-    r = usb_cb_setup (ctrl_p->bmRequestType, req,
-                     ctrl_p->wValue, ctrl_p->wIndex, ctrl_p->wLength);
+    r = usb_cb_setup (dev_p->bmRequestType, req_no,
+                     (struct req_args *)&dev_p->value);
 
   if (r != USB_SUCCESS)
     dev_p->state = STALLED;
   else
     {
-      if (USB_SETUP_GET (ctrl_p->bmRequestType))
+      if (USB_SETUP_SET (dev_p->bmRequestType))
        {
-         uint32_t len = ctrl_p->wLength;
-
-         /* Restrict the data length to be the one host asks for */
-         if (data_p->len > len)
-           data_p->len = len;
-
-         if ((data_p->len % USB_MAX_PACKET_SIZE) == 0)
-           data_p->require_zlp = TRUE;
+         if (dev_p->len == 0)
+           {
+             dev_p->state = WAIT_STATUS_IN;
+             st103_set_tx_count (ENDP0, 0);
+             st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_VALID);
+           }
          else
-           data_p->require_zlp = FALSE;
-
-         dev_p->state = IN_DATA;
-         handle_datastage_in ();
-       }
-      else if (ctrl_p->wLength == 0)
-       {
-         dev_p->state = WAIT_STATUS_IN;
-         st103_set_tx_count (ENDP0, 0);
-         st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_VALID);
-       }
-      else
-       {
-         dev_p->state = OUT_DATA;
-         st103_ep_set_rx_status (ENDP0, EP_RX_VALID);
+           {
+             dev_p->state = OUT_DATA;
+             st103_ep_set_rx_status (ENDP0, EP_RX_VALID);
+           }
        }
     }
 }
@@ -881,17 +812,16 @@ static void handle_in0 (void)
     handle_datastage_in ();
   else if (dev_p->state == WAIT_STATUS_IN)
     {
-      if ((ctrl_p->bRequest == SET_ADDRESS) &&
-         ((ctrl_p->bmRequestType & (REQUEST_TYPE | RECIPIENT))
+      if ((dev_p->bRequest == SET_ADDRESS) &&
+         ((dev_p->bmRequestType & (REQUEST_TYPE | RECIPIENT))
           == (STANDARD_REQUEST | DEVICE_RECIPIENT)))
        {
-         st103_set_daddr (ctrl_p->wValue);
-         usb_cb_handle_event (USB_EVENT_ADDRESS, ctrl_p->wValue);
+         st103_set_daddr (dev_p->value);
+         usb_cb_handle_event (USB_EVENT_ADDRESS, dev_p->value);
        }
       else
-       usb_cb_ctrl_write_finish  (ctrl_p->bmRequestType,
-                                  ctrl_p->bRequest, ctrl_p->wValue,
-                                  ctrl_p->wIndex, ctrl_p->wLength);
+       usb_cb_ctrl_write_finish (dev_p->bmRequestType, dev_p->bRequest,
+                                 (struct req_args *)&dev_p->value);
 
       dev_p->state = STALLED;
     }
@@ -913,109 +843,58 @@ static void handle_out0 (void)
     dev_p->state = STALLED;
 }
 \f
-static void nop_proc (void)
-{
-}
-
-#define WEAK __attribute__ ((weak, alias ("nop_proc")))
-void WEAK EP1_IN_Callback (void);
-void WEAK EP2_IN_Callback (void);
-void WEAK EP3_IN_Callback (void);
-void WEAK EP4_IN_Callback (void);
-void WEAK EP5_IN_Callback (void);
-void WEAK EP6_IN_Callback (void);
-void WEAK EP7_IN_Callback (void);
-
-void WEAK EP1_OUT_Callback (void);
-void WEAK EP2_OUT_Callback (void);
-void WEAK EP3_OUT_Callback (void);
-void WEAK EP4_OUT_Callback (void);
-void WEAK EP5_OUT_Callback (void);
-void WEAK EP6_OUT_Callback (void);
-void WEAK EP7_OUT_Callback (void);
-
 static void
-usb_handle_transfer (void)
+usb_handle_transfer (uint16_t istr_value)
 {
   uint16_t ep_value = 0;
-  uint16_t istr_value;
   uint8_t ep_index;
 
-  while (((istr_value = st103_get_istr ()) & ISTR_CTR) != 0)
+  ep_index = (istr_value & ISTR_EP_ID);
+  /* Decode and service non control endpoints interrupt  */
+  /* process related endpoint register */
+  ep_value = st103_get_epreg (ep_index);
+
+  if (ep_index == 0)
     {
-      ep_index = (istr_value & ISTR_EP_ID);
-      if (ep_index == 0)
+      if ((ep_value & EP_CTR_TX))
        {
-         if ((istr_value & ISTR_DIR) == 0)
-           {                           /* DIR = 0 */
-             /* DIR = 0      => IN  int */
-             /* DIR = 0 implies that (EP_CTR_TX = 1) always  */
+         st103_ep_clear_ctr_tx (ep_index);
+         handle_in0 ();
+       }
 
-             st103_ep_clear_ctr_tx (ENDP0);
-             handle_in0 ();
-           }
-         else
-           {                           /* DIR = 1 */
-             /* DIR = 1 & CTR_RX       => SETUP or OUT int */
-             /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
-
-             ep_value = st103_get_epreg (ENDP0);
-             if ((ep_value & EP_SETUP) != 0)
-               {
-                 st103_ep_clear_ctr_rx (ENDP0);
-                 handle_setup0 ();
-               }
-             else if ((ep_value & EP_CTR_RX) != 0)
-               {
-                 st103_ep_clear_ctr_rx (ENDP0);
-                 handle_out0 ();
-               }
-           }
+      if ((ep_value & EP_CTR_RX))
+       {
+         st103_ep_clear_ctr_rx (ep_index);
 
-         if (dev_p->state == STALLED)
-           st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_STALL);
+         if ((ep_value & EP_SETUP))
+           handle_setup0 ();
+         else
+           handle_out0 ();
        }
-      else
-       {
-         /* Decode and service non control endpoints interrupt  */
-         /* process related endpoint register */
-         ep_value = st103_get_epreg (ep_index);
 
-         if ((ep_value & EP_CTR_RX) != 0)
-           {
-             st103_ep_clear_ctr_rx (ep_index);
-             switch ((ep_index - 1))
-               {
-               case 0: EP1_OUT_Callback ();  break;
-               case 1: EP2_OUT_Callback ();  break;
-               case 2: EP3_OUT_Callback ();  break;
-               case 3: EP4_OUT_Callback ();  break;
-               case 4: EP5_OUT_Callback ();  break;
-               case 5: EP6_OUT_Callback ();  break;
-               case 6: EP7_OUT_Callback ();  break;
-               }
-           }
+      if (dev_p->state == STALLED)
+       st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_STALL);
+    }
+  else
+    {
+      if ((ep_value & EP_CTR_RX))
+       {
+         st103_ep_clear_ctr_rx (ep_index);
+         usb_cb_rx_ready (ep_index);
+       }
 
-         if ((ep_value & EP_CTR_TX) != 0)
-           {
-             st103_ep_clear_ctr_tx (ep_index);
-             switch ((ep_index - 1))
-               {
-               case 0: EP1_IN_Callback ();  break;
-               case 1: EP2_IN_Callback ();  break;
-               case 2: EP3_IN_Callback ();  break;
-               case 3: EP4_IN_Callback ();  break;
-               case 4: EP5_IN_Callback ();  break;
-               case 5: EP6_IN_Callback ();  break;
-               case 6: EP7_IN_Callback ();  break;
-               }
-           }
+      if ((ep_value & EP_CTR_TX))
+       {
+         st103_ep_clear_ctr_tx (ep_index);
+         usb_cb_tx_done (ep_index);
        }
     }
 }
 \f
-void usb_lld_reset (void)
+void usb_lld_reset (uint8_t feature)
 {
+  usb_lld_set_configuration (0);
+  dev_p->current_feature = feature;
   st103_set_btable ();
   st103_set_daddr (0);
 }
@@ -1122,14 +1001,9 @@ uint8_t usb_lld_current_configuration (void)
   return dev_p->current_configuration;
 }
 
-void usb_lld_set_feature (uint8_t feature)
+void usb_lld_set_data_to_recv (void *p, size_t len)
 {
-  dev_p->current_feature = feature;
-}
-
-void usb_lld_set_data_to_send (const void *p, size_t len)
-{
-  data_p->addr = (uint8_t *)p;
+  data_p->addr = p;
   data_p->len = len;
 }
 
@@ -1205,3 +1079,49 @@ void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n)
       *d = (w & 0xff);
     }
 }
+
+
+/*
+ * BUF: Pointer to data memory.  Data memory should not be allocated
+ *      on stack when BUFLEN > USB_MAX_PACKET_SIZE.
+ *
+ * BUFLEN: size of the data.
+ */
+int
+usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *ctl)
+{
+  uint32_t len_asked = ctl->len;
+  uint32_t len;
+
+  data_p->addr = (void *)buf;
+  data_p->len = buflen;
+
+  /* Restrict the data length to be the one host asks for */
+  if (data_p->len > len_asked)
+    data_p->len = len_asked;
+
+  if (data_p->len != 0 && (data_p->len % USB_MAX_PACKET_SIZE) == 0)
+    data_p->require_zlp = 1;
+
+  if (data_p->len < USB_MAX_PACKET_SIZE)
+    {
+      len = data_p->len;
+      dev_p->state = LAST_IN_DATA;
+    }
+  else
+    {
+      len = USB_MAX_PACKET_SIZE;
+      dev_p->state = IN_DATA;
+    }
+
+  if (len)
+    {
+      usb_lld_to_pmabuf (data_p->addr, st103_get_tx_addr (ENDP0), len);
+      data_p->len -= len;
+      data_p->addr += len;
+    }
+
+  st103_set_tx_count (ENDP0, len);
+  st103_ep_set_tx_status (ENDP0, EP_TX_VALID);
+  return USB_SUCCESS;
+}