Sync betaflight to Gitea
This commit is contained in:
@@ -0,0 +1,530 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file usbh_cdc_class.c
|
||||
* @brief usb host msc class type
|
||||
**************************************************************************
|
||||
* Copyright notice & Disclaimer
|
||||
*
|
||||
* The software Board Support Package (BSP) that is made available to
|
||||
* download from Artery official website is the copyrighted work of Artery.
|
||||
* Artery authorizes customers to use, copy, and distribute the BSP
|
||||
* software and its related documentation for the purpose of design and
|
||||
* development in conjunction with Artery microcontrollers. Use of the
|
||||
* software is governed by this copyright notice and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
|
||||
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
|
||||
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
|
||||
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
|
||||
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
#include "usbh_cdc_class.h"
|
||||
#include "usb_conf.h"
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_ctrl.h"
|
||||
#include "string.h"
|
||||
|
||||
/** @addtogroup AT32F435_437_middlewares_usbh_class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup usbh_cdc_class
|
||||
* @brief usb host class cdc demo
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup usbh_cdc_class_private_functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
static usb_sts_type uhost_init_handler(void *uhost);
|
||||
static usb_sts_type uhost_reset_handler(void *uhost);
|
||||
static usb_sts_type uhost_request_handler(void *uhost);
|
||||
static usb_sts_type uhost_process_handler(void *uhost);
|
||||
static usb_sts_type get_linecoding(usbh_core_type *uhost, cdc_line_coding_type *linecoding);
|
||||
static usb_sts_type set_linecoding(usbh_core_type *uhost, cdc_line_coding_type *linecoding);
|
||||
|
||||
static void cdc_process_transmission(usbh_core_type *uhost);
|
||||
static void cdc_process_reception(usbh_core_type *uhost);
|
||||
usbh_cdc_type usbh_cdc;
|
||||
|
||||
usbh_class_handler_type uhost_cdc_class_handler =
|
||||
{
|
||||
uhost_init_handler,
|
||||
uhost_reset_handler,
|
||||
uhost_request_handler,
|
||||
uhost_process_handler,
|
||||
&usbh_cdc
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief usb host class init handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type uhost_init_handler(void *uhost)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usb_sts_type status = USB_OK;
|
||||
uint8_t if_x;
|
||||
usbh_cdc_type *pcdc = &usbh_cdc;
|
||||
puhost->class_handler->pdata = &usbh_cdc;
|
||||
|
||||
memset((void *)pcdc, 0, sizeof(usbh_cdc_type));
|
||||
if_x = usbh_find_interface(puhost, USB_CLASS_CODE_CDC, ABSTRACT_CONTROL_MODEL, COMMON_AT_COMMAND);
|
||||
if(if_x == 0xFF)
|
||||
{
|
||||
USBH_DEBUG("cannot find the interface for communication interface class!");
|
||||
return USB_NOT_SUPPORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(if_x < puhost->dev.cfg_desc.cfg.bNumInterfaces)
|
||||
{
|
||||
USBH_DEBUG ("switching to interface (#%d)", if_x);
|
||||
USBH_DEBUG ("class : %xh", puhost->dev.cfg_desc.interface[if_x].interface.bInterfaceClass);
|
||||
USBH_DEBUG ("subclass : %xh", puhost->dev.cfg_desc.interface[if_x].interface.bInterfaceSubClass );
|
||||
USBH_DEBUG ("protocol : %xh", puhost->dev.cfg_desc.interface[if_x].interface.bInterfaceProtocol );
|
||||
if(puhost->dev.cfg_desc.interface[if_x].interface.bInterfaceClass == COMMUNICATION_INTERFACE_CLASS_CODE)
|
||||
{
|
||||
USBH_DEBUG("CDC device!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
USBH_DEBUG ("cannot select this interface.");
|
||||
}
|
||||
|
||||
/* collect the notification endpoint address and length */
|
||||
if(puhost->dev.cfg_desc.interface[if_x].endpoint[0].bEndpointAddress & 0x80)
|
||||
{
|
||||
pcdc->common_interface.notif_endpoint = puhost->dev.cfg_desc.interface[if_x].endpoint[0].bEndpointAddress;
|
||||
pcdc->common_interface.notif_endpoint_size = puhost->dev.cfg_desc.interface[if_x].endpoint[0].wMaxPacketSize;
|
||||
}
|
||||
/* allocate the length for host channel number in */
|
||||
pcdc->common_interface.notif_channel = usbh_alloc_channel(puhost, pcdc->common_interface.notif_endpoint);
|
||||
|
||||
/* enable channel */
|
||||
usbh_hc_open(puhost,
|
||||
pcdc->common_interface.notif_channel,
|
||||
pcdc->common_interface.notif_endpoint,
|
||||
puhost->dev.address,
|
||||
EPT_INT_TYPE,
|
||||
pcdc->common_interface.notif_endpoint_size,
|
||||
puhost->dev.speed);
|
||||
|
||||
usbh_set_toggle(puhost, pcdc->common_interface.notif_channel, 0);
|
||||
|
||||
|
||||
if_x = usbh_find_interface(puhost, DATA_INTERFACE_CLASS_CODE, RESERVED, NO_CLASS_SPECIFIC_PROTOCOL_CODE);
|
||||
if(if_x == 0xFF)
|
||||
{
|
||||
USBH_DEBUG("cannot find the interface for data interface class!");
|
||||
return USB_NOT_SUPPORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* collect the class specific endpoint address and length */
|
||||
if(puhost->dev.cfg_desc.interface[if_x].endpoint[0].bEndpointAddress & 0x80)
|
||||
{
|
||||
pcdc->data_interface.in_endpoint = puhost->dev.cfg_desc.interface[if_x].endpoint[0].bEndpointAddress;
|
||||
pcdc->data_interface.in_endpoint_size = puhost->dev.cfg_desc.interface[if_x].endpoint[0].wMaxPacketSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcdc->data_interface.out_endpoint = puhost->dev.cfg_desc.interface[if_x].endpoint[0].bEndpointAddress;
|
||||
pcdc->data_interface.out_endpoint_size = puhost->dev.cfg_desc.interface[if_x].endpoint[0].wMaxPacketSize;
|
||||
}
|
||||
|
||||
if(puhost->dev.cfg_desc.interface[if_x].endpoint[1].bEndpointAddress & 0x80)
|
||||
{
|
||||
pcdc->data_interface.in_endpoint = puhost->dev.cfg_desc.interface[if_x].endpoint[1].bEndpointAddress;
|
||||
pcdc->data_interface.in_endpoint_size = puhost->dev.cfg_desc.interface[if_x].endpoint[1].wMaxPacketSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcdc->data_interface.out_endpoint = puhost->dev.cfg_desc.interface[if_x].endpoint[1].bEndpointAddress;
|
||||
pcdc->data_interface.out_endpoint_size = puhost->dev.cfg_desc.interface[if_x].endpoint[1].wMaxPacketSize;
|
||||
}
|
||||
|
||||
/* allocate the length for host channel number in */
|
||||
pcdc->data_interface.in_channel = usbh_alloc_channel(puhost, pcdc->data_interface.in_endpoint);
|
||||
/* allocate the length for host channel number out */
|
||||
pcdc->data_interface.out_channel = usbh_alloc_channel(puhost, pcdc->data_interface.out_endpoint);
|
||||
|
||||
/* enable in channel */
|
||||
usbh_hc_open(puhost,
|
||||
pcdc->data_interface.in_channel,
|
||||
pcdc->data_interface.in_endpoint,
|
||||
puhost->dev.address,
|
||||
EPT_BULK_TYPE,
|
||||
pcdc->data_interface.in_endpoint_size,
|
||||
puhost->dev.speed);
|
||||
|
||||
/* enable out channel */
|
||||
usbh_hc_open(puhost,
|
||||
pcdc->data_interface.out_channel,
|
||||
pcdc->data_interface.out_endpoint,
|
||||
puhost->dev.address,
|
||||
EPT_BULK_TYPE,
|
||||
pcdc->data_interface.out_endpoint_size,
|
||||
puhost->dev.speed);
|
||||
|
||||
usbh_set_toggle(puhost, pcdc->data_interface.in_channel, 0);
|
||||
usbh_set_toggle(puhost, pcdc->data_interface.out_channel, 0);
|
||||
|
||||
pcdc->state = CDC_IDLE_STATE;
|
||||
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host class reset handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type uhost_reset_handler(void *uhost)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_cdc_type *pcdc = (usbh_cdc_type *)puhost->class_handler->pdata;
|
||||
usb_sts_type status = USB_OK;
|
||||
|
||||
if(puhost->class_handler->pdata == NULL)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if(pcdc->common_interface.notif_channel != 0 )
|
||||
{
|
||||
usbh_free_channel(puhost, pcdc->common_interface.notif_channel);
|
||||
usbh_ch_disable(puhost, pcdc->common_interface.notif_channel);
|
||||
pcdc->common_interface.notif_channel = 0;
|
||||
}
|
||||
|
||||
if(pcdc->data_interface.in_channel != 0 )
|
||||
{
|
||||
usbh_free_channel(puhost, pcdc->data_interface.in_channel);
|
||||
usbh_ch_disable(puhost, pcdc->data_interface.in_channel);
|
||||
pcdc->data_interface.in_channel = 0;
|
||||
}
|
||||
|
||||
if(pcdc->data_interface.out_channel != 0 )
|
||||
{
|
||||
usbh_free_channel(puhost, pcdc->data_interface.out_channel);
|
||||
usbh_ch_disable(puhost, pcdc->data_interface.out_channel);
|
||||
pcdc->data_interface.out_channel = 0;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host cdc class request handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type uhost_request_handler(void *uhost)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_cdc_type *pcdc = (usbh_cdc_type *)puhost->class_handler->pdata;
|
||||
usb_sts_type status = USB_WAIT;
|
||||
|
||||
status = get_linecoding(uhost, &pcdc->linecoding);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host cdc get linecoding handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param linecoding: pointer to the structure of cdc_line_coding_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type get_linecoding(usbh_core_type *uhost, cdc_line_coding_type *linecoding)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usb_sts_type status = USB_WAIT;
|
||||
if(puhost->ctrl.state == CONTROL_IDLE )
|
||||
{
|
||||
uhost->ctrl.setup.bmRequestType = USB_DIR_D2H | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE;
|
||||
uhost->ctrl.setup.bRequest = CDC_GET_LINE_CODING;
|
||||
uhost->ctrl.setup.wValue = 0;
|
||||
uhost->ctrl.setup.wLength = LINE_CODING_STRUCTURE_SIZE;
|
||||
uhost->ctrl.setup.wIndex = 0;
|
||||
|
||||
usbh_ctrl_request(uhost, linecoding->array, LINE_CODING_STRUCTURE_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = usbh_ctrl_result_check(puhost, CONTROL_IDLE, ENUM_IDLE);
|
||||
if(status == USB_OK || status == USB_NOT_SUPPORT)
|
||||
{
|
||||
status = USB_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host cdc set linecoding handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param linecoding: pointer to the structure of cdc_line_coding_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type set_linecoding(usbh_core_type *uhost, cdc_line_coding_type *linecoding)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usb_sts_type status = USB_WAIT;
|
||||
|
||||
if(puhost->ctrl.state == CONTROL_IDLE )
|
||||
{
|
||||
uhost->ctrl.setup.bmRequestType = USB_DIR_H2D | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE;
|
||||
uhost->ctrl.setup.bRequest = CDC_SET_LINE_CODING;
|
||||
uhost->ctrl.setup.wValue = 0;
|
||||
uhost->ctrl.setup.wLength = LINE_CODING_STRUCTURE_SIZE;
|
||||
uhost->ctrl.setup.wIndex = 0;
|
||||
|
||||
status = usbh_ctrl_request(uhost, linecoding->array, LINE_CODING_STRUCTURE_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = usbh_ctrl_result_check(puhost, CONTROL_IDLE, ENUM_IDLE);
|
||||
if(status == USB_OK || status == USB_NOT_SUPPORT)
|
||||
{
|
||||
status = USB_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host class process handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type uhost_process_handler(void *uhost)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_cdc_type *pcdc = (usbh_cdc_type *)puhost->class_handler->pdata;
|
||||
usb_sts_type status;
|
||||
|
||||
switch(pcdc->state)
|
||||
{
|
||||
case CDC_IDLE_STATE:
|
||||
status = USB_OK;
|
||||
break;
|
||||
|
||||
case CDC_SET_LINE_CODING_STATE:
|
||||
status = set_linecoding(puhost, pcdc->puserlinecoding);
|
||||
if(status == USB_OK)
|
||||
pcdc->state = CDC_GET_LAST_LINE_CODING_STATE;
|
||||
break;
|
||||
|
||||
case CDC_GET_LAST_LINE_CODING_STATE:
|
||||
status = get_linecoding(puhost, &(pcdc->linecoding));
|
||||
if(status == USB_OK)
|
||||
{
|
||||
pcdc->state = CDC_IDLE_STATE;
|
||||
if((pcdc->linecoding.line_coding_b.char_format == pcdc->puserlinecoding->line_coding_b.char_format)&&
|
||||
(pcdc->linecoding.line_coding_b.data_bits == pcdc->puserlinecoding->line_coding_b.data_bits)&&
|
||||
(pcdc->linecoding.line_coding_b.parity_type == pcdc->puserlinecoding->line_coding_b.parity_type)&&
|
||||
(pcdc->linecoding.line_coding_b.data_baudrate == pcdc->puserlinecoding->line_coding_b.data_baudrate))
|
||||
{
|
||||
/* line coding changed */
|
||||
}
|
||||
}
|
||||
pcdc->state = CDC_IDLE_STATE;
|
||||
break;
|
||||
|
||||
case CDC_TRANSFER_DATA:
|
||||
cdc_process_transmission(puhost);
|
||||
cdc_process_reception(puhost);
|
||||
break;
|
||||
|
||||
case CDC_ERROR_STATE:
|
||||
status = usbh_clear_ept_feature(puhost, 0, pcdc->common_interface.notif_channel);
|
||||
if(status == USB_OK)
|
||||
pcdc->state = CDC_IDLE_STATE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host cdc class process transmission handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static void cdc_process_transmission(usbh_core_type *uhost)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_cdc_type *pcdc = (usbh_cdc_type *)puhost->class_handler->pdata;
|
||||
|
||||
switch(pcdc->data_tx_state)
|
||||
{
|
||||
case CDC_SEND_DATA:
|
||||
if(pcdc->tx_len > pcdc->data_interface.out_endpoint_size)
|
||||
{
|
||||
usbh_bulk_send(puhost, pcdc->data_interface.out_channel, (uint8_t*)pcdc->tx_data, pcdc->data_interface.out_endpoint_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
usbh_bulk_send(puhost, pcdc->data_interface.out_channel, (uint8_t*)pcdc->tx_data, pcdc->tx_len);
|
||||
}
|
||||
pcdc->data_tx_state = CDC_SEND_DATA_WAIT;
|
||||
break;
|
||||
|
||||
case CDC_SEND_DATA_WAIT:
|
||||
if(uhost->urb_state[pcdc->data_interface.out_channel] == URB_DONE)
|
||||
{
|
||||
if(pcdc->tx_len > pcdc->data_interface.out_endpoint_size)
|
||||
{
|
||||
pcdc->tx_len -= pcdc->data_interface.out_endpoint_size;
|
||||
pcdc->tx_data += pcdc->data_interface.out_endpoint_size;
|
||||
pcdc->data_tx_state = CDC_SEND_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcdc->tx_len = 0;
|
||||
pcdc->data_tx_state = CDC_IDLE;
|
||||
cdc_transmit_complete(uhost);
|
||||
}
|
||||
}
|
||||
else if( uhost->urb_state[pcdc->data_interface.out_channel] == URB_NOTREADY)
|
||||
{
|
||||
pcdc->data_tx_state = CDC_SEND_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host cdc class start transmission handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param data: tx data pointer
|
||||
* @param len: tx data len
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
void cdc_start_transmission(usbh_core_type *uhost, uint8_t *data, uint32_t len)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_cdc_type *pcdc = (usbh_cdc_type *)puhost->class_handler->pdata;
|
||||
if(pcdc->data_tx_state == CDC_IDLE)
|
||||
{
|
||||
pcdc->data_tx_state = CDC_SEND_DATA;
|
||||
pcdc->state = CDC_TRANSFER_DATA;
|
||||
pcdc->tx_data = data;
|
||||
pcdc->tx_len = len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief usb host cdc class transmit complete
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
__weak void cdc_transmit_complete(usbh_core_type *uhost)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host cdc class process reception handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static void cdc_process_reception(usbh_core_type *uhost)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_cdc_type *pcdc = (usbh_cdc_type *)puhost->class_handler->pdata;
|
||||
uint32_t len = 0;
|
||||
|
||||
switch(pcdc->data_rx_state)
|
||||
{
|
||||
case CDC_RECEIVE_DATA:
|
||||
usbh_bulk_recv(puhost, pcdc->data_interface.in_channel, (uint8_t*)pcdc->rx_data, pcdc->data_interface.in_endpoint_size);
|
||||
pcdc->data_rx_state = CDC_RECEIVE_DATA_WAIT;
|
||||
break;
|
||||
|
||||
case CDC_RECEIVE_DATA_WAIT:
|
||||
if(uhost->urb_state[pcdc->data_interface.in_channel] == URB_DONE)
|
||||
{
|
||||
len = uhost->hch[pcdc->data_interface.in_channel].trans_count;
|
||||
if(pcdc->rx_len > len && len > pcdc->data_interface.in_endpoint_size)
|
||||
{
|
||||
pcdc->rx_len -= len;
|
||||
pcdc->rx_data += len;
|
||||
pcdc->data_rx_state = CDC_RECEIVE_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcdc->data_rx_state = CDC_IDLE;
|
||||
cdc_receive_complete(uhost);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host cdc class start reception handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param data: receive data pointer
|
||||
* @param len: receive data len
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
void cdc_start_reception(usbh_core_type *uhost, uint8_t *data, uint32_t len)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_cdc_type *pcdc = (usbh_cdc_type *)puhost->class_handler->pdata;
|
||||
|
||||
if(pcdc->data_rx_state == CDC_IDLE)
|
||||
{
|
||||
pcdc->data_rx_state = CDC_RECEIVE_DATA;
|
||||
pcdc->state = CDC_TRANSFER_DATA;
|
||||
pcdc->rx_data = data;
|
||||
pcdc->rx_len = len;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host cdc class reception complete
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
__weak void cdc_receive_complete(usbh_core_type *uhost)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,282 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file usbh_cdc_class.h
|
||||
* @brief usb host cdc class header file
|
||||
**************************************************************************
|
||||
* Copyright notice & Disclaimer
|
||||
*
|
||||
* The software Board Support Package (BSP) that is made available to
|
||||
* download from Artery official website is the copyrighted work of Artery.
|
||||
* Artery authorizes customers to use, copy, and distribute the BSP
|
||||
* software and its related documentation for the purpose of design and
|
||||
* development in conjunction with Artery microcontrollers. Use of the
|
||||
* software is governed by this copyright notice and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
|
||||
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
|
||||
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
|
||||
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
|
||||
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBH_MSC_CLASS_H
|
||||
#define __USBH_MSC_CLASS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "usbh_core.h"
|
||||
#include "usb_conf.h"
|
||||
|
||||
/** @addtogroup AT32F435_437_middlewares_usbh_class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup USBH_cdc_class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBH_cdc_class_definition
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*Communication Class codes*/
|
||||
#define USB_CDC_CLASS 0x02
|
||||
#define COMMUNICATION_INTERFACE_CLASS_CODE 0x02
|
||||
|
||||
/*Data Interface Class Codes*/
|
||||
#define DATA_INTERFACE_CLASS_CODE 0x0A
|
||||
|
||||
/*Communication sub class codes*/
|
||||
#define RESERVED 0x00
|
||||
#define DIRECT_LINE_CONTROL_MODEL 0x01
|
||||
#define ABSTRACT_CONTROL_MODEL 0x02
|
||||
#define TELEPHONE_CONTROL_MODEL 0x03
|
||||
#define MULTICHANNEL_CONTROL_MODEL 0x04
|
||||
#define CAPI_CONTROL_MODEL 0x05
|
||||
#define ETHERNET_NETWORKING_CONTROL_MODEL 0x06
|
||||
#define ATM_NETWORKING_CONTROL_MODEL 0x07
|
||||
|
||||
|
||||
/*Communication Interface Class Control Protocol Codes*/
|
||||
#define NO_CLASS_SPECIFIC_PROTOCOL_CODE 0x00
|
||||
#define COMMON_AT_COMMAND 0x01
|
||||
#define VENDOR_SPECIFIC 0xFF
|
||||
|
||||
|
||||
#define CS_INTERFACE 0x24
|
||||
#define CDC_PAGE_SIZE_64 0x40
|
||||
|
||||
/*Class-Specific Request Codes*/
|
||||
#define CDC_SEND_ENCAPSULATED_COMMAND 0x00
|
||||
#define CDC_GET_ENCAPSULATED_RESPONSE 0x01
|
||||
#define CDC_SET_COMM_FEATURE 0x02
|
||||
#define CDC_GET_COMM_FEATURE 0x03
|
||||
#define CDC_CLEAR_COMM_FEATURE 0x04
|
||||
|
||||
#define CDC_SET_AUX_LINE_STATE 0x10
|
||||
#define CDC_SET_HOOK_STATE 0x11
|
||||
#define CDC_PULSE_SETUP 0x12
|
||||
#define CDC_SEND_PULSE 0x13
|
||||
#define CDC_SET_PULSE_TIME 0x14
|
||||
#define CDC_RING_AUX_JACK 0x15
|
||||
|
||||
#define CDC_SET_LINE_CODING 0x20
|
||||
#define CDC_GET_LINE_CODING 0x21
|
||||
#define CDC_SET_CONTROL_LINE_STATE 0x22
|
||||
#define CDC_SEND_BREAK 0x23
|
||||
|
||||
#define CDC_SET_RINGER_PARMS 0x30
|
||||
#define CDC_GET_RINGER_PARMS 0x31
|
||||
#define CDC_SET_OPERATION_PARMS 0x32
|
||||
#define CDC_GET_OPERATION_PARMS 0x33
|
||||
#define CDC_SET_LINE_PARMS 0x34
|
||||
#define CDC_GET_LINE_PARMS 0x35
|
||||
#define CDC_DIAL_DIGITS 0x36
|
||||
#define CDC_SET_UNIT_PARAMETER 0x37
|
||||
#define CDC_GET_UNIT_PARAMETER 0x38
|
||||
#define CDC_CLEAR_UNIT_PARAMETER 0x39
|
||||
#define CDC_GET_PROFILE 0x3A
|
||||
|
||||
#define CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40
|
||||
#define CDC_SET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x41
|
||||
#define CDC_GET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x42
|
||||
#define CDC_SET_ETHERNET_PACKET_FILTER 0x43
|
||||
#define CDC_GET_ETHERNET_STATISTIC 0x44
|
||||
|
||||
#define CDC_SET_ATM_DATA_FORMAT 0x50
|
||||
#define CDC_GET_ATM_DEVICE_STATISTICS 0x51
|
||||
#define CDC_SET_ATM_DEFAULT_VC 0x52
|
||||
#define CDC_GET_ATM_VC_STATISTICS 0x53
|
||||
|
||||
|
||||
/* wValue for SetControlLineState*/
|
||||
#define CDC_ACTIVATE_CARRIER_SIGNAL_RTS 0x0002
|
||||
#define CDC_DEACTIVATE_CARRIER_SIGNAL_RTS 0x0000
|
||||
#define CDC_ACTIVATE_SIGNAL_DTR 0x0001
|
||||
#define CDC_DEACTIVATE_SIGNAL_DTR 0x0000
|
||||
|
||||
#define LINE_CODING_STRUCTURE_SIZE 0x07
|
||||
|
||||
/* states for cdc state machine */
|
||||
typedef enum
|
||||
{
|
||||
CDC_IDLE = 0x0,
|
||||
CDC_SEND_DATA = 0x1,
|
||||
CDC_SEND_DATA_WAIT = 0x2,
|
||||
CDC_RECEIVE_DATA = 0x3,
|
||||
CDC_RECEIVE_DATA_WAIT = 0x4,
|
||||
} cdc_data_state_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CDC_IDLE_STATE = 0x0,
|
||||
CDC_SET_LINE_CODING_STATE = 0x1,
|
||||
CDC_GET_LAST_LINE_CODING_STATE = 0x2,
|
||||
CDC_TRANSFER_DATA = 0x3,
|
||||
CDC_ERROR_STATE = 0x4,
|
||||
} cdc_state_type;
|
||||
|
||||
|
||||
/*line coding structure*/
|
||||
typedef union _cdc_line_coding_structure
|
||||
{
|
||||
uint8_t array[LINE_CODING_STRUCTURE_SIZE];
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t data_baudrate; /*data terminal rate, in bits per second*/
|
||||
uint8_t char_format; /* Stop bits
|
||||
0 - 1 Stop bit
|
||||
1 - 1.5 Stop bits
|
||||
2 - 2 Stop bits*/
|
||||
uint8_t parity_type; /* parity
|
||||
0 - none
|
||||
1 - odd
|
||||
2 - even
|
||||
3 - mark
|
||||
4 - space*/
|
||||
uint8_t data_bits; /* data bits (5, 6, 7, 8 or 16). */
|
||||
}line_coding_b;
|
||||
} cdc_line_coding_type;
|
||||
|
||||
|
||||
|
||||
/* header functional descriptor */
|
||||
typedef struct _functional_descriptor_header
|
||||
{
|
||||
uint8_t bfunctionlength; /* size of this descriptor. */
|
||||
uint8_t bdescriptortype; /* cs_interface (0x24) */
|
||||
uint8_t bdescriptorsubtype; /* header functional descriptor subtype as */
|
||||
uint16_t bcdcdc; /* usb class definitions for communication
|
||||
devices specification release number in
|
||||
binary-coded decimal. */
|
||||
} cdc_headerfuncdesc_type;
|
||||
|
||||
/* call management functional descriptor */
|
||||
typedef struct _callmgmt_functional_descriptor
|
||||
{
|
||||
uint8_t blength; /* size of this functional descriptor, in bytes */
|
||||
uint8_t bdescriptortype; /* cs_interface (0x24) */
|
||||
uint8_t bdescriptorsubtype; /* call management functional descriptor subtype */
|
||||
uint8_t bmcapabilities; /* bmcapabilities: d0+d1 */
|
||||
uint8_t bdatainterface; /* bdatainterface: 1 */
|
||||
} cdc_callmgmtfuncdesc_type;
|
||||
|
||||
/* abstract control management functional descriptor */
|
||||
typedef struct _abstractcntrlmgmt_functional_descriptor
|
||||
{
|
||||
uint8_t blength; /* size of this functional descriptor, in bytes */
|
||||
uint8_t bdescriptortype; /* cs_interface (0x24) */
|
||||
uint8_t bdescriptorsubtype; /* abstract control management functional
|
||||
descriptor subtype */
|
||||
uint8_t bmcapabilities; /* the capabilities that this configuration supports */
|
||||
} cdc_abstcntrlmgmtfuncdesc_type;
|
||||
|
||||
/* union functional descriptor */
|
||||
typedef struct _union_functional_descriptor
|
||||
{
|
||||
uint8_t blength; /* size of this functional descriptor, in bytes */
|
||||
uint8_t bdescriptortype; /* cs_interface (0x24) */
|
||||
uint8_t bdescriptorsubtype; /* union functional descriptor subtype */
|
||||
uint8_t bmasterinterface; /* the interface number of the communication or
|
||||
data class interface */
|
||||
uint8_t bslaveinterface0; /* interface number of first slave */
|
||||
} cdc_unionfuncdesc_type;
|
||||
|
||||
|
||||
typedef struct _usbh_cdcinterfacedesc
|
||||
{
|
||||
cdc_headerfuncdesc_type cdc_headerfuncdesc;
|
||||
cdc_callmgmtfuncdesc_type cdc_callmgmtfuncdesc;
|
||||
cdc_abstcntrlmgmtfuncdesc_type cdc_abstcntrlmgmtfuncdesc;
|
||||
cdc_unionfuncdesc_type cdc_unionfuncdesc;
|
||||
} cdc_interfacedesc_type;
|
||||
|
||||
|
||||
/* structure for cdc process */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t notif_channel;
|
||||
uint8_t notif_endpoint;
|
||||
uint8_t buff[8];
|
||||
uint16_t notif_endpoint_size;
|
||||
} cdc_common_interface_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t in_channel;
|
||||
uint8_t out_channel;
|
||||
uint8_t out_endpoint;
|
||||
uint8_t in_endpoint;
|
||||
uint8_t buff[8];
|
||||
uint16_t out_endpoint_size;
|
||||
uint16_t in_endpoint_size;
|
||||
} cdc_data_interface_type;
|
||||
|
||||
/**
|
||||
* @brief usb cdc struct
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
cdc_common_interface_type common_interface;
|
||||
cdc_data_interface_type data_interface;
|
||||
cdc_interfacedesc_type cdc_desc;
|
||||
cdc_line_coding_type linecoding;
|
||||
cdc_line_coding_type *puserlinecoding;
|
||||
cdc_state_type state;
|
||||
cdc_data_state_type data_tx_state;
|
||||
cdc_data_state_type data_rx_state;
|
||||
|
||||
uint8_t *rx_data;
|
||||
uint8_t *tx_data;
|
||||
uint32_t rx_len;
|
||||
uint32_t tx_len;
|
||||
}usbh_cdc_type;
|
||||
|
||||
extern usbh_class_handler_type uhost_cdc_class_handler;
|
||||
extern usbh_cdc_type usbh_cdc;
|
||||
void cdc_start_transmission(usbh_core_type *phost, uint8_t *data, uint32_t len);
|
||||
void cdc_start_reception(usbh_core_type *uhost, uint8_t *data, uint32_t len);
|
||||
__weak void cdc_transmit_complete(usbh_core_type *uhost);
|
||||
__weak void cdc_receive_complete(usbh_core_type *uhost);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,451 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file usbh_hid_class.c
|
||||
* @brief usb host hid class type
|
||||
**************************************************************************
|
||||
* Copyright notice & Disclaimer
|
||||
*
|
||||
* The software Board Support Package (BSP) that is made available to
|
||||
* download from Artery official website is the copyrighted work of Artery.
|
||||
* Artery authorizes customers to use, copy, and distribute the BSP
|
||||
* software and its related documentation for the purpose of design and
|
||||
* development in conjunction with Artery microcontrollers. Use of the
|
||||
* software is governed by this copyright notice and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
|
||||
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
|
||||
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
|
||||
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
|
||||
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
#include "usbh_hid_class.h"
|
||||
#include "usb_conf.h"
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_ctrl.h"
|
||||
#include "usbh_hid_mouse.h"
|
||||
#include "usbh_hid_keyboard.h"
|
||||
|
||||
/** @addtogroup AT32F435_437_middlewares_usbh_class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBH_hid_class
|
||||
* @brief usb host class hid demo
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBH_hid_class_private_functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
static usb_sts_type uhost_init_handler(void *uhost);
|
||||
static usb_sts_type uhost_reset_handler(void *uhost);
|
||||
static usb_sts_type uhost_request_handler(void *uhost);
|
||||
static usb_sts_type uhost_process_handler(void *uhost);
|
||||
|
||||
usbh_hid_type usbh_hid;
|
||||
usbh_class_handler_type uhost_hid_class_handler =
|
||||
{
|
||||
uhost_init_handler,
|
||||
uhost_reset_handler,
|
||||
uhost_request_handler,
|
||||
uhost_process_handler,
|
||||
&usbh_hid
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief usb host class init handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type uhost_init_handler(void *uhost)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usb_sts_type status = USB_OK;
|
||||
uint8_t hidx, eptidx = 0;
|
||||
usbh_hid_type *phid = &usbh_hid;
|
||||
|
||||
puhost->class_handler->pdata = &usbh_hid;
|
||||
|
||||
/* get hid interface */
|
||||
hidx = usbh_find_interface(puhost, USB_CLASS_CODE_HID, 0x01, 0xFF);
|
||||
if(hidx == 0xFF)
|
||||
{
|
||||
USBH_DEBUG("Unsupport Device!");
|
||||
return USB_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
/* get hid protocol */
|
||||
phid->protocol = puhost->dev.cfg_desc.interface[hidx].interface.bInterfaceProtocol;
|
||||
|
||||
if(phid->protocol == USB_HID_MOUSE_PROTOCOL_CODE)
|
||||
{
|
||||
USBH_DEBUG("Mouse Device!");
|
||||
}
|
||||
else if(phid->protocol == USB_HID_KEYBOARD_PROTOCOL_CODE)
|
||||
{
|
||||
USBH_DEBUG("Keyboard Device!");
|
||||
}
|
||||
|
||||
for(eptidx = 0; eptidx < puhost->dev.cfg_desc.interface[hidx].interface.bNumEndpoints; eptidx ++)
|
||||
{
|
||||
if(puhost->dev.cfg_desc.interface[hidx].endpoint[eptidx].bEndpointAddress & 0x80)
|
||||
{
|
||||
/* find interface out endpoint information */
|
||||
phid->eptin = puhost->dev.cfg_desc.interface[hidx].endpoint[eptidx].bEndpointAddress;
|
||||
phid->in_maxpacket = puhost->dev.cfg_desc.interface[hidx].endpoint[eptidx].wMaxPacketSize;
|
||||
phid->in_poll = puhost->dev.cfg_desc.interface[hidx].endpoint[eptidx].bInterval;
|
||||
|
||||
phid->chin = usbh_alloc_channel(puhost, phid->eptin);
|
||||
/* enable channel */
|
||||
usbh_hc_open(puhost, phid->chin,phid->eptin,
|
||||
puhost->dev.address, EPT_INT_TYPE,
|
||||
phid->in_maxpacket,
|
||||
puhost->dev.speed);
|
||||
usbh_set_toggle(puhost, phid->chin, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* get interface out endpoint information */
|
||||
phid->eptout = puhost->dev.cfg_desc.interface[hidx].endpoint[eptidx].bEndpointAddress;
|
||||
phid->out_maxpacket = puhost->dev.cfg_desc.interface[hidx].endpoint[eptidx].wMaxPacketSize;
|
||||
phid->out_poll = puhost->dev.cfg_desc.interface[hidx].endpoint[eptidx].bInterval;
|
||||
|
||||
phid->chout = usbh_alloc_channel(puhost, usbh_hid.eptout);
|
||||
/* enable channel */
|
||||
usbh_hc_open(puhost, phid->chout, phid->eptout,
|
||||
puhost->dev.address, EPT_INT_TYPE,
|
||||
phid->out_maxpacket,
|
||||
puhost->dev.speed);
|
||||
usbh_set_toggle(puhost, phid->chout, 0);
|
||||
}
|
||||
}
|
||||
phid->ctrl_state = USB_HID_STATE_IDLE;
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host class reset handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type uhost_reset_handler(void *uhost)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_hid_type *phid = (usbh_hid_type *)puhost->class_handler->pdata;
|
||||
usb_sts_type status = USB_OK;
|
||||
if(puhost->class_handler->pdata == NULL)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if(phid->chin != 0)
|
||||
{
|
||||
/* free in channel */
|
||||
usbh_free_channel(puhost, phid->chin);
|
||||
usbh_ch_disable(puhost, phid->chin);
|
||||
phid->chin = 0;
|
||||
}
|
||||
|
||||
if(phid->chout != 0)
|
||||
{
|
||||
/* free out channel */
|
||||
usbh_free_channel(puhost, phid->chout);
|
||||
usbh_ch_disable(puhost, phid->chout);
|
||||
phid->chout = 0;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host hid class get descriptor
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param length: descriptor length
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type usbh_hid_get_desc(void *uhost, uint16_t length)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_hid_type *phid = (usbh_hid_type *)puhost->class_handler->pdata;
|
||||
usb_sts_type status = USB_WAIT;
|
||||
uint8_t bm_req;
|
||||
uint16_t wvalue;
|
||||
if(puhost->ctrl.state == CONTROL_IDLE)
|
||||
{
|
||||
bm_req = USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_STANDARD;
|
||||
wvalue = (0x21 << 8) & 0xFF00;
|
||||
|
||||
usbh_get_descriptor(puhost, length, bm_req,
|
||||
wvalue, puhost->rx_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(usbh_ctrl_result_check(puhost, CONTROL_IDLE, ENUM_IDLE) == USB_OK)
|
||||
{
|
||||
phid->hid_desc.bLength = puhost->rx_buffer[0];
|
||||
phid->hid_desc.bDescriptorType = puhost->rx_buffer[1];
|
||||
phid->hid_desc.bcdHID = SWAPBYTE(puhost->rx_buffer+2);
|
||||
phid->hid_desc.bCountryCode = puhost->rx_buffer[4];
|
||||
phid->hid_desc.bNumDescriptors = puhost->rx_buffer[5];
|
||||
phid->hid_desc.bReportDescriptorType = puhost->rx_buffer[6];
|
||||
phid->hid_desc.wItemLength = SWAPBYTE(puhost->rx_buffer+7);
|
||||
status = USB_OK;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief usb host hid class get report
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param length: reprot length
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type usbh_hid_get_report(void *uhost, uint16_t length)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usb_sts_type status = USB_WAIT;
|
||||
uint8_t bm_req;
|
||||
uint16_t wvalue;
|
||||
if(puhost->ctrl.state == CONTROL_IDLE)
|
||||
{
|
||||
bm_req = USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_STANDARD;
|
||||
wvalue = (0x22 << 8) & 0xFF00;
|
||||
|
||||
usbh_get_descriptor(puhost, length, bm_req,
|
||||
wvalue, puhost->rx_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(usbh_ctrl_result_check(puhost, CONTROL_IDLE, ENUM_IDLE) == USB_OK)
|
||||
{
|
||||
status = USB_OK;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host hid class set idle
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param id: id
|
||||
* @param dr: dr
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type usbh_hid_set_idle(void *uhost, uint8_t id, uint8_t dr)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usb_sts_type status = USB_WAIT;
|
||||
if(puhost->ctrl.state == CONTROL_IDLE)
|
||||
{
|
||||
puhost->ctrl.setup.bmRequestType = USB_DIR_H2D | USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_CLASS;
|
||||
puhost->ctrl.setup.bRequest = USB_HID_SET_IDLE;
|
||||
puhost->ctrl.setup.wValue = (dr << 8) | id;
|
||||
puhost->ctrl.setup.wIndex = 0;
|
||||
puhost->ctrl.setup.wLength = 0;
|
||||
usbh_ctrl_request(puhost, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = usbh_ctrl_result_check(puhost, CONTROL_IDLE, ENUM_IDLE);
|
||||
if(status == USB_OK || status == USB_NOT_SUPPORT)
|
||||
{
|
||||
status = USB_OK;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host hid class set protocol
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param protocol: portocol number
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type usbh_hid_set_protocol(void *uhost, uint8_t protocol)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usb_sts_type status = USB_WAIT;
|
||||
if(puhost->ctrl.state == CONTROL_IDLE)
|
||||
{
|
||||
puhost->ctrl.setup.bmRequestType = USB_DIR_H2D | USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_CLASS;
|
||||
puhost->ctrl.setup.bRequest = USB_HID_SET_PROTOCOL;
|
||||
puhost->ctrl.setup.wValue = protocol;
|
||||
puhost->ctrl.setup.wIndex = 0;
|
||||
puhost->ctrl.setup.wLength = 0;
|
||||
usbh_ctrl_request(puhost, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = usbh_ctrl_result_check(puhost, CONTROL_IDLE, ENUM_IDLE);
|
||||
if(status == USB_OK || status == USB_NOT_SUPPORT)
|
||||
{
|
||||
status = USB_OK;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host clear feature
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param ept_num: endpoint number
|
||||
* @param hc_num: channel number
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type usbh_clear_endpoint_feature(usbh_core_type *uhost, uint8_t ept_num, uint8_t hc_num)
|
||||
{
|
||||
usb_sts_type status = USB_WAIT;
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
uint8_t bm_req;
|
||||
bm_req = USB_REQ_RECIPIENT_ENDPOINT | USB_REQ_TYPE_STANDARD;
|
||||
if(puhost->ctrl.state == CONTROL_IDLE)
|
||||
{
|
||||
puhost->ctrl.setup.bmRequestType = USB_DIR_H2D | bm_req;
|
||||
puhost->ctrl.setup.bRequest = USB_STD_REQ_CLEAR_FEATURE;
|
||||
puhost->ctrl.setup.wValue = 0x00;
|
||||
puhost->ctrl.setup.wLength = 0;
|
||||
puhost->ctrl.setup.wIndex = ept_num;
|
||||
if((ept_num & 0x80) == USB_DIR_D2H)
|
||||
{
|
||||
puhost->hch[hc_num].toggle_in = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
puhost->hch[hc_num].toggle_out = 0;
|
||||
}
|
||||
status = usbh_ctrl_request(puhost, 0, 0);
|
||||
}
|
||||
if(usbh_ctrl_result_check(puhost, CONTROL_IDLE, ENUM_IDLE) == USB_OK)
|
||||
{
|
||||
status = USB_OK;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host hid class request handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type uhost_request_handler(void *uhost)
|
||||
{
|
||||
usb_sts_type status = USB_WAIT;
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_hid_type *phid = (usbh_hid_type *)puhost->class_handler->pdata;
|
||||
|
||||
switch(phid->ctrl_state)
|
||||
{
|
||||
case USB_HID_STATE_IDLE:
|
||||
phid->ctrl_state = USB_HID_STATE_GET_DESC;
|
||||
break;
|
||||
case USB_HID_STATE_GET_DESC:
|
||||
if(usbh_hid_get_desc(puhost, 9) == USB_OK)
|
||||
{
|
||||
phid->ctrl_state = USB_HID_STATE_GET_REPORT;
|
||||
}
|
||||
break;
|
||||
case USB_HID_STATE_GET_REPORT:
|
||||
if(usbh_hid_get_report(puhost, phid->hid_desc.wItemLength) == USB_OK)
|
||||
{
|
||||
phid->ctrl_state = USB_HID_STATE_SET_IDLE;
|
||||
}
|
||||
break;
|
||||
case USB_HID_STATE_SET_IDLE:
|
||||
if(usbh_hid_set_idle(puhost, 0, 0) == USB_OK)
|
||||
{
|
||||
phid->ctrl_state = USB_HID_STATE_SET_PROTOCOL;
|
||||
}
|
||||
break;
|
||||
case USB_HID_STATE_SET_PROTOCOL:
|
||||
if(usbh_hid_set_protocol(puhost, 0) == USB_OK)
|
||||
{
|
||||
phid->ctrl_state = USB_HID_STATE_COMPLETE;
|
||||
}
|
||||
break;
|
||||
case USB_HID_STATE_COMPLETE:
|
||||
phid->state = USB_HID_INIT;
|
||||
status = USB_OK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host hid class process handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type uhost_process_handler(void *uhost)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_hid_type *phid = (usbh_hid_type *)puhost->class_handler->pdata;
|
||||
urb_sts_type urb_status;
|
||||
switch(phid->state)
|
||||
{
|
||||
case USB_HID_INIT:
|
||||
phid->state = USB_HID_GET;
|
||||
break;
|
||||
|
||||
case USB_HID_GET:
|
||||
usbh_interrupt_recv(puhost, phid->chin, (uint8_t *)phid->buffer, phid->in_maxpacket);
|
||||
phid->state = USB_HID_POLL;
|
||||
phid->poll_timer = usbh_get_frame(puhost->usb_reg);
|
||||
break;
|
||||
|
||||
case USB_HID_POLL:
|
||||
if((usbh_get_frame(puhost->usb_reg) - phid->poll_timer) >= phid->in_poll )
|
||||
{
|
||||
phid->state = USB_HID_GET;
|
||||
}
|
||||
else
|
||||
{
|
||||
urb_status = usbh_get_urb_status(puhost, phid->chin);
|
||||
if(urb_status == URB_DONE)
|
||||
{
|
||||
puhost->urb_state[phid->chin] = URB_IDLE;
|
||||
if(phid->protocol == USB_HID_MOUSE_PROTOCOL_CODE)
|
||||
{
|
||||
usbh_hid_mouse_decode((uint8_t *)phid->buffer);
|
||||
}
|
||||
else if(phid->protocol == USB_HID_KEYBOARD_PROTOCOL_CODE)
|
||||
{
|
||||
usbh_hid_keyboard_decode((uint8_t *)phid->buffer);
|
||||
}
|
||||
|
||||
}
|
||||
else if(urb_status == URB_STALL)
|
||||
{
|
||||
if(usbh_clear_endpoint_feature(puhost, phid->eptin, phid->chin) == USB_OK)
|
||||
{
|
||||
phid->state = USB_HID_GET;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return USB_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file usbh_hid_class.h
|
||||
* @brief usb host hid class header file
|
||||
**************************************************************************
|
||||
* Copyright notice & Disclaimer
|
||||
*
|
||||
* The software Board Support Package (BSP) that is made available to
|
||||
* download from Artery official website is the copyrighted work of Artery.
|
||||
* Artery authorizes customers to use, copy, and distribute the BSP
|
||||
* software and its related documentation for the purpose of design and
|
||||
* development in conjunction with Artery microcontrollers. Use of the
|
||||
* software is governed by this copyright notice and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
|
||||
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
|
||||
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
|
||||
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
|
||||
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBH_HID_CLASS_H
|
||||
#define __USBH_HID_CLASS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "usbh_core.h"
|
||||
#include "usb_conf.h"
|
||||
|
||||
/** @addtogroup AT32F435_437_middlewares_usbh_class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup USBH_hid_class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBH_hid_class_definition
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief usb hid protocol code
|
||||
*/
|
||||
#define USB_HID_NONE_PROTOCOL_CODE 0x00
|
||||
#define USB_HID_KEYBOARD_PROTOCOL_CODE 0x01
|
||||
#define USB_HID_MOUSE_PROTOCOL_CODE 0x02
|
||||
|
||||
/**
|
||||
* @brief usb hid request code
|
||||
*/
|
||||
#define USB_HID_GET_REPORT 0x01
|
||||
#define USB_HID_GET_IDLE 0x02
|
||||
#define USB_HID_GET_PROTOCOL 0x03
|
||||
#define USB_HID_SET_REPORT 0x09
|
||||
#define USB_HID_SET_IDLE 0x0A
|
||||
#define USB_HID_SET_PROTOCOL 0x0B
|
||||
|
||||
/**
|
||||
* @brief usb hid request state
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
USB_HID_STATE_IDLE,
|
||||
USB_HID_STATE_GET_DESC,
|
||||
USB_HID_STATE_GET_REPORT,
|
||||
USB_HID_STATE_SET_IDLE,
|
||||
USB_HID_STATE_SET_PROTOCOL,
|
||||
USB_HID_STATE_COMPLETE,
|
||||
}usb_hid_ctrl_state_type;
|
||||
|
||||
/**
|
||||
* @brief usb hid process state
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
USB_HID_INIT,
|
||||
USB_HID_GET,
|
||||
USB_HID_SEND,
|
||||
USB_HID_POLL,
|
||||
USB_HID_BUSY,
|
||||
USB_HID_ERROR,
|
||||
}usb_hid_state_type;
|
||||
|
||||
/**
|
||||
* @brief usb hid descriptor type
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bcdHID;
|
||||
uint8_t bCountryCode;
|
||||
uint8_t bNumDescriptors;
|
||||
uint8_t bReportDescriptorType;
|
||||
uint16_t wItemLength;
|
||||
}usb_hid_desc_type;
|
||||
|
||||
/**
|
||||
* @brief usb hid struct
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t chin;
|
||||
uint8_t eptin;
|
||||
uint16_t in_maxpacket;
|
||||
uint8_t in_poll;
|
||||
|
||||
uint8_t chout;
|
||||
uint8_t eptout;
|
||||
uint16_t out_maxpacket;
|
||||
uint8_t out_poll;
|
||||
uint8_t protocol;
|
||||
|
||||
|
||||
usb_hid_desc_type hid_desc;
|
||||
usb_hid_ctrl_state_type ctrl_state;
|
||||
usb_hid_state_type state;
|
||||
uint16_t poll_timer;
|
||||
uint32_t buffer[16];
|
||||
}usbh_hid_type;
|
||||
|
||||
extern usbh_class_handler_type uhost_hid_class_handler;
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,253 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file usbh_hid_keyboard.c
|
||||
* @brief usb host hid keyboard type
|
||||
**************************************************************************
|
||||
* Copyright notice & Disclaimer
|
||||
*
|
||||
* The software Board Support Package (BSP) that is made available to
|
||||
* download from Artery official website is the copyrighted work of Artery.
|
||||
* Artery authorizes customers to use, copy, and distribute the BSP
|
||||
* software and its related documentation for the purpose of design and
|
||||
* development in conjunction with Artery microcontrollers. Use of the
|
||||
* software is governed by this copyright notice and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
|
||||
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
|
||||
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
|
||||
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
|
||||
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
#include "usbh_hid_keyboard.h"
|
||||
|
||||
/** @addtogroup AT32F435_437_middlewares_usbh_class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBH_hid_class_keyboard
|
||||
* @brief usb host class hid keyboard
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBH_hid_class_keyboard_private_functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
static const uint8_t hid_keyboard_codes[] =
|
||||
{
|
||||
0, 0, 0, 0, 31, 50, 48, 33,
|
||||
19, 34, 35, 36, 24, 37, 38, 39,
|
||||
52, 51, 25, 26, 17, 20, 32, 21,
|
||||
23, 49, 18, 47, 22, 46, 2, 3,
|
||||
4, 5, 6, 7, 8, 9, 10, 11,
|
||||
43, 110, 15, 16, 61, 12, 13, 27,
|
||||
28, 29, 42, 40, 41, 1, 53, 54,
|
||||
55, 30, 112, 113, 114, 115, 116, 117,
|
||||
118, 119, 120, 121, 122, 123, 124, 125,
|
||||
126, 75, 80, 85, 76, 81, 86, 89,
|
||||
79, 84, 83, 90, 95, 100, 105, 106,
|
||||
108, 93, 98, 103, 92, 97, 102, 91,
|
||||
96, 101, 99, 104, 45, 129, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 107, 0, 56,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
58, 44, 60, 127, 64, 57, 62, 128,
|
||||
};
|
||||
|
||||
#ifdef QWERTY_KEYBOARD
|
||||
|
||||
static const int8_t hid_keyboard_key[] = {
|
||||
'\0', '`', '1', '2', '3', '4', '5', '6',
|
||||
'7', '8', '9', '0', '-', '=', '\0', '\r',
|
||||
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u',
|
||||
'i', 'o', 'p', '[', ']', '\\',
|
||||
'\0', 'a', 's', 'd', 'f', 'g', 'h', 'j',
|
||||
'k', 'l', ';', '\'', '\0', '\n',
|
||||
'\0', '\0', 'z', 'x', 'c', 'v', 'b', 'n',
|
||||
'm', ',', '.', '/', '\0', '\0',
|
||||
'\0', '\0', '\0', ' ', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '7', '4', '1',
|
||||
'\0', '/', '8', '5', '2',
|
||||
'0', '*', '9', '6', '3',
|
||||
'.', '-', '+', '\0', '\n', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0'
|
||||
};
|
||||
|
||||
static const int8_t hid_keyboard_key_shift[] = {
|
||||
'\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
|
||||
'_', '+', '\0', '\0', '\0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U',
|
||||
'I', 'O', 'P', '{', '}', '|', '\0', 'A', 'S', 'D', 'F', 'G',
|
||||
'H', 'J', 'K', 'L', ':', '"', '\0', '\n', '\0', '\0', 'Z', 'X',
|
||||
'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
|
||||
};
|
||||
|
||||
#else
|
||||
static const int8_t hid_keyboard_key[] = {
|
||||
'\0', '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
|
||||
'-', '=', '\0', '\r', '\t', 'a', 'z', 'e', 'r', 't', 'y', 'u',
|
||||
'i', 'o', 'p', '[', ']', '\\', '\0', 'q', 's', 'd', 'f', 'g',
|
||||
'h', 'j', 'k', 'l', 'm', '\0', '\0', '\n', '\0', '\0', 'w', 'x',
|
||||
'c', 'v', 'b', 'n', ',', ';', ':', '!', '\0', '\0', '\0', '\0',
|
||||
'\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '4', '1','\0', '/',
|
||||
'8', '5', '2', '0', '*', '9', '6', '3', '.', '-', '+', '\0',
|
||||
'\n', '\0', '\0', '\0', '\0', '\0', '\0','\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
|
||||
};
|
||||
|
||||
static const int8_t hid_keyboard_key_shift[] = {
|
||||
'\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_',
|
||||
'+', '\0', '\0', '\0', 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O',
|
||||
'P', '{', '}', '*', '\0', 'Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K',
|
||||
'L', 'M', '%', '\0', '\n', '\0', '\0', 'W', 'X', 'C', 'V', 'B', 'N',
|
||||
'?', '.', '/', '\0', '\0', '\0','\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief usb host hid keyboard decode
|
||||
* @param data: keyboard data
|
||||
* @retval none
|
||||
*/
|
||||
void usbh_hid_keyboard_decode(uint8_t *data)
|
||||
{
|
||||
static uint8_t shift;
|
||||
static uint8_t keys[KEYBOARD_MAX_NB_PRESSED];
|
||||
static uint8_t keys_n[KEYBOARD_MAX_NB_PRESSED];
|
||||
static uint8_t keys_l[KEYBOARD_MAX_NB_PRESSED];
|
||||
static uint8_t key_newest;
|
||||
static uint8_t nb_keys;
|
||||
static uint8_t nb_keys_n;
|
||||
static uint8_t nb_keys_l;
|
||||
|
||||
uint8_t idx;
|
||||
uint8_t idy;
|
||||
uint8_t err;
|
||||
uint8_t out;
|
||||
|
||||
nb_keys = 0;
|
||||
nb_keys_n = 0;
|
||||
nb_keys_l = 0;
|
||||
key_newest = 0;
|
||||
|
||||
if(data[0] == KEYBOARD_LEFT_SHIFT || data[0] == KEYBOARD_RIGHT_SHIFT)
|
||||
{
|
||||
shift = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
shift = FALSE;
|
||||
}
|
||||
err = FALSE;
|
||||
|
||||
for(idx = 2; idx < 2 + KEYBOARD_MAX_NB_PRESSED; idx ++)
|
||||
{
|
||||
if((data[idx] == 0x01) ||
|
||||
(data[idx] == 0x02) ||
|
||||
(data[idx] == 0x03))
|
||||
{
|
||||
err = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if(err == TRUE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
nb_keys = 0;
|
||||
nb_keys_n = 0;
|
||||
for(idx = 2; idx < 2 + KEYBOARD_MAX_NB_PRESSED; idx ++)
|
||||
{
|
||||
if(data[idx] != 0)
|
||||
{
|
||||
keys[nb_keys] = data[idx];
|
||||
nb_keys ++;
|
||||
for(idy = 0; idy < nb_keys_l; idy ++)
|
||||
{
|
||||
if(data[idx] == keys_l[idy])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(idy == nb_keys_l)
|
||||
{
|
||||
keys_n[nb_keys_n] = data[idx];
|
||||
nb_keys_n ++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(nb_keys_n == 1)
|
||||
{
|
||||
key_newest = keys_n[0];
|
||||
|
||||
if(shift == TRUE)
|
||||
{
|
||||
out = hid_keyboard_key_shift[hid_keyboard_codes[key_newest]];
|
||||
}
|
||||
else
|
||||
{
|
||||
out = hid_keyboard_key[hid_keyboard_codes[key_newest]];
|
||||
}
|
||||
/* callback user handler */
|
||||
USBH_DEBUG("%c", out);
|
||||
}
|
||||
else
|
||||
{
|
||||
key_newest = 0;
|
||||
}
|
||||
|
||||
nb_keys_l = nb_keys;
|
||||
for(idx = 0; idx < KEYBOARD_MAX_NB_PRESSED; idx ++)
|
||||
{
|
||||
keys_l[idx] = keys[idx];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file usbh_hid_keyboard.h
|
||||
* @brief usb host hid keyboard header file
|
||||
**************************************************************************
|
||||
* Copyright notice & Disclaimer
|
||||
*
|
||||
* The software Board Support Package (BSP) that is made available to
|
||||
* download from Artery official website is the copyrighted work of Artery.
|
||||
* Artery authorizes customers to use, copy, and distribute the BSP
|
||||
* software and its related documentation for the purpose of design and
|
||||
* development in conjunction with Artery microcontrollers. Use of the
|
||||
* software is governed by this copyright notice and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
|
||||
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
|
||||
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
|
||||
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
|
||||
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBH_HID_KEYBOARD_H
|
||||
#define __USBH_HID_KEYBOARD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "usb_conf.h"
|
||||
|
||||
/** @addtogroup AT32F435_437_middlewares_usbh_class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup USBH_hid_class_keyboard
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBH_hid_class_keyboard_definition
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief usb keyboard option code
|
||||
*/
|
||||
#define KEYBOARD_LEFT_CTRL 0x01
|
||||
#define KEYBOARD_LEFT_SHIFT 0x02
|
||||
#define KEYBOARD_LEFT_ALT 0x04
|
||||
#define KEYBOARD_LEFT_GUI 0x08
|
||||
#define KEYBOARD_RIGHT_CTRL 0x10
|
||||
#define KEYBOARD_RIGHT_SHIFT 0x20
|
||||
#define KEYBOARD_RIGHT_ALT 0x40
|
||||
#define KEYBOARD_RIGHT_GUI 0x80
|
||||
|
||||
#define KEYBOARD_MAX_NB_PRESSED 6
|
||||
|
||||
#ifndef AZERTY_KEYBOARD
|
||||
#define QWERTY_KEYBOARD
|
||||
#endif
|
||||
|
||||
void usbh_hid_keyboard_decode(uint8_t *data);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file usbh_hid_mouse.c
|
||||
* @brief usb host hid mouse type
|
||||
**************************************************************************
|
||||
* Copyright notice & Disclaimer
|
||||
*
|
||||
* The software Board Support Package (BSP) that is made available to
|
||||
* download from Artery official website is the copyrighted work of Artery.
|
||||
* Artery authorizes customers to use, copy, and distribute the BSP
|
||||
* software and its related documentation for the purpose of design and
|
||||
* development in conjunction with Artery microcontrollers. Use of the
|
||||
* software is governed by this copyright notice and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
|
||||
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
|
||||
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
|
||||
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
|
||||
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
#include "usbh_hid_mouse.h"
|
||||
|
||||
/** @addtogroup AT32F435_437_middlewares_usbh_class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBH_hid_class_mouse
|
||||
* @brief usb host class hid mouse
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBH_hid_class_mouse_private_functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
usb_hid_mouse_type hid_mouse;
|
||||
uint16_t x_pos = 0, y_pos = 0;
|
||||
|
||||
/**
|
||||
* @brief usb host hid position
|
||||
* @param x: x position
|
||||
* @param y: y position
|
||||
* @retval none
|
||||
*/
|
||||
void usbh_hid_mouse_position(uint8_t x, uint8_t y)
|
||||
{
|
||||
if((x != 0) || (y != 0))
|
||||
{
|
||||
x_pos += x / 2;
|
||||
y_pos += y / 2;
|
||||
|
||||
if(x_pos > MOUSE_WINDOW_WIDTH - 12)
|
||||
{
|
||||
x_pos = MOUSE_WINDOW_WIDTH - 12;
|
||||
}
|
||||
if(y_pos > MOUSE_WINDOW_HEIGHT - 12)
|
||||
{
|
||||
y_pos = MOUSE_WINDOW_HEIGHT - 12;
|
||||
}
|
||||
|
||||
if(x_pos < 2)
|
||||
{
|
||||
x_pos = 2;
|
||||
}
|
||||
if(y_pos < 2)
|
||||
{
|
||||
y_pos = 2;
|
||||
}
|
||||
USBH_DEBUG("Moving Mouse");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host hid button press
|
||||
* @param button: button id
|
||||
* @retval none
|
||||
*/
|
||||
void usbh_hid_mouse_button_press(uint8_t button)
|
||||
{
|
||||
switch(button)
|
||||
{
|
||||
case MOUSE_BUTTON_LEFT:
|
||||
/* left button */
|
||||
USBH_DEBUG("Left Button Pressed ");
|
||||
break;
|
||||
case MOUSE_BUTTON_RIGHT:
|
||||
USBH_DEBUG("Right Button Pressed ");
|
||||
/* left button */
|
||||
break;
|
||||
case MOUSE_BUTTON_MIDDLE:
|
||||
USBH_DEBUG("Middle Button Pressed ");
|
||||
/* middle button */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host hid button release
|
||||
* @param button: button id
|
||||
* @retval none
|
||||
*/
|
||||
void usbh_hid_mouse_button_release(uint8_t button)
|
||||
{
|
||||
switch(button)
|
||||
{
|
||||
case MOUSE_BUTTON_LEFT:
|
||||
/* left button */
|
||||
USBH_DEBUG("Left Button Released ");
|
||||
break;
|
||||
case MOUSE_BUTTON_RIGHT:
|
||||
/* left button */
|
||||
USBH_DEBUG("Right Button Released ");
|
||||
break;
|
||||
case MOUSE_BUTTON_MIDDLE:
|
||||
/* middle button */
|
||||
USBH_DEBUG("Middle Button Released ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host hid mouse process
|
||||
* @param mouse: mouse data type
|
||||
* @retval none
|
||||
*/
|
||||
void usbh_hid_mouse_process(usb_hid_mouse_type *mouse)
|
||||
{
|
||||
uint8_t idx = 1;
|
||||
static uint8_t b_state[3] = {0};
|
||||
if((mouse->x != 0) && (mouse->y != 0))
|
||||
{
|
||||
usbh_hid_mouse_position(mouse->x, mouse->y);
|
||||
}
|
||||
|
||||
for(idx = 0; idx < 3; idx ++)
|
||||
{
|
||||
if(mouse->button & 1 << idx)
|
||||
{
|
||||
if(b_state[idx] == 0)
|
||||
{
|
||||
usbh_hid_mouse_button_press(idx);
|
||||
b_state[idx] = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(b_state[idx] == 1)
|
||||
{
|
||||
usbh_hid_mouse_button_release(idx);
|
||||
b_state[idx] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host hid mouse decode
|
||||
* @param mouse_data: mouse data
|
||||
* @retval none
|
||||
*/
|
||||
void usbh_hid_mouse_decode(uint8_t *mouse_data)
|
||||
{
|
||||
hid_mouse.button = mouse_data[0];
|
||||
hid_mouse.x = mouse_data[1];
|
||||
hid_mouse.y = mouse_data[2];
|
||||
hid_mouse.z = mouse_data[3];
|
||||
|
||||
usbh_hid_mouse_process(&hid_mouse);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file usbh_hid_mouse.h
|
||||
* @brief usb host hid mouse header file
|
||||
**************************************************************************
|
||||
* Copyright notice & Disclaimer
|
||||
*
|
||||
* The software Board Support Package (BSP) that is made available to
|
||||
* download from Artery official website is the copyrighted work of Artery.
|
||||
* Artery authorizes customers to use, copy, and distribute the BSP
|
||||
* software and its related documentation for the purpose of design and
|
||||
* development in conjunction with Artery microcontrollers. Use of the
|
||||
* software is governed by this copyright notice and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
|
||||
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
|
||||
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
|
||||
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
|
||||
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBH_HID_MOUSE_H
|
||||
#define __USBH_HID_MOUSE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "usb_conf.h"
|
||||
|
||||
/** @addtogroup AT32F435_437_middlewares_usbh_class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup USBH_hid_class_mouse
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBH_hid_class_mouse_definition
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief usb hid mouse x y
|
||||
*/
|
||||
#define MOUSE_WINDOW_X 100
|
||||
#define MOUSE_WINDOW_Y 220
|
||||
#define MOUSE_WINDOW_HEIGHT 90
|
||||
#define MOUSE_WINDOW_WIDTH 128
|
||||
|
||||
/**
|
||||
* @brief usb hid mouse button
|
||||
*/
|
||||
#define MOUSE_BUTTON_LEFT 0x00
|
||||
#define MOUSE_BUTTON_RIGHT 0x01
|
||||
#define MOUSE_BUTTON_MIDDLE 0x02
|
||||
|
||||
/**
|
||||
* @brief usb hid mouse type
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t button;
|
||||
uint8_t x;
|
||||
uint8_t y;
|
||||
uint8_t z;
|
||||
}usb_hid_mouse_type;
|
||||
|
||||
void usbh_hid_mouse_decode(uint8_t *mouse_data);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,669 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file usbh_msc_bot_scsi.c
|
||||
* @brief usb host msc bulk-only transfer and scsi type
|
||||
**************************************************************************
|
||||
* Copyright notice & Disclaimer
|
||||
*
|
||||
* The software Board Support Package (BSP) that is made available to
|
||||
* download from Artery official website is the copyrighted work of Artery.
|
||||
* Artery authorizes customers to use, copy, and distribute the BSP
|
||||
* software and its related documentation for the purpose of design and
|
||||
* development in conjunction with Artery microcontrollers. Use of the
|
||||
* software is governed by this copyright notice and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
|
||||
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
|
||||
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
|
||||
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
|
||||
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
#include "usbh_msc_bot_scsi.h"
|
||||
#include "usbh_msc_class.h"
|
||||
#include "usb_conf.h"
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_ctrl.h"
|
||||
|
||||
/** @addtogroup AT32F435_437_middlewares_usbh_class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBH_msc_bot_scsi_class
|
||||
* @brief usb host class msc bot scsi
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBH_msc_bot_scsi_class_private_functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
static usb_sts_type usbh_bot_cbw(msc_bot_cbw_type *cbw, uint32_t data_length, uint8_t cmd_len, uint8_t flag);
|
||||
static usb_sts_type usbh_cmd_inquiry(msc_bot_trans_type *bot_trans, uint8_t *cmd, uint8_t lun);
|
||||
static usb_sts_type usbh_cmd_capacity10(msc_bot_trans_type *bot_trans, uint8_t *cmd, uint8_t lun);
|
||||
static usb_sts_type usbh_cmd_test_unit_ready(msc_bot_trans_type *bot_trans, uint8_t *cmd, uint8_t lun);
|
||||
static usb_sts_type usbh_cmd_requset_sense(msc_bot_trans_type *bot_trans, uint8_t *cmd, uint8_t lun);
|
||||
static usb_sts_type usbh_cmd_write(msc_bot_trans_type *bot_trans, uint8_t *cmd, uint8_t lun,
|
||||
uint32_t data_len, uint32_t address, uint8_t *buffer);
|
||||
static usb_sts_type usbh_cmd_read(msc_bot_trans_type *bot_trans, uint8_t *cmd, uint8_t lun,
|
||||
uint32_t data_len, uint32_t address, uint8_t *buffer);
|
||||
|
||||
/**
|
||||
* @brief usb host bulk-only cbw
|
||||
* @param cbw: to the structure of msc_bot_cbw_type
|
||||
* @param data_length: data length
|
||||
* @param cmd_len: command len
|
||||
* @param flag: cbw flag
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type usbh_bot_cbw(msc_bot_cbw_type *cbw, uint32_t data_length, uint8_t cmd_len, uint8_t flag)
|
||||
{
|
||||
uint8_t i_index;
|
||||
cbw->dCBWSignature = MSC_CBW_SIGNATURE;
|
||||
cbw->dCBWTag = MSC_CBW_TAG;
|
||||
cbw->dCBWDataTransferLength = data_length;
|
||||
cbw->bmCBWFlags = flag;
|
||||
cbw->bCBWCBLength = cmd_len;
|
||||
for(i_index = 0; i_index < MSC_CBW_CB_LEN; i_index ++)
|
||||
{
|
||||
cbw->CBWCB[i_index] = 0x00;
|
||||
}
|
||||
return USB_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc command inquiry
|
||||
* @param bot_trans: to the structure of msc_bot_trans_type
|
||||
* @param cmd: command buffer
|
||||
* @param lun: logical unit number
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type usbh_cmd_inquiry(msc_bot_trans_type *bot_trans, uint8_t *cmd, uint8_t lun)
|
||||
{
|
||||
usbh_msc_type *msc_struct = (usbh_msc_type *)bot_trans->msc_struct;
|
||||
cmd[0] = MSC_OPCODE_INQUIRY;
|
||||
cmd[1] = lun << 5;
|
||||
cmd[4] = MSC_INQUIRY_DATA_LEN;
|
||||
|
||||
bot_trans->data = (uint8_t *)&msc_struct->l_unit_n[lun].inquiry;
|
||||
return USB_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc command capacity10
|
||||
* @param bot_trans: to the structure of msc_bot_trans_type
|
||||
* @param cmd: command buffer
|
||||
* @param lun: logical unit number
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type usbh_cmd_capacity10(msc_bot_trans_type *bot_trans, uint8_t *cmd, uint8_t lun)
|
||||
{
|
||||
usbh_msc_type *msc_struct = (usbh_msc_type *)bot_trans->msc_struct;
|
||||
cmd[0] = MSC_OPCODE_CAPACITY;
|
||||
cmd[1] = lun << 5;
|
||||
|
||||
msc_struct->bot_trans.data = (uint8_t *)bot_trans->buffer;
|
||||
return USB_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc command test unit ready
|
||||
* @param bot_trans: to the structure of msc_bot_trans_type
|
||||
* @param cmd: command buffer
|
||||
* @param lun: logical unit number
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type usbh_cmd_test_unit_ready(msc_bot_trans_type *bot_trans, uint8_t *cmd, uint8_t lun)
|
||||
{
|
||||
cmd[0] = MSC_OPCODE_TEST_UNIT_READY;
|
||||
cmd[1] = lun << 5;
|
||||
|
||||
return USB_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc command request sense
|
||||
* @param bot_trans: to the structure of msc_bot_trans_type
|
||||
* @param cmd: command buffer
|
||||
* @param lun: logical unit number
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type usbh_cmd_requset_sense(msc_bot_trans_type *bot_trans, uint8_t *cmd, uint8_t lun)
|
||||
{
|
||||
cmd[0] = MSC_OPCODE_REQUEST_SENSE;
|
||||
cmd[1] = lun << 5;
|
||||
cmd[4] = MSC_REQUEST_SENSE_DATA_LEN;
|
||||
|
||||
bot_trans->data = bot_trans->buffer;
|
||||
return USB_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc command write
|
||||
* @param bot_trans: to the structure of msc_bot_trans_type
|
||||
* @param cmd: command buffer
|
||||
* @param lun: logical unit number
|
||||
* @param data_len: transfer data length
|
||||
* @param address: logical block address
|
||||
* @param buffer: transfer data buffer
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type usbh_cmd_write(msc_bot_trans_type *bot_trans, uint8_t *cmd, uint8_t lun,
|
||||
uint32_t data_len, uint32_t address, uint8_t *buffer)
|
||||
{
|
||||
cmd[0] = MSC_OPCODE_WRITE10;
|
||||
cmd[1] = lun << 5;
|
||||
cmd[2] = (uint8_t)(address >> 24);
|
||||
cmd[3] = (uint8_t)(address >> 16);
|
||||
cmd[4] = (uint8_t)(address >> 8);
|
||||
cmd[5] = (uint8_t)(address & 0xFF);
|
||||
|
||||
cmd[7] = data_len >> 8;
|
||||
cmd[8] = data_len;
|
||||
|
||||
bot_trans->data = buffer;
|
||||
return USB_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc command read
|
||||
* @param bot_trans: to the structure of msc_bot_trans_type
|
||||
* @param cmd: command buffer
|
||||
* @param lun: logical unit number
|
||||
* @param data_len: transfer data length
|
||||
* @param address: logical block address
|
||||
* @param buffer: transfer data buffer
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type usbh_cmd_read(msc_bot_trans_type *bot_trans, uint8_t *cmd, uint8_t lun,
|
||||
uint32_t data_len, uint32_t address, uint8_t *buffer)
|
||||
{
|
||||
cmd[0] = MSC_OPCODE_READ10;
|
||||
cmd[1] = lun << 5;
|
||||
cmd[2] = (uint8_t)(address >> 24);
|
||||
cmd[3] = (uint8_t)(address >> 16);
|
||||
cmd[4] = (uint8_t)(address >> 8);
|
||||
cmd[5] = (uint8_t)(address & 0xFF);
|
||||
|
||||
cmd[7] = data_len >> 8;
|
||||
cmd[8] = data_len;
|
||||
|
||||
bot_trans->data = buffer;
|
||||
return USB_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host csw check
|
||||
* @param cbw: to the structure of msc_bot_cbw_type
|
||||
* @param csw: to the structure of msc_bot_csw_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type usbh_check_csw(void *uhost, msc_bot_cbw_type *cbw, msc_bot_csw_type *csw)
|
||||
{
|
||||
usb_sts_type status = USB_FAIL;
|
||||
if(csw->dCBWSignature == MSC_CSW_SIGNATURE)
|
||||
{
|
||||
if(csw->dCBWTag == cbw->dCBWTag)
|
||||
{
|
||||
if(csw->bCSWStatus == 0)
|
||||
{
|
||||
status = USB_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc bulk-only request
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param bot_trans: to the structure of msc_bot_trans_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type usb_bot_request(void *uhost, msc_bot_trans_type *bot_trans)
|
||||
{
|
||||
usb_sts_type status = USB_WAIT;
|
||||
urb_sts_type urb_status;
|
||||
usb_sts_type clr_status;
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_msc_type *msc_struct = (usbh_msc_type *)bot_trans->msc_struct;
|
||||
switch(bot_trans->bot_state)
|
||||
{
|
||||
case BOT_STATE_SEND_CBW:
|
||||
usbh_bulk_send(puhost, msc_struct->chout, (uint8_t *)(&bot_trans->cbw), MSC_CBW_LEN);
|
||||
bot_trans->bot_state = BOT_STATE_SEND_CBW_WAIT;
|
||||
break;
|
||||
|
||||
case BOT_STATE_SEND_CBW_WAIT:
|
||||
urb_status = usbh_get_urb_status(puhost, msc_struct->chout);
|
||||
if(urb_status == URB_DONE)
|
||||
{
|
||||
if(bot_trans->cbw.dCBWDataTransferLength != 0)
|
||||
{
|
||||
if(bot_trans->cbw.bmCBWFlags == MSC_CBW_FLAG_IN)
|
||||
{
|
||||
bot_trans->bot_state = BOT_STATE_DATA_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
bot_trans->bot_state = BOT_STATE_DATA_OUT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bot_trans->bot_state = BOT_STATE_RECV_CSW;
|
||||
}
|
||||
}
|
||||
else if(urb_status == URB_NOTREADY)
|
||||
{
|
||||
bot_trans->bot_state = BOT_STATE_SEND_CBW;
|
||||
}
|
||||
else if(urb_status == URB_STALL)
|
||||
{
|
||||
bot_trans->bot_state = BOT_STATE_ERROR_OUT;
|
||||
}
|
||||
break;
|
||||
|
||||
case BOT_STATE_DATA_IN:
|
||||
usbh_bulk_recv(puhost, msc_struct->chin, bot_trans->data,
|
||||
msc_struct->in_maxpacket);
|
||||
bot_trans->bot_state = BOT_STATE_DATA_IN_WAIT;
|
||||
break;
|
||||
|
||||
case BOT_STATE_DATA_IN_WAIT:
|
||||
urb_status = usbh_get_urb_status(puhost, msc_struct->chin);
|
||||
if(urb_status == URB_DONE)
|
||||
{
|
||||
if(bot_trans->cbw.dCBWDataTransferLength > msc_struct->in_maxpacket)
|
||||
{
|
||||
bot_trans->data += msc_struct->in_maxpacket;
|
||||
bot_trans->cbw.dCBWDataTransferLength -= msc_struct->in_maxpacket;
|
||||
}
|
||||
else
|
||||
{
|
||||
bot_trans->cbw.dCBWDataTransferLength = 0;
|
||||
}
|
||||
if(bot_trans->cbw.dCBWDataTransferLength > 0)
|
||||
{
|
||||
usbh_bulk_recv(puhost, msc_struct->chin, bot_trans->data,
|
||||
msc_struct->in_maxpacket);
|
||||
}
|
||||
else
|
||||
{
|
||||
bot_trans->bot_state = BOT_STATE_RECV_CSW;
|
||||
}
|
||||
}
|
||||
else if(urb_status == URB_STALL)
|
||||
{
|
||||
bot_trans->bot_state = BOT_STATE_ERROR_IN;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case BOT_STATE_DATA_OUT:
|
||||
usbh_bulk_send(puhost, msc_struct->chout, bot_trans->data, msc_struct->out_maxpacket);
|
||||
bot_trans->bot_state = BOT_STATE_DATA_OUT_WAIT;
|
||||
break;
|
||||
|
||||
case BOT_STATE_DATA_OUT_WAIT:
|
||||
urb_status = usbh_get_urb_status(puhost, msc_struct->chout);
|
||||
if(urb_status == URB_DONE)
|
||||
{
|
||||
if(bot_trans->cbw.dCBWDataTransferLength > msc_struct->out_maxpacket)
|
||||
{
|
||||
bot_trans->data += msc_struct->out_maxpacket;
|
||||
bot_trans->cbw.dCBWDataTransferLength -= msc_struct->out_maxpacket;
|
||||
}
|
||||
else
|
||||
{
|
||||
bot_trans->cbw.dCBWDataTransferLength = 0;
|
||||
}
|
||||
if(bot_trans->cbw.dCBWDataTransferLength > 0)
|
||||
{
|
||||
usbh_bulk_send(puhost, msc_struct->chout, bot_trans->data, msc_struct->out_maxpacket);
|
||||
}
|
||||
else
|
||||
{
|
||||
bot_trans->bot_state = BOT_STATE_RECV_CSW;
|
||||
}
|
||||
}
|
||||
else if(urb_status == URB_NOTREADY)
|
||||
{
|
||||
bot_trans->bot_state = BOT_STATE_DATA_OUT;
|
||||
}
|
||||
else if(urb_status == URB_STALL)
|
||||
{
|
||||
bot_trans->bot_state = BOT_STATE_ERROR_OUT;
|
||||
}
|
||||
break;
|
||||
|
||||
case BOT_STATE_RECV_CSW:
|
||||
usbh_bulk_recv(puhost, msc_struct->chin, (uint8_t *)&bot_trans->csw,
|
||||
MSC_CSW_LEN);
|
||||
bot_trans->bot_state = BOT_STATE_RECV_CSW_WAIT;
|
||||
|
||||
break;
|
||||
case BOT_STATE_RECV_CSW_WAIT:
|
||||
urb_status = usbh_get_urb_status(puhost, msc_struct->chin);
|
||||
if(urb_status == URB_DONE)
|
||||
{
|
||||
bot_trans->bot_state = BOT_STATE_SEND_CBW;
|
||||
bot_trans->cmd_state = CMD_STATE_SEND;
|
||||
status = usbh_check_csw(uhost, &bot_trans->cbw, &bot_trans->csw);
|
||||
}
|
||||
else if(urb_status == URB_STALL)
|
||||
{
|
||||
bot_trans->bot_state = BOT_STATE_ERROR_IN;
|
||||
}
|
||||
|
||||
break;
|
||||
case BOT_STATE_ERROR_IN:
|
||||
clr_status = usbh_clear_ept_feature(puhost, msc_struct->eptin, msc_struct->chin);
|
||||
if(clr_status == USB_OK)
|
||||
{
|
||||
bot_trans->bot_state = BOT_STATE_RECV_CSW;
|
||||
usbh_set_toggle(puhost, msc_struct->chin, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
case BOT_STATE_ERROR_OUT:
|
||||
clr_status = usbh_clear_ept_feature(puhost, msc_struct->eptout, msc_struct->chout);
|
||||
if(clr_status == USB_OK)
|
||||
{
|
||||
usbh_set_toggle(puhost, msc_struct->chout, 1 - puhost->hch[msc_struct->chout].toggle_out);
|
||||
usbh_set_toggle(puhost, msc_struct->chin, 0);
|
||||
bot_trans->bot_state = BOT_STATE_ERROR_IN;
|
||||
}
|
||||
break;
|
||||
case BOT_STATE_COMPLETE:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc bulk-only get inquiry request
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param bot_trans: to the structure of msc_bot_trans_type
|
||||
* @param lun: logical unit number
|
||||
* @param inquiry: to the structure of msc_scsi_data_inquiry
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type usbh_msc_bot_scsi_get_inquiry(void *uhost, msc_bot_trans_type *bot_trans,
|
||||
uint8_t lun, msc_scsi_data_inquiry *inquiry)
|
||||
{
|
||||
usb_sts_type status = USB_WAIT;
|
||||
switch(bot_trans->cmd_state)
|
||||
{
|
||||
case CMD_STATE_SEND:
|
||||
usbh_bot_cbw(&bot_trans->cbw, MSC_INQUIRY_DATA_LEN, MSC_INQUIRY_CMD_LEN, MSC_CBW_FLAG_IN);
|
||||
bot_trans->cbw.bCBWLUN = lun;
|
||||
usbh_cmd_inquiry(bot_trans, bot_trans->cbw.CBWCB, lun);
|
||||
bot_trans->cmd_state = CMD_STATE_WAIT;
|
||||
bot_trans->bot_state = BOT_STATE_SEND_CBW;
|
||||
break;
|
||||
|
||||
case CMD_STATE_WAIT:
|
||||
status = usb_bot_request(uhost, bot_trans);
|
||||
if(status == USB_OK)
|
||||
{
|
||||
bot_trans->cmd_state = CMD_STATE_SEND;
|
||||
}
|
||||
if(status == USB_FAIL)
|
||||
{
|
||||
bot_trans->cmd_state = CMD_STATE_SEND;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc bulk-only capacity request
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param bot_trans: to the structure of msc_bot_trans_type
|
||||
* @param lun: logical unit number
|
||||
* @param capacity: to the structure of msc_scsi_data_capacity
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type usbh_msc_bot_scsi_capacity(void *uhost, msc_bot_trans_type *bot_trans,
|
||||
uint8_t lun, msc_scsi_data_capacity *capacity)
|
||||
{
|
||||
usb_sts_type status = USB_WAIT;
|
||||
switch(bot_trans->cmd_state)
|
||||
{
|
||||
case CMD_STATE_SEND:
|
||||
usbh_bot_cbw(&bot_trans->cbw, MSC_CAPACITY10_DATA_LEN, MSC_CAPACITY10_CMD_LEN, MSC_CBW_FLAG_IN);
|
||||
bot_trans->cbw.bCBWLUN = lun;
|
||||
usbh_cmd_capacity10(bot_trans, bot_trans->cbw.CBWCB, lun);
|
||||
bot_trans->cmd_state = CMD_STATE_WAIT;
|
||||
bot_trans->bot_state = BOT_STATE_SEND_CBW;
|
||||
break;
|
||||
|
||||
case CMD_STATE_WAIT:
|
||||
status = usb_bot_request(uhost, bot_trans);
|
||||
if(status == USB_OK)
|
||||
{
|
||||
capacity->blk_nbr = bot_trans->buffer[3] | bot_trans->buffer[2] << 8 |
|
||||
bot_trans->buffer[1] << 16 | bot_trans->buffer[0] << 24;
|
||||
capacity->blk_size = bot_trans->buffer[7] | bot_trans->buffer[6] << 8 ;
|
||||
bot_trans->cmd_state = CMD_STATE_SEND;
|
||||
}
|
||||
if(status == USB_FAIL)
|
||||
{
|
||||
bot_trans->cmd_state = CMD_STATE_SEND;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc bulk-only tet unit ready request
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param bot_trans: to the structure of msc_bot_trans_type
|
||||
* @param lun: logical unit number
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type usbh_msc_bot_scsi_test_unit_ready(void *uhost, msc_bot_trans_type *bot_trans,
|
||||
uint8_t lun)
|
||||
{
|
||||
usb_sts_type status = USB_WAIT;
|
||||
switch(bot_trans->cmd_state)
|
||||
{
|
||||
case CMD_STATE_SEND:
|
||||
usbh_bot_cbw(&bot_trans->cbw, MSC_TEST_UNIT_READY_DATA_LEN,
|
||||
MSC_TEST_UNIT_READY_CMD_LEN, MSC_CBW_FLAG_OUT);
|
||||
bot_trans->cbw.bCBWLUN = lun;
|
||||
usbh_cmd_test_unit_ready(bot_trans, bot_trans->cbw.CBWCB, lun);
|
||||
bot_trans->cmd_state = CMD_STATE_WAIT;
|
||||
bot_trans->bot_state = BOT_STATE_SEND_CBW;
|
||||
break;
|
||||
|
||||
case CMD_STATE_WAIT:
|
||||
status = usb_bot_request(uhost, bot_trans);
|
||||
if(status == USB_OK)
|
||||
{
|
||||
bot_trans->cmd_state = CMD_STATE_SEND;
|
||||
}
|
||||
if(status == USB_FAIL)
|
||||
{
|
||||
bot_trans->cmd_state = CMD_STATE_SEND;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc bulk-only request sense request
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param bot_trans: to the structure of msc_bot_trans_type
|
||||
* @param lun: logical unit number
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type usbh_msc_bot_scsi_request_sense(void *uhost, msc_bot_trans_type *bot_trans,
|
||||
uint8_t lun)
|
||||
{
|
||||
usb_sts_type status = USB_WAIT;
|
||||
switch(bot_trans->cmd_state)
|
||||
{
|
||||
case CMD_STATE_SEND:
|
||||
usbh_bot_cbw(&bot_trans->cbw, MSC_REQUEST_SENSE_DATA_LEN,
|
||||
MSC_REQUEST_SENSE_CMD_LEN, MSC_CBW_FLAG_IN);
|
||||
bot_trans->cbw.bCBWLUN = lun;
|
||||
usbh_cmd_requset_sense(bot_trans, bot_trans->cbw.CBWCB, lun);
|
||||
bot_trans->cmd_state = CMD_STATE_WAIT;
|
||||
bot_trans->bot_state = BOT_STATE_SEND_CBW;
|
||||
break;
|
||||
|
||||
case CMD_STATE_WAIT:
|
||||
status = usb_bot_request(uhost, bot_trans);
|
||||
if(status == USB_OK)
|
||||
{
|
||||
bot_trans->cmd_state = CMD_STATE_SEND;
|
||||
}
|
||||
if(status == USB_FAIL)
|
||||
{
|
||||
bot_trans->cmd_state = CMD_STATE_SEND;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc bulk-only write request
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param bot_trans: to the structure of msc_bot_trans_type
|
||||
* @param address: logical block address
|
||||
* @param write_data: write data buffer
|
||||
* @param write_len: write data length
|
||||
* @param lun: logical unit number
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type usbh_msc_bot_scsi_write(void *uhost, msc_bot_trans_type *bot_trans,
|
||||
uint32_t address, uint8_t *write_data,
|
||||
uint32_t write_len, uint8_t lun)
|
||||
{
|
||||
usb_sts_type status = USB_WAIT;
|
||||
switch(bot_trans->cmd_state)
|
||||
{
|
||||
case CMD_STATE_SEND:
|
||||
usbh_bot_cbw(&bot_trans->cbw, write_len * 512,
|
||||
MSC_WRITE_CMD_LEN, MSC_CBW_FLAG_OUT);
|
||||
bot_trans->cbw.bCBWLUN = lun;
|
||||
usbh_cmd_write(bot_trans, bot_trans->cbw.CBWCB, lun, write_len, address, write_data);
|
||||
bot_trans->cmd_state = CMD_STATE_WAIT;
|
||||
bot_trans->bot_state = BOT_STATE_SEND_CBW;
|
||||
break;
|
||||
|
||||
case CMD_STATE_WAIT:
|
||||
status = usb_bot_request(uhost, bot_trans);
|
||||
if(status == USB_OK)
|
||||
{
|
||||
bot_trans->cmd_state = CMD_STATE_SEND;
|
||||
}
|
||||
if(status == USB_FAIL)
|
||||
{
|
||||
bot_trans->cmd_state = CMD_STATE_SEND;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc bulk-only read request
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param bot_trans: to the structure of msc_bot_trans_type
|
||||
* @param address: logical block address
|
||||
* @param read_data: read data buffer
|
||||
* @param read_len: read data length
|
||||
* @param lun: logical unit number
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type usbh_msc_bot_scsi_read(void *uhost, msc_bot_trans_type *bot_trans,
|
||||
uint32_t address, uint8_t *read_data,
|
||||
uint32_t read_len, uint8_t lun)
|
||||
{
|
||||
usb_sts_type status = USB_WAIT;
|
||||
switch(bot_trans->cmd_state)
|
||||
{
|
||||
case CMD_STATE_SEND:
|
||||
usbh_bot_cbw(&bot_trans->cbw, read_len * 512,
|
||||
MSC_READ_CMD_LEN, MSC_CBW_FLAG_IN);
|
||||
bot_trans->cbw.bCBWLUN = lun;
|
||||
usbh_cmd_read(bot_trans, bot_trans->cbw.CBWCB, lun, read_len, address, read_data);
|
||||
bot_trans->cmd_state = CMD_STATE_WAIT;
|
||||
bot_trans->bot_state = BOT_STATE_SEND_CBW;
|
||||
break;
|
||||
|
||||
case CMD_STATE_WAIT:
|
||||
status = usb_bot_request(uhost, bot_trans);
|
||||
if(status == USB_OK)
|
||||
{
|
||||
bot_trans->cmd_state = CMD_STATE_SEND;
|
||||
}
|
||||
if(status == USB_FAIL)
|
||||
{
|
||||
bot_trans->cmd_state = CMD_STATE_SEND;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc init
|
||||
* @param msc_struct: to the structure of usbh_msc_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type msc_bot_scsi_init(usbh_msc_type *msc_struct)
|
||||
{
|
||||
msc_struct->state = USBH_MSC_INIT;
|
||||
msc_struct->ctrl_state = USBH_MSC_STATE_IDLE;
|
||||
msc_struct->error = MSC_OK;
|
||||
msc_struct->cur_lun = 0;
|
||||
msc_struct->max_lun = 0;
|
||||
msc_struct->use_lun = 0;
|
||||
msc_struct->bot_trans.msc_struct = &usbh_msc;
|
||||
msc_struct->bot_trans.cmd_state = CMD_STATE_SEND;
|
||||
msc_struct->bot_trans.bot_state = BOT_STATE_SEND_CBW;
|
||||
return USB_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file usbh_msc_bot_scsi.h
|
||||
* @brief usb host msc bulk-only transfer and scsi header file
|
||||
**************************************************************************
|
||||
* Copyright notice & Disclaimer
|
||||
*
|
||||
* The software Board Support Package (BSP) that is made available to
|
||||
* download from Artery official website is the copyrighted work of Artery.
|
||||
* Artery authorizes customers to use, copy, and distribute the BSP
|
||||
* software and its related documentation for the purpose of design and
|
||||
* development in conjunction with Artery microcontrollers. Use of the
|
||||
* software is governed by this copyright notice and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
|
||||
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
|
||||
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
|
||||
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
|
||||
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBH_MSC_BOT_SCSI_H
|
||||
#define __USBH_MSC_BOT_SCSI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "usbh_core.h"
|
||||
#include "usb_conf.h"
|
||||
|
||||
/** @addtogroup AT32F435_437_middlewares_usbh_class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup USBH_msc_bot_scsi_class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBH_msc_bot_scsi_class_definition
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define MSC_CBW_SIGNATURE 0x43425355
|
||||
#define MSC_CSW_SIGNATURE 0x53425355
|
||||
#define MSC_CBW_TAG 0x50607080
|
||||
#define MSC_CBW_FLAG_IN 0x80
|
||||
#define MSC_CBW_FLAG_OUT 0x00
|
||||
|
||||
#define MSC_CBW_LEN 31
|
||||
#define MSC_CSW_LEN 13
|
||||
#define MSC_CBW_CB_LEN 16
|
||||
#define MSC_TEST_UNIT_READY_CMD_LEN 12
|
||||
#define MSC_TEST_UNIT_READY_DATA_LEN 0
|
||||
#define MSC_INQUIRY_CMD_LEN 12
|
||||
#define MSC_INQUIRY_DATA_LEN 36
|
||||
#define MSC_CAPACITY10_CMD_LEN 12
|
||||
#define MSC_CAPACITY10_DATA_LEN 8
|
||||
#define MSC_REQUEST_SENSE_CMD_LEN 12
|
||||
#define MSC_REQUEST_SENSE_DATA_LEN 18
|
||||
#define MSC_WRITE_CMD_LEN 12
|
||||
#define MSC_READ_CMD_LEN 10
|
||||
|
||||
#define MSC_OPCODE_INQUIRY 0x12
|
||||
#define MSC_OPCODE_CAPACITY 0x25
|
||||
#define MSC_OPCODE_TEST_UNIT_READY 0x00
|
||||
#define MSC_OPCODE_REQUEST_SENSE 0x03
|
||||
#define MSC_OPCODE_WRITE10 0x2A
|
||||
#define MSC_OPCODE_READ10 0x28
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BOT_STATE_IDLE,
|
||||
BOT_STATE_SEND_CBW,
|
||||
BOT_STATE_SEND_CBW_WAIT,
|
||||
BOT_STATE_DATA_IN,
|
||||
BOT_STATE_DATA_IN_WAIT,
|
||||
BOT_STATE_DATA_OUT,
|
||||
BOT_STATE_DATA_OUT_WAIT,
|
||||
BOT_STATE_RECV_CSW,
|
||||
BOT_STATE_RECV_CSW_WAIT,
|
||||
BOT_STATE_ERROR_IN,
|
||||
BOT_STATE_ERROR_OUT,
|
||||
BOT_STATE_COMPLETE
|
||||
}msc_bot_state_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CMD_STATE_SEND,
|
||||
CMD_STATE_WAIT,
|
||||
}msc_cmd_state_type;
|
||||
|
||||
/**
|
||||
* @brief usb msc process state
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
USBH_MSC_INIT,
|
||||
USBH_MSC_INQUIRY,
|
||||
USBH_MSC_TEST_UNIT_READY,
|
||||
USBH_MSC_READ_CAPACITY10,
|
||||
USBH_MSC_REQUEST_SENSE,
|
||||
USBH_MSC_READ10,
|
||||
USBH_MSC_WRITE,
|
||||
USBH_MSC_BUSY,
|
||||
USBH_MSC_ERROR,
|
||||
USBH_MSC_IDLE
|
||||
}msc_state_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MSC_OK,
|
||||
MSC_NOT_READY,
|
||||
MSC_ERROR
|
||||
}msc_error_type;
|
||||
|
||||
|
||||
/**
|
||||
* @brief usb msc inquiry data type
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t pdev_type;
|
||||
uint8_t rmb;
|
||||
uint8_t version;
|
||||
uint8_t data_format;
|
||||
uint8_t length;
|
||||
uint8_t reserved[3];
|
||||
uint8_t vendor[8];
|
||||
uint8_t product[16];
|
||||
uint8_t revision[4];
|
||||
}msc_scsi_data_inquiry;
|
||||
|
||||
|
||||
/**
|
||||
* @brief usb msc capacity data type
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t blk_nbr;
|
||||
uint32_t blk_size;
|
||||
}msc_scsi_data_capacity;
|
||||
|
||||
/**
|
||||
* @brief usb msc bulk-only command block wrapper type
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t dCBWSignature;
|
||||
uint32_t dCBWTag;
|
||||
uint32_t dCBWDataTransferLength;
|
||||
uint8_t bmCBWFlags;
|
||||
uint8_t bCBWLUN;
|
||||
uint8_t bCBWCBLength;
|
||||
uint8_t CBWCB[MSC_CBW_CB_LEN];
|
||||
}msc_bot_cbw_type;
|
||||
|
||||
/**
|
||||
* @brief usb msc bulk-only command status wrapper type
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t dCBWSignature;
|
||||
uint32_t dCBWTag;
|
||||
uint32_t dCSWDataResidue;
|
||||
uint8_t bCSWStatus;
|
||||
}msc_bot_csw_type;
|
||||
|
||||
/**
|
||||
* @brief usb msc bulk-only transfer control type
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t buffer[32];
|
||||
msc_bot_cbw_type cbw;
|
||||
msc_bot_csw_type csw;
|
||||
msc_cmd_state_type cmd_state;
|
||||
msc_bot_state_type bot_state;
|
||||
uint8_t *data;
|
||||
void *msc_struct;
|
||||
}msc_bot_trans_type;
|
||||
|
||||
/**
|
||||
* @brief usb msc bank type
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
msc_scsi_data_inquiry inquiry;
|
||||
msc_scsi_data_capacity capacity;
|
||||
msc_state_type state;
|
||||
msc_error_type ready;
|
||||
usb_sts_type pre_state;
|
||||
uint8_t change;
|
||||
}usbh_msc_unit_type;
|
||||
|
||||
|
||||
usb_sts_type usb_bot_request(void *uhost, msc_bot_trans_type *bot_trans);
|
||||
|
||||
usb_sts_type usbh_msc_bot_scsi_get_inquiry(void *uhost, msc_bot_trans_type *bot_trans,
|
||||
uint8_t lun, msc_scsi_data_inquiry *inquiry);
|
||||
|
||||
usb_sts_type usbh_msc_bot_scsi_capacity(void *uhost, msc_bot_trans_type *bot_trans,
|
||||
uint8_t lun, msc_scsi_data_capacity *capacity);
|
||||
|
||||
usb_sts_type usbh_msc_bot_scsi_test_unit_ready(void *uhost, msc_bot_trans_type *bot_trans,
|
||||
uint8_t lun);
|
||||
|
||||
usb_sts_type usbh_msc_bot_scsi_request_sense(void *uhost, msc_bot_trans_type *bot_trans,
|
||||
uint8_t lun);
|
||||
|
||||
usb_sts_type usbh_msc_bot_scsi_write(void *uhost, msc_bot_trans_type *bot_trans,
|
||||
uint32_t address, uint8_t *write_data,
|
||||
uint32_t write_len, uint8_t lun);
|
||||
|
||||
usb_sts_type usbh_msc_bot_scsi_read(void *uhost, msc_bot_trans_type *bot_trans,
|
||||
uint32_t address, uint8_t *read_data,
|
||||
uint32_t read_len, uint8_t lun);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,521 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file usbh_msc_class.c
|
||||
* @brief usb host msc class type
|
||||
**************************************************************************
|
||||
* Copyright notice & Disclaimer
|
||||
*
|
||||
* The software Board Support Package (BSP) that is made available to
|
||||
* download from Artery official website is the copyrighted work of Artery.
|
||||
* Artery authorizes customers to use, copy, and distribute the BSP
|
||||
* software and its related documentation for the purpose of design and
|
||||
* development in conjunction with Artery microcontrollers. Use of the
|
||||
* software is governed by this copyright notice and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
|
||||
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
|
||||
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
|
||||
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
|
||||
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
#include "usbh_msc_class.h"
|
||||
#include "usb_conf.h"
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_ctrl.h"
|
||||
|
||||
/** @addtogroup AT32F435_437_middlewares_usbh_class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBH_msc_class
|
||||
* @brief usb host class msc demo
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBH_msc_class_private_functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
static usb_sts_type uhost_init_handler(void *uhost);
|
||||
static usb_sts_type uhost_reset_handler(void *uhost);
|
||||
static usb_sts_type uhost_request_handler(void *uhost);
|
||||
static usb_sts_type uhost_process_handler(void *uhost);
|
||||
|
||||
static usb_sts_type usbh_msc_get_max_lun(void *uhost, uint8_t *lun);
|
||||
static usb_sts_type usbh_msc_clear_feature(void *uhost, uint8_t ept_num);
|
||||
|
||||
|
||||
usbh_msc_type usbh_msc;
|
||||
|
||||
usbh_class_handler_type uhost_msc_class_handler =
|
||||
{
|
||||
uhost_init_handler,
|
||||
uhost_reset_handler,
|
||||
uhost_request_handler,
|
||||
uhost_process_handler,
|
||||
&usbh_msc
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief usb host class init handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type uhost_init_handler(void *uhost)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usb_sts_type status = USB_OK;
|
||||
uint8_t if_x, eptidx = 0;
|
||||
usbh_msc_type *pmsc = &usbh_msc;
|
||||
puhost->class_handler->pdata = &usbh_msc;
|
||||
|
||||
if_x = usbh_find_interface(puhost, USB_CLASS_CODE_MSC, MSC_SUBCLASS_SCSI_TRANS, MSC_PROTOCOL_BBB);
|
||||
if(if_x == 0xFF)
|
||||
{
|
||||
USBH_DEBUG("Unsupport Device!");
|
||||
return USB_NOT_SUPPORT;
|
||||
}
|
||||
pmsc->protocol = puhost->dev.cfg_desc.interface[if_x].interface.bInterfaceProtocol;
|
||||
|
||||
for(eptidx = 0; eptidx < puhost->dev.cfg_desc.interface[if_x].interface.bNumEndpoints; eptidx ++)
|
||||
{
|
||||
if(puhost->dev.cfg_desc.interface[if_x].endpoint[eptidx].bEndpointAddress & 0x80)
|
||||
{
|
||||
pmsc->eptin = puhost->dev.cfg_desc.interface[if_x].endpoint[eptidx].bEndpointAddress;
|
||||
pmsc->in_maxpacket = puhost->dev.cfg_desc.interface[if_x].endpoint[eptidx].wMaxPacketSize;
|
||||
pmsc->in_poll = puhost->dev.cfg_desc.interface[if_x].endpoint[eptidx].bInterval;
|
||||
|
||||
pmsc->chin = usbh_alloc_channel(puhost, pmsc->eptin);
|
||||
/* enable channel */
|
||||
usbh_hc_open(puhost, pmsc->chin, pmsc->eptin,
|
||||
puhost->dev.address, EPT_BULK_TYPE,
|
||||
pmsc->in_maxpacket,
|
||||
puhost->dev.speed);
|
||||
}
|
||||
else
|
||||
{
|
||||
pmsc->eptout = puhost->dev.cfg_desc.interface[if_x].endpoint[eptidx].bEndpointAddress;
|
||||
pmsc->out_maxpacket = puhost->dev.cfg_desc.interface[if_x].endpoint[eptidx].wMaxPacketSize;
|
||||
pmsc->out_poll = puhost->dev.cfg_desc.interface[if_x].endpoint[eptidx].bInterval;
|
||||
|
||||
pmsc->chout = usbh_alloc_channel(puhost, pmsc->eptout);
|
||||
/* enable channel */
|
||||
usbh_hc_open(puhost, pmsc->chout,pmsc->eptout,
|
||||
puhost->dev.address, EPT_BULK_TYPE,
|
||||
pmsc->out_maxpacket,
|
||||
puhost->dev.speed);
|
||||
}
|
||||
}
|
||||
|
||||
msc_bot_scsi_init(pmsc);
|
||||
usbh_set_toggle(puhost, pmsc->chout, 0);
|
||||
usbh_set_toggle(puhost, pmsc->chin, 0);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host class reset handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type uhost_reset_handler(void *uhost)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_msc_type *pmsc = (usbh_msc_type *)puhost->class_handler->pdata;
|
||||
usb_sts_type status = USB_OK;
|
||||
uint8_t i_index = 0;
|
||||
|
||||
if(puhost->class_handler->pdata == NULL)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
for(i_index = 0; i_index < pmsc->max_lun ; i_index ++)
|
||||
{
|
||||
pmsc->l_unit_n[i_index].pre_state = USB_FAIL;
|
||||
pmsc->l_unit_n[i_index].change = 0;
|
||||
pmsc->l_unit_n[i_index].state = USBH_MSC_INIT;
|
||||
pmsc->l_unit_n[i_index].ready = MSC_NOT_READY;
|
||||
}
|
||||
|
||||
if(pmsc->chin != 0 )
|
||||
{
|
||||
usbh_free_channel(puhost, pmsc->chin);
|
||||
usbh_ch_disable(puhost, pmsc->chin);
|
||||
pmsc->chin = 0;
|
||||
}
|
||||
|
||||
if(pmsc->chout != 0 )
|
||||
{
|
||||
usbh_free_channel(puhost, pmsc->chout);
|
||||
usbh_ch_disable(puhost, pmsc->chout);
|
||||
pmsc->chout = 0;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host hid class request handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type uhost_request_handler(void *uhost)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_msc_type *pmsc = (usbh_msc_type *)puhost->class_handler->pdata;
|
||||
usb_sts_type status = USB_WAIT;
|
||||
uint8_t i_index = 0;
|
||||
|
||||
switch(pmsc->ctrl_state)
|
||||
{
|
||||
case USBH_MSC_STATE_IDLE:
|
||||
pmsc->ctrl_state = USBH_MSC_STATE_GET_LUN;
|
||||
break;
|
||||
case USBH_MSC_STATE_GET_LUN:
|
||||
if((status = usbh_msc_get_max_lun(uhost, (uint8_t *)&pmsc->max_lun)) == USB_OK)
|
||||
{
|
||||
pmsc->max_lun = (pmsc->max_lun & 0xFF) > USBH_SUPPORT_MAX_LUN ? USBH_SUPPORT_MAX_LUN:((pmsc->max_lun & 0xFF) + 1);
|
||||
USBH_DEBUG("Support max lun %d", pmsc->max_lun);
|
||||
for(i_index = 0; i_index < pmsc->max_lun ; i_index ++)
|
||||
{
|
||||
pmsc->l_unit_n[i_index].pre_state = USB_FAIL;
|
||||
pmsc->l_unit_n[i_index].change = 0;
|
||||
pmsc->l_unit_n[i_index].state = USBH_MSC_INIT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case USBH_MSC_STATE_ERROR:
|
||||
if((usbh_msc_clear_feature(uhost, 0)) == USB_OK)
|
||||
{
|
||||
pmsc->ctrl_state = USBH_MSC_STATE_GET_LUN;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host class process handler
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type uhost_process_handler(void *uhost)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_msc_type *pmsc = (usbh_msc_type *)puhost->class_handler->pdata;
|
||||
uint64_t msize = 0;
|
||||
usb_sts_type status;
|
||||
switch(pmsc->state)
|
||||
{
|
||||
case USBH_MSC_INIT:
|
||||
if(pmsc->cur_lun < pmsc->max_lun)
|
||||
{
|
||||
switch(pmsc->l_unit_n[pmsc->cur_lun].state)
|
||||
{
|
||||
case USBH_MSC_INIT:
|
||||
pmsc->l_unit_n[pmsc->cur_lun].ready = MSC_NOT_READY;
|
||||
pmsc->l_unit_n[pmsc->cur_lun].state = USBH_MSC_INQUIRY;
|
||||
break;
|
||||
case USBH_MSC_INQUIRY:
|
||||
status = usbh_msc_bot_scsi_get_inquiry(uhost, &pmsc->bot_trans, pmsc->cur_lun, &pmsc->l_unit_n[pmsc->cur_lun].inquiry);
|
||||
if(status == USB_OK)
|
||||
{
|
||||
pmsc->l_unit_n[pmsc->cur_lun].state = USBH_MSC_TEST_UNIT_READY;
|
||||
}
|
||||
else if(status == USB_FAIL)
|
||||
{
|
||||
pmsc->l_unit_n[pmsc->cur_lun].state = USBH_MSC_REQUEST_SENSE;
|
||||
}
|
||||
break;
|
||||
case USBH_MSC_TEST_UNIT_READY:
|
||||
status = usbh_msc_bot_scsi_test_unit_ready(uhost, &pmsc->bot_trans, pmsc->cur_lun);
|
||||
if(status == USB_OK)
|
||||
{
|
||||
pmsc->l_unit_n[pmsc->cur_lun].state = USBH_MSC_READ_CAPACITY10;
|
||||
pmsc->l_unit_n[pmsc->cur_lun].ready = MSC_OK;
|
||||
}
|
||||
else if(status == USB_FAIL)
|
||||
{
|
||||
pmsc->l_unit_n[pmsc->cur_lun].state = USBH_MSC_REQUEST_SENSE;
|
||||
pmsc->l_unit_n[pmsc->cur_lun].ready = MSC_NOT_READY;
|
||||
}
|
||||
break;
|
||||
|
||||
case USBH_MSC_READ_CAPACITY10:
|
||||
status = usbh_msc_bot_scsi_capacity(uhost, &pmsc->bot_trans, pmsc->cur_lun, &pmsc->l_unit_n[pmsc->cur_lun].capacity);
|
||||
if(status == USB_OK)
|
||||
{
|
||||
msize = (uint64_t)pmsc->l_unit_n[pmsc->cur_lun].capacity.blk_nbr * (uint64_t)pmsc->l_unit_n[pmsc->cur_lun].capacity.blk_size;
|
||||
USBH_DEBUG("Device capacity: %llu Byte", msize);
|
||||
USBH_DEBUG("Block num: %d ", pmsc->l_unit_n[pmsc->cur_lun].capacity.blk_nbr);
|
||||
USBH_DEBUG("Block size: %d Byte", pmsc->l_unit_n[pmsc->cur_lun].capacity.blk_size);
|
||||
pmsc->l_unit_n[pmsc->cur_lun].state = USBH_MSC_IDLE;
|
||||
pmsc->cur_lun ++;
|
||||
}
|
||||
else if(status == USB_FAIL)
|
||||
{
|
||||
pmsc->l_unit_n[pmsc->cur_lun].state = USBH_MSC_REQUEST_SENSE;
|
||||
}
|
||||
break;
|
||||
case USBH_MSC_REQUEST_SENSE:
|
||||
status = usbh_msc_bot_scsi_request_sense(uhost, &pmsc->bot_trans, pmsc->cur_lun);
|
||||
if(status == USB_OK)
|
||||
{
|
||||
pmsc->l_unit_n[pmsc->cur_lun].state = USBH_MSC_TEST_UNIT_READY;
|
||||
}
|
||||
else if(status == USB_FAIL)
|
||||
{
|
||||
pmsc->l_unit_n[pmsc->cur_lun].ready = MSC_NOT_READY;
|
||||
pmsc->l_unit_n[pmsc->cur_lun].state = USBH_MSC_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case USBH_MSC_BUSY:
|
||||
break;
|
||||
case USBH_MSC_ERROR:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
pmsc->state = USBH_MSC_IDLE;
|
||||
}
|
||||
break;
|
||||
case USBH_MSC_IDLE:
|
||||
if(puhost->user_handler->user_application != NULL)
|
||||
{
|
||||
puhost->user_handler->user_application();
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return USB_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief usb host msc get max lun
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param lun: max lun buffer
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type usbh_msc_get_max_lun(void *uhost, uint8_t *lun)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usb_sts_type status = USB_WAIT;
|
||||
if(puhost->ctrl.state == CONTROL_IDLE )
|
||||
{
|
||||
puhost->ctrl.setup.bmRequestType = USB_DIR_D2H | USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_CLASS;
|
||||
puhost->ctrl.setup.bRequest = MSC_REQ_GET_MAX_LUN;
|
||||
puhost->ctrl.setup.wValue = 0;
|
||||
puhost->ctrl.setup.wIndex = 0;
|
||||
puhost->ctrl.setup.wLength = 1;
|
||||
usbh_ctrl_request(puhost, lun, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = usbh_ctrl_result_check(puhost, CONTROL_IDLE, ENUM_IDLE);
|
||||
if(status == USB_OK || status == USB_NOT_SUPPORT)
|
||||
{
|
||||
status = USB_OK;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc clear feature
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param ept_num: endpoint number
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
static usb_sts_type usbh_msc_clear_feature(void *uhost, uint8_t ept_num)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usb_sts_type status = USB_WAIT;
|
||||
if(puhost->ctrl.state == CONTROL_IDLE )
|
||||
{
|
||||
puhost->ctrl.setup.bmRequestType = USB_DIR_H2D | USB_REQ_RECIPIENT_ENDPOINT | USB_REQ_TYPE_STANDARD;
|
||||
puhost->ctrl.setup.bRequest = USB_STD_REQ_CLEAR_FEATURE;
|
||||
puhost->ctrl.setup.wValue = 0;
|
||||
puhost->ctrl.setup.wIndex = ept_num;
|
||||
puhost->ctrl.setup.wLength = 0;
|
||||
usbh_ctrl_request(puhost, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = usbh_ctrl_result_check(puhost, CONTROL_IDLE, ENUM_IDLE);
|
||||
if(status == USB_OK || status == USB_NOT_SUPPORT)
|
||||
{
|
||||
status = USB_OK;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc clear feature
|
||||
* @param lun: logical unit number
|
||||
* @retval msc_error_type status
|
||||
*/
|
||||
msc_error_type usbh_msc_is_ready(void *uhost, uint8_t lun)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_msc_type *pmsc = (usbh_msc_type *)puhost->class_handler->pdata;
|
||||
return pmsc->l_unit_n[lun].ready;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief usb host msc read and write handle
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param address: logical block address
|
||||
* @param data_len: transfer data length
|
||||
* @param buffer: transfer data buffer
|
||||
* @param lun: logical unit number
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type usbh_msc_rw_handle(void *uhost, uint32_t address, uint32_t len, uint8_t *buffer, uint8_t lun)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_msc_type *pmsc = (usbh_msc_type *)puhost->class_handler->pdata;
|
||||
usb_sts_type status = USB_WAIT;
|
||||
switch(pmsc->l_unit_n[lun].state)
|
||||
{
|
||||
case USBH_MSC_READ10:
|
||||
status = usbh_msc_bot_scsi_read(uhost, &pmsc->bot_trans, address, buffer, len, lun);
|
||||
if(status == USB_OK)
|
||||
{
|
||||
pmsc->l_unit_n[lun].state = USBH_MSC_IDLE;
|
||||
}
|
||||
else if(status == USB_FAIL)
|
||||
{
|
||||
pmsc->l_unit_n[lun].state = USBH_MSC_REQUEST_SENSE;
|
||||
status = USB_WAIT;
|
||||
}
|
||||
break;
|
||||
case USBH_MSC_WRITE:
|
||||
status = usbh_msc_bot_scsi_write(uhost, &pmsc->bot_trans, address, buffer, len, lun);
|
||||
if(status == USB_OK)
|
||||
{
|
||||
pmsc->l_unit_n[lun].state = USBH_MSC_IDLE;
|
||||
}
|
||||
else if(status == USB_FAIL)
|
||||
{
|
||||
pmsc->l_unit_n[lun].state = USBH_MSC_REQUEST_SENSE;
|
||||
status = USB_WAIT;
|
||||
}
|
||||
break;
|
||||
case USBH_MSC_REQUEST_SENSE:
|
||||
status = usbh_msc_bot_scsi_request_sense(uhost, &pmsc->bot_trans, lun);
|
||||
if(status == USB_OK)
|
||||
{
|
||||
pmsc->l_unit_n[lun].state = USBH_MSC_IDLE;
|
||||
status = USB_FAIL;
|
||||
}
|
||||
else if(status == USB_FAIL)
|
||||
{
|
||||
USBH_DEBUG("device not support");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc read
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param address: logical block address
|
||||
* @param data_len: transfer data length
|
||||
* @param buffer: transfer data buffer
|
||||
* @param lun: logical unit number
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type usbh_msc_read(void *uhost, uint32_t address, uint32_t len, uint8_t *buffer, uint8_t lun)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_msc_type *pmsc = (usbh_msc_type *)puhost->class_handler->pdata;
|
||||
uint32_t timeout = 0;
|
||||
if(puhost->conn_sts == 0 || puhost->global_state != USBH_CLASS
|
||||
|| pmsc->l_unit_n[lun].state != USBH_MSC_IDLE)
|
||||
{
|
||||
return USB_FAIL;
|
||||
}
|
||||
pmsc->bot_trans.msc_struct = &usbh_msc;
|
||||
pmsc->l_unit_n[lun].state = USBH_MSC_READ10;
|
||||
pmsc->use_lun = lun;
|
||||
|
||||
timeout = puhost->timer;
|
||||
|
||||
while(usbh_msc_rw_handle(uhost, address, len, buffer, lun) == USB_WAIT)
|
||||
{
|
||||
if(puhost->conn_sts == 0 || (puhost->timer - timeout) > (len * 10000))
|
||||
{
|
||||
pmsc->l_unit_n[lun].state = USBH_MSC_IDLE;
|
||||
return USB_FAIL;
|
||||
}
|
||||
}
|
||||
return USB_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb host msc write
|
||||
* @param uhost: to the structure of usbh_core_type
|
||||
* @param address: logical block address
|
||||
* @param data_len: transfer data length
|
||||
* @param buffer: transfer data buffer
|
||||
* @param lun: logical unit number
|
||||
* @retval status: usb_sts_type status
|
||||
*/
|
||||
usb_sts_type usbh_msc_write(void *uhost, uint32_t address, uint32_t len, uint8_t *buffer, uint8_t lun)
|
||||
{
|
||||
usbh_core_type *puhost = (usbh_core_type *)uhost;
|
||||
usbh_msc_type *pmsc = (usbh_msc_type *)puhost->class_handler->pdata;
|
||||
uint32_t timeout = 0;
|
||||
if(puhost->conn_sts == 0 || puhost->global_state != USBH_CLASS
|
||||
|| pmsc->l_unit_n[lun].state != USBH_MSC_IDLE)
|
||||
{
|
||||
return USB_FAIL;
|
||||
}
|
||||
|
||||
pmsc->bot_trans.msc_struct = &usbh_msc;
|
||||
pmsc->l_unit_n[lun].state = USBH_MSC_WRITE;
|
||||
pmsc->use_lun = lun;
|
||||
|
||||
timeout = puhost->timer;
|
||||
while(usbh_msc_rw_handle(uhost, address, len, buffer, lun) == USB_WAIT)
|
||||
{
|
||||
if(puhost->conn_sts == 0 || (puhost->timer - timeout) > (len * 10000))
|
||||
{
|
||||
pmsc->l_unit_n[lun].state = USBH_MSC_IDLE;
|
||||
return USB_FAIL;
|
||||
}
|
||||
}
|
||||
return USB_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file usbh_msc_class.h
|
||||
* @brief usb host msc class header file
|
||||
**************************************************************************
|
||||
* Copyright notice & Disclaimer
|
||||
*
|
||||
* The software Board Support Package (BSP) that is made available to
|
||||
* download from Artery official website is the copyrighted work of Artery.
|
||||
* Artery authorizes customers to use, copy, and distribute the BSP
|
||||
* software and its related documentation for the purpose of design and
|
||||
* development in conjunction with Artery microcontrollers. Use of the
|
||||
* software is governed by this copyright notice and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
|
||||
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
|
||||
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
|
||||
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
|
||||
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBH_MSC_CLASS_H
|
||||
#define __USBH_MSC_CLASS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "usbh_core.h"
|
||||
#include "usb_conf.h"
|
||||
#include "usbh_msc_bot_scsi.h"
|
||||
|
||||
/** @addtogroup AT32F435_437_middlewares_usbh_class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup USBH_msc_class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBH_msc_class_definition
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief usb msc subclass code
|
||||
*/
|
||||
#define MSC_SUBCLASS_SCSI_TRANS 0x06
|
||||
|
||||
/**
|
||||
* @brief usb msc protocol code
|
||||
*/
|
||||
#define MSC_PROTOCOL_BBB 0x50
|
||||
|
||||
/**
|
||||
* @brief usb msc request code
|
||||
*/
|
||||
#define MSC_REQ_GET_MAX_LUN 0xFE
|
||||
#define MSC_REQ_BOMSR 0xFF
|
||||
|
||||
/**
|
||||
* @brief usb hid request code
|
||||
*/
|
||||
#define USB_HID_GET_REPORT 0x01
|
||||
#define USB_HID_GET_IDLE 0x02
|
||||
#define USB_HID_GET_PROTOCOL 0x03
|
||||
#define USB_HID_SET_REPORT 0x09
|
||||
#define USB_HID_SET_IDLE 0x0A
|
||||
#define USB_HID_SET_PROTOCOL 0x0B
|
||||
|
||||
|
||||
#define USBH_SUPPORT_MAX_LUN 0x2
|
||||
|
||||
/**
|
||||
* @brief usb msc request state
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
USBH_MSC_STATE_IDLE,
|
||||
USBH_MSC_STATE_GET_LUN,
|
||||
USBH_MSC_STATE_ERROR,
|
||||
USBH_MSC_STATE_COMPLETE,
|
||||
}usbh_msc_ctrl_state_type;
|
||||
|
||||
/**
|
||||
* @brief usb msc struct
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t chin;
|
||||
uint8_t eptin;
|
||||
uint16_t in_maxpacket;
|
||||
uint8_t in_poll;
|
||||
|
||||
uint8_t chout;
|
||||
uint8_t eptout;
|
||||
uint16_t out_maxpacket;
|
||||
uint8_t out_poll;
|
||||
uint8_t protocol;
|
||||
|
||||
uint32_t max_lun;
|
||||
uint32_t cur_lun;
|
||||
uint32_t use_lun;
|
||||
|
||||
|
||||
usbh_msc_ctrl_state_type ctrl_state;
|
||||
msc_state_type state;
|
||||
uint8_t error;
|
||||
msc_bot_trans_type bot_trans;
|
||||
usbh_msc_unit_type l_unit_n[USBH_SUPPORT_MAX_LUN];
|
||||
uint16_t poll_timer;
|
||||
uint8_t buffer[64];
|
||||
}usbh_msc_type;
|
||||
|
||||
extern usbh_class_handler_type uhost_msc_class_handler;
|
||||
extern usbh_msc_type usbh_msc;
|
||||
msc_error_type usbh_msc_is_ready(void *uhost, uint8_t lun);
|
||||
usb_sts_type usbh_msc_write(void *uhost, uint32_t address, uint32_t len, uint8_t *buffer, uint8_t lun);
|
||||
usb_sts_type usbh_msc_read(void *uhost, uint32_t address, uint32_t len, uint8_t *buffer, uint8_t lun);
|
||||
usb_sts_type usbh_msc_rw_handle(void *uhost, uint32_t address, uint32_t len, uint8_t *buffer, uint8_t lun);
|
||||
usb_sts_type msc_bot_scsi_init(usbh_msc_type *msc_struct);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user