Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Readme.md@1:0c3b6cc480b6, 2017-02-13 (annotated)
- Committer:
- Timmmm
- Date:
- Mon Feb 13 14:56:00 2017 +0000
- Revision:
- 1:0c3b6cc480b6
- Parent:
- 0:1a3aa2e25db9
Various changes?
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Timmmm | 0:1a3aa2e25db9 | 1 | # WinUSB Device Example |
Timmmm | 0:1a3aa2e25db9 | 2 | |
Timmmm | 0:1a3aa2e25db9 | 3 | If you've ever got frustrated with hardcoded COM ports and parsing text-based serial |
Timmmm | 0:1a3aa2e25db9 | 4 | protocols, this is for you. |
Timmmm | 0:1a3aa2e25db9 | 5 | |
Timmmm | 0:1a3aa2e25db9 | 6 | ## Introduction |
Timmmm | 0:1a3aa2e25db9 | 7 | |
Timmmm | 0:1a3aa2e25db9 | 8 | When we want our microcontroller to communicate with a control program running on a computer |
Timmmm | 0:1a3aa2e25db9 | 9 | via USB, the usual solution is to use serial-over-USB. It's easy, universally supported, and |
Timmmm | 0:1a3aa2e25db9 | 10 | signed drivers are often automatically installed - this is even called out as a selling point |
Timmmm | 0:1a3aa2e25db9 | 11 | by FTDI who make most of the serial-to-USB interface chips used by hobbiests. |
Timmmm | 0:1a3aa2e25db9 | 12 | |
Timmmm | 0:1a3aa2e25db9 | 13 | There are other advantages of serial control interfaces: |
Timmmm | 0:1a3aa2e25db9 | 14 | |
Timmmm | 0:1a3aa2e25db9 | 15 | * It doesn't require a specific program to control - you can use an terminal program. My favourite is Termie. |
Timmmm | 0:1a3aa2e25db9 | 16 | * It's easy to debug and you can easily add printf()-style debugging to your program. |
Timmmm | 0:1a3aa2e25db9 | 17 | * All microcontrollers support UART. |
Timmmm | 0:1a3aa2e25db9 | 18 | |
Timmmm | 0:1a3aa2e25db9 | 19 | Eventually however you will run up against the limitations. The highest 'standard' speed is 115200 kb/s. Some |
Timmmm | 0:1a3aa2e25db9 | 20 | microcontrollers support higher speeds, even up to 3 Mb/s but that is rare. Since the protocol |
Timmmm | 0:1a3aa2e25db9 | 21 | is stream-based you must create your own framing system or resort to text-based protocol. |
Timmmm | 0:1a3aa2e25db9 | 22 | |
Timmmm | 0:1a3aa2e25db9 | 23 | Another big problem is that there isn't a good way to detect which COM port your device is plugged |
Timmmm | 0:1a3aa2e25db9 | 24 | into. Even if your serial API allows enumerating ports (many don't) you might have several different |
Timmmm | 0:1a3aa2e25db9 | 25 | serial devices plugged in. Distinguishing them becomes a nightmare, especially as the COM port |
Timmmm | 0:1a3aa2e25db9 | 26 | can change across reboots, and if you move the device between physical USB ports. |
Timmmm | 0:1a3aa2e25db9 | 27 | |
Timmmm | 0:1a3aa2e25db9 | 28 | A solution - if your microcontroller supports it - is to use USB as nature intended. Turn your |
Timmmm | 0:1a3aa2e25db9 | 29 | device into a custom USB device and have your program communicate with it via libusb. This |
Timmmm | 0:1a3aa2e25db9 | 30 | is more complicated, but the end result is better. |
Timmmm | 0:1a3aa2e25db9 | 31 | |
Timmmm | 0:1a3aa2e25db9 | 32 | Fortunately mBed comes with USB device support for several boards. We'll look at implementing |
Timmmm | 0:1a3aa2e25db9 | 33 | a simple on/off switch with the FRDM-K22F. |
Timmmm | 0:1a3aa2e25db9 | 34 | |
Timmmm | 0:1a3aa2e25db9 | 35 | ## WinUSB Devices / WICD |
Timmmm | 0:1a3aa2e25db9 | 36 | |
Timmmm | 0:1a3aa2e25db9 | 37 | One of the first problems you'll discover - at least on Windows - is the need for signed device drivers. |
Timmmm | 0:1a3aa2e25db9 | 38 | In the past the only way to support a custom USB device seamlessly on Windows was to write a USB |
Timmmm | 0:1a3aa2e25db9 | 39 | driver (difficult!) and submit it to Microsoft to be tested and signed (expensive!). Fortunately now |
Timmmm | 0:1a3aa2e25db9 | 40 | there is a better way. |
Timmmm | 0:1a3aa2e25db9 | 41 | |
Timmmm | 0:1a3aa2e25db9 | 42 | By configuring our USB device in a certain way we can identify it to Windows as a "WinUSB Device". This |
Timmmm | 0:1a3aa2e25db9 | 43 | means that Windows 7 and later will automatically install Microsoft's WinUSB driver for it. This |
Timmmm | 0:1a3aa2e25db9 | 44 | is a generic driver that allows access to USB functions from userspace - i.e. your program. |
Timmmm | 0:1a3aa2e25db9 | 45 | libusb has support for the WinUSB driver so you can still write cross-platform code. |
Timmmm | 0:1a3aa2e25db9 | 46 | |
Timmmm | 0:1a3aa2e25db9 | 47 | Before I explain how to implement WinUSB I'll give brief overview of how USB works. |
Timmmm | 0:1a3aa2e25db9 | 48 | |
Timmmm | 0:1a3aa2e25db9 | 49 | ## A very brief introduction to USB |
Timmmm | 0:1a3aa2e25db9 | 50 | |
Timmmm | 0:1a3aa2e25db9 | 51 | USB comes in a few flavours: |
Timmmm | 0:1a3aa2e25db9 | 52 | |
Timmmm | 0:1a3aa2e25db9 | 53 | * USB 1.1 - Supports "Low Speed" (1.5 Mb/s) and "Full Speed" (12 Mb/s) |
Timmmm | 0:1a3aa2e25db9 | 54 | * USB 2 - Adds support for "High Speed" (480 Mb/s) |
Timmmm | 0:1a3aa2e25db9 | 55 | * USB 3 - Adds support for "Super Speed" (lots of Mb/s) |
Timmmm | 0:1a3aa2e25db9 | 56 | |
Timmmm | 0:1a3aa2e25db9 | 57 | To be clear: Low Speed < Full Speed < High Speed < Super Speed. Woo branding. Virtually all microcontrollers |
Timmmm | 0:1a3aa2e25db9 | 58 | with USB support support USB 2, though almost all of them only support Full Speed, and not High Speed. An exception |
Timmmm | 0:1a3aa2e25db9 | 59 | is the Atmel SAM3X8E and similar which is found on the Arduino Due. |
Timmmm | 0:1a3aa2e25db9 | 60 | |
Timmmm | 0:1a3aa2e25db9 | 61 | USB is a packet based protocol. Each transmission and reception is initiated with an 8-byte 'setup packet'. It has a very simple |
Timmmm | 0:1a3aa2e25db9 | 62 | structure: |
Timmmm | 0:1a3aa2e25db9 | 63 | |
Timmmm | 0:1a3aa2e25db9 | 64 | struct SetupPacket |
Timmmm | 0:1a3aa2e25db9 | 65 | { |
Timmmm | 0:1a3aa2e25db9 | 66 | uint8_t bmRequestType; |
Timmmm | 0:1a3aa2e25db9 | 67 | uint8_t bRequest; |
Timmmm | 0:1a3aa2e25db9 | 68 | uint16_t wValue; |
Timmmm | 0:1a3aa2e25db9 | 69 | uint16_t wIndex; |
Timmmm | 0:1a3aa2e25db9 | 70 | uint16_t wLength; |
Timmmm | 0:1a3aa2e25db9 | 71 | }; |
Timmmm | 0:1a3aa2e25db9 | 72 | |
Timmmm | 0:1a3aa2e25db9 | 73 | All transfers are initiated by the host - the peripheral only ever responds to requests. If it wants to send data |
Timmmm | 0:1a3aa2e25db9 | 74 | it must wait to be polled. |
Timmmm | 0:1a3aa2e25db9 | 75 | |
Timmmm | 0:1a3aa2e25db9 | 76 | The `bmRequestType` lets the host do various standard and vendor requests. Aside from initating data transfers |
Timmmm | 0:1a3aa2e25db9 | 77 | it allows the host to request configuration descriptors which describe what the device is (keyboard, mouse, etc.), |
Timmmm | 0:1a3aa2e25db9 | 78 | its name, manufacturer, data endpoints, and loads more. |
Timmmm | 0:1a3aa2e25db9 | 79 | |
Timmmm | 0:1a3aa2e25db9 | 80 | The main configuration descriptor describes the most important detail - the endpoints. Endpoints are really just |
Timmmm | 0:1a3aa2e25db9 | 81 | addresses within the device that you can send data to or from. If you like you can just have one transmit and |
Timmmm | 0:1a3aa2e25db9 | 82 | one receive endpoint and do your own addressing. However there are some different types of endpoints so you may |
Timmmm | 0:1a3aa2e25db9 | 83 | wish to have more than two. The simplest type that we'll be looking at is the interrupt endpoint, designed for |
Timmmm | 0:1a3aa2e25db9 | 84 | small fast bits of data, e.g. keystrokes or mouse movements, or control and status. |
Timmmm | 0:1a3aa2e25db9 | 85 | |
Timmmm | 0:1a3aa2e25db9 | 86 | You can simply send and receive packets to/from the endpoints, in a very similar maner to UDP. |
Timmmm | 0:1a3aa2e25db9 | 87 | |
Timmmm | 0:1a3aa2e25db9 | 88 | ## A USBSwitch class |
Timmmm | 0:1a3aa2e25db9 | 89 | |
Timmmm | 0:1a3aa2e25db9 | 90 | We'll implement a generic USBControl class that allows sending and receiving data packets via interrupt endpoints |
Timmmm | 0:1a3aa2e25db9 | 91 | and then subclass it to implement a light bulb device with a switch. We'll mirror the device on a desktop |
Timmmm | 0:1a3aa2e25db9 | 92 | application using Qt, so you can switch the light on and off from the device or the computer, and its state |
Timmmm | 0:1a3aa2e25db9 | 93 | will update on both. |
Timmmm | 0:1a3aa2e25db9 | 94 | |
Timmmm | 0:1a3aa2e25db9 | 95 | Finally we'll make it into a WinUSB device so the driver is installed automatically. |
Timmmm | 0:1a3aa2e25db9 | 96 | |
Timmmm | 0:1a3aa2e25db9 | 97 | ## A note on Vendor and Product IDs |
Timmmm | 0:1a3aa2e25db9 | 98 | |
Timmmm | 0:1a3aa2e25db9 | 99 | There is one annoying thing about using native USB for communication. Your device must be given a |
Timmmm | 0:1a3aa2e25db9 | 100 | Vendor ID and Product ID. These 16-bit identifiers are used to distinguish products and are the usual |
Timmmm | 0:1a3aa2e25db9 | 101 | method a program uses to find plugged-in devices it cares about. |
Timmmm | 0:1a3aa2e25db9 | 102 | |
Timmmm | 0:1a3aa2e25db9 | 103 | Unfortunately since they are only 16-bit, there are only 65536 possible vendors, and each can only |
Timmmm | 0:1a3aa2e25db9 | 104 | have 65536 products. This was a deliberate ploy by the USB Implementors' Forum (USB-IF) to allow them |
Timmmm | 0:1a3aa2e25db9 | 105 | to justify charging exhorbitant fees to claim a Vendor ID. |
Timmmm | 0:1a3aa2e25db9 | 106 | |
Timmmm | 0:1a3aa2e25db9 | 107 | It is beyond the means of most hobbiests to buy a Vendor ID, and the USB-IF has shut down vendors who |
Timmmm | 0:1a3aa2e25db9 | 108 | offered their Product IDs for sale for a reasonable price. Therefore the only real solution is to |
Timmmm | 0:1a3aa2e25db9 | 109 | fuck the USB-IF and squat on an unused or abandoned Vendor ID. Perhaps if enough people do this the |
Timmmm | 0:1a3aa2e25db9 | 110 | USB-IF will provide a real solution, since there's little they can do to stop it. |
Timmmm | 0:1a3aa2e25db9 | 111 | |
Timmmm | 0:1a3aa2e25db9 | 112 | I use the Vendor ID 0x0004 which is for Nebraska Furniture Mart (seriously). I doubt they will be using |
Timmmm | 0:1a3aa2e25db9 | 113 | it any time soon! Others have suggested using 0xF055 (FOSS). |
Timmmm | 0:1a3aa2e25db9 | 114 | |
Timmmm | 0:1a3aa2e25db9 | 115 | ## How Windows probes WinUSB devices |
Timmmm | 0:1a3aa2e25db9 | 116 | |
Timmmm | 0:1a3aa2e25db9 | 117 | The first thing Windows does to probe WinUSB devices is to send a GET_DESCRIPTOR request |
Timmmm | 0:1a3aa2e25db9 | 118 | for the STRING_DESCRIPTOR at offset 0xEE. The value 0xEE is defined by Microsoft to be the index |
Timmmm | 0:1a3aa2e25db9 | 119 | of the MSOS (MicroSoft Operating System) string. |
Timmmm | 0:1a3aa2e25db9 | 120 | |
Timmmm | 0:1a3aa2e25db9 | 121 | A WinUSB device should return a valid MSOS string descriptor which looks like this: |
Timmmm | 0:1a3aa2e25db9 | 122 | |
Timmmm | 0:1a3aa2e25db9 | 123 | struct PACKED WindowsOsString |
Timmmm | 0:1a3aa2e25db9 | 124 | { |
Timmmm | 0:1a3aa2e25db9 | 125 | uint8_t bLength; // Length of this structure, 0x12. |
Timmmm | 0:1a3aa2e25db9 | 126 | uint8_t bDescriptorType; // String descriptor, 0x03 (STRING_DESCRIPTOR) |
Timmmm | 0:1a3aa2e25db9 | 127 | uint8_t qwSignature[14]; // 'MSFT100' but in UTF-16 ( "M\0S\0F\0T\01\00\00\0" ) |
Timmmm | 0:1a3aa2e25db9 | 128 | uint8_t bMS_VendorCode; // Vendor code to retrieve OS feature desciptors. Can be changed. Example 0x01. |
Timmmm | 0:1a3aa2e25db9 | 129 | uint8_t bPad; // Padding, 0x00. |
Timmmm | 0:1a3aa2e25db9 | 130 | }; |
Timmmm | 0:1a3aa2e25db9 | 131 | |
Timmmm | 0:1a3aa2e25db9 | 132 | The only variable information in this sturcture is the bMS_VendorCode value. This can be set to anything. |
Timmmm | 0:1a3aa2e25db9 | 133 | It is used in the following USB requests that Windows makes. |
Timmmm | 0:1a3aa2e25db9 | 134 | |
Timmmm | 0:1a3aa2e25db9 | 135 | After obtaining the WindowsOsString structure, Windows makes several vendor requests as using the |
Timmmm | 0:1a3aa2e25db9 | 136 | bMS_VendorCode value as the request type. The value of wIndex indicates which of several things it wants. |
Timmmm | 0:1a3aa2e25db9 | 137 | The main ones that concern us are: |
Timmmm | 0:1a3aa2e25db9 | 138 | |
Timmmm | 0:1a3aa2e25db9 | 139 | #define COMPAT_ID_INDEX (4) |
Timmmm | 0:1a3aa2e25db9 | 140 | #define EXTENDED_PROPERTIES_INDEX (5) |
Timmmm | 0:1a3aa2e25db9 | 141 | |
Timmmm | 0:1a3aa2e25db9 | 142 | The first is for the "Compatible IDs" - the device must return a compatible ID of "WINUSB". |
Timmmm | 0:1a3aa2e25db9 | 143 | |
Timmmm | 0:1a3aa2e25db9 | 144 | The second is for the extended properties. Extended properties allow you to set the device icon, label, and |
Timmmm | 0:1a3aa2e25db9 | 145 | an interface GUID which can be used by programs instead of the Vendor/Product ID to find the device. This |
Timmmm | 0:1a3aa2e25db9 | 146 | is actually a great move by Microsoft as the Vendor/Product ID system sucks (see below). |
Timmmm | 0:1a3aa2e25db9 | 147 | |
Timmmm | 0:1a3aa2e25db9 | 148 | ## Implementation in mBed |
Timmmm | 0:1a3aa2e25db9 | 149 | |
Timmmm | 0:1a3aa2e25db9 | 150 | To implement this in mBed we first make a WinUSBDevice class that derives from USBDevice: |
Timmmm | 0:1a3aa2e25db9 | 151 | |
Timmmm | 0:1a3aa2e25db9 | 152 | class WinUSBDevice : public USBDevice |
Timmmm | 0:1a3aa2e25db9 | 153 | { |
Timmmm | 0:1a3aa2e25db9 | 154 | public: |
Timmmm | 0:1a3aa2e25db9 | 155 | WinUSBDevice(uint16_t vendor_id, uint16_t product_id, uint16_t product_release); |
Timmmm | 0:1a3aa2e25db9 | 156 | |
Timmmm | 0:1a3aa2e25db9 | 157 | We need to intercept setup requests, and possibly handle them before the default handling code runs. |
Timmmm | 0:1a3aa2e25db9 | 158 | mBed provides a virtual function we can override for that: |
Timmmm | 0:1a3aa2e25db9 | 159 | |
Timmmm | 0:1a3aa2e25db9 | 160 | // Handle vendor setup requests. Return true if we handle the request, otherwise false to let mBed do its |
Timmmm | 0:1a3aa2e25db9 | 161 | // default action, which is to call requestSetup(). |
Timmmm | 0:1a3aa2e25db9 | 162 | bool USBCallback_request(); // override; // override commented out because mBed'd online compiler still doesn't use C++11 |
Timmmm | 0:1a3aa2e25db9 | 163 | |
Timmmm | 0:1a3aa2e25db9 | 164 | Finally we need somewhere to store the data that we will return: |
Timmmm | 0:1a3aa2e25db9 | 165 | |
Timmmm | 0:1a3aa2e25db9 | 166 | private: |
Timmmm | 0:1a3aa2e25db9 | 167 | WindowsOsString osStringDesc; |
Timmmm | 0:1a3aa2e25db9 | 168 | CompatIdData compatIdData; |
Timmmm | 0:1a3aa2e25db9 | 169 | ExtendedPropertyData extendedPropertyData; |
Timmmm | 0:1a3aa2e25db9 | 170 | }; |
Timmmm | 0:1a3aa2e25db9 | 171 | |
Timmmm | 0:1a3aa2e25db9 | 172 | In the WinUSBDevice constructor we initialise the data to return: |
Timmmm | 0:1a3aa2e25db9 | 173 | |
Timmmm | 0:1a3aa2e25db9 | 174 | ... |
Timmmm | 0:1a3aa2e25db9 | 175 | |
Timmmm | 0:1a3aa2e25db9 | 176 | And now we get to the meat - filtering out the WinUSB-related requests to handle, and returning the data |
Timmmm | 0:1a3aa2e25db9 | 177 | we have crafted: |
Timmmm | 0:1a3aa2e25db9 | 178 | |
Timmmm | 0:1a3aa2e25db9 | 179 | bool WinUSBDevice::USBCallback_request() |
Timmmm | 0:1a3aa2e25db9 | 180 | { |
Timmmm | 0:1a3aa2e25db9 | 181 | |
Timmmm | 1:0c3b6cc480b6 | 182 | Returning false means 'I didn't handle this; carry on as you were'. Returning true means |
Timmmm | 1:0c3b6cc480b6 | 183 | 'I've handled this and stored a response in transfer'. |
Timmmm | 1:0c3b6cc480b6 | 184 | |
Timmmm | 0:1a3aa2e25db9 | 185 | First we need a reference to the transfer structure which contains both the request information |
Timmmm | 0:1a3aa2e25db9 | 186 | and provides a place to store our response. The USBDevice::transfer member is actually private |
Timmmm | 0:1a3aa2e25db9 | 187 | but there is a protected function to access it. (Thank you mBed people - I always knew your APIs were the best! |
Timmmm | 0:1a3aa2e25db9 | 188 | Except the BLE API; that sucks medium time.) |
Timmmm | 0:1a3aa2e25db9 | 189 | |
Timmmm | 0:1a3aa2e25db9 | 190 | // This can never be null. |
Timmmm | 0:1a3aa2e25db9 | 191 | CONTROL_TRANSFER& transfer = *getTransferPtr(); |
Timmmm | 0:1a3aa2e25db9 | 192 | |
Timmmm | 1:0c3b6cc480b6 | 193 | Requests can be addressed to the device, an interface or an endpoint. Most WinUSB requests are addressed |
Timmmm | 1:0c3b6cc480b6 | 194 | to the device, but the Extended Properties request is sent to the interface, so we'll just ignore what |
Timmmm | 1:0c3b6cc480b6 | 195 | the recipient is. We only have on interface anyway. |
Timmmm | 1:0c3b6cc480b6 | 196 | |
Timmmm | 0:1a3aa2e25db9 | 197 | |
Timmmm | 0:1a3aa2e25db9 | 198 | Next we see if this is a request for the 0xEE string descriptor. |
Timmmm | 0:1a3aa2e25db9 | 199 | |
Timmmm | 0:1a3aa2e25db9 | 200 | // Intercept the request for string descriptor 0xEE |
Timmmm | 0:1a3aa2e25db9 | 201 | if (transfer.setup.bmRequestType.Type == STANDARD_TYPE && |
Timmmm | 0:1a3aa2e25db9 | 202 | transfer.setup.bRequest == GET_DESCRIPTOR && |
Timmmm | 0:1a3aa2e25db9 | 203 | DESCRIPTOR_TYPE(transfer.setup.wValue) == STRING_DESCRIPTOR && |
Timmmm | 0:1a3aa2e25db9 | 204 | DESCRIPTOR_INDEX(transfer.setup.wValue) == STRING_OFFSET_MSOS) |
Timmmm | 0:1a3aa2e25db9 | 205 | { |
Timmmm | 0:1a3aa2e25db9 | 206 | |
Timmmm | 0:1a3aa2e25db9 | 207 | If it is, return our MSOS string descriptor. |
Timmmm | 0:1a3aa2e25db9 | 208 | |
Timmmm | 0:1a3aa2e25db9 | 209 | transfer.ptr = reinterpret_cast<uint8_t*>(&osStringDesc); |
Timmmm | 0:1a3aa2e25db9 | 210 | transfer.remaining = osStringDesc.bLength; |
Timmmm | 0:1a3aa2e25db9 | 211 | transfer.direction = DEVICE_TO_HOST; |
Timmmm | 0:1a3aa2e25db9 | 212 | return true; |
Timmmm | 0:1a3aa2e25db9 | 213 | } |
Timmmm | 0:1a3aa2e25db9 | 214 | |
Timmmm | 0:1a3aa2e25db9 | 215 | After Windows has made that request it will send vendor requests using our custom request type |
Timmmm | 0:1a3aa2e25db9 | 216 | (GET_MS_DESCRIPTORS). |
Timmmm | 0:1a3aa2e25db9 | 217 | |
Timmmm | 0:1a3aa2e25db9 | 218 | // Our custom descriptor. |
Timmmm | 0:1a3aa2e25db9 | 219 | if (transfer.setup.bmRequestType.Type == VENDOR_TYPE && |
Timmmm | 0:1a3aa2e25db9 | 220 | transfer.setup.bRequest == GET_MS_DESCRIPTORS) |
Timmmm | 0:1a3aa2e25db9 | 221 | { |
Timmmm | 0:1a3aa2e25db9 | 222 | |
Timmmm | 0:1a3aa2e25db9 | 223 | Then we need to see which descriptor Windows wants and return the appropriate one. |
Timmmm | 0:1a3aa2e25db9 | 224 | |
Timmmm | 0:1a3aa2e25db9 | 225 | switch (transfer.setup.wIndex) |
Timmmm | 0:1a3aa2e25db9 | 226 | { |
Timmmm | 0:1a3aa2e25db9 | 227 | case COMPAT_ID_INDEX: // Extended Compat ID |
Timmmm | 0:1a3aa2e25db9 | 228 | transfer.ptr = reinterpret_cast<uint8_t*>(&compatIdData); |
Timmmm | 0:1a3aa2e25db9 | 229 | transfer.remaining = sizeof(compatIdData); |
Timmmm | 0:1a3aa2e25db9 | 230 | transfer.direction = DEVICE_TO_HOST; |
Timmmm | 0:1a3aa2e25db9 | 231 | return true; |
Timmmm | 0:1a3aa2e25db9 | 232 | case EXTENDED_PROPERTIES_INDEX: // Extended Properties. |
Timmmm | 0:1a3aa2e25db9 | 233 | transfer.ptr = reinterpret_cast<uint8_t*>(&extendedPropertyData); |
Timmmm | 0:1a3aa2e25db9 | 234 | transfer.remaining = sizeof(extendedPropertyData); |
Timmmm | 0:1a3aa2e25db9 | 235 | transfer.direction = DEVICE_TO_HOST; |
Timmmm | 0:1a3aa2e25db9 | 236 | return true; |
Timmmm | 0:1a3aa2e25db9 | 237 | case GENRE_INDEX: // Genre |
Timmmm | 0:1a3aa2e25db9 | 238 | default: |
Timmmm | 0:1a3aa2e25db9 | 239 | return false; |
Timmmm | 0:1a3aa2e25db9 | 240 | } |
Timmmm | 0:1a3aa2e25db9 | 241 | } |
Timmmm | 0:1a3aa2e25db9 | 242 | |
Timmmm | 0:1a3aa2e25db9 | 243 | If it wasn't a relevant request, let mBed handle it as it would have. |
Timmmm | 0:1a3aa2e25db9 | 244 | |
Timmmm | 0:1a3aa2e25db9 | 245 | return false; |
Timmmm | 0:1a3aa2e25db9 | 246 | } |
Timmmm | 0:1a3aa2e25db9 | 247 | |
Timmmm | 0:1a3aa2e25db9 | 248 | And we're done! Next we need a USB class that takes advantage of this WinUSBDevice class and |
Timmmm | 0:1a3aa2e25db9 | 249 | responds to our control transfers. |
Timmmm | 0:1a3aa2e25db9 | 250 | |
Timmmm | 1:0c3b6cc480b6 | 251 | |
Timmmm | 1:0c3b6cc480b6 | 252 | ...WIP... |