📄 serial_driver.c
字号:
USB_UNICODE('2'),
USB_UNICODE('3'),
USB_UNICODE('4'),
USB_UNICODE('5'),
USB_UNICODE('6'),
USB_UNICODE('7'),
USB_UNICODE('8'),
USB_UNICODE('9'),
USB_UNICODE('A'),
USB_UNICODE('F')
};
//! \brief List of string descriptors
const char *pStrings[] = {
(char *) &sLanguageID,
pManufacturer,
pProduct,
pSerialNumber
};
//! \brief List of endpoint descriptors
const S_usb_endpoint_descriptor *pEndpoints[] = {
&(sConfiguration.sDataOut),
&(sConfiguration.sDataIn),
&(sConfiguration.sNotification)
};
//! \brief Standard descriptors list
const S_std_descriptors sDescriptors = {
&sDevice,
(S_usb_configuration_descriptor *) &sConfiguration,
pStrings,
pEndpoints
};
//------------------------------------------------------------------------------
// Internal functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief Sets asynchronous line-character formatting properties
//!
//! This function is used as a callback when receiving the data part
//! of a SET_LINE_CODING request.
//! \param pSer Pointer to a S_ser instance
//! \see S_ser
//! \see usbcdc11.pdf - Section 6.2.12
//------------------------------------------------------------------------------
static void ACM_SetLineCoding(const S_ser *pSer)
{
USB_SendZLP0(pSer->sClass.pUsb, 0, 0);
}
//------------------------------------------------------------------------------
//! \brief Sends the currently configured line coding to the host
//! \param pSer Pointer to a S_ser instance
//! \see S_ser
//! \see usbcdc11.pdf - Section 6.2.13
//------------------------------------------------------------------------------
static void ACM_GetLineCoding(const S_ser *pSer)
{
USB_Write(pSer->sClass.pUsb,
0,
(void *) &(pSer->sLineCoding),
sizeof(S_cdc_line_coding),
0,
0);
}
//------------------------------------------------------------------------------
//! \brief Sets the state of control line parameters.
//! \param pSer Pointer to a S_ser instance
//! \param isActivateCarrier Indicates if the device should activate
//! its carrier
//! \param isDTEPresent Indicates if the terminal is present
//! \see S_ser
//! \see usbcdc11.pdf - Section 6.2.14
//------------------------------------------------------------------------------
static void ACM_SetControlLineState(S_ser *pSer,
bool isActivateCarrier,
bool isDTEPresent)
{
pSer->isCarrierActivated = isActivateCarrier;
USB_SendZLP0(pSer->sClass.pUsb, 0, 0);
}
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief SETUP request handler for an Abstract Control Model device
//! \param pSer Pointer to a S_ser instance
//! \see S_ser
//! \see usbcdc11.pdf - Section 6.2
//------------------------------------------------------------------------------
void SER_RequestHandler(S_ser *pSer)
{
S_usb_request *pSetup = USB_GetSetup(pSer->sClass.pUsb);
TRACE_DEBUG_M("NewReq ");
// Handle the request
switch (pSetup->bRequest) {
//-----------------------
case CDC_SET_LINE_CODING:
//-----------------------
TRACE_DEBUG_M("sLineCoding ");
// Start the read operation with ACM_SetLineCoding as the callback
USB_Read(pSer->sClass.pUsb,
0,
(void *) &(pSer->sLineCoding),
sizeof(S_cdc_line_coding),
(Callback_f) ACM_SetLineCoding,
pSer);
break;
//-----------------------
case CDC_GET_LINE_CODING:
//-----------------------
TRACE_DEBUG_M("gLineCoding ");
ACM_GetLineCoding(pSer);
break;
//------------------------------
case CDC_SET_CONTROL_LINE_STATE:
//------------------------------
{
bool isActivateCarrier = false;
bool isDTEPresent = false;
TRACE_DEBUG_M("sControlLineState(");
if (ISSET(pSetup->wValue, CDC_DTE_PRESENT)) {
isDTEPresent = true;
}
if (ISSET(pSetup->wValue, CDC_ACTIVATE_CARRIER)) {
isActivateCarrier = true;
}
TRACE_DEBUG_M("%d,%d) ", isDTEPresent, isActivateCarrier);
ACM_SetControlLineState(pSer, isActivateCarrier, isDTEPresent);
}
break;
//------
default:
//------
// Forward request to standard request handler
STD_RequestHandler((S_std_class *) pSer);
break;
}
}
//------------------------------------------------------------------------------
//! \brief Initializes a CDC serial driver
//!
//! This method sets the standard descriptors of the device and the
//! default CDC configuration.
//! \param pSer Pointer to a S_ser instance
//! \param pUsb Pointer to the S_usb driver instance to use
//! \see S_ser
//! \see S_usb
//------------------------------------------------------------------------------
void SER_Init(S_ser *pSer, const S_usb *pUsb)
{
// Initialize standard class attributes
pSer->sClass.pUsb = pUsb;
pSer->sClass.pDescriptors = &sDescriptors;
// Initialize ACM attributes
// Line coding
pSer->sLineCoding.dwDTERate = 0;
pSer->sLineCoding.bCharFormat = 0;
pSer->sLineCoding.bParityType = 0;
pSer->sLineCoding.bDataBits = 0;
// Carrier
pSer->isCarrierActivated = false;
// Initialize the USB driver
USB_Init(pUsb);
}
//------------------------------------------------------------------------------
//! \brief Reads data from the Data OUT endpoint
//! \param pSer Pointer to a S_ser instance
//! \param pBuffer Buffer in which to store the received data
//! \param dLength Length of data buffer
//! \param fCallback Optional callback function
//! \param pArgument Optional parameter for the callback function
//! \return SER_STATUS_SUCCESS if transfer has started successfully;
//! SER_STATUS_LOCKED if endpoint is currently in use;
//! SER_STATUS_ERROR if transfer cannot be started.
//------------------------------------------------------------------------------
unsigned char SER_Read(S_ser *pSer,
void *pBuffer,
unsigned int dLength,
Callback_f fCallback,
void *pArgument)
{
return USB_Read(pSer->sClass.pUsb, SER_EPT_DATA_OUT, pBuffer,
dLength, fCallback, pArgument);
}
//------------------------------------------------------------------------------
//! \brief Sends data through the Data IN endpoint
//! \param pSer Pointer to a S_ser instance
//! \param pBuffer Buffer holding the data to transmit
//! \param dLength Length of data buffer
//! \param fCallback Optional callback function
//! \param pArgument Optional parameter for the callback function
//! \return SER_STATUS_SUCCESS if transfer has started successfully;
//! SER_STATUS_LOCKED if endpoint is currently in use;
//! SER_STATUS_ERROR if transfer cannot be started.
//------------------------------------------------------------------------------
unsigned char SER_Write(S_ser *pSer,
void *pBuffer,
unsigned int dLength,
Callback_f fCallback,
void *pArgument)
{
return USB_Write(pSer->sClass.pUsb, SER_EPT_DATA_IN, pBuffer,
dLength, fCallback, pArgument);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -