添加GD32H7的CMake工程
This commit is contained in:
@@ -0,0 +1,646 @@
|
||||
/*!
|
||||
\file usbh_cdc_core.c
|
||||
\brief USB host CDC class driver
|
||||
|
||||
\version 2025-01-24, V1.4.0, firmware for GD32H7xx
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "usbh_cdc_core.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef USB_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment = 4
|
||||
#endif
|
||||
#endif /* USB_HS_INTERNAL_DMA_ENABLED */
|
||||
|
||||
__ALIGN_BEGIN uint8_t tx_buf[CDC_BUFFER_SIZE] __ALIGN_END;
|
||||
|
||||
#ifdef USB_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment = 4
|
||||
#endif
|
||||
#endif /* USB_HS_INTERNAL_DMA_ENABLED */
|
||||
|
||||
__ALIGN_BEGIN uint8_t rx_buf[CDC_BUFFER_SIZE] __ALIGN_END;
|
||||
|
||||
/* local function prototypes ('static') */
|
||||
static usbh_status cdc_interface_init(usbh_host *uhost);
|
||||
static void cdc_interface_deinit(usbh_host *uhost);
|
||||
static usbh_status cdc_class_request(usbh_host *uhost);
|
||||
static usbh_status cdc_handle(usbh_host *uhost);
|
||||
static void cdc_process_transmission(usbh_host *uhost);
|
||||
static void cdc_process_reception(usbh_host *uhost);
|
||||
static void cdc_init_txrxparam(usbh_host *uhost);
|
||||
static void cdc_receive_data(usbh_host *uhost, cdc_xfer *cdc_data);
|
||||
|
||||
usbh_class usbh_cdc = {
|
||||
USB_CLASS_CDC,
|
||||
cdc_interface_init,
|
||||
cdc_interface_deinit,
|
||||
cdc_class_request,
|
||||
cdc_handle
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief send data to the device
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[in] data: data pointer
|
||||
\param[in] length: data length
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void cdc_data_send(usbh_host *uhost, uint8_t *data, uint16_t length)
|
||||
{
|
||||
usbh_cdc_handler *cdc = (usbh_cdc_handler *)uhost->active_class->class_data;
|
||||
|
||||
if(CDC_IDLE == cdc->tx_param.cdc_cur_state) {
|
||||
cdc->tx_param.prxtx_buff = data;
|
||||
cdc->tx_param.data_length = length;
|
||||
cdc->tx_param.cdc_cur_state = CDC_SEND_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief send dummy data to the device
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void cdc_dummydata_send(usbh_host *uhost)
|
||||
{
|
||||
usbh_cdc_handler *cdc = (usbh_cdc_handler *)uhost->active_class->class_data;
|
||||
|
||||
static uint8_t cdc_send_buf[17] = {0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x20, 0x6C, 0x69, 0x6E, 0x65};
|
||||
|
||||
if(CDC_IDLE == cdc->tx_param.cdc_cur_state) {
|
||||
cdc->tx_param.prxtx_buff = cdc_send_buf;
|
||||
cdc->tx_param.data_length = sizeof(cdc_send_buf);
|
||||
cdc->tx_param.cdc_cur_state = CDC_SEND_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable CDC receive
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void cdc_start_reception(usbh_host *uhost)
|
||||
{
|
||||
usbh_cdc_handler *cdc = (usbh_cdc_handler *)uhost->active_class->class_data;
|
||||
|
||||
cdc->rx_enabled = 1U;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief stop CDC receive
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void cdc_stop_reception(usbh_host *uhost)
|
||||
{
|
||||
usbh_cdc_handler *cdc = (usbh_cdc_handler *)uhost->active_class->class_data;
|
||||
|
||||
cdc->rx_enabled = 0U;
|
||||
|
||||
usb_pipe_halt(uhost->data, cdc->data_itf.pipe_in);
|
||||
usbh_pipe_free(uhost->data, cdc->data_itf.pipe_in);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get currently configured line coding
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[out] none
|
||||
\retval operation status
|
||||
*/
|
||||
usbh_status cdc_get_line_coding(usbh_host *uhost)
|
||||
{
|
||||
usbh_status status = USBH_BUSY;
|
||||
usbh_cdc_handler *cdc = (usbh_cdc_handler *)uhost->active_class->class_data;
|
||||
|
||||
if (CTL_IDLE == uhost->control.ctl_state) {
|
||||
usbh_control *usb_ctl = &uhost->control;
|
||||
|
||||
usb_ctl->setup.req = (usb_req) {
|
||||
.bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS,
|
||||
.bRequest = GET_LINE_CODING,
|
||||
.wValue = 0U,
|
||||
.wIndex = 0U,
|
||||
.wLength = LINE_CODING_STRUCTURE_SIZE
|
||||
};
|
||||
|
||||
usbh_ctlstate_config(uhost, cdc->line_code_get.array, LINE_CODING_STRUCTURE_SIZE);
|
||||
}
|
||||
|
||||
status = usbh_ctl_handler(uhost);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief specify typical asynchronous line-character formatting properties
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[out] none
|
||||
\retval operation status
|
||||
*/
|
||||
usbh_status cdc_set_line_coding(usbh_host *uhost)
|
||||
{
|
||||
usbh_status status = USBH_BUSY;
|
||||
usbh_cdc_handler *cdc = (usbh_cdc_handler *)uhost->active_class->class_data;
|
||||
|
||||
if(CTL_IDLE == uhost->control.ctl_state) {
|
||||
usbh_control *usb_ctl = &uhost->control;
|
||||
|
||||
usb_ctl->setup.req = (usb_req) {
|
||||
.bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS,
|
||||
.bRequest = SET_LINE_CODING,
|
||||
.wValue = 0U,
|
||||
.wIndex = 0U,
|
||||
.wLength = LINE_CODING_STRUCTURE_SIZE
|
||||
};
|
||||
|
||||
usbh_ctlstate_config(uhost, cdc->line_code_set.array, LINE_CODING_STRUCTURE_SIZE);
|
||||
}
|
||||
|
||||
status = usbh_ctl_handler(uhost);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief this request generates RS-232/V.24 style control signals
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[out] none
|
||||
\retval operation status
|
||||
*/
|
||||
usbh_status cdc_set_control_line_state(usbh_host *uhost)
|
||||
{
|
||||
usbh_status status = USBH_BUSY;
|
||||
|
||||
if(CTL_IDLE == uhost->control.ctl_state) {
|
||||
usbh_control *usb_ctl = &uhost->control;
|
||||
|
||||
usb_ctl->setup.req = (usb_req) {
|
||||
.bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS,
|
||||
.bRequest = SET_CONTROL_LINE_STATE,
|
||||
.wValue = CDC_DEACTIVATE_CARRIER_SIGNAL_RTS | CDC_DEACTIVATE_SIGNAL_DTR,
|
||||
.wIndex = 0U,
|
||||
.wLength = 0U
|
||||
};
|
||||
|
||||
usbh_ctlstate_config(uhost, NULL, 0U);
|
||||
}
|
||||
|
||||
status = usbh_ctl_handler(uhost);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief this function prepares the state before issuing the class specific commands
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void cdc_change_state_to_issue_setconfig(usbh_host *uhost)
|
||||
{
|
||||
usbh_cdc_handler *cdc = (usbh_cdc_handler *)uhost->active_class->class_data;
|
||||
|
||||
uhost->backup_state = uhost->cur_state;
|
||||
uhost->cur_state = HOST_CLASS_ENUM;
|
||||
|
||||
cdc->req_state = CDC_SET_LINE_CODING_RQUEST;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief this function prepares the state before issuing the class specific commands
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void cdc_issue_getconfig(usbh_host *uhost)
|
||||
{
|
||||
usbh_cdc_handler *cdc = (usbh_cdc_handler *)uhost->active_class->class_data;
|
||||
|
||||
uhost->backup_state = uhost->cur_state;
|
||||
uhost->cur_state = HOST_CLASS_ENUM;
|
||||
|
||||
cdc->req_state = CDC_GET_LINE_CODING_RQUEST;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief init the CDC class
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[out] none
|
||||
\retval operation status
|
||||
*/
|
||||
static usbh_status cdc_interface_init(usbh_host *uhost)
|
||||
{
|
||||
usbh_status status = USBH_OK;
|
||||
|
||||
uint8_t interface = usbh_interface_find(&uhost->dev_prop, USB_CLASS_CDC, USB_CDC_SUBCLASS_ACM, USB_CDC_PROTOCOL_AT);
|
||||
|
||||
if(0xFFU == interface) {
|
||||
uhost->usr_cb->dev_not_supported();
|
||||
|
||||
status = USBH_FAIL;
|
||||
} else {
|
||||
usbh_interface_select(&uhost->dev_prop, interface);
|
||||
|
||||
static usbh_cdc_handler cdc_handler;
|
||||
|
||||
memset(&cdc_handler, 0U, sizeof(usbh_cdc_handler));
|
||||
|
||||
uhost->active_class->class_data = (void *)&cdc_handler;
|
||||
|
||||
usb_desc_ep *ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[0];
|
||||
|
||||
/* collect the notification endpoint address and length */
|
||||
if(ep_desc->bEndpointAddress & 0x80U) {
|
||||
cdc_handler.cmd_itf.ep_notify = ep_desc->bEndpointAddress;
|
||||
cdc_handler.cmd_itf.ep_size_notify = ep_desc->wMaxPacketSize;
|
||||
}
|
||||
|
||||
/* allocate the length for host channel number in */
|
||||
cdc_handler.cmd_itf.pipe_notify = usbh_pipe_allocate(uhost->data, cdc_handler.cmd_itf.ep_notify);
|
||||
|
||||
/* open channel for in endpoint */
|
||||
usbh_pipe_create(uhost->data,
|
||||
&uhost->dev_prop,
|
||||
cdc_handler.cmd_itf.pipe_notify,
|
||||
USB_EPTYPE_INTR,
|
||||
cdc_handler.cmd_itf.ep_size_notify);
|
||||
|
||||
usbh_pipe_toggle_set(uhost->data, cdc_handler.cmd_itf.pipe_notify, 0U);
|
||||
|
||||
interface = usbh_interface_find(&uhost->dev_prop, USB_CLASS_DATA, USB_CDC_SUBCLASS_RESERVED, USB_CDC_PROTOCOL_NONE);
|
||||
|
||||
ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[0];
|
||||
|
||||
if(ep_desc->bEndpointAddress & 0x80U) {
|
||||
cdc_handler.data_itf.ep_in = ep_desc->bEndpointAddress;
|
||||
cdc_handler.data_itf.ep_size_in = ep_desc->wMaxPacketSize;
|
||||
} else {
|
||||
cdc_handler.data_itf.ep_out = ep_desc->bEndpointAddress;
|
||||
cdc_handler.data_itf.ep_size_out = ep_desc->wMaxPacketSize;
|
||||
}
|
||||
|
||||
ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[1];
|
||||
|
||||
if(ep_desc->bEndpointAddress & 0x80U) {
|
||||
cdc_handler.data_itf.ep_in = ep_desc->bEndpointAddress;
|
||||
cdc_handler.data_itf.ep_size_in = ep_desc->wMaxPacketSize;
|
||||
} else {
|
||||
cdc_handler.data_itf.ep_out = ep_desc->bEndpointAddress;
|
||||
cdc_handler.data_itf.ep_size_out = ep_desc->wMaxPacketSize;
|
||||
}
|
||||
|
||||
/* allocate the length for host channel number out */
|
||||
cdc_handler.data_itf.pipe_out = usbh_pipe_allocate(uhost->data, cdc_handler.data_itf.ep_out);
|
||||
|
||||
/* allocate the length for host channel number in */
|
||||
cdc_handler.data_itf.pipe_in = usbh_pipe_allocate(uhost->data, cdc_handler.data_itf.ep_in);
|
||||
|
||||
/* open channel for OUT endpoint */
|
||||
usbh_pipe_create(uhost->data,
|
||||
&uhost->dev_prop,
|
||||
cdc_handler.data_itf.pipe_out,
|
||||
USB_EPTYPE_BULK,
|
||||
cdc_handler.data_itf.ep_size_out);
|
||||
|
||||
/* open channel for IN endpoint */
|
||||
usbh_pipe_create(uhost->data,
|
||||
&uhost->dev_prop,
|
||||
cdc_handler.data_itf.pipe_in,
|
||||
USB_EPTYPE_BULK,
|
||||
cdc_handler.data_itf.ep_size_in);
|
||||
|
||||
usbh_pipe_toggle_set(uhost->data, cdc_handler.data_itf.ep_out, 0U);
|
||||
usbh_pipe_toggle_set(uhost->data, cdc_handler.data_itf.pipe_in, 0U);
|
||||
|
||||
cdc_handler.req_state = CDC_GET_LINE_CODING_RQUEST;
|
||||
|
||||
/* initialize the TX/TX parameters */
|
||||
cdc_init_txrxparam(uhost);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief deinit the host channels used for the CDC class
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void cdc_interface_deinit(usbh_host *uhost)
|
||||
{
|
||||
usbh_cdc_handler *cdc = (usbh_cdc_handler *)uhost->active_class->class_data;
|
||||
|
||||
/* reset the channel as free */
|
||||
if(cdc->cmd_itf.pipe_notify) {
|
||||
usb_pipe_halt(uhost->data, cdc->cmd_itf.pipe_notify);
|
||||
usbh_pipe_free(uhost->data, cdc->cmd_itf.pipe_notify);
|
||||
|
||||
cdc->cmd_itf.pipe_notify = 0U;
|
||||
}
|
||||
|
||||
/* reset the channel as free */
|
||||
if(cdc->data_itf.pipe_out) {
|
||||
usb_pipe_halt(uhost->data, cdc->data_itf.pipe_out);
|
||||
usbh_pipe_free(uhost->data, cdc->data_itf.pipe_out);
|
||||
|
||||
cdc->data_itf.pipe_out = 0U;
|
||||
}
|
||||
|
||||
/* reset the channel as free */
|
||||
if(cdc->data_itf.pipe_in) {
|
||||
usb_pipe_halt(uhost->data, cdc->data_itf.pipe_in);
|
||||
usbh_pipe_free(uhost->data, cdc->data_itf.pipe_in);
|
||||
|
||||
cdc->data_itf.pipe_in = 0U;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief handler CDC class requests
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[out] none
|
||||
\retval operation status
|
||||
*/
|
||||
static usbh_status cdc_class_request(usbh_host *uhost)
|
||||
{
|
||||
usbh_status status = USBH_BUSY;
|
||||
usbh_status class_req_status = USBH_BUSY;
|
||||
usbh_cdc_handler *cdc = (usbh_cdc_handler *)uhost->active_class->class_data;
|
||||
|
||||
switch(cdc->req_state) {
|
||||
case CDC_GET_LINE_CODING_RQUEST:
|
||||
/* issue the get line coding request */
|
||||
class_req_status = cdc_get_line_coding(uhost);
|
||||
|
||||
if(USBH_OK == class_req_status) {
|
||||
cdc->req_state = CDC_SET_CONTROL_LINE_STATE_REQUEST;
|
||||
}
|
||||
break;
|
||||
|
||||
case CDC_SET_LINE_CODING_RQUEST:
|
||||
/* issue the set line coding request */
|
||||
class_req_status = cdc_set_line_coding(uhost);
|
||||
|
||||
if(USBH_OK == class_req_status) {
|
||||
cdc->req_state = CDC_GET_LINE_CODING_RQUEST;
|
||||
}
|
||||
|
||||
if(USBH_NOT_SUPPORTED == class_req_status) {
|
||||
/* a clear feature should be issued here */
|
||||
cdc->req_state = CDC_ERROR_STATE;
|
||||
}
|
||||
break;
|
||||
|
||||
case CDC_SET_CONTROL_LINE_STATE_REQUEST:
|
||||
/* issue the set control line coding */
|
||||
class_req_status = cdc_set_control_line_state(uhost);
|
||||
|
||||
if(USBH_OK == class_req_status) {
|
||||
cdc->req_state = CDC_SET_CONTROL_LINE_STATE_REQUEST;
|
||||
|
||||
/* also set the state of receive CDCRxParam to IDLE */
|
||||
cdc->rx_param.cdc_cur_state = CDC_IDLE;
|
||||
|
||||
status = USBH_OK; /* this return from class specific routines request*/
|
||||
}
|
||||
break;
|
||||
|
||||
case CDC_ERROR_STATE:
|
||||
class_req_status = usbh_clrfeature(uhost, 0x00U, uhost->control.pipe_out_num);
|
||||
|
||||
if(USBH_OK == class_req_status) {
|
||||
cdc->req_state = CDC_GET_LINE_CODING_RQUEST;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief managing state machine for CDC data transfers
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[out] none
|
||||
\retval operation status
|
||||
*/
|
||||
static usbh_status cdc_handle(usbh_host *uhost)
|
||||
{
|
||||
usbh_status status = USBH_OK;
|
||||
|
||||
/* call application process */
|
||||
uhost->usr_cb->dev_user_app();
|
||||
|
||||
/* handle the transmission */
|
||||
cdc_process_transmission(uhost);
|
||||
|
||||
/* always send in packet to device */
|
||||
cdc_process_reception(uhost);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief the function is responsible for sending data to the device
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void cdc_process_transmission(usbh_host *uhost)
|
||||
{
|
||||
static uint32_t len ;
|
||||
usb_urb_state urb_status_tx = URB_IDLE;
|
||||
usbh_cdc_handler *cdc = (usbh_cdc_handler *)uhost->active_class->class_data;
|
||||
|
||||
urb_status_tx = usbh_urbstate_get(uhost->data, cdc->data_itf.pipe_out);
|
||||
|
||||
switch(cdc->tx_param.cdc_cur_state) {
|
||||
case CDC_IDLE:
|
||||
break;
|
||||
|
||||
case CDC_SEND_DATA:
|
||||
if((URB_DONE == urb_status_tx) || (URB_IDLE == urb_status_tx)) {
|
||||
/* check the data length is more then the usbh_cdc_handler.data_itf.length */
|
||||
if(cdc->tx_param.data_length > cdc->data_itf.ep_size_out) {
|
||||
len = cdc->data_itf.ep_size_out;
|
||||
|
||||
/* send the data */
|
||||
usbh_data_send(uhost->data,
|
||||
cdc->tx_param.prxtx_buff,
|
||||
cdc->data_itf.pipe_out,
|
||||
len);
|
||||
} else {
|
||||
len = cdc->tx_param.data_length;
|
||||
|
||||
/* send the remaining data */
|
||||
usbh_data_send(uhost->data,
|
||||
cdc->tx_param.prxtx_buff,
|
||||
cdc->data_itf.pipe_out,
|
||||
len);
|
||||
}
|
||||
|
||||
cdc->tx_param.cdc_cur_state = CDC_DATA_SENT;
|
||||
}
|
||||
break;
|
||||
|
||||
case CDC_DATA_SENT:
|
||||
/* check the status done for transmission */
|
||||
if(URB_DONE == urb_status_tx) {
|
||||
/* point to next chunk of data */
|
||||
cdc->tx_param.prxtx_buff += len;
|
||||
|
||||
/* decrease the data length */
|
||||
cdc->tx_param.data_length -= len;
|
||||
|
||||
if(0U == cdc->tx_param.data_length) {
|
||||
cdc->tx_param.cdc_cur_state = CDC_IDLE;
|
||||
} else {
|
||||
cdc->tx_param.cdc_cur_state = CDC_SEND_DATA;
|
||||
}
|
||||
} else if(URB_NOTREADY == urb_status_tx) {
|
||||
/* send the same data */
|
||||
usbh_data_send(uhost->data,
|
||||
(cdc->tx_param.prxtx_buff),
|
||||
cdc->data_itf.pipe_out,
|
||||
len);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief the function is responsible for reception of data from the device
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void cdc_process_reception(usbh_host *uhost)
|
||||
{
|
||||
usb_core_driver *udev = (usb_core_driver *)uhost->data;
|
||||
usbh_cdc_handler *cdc = (usbh_cdc_handler *)uhost->active_class->class_data;
|
||||
|
||||
if(1U == cdc->rx_enabled) {
|
||||
usb_urb_state urb_status_rx = usbh_urbstate_get(udev, cdc->data_itf.pipe_in);
|
||||
|
||||
switch(cdc->rx_param.cdc_cur_state) {
|
||||
case CDC_IDLE:
|
||||
/* check the received length lesser then the remaining space available in the buffer */
|
||||
if(cdc->rx_param.data_length < (cdc->rx_param.buffer_len - cdc->data_itf.ep_size_in)) {
|
||||
/* receive the data */
|
||||
usbh_data_recev(udev,
|
||||
cdc->rx_param.pfill_buff,
|
||||
cdc->data_itf.pipe_in,
|
||||
cdc->data_itf.ep_size_in);
|
||||
|
||||
/* change the CDC state to USBH_CDC_GET_DATA*/
|
||||
cdc->rx_param.cdc_cur_state = CDC_GET_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
case CDC_GET_DATA:
|
||||
/* check the last state of the device is URB_DONE */
|
||||
if(URB_DONE == urb_status_rx) {
|
||||
/* move the pointer as well as data length */
|
||||
cdc->rx_param.data_length += udev->host.pipe[cdc->data_itf.pipe_in].xfer_count;
|
||||
cdc->rx_param.pfill_buff += udev->host.pipe[cdc->data_itf.pipe_in].xfer_count;
|
||||
|
||||
/* Process the received data */
|
||||
cdc_receive_data(uhost, &cdc->rx_param);
|
||||
|
||||
/*change the state OD the CDC state*/
|
||||
cdc->rx_param.cdc_cur_state = CDC_IDLE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize the transmit and receive buffer and its parameter
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void cdc_init_txrxparam(usbh_host *uhost)
|
||||
{
|
||||
usbh_cdc_handler *cdc = (usbh_cdc_handler *)uhost->active_class->class_data;
|
||||
|
||||
/* initialize the transmit buffer and its parameter */
|
||||
cdc->tx_param.cdc_cur_state = CDC_IDLE;
|
||||
cdc->tx_param.data_length = 0U;
|
||||
cdc->tx_param.prxtx_buff = tx_buf;
|
||||
|
||||
/* initialize the receive buffer and its parameter */
|
||||
cdc->rx_param.cdc_cur_state = CDC_IDLE;
|
||||
cdc->rx_param.data_length = 0U;
|
||||
cdc->rx_param.pfill_buff = rx_buf;
|
||||
cdc->rx_param.pempty_buff = rx_buf;
|
||||
cdc->rx_param.buffer_len = sizeof(rx_buf);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief call back function from CDC core layer to redirect the received data on the user out put system
|
||||
\param[in] uhost: pointer to USB host
|
||||
\param[in] cdc_data: data structure
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void cdc_receive_data(usbh_host *uhost, cdc_xfer *cdc_data)
|
||||
{
|
||||
usbh_cdc_handler *cdc = (usbh_cdc_handler *)uhost->active_class->class_data;
|
||||
|
||||
if(cdc_data->pempty_buff < cdc_data->pfill_buff) {
|
||||
/* redirect the received data on the user out put system */
|
||||
cdc->user_cb.receive(cdc_data->pempty_buff);
|
||||
|
||||
cdc_data->pfill_buff = cdc_data->pempty_buff;
|
||||
|
||||
/* reset the data length to zero */
|
||||
cdc_data->data_length = 0U;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user