mirror of https://github.com/XIVN1987/DAPLink
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
486 lines
14 KiB
486 lines
14 KiB
#include "NuMicro.h" |
|
#include "vcom_serial.h" |
|
#include "hid_transfer.h" |
|
|
|
|
|
void HID_InitEP(int usbhs) |
|
{ |
|
/* EPA ==> HID Interrupt IN endpoint */ |
|
HSUSBD_ConfigEp(EPA, HID_INT_IN_EP & 0x0F, HSUSBD_EP_CFG_TYPE_INT, HSUSBD_EP_CFG_DIR_IN); |
|
HSUSBD_SetEpBufAddr(EPA, HID_INT_IN_BUF_BA, HID_INT_IN_BUF_SZ); |
|
HSUSBD_SET_MAX_PAYLOAD(EPA, usbhs ? HID_INT_IN_SZ_HS : HID_INT_IN_SZ_FS); |
|
HSUSBD_ENABLE_EP_INT(EPA, HSUSBD_EPINTEN_TXPKIEN_Msk); |
|
|
|
/* EPB ==> HID Interrupt OUT endpoint */ |
|
HSUSBD_ConfigEp(EPB, HID_INT_OUT_EP & 0x0F, HSUSBD_EP_CFG_TYPE_INT, HSUSBD_EP_CFG_DIR_OUT); |
|
HSUSBD_SetEpBufAddr(EPB, HID_INT_OUT_BUF_BA, HID_INT_OUT_BUF_SZ); |
|
HSUSBD_SET_MAX_PAYLOAD(EPB, usbhs ? HID_INT_OUT_SZ_HS : HID_INT_OUT_SZ_FS); |
|
HSUSBD_ENABLE_EP_INT(EPB, HSUSBD_EPINTEN_RXPKIEN_Msk); |
|
|
|
/* EPC ==> CDC Interrupt IN endpoint */ |
|
HSUSBD_ConfigEp(EPC, CDC_INT_IN_EP & 0x0F, HSUSBD_EP_CFG_TYPE_INT, HSUSBD_EP_CFG_DIR_IN); |
|
HSUSBD_SetEpBufAddr(EPC, CDC_INT_IN_BUF_BA, CDC_INT_IN_BUF_SZ); |
|
HSUSBD_SET_MAX_PAYLOAD(EPC, usbhs ? CDC_INT_IN_SZ_HS : CDC_INT_IN_SZ_FS); |
|
|
|
/* EPD ==> CDC Bulk IN endpoint */ |
|
HSUSBD_ConfigEp(EPD, CDC_BULK_IN_EP & 0x0F, HSUSBD_EP_CFG_TYPE_BULK, HSUSBD_EP_CFG_DIR_IN); |
|
HSUSBD->EP[EPD].EPRSPCTL = HSUSBD->EP[EPD].EPRSPCTL & (~HSUSBD_EP_RSPCTL_MODE_MASK) | HSUSBD_EP_RSPCTL_MODE_MANUAL; |
|
HSUSBD_SetEpBufAddr(EPD, CDC_BULK_IN_BUF_BA, CDC_BULK_IN_BUF_SZ); |
|
HSUSBD_SET_MAX_PAYLOAD(EPD, usbhs ? CDC_BULK_IN_SZ_HS : CDC_BULK_IN_SZ_FS); |
|
HSUSBD_ENABLE_EP_INT(EPD, HSUSBD_EPINTEN_TXPKIEN_Msk); |
|
|
|
/* EPE ==> CDC Bulk OUT endpoint */ |
|
HSUSBD_ConfigEp(EPE, CDC_BULK_OUT_EP & 0x0F, HSUSBD_EP_CFG_TYPE_BULK, HSUSBD_EP_CFG_DIR_OUT); |
|
HSUSBD_SetEpBufAddr(EPE, CDC_BULK_OUT_BUF_BA, CDC_BULK_OUT_BUF_SZ); |
|
HSUSBD_SET_MAX_PAYLOAD(EPE, usbhs ? CDC_BULK_OUT_SZ_HS : CDC_BULK_OUT_SZ_FS); |
|
HSUSBD_ENABLE_EP_INT(EPE, HSUSBD_EPINTEN_RXPKIEN_Msk); |
|
} |
|
|
|
|
|
void HID_Init(void) |
|
{ |
|
HSUSBD_SET_ADDR(0); |
|
|
|
/* Enable USB BUS, Control Endpoint and Endpoint A-E global interrupt */ |
|
HSUSBD_ENABLE_USB_INT(HSUSBD_GINTEN_USBIEN_Msk | |
|
HSUSBD_GINTEN_CEPIEN_Msk | |
|
HSUSBD_GINTEN_EPAIEN_Msk | |
|
HSUSBD_GINTEN_EPBIEN_Msk | |
|
HSUSBD_GINTEN_EPCIEN_Msk | |
|
HSUSBD_GINTEN_EPDIEN_Msk | |
|
HSUSBD_GINTEN_EPEIEN_Msk); |
|
|
|
/* Enable Plug-In/Un-Plug and Reset bus interrupt */ |
|
HSUSBD_ENABLE_BUS_INT(HSUSBD_BUSINTEN_VBUSDETIEN_Msk | |
|
HSUSBD_BUSINTEN_RSTIEN_Msk); |
|
|
|
/* Control endpoint */ |
|
HSUSBD_SetEpBufAddr(CEP, EP0_BUF_BASE, EP0_BUF_SIZE); |
|
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_SETUPPKIEN_Msk | |
|
HSUSBD_CEPINTEN_STSDONEIEN_Msk); |
|
|
|
HID_InitEP(0); |
|
} |
|
|
|
|
|
void EPA_Handler(void) // HID Interrupt IN |
|
{ |
|
HID_SetInReport(); |
|
} |
|
|
|
void EPB_Handler(void) // HID Interrupt OUT |
|
{ |
|
static uint8_t buff[1024]; |
|
|
|
int len = HSUSBD->EP[EPB].EPDATCNT & 0xFFFF; |
|
for(int i = 0; i < len; i++) |
|
buff[i] = HSUSBD->EP[EPB].EPDAT_BYTE; |
|
HID_GetOutReport(buff, len); |
|
} |
|
|
|
void EPD_Handler(void) // CDC Bulk IN |
|
{ |
|
Vcom.in_ready = 1; |
|
} |
|
|
|
void EPE_Handler(void) // CDC Bulk OUT |
|
{ |
|
Vcom.out_bytes = HSUSBD->EP[EPE].EPDATCNT & 0xFFFF; |
|
for(int i = 0; i < Vcom.out_bytes; i++) |
|
Vcom.out_buff[i] = HSUSBD->EP[EPE].EPDAT_BYTE; |
|
|
|
Vcom.out_ready = 1; |
|
} |
|
|
|
void USBD20_IRQHandler(void) |
|
{ |
|
uint32_t usb_if, bus_if, ept_if; |
|
|
|
usb_if = HSUSBD->GINTSTS & HSUSBD->GINTEN; |
|
|
|
/* Bus Event */ |
|
if(usb_if & HSUSBD_GINTSTS_USBIF_Msk) |
|
{ |
|
bus_if = HSUSBD->BUSINTSTS & HSUSBD->BUSINTEN; |
|
|
|
if(bus_if & HSUSBD_BUSINTSTS_VBUSDETIF_Msk) |
|
{ |
|
if(HSUSBD_IS_ATTACHED()) // USB Plug In |
|
{ |
|
HSUSBD_ENABLE_USB(); |
|
} |
|
else // USB Un-plug |
|
{ |
|
HSUSBD_DISABLE_USB(); |
|
} |
|
|
|
HSUSBD_CLR_BUS_INT_FLAG(HSUSBD_BUSINTSTS_VBUSDETIF_Msk); |
|
} |
|
|
|
if(bus_if & HSUSBD_BUSINTSTS_RSTIF_Msk) |
|
{ |
|
HSUSBD_SwReset(); |
|
HSUSBD_SET_ADDR(0); |
|
|
|
HID_InitEP(HSUSBD->OPER & HSUSBD_OPER_CURSPD_Msk); |
|
|
|
HSUSBD_CLR_CEP_INT_FLAG(0x1FFC); |
|
HSUSBD_CLR_BUS_INT_FLAG(HSUSBD_BUSINTSTS_RSTIF_Msk); |
|
} |
|
|
|
if(bus_if & HSUSBD_BUSINTSTS_SOFIF_Msk) |
|
{ |
|
HSUSBD_CLR_BUS_INT_FLAG(HSUSBD_BUSINTSTS_SOFIF_Msk); |
|
} |
|
} |
|
|
|
/* Control Endpoint */ |
|
if(usb_if & HSUSBD_GINTSTS_CEPIF_Msk) |
|
{ |
|
ept_if = HSUSBD->CEPINTSTS & HSUSBD->CEPINTEN; |
|
|
|
if(ept_if & HSUSBD_CEPINTSTS_SETUPPKIF_Msk) |
|
{ |
|
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_SETUPPKIF_Msk); |
|
HSUSBD_ProcessSetupPacket(); |
|
return; |
|
} |
|
|
|
if(ept_if & HSUSBD_CEPINTSTS_OUTTKIF_Msk) |
|
{ |
|
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_OUTTKIF_Msk); |
|
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk); |
|
return; |
|
} |
|
|
|
if(ept_if & HSUSBD_CEPINTSTS_INTKIF_Msk) |
|
{ |
|
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk); |
|
if(!(ept_if & HSUSBD_CEPINTSTS_STSDONEIF_Msk)) |
|
{ |
|
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_TXPKIF_Msk); |
|
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_TXPKIEN_Msk); |
|
HSUSBD_CtrlIn(); |
|
} |
|
else |
|
{ |
|
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_TXPKIF_Msk); |
|
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_TXPKIEN_Msk | HSUSBD_CEPINTEN_STSDONEIEN_Msk); |
|
} |
|
return; |
|
} |
|
|
|
if(ept_if & HSUSBD_CEPINTSTS_TXPKIF_Msk) |
|
{ |
|
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk); |
|
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR); |
|
if(g_hsusbd_CtrlInSize) |
|
{ |
|
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk); |
|
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_INTKIEN_Msk); |
|
} |
|
else |
|
{ |
|
if(g_hsusbd_CtrlZero == 1) |
|
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_ZEROLEN); |
|
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk); |
|
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_SETUPPKIEN_Msk|HSUSBD_CEPINTEN_STSDONEIEN_Msk); |
|
} |
|
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_TXPKIF_Msk); |
|
return; |
|
} |
|
|
|
if(ept_if & HSUSBD_CEPINTSTS_RXPKIF_Msk) |
|
{ |
|
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_RXPKIF_Msk); |
|
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR); |
|
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_SETUPPKIEN_Msk|HSUSBD_CEPINTEN_STSDONEIEN_Msk); |
|
return; |
|
} |
|
|
|
if(ept_if & HSUSBD_CEPINTSTS_STSDONEIF_Msk) |
|
{ |
|
HSUSBD_UpdateDeviceState(); |
|
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk); |
|
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_SETUPPKIEN_Msk); |
|
return; |
|
} |
|
} |
|
|
|
/* HID Interrupt IN */ |
|
if(usb_if & HSUSBD_GINTSTS_EPAIF_Msk) |
|
{ |
|
ept_if = HSUSBD->EP[EPA].EPINTSTS & HSUSBD->EP[EPA].EPINTEN; |
|
|
|
if(ept_if & HSUSBD_EPINTSTS_TXPKIF_Msk) |
|
EPA_Handler(); |
|
|
|
HSUSBD_CLR_EP_INT_FLAG(EPA, ept_if); |
|
} |
|
|
|
/* HID Interrupt OUT */ |
|
if(usb_if & HSUSBD_GINTSTS_EPBIF_Msk) |
|
{ |
|
ept_if = HSUSBD->EP[EPB].EPINTSTS & HSUSBD->EP[EPB].EPINTEN; |
|
|
|
if(ept_if & HSUSBD_EPINTSTS_RXPKIF_Msk) |
|
EPB_Handler(); |
|
|
|
HSUSBD_CLR_EP_INT_FLAG(EPB, ept_if); |
|
} |
|
|
|
/* CDC Interrupt IN */ |
|
if(usb_if & HSUSBD_GINTSTS_EPCIF_Msk) |
|
{ |
|
ept_if = HSUSBD->EP[EPC].EPINTSTS & HSUSBD->EP[EPC].EPINTEN; |
|
|
|
HSUSBD_CLR_EP_INT_FLAG(EPC, ept_if); |
|
} |
|
|
|
/* CDC Bulk IN */ |
|
if(usb_if & HSUSBD_GINTSTS_EPDIF_Msk) |
|
{ |
|
ept_if = HSUSBD->EP[EPD].EPINTSTS & HSUSBD->EP[EPD].EPINTEN; |
|
|
|
if(ept_if & HSUSBD_EPINTSTS_TXPKIF_Msk) |
|
EPD_Handler(); |
|
|
|
HSUSBD_CLR_EP_INT_FLAG(EPD, ept_if); |
|
} |
|
|
|
/* CDC Bulk OUT */ |
|
if(usb_if & HSUSBD_GINTSTS_EPEIF_Msk) |
|
{ |
|
ept_if = HSUSBD->EP[EPE].EPINTSTS & HSUSBD->EP[EPE].EPINTEN; |
|
|
|
if(ept_if & HSUSBD_EPINTSTS_RXPKIF_Msk) |
|
EPE_Handler(); |
|
|
|
HSUSBD_CLR_EP_INT_FLAG(EPE, ept_if); |
|
} |
|
|
|
if(usb_if & HSUSBD_GINTSTS_EPFIF_Msk) |
|
{ |
|
ept_if = HSUSBD->EP[EPF].EPINTSTS & HSUSBD->EP[EPF].EPINTEN; |
|
|
|
HSUSBD_CLR_EP_INT_FLAG(EPF, ept_if); |
|
} |
|
} |
|
|
|
|
|
void HID_ClassRequest(void) |
|
{ |
|
if(gUsbCmd.bmRequestType & 0x80) |
|
{ |
|
/* Device to host */ |
|
switch(gUsbCmd.bRequest) |
|
{ |
|
case GET_IDLE: |
|
case GET_REPORT: |
|
case GET_PROTOCOL: |
|
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk); |
|
break; |
|
|
|
case GET_LINE_CODE: |
|
HSUSBD_PrepareCtrlIn((uint8_t *)&LineCfg, 7); |
|
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk); |
|
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_INTKIEN_Msk); |
|
break; |
|
|
|
default: |
|
/* Setup error, stall the device */ |
|
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk); |
|
break; |
|
} |
|
} |
|
else |
|
{ |
|
/* Host to device */ |
|
switch(gUsbCmd.bRequest) |
|
{ |
|
case SET_IDLE: |
|
case SET_REPORT: |
|
/* Status stage */ |
|
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk); |
|
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR); |
|
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk); |
|
break; |
|
|
|
case SET_PROTOCOL: |
|
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk); |
|
break; |
|
|
|
case SET_LINE_CODE: |
|
HSUSBD_CtrlOut((uint8_t *)&LineCfg, 7); |
|
|
|
/* Status stage */ |
|
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk); |
|
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR); |
|
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk); |
|
break; |
|
|
|
case SET_CONTROL_LINE: |
|
Vcom.hw_flow = gUsbCmd.wValue; |
|
|
|
/* Status stage */ |
|
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk); |
|
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR); |
|
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk); |
|
break; |
|
|
|
default: |
|
/* Setup error, stall the device */ |
|
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
|
|
extern uint8_t MS_OS_20_DescriptorSet[]; |
|
void WINUSB_VendorRequest(void) |
|
{ |
|
uint16_t len; |
|
|
|
if(gUsbCmd.bmRequestType & 0x80) |
|
{ |
|
/* Device to host */ |
|
switch(gUsbCmd.bRequest) |
|
{ |
|
case WINUSB_VENDOR_CODE: |
|
switch(gUsbCmd.wIndex & 0xFF) |
|
{ |
|
case 7: |
|
len = Minimum(gUsbCmd.wLength, MS_OS_20_DescriptorSet[8] | (MS_OS_20_DescriptorSet[9] << 8)); |
|
HSUSBD_PrepareCtrlIn(MS_OS_20_DescriptorSet, len); |
|
|
|
/* Status stage */ |
|
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk); |
|
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_INTKIEN_Msk); |
|
return; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
/* Host to device */ |
|
} |
|
|
|
USBD_SetStall(0); |
|
} |
|
|
|
|
|
/***************************************************************/ |
|
#include "DAP_Config.h" |
|
#include "DAP.h" |
|
|
|
static volatile uint8_t USB_RequestFlag; // Request Buffer Usage Flag |
|
static volatile uint32_t USB_RequestIn; // Request Buffer In Index |
|
static volatile uint32_t USB_RequestOut; // Request Buffer Out Index |
|
|
|
static volatile uint8_t USB_ResponseIdle = 1; // Response Buffer Idle Flag |
|
static volatile uint8_t USB_ResponseFlag; // Response Buffer Usage Flag |
|
static volatile uint32_t USB_ResponseIn; // Response Buffer In Index |
|
static volatile uint32_t USB_ResponseOut; // Response Buffer Out Index |
|
|
|
static uint8_t USB_Request [DAP_PACKET_COUNT][DAP_PACKET_SIZE]; // Request Buffer |
|
static uint8_t USB_Response[DAP_PACKET_COUNT][DAP_PACKET_SIZE]; // Response Buffer |
|
static uint16_t USB_ResponseSize[DAP_PACKET_COUNT]; // number of bytes in response |
|
|
|
|
|
uint8_t usbd_hid_process(void) |
|
{ |
|
uint32_t n, len; |
|
|
|
if((USB_RequestOut != USB_RequestIn) || USB_RequestFlag) |
|
{ |
|
USB_ResponseSize[USB_ResponseIn] = DAP_ProcessCommand(USB_Request[USB_RequestOut], USB_Response[USB_ResponseIn]); |
|
|
|
// Update request index and flag |
|
n = USB_RequestOut + 1; |
|
if(n == DAP_PACKET_COUNT) |
|
n = 0; |
|
USB_RequestOut = n; |
|
|
|
if(USB_RequestOut == USB_RequestIn) |
|
USB_RequestFlag = 0; |
|
|
|
if(USB_ResponseIdle) |
|
{ |
|
USB_ResponseIdle = 0; |
|
|
|
#ifdef DAP_FW_V1 |
|
len = DAP_PACKET_SIZE; |
|
#else |
|
len = USB_ResponseSize[USB_ResponseIn]; |
|
#endif |
|
for(int i = 0; i < len; i++) |
|
HSUSBD->EP[EPA].EPDAT_BYTE = USB_Response[USB_ResponseIn][i]; |
|
HSUSBD->EP[EPA].EPTXCNT = len; |
|
} |
|
else |
|
{ |
|
n = USB_ResponseIn + 1; |
|
if(n == DAP_PACKET_COUNT) |
|
n = 0; |
|
USB_ResponseIn = n; |
|
|
|
if(USB_ResponseIn == USB_ResponseOut) |
|
USB_ResponseFlag = 1; |
|
} |
|
|
|
return 1; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
|
|
void HID_GetOutReport(uint8_t *buf, uint32_t len) |
|
{ |
|
if(buf[0] == ID_DAP_TransferAbort) |
|
{ |
|
DAP_TransferAbort = 1; |
|
return; |
|
} |
|
|
|
if(USB_RequestFlag && (USB_RequestIn == USB_RequestOut)) |
|
return; // Discard packet when buffer is full |
|
|
|
// Store data into request packet buffer |
|
USBD_MemCopy(USB_Request[USB_RequestIn], buf, len); |
|
|
|
USB_RequestIn++; |
|
if(USB_RequestIn == DAP_PACKET_COUNT) |
|
USB_RequestIn = 0; |
|
if(USB_RequestIn == USB_RequestOut) |
|
USB_RequestFlag = 1; |
|
} |
|
|
|
|
|
void HID_SetInReport(void) |
|
{ |
|
uint32_t len; |
|
|
|
if((USB_ResponseOut != USB_ResponseIn) || USB_ResponseFlag) |
|
{ |
|
#ifdef DAP_FW_V1 |
|
len = DAP_PACKET_SIZE; |
|
#else |
|
len = USB_ResponseSize[USB_ResponseOut]; |
|
#endif |
|
for(int i = 0; i < len; i++) |
|
HSUSBD->EP[EPA].EPDAT_BYTE = USB_Response[USB_ResponseOut][i]; |
|
HSUSBD->EP[EPA].EPTXCNT = len; |
|
|
|
USB_ResponseOut++; |
|
if (USB_ResponseOut == DAP_PACKET_COUNT) |
|
USB_ResponseOut = 0; |
|
if (USB_ResponseOut == USB_ResponseIn) |
|
USB_ResponseFlag = 0; |
|
} |
|
else |
|
{ |
|
USB_ResponseIdle = 1; |
|
} |
|
}
|
|
|