More USB driver change

This commit is contained in:
NIIBE Yutaka
2015-07-28 10:18:39 +09:00
parent 9e3af06141
commit fbdac6a96a
6 changed files with 194 additions and 215 deletions

View File

@@ -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> 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_send): Remove.
(usb_lld_set_data_to_recv): Not a macro but a function. (usb_lld_set_data_to_recv): Not a macro but a function.
(std_get_status): Don't use statically allocated memory. (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. (handle_setup0): Follow the change.
* src/usb_ctrl.c (vcom_port_data_setup, usb_cb_setup) * 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. * src/usb_desc.c (usb_cb_get_descriptor): Likewise.
2015-07-24 Niibe Yutaka <gniibe@fsij.org> 2015-07-24 Niibe Yutaka <gniibe@fsij.org>

View File

@@ -1,7 +1,8 @@
/* /*
* usb-msc.c -- USB Mass Storage Class protocol handling * 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> * Author: NIIBE Yutaka <gniibe@fsij.org>
* *
* This file is a part of Gnuk, a GnuPG USB Token implementation. * 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_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[] = { static const uint8_t scsi_inquiry_data[] = {
0x00, /* Direct Access Device. */ 0x00, /* Direct Access Device. */
0x80, /* RMB = 1: Removable Medium. */ 0x80, /* RMB = 1: Removable Medium. */
0x05, /* Version: SPC-3. */ 0x00, /* Version: not claim conformance. */
0x02, /* Response format: SPC-3. */ 0x02, /* Response format: SPC-3. */
36 - 4, /* Additional Length. */ 36 - 4, /* Additional Length. */
0x00, 0x00,
@@ -330,6 +333,11 @@ msc_handle_command (void)
CSW.dCSWTag = CBW.dCBWTag; CSW.dCSWTag = CBW.dCBWTag;
switch (CBW.CBWCB[0]) { 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: case SCSI_REQUEST_SENSE:
if (CBW.CBWCB[1] & 0x01) /* DESC */ if (CBW.CBWCB[1] & 0x01) /* DESC */
msc_send_result ((uint8_t *)&scsi_sense_data_desc, msc_send_result ((uint8_t *)&scsi_sense_data_desc,
@@ -345,10 +353,18 @@ msc_handle_command (void)
} }
goto done; goto done;
case SCSI_INQUIRY: case SCSI_INQUIRY:
if (CBW.CBWCB[1] & 0x01) /* EVPD */ if (CBW.CBWCB[1] & 0x01)
/* assume page 00 */ /* EVPD */
msc_send_result ((uint8_t *)&scsi_inquiry_data_00, {
sizeof scsi_inquiry_data_00); 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 else
msc_send_result ((uint8_t *)&scsi_inquiry_data, msc_send_result ((uint8_t *)&scsi_inquiry_data,
sizeof scsi_inquiry_data); sizeof scsi_inquiry_data);
@@ -462,6 +478,7 @@ msc_handle_command (void)
if (CBW.CBWCB[8]-- == 0) if (CBW.CBWCB[8]-- == 0)
CBW.CBWCB[7]--; CBW.CBWCB[7]--;
CSW.dCSWDataResidue += 512; CSW.dCSWDataResidue += 512;
lba++;
} }
else else
{ {
@@ -507,6 +524,7 @@ msc_handle_command (void)
if (CBW.CBWCB[8]-- == 0) if (CBW.CBWCB[8]-- == 0)
CBW.CBWCB[7]--; CBW.CBWCB[7]--;
CSW.dCSWDataResidue -= 512; CSW.dCSWDataResidue -= 512;
lba++;
} }
else else
{ {

View File

@@ -58,12 +58,12 @@ static struct line_coding line_coding = {
}; };
static int 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 (USB_SETUP_GET (req))
{ {
if (req_no == USB_CDC_REQ_GET_LINE_CODING) 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) */ 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; uint8_t connected_saved = stdout.connected;
if (value != 0) if (detail->value != 0)
{ {
if (stdout.connected == 0) if (stdout.connected == 0)
/* It's Open call */ /* It's Open call */
@@ -259,8 +259,7 @@ static int download_check_crc32 (const uint32_t *end_p)
} }
int int
usb_cb_setup (uint8_t req, uint8_t req_no, usb_cb_setup (uint8_t req, uint8_t req_no, struct control_info *detail)
uint16_t value, uint16_t index, uint16_t len)
{ {
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT); 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 (USB_SETUP_GET (req))
{ {
if (req_no == USB_FSIJ_GNUK_MEMINFO) 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 */ 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 (req_no == USB_FSIJ_GNUK_DOWNLOAD)
{ {
if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED) if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED)
return USB_UNSUPPORT; return USB_UNSUPPORT;
if (addr < &_regnual_start || addr + len > __heap_end__) if (addr < &_regnual_start || addr + detail->len > __heap_end__)
return USB_UNSUPPORT; return USB_UNSUPPORT;
if (index + len < 256) if (detail->index + detail->len < 256)
memset (addr + index + len, 0, 256 - (index + len)); 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; 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) if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED)
return USB_UNSUPPORT; return USB_UNSUPPORT;
@@ -299,27 +298,28 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
return download_check_crc32 ((uint32_t *)addr); 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; return USB_UNSUPPORT;
ccid_card_change_signal (value); ccid_card_change_signal (detail->value);
return USB_SUCCESS; return USB_SUCCESS;
} }
} }
} }
else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT)) else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT))
{ {
if (index == ICC_INTERFACE) if (detail->index == ICC_INTERFACE)
{ {
if (USB_SETUP_GET (req)) if (USB_SETUP_GET (req))
{ {
if (req_no == USB_CCID_REQ_GET_CLOCK_FREQUENCIES) 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) else if (req_no == USB_CCID_REQ_GET_DATA_RATES)
return usb_lld_answer_control (data_rate_table, return usb_lld_reply_request (data_rate_table,
sizeof (data_rate_table)); sizeof (data_rate_table), detail);
} }
else else
{ {
@@ -335,19 +335,19 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
switch (req_no) switch (req_no)
{ {
case USB_HID_REQ_GET_IDLE: 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: 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; return USB_SUCCESS;
case USB_HID_REQ_GET_REPORT: case USB_HID_REQ_GET_REPORT:
/* Request of LED status and key press */ /* 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: case USB_HID_REQ_SET_REPORT:
/* Received LED set request */ /* Received LED set request */
if (len == 1) if (detail->len == 1)
usb_lld_set_data_to_recv (&hid_report, len); usb_lld_set_data_to_recv (&hid_report, detail->len);
return USB_SUCCESS; return USB_SUCCESS;
case USB_HID_REQ_GET_PROTOCOL: case USB_HID_REQ_GET_PROTOCOL:
@@ -362,7 +362,7 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
#endif #endif
#ifdef ENABLE_VIRTUAL_COM_PORT #ifdef ENABLE_VIRTUAL_COM_PORT
else if (index == VCOM_INTERFACE_0) 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 #endif
#ifdef PINPAD_DND_SUPPORT #ifdef PINPAD_DND_SUPPORT
else if (index == MSC_INTERFACE) 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 (USB_SETUP_GET (req))
{ {
if (req_no == MSC_GET_MAX_LUN_COMMAND) 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 else
if (req_no == MSC_MASS_STORAGE_RESET_COMMAND) if (req_no == MSC_MASS_STORAGE_RESET_COMMAND)
@@ -385,14 +386,13 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
void void
usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value, usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value)
uint16_t index, uint16_t len)
{ {
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT); uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
if (type_rcp == (VENDOR_REQUEST | DEVICE_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) if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED)
return; return;
@@ -459,9 +459,11 @@ int usb_cb_handle_event (uint8_t event_type, uint16_t value)
return USB_UNSUPPORT; 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; const uint8_t zero = 0;
uint16_t interface = detail->index;
uint16_t alt = detail->value;
if (interface >= NUM_INTERFACES) if (interface >= NUM_INTERFACES)
return USB_UNSUPPORT; return USB_UNSUPPORT;
@@ -478,10 +480,10 @@ int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
} }
case USB_GET_INTERFACE: case USB_GET_INTERFACE:
return usb_lld_answer_control (&zero, 1); return usb_lld_reply_request (&zero, 1, detail);
default:
case USB_QUERY_INTERFACE: case USB_QUERY_INTERFACE:
default:
return USB_SUCCESS; return USB_SUCCESS;
} }
} }

View File

@@ -59,7 +59,7 @@ static const uint8_t hid_report_desc[] = {
#define USB_ICC_DATA_SIZE 64 #define USB_ICC_DATA_SIZE 64
/* USB Standard Device Descriptor */ /* USB Standard Device Descriptor */
static const uint8_t gnukDeviceDescriptor[] = { static const uint8_t device_desc[] = {
18, /* bLength */ 18, /* bLength */
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x10, 0x01, /* bcdUSB = 1.1 */ 0x10, 0x01, /* bcdUSB = 1.1 */
@@ -99,7 +99,7 @@ static const uint8_t gnukDeviceDescriptor[] = {
/* Configuation Descriptor */ /* Configuation Descriptor */
static const uint8_t gnukConfigDescriptor[] = { static const uint8_t config_desc[] = {
9, /* bLength: Configuation Descriptor size */ 9, /* bLength: Configuation Descriptor size */
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */ USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
W_TOTAL_LENGTH, 0x00, /* wTotalLength:no of returned bytes */ W_TOTAL_LENGTH, 0x00, /* wTotalLength:no of returned bytes */
@@ -346,21 +346,20 @@ static const struct desc string_descriptors[] = {
int int
usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index, 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 (rcp == DEVICE_RECIPIENT)
{ {
if (desc_type == DEVICE_DESCRIPTOR) if (desc_type == DEVICE_DESCRIPTOR)
return usb_lld_answer_control (gnukDeviceDescriptor, return usb_lld_reply_request (device_desc, sizeof (device_desc), detail);
sizeof (gnukDeviceDescriptor));
else if (desc_type == CONFIG_DESCRIPTOR) else if (desc_type == CONFIG_DESCRIPTOR)
return usb_lld_answer_control (gnukConfigDescriptor, return usb_lld_reply_request (config_desc, sizeof (config_desc), detail);
sizeof (gnukConfigDescriptor));
else if (desc_type == STRING_DESCRIPTOR) else if (desc_type == STRING_DESCRIPTOR)
{ {
if (desc_index < NUM_STRING_DESC) if (desc_index < NUM_STRING_DESC)
return usb_lld_answer_control (string_descriptors[desc_index].desc, return usb_lld_reply_request (string_descriptors[desc_index].desc,
string_descriptors[desc_index].size); string_descriptors[desc_index].size,
detail);
else if (desc_index == NUM_STRING_DESC) else if (desc_index == NUM_STRING_DESC)
{ {
uint8_t usbbuf[64]; 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[0] = len = i*2 + 2;
usbbuf[1] = USB_STRING_DESCRIPTOR_TYPE; usbbuf[1] = USB_STRING_DESCRIPTOR_TYPE;
if (len > length) return usb_lld_reply_request (usbbuf, len, detail);
len = length;
return usb_lld_answer_control (usbbuf, len);
} }
} }
} }
#ifdef HID_CARD_CHANGE_SUPPORT
else if (rcp == INTERFACE_RECIPIENT) else if (rcp == INTERFACE_RECIPIENT)
{ {
#ifdef HID_CARD_CHANGE_SUPPORT if (detail->index == 1)
if (index == 1)
{ {
if (desc_type == USB_DT_HID) 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) 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; return USB_UNSUPPORT;
} }

View File

@@ -55,15 +55,19 @@ enum
USB_SUCCESS = 1, USB_SUCCESS = 1,
}; };
struct control_info {
uint16_t value;
uint16_t index;
uint16_t len;
};
void usb_cb_device_reset (void); void usb_cb_device_reset (void);
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, int usb_cb_setup (uint8_t req, uint8_t req_no, struct control_info *detail);
uint16_t value, uint16_t index, uint16_t len); int usb_cb_interface (uint8_t cmd, struct control_info *detail);
int usb_cb_setup (uint8_t req, uint8_t req_no, uint16_t value,
uint16_t index, uint16_t len);
int usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index, 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_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 { enum {
USB_EVENT_ADDRESS, USB_EVENT_ADDRESS,
@@ -89,7 +93,6 @@ enum DEVICE_STATE
CONFIGURED CONFIGURED
}; };
void usb_lld_init (uint8_t feature); void usb_lld_init (uint8_t feature);
void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n); 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); 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_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_tx_enable (int ep_num, size_t len);
void usb_lld_write (uint8_t ep_num, const void *buf, 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); void usb_lld_rx_enable (int ep_num);
int usb_lld_rx_data_len (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); void usb_lld_rxcpy (uint8_t *dst, int ep_num, int offset, size_t len);

View File

@@ -1,9 +1,6 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#define TRUE 1
#define FALSE 0
#include "sys.h" #include "sys.h"
#include "usb_lld.h" #include "usb_lld.h"
@@ -49,33 +46,27 @@ enum FEATURE_SELECTOR
struct DATA_INFO struct DATA_INFO
{ {
uint16_t len;
uint16_t offset;
uint8_t *addr; uint8_t *addr;
uint16_t len;
uint8_t require_zlp; 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 struct DEVICE_INFO
{ {
uint8_t current_configuration; uint8_t current_configuration;
uint8_t current_feature; uint8_t current_feature;
uint8_t state; 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 DEVICE_INFO device_info;
static struct DATA_INFO data_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 DEVICE_INFO *const dev_p = &device_info;
static struct DATA_INFO *const data_p = &data_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) if (data_p->addr && data_p->len)
{ {
uint8_t *buf;
uint32_t len = st103_get_rx_count (ENDP0); uint32_t len = st103_get_rx_count (ENDP0);
if (len > data_p->len) if (len > data_p->len)
len = data_p->len; len = data_p->len;
buf = data_p->addr + data_p->offset; usb_lld_from_pmabuf (data_p->addr, st103_get_rx_addr (ENDP0), len);
usb_lld_from_pmabuf (buf, st103_get_rx_addr (ENDP0), len);
data_p->len -= len; data_p->len -= len;
data_p->offset += len; data_p->addr += len;
} }
if (data_p->len == 0) if (data_p->len == 0)
@@ -440,13 +429,12 @@ static void handle_datastage_out (void)
static void handle_datastage_in (void) static void handle_datastage_in (void)
{ {
uint32_t len = USB_MAX_PACKET_SIZE;; 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->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 */ /* No more data to send. Send empty packet */
st103_set_tx_count (ENDP0, 0); st103_set_tx_count (ENDP0, 0);
@@ -467,37 +455,33 @@ static void handle_datastage_in (void)
if (len > data_p->len) if (len > data_p->len)
len = data_p->len; len = data_p->len;
buf = (const uint8_t *)data_p->addr + data_p->offset; usb_lld_to_pmabuf (data_p->addr, st103_get_tx_addr (ENDP0), len);
usb_lld_to_pmabuf (buf, st103_get_tx_addr (ENDP0), len);
data_p->len -= len; data_p->len -= len;
data_p->offset += len; data_p->addr += len;
st103_set_tx_count (ENDP0, len); st103_set_tx_count (ENDP0, len);
st103_ep_set_tx_status (ENDP0, EP_TX_VALID); st103_ep_set_tx_status (ENDP0, EP_TX_VALID);
} }
typedef int (*HANDLER) (uint8_t req, typedef int (*HANDLER) (uint8_t req, struct control_info *detail);
uint16_t value, uint16_t index, uint16_t length);
static int std_none (uint8_t req, static int std_none (uint8_t req, struct control_info *detail)
uint16_t value, uint16_t index, uint16_t length)
{ {
(void)req; (void)value; (void)index; (void)length; (void)req; (void)detail;
return USB_UNSUPPORT; return USB_UNSUPPORT;
} }
static int std_get_status (uint8_t req, static int std_get_status (uint8_t req, struct control_info *detail)
uint16_t value, uint16_t index, uint16_t length)
{ {
uint8_t rcp = req & RECIPIENT; uint8_t rcp = req & RECIPIENT;
uint16_t status_info = 0; 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) || (req & REQUEST_DIR) == 0)
return USB_UNSUPPORT; return USB_UNSUPPORT;
if (rcp == DEVICE_RECIPIENT) if (rcp == DEVICE_RECIPIENT)
{ {
if (index == 0) if (detail->index == 0)
{ {
/* Get Device Status */ /* Get Device Status */
uint8_t feature = dev_p->current_feature; uint8_t feature = dev_p->current_feature;
@@ -514,7 +498,7 @@ static int std_get_status (uint8_t req,
else /* Self-powered */ else /* Self-powered */
status_info &= ~1; 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) else if (rcp == INTERFACE_RECIPIENT)
@@ -524,21 +508,21 @@ static int std_get_status (uint8_t req,
if (dev_p->current_configuration == 0) if (dev_p->current_configuration == 0)
return USB_UNSUPPORT; return USB_UNSUPPORT;
r = usb_cb_interface (USB_QUERY_INTERFACE, index, 0); r = usb_cb_interface (USB_QUERY_INTERFACE, detail);
if (r != USB_SUCCESS) if (r != USB_SUCCESS)
return USB_UNSUPPORT; 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) else if (rcp == ENDPOINT_RECIPIENT)
{ {
uint8_t endpoint = (index & 0x0f); uint8_t endpoint = (detail->index & 0x0f);
uint16_t status; uint16_t status;
if ((index & 0x70) || endpoint == ENDP0) if ((detail->index & 0x70) || endpoint == ENDP0)
return USB_UNSUPPORT; return USB_UNSUPPORT;
if ((index & 0x80)) if ((detail->index & 0x80))
{ {
status = st103_ep_get_tx_status (endpoint); status = st103_ep_get_tx_status (endpoint);
if (status == 0) /* Disabled */ if (status == 0) /* Disabled */
@@ -555,14 +539,13 @@ static int std_get_status (uint8_t req,
status_info |= 1; /* OUT Endpoint stalled */ 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; return USB_UNSUPPORT;
} }
static int std_clear_feature (uint8_t req, uint16_t value, static int std_clear_feature (uint8_t req, struct control_info *detail)
uint16_t index, uint16_t length)
{ {
uint8_t rcp = req & RECIPIENT; 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 (rcp == DEVICE_RECIPIENT)
{ {
if (length != 0 || index != 0) if (detail->len != 0 || detail->index != 0)
return USB_UNSUPPORT; return USB_UNSUPPORT;
if (value == DEVICE_REMOTE_WAKEUP) if (detail->value == DEVICE_REMOTE_WAKEUP)
{ {
dev_p->current_feature &= ~(1 << 5); dev_p->current_feature &= ~(1 << 5);
return USB_SUCCESS; return USB_SUCCESS;
@@ -582,17 +565,17 @@ static int std_clear_feature (uint8_t req, uint16_t value,
} }
else if (rcp == ENDPOINT_RECIPIENT) else if (rcp == ENDPOINT_RECIPIENT)
{ {
uint8_t endpoint = (index & 0x0f); uint8_t endpoint = (detail->index & 0x0f);
uint16_t status; uint16_t status;
if (dev_p->current_configuration == 0) if (dev_p->current_configuration == 0)
return USB_UNSUPPORT; return USB_UNSUPPORT;
if (length != 0 || (index >> 8) != 0 || value != ENDPOINT_STALL if (detail->len != 0 || (detail->index >> 8) != 0
|| endpoint == ENDP0) || detail->value != ENDPOINT_STALL || endpoint == ENDP0)
return USB_UNSUPPORT; return USB_UNSUPPORT;
if ((index & 0x80)) if ((detail->index & 0x80))
status = st103_ep_get_tx_status (endpoint); status = st103_ep_get_tx_status (endpoint);
else else
status = st103_ep_get_rx_status (endpoint); 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 */ if (status == 0) /* Disabled */
return USB_UNSUPPORT; return USB_UNSUPPORT;
if (index & 0x80) /* IN endpoint */ if (detail->index & 0x80) /* IN endpoint */
st103_ep_clear_dtog_tx (endpoint); st103_ep_clear_dtog_tx (endpoint);
else /* OUT endpoint */ else /* OUT endpoint */
st103_ep_clear_dtog_rx (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; return USB_UNSUPPORT;
} }
static int std_set_feature (uint8_t req, uint16_t value, static int std_set_feature (uint8_t req, struct control_info *detail)
uint16_t index, uint16_t length)
{ {
uint8_t rcp = req & RECIPIENT; 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 (rcp == DEVICE_RECIPIENT)
{ {
if (length != 0 || index != 0) if (detail->len != 0 || detail->index != 0)
return USB_UNSUPPORT; return USB_UNSUPPORT;
if (value == DEVICE_REMOTE_WAKEUP) if (detail->value == DEVICE_REMOTE_WAKEUP)
{ {
dev_p->current_feature |= 1 << 5; dev_p->current_feature |= 1 << 5;
// event?? // event??
@@ -634,16 +616,17 @@ static int std_set_feature (uint8_t req, uint16_t value,
} }
else if (rcp == ENDPOINT_RECIPIENT) else if (rcp == ENDPOINT_RECIPIENT)
{ {
uint8_t endpoint = (index & 0x0f); uint8_t endpoint = (detail->index & 0x0f);
uint32_t status; uint32_t status;
if (dev_p->current_configuration == 0) if (dev_p->current_configuration == 0)
return USB_UNSUPPORT; 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; return USB_UNSUPPORT;
if ((index & 0x80)) if ((detail->index & 0x80))
status = st103_ep_get_tx_status (endpoint); status = st103_ep_get_tx_status (endpoint);
else else
status = st103_ep_get_rx_status (endpoint); 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 */ if (status == 0) /* Disabled */
return USB_UNSUPPORT; return USB_UNSUPPORT;
if (index & 0x80) if (detail->index & 0x80)
/* IN endpoint */ /* IN endpoint */
st103_ep_set_tx_status (endpoint, EP_TX_STALL); st103_ep_set_tx_status (endpoint, EP_TX_STALL);
else else
@@ -665,74 +648,59 @@ static int std_set_feature (uint8_t req, uint16_t value,
return USB_UNSUPPORT; return USB_UNSUPPORT;
} }
static int std_set_address (uint8_t req, uint16_t value, static int std_set_address (uint8_t req, struct control_info *detail)
uint16_t index, uint16_t length)
{ {
uint8_t rcp = req & RECIPIENT; uint8_t rcp = req & RECIPIENT;
if ((req & REQUEST_DIR) == 1) if ((req & REQUEST_DIR) == 1)
return USB_UNSUPPORT; return USB_UNSUPPORT;
if (rcp == DEVICE_RECIPIENT) if (rcp == DEVICE_RECIPIENT && detail->len == 0 && detail->value <= 127
{ && detail->index == 0 && dev_p->current_configuration == 0)
if (length == 0 && value <= 127 && index == 0 return USB_SUCCESS;
&& dev_p->current_configuration == 0)
return USB_SUCCESS;
}
return USB_UNSUPPORT; return USB_UNSUPPORT;
} }
static int std_get_descriptor (uint8_t req, uint16_t value, static int std_get_descriptor (uint8_t req, struct control_info *detail)
uint16_t index, uint16_t length)
{ {
uint8_t rcp = req & RECIPIENT; uint8_t rcp = req & RECIPIENT;
if ((req & REQUEST_DIR) == 0) if ((req & REQUEST_DIR) == 0)
return USB_UNSUPPORT; return USB_UNSUPPORT;
(void)length; return usb_cb_get_descriptor (rcp, (detail->value >> 8),
return usb_cb_get_descriptor (rcp, (value >> 8), (value & 0xff), (detail->value & 0xff), detail);
index, length);
} }
static int std_get_configuration (uint8_t req, uint16_t value, static int std_get_configuration (uint8_t req, struct control_info *detail)
uint16_t index, uint16_t length)
{ {
uint8_t rcp = req & RECIPIENT; uint8_t rcp = req & RECIPIENT;
(void)detail;
if ((req & REQUEST_DIR) == 0) if ((req & REQUEST_DIR) == 0)
return USB_UNSUPPORT; return USB_UNSUPPORT;
(void)value; (void)index; (void)length;
if (rcp == DEVICE_RECIPIENT) 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; return USB_UNSUPPORT;
} }
static int std_set_configuration (uint8_t req, uint16_t value, static int std_set_configuration (uint8_t req, struct control_info *detail)
uint16_t index, uint16_t length)
{ {
uint8_t rcp = req & RECIPIENT; uint8_t rcp = req & RECIPIENT;
if ((req & REQUEST_DIR) == 1) if ((req & REQUEST_DIR) == 1)
return USB_UNSUPPORT; return USB_UNSUPPORT;
if (rcp == DEVICE_RECIPIENT && index == 0 && length == 0) if (rcp == DEVICE_RECIPIENT && detail->index == 0 && detail->len == 0)
{ return usb_cb_handle_event (USB_EVENT_CONFIG, detail->value);
int r;
r = usb_cb_handle_event (USB_EVENT_CONFIG, value);
if (r == USB_SUCCESS)
return USB_SUCCESS;
}
return USB_UNSUPPORT; return USB_UNSUPPORT;
} }
static int std_get_interface (uint8_t req, uint16_t value, static int std_get_interface (uint8_t req, struct control_info *detail)
uint16_t index, uint16_t length)
{ {
uint8_t rcp = req & RECIPIENT; 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 (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; return USB_UNSUPPORT;
if (dev_p->current_configuration == 0) if (dev_p->current_configuration == 0)
return USB_UNSUPPORT; return USB_UNSUPPORT;
return usb_cb_interface (USB_GET_INTERFACE, index, 0); return usb_cb_interface (USB_GET_INTERFACE, detail);
} }
return USB_UNSUPPORT; return USB_UNSUPPORT;
} }
static int std_set_interface (uint8_t req, uint16_t value, static int std_set_interface (uint8_t req, struct control_info *detail)
uint16_t index, uint16_t length)
{ {
uint8_t rcp = req & RECIPIENT; 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; return USB_UNSUPPORT;
if (rcp == INTERFACE_RECIPIENT) return usb_cb_interface (USB_SET_INTERFACE, detail);
{
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;
} }
static void handle_setup0 (void) static void handle_setup0 (void)
{ {
const uint16_t *pw; const uint16_t *pw;
struct control_info ctrl;
uint16_t w; uint16_t w;
uint8_t req; uint8_t req_no;
int r = USB_UNSUPPORT; int r = USB_UNSUPPORT;
HANDLER handler; HANDLER handler;
pw = (uint16_t *)(PMA_ADDR + (uint8_t *)(st103_get_rx_addr (ENDP0) * 2)); pw = (uint16_t *)(PMA_ADDR + (uint8_t *)(st103_get_rx_addr (ENDP0) * 2));
w = *pw++; w = *pw++;
ctrl_p->bmRequestType = w & 0xff; dev_p->bmRequestType = w & 0xff;
ctrl_p->bRequest = req = w >> 8; dev_p->bRequest = req_no = w >> 8;
pw++; pw++;
ctrl_p->wValue = *pw++; ctrl.value = *pw++;
pw++; pw++;
ctrl_p->wIndex = *pw++; ctrl.index = *pw++;
pw++; pw++;
ctrl_p->wLength = *pw; ctrl.len = *pw;
data_p->addr = NULL; data_p->addr = NULL;
data_p->len = 0; 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 0: handler = std_get_status; break;
case 1: handler = std_clear_feature; break; case 1: handler = std_clear_feature; break;
@@ -822,30 +777,30 @@ static void handle_setup0 (void)
default: handler = std_none; break; default: handler = std_none; break;
} }
r = (*handler) (ctrl_p->bmRequestType, r = (*handler) (dev_p->bmRequestType, &ctrl);
ctrl_p->wValue, ctrl_p->wIndex, ctrl_p->wLength);
} }
} }
else else
r = usb_cb_setup (ctrl_p->bmRequestType, req, r = usb_cb_setup (dev_p->bmRequestType, req_no, &ctrl);
ctrl_p->wValue, ctrl_p->wIndex, ctrl_p->wLength);
if (r != USB_SUCCESS) if (r != USB_SUCCESS)
dev_p->state = STALLED; dev_p->state = STALLED;
else else
{ {
if (USB_SETUP_GET (ctrl_p->bmRequestType)) if (USB_SETUP_SET (dev_p->bmRequestType))
;
else if (ctrl_p->wLength == 0)
{ {
dev_p->state = WAIT_STATUS_IN; dev_p->value = ctrl.value;
st103_set_tx_count (ENDP0, 0); if (ctrl.len == 0)
st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_VALID); {
} dev_p->state = WAIT_STATUS_IN;
else st103_set_tx_count (ENDP0, 0);
{ st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_VALID);
dev_p->state = OUT_DATA; }
st103_ep_set_rx_status (ENDP0, EP_RX_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 (); handle_datastage_in ();
else if (dev_p->state == WAIT_STATUS_IN) else if (dev_p->state == WAIT_STATUS_IN)
{ {
if ((ctrl_p->bRequest == SET_ADDRESS) && if ((dev_p->bRequest == SET_ADDRESS) &&
((ctrl_p->bmRequestType & (REQUEST_TYPE | RECIPIENT)) ((dev_p->bmRequestType & (REQUEST_TYPE | RECIPIENT))
== (STANDARD_REQUEST | DEVICE_RECIPIENT))) == (STANDARD_REQUEST | DEVICE_RECIPIENT)))
{ {
st103_set_daddr (ctrl_p->wValue); st103_set_daddr (dev_p->value);
usb_cb_handle_event (USB_EVENT_ADDRESS, ctrl_p->wValue); usb_cb_handle_event (USB_EVENT_ADDRESS, dev_p->value);
} }
else else
usb_cb_ctrl_write_finish (ctrl_p->bmRequestType, usb_cb_ctrl_write_finish (dev_p->bmRequestType, dev_p->bRequest,
ctrl_p->bRequest, ctrl_p->wValue, dev_p->value);
ctrl_p->wIndex, ctrl_p->wLength);
dev_p->state = STALLED; 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. * BUFLEN: size of the data.
*/ */
int 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; uint32_t len;
data_p->addr = (void *)buf; data_p->addr = (void *)buf;
@@ -1188,9 +1142,7 @@ usb_lld_answer_control (const void *buf, size_t buflen)
data_p->len = len_asked; data_p->len = len_asked;
if (data_p->len != 0 && (data_p->len % USB_MAX_PACKET_SIZE) == 0) if (data_p->len != 0 && (data_p->len % USB_MAX_PACKET_SIZE) == 0)
data_p->require_zlp = TRUE; data_p->require_zlp = 1;
else
data_p->require_zlp = FALSE;
if (data_p->len < USB_MAX_PACKET_SIZE) 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); usb_lld_to_pmabuf (data_p->addr, st103_get_tx_addr (ENDP0), len);
data_p->len -= len; data_p->len -= len;
data_p->offset += len; data_p->addr += len;
} }
st103_set_tx_count (ENDP0, len); st103_set_tx_count (ENDP0, len);