Add USB HID support. Runs as an alternative to VCP+MSC.
This commit is contained in:
parent
2839168340
commit
58a1b4c6cf
@ -75,6 +75,7 @@ SRC_STM = \
|
|||||||
usbd_usr.c \
|
usbd_usr.c \
|
||||||
usbd_desc.c \
|
usbd_desc.c \
|
||||||
usbd_pyb_core.c \
|
usbd_pyb_core.c \
|
||||||
|
usbd_pyb_core2.c \
|
||||||
usbd_cdc_vcp.c \
|
usbd_cdc_vcp.c \
|
||||||
usbd_msc_bot.c \
|
usbd_msc_bot.c \
|
||||||
usbd_msc_data.c \
|
usbd_msc_data.c \
|
||||||
|
@ -73,12 +73,27 @@
|
|||||||
#include "usbd_msc_bot.h"
|
#include "usbd_msc_bot.h"
|
||||||
#include "usbd_msc_mem.h"
|
#include "usbd_msc_mem.h"
|
||||||
|
|
||||||
#define USB_PYB_CONFIG_DESC_SIZ (98) // for both CDC VCP and MSC interfaces
|
#define USB_PYB_USE_MSC (1)
|
||||||
|
|
||||||
|
#if USB_PYB_USE_MSC
|
||||||
//#define USB_PYB_CONFIG_DESC_SIZ (67) // for only CDC VCP interfaces
|
//#define USB_PYB_CONFIG_DESC_SIZ (67) // for only CDC VCP interfaces
|
||||||
|
#define USB_PYB_CONFIG_DESC_SIZ (98) // for both CDC VCP and MSC interfaces
|
||||||
|
#else // USE_HID
|
||||||
|
#define USB_PYB_CONFIG_DESC_SIZ (100) // for both CDC VCP and HID interfaces
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MSC_EPIN_SIZE MSC_MAX_PACKET
|
#define MSC_EPIN_SIZE MSC_MAX_PACKET
|
||||||
#define MSC_EPOUT_SIZE MSC_MAX_PACKET
|
#define MSC_EPOUT_SIZE MSC_MAX_PACKET
|
||||||
|
|
||||||
|
#define HID_MOUSE_REPORT_DESC_SIZE (74)
|
||||||
|
|
||||||
|
#define HID_DESCRIPTOR_TYPE 0x21
|
||||||
|
#define HID_REPORT_DESC 0x22
|
||||||
|
|
||||||
|
// HID parameters
|
||||||
|
#define HID_IN_EP (0x83)
|
||||||
|
#define HID_IN_PACKET (4) /* maximum, and actual, packet size */
|
||||||
|
|
||||||
/*********************************************
|
/*********************************************
|
||||||
PYB Device library callbacks
|
PYB Device library callbacks
|
||||||
*********************************************/
|
*********************************************/
|
||||||
@ -108,8 +123,14 @@ __ALIGN_BEGIN uint8_t APP_Rx_Buffer[APP_RX_DATA_SIZE] __ALIGN_END;
|
|||||||
|
|
||||||
__ALIGN_BEGIN static uint8_t CmdBuff[CDC_CMD_PACKET_SZE] __ALIGN_END;
|
__ALIGN_BEGIN static uint8_t CmdBuff[CDC_CMD_PACKET_SZE] __ALIGN_END;
|
||||||
|
|
||||||
|
#if USB_PYB_USE_MSC
|
||||||
__ALIGN_BEGIN static uint8_t USBD_MSC_MaxLun __ALIGN_END = 0;
|
__ALIGN_BEGIN static uint8_t USBD_MSC_MaxLun __ALIGN_END = 0;
|
||||||
__ALIGN_BEGIN static uint8_t USBD_MSC_AltSet __ALIGN_END = 0;
|
__ALIGN_BEGIN static uint8_t USBD_MSC_AltSet __ALIGN_END = 0;
|
||||||
|
#else
|
||||||
|
__ALIGN_BEGIN static uint8_t USBD_HID_AltSet __ALIGN_END = 0;
|
||||||
|
__ALIGN_BEGIN static uint8_t USBD_HID_Protocol __ALIGN_END = 0;
|
||||||
|
__ALIGN_BEGIN static uint8_t USBD_HID_IdleState __ALIGN_END = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
uint32_t APP_Rx_ptr_in = 0;
|
uint32_t APP_Rx_ptr_in = 0;
|
||||||
uint32_t APP_Rx_ptr_out = 0;
|
uint32_t APP_Rx_ptr_out = 0;
|
||||||
@ -246,6 +267,7 @@ __ALIGN_BEGIN static uint8_t usbd_pyb_CfgDesc[USB_PYB_CONFIG_DESC_SIZ] __ALIGN_E
|
|||||||
HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
|
HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
|
||||||
0x00, // bInterval: ignore for Bulk transfer
|
0x00, // bInterval: ignore for Bulk transfer
|
||||||
|
|
||||||
|
#if USB_PYB_USE_MSC
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
// MSC only has 1 interface so doesn't need an IAD
|
// MSC only has 1 interface so doesn't need an IAD
|
||||||
|
|
||||||
@ -278,8 +300,97 @@ __ALIGN_BEGIN static uint8_t usbd_pyb_CfgDesc[USB_PYB_CONFIG_DESC_SIZ] __ALIGN_E
|
|||||||
LOBYTE(MSC_MAX_PACKET), // wMaxPacketSize
|
LOBYTE(MSC_MAX_PACKET), // wMaxPacketSize
|
||||||
HIBYTE(MSC_MAX_PACKET),
|
HIBYTE(MSC_MAX_PACKET),
|
||||||
0x00, // bInterval: ignore for Bulk transfer
|
0x00, // bInterval: ignore for Bulk transfer
|
||||||
|
|
||||||
|
#else
|
||||||
|
//==========================================================================
|
||||||
|
// HID only has 1 interface so doesn't need an IAD
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Interface Descriptor
|
||||||
|
0x09, // bLength: Interface Descriptor size
|
||||||
|
USB_INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType: interface descriptor
|
||||||
|
0x02, // bInterfaceNumber: Number of Interface
|
||||||
|
0x00, // bAlternateSetting: Alternate setting
|
||||||
|
0x01, // bNumEndpoints
|
||||||
|
0x03, // bInterfaceClass: HID Class
|
||||||
|
0x01, // bInterfaceSubClass: 0=no boot, 1=BOOT
|
||||||
|
0x01, // nInterfaceProtocol: 0=none, 1=keyboard, 2=mouse
|
||||||
|
0x00, // iInterface:
|
||||||
|
|
||||||
|
// Descriptor of Joystick Mouse HID
|
||||||
|
0x09, // bLength: HID Descriptor size
|
||||||
|
HID_DESCRIPTOR_TYPE, // bDescriptorType: HID
|
||||||
|
0x11, // bcdHID: HID Class Spec release number, low byte
|
||||||
|
0x01, // bcdHID: high byte
|
||||||
|
0x00, // bCountryCode: Hardware target country (0=unsupported)
|
||||||
|
0x01, // bNumDescriptors: Number of HID class descriptors to follow
|
||||||
|
HID_REPORT_DESC, // bDescriptorType: report
|
||||||
|
HID_MOUSE_REPORT_DESC_SIZE, // wItemLength: Total length of Report descriptor
|
||||||
|
0x00,
|
||||||
|
|
||||||
|
// Endpoint IN descriptor
|
||||||
|
0x07, // bLength: Endpoint descriptor length
|
||||||
|
USB_ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType: Endpoint descriptor type
|
||||||
|
HID_IN_EP, // bEndpointAddress: IN, address of HID
|
||||||
|
0x03, // bmAttributes: Interrupt endpoint type
|
||||||
|
LOBYTE(HID_IN_PACKET), // wMaxPacketSize
|
||||||
|
HIBYTE(HID_IN_PACKET),
|
||||||
|
0x0a, // bInterval: polling interval, units of 1ms
|
||||||
|
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
|
||||||
|
{
|
||||||
|
0x05, 0x01,
|
||||||
|
0x09, 0x02,
|
||||||
|
0xA1, 0x01,
|
||||||
|
0x09, 0x01,
|
||||||
|
|
||||||
|
0xA1, 0x00,
|
||||||
|
0x05, 0x09,
|
||||||
|
0x19, 0x01,
|
||||||
|
0x29, 0x03,
|
||||||
|
|
||||||
|
0x15, 0x00,
|
||||||
|
0x25, 0x01,
|
||||||
|
0x95, 0x03,
|
||||||
|
0x75, 0x01,
|
||||||
|
|
||||||
|
0x81, 0x02,
|
||||||
|
0x95, 0x01,
|
||||||
|
0x75, 0x05,
|
||||||
|
0x81, 0x01,
|
||||||
|
|
||||||
|
0x05, 0x01,
|
||||||
|
0x09, 0x30,
|
||||||
|
0x09, 0x31,
|
||||||
|
0x09, 0x38,
|
||||||
|
|
||||||
|
0x15, 0x81,
|
||||||
|
0x25, 0x7F,
|
||||||
|
0x75, 0x08,
|
||||||
|
0x95, 0x03,
|
||||||
|
|
||||||
|
0x81, 0x06,
|
||||||
|
0xC0, 0x09,
|
||||||
|
0x3c, 0x05,
|
||||||
|
0xff, 0x09,
|
||||||
|
|
||||||
|
0x01, 0x15,
|
||||||
|
0x00, 0x25,
|
||||||
|
0x01, 0x75,
|
||||||
|
0x01, 0x95,
|
||||||
|
|
||||||
|
0x02, 0xb1,
|
||||||
|
0x22, 0x75,
|
||||||
|
0x06, 0x95,
|
||||||
|
0x01, 0xb1,
|
||||||
|
|
||||||
|
0x01, 0xc0
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/** @defgroup usbd_pyb_Private_Functions
|
/** @defgroup usbd_pyb_Private_Functions
|
||||||
* @{
|
* @{
|
||||||
@ -333,6 +444,7 @@ static uint8_t usbd_pyb_Init(void *pdev, uint8_t cfgidx) {
|
|||||||
(uint8_t*)(USB_Rx_Buffer),
|
(uint8_t*)(USB_Rx_Buffer),
|
||||||
CDC_DATA_OUT_PACKET_SIZE);
|
CDC_DATA_OUT_PACKET_SIZE);
|
||||||
|
|
||||||
|
#if USB_PYB_USE_MSC
|
||||||
//----------------------------------
|
//----------------------------------
|
||||||
// MSC component
|
// MSC component
|
||||||
|
|
||||||
@ -351,6 +463,17 @@ static uint8_t usbd_pyb_Init(void *pdev, uint8_t cfgidx) {
|
|||||||
// Init the BOT layer
|
// Init the BOT layer
|
||||||
MSC_BOT_Init(pdev);
|
MSC_BOT_Init(pdev);
|
||||||
|
|
||||||
|
#else
|
||||||
|
//----------------------------------
|
||||||
|
// HID component
|
||||||
|
|
||||||
|
// Open EP IN
|
||||||
|
DCD_EP_Open(pdev,
|
||||||
|
HID_IN_EP,
|
||||||
|
HID_IN_PACKET,
|
||||||
|
USB_OTG_EP_INT);
|
||||||
|
#endif
|
||||||
|
|
||||||
return USBD_OK;
|
return USBD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,6 +495,7 @@ static uint8_t usbd_pyb_DeInit(void *pdev, uint8_t cfgidx) {
|
|||||||
// Restore default state of the Interface physical components
|
// Restore default state of the Interface physical components
|
||||||
VCP_fops.pIf_DeInit();
|
VCP_fops.pIf_DeInit();
|
||||||
|
|
||||||
|
#if USB_PYB_USE_MSC
|
||||||
//----------------------------------
|
//----------------------------------
|
||||||
// MSC component
|
// MSC component
|
||||||
|
|
||||||
@ -382,12 +506,27 @@ static uint8_t usbd_pyb_DeInit(void *pdev, uint8_t cfgidx) {
|
|||||||
// Un Init the BOT layer
|
// Un Init the BOT layer
|
||||||
MSC_BOT_DeInit(pdev);
|
MSC_BOT_DeInit(pdev);
|
||||||
|
|
||||||
|
#else
|
||||||
|
//----------------------------------
|
||||||
|
// HID component
|
||||||
|
|
||||||
|
// Close HID EP
|
||||||
|
DCD_EP_Close(pdev, HID_IN_EP);
|
||||||
|
#endif
|
||||||
|
|
||||||
return USBD_OK;
|
return USBD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BOT_GET_MAX_LUN 0xFE
|
#define BOT_GET_MAX_LUN 0xFE
|
||||||
#define BOT_RESET 0xFF
|
#define BOT_RESET 0xFF
|
||||||
|
|
||||||
|
#define HID_REQ_SET_PROTOCOL (0x0B)
|
||||||
|
#define HID_REQ_GET_PROTOCOL (0x03)
|
||||||
|
#define HID_REQ_SET_IDLE (0x0A)
|
||||||
|
#define HID_REQ_GET_IDLE (0x02)
|
||||||
|
#define HID_REQ_SET_REPORT (0x09) // used?
|
||||||
|
#define HID_REQ_GET_REPORT (0x01) // used?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief usbd_pyb_Setup
|
* @brief usbd_pyb_Setup
|
||||||
* Handle the CDC specific requests
|
* Handle the CDC specific requests
|
||||||
@ -411,6 +550,7 @@ static uint8_t usbd_pyb_Setup(void *pdev, USB_SETUP_REQ *req) {
|
|||||||
len = MIN(USB_CDC_DESC_SIZ, req->wLength); // TODO
|
len = MIN(USB_CDC_DESC_SIZ, req->wLength); // TODO
|
||||||
}
|
}
|
||||||
return USBD_CtlSendData(pdev, pbuf, len);
|
return USBD_CtlSendData(pdev, pbuf, len);
|
||||||
|
// TODO stuff here for HID, using HID_MOUSE_ReportDesc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
@ -424,7 +564,11 @@ static uint8_t usbd_pyb_Setup(void *pdev, USB_SETUP_REQ *req) {
|
|||||||
if ((req->wIndex & 0xff) <= 1) {
|
if ((req->wIndex & 0xff) <= 1) {
|
||||||
return USBD_CtlSendData(pdev, &usbd_cdc_AltSet, 1);
|
return USBD_CtlSendData(pdev, &usbd_cdc_AltSet, 1);
|
||||||
} else {
|
} else {
|
||||||
|
#if USB_PYB_USE_MSC
|
||||||
return USBD_CtlSendData(pdev, &USBD_MSC_AltSet, 1);
|
return USBD_CtlSendData(pdev, &USBD_MSC_AltSet, 1);
|
||||||
|
#else
|
||||||
|
return USBD_CtlSendData(pdev, &USBD_HID_AltSet, 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
case USB_REQ_SET_INTERFACE:
|
case USB_REQ_SET_INTERFACE:
|
||||||
@ -432,7 +576,11 @@ static uint8_t usbd_pyb_Setup(void *pdev, USB_SETUP_REQ *req) {
|
|||||||
if ((req->wIndex & 0xff) <= 1) {
|
if ((req->wIndex & 0xff) <= 1) {
|
||||||
usbd_cdc_AltSet = req->wValue;
|
usbd_cdc_AltSet = req->wValue;
|
||||||
} else {
|
} else {
|
||||||
|
#if USB_PYB_USE_MSC
|
||||||
USBD_MSC_AltSet = req->wValue;
|
USBD_MSC_AltSet = req->wValue;
|
||||||
|
#else
|
||||||
|
USBD_HID_AltSet = req->wValue;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return USBD_OK;
|
return USBD_OK;
|
||||||
}
|
}
|
||||||
@ -442,6 +590,7 @@ static uint8_t usbd_pyb_Setup(void *pdev, USB_SETUP_REQ *req) {
|
|||||||
// Standard Endpoint Request -------------------------------------------
|
// Standard Endpoint Request -------------------------------------------
|
||||||
case (USB_REQ_TYPE_STANDARD | USB_REQ_RECIPIENT_ENDPOINT):
|
case (USB_REQ_TYPE_STANDARD | USB_REQ_RECIPIENT_ENDPOINT):
|
||||||
// req->wIndex is the endpoint number, including direction
|
// req->wIndex is the endpoint number, including direction
|
||||||
|
#if USB_PYB_USE_MSC
|
||||||
if (req->wIndex == MSC_IN_EP || req->wIndex == MSC_OUT_EP) {
|
if (req->wIndex == MSC_IN_EP || req->wIndex == MSC_OUT_EP) {
|
||||||
// MSC component
|
// MSC component
|
||||||
switch (req->bRequest) {
|
switch (req->bRequest) {
|
||||||
@ -464,6 +613,7 @@ static uint8_t usbd_pyb_Setup(void *pdev, USB_SETUP_REQ *req) {
|
|||||||
return USBD_OK;
|
return USBD_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// CDC Class Requests ------------------------------
|
// CDC Class Requests ------------------------------
|
||||||
@ -502,6 +652,7 @@ static uint8_t usbd_pyb_Setup(void *pdev, USB_SETUP_REQ *req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else if (req->wIndex == 2) {
|
} else if (req->wIndex == 2) {
|
||||||
|
#if USB_PYB_USE_MSC
|
||||||
// MSC component
|
// MSC component
|
||||||
switch (req->bRequest) {
|
switch (req->bRequest) {
|
||||||
case BOT_GET_MAX_LUN:
|
case BOT_GET_MAX_LUN:
|
||||||
@ -520,6 +671,24 @@ static uint8_t usbd_pyb_Setup(void *pdev, USB_SETUP_REQ *req) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
// HID component
|
||||||
|
switch (req->bRequest) {
|
||||||
|
case HID_REQ_SET_PROTOCOL:
|
||||||
|
USBD_HID_Protocol = req->wValue;
|
||||||
|
return USBD_OK;
|
||||||
|
|
||||||
|
case HID_REQ_GET_PROTOCOL:
|
||||||
|
return USBD_CtlSendData(pdev, &USBD_HID_Protocol, 1);
|
||||||
|
|
||||||
|
case HID_REQ_SET_IDLE:
|
||||||
|
USBD_HID_IdleState = (req->wValue >> 8);
|
||||||
|
return USBD_OK;
|
||||||
|
|
||||||
|
case HID_REQ_GET_IDLE:
|
||||||
|
return USBD_CtlSendData(pdev, &USBD_HID_IdleState, 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -590,9 +759,18 @@ static uint8_t usbd_pyb_DataIn(void *pdev, uint8_t epnum) {
|
|||||||
}
|
}
|
||||||
return USBD_OK;
|
return USBD_OK;
|
||||||
|
|
||||||
|
#if USB_PYB_USE_MSC
|
||||||
case (MSC_IN_EP & 0x7f): // TODO?
|
case (MSC_IN_EP & 0x7f): // TODO?
|
||||||
MSC_BOT_DataIn(pdev, epnum);
|
MSC_BOT_DataIn(pdev, epnum);
|
||||||
return USBD_OK;
|
return USBD_OK;
|
||||||
|
|
||||||
|
#else
|
||||||
|
case (HID_IN_EP & 0x7f):
|
||||||
|
/* Ensure that the FIFO is empty before a new transfer, this condition could
|
||||||
|
be caused by a new transfer before the end of the previous transfer */
|
||||||
|
DCD_EP_Flush(pdev, HID_IN_EP);
|
||||||
|
return USBD_OK;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("DI %x\n", epnum);
|
printf("DI %x\n", epnum);
|
||||||
@ -626,9 +804,11 @@ static uint8_t usbd_pyb_DataOut(void *pdev, uint8_t epnum) {
|
|||||||
CDC_DATA_OUT_PACKET_SIZE);
|
CDC_DATA_OUT_PACKET_SIZE);
|
||||||
return USBD_OK;
|
return USBD_OK;
|
||||||
|
|
||||||
|
#if USB_PYB_USE_MSC
|
||||||
case (MSC_OUT_EP & 0x7f): // TODO is this correct?
|
case (MSC_OUT_EP & 0x7f): // TODO is this correct?
|
||||||
MSC_BOT_DataOut(pdev, epnum);
|
MSC_BOT_DataOut(pdev, epnum);
|
||||||
return USBD_OK;
|
return USBD_OK;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("DO %x\n", epnum);
|
printf("DO %x\n", epnum);
|
||||||
@ -733,3 +913,19 @@ static uint8_t *usbd_pyb_GetCfgDesc(uint8_t speed, uint16_t *length) {
|
|||||||
*length = sizeof(usbd_pyb_CfgDesc);
|
*length = sizeof(usbd_pyb_CfgDesc);
|
||||||
return usbd_pyb_CfgDesc;
|
return usbd_pyb_CfgDesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief USBD_HID_SendReport
|
||||||
|
* Send HID Report
|
||||||
|
* @param pdev: device instance
|
||||||
|
* @param buff: pointer to report (4 bytes: ?, x, y, ?)
|
||||||
|
* @retval status
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
uint8_t USBD_HID_SendReport(USB_OTG_CORE_HANDLE *pdev, uint8_t *report, uint16_t len) {
|
||||||
|
if (pdev->dev.device_status == USB_OTG_CONFIGURED) {
|
||||||
|
DCD_EP_Tx(pdev, HID_IN_EP, report, len);
|
||||||
|
}
|
||||||
|
return USBD_OK;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
@ -1 +1,4 @@
|
|||||||
extern USBD_Class_cb_TypeDef USBD_PYB_cb;
|
extern USBD_Class_cb_TypeDef USBD_PYB_cb;
|
||||||
|
extern USBD_Class_cb_TypeDef USBD_PYB_HID_cb;
|
||||||
|
|
||||||
|
uint8_t USBD_HID_SendReport(USB_OTG_CORE_HANDLE *pdev, uint8_t *report, uint16_t len);
|
||||||
|
323
stm/lib/usbd_pyb_core2.c
Normal file
323
stm/lib/usbd_pyb_core2.c
Normal file
@ -0,0 +1,323 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "usbd_ioreq.h"
|
||||||
|
#include "usbd_desc.h"
|
||||||
|
#include "usbd_req.h"
|
||||||
|
#include "usbd_pyb_core.h"
|
||||||
|
|
||||||
|
#define USB_PYB_CONFIG_DESC_SIZ (34)
|
||||||
|
|
||||||
|
#define HID_MOUSE_REPORT_DESC_SIZE (74)
|
||||||
|
|
||||||
|
#define HID_DESCRIPTOR_TYPE (0x21)
|
||||||
|
#define HID_REPORT_DESC (0x22)
|
||||||
|
|
||||||
|
#define HID_IN_EP (0x81)
|
||||||
|
#define HID_IN_PACKET (4) /* maximum, and actual, packet size */
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
PYB Device library callbacks
|
||||||
|
*********************************************/
|
||||||
|
|
||||||
|
static uint8_t usbd_pyb_Init (void *pdev, uint8_t cfgidx);
|
||||||
|
static uint8_t usbd_pyb_DeInit (void *pdev, uint8_t cfgidx);
|
||||||
|
static uint8_t usbd_pyb_Setup (void *pdev, USB_SETUP_REQ *req);
|
||||||
|
static uint8_t usbd_pyb_DataIn (void *pdev, uint8_t epnum);
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
PYB specific management functions
|
||||||
|
*********************************************/
|
||||||
|
|
||||||
|
static uint8_t *usbd_pyb_GetCfgDesc(uint8_t speed, uint16_t *length);
|
||||||
|
|
||||||
|
__ALIGN_BEGIN static uint8_t USBD_HID_AltSet __ALIGN_END = 0;
|
||||||
|
__ALIGN_BEGIN static uint8_t USBD_HID_Protocol __ALIGN_END = 0;
|
||||||
|
__ALIGN_BEGIN static uint8_t USBD_HID_IdleState __ALIGN_END = 0;
|
||||||
|
|
||||||
|
/* PYB interface class callbacks structure */
|
||||||
|
USBD_Class_cb_TypeDef USBD_PYB_HID_cb =
|
||||||
|
{
|
||||||
|
usbd_pyb_Init,
|
||||||
|
usbd_pyb_DeInit,
|
||||||
|
usbd_pyb_Setup,
|
||||||
|
NULL, // EP0_TxSent
|
||||||
|
NULL, // usbd_pyb_EP0_RxReady,
|
||||||
|
usbd_pyb_DataIn,
|
||||||
|
NULL, // usbd_pyb_DataOut,
|
||||||
|
NULL, // usbd_pyb_SOF,
|
||||||
|
NULL, // IsoINIncomplete
|
||||||
|
NULL, // IsoOUTIncomplete
|
||||||
|
usbd_pyb_GetCfgDesc,
|
||||||
|
// for OTG_HS support need to add other cfg desc here
|
||||||
|
};
|
||||||
|
|
||||||
|
/* USB PYB device Configuration Descriptor */
|
||||||
|
__ALIGN_BEGIN static uint8_t usbd_pyb_CfgDesc[USB_PYB_CONFIG_DESC_SIZ] __ALIGN_END =
|
||||||
|
{
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Configuration Descriptor
|
||||||
|
0x09, // bLength: Configuration Descriptor size
|
||||||
|
USB_CONFIGURATION_DESCRIPTOR_TYPE, // bDescriptorType: Configuration
|
||||||
|
LOBYTE(USB_PYB_CONFIG_DESC_SIZ), // wTotalLength: no of returned bytes
|
||||||
|
HIBYTE(USB_PYB_CONFIG_DESC_SIZ),
|
||||||
|
0x01, // bNumInterfaces: 1 interfaces
|
||||||
|
0x01, // bConfigurationValue: Configuration value
|
||||||
|
0x04, // iConfiguration: Index of string descriptor describing the configuration
|
||||||
|
0x80, // bmAttributes: bus powered; 0xc0 for self powered
|
||||||
|
0xfa, // bMaxPower: in units of 2mA
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Interface Descriptor
|
||||||
|
0x09, // bLength: Interface Descriptor size
|
||||||
|
USB_INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType: interface descriptor
|
||||||
|
0x00, // bInterfaceNumber: Number of Interface
|
||||||
|
0x00, // bAlternateSetting: Alternate setting
|
||||||
|
0x01, // bNumEndpoints
|
||||||
|
0x03, // bInterfaceClass: HID Class
|
||||||
|
0x01, // bInterfaceSubClass: 0=no boot, 1=BOOT
|
||||||
|
0x02, // nInterfaceProtocol: 0=none, 1=keyboard, 2=mouse
|
||||||
|
0x00, // iInterface:
|
||||||
|
|
||||||
|
// Descriptor of Joystick Mouse HID
|
||||||
|
0x09, // bLength: HID Descriptor size
|
||||||
|
HID_DESCRIPTOR_TYPE, // bDescriptorType: HID
|
||||||
|
0x11, // bcdHID: HID Class Spec release number, low byte
|
||||||
|
0x01, // bcdHID: high byte
|
||||||
|
0x00, // bCountryCode: Hardware target country (0=unsupported)
|
||||||
|
0x01, // bNumDescriptors: Number of HID class descriptors to follow
|
||||||
|
HID_REPORT_DESC, // bDescriptorType: report
|
||||||
|
HID_MOUSE_REPORT_DESC_SIZE, // wItemLength: Total length of Report descriptor
|
||||||
|
0x00,
|
||||||
|
|
||||||
|
// Endpoint IN descriptor
|
||||||
|
0x07, // bLength: Endpoint descriptor length
|
||||||
|
USB_ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType: Endpoint descriptor type
|
||||||
|
HID_IN_EP, // bEndpointAddress: IN, address of HID
|
||||||
|
0x03, // bmAttributes: Interrupt endpoint type
|
||||||
|
LOBYTE(HID_IN_PACKET), // wMaxPacketSize
|
||||||
|
HIBYTE(HID_IN_PACKET),
|
||||||
|
0x0a, // bInterval: polling interval, units of 1ms
|
||||||
|
};
|
||||||
|
|
||||||
|
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
|
||||||
|
{
|
||||||
|
0x05, 0x01,
|
||||||
|
0x09, 0x02,
|
||||||
|
0xA1, 0x01,
|
||||||
|
0x09, 0x01,
|
||||||
|
|
||||||
|
0xA1, 0x00,
|
||||||
|
0x05, 0x09,
|
||||||
|
0x19, 0x01,
|
||||||
|
0x29, 0x03,
|
||||||
|
|
||||||
|
0x15, 0x00,
|
||||||
|
0x25, 0x01,
|
||||||
|
0x95, 0x03,
|
||||||
|
0x75, 0x01,
|
||||||
|
|
||||||
|
0x81, 0x02,
|
||||||
|
0x95, 0x01,
|
||||||
|
0x75, 0x05,
|
||||||
|
0x81, 0x01,
|
||||||
|
|
||||||
|
0x05, 0x01,
|
||||||
|
0x09, 0x30,
|
||||||
|
0x09, 0x31,
|
||||||
|
0x09, 0x38,
|
||||||
|
|
||||||
|
0x15, 0x81,
|
||||||
|
0x25, 0x7F,
|
||||||
|
0x75, 0x08,
|
||||||
|
0x95, 0x03,
|
||||||
|
|
||||||
|
0x81, 0x06,
|
||||||
|
0xC0, 0x09,
|
||||||
|
0x3c, 0x05,
|
||||||
|
0xff, 0x09,
|
||||||
|
|
||||||
|
0x01, 0x15,
|
||||||
|
0x00, 0x25,
|
||||||
|
0x01, 0x75,
|
||||||
|
0x01, 0x95,
|
||||||
|
|
||||||
|
0x02, 0xb1,
|
||||||
|
0x22, 0x75,
|
||||||
|
0x06, 0x95,
|
||||||
|
0x01, 0xb1,
|
||||||
|
|
||||||
|
0x01, 0xc0
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief usbd_pyb_Init
|
||||||
|
* Initilaize the PYB interface
|
||||||
|
* @param pdev: device instance
|
||||||
|
* @param cfgidx: Configuration index
|
||||||
|
* @retval status
|
||||||
|
*/
|
||||||
|
static uint8_t usbd_pyb_Init(void *pdev, uint8_t cfgidx) {
|
||||||
|
// deinit first to reset
|
||||||
|
usbd_pyb_DeInit(pdev, cfgidx);
|
||||||
|
|
||||||
|
// Open EP IN
|
||||||
|
DCD_EP_Open(pdev,
|
||||||
|
HID_IN_EP,
|
||||||
|
HID_IN_PACKET,
|
||||||
|
USB_OTG_EP_INT);
|
||||||
|
|
||||||
|
return USBD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief usbd_pyb_Init
|
||||||
|
* DeInitialize the CDC layer
|
||||||
|
* @param pdev: device instance
|
||||||
|
* @param cfgidx: Configuration index
|
||||||
|
* @retval status
|
||||||
|
*/
|
||||||
|
static uint8_t usbd_pyb_DeInit(void *pdev, uint8_t cfgidx) {
|
||||||
|
// Close HID EP
|
||||||
|
DCD_EP_Close(pdev, HID_IN_EP);
|
||||||
|
|
||||||
|
return USBD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HID_REQ_SET_PROTOCOL (0x0B)
|
||||||
|
#define HID_REQ_GET_PROTOCOL (0x03)
|
||||||
|
#define HID_REQ_SET_IDLE (0x0A)
|
||||||
|
#define HID_REQ_GET_IDLE (0x02)
|
||||||
|
#define HID_REQ_SET_REPORT (0x09) // used?
|
||||||
|
#define HID_REQ_GET_REPORT (0x01) // used?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief usbd_pyb_Setup
|
||||||
|
* Handle the CDC specific requests
|
||||||
|
* @param pdev: instance
|
||||||
|
* @param req: usb requests
|
||||||
|
* @retval status
|
||||||
|
*/
|
||||||
|
static uint8_t usbd_pyb_Setup(void *pdev, USB_SETUP_REQ *req) {
|
||||||
|
switch (req->bmRequest & (USB_REQ_TYPE_MASK | USB_REQ_RECIPIENT_MASK)) {
|
||||||
|
|
||||||
|
// Standard Device Request ---------------------------------------------
|
||||||
|
case (USB_REQ_TYPE_STANDARD | USB_REQ_RECIPIENT_DEVICE):
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Standard Interface Request ------------------------------------------
|
||||||
|
case (USB_REQ_TYPE_STANDARD | USB_REQ_RECIPIENT_INTERFACE):
|
||||||
|
switch (req->bRequest) {
|
||||||
|
case USB_REQ_GET_DESCRIPTOR: // needed for HID; SU 0x81 0x06 0x2200 0x00 request
|
||||||
|
// wIndex & 0xff is the interface
|
||||||
|
if ((req->wIndex & 0xff) == 0) {
|
||||||
|
uint16_t len = 0;
|
||||||
|
uint8_t *pbuf = NULL;
|
||||||
|
if( req->wValue >> 8 == HID_REPORT_DESC) {
|
||||||
|
len = MIN(HID_MOUSE_REPORT_DESC_SIZE , req->wLength);
|
||||||
|
pbuf = HID_MOUSE_ReportDesc;
|
||||||
|
return USBD_CtlSendData (pdev, pbuf, len);
|
||||||
|
} else if( req->wValue >> 8 == HID_DESCRIPTOR_TYPE) {
|
||||||
|
pbuf = usbd_pyb_CfgDesc + 0x09 + 0x09;
|
||||||
|
len = MIN(0x09 , req->wLength);
|
||||||
|
return USBD_CtlSendData (pdev, pbuf, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case USB_REQ_GET_INTERFACE:
|
||||||
|
// wIndex & 0xff is the interface
|
||||||
|
if ((req->wIndex & 0xff) == 0) {
|
||||||
|
return USBD_CtlSendData(pdev, &USBD_HID_AltSet, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
case USB_REQ_SET_INTERFACE:
|
||||||
|
if ((uint8_t)(req->wValue) < USBD_ITF_MAX_NUM) { // TODO
|
||||||
|
if ((req->wIndex & 0xff) == 0) {
|
||||||
|
USBD_HID_AltSet = req->wValue;
|
||||||
|
}
|
||||||
|
return USBD_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Standard Endpoint Request -------------------------------------------
|
||||||
|
case (USB_REQ_TYPE_STANDARD | USB_REQ_RECIPIENT_ENDPOINT):
|
||||||
|
// req->wIndex is the endpoint number, including direction
|
||||||
|
break;
|
||||||
|
|
||||||
|
// CDC Class Requests ------------------------------
|
||||||
|
case (USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE):
|
||||||
|
// req->wIndex is the recipient interface number
|
||||||
|
if (req->wIndex == 0) {
|
||||||
|
// HID component
|
||||||
|
switch (req->bRequest) {
|
||||||
|
case HID_REQ_SET_PROTOCOL:
|
||||||
|
USBD_HID_Protocol = req->wValue;
|
||||||
|
return USBD_OK;
|
||||||
|
|
||||||
|
case HID_REQ_GET_PROTOCOL:
|
||||||
|
return USBD_CtlSendData(pdev, &USBD_HID_Protocol, 1);
|
||||||
|
|
||||||
|
case HID_REQ_SET_IDLE:
|
||||||
|
USBD_HID_IdleState = (req->wValue >> 8);
|
||||||
|
return USBD_OK;
|
||||||
|
|
||||||
|
case HID_REQ_GET_IDLE:
|
||||||
|
return USBD_CtlSendData(pdev, &USBD_HID_IdleState, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("SU %x %x %x %x\n", req->bmRequest, req->bRequest, req->wValue, req->wIndex);
|
||||||
|
|
||||||
|
// invalid command
|
||||||
|
USBD_CtlError(pdev, req);
|
||||||
|
return USBD_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief usbd_pyb_DataIn
|
||||||
|
* Data sent on non-control IN endpoint
|
||||||
|
* @param pdev: device instance
|
||||||
|
* @param epnum: endpoint number
|
||||||
|
* @retval status
|
||||||
|
*/
|
||||||
|
static uint8_t usbd_pyb_DataIn(void *pdev, uint8_t epnum) {
|
||||||
|
switch (epnum) {
|
||||||
|
case (HID_IN_EP & 0x7f):
|
||||||
|
/* Ensure that the FIFO is empty before a new transfer, this condition could
|
||||||
|
be caused by a new transfer before the end of the previous transfer */
|
||||||
|
DCD_EP_Flush(pdev, HID_IN_EP);
|
||||||
|
return USBD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("DI %x\n", epnum);
|
||||||
|
|
||||||
|
return USBD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief usbd_pyb_GetCfgDesc
|
||||||
|
* Return configuration descriptor
|
||||||
|
* @param speed : current device speed
|
||||||
|
* @param length : pointer data length
|
||||||
|
* @retval pointer to descriptor buffer
|
||||||
|
*/
|
||||||
|
static uint8_t *usbd_pyb_GetCfgDesc(uint8_t speed, uint16_t *length) {
|
||||||
|
*length = sizeof(usbd_pyb_CfgDesc);
|
||||||
|
return usbd_pyb_CfgDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief USBD_HID_SendReport
|
||||||
|
* Send HID Report
|
||||||
|
* @param pdev: device instance
|
||||||
|
* @param buff: pointer to report (4 bytes: ?, x, y, ?)
|
||||||
|
* @retval status
|
||||||
|
*/
|
||||||
|
uint8_t USBD_HID_SendReport(USB_OTG_CORE_HANDLE *pdev, uint8_t *report, uint16_t len) {
|
||||||
|
if (pdev->dev.device_status == USB_OTG_CONFIGURED) {
|
||||||
|
DCD_EP_Tx(pdev, HID_IN_EP, report, len);
|
||||||
|
}
|
||||||
|
return USBD_OK;
|
||||||
|
}
|
41
stm/main.c
41
stm/main.c
@ -451,6 +451,17 @@ py_obj_t pyb_mma_read() {
|
|||||||
return rt_build_tuple(4, data); // items in reverse order in data
|
return rt_build_tuple(4, data); // items in reverse order in data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
py_obj_t pyb_hid_send_report(py_obj_t arg) {
|
||||||
|
py_obj_t *items = py_get_array_fixed_n(arg, 4);
|
||||||
|
uint8_t data[4];
|
||||||
|
data[0] = py_get_int(items[0]);
|
||||||
|
data[1] = py_get_int(items[1]);
|
||||||
|
data[2] = py_get_int(items[2]);
|
||||||
|
data[3] = py_get_int(items[3]);
|
||||||
|
usb_hid_send_report(data);
|
||||||
|
return py_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
// TODO disable JTAG
|
// TODO disable JTAG
|
||||||
|
|
||||||
@ -514,6 +525,7 @@ soft_reset:
|
|||||||
rt_store_attr(m, qstr_from_str_static("sw"), rt_make_function_0(pyb_sw));
|
rt_store_attr(m, qstr_from_str_static("sw"), rt_make_function_0(pyb_sw));
|
||||||
rt_store_attr(m, qstr_from_str_static("servo"), rt_make_function_1(pyb_servo_set));
|
rt_store_attr(m, qstr_from_str_static("servo"), rt_make_function_1(pyb_servo_set));
|
||||||
rt_store_attr(m, qstr_from_str_static("mma"), rt_make_function_0(pyb_mma_read));
|
rt_store_attr(m, qstr_from_str_static("mma"), rt_make_function_0(pyb_mma_read));
|
||||||
|
rt_store_attr(m, qstr_from_str_static("hid"), rt_make_function_1(pyb_hid_send_report));
|
||||||
rt_store_name(qstr_from_str_static("pyb"), m);
|
rt_store_name(qstr_from_str_static("pyb"), m);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -814,6 +826,35 @@ soft_reset:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HID example
|
||||||
|
if (0) {
|
||||||
|
uint8_t data[4];
|
||||||
|
data[0] = 0;
|
||||||
|
data[1] = 1;
|
||||||
|
data[2] = -2;
|
||||||
|
data[3] = 0;
|
||||||
|
for (;;) {
|
||||||
|
if (sw_get()) {
|
||||||
|
data[0] = 0x01; // 0x04 is middle, 0x02 is right
|
||||||
|
} else {
|
||||||
|
data[0] = 0x00;
|
||||||
|
}
|
||||||
|
mma_start(MMA_ADDR, 1);
|
||||||
|
mma_send_byte(0);
|
||||||
|
mma_restart(MMA_ADDR, 0);
|
||||||
|
for (int i = 0; i <= 1; i++) {
|
||||||
|
int v = mma_read_ack() & 0x3f;
|
||||||
|
if (v & 0x20) {
|
||||||
|
v |= ~0x1f;
|
||||||
|
}
|
||||||
|
data[1 + i] = v;
|
||||||
|
}
|
||||||
|
mma_read_nack();
|
||||||
|
usb_hid_send_report(data);
|
||||||
|
sys_tick_delay_ms(15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
do_repl();
|
do_repl();
|
||||||
|
|
||||||
// benchmark C version of impl02.py
|
// benchmark C version of impl02.py
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "std.h"
|
#include "std.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
@ -23,6 +23,7 @@ void usb_init(void) {
|
|||||||
if (!is_enabled) {
|
if (!is_enabled) {
|
||||||
// only init USB once in the device's power-lifetime
|
// only init USB once in the device's power-lifetime
|
||||||
USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_PYB_cb, &USR_cb);
|
USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_PYB_cb, &USR_cb);
|
||||||
|
//USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_PYB_HID_cb, &USR_cb);
|
||||||
}
|
}
|
||||||
rx_buf_in = 0;
|
rx_buf_in = 0;
|
||||||
rx_buf_out = 0;
|
rx_buf_out = 0;
|
||||||
@ -100,3 +101,7 @@ void usb_vcp_send_strn_cooked(const char *str, int len) {
|
|||||||
APP_Rx_ptr_in = (APP_Rx_ptr_in + 1) & (APP_RX_DATA_SIZE - 1);
|
APP_Rx_ptr_in = (APP_Rx_ptr_in + 1) & (APP_RX_DATA_SIZE - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void usb_hid_send_report(uint8_t *buf) {
|
||||||
|
USBD_HID_SendReport(&USB_OTG_dev, buf, 4);
|
||||||
|
}
|
||||||
|
@ -5,3 +5,4 @@ char usb_vcp_rx_get(void);
|
|||||||
void usb_vcp_send_str(const char* str);
|
void usb_vcp_send_str(const char* str);
|
||||||
void usb_vcp_send_strn(const char* str, int len);
|
void usb_vcp_send_strn(const char* str, int len);
|
||||||
void usb_vcp_send_strn_cooked(const char *str, int len);
|
void usb_vcp_send_strn_cooked(const char *str, int len);
|
||||||
|
void usb_hid_send_report(uint8_t *buf); // 4 bytes for mouse: ?, x, y, ?
|
||||||
|
Loading…
Reference in New Issue
Block a user