rt-thread-official/bsp/swm341/libraries/SWM341_StdPeriph_Driver/SWM341_usbd.c

515 lines
17 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******************************************************************************************************************************************
* 文件名称: SWM341_usbd.c
* 功能说明: SWM341单片机的USB设备功能驱动库
* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1
* 注意事项:
* 版本日期: V1.1.0 2020年11月3日
* 升级记录:
*
*
*******************************************************************************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION
* REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE
* FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN-
* -ECTION WITH THEIR PRODUCTS.
*
* COPYRIGHT 2012 Synwit Technology
*******************************************************************************************************************************************/
#include <string.h>
#include "SWM341.h"
#include "SWM341_usbd.h"
USBD_Info_t USBD_Info;
static uint8_t *CtrlIn_Ptr = 0;
static uint8_t *CtrlOut_Ptr = 0;
static volatile uint32_t CtrlIn_Size = 0;
static volatile uint32_t CtrlOut_Size = 0;
static volatile uint32_t CtrlOut_Limit = 0;
/******************************************************************************************************************************************
* 函数名称: USBD_Init()
* 功能说明: USB Device 初始化
* 输 入: 无
* 输 出: 无
* 注意事项: 无
******************************************************************************************************************************************/
void USBD_Init(void)
{
uint8_t ep_reg = 0, ep_nbr, ep_dir, ep_type, cfg, intf, alt;
uint16_t ep_pksz;
uint8_t *pCfg = USBD_Info.DescConfig;
uint32_t total_len = pCfg[2] + (pCfg[3] << 8);
uint32_t epie = 0x00010001;
SYS->USBCR = 0;
for(int i = 0; i < CyclesPerUs; i++) __NOP();
SYS->USBCR |= (1 << SYS_USBCR_RST48M_Pos); __DSB();
SYS->USBCR |= (1 << SYS_USBCR_RST12M_Pos); __DSB();
SYS->USBCR |= (1 << SYS_USBCR_RSTPLL_Pos); __DSB();
SYS->USBCR &= ~SYS_USBCR_ROLE_Msk;
SYS->USBCR |= (USBD_Info.Mode << SYS_USBCR_ROLE_Pos);
SYS->USBCR |= (1 << SYS_USBCR_VBUS_Pos);
SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_USB_Pos);
USBD_EPConfig(ep_reg++, 0, USB_EP_IN, USB_EP_CTRL, USBD_Info.CtrlPkSiz, 0, 0, 0); // Control In
USBD_EPConfig(ep_reg++, 0, USB_EP_OUT, USB_EP_CTRL, USBD_Info.CtrlPkSiz, 0, 0, 0); // Control Out
while(pCfg < (USBD_Info.DescConfig + total_len))
{
switch(pCfg[1])
{
case USB_DESC_CONFIG:
cfg = pCfg[5];
break;
case USB_DESC_INTERFACE:
intf = pCfg[2];
alt = pCfg[3];
break;
case USB_DESC_ENDPOINT:
ep_nbr = pCfg[2] & 0x0F;
ep_dir = pCfg[2] & USB_EP_IN;
ep_type = pCfg[3] & 0x03;
ep_pksz = pCfg[4] + (pCfg[5] << 8);
USBD_EPConfig(ep_reg++, ep_nbr, ep_dir, ep_type, ep_pksz, cfg, intf, alt);
epie |= (1 << ep_nbr) << (ep_dir ? 0 : 16);
break;
}
pCfg += pCfg[0];
}
USBD->FFTHR = (0xFFF << 16) | (0x000 << 0); // 无用
USBD->DEVCR = (USBD_Info.Speed << USBD_DEVCR_SPEED_Pos) |
(1 << USBD_DEVCR_DEVICE_Pos) |
(1 << USBD_DEVCR_CSRDONE_Pos);
USBD->DEVIE = (1 << USBD_DEVIE_RST_Pos) |
(1 << USBD_DEVIE_SETUP_Pos) |
(1 << USBD_DEVIE_SETCFG_Pos);
USBD->EPIE = epie;
SYS->USBPHYCR &= ~SYS_USBPHYCR_OPMODE_Msk;
SYS->USBPHYCR |= (0 << SYS_USBPHYCR_OPMODE_Pos); //Normal Operation
}
/******************************************************************************************************************************************
* 函数名称: USBD_EPConfig()
* 功能说明: USB Device Endpoint Configure
* 输 入: uint8_t ep_reg Endpoint Register
* uint8_t ep_nbr Endpoint Number used by host
* uint8_t ep_dir Endpoint Direction, 0 Out 1 In
* uint8_t ep_type Endpoint Type, 0 Control 1 Isochronous 2 Bulk 3 Interrupt
* uint16_t ep_pksz Maximum packet size in byte
* uint8_t cfg Configuration number to which this endpoint belongs
* uint8_t intf Interface number to which this endpoint belongs
* uint8_t alt Alternate setting to which this endpoint belongs
* 输 出: 无
* 注意事项: 无
******************************************************************************************************************************************/
void USBD_EPConfig(uint8_t ep_reg, uint8_t ep_nbr, uint8_t ep_dir, uint8_t ep_type, uint16_t ep_pksz, uint8_t cfg, uint8_t intf, uint8_t alt)
{
ep_dir = ep_dir ? 1 : 0; // for USB_EP_IN、USB_EP_OUT
USBD->EPCFG[ep_reg] = (ep_nbr << USBD_EPCFG_EPNR_Pos) |
(ep_dir << USBD_EPCFG_DIR_Pos) |
(ep_type << USBD_EPCFG_TYPE_Pos) |
(cfg << USBD_EPCFG_CFG_Pos) |
(intf << USBD_EPCFG_INTF_Pos) |
(alt << USBD_EPCFG_ALT_Pos) |
(ep_pksz << USBD_EPCFG_PKSZ_Pos);
if(ep_dir == USB_EP_OUT)
{
USBD->OUTEP[ep_nbr].RXCR = 0;
USBD->OUTEP[ep_nbr].RXCR = USBD_RXCR_FLUSHFF_Msk;
}
else
{
USBD->INEP[ep_nbr].TXCR = 0;
USBD->INEP[ep_nbr].TXCR = USBD_TXCR_FLUSHFF_Msk;
}
}
/******************************************************************************************************************************************
* 函数名称: USBD_Open()
* 功能说明: USB Device 打开
* 输 入: 无
* 输 出: 无
* 注意事项: 无
******************************************************************************************************************************************/
void USBD_Open(void)
{
NVIC_EnableIRQ(USB_IRQn);
}
/******************************************************************************************************************************************
* 函数名称: USBD_Close()
* 功能说明: USB Device 关闭
* 输 入: 无
* 输 出: 无
* 注意事项: 无
******************************************************************************************************************************************/
void USBD_Close(void)
{
NVIC_DisableIRQ(USB_IRQn);
}
void USBD_StandardRequest(USB_Setup_Packet_t * pSetup);
void USBD_GetDescriptor(USB_Setup_Packet_t * pSetup);
static USB_Setup_Packet_t Setup_Packet;
USB_Setup_Packet_t * pUSB_Setup = &Setup_Packet;
/******************************************************************************************************************************************
* 函数名称: USBD_ProcessSetupPacket()
* 功能说明: 处理Setup包
* 输 入: 无
* 输 出: 无
* 注意事项: 无
******************************************************************************************************************************************/
void USBD_ProcessSetupPacket(void)
{
((volatile uint32_t *)pUSB_Setup)[0] = USBD->SETUPD1;
((volatile uint32_t *)pUSB_Setup)[1] = USBD->SETUPD2;
switch(pUSB_Setup->bRequestType & 0x60)
{
case USB_REQ_STANDARD:
USBD_StandardRequest(pUSB_Setup);
break;
case USB_REQ_CLASS:
if(USBD_Info.pClassRequest_Callback != NULL)
{
USBD_Info.pClassRequest_Callback(pUSB_Setup);
}
break;
case USB_REQ_VENDOR:
if(USBD_Info.pVendorRequest_Callback != NULL)
{
USBD_Info.pVendorRequest_Callback(pUSB_Setup);
}
break;
default:
/* Setup error, stall the device */
USBD_Stall0();
break;
}
}
/******************************************************************************************************************************************
* 函数名称: USBD_StandardRequest()
* 功能说明: 处理标准请求
* 输 入: 无
* 输 出: 无
* 注意事项: GetDescriptor、SetDescriptor、SyncFrame之外的标准命令USB模块自动处理无需用户代码参与
******************************************************************************************************************************************/
void USBD_StandardRequest(USB_Setup_Packet_t * pSetup)
{
if(pSetup->bRequestType & 0x80) // Device to host
{
switch(pSetup->bRequest)
{
case USB_GET_DESCRIPTOR:
USBD_GetDescriptor(pSetup);
/* Status stage */
USBD_RxReady(0);
break;
default:
/* Setup error, stall the device */
USBD_Stall0();
break;
}
}
else // Host to device
{
switch(pSetup->bRequest)
{
default:
/* Setup error, stall the device */
USBD_Stall0();
break;
}
}
}
/******************************************************************************************************************************************
* 函数名称: USBD_GetDescriptor()
* 功能说明: 处理标准请求GetDescriptor
* 输 入: 无
* 输 出: 无
* 注意事项: 无
******************************************************************************************************************************************/
void USBD_GetDescriptor(USB_Setup_Packet_t * pSetup)
{
#define min(a, b) ((a)<(b) ? (a) : (b))
switch(pSetup->wValue >> 8)
{
case USB_DESC_DEVICE:
USBD_PrepareCtrlIn(USBD_Info.DescDevice, min(pSetup->wLength, USBD_Info.DescDevice[0]));
break;
case USB_DESC_CONFIG:
{
uint16_t total_len = USBD_Info.DescConfig[2] + (USBD_Info.DescConfig[3] << 8);
USBD_PrepareCtrlIn(USBD_Info.DescConfig, min(pSetup->wLength, total_len));
break;
}
case USB_DESC_STRING:
{
uint8_t index = pSetup->wValue & 0xFF;
if(index < 6)
{
USBD_PrepareCtrlIn(USBD_Info.DescString[index], min(pSetup->wLength, USBD_Info.DescString[index][0]));
}
else if((index == 0xEE) && USBD_Info.DescOSString)
{
USBD_PrepareCtrlIn(USBD_Info.DescOSString, min(pSetup->wLength, USBD_Info.DescOSString[0]));
}
else
{
/* Not support. Reply STALL. */
USBD_Stall0();
}
break;
}
case USB_DESC_BOS:
{
uint16_t total_len = USBD_Info.DescBOS[2] + (USBD_Info.DescBOS[3] << 8);
USBD_PrepareCtrlIn(USBD_Info.DescBOS, min(pSetup->wLength, total_len));
break;
}
case USB_DESC_HID:
{
uint8_t index = pSetup->wIndex & 0xFF;
uint16_t offset = USBD_Info.DescHIDOffset[index];
uint8_t *descHID = &USBD_Info.DescConfig[offset];
USBD_PrepareCtrlIn(descHID, min(pSetup->wLength, descHID[0]));
break;
}
case USB_DESC_HID_RPT:
{
uint8_t index = pSetup->wIndex & 0xFF;
uint16_t offset = USBD_Info.DescHIDOffset[index];
uint8_t *descHID = &USBD_Info.DescConfig[offset];
uint16_t report_len = descHID[7] + (descHID[8] << 8);
USBD_PrepareCtrlIn(USBD_Info.DescHIDReport[index], min(pSetup->wLength, report_len));
break;
}
default:
/* Not support. Reply STALL.*/
USBD_Stall0();
break;
}
}
/******************************************************************************************************************************************
* 函数名称: USBD_PrepareCtrlIn()
* 功能说明: Prepare the first Control IN pipe
* 输 入: 无
* 输 出: 无
* 注意事项: 无
******************************************************************************************************************************************/
void USBD_PrepareCtrlIn(uint8_t buf[], uint32_t size)
{
CtrlIn_Ptr = buf;
CtrlIn_Size = size;
USBD_CtrlIn();
}
/******************************************************************************************************************************************
* 函数名称: USBD_CtrlIn()
* 功能说明: Repeat Control IN pipe. This function processes the remained data of Control IN transfer
* 输 入: 无
* 输 出: 无
* 注意事项: 无
******************************************************************************************************************************************/
void USBD_CtrlIn(void)
{
static uint8_t ZeroLenPk = 0;
if(CtrlIn_Size)
{
/* Process remained data */
if(CtrlIn_Size > USBD_Info.CtrlPkSiz)
{
USBD_TxWrite(0, CtrlIn_Ptr, USBD_Info.CtrlPkSiz);
CtrlIn_Ptr += USBD_Info.CtrlPkSiz;
CtrlIn_Size -= USBD_Info.CtrlPkSiz;
}
else
{
USBD_TxWrite(0, CtrlIn_Ptr, CtrlIn_Size);
if(CtrlIn_Size == USBD_Info.CtrlPkSiz)
{
ZeroLenPk = 1;
}
CtrlIn_Ptr = 0;
CtrlIn_Size = 0;
}
}
else
{
/* For the case of data size is integral times maximum packet size */
if(ZeroLenPk)
{
ZeroLenPk = 0;
USBD_TxWrite(0, 0, 0);
}
}
}
/******************************************************************************************************************************************
* 函数名称: USBD_PrepareCtrlOut()
* 功能说明: Prepare the first Control OUT pipe
* 输 入: 无
* 输 出: 无
* 注意事项: 无
******************************************************************************************************************************************/
void USBD_PrepareCtrlOut(uint8_t *buf, uint32_t size)
{
CtrlOut_Ptr = buf;
CtrlOut_Size = 0u;
CtrlOut_Limit = size;
USBD_RxReady(0);
}
/******************************************************************************************************************************************
* 函数名称: USBD_CtrlOut()
* 功能说明: Repeat Control OUT pipe. This function processes the successive Control OUT transfer
* 输 入: 无
* 输 出: 无
* 注意事项: 无
******************************************************************************************************************************************/
void USBD_CtrlOut(void)
{
if(CtrlOut_Size < CtrlOut_Limit)
{
uint16_t size = USBD_RxRead(CtrlOut_Ptr, CtrlOut_Limit - CtrlOut_Size);
CtrlOut_Ptr += size;
CtrlOut_Size += size;
if(CtrlOut_Size < CtrlOut_Limit)
{
USBD_RxReady(0);
}
}
}
/******************************************************************************************************************************************
* 函数名称: USBD_TxWrite()
* 功能说明: 将要发送到主机的数据写入端点的FIFO
* 输 入: uint8_t epnr endpoint number
* uint8_t *data 要写入FIFO的数据
* uint16_t size 要写入数据的个数
* 输 出: 无
* 注意事项: 无
******************************************************************************************************************************************/
void USBD_TxWrite(uint8_t epnr, uint8_t *data, uint16_t size)
{
__disable_irq();
USBD->INEP[epnr].TXCR = (1 << USBD_TXCR_FLUSHFF_Pos);
USBD->INEP[epnr].TXTRSZ = size;
if(size) USBD_memcpy((uint8_t *)USBD->TXBUF[epnr], data, size);
USBD->INEP[epnr].TXCR = (1 << USBD_TXCR_FFRDY_Pos);
__enable_irq();
}
/******************************************************************************************************************************************
* 函数名称: USBD_RxRead()
* 功能说明: 读取接收到的数据
* 输 入: uint8_t *buff 读取到的数据存入buff
* uint16_t size buff大小
* 输 出: uint16_t 实际读取到数据的个数
* 注意事项: 无
******************************************************************************************************************************************/
uint16_t USBD_RxRead(uint8_t *buff, uint16_t size)
{
__disable_irq();
uint16_t real_size = (USBD->RXSR & USBD_RXSR_TRSZ_Msk) >> USBD_RXSR_TRSZ_Pos;
if(size > real_size)
size = real_size;
USBD_memcpy(buff, (uint8_t *)USBD->RXBUF, size);
__enable_irq();
return size;
}
/******************************************************************************************************************************************
* 函数名称: USBD_memcpy()
* 功能说明: 访问 USB Buffer 的 memcpy
* 输 入: void *destin 目的地址
* void *source 源地址
* uint32_t nByte 拷贝字节数
* 输 出: 无
* 注意事项: 访问 USB Buffer 必须使用 USBD_memcpy不能使用库函数 memcpy
******************************************************************************************************************************************/
void USBD_memcpy(uint8_t *destin, uint8_t *source, uint32_t nByte)
{
while(nByte > 3)
{
*((uint32_t *)destin) = *((uint32_t *)source);
destin += 4;
source += 4;
nByte -= 4;
}
while(nByte > 1)
{
*((uint16_t *)destin) = *((uint16_t *)source);
destin += 2;
source += 2;
nByte -= 2;
}
while(nByte > 0)
{
*destin = *source;
destin += 1;
source += 1;
nByte -= 1;
}
}