diff --git a/stm/Makefile b/stm/Makefile index dace8cb6c..5ad469d71 100644 --- a/stm/Makefile +++ b/stm/Makefile @@ -75,6 +75,7 @@ SRC_STM = \ usbd_usr.c \ usbd_desc.c \ usbd_pyb_core.c \ + usbd_pyb_core2.c \ usbd_cdc_vcp.c \ usbd_msc_bot.c \ usbd_msc_data.c \ diff --git a/stm/lib/usbd_pyb_core.c b/stm/lib/usbd_pyb_core.c index 9c009a064..ac51e3ad8 100644 --- a/stm/lib/usbd_pyb_core.c +++ b/stm/lib/usbd_pyb_core.c @@ -73,12 +73,27 @@ #include "usbd_msc_bot.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 (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_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 *********************************************/ @@ -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; +#if USB_PYB_USE_MSC __ALIGN_BEGIN static uint8_t USBD_MSC_MaxLun __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_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), 0x00, // bInterval: ignore for Bulk transfer +#if USB_PYB_USE_MSC //========================================================================== // 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 HIBYTE(MSC_MAX_PACKET), 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 * @{ @@ -333,6 +444,7 @@ static uint8_t usbd_pyb_Init(void *pdev, uint8_t cfgidx) { (uint8_t*)(USB_Rx_Buffer), CDC_DATA_OUT_PACKET_SIZE); +#if USB_PYB_USE_MSC //---------------------------------- // MSC component @@ -351,6 +463,17 @@ static uint8_t usbd_pyb_Init(void *pdev, uint8_t cfgidx) { // Init the BOT layer 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; } @@ -372,6 +495,7 @@ static uint8_t usbd_pyb_DeInit(void *pdev, uint8_t cfgidx) { // Restore default state of the Interface physical components VCP_fops.pIf_DeInit(); +#if USB_PYB_USE_MSC //---------------------------------- // MSC component @@ -382,12 +506,27 @@ static uint8_t usbd_pyb_DeInit(void *pdev, uint8_t cfgidx) { // Un Init the BOT layer MSC_BOT_DeInit(pdev); +#else + //---------------------------------- + // HID component + + // Close HID EP + DCD_EP_Close(pdev, HID_IN_EP); +#endif + return USBD_OK; } #define BOT_GET_MAX_LUN 0xFE #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 * 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 } 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) { return USBD_CtlSendData(pdev, &usbd_cdc_AltSet, 1); } else { +#if USB_PYB_USE_MSC return USBD_CtlSendData(pdev, &USBD_MSC_AltSet, 1); +#else + return USBD_CtlSendData(pdev, &USBD_HID_AltSet, 1); +#endif } 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) { usbd_cdc_AltSet = req->wValue; } else { +#if USB_PYB_USE_MSC USBD_MSC_AltSet = req->wValue; +#else + USBD_HID_AltSet = req->wValue; +#endif } return USBD_OK; } @@ -442,6 +590,7 @@ static uint8_t usbd_pyb_Setup(void *pdev, USB_SETUP_REQ *req) { // Standard Endpoint Request ------------------------------------------- case (USB_REQ_TYPE_STANDARD | USB_REQ_RECIPIENT_ENDPOINT): // req->wIndex is the endpoint number, including direction +#if USB_PYB_USE_MSC if (req->wIndex == MSC_IN_EP || req->wIndex == MSC_OUT_EP) { // MSC component switch (req->bRequest) { @@ -464,6 +613,7 @@ static uint8_t usbd_pyb_Setup(void *pdev, USB_SETUP_REQ *req) { return USBD_OK; } } +#endif break; // CDC Class Requests ------------------------------ @@ -502,6 +652,7 @@ static uint8_t usbd_pyb_Setup(void *pdev, USB_SETUP_REQ *req) { } } else if (req->wIndex == 2) { +#if USB_PYB_USE_MSC // MSC component switch (req->bRequest) { case BOT_GET_MAX_LUN: @@ -520,6 +671,24 @@ static uint8_t usbd_pyb_Setup(void *pdev, USB_SETUP_REQ *req) { } 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; } @@ -590,9 +759,18 @@ static uint8_t usbd_pyb_DataIn(void *pdev, uint8_t epnum) { } return USBD_OK; +#if USB_PYB_USE_MSC case (MSC_IN_EP & 0x7f): // TODO? MSC_BOT_DataIn(pdev, epnum); 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); @@ -626,9 +804,11 @@ static uint8_t usbd_pyb_DataOut(void *pdev, uint8_t epnum) { CDC_DATA_OUT_PACKET_SIZE); return USBD_OK; +#if USB_PYB_USE_MSC case (MSC_OUT_EP & 0x7f): // TODO is this correct? MSC_BOT_DataOut(pdev, epnum); return USBD_OK; +#endif } 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); 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; +} +*/ diff --git a/stm/lib/usbd_pyb_core.h b/stm/lib/usbd_pyb_core.h index e4cdb1fc0..761ca2253 100644 --- a/stm/lib/usbd_pyb_core.h +++ b/stm/lib/usbd_pyb_core.h @@ -1 +1,4 @@ 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); diff --git a/stm/lib/usbd_pyb_core2.c b/stm/lib/usbd_pyb_core2.c new file mode 100644 index 000000000..c1abda3e7 --- /dev/null +++ b/stm/lib/usbd_pyb_core2.c @@ -0,0 +1,323 @@ +#include + +#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; +} diff --git a/stm/main.c b/stm/main.c index 5dc03bc69..ffefbb64c 100644 --- a/stm/main.c +++ b/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 } +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) { // 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("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("hid"), rt_make_function_1(pyb_hid_send_report)); 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(); // benchmark C version of impl02.py diff --git a/stm/printf.c b/stm/printf.c index 3ccdd7084..4c178b94b 100644 --- a/stm/printf.c +++ b/stm/printf.c @@ -1,3 +1,4 @@ +#include #include #include "std.h" #include "misc.h" diff --git a/stm/usb.c b/stm/usb.c index 97e96c35e..b0fbfa194 100644 --- a/stm/usb.c +++ b/stm/usb.c @@ -23,6 +23,7 @@ void usb_init(void) { if (!is_enabled) { // 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_HID_cb, &USR_cb); } rx_buf_in = 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); } } + +void usb_hid_send_report(uint8_t *buf) { + USBD_HID_SendReport(&USB_OTG_dev, buf, 4); +} diff --git a/stm/usb.h b/stm/usb.h index 74041043e..c4b3b151f 100644 --- a/stm/usb.h +++ b/stm/usb.h @@ -5,3 +5,4 @@ char usb_vcp_rx_get(void); void usb_vcp_send_str(const char* str); void usb_vcp_send_strn(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, ?