|
@@ -0,0 +1,1089 @@
|
|
|
|
|
+/*
|
|
|
|
|
+ * Copyright (c) 2022 OpenLuat & AirM2M
|
|
|
|
|
+ *
|
|
|
|
|
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
|
|
|
+ * this software and associated documentation files (the "Software"), to deal in
|
|
|
|
|
+ * the Software without restriction, including without limitation the rights to
|
|
|
|
|
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
|
|
|
+ * the Software, and to permit persons to whom the Software is furnished to do so,
|
|
|
|
|
+ * subject to the following conditions:
|
|
|
|
|
+ *
|
|
|
|
|
+ * The above copyright notice and this permission notice shall be included in all
|
|
|
|
|
+ * copies or substantial portions of the Software.
|
|
|
|
|
+ *
|
|
|
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
|
|
|
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
|
|
|
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
|
|
|
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
|
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+#include "user.h"
|
|
|
|
|
+
|
|
|
|
|
+enum
|
|
|
|
|
+{
|
|
|
|
|
+ DEVICE_INTERFACE_HID_SN,
|
|
|
|
|
+ DEVICE_INTERFACE_MSC_SN,
|
|
|
|
|
+ DEVICE_INTERFACE_SERIAL_SN,
|
|
|
|
|
+ DEVICE_INTERFACE_MAX,
|
|
|
|
|
+};
|
|
|
|
|
+#define DEVICE_HID_KEYBOARD_EP_IN (0x01)
|
|
|
|
|
+#define DEVICE_HID_KEYBOARD_EP_OUT (0x01)
|
|
|
|
|
+#define DEVICE_MASS_STORAGE_EP_IN (0x02)
|
|
|
|
|
+#define DEVICE_MASS_STORAGE_EP_OUT (0x02)
|
|
|
|
|
+#define DEVICE_GENERIC_SERIAL_EP_IN (0x03)
|
|
|
|
|
+#define DEVICE_GENERIC_SERIAL_EP_OUT (0x03)
|
|
|
|
|
+#define VIRTUAL_SERIAL_BUFFER_LEN (8192)
|
|
|
|
|
+#define VIRTUAL_VHID_BUFFER_LEN (2048)
|
|
|
|
|
+#define VIRTUAL_UDISK_BLOCKS_LEN (512)
|
|
|
|
|
+#define VIRTUAL_UDISK_BLOCKS_NUMS (32)
|
|
|
|
|
+#define VIRTUAL_UDISK_LEN (VIRTUAL_UDISK_BLOCKS_NUMS * VIRTUAL_UDISK_BLOCKS_LEN)
|
|
|
|
|
+//#define TEST_SPEED
|
|
|
|
|
+
|
|
|
|
|
+typedef struct
|
|
|
|
|
+{
|
|
|
|
|
+ uint32_t CurAddress;
|
|
|
|
|
+ uint32_t BlockNums;
|
|
|
|
|
+ uint32_t BlockSize;
|
|
|
|
|
+ uint32_t BlockTotalNums;
|
|
|
|
|
+ uint8_t *VirtualData;
|
|
|
|
|
+}Virtual_UDiskCtrlStruct;
|
|
|
|
|
+
|
|
|
|
|
+typedef struct
|
|
|
|
|
+{
|
|
|
|
|
+ Buffer_Struct TxBuf;
|
|
|
|
|
+ Buffer_Struct TxCacheBuf; // 缓存下次发送的数据
|
|
|
|
|
+ CBFuncEx_t CB;
|
|
|
|
|
+ uint8_t USB_ID;
|
|
|
|
|
+ uint8_t IsReady;
|
|
|
|
|
+ uint8_t ToHostEpIndex;
|
|
|
|
|
+}Virtual_HIDCtrlStruct;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+typedef struct
|
|
|
|
|
+{
|
|
|
|
|
+ Buffer_Struct TxBuf;
|
|
|
|
|
+ Buffer_Struct TxCacheBuf; // 缓存下次发送的数据
|
|
|
|
|
+ Buffer_Struct RxBuf;
|
|
|
|
|
+ CBFuncEx_t CB;
|
|
|
|
|
+ Timer_t *RxTimer;
|
|
|
|
|
+ uint32_t RxTimeoutUS;
|
|
|
|
|
+ uint8_t *TxData;
|
|
|
|
|
+ uint8_t USBOnOff;
|
|
|
|
|
+ uint8_t UartOnOff;
|
|
|
|
|
+ uint8_t USB_ID;
|
|
|
|
|
+ uint8_t ToHostEpIndex;
|
|
|
|
|
+ uint8_t ToDeviceEpIndex;
|
|
|
|
|
+}Virtual_UartCtrlStruct;
|
|
|
|
|
+
|
|
|
|
|
+static MSC_SCSICtrlStruct prvLuatOS_SCSI;
|
|
|
|
|
+static Virtual_HIDCtrlStruct prvLuatOS_VirtualHID;
|
|
|
|
|
+static Virtual_UDiskCtrlStruct prvLuatOS_VirtualUDisk;
|
|
|
|
|
+static Virtual_UartCtrlStruct prvLuatOS_VirtualUart[VIRTUAL_UART_MAX];
|
|
|
|
|
+
|
|
|
|
|
+/* LangID = 0x0409: U.S. English */
|
|
|
|
|
+static const char prvCore_StringManufacturer[] = "airm2m";
|
|
|
|
|
+static const char prvCore_StringProduct[] = "air105 usb device";
|
|
|
|
|
+static const char prvCore_StringSerial[] = "00001";
|
|
|
|
|
+static const char prvCore_StringConfig[] = "luatos";
|
|
|
|
|
+static const char *prvCore_StringInterface[3] = {
|
|
|
|
|
+ "virtual Mass Storage Device",
|
|
|
|
|
+ "virtual HID Keyboard",
|
|
|
|
|
+ "virtual Serial"
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+static const usb_device_descriptor_t prvCore_DeviceDesc =
|
|
|
|
|
+{
|
|
|
|
|
+ .bLength = USB_LEN_DEV_DESC,
|
|
|
|
|
+ .bDescriptorType = UDESC_DEVICE,
|
|
|
|
|
+ .bcdUSB = {0x00, 0x02},
|
|
|
|
|
+ .bDeviceClass = UDCLASS_IN_INTERFACE,
|
|
|
|
|
+ .bDeviceSubClass = 0,
|
|
|
|
|
+ .bDeviceProtocol = 0,
|
|
|
|
|
+ .bMaxPacketSize = 0x40,
|
|
|
|
|
+ .idVendor = {0x82, 0x17},
|
|
|
|
|
+ .idProduct = {0x00, 0x4e},
|
|
|
|
|
+// .idVendor = {0x83, 0x04},
|
|
|
|
|
+// .idProduct = {0x20, 0x57},
|
|
|
|
|
+ .bcdDevice = {0x00, 0x02},
|
|
|
|
|
+ .iManufacturer = USBD_IDX_MANUFACTURER_STR,
|
|
|
|
|
+ .iProduct = USBD_IDX_PRODUCT_STR,
|
|
|
|
|
+ .iSerialNumber = 0,
|
|
|
|
|
+ .bNumConfigurations = 1,
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static const usb_device_qualifier_t prvCore_QualifierDesc =
|
|
|
|
|
+{
|
|
|
|
|
+ .bLength = USB_LEN_DEV_QUALIFIER_DESC, /* bLength */
|
|
|
|
|
+ .bDescriptorType = UDESC_DEVICE_QUALIFIER, /* bDescriptorType */
|
|
|
|
|
+ .bcdUSB = {0x00, 0x02},
|
|
|
|
|
+ .bDeviceClass = UDCLASS_IN_INTERFACE,
|
|
|
|
|
+ .bDeviceSubClass = 0,
|
|
|
|
|
+ .bDeviceProtocol = 0,
|
|
|
|
|
+ .bMaxPacketSize0 = 0x40,
|
|
|
|
|
+ .bNumConfigurations = 1,
|
|
|
|
|
+ .bReserved = 0
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static const usb_config_descriptor_t prvCore_ConfigDesc =
|
|
|
|
|
+{
|
|
|
|
|
+ .bLength = USB_LEN_CFG_DESC,
|
|
|
|
|
+ .bDescriptorType = UDESC_CONFIG,
|
|
|
|
|
+ .wTotalLength = {0x00, 0x00},
|
|
|
|
|
+ .bNumInterface = DEVICE_INTERFACE_MAX,
|
|
|
|
|
+ .bConfigurationValue = 1,
|
|
|
|
|
+ .iConfiguration = USBD_IDX_CONFIG_STR,
|
|
|
|
|
+ .bmAttributes = UC_SELF_POWERED|UC_BUS_POWERED,
|
|
|
|
|
+ .bMaxPower = (USB_MIN_POWER >> 1),
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static const usb_interface_assoc_descriptor_t prvCore_AssocInterfaceDesc =
|
|
|
|
|
+{
|
|
|
|
|
+ .bLength = USB_LEN_ASSOC_IF_DESC,
|
|
|
|
|
+ .bDescriptorType = UDESC_IFACE_ASSOC,
|
|
|
|
|
+ .bFirstInterface = 0,
|
|
|
|
|
+ .bInterfaceCount = 1,
|
|
|
|
|
+// .bFunctionClass = UICLASS_MASS,
|
|
|
|
|
+// .bFunctionSubClass = UISUBCLASS_SCSI,
|
|
|
|
|
+// .bFunctionProtocol = UIPROTO_MASS_BBB,
|
|
|
|
|
+// .bFunctionClass = 0,
|
|
|
|
|
+// .bFunctionSubClass = 0,
|
|
|
|
|
+// .bFunctionProtocol = 0,
|
|
|
|
|
+ .bFunctionClass = UICLASS_HID,
|
|
|
|
|
+ .bFunctionSubClass = 0,
|
|
|
|
|
+ .bFunctionProtocol = UIPROTO_BOOT_KEYBOARD,
|
|
|
|
|
+ .iFunction = USBD_IDX_INTERFACE0_STR,
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static const usb_interface_descriptor_t prvCore_MassStorgeInterfaceDesc =
|
|
|
|
|
+{
|
|
|
|
|
+ .bLength = USB_LEN_IF_DESC,
|
|
|
|
|
+ .bDescriptorType = UDESC_INTERFACE,
|
|
|
|
|
+ .bInterfaceNumber = DEVICE_INTERFACE_MSC_SN,
|
|
|
|
|
+ .bAlternateSetting = 0,
|
|
|
|
|
+ .bNumEndpoints = 2,
|
|
|
|
|
+ .bInterfaceClass = UICLASS_MASS,
|
|
|
|
|
+ .bInterfaceSubClass = UISUBCLASS_SCSI,
|
|
|
|
|
+ .bInterfaceProtocol = UIPROTO_MASS_BBB,
|
|
|
|
|
+ .iInterface = USBD_IDX_INTERFACE0_STR,
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static const usb_endpoint_descriptor_t prvCore_MassStorgeEndpointDesc[2] =
|
|
|
|
|
+{
|
|
|
|
|
+ {
|
|
|
|
|
+ .bLength = USB_LEN_EP_DESC,
|
|
|
|
|
+ .bDescriptorType = UDESC_ENDPOINT,
|
|
|
|
|
+ .bEndpointAddress = UE_DIR_IN|DEVICE_MASS_STORAGE_EP_IN,
|
|
|
|
|
+ .bmAttributes = UE_BULK,
|
|
|
|
|
+ .wMaxPacketSize = {0x40,0x00},
|
|
|
|
|
+ .bInterval = 10,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ .bLength = USB_LEN_EP_DESC,
|
|
|
|
|
+ .bDescriptorType = UDESC_ENDPOINT,
|
|
|
|
|
+ .bEndpointAddress = UE_DIR_OUT|DEVICE_MASS_STORAGE_EP_OUT,
|
|
|
|
|
+ .bmAttributes = UE_BULK,
|
|
|
|
|
+ .wMaxPacketSize = {0x40,0x00},
|
|
|
|
|
+ .bInterval = 10,
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static const usb_interface_descriptor_t prvCore_HIDInterfaceDesc =
|
|
|
|
|
+{
|
|
|
|
|
+ .bLength = USB_LEN_IF_DESC,
|
|
|
|
|
+ .bDescriptorType = UDESC_INTERFACE,
|
|
|
|
|
+ .bInterfaceNumber = DEVICE_INTERFACE_HID_SN,
|
|
|
|
|
+ .bAlternateSetting = 0,
|
|
|
|
|
+ .bNumEndpoints = 2,
|
|
|
|
|
+ .bInterfaceClass = UICLASS_HID,
|
|
|
|
|
+ .bInterfaceSubClass = 0,
|
|
|
|
|
+ .bInterfaceProtocol = UIPROTO_BOOT_KEYBOARD,
|
|
|
|
|
+ .iInterface = USBD_IDX_INTERFACE0_STR + 1,
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static const usb_endpoint_descriptor_t prvCore_HIDEndpointDesc[2] =
|
|
|
|
|
+{
|
|
|
|
|
+ {
|
|
|
|
|
+ .bLength = USB_LEN_EP_DESC,
|
|
|
|
|
+ .bDescriptorType = UDESC_ENDPOINT,
|
|
|
|
|
+ .bEndpointAddress = UE_DIR_IN|DEVICE_HID_KEYBOARD_EP_IN,
|
|
|
|
|
+ .bmAttributes = UE_INTERRUPT,
|
|
|
|
|
+ .wMaxPacketSize = {0x08,0x00},
|
|
|
|
|
+ .bInterval = 10,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ .bLength = USB_LEN_EP_DESC,
|
|
|
|
|
+ .bDescriptorType = UDESC_ENDPOINT,
|
|
|
|
|
+ .bEndpointAddress = UE_DIR_OUT|DEVICE_HID_KEYBOARD_EP_OUT,
|
|
|
|
|
+ .bmAttributes = UE_INTERRUPT,
|
|
|
|
|
+ .wMaxPacketSize = {0x08,0x00},
|
|
|
|
|
+ .bInterval = 10,
|
|
|
|
|
+ },
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static const usb_interface_descriptor_t prvCore_SerialInterfaceDesc =
|
|
|
|
|
+{
|
|
|
|
|
+ .bLength = USB_LEN_IF_DESC,
|
|
|
|
|
+ .bDescriptorType = UDESC_INTERFACE,
|
|
|
|
|
+ .bInterfaceNumber = DEVICE_INTERFACE_SERIAL_SN,
|
|
|
|
|
+ .bAlternateSetting = 0,
|
|
|
|
|
+ .bNumEndpoints = 2,
|
|
|
|
|
+ .bInterfaceClass = UICLASS_VENDOR,
|
|
|
|
|
+ .bInterfaceSubClass = 0,
|
|
|
|
|
+ .bInterfaceProtocol = 0,
|
|
|
|
|
+ .iInterface = USBD_IDX_INTERFACE0_STR + 2,
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static const usb_endpoint_descriptor_t prvCore_SerialEndpointDesc[2] =
|
|
|
|
|
+{
|
|
|
|
|
+ {
|
|
|
|
|
+ .bLength = USB_LEN_EP_DESC,
|
|
|
|
|
+ .bDescriptorType = UDESC_ENDPOINT,
|
|
|
|
|
+ .bEndpointAddress = UE_DIR_IN|DEVICE_GENERIC_SERIAL_EP_IN,
|
|
|
|
|
+ .bmAttributes = UE_BULK,
|
|
|
|
|
+ .wMaxPacketSize = {0x40,0x00},
|
|
|
|
|
+ .bInterval = 10,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ .bLength = USB_LEN_EP_DESC,
|
|
|
|
|
+ .bDescriptorType = UDESC_ENDPOINT,
|
|
|
|
|
+ .bEndpointAddress = UE_DIR_OUT|DEVICE_GENERIC_SERIAL_EP_OUT,
|
|
|
|
|
+ .bmAttributes = UE_BULK,
|
|
|
|
|
+ .wMaxPacketSize = {0x40,0x00},
|
|
|
|
|
+ .bInterval = 10,
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static const usb_hid_descriptor_t prvCore_HIDDesc =
|
|
|
|
|
+{
|
|
|
|
|
+ .bLength = 9,
|
|
|
|
|
+ .bDescriptorType = USB_HID_DESCRIPTOR_TYPE,
|
|
|
|
|
+ .bcdHID = {0x11, 0x01},
|
|
|
|
|
+ .bCountryCode = 0x21,
|
|
|
|
|
+ .bNumDescriptors = 1,
|
|
|
|
|
+ .bReportDescriptorType = USB_HID_REPORT_DESC,
|
|
|
|
|
+ .wDescriptorLength = {63,0},
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static const char prvCore_HIDReportDesc[63] = {
|
|
|
|
|
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
|
|
|
|
+ 0x09, 0x06, // USAGE (Keyboard)
|
|
|
|
|
+ 0xa1, 0x01, // COLLECTION (Application)
|
|
|
|
|
+ 0x05, 0x07, // USAGE_PAGE (Keyboard)
|
|
|
|
|
+ 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
|
|
|
|
|
+ 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
|
|
|
|
|
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
|
|
|
|
|
+ 0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
|
|
|
|
+ 0x75, 0x01, // REPORT_SIZE (1)
|
|
|
|
|
+ 0x95, 0x08, // REPORT_COUNT (8)
|
|
|
|
|
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
|
|
|
|
|
+ 0x95, 0x01, // REPORT_COUNT (1)
|
|
|
|
|
+ 0x75, 0x08, // REPORT_SIZE (8)
|
|
|
|
|
+ 0x81, 0x03, // INPUT (Cnst,Var,Abs)
|
|
|
|
|
+ 0x95, 0x05, // REPORT_COUNT (5)
|
|
|
|
|
+ 0x75, 0x01, // REPORT_SIZE (1)
|
|
|
|
|
+ 0x05, 0x08, // USAGE_PAGE (LEDs)
|
|
|
|
|
+ 0x19, 0x01, // USAGE_MINIMUM (Num Lock)
|
|
|
|
|
+ 0x29, 0x05, // USAGE_MAXIMUM (Kana)
|
|
|
|
|
+ 0x91, 0x02, // OUTPUT (Data,Var,Abs)
|
|
|
|
|
+ 0x95, 0x01, // REPORT_COUNT (1)
|
|
|
|
|
+ 0x75, 0x03, // REPORT_SIZE (3)
|
|
|
|
|
+ 0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
|
|
|
|
|
+ 0x95, 0x06, // REPORT_COUNT (6)
|
|
|
|
|
+ 0x75, 0x08, // REPORT_SIZE (8)
|
|
|
|
|
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
|
|
|
|
|
+ 0x25, 0xff, // LOGICAL_MAXIMUM (255)
|
|
|
|
|
+ 0x05, 0x07, // USAGE_PAGE (Keyboard)
|
|
|
|
|
+ 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
|
|
|
|
|
+ 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
|
|
|
|
|
+ 0x81, 0x00, // INPUT (Data,Ary,Abs)
|
|
|
|
|
+ 0xc0 // END_COLLECTION
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_GetHIDDesc(void *pData, void *pParam)
|
|
|
|
|
+{
|
|
|
|
|
+ if (pData)
|
|
|
|
|
+ {
|
|
|
|
|
+ memcpy(pData, &prvCore_HIDDesc, sizeof(usb_hid_descriptor_t));
|
|
|
|
|
+ }
|
|
|
|
|
+ return sizeof(usb_hid_descriptor_t);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static usb_full_interface_t prvCore_InterfaceList[3] =
|
|
|
|
|
+{
|
|
|
|
|
+ {
|
|
|
|
|
+ &prvCore_HIDInterfaceDesc,
|
|
|
|
|
+ prvCore_HIDEndpointDesc,
|
|
|
|
|
+ NULL,
|
|
|
|
|
+ prvCore_GetHIDDesc,
|
|
|
|
|
+ 2,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ &prvCore_MassStorgeInterfaceDesc,
|
|
|
|
|
+ prvCore_MassStorgeEndpointDesc,
|
|
|
|
|
+ NULL,
|
|
|
|
|
+ NULL,
|
|
|
|
|
+ 2,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ &prvCore_SerialInterfaceDesc,
|
|
|
|
|
+ prvCore_SerialEndpointDesc,
|
|
|
|
|
+ NULL,
|
|
|
|
|
+ NULL,
|
|
|
|
|
+ 2,
|
|
|
|
|
+ },
|
|
|
|
|
+};
|
|
|
|
|
+static const usb_full_config_t prvCore_Config =
|
|
|
|
|
+{
|
|
|
|
|
+ .pConfigDesc = &prvCore_ConfigDesc,
|
|
|
|
|
+ .pInterfaceAssocDesc = &prvCore_AssocInterfaceDesc,
|
|
|
|
|
+ .pInterfaceFullDesc = prvCore_InterfaceList,
|
|
|
|
|
+ .InterfaceNum = 3,
|
|
|
|
|
+};
|
|
|
|
|
+static const USB_FullConfigStruct prvCore_FullConfig =
|
|
|
|
|
+{
|
|
|
|
|
+ .pQualifierDesc = NULL,
|
|
|
|
|
+ .pFullConfig = {&prvCore_Config, NULL, NULL},
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static const uint8_t prvCore_StandardInquiryData[STANDARD_INQUIRY_DATA_LEN] =
|
|
|
|
|
+{
|
|
|
|
|
+ 0x00, //磁盘设备
|
|
|
|
|
+ 0x00, //其中最高位D7为RMB。RMB=0,表示不可移除设备。如果RMB=1,则为可移除设备。
|
|
|
|
|
+ 0x02, //各种版本号
|
|
|
|
|
+ 0x02, //数据响应格式 0x02
|
|
|
|
|
+ 0x1F, //附加数据长度,为31字节
|
|
|
|
|
+ 0x00, //保留
|
|
|
|
|
+ 0x00, //保留
|
|
|
|
|
+ 0x00, //保留
|
|
|
|
|
+ 'A','I','R','M','2','M',' ',' ',
|
|
|
|
|
+ 'L','U','A','T','O','S','-','S','O','C',' ','U','S','B',' ',' ',
|
|
|
|
|
+ '1','.','0','0'
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static const uint8_t prvCore_MSCPage00InquiryData[LENGTH_INQUIRY_PAGE00] =
|
|
|
|
|
+{
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ (LENGTH_INQUIRY_PAGE00 - 4U),
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x80
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+/* USB Mass storage VPD Page 0x80 Inquiry Data for Unit Serial Number */
|
|
|
|
|
+static const uint8_t prvCore_MSCPage80InquiryData[LENGTH_INQUIRY_PAGE80] =
|
|
|
|
|
+{
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x80,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ LENGTH_INQUIRY_PAGE80,
|
|
|
|
|
+ 0x20, /* Put Product Serial number */
|
|
|
|
|
+ 0x20,
|
|
|
|
|
+ 0x20,
|
|
|
|
|
+ 0x20
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+/* USB Mass storage sense 6 Data */
|
|
|
|
|
+static const uint8_t prvCore_MSCModeSense6data[MODE_SENSE6_LEN] =
|
|
|
|
|
+{
|
|
|
|
|
+ 0x22,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x08,
|
|
|
|
|
+ 0x12,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+/* USB Mass storage sense 10 Data */
|
|
|
|
|
+static const uint8_t prvCore_MSCModeSense10data[MODE_SENSE10_LEN] =
|
|
|
|
|
+{
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x26,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x08,
|
|
|
|
|
+ 0x12,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00,
|
|
|
|
|
+ 0x00
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_SCSIInit(uint8_t LUN, void *pUserData)
|
|
|
|
|
+{
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_SCSIGetCapacity(uint8_t LUN, uint32_t *BlockNum, uint32_t *BlockSize, void *pUserData)
|
|
|
|
|
+{
|
|
|
|
|
+ *BlockNum = prvLuatOS_VirtualUDisk.BlockTotalNums;
|
|
|
|
|
+ *BlockSize = prvLuatOS_VirtualUDisk.BlockSize;
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_SCSIIsReady(uint8_t LUN, void *pUserData)
|
|
|
|
|
+{
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_SCSIIsWriteProtected(uint8_t LUN, void *pUserData)
|
|
|
|
|
+{
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_SCSIPreRead(uint8_t LUN, uint32_t BlockAddress, uint32_t BlockNums, void *pUserData)
|
|
|
|
|
+{
|
|
|
|
|
+ if ((BlockAddress + BlockNums) * prvLuatOS_VirtualUDisk.BlockSize > VIRTUAL_UDISK_LEN)
|
|
|
|
|
+ {
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ prvLuatOS_VirtualUDisk.CurAddress = BlockAddress * prvLuatOS_VirtualUDisk.BlockSize;
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_SCSIRead(uint8_t LUN, uint32_t Len, uint8_t **pOutData, uint32_t *OutLen, void *pUserData)
|
|
|
|
|
+{
|
|
|
|
|
+ if (Len + prvLuatOS_VirtualUDisk.CurAddress > VIRTUAL_UDISK_LEN)
|
|
|
|
|
+ {
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ *pOutData = &prvLuatOS_VirtualUDisk.VirtualData[prvLuatOS_VirtualUDisk.CurAddress];
|
|
|
|
|
+ *OutLen = Len;
|
|
|
|
|
+ prvLuatOS_VirtualUDisk.CurAddress += Len;
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_SCSIPreWrite(uint8_t LUN, uint32_t BlockAddress, uint32_t BlockNums, void *pUserData)
|
|
|
|
|
+{
|
|
|
|
|
+ if ((BlockAddress + BlockNums) * prvLuatOS_VirtualUDisk.BlockSize > VIRTUAL_UDISK_LEN)
|
|
|
|
|
+ {
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ prvLuatOS_VirtualUDisk.CurAddress = BlockAddress * prvLuatOS_VirtualUDisk.BlockSize;
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_SCSIWrite(uint8_t LUN, uint8_t *Data, uint32_t Len, void *pUserData)
|
|
|
|
|
+{
|
|
|
|
|
+ if (Len + prvLuatOS_VirtualUDisk.CurAddress > VIRTUAL_UDISK_LEN)
|
|
|
|
|
+ {
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ memcpy(&prvLuatOS_VirtualUDisk.VirtualData[prvLuatOS_VirtualUDisk.CurAddress], Data, Len);
|
|
|
|
|
+ prvLuatOS_VirtualUDisk.CurAddress += Len;
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+static int32_t prvCore_SCSIUserCmd(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct *pMSC)
|
|
|
|
|
+{
|
|
|
|
|
+ return -1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_SCSIGetMaxLUN(uint8_t *LUN, void *pUserData)
|
|
|
|
|
+{
|
|
|
|
|
+ *LUN = 0;
|
|
|
|
|
+}
|
|
|
|
|
+static const USB_StorageSCSITypeDef prvCore_SCSIFun =
|
|
|
|
|
+{
|
|
|
|
|
+ prvCore_SCSIGetMaxLUN,
|
|
|
|
|
+ prvCore_SCSIInit,
|
|
|
|
|
+ prvCore_SCSIGetCapacity,
|
|
|
|
|
+ prvCore_SCSIIsReady,
|
|
|
|
|
+ prvCore_SCSIIsWriteProtected,
|
|
|
|
|
+ prvCore_SCSIPreRead,
|
|
|
|
|
+ prvCore_SCSIRead,
|
|
|
|
|
+ prvCore_SCSIPreWrite,
|
|
|
|
|
+ prvCore_SCSIWrite,
|
|
|
|
|
+ prvCore_SCSIUserCmd,
|
|
|
|
|
+ &prvCore_StandardInquiryData,
|
|
|
|
|
+ &prvCore_MSCPage00InquiryData,
|
|
|
|
|
+ &prvCore_MSCPage80InquiryData,
|
|
|
|
|
+ &prvCore_MSCModeSense6data,
|
|
|
|
|
+ &prvCore_MSCModeSense10data,
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static void prvCore_VUartOpen(Virtual_UartCtrlStruct *pVUart, uint8_t UartID)
|
|
|
|
|
+{
|
|
|
|
|
+ pVUart->USBOnOff = 1;
|
|
|
|
|
+ if (pVUart->TxBuf.Data)
|
|
|
|
|
+ {
|
|
|
|
|
+ DBG("send last data %ubyte", pVUart->TxBuf.MaxLen);
|
|
|
|
|
+ USB_StackTxEpData(pVUart->USB_ID, pVUart->ToHostEpIndex, pVUart->TxBuf.Data, pVUart->TxBuf.MaxLen, pVUart->TxBuf.MaxLen, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (pVUart->TxCacheBuf.Pos)
|
|
|
|
|
+ {
|
|
|
|
|
+ DBG("send cache data %ubyte", pVUart->TxCacheBuf.Pos);
|
|
|
|
|
+ Buffer_StaticInit(&pVUart->TxBuf, pVUart->TxCacheBuf.Data, pVUart->TxCacheBuf.Pos);
|
|
|
|
|
+ OS_InitBuffer(&pVUart->TxCacheBuf, VIRTUAL_SERIAL_BUFFER_LEN);
|
|
|
|
|
+ USB_StackTxEpData(pVUart->USB_ID, pVUart->ToHostEpIndex, pVUart->TxBuf.Data, pVUart->TxBuf.MaxLen, pVUart->TxBuf.MaxLen, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ pVUart->CB(UartID, UART_CB_CONNECTED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_VUartRxTimeoutCB(void *pData, void *pParam)
|
|
|
|
|
+{
|
|
|
|
|
+ uint32_t UartID = (uint32_t)pParam;
|
|
|
|
|
+ prvLuatOS_VirtualUart[UartID].CB(UartID, UART_CB_RX_TIMEOUT);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_VHIDDummyCB(void *pData, void *pParam)
|
|
|
|
|
+{
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_VUartDummyCB(void *pData, void *pParam)
|
|
|
|
|
+{
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_VMSCDummyCB(void *pData, void *pParam)
|
|
|
|
|
+{
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void prvCore_VHIDSetReady(uint8_t OnOff)
|
|
|
|
|
+{
|
|
|
|
|
+ if (prvLuatOS_VirtualHID.IsReady != OnOff)
|
|
|
|
|
+ {
|
|
|
|
|
+ prvLuatOS_VirtualHID.IsReady = OnOff;
|
|
|
|
|
+ prvLuatOS_VirtualHID.CB(prvLuatOS_VirtualHID.USB_ID, prvLuatOS_VirtualHID.IsReady);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_USBEp0CB(void *pData, void *pParam)
|
|
|
|
|
+{
|
|
|
|
|
+ int32_t Result = -ERROR_CMD_NOT_SUPPORT;
|
|
|
|
|
+ USB_EndpointDataStruct *pEpData = (USB_EndpointDataStruct *)pData;
|
|
|
|
|
+ USB_StorageSCSITypeDef *pUserFun = (USB_StorageSCSITypeDef *)prvLuatOS_SCSI.pSCSIUserFunList;
|
|
|
|
|
+ uint16_t wLength, wValue;
|
|
|
|
|
+ Virtual_UartCtrlStruct *pVUart;
|
|
|
|
|
+// DBG("%d,%d,%d,%d", pEpData->USB_ID, pEpData->EpIndex, pEpData->IsToDevice, pEpData->Len);
|
|
|
|
|
+ if (!pEpData->IsDataStage)
|
|
|
|
|
+ {
|
|
|
|
|
+ wLength = BytesGetLe16(pEpData->pLastRequest->wLength);
|
|
|
|
|
+ if (pEpData->IsToDevice)
|
|
|
|
|
+ {
|
|
|
|
|
+ switch (pEpData->pLastRequest->bRequest)
|
|
|
|
|
+ {
|
|
|
|
|
+ case UCDC_SET_CONTROL_LINE_STATE:
|
|
|
|
|
+ pVUart = &prvLuatOS_VirtualUart[pEpData->pLastRequest->wIndex[0] - DEVICE_INTERFACE_SERIAL_SN];
|
|
|
|
|
+ switch (pEpData->pLastRequest->wValue[0])
|
|
|
|
|
+ {
|
|
|
|
|
+ case 0:
|
|
|
|
|
+ //close serial
|
|
|
|
|
+ pVUart->USBOnOff = 0;
|
|
|
|
|
+ pVUart->CB(pEpData->pLastRequest->wIndex[0] - DEVICE_INTERFACE_SERIAL_SN, UART_CB_ERROR);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 1:
|
|
|
|
|
+ case 3:
|
|
|
|
|
+ //open serial
|
|
|
|
|
+ prvCore_VUartOpen(pVUart, pEpData->pLastRequest->wIndex[0] - DEVICE_INTERFACE_SERIAL_SN);
|
|
|
|
|
+ prvLuatOS_VirtualUart[pEpData->pLastRequest->wIndex[0] - DEVICE_INTERFACE_SERIAL_SN].USBOnOff = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ Result = ERROR_NONE;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case USB_HID_REQ_SET_IDLE:
|
|
|
|
|
+ prvCore_VHIDSetReady(1);
|
|
|
|
|
+ Result = ERROR_NONE;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case UR_GET_DESCRIPTOR:
|
|
|
|
|
+ switch(pEpData->pLastRequest->wValue[1])
|
|
|
|
|
+ {
|
|
|
|
|
+ case USB_HID_REPORT_DESC:
|
|
|
|
|
+ USB_StackTxEpData(pEpData->USB_ID, pEpData->EpIndex, prvCore_HIDReportDesc, sizeof(prvCore_HIDReportDesc), wLength, 1);
|
|
|
|
|
+ Result = ERROR_NONE;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case MSC_GET_MAX_LUN:
|
|
|
|
|
+ pUserFun->GetMaxLUN(&prvLuatOS_SCSI.LogicalUnitNum, prvLuatOS_SCSI.pUserData);
|
|
|
|
|
+ USB_StackTxEpData(pEpData->USB_ID, pEpData->EpIndex, &prvLuatOS_SCSI.LogicalUnitNum, 1, wLength, 1);
|
|
|
|
|
+
|
|
|
|
|
+ Result = ERROR_NONE;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case MSC_RESET:
|
|
|
|
|
+ Result = ERROR_NONE;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return Result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_MSCCB(void *pData, void *pParam)
|
|
|
|
|
+{
|
|
|
|
|
+ USB_EndpointDataStruct *pEpData = (USB_EndpointDataStruct *)pData;
|
|
|
|
|
+ USB_MSCHandle(pEpData, &prvLuatOS_SCSI);
|
|
|
|
|
+ return ERROR_NONE;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_HIDCB(void *pData, void *pParam)
|
|
|
|
|
+{
|
|
|
|
|
+ USB_EndpointDataStruct *pEpData = (USB_EndpointDataStruct *)pData;
|
|
|
|
|
+ uint32_t USB_ID = (uint32_t)pParam;
|
|
|
|
|
+ Virtual_HIDCtrlStruct *pVHID = &prvLuatOS_VirtualHID;
|
|
|
|
|
+ if (pEpData->IsToDevice)
|
|
|
|
|
+ {
|
|
|
|
|
+ prvCore_VHIDSetReady(1);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ OS_DeInitBuffer(&pVHID->TxBuf);
|
|
|
|
|
+ if (pVHID->TxCacheBuf.Pos)
|
|
|
|
|
+ {
|
|
|
|
|
+ Buffer_StaticInit(&pVHID->TxBuf, pVHID->TxCacheBuf.Data, pVHID->TxCacheBuf.Pos);
|
|
|
|
|
+ OS_InitBuffer(&pVHID->TxCacheBuf, VIRTUAL_VHID_BUFFER_LEN);
|
|
|
|
|
+ USB_StackTxEpData(pVHID->USB_ID, pVHID->ToHostEpIndex, pVHID->TxBuf.Data, pVHID->TxBuf.MaxLen, pVHID->TxBuf.MaxLen, 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ pVHID->CB(USB_ID, USB_HID_SEND_DONE);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return ERROR_NONE;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_SerialCB(void *pData, void *pParam)
|
|
|
|
|
+{
|
|
|
|
|
+ USB_EndpointDataStruct *pEpData = (USB_EndpointDataStruct *)pData;
|
|
|
|
|
+ uint32_t UartID = (uint32_t)pParam;
|
|
|
|
|
+ Virtual_UartCtrlStruct *pVUart = &prvLuatOS_VirtualUart[UartID];
|
|
|
|
|
+ if (pEpData->IsToDevice)
|
|
|
|
|
+ {
|
|
|
|
|
+ //open serial
|
|
|
|
|
+ if (!pVUart->USBOnOff)
|
|
|
|
|
+ {
|
|
|
|
|
+ prvCore_VUartOpen(pVUart, UartID);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (pEpData->Data && pEpData->Len)
|
|
|
|
|
+ {
|
|
|
|
|
+ if ((pVUart->RxBuf.Pos + pEpData->Len) >= pVUart->RxBuf.MaxLen)
|
|
|
|
|
+ {
|
|
|
|
|
+ OS_ReSizeBuffer(&pVUart->RxBuf, pVUart->RxBuf.MaxLen * 2);
|
|
|
|
|
+ }
|
|
|
|
|
+ OS_BufferWrite(&pVUart->RxBuf, pEpData->Data, pEpData->Len);
|
|
|
|
|
+ if (pEpData->IsDataStage && pVUart->RxTimeoutUS)
|
|
|
|
|
+ {
|
|
|
|
|
+ Timer_StartUS(pVUart->RxTimer, pVUart->RxTimeoutUS, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ Timer_Stop(pVUart->RxTimer);
|
|
|
|
|
+ pVUart->CB(UartID, UART_CB_RX_NEW);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ OS_DeInitBuffer(&pVUart->TxBuf);
|
|
|
|
|
+ if (pVUart->TxCacheBuf.Pos)
|
|
|
|
|
+ {
|
|
|
|
|
+ Buffer_StaticInit(&pVUart->TxBuf, pVUart->TxCacheBuf.Data, pVUart->TxCacheBuf.Pos);
|
|
|
|
|
+ OS_InitBuffer(&pVUart->TxCacheBuf, VIRTUAL_SERIAL_BUFFER_LEN);
|
|
|
|
|
+ USB_StackTxEpData(pVUart->USB_ID, pVUart->ToHostEpIndex, pVUart->TxBuf.Data, pVUart->TxBuf.MaxLen, pVUart->TxBuf.MaxLen, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ pVUart->CB(UartID, UART_CB_TX_ALL_DONE);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return ERROR_NONE;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int32_t prvCore_USBStateCB(void *pData, void *pParam)
|
|
|
|
|
+{
|
|
|
|
|
+ PV_Union uPV;
|
|
|
|
|
+ uint8_t i;
|
|
|
|
|
+ uPV.p = pData;
|
|
|
|
|
+ switch(uPV.u8[1])
|
|
|
|
|
+ {
|
|
|
|
|
+ case USBD_BUS_TYPE_DISCONNECT:
|
|
|
|
|
+ prvCore_VHIDSetReady(0);
|
|
|
|
|
+ USB_MSCReset(&prvLuatOS_SCSI);
|
|
|
|
|
+ for(i = 0; i < VIRTUAL_UART_MAX; i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ prvLuatOS_VirtualUart[i].USBOnOff = 0;
|
|
|
|
|
+ prvLuatOS_VirtualUart[i].CB(i, UART_CB_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case USBD_BUS_TYPE_ENABLE_CONNECT:
|
|
|
|
|
+ USB_StackStartDevice(uPV.u8[0]);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Core_USBDefaultDeviceStart(uint8_t USB_ID)
|
|
|
|
|
+{
|
|
|
|
|
+ uint8_t langid[2] = {0x09, 0x04};
|
|
|
|
|
+ int i;
|
|
|
|
|
+ prvLuatOS_VirtualHID.USB_ID = USB_ID;
|
|
|
|
|
+ prvLuatOS_VirtualHID.IsReady = 0;
|
|
|
|
|
+ prvLuatOS_VirtualHID.ToHostEpIndex = DEVICE_HID_KEYBOARD_EP_IN;
|
|
|
|
|
+ prvLuatOS_VirtualUDisk.BlockTotalNums = VIRTUAL_UDISK_BLOCKS_NUMS;
|
|
|
|
|
+ prvLuatOS_VirtualUDisk.BlockSize = VIRTUAL_UDISK_BLOCKS_LEN;
|
|
|
|
|
+ prvLuatOS_SCSI.LogicalUnitNum = 0;
|
|
|
|
|
+ prvLuatOS_SCSI.ToHostEpIndex = DEVICE_MASS_STORAGE_EP_IN;
|
|
|
|
|
+ prvLuatOS_SCSI.ToDeviceEpIndex = DEVICE_MASS_STORAGE_EP_OUT;
|
|
|
|
|
+ prvLuatOS_SCSI.pSCSIUserFunList = &prvCore_SCSIFun;
|
|
|
|
|
+ if (!prvLuatOS_VirtualHID.CB)
|
|
|
|
|
+ {
|
|
|
|
|
+ prvLuatOS_VirtualHID.CB = prvCore_VHIDDummyCB;
|
|
|
|
|
+ }
|
|
|
|
|
+ OS_ReInitBuffer(&prvLuatOS_VirtualHID.TxCacheBuf, VIRTUAL_VHID_BUFFER_LEN);
|
|
|
|
|
+ USB_StackPowerOnOff(USB_ID, 1);
|
|
|
|
|
+ USB_StackStop(USB_ID);
|
|
|
|
|
+ USB_StackClearSetup(USB_ID);
|
|
|
|
|
+ USB_StackSetDeviceBusPower(USB_ID, 1);
|
|
|
|
|
+ USB_StackSetEpCB(USB_ID, 0, prvCore_USBEp0CB, NULL);
|
|
|
|
|
+ USB_StackSetEpCB(USB_ID, DEVICE_HID_KEYBOARD_EP_IN, prvCore_HIDCB, USB_ID);
|
|
|
|
|
+ USB_StackSetEpCB(USB_ID, DEVICE_HID_KEYBOARD_EP_OUT, prvCore_HIDCB, USB_ID);
|
|
|
|
|
+ USB_StackSetEpCB(USB_ID, DEVICE_MASS_STORAGE_EP_IN, prvCore_MSCCB, USB_ID);
|
|
|
|
|
+ USB_StackSetEpCB(USB_ID, DEVICE_MASS_STORAGE_EP_OUT, prvCore_MSCCB, USB_ID);
|
|
|
|
|
+ USB_StackSetEpCB(USB_ID, DEVICE_GENERIC_SERIAL_EP_IN, prvCore_SerialCB, VIRTUAL_UART0);
|
|
|
|
|
+ USB_StackSetEpCB(USB_ID, DEVICE_GENERIC_SERIAL_EP_OUT, prvCore_SerialCB, VIRTUAL_UART0);
|
|
|
|
|
+ USB_StackSetDeviceConfig(USB_ID, &prvCore_DeviceDesc, &prvCore_FullConfig, 1, USBD_IDX_INTERFACE0_STR + 3, prvCore_USBStateCB, NULL);
|
|
|
|
|
+ USB_StackSetCharString(USB_ID, USBD_IDX_LANGID_STR, langid, 2);
|
|
|
|
|
+ USB_StackSetCharString(USB_ID, USBD_IDX_MANUFACTURER_STR, prvCore_StringManufacturer, sizeof(prvCore_StringManufacturer));
|
|
|
|
|
+ USB_StackSetCharString(USB_ID, USBD_IDX_PRODUCT_STR, prvCore_StringProduct, sizeof(prvCore_StringProduct));
|
|
|
|
|
+ USB_StackSetCharString(USB_ID, USBD_IDX_SERIAL_STR, prvCore_StringSerial, sizeof(prvCore_StringSerial));
|
|
|
|
|
+ USB_StackSetCharString(USB_ID, USBD_IDX_CONFIG_STR, prvCore_StringConfig, sizeof(prvCore_StringConfig));
|
|
|
|
|
+ for(i = 0; i < 3; i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ USB_StackSetCharString(USB_ID, USBD_IDX_INTERFACE0_STR + i, prvCore_StringInterface[i], strlen(prvCore_StringInterface[i]));
|
|
|
|
|
+ }
|
|
|
|
|
+ for(i = 0; i < VIRTUAL_UART_MAX; i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ prvLuatOS_VirtualUart[i].USBOnOff = 0;
|
|
|
|
|
+ prvLuatOS_VirtualUart[i].USB_ID = USB_ID;
|
|
|
|
|
+ if (!prvLuatOS_VirtualUart[i].RxTimer)
|
|
|
|
|
+ {
|
|
|
|
|
+ prvLuatOS_VirtualUart[i].RxTimer = Timer_Create(prvCore_VUartRxTimeoutCB, i, NULL);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!prvLuatOS_VirtualUart[i].CB)
|
|
|
|
|
+ {
|
|
|
|
|
+ prvLuatOS_VirtualUart[i].CB = prvCore_VUartDummyCB;
|
|
|
|
|
+ }
|
|
|
|
|
+ prvLuatOS_VirtualUart[i].RxTimeoutUS = 150;
|
|
|
|
|
+ OS_ReInitBuffer(&prvLuatOS_VirtualUart[i].TxCacheBuf, VIRTUAL_SERIAL_BUFFER_LEN);
|
|
|
|
|
+ OS_ReInitBuffer(&prvLuatOS_VirtualUart[i].RxBuf, VIRTUAL_SERIAL_BUFFER_LEN);
|
|
|
|
|
+ }
|
|
|
|
|
+ prvLuatOS_VirtualUart[VIRTUAL_UART0].ToDeviceEpIndex = DEVICE_GENERIC_SERIAL_EP_IN;
|
|
|
|
|
+ prvLuatOS_VirtualUart[VIRTUAL_UART0].ToHostEpIndex = DEVICE_GENERIC_SERIAL_EP_OUT;
|
|
|
|
|
+ prvLuatOS_VirtualUDisk.VirtualData = prvLuatOS_VirtualUart[VIRTUAL_UART0].TxCacheBuf.Data;
|
|
|
|
|
+ USB_MSCReset(&prvLuatOS_SCSI);
|
|
|
|
|
+
|
|
|
|
|
+ USB_StackStartDevice(USB_ID);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+void Core_VHIDInit(uint8_t USB_ID, CBFuncEx_t CB)
|
|
|
|
|
+{
|
|
|
|
|
+ if (CB)
|
|
|
|
|
+ {
|
|
|
|
|
+ prvLuatOS_VirtualHID.CB = CB;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ prvLuatOS_VirtualHID.CB = prvCore_VHIDDummyCB;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Core_VUartInit(uint8_t UartID, uint32_t BaudRate, uint8_t IsRxCacheEnable, uint8_t DataBits, uint8_t Parity, uint8_t StopBits, CBFuncEx_t CB)
|
|
|
|
|
+{
|
|
|
|
|
+ Virtual_UartCtrlStruct *pVUart = &prvLuatOS_VirtualUart[UartID];
|
|
|
|
|
+// switch(UartID)
|
|
|
|
|
+// {
|
|
|
|
|
+// case VIRTUAL_UART0:
|
|
|
|
|
+// if (!prvService.IsUSBOpen)
|
|
|
|
|
+// {
|
|
|
|
|
+// Core_USBDefaultDeviceStart(USB_ID0);
|
|
|
|
|
+// prvService.IsUSBOpen = 1;
|
|
|
|
|
+// }
|
|
|
|
|
+// break;
|
|
|
|
|
+// }
|
|
|
|
|
+ if (CB)
|
|
|
|
|
+ {
|
|
|
|
|
+ pVUart->CB = CB;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ pVUart->CB = prvCore_VUartDummyCB;
|
|
|
|
|
+ }
|
|
|
|
|
+ pVUart->UartOnOff = 1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Core_VUartDeInit(uint8_t UartID)
|
|
|
|
|
+{
|
|
|
|
|
+ Virtual_UartCtrlStruct *pVUart = &prvLuatOS_VirtualUart[UartID];
|
|
|
|
|
+ pVUart->UartOnOff = 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Core_VUartSetRxTimeout(uint8_t UartID, uint32_t TimeoutUS)
|
|
|
|
|
+{
|
|
|
|
|
+ Virtual_UartCtrlStruct *pVUart = &prvLuatOS_VirtualUart[UartID];
|
|
|
|
|
+ pVUart->RxTimeoutUS = TimeoutUS;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Core_VUartSetCb(uint8_t UartID, CBFuncEx_t CB)
|
|
|
|
|
+{
|
|
|
|
|
+ Virtual_UartCtrlStruct *pVUart = &prvLuatOS_VirtualUart[UartID];
|
|
|
|
|
+ if (CB)
|
|
|
|
|
+ {
|
|
|
|
|
+ pVUart->CB = CB;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ pVUart->CB = prvCore_VUartDummyCB;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+uint32_t Core_VUartRxBufferRead(uint8_t UartID, uint8_t *Data, uint32_t Len)
|
|
|
|
|
+{
|
|
|
|
|
+ uint32_t ReadLen;
|
|
|
|
|
+ Virtual_UartCtrlStruct *pVUart = &prvLuatOS_VirtualUart[UartID];
|
|
|
|
|
+ switch(UartID)
|
|
|
|
|
+ {
|
|
|
|
|
+ case VIRTUAL_UART0:
|
|
|
|
|
+ USB_StackEpIntOnOff(pVUart->USB_ID, pVUart->ToDeviceEpIndex, 1, 0);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!Len)
|
|
|
|
|
+ {
|
|
|
|
|
+ ReadLen = pVUart->RxBuf.Pos;
|
|
|
|
|
+ goto READ_END;
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+ ReadLen = (pVUart->RxBuf.Pos < Len)?pVUart->RxBuf.Pos:Len;
|
|
|
|
|
+ memcpy(Data, pVUart->RxBuf.Data, ReadLen);
|
|
|
|
|
+ OS_BufferRemove(&pVUart->RxBuf, ReadLen);
|
|
|
|
|
+ if (!pVUart->RxBuf.Pos && pVUart->RxBuf.MaxLen > VIRTUAL_SERIAL_BUFFER_LEN)
|
|
|
|
|
+ {
|
|
|
|
|
+ OS_ReInitBuffer(&pVUart->RxBuf, VIRTUAL_SERIAL_BUFFER_LEN);
|
|
|
|
|
+ }
|
|
|
|
|
+READ_END:
|
|
|
|
|
+ switch(UartID)
|
|
|
|
|
+ {
|
|
|
|
|
+ case VIRTUAL_UART0:
|
|
|
|
|
+ USB_StackEpIntOnOff(pVUart->USB_ID, pVUart->ToDeviceEpIndex, 1, 1);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ return ReadLen;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int32_t Core_VUartBufferTx(uint8_t UartID, const uint8_t *Data, uint32_t Len)
|
|
|
|
|
+{
|
|
|
|
|
+ Virtual_UartCtrlStruct *pVUart = &prvLuatOS_VirtualUart[UartID];
|
|
|
|
|
+
|
|
|
|
|
+ switch(UartID)
|
|
|
|
|
+ {
|
|
|
|
|
+ case VIRTUAL_UART0:
|
|
|
|
|
+ if (!pVUart->USBOnOff)
|
|
|
|
|
+ {
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ USB_StackEpIntOnOff(pVUart->USB_ID, pVUart->ToHostEpIndex, 0, 0);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (Data && Len)
|
|
|
|
|
+ {
|
|
|
|
|
+ OS_BufferWrite(&pVUart->TxCacheBuf, Data, Len);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (pVUart->TxBuf.Data || pVUart->TxBuf.MaxLen)
|
|
|
|
|
+ {
|
|
|
|
|
+ goto TX_END;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 把缓存的Tx指针交给发送的Tx指针,缓存的Tx指针重新建立一个
|
|
|
|
|
+ Buffer_StaticInit(&pVUart->TxBuf, pVUart->TxCacheBuf.Data, pVUart->TxCacheBuf.Pos);
|
|
|
|
|
+ OS_InitBuffer(&pVUart->TxCacheBuf, VIRTUAL_SERIAL_BUFFER_LEN);
|
|
|
|
|
+ USB_StackTxEpData(pVUart->USB_ID, pVUart->ToHostEpIndex, pVUart->TxBuf.Data, pVUart->TxBuf.MaxLen, pVUart->TxBuf.MaxLen, 0);
|
|
|
|
|
+TX_END:
|
|
|
|
|
+ switch(UartID)
|
|
|
|
|
+ {
|
|
|
|
|
+ case VIRTUAL_UART0:
|
|
|
|
|
+ USB_StackEpIntOnOff(pVUart->USB_ID, pVUart->ToHostEpIndex, 0, 1);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
+void Core_VUartBufferTxStop(uint8_t UartID)
|
|
|
|
|
+{
|
|
|
|
|
+ Virtual_UartCtrlStruct *pVUart = &prvLuatOS_VirtualUart[UartID];
|
|
|
|
|
+ switch(UartID)
|
|
|
|
|
+ {
|
|
|
|
|
+ case VIRTUAL_UART0:
|
|
|
|
|
+ USB_StackEpIntOnOff(pVUart->USB_ID, pVUart->ToHostEpIndex, 0, 0);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ OS_DeInitBuffer(&pVUart->TxBuf);
|
|
|
|
|
+ pVUart->TxCacheBuf.Pos = 0;
|
|
|
|
|
+ USB_StackStopDeviceTx(pVUart->USB_ID, pVUart->ToHostEpIndex, 0);
|
|
|
|
|
+ switch(UartID)
|
|
|
|
|
+ {
|
|
|
|
|
+ case VIRTUAL_UART0:
|
|
|
|
|
+ USB_StackEpIntOnOff(pVUart->USB_ID, pVUart->ToHostEpIndex, 0, 1);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Core_VHIDUploadData(uint8_t USB_ID, uint8_t *Data, uint16_t Len)
|
|
|
|
|
+{
|
|
|
|
|
+ if (!prvLuatOS_VirtualHID.IsReady) return;
|
|
|
|
|
+ USB_HIDKeyValue HIDKey;
|
|
|
|
|
+ USB_HIDKeyBoradKeyStruct HIDKeyBoard;
|
|
|
|
|
+ uint16_t Pos;
|
|
|
|
|
+ volatile uint8_t IsShift, i, LastValue;
|
|
|
|
|
+ Virtual_HIDCtrlStruct *pVHID = &prvLuatOS_VirtualHID;
|
|
|
|
|
+ USB_StackEpIntOnOff(pVHID->USB_ID, pVHID->ToHostEpIndex, 0, 0);
|
|
|
|
|
+
|
|
|
|
|
+ if (Data && Len)
|
|
|
|
|
+ {
|
|
|
|
|
+ if ((Len*16 + pVHID->TxCacheBuf.Pos) > pVHID->TxCacheBuf.MaxLen)
|
|
|
|
|
+ {
|
|
|
|
|
+ OS_ReSizeBuffer(&pVHID->TxCacheBuf, Len*16 + pVHID->TxCacheBuf.Pos);
|
|
|
|
|
+ }
|
|
|
|
|
+ Pos = 0;
|
|
|
|
|
+ while(Pos < Len)
|
|
|
|
|
+ {
|
|
|
|
|
+ memset(&HIDKeyBoard, 0, sizeof(USB_HIDKeyBoradKeyStruct));
|
|
|
|
|
+ HIDKey = USB_HIDGetValueFromAscii(Data[Pos]);
|
|
|
|
|
+ Pos++;
|
|
|
|
|
+ IsShift = HIDKey.Shift;
|
|
|
|
|
+ LastValue = HIDKey.Value;
|
|
|
|
|
+ HIDKeyBoard.SPECIALHID_KEY_b.RightShift = IsShift;
|
|
|
|
|
+ HIDKeyBoard.PressKey[0] = HIDKey.Value;
|
|
|
|
|
+// DBG("%u,%c,%d,%x,%d", Pos - 1, Data[Pos - 1], 0, HIDKey.Value, HIDKey.Shift);
|
|
|
|
|
+ADD_REST:
|
|
|
|
|
+ for(i = 1; i < 4; i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ HIDKey = USB_HIDGetValueFromAscii(Data[Pos]);
|
|
|
|
|
+ Pos++;
|
|
|
|
|
+ if ((IsShift != HIDKey.Shift))
|
|
|
|
|
+ {
|
|
|
|
|
+ //shift发生切换,必须换新的data
|
|
|
|
|
+ OS_BufferWrite(&pVHID->TxCacheBuf, &HIDKeyBoard, sizeof(HIDKeyBoard));
|
|
|
|
|
+ memset(&HIDKeyBoard, 0, sizeof(USB_HIDKeyBoradKeyStruct));
|
|
|
|
|
+ //加入一个抬起的data
|
|
|
|
|
+ OS_BufferWrite(&pVHID->TxCacheBuf, &HIDKeyBoard, sizeof(HIDKeyBoard));
|
|
|
|
|
+ IsShift = HIDKey.Shift;
|
|
|
|
|
+ LastValue = HIDKey.Value;
|
|
|
|
|
+ HIDKeyBoard.SPECIALHID_KEY_b.RightShift = IsShift;
|
|
|
|
|
+ HIDKeyBoard.PressKey[0] = HIDKey.Value;
|
|
|
|
|
+// DBG("%u,%c,%d,%x,%d", Pos - 1, Data[Pos - 1], 0, HIDKey.Value, HIDKey.Shift);
|
|
|
|
|
+ if (Pos < Len)
|
|
|
|
|
+ {
|
|
|
|
|
+ goto ADD_REST;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (LastValue == HIDKey.Value)
|
|
|
|
|
+ {
|
|
|
|
|
+ OS_BufferWrite(&pVHID->TxCacheBuf, &HIDKeyBoard, sizeof(HIDKeyBoard));
|
|
|
|
|
+ memset(&HIDKeyBoard, 0, sizeof(USB_HIDKeyBoradKeyStruct));
|
|
|
|
|
+ //加入一个抬起的data
|
|
|
|
|
+ OS_BufferWrite(&pVHID->TxCacheBuf, &HIDKeyBoard, sizeof(HIDKeyBoard));
|
|
|
|
|
+ IsShift = HIDKey.Shift;
|
|
|
|
|
+ LastValue = HIDKey.Value;
|
|
|
|
|
+ HIDKeyBoard.SPECIALHID_KEY_b.RightShift = IsShift;
|
|
|
|
|
+ HIDKeyBoard.PressKey[0] = HIDKey.Value;
|
|
|
|
|
+// DBG("%u,%c,%d,%x,%d", Pos - 1, Data[Pos - 1], 0, HIDKey.Value, HIDKey.Shift);
|
|
|
|
|
+ if (Pos < Len)
|
|
|
|
|
+ {
|
|
|
|
|
+ goto ADD_REST;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ LastValue = HIDKey.Value;
|
|
|
|
|
+ HIDKeyBoard.PressKey[i] = HIDKey.Value;
|
|
|
|
|
+// DBG("%u,%c,%d,%x,%d", Pos - 1, Data[Pos - 1], i, HIDKey.Value, HIDKey.Shift);
|
|
|
|
|
+ if (Pos >= Len)
|
|
|
|
|
+ {
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ OS_BufferWrite(&pVHID->TxCacheBuf, &HIDKeyBoard, sizeof(HIDKeyBoard));
|
|
|
|
|
+ //加入一个抬起的data
|
|
|
|
|
+ memset(&HIDKeyBoard, 0, sizeof(USB_HIDKeyBoradKeyStruct));
|
|
|
|
|
+ OS_BufferWrite(&pVHID->TxCacheBuf, &HIDKeyBoard, sizeof(HIDKeyBoard));
|
|
|
|
|
+ }
|
|
|
|
|
+ //加入一个抬起的data
|
|
|
|
|
+ memset(&HIDKeyBoard, 0, sizeof(USB_HIDKeyBoradKeyStruct));
|
|
|
|
|
+ OS_BufferWrite(&pVHID->TxCacheBuf, &HIDKeyBoard, sizeof(HIDKeyBoard));
|
|
|
|
|
+ }
|
|
|
|
|
+// pVHID->TxCacheBuf.Pos = 0;
|
|
|
|
|
+// return;
|
|
|
|
|
+ if (pVHID->TxBuf.Data || pVHID->TxBuf.MaxLen)
|
|
|
|
|
+ {
|
|
|
|
|
+ goto UPLOAD_END;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 把缓存的Tx指针交给发送的Tx指针,缓存的Tx指针重新建立一个
|
|
|
|
|
+ Buffer_StaticInit(&pVHID->TxBuf, pVHID->TxCacheBuf.Data, pVHID->TxCacheBuf.Pos);
|
|
|
|
|
+ OS_InitBuffer(&pVHID->TxCacheBuf, VIRTUAL_VHID_BUFFER_LEN);
|
|
|
|
|
+ USB_StackTxEpData(pVHID->USB_ID, pVHID->ToHostEpIndex, pVHID->TxBuf.Data, pVHID->TxBuf.MaxLen, pVHID->TxBuf.MaxLen, 1);
|
|
|
|
|
+UPLOAD_END:
|
|
|
|
|
+ USB_StackEpIntOnOff(pVHID->USB_ID, pVHID->ToHostEpIndex, 0, 1);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Core_VHIDUploadStop(uint8_t USB_ID)
|
|
|
|
|
+{
|
|
|
|
|
+ Virtual_HIDCtrlStruct *pVHID = &prvLuatOS_VirtualHID;
|
|
|
|
|
+ USB_StackEpIntOnOff(pVHID->USB_ID, pVHID->ToHostEpIndex, 0, 0);
|
|
|
|
|
+ OS_DeInitBuffer(&pVHID->TxBuf);
|
|
|
|
|
+ pVHID->TxCacheBuf.Pos = 0;
|
|
|
|
|
+ USB_StackStopDeviceTx(pVHID->USB_ID, pVHID->ToHostEpIndex, 0);
|
|
|
|
|
+ USB_StackEpIntOnOff(pVHID->USB_ID, pVHID->ToHostEpIndex, 0, 1);
|
|
|
|
|
+}
|