remove comments to reduce rows
This commit is contained in:
@@ -63,6 +63,7 @@ struct audio_entity_info {
|
|||||||
|
|
||||||
static usb_slist_t usbd_audio_entity_info_head = USB_SLIST_OBJECT_INIT(usbd_audio_entity_info_head);
|
static usb_slist_t usbd_audio_entity_info_head = USB_SLIST_OBJECT_INIT(usbd_audio_entity_info_head);
|
||||||
|
|
||||||
|
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
|
||||||
const uint8_t default_sampling_freq_table[] = {
|
const uint8_t default_sampling_freq_table[] = {
|
||||||
AUDIO_SAMPLE_FREQ_NUM(1),
|
AUDIO_SAMPLE_FREQ_NUM(1),
|
||||||
// AUDIO_SAMPLE_FREQ_4B(8000),
|
// AUDIO_SAMPLE_FREQ_4B(8000),
|
||||||
@@ -90,6 +91,7 @@ const uint8_t default_sampling_freq_table[] = {
|
|||||||
AUDIO_SAMPLE_FREQ_4B(192000),
|
AUDIO_SAMPLE_FREQ_4B(192000),
|
||||||
AUDIO_SAMPLE_FREQ_4B(0x00),
|
AUDIO_SAMPLE_FREQ_4B(0x00),
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
|
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
|
||||||
static int audio_custom_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int audio_custom_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
@@ -144,7 +146,9 @@ static int audio_class_request_handler(struct usb_setup_packet *setup, uint8_t *
|
|||||||
|
|
||||||
struct audio_entity_info *current_entity_info = NULL;
|
struct audio_entity_info *current_entity_info = NULL;
|
||||||
struct usbd_audio_attribute_control *current_feature_control = NULL;
|
struct usbd_audio_attribute_control *current_feature_control = NULL;
|
||||||
|
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
|
||||||
uint32_t *sampling_freq;
|
uint32_t *sampling_freq;
|
||||||
|
#endif
|
||||||
usb_slist_t *i;
|
usb_slist_t *i;
|
||||||
uint8_t entity_id;
|
uint8_t entity_id;
|
||||||
uint8_t control_selector;
|
uint8_t control_selector;
|
||||||
@@ -176,8 +180,9 @@ static int audio_class_request_handler(struct usb_setup_packet *setup, uint8_t *
|
|||||||
}
|
}
|
||||||
|
|
||||||
current_feature_control = (struct usbd_audio_attribute_control *)current_entity_info->priv[0];
|
current_feature_control = (struct usbd_audio_attribute_control *)current_entity_info->priv[0];
|
||||||
|
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
|
||||||
sampling_freq = (uint32_t *)current_entity_info->priv[1];
|
sampling_freq = (uint32_t *)current_entity_info->priv[1];
|
||||||
|
#endif
|
||||||
if (current_entity_info->bDescriptorSubtype == AUDIO_CONTROL_FEATURE_UNIT) {
|
if (current_entity_info->bDescriptorSubtype == AUDIO_CONTROL_FEATURE_UNIT) {
|
||||||
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
|
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
|
||||||
float volume2db = 0.0;
|
float volume2db = 0.0;
|
||||||
@@ -443,11 +448,15 @@ void usbd_audio_add_entity(uint8_t entity_id, uint16_t bDescriptorSubtype)
|
|||||||
#endif
|
#endif
|
||||||
entity_info->priv[0] = control;
|
entity_info->priv[0] = control;
|
||||||
} else if (bDescriptorSubtype == AUDIO_CONTROL_CLOCK_SOURCE) {
|
} else if (bDescriptorSubtype == AUDIO_CONTROL_CLOCK_SOURCE) {
|
||||||
|
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
|
||||||
uint32_t *sampling_freq = usb_malloc(sizeof(uint32_t) * CONFIG_USBDEV_AUDIO_MAX_CHANNEL);
|
uint32_t *sampling_freq = usb_malloc(sizeof(uint32_t) * CONFIG_USBDEV_AUDIO_MAX_CHANNEL);
|
||||||
for (size_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
|
for (size_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
|
||||||
sampling_freq[ch] = 16000;
|
sampling_freq[ch] = 16000;
|
||||||
}
|
}
|
||||||
entity_info->priv[1] = sampling_freq;
|
entity_info->priv[1] = sampling_freq;
|
||||||
|
#else
|
||||||
|
entity_info->priv[1] = NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_slist_add_tail(&usbd_audio_entity_info_head, &entity_info->list);
|
usb_slist_add_tail(&usbd_audio_entity_info_head, &entity_info->list);
|
||||||
@@ -464,12 +473,12 @@ __WEAK void usbd_audio_set_mute(uint8_t entity_id, uint8_t ch, uint8_t enable)
|
|||||||
__WEAK void usbd_audio_set_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq)
|
__WEAK void usbd_audio_set_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
|
||||||
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
|
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
|
||||||
{
|
{
|
||||||
*sampling_freq_table = (uint8_t *)default_sampling_freq_table;
|
*sampling_freq_table = (uint8_t *)default_sampling_freq_table;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
__WEAK void usbd_audio_set_pitch(uint8_t ep, bool enable)
|
__WEAK void usbd_audio_set_pitch(uint8_t ep, bool enable)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
const char *stop_name[] = { "1", "1.5", "2" };
|
const char *stop_name[] = { "1", "1.5", "2" };
|
||||||
const char *parity_name[] = { "N", "O", "E", "M", "S" };
|
const char *parity_name[] = { "N", "O", "E", "M", "S" };
|
||||||
|
|
||||||
/* Device data structure */
|
|
||||||
struct usbd_cdc {
|
struct usbd_cdc {
|
||||||
struct cdc_line_coding line_coding;
|
struct cdc_line_coding line_coding;
|
||||||
bool dtr;
|
bool dtr;
|
||||||
@@ -48,15 +47,7 @@ static void usbd_cdc_acm_reset(void)
|
|||||||
g_usbd_cdc_acm_class.line_coding.bCharFormat = 0;
|
g_usbd_cdc_acm_class.line_coding.bCharFormat = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/**
|
|
||||||
* @brief Handler called for Class requests not handled by the USB stack.
|
|
||||||
*
|
|
||||||
* @param setup Information about the request to execute.
|
|
||||||
* @param len Size of the buffer.
|
|
||||||
* @param data Buffer containing the request result.
|
|
||||||
*
|
|
||||||
* @return 0 on success, negative errno code on fail.
|
|
||||||
*/
|
|
||||||
static int cdc_acm_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int cdc_acm_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
USB_LOG_DBG("CDC Class request: "
|
USB_LOG_DBG("CDC Class request: "
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#include "usbd_core.h"
|
#include "usbd_core.h"
|
||||||
#include "usbd_dfu.h"
|
#include "usbd_dfu.h"
|
||||||
|
|
||||||
/* Device data structure */
|
|
||||||
struct dfu_cfg_priv {
|
struct dfu_cfg_priv {
|
||||||
struct dfu_info info;
|
struct dfu_info info;
|
||||||
} usbd_dfu_cfg;
|
} usbd_dfu_cfg;
|
||||||
|
|||||||
@@ -23,9 +23,6 @@
|
|||||||
#include "usbd_core.h"
|
#include "usbd_core.h"
|
||||||
#include "usbd_hid.h"
|
#include "usbd_hid.h"
|
||||||
|
|
||||||
#define HID_STATE_IDLE 0
|
|
||||||
#define HID_STATE_BUSY 1
|
|
||||||
|
|
||||||
struct usbd_hid {
|
struct usbd_hid {
|
||||||
const uint8_t *hid_descriptor;
|
const uint8_t *hid_descriptor;
|
||||||
const uint8_t *hid_report_descriptor;
|
const uint8_t *hid_report_descriptor;
|
||||||
|
|||||||
@@ -76,9 +76,6 @@ USB_NOCACHE_RAM_SECTION struct usbd_msc_cfg_priv {
|
|||||||
uint8_t block_buffer[CONFIG_USBDEV_MSC_BLOCK_SIZE];
|
uint8_t block_buffer[CONFIG_USBDEV_MSC_BLOCK_SIZE];
|
||||||
} usbd_msc_cfg;
|
} usbd_msc_cfg;
|
||||||
|
|
||||||
/*memory OK (after a usbd_msc_memory_verify)*/
|
|
||||||
static bool memOK;
|
|
||||||
|
|
||||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||||
static volatile uint8_t thread_op;
|
static volatile uint8_t thread_op;
|
||||||
static usb_osal_sem_t msc_sem;
|
static usb_osal_sem_t msc_sem;
|
||||||
@@ -91,15 +88,6 @@ static void usbd_msc_reset(void)
|
|||||||
usbd_msc_cfg.stage = MSC_READ_CBW;
|
usbd_msc_cfg.stage = MSC_READ_CBW;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Handler called for Class requests not handled by the USB stack.
|
|
||||||
*
|
|
||||||
* @param setup Information about the request to execute.
|
|
||||||
* @param len Size of the buffer.
|
|
||||||
* @param data Buffer containing the request result.
|
|
||||||
*
|
|
||||||
* @return 0 on success, negative errno code on fail.
|
|
||||||
*/
|
|
||||||
static int msc_storage_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int msc_storage_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
USB_LOG_DBG("MSC Class request: "
|
USB_LOG_DBG("MSC Class request: "
|
||||||
@@ -640,7 +628,8 @@ static bool SCSI_write12(uint8_t **data, uint32_t *len)
|
|||||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, &usbd_msc_cfg.block_buffer[usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size], MASS_STORAGE_BULK_EP_MPS);
|
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, &usbd_msc_cfg.block_buffer[usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size], MASS_STORAGE_BULK_EP_MPS);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
/* do not use verify to reduce code size */
|
||||||
|
#if 0
|
||||||
static bool SCSI_verify10(uint8_t **data, uint32_t *len)
|
static bool SCSI_verify10(uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
/* Logical Block Address of First Block */
|
/* Logical Block Address of First Block */
|
||||||
@@ -681,11 +670,10 @@ static bool SCSI_verify10(uint8_t **data, uint32_t *len)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
memOK = true;
|
|
||||||
usbd_msc_cfg.stage = MSC_DATA_OUT;
|
usbd_msc_cfg.stage = MSC_DATA_OUT;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||||
static void usbd_msc_thread_memory_read_done(void)
|
static void usbd_msc_thread_memory_read_done(void)
|
||||||
{
|
{
|
||||||
@@ -863,7 +851,8 @@ static bool SCSI_CBWDecode(uint32_t nbytes)
|
|||||||
ret = SCSI_write12(NULL, 0);
|
ret = SCSI_write12(NULL, 0);
|
||||||
break;
|
break;
|
||||||
case SCSI_CMD_VERIFY10:
|
case SCSI_CMD_VERIFY10:
|
||||||
ret = SCSI_verify10(NULL, 0);
|
//ret = SCSI_verify10(NULL, 0);
|
||||||
|
ret = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#include "usbd_core.h"
|
#include "usbd_core.h"
|
||||||
#include "usbd_mtp.h"
|
#include "usbd_mtp.h"
|
||||||
|
|
||||||
/* Device data structure */
|
|
||||||
struct mtp_cfg_priv {
|
struct mtp_cfg_priv {
|
||||||
uint8_t device_status;
|
uint8_t device_status;
|
||||||
} usbd_mtp_cfg;
|
} usbd_mtp_cfg;
|
||||||
@@ -41,15 +40,6 @@ struct mtp_cfg_priv {
|
|||||||
/* Describe EndPoints configuration */
|
/* Describe EndPoints configuration */
|
||||||
static usbd_endpoint_t mtp_ep_data[2];
|
static usbd_endpoint_t mtp_ep_data[2];
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Handler called for Class requests not handled by the USB stack.
|
|
||||||
*
|
|
||||||
* @param setup Information about the request to execute.
|
|
||||||
* @param len Size of the buffer.
|
|
||||||
* @param data Buffer containing the request result.
|
|
||||||
*
|
|
||||||
* @return 0 on success, negative errno code on fail.
|
|
||||||
*/
|
|
||||||
static int mtp_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int mtp_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
USB_LOG_DBG("MTP Class request: "
|
USB_LOG_DBG("MTP Class request: "
|
||||||
|
|||||||
@@ -23,21 +23,11 @@
|
|||||||
#include "usbd_core.h"
|
#include "usbd_core.h"
|
||||||
#include "usbd_printer.h"
|
#include "usbd_printer.h"
|
||||||
|
|
||||||
/* Device data structure */
|
|
||||||
struct printer_cfg_priv {
|
struct printer_cfg_priv {
|
||||||
uint8_t *device_id;
|
uint8_t *device_id;
|
||||||
uint8_t port_status;
|
uint8_t port_status;
|
||||||
} usbd_printer_cfg;
|
} usbd_printer_cfg;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Handler called for Class requests not handled by the USB stack.
|
|
||||||
*
|
|
||||||
* @param setup Information about the request to execute.
|
|
||||||
* @param len Size of the buffer.
|
|
||||||
* @param data Buffer containing the request result.
|
|
||||||
*
|
|
||||||
* @return 0 on success, negative errno code on fail.
|
|
||||||
*/
|
|
||||||
static int printer_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int printer_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
USB_LOG_DBG("Printer Class request: "
|
USB_LOG_DBG("Printer Class request: "
|
||||||
|
|||||||
@@ -35,35 +35,20 @@ extern "C" {
|
|||||||
* Structure containing the USB endpoint configuration.
|
* Structure containing the USB endpoint configuration.
|
||||||
*/
|
*/
|
||||||
struct usbd_endpoint_cfg {
|
struct usbd_endpoint_cfg {
|
||||||
/** The number associated with the EP in the device
|
uint8_t ep_addr; /* Endpoint addr with direction */
|
||||||
* configuration structure
|
uint8_t ep_type; /* Endpoint type */
|
||||||
* IN EP = 0x80 | \<endpoint number\>
|
uint16_t ep_mps; /* Endpoint max packet size */
|
||||||
* OUT EP = 0x00 | \<endpoint number\>
|
|
||||||
*/
|
|
||||||
uint8_t ep_addr;
|
|
||||||
/** Endpoint Transfer Type.
|
|
||||||
* May be Bulk, Interrupt, Control or Isochronous
|
|
||||||
*/
|
|
||||||
uint8_t ep_type;
|
|
||||||
/** Endpoint max packet size */
|
|
||||||
uint16_t ep_mps;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief USB Device Core Layer API
|
|
||||||
* @defgroup _usb_device_core_api USB Device Core API
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief init device controller registers.
|
* @brief init device controller registers.
|
||||||
* @return 0 on success, negative errno code on fail.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usb_dc_init(void);
|
int usb_dc_init(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief deinit device controller registers.
|
* @brief deinit device controller registers.
|
||||||
* @return 0 on success, negative errno code on fail.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usb_dc_deinit(void);
|
int usb_dc_deinit(void);
|
||||||
|
|
||||||
@@ -72,43 +57,35 @@ int usb_dc_deinit(void);
|
|||||||
*
|
*
|
||||||
* @param[in] addr Device address
|
* @param[in] addr Device address
|
||||||
*
|
*
|
||||||
* @return 0 on success, negative errno code on fail.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usbd_set_address(const uint8_t addr);
|
int usbd_set_address(const uint8_t addr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief configure and enable endpoint.
|
* @brief configure and enable endpoint.
|
||||||
*
|
*
|
||||||
* This function sets endpoint configuration according to one specified in USB.
|
* @param [in] ep_cfg Endpoint config.
|
||||||
* endpoint descriptor and then enables it for data transfers.
|
|
||||||
*
|
*
|
||||||
* @param [in] ep_desc Endpoint descriptor byte array.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*
|
|
||||||
* @return true if successfully configured and enabled.
|
|
||||||
*/
|
*/
|
||||||
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg);
|
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Disable the selected endpoint
|
* @brief Disable the selected endpoint
|
||||||
*
|
*
|
||||||
* Function to disable the selected endpoint. Upon success interrupts are
|
* @param[in] ep Endpoint address
|
||||||
* disabled for the corresponding endpoint and the endpoint is no longer able
|
|
||||||
* for transmitting/receiving data.
|
|
||||||
*
|
*
|
||||||
* @param[in] ep Endpoint address corresponding to the one
|
* @return On success will return 0, and others indicate fail.
|
||||||
* listed in the device configuration table
|
|
||||||
*
|
|
||||||
* @return 0 on success, negative errno code on fail.
|
|
||||||
*/
|
*/
|
||||||
int usbd_ep_close(const uint8_t ep);
|
int usbd_ep_close(const uint8_t ep);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set stall condition for the selected endpoint
|
* @brief Set stall condition for the selected endpoint
|
||||||
*
|
*
|
||||||
* @param[in] ep Endpoint address corresponding to the one
|
* @param[in] ep Endpoint address
|
||||||
* listed in the device configuration table
|
|
||||||
*
|
*
|
||||||
* @return 0 on success, negative errno code on fail.
|
*
|
||||||
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usbd_ep_set_stall(const uint8_t ep);
|
int usbd_ep_set_stall(const uint8_t ep);
|
||||||
|
|
||||||
@@ -118,18 +95,18 @@ int usbd_ep_set_stall(const uint8_t ep);
|
|||||||
* @param[in] ep Endpoint address corresponding to the one
|
* @param[in] ep Endpoint address corresponding to the one
|
||||||
* listed in the device configuration table
|
* listed in the device configuration table
|
||||||
*
|
*
|
||||||
* @return 0 on success, negative errno code on fail.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usbd_ep_clear_stall(const uint8_t ep);
|
int usbd_ep_clear_stall(const uint8_t ep);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if the selected endpoint is stalled
|
* @brief Check if the selected endpoint is stalled
|
||||||
*
|
*
|
||||||
* @param[in] ep Endpoint address corresponding to the one
|
* @param[in] ep Endpoint address
|
||||||
* listed in the device configuration table
|
*
|
||||||
* @param[out] stalled Endpoint stall status
|
* @param[out] stalled Endpoint stall status
|
||||||
*
|
*
|
||||||
* @return 0 on success, negative errno code on fail.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled);
|
int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled);
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
/**< maximum packet size (MPS) for EP 0 */
|
/**< maximum packet size (MPS) for EP 0 */
|
||||||
#define USB_CTRL_EP_MPS 64
|
#define USB_CTRL_EP_MPS 64
|
||||||
|
|
||||||
// USB PID Types
|
/* USB PID Types */
|
||||||
#define USB_PID_OUT (0x01) /* Tokens */
|
#define USB_PID_OUT (0x01) /* Tokens */
|
||||||
#define USB_PID_IN (0x09)
|
#define USB_PID_IN (0x09)
|
||||||
#define USB_PID_SOF (0x05)
|
#define USB_PID_SOF (0x05)
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ extern "C" {
|
|||||||
|
|
||||||
typedef void (*usbh_asynch_callback_t)(void *arg, int nbytes);
|
typedef void (*usbh_asynch_callback_t)(void *arg, int nbytes);
|
||||||
typedef void *usbh_epinfo_t;
|
typedef void *usbh_epinfo_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief USB Endpoint Configuration.
|
* @brief USB Endpoint Configuration.
|
||||||
*
|
*
|
||||||
@@ -38,38 +39,24 @@ typedef void *usbh_epinfo_t;
|
|||||||
*/
|
*/
|
||||||
struct usbh_endpoint_cfg {
|
struct usbh_endpoint_cfg {
|
||||||
struct usbh_hubport *hport;
|
struct usbh_hubport *hport;
|
||||||
/** The number associated with the EP in the device
|
uint8_t ep_addr; /* Endpoint addr with direction */
|
||||||
* configuration structure
|
uint8_t ep_type; /* Endpoint type */
|
||||||
* IN EP = 0x80 | \<endpoint number\>
|
uint16_t ep_mps; /* Endpoint max packet size */
|
||||||
* OUT EP = 0x00 | \<endpoint number\>
|
uint8_t ep_interval; /* Endpoint interval */
|
||||||
*/
|
uint16_t ep_mps; /* Endpoint max packet size */
|
||||||
uint8_t ep_addr;
|
|
||||||
/** Endpoint Transfer Type.
|
|
||||||
* May be Bulk, Interrupt, Control or Isochronous
|
|
||||||
*/
|
|
||||||
uint8_t ep_type;
|
|
||||||
uint8_t ep_interval;
|
|
||||||
/** Endpoint max packet size */
|
|
||||||
uint16_t ep_mps;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief USB Host Core Layer API
|
|
||||||
* @defgroup _usb_host_core_api USB Host Core API
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief usb host software init, used for global reset.
|
* @brief usb host software init, used for global reset.
|
||||||
*
|
*
|
||||||
* @return int
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usb_hc_sw_init(void);
|
int usb_hc_sw_init(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief usb host controller hardware init.
|
* @brief usb host controller hardware init.
|
||||||
*
|
*
|
||||||
* @return int
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usb_hc_hw_init(void);
|
int usb_hc_hw_init(void);
|
||||||
|
|
||||||
@@ -77,8 +64,7 @@ int usb_hc_hw_init(void);
|
|||||||
* @brief get port connect status
|
* @brief get port connect status
|
||||||
*
|
*
|
||||||
* @param port
|
* @param port
|
||||||
* @return true
|
* @return On success will return 0, and others indicate fail.
|
||||||
* @return false
|
|
||||||
*/
|
*/
|
||||||
bool usbh_get_port_connect_status(const uint8_t port);
|
bool usbh_get_port_connect_status(const uint8_t port);
|
||||||
|
|
||||||
@@ -86,7 +72,7 @@ bool usbh_get_port_connect_status(const uint8_t port);
|
|||||||
* @brief reset roothub port
|
* @brief reset roothub port
|
||||||
*
|
*
|
||||||
* @param port port index
|
* @param port port index
|
||||||
* @return int
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usbh_reset_port(const uint8_t port);
|
int usbh_reset_port(const uint8_t port);
|
||||||
|
|
||||||
|
|||||||
@@ -138,23 +138,11 @@
|
|||||||
#define HI_BYTE(x) ((uint8_t)((x & 0xFF00) >> 8))
|
#define HI_BYTE(x) ((uint8_t)((x & 0xFF00) >> 8))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* @def MAX
|
|
||||||
* @brief The larger value between @p a and @p b.
|
|
||||||
* @note Arguments are evaluated twice.
|
|
||||||
*/
|
|
||||||
#ifndef MAX
|
#ifndef MAX
|
||||||
/* Use Z_MAX for a GCC-only, single evaluation version */
|
|
||||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* @def MIN
|
|
||||||
* @brief The smaller value between @p a and @p b.
|
|
||||||
* @note Arguments are evaluated twice.
|
|
||||||
*/
|
|
||||||
#ifndef MIN
|
#ifndef MIN
|
||||||
/* Use Z_MIN for a GCC-only, single evaluation version */
|
|
||||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -208,13 +196,6 @@
|
|||||||
(field)[3] = (uint8_t)((value) >> 0); \
|
(field)[3] = (uint8_t)((value) >> 0); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define REQTYPE_GET_DIR(x) (((x) >> 7) & 0x01)
|
|
||||||
#define REQTYPE_GET_TYPE(x) (((x) >> 5) & 0x03U)
|
|
||||||
#define REQTYPE_GET_RECIP(x) ((x)&0x1F)
|
|
||||||
|
|
||||||
#define GET_DESC_TYPE(x) (((x) >> 8) & 0xFFU)
|
|
||||||
#define GET_DESC_INDEX(x) ((x)&0xFFU)
|
|
||||||
|
|
||||||
#define WBVAL(x) (x & 0xFF), ((x >> 8) & 0xFF)
|
#define WBVAL(x) (x & 0xFF), ((x >> 8) & 0xFF)
|
||||||
#define DBVAL(x) (x & 0xFF), ((x >> 8) & 0xFF), ((x >> 16) & 0xFF), ((x >> 24) & 0xFF)
|
#define DBVAL(x) (x & 0xFF), ((x >> 8) & 0xFF), ((x >> 16) & 0xFF), ((x >> 24) & 0xFF)
|
||||||
|
|
||||||
@@ -239,6 +220,4 @@
|
|||||||
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
|
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
|
||||||
9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
||||||
|
|
||||||
#define USB_DESC_SECTION __attribute__((section("usb_desc"))) __USED __ALIGNED(1)
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
264
core/usbd_core.c
264
core/usbd_core.c
@@ -61,8 +61,6 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_cfg_priv {
|
|||||||
bool configured;
|
bool configured;
|
||||||
/** Currently selected configuration */
|
/** Currently selected configuration */
|
||||||
uint8_t configuration;
|
uint8_t configuration;
|
||||||
/** Remote wakeup feature status */
|
|
||||||
uint16_t remote_wakeup;
|
|
||||||
} usbd_core_cfg;
|
} usbd_core_cfg;
|
||||||
|
|
||||||
static usb_slist_t usbd_class_head = USB_SLIST_OBJECT_INIT(usbd_class_head);
|
static usb_slist_t usbd_class_head = USB_SLIST_OBJECT_INIT(usbd_class_head);
|
||||||
@@ -70,17 +68,8 @@ static struct usb_msosv1_descriptor *msosv1_desc;
|
|||||||
static struct usb_msosv2_descriptor *msosv2_desc;
|
static struct usb_msosv2_descriptor *msosv2_desc;
|
||||||
static struct usb_bos_descriptor *bos_desc;
|
static struct usb_bos_descriptor *bos_desc;
|
||||||
|
|
||||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
|
||||||
void usbd_set_feature(uint16_t index, uint16_t value);
|
|
||||||
void usbd_clear_feature(uint16_t index, uint16_t value);
|
|
||||||
#endif
|
|
||||||
static void usbd_class_event_notify_handler(uint8_t event, void *arg);
|
static void usbd_class_event_notify_handler(uint8_t event, void *arg);
|
||||||
/**
|
|
||||||
* @brief print the contents of a setup packet
|
|
||||||
*
|
|
||||||
* @param [in] setup The setup packet
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static void usbd_print_setup(struct usb_setup_packet *setup)
|
static void usbd_print_setup(struct usb_setup_packet *setup)
|
||||||
{
|
{
|
||||||
USB_LOG_INFO("Setup: "
|
USB_LOG_INFO("Setup: "
|
||||||
@@ -92,65 +81,10 @@ static void usbd_print_setup(struct usb_setup_packet *setup)
|
|||||||
setup->wLength);
|
setup->wLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if the device is in Configured state
|
|
||||||
*
|
|
||||||
* @return true if Configured, false otherwise.
|
|
||||||
*/
|
|
||||||
static bool is_device_configured(void)
|
static bool is_device_configured(void)
|
||||||
{
|
{
|
||||||
return (usbd_core_cfg.configuration != 0);
|
return (usbd_core_cfg.configuration != 0);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @brief Check if the interface of given number is valid
|
|
||||||
*
|
|
||||||
* @param [in] interface Number of the addressed interface
|
|
||||||
*
|
|
||||||
* This function searches through descriptor and checks
|
|
||||||
* is the Host has addressed valid interface.
|
|
||||||
*
|
|
||||||
* @return true if interface exists - valid
|
|
||||||
*/
|
|
||||||
static bool is_interface_valid(uint8_t interface)
|
|
||||||
{
|
|
||||||
const uint8_t *p = (uint8_t *)usbd_core_cfg.descriptors;
|
|
||||||
const struct usb_configuration_descriptor *cfg_descr;
|
|
||||||
|
|
||||||
/* Search through descriptor for matching interface */
|
|
||||||
while (p[DESC_bLength] != 0U) {
|
|
||||||
if (p[DESC_bDescriptorType] == USB_DESCRIPTOR_TYPE_CONFIGURATION) {
|
|
||||||
cfg_descr = (const struct usb_configuration_descriptor *)p;
|
|
||||||
|
|
||||||
if (interface < cfg_descr->bNumInterfaces) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p += p[DESC_bLength];
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @brief Check if the endpoint of given address is valid
|
|
||||||
*
|
|
||||||
* @param [in] ep Address of the Endpoint
|
|
||||||
*
|
|
||||||
* This function checks if the Endpoint of given address
|
|
||||||
* is valid for the configured device. Valid Endpoint is
|
|
||||||
* either Control Endpoint or one used by the device.
|
|
||||||
*
|
|
||||||
* @return true if endpoint exists - valid
|
|
||||||
*/
|
|
||||||
// static bool is_ep_valid(uint8_t ep)
|
|
||||||
// {
|
|
||||||
// /* Check if its Endpoint 0 */
|
|
||||||
// if ((ep & 0x7f) == 0) {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief configure and enable endpoint
|
* @brief configure and enable endpoint
|
||||||
@@ -219,8 +153,8 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
|||||||
uint32_t cur_index = 0U;
|
uint32_t cur_index = 0U;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
type = GET_DESC_TYPE(type_index);
|
type = HI_BYTE(type_index);
|
||||||
index = GET_DESC_INDEX(type_index);
|
index = LO_BYTE(type_index);
|
||||||
|
|
||||||
if ((type == USB_DESCRIPTOR_TYPE_STRING) && (index == USB_OSDESC_STRING_DESC_INDEX)) {
|
if ((type == USB_DESCRIPTOR_TYPE_STRING) && (index == USB_OSDESC_STRING_DESC_INDEX)) {
|
||||||
USB_LOG_INFO("read MS OS 2.0 descriptor string\r\n");
|
USB_LOG_INFO("read MS OS 2.0 descriptor string\r\n");
|
||||||
@@ -276,14 +210,12 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
/* set data pointer */
|
/* found descriptor, save descriptor premiere address */
|
||||||
*data = p;
|
*data = p;
|
||||||
|
|
||||||
/* get length from structure */
|
|
||||||
if ((type == USB_DESCRIPTOR_TYPE_CONFIGURATION) || ((type == USB_DESCRIPTOR_TYPE_OTHER_SPEED))) {
|
if ((type == USB_DESCRIPTOR_TYPE_CONFIGURATION) || ((type == USB_DESCRIPTOR_TYPE_OTHER_SPEED))) {
|
||||||
/* configuration descriptor is an
|
/* configuration or other speed descriptor is an
|
||||||
* exception, length is at offset
|
* exception, length is at offset 2 and 3
|
||||||
* 2 and 3
|
|
||||||
*/
|
*/
|
||||||
*len = (p[CONF_DESC_wTotalLength]) |
|
*len = (p[CONF_DESC_wTotalLength]) |
|
||||||
(p[CONF_DESC_wTotalLength + 1] << 8);
|
(p[CONF_DESC_wTotalLength + 1] << 8);
|
||||||
@@ -318,12 +250,6 @@ static bool usbd_set_configuration(uint8_t config_index, uint8_t alt_setting)
|
|||||||
uint8_t cur_config = 0xFF;
|
uint8_t cur_config = 0xFF;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
if (config_index == 0U) {
|
|
||||||
/* TODO: unconfigure device */
|
|
||||||
USB_LOG_ERR("Device not configured - invalid configuration\r\n");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* configure endpoints for this configuration/altsetting */
|
/* configure endpoints for this configuration/altsetting */
|
||||||
while (p[DESC_bLength] != 0U) {
|
while (p[DESC_bLength] != 0U) {
|
||||||
switch (p[DESC_bDescriptorType]) {
|
switch (p[DESC_bDescriptorType]) {
|
||||||
@@ -436,46 +362,34 @@ static bool usbd_set_interface(uint8_t iface, uint8_t alt_setting)
|
|||||||
static bool usbd_std_device_req_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static bool usbd_std_device_req_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
uint16_t value = setup->wValue;
|
uint16_t value = setup->wValue;
|
||||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
|
||||||
uint16_t index = setup->wIndex;
|
|
||||||
#endif
|
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
||||||
switch (setup->bRequest) {
|
switch (setup->bRequest) {
|
||||||
case USB_REQUEST_GET_STATUS:
|
case USB_REQUEST_GET_STATUS:
|
||||||
/* bit 0: self-powered */
|
/* bit 0: self-powered */
|
||||||
/* bit 1: remote wakeup */
|
/* bit 1: remote wakeup */
|
||||||
*data = (uint8_t *)&usbd_core_cfg.remote_wakeup;
|
(*data)[0] = 0x00;
|
||||||
|
(*data)[1] = 0x00;
|
||||||
*len = 2;
|
*len = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_REQUEST_CLEAR_FEATURE:
|
case USB_REQUEST_CLEAR_FEATURE:
|
||||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
|
||||||
/* process for feature */
|
|
||||||
usbd_clear_feature(index, value);
|
|
||||||
#endif
|
|
||||||
if (value == USB_FEATURE_REMOTE_WAKEUP) {
|
if (value == USB_FEATURE_REMOTE_WAKEUP) {
|
||||||
usbd_core_cfg.remote_wakeup = 0;
|
|
||||||
usbd_class_event_notify_handler(USBD_EVENT_CLEAR_REMOTE_WAKEUP, NULL);
|
usbd_class_event_notify_handler(USBD_EVENT_CLEAR_REMOTE_WAKEUP, NULL);
|
||||||
}
|
}
|
||||||
|
*len = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_REQUEST_SET_FEATURE:
|
case USB_REQUEST_SET_FEATURE:
|
||||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
|
||||||
/* process for feature */
|
|
||||||
usbd_set_feature(index, value);
|
|
||||||
#endif
|
|
||||||
if (value == USB_FEATURE_REMOTE_WAKEUP) {
|
if (value == USB_FEATURE_REMOTE_WAKEUP) {
|
||||||
usbd_core_cfg.remote_wakeup = 1;
|
|
||||||
usbd_class_event_notify_handler(USBD_EVENT_SET_REMOTE_WAKEUP, NULL);
|
usbd_class_event_notify_handler(USBD_EVENT_SET_REMOTE_WAKEUP, NULL);
|
||||||
}
|
}
|
||||||
|
*len = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_REQUEST_SET_ADDRESS:
|
case USB_REQUEST_SET_ADDRESS:
|
||||||
usbd_set_address(value);
|
usbd_set_address(value);
|
||||||
|
*len = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_REQUEST_GET_DESCRIPTOR:
|
case USB_REQUEST_GET_DESCRIPTOR:
|
||||||
@@ -487,7 +401,6 @@ static bool usbd_std_device_req_handler(struct usb_setup_packet *setup, uint8_t
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_REQUEST_GET_CONFIGURATION:
|
case USB_REQUEST_GET_CONFIGURATION:
|
||||||
/* indicate if we are configured */
|
|
||||||
*data = (uint8_t *)&usbd_core_cfg.configuration;
|
*data = (uint8_t *)&usbd_core_cfg.configuration;
|
||||||
*len = 1;
|
*len = 1;
|
||||||
break;
|
break;
|
||||||
@@ -496,28 +409,22 @@ static bool usbd_std_device_req_handler(struct usb_setup_packet *setup, uint8_t
|
|||||||
value &= 0xFF;
|
value &= 0xFF;
|
||||||
|
|
||||||
if (!usbd_set_configuration(value, 0)) {
|
if (!usbd_set_configuration(value, 0)) {
|
||||||
USB_LOG_DBG("USB Set Configuration failed\r\n");
|
|
||||||
ret = false;
|
ret = false;
|
||||||
} else {
|
} else {
|
||||||
/* configuration successful,
|
|
||||||
* update current configuration
|
|
||||||
*/
|
|
||||||
usbd_core_cfg.configuration = value;
|
usbd_core_cfg.configuration = value;
|
||||||
usbd_core_cfg.configured = true;
|
usbd_core_cfg.configured = true;
|
||||||
usbd_class_event_notify_handler(USBD_EVENT_CONFIGURED, NULL);
|
usbd_class_event_notify_handler(USBD_EVENT_CONFIGURED, NULL);
|
||||||
usbd_configure_done_callback();
|
usbd_configure_done_callback();
|
||||||
}
|
}
|
||||||
|
*len = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_REQUEST_GET_INTERFACE:
|
case USB_REQUEST_GET_INTERFACE:
|
||||||
break;
|
|
||||||
|
|
||||||
case USB_REQUEST_SET_INTERFACE:
|
case USB_REQUEST_SET_INTERFACE:
|
||||||
|
ret = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
USB_LOG_ERR("Illegal device req 0x%02x\r\n", setup->bRequest);
|
|
||||||
ret = false;
|
ret = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -537,48 +444,40 @@ static bool usbd_std_device_req_handler(struct usb_setup_packet *setup, uint8_t
|
|||||||
static bool usbd_std_interface_req_handler(struct usb_setup_packet *setup,
|
static bool usbd_std_interface_req_handler(struct usb_setup_packet *setup,
|
||||||
uint8_t **data, uint32_t *len)
|
uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
/** The device must be configured to accept standard interface
|
bool ret = true;
|
||||||
* requests and the addressed Interface must be valid.
|
|
||||||
*/
|
/* Only when device is configured, then interface requests can be valid. */
|
||||||
if (!is_device_configured() ||
|
if (!is_device_configured()) {
|
||||||
(!is_interface_valid((uint8_t)setup->wIndex))) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (setup->bRequest) {
|
switch (setup->bRequest) {
|
||||||
case USB_REQUEST_GET_STATUS:
|
case USB_REQUEST_GET_STATUS:
|
||||||
/* no bits specified */
|
(*data)[0] = 0x00;
|
||||||
*data = (uint8_t *)&usbd_core_cfg.remote_wakeup;
|
(*data)[1] = 0x00;
|
||||||
|
|
||||||
*len = 2;
|
*len = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_REQUEST_CLEAR_FEATURE:
|
case USB_REQUEST_CLEAR_FEATURE:
|
||||||
case USB_REQUEST_SET_FEATURE:
|
case USB_REQUEST_SET_FEATURE:
|
||||||
/* not defined for interface */
|
ret = false;
|
||||||
return false;
|
break;
|
||||||
|
|
||||||
case USB_REQUEST_GET_INTERFACE:
|
case USB_REQUEST_GET_INTERFACE:
|
||||||
/** This handler is called for classes that does not support
|
|
||||||
* alternate Interfaces so always return 0. Classes that
|
|
||||||
* support alternative interfaces handles GET_INTERFACE
|
|
||||||
* in custom_handler.
|
|
||||||
*/
|
|
||||||
(*data)[0] = 0;
|
(*data)[0] = 0;
|
||||||
|
|
||||||
*len = 1;
|
*len = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_REQUEST_SET_INTERFACE:
|
case USB_REQUEST_SET_INTERFACE:
|
||||||
usbd_set_interface(setup->wIndex, setup->wValue);
|
usbd_set_interface(setup->wIndex, setup->wValue);
|
||||||
|
*len = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
USB_LOG_ERR("Illegal interface req 0x%02x\r\n", setup->bRequest);
|
ret = false;
|
||||||
return false;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -593,87 +492,56 @@ static bool usbd_std_interface_req_handler(struct usb_setup_packet *setup,
|
|||||||
static bool usbd_std_endpoint_req_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static bool usbd_std_endpoint_req_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
uint8_t ep = (uint8_t)setup->wIndex;
|
uint8_t ep = (uint8_t)setup->wIndex;
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
/* Only when device is configured, then endpoint requests can be valid. */
|
||||||
|
if (!is_device_configured()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
switch (setup->bRequest) {
|
switch (setup->bRequest) {
|
||||||
case USB_REQUEST_GET_STATUS:
|
case USB_REQUEST_GET_STATUS:
|
||||||
|
(*data)[0] = 0x00;
|
||||||
/** This request is valid for Control Endpoints when
|
(*data)[1] = 0x00;
|
||||||
* the device is not yet configured. For other
|
|
||||||
* Endpoints the device must be configured.
|
|
||||||
* Firstly check if addressed ep is Control Endpoint.
|
|
||||||
* If no then the device must be in Configured state
|
|
||||||
* to accept the request.
|
|
||||||
*/
|
|
||||||
if (((ep & 0x7f) == 0) || is_device_configured()) {
|
|
||||||
/* bit 0 - Endpoint halted or not */
|
|
||||||
usbd_ep_is_stalled(ep, (uint8_t *)&usbd_core_cfg.remote_wakeup);
|
|
||||||
*data = (uint8_t *)&usbd_core_cfg.remote_wakeup;
|
|
||||||
|
|
||||||
*len = 2;
|
*len = 2;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case USB_REQUEST_CLEAR_FEATURE:
|
case USB_REQUEST_CLEAR_FEATURE:
|
||||||
if (setup->wValue == USB_FEATURE_ENDPOINT_HALT) {
|
if (setup->wValue == USB_FEATURE_ENDPOINT_HALT) {
|
||||||
/** This request is valid for Control Endpoints when
|
USB_LOG_ERR("ep:%02x clear halt\r\n", ep);
|
||||||
* the device is not yet configured. For other
|
|
||||||
* Endpoints the device must be configured.
|
|
||||||
* Firstly check if addressed ep is Control Endpoint.
|
|
||||||
* If no then the device must be in Configured state
|
|
||||||
* to accept the request.
|
|
||||||
*/
|
|
||||||
if (((ep & 0x7f) == 0) || is_device_configured()) {
|
|
||||||
USB_LOG_ERR("ep:%x clear halt\r\n", ep);
|
|
||||||
|
|
||||||
usbd_ep_clear_stall(ep);
|
usbd_ep_clear_stall(ep);
|
||||||
usbd_class_event_notify_handler(USBD_EVENT_CLEAR_HALT, NULL);
|
usbd_class_event_notify_handler(USBD_EVENT_CLEAR_HALT, NULL);
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
ret = false;
|
||||||
}
|
}
|
||||||
}
|
*len = 0;
|
||||||
|
break;
|
||||||
/* only ENDPOINT_HALT defined for endpoints */
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case USB_REQUEST_SET_FEATURE:
|
case USB_REQUEST_SET_FEATURE:
|
||||||
if (setup->wValue == USB_FEATURE_ENDPOINT_HALT) {
|
if (setup->wValue == USB_FEATURE_ENDPOINT_HALT) {
|
||||||
/** This request is valid for Control Endpoints when
|
USB_LOG_ERR("ep:%02x set halt\r\n", ep);
|
||||||
* the device is not yet configured. For other
|
|
||||||
* Endpoints the device must be configured.
|
|
||||||
* Firstly check if addressed ep is Control Endpoint.
|
|
||||||
* If no then the device must be in Configured state
|
|
||||||
* to accept the request.
|
|
||||||
*/
|
|
||||||
if (((ep & 0x7f) == 0) || is_device_configured()) {
|
|
||||||
/* set HALT by stalling */
|
|
||||||
USB_LOG_ERR("ep:%x set halt\r\n", ep);
|
|
||||||
|
|
||||||
usbd_ep_set_stall(ep);
|
usbd_ep_set_stall(ep);
|
||||||
usbd_class_event_notify_handler(USBD_EVENT_SET_HALT, NULL);
|
usbd_class_event_notify_handler(USBD_EVENT_SET_HALT, NULL);
|
||||||
|
} else {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
*len = 0;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* only ENDPOINT_HALT defined for endpoints */
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case USB_REQUEST_SYNCH_FRAME:
|
case USB_REQUEST_SYNCH_FRAME:
|
||||||
|
ret = false;
|
||||||
return false;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
USB_LOG_ERR("Illegal ep req 0x%02x\r\n", setup->bRequest);
|
ret = false;
|
||||||
return false;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief default handler for standard ('chapter 9') requests
|
* @brief handle standard requests (list in chapter 9)
|
||||||
*
|
|
||||||
* If a custom request handler was installed, this handler is called first.
|
|
||||||
*
|
*
|
||||||
* @param [in] setup The setup packet
|
* @param [in] setup The setup packet
|
||||||
* @param [in,out] data Data buffer
|
* @param [in,out] data Data buffer
|
||||||
@@ -709,6 +577,7 @@ static int usbd_standard_request_handler(struct usb_setup_packet *setup, uint8_t
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
rc = -1;
|
rc = -1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@@ -727,7 +596,6 @@ static int usbd_standard_request_handler(struct usb_setup_packet *setup, uint8_t
|
|||||||
*/
|
*/
|
||||||
static int usbd_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int usbd_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
USB_LOG_DBG("bRequest 0x%02x, wIndex 0x%04x\r\n", setup->bRequest, setup->wIndex);
|
|
||||||
usb_slist_t *i, *j;
|
usb_slist_t *i, *j;
|
||||||
if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_INTERFACE) {
|
if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_INTERFACE) {
|
||||||
usb_slist_for_each(i, &usbd_class_head)
|
usb_slist_for_each(i, &usbd_class_head)
|
||||||
@@ -774,13 +642,6 @@ static int usbd_class_request_handler(struct usb_setup_packet *setup, uint8_t **
|
|||||||
*/
|
*/
|
||||||
static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
USB_LOG_DBG("bRequest 0x%02x, wValue0x%04x, wIndex 0x%04x\r\n", setup->bRequest, setup->wValue, setup->wIndex);
|
|
||||||
|
|
||||||
// if((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) != USB_REQUEST_RECIPIENT_DEVICE)
|
|
||||||
// {
|
|
||||||
// return -1;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (msosv1_desc) {
|
if (msosv1_desc) {
|
||||||
if (setup->bRequest == msosv1_desc->vendor_code) {
|
if (setup->bRequest == msosv1_desc->vendor_code) {
|
||||||
switch (setup->wIndex) {
|
switch (setup->wIndex) {
|
||||||
@@ -836,9 +697,7 @@ static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t *
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief handler for special requests
|
* @brief handler for special requests (for hid report or audio ep request, later will be removed)
|
||||||
*
|
|
||||||
* If a custom request handler was installed, this handler is called first.
|
|
||||||
*
|
*
|
||||||
* @param [in] setup The setup packet
|
* @param [in] setup The setup packet
|
||||||
* @param [in,out] data Data buffer
|
* @param [in,out] data Data buffer
|
||||||
@@ -848,8 +707,6 @@ static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t *
|
|||||||
*/
|
*/
|
||||||
static int usbd_custom_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int usbd_custom_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
USB_LOG_DBG("bRequest 0x%02x, wIndex 0x%04x\r\n", setup->bRequest, setup->wIndex);
|
|
||||||
|
|
||||||
if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) != USB_REQUEST_RECIPIENT_INTERFACE) {
|
if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) != USB_REQUEST_RECIPIENT_INTERFACE) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -873,12 +730,7 @@ static int usbd_custom_request_handler(struct usb_setup_packet *setup, uint8_t *
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief handle a request by calling one of the installed request handlers
|
* @brief handle setup request( standard/class/vendor/other)
|
||||||
*
|
|
||||||
* Local function to handle a request by calling one of the installed request
|
|
||||||
* handlers. In case of data going from host to device, the data is at *ppbData.
|
|
||||||
* In case of data going from device to host, the handler can either choose to
|
|
||||||
* write its data at *ppbData or update the data pointer.
|
|
||||||
*
|
*
|
||||||
* @param [in] setup The setup packet
|
* @param [in] setup The setup packet
|
||||||
* @param [in,out] data Data buffer
|
* @param [in,out] data Data buffer
|
||||||
@@ -993,7 +845,7 @@ void usbd_event_ep0_setup_complete_handler(uint8_t *psetup)
|
|||||||
usbd_core_cfg.ep0_data_buf_len = setup->wLength;
|
usbd_core_cfg.ep0_data_buf_len = setup->wLength;
|
||||||
usbd_core_cfg.zlp_flag = false;
|
usbd_core_cfg.zlp_flag = false;
|
||||||
|
|
||||||
/* this maybe set code in class request code */
|
/* handle class request when all the data is received */
|
||||||
if (setup->wLength && ((setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) {
|
if (setup->wLength && ((setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) {
|
||||||
USB_LOG_DBG("Start reading %d bytes from ep0\r\n", setup->wLength);
|
USB_LOG_DBG("Start reading %d bytes from ep0\r\n", setup->wLength);
|
||||||
usbd_ep_start_read(USB_CONTROL_OUT_EP0, usbd_core_cfg.ep0_data_buf, setup->wLength);
|
usbd_ep_start_read(USB_CONTROL_OUT_EP0, usbd_core_cfg.ep0_data_buf, setup->wLength);
|
||||||
@@ -1163,13 +1015,3 @@ int usbd_initialize(void)
|
|||||||
usb_dc_init();
|
usb_dc_init();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
|
||||||
__WEAK void usbd_set_feature(uint16_t index, uint16_t value)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
__WEAK void usbd_clear_feature(uint16_t index, uint16_t value)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -82,26 +82,8 @@ enum usbd_event_type {
|
|||||||
USBD_EVENT_UNKNOWN
|
USBD_EVENT_UNKNOWN
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
typedef int (*usbd_request_handler)(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len);
|
||||||
* @brief Callback function signature for the USB Endpoint status
|
|
||||||
*/
|
|
||||||
typedef void (*usbd_endpoint_callback)(uint8_t ep, uint32_t nbytes);
|
typedef void (*usbd_endpoint_callback)(uint8_t ep, uint32_t nbytes);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Callback function signature for class specific requests
|
|
||||||
*
|
|
||||||
* Function which handles Class specific requests corresponding to an
|
|
||||||
* interface number specified in the device descriptor table. For host
|
|
||||||
* to device direction the 'len' and 'payload_data' contain the length
|
|
||||||
* of the received data and the pointer to the received data respectively.
|
|
||||||
* For device to host class requests, 'len' and 'payload_data' should be
|
|
||||||
* set by the callback function with the length and the address of the
|
|
||||||
* data to be transmitted buffer respectively.
|
|
||||||
*/
|
|
||||||
typedef int (*usbd_request_handler)(struct usb_setup_packet *setup,
|
|
||||||
uint8_t **data, uint32_t *len);
|
|
||||||
|
|
||||||
/* callback function pointer structure for Application to handle events */
|
|
||||||
typedef void (*usbd_notify_handler)(uint8_t event, void *arg);
|
typedef void (*usbd_notify_handler)(uint8_t event, void *arg);
|
||||||
|
|
||||||
typedef struct usbd_endpoint {
|
typedef struct usbd_endpoint {
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ struct usbh_devaddr_priv {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct usbh_roothubport_priv {
|
struct usbh_roothubport_priv {
|
||||||
struct usbh_hubport hport; /* Common hub port definitions */
|
struct usbh_hubport hport;
|
||||||
struct usbh_devaddr_priv devgen; /* Address generation data */
|
struct usbh_devaddr_priv devgen;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct usbh_core_priv {
|
struct usbh_core_priv {
|
||||||
@@ -75,11 +75,7 @@ static int usbh_allocate_devaddr(struct usbh_devaddr_priv *devgen)
|
|||||||
int index;
|
int index;
|
||||||
int bitno;
|
int bitno;
|
||||||
|
|
||||||
/* Loop until we find a valid device address */
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* Try the next device address */
|
|
||||||
|
|
||||||
devaddr = devgen->next;
|
devaddr = devgen->next;
|
||||||
if (devgen->next >= 0x7f) {
|
if (devgen->next >= 0x7f) {
|
||||||
devgen->next = 1;
|
devgen->next = 1;
|
||||||
@@ -87,24 +83,14 @@ static int usbh_allocate_devaddr(struct usbh_devaddr_priv *devgen)
|
|||||||
devgen->next++;
|
devgen->next++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is this address already allocated? */
|
|
||||||
|
|
||||||
index = devaddr >> 5;
|
index = devaddr >> 5;
|
||||||
bitno = devaddr & 0x1f;
|
bitno = devaddr & 0x1f;
|
||||||
if ((devgen->alloctab[index] & (1 << bitno)) == 0) {
|
if ((devgen->alloctab[index] & (1 << bitno)) == 0) {
|
||||||
/* No... allocate it now */
|
|
||||||
|
|
||||||
devgen->alloctab[index] |= (1 << bitno);
|
devgen->alloctab[index] |= (1 << bitno);
|
||||||
return (int)devaddr;
|
return (int)devaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This address has already been allocated. The following logic will
|
|
||||||
* prevent (unexpected) infinite loops.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (startaddr == devaddr) {
|
if (startaddr == devaddr) {
|
||||||
/* We are back where we started... the are no free device address */
|
|
||||||
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,13 +105,12 @@ static int usbh_free_devaddr(struct usbh_devaddr_priv *devgen, uint8_t devaddr)
|
|||||||
index = devaddr >> USB_DEV_ADDR_MARK_OFFSET;
|
index = devaddr >> USB_DEV_ADDR_MARK_OFFSET;
|
||||||
bitno = devaddr & USB_DEV_ADDR_MARK_MASK;
|
bitno = devaddr & USB_DEV_ADDR_MARK_MASK;
|
||||||
|
|
||||||
/* Free the address by clearing the associated bit in the alloctab[]; */
|
/* Free the address */
|
||||||
if ((devgen->alloctab[index] |= (1 << bitno)) != 0) {
|
if ((devgen->alloctab[index] |= (1 << bitno)) != 0) {
|
||||||
devgen->alloctab[index] &= ~(1 << bitno);
|
devgen->alloctab[index] &= ~(1 << bitno);
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Reset the next pointer if the one just released has a lower value */
|
|
||||||
|
|
||||||
if (devaddr < devgen->next) {
|
if (devaddr < devgen->next) {
|
||||||
devgen->next = devaddr;
|
devgen->next = devaddr;
|
||||||
@@ -463,7 +448,7 @@ static int usbh_enumerate(struct usbh_hubport *hport)
|
|||||||
ep_mps = 64;
|
ep_mps = 64;
|
||||||
descsize = USB_SIZEOF_DEVICE_DESC;
|
descsize = USB_SIZEOF_DEVICE_DESC;
|
||||||
} else {
|
} else {
|
||||||
/* Eight will work for both low- and full-speed */
|
/* For low or full, we use 8 bytes, 64 bytes is also ok */
|
||||||
ep_mps = 8;
|
ep_mps = 8;
|
||||||
descsize = 8;
|
descsize = 8;
|
||||||
}
|
}
|
||||||
@@ -516,7 +501,7 @@ static int usbh_enumerate(struct usbh_hubport *hport)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wait device address set completely */
|
/* Wait device set address completely */
|
||||||
usb_osal_msleep(2);
|
usb_osal_msleep(2);
|
||||||
|
|
||||||
/* Assign the function address to the port */
|
/* Assign the function address to the port */
|
||||||
|
|||||||
@@ -30,12 +30,6 @@
|
|||||||
#define USB_OTG_HC(i) ((USB_OTG_HostChannelTypeDef *)(USB_BASE + USB_OTG_HOST_CHANNEL_BASE + ((i)*USB_OTG_HOST_CHANNEL_SIZE)))
|
#define USB_OTG_HC(i) ((USB_OTG_HostChannelTypeDef *)(USB_BASE + USB_OTG_HOST_CHANNEL_BASE + ((i)*USB_OTG_HOST_CHANNEL_SIZE)))
|
||||||
#define USB_OTG_FIFO(i) *(__IO uint32_t *)(USB_BASE + USB_OTG_FIFO_BASE + ((i)*USB_OTG_FIFO_SIZE))
|
#define USB_OTG_FIFO(i) *(__IO uint32_t *)(USB_BASE + USB_OTG_FIFO_BASE + ((i)*USB_OTG_FIFO_SIZE))
|
||||||
|
|
||||||
/* This structure retains the state of one host channel. NOTE: Since there
|
|
||||||
* is only one channel operation active at a time, some of the fields in
|
|
||||||
* in the structure could be moved in struct stm32_ubhost_s to achieve
|
|
||||||
* some memory savings.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct dwc2_pipe {
|
struct dwc2_pipe {
|
||||||
uint8_t ep_addr;
|
uint8_t ep_addr;
|
||||||
uint8_t ep_type;
|
uint8_t ep_type;
|
||||||
@@ -358,65 +352,25 @@ static inline uint32_t dwc2_get_current_frame(void)
|
|||||||
return (USB_OTG_HOST->HFNUM & USB_OTG_HFNUM_FRNUM);
|
return (USB_OTG_HOST->HFNUM & USB_OTG_HFNUM_FRNUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: dwc2_pipe_alloc
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Allocate a channel.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static int dwc2_pipe_alloc(void)
|
static int dwc2_pipe_alloc(void)
|
||||||
{
|
{
|
||||||
int chidx;
|
int chidx;
|
||||||
|
|
||||||
/* Search the table of channels */
|
|
||||||
|
|
||||||
for (chidx = 0; chidx < CONFIG_USB_DWC2_PIPE_NUM; chidx++) {
|
for (chidx = 0; chidx < CONFIG_USB_DWC2_PIPE_NUM; chidx++) {
|
||||||
/* Is this channel available? */
|
|
||||||
if (!g_dwc2_hcd.chan[chidx].inuse) {
|
if (!g_dwc2_hcd.chan[chidx].inuse) {
|
||||||
/* Yes... make it "in use" and return the index */
|
|
||||||
|
|
||||||
g_dwc2_hcd.chan[chidx].inuse = true;
|
g_dwc2_hcd.chan[chidx].inuse = true;
|
||||||
return chidx;
|
return chidx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All of the channels are "in-use" */
|
|
||||||
|
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: dwc2_pipe_free
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Free a previoiusly allocated channel.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static void dwc2_pipe_free(struct dwc2_pipe *chan)
|
static void dwc2_pipe_free(struct dwc2_pipe *chan)
|
||||||
{
|
{
|
||||||
/* Mark the channel available */
|
|
||||||
|
|
||||||
chan->inuse = false;
|
chan->inuse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: dwc2_pipe_waitsetup
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Set the request for the transfer complete event well BEFORE enabling
|
|
||||||
* the transfer (as soon as we are absolutely committed to the transfer).
|
|
||||||
* We do this to minimize race conditions. This logic would have to be
|
|
||||||
* expanded if we want to have more than one packet in flight at a time!
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* Called from a normal thread context BEFORE the transfer has been
|
|
||||||
* started.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static int dwc2_pipe_waitsetup(struct dwc2_pipe *chan)
|
static int dwc2_pipe_waitsetup(struct dwc2_pipe *chan)
|
||||||
{
|
{
|
||||||
size_t flags;
|
size_t flags;
|
||||||
@@ -424,13 +378,7 @@ static int dwc2_pipe_waitsetup(struct dwc2_pipe *chan)
|
|||||||
|
|
||||||
flags = usb_osal_enter_critical_section();
|
flags = usb_osal_enter_critical_section();
|
||||||
|
|
||||||
/* Is the device still connected? */
|
|
||||||
|
|
||||||
if (usbh_get_port_connect_status(1)) {
|
if (usbh_get_port_connect_status(1)) {
|
||||||
/* Yes.. then set waiter to indicate that we expect to be informed
|
|
||||||
* when either (1) the device is disconnected, or (2) the transfer
|
|
||||||
* completed.
|
|
||||||
*/
|
|
||||||
chan->waiter = true;
|
chan->waiter = true;
|
||||||
chan->result = -EBUSY;
|
chan->result = -EBUSY;
|
||||||
chan->xfrd = 0;
|
chan->xfrd = 0;
|
||||||
@@ -444,21 +392,6 @@ static int dwc2_pipe_waitsetup(struct dwc2_pipe *chan)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: dwc2_pipe_asynchsetup
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Set the request for the transfer complete event well BEFORE enabling
|
|
||||||
* the transfer (as soon as we are absolutely committed to the to avoid
|
|
||||||
* transfer). We do this to minimize race conditions. This logic would
|
|
||||||
* have to be expanded if we want to have more than one packet in flight
|
|
||||||
* at a time!
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* Might be called from the level of an interrupt handler
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef CONFIG_USBHOST_ASYNCH
|
#ifdef CONFIG_USBHOST_ASYNCH
|
||||||
static int dwc2_pipe_asynchsetup(struct dwc2_pipe *chan, usbh_asynch_callback_t callback, void *arg)
|
static int dwc2_pipe_asynchsetup(struct dwc2_pipe *chan, usbh_asynch_callback_t callback, void *arg)
|
||||||
{
|
{
|
||||||
@@ -466,14 +399,8 @@ static int dwc2_pipe_asynchsetup(struct dwc2_pipe *chan, usbh_asynch_callback_t
|
|||||||
int ret = -ENODEV;
|
int ret = -ENODEV;
|
||||||
|
|
||||||
flags = usb_osal_enter_critical_section();
|
flags = usb_osal_enter_critical_section();
|
||||||
/* Is the device still connected? */
|
|
||||||
|
|
||||||
if (usbh_get_port_connect_status(1)) {
|
if (usbh_get_port_connect_status(1)) {
|
||||||
/* Yes.. then set waiter to indicate that we expect to be informed
|
|
||||||
* when either (1) the device is disconnected, or (2) the transfer
|
|
||||||
* completed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
chan->waiter = false;
|
chan->waiter = false;
|
||||||
chan->result = -EBUSY;
|
chan->result = -EBUSY;
|
||||||
chan->xfrd = 0;
|
chan->xfrd = 0;
|
||||||
@@ -488,27 +415,11 @@ static int dwc2_pipe_asynchsetup(struct dwc2_pipe *chan, usbh_asynch_callback_t
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: dwc2_pipe_wait
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Wait for a transfer on a channel to complete.
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* Called from a normal thread context
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static int dwc2_pipe_wait(struct dwc2_pipe *chan, uint32_t timeout)
|
static int dwc2_pipe_wait(struct dwc2_pipe *chan, uint32_t timeout)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Loop, testing for an end of transfer condition. The channel 'result'
|
/* wait until timeout or sem give */
|
||||||
* was set to EBUSY and 'waiter' was set to true before the transfer;
|
|
||||||
* 'waiter' will be set to false and 'result' will be set appropriately
|
|
||||||
* when the transfer is completed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (chan->waiter) {
|
if (chan->waiter) {
|
||||||
ret = usb_osal_sem_take(chan->waitsem, timeout);
|
ret = usb_osal_sem_take(chan->waitsem, timeout);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -516,48 +427,25 @@ static int dwc2_pipe_wait(struct dwc2_pipe *chan, uint32_t timeout)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The transfer is complete re-enable interrupts and return the result */
|
/* Sem give, check if giving from error isr */
|
||||||
ret = chan->result;
|
ret = chan->result;
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return chan->xfrd;
|
return chan->xfrd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: dwc2_pipe_wakeup
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* A channel transfer has completed... wakeup any threads waiting for the
|
|
||||||
* transfer to complete.
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* This function is called from the transfer complete interrupt handler for
|
|
||||||
* the channel. Interrupts are disabled.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static void dwc2_pipe_wakeup(struct dwc2_pipe *chan)
|
static void dwc2_pipe_wakeup(struct dwc2_pipe *chan)
|
||||||
{
|
{
|
||||||
usbh_asynch_callback_t callback;
|
usbh_asynch_callback_t callback;
|
||||||
void *arg;
|
void *arg;
|
||||||
int nbytes;
|
int nbytes;
|
||||||
|
|
||||||
/* Is the transfer complete? */
|
|
||||||
|
|
||||||
if (chan->result != -EBUSY) {
|
|
||||||
/* Is there a thread waiting for this transfer to complete? */
|
|
||||||
|
|
||||||
if (chan->waiter) {
|
if (chan->waiter) {
|
||||||
/* Wake'em up! */
|
|
||||||
chan->waiter = false;
|
chan->waiter = false;
|
||||||
usb_osal_sem_give(chan->waitsem);
|
usb_osal_sem_give(chan->waitsem);
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_USBHOST_ASYNCH
|
#ifdef CONFIG_USBHOST_ASYNCH
|
||||||
/* No.. is an asynchronous callback expected when the transfer
|
|
||||||
* completes?
|
|
||||||
*/
|
|
||||||
else if (chan->callback) {
|
else if (chan->callback) {
|
||||||
callback = chan->callback;
|
callback = chan->callback;
|
||||||
arg = chan->arg;
|
arg = chan->arg;
|
||||||
@@ -574,9 +462,9 @@ static void dwc2_pipe_wakeup(struct dwc2_pipe *chan)
|
|||||||
#endif
|
#endif
|
||||||
callback(arg, nbytes);
|
callback(arg, nbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
__WEAK void usb_hc_low_level_init(void)
|
__WEAK void usb_hc_low_level_init(void)
|
||||||
{
|
{
|
||||||
@@ -755,6 +643,7 @@ int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg)
|
|||||||
|
|
||||||
chan = &g_dwc2_hcd.chan[chidx];
|
chan = &g_dwc2_hcd.chan[chidx];
|
||||||
|
|
||||||
|
/* store variables */
|
||||||
waitsem = chan->waitsem;
|
waitsem = chan->waitsem;
|
||||||
exclsem = chan->exclsem;
|
exclsem = chan->exclsem;
|
||||||
|
|
||||||
@@ -775,6 +664,7 @@ int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg)
|
|||||||
chan->data_pid = HC_PID_DATA0;
|
chan->data_pid = HC_PID_DATA0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* restore variables */
|
||||||
chan->inuse = true;
|
chan->inuse = true;
|
||||||
chan->waitsem = waitsem;
|
chan->waitsem = waitsem;
|
||||||
chan->exclsem = exclsem;
|
chan->exclsem = exclsem;
|
||||||
@@ -1076,9 +966,7 @@ int usb_ep_cancel(usbh_epinfo_t ep)
|
|||||||
|
|
||||||
flags = usb_osal_enter_critical_section();
|
flags = usb_osal_enter_critical_section();
|
||||||
|
|
||||||
chan->result = -ESHUTDOWN;
|
|
||||||
#ifdef CONFIG_USBHOST_ASYNCH
|
#ifdef CONFIG_USBHOST_ASYNCH
|
||||||
/* Extract the callback information */
|
|
||||||
callback = chan->callback;
|
callback = chan->callback;
|
||||||
arg = chan->arg;
|
arg = chan->arg;
|
||||||
chan->callback = NULL;
|
chan->callback = NULL;
|
||||||
@@ -1087,17 +975,14 @@ int usb_ep_cancel(usbh_epinfo_t ep)
|
|||||||
#endif
|
#endif
|
||||||
usb_osal_leave_critical_section(flags);
|
usb_osal_leave_critical_section(flags);
|
||||||
|
|
||||||
/* Is there a thread waiting for this transfer to complete? */
|
/* Check if there is a thread waiting for this transfer to complete? */
|
||||||
|
|
||||||
if (chan->waiter) {
|
if (chan->waiter) {
|
||||||
/* Wake'em up! */
|
|
||||||
chan->waiter = false;
|
chan->waiter = false;
|
||||||
usb_osal_sem_give(chan->waitsem);
|
usb_osal_sem_give(chan->waitsem);
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_USBHOST_ASYNCH
|
#ifdef CONFIG_USBHOST_ASYNCH
|
||||||
/* No.. is an asynchronous callback expected when the transfer completes? */
|
/* No.. is an asynchronous callback expected when the transfer completes? */
|
||||||
else if (callback) {
|
else if (callback) {
|
||||||
/* Then perform the callback */
|
|
||||||
callback(arg, -ESHUTDOWN);
|
callback(arg, -ESHUTDOWN);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -96,21 +96,6 @@ bool hcd_init(uint8_t rhport)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: hpm_ehci_pipe_waitsetup
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Set the request for the transfer complete event well BEFORE enabling
|
|
||||||
* the transfer (as soon as we are absolutely committed to the transfer).
|
|
||||||
* We do this to minimize race conditions. This logic would have to be
|
|
||||||
* expanded if we want to have more than one packet in flight at a time!
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* Called from a normal thread context BEFORE the transfer has been
|
|
||||||
* started.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static int hpm_ehci_pipe_waitsetup(struct hpm_ehci_pipe *chan)
|
static int hpm_ehci_pipe_waitsetup(struct hpm_ehci_pipe *chan)
|
||||||
{
|
{
|
||||||
size_t flags;
|
size_t flags;
|
||||||
@@ -118,13 +103,8 @@ static int hpm_ehci_pipe_waitsetup(struct hpm_ehci_pipe *chan)
|
|||||||
|
|
||||||
flags = usb_osal_enter_critical_section();
|
flags = usb_osal_enter_critical_section();
|
||||||
|
|
||||||
/* Is the device still connected? */
|
|
||||||
|
|
||||||
if (usbh_get_port_connect_status(1)) {
|
if (usbh_get_port_connect_status(1)) {
|
||||||
/* Yes.. then set waiter to indicate that we expect to be informed
|
|
||||||
* when either (1) the device is disconnected, or (2) the transfer
|
|
||||||
* completed.
|
|
||||||
*/
|
|
||||||
chan->waiter = true;
|
chan->waiter = true;
|
||||||
chan->result = -EBUSY;
|
chan->result = -EBUSY;
|
||||||
chan->xfrd = 0;
|
chan->xfrd = 0;
|
||||||
@@ -138,21 +118,6 @@ static int hpm_ehci_pipe_waitsetup(struct hpm_ehci_pipe *chan)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: hpm_ehci_pipe_asynchsetup
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Set the request for the transfer complete event well BEFORE enabling
|
|
||||||
* the transfer (as soon as we are absolutely committed to the to avoid
|
|
||||||
* transfer). We do this to minimize race conditions. This logic would
|
|
||||||
* have to be expanded if we want to have more than one packet in flight
|
|
||||||
* at a time!
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* Might be called from the level of an interrupt handler
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef CONFIG_USBHOST_ASYNCH
|
#ifdef CONFIG_USBHOST_ASYNCH
|
||||||
static int hpm_ehci_pipe_asynchsetup(struct hpm_ehci_pipe *chan, usbh_asynch_callback_t callback, void *arg)
|
static int hpm_ehci_pipe_asynchsetup(struct hpm_ehci_pipe *chan, usbh_asynch_callback_t callback, void *arg)
|
||||||
{
|
{
|
||||||
@@ -160,14 +125,8 @@ static int hpm_ehci_pipe_asynchsetup(struct hpm_ehci_pipe *chan, usbh_asynch_cal
|
|||||||
int ret = -ENODEV;
|
int ret = -ENODEV;
|
||||||
|
|
||||||
flags = usb_osal_enter_critical_section();
|
flags = usb_osal_enter_critical_section();
|
||||||
/* Is the device still connected? */
|
|
||||||
|
|
||||||
if (usbh_get_port_connect_status(1)) {
|
if (usbh_get_port_connect_status(1)) {
|
||||||
/* Yes.. then set waiter to indicate that we expect to be informed
|
|
||||||
* when either (1) the device is disconnected, or (2) the transfer
|
|
||||||
* completed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
chan->waiter = false;
|
chan->waiter = false;
|
||||||
chan->result = -EBUSY;
|
chan->result = -EBUSY;
|
||||||
chan->xfrd = 0;
|
chan->xfrd = 0;
|
||||||
@@ -182,27 +141,11 @@ static int hpm_ehci_pipe_asynchsetup(struct hpm_ehci_pipe *chan, usbh_asynch_cal
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: hpm_ehci_pipe_wait
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Wait for a transfer on a channel to complete.
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* Called from a normal thread context
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static int hpm_ehci_pipe_wait(struct hpm_ehci_pipe *chan, uint32_t timeout)
|
static int hpm_ehci_pipe_wait(struct hpm_ehci_pipe *chan, uint32_t timeout)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Loop, testing for an end of transfer condition. The channel 'result'
|
/* wait until timeout or sem give */
|
||||||
* was set to EBUSY and 'waiter' was set to true before the transfer;
|
|
||||||
* 'waiter' will be set to false and 'result' will be set appropriately
|
|
||||||
* when the transfer is completed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (chan->waiter) {
|
if (chan->waiter) {
|
||||||
ret = usb_osal_sem_take(chan->waitsem, timeout);
|
ret = usb_osal_sem_take(chan->waitsem, timeout);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -210,7 +153,7 @@ static int hpm_ehci_pipe_wait(struct hpm_ehci_pipe *chan, uint32_t timeout)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The transfer is complete re-enable interrupts and return the result */
|
/* Sem give, check if giving from error isr */
|
||||||
ret = chan->result;
|
ret = chan->result;
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -219,39 +162,17 @@ static int hpm_ehci_pipe_wait(struct hpm_ehci_pipe *chan, uint32_t timeout)
|
|||||||
return chan->xfrd;
|
return chan->xfrd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: hpm_ehci_pipe_wakeup
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* A channel transfer has completed... wakeup any threads waiting for the
|
|
||||||
* transfer to complete.
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* This function is called from the transfer complete interrupt handler for
|
|
||||||
* the channel. Interrupts are disabled.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static void hpm_ehci_pipe_wakeup(struct hpm_ehci_pipe *chan)
|
static void hpm_ehci_pipe_wakeup(struct hpm_ehci_pipe *chan)
|
||||||
{
|
{
|
||||||
usbh_asynch_callback_t callback;
|
usbh_asynch_callback_t callback;
|
||||||
void *arg;
|
void *arg;
|
||||||
int nbytes;
|
int nbytes;
|
||||||
|
|
||||||
/* Is the transfer complete? */
|
|
||||||
|
|
||||||
if (chan->result != -EBUSY) {
|
|
||||||
/* Is there a thread waiting for this transfer to complete? */
|
|
||||||
|
|
||||||
if (chan->waiter) {
|
if (chan->waiter) {
|
||||||
/* Wake'em up! */
|
|
||||||
chan->waiter = false;
|
chan->waiter = false;
|
||||||
usb_osal_sem_give(chan->waitsem);
|
usb_osal_sem_give(chan->waitsem);
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_USBHOST_ASYNCH
|
#ifdef CONFIG_USBHOST_ASYNCH
|
||||||
/* No.. is an asynchronous callback expected when the transfer
|
|
||||||
* completes?
|
|
||||||
*/
|
|
||||||
else if (chan->callback) {
|
else if (chan->callback) {
|
||||||
callback = chan->callback;
|
callback = chan->callback;
|
||||||
arg = chan->arg;
|
arg = chan->arg;
|
||||||
@@ -270,7 +191,6 @@ static void hpm_ehci_pipe_wakeup(struct hpm_ehci_pipe *chan)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
__WEAK void usb_hc_low_level_init(void)
|
__WEAK void usb_hc_low_level_init(void)
|
||||||
{
|
{
|
||||||
@@ -394,6 +314,7 @@ int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* store variables */
|
||||||
waitsem = chan->waitsem;
|
waitsem = chan->waitsem;
|
||||||
exclsem = chan->exclsem;
|
exclsem = chan->exclsem;
|
||||||
|
|
||||||
@@ -419,7 +340,7 @@ int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg)
|
|||||||
|
|
||||||
usb_host_edpt_open(&usb_host_handle, hport->dev_addr, &ep_desc);
|
usb_host_edpt_open(&usb_host_handle, hport->dev_addr, &ep_desc);
|
||||||
|
|
||||||
/* restore variable */
|
/* restore variables */
|
||||||
chan->waitsem = waitsem;
|
chan->waitsem = waitsem;
|
||||||
chan->exclsem = exclsem;
|
chan->exclsem = exclsem;
|
||||||
|
|
||||||
|
|||||||
@@ -262,21 +262,6 @@ static void musb_read_packet(uint8_t ep_idx, uint8_t *buffer, uint16_t len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: musb_pipe_waitsetup
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Set the request for the transfer complete event well BEFORE enabling
|
|
||||||
* the transfer (as soon as we are absolutely committed to the transfer).
|
|
||||||
* We do this to minimize race conditions. This logic would have to be
|
|
||||||
* expanded if we want to have more than one packet in flight at a time!
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* Called from a normal thread context BEFORE the transfer has been
|
|
||||||
* started.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static int musb_pipe_waitsetup(struct musb_pipe *chan)
|
static int musb_pipe_waitsetup(struct musb_pipe *chan)
|
||||||
{
|
{
|
||||||
size_t flags;
|
size_t flags;
|
||||||
@@ -284,13 +269,7 @@ static int musb_pipe_waitsetup(struct musb_pipe *chan)
|
|||||||
|
|
||||||
flags = usb_osal_enter_critical_section();
|
flags = usb_osal_enter_critical_section();
|
||||||
|
|
||||||
/* Is the device still connected? */
|
|
||||||
|
|
||||||
if (usbh_get_port_connect_status(0)) {
|
if (usbh_get_port_connect_status(0)) {
|
||||||
/* Yes.. then set waiter to indicate that we expect to be informed
|
|
||||||
* when either (1) the device is disconnected, or (2) the transfer
|
|
||||||
* completed.
|
|
||||||
*/
|
|
||||||
chan->waiter = true;
|
chan->waiter = true;
|
||||||
chan->enable = true;
|
chan->enable = true;
|
||||||
chan->result = -EBUSY;
|
chan->result = -EBUSY;
|
||||||
@@ -305,21 +284,6 @@ static int musb_pipe_waitsetup(struct musb_pipe *chan)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: musb_pipe_asynchsetup
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Set the request for the transfer complete event well BEFORE enabling
|
|
||||||
* the transfer (as soon as we are absolutely committed to the to avoid
|
|
||||||
* transfer). We do this to minimize race conditions. This logic would
|
|
||||||
* have to be expanded if we want to have more than one packet in flight
|
|
||||||
* at a time!
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* Might be called from the level of an interrupt handler
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef CONFIG_USBHOST_ASYNCH
|
#ifdef CONFIG_USBHOST_ASYNCH
|
||||||
static int musb_pipe_asynchsetup(struct musb_pipe *chan, usbh_asynch_callback_t callback, void *arg)
|
static int musb_pipe_asynchsetup(struct musb_pipe *chan, usbh_asynch_callback_t callback, void *arg)
|
||||||
{
|
{
|
||||||
@@ -327,13 +291,8 @@ static int musb_pipe_asynchsetup(struct musb_pipe *chan, usbh_asynch_callback_t
|
|||||||
int ret = -ENODEV;
|
int ret = -ENODEV;
|
||||||
|
|
||||||
flags = usb_osal_enter_critical_section();
|
flags = usb_osal_enter_critical_section();
|
||||||
/* Is the device still connected? */
|
|
||||||
|
|
||||||
if (usbh_get_port_connect_status(0)) {
|
if (usbh_get_port_connect_status(0)) {
|
||||||
/* Yes.. then set waiter to indicate that we expect to be informed
|
|
||||||
* when either (1) the device is disconnected, or (2) the transfer
|
|
||||||
* completed.
|
|
||||||
*/
|
|
||||||
chan->waiter = false;
|
chan->waiter = false;
|
||||||
chan->enable = true;
|
chan->enable = true;
|
||||||
chan->result = -EBUSY;
|
chan->result = -EBUSY;
|
||||||
@@ -348,27 +307,11 @@ static int musb_pipe_asynchsetup(struct musb_pipe *chan, usbh_asynch_callback_t
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: musb_pipe_wait
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Wait for a transfer on a channel to complete.
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* Called from a normal thread context
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static int musb_pipe_wait(struct musb_pipe *chan, uint32_t timeout)
|
static int musb_pipe_wait(struct musb_pipe *chan, uint32_t timeout)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Loop, testing for an end of transfer condition. The channel 'result'
|
/* wait until timeout or sem give */
|
||||||
* was set to EBUSY and 'waiter' was set to true before the transfer;
|
|
||||||
* 'waiter' will be set to false and 'result' will be set appropriately
|
|
||||||
* when the transfer is completed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (chan->waiter) {
|
if (chan->waiter) {
|
||||||
ret = usb_osal_sem_take(chan->waitsem, timeout);
|
ret = usb_osal_sem_take(chan->waitsem, timeout);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -376,7 +319,7 @@ static int musb_pipe_wait(struct musb_pipe *chan, uint32_t timeout)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The transfer is complete and return the result */
|
/* Sem give, check if giving from error isr */
|
||||||
ret = chan->result;
|
ret = chan->result;
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -386,19 +329,6 @@ static int musb_pipe_wait(struct musb_pipe *chan, uint32_t timeout)
|
|||||||
return chan->xfrd;
|
return chan->xfrd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: musb_pipe_wakeup
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* A channel transfer has completed... wakeup any threads waiting for the
|
|
||||||
* transfer to complete.
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* This function is called from the transfer complete interrupt handler for
|
|
||||||
* the channel. Interrupts are disabled.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static void musb_pipe_wakeup(struct musb_pipe *chan)
|
static void musb_pipe_wakeup(struct musb_pipe *chan)
|
||||||
{
|
{
|
||||||
usbh_asynch_callback_t callback;
|
usbh_asynch_callback_t callback;
|
||||||
@@ -406,16 +336,11 @@ static void musb_pipe_wakeup(struct musb_pipe *chan)
|
|||||||
int nbytes;
|
int nbytes;
|
||||||
|
|
||||||
chan->enable = false;
|
chan->enable = false;
|
||||||
/* Is the transfer complete? */
|
|
||||||
if (chan->waiter) {
|
if (chan->waiter) {
|
||||||
/* Wake'em up! */
|
|
||||||
chan->waiter = false;
|
chan->waiter = false;
|
||||||
usb_osal_sem_give(chan->waitsem);
|
usb_osal_sem_give(chan->waitsem);
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_USBHOST_ASYNCH
|
#ifdef CONFIG_USBHOST_ASYNCH
|
||||||
/* No.. is an asynchronous callback expected when the transfer
|
|
||||||
* completes?
|
|
||||||
*/
|
|
||||||
else if (chan->callback) {
|
else if (chan->callback) {
|
||||||
callback = chan->callback;
|
callback = chan->callback;
|
||||||
arg = chan->arg;
|
arg = chan->arg;
|
||||||
@@ -893,7 +818,6 @@ int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t bufl
|
|||||||
usb_osal_mutex_give(g_musb_hcd.exclsem[chan->ep_idx]);
|
usb_osal_mutex_give(g_musb_hcd.exclsem[chan->ep_idx]);
|
||||||
return ret;
|
return ret;
|
||||||
errout_with_mutex:
|
errout_with_mutex:
|
||||||
chan->enable = false;
|
|
||||||
chan->enable = false;
|
chan->enable = false;
|
||||||
usb_osal_mutex_give(g_musb_hcd.exclsem[chan->ep_idx]);
|
usb_osal_mutex_give(g_musb_hcd.exclsem[chan->ep_idx]);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -966,7 +890,6 @@ int usbh_ep_intr_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t bufl
|
|||||||
usb_osal_mutex_give(g_musb_hcd.exclsem[chan->ep_idx]);
|
usb_osal_mutex_give(g_musb_hcd.exclsem[chan->ep_idx]);
|
||||||
return ret;
|
return ret;
|
||||||
errout_with_mutex:
|
errout_with_mutex:
|
||||||
chan->enable = false;
|
|
||||||
chan->enable = false;
|
chan->enable = false;
|
||||||
usb_osal_mutex_give(g_musb_hcd.exclsem[chan->ep_idx]);
|
usb_osal_mutex_give(g_musb_hcd.exclsem[chan->ep_idx]);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -995,17 +918,15 @@ int usb_ep_cancel(usbh_epinfo_t ep)
|
|||||||
|
|
||||||
chan->enable = false;
|
chan->enable = false;
|
||||||
usb_osal_leave_critical_section(flags);
|
usb_osal_leave_critical_section(flags);
|
||||||
/* Is there a thread waiting for this transfer to complete? */
|
|
||||||
|
|
||||||
|
/* Check if there is a thread waiting for this transfer to complete? */
|
||||||
if (chan->waiter) {
|
if (chan->waiter) {
|
||||||
/* Wake'em up! */
|
|
||||||
chan->waiter = false;
|
chan->waiter = false;
|
||||||
usb_osal_sem_give(chan->waitsem);
|
usb_osal_sem_give(chan->waitsem);
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_USBHOST_ASYNCH
|
#ifdef CONFIG_USBHOST_ASYNCH
|
||||||
/* No.. is an asynchronous callback expected when the transfer completes? */
|
/* No.. is an asynchronous callback expected when the transfer completes? */
|
||||||
else if (callback) {
|
else if (callback) {
|
||||||
/* Then perform the callback */
|
|
||||||
callback(arg, -ESHUTDOWN);
|
callback(arg, -ESHUTDOWN);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "usbd_core.h"
|
#include "usbd_core.h"
|
||||||
|
|
||||||
#ifndef USBD_IRQHandler
|
#ifndef USBD_IRQHandler
|
||||||
#define USBD_IRQHandler USB_FS_Handler //use actual usb irq name instead
|
#define USBD_IRQHandler USBD_IRQHandler
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef USB_NUM_BIDIR_ENDPOINTS
|
#ifndef USB_NUM_BIDIR_ENDPOINTS
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "usbh_core.h"
|
#include "usbh_core.h"
|
||||||
|
|
||||||
#ifndef USBH_IRQHandler
|
#ifndef USBH_IRQHandler
|
||||||
#define USBH_IRQHandler OTG_FS_IRQHandler
|
#define USBH_IRQHandler USBH_IRQHandler
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct xxx_pipe {
|
struct xxx_pipe {
|
||||||
@@ -20,65 +20,25 @@ struct xxx_hcd {
|
|||||||
struct xxx_pipe chan[5];
|
struct xxx_pipe chan[5];
|
||||||
} g_xxx_hcd;
|
} g_xxx_hcd;
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: xxx_pipe_alloc
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Allocate a channel.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static int xxx_pipe_alloc(void)
|
static int xxx_pipe_alloc(void)
|
||||||
{
|
{
|
||||||
int chidx;
|
int chidx;
|
||||||
|
|
||||||
/* Search the table of channels */
|
|
||||||
|
|
||||||
for (chidx = 0; chidx < HCD_MAX_ENDPOINT; chidx++) {
|
for (chidx = 0; chidx < HCD_MAX_ENDPOINT; chidx++) {
|
||||||
/* Is this channel available? */
|
|
||||||
if (!g_xxx_hcd.chan[chidx].inuse) {
|
if (!g_xxx_hcd.chan[chidx].inuse) {
|
||||||
/* Yes... make it "in use" and return the index */
|
|
||||||
|
|
||||||
g_xxx_hcd.chan[chidx].inuse = true;
|
g_xxx_hcd.chan[chidx].inuse = true;
|
||||||
return chidx;
|
return chidx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All of the channels are "in-use" */
|
|
||||||
|
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: xxx_pipe_free
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Free a previoiusly allocated channel.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static void xxx_pipe_free(struct xxx_pipe *chan)
|
static void xxx_pipe_free(struct xxx_pipe *chan)
|
||||||
{
|
{
|
||||||
/* Mark the channel available */
|
|
||||||
|
|
||||||
chan->inuse = false;
|
chan->inuse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: xxx_pipe_waitsetup
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Set the request for the transfer complete event well BEFORE enabling
|
|
||||||
* the transfer (as soon as we are absolutely committed to the transfer).
|
|
||||||
* We do this to minimize race conditions. This logic would have to be
|
|
||||||
* expanded if we want to have more than one packet in flight at a time!
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* Called from a normal thread context BEFORE the transfer has been
|
|
||||||
* started.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static int xxx_pipe_waitsetup(struct xxx_pipe *chan)
|
static int xxx_pipe_waitsetup(struct xxx_pipe *chan)
|
||||||
{
|
{
|
||||||
size_t flags;
|
size_t flags;
|
||||||
@@ -86,13 +46,8 @@ static int xxx_pipe_waitsetup(struct xxx_pipe *chan)
|
|||||||
|
|
||||||
flags = usb_osal_enter_critical_section();
|
flags = usb_osal_enter_critical_section();
|
||||||
|
|
||||||
/* Is the device still connected? */
|
|
||||||
|
|
||||||
if (usbh_get_port_connect_status(1)) {
|
if (usbh_get_port_connect_status(1)) {
|
||||||
/* Yes.. then set waiter to indicate that we expect to be informed
|
|
||||||
* when either (1) the device is disconnected, or (2) the transfer
|
|
||||||
* completed.
|
|
||||||
*/
|
|
||||||
chan->waiter = true;
|
chan->waiter = true;
|
||||||
chan->result = -EBUSY;
|
chan->result = -EBUSY;
|
||||||
chan->xfrd = 0;
|
chan->xfrd = 0;
|
||||||
@@ -106,21 +61,6 @@ static int xxx_pipe_waitsetup(struct xxx_pipe *chan)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: xxx_pipe_asynchsetup
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Set the request for the transfer complete event well BEFORE enabling
|
|
||||||
* the transfer (as soon as we are absolutely committed to the to avoid
|
|
||||||
* transfer). We do this to minimize race conditions. This logic would
|
|
||||||
* have to be expanded if we want to have more than one packet in flight
|
|
||||||
* at a time!
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* Might be called from the level of an interrupt handler
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef CONFIG_USBHOST_ASYNCH
|
#ifdef CONFIG_USBHOST_ASYNCH
|
||||||
static int xxx_pipe_asynchsetup(struct xxx_pipe *chan, usbh_asynch_callback_t callback, void *arg)
|
static int xxx_pipe_asynchsetup(struct xxx_pipe *chan, usbh_asynch_callback_t callback, void *arg)
|
||||||
{
|
{
|
||||||
@@ -128,13 +68,8 @@ static int xxx_pipe_asynchsetup(struct xxx_pipe *chan, usbh_asynch_callback_t ca
|
|||||||
int ret = -ENODEV;
|
int ret = -ENODEV;
|
||||||
|
|
||||||
flags = usb_osal_enter_critical_section();
|
flags = usb_osal_enter_critical_section();
|
||||||
/* Is the device still connected? */
|
|
||||||
|
|
||||||
if (usbh_get_port_connect_status(1)) {
|
if (usbh_get_port_connect_status(1)) {
|
||||||
/* Yes.. then set waiter to indicate that we expect to be informed
|
|
||||||
* when either (1) the device is disconnected, or (2) the transfer
|
|
||||||
* completed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
chan->waiter = false;
|
chan->waiter = false;
|
||||||
chan->result = -EBUSY;
|
chan->result = -EBUSY;
|
||||||
@@ -150,27 +85,10 @@ static int xxx_pipe_asynchsetup(struct xxx_pipe *chan, usbh_asynch_callback_t ca
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: xxx_pipe_wait
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Wait for a transfer on a channel to complete.
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* Called from a normal thread context
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static int xxx_pipe_wait(struct xxx_pipe *chan, uint32_t timeout)
|
static int xxx_pipe_wait(struct xxx_pipe *chan, uint32_t timeout)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Loop, testing for an end of transfer condition. The channel 'result'
|
|
||||||
* was set to EBUSY and 'waiter' was set to true before the transfer;
|
|
||||||
* 'waiter' will be set to false and 'result' will be set appropriately
|
|
||||||
* when the transfer is completed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (chan->waiter) {
|
if (chan->waiter) {
|
||||||
ret = usb_osal_sem_take(chan->waitsem, timeout);
|
ret = usb_osal_sem_take(chan->waitsem, timeout);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -178,7 +96,6 @@ static int xxx_pipe_wait(struct xxx_pipe *chan, uint32_t timeout)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The transfer is complete re-enable interrupts and return the result */
|
|
||||||
ret = chan->result;
|
ret = chan->result;
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -187,39 +104,17 @@ static int xxx_pipe_wait(struct xxx_pipe *chan, uint32_t timeout)
|
|||||||
return chan->xfrd;
|
return chan->xfrd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: xxx_pipe_wakeup
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* A channel transfer has completed... wakeup any threads waiting for the
|
|
||||||
* transfer to complete.
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* This function is called from the transfer complete interrupt handler for
|
|
||||||
* the channel. Interrupts are disabled.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static void xxx_pipe_wakeup(struct xxx_pipe *chan)
|
static void xxx_pipe_wakeup(struct xxx_pipe *chan)
|
||||||
{
|
{
|
||||||
usbh_asynch_callback_t callback;
|
usbh_asynch_callback_t callback;
|
||||||
void *arg;
|
void *arg;
|
||||||
int nbytes;
|
int nbytes;
|
||||||
|
|
||||||
/* Is the transfer complete? */
|
|
||||||
|
|
||||||
if (chan->result != -EBUSY) {
|
|
||||||
/* Is there a thread waiting for this transfer to complete? */
|
|
||||||
|
|
||||||
if (chan->waiter) {
|
if (chan->waiter) {
|
||||||
/* Wake'em up! */
|
|
||||||
chan->waiter = false;
|
chan->waiter = false;
|
||||||
usb_osal_sem_give(chan->waitsem);
|
usb_osal_sem_give(chan->waitsem);
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_USBHOST_ASYNCH
|
#ifdef CONFIG_USBHOST_ASYNCH
|
||||||
/* No.. is an asynchronous callback expected when the transfer
|
|
||||||
* completes?
|
|
||||||
*/
|
|
||||||
else if (chan->callback) {
|
else if (chan->callback) {
|
||||||
callback = chan->callback;
|
callback = chan->callback;
|
||||||
arg = chan->arg;
|
arg = chan->arg;
|
||||||
@@ -234,7 +129,6 @@ static void xxx_pipe_wakeup(struct xxx_pipe *chan)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
__WEAK void usb_hc_low_level_init(void)
|
__WEAK void usb_hc_low_level_init(void)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user