524 lines
23 KiB
C
524 lines
23 KiB
C
#include "hal.h"
|
|
#include "hal_usb_cdc.h"
|
|
#include "hal_serial_usb.h"
|
|
#include "usbcfg.h"
|
|
|
|
SerialUSBDriver SDU1;
|
|
volatile bool cdc_dtr = false;
|
|
|
|
#define HID_EP 1
|
|
#define CDC_INT_EP 2
|
|
#define CDC_DATA_EP 3
|
|
|
|
#define HID_EP_SIZE 0x0020U
|
|
#define CDC_INT_SIZE 0x0010U
|
|
#define CDC_DATA_SIZE 0x0040U
|
|
|
|
#define HID_IF_DESC_SIZE \
|
|
(USB_DESC_INTERFACE_SIZE + 9U + (USB_DESC_ENDPOINT_SIZE * 2U))
|
|
|
|
#define CDC_FUNC_DESC_SIZE (5U + 5U + 4U + 5U)
|
|
|
|
#define CDC_IF_DESC_SIZE \
|
|
(USB_DESC_INTERFACE_SIZE + CDC_FUNC_DESC_SIZE + \
|
|
USB_DESC_ENDPOINT_SIZE + \
|
|
USB_DESC_INTERFACE_SIZE + (USB_DESC_ENDPOINT_SIZE * 2U))
|
|
|
|
#define IAD_CDC_SIZE \
|
|
(USB_DESC_INTERFACE_ASSOCIATION_SIZE + CDC_IF_DESC_SIZE)
|
|
|
|
#define CONFIG_TOTAL_SIZE \
|
|
(USB_DESC_CONFIGURATION_SIZE + HID_IF_DESC_SIZE + IAD_CDC_SIZE)
|
|
|
|
/*
|
|
* USB Device Descriptor.
|
|
*/
|
|
static const uint8_t device_descriptor_data[18] = {
|
|
USB_DESC_DEVICE (0x0200,
|
|
0xEF, /* bDeviceClass (Miscellaneous). */
|
|
0x02, /* bDeviceSubClass (Common). */
|
|
0x01, /* bDeviceProtocol (IAD). */
|
|
0x40, /* bMaxPacketSize. */
|
|
0xEDDE, /* idVendor. */
|
|
0x2025, /* idProduct. */
|
|
0x0200, /* bcdDevice. */
|
|
1, /* iManufacturer. */
|
|
2, /* iProduct. */
|
|
3, /* iSerialNumber. */
|
|
1) /* bNumConfigurations. */
|
|
};
|
|
|
|
static const USBDescriptor device_descriptor = {
|
|
sizeof device_descriptor_data,
|
|
device_descriptor_data
|
|
};
|
|
|
|
/*
|
|
* Configuration Descriptor tree for HID LampArray + CDC ACM.
|
|
*/
|
|
static const uint8_t configuration_descriptor_data[] = {
|
|
/* Configuration Descriptor */
|
|
USB_DESC_CONFIGURATION(CONFIG_TOTAL_SIZE,
|
|
3, /* bNumInterfaces (HID + CDC ctrl + CDC data). */
|
|
0x01, /* bConfigurationValue. */
|
|
0, /* iConfiguration. */
|
|
0xC0, /* bmAttributes (self powered). */
|
|
50), /* bMaxPower (100mA). */
|
|
|
|
/* HID Interface (0) */
|
|
USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */
|
|
0x00, /* bAlternateSetting. */
|
|
0x02, /* bNumEndpoints. */
|
|
0x03, /* bInterfaceClass (HID). */
|
|
0x00, /* bInterfaceSubClass. */
|
|
0x00, /* bInterfaceProtocol. */
|
|
0), /* iInterface. */
|
|
|
|
/* HID Class Descriptor */
|
|
USB_DESC_BYTE (0x09), /* bLength. */
|
|
USB_DESC_BYTE (0x21), /* bDescriptorType (HID). */
|
|
USB_DESC_BCD (0x111), /* bcdHID (1.1). */
|
|
USB_DESC_BYTE (0x00), /* bCountryCode (None). */
|
|
USB_DESC_BYTE (0x01), /* bNumDescriptors. */
|
|
USB_DESC_BYTE (0x22), /* bDescriptorType (Report). */
|
|
USB_DESC_WORD (292), /* wDescriptorLength. */
|
|
|
|
/* HID EP1 IN */
|
|
USB_DESC_ENDPOINT (USB_ENDPOINT_IN(HID_EP),
|
|
USB_EP_MODE_TYPE_INTR,
|
|
HID_EP_SIZE,
|
|
0xFF),
|
|
/* HID EP1 OUT */
|
|
USB_DESC_ENDPOINT (USB_ENDPOINT_OUT(HID_EP),
|
|
USB_EP_MODE_TYPE_INTR,
|
|
HID_EP_SIZE,
|
|
0xFF),
|
|
|
|
/* IAD grouping the two CDC interfaces */
|
|
USB_DESC_INTERFACE_ASSOCIATION(
|
|
0x01, /* bFirstInterface. */
|
|
2, /* bInterfaceCount. */
|
|
CDC_COMMUNICATION_INTERFACE_CLASS,
|
|
CDC_ABSTRACT_CONTROL_MODEL,
|
|
0x01, /* bFunctionProtocol (AT commands). */
|
|
0), /* iFunction. */
|
|
|
|
/* CDC Control Interface (1) */
|
|
USB_DESC_INTERFACE (0x01,
|
|
0x00,
|
|
0x01, /* bNumEndpoints (interrupt IN). */
|
|
CDC_COMMUNICATION_INTERFACE_CLASS,
|
|
CDC_ABSTRACT_CONTROL_MODEL,
|
|
0x01,
|
|
0),
|
|
|
|
/* Header Functional Descriptor */
|
|
USB_DESC_BYTE(5), USB_DESC_BYTE(CDC_CS_INTERFACE), USB_DESC_BYTE(CDC_HEADER),
|
|
USB_DESC_BCD(0x0110),
|
|
|
|
/* Call Management Functional Descriptor */
|
|
USB_DESC_BYTE(5), USB_DESC_BYTE(CDC_CS_INTERFACE), USB_DESC_BYTE(CDC_CALL_MANAGEMENT),
|
|
USB_DESC_BYTE(0x03), /* bmCapabilities. */
|
|
USB_DESC_BYTE(0x02), /* bDataInterface. */
|
|
|
|
/* Abstract Control Management Functional Descriptor */
|
|
USB_DESC_BYTE(4), USB_DESC_BYTE(CDC_CS_INTERFACE),
|
|
USB_DESC_BYTE(CDC_ABSTRACT_CONTROL_MANAGEMENT),
|
|
USB_DESC_BYTE(0x02), /* bmCapabilities. */
|
|
|
|
/* Union Functional Descriptor */
|
|
USB_DESC_BYTE(5), USB_DESC_BYTE(CDC_CS_INTERFACE), USB_DESC_BYTE(CDC_UNION),
|
|
USB_DESC_BYTE(0x01), /* bMasterInterface. */
|
|
USB_DESC_BYTE(0x02), /* bSlaveInterface. */
|
|
|
|
/* CDC Interrupt IN EP2 */
|
|
USB_DESC_ENDPOINT (USB_ENDPOINT_IN(CDC_INT_EP),
|
|
USB_EP_MODE_TYPE_INTR,
|
|
CDC_INT_SIZE,
|
|
0x01),
|
|
|
|
/* CDC Data Interface (2) */
|
|
USB_DESC_INTERFACE (0x02,
|
|
0x00,
|
|
0x02, /* bNumEndpoints (bulk IN + OUT). */
|
|
CDC_DATA_INTERFACE_CLASS,
|
|
0x00,
|
|
0x00,
|
|
0),
|
|
|
|
/* CDC Bulk OUT EP3 */
|
|
USB_DESC_ENDPOINT (USB_ENDPOINT_OUT(CDC_DATA_EP),
|
|
USB_EP_MODE_TYPE_BULK,
|
|
CDC_DATA_SIZE,
|
|
0x00),
|
|
/* CDC Bulk IN EP3 */
|
|
USB_DESC_ENDPOINT (USB_ENDPOINT_IN(CDC_DATA_EP),
|
|
USB_EP_MODE_TYPE_BULK,
|
|
CDC_DATA_SIZE,
|
|
0x00),
|
|
};
|
|
|
|
static const USBDescriptor configuration_descriptor = {
|
|
sizeof configuration_descriptor_data,
|
|
configuration_descriptor_data
|
|
};
|
|
|
|
/* Generated by WaratahCmd.exe from lampArray sample */
|
|
static const uint8_t hid_report_descriptor_data[292] = {
|
|
0x05, 0x59, // UsagePage(Lighting And Illumination[0x0059])
|
|
0x09, 0x01, // UsageId(LampArray[0x0001])
|
|
0xA1, 0x01, // Collection(Application)
|
|
0x85, 0x01, // ReportId(1)
|
|
0x09, 0x02, // UsageId(LampArrayAttributesReport[0x0002])
|
|
0xA1, 0x02, // Collection(Logical)
|
|
0x09, 0x03, // UsageId(LampCount[0x0003])
|
|
0x15, 0x00, // LogicalMinimum(0)
|
|
0x27, 0xFF, 0xFF, 0x00, 0x00, // LogicalMaximum(65,535)
|
|
0x95, 0x01, // ReportCount(1)
|
|
0x75, 0x10, // ReportSize(16)
|
|
0xB1, 0x03, // Feature(Constant, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
|
0x09, 0x04, // UsageId(BoundingBoxWidthInMicrometers[0x0004])
|
|
0x09, 0x05, // UsageId(BoundingBoxHeightInMicrometers[0x0005])
|
|
0x09, 0x06, // UsageId(BoundingBoxDepthInMicrometers[0x0006])
|
|
0x09, 0x07, // UsageId(LampArrayKind[0x0007])
|
|
0x09, 0x08, // UsageId(MinUpdateIntervalInMicroseconds[0x0008])
|
|
0x27, 0xFF, 0xFF, 0xFF, 0x7F, // LogicalMaximum(2,147,483,647)
|
|
0x95, 0x05, // ReportCount(5)
|
|
0x75, 0x20, // ReportSize(32)
|
|
0xB1, 0x03, // Feature(Constant, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
|
0xC0, // EndCollection()
|
|
0x85, 0x02, // ReportId(2)
|
|
0x09, 0x20, // UsageId(LampAttributesRequestReport[0x0020])
|
|
0xA1, 0x02, // Collection(Logical)
|
|
0x09, 0x21, // UsageId(LampId[0x0021])
|
|
0x27, 0xFF, 0xFF, 0x00, 0x00, // LogicalMaximum(65,535)
|
|
0x95, 0x01, // ReportCount(1)
|
|
0x75, 0x10, // ReportSize(16)
|
|
0xB1, 0x02, // Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
|
0xC0, // EndCollection()
|
|
0x85, 0x03, // ReportId(3)
|
|
0x09, 0x22, // UsageId(LampAttributesResponseReport[0x0022])
|
|
0xA1, 0x02, // Collection(Logical)
|
|
0x09, 0x21, // UsageId(LampId[0x0021])
|
|
0xB1, 0x02, // Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
|
0x09, 0x23, // UsageId(PositionXInMicrometers[0x0023])
|
|
0x09, 0x24, // UsageId(PositionYInMicrometers[0x0024])
|
|
0x09, 0x25, // UsageId(PositionZInMicrometers[0x0025])
|
|
0x09, 0x27, // UsageId(UpdateLatencyInMicroseconds[0x0027])
|
|
0x09, 0x26, // UsageId(LampPurposes[0x0026])
|
|
0x27, 0xFF, 0xFF, 0xFF, 0x7F, // LogicalMaximum(2,147,483,647)
|
|
0x95, 0x05, // ReportCount(5)
|
|
0x75, 0x20, // ReportSize(32)
|
|
0xB1, 0x02, // Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
|
0x09, 0x28, // UsageId(RedLevelCount[0x0028])
|
|
0x09, 0x29, // UsageId(GreenLevelCount[0x0029])
|
|
0x09, 0x2A, // UsageId(BlueLevelCount[0x002A])
|
|
0x09, 0x2B, // UsageId(IntensityLevelCount[0x002B])
|
|
0x09, 0x2C, // UsageId(IsProgrammable[0x002C])
|
|
0x09, 0x2D, // UsageId(InputBinding[0x002D])
|
|
0x26, 0xFF, 0x00, // LogicalMaximum(255)
|
|
0x95, 0x06, // ReportCount(6)
|
|
0x75, 0x08, // ReportSize(8)
|
|
0xB1, 0x02, // Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
|
0xC0, // EndCollection()
|
|
0x85, 0x04, // ReportId(4)
|
|
0x09, 0x50, // UsageId(LampMultiUpdateReport[0x0050])
|
|
0xA1, 0x02, // Collection(Logical)
|
|
0x09, 0x03, // UsageId(LampCount[0x0003])
|
|
0x25, 0x08, // LogicalMaximum(8)
|
|
0x95, 0x01, // ReportCount(1)
|
|
0xB1, 0x02, // Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
|
0x09, 0x55, // UsageId(LampUpdateFlags[0x0055])
|
|
0x25, 0x01, // LogicalMaximum(1)
|
|
0xB1, 0x02, // Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
|
0x09, 0x21, // UsageId(LampId[0x0021])
|
|
0x27, 0xFF, 0xFF, 0x00, 0x00, // LogicalMaximum(65,535)
|
|
0x95, 0x08, // ReportCount(8)
|
|
0x75, 0x10, // ReportSize(16)
|
|
0xB1, 0x02, // Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
|
0x09, 0x51, // UsageId(RedUpdateChannel[0x0051])
|
|
0x09, 0x52, // UsageId(GreenUpdateChannel[0x0052])
|
|
0x09, 0x53, // UsageId(BlueUpdateChannel[0x0053])
|
|
0x09, 0x54, // UsageId(IntensityUpdateChannel[0x0054])
|
|
0x09, 0x51, // UsageId(RedUpdateChannel[0x0051])
|
|
0x09, 0x52, // UsageId(GreenUpdateChannel[0x0052])
|
|
0x09, 0x53, // UsageId(BlueUpdateChannel[0x0053])
|
|
0x09, 0x54, // UsageId(IntensityUpdateChannel[0x0054])
|
|
0x09, 0x51, // UsageId(RedUpdateChannel[0x0051])
|
|
0x09, 0x52, // UsageId(GreenUpdateChannel[0x0052])
|
|
0x09, 0x53, // UsageId(BlueUpdateChannel[0x0053])
|
|
0x09, 0x54, // UsageId(IntensityUpdateChannel[0x0054])
|
|
0x09, 0x51, // UsageId(RedUpdateChannel[0x0051])
|
|
0x09, 0x52, // UsageId(GreenUpdateChannel[0x0052])
|
|
0x09, 0x53, // UsageId(BlueUpdateChannel[0x0053])
|
|
0x09, 0x54, // UsageId(IntensityUpdateChannel[0x0054])
|
|
0x09, 0x51, // UsageId(RedUpdateChannel[0x0051])
|
|
0x09, 0x52, // UsageId(GreenUpdateChannel[0x0052])
|
|
0x09, 0x53, // UsageId(BlueUpdateChannel[0x0053])
|
|
0x09, 0x54, // UsageId(IntensityUpdateChannel[0x0054])
|
|
0x09, 0x51, // UsageId(RedUpdateChannel[0x0051])
|
|
0x09, 0x52, // UsageId(GreenUpdateChannel[0x0052])
|
|
0x09, 0x53, // UsageId(BlueUpdateChannel[0x0053])
|
|
0x09, 0x54, // UsageId(IntensityUpdateChannel[0x0054])
|
|
0x09, 0x51, // UsageId(RedUpdateChannel[0x0051])
|
|
0x09, 0x52, // UsageId(GreenUpdateChannel[0x0052])
|
|
0x09, 0x53, // UsageId(BlueUpdateChannel[0x0053])
|
|
0x09, 0x54, // UsageId(IntensityUpdateChannel[0x0054])
|
|
0x09, 0x51, // UsageId(RedUpdateChannel[0x0051])
|
|
0x09, 0x52, // UsageId(GreenUpdateChannel[0x0052])
|
|
0x09, 0x53, // UsageId(BlueUpdateChannel[0x0053])
|
|
0x09, 0x54, // UsageId(IntensityUpdateChannel[0x0054])
|
|
0x26, 0xFF, 0x00, // LogicalMaximum(255)
|
|
0x95, 0x20, // ReportCount(32)
|
|
0x75, 0x08, // ReportSize(8)
|
|
0xB1, 0x02, // Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
|
0xC0, // EndCollection()
|
|
0x85, 0x05, // ReportId(5)
|
|
0x09, 0x60, // UsageId(LampRangeUpdateReport[0x0060])
|
|
0xA1, 0x02, // Collection(Logical)
|
|
0x09, 0x55, // UsageId(LampUpdateFlags[0x0055])
|
|
0x25, 0x01, // LogicalMaximum(1)
|
|
0x95, 0x01, // ReportCount(1)
|
|
0xB1, 0x02, // Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
|
0x09, 0x61, // UsageId(LampIdStart[0x0061])
|
|
0x09, 0x62, // UsageId(LampIdEnd[0x0062])
|
|
0x27, 0xFF, 0xFF, 0x00, 0x00, // LogicalMaximum(65,535)
|
|
0x95, 0x02, // ReportCount(2)
|
|
0x75, 0x10, // ReportSize(16)
|
|
0xB1, 0x02, // Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
|
0x09, 0x51, // UsageId(RedUpdateChannel[0x0051])
|
|
0x09, 0x52, // UsageId(GreenUpdateChannel[0x0052])
|
|
0x09, 0x53, // UsageId(BlueUpdateChannel[0x0053])
|
|
0x09, 0x54, // UsageId(IntensityUpdateChannel[0x0054])
|
|
0x26, 0xFF, 0x00, // LogicalMaximum(255)
|
|
0x95, 0x04, // ReportCount(4)
|
|
0x75, 0x08, // ReportSize(8)
|
|
0xB1, 0x02, // Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
|
0xC0, // EndCollection()
|
|
0x85, 0x06, // ReportId(6)
|
|
0x09, 0x70, // UsageId(LampArrayControlReport[0x0070])
|
|
0xA1, 0x02, // Collection(Logical)
|
|
0x09, 0x71, // UsageId(AutonomousMode[0x0071])
|
|
0x25, 0x01, // LogicalMaximum(1)
|
|
0x95, 0x01, // ReportCount(1)
|
|
0xB1, 0x02, // Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
|
0xC0, // EndCollection()
|
|
0xC0, // EndCollection()
|
|
};
|
|
|
|
static const USBDescriptor hid_report_descriptor = {
|
|
sizeof hid_report_descriptor_data,
|
|
hid_report_descriptor_data
|
|
};
|
|
|
|
static const uint8_t usb_string0[] = {
|
|
USB_DESC_BYTE(4),
|
|
USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
|
|
USB_DESC_WORD(0x0409)
|
|
};
|
|
|
|
static const uint8_t usb_string1[] = {
|
|
USB_DESC_BYTE(16),
|
|
USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
|
|
'M', 0, 'e', 0, 't', 0, 'z', 0, 'N', 0, 'e', 0, 't', 0
|
|
};
|
|
|
|
static const uint8_t usb_string2[] = {
|
|
USB_DESC_BYTE(30),
|
|
USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
|
|
'T', 0, 'w', 0, 'i', 0, 'n', 0, 'k', 0, 'l', 0, 'e', 0,
|
|
'S', 0, 't', 0, 'i', 0, 'c', 0, 'k', 0, 'V', 0, '2', 0
|
|
};
|
|
|
|
static const uint8_t usb_string3[] = {
|
|
USB_DESC_BYTE(2 + 12*2), /* bLength */
|
|
USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
|
|
'T', 0, 'w', 0, 'i', 0, 'n', 0, 'k', 0, 'l', 0,
|
|
'e', 0, 'S', 0, 't', 0, 'i', 0, 'c', 0, 'k', 0
|
|
};
|
|
|
|
static const USBDescriptor usb_strings[] = {
|
|
{sizeof usb_string0, usb_string0},
|
|
{sizeof usb_string1, usb_string1},
|
|
{sizeof usb_string2, usb_string2},
|
|
{sizeof usb_string3, usb_string3}
|
|
};
|
|
|
|
static const USBDescriptor *get_descriptor(USBDriver *usbp, uint8_t dtype,
|
|
uint8_t dindex, uint16_t lang) {
|
|
(void)usbp;
|
|
(void)lang;
|
|
switch (dtype) {
|
|
case USB_DESCRIPTOR_DEVICE:
|
|
return &device_descriptor;
|
|
case USB_DESCRIPTOR_CONFIGURATION:
|
|
return &configuration_descriptor;
|
|
case USB_DESCRIPTOR_STRING:
|
|
if (dindex < 4)
|
|
return &usb_strings[dindex];
|
|
break;
|
|
case 0x22:
|
|
return &hid_report_descriptor;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
#define HID_GET_REPORT 0x01U
|
|
#define HID_SET_REPORT 0x09U
|
|
#define HID_SET_IDLE 0x0AU
|
|
|
|
#define HID_REPORT_BUF_SIZE 64U
|
|
|
|
static uint8_t hid_get_buf[HID_REPORT_BUF_SIZE];
|
|
static uint8_t hid_set_buf[HID_REPORT_BUF_SIZE];
|
|
|
|
static struct {
|
|
uint8_t id;
|
|
uint16_t len;
|
|
} hid_set_ctx;
|
|
|
|
static void hid_set_cb(USBDriver *usbp) {
|
|
(void)usbp;
|
|
isr_hid_set_report(hid_set_ctx.id, hid_set_buf, hid_set_ctx.len);
|
|
}
|
|
|
|
/* EP1: HID interrupt IN/OUT */
|
|
static USBInEndpointState ep1instate;
|
|
static USBOutEndpointState ep1outstate;
|
|
static const USBEndpointConfig ep1config = {
|
|
USB_EP_MODE_TYPE_INTR,
|
|
NULL, NULL, NULL,
|
|
HID_EP_SIZE, HID_EP_SIZE,
|
|
&ep1instate, &ep1outstate,
|
|
1, NULL
|
|
};
|
|
|
|
/* EP2: CDC interrupt IN (notifications) */
|
|
static USBInEndpointState ep2instate;
|
|
static const USBEndpointConfig ep2config = {
|
|
USB_EP_MODE_TYPE_INTR,
|
|
NULL,
|
|
sduInterruptTransmitted,
|
|
NULL,
|
|
CDC_INT_SIZE, 0x0000,
|
|
&ep2instate, NULL,
|
|
1, NULL
|
|
};
|
|
|
|
/* EP3: CDC bulk IN/OUT (data) */
|
|
static USBInEndpointState ep3instate;
|
|
static USBOutEndpointState ep3outstate;
|
|
static const USBEndpointConfig ep3config = {
|
|
USB_EP_MODE_TYPE_BULK,
|
|
NULL,
|
|
sduDataTransmitted,
|
|
sduDataReceived,
|
|
CDC_DATA_SIZE, CDC_DATA_SIZE,
|
|
&ep3instate, &ep3outstate,
|
|
1, NULL
|
|
};
|
|
|
|
static bool usb_request(USBDriver *usbp) {
|
|
uint8_t rtype = usbp->setup[0];
|
|
uint8_t req = usbp->setup[1];
|
|
|
|
if ((rtype & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE &&
|
|
req == USB_REQ_SET_INTERFACE) {
|
|
usbSetupTransfer(usbp, NULL, 0, NULL);
|
|
return true;
|
|
}
|
|
|
|
/* HID class requests targeted at interface 0 */
|
|
if ((rtype & (USB_RTYPE_TYPE_MASK | USB_RTYPE_RECIPIENT_MASK)) ==
|
|
(USB_RTYPE_TYPE_CLASS | USB_RTYPE_RECIPIENT_INTERFACE) &&
|
|
usbp->setup[4] == 0x00U) {
|
|
|
|
uint8_t report_id = usbp->setup[2];
|
|
uint16_t wlength = (uint16_t)usbp->setup[6] |
|
|
((uint16_t)usbp->setup[7] << 8);
|
|
|
|
switch (req) {
|
|
case HID_GET_REPORT: {
|
|
size_t len = HID_REPORT_BUF_SIZE;
|
|
if (!isr_hid_get_report(report_id, hid_get_buf, &len))
|
|
return false;
|
|
usbSetupTransfer(usbp, hid_get_buf,
|
|
len < wlength ? len : wlength, NULL);
|
|
return true;
|
|
}
|
|
case HID_SET_REPORT:
|
|
hid_set_ctx.id = report_id;
|
|
hid_set_ctx.len = wlength < HID_REPORT_BUF_SIZE
|
|
? wlength : HID_REPORT_BUF_SIZE;
|
|
usbSetupTransfer(usbp, hid_set_buf, hid_set_ctx.len, hid_set_cb);
|
|
return true;
|
|
case HID_SET_IDLE:
|
|
usbSetupTransfer(usbp, NULL, 0, NULL);
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ((rtype & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS &&
|
|
req == CDC_SET_CONTROL_LINE_STATE)
|
|
cdc_dtr = (usbp->setup[2] & 0x01U) != 0U;
|
|
|
|
return sduRequestsHook(usbp);
|
|
}
|
|
|
|
static void usb_event(USBDriver *usbp, usbevent_t event) {
|
|
switch (event) {
|
|
case USB_EVENT_ADDRESS:
|
|
return;
|
|
case USB_EVENT_CONFIGURED:
|
|
chSysLockFromISR();
|
|
if (usbp->state == USB_ACTIVE) {
|
|
usbInitEndpointI(usbp, HID_EP, &ep1config);
|
|
usbInitEndpointI(usbp, CDC_INT_EP, &ep2config);
|
|
usbInitEndpointI(usbp, CDC_DATA_EP, &ep3config);
|
|
sduConfigureHookI(&SDU1);
|
|
} else if (usbp->state == USB_SELECTED) {
|
|
usbDisableEndpointsI(usbp);
|
|
}
|
|
chSysUnlockFromISR();
|
|
return;
|
|
case USB_EVENT_RESET:
|
|
case USB_EVENT_UNCONFIGURED:
|
|
case USB_EVENT_SUSPEND:
|
|
cdc_dtr = false;
|
|
chSysLockFromISR();
|
|
sduSuspendHookI(&SDU1);
|
|
chSysUnlockFromISR();
|
|
return;
|
|
case USB_EVENT_WAKEUP:
|
|
chSysLockFromISR();
|
|
sduWakeupHookI(&SDU1);
|
|
chSysUnlockFromISR();
|
|
return;
|
|
case USB_EVENT_STALLED:
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void sof_handler(USBDriver *usbp) {
|
|
(void)usbp;
|
|
osalSysLockFromISR();
|
|
sduSOFHookI(&SDU1);
|
|
osalSysUnlockFromISR();
|
|
}
|
|
|
|
const USBConfig usbcfg = {
|
|
usb_event,
|
|
get_descriptor,
|
|
usb_request,
|
|
sof_handler
|
|
};
|
|
|
|
const SerialUSBConfig serusbcfg = {
|
|
&USBD1,
|
|
CDC_DATA_EP, /* bulk_in */
|
|
CDC_DATA_EP, /* bulk_out */
|
|
CDC_INT_EP /* int_in */
|
|
};
|