Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/flipperdevices/libusb_stm32.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry <dmitrystu@gmail.com>2018-06-03 19:27:57 +0300
committerDmitry <dmitrystu@gmail.com>2018-06-03 19:27:57 +0300
commit5a43907bc930bd2d3215facdaf774b3d40d55a99 (patch)
treef153ad8b0010f1640532fef912b3d0068fd1876d
parent7528ec83cc414432b0cd7760e293eac5c866198d (diff)
parent57e846f24dc399853299f14292b7101dc1c0cd34 (diff)
Merge branch 'TravisRo-master' into winusbwinusb
-rw-r--r--demo/winusb_loop.c372
-rw-r--r--inc/ms_os.h136
2 files changed, 508 insertions, 0 deletions
diff --git a/demo/winusb_loop.c b/demo/winusb_loop.c
new file mode 100644
index 0000000..9b9eff8
--- /dev/null
+++ b/demo/winusb_loop.c
@@ -0,0 +1,372 @@
+/* This file is the part of the Lightweight USB device Stack for STM32 microcontrollers
+ *
+ * Copyright ©2018 Travis Robinson <libusbdotnet[at]gmail[dot]com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f1xx_hal.h"
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include "usb.h"
+#include "ms_os.h"
+
+#ifndef _STM32_WUSB_CONFIG_
+
+// YOUR VENDOR ID
+// http://pid.codes/1209/
+#define WUSB_VEND_ID 0x1209
+
+// YOUR PRODUCT ID
+#define WUSB_PROD_ID 0x0777
+
+// YOUR MANUFACTURER NAME
+#define WUSB_MANUFACTURER_STR "github.TravisRo"
+
+// YOUR PRODUCT NAME
+#define WUSB_PRODUCT_STR "WinUSB Communication Device"
+
+// YOUR DEVICE-INTERFACE-GUID
+// NOTE: A '\0' terminator is required! (This is a multi-sz field)
+#define WUSB_DEVICE_INTERFACE_GUID "{B7705C49-EAC6-4C73-AE94-ACAEF841D599}\0"
+
+#else
+#endif
+
+/////////////////////////////////// DEMO ENDPOINT SETUP ////////////////////////////////////
+#define WUSB_EP0_MAXPACKET_SIZE (8)
+#define WUSB_EP1_MAXPACKET_SIZE (64)
+#define WUSB_EP1_RX (0x01)
+#define WUSB_EP1_TX (0x82)
+
+//////////////////////////////////////// VARIABLES ////////////////////////////////////////
+// USB device
+usbd_device udev;
+
+// USB device buffer (buffer for ep0 rx requests [usbd_ctlreq])
+// 32 bytes gives us an extra 24 bytes for an incoming data payload.
+// This can bet set as low as 2! (8 bytes to hold the setup
+uint32_t wusb_control_buffer[8];
+
+
+// STM32CUBE RTC handle
+RTC_HandleTypeDef hrtc;
+
+// DEMO endpoint buffer for loopback
+uint8_t fifo[WUSB_EP1_MAXPACKET_SIZE * 4];
+uint32_t fpos = 0;
+
+////////////////////////////////////// DEMO PROTOTYPES //////////////////////////////////////
+static void cdc_loopback(usbd_device* dev, uint8_t event, uint8_t ep);
+
+//////////////////////////////////////// DESCRIPTORS ////////////////////////////////////////
+struct winusb_config {
+ struct usb_config_descriptor cfg;
+ struct usb_interface_descriptor intf1;
+ struct usb_endpoint_descriptor eprx1;
+ struct usb_endpoint_descriptor eptx1;
+} __attribute__((packed));
+
+static const struct usb_device_descriptor device_desc = {
+ .bLength = sizeof(struct usb_device_descriptor),
+ .bDescriptorType = USB_DTYPE_DEVICE,
+ .bcdUSB = VERSION_BCD(2, 0, 0),
+ .bDeviceClass = USB_CLASS_PER_INTERFACE,
+ .bDeviceSubClass = USB_SUBCLASS_NONE,
+ .bDeviceProtocol = USB_PROTO_NONE,
+ .bMaxPacketSize0 = 8,
+ .idVendor = WUSB_VEND_ID,
+ .idProduct = WUSB_PROD_ID,
+ .bcdDevice = VERSION_BCD(1, 0, 0),
+ .iManufacturer = 1,
+ .iProduct = 2,
+ .iSerialNumber = INTSERIALNO_DESCRIPTOR,
+ .bNumConfigurations = 1,
+};
+
+static const struct winusb_config config_desc = {
+ .cfg = {
+ .bLength = sizeof(struct usb_config_descriptor),
+ .bDescriptorType = USB_DTYPE_CONFIGURATION,
+ .wTotalLength = sizeof(struct winusb_config),
+ .bNumInterfaces = 1,
+ .bConfigurationValue = 1,
+ .iConfiguration = NO_DESCRIPTOR,
+ .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
+ .bMaxPower = USB_CFG_POWER_MA(100),
+ },
+
+ .intf1 = {
+ .bLength = sizeof(struct usb_interface_descriptor),
+ .bDescriptorType = USB_DTYPE_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_APP_SPEC,
+ .bInterfaceSubClass = 0x01,
+ .bInterfaceProtocol = 0x07,
+ .iInterface = NO_DESCRIPTOR,
+ },
+ .eprx1 = {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DTYPE_ENDPOINT,
+ .bEndpointAddress = WUSB_EP1_RX,
+ .bmAttributes = USB_EPTYPE_BULK,
+ .wMaxPacketSize = WUSB_EP1_MAXPACKET_SIZE,
+ .bInterval = 0x00,
+ },
+ .eptx1 = {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DTYPE_ENDPOINT,
+ .bEndpointAddress = WUSB_EP1_TX,
+ .bmAttributes = USB_EPTYPE_BULK,
+ .wMaxPacketSize = WUSB_EP1_MAXPACKET_SIZE,
+ .bInterval = 0x00,
+ },
+};
+
+#define MS_VENDOR_CODE 0x20
+static const struct usb_string_descriptor ms_os_desc = USB_STRING_DESC("MSFT100\x20");
+
+static const struct usb_string_descriptor lang_desc = USB_ARRAY_DESC(USB_LANGID_ENG_US);
+static const struct usb_string_descriptor manuf_desc_en = USB_STRING_DESC(WUSB_MANUFACTURER_STR);
+static const struct usb_string_descriptor prod_desc_en = USB_STRING_DESC(WUSB_PRODUCT_STR);
+
+static const struct usb_string_descriptor*const dtable[] = {
+ &lang_desc,
+ &manuf_desc_en,
+ &prod_desc_en,
+};
+
+static const struct wusb_devguid_extprop_feature_descriptor devguid_ext_prop_feature_desc = {
+ .dwLength = sizeof(struct wusb_devguid_extprop_feature_descriptor),
+ .bcdVersion = VERSION_BCD(1,0,0),
+ .wIndex = 5,
+ .wCount = 1,
+ .dev_guid_property = {
+ .dwPropertyLength = sizeof(struct wusb_devguid_property),
+ .dwPropertyType = 7, // (7 = Unicode REG_MULTI_SZ)
+ .wPropertyNameLength = 42,
+ .wPropertyName = STRING_TO_WCHARS("DeviceInterfaceGUIDs"),
+ .dwPropertyDataLength = 80,
+ .wPropertyData = STRING_TO_WCHARS(WUSB_DEVICE_INTERFACE_GUID)
+ }
+};
+
+static const struct ms_os_compatid_descriptor compatid_desc = {
+ .dwLength = sizeof(struct ms_os_compatid_descriptor),
+ .bcdVersion = VERSION_BCD(1,0,0),
+ .wIndex = 4,
+ .bCount = 1,
+ ._reservedA = {0, 0, 0, 0, 0, 0, 0},
+ .bInterfaceNumber = 0,
+ ._reservedB = {0},
+ .chCompatibleID = {'W', 'I', 'N', 'U', 'S', 'B', 0, 0},
+ .chSubCompatibleID = {0, 0, 0, 0, 0, 0, 0, 0},
+ ._reservedC = {0, 0, 0, 0, 0, 0}
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////// USB Core callbacks //////////////////////////////////////////////
+static usbd_respond wusb_getdesc(usbd_ctlreq* req, void** address, uint16_t* length) {
+ const uint8_t dtype = req->wValue >> 8;
+ const uint8_t dnumber = req->wValue & 0xFF;
+ const void* desc;
+ uint16_t len = 0;
+ switch (dtype) {
+ case USB_DTYPE_DEVICE:
+ desc = &device_desc;
+ break;
+ case USB_DTYPE_CONFIGURATION:
+ desc = &config_desc;
+ len = sizeof(config_desc);
+ break;
+ case USB_DTYPE_STRING:
+ if (dnumber < 3) {
+ desc = dtable[dnumber];
+ }
+ else if (dnumber == 0xEE) {
+ // Microsoft OS String Descriptor
+ desc = &ms_os_desc;
+
+ /* MSDN NOTES
+ After the operating system requests a Microsoft OS String Descriptor from a device, it creates the following registry key:
+ HLKM\SYSTEM\CurrentControlSet\Control\UsbFlags\*vvvvpppprrrrr*
+
+ The operating system creates a registry entry, named osvc, under this registry key that indicates whether the device supports
+ Microsoft OS Descriptors. If the device does not provide a valid response the first time that the operating system queries it
+ for a Microsoft OS String Descriptor, the operating system will make no further requests for that descriptor.
+
+ [TR] Once it gets a successful enuration, it will make no further requests for it PERIOD.
+ [TR] You can change bcdDevice in the device descriptor to get a re-request or delete the UsbFlags key for your dev.
+ */
+ }
+ else {
+ return usbd_fail;
+ }
+ break;
+ default:
+ return usbd_fail;
+ }
+ if (len == 0) {
+ len = ((struct usb_header_descriptor*)desc)->bLength;
+ }
+ *address = (void*)desc;
+ *length = len;
+ return usbd_ack;
+}
+
+static usbd_respond wusb_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) {
+
+ // NOTE: In-order to get Windows to request these, the device must return the
+ // special string descriptor at index 0xEE
+ if (req->bRequest == MS_VENDOR_CODE &&
+ req->bmRequestType == (USB_REQ_DEVTOHOST | USB_REQ_VENDOR | USB_REQ_DEVICE)) {
+ switch (req->wIndex) {
+
+ case 0x04: // Compatible ID Feature Descriptor
+ // NOTE: data_ptr and data_count are the same as the address and length params
+ // in the get descriptor request.
+ dev->status.data_ptr = (void*)&compatid_desc;
+ dev->status.data_count = sizeof(compatid_desc);
+ return usbd_ack;
+
+ case 0x05: // Microsoft Extended Properties Feature Descriptor
+ dev->status.data_ptr = (void*)&devguid_ext_prop_feature_desc;
+ dev->status.data_count = sizeof(devguid_ext_prop_feature_desc);
+ return usbd_ack;
+
+ default: ;
+ }
+ }
+
+ return usbd_fail;
+}
+
+
+static usbd_respond wusb_setconf(usbd_device* dev, uint8_t cfg) {
+ switch (cfg) {
+ case 0:
+ /* deconfiguring device */
+ usbd_ep_deconfig(dev, WUSB_EP1_TX);
+ usbd_ep_deconfig(dev, WUSB_EP1_RX);
+ usbd_reg_endpoint(dev, WUSB_EP1_RX, 0);
+ usbd_reg_endpoint(dev, WUSB_EP1_TX, 0);
+ return usbd_ack;
+ case 1:
+ /* configuring device */
+ usbd_ep_config(dev, WUSB_EP1_RX, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, WUSB_EP1_MAXPACKET_SIZE);
+ usbd_ep_config(dev, WUSB_EP1_TX, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, WUSB_EP1_MAXPACKET_SIZE);
+
+ usbd_reg_endpoint(dev, WUSB_EP1_RX, cdc_loopback);
+ usbd_reg_endpoint(dev, WUSB_EP1_TX, cdc_loopback);
+
+ usbd_ep_write(dev, WUSB_EP1_TX, 0, 0);
+ return usbd_ack;
+ default:
+ return usbd_fail;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////// DEMO MAIN //////////////////////////////////////////////////
+static void cdc_loopback(usbd_device* dev, uint8_t event, uint8_t ep) {
+ int _t;
+ switch (event) {
+ case usbd_evt_eptx:
+ _t = usbd_ep_write(dev,
+ WUSB_EP1_TX,
+ &fifo[0],
+ (fpos < WUSB_EP1_MAXPACKET_SIZE) ? fpos : WUSB_EP1_MAXPACKET_SIZE);
+ if (_t > 0) {
+ memmove(&fifo[0], &fifo[_t], fpos - _t);
+ fpos -= _t;
+ }
+ case usbd_evt_eprx:
+ if (fpos < (sizeof(fifo) - WUSB_EP1_MAXPACKET_SIZE)) {
+ _t = usbd_ep_read(dev, WUSB_EP1_RX, &fifo[fpos], WUSB_EP1_MAXPACKET_SIZE);
+ if (_t > 0) {
+ fpos += _t;
+ }
+ }
+ default:
+ break;
+ }
+}
+
+static void wusb_init_usbd(void) {
+
+ usbd_init(&udev, &usbd_hw, WUSB_EP0_MAXPACKET_SIZE, wusb_control_buffer, sizeof(wusb_control_buffer));
+ usbd_reg_config(&udev, wusb_setconf);
+ usbd_reg_control(&udev, wusb_control);
+ usbd_reg_descr(&udev, wusb_getdesc);
+}
+
+#if defined(WUSB_USE_IRQ)
+#if defined(STM32L052xx)
+#define USB_HANDLER USB_IRQHandler
+#define USB_NVIC_IRQ USB_IRQn
+#elif defined(STM32L100xC)
+#define USB_HANDLER USB_LP_IRQHandler
+#define USB_NVIC_IRQ USB_LP_IRQn
+#elif defined(STM32L476xx)
+#define USB_HANDLER OTG_FS_IRQHandler
+#define USB_NVIC_IRQ OTG_FS_IRQn
+#elif defined(STM32F103x6)
+#define USB_HANDLER USB_LP_CAN1_RX0_IRQHandler
+#define USB_NVIC_IRQ USB_LP_CAN1_RX0_IRQn
+#elif defined(STM32F103xE)
+#define USB_HANDLER USB_LP_CAN1_RX0_IRQHandler
+#define USB_NVIC_IRQ USB_LP_CAN1_RX0_IRQn
+#elif defined(STM32F429xx)
+#define USB_HANDLER OTG_FS_IRQHandler
+#define USB_NVIC_IRQ OTG_FS_IRQn
+#else
+#error Not supported
+#endif
+#endif
+
+void USB_HANDLER(void) {
+ usbd_poll(&udev);
+}
+
+#ifdef CUBE_CALLS_MAIN
+void wusb_main(void) {
+#else
+ void main(void) {
+#endif
+
+ wusb_init_usbd();
+
+#ifdef USB_NVIC_IRQ
+ NVIC_EnableIRQ(USB_NVIC_IRQ);
+#endif
+ usbd_enable(&udev, true);
+ usbd_connect(&udev, true);
+ uint32_t curTick = HAL_GetTick();
+ while (true) {
+
+#ifndef USB_NVIC_IRQ
+ usbd_poll(&udev);
+#endif
+
+ const uint32_t nextTick = HAL_GetTick();
+ if (curTick + 1000 < nextTick) {
+ curTick = nextTick;
+ HAL_GPIO_TogglePin(LED_1_GPIO_Port, LED_1_Pin);
+ }
+#ifdef USB_NVIC_IRQ
+ __WFI();
+#endif
+ }
+}
diff --git a/inc/ms_os.h b/inc/ms_os.h
new file mode 100644
index 0000000..9160991
--- /dev/null
+++ b/inc/ms_os.h
@@ -0,0 +1,136 @@
+#ifndef _MS_OS_H_
+#define _MS_OS_H_
+/**
+ * Extended Properties OS Feature Descriptor Specification
+ * Extended Compat ID OS Feature Descriptor Specification
+ * v1.0
+ */
+
+/* This file is the part of the Lightweight USB device Stack for STM32 microcontrollers
+ *
+ * Copyright ©2018 Travis Robinson <libusbdotnet[at]gmail[dot]com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Macro to create a unicode char array */
+#define STRING_TO_WCHARS(s) {CAT(u,s)}
+
+/** Macro to return the total byte length of a string as if it were a unicode char array */
+#define SIZE_OF_WSTRING(s) sizeof(CAT(u,s))
+
+/** Total Length of a custom property name (in bytes).
+ *
+ * This can be hard-coded at 42 for a 'DeviceInterFaceGUIDs' property name.
+ */
+#define MSOS_DEVGUID_NAME_BLEN (SIZE_OF_WSTRING("DeviceInterfaceGUIDs"))
+
+/** Total Length of a custom property value (in bytes).
+ *
+ * This can be hard-coded at 80 for a 'DeviceInterFaceGUIDs' property value.
+ */
+#define MSOS_DEVGUID_VALUE_BLEN (SIZE_OF_WSTRING("{00000000-0000-0000-0000-000000000000}\0"))
+
+/**
+ * \brief windows (winusb) Extended Compat ID OS Feature Descriptor
+ *
+ * Stores one or more compatible IDs and subcompatible IDs in device firmware on a per-interface or per-function
+ * basis. Windows can then use these values much like class and subclass values to select an appropriate driver.
+ * (WinUSB for example)
+ */
+struct ms_os_compatid_descriptor {
+
+ /**<\brief The length, in bytes, of the complete descriptor (DWORD LE). (40 bytes) */
+ uint32_t dwLength;
+
+ /**<\brief The descriptor’s version number, in binary coded decimal (BCD) format. (v1.00) */
+ uint16_t bcdVersion;
+
+ /**<\brief The index for extended properties OS descriptors. (always 0x04 for extended compat ID descriptors) */
+ uint16_t wIndex;
+
+ /**<\brief The number of custom property sections that follow the header section. (1 property) */
+ uint8_t bCount;
+
+ /**<\brief Not used. fill with zeros. */
+ uint8_t _reservedA[7];
+
+ /**<\brief Interface or function that is associated with the IDs in this section */
+ uint8_t bInterfaceNumber;
+
+ /**<\brief Not used. fill with zeros. */
+ uint8_t _reservedB[1];
+
+ /**<\brief A fixed string assign by Microsoft. 8 chars. fill extras with zero. (See MSDN) */
+ uint8_t chCompatibleID[8];
+
+ /**<\brief A fixed string assign by Microsoft. 8 chars. fill extras with zero. (See MSDN) */
+ uint8_t chSubCompatibleID[8];
+
+ /**<\brief Not used. fill with zeros. */
+ uint8_t _reservedC[6];
+}__attribute__((packed));
+
+/**
+ * \brief windows (winusb) \bDeviceInterfaceGUIDs custom property
+ *
+ * This is a DeviceInterfaceGUIDs property section used in \ref wusb_devguid_extprop_feature_descriptor.
+ *
+ */
+struct wusb_devguid_property {
+ /**<\brief The size of this custom properties section, in bytes (136 bytes) */
+ uint32_t dwPropertyLength;
+
+ /**<\brief Property data format (7 = Unicode REG_MULTI_SZ) */
+ uint32_t dwPropertyType;
+
+ /**<\brief The total length of wPropertyName, in bytes (42) */
+ uint16_t wPropertyNameLength;
+
+ /**<\brief The property name, as a NULL-terminated Unicode string (42 bytes) */
+ uint16_t wPropertyName[MSOS_DEVGUID_NAME_BLEN / 2];
+
+ /**<\brief The total length of wPropertyData, in bytes (80) */
+ uint32_t dwPropertyDataLength;
+
+ /**<\brief (format-dependent) sz = Unicode strings (REG_MULTI_SZ, 76wchars + wnull + wnull = 80 bytes) */
+ uint16_t wPropertyData[MSOS_DEVGUID_VALUE_BLEN / 2];
+
+} __attribute__((packed));
+
+/**
+ * \brief windows (winusb) \bDeviceInterfaceGUIDs extended property feature descriptor
+ *
+ * This is an extended property feature descriptor containing a DeviceInterfaceGUIDs property section.
+ *
+ * Store DeviceInterfaceGUIDs in firmware and use them on Windows to locate and open a device.
+ *
+ */
+struct wusb_devguid_extprop_feature_descriptor {
+
+ /**<\brief The length, in bytes, of the complete extended properties descriptor (DWORD LE). (146 bytes) */
+ uint32_t dwLength;
+
+ /**<\brief The descriptor’s version number, in binary coded decimal (BCD) format. */
+ uint16_t bcdVersion;
+
+ /**<\brief The index for extended properties OS descriptors. (always 5) */
+ uint16_t wIndex;
+
+ /**<\brief The number of custom property sections that follow the header section. (1 property) */
+ uint16_t wCount;
+
+ /**<\brief device interface guid custom property */
+ struct wusb_devguid_property dev_guid_property;
+
+}__attribute__((packed));
+
+#endif \ No newline at end of file