More USB driver change
authorNIIBE Yutaka <gniibe@fsij.org>
Tue, 28 Jul 2015 01:18:39 +0000 (10:18 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Tue, 28 Jul 2015 01:18:39 +0000 (10:18 +0900)
ChangeLog
src/usb-msc.c
src/usb_ctrl.c
src/usb_desc.c
src/usb_lld.h
src/usb_stm32f103.c

index 6a90611..747a9c0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,13 +1,20 @@
+2015-07-28  Niibe Yutaka  <gniibe@fsij.org>
+
+       * src/usb-msc.c: Update from Fraucheky.
+
+       * src/usb_stm32f103.c (struct DATA_INFO): Remove offset.
+       (struct DEVICE_INFO): Integrate CONTROL_INFO.
+
 2015-07-27  Niibe Yutaka  <gniibe@fsij.org>
 
-       * src/usb_stm32f103.c (usb_lld_answer_control): New.
+       * src/usb_stm32f103.c (usb_lld_reply_request): New.
        (usb_lld_set_data_to_send): Remove.
        (usb_lld_set_data_to_recv): Not a macro but a function.
        (std_get_status): Don't use statically allocated memory.
-       (std_get_configuration): Use usb_lld_answer_control.
+       (std_get_configuration): Use usb_lld_reply_request.
        (handle_setup0): Follow the change.
        * src/usb_ctrl.c (vcom_port_data_setup, usb_cb_setup)
-       (usb_cb_interface): Use usb_lld_answer_control.
+       (usb_cb_interface): Use usb_lld_reply_request.
        * src/usb_desc.c (usb_cb_get_descriptor): Likewise.
 
 2015-07-24  Niibe Yutaka  <gniibe@fsij.org>
index 8e0801c..e9e9161 100644 (file)
@@ -1,7 +1,8 @@
 /*
  * usb-msc.c -- USB Mass Storage Class protocol handling
  *
- * Copyright (C) 2011, 2012, 2013 Free Software Initiative of Japan
+ * Copyright (C) 2011, 2012, 2013, 2015
+ *               Free Software Initiative of Japan
  * Author: NIIBE Yutaka <gniibe@fsij.org>
  *
  * This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -170,11 +171,13 @@ EP6_OUT_Callback (void)
 }
 
 static const uint8_t scsi_inquiry_data_00[] = { 0, 0, 0, 0, 0 };
+static const uint8_t scsi_inquiry_data_83[] = { 0, 0x83, 0, 0 };
+
 
 static const uint8_t scsi_inquiry_data[] = {
   0x00,                                /* Direct Access Device.      */
   0x80,                                /* RMB = 1: Removable Medium. */
-  0x05,                                /* Version: SPC-3.            */
+  0x00,                                /* Version: not claim conformance.  */
   0x02,                                /* Response format: SPC-3.    */
   36 - 4,                      /* Additional Length.         */
   0x00,
@@ -330,6 +333,11 @@ msc_handle_command (void)
 
   CSW.dCSWTag = CBW.dCBWTag;
   switch (CBW.CBWCB[0]) {
+  case SCSI_REPORT_LUN:
+    buf[0]  = buf[1] = buf[2] = buf[3] = 0;
+    buf[4]  = buf[5] = buf[6] = buf[7] = 0;
+    msc_send_result (buf, 8);
+    goto done;
   case SCSI_REQUEST_SENSE:
     if (CBW.CBWCB[1] & 0x01) /* DESC */
       msc_send_result ((uint8_t *)&scsi_sense_data_desc,
@@ -345,10 +353,18 @@ msc_handle_command (void)
       }
     goto done;
   case SCSI_INQUIRY:
-    if (CBW.CBWCB[1] & 0x01) /* EVPD */
-      /* assume page 00 */
-      msc_send_result ((uint8_t *)&scsi_inquiry_data_00,
-                      sizeof scsi_inquiry_data_00);
+    if (CBW.CBWCB[1] & 0x01)
+      /* EVPD */
+      {
+       if (CBW.CBWCB[2] == 0x83)
+         /* Handle the case Page Code 0x83 */
+         msc_send_result ((uint8_t *)&scsi_inquiry_data_83,
+                          sizeof scsi_inquiry_data_83);
+       else
+         /* Otherwise, assume page 00 */
+         msc_send_result ((uint8_t *)&scsi_inquiry_data_00,
+                          sizeof scsi_inquiry_data_00);
+      }
     else
       msc_send_result ((uint8_t *)&scsi_inquiry_data,
                       sizeof scsi_inquiry_data);
@@ -462,6 +478,7 @@ msc_handle_command (void)
                  if (CBW.CBWCB[8]-- == 0)
                    CBW.CBWCB[7]--;
                  CSW.dCSWDataResidue += 512;
+                 lba++;
                }
              else
                {
@@ -507,6 +524,7 @@ msc_handle_command (void)
                  if (CBW.CBWCB[8]-- == 0)
                    CBW.CBWCB[7]--;
                  CSW.dCSWDataResidue -= 512;
+                 lba++;
                }
              else
                {
index b76ffaa..bf26c29 100644 (file)
@@ -58,12 +58,12 @@ static struct line_coding line_coding = {
 };
 
 static int
-vcom_port_data_setup (uint8_t req, uint8_t req_no, uint16_t value)
+vcom_port_data_setup (uint8_t req, uint8_t req_no, struct control_info *detail)
 {
   if (USB_SETUP_GET (req))
     {
       if (req_no == USB_CDC_REQ_GET_LINE_CODING)
-       return usb_lld_answer_control (&line_coding, sizeof(line_coding));
+       return usb_lld_reply_request (&line_coding, sizeof(line_coding), detail);
     }
   else  /* USB_SETUP_SET (req) */
     {
@@ -76,7 +76,7 @@ vcom_port_data_setup (uint8_t req, uint8_t req_no, uint16_t value)
        {
          uint8_t connected_saved = stdout.connected;
 
-         if (value != 0)
+         if (detail->value != 0)
            {
              if (stdout.connected == 0)
                /* It's Open call */
@@ -259,8 +259,7 @@ static int download_check_crc32 (const uint32_t *end_p)
 }
 
 int
-usb_cb_setup (uint8_t req, uint8_t req_no,
-             uint16_t value, uint16_t index, uint16_t len)
+usb_cb_setup (uint8_t req, uint8_t req_no, struct control_info *detail)
 {
   uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
 
@@ -269,27 +268,27 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
       if (USB_SETUP_GET (req))
        {
          if (req_no == USB_FSIJ_GNUK_MEMINFO)
-           return usb_lld_answer_control (mem_info, sizeof (mem_info));
+           return usb_lld_reply_request (mem_info, sizeof (mem_info), detail);
        }
       else /* SETUP_SET */
        {
-         uint8_t *addr = (uint8_t *)(0x20000000 + value * 0x100 + index);
+         uint8_t *addr = (uint8_t *)(0x20000000 + detail->value * 0x100 + detail->index);
 
          if (req_no == USB_FSIJ_GNUK_DOWNLOAD)
            {
              if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED)
                return USB_UNSUPPORT;
 
-             if (addr < &_regnual_start || addr + len > __heap_end__)
+             if (addr < &_regnual_start || addr + detail->len > __heap_end__)
                return USB_UNSUPPORT;
 
-             if (index + len < 256)
-               memset (addr + index + len, 0, 256 - (index + len));
+             if (detail->index + detail->len < 256)
+               memset (addr + detail->index + detail->len, 0, 256 - (detail->index + detail->len));
 
-             usb_lld_set_data_to_recv (addr, len);
+             usb_lld_set_data_to_recv (addr, detail->len);
              return USB_SUCCESS;
            }
-         else if (req_no == USB_FSIJ_GNUK_EXEC && len == 0)
+         else if (req_no == USB_FSIJ_GNUK_EXEC && detail->len == 0)
            {
              if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED)
                return USB_UNSUPPORT;
@@ -299,27 +298,28 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
 
              return download_check_crc32 ((uint32_t *)addr);
            }
-         else if (req_no == USB_FSIJ_GNUK_CARD_CHANGE && len == 0)
+         else if (req_no == USB_FSIJ_GNUK_CARD_CHANGE && detail->len == 0)
            {
-             if (value != 0 && value != 1 && value != 2)
+             if (detail->value != 0 && detail->value != 1 && detail->value != 2)
                return USB_UNSUPPORT;
 
-             ccid_card_change_signal (value);
+             ccid_card_change_signal (detail->value);
              return USB_SUCCESS;
            }
        }
     }
   else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT))
     {
-      if (index == ICC_INTERFACE)
+      if (detail->index == ICC_INTERFACE)
        {
          if (USB_SETUP_GET (req))
            {
              if (req_no == USB_CCID_REQ_GET_CLOCK_FREQUENCIES)
-               return usb_lld_answer_control (freq_table, sizeof (freq_table));
+               return usb_lld_reply_request (freq_table, sizeof (freq_table),
+                                             detail);
              else if (req_no == USB_CCID_REQ_GET_DATA_RATES)
-               return usb_lld_answer_control (data_rate_table,
-                                              sizeof (data_rate_table));
+               return usb_lld_reply_request (data_rate_table,
+                                             sizeof (data_rate_table), detail);
            }
          else
            {
@@ -335,19 +335,19 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
          switch (req_no)
            {
            case USB_HID_REQ_GET_IDLE:
-             return usb_lld_answer_control (&hid_idle_rate, 1);
+             return usb_lld_reply_request (&hid_idle_rate, 1, detail);
            case USB_HID_REQ_SET_IDLE:
-             usb_lld_set_data_to_recv (&hid_idle_rate, 1);
+             usb_lld_set_data_to_recv (&hid_idle_rate, 1, detail);
              return USB_SUCCESS;
 
            case USB_HID_REQ_GET_REPORT:
              /* Request of LED status and key press */
-             return usb_lld_answer_control (&hid_report, 2);
+             return usb_lld_reply_request (&hid_report, 2, detail);
 
            case USB_HID_REQ_SET_REPORT:
              /* Received LED set request */
-             if (len == 1)
-               usb_lld_set_data_to_recv (&hid_report, len);
+             if (detail->len == 1)
+               usb_lld_set_data_to_recv (&hid_report, detail->len);
              return USB_SUCCESS;
 
            case USB_HID_REQ_GET_PROTOCOL:
@@ -362,7 +362,7 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
 #endif
 #ifdef ENABLE_VIRTUAL_COM_PORT
       else if (index == VCOM_INTERFACE_0)
-       return vcom_port_data_setup (req, req_no, value);
+       return vcom_port_data_setup (req, req_no, detail);
 #endif
 #ifdef PINPAD_DND_SUPPORT
       else if (index == MSC_INTERFACE)
@@ -370,7 +370,8 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
          if (USB_SETUP_GET (req))
            {
              if (req_no == MSC_GET_MAX_LUN_COMMAND)
-               return usb_lld_answer_control (lun_table, sizeof (lun_table));
+               return usb_lld_reply_request (lun_table, sizeof (lun_table),
+                                             detail);
            }
          else
            if (req_no == MSC_MASS_STORAGE_RESET_COMMAND)
@@ -385,14 +386,13 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
 
 
 void
-usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value,
-                         uint16_t index, uint16_t len)
+usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value)
 {
   uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
 
   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT))
     {
-      if (USB_SETUP_SET (req) && req_no == USB_FSIJ_GNUK_EXEC && len == 0)
+      if (USB_SETUP_SET (req) && req_no == USB_FSIJ_GNUK_EXEC)
        {
          if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED)
            return;
@@ -459,9 +459,11 @@ int usb_cb_handle_event (uint8_t event_type, uint16_t value)
   return USB_UNSUPPORT;
 }
 
-int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
+int usb_cb_interface (uint8_t cmd, struct control_info *detail)
 {
   const uint8_t zero = 0;
+  uint16_t interface = detail->index;
+  uint16_t alt = detail->value;
 
   if (interface >= NUM_INTERFACES)
     return USB_UNSUPPORT;
@@ -478,10 +480,10 @@ int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
        }
 
     case USB_GET_INTERFACE:
-      return usb_lld_answer_control (&zero, 1);
+      return usb_lld_reply_request (&zero, 1, detail);
 
-    default:
     case USB_QUERY_INTERFACE:
+    default:
       return USB_SUCCESS;
     }
 }
index 804b3be..8db6f3e 100644 (file)
@@ -59,7 +59,7 @@ static const uint8_t hid_report_desc[] = {
 #define USB_ICC_DATA_SIZE 64
 
 /* USB Standard Device Descriptor */
-static const uint8_t gnukDeviceDescriptor[] = {
+static const uint8_t device_desc[] = {
   18,   /* bLength */
   USB_DEVICE_DESCRIPTOR_TYPE,     /* bDescriptorType */
   0x10, 0x01,   /* bcdUSB = 1.1 */
@@ -99,7 +99,7 @@ static const uint8_t gnukDeviceDescriptor[] = {
 
 
 /* Configuation Descriptor */
-static const uint8_t gnukConfigDescriptor[] = {
+static const uint8_t config_desc[] = {
   9,                      /* bLength: Configuation Descriptor size */
   USB_CONFIGURATION_DESCRIPTOR_TYPE,      /* bDescriptorType: Configuration */
   W_TOTAL_LENGTH, 0x00,   /* wTotalLength:no of returned bytes */
@@ -346,21 +346,20 @@ static const struct desc string_descriptors[] = {
 
 int
 usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
-                      uint16_t index, uint16_t length)
+                      struct control_info *detail)
 {
   if (rcp == DEVICE_RECIPIENT)
     {
       if (desc_type == DEVICE_DESCRIPTOR)
-       return usb_lld_answer_control (gnukDeviceDescriptor,
-                                      sizeof (gnukDeviceDescriptor));
+       return usb_lld_reply_request (device_desc, sizeof (device_desc), detail);
       else if (desc_type == CONFIG_DESCRIPTOR)
-       return usb_lld_answer_control (gnukConfigDescriptor,
-                                      sizeof (gnukConfigDescriptor));
+       return usb_lld_reply_request (config_desc, sizeof (config_desc), detail);
       else if (desc_type == STRING_DESCRIPTOR)
        {
          if (desc_index < NUM_STRING_DESC)
-           return usb_lld_answer_control (string_descriptors[desc_index].desc,
-                                          string_descriptors[desc_index].size);
+           return usb_lld_reply_request (string_descriptors[desc_index].desc,
+                                         string_descriptors[desc_index].size,
+                                         detail);
          else if (desc_index == NUM_STRING_DESC)
            {
              uint8_t usbbuf[64];
@@ -377,27 +376,24 @@ usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
                }
              usbbuf[0] = len = i*2 + 2;
              usbbuf[1] = USB_STRING_DESCRIPTOR_TYPE;
-             if (len > length)
-               len = length;
-             return usb_lld_answer_control (usbbuf, len);
+             return usb_lld_reply_request (usbbuf, len, detail);
            }
        }
     }
+#ifdef HID_CARD_CHANGE_SUPPORT
   else if (rcp == INTERFACE_RECIPIENT)
     {
-#ifdef HID_CARD_CHANGE_SUPPORT
-      if (index == 1)
+      if (detail->index == 1)
        {
          if (desc_type == USB_DT_HID)
-           return usb_lld_answer_control (gnukConfigDescriptor+ICC_TOTAL_LENGTH+9, 9);
+           return usb_lld_reply_request (config_desc+ICC_TOTAL_LENGTH+9, 9,
+                                         detail);
          else if (desc_type == USB_DT_REPORT)
-           return usb_lld_answer_control (hid_report_desc, HID_REPORT_DESC_SIZE);
+           return usb_lld_reply_request (hid_report_desc, HID_REPORT_DESC_SIZE,
+                                         detail);
        }
-      else
-#else
-      (void)index;
-#endif
     }
+#endif
 
   return USB_UNSUPPORT;
 }
index 2608bd7..fd4bc08 100644 (file)
@@ -55,15 +55,19 @@ enum
   USB_SUCCESS = 1,
 };
 
+struct control_info {
+  uint16_t value;
+  uint16_t index;
+  uint16_t len;
+};
+
 void usb_cb_device_reset (void);
-void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no,
-                              uint16_t value, uint16_t index, uint16_t len);
-int usb_cb_setup (uint8_t req, uint8_t req_no, uint16_t value,
-                 uint16_t index, uint16_t len);
+int usb_cb_setup (uint8_t req, uint8_t req_no, struct control_info *detail);
+int usb_cb_interface (uint8_t cmd, struct control_info *detail);
 int usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
-                          uint16_t index, uint16_t length);
+                          struct control_info *detail);
 int usb_cb_handle_event (uint8_t event_type, uint16_t value);
-int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t value);
+void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value);
 
 enum {
   USB_EVENT_ADDRESS,
@@ -89,7 +93,6 @@ enum DEVICE_STATE
   CONFIGURED
 };
 
-
 void usb_lld_init (uint8_t feature);
 void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n);
 void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n);
@@ -99,7 +102,8 @@ int usb_lld_tx_data_len (int ep_num);
 void usb_lld_txcpy (const void *src, int ep_num, int offset, size_t len);
 void usb_lld_tx_enable (int ep_num, size_t len);
 void usb_lld_write (uint8_t ep_num, const void *buf, size_t len);
-int usb_lld_answer_control (const void *buf, size_t buflen);
+int usb_lld_reply_request (const void *buf, size_t buflen,
+                          struct control_info *ctrl);
 void usb_lld_rx_enable (int ep_num);
 int usb_lld_rx_data_len (int ep_num);
 void usb_lld_rxcpy (uint8_t *dst, int ep_num, int offset, size_t len);
index a874e41..c213d6a 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,27 @@ 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;
 };
 
-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;
 
@@ -412,16 +403,14 @@ 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)
@@ -440,13 +429,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);
@@ -467,37 +455,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 control_info *detail);
 
-static int std_none (uint8_t req,
-                    uint16_t value, uint16_t index, uint16_t length)
+static int std_none (uint8_t req, struct control_info *detail)
 {
-  (void)req; (void)value; (void)index; (void)length;
+  (void)req; (void)detail;
   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 control_info *detail)
 {
   uint8_t rcp = req & RECIPIENT;
   uint16_t status_info = 0;
 
-  if (value != 0 || length != 2 || (index >> 8) != 0
+  if (detail->value != 0 || detail->len != 2 || (detail->index >> 8) != 0
       || (req & REQUEST_DIR) == 0)
     return USB_UNSUPPORT;
 
   if (rcp == DEVICE_RECIPIENT)
     {
-      if (index == 0)
+      if (detail->index == 0)
        {
          /* Get Device Status */
          uint8_t feature = dev_p->current_feature;
@@ -514,7 +498,7 @@ static int std_get_status (uint8_t req,
          else /* Self-powered */
            status_info &= ~1;
 
-         return usb_lld_answer_control (&status_info, 2);
+         return usb_lld_reply_request (&status_info, 2, detail);
        }
     }
   else if (rcp == INTERFACE_RECIPIENT)
@@ -524,21 +508,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, detail);
       if (r != USB_SUCCESS)
        return USB_UNSUPPORT;
 
-      return usb_lld_answer_control (&status_info, 2);
+      return usb_lld_reply_request (&status_info, 2, detail);
     }
   else if (rcp == ENDPOINT_RECIPIENT)
     {
-      uint8_t endpoint = (index & 0x0f);
+      uint8_t endpoint = (detail->index & 0x0f);
       uint16_t status;
 
-      if ((index & 0x70) || endpoint == ENDP0)
+      if ((detail->index & 0x70) || endpoint == ENDP0)
        return USB_UNSUPPORT;
 
-      if ((index & 0x80))
+      if ((detail->index & 0x80))
        {
          status = st103_ep_get_tx_status (endpoint);
          if (status == 0)              /* Disabled */
@@ -555,14 +539,13 @@ static int std_get_status (uint8_t req,
            status_info |= 1; /* OUT Endpoint stalled */
        }
 
-      return usb_lld_answer_control (&status_info, 2);
+      return usb_lld_reply_request (&status_info, 2, detail);
     }
 
   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 control_info *detail)
 {
   uint8_t rcp = req & RECIPIENT;
 
@@ -571,10 +554,10 @@ static int std_clear_feature (uint8_t req, uint16_t value,
 
   if (rcp == DEVICE_RECIPIENT)
     {
-      if (length != 0 || index != 0)
+      if (detail->len != 0 || detail->index != 0)
        return USB_UNSUPPORT;
 
-      if (value == DEVICE_REMOTE_WAKEUP)
+      if (detail->value == DEVICE_REMOTE_WAKEUP)
        {
          dev_p->current_feature &= ~(1 << 5);
          return USB_SUCCESS;
@@ -582,17 +565,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 = (detail->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 (detail->len != 0 || (detail->index >> 8) != 0
+         || detail->value != ENDPOINT_STALL || endpoint == ENDP0)
        return USB_UNSUPPORT;
 
-      if ((index & 0x80))
+      if ((detail->index & 0x80))
        status = st103_ep_get_tx_status (endpoint);
       else
        status = st103_ep_get_rx_status (endpoint);
@@ -600,7 +583,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 (detail->index & 0x80)                /* IN endpoint */
        st103_ep_clear_dtog_tx (endpoint);
       else                     /* OUT endpoint */
        st103_ep_clear_dtog_rx (endpoint);
@@ -612,8 +595,7 @@ 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 control_info *detail)
 {
   uint8_t rcp = req & RECIPIENT;
 
@@ -622,10 +604,10 @@ static int std_set_feature (uint8_t req, uint16_t value,
 
   if (rcp == DEVICE_RECIPIENT)
     {
-      if (length != 0 || index != 0)
+      if (detail->len != 0 || detail->index != 0)
        return USB_UNSUPPORT;
 
-      if (value == DEVICE_REMOTE_WAKEUP)
+      if (detail->value == DEVICE_REMOTE_WAKEUP)
        {
          dev_p->current_feature |= 1 << 5;
          // event??
@@ -634,16 +616,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 = (detail->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 (detail->len != 0 || (detail->index >> 8) != 0
+         || detail->value != 0 || endpoint == ENDP0)
        return USB_UNSUPPORT;
 
-      if ((index & 0x80))
+      if ((detail->index & 0x80))
        status = st103_ep_get_tx_status (endpoint);
       else
        status = st103_ep_get_rx_status (endpoint);
@@ -651,7 +634,7 @@ static int std_set_feature (uint8_t req, uint16_t value,
       if (status == 0)         /* Disabled */
        return USB_UNSUPPORT;
 
-      if (index & 0x80)
+      if (detail->index & 0x80)
        /* IN endpoint */
        st103_ep_set_tx_status (endpoint, EP_TX_STALL);
       else
@@ -665,74 +648,59 @@ 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 control_info *detail)
 {
   uint8_t rcp = req & RECIPIENT;
 
   if ((req & REQUEST_DIR) == 1)
     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 && detail->len == 0 && detail->value <= 127
+      && detail->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 control_info *detail)
 {
   uint8_t rcp = req & RECIPIENT;
 
   if ((req & REQUEST_DIR) == 0)
     return USB_UNSUPPORT;
 
-  (void)length;
-  return usb_cb_get_descriptor (rcp, (value >> 8), (value & 0xff),
-                               index, length);
+  return usb_cb_get_descriptor (rcp, (detail->value >> 8),
+                               (detail->value & 0xff), detail);
 }
 
-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 control_info *detail)
 {
   uint8_t rcp = req & RECIPIENT;
 
+  (void)detail;
   if ((req & REQUEST_DIR) == 0)
     return USB_UNSUPPORT;
 
-  (void)value;  (void)index;  (void)length;
   if (rcp == DEVICE_RECIPIENT)
-    return usb_lld_answer_control (&dev_p->current_configuration, 1);
+    return usb_lld_reply_request (&dev_p->current_configuration, 1, detail);
 
   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 control_info *detail)
 {
   uint8_t rcp = req & RECIPIENT;
 
   if ((req & REQUEST_DIR) == 1)
     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 && detail->index == 0 && detail->len == 0)
+    return usb_cb_handle_event (USB_EVENT_CONFIG, detail->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 control_info *detail)
 {
   uint8_t rcp = req & RECIPIENT;
 
@@ -741,74 +709,61 @@ static int std_get_interface (uint8_t req, uint16_t value,
 
   if (rcp == INTERFACE_RECIPIENT)
     {
-      if (value != 0 || (index >> 8) != 0 || length != 1)
+      if (detail->value != 0 || (detail->index >> 8) != 0 || detail->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, detail);
     }
 
   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 control_info *detail)
 {
   uint8_t rcp = req & RECIPIENT;
 
-  if ((req & REQUEST_DIR) == 1)
+  if ((req & REQUEST_DIR) == 1 || rcp != INTERFACE_RECIPIENT
+      || detail->len != 0 || (detail->index >> 8) != 0
+      || (detail->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, detail);
 }
 
 
 static void handle_setup0 (void)
 {
   const uint16_t *pw;
+  struct control_info ctrl;
   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++;
+  ctrl.value = *pw++;
   pw++;
-  ctrl_p->wIndex  = *pw++;
+  ctrl.index  = *pw++;
   pw++;
-  ctrl_p->wLength = *pw;
+  ctrl.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;
@@ -822,30 +777,30 @@ 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, &ctrl);
        }
     }
   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, &ctrl);
 
   if (r != USB_SUCCESS)
     dev_p->state = STALLED;
   else
     {
-      if (USB_SETUP_GET (ctrl_p->bmRequestType))
-       ;
-      else if (ctrl_p->wLength == 0)
+      if (USB_SETUP_SET (dev_p->bmRequestType))
        {
-         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->value = ctrl.value;
+         if (ctrl.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
+           {
+             dev_p->state = OUT_DATA;
+             st103_ep_set_rx_status (ENDP0, EP_RX_VALID);
+           }
        }
     }
 }
@@ -856,17 +811,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,
+                                  dev_p->value);
 
       dev_p->state = STALLED;
     }
@@ -1175,9 +1129,9 @@ void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n)
  * BUFLEN: size of the data.
  */
 int
-usb_lld_answer_control (const void *buf, size_t buflen)
+usb_lld_reply_request (const void *buf, size_t buflen, struct control_info *ctl)
 {
-  uint32_t len_asked = ctrl_p->wLength;
+  uint32_t len_asked = ctl->len;
   uint32_t len;
 
   data_p->addr = (void *)buf;
@@ -1188,9 +1142,7 @@ usb_lld_answer_control (const void *buf, size_t buflen)
     data_p->len = len_asked;
 
   if (data_p->len != 0 && (data_p->len % USB_MAX_PACKET_SIZE) == 0)
-    data_p->require_zlp = TRUE;
-  else
-    data_p->require_zlp = FALSE;
+    data_p->require_zlp = 1;
 
   if (data_p->len < USB_MAX_PACKET_SIZE)
     {
@@ -1207,7 +1159,7 @@ usb_lld_answer_control (const void *buf, size_t buflen)
     {
       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);