adds a USB serial port to your design
Dependents: Example_WatchDog_Timer
Revision 82:584b0afbd742, committed 2019-02-26
- Comitter:
- rlanders73
- Date:
- Tue Feb 26 20:56:58 2019 +0000
- Parent:
- 81:0ecf1a603426
- Commit message:
- removed unsupported USB descriptors for geneva
Changed in this revision
--- a/USBAudio/USBAudio.cpp Wed Feb 20 20:54:28 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,641 +0,0 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License -* -* 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 "stdint.h" -#include "USBAudio.h" -#include "USBAudio_Types.h" - - - -USBAudio::USBAudio(uint32_t frequency_in, uint8_t channel_nb_in, uint32_t frequency_out, uint8_t channel_nb_out, uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release) { - mute = 0; - volCur = 0x0080; - volMin = 0x0000; - volMax = 0x0100; - volRes = 0x0004; - available = false; - - FREQ_IN = frequency_in; - FREQ_OUT = frequency_out; - - this->channel_nb_in = channel_nb_in; - this->channel_nb_out = channel_nb_out; - - // stereo -> *2, mono -> *1 - PACKET_SIZE_ISO_IN = (FREQ_IN / 500) * channel_nb_in; - PACKET_SIZE_ISO_OUT = (FREQ_OUT / 500) * channel_nb_out; - - // STEREO -> left and right - channel_config_in = (channel_nb_in == 1) ? CHANNEL_M : CHANNEL_L + CHANNEL_R; - channel_config_out = (channel_nb_out == 1) ? CHANNEL_M : CHANNEL_L + CHANNEL_R; - - SOF_handler = false; - - buf_stream_out = NULL; - buf_stream_in = NULL; - - interruptOUT = false; - writeIN = false; - interruptIN = false; - available = false; - - volume = 0; - - // connect the device - USBDevice::connect(); -} - -bool USBAudio::read(uint8_t * buf) { - buf_stream_in = buf; - SOF_handler = false; - while (!available || !SOF_handler); - available = false; - return true; -} - -bool USBAudio::readNB(uint8_t * buf) { - buf_stream_in = buf; - SOF_handler = false; - while (!SOF_handler); - if (available) { - available = false; - buf_stream_in = NULL; - return true; - } - return false; -} - -bool USBAudio::readWrite(uint8_t * buf_read, uint8_t * buf_write) { - buf_stream_in = buf_read; - SOF_handler = false; - writeIN = false; - if (interruptIN) { - USBDevice::writeNB(EPISO_IN, buf_write, PACKET_SIZE_ISO_OUT, PACKET_SIZE_ISO_OUT); - } else { - buf_stream_out = buf_write; - } - while (!available); - if (interruptIN) { - while (!writeIN); - } - while (!SOF_handler); - return true; -} - - -bool USBAudio::write(uint8_t * buf) { - writeIN = false; - SOF_handler = false; - if (interruptIN) { - USBDevice::writeNB(EPISO_IN, buf, PACKET_SIZE_ISO_OUT, PACKET_SIZE_ISO_OUT); - } else { - buf_stream_out = buf; - } - while (!SOF_handler); - if (interruptIN) { - while (!writeIN); - } - return true; -} - -void USBAudio::writeSync(uint8_t *buf, AudioSampleCorrectType jitter_nb) -{ - if ((jitter_nb != RemoveOneSample) && (jitter_nb != AddOneSample)) { - jitter_nb = NoCorrection; - } - /* each sample is 2 bytes */ - USBDevice::writeNB(EPISO_IN, buf, PACKET_SIZE_ISO_OUT + jitter_nb *(this->channel_nb_out*2), PACKET_SIZE_ISO_OUT+this->channel_nb_out*2); -} - -uint32_t USBAudio::readSync(uint8_t *buf) -{ - uint32_t size = 0; - USBDevice::readEP(EPISO_OUT, (uint8_t *)buf, &size, PACKET_SIZE_ISO_IN); - return size; -} - -float USBAudio::getVolume() { - return (mute) ? 0.0 : volume; -} - - -bool USBAudio::EPISO_OUT_callback() { - uint32_t size = 0; - interruptOUT = true; - if (buf_stream_in != NULL) { - readEP(EPISO_OUT, (uint8_t *)buf_stream_in, &size, PACKET_SIZE_ISO_IN); - available = true; - buf_stream_in = NULL; - } - else { - if (rxDone) - rxDone.call(); - } - readStart(EPISO_OUT, PACKET_SIZE_ISO_IN); - return false; -} - - -bool USBAudio::EPISO_IN_callback() { - interruptIN = true; - writeIN = true; - if (txDone) - txDone.call(); - return true; -} - - - -// Called in ISR context on each start of frame -void USBAudio::SOF(int frameNumber) { - uint32_t size = 0; - - if (!interruptOUT) { - // read the isochronous endpoint - if (buf_stream_in != NULL) { - if (USBDevice::readEP_NB(EPISO_OUT, (uint8_t *)buf_stream_in, &size, PACKET_SIZE_ISO_IN)) { - if (size) { - available = true; - readStart(EPISO_OUT, PACKET_SIZE_ISO_IN); - buf_stream_in = NULL; - } - } - } - } - - if (!interruptIN) { - // write if needed - if (buf_stream_out != NULL) { - USBDevice::writeNB(EPISO_IN, (uint8_t *)buf_stream_out, PACKET_SIZE_ISO_OUT, PACKET_SIZE_ISO_OUT); - buf_stream_out = NULL; - } - } - - SOF_handler = true; -} - - -// Called in ISR context -// Set configuration. Return false if the configuration is not supported. -bool USBAudio::USBCallback_setConfiguration(uint8_t configuration) { - if (configuration != DEFAULT_CONFIGURATION) { - return false; - } - - // Configure isochronous endpoint - realiseEndpoint(EPISO_OUT, PACKET_SIZE_ISO_IN, ISOCHRONOUS); - realiseEndpoint(EPISO_IN, PACKET_SIZE_ISO_OUT+this->channel_nb_out*2, ISOCHRONOUS); - - // activate readings on this endpoint - readStart(EPISO_OUT, PACKET_SIZE_ISO_IN); - return true; -} - - -// Called in ISR context -// Set alternate setting. Return false if the alternate setting is not supported -bool USBAudio::USBCallback_setInterface(uint16_t interface, uint8_t alternate) { - if (interface == 0 && alternate == 0) { - return true; - } - if (interface == 1 && (alternate == 0 || alternate == 1)) { - return true; - } - if (interface == 2 && (alternate == 0 || alternate == 1)) { - return true; - } - return false; -} - - - -// Called in ISR context -// Called by USBDevice on Endpoint0 request -// This is used to handle extensions to standard requests and class specific requests. -// Return true if class handles this request -bool USBAudio::USBCallback_request() { - bool success = false; - CONTROL_TRANSFER * transfer = getTransferPtr(); - - // Process class-specific requests - if (transfer->setup.bmRequestType.Type == CLASS_TYPE) { - - // Feature Unit: Interface = 0, ID = 2 - if (transfer->setup.wIndex == 0x0200) { - - // Master Channel - if ((transfer->setup.wValue & 0xff) == 0) { - - switch (transfer->setup.wValue >> 8) { - case MUTE_CONTROL: - switch (transfer->setup.bRequest) { - case REQUEST_GET_CUR: - transfer->remaining = 1; - transfer->ptr = &mute; - transfer->direction = DEVICE_TO_HOST; - success = true; - break; - - case REQUEST_SET_CUR: - transfer->remaining = 1; - transfer->notify = true; - transfer->direction = HOST_TO_DEVICE; - success = true; - break; - default: - break; - } - break; - case VOLUME_CONTROL: - switch (transfer->setup.bRequest) { - case REQUEST_GET_CUR: - transfer->remaining = 2; - transfer->ptr = (uint8_t *)&volCur; - transfer->direction = DEVICE_TO_HOST; - success = true; - break; - case REQUEST_GET_MIN: - transfer->remaining = 2; - transfer->ptr = (uint8_t *)&volMin; - transfer->direction = DEVICE_TO_HOST; - success = true; - break; - case REQUEST_GET_MAX: - transfer->remaining = 2; - transfer->ptr = (uint8_t *)&volMax; - transfer->direction = DEVICE_TO_HOST; - success = true; - break; - case REQUEST_GET_RES: - transfer->remaining = 2; - transfer->ptr = (uint8_t *)&volRes; - transfer->direction = DEVICE_TO_HOST; - success = true; - break; - - case REQUEST_SET_CUR: - transfer->remaining = 2; - transfer->notify = true; - transfer->direction = HOST_TO_DEVICE; - success = true; - break; - case REQUEST_SET_MIN: - transfer->remaining = 2; - transfer->notify = true; - transfer->direction = HOST_TO_DEVICE; - success = true; - break; - case REQUEST_SET_MAX: - transfer->remaining = 2; - transfer->notify = true; - transfer->direction = HOST_TO_DEVICE; - success = true; - break; - case REQUEST_SET_RES: - transfer->remaining = 2; - transfer->notify = true; - transfer->direction = HOST_TO_DEVICE; - success = true; - break; - } - break; - default: - break; - } - } - } - } - return success; -} - - -// Called in ISR context when a data OUT stage has been performed -void USBAudio::USBCallback_requestCompleted(uint8_t * buf, uint32_t length) { - if ((length == 1) || (length == 2)) { - uint16_t data = (length == 1) ? *buf : *((uint16_t *)buf); - CONTROL_TRANSFER * transfer = getTransferPtr(); - switch (transfer->setup.wValue >> 8) { - case MUTE_CONTROL: - switch (transfer->setup.bRequest) { - case REQUEST_SET_CUR: - mute = data & 0xff; - if (updateVol) - updateVol.call(); - break; - default: - break; - } - break; - case VOLUME_CONTROL: - switch (transfer->setup.bRequest) { - case REQUEST_SET_CUR: - volCur = data; - volume = (float)volCur/(float)volMax; - if (updateVol) - updateVol.call(); - break; - default: - break; - } - break; - default: - break; - } - } -} - - - -#define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \ - + (5 * INTERFACE_DESCRIPTOR_LENGTH) \ - + (1 * CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1) \ - + (2 * INPUT_TERMINAL_DESCRIPTOR_LENGTH) \ - + (1 * FEATURE_UNIT_DESCRIPTOR_LENGTH) \ - + (2 * OUTPUT_TERMINAL_DESCRIPTOR_LENGTH) \ - + (2 * STREAMING_INTERFACE_DESCRIPTOR_LENGTH) \ - + (2 * FORMAT_TYPE_I_DESCRIPTOR_LENGTH) \ - + (2 * (ENDPOINT_DESCRIPTOR_LENGTH + 2)) \ - + (2 * STREAMING_ENDPOINT_DESCRIPTOR_LENGTH) ) - -#define TOTAL_CONTROL_INTF_LENGTH (CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1 + \ - 2*INPUT_TERMINAL_DESCRIPTOR_LENGTH + \ - FEATURE_UNIT_DESCRIPTOR_LENGTH + \ - 2*OUTPUT_TERMINAL_DESCRIPTOR_LENGTH) - -uint8_t * USBAudio::configurationDesc() { - static uint8_t configDescriptor[] = { - // Configuration 1 - CONFIGURATION_DESCRIPTOR_LENGTH, // bLength - CONFIGURATION_DESCRIPTOR, // bDescriptorType - LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB) - MSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (MSB) - 0x03, // bNumInterfaces - DEFAULT_CONFIGURATION, // bConfigurationValue - 0x00, // iConfiguration - 0x80, // bmAttributes - 50, // bMaxPower - - // Interface 0, Alternate Setting 0, Audio Control - INTERFACE_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR, // bDescriptorType - 0x00, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x00, // bNumEndpoints - AUDIO_CLASS, // bInterfaceClass - SUBCLASS_AUDIOCONTROL, // bInterfaceSubClass - 0x00, // bInterfaceProtocol - 0x00, // iInterface - - - // Audio Control Interface - CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1,// bLength - INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType - CONTROL_HEADER, // bDescriptorSubtype - LSB(0x0100), // bcdADC (LSB) - MSB(0x0100), // bcdADC (MSB) - LSB(TOTAL_CONTROL_INTF_LENGTH), // wTotalLength - MSB(TOTAL_CONTROL_INTF_LENGTH), // wTotalLength - 0x02, // bInCollection - 0x01, // baInterfaceNr - 0x02, // baInterfaceNr - - // Audio Input Terminal (Speaker) - INPUT_TERMINAL_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType - CONTROL_INPUT_TERMINAL, // bDescriptorSubtype - 0x01, // bTerminalID - LSB(TERMINAL_USB_STREAMING), // wTerminalType - MSB(TERMINAL_USB_STREAMING), // wTerminalType - 0x00, // bAssocTerminal - channel_nb_in, // bNrChannels - (uint8_t)(LSB(channel_config_in)), // wChannelConfig - (uint8_t)(MSB(channel_config_in)), // wChannelConfig - 0x00, // iChannelNames - 0x00, // iTerminal - - // Audio Feature Unit (Speaker) - FEATURE_UNIT_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType - CONTROL_FEATURE_UNIT, // bDescriptorSubtype - 0x02, // bUnitID - 0x01, // bSourceID - 0x01, // bControlSize - CONTROL_MUTE | - CONTROL_VOLUME, // bmaControls(0) - 0x00, // bmaControls(1) - 0x00, // iTerminal - - // Audio Output Terminal (Speaker) - OUTPUT_TERMINAL_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType - CONTROL_OUTPUT_TERMINAL, // bDescriptorSubtype - 0x03, // bTerminalID - LSB(TERMINAL_SPEAKER), // wTerminalType - MSB(TERMINAL_SPEAKER), // wTerminalType - 0x00, // bAssocTerminal - 0x02, // bSourceID - 0x00, // iTerminal - - - // Audio Input Terminal (Microphone) - INPUT_TERMINAL_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType - CONTROL_INPUT_TERMINAL, // bDescriptorSubtype - 0x04, // bTerminalID - LSB(TERMINAL_MICROPHONE), // wTerminalType - MSB(TERMINAL_MICROPHONE), // wTerminalType - 0x00, // bAssocTerminal - channel_nb_out, // bNrChannels - (uint8_t)(LSB(channel_config_out)), // wChannelConfig - (uint8_t)(MSB(channel_config_out)), // wChannelConfig - 0x00, // iChannelNames - 0x00, // iTerminal - - // Audio Output Terminal (Microphone) - OUTPUT_TERMINAL_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType - CONTROL_OUTPUT_TERMINAL, // bDescriptorSubtype - 0x05, // bTerminalID - LSB(TERMINAL_USB_STREAMING), // wTerminalType - MSB(TERMINAL_USB_STREAMING), // wTerminalType - 0x00, // bAssocTerminal - 0x04, // bSourceID - 0x00, // iTerminal - - - - - - - // Interface 1, Alternate Setting 0, Audio Streaming - Zero Bandwith - INTERFACE_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR, // bDescriptorType - 0x01, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x00, // bNumEndpoints - AUDIO_CLASS, // bInterfaceClass - SUBCLASS_AUDIOSTREAMING, // bInterfaceSubClass - 0x00, // bInterfaceProtocol - 0x00, // iInterface - - // Interface 1, Alternate Setting 1, Audio Streaming - Operational - INTERFACE_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR, // bDescriptorType - 0x01, // bInterfaceNumber - 0x01, // bAlternateSetting - 0x01, // bNumEndpoints - AUDIO_CLASS, // bInterfaceClass - SUBCLASS_AUDIOSTREAMING, // bInterfaceSubClass - 0x00, // bInterfaceProtocol - 0x00, // iInterface - - // Audio Streaming Interface - STREAMING_INTERFACE_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType - STREAMING_GENERAL, // bDescriptorSubtype - 0x01, // bTerminalLink - 0x00, // bDelay - LSB(FORMAT_PCM), // wFormatTag - MSB(FORMAT_PCM), // wFormatTag - - // Audio Type I Format - FORMAT_TYPE_I_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType - STREAMING_FORMAT_TYPE, // bDescriptorSubtype - FORMAT_TYPE_I, // bFormatType - channel_nb_in, // bNrChannels - 0x02, // bSubFrameSize - 16, // bBitResolution - 0x01, // bSamFreqType - (uint8_t)(LSB(FREQ_IN)), // tSamFreq - (uint8_t)((FREQ_IN >> 8) & 0xff), // tSamFreq - (uint8_t)((FREQ_IN >> 16) & 0xff), // tSamFreq - - // Endpoint - Standard Descriptor - ENDPOINT_DESCRIPTOR_LENGTH + 2, // bLength - ENDPOINT_DESCRIPTOR, // bDescriptorType - PHY_TO_DESC(EPISO_OUT), // bEndpointAddress - E_ISOCHRONOUS, // bmAttributes - (uint8_t)(LSB(PACKET_SIZE_ISO_IN)), // wMaxPacketSize - (uint8_t)(MSB(PACKET_SIZE_ISO_IN)), // wMaxPacketSize - 0x01, // bInterval - 0x00, // bRefresh - 0x00, // bSynchAddress - - // Endpoint - Audio Streaming - STREAMING_ENDPOINT_DESCRIPTOR_LENGTH, // bLength - ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType - ENDPOINT_GENERAL, // bDescriptor - 0x00, // bmAttributes - 0x00, // bLockDelayUnits - LSB(0x0000), // wLockDelay - MSB(0x0000), // wLockDelay - - - - - - - - // Interface 1, Alternate Setting 0, Audio Streaming - Zero Bandwith - INTERFACE_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR, // bDescriptorType - 0x02, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x00, // bNumEndpoints - AUDIO_CLASS, // bInterfaceClass - SUBCLASS_AUDIOSTREAMING, // bInterfaceSubClass - 0x00, // bInterfaceProtocol - 0x00, // iInterface - - // Interface 1, Alternate Setting 1, Audio Streaming - Operational - INTERFACE_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR, // bDescriptorType - 0x02, // bInterfaceNumber - 0x01, // bAlternateSetting - 0x01, // bNumEndpoints - AUDIO_CLASS, // bInterfaceClass - SUBCLASS_AUDIOSTREAMING, // bInterfaceSubClass - 0x00, // bInterfaceProtocol - 0x00, // iInterface - - // Audio Streaming Interface - STREAMING_INTERFACE_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType - SUBCLASS_AUDIOCONTROL, // bDescriptorSubtype - 0x05, // bTerminalLink (output terminal microphone) - 0x01, // bDelay - 0x01, // wFormatTag - 0x00, // wFormatTag - - // Audio Type I Format - FORMAT_TYPE_I_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType - SUBCLASS_AUDIOSTREAMING, // bDescriptorSubtype - FORMAT_TYPE_I, // bFormatType - channel_nb_out, // bNrChannels - 0x02, // bSubFrameSize - 0x10, // bBitResolution - 0x01, // bSamFreqType - (uint8_t)(LSB(FREQ_OUT)), // tSamFreq - (uint8_t)((FREQ_OUT >> 8) & 0xff), // tSamFreq - (uint8_t)((FREQ_OUT >> 16) & 0xff), // tSamFreq - - // Endpoint - Standard Descriptor - ENDPOINT_DESCRIPTOR_LENGTH + 2, // bLength - ENDPOINT_DESCRIPTOR, // bDescriptorType - PHY_TO_DESC(EPISO_IN), // bEndpointAddress - E_ISOCHRONOUS, // bmAttributes - (uint8_t)(LSB(PACKET_SIZE_ISO_OUT+channel_nb_out*2)), // wMaxPacketSize - (uint8_t)(MSB(PACKET_SIZE_ISO_OUT+channel_nb_out*2)), // wMaxPacketSize - 0x01, // bInterval - 0x00, // bRefresh - 0x00, // bSynchAddress - - // Endpoint - Audio Streaming - STREAMING_ENDPOINT_DESCRIPTOR_LENGTH, // bLength - ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType - ENDPOINT_GENERAL, // bDescriptor - 0x00, // bmAttributes - 0x00, // bLockDelayUnits - LSB(0x0000), // wLockDelay - MSB(0x0000), // wLockDelay - - // Terminator - 0 // bLength - }; - return configDescriptor; -} - -uint8_t * USBAudio::stringIinterfaceDesc() { - static uint8_t stringIinterfaceDescriptor[] = { - 0x0c, //bLength - STRING_DESCRIPTOR, //bDescriptorType 0x03 - 'A',0,'u',0,'d',0,'i',0,'o',0 //bString iInterface - Audio - }; - return stringIinterfaceDescriptor; -} - -uint8_t * USBAudio::stringIproductDesc() { - static uint8_t stringIproductDescriptor[] = { - 0x16, //bLength - STRING_DESCRIPTOR, //bDescriptorType 0x03 - 'M',0,'b',0,'e',0,'d',0,' ',0,'A',0,'u',0,'d',0,'i',0,'o',0 //bString iProduct - Mbed Audio - }; - return stringIproductDescriptor; -}
--- a/USBAudio/USBAudio.h Wed Feb 20 20:54:28 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,337 +0,0 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License -* -* 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. -*/ - -#ifndef USBAudio_H -#define USBAudio_H - -/* These headers are included for child class. */ -#include "USBEndpoints.h" -#include "USBDescriptor.h" -#include "USBDevice_Types.h" - -#include "USBDevice.h" -#include "Callback.h" - -/** -* USBAudio example -* -* @code -* #include "mbed.h" -* #include "USBAudio.h" -* -* Serial pc(USBTX, USBRX); -* -* // frequency: 48 kHz -* #define FREQ 48000 -* -* // 1 channel: mono -* #define NB_CHA 1 -* -* // length of an audio packet: each ms, we receive 48 * 16bits ->48 * 2 bytes. as there is one channel, the length will be 48 * 2 * 1 -* #define AUDIO_LENGTH_PACKET 48 * 2 * 1 -* -* // USBAudio -* USBAudio audio(FREQ, NB_CHA); -* -* int main() { -* int16_t buf[AUDIO_LENGTH_PACKET/2]; -* -* while (1) { -* // read an audio packet -* audio.read((uint8_t *)buf); -* -* -* // print packet received -* pc.printf("recv: "); -* for(int i = 0; i < AUDIO_LENGTH_PACKET/2; i++) { -* pc.printf("%d ", buf[i]); -* } -* pc.printf("\r\n"); -* } -* } -* @endcode -*/ -class USBAudio: public USBDevice { -public: - - /** - * Constructor - * - * @param frequency_in frequency in Hz (default: 48000) - * @param channel_nb_in channel number (1 or 2) (default: 1) - * @param frequency_out frequency in Hz (default: 8000) - * @param channel_nb_out_in channel number (1 or 2) (default: 1) - * @param vendor_id Your vendor_id - * @param product_id Your product_id - * @param product_release Your preoduct_release - */ - USBAudio(uint32_t frequency_in = 48000, uint8_t channel_nb_in = 1, uint32_t frequency_out = 8000, uint8_t channel_nb_out = 1, uint16_t vendor_id = 0x7bb8, uint16_t product_id = 0x1111, uint16_t product_release = 0x0100); - - /** - * Get current volume between 0.0 and 1.0 - * - * @returns volume - */ - float getVolume(); - - /** - * Read an audio packet. During a frame, only a single reading (you can't write and read an audio packet during the same frame)can be done using this method. Warning: Blocking - * - * @param buf pointer on a buffer which will be filled with an audio packet - * - * @returns true if successfull - */ - bool read(uint8_t * buf); - - /** - * Try to read an audio packet. During a frame, only a single reading (you can't write and read an audio packet during the same frame)can be done using this method. Warning: Non Blocking - * - * @param buf pointer on a buffer which will be filled if an audio packet is available - * - * @returns true if successfull - */ - bool readNB(uint8_t * buf); - - /** - * read last received packet if some. - * @param buf pointer on a buffer which will be filled if an audio packet is available - * - * @returns the packet length - */ - uint32_t readSync(uint8_t *buf); - - /** - * Write an audio packet. During a frame, only a single writing (you can't write and read an audio packet during the same frame)can be done using this method. - * - * @param buf pointer on the audio packet which will be sent - * @returns true if successful - */ - bool write(uint8_t * buf); - - /** Audio Jitter value*/ - enum AudioSampleCorrectType { - RemoveOneSample = -1, - NoCorrection = 0, - AddOneSample = 1 - }; - /** - * Write packet in endpoint fifo. assuming tx fifo is empty - * @param buf pointer on the audio packet which will be sent - * @param jitter_nb : AudioSampleCorrecttype - **/ - void writeSync(uint8_t *buf, AudioSampleCorrectType jitter_nb = NoCorrection ); - - /** - * Write and read an audio packet at the same time (on the same frame) - * - * @param buf_read pointer on a buffer which will be filled with an audio packet - * @param buf_write pointer on the audio packet which will be sent - * @returns true if successful - */ - bool readWrite(uint8_t * buf_read, uint8_t * buf_write); - - - /** attach a handler to update the volume - * - * @param function Function to attach - * - */ - void attach(void(*fptr)(void)) { - updateVol.attach(fptr); - } - /** attach a handler to Tx Done - * - * @param function Function to attach - * - */ - void attachTx(void(*fptr)(void)) { - txDone.attach(fptr); - } - /** attach a handler to Rx Done - * - * @param function Function to attach - * - */ - void attachRx(void(*fptr)(void)) { - rxDone.attach(fptr); - } - - /** Attach a nonstatic void/void member function to update the volume - * - * @param tptr Object pointer - * @param mptr Member function pointer - * - */ - template<typename T> - void attach(T *tptr, void(T::*mptr)(void)) { - updateVol.attach(tptr, mptr); - } - template<typename T> - void attachTx(T *tptr, void(T::*mptr)(void)) { - txDone.attach(tptr, mptr); - } - template<typename T> - void attachRx(T *tptr, void(T::*mptr)(void)) { - rxDone.attach(tptr, mptr); - } - - -protected: - - /* - * Called by USBDevice layer. Set configuration of the device. - * For instance, you can add all endpoints that you need on this function. - * - * @param configuration Number of the configuration - * @returns true if class handles this request - */ - virtual bool USBCallback_setConfiguration(uint8_t configuration); - - /* - * Called by USBDevice on Endpoint0 request. Warning: Called in ISR context - * This is used to handle extensions to standard requests - * and class specific requests - * - * @returns true if class handles this request - */ - virtual bool USBCallback_request(); - - /* - * Get string product descriptor - * - * @returns pointer to the string product descriptor - */ - virtual uint8_t * stringIproductDesc(); - - /* - * Get string interface descriptor - * - * @returns pointer to the string interface descriptor - */ - virtual uint8_t * stringIinterfaceDesc(); - - /* - * Get configuration descriptor - * - * @returns pointer to the configuration descriptor - */ - virtual uint8_t * configurationDesc(); - - /* - * Called by USBDevice layer. Set interface/alternate of the device. - * - * @param interface Number of the interface to be configured - * @param alternate Number of the alternate to be configured - * @returns true if class handles this request - */ - virtual bool USBCallback_setInterface(uint16_t interface, uint8_t alternate); - - /* - * Called by USBDevice on Endpoint0 request completion - * if the 'notify' flag has been set to true. Warning: Called in ISR context - * - * In this case it is used to indicate that a HID report has - * been received from the host on endpoint 0 - * - * @param buf buffer received on endpoint 0 - * @param length length of this buffer - */ - virtual void USBCallback_requestCompleted(uint8_t * buf, uint32_t length); - - /* - * Callback called on each Start of Frame event - */ - virtual void SOF(int frameNumber); - - /* - * Callback called when a packet is received - */ - virtual bool EPISO_OUT_callback(); - - /* - * Callback called when a packet has been sent - */ - virtual bool EPISO_IN_callback(); - -private: - - // stream available ? - volatile bool available; - - // interrupt OUT has been received - volatile bool interruptOUT; - - // interrupt IN has been received - volatile bool interruptIN; - - // audio packet has been written - volatile bool writeIN; - - // FREQ - uint32_t FREQ_OUT; - uint32_t FREQ_IN; - - // size of the maximum packet for the isochronous endpoint - uint32_t PACKET_SIZE_ISO_IN; - uint32_t PACKET_SIZE_ISO_OUT; - - // mono, stereo,... - uint8_t channel_nb_in; - uint8_t channel_nb_out; - - // channel config: master, left, right - uint8_t channel_config_in; - uint8_t channel_config_out; - - // mute state - uint8_t mute; - - // Volume Current Value - uint16_t volCur; - - // Volume Minimum Value - uint16_t volMin; - - // Volume Maximum Value - uint16_t volMax; - - // Volume Resolution - uint16_t volRes; - - // Buffer containing one audio packet (to be read) - volatile uint8_t * buf_stream_in; - - // Buffer containing one audio packet (to be written) - volatile uint8_t * buf_stream_out; - - // callback to update volume - Callback<void()> updateVol; - - // callback transmit Done - Callback<void()> txDone; - // callback transmit Done - Callback<void()> rxDone; - - // boolean showing that the SOF handler has been called. Useful for readNB. - volatile bool SOF_handler; - - volatile float volume; - -}; - -#endif
--- a/USBAudio/USBAudio_Types.h Wed Feb 20 20:54:28 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License -* -* 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. -*/ - -#ifndef USBAUDIO_TYPES_H -#define USBAUDIO_TYPES_H - - -#define DEFAULT_CONFIGURATION (1) - -// Audio Request Codes -#define REQUEST_SET_CUR 0x01 -#define REQUEST_GET_CUR 0x81 -#define REQUEST_SET_MIN 0x02 -#define REQUEST_GET_MIN 0x82 -#define REQUEST_SET_MAX 0x03 -#define REQUEST_GET_MAX 0x83 -#define REQUEST_SET_RES 0x04 -#define REQUEST_GET_RES 0x84 - -#define MUTE_CONTROL 0x01 -#define VOLUME_CONTROL 0x02 - - -// Audio Descriptor Sizes -#define CONTROL_INTERFACE_DESCRIPTOR_LENGTH 0x09 -#define STREAMING_INTERFACE_DESCRIPTOR_LENGTH 0x07 -#define INPUT_TERMINAL_DESCRIPTOR_LENGTH 0x0C -#define OUTPUT_TERMINAL_DESCRIPTOR_LENGTH 0x09 -#define FEATURE_UNIT_DESCRIPTOR_LENGTH 0x09 -#define STREAMING_ENDPOINT_DESCRIPTOR_LENGTH 0x07 - -// Audio Format Type Descriptor Sizes -#define FORMAT_TYPE_I_DESCRIPTOR_LENGTH 0x0b - -#define AUDIO_CLASS 0x01 -#define SUBCLASS_AUDIOCONTROL 0x01 -#define SUBCLASS_AUDIOSTREAMING 0x02 - -// Audio Descriptor Types -#define INTERFACE_DESCRIPTOR_TYPE 0x24 -#define ENDPOINT_DESCRIPTOR_TYPE 0x25 - -// Audio Control Interface Descriptor Subtypes -#define CONTROL_HEADER 0x01 -#define CONTROL_INPUT_TERMINAL 0x02 -#define CONTROL_OUTPUT_TERMINAL 0x03 -#define CONTROL_FEATURE_UNIT 0x06 - -// USB Terminal Types -#define TERMINAL_USB_STREAMING 0x0101 - -// Predefined Audio Channel Configuration Bits -// Mono -#define CHANNEL_M 0x0000 -#define CHANNEL_L 0x0001 /* Left Front */ -#define CHANNEL_R 0x0002 /* Right Front */ - -// Feature Unit Control Bits -#define CONTROL_MUTE 0x0001 -#define CONTROL_VOLUME 0x0002 - -// Input Terminal Types -#define TERMINAL_MICROPHONE 0x0201 - -// Output Terminal Types -#define TERMINAL_SPEAKER 0x0301 -#define TERMINAL_HEADPHONES 0x0302 - -// Audio Streaming Interface Descriptor Subtypes -#define STREAMING_GENERAL 0x01 -#define STREAMING_FORMAT_TYPE 0x02 - -// Audio Data Format Type I Codes -#define FORMAT_PCM 0x0001 - -// Audio Format Types -#define FORMAT_TYPE_I 0x01 - -// Audio Endpoint Descriptor Subtypes -#define ENDPOINT_GENERAL 0x01 - -#endif
--- a/USBHID/USBHID.cpp Wed Feb 20 20:54:28 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,279 +0,0 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License -* -* 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 "stdint.h" -#include "USBHAL.h" -#include "USBHID.h" - - -USBHID::USBHID(uint8_t output_report_length, uint8_t input_report_length, uint16_t vendor_id, uint16_t product_id, uint16_t product_release, bool connect): USBDevice(vendor_id, product_id, product_release) -{ - output_length = output_report_length; - input_length = input_report_length; - if(connect) { - USBDevice::connect(); - } -} - - -bool USBHID::send(HID_REPORT *report) -{ - return write(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE); -} - -bool USBHID::sendNB(HID_REPORT *report) -{ - return writeNB(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE); -} - - -bool USBHID::read(HID_REPORT *report) -{ - uint32_t bytesRead = 0; - bool result; - result = USBDevice::readEP(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE); - if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE)) - return false; - report->length = bytesRead; - return result; -} - - -bool USBHID::readNB(HID_REPORT *report) -{ - uint32_t bytesRead = 0; - bool result; - result = USBDevice::readEP_NB(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE); - // if readEP_NB did not succeed, does not issue a readStart - if (!result) - return false; - report->length = bytesRead; - if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE)) - return false; - return result; -} - - -uint16_t USBHID::reportDescLength() { - reportDesc(); - return reportLength; -} - - - -// -// Route callbacks from lower layers to class(es) -// - - -// Called in ISR context -// Called by USBDevice on Endpoint0 request -// This is used to handle extensions to standard requests -// and class specific requests -// Return true if class handles this request -bool USBHID::USBCallback_request() { - bool success = false; - CONTROL_TRANSFER * transfer = getTransferPtr(); - uint8_t *hidDescriptor; - - // Process additional standard requests - - if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE)) - { - switch (transfer->setup.bRequest) - { - case GET_DESCRIPTOR: - switch (DESCRIPTOR_TYPE(transfer->setup.wValue)) - { - case REPORT_DESCRIPTOR: - if ((reportDesc() != NULL) \ - && (reportDescLength() != 0)) - { - transfer->remaining = reportDescLength(); - transfer->ptr = reportDesc(); - transfer->direction = DEVICE_TO_HOST; - success = true; - } - break; - case HID_DESCRIPTOR: - // Find the HID descriptor, after the configuration descriptor - hidDescriptor = findDescriptor(HID_DESCRIPTOR); - if (hidDescriptor != NULL) - { - transfer->remaining = HID_DESCRIPTOR_LENGTH; - transfer->ptr = hidDescriptor; - transfer->direction = DEVICE_TO_HOST; - success = true; - } - break; - - default: - break; - } - break; - default: - break; - } - } - - // Process class-specific requests - - if (transfer->setup.bmRequestType.Type == CLASS_TYPE) - { - switch (transfer->setup.bRequest) - { - case SET_REPORT: - // First byte will be used for report ID - outputReport.data[0] = transfer->setup.wValue & 0xff; - outputReport.length = transfer->setup.wLength + 1; - - transfer->remaining = sizeof(outputReport.data) - 1; - transfer->ptr = &outputReport.data[1]; - transfer->direction = HOST_TO_DEVICE; - transfer->notify = true; - success = true; - default: - break; - } - } - - return success; -} - - -#define DEFAULT_CONFIGURATION (1) - - -// Called in ISR context -// Set configuration. Return false if the -// configuration is not supported -bool USBHID::USBCallback_setConfiguration(uint8_t configuration) { - if (configuration != DEFAULT_CONFIGURATION) { - return false; - } - - // Configure endpoints > 0 - addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT); - addEndpoint(EPINT_OUT, MAX_PACKET_SIZE_EPINT); - - // We activate the endpoint to be able to recceive data - readStart(EPINT_OUT, MAX_PACKET_SIZE_EPINT); - return true; -} - - -uint8_t * USBHID::stringIinterfaceDesc() { - static uint8_t stringIinterfaceDescriptor[] = { - 0x08, //bLength - STRING_DESCRIPTOR, //bDescriptorType 0x03 - 'H',0,'I',0,'D',0, //bString iInterface - HID - }; - return stringIinterfaceDescriptor; -} - -uint8_t * USBHID::stringIproductDesc() { - static uint8_t stringIproductDescriptor[] = { - 0x16, //bLength - STRING_DESCRIPTOR, //bDescriptorType 0x03 - 'H',0,'I',0,'D',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 //bString iProduct - HID device - }; - return stringIproductDescriptor; -} - - - -uint8_t * USBHID::reportDesc() { - static uint8_t reportDescriptor[] = { - USAGE_PAGE(2), LSB(0xFFAB), MSB(0xFFAB), - USAGE(2), LSB(0x0200), MSB(0x0200), - COLLECTION(1), 0x01, // Collection (Application) - - REPORT_SIZE(1), 0x08, // 8 bits - LOGICAL_MINIMUM(1), 0x00, - LOGICAL_MAXIMUM(1), 0xFF, - - REPORT_COUNT(1), input_length, - USAGE(1), 0x01, - INPUT(1), 0x02, // Data, Var, Abs - - REPORT_COUNT(1), output_length, - USAGE(1), 0x02, - OUTPUT(1), 0x02, // Data, Var, Abs - - END_COLLECTION(0), - }; - reportLength = sizeof(reportDescriptor); - return reportDescriptor; -} - -#define DEFAULT_CONFIGURATION (1) -#define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \ - + (1 * INTERFACE_DESCRIPTOR_LENGTH) \ - + (1 * HID_DESCRIPTOR_LENGTH) \ - + (2 * ENDPOINT_DESCRIPTOR_LENGTH)) - -uint8_t * USBHID::configurationDesc() { - static uint8_t configurationDescriptor[] = { - CONFIGURATION_DESCRIPTOR_LENGTH, // bLength - CONFIGURATION_DESCRIPTOR, // bDescriptorType - LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB) - MSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (MSB) - 0x01, // bNumInterfaces - DEFAULT_CONFIGURATION, // bConfigurationValue - 0x00, // iConfiguration - C_RESERVED | C_SELF_POWERED, // bmAttributes - C_POWER(0), // bMaxPower - - INTERFACE_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR, // bDescriptorType - 0x00, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x02, // bNumEndpoints - HID_CLASS, // bInterfaceClass - HID_SUBCLASS_NONE, // bInterfaceSubClass - HID_PROTOCOL_NONE, // bInterfaceProtocol - 0x00, // iInterface - - HID_DESCRIPTOR_LENGTH, // bLength - HID_DESCRIPTOR, // bDescriptorType - LSB(HID_VERSION_1_11), // bcdHID (LSB) - MSB(HID_VERSION_1_11), // bcdHID (MSB) - 0x00, // bCountryCode - 0x01, // bNumDescriptors - REPORT_DESCRIPTOR, // bDescriptorType - (uint8_t)(LSB(reportDescLength())), // wDescriptorLength (LSB) - (uint8_t)(MSB(reportDescLength())), // wDescriptorLength (MSB) - - ENDPOINT_DESCRIPTOR_LENGTH, // bLength - ENDPOINT_DESCRIPTOR, // bDescriptorType - PHY_TO_DESC(EPINT_IN), // bEndpointAddress - E_INTERRUPT, // bmAttributes - LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) - 1, // bInterval (milliseconds) - - ENDPOINT_DESCRIPTOR_LENGTH, // bLength - ENDPOINT_DESCRIPTOR, // bDescriptorType - PHY_TO_DESC(EPINT_OUT), // bEndpointAddress - E_INTERRUPT, // bmAttributes - LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) - 1, // bInterval (milliseconds) - }; - return configurationDescriptor; -}
--- a/USBHID/USBHID.h Wed Feb 20 20:54:28 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,172 +0,0 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License -* -* 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. -*/ - -#ifndef USB_HID_H -#define USB_HID_H - -/* These headers are included for child class. */ -#include "USBEndpoints.h" -#include "USBDescriptor.h" -#include "USBDevice_Types.h" - -#include "USBHID_Types.h" -#include "USBDevice.h" - - -/** - * USBHID example - * @code - * #include "mbed.h" - * #include "USBHID.h" - * - * USBHID hid; - * HID_REPORT recv; - * BusOut leds(LED1,LED2,LED3,LED4); - * - * int main(void) { - * while (1) { - * hid.read(&recv); - * leds = recv.data[0]; - * } - * } - * @endcode - */ - -class USBHID: public USBDevice { -public: - - /** - * Constructor - * - * @param output_report_length Maximum length of a sent report (up to 64 bytes) (default: 64 bytes) - * @param input_report_length Maximum length of a received report (up to 64 bytes) (default: 64 bytes) - * @param vendor_id Your vendor_id - * @param product_id Your product_id - * @param product_release Your preoduct_release - * @param connect Connect the device - */ - USBHID(uint8_t output_report_length = 64, uint8_t input_report_length = 64, uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0006, uint16_t product_release = 0x0001, bool connect = true); - - - /** - * Send a Report. warning: blocking - * - * @param report Report which will be sent (a report is defined by all data and the length) - * @returns true if successful - */ - bool send(HID_REPORT *report); - - - /** - * Send a Report. warning: non blocking - * - * @param report Report which will be sent (a report is defined by all data and the length) - * @returns true if successful - */ - bool sendNB(HID_REPORT *report); - - /** - * Read a report: blocking - * - * @param report pointer to the report to fill - * @returns true if successful - */ - bool read(HID_REPORT * report); - - /** - * Read a report: non blocking - * - * @param report pointer to the report to fill - * @returns true if successful - */ - bool readNB(HID_REPORT * report); - -protected: - uint16_t reportLength; - - /* - * Get the Report descriptor - * - * @returns pointer to the report descriptor - */ - virtual uint8_t * reportDesc(); - - /* - * Get the length of the report descriptor - * - * @returns the length of the report descriptor - */ - virtual uint16_t reportDescLength(); - - /* - * Get string product descriptor - * - * @returns pointer to the string product descriptor - */ - virtual uint8_t * stringIproductDesc(); - - /* - * Get string interface descriptor - * - * @returns pointer to the string interface descriptor - */ - virtual uint8_t * stringIinterfaceDesc(); - - /* - * Get configuration descriptor - * - * @returns pointer to the configuration descriptor - */ - virtual uint8_t * configurationDesc(); - - - /* - * HID Report received by SET_REPORT request. Warning: Called in ISR context - * First byte of data will be the report ID - * - * @param report Data and length received - */ - virtual void HID_callbackSetReport(HID_REPORT *report){}; - - - /* - * Called by USBDevice on Endpoint0 request. Warning: Called in ISR context - * This is used to handle extensions to standard requests - * and class specific requests - * - * @returns true if class handles this request - */ - virtual bool USBCallback_request(); - - - /* - * Called by USBDevice layer. Set configuration of the device. - * For instance, you can add all endpoints that you need on this function. - * - * @param configuration Number of the configuration - * @returns true if class handles this request - */ - virtual bool USBCallback_setConfiguration(uint8_t configuration); - -private: - HID_REPORT outputReport; - uint8_t output_length; - uint8_t input_length; -}; - -#endif
--- a/USBHID/USBHID_Types.h Wed Feb 20 20:54:28 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License -* -* 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. -*/ - -#ifndef USBCLASS_HID_TYPES -#define USBCLASS_HID_TYPES - -#include <stdint.h> - -/* */ -#define HID_VERSION_1_11 (0x0111) - -/* HID Class */ -#define HID_CLASS (3) -#define HID_SUBCLASS_NONE (0) -#define HID_SUBCLASS_BOOT (1) -#define HID_PROTOCOL_NONE (0) -#define HID_PROTOCOL_KEYBOARD (1) -#define HID_PROTOCOL_MOUSE (2) - -/* Descriptors */ -#define HID_DESCRIPTOR (33) -#define HID_DESCRIPTOR_LENGTH (0x09) -#define REPORT_DESCRIPTOR (34) - -/* Class requests */ -#define GET_REPORT (0x1) -#define GET_IDLE (0x2) -#define SET_REPORT (0x9) -#define SET_IDLE (0xa) - -/* HID Class Report Descriptor */ -/* Short items: size is 0, 1, 2 or 3 specifying 0, 1, 2 or 4 (four) bytes */ -/* of data as per HID Class standard */ - -/* Main items */ -#define INPUT(size) (0x80 | size) -#define OUTPUT(size) (0x90 | size) -#define FEATURE(size) (0xb0 | size) -#define COLLECTION(size) (0xa0 | size) -#define END_COLLECTION(size) (0xc0 | size) - -/* Global items */ -#define USAGE_PAGE(size) (0x04 | size) -#define LOGICAL_MINIMUM(size) (0x14 | size) -#define LOGICAL_MAXIMUM(size) (0x24 | size) -#define PHYSICAL_MINIMUM(size) (0x34 | size) -#define PHYSICAL_MAXIMUM(size) (0x44 | size) -#define UNIT_EXPONENT(size) (0x54 | size) -#define UNIT(size) (0x64 | size) -#define REPORT_SIZE(size) (0x74 | size) -#define REPORT_ID(size) (0x84 | size) -#define REPORT_COUNT(size) (0x94 | size) -#define PUSH(size) (0xa4 | size) -#define POP(size) (0xb4 | size) - -/* Local items */ -#define USAGE(size) (0x08 | size) -#define USAGE_MINIMUM(size) (0x18 | size) -#define USAGE_MAXIMUM(size) (0x28 | size) -#define DESIGNATOR_INDEX(size) (0x38 | size) -#define DESIGNATOR_MINIMUM(size) (0x48 | size) -#define DESIGNATOR_MAXIMUM(size) (0x58 | size) -#define STRING_INDEX(size) (0x78 | size) -#define STRING_MINIMUM(size) (0x88 | size) -#define STRING_MAXIMUM(size) (0x98 | size) -#define DELIMITER(size) (0xa8 | size) - -/* HID Report */ -/* Where report IDs are used the first byte of 'data' will be the */ -/* report ID and 'length' will include this report ID byte. */ - -#define MAX_HID_REPORT_SIZE (64) - -typedef struct { - uint32_t length; - uint8_t data[MAX_HID_REPORT_SIZE]; -} HID_REPORT; - -#endif
--- a/USBHID/USBKeyboard.cpp Wed Feb 20 20:54:28 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,553 +0,0 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License -* -* 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 "stdint.h" - -#include "USBKeyboard.h" - -#define REPORT_ID_KEYBOARD 1 -#define REPORT_ID_VOLUME 3 - - -typedef struct { - unsigned char usage; - unsigned char modifier; -} KEYMAP; - -#ifdef US_KEYBOARD -/* US keyboard (as HID standard) */ -#define KEYMAP_SIZE (152) -const KEYMAP keymap[KEYMAP_SIZE] = { - {0, 0}, /* NUL */ - {0, 0}, /* SOH */ - {0, 0}, /* STX */ - {0, 0}, /* ETX */ - {0, 0}, /* EOT */ - {0, 0}, /* ENQ */ - {0, 0}, /* ACK */ - {0, 0}, /* BEL */ - {0x2a, 0}, /* BS */ /* Keyboard Delete (Backspace) */ - {0x2b, 0}, /* TAB */ /* Keyboard Tab */ - {0x28, 0}, /* LF */ /* Keyboard Return (Enter) */ - {0, 0}, /* VT */ - {0, 0}, /* FF */ - {0, 0}, /* CR */ - {0, 0}, /* SO */ - {0, 0}, /* SI */ - {0, 0}, /* DEL */ - {0, 0}, /* DC1 */ - {0, 0}, /* DC2 */ - {0, 0}, /* DC3 */ - {0, 0}, /* DC4 */ - {0, 0}, /* NAK */ - {0, 0}, /* SYN */ - {0, 0}, /* ETB */ - {0, 0}, /* CAN */ - {0, 0}, /* EM */ - {0, 0}, /* SUB */ - {0, 0}, /* ESC */ - {0, 0}, /* FS */ - {0, 0}, /* GS */ - {0, 0}, /* RS */ - {0, 0}, /* US */ - {0x2c, 0}, /* */ - {0x1e, KEY_SHIFT}, /* ! */ - {0x34, KEY_SHIFT}, /* " */ - {0x20, KEY_SHIFT}, /* # */ - {0x21, KEY_SHIFT}, /* $ */ - {0x22, KEY_SHIFT}, /* % */ - {0x24, KEY_SHIFT}, /* & */ - {0x34, 0}, /* ' */ - {0x26, KEY_SHIFT}, /* ( */ - {0x27, KEY_SHIFT}, /* ) */ - {0x25, KEY_SHIFT}, /* * */ - {0x2e, KEY_SHIFT}, /* + */ - {0x36, 0}, /* , */ - {0x2d, 0}, /* - */ - {0x37, 0}, /* . */ - {0x38, 0}, /* / */ - {0x27, 0}, /* 0 */ - {0x1e, 0}, /* 1 */ - {0x1f, 0}, /* 2 */ - {0x20, 0}, /* 3 */ - {0x21, 0}, /* 4 */ - {0x22, 0}, /* 5 */ - {0x23, 0}, /* 6 */ - {0x24, 0}, /* 7 */ - {0x25, 0}, /* 8 */ - {0x26, 0}, /* 9 */ - {0x33, KEY_SHIFT}, /* : */ - {0x33, 0}, /* ; */ - {0x36, KEY_SHIFT}, /* < */ - {0x2e, 0}, /* = */ - {0x37, KEY_SHIFT}, /* > */ - {0x38, KEY_SHIFT}, /* ? */ - {0x1f, KEY_SHIFT}, /* @ */ - {0x04, KEY_SHIFT}, /* A */ - {0x05, KEY_SHIFT}, /* B */ - {0x06, KEY_SHIFT}, /* C */ - {0x07, KEY_SHIFT}, /* D */ - {0x08, KEY_SHIFT}, /* E */ - {0x09, KEY_SHIFT}, /* F */ - {0x0a, KEY_SHIFT}, /* G */ - {0x0b, KEY_SHIFT}, /* H */ - {0x0c, KEY_SHIFT}, /* I */ - {0x0d, KEY_SHIFT}, /* J */ - {0x0e, KEY_SHIFT}, /* K */ - {0x0f, KEY_SHIFT}, /* L */ - {0x10, KEY_SHIFT}, /* M */ - {0x11, KEY_SHIFT}, /* N */ - {0x12, KEY_SHIFT}, /* O */ - {0x13, KEY_SHIFT}, /* P */ - {0x14, KEY_SHIFT}, /* Q */ - {0x15, KEY_SHIFT}, /* R */ - {0x16, KEY_SHIFT}, /* S */ - {0x17, KEY_SHIFT}, /* T */ - {0x18, KEY_SHIFT}, /* U */ - {0x19, KEY_SHIFT}, /* V */ - {0x1a, KEY_SHIFT}, /* W */ - {0x1b, KEY_SHIFT}, /* X */ - {0x1c, KEY_SHIFT}, /* Y */ - {0x1d, KEY_SHIFT}, /* Z */ - {0x2f, 0}, /* [ */ - {0x31, 0}, /* \ */ - {0x30, 0}, /* ] */ - {0x23, KEY_SHIFT}, /* ^ */ - {0x2d, KEY_SHIFT}, /* _ */ - {0x35, 0}, /* ` */ - {0x04, 0}, /* a */ - {0x05, 0}, /* b */ - {0x06, 0}, /* c */ - {0x07, 0}, /* d */ - {0x08, 0}, /* e */ - {0x09, 0}, /* f */ - {0x0a, 0}, /* g */ - {0x0b, 0}, /* h */ - {0x0c, 0}, /* i */ - {0x0d, 0}, /* j */ - {0x0e, 0}, /* k */ - {0x0f, 0}, /* l */ - {0x10, 0}, /* m */ - {0x11, 0}, /* n */ - {0x12, 0}, /* o */ - {0x13, 0}, /* p */ - {0x14, 0}, /* q */ - {0x15, 0}, /* r */ - {0x16, 0}, /* s */ - {0x17, 0}, /* t */ - {0x18, 0}, /* u */ - {0x19, 0}, /* v */ - {0x1a, 0}, /* w */ - {0x1b, 0}, /* x */ - {0x1c, 0}, /* y */ - {0x1d, 0}, /* z */ - {0x2f, KEY_SHIFT}, /* { */ - {0x31, KEY_SHIFT}, /* | */ - {0x30, KEY_SHIFT}, /* } */ - {0x35, KEY_SHIFT}, /* ~ */ - {0,0}, /* DEL */ - - {0x3a, 0}, /* F1 */ - {0x3b, 0}, /* F2 */ - {0x3c, 0}, /* F3 */ - {0x3d, 0}, /* F4 */ - {0x3e, 0}, /* F5 */ - {0x3f, 0}, /* F6 */ - {0x40, 0}, /* F7 */ - {0x41, 0}, /* F8 */ - {0x42, 0}, /* F9 */ - {0x43, 0}, /* F10 */ - {0x44, 0}, /* F11 */ - {0x45, 0}, /* F12 */ - - {0x46, 0}, /* PRINT_SCREEN */ - {0x47, 0}, /* SCROLL_LOCK */ - {0x39, 0}, /* CAPS_LOCK */ - {0x53, 0}, /* NUM_LOCK */ - {0x49, 0}, /* INSERT */ - {0x4a, 0}, /* HOME */ - {0x4b, 0}, /* PAGE_UP */ - {0x4e, 0}, /* PAGE_DOWN */ - - {0x4f, 0}, /* RIGHT_ARROW */ - {0x50, 0}, /* LEFT_ARROW */ - {0x51, 0}, /* DOWN_ARROW */ - {0x52, 0}, /* UP_ARROW */ -}; - -#else -/* UK keyboard */ -#define KEYMAP_SIZE (152) -const KEYMAP keymap[KEYMAP_SIZE] = { - {0, 0}, /* NUL */ - {0, 0}, /* SOH */ - {0, 0}, /* STX */ - {0, 0}, /* ETX */ - {0, 0}, /* EOT */ - {0, 0}, /* ENQ */ - {0, 0}, /* ACK */ - {0, 0}, /* BEL */ - {0x2a, 0}, /* BS */ /* Keyboard Delete (Backspace) */ - {0x2b, 0}, /* TAB */ /* Keyboard Tab */ - {0x28, 0}, /* LF */ /* Keyboard Return (Enter) */ - {0, 0}, /* VT */ - {0, 0}, /* FF */ - {0, 0}, /* CR */ - {0, 0}, /* SO */ - {0, 0}, /* SI */ - {0, 0}, /* DEL */ - {0, 0}, /* DC1 */ - {0, 0}, /* DC2 */ - {0, 0}, /* DC3 */ - {0, 0}, /* DC4 */ - {0, 0}, /* NAK */ - {0, 0}, /* SYN */ - {0, 0}, /* ETB */ - {0, 0}, /* CAN */ - {0, 0}, /* EM */ - {0, 0}, /* SUB */ - {0, 0}, /* ESC */ - {0, 0}, /* FS */ - {0, 0}, /* GS */ - {0, 0}, /* RS */ - {0, 0}, /* US */ - {0x2c, 0}, /* */ - {0x1e, KEY_SHIFT}, /* ! */ - {0x1f, KEY_SHIFT}, /* " */ - {0x32, 0}, /* # */ - {0x21, KEY_SHIFT}, /* $ */ - {0x22, KEY_SHIFT}, /* % */ - {0x24, KEY_SHIFT}, /* & */ - {0x34, 0}, /* ' */ - {0x26, KEY_SHIFT}, /* ( */ - {0x27, KEY_SHIFT}, /* ) */ - {0x25, KEY_SHIFT}, /* * */ - {0x2e, KEY_SHIFT}, /* + */ - {0x36, 0}, /* , */ - {0x2d, 0}, /* - */ - {0x37, 0}, /* . */ - {0x38, 0}, /* / */ - {0x27, 0}, /* 0 */ - {0x1e, 0}, /* 1 */ - {0x1f, 0}, /* 2 */ - {0x20, 0}, /* 3 */ - {0x21, 0}, /* 4 */ - {0x22, 0}, /* 5 */ - {0x23, 0}, /* 6 */ - {0x24, 0}, /* 7 */ - {0x25, 0}, /* 8 */ - {0x26, 0}, /* 9 */ - {0x33, KEY_SHIFT}, /* : */ - {0x33, 0}, /* ; */ - {0x36, KEY_SHIFT}, /* < */ - {0x2e, 0}, /* = */ - {0x37, KEY_SHIFT}, /* > */ - {0x38, KEY_SHIFT}, /* ? */ - {0x34, KEY_SHIFT}, /* @ */ - {0x04, KEY_SHIFT}, /* A */ - {0x05, KEY_SHIFT}, /* B */ - {0x06, KEY_SHIFT}, /* C */ - {0x07, KEY_SHIFT}, /* D */ - {0x08, KEY_SHIFT}, /* E */ - {0x09, KEY_SHIFT}, /* F */ - {0x0a, KEY_SHIFT}, /* G */ - {0x0b, KEY_SHIFT}, /* H */ - {0x0c, KEY_SHIFT}, /* I */ - {0x0d, KEY_SHIFT}, /* J */ - {0x0e, KEY_SHIFT}, /* K */ - {0x0f, KEY_SHIFT}, /* L */ - {0x10, KEY_SHIFT}, /* M */ - {0x11, KEY_SHIFT}, /* N */ - {0x12, KEY_SHIFT}, /* O */ - {0x13, KEY_SHIFT}, /* P */ - {0x14, KEY_SHIFT}, /* Q */ - {0x15, KEY_SHIFT}, /* R */ - {0x16, KEY_SHIFT}, /* S */ - {0x17, KEY_SHIFT}, /* T */ - {0x18, KEY_SHIFT}, /* U */ - {0x19, KEY_SHIFT}, /* V */ - {0x1a, KEY_SHIFT}, /* W */ - {0x1b, KEY_SHIFT}, /* X */ - {0x1c, KEY_SHIFT}, /* Y */ - {0x1d, KEY_SHIFT}, /* Z */ - {0x2f, 0}, /* [ */ - {0x64, 0}, /* \ */ - {0x30, 0}, /* ] */ - {0x23, KEY_SHIFT}, /* ^ */ - {0x2d, KEY_SHIFT}, /* _ */ - {0x35, 0}, /* ` */ - {0x04, 0}, /* a */ - {0x05, 0}, /* b */ - {0x06, 0}, /* c */ - {0x07, 0}, /* d */ - {0x08, 0}, /* e */ - {0x09, 0}, /* f */ - {0x0a, 0}, /* g */ - {0x0b, 0}, /* h */ - {0x0c, 0}, /* i */ - {0x0d, 0}, /* j */ - {0x0e, 0}, /* k */ - {0x0f, 0}, /* l */ - {0x10, 0}, /* m */ - {0x11, 0}, /* n */ - {0x12, 0}, /* o */ - {0x13, 0}, /* p */ - {0x14, 0}, /* q */ - {0x15, 0}, /* r */ - {0x16, 0}, /* s */ - {0x17, 0}, /* t */ - {0x18, 0}, /* u */ - {0x19, 0}, /* v */ - {0x1a, 0}, /* w */ - {0x1b, 0}, /* x */ - {0x1c, 0}, /* y */ - {0x1d, 0}, /* z */ - {0x2f, KEY_SHIFT}, /* { */ - {0x64, KEY_SHIFT}, /* | */ - {0x30, KEY_SHIFT}, /* } */ - {0x32, KEY_SHIFT}, /* ~ */ - {0,0}, /* DEL */ - - {0x3a, 0}, /* F1 */ - {0x3b, 0}, /* F2 */ - {0x3c, 0}, /* F3 */ - {0x3d, 0}, /* F4 */ - {0x3e, 0}, /* F5 */ - {0x3f, 0}, /* F6 */ - {0x40, 0}, /* F7 */ - {0x41, 0}, /* F8 */ - {0x42, 0}, /* F9 */ - {0x43, 0}, /* F10 */ - {0x44, 0}, /* F11 */ - {0x45, 0}, /* F12 */ - - {0x46, 0}, /* PRINT_SCREEN */ - {0x47, 0}, /* SCROLL_LOCK */ - {0x39, 0}, /* CAPS_LOCK */ - {0x53, 0}, /* NUM_LOCK */ - {0x49, 0}, /* INSERT */ - {0x4a, 0}, /* HOME */ - {0x4b, 0}, /* PAGE_UP */ - {0x4e, 0}, /* PAGE_DOWN */ - - {0x4f, 0}, /* RIGHT_ARROW */ - {0x50, 0}, /* LEFT_ARROW */ - {0x51, 0}, /* DOWN_ARROW */ - {0x52, 0}, /* UP_ARROW */ -}; -#endif - -uint8_t * USBKeyboard::reportDesc() { - static uint8_t reportDescriptor[] = { - USAGE_PAGE(1), 0x01, // Generic Desktop - USAGE(1), 0x06, // Keyboard - COLLECTION(1), 0x01, // Application - REPORT_ID(1), REPORT_ID_KEYBOARD, - - USAGE_PAGE(1), 0x07, // Key Codes - USAGE_MINIMUM(1), 0xE0, - USAGE_MAXIMUM(1), 0xE7, - LOGICAL_MINIMUM(1), 0x00, - LOGICAL_MAXIMUM(1), 0x01, - REPORT_SIZE(1), 0x01, - REPORT_COUNT(1), 0x08, - INPUT(1), 0x02, // Data, Variable, Absolute - REPORT_COUNT(1), 0x01, - REPORT_SIZE(1), 0x08, - INPUT(1), 0x01, // Constant - - - REPORT_COUNT(1), 0x05, - REPORT_SIZE(1), 0x01, - USAGE_PAGE(1), 0x08, // LEDs - USAGE_MINIMUM(1), 0x01, - USAGE_MAXIMUM(1), 0x05, - OUTPUT(1), 0x02, // Data, Variable, Absolute - REPORT_COUNT(1), 0x01, - REPORT_SIZE(1), 0x03, - OUTPUT(1), 0x01, // Constant - - - REPORT_COUNT(1), 0x06, - REPORT_SIZE(1), 0x08, - LOGICAL_MINIMUM(1), 0x00, - LOGICAL_MAXIMUM(1), 0x65, - USAGE_PAGE(1), 0x07, // Key Codes - USAGE_MINIMUM(1), 0x00, - USAGE_MAXIMUM(1), 0x65, - INPUT(1), 0x00, // Data, Array - END_COLLECTION(0), - - // Media Control - USAGE_PAGE(1), 0x0C, - USAGE(1), 0x01, - COLLECTION(1), 0x01, - REPORT_ID(1), REPORT_ID_VOLUME, - USAGE_PAGE(1), 0x0C, - LOGICAL_MINIMUM(1), 0x00, - LOGICAL_MAXIMUM(1), 0x01, - REPORT_SIZE(1), 0x01, - REPORT_COUNT(1), 0x07, - USAGE(1), 0xB5, // Next Track - USAGE(1), 0xB6, // Previous Track - USAGE(1), 0xB7, // Stop - USAGE(1), 0xCD, // Play / Pause - USAGE(1), 0xE2, // Mute - USAGE(1), 0xE9, // Volume Up - USAGE(1), 0xEA, // Volume Down - INPUT(1), 0x02, // Input (Data, Variable, Absolute) - REPORT_COUNT(1), 0x01, - INPUT(1), 0x01, - END_COLLECTION(0), - }; - reportLength = sizeof(reportDescriptor); - return reportDescriptor; -} - - -bool USBKeyboard::EPINT_OUT_callback() { - uint32_t bytesRead = 0; - uint8_t led[65]; - USBDevice::readEP(EPINT_OUT, led, &bytesRead, MAX_HID_REPORT_SIZE); - - // we take led[1] because led[0] is the report ID - lock_status = led[1] & 0x07; - - // We activate the endpoint to be able to recceive data - if (!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE)) - return false; - return true; -} - -uint8_t USBKeyboard::lockStatus() { - return lock_status; -} - -int USBKeyboard::_putc(int c) { - return keyCode(c, keymap[c].modifier); -} - -bool USBKeyboard::keyCode(uint8_t key, uint8_t modifier) { - // Send a simulated keyboard keypress. Returns true if successful. - HID_REPORT report; - - report.data[0] = REPORT_ID_KEYBOARD; - report.data[1] = modifier; - report.data[2] = 0; - report.data[3] = keymap[key].usage; - report.data[4] = 0; - report.data[5] = 0; - report.data[6] = 0; - report.data[7] = 0; - report.data[8] = 0; - - report.length = 9; - - if (!send(&report)) { - return false; - } - - report.data[1] = 0; - report.data[3] = 0; - - if (!send(&report)) { - return false; - } - - return true; - -} - - -bool USBKeyboard::mediaControl(MEDIA_KEY key) { - HID_REPORT report; - - report.data[0] = REPORT_ID_VOLUME; - report.data[1] = (1 << key) & 0x7f; - - report.length = 2; - - if (!send(&report)) { - return false; - } - - report.data[0] = REPORT_ID_VOLUME; - report.data[1] = 0; - - report.length = 2; - - return send(&report); -} - - -#define DEFAULT_CONFIGURATION (1) -#define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \ - + (1 * INTERFACE_DESCRIPTOR_LENGTH) \ - + (1 * HID_DESCRIPTOR_LENGTH) \ - + (2 * ENDPOINT_DESCRIPTOR_LENGTH)) - -uint8_t * USBKeyboard::configurationDesc() { - static uint8_t configurationDescriptor[] = { - CONFIGURATION_DESCRIPTOR_LENGTH, // bLength - CONFIGURATION_DESCRIPTOR, // bDescriptorType - LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB) - MSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (MSB) - 0x01, // bNumInterfaces - DEFAULT_CONFIGURATION, // bConfigurationValue - 0x00, // iConfiguration - C_RESERVED | C_SELF_POWERED, // bmAttributes - C_POWER(0), // bMaxPower - - INTERFACE_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR, // bDescriptorType - 0x00, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x02, // bNumEndpoints - HID_CLASS, // bInterfaceClass - HID_SUBCLASS_BOOT, // bInterfaceSubClass - HID_PROTOCOL_KEYBOARD, // bInterfaceProtocol - 0x00, // iInterface - - HID_DESCRIPTOR_LENGTH, // bLength - HID_DESCRIPTOR, // bDescriptorType - LSB(HID_VERSION_1_11), // bcdHID (LSB) - MSB(HID_VERSION_1_11), // bcdHID (MSB) - 0x00, // bCountryCode - 0x01, // bNumDescriptors - REPORT_DESCRIPTOR, // bDescriptorType - (uint8_t)(LSB(reportDescLength())), // wDescriptorLength (LSB) - (uint8_t)(MSB(reportDescLength())), // wDescriptorLength (MSB) - - ENDPOINT_DESCRIPTOR_LENGTH, // bLength - ENDPOINT_DESCRIPTOR, // bDescriptorType - PHY_TO_DESC(EPINT_IN), // bEndpointAddress - E_INTERRUPT, // bmAttributes - LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) - 1, // bInterval (milliseconds) - - ENDPOINT_DESCRIPTOR_LENGTH, // bLength - ENDPOINT_DESCRIPTOR, // bDescriptorType - PHY_TO_DESC(EPINT_OUT), // bEndpointAddress - E_INTERRUPT, // bmAttributes - LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) - 1, // bInterval (milliseconds) - }; - return configurationDescriptor; -}
--- a/USBHID/USBKeyboard.h Wed Feb 20 20:54:28 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,188 +0,0 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License -* -* 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. -*/ - -#ifndef USBKEYBOARD_H -#define USBKEYBOARD_H - -#include "USBHID.h" -#include "Stream.h" - -/* Modifiers, left keys then right keys. */ -enum MODIFIER_KEY { - KEY_CTRL = 0x01, - KEY_SHIFT = 0x02, - KEY_ALT = 0x04, - KEY_LOGO = 0x08, - KEY_RCTRL = 0x10, - KEY_RSHIFT = 0x20, - KEY_RALT = 0x40, - KEY_RLOGO = 0x80, -}; - - -enum MEDIA_KEY { - KEY_NEXT_TRACK, /*!< next Track Button */ - KEY_PREVIOUS_TRACK, /*!< Previous track Button */ - KEY_STOP, /*!< Stop Button */ - KEY_PLAY_PAUSE, /*!< Play/Pause Button */ - KEY_MUTE, /*!< Mute Button */ - KEY_VOLUME_UP, /*!< Volume Up Button */ - KEY_VOLUME_DOWN, /*!< Volume Down Button */ -}; - -enum FUNCTION_KEY { - KEY_F1 = 128, /* F1 key */ - KEY_F2, /* F2 key */ - KEY_F3, /* F3 key */ - KEY_F4, /* F4 key */ - KEY_F5, /* F5 key */ - KEY_F6, /* F6 key */ - KEY_F7, /* F7 key */ - KEY_F8, /* F8 key */ - KEY_F9, /* F9 key */ - KEY_F10, /* F10 key */ - KEY_F11, /* F11 key */ - KEY_F12, /* F12 key */ - - KEY_PRINT_SCREEN, /* Print Screen key */ - KEY_SCROLL_LOCK, /* Scroll lock */ - KEY_CAPS_LOCK, /* caps lock */ - KEY_NUM_LOCK, /* num lock */ - KEY_INSERT, /* Insert key */ - KEY_HOME, /* Home key */ - KEY_PAGE_UP, /* Page Up key */ - KEY_PAGE_DOWN, /* Page Down key */ - - RIGHT_ARROW, /* Right arrow */ - LEFT_ARROW, /* Left arrow */ - DOWN_ARROW, /* Down arrow */ - UP_ARROW, /* Up arrow */ -}; - -/** - * USBKeyboard example - * @code - * - * #include "mbed.h" - * #include "USBKeyboard.h" - * - * USBKeyboard key; - * - * int main(void) - * { - * while (1) - * { - * key.printf("Hello World\r\n"); - * wait(1); - * } - * } - * - * @endcode - */ -class USBKeyboard: public USBHID, public Stream { -public: - - /** - * Constructor - * - * - * @param leds Leds bus: first: NUM_LOCK, second: CAPS_LOCK, third: SCROLL_LOCK - * @param vendor_id Your vendor_id (default: 0x1235) - * @param product_id Your product_id (default: 0x0050) - * @param product_release Your preoduct_release (default: 0x0001) - * - */ - USBKeyboard(uint16_t vendor_id = 0x1235, uint16_t product_id = 0x0050, uint16_t product_release = 0x0001): - USBHID(0, 0, vendor_id, product_id, product_release, false) { - lock_status = 0; - connect(); - }; - - /** - * To send a character defined by a modifier(CTRL, SHIFT, ALT) and the key - * - * @code - * //To send CTRL + s (save) - * keyboard.keyCode('s', KEY_CTRL); - * @endcode - * - * @param modifier bit 0: KEY_CTRL, bit 1: KEY_SHIFT, bit 2: KEY_ALT (default: 0) - * @param key character to send - * @returns true if there is no error, false otherwise - */ - bool keyCode(uint8_t key, uint8_t modifier = 0); - - /** - * Send a character - * - * @param c character to be sent - * @returns true if there is no error, false otherwise - */ - virtual int _putc(int c); - - /** - * Control media keys - * - * @param key media key pressed (KEY_NEXT_TRACK, KEY_PREVIOUS_TRACK, KEY_STOP, KEY_PLAY_PAUSE, KEY_MUTE, KEY_VOLUME_UP, KEY_VOLUME_DOWN) - * @returns true if there is no error, false otherwise - */ - bool mediaControl(MEDIA_KEY key); - - /* - * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength. - * - * @returns pointer to the report descriptor - */ - virtual uint8_t * reportDesc(); - - /* - * Called when a data is received on the OUT endpoint. Useful to switch on LED of LOCK keys - * - * @returns if handle by subclass, return true - */ - virtual bool EPINT_OUT_callback(); - - /** - * Read status of lock keys. Useful to switch-on/off leds according to key pressed. Only the first three bits of the result is important: - * - First bit: NUM_LOCK - * - Second bit: CAPS_LOCK - * - Third bit: SCROLL_LOCK - * - * @returns status of lock keys - */ - uint8_t lockStatus(); - -protected: - /* - * Get configuration descriptor - * - * @returns pointer to the configuration descriptor - */ - virtual uint8_t * configurationDesc(); - -private: - //dummy otherwise it doesn,t compile (we must define all methods of an abstract class) - virtual int _getc() { - return -1; - }; - - uint8_t lock_status; - -}; - -#endif
--- a/USBHID/USBMouse.cpp Wed Feb 20 20:54:28 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,244 +0,0 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License -* -* 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 "stdint.h" -#include "USBMouse.h" - -bool USBMouse::update(int16_t x, int16_t y, uint8_t button, int8_t z) { - switch (mouse_type) { - case REL_MOUSE: - while (x > 127) { - if (!mouseSend(127, 0, button, z)) return false; - x = x - 127; - } - while (x < -128) { - if (!mouseSend(-128, 0, button, z)) return false; - x = x + 128; - } - while (y > 127) { - if (!mouseSend(0, 127, button, z)) return false; - y = y - 127; - } - while (y < -128) { - if (!mouseSend(0, -128, button, z)) return false; - y = y + 128; - } - return mouseSend(x, y, button, z); - case ABS_MOUSE: - HID_REPORT report; - - report.data[0] = x & 0xff; - report.data[1] = (x >> 8) & 0xff; - report.data[2] = y & 0xff; - report.data[3] = (y >> 8) & 0xff; - report.data[4] = -z; - report.data[5] = button & 0x07; - - report.length = 6; - - return send(&report); - default: - return false; - } -} - -bool USBMouse::mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z) { - HID_REPORT report; - report.data[0] = buttons & 0x07; - report.data[1] = x; - report.data[2] = y; - report.data[3] = -z; // >0 to scroll down, <0 to scroll up - - report.length = 4; - - return send(&report); -} - -bool USBMouse::move(int16_t x, int16_t y) { - return update(x, y, button, 0); -} - -bool USBMouse::scroll(int8_t z) { - return update(0, 0, button, z); -} - - -bool USBMouse::doubleClick() { - if (!click(MOUSE_LEFT)) - return false; - wait(0.1); - return click(MOUSE_LEFT); -} - -bool USBMouse::click(uint8_t button) { - if (!update(0, 0, button, 0)) - return false; - wait(0.01); - return update(0, 0, 0, 0); -} - -bool USBMouse::press(uint8_t button_) { - button = button_ & 0x07; - return update(0, 0, button, 0); -} - -bool USBMouse::release(uint8_t button_) { - button = (button & (~button_)) & 0x07; - return update(0, 0, button, 0); -} - - -uint8_t * USBMouse::reportDesc() { - - if (mouse_type == REL_MOUSE) { - static uint8_t reportDescriptor[] = { - USAGE_PAGE(1), 0x01, // Genric Desktop - USAGE(1), 0x02, // Mouse - COLLECTION(1), 0x01, // Application - USAGE(1), 0x01, // Pointer - COLLECTION(1), 0x00, // Physical - - REPORT_COUNT(1), 0x03, - REPORT_SIZE(1), 0x01, - USAGE_PAGE(1), 0x09, // Buttons - USAGE_MINIMUM(1), 0x1, - USAGE_MAXIMUM(1), 0x3, - LOGICAL_MINIMUM(1), 0x00, - LOGICAL_MAXIMUM(1), 0x01, - INPUT(1), 0x02, - REPORT_COUNT(1), 0x01, - REPORT_SIZE(1), 0x05, - INPUT(1), 0x01, - - REPORT_COUNT(1), 0x03, - REPORT_SIZE(1), 0x08, - USAGE_PAGE(1), 0x01, - USAGE(1), 0x30, // X - USAGE(1), 0x31, // Y - USAGE(1), 0x38, // scroll - LOGICAL_MINIMUM(1), 0x81, - LOGICAL_MAXIMUM(1), 0x7f, - INPUT(1), 0x06, // Relative data - - END_COLLECTION(0), - END_COLLECTION(0), - }; - reportLength = sizeof(reportDescriptor); - return reportDescriptor; - } else if (mouse_type == ABS_MOUSE) { - static uint8_t reportDescriptor[] = { - USAGE_PAGE(1), 0x01, // Generic Desktop - USAGE(1), 0x02, // Mouse - COLLECTION(1), 0x01, // Application - USAGE(1), 0x01, // Pointer - COLLECTION(1), 0x00, // Physical - - USAGE_PAGE(1), 0x01, // Generic Desktop - USAGE(1), 0x30, // X - USAGE(1), 0x31, // Y - LOGICAL_MINIMUM(1), 0x00, // 0 - LOGICAL_MAXIMUM(2), 0xff, 0x7f, // 32767 - REPORT_SIZE(1), 0x10, - REPORT_COUNT(1), 0x02, - INPUT(1), 0x02, // Data, Variable, Absolute - - USAGE_PAGE(1), 0x01, // Generic Desktop - USAGE(1), 0x38, // scroll - LOGICAL_MINIMUM(1), 0x81, // -127 - LOGICAL_MAXIMUM(1), 0x7f, // 127 - REPORT_SIZE(1), 0x08, - REPORT_COUNT(1), 0x01, - INPUT(1), 0x06, // Data, Variable, Relative - - USAGE_PAGE(1), 0x09, // Buttons - USAGE_MINIMUM(1), 0x01, - USAGE_MAXIMUM(1), 0x03, - LOGICAL_MINIMUM(1), 0x00, // 0 - LOGICAL_MAXIMUM(1), 0x01, // 1 - REPORT_COUNT(1), 0x03, - REPORT_SIZE(1), 0x01, - INPUT(1), 0x02, // Data, Variable, Absolute - REPORT_COUNT(1), 0x01, - REPORT_SIZE(1), 0x05, - INPUT(1), 0x01, // Constant - - END_COLLECTION(0), - END_COLLECTION(0) - }; - reportLength = sizeof(reportDescriptor); - return reportDescriptor; - } - return NULL; -} - -#define DEFAULT_CONFIGURATION (1) -#define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \ - + (1 * INTERFACE_DESCRIPTOR_LENGTH) \ - + (1 * HID_DESCRIPTOR_LENGTH) \ - + (2 * ENDPOINT_DESCRIPTOR_LENGTH)) - -uint8_t * USBMouse::configurationDesc() { - static uint8_t configurationDescriptor[] = { - CONFIGURATION_DESCRIPTOR_LENGTH, // bLength - CONFIGURATION_DESCRIPTOR, // bDescriptorType - LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB) - MSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (MSB) - 0x01, // bNumInterfaces - DEFAULT_CONFIGURATION, // bConfigurationValue - 0x00, // iConfiguration - C_RESERVED | C_SELF_POWERED, // bmAttributes - C_POWER(0), // bMaxPower - - INTERFACE_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR, // bDescriptorType - 0x00, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x02, // bNumEndpoints - HID_CLASS, // bInterfaceClass - HID_SUBCLASS_BOOT, // bInterfaceSubClass - HID_PROTOCOL_MOUSE, // bInterfaceProtocol - 0x00, // iInterface - - HID_DESCRIPTOR_LENGTH, // bLength - HID_DESCRIPTOR, // bDescriptorType - LSB(HID_VERSION_1_11), // bcdHID (LSB) - MSB(HID_VERSION_1_11), // bcdHID (MSB) - 0x00, // bCountryCode - 0x01, // bNumDescriptors - REPORT_DESCRIPTOR, // bDescriptorType - (uint8_t)(LSB(reportDescLength())), // wDescriptorLength (LSB) - (uint8_t)(MSB(reportDescLength())), // wDescriptorLength (MSB) - - ENDPOINT_DESCRIPTOR_LENGTH, // bLength - ENDPOINT_DESCRIPTOR, // bDescriptorType - PHY_TO_DESC(EPINT_IN), // bEndpointAddress - E_INTERRUPT, // bmAttributes - LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) - 1, // bInterval (milliseconds) - - ENDPOINT_DESCRIPTOR_LENGTH, // bLength - ENDPOINT_DESCRIPTOR, // bDescriptorType - PHY_TO_DESC(EPINT_OUT), // bEndpointAddress - E_INTERRUPT, // bmAttributes - LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) - 1, // bInterval (milliseconds) - }; - return configurationDescriptor; -}
--- a/USBHID/USBMouse.h Wed Feb 20 20:54:28 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,209 +0,0 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License -* -* 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. -*/ - -#ifndef USBMOUSE_H -#define USBMOUSE_H - -#include "USBHID.h" - -#define REPORT_ID_MOUSE 2 - -/* Common usage */ - -enum MOUSE_BUTTON -{ - MOUSE_LEFT = 1, - MOUSE_RIGHT = 2, - MOUSE_MIDDLE = 4, -}; - -/* X and Y limits */ -/* These values do not directly map to screen pixels */ -/* Zero may be interpreted as meaning 'no movement' */ -#define X_MIN_ABS (1) /*!< Minimum value on x-axis */ -#define Y_MIN_ABS (1) /*!< Minimum value on y-axis */ -#define X_MAX_ABS (0x7fff) /*!< Maximum value on x-axis */ -#define Y_MAX_ABS (0x7fff) /*!< Maximum value on y-axis */ - -#define X_MIN_REL (-127) /*!< The maximum value that we can move to the left on the x-axis */ -#define Y_MIN_REL (-127) /*!< The maximum value that we can move up on the y-axis */ -#define X_MAX_REL (127) /*!< The maximum value that we can move to the right on the x-axis */ -#define Y_MAX_REL (127) /*!< The maximum value that we can move down on the y-axis */ - -enum MOUSE_TYPE -{ - ABS_MOUSE, - REL_MOUSE, -}; - -/** - * - * USBMouse example - * @code - * #include "mbed.h" - * #include "USBMouse.h" - * - * USBMouse mouse; - * - * int main(void) - * { - * while (1) - * { - * mouse.move(20, 0); - * wait(0.5); - * } - * } - * - * @endcode - * - * - * @code - * #include "mbed.h" - * #include "USBMouse.h" - * #include <math.h> - * - * USBMouse mouse(ABS_MOUSE); - * - * int main(void) - * { - * uint16_t x_center = (X_MAX_ABS - X_MIN_ABS)/2; - * uint16_t y_center = (Y_MAX_ABS - Y_MIN_ABS)/2; - * uint16_t x_screen = 0; - * uint16_t y_screen = 0; - * - * uint32_t x_origin = x_center; - * uint32_t y_origin = y_center; - * uint32_t radius = 5000; - * uint32_t angle = 0; - * - * while (1) - * { - * x_screen = x_origin + cos((double)angle*3.14/180.0)*radius; - * y_screen = y_origin + sin((double)angle*3.14/180.0)*radius; - * - * mouse.move(x_screen, y_screen); - * angle += 3; - * wait(0.01); - * } - * } - * - * @endcode - */ -class USBMouse: public USBHID -{ - public: - - /** - * Constructor - * - * @param mouse_type Mouse type: ABS_MOUSE (absolute mouse) or REL_MOUSE (relative mouse) (default: REL_MOUSE) - * @param vendor_id Your vendor_id (default: 0x1234) - * @param product_id Your product_id (default: 0x0001) - * @param product_release Your preoduct_release (default: 0x0001) - * - */ - USBMouse(MOUSE_TYPE mouse_type = REL_MOUSE, uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0001, uint16_t product_release = 0x0001): - USBHID(0, 0, vendor_id, product_id, product_release, false) - { - button = 0; - this->mouse_type = mouse_type; - connect(); - }; - - /** - * Write a state of the mouse - * - * @param x x-axis position - * @param y y-axis position - * @param buttons buttons state (first bit represents MOUSE_LEFT, second bit MOUSE_RIGHT and third bit MOUSE_MIDDLE) - * @param z wheel state (>0 to scroll down, <0 to scroll up) - * @returns true if there is no error, false otherwise - */ - bool update(int16_t x, int16_t y, uint8_t buttons, int8_t z); - - - /** - * Move the cursor to (x, y) - * - * @param x-axis position - * @param y-axis position - * @returns true if there is no error, false otherwise - */ - bool move(int16_t x, int16_t y); - - /** - * Press one or several buttons - * - * @param button button state (ex: press(MOUSE_LEFT)) - * @returns true if there is no error, false otherwise - */ - bool press(uint8_t button); - - /** - * Release one or several buttons - * - * @param button button state (ex: release(MOUSE_LEFT)) - * @returns true if there is no error, false otherwise - */ - bool release(uint8_t button); - - /** - * Double click (MOUSE_LEFT) - * - * @returns true if there is no error, false otherwise - */ - bool doubleClick(); - - /** - * Click - * - * @param button state of the buttons ( ex: clic(MOUSE_LEFT)) - * @returns true if there is no error, false otherwise - */ - bool click(uint8_t button); - - /** - * Scrolling - * - * @param z value of the wheel (>0 to go down, <0 to go up) - * @returns true if there is no error, false otherwise - */ - bool scroll(int8_t z); - - /* - * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength. - * - * @returns pointer to the report descriptor - */ - virtual uint8_t * reportDesc(); - - protected: - /* - * Get configuration descriptor - * - * @returns pointer to the configuration descriptor - */ - virtual uint8_t * configurationDesc(); - - private: - MOUSE_TYPE mouse_type; - uint8_t button; - bool mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z); -}; - -#endif
--- a/USBHID/USBMouseKeyboard.cpp Wed Feb 20 20:54:28 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,706 +0,0 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License -* -* 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 "stdint.h" -#include "USBMouseKeyboard.h" - -typedef struct { - unsigned char usage; - unsigned char modifier; -} KEYMAP; - -#ifdef US_KEYBOARD -/* US keyboard (as HID standard) */ -#define KEYMAP_SIZE (152) -const KEYMAP keymap[KEYMAP_SIZE] = { - {0, 0}, /* NUL */ - {0, 0}, /* SOH */ - {0, 0}, /* STX */ - {0, 0}, /* ETX */ - {0, 0}, /* EOT */ - {0, 0}, /* ENQ */ - {0, 0}, /* ACK */ - {0, 0}, /* BEL */ - {0x2a, 0}, /* BS */ /* Keyboard Delete (Backspace) */ - {0x2b, 0}, /* TAB */ /* Keyboard Tab */ - {0x28, 0}, /* LF */ /* Keyboard Return (Enter) */ - {0, 0}, /* VT */ - {0, 0}, /* FF */ - {0, 0}, /* CR */ - {0, 0}, /* SO */ - {0, 0}, /* SI */ - {0, 0}, /* DEL */ - {0, 0}, /* DC1 */ - {0, 0}, /* DC2 */ - {0, 0}, /* DC3 */ - {0, 0}, /* DC4 */ - {0, 0}, /* NAK */ - {0, 0}, /* SYN */ - {0, 0}, /* ETB */ - {0, 0}, /* CAN */ - {0, 0}, /* EM */ - {0, 0}, /* SUB */ - {0, 0}, /* ESC */ - {0, 0}, /* FS */ - {0, 0}, /* GS */ - {0, 0}, /* RS */ - {0, 0}, /* US */ - {0x2c, 0}, /* */ - {0x1e, KEY_SHIFT}, /* ! */ - {0x34, KEY_SHIFT}, /* " */ - {0x20, KEY_SHIFT}, /* # */ - {0x21, KEY_SHIFT}, /* $ */ - {0x22, KEY_SHIFT}, /* % */ - {0x24, KEY_SHIFT}, /* & */ - {0x34, 0}, /* ' */ - {0x26, KEY_SHIFT}, /* ( */ - {0x27, KEY_SHIFT}, /* ) */ - {0x25, KEY_SHIFT}, /* * */ - {0x2e, KEY_SHIFT}, /* + */ - {0x36, 0}, /* , */ - {0x2d, 0}, /* - */ - {0x37, 0}, /* . */ - {0x38, 0}, /* / */ - {0x27, 0}, /* 0 */ - {0x1e, 0}, /* 1 */ - {0x1f, 0}, /* 2 */ - {0x20, 0}, /* 3 */ - {0x21, 0}, /* 4 */ - {0x22, 0}, /* 5 */ - {0x23, 0}, /* 6 */ - {0x24, 0}, /* 7 */ - {0x25, 0}, /* 8 */ - {0x26, 0}, /* 9 */ - {0x33, KEY_SHIFT}, /* : */ - {0x33, 0}, /* ; */ - {0x36, KEY_SHIFT}, /* < */ - {0x2e, 0}, /* = */ - {0x37, KEY_SHIFT}, /* > */ - {0x38, KEY_SHIFT}, /* ? */ - {0x1f, KEY_SHIFT}, /* @ */ - {0x04, KEY_SHIFT}, /* A */ - {0x05, KEY_SHIFT}, /* B */ - {0x06, KEY_SHIFT}, /* C */ - {0x07, KEY_SHIFT}, /* D */ - {0x08, KEY_SHIFT}, /* E */ - {0x09, KEY_SHIFT}, /* F */ - {0x0a, KEY_SHIFT}, /* G */ - {0x0b, KEY_SHIFT}, /* H */ - {0x0c, KEY_SHIFT}, /* I */ - {0x0d, KEY_SHIFT}, /* J */ - {0x0e, KEY_SHIFT}, /* K */ - {0x0f, KEY_SHIFT}, /* L */ - {0x10, KEY_SHIFT}, /* M */ - {0x11, KEY_SHIFT}, /* N */ - {0x12, KEY_SHIFT}, /* O */ - {0x13, KEY_SHIFT}, /* P */ - {0x14, KEY_SHIFT}, /* Q */ - {0x15, KEY_SHIFT}, /* R */ - {0x16, KEY_SHIFT}, /* S */ - {0x17, KEY_SHIFT}, /* T */ - {0x18, KEY_SHIFT}, /* U */ - {0x19, KEY_SHIFT}, /* V */ - {0x1a, KEY_SHIFT}, /* W */ - {0x1b, KEY_SHIFT}, /* X */ - {0x1c, KEY_SHIFT}, /* Y */ - {0x1d, KEY_SHIFT}, /* Z */ - {0x2f, 0}, /* [ */ - {0x31, 0}, /* \ */ - {0x30, 0}, /* ] */ - {0x23, KEY_SHIFT}, /* ^ */ - {0x2d, KEY_SHIFT}, /* _ */ - {0x35, 0}, /* ` */ - {0x04, 0}, /* a */ - {0x05, 0}, /* b */ - {0x06, 0}, /* c */ - {0x07, 0}, /* d */ - {0x08, 0}, /* e */ - {0x09, 0}, /* f */ - {0x0a, 0}, /* g */ - {0x0b, 0}, /* h */ - {0x0c, 0}, /* i */ - {0x0d, 0}, /* j */ - {0x0e, 0}, /* k */ - {0x0f, 0}, /* l */ - {0x10, 0}, /* m */ - {0x11, 0}, /* n */ - {0x12, 0}, /* o */ - {0x13, 0}, /* p */ - {0x14, 0}, /* q */ - {0x15, 0}, /* r */ - {0x16, 0}, /* s */ - {0x17, 0}, /* t */ - {0x18, 0}, /* u */ - {0x19, 0}, /* v */ - {0x1a, 0}, /* w */ - {0x1b, 0}, /* x */ - {0x1c, 0}, /* y */ - {0x1d, 0}, /* z */ - {0x2f, KEY_SHIFT}, /* { */ - {0x31, KEY_SHIFT}, /* | */ - {0x30, KEY_SHIFT}, /* } */ - {0x35, KEY_SHIFT}, /* ~ */ - {0,0}, /* DEL */ - - {0x3a, 0}, /* F1 */ - {0x3b, 0}, /* F2 */ - {0x3c, 0}, /* F3 */ - {0x3d, 0}, /* F4 */ - {0x3e, 0}, /* F5 */ - {0x3f, 0}, /* F6 */ - {0x40, 0}, /* F7 */ - {0x41, 0}, /* F8 */ - {0x42, 0}, /* F9 */ - {0x43, 0}, /* F10 */ - {0x44, 0}, /* F11 */ - {0x45, 0}, /* F12 */ - - {0x46, 0}, /* PRINT_SCREEN */ - {0x47, 0}, /* SCROLL_LOCK */ - {0x39, 0}, /* CAPS_LOCK */ - {0x53, 0}, /* NUM_LOCK */ - {0x49, 0}, /* INSERT */ - {0x4a, 0}, /* HOME */ - {0x4b, 0}, /* PAGE_UP */ - {0x4e, 0}, /* PAGE_DOWN */ - - {0x4f, 0}, /* RIGHT_ARROW */ - {0x50, 0}, /* LEFT_ARROW */ - {0x51, 0}, /* DOWN_ARROW */ - {0x52, 0}, /* UP_ARROW */ -}; - -#else -/* UK keyboard */ -#define KEYMAP_SIZE (152) -const KEYMAP keymap[KEYMAP_SIZE] = { - {0, 0}, /* NUL */ - {0, 0}, /* SOH */ - {0, 0}, /* STX */ - {0, 0}, /* ETX */ - {0, 0}, /* EOT */ - {0, 0}, /* ENQ */ - {0, 0}, /* ACK */ - {0, 0}, /* BEL */ - {0x2a, 0}, /* BS */ /* Keyboard Delete (Backspace) */ - {0x2b, 0}, /* TAB */ /* Keyboard Tab */ - {0x28, 0}, /* LF */ /* Keyboard Return (Enter) */ - {0, 0}, /* VT */ - {0, 0}, /* FF */ - {0, 0}, /* CR */ - {0, 0}, /* SO */ - {0, 0}, /* SI */ - {0, 0}, /* DEL */ - {0, 0}, /* DC1 */ - {0, 0}, /* DC2 */ - {0, 0}, /* DC3 */ - {0, 0}, /* DC4 */ - {0, 0}, /* NAK */ - {0, 0}, /* SYN */ - {0, 0}, /* ETB */ - {0, 0}, /* CAN */ - {0, 0}, /* EM */ - {0, 0}, /* SUB */ - {0, 0}, /* ESC */ - {0, 0}, /* FS */ - {0, 0}, /* GS */ - {0, 0}, /* RS */ - {0, 0}, /* US */ - {0x2c, 0}, /* */ - {0x1e, KEY_SHIFT}, /* ! */ - {0x1f, KEY_SHIFT}, /* " */ - {0x32, 0}, /* # */ - {0x21, KEY_SHIFT}, /* $ */ - {0x22, KEY_SHIFT}, /* % */ - {0x24, KEY_SHIFT}, /* & */ - {0x34, 0}, /* ' */ - {0x26, KEY_SHIFT}, /* ( */ - {0x27, KEY_SHIFT}, /* ) */ - {0x25, KEY_SHIFT}, /* * */ - {0x2e, KEY_SHIFT}, /* + */ - {0x36, 0}, /* , */ - {0x2d, 0}, /* - */ - {0x37, 0}, /* . */ - {0x38, 0}, /* / */ - {0x27, 0}, /* 0 */ - {0x1e, 0}, /* 1 */ - {0x1f, 0}, /* 2 */ - {0x20, 0}, /* 3 */ - {0x21, 0}, /* 4 */ - {0x22, 0}, /* 5 */ - {0x23, 0}, /* 6 */ - {0x24, 0}, /* 7 */ - {0x25, 0}, /* 8 */ - {0x26, 0}, /* 9 */ - {0x33, KEY_SHIFT}, /* : */ - {0x33, 0}, /* ; */ - {0x36, KEY_SHIFT}, /* < */ - {0x2e, 0}, /* = */ - {0x37, KEY_SHIFT}, /* > */ - {0x38, KEY_SHIFT}, /* ? */ - {0x34, KEY_SHIFT}, /* @ */ - {0x04, KEY_SHIFT}, /* A */ - {0x05, KEY_SHIFT}, /* B */ - {0x06, KEY_SHIFT}, /* C */ - {0x07, KEY_SHIFT}, /* D */ - {0x08, KEY_SHIFT}, /* E */ - {0x09, KEY_SHIFT}, /* F */ - {0x0a, KEY_SHIFT}, /* G */ - {0x0b, KEY_SHIFT}, /* H */ - {0x0c, KEY_SHIFT}, /* I */ - {0x0d, KEY_SHIFT}, /* J */ - {0x0e, KEY_SHIFT}, /* K */ - {0x0f, KEY_SHIFT}, /* L */ - {0x10, KEY_SHIFT}, /* M */ - {0x11, KEY_SHIFT}, /* N */ - {0x12, KEY_SHIFT}, /* O */ - {0x13, KEY_SHIFT}, /* P */ - {0x14, KEY_SHIFT}, /* Q */ - {0x15, KEY_SHIFT}, /* R */ - {0x16, KEY_SHIFT}, /* S */ - {0x17, KEY_SHIFT}, /* T */ - {0x18, KEY_SHIFT}, /* U */ - {0x19, KEY_SHIFT}, /* V */ - {0x1a, KEY_SHIFT}, /* W */ - {0x1b, KEY_SHIFT}, /* X */ - {0x1c, KEY_SHIFT}, /* Y */ - {0x1d, KEY_SHIFT}, /* Z */ - {0x2f, 0}, /* [ */ - {0x64, 0}, /* \ */ - {0x30, 0}, /* ] */ - {0x23, KEY_SHIFT}, /* ^ */ - {0x2d, KEY_SHIFT}, /* _ */ - {0x35, 0}, /* ` */ - {0x04, 0}, /* a */ - {0x05, 0}, /* b */ - {0x06, 0}, /* c */ - {0x07, 0}, /* d */ - {0x08, 0}, /* e */ - {0x09, 0}, /* f */ - {0x0a, 0}, /* g */ - {0x0b, 0}, /* h */ - {0x0c, 0}, /* i */ - {0x0d, 0}, /* j */ - {0x0e, 0}, /* k */ - {0x0f, 0}, /* l */ - {0x10, 0}, /* m */ - {0x11, 0}, /* n */ - {0x12, 0}, /* o */ - {0x13, 0}, /* p */ - {0x14, 0}, /* q */ - {0x15, 0}, /* r */ - {0x16, 0}, /* s */ - {0x17, 0}, /* t */ - {0x18, 0}, /* u */ - {0x19, 0}, /* v */ - {0x1a, 0}, /* w */ - {0x1b, 0}, /* x */ - {0x1c, 0}, /* y */ - {0x1d, 0}, /* z */ - {0x2f, KEY_SHIFT}, /* { */ - {0x64, KEY_SHIFT}, /* | */ - {0x30, KEY_SHIFT}, /* } */ - {0x32, KEY_SHIFT}, /* ~ */ - {0,0}, /* DEL */ - - {0x3a, 0}, /* F1 */ - {0x3b, 0}, /* F2 */ - {0x3c, 0}, /* F3 */ - {0x3d, 0}, /* F4 */ - {0x3e, 0}, /* F5 */ - {0x3f, 0}, /* F6 */ - {0x40, 0}, /* F7 */ - {0x41, 0}, /* F8 */ - {0x42, 0}, /* F9 */ - {0x43, 0}, /* F10 */ - {0x44, 0}, /* F11 */ - {0x45, 0}, /* F12 */ - - {0x46, 0}, /* PRINT_SCREEN */ - {0x47, 0}, /* SCROLL_LOCK */ - {0x39, 0}, /* CAPS_LOCK */ - {0x53, 0}, /* NUM_LOCK */ - {0x49, 0}, /* INSERT */ - {0x4a, 0}, /* HOME */ - {0x4b, 0}, /* PAGE_UP */ - {0x4e, 0}, /* PAGE_DOWN */ - - {0x4f, 0}, /* RIGHT_ARROW */ - {0x50, 0}, /* LEFT_ARROW */ - {0x51, 0}, /* DOWN_ARROW */ - {0x52, 0}, /* UP_ARROW */ -}; -#endif - - -uint8_t * USBMouseKeyboard::reportDesc() { - if (mouse_type == REL_MOUSE) { - static uint8_t reportDescriptor[] = { - // Keyboard - USAGE_PAGE(1), 0x01, - USAGE(1), 0x06, - COLLECTION(1), 0x01, - REPORT_ID(1), REPORT_ID_KEYBOARD, - USAGE_PAGE(1), 0x07, - USAGE_MINIMUM(1), 0xE0, - USAGE_MAXIMUM(1), 0xE7, - LOGICAL_MINIMUM(1), 0x00, - LOGICAL_MAXIMUM(1), 0x01, - REPORT_SIZE(1), 0x01, - REPORT_COUNT(1), 0x08, - INPUT(1), 0x02, - REPORT_COUNT(1), 0x01, - REPORT_SIZE(1), 0x08, - INPUT(1), 0x01, - REPORT_COUNT(1), 0x05, - REPORT_SIZE(1), 0x01, - USAGE_PAGE(1), 0x08, - USAGE_MINIMUM(1), 0x01, - USAGE_MAXIMUM(1), 0x05, - OUTPUT(1), 0x02, - REPORT_COUNT(1), 0x01, - REPORT_SIZE(1), 0x03, - OUTPUT(1), 0x01, - REPORT_COUNT(1), 0x06, - REPORT_SIZE(1), 0x08, - LOGICAL_MINIMUM(1), 0x00, - LOGICAL_MAXIMUM(2), 0xff, 0x00, - USAGE_PAGE(1), 0x07, - USAGE_MINIMUM(1), 0x00, - USAGE_MAXIMUM(2), 0xff, 0x00, - INPUT(1), 0x00, - END_COLLECTION(0), - - // Mouse - USAGE_PAGE(1), 0x01, // Generic Desktop - USAGE(1), 0x02, // Mouse - COLLECTION(1), 0x01, // Application - USAGE(1), 0x01, // Pointer - COLLECTION(1), 0x00, // Physical - REPORT_ID(1), REPORT_ID_MOUSE, - REPORT_COUNT(1), 0x03, - REPORT_SIZE(1), 0x01, - USAGE_PAGE(1), 0x09, // Buttons - USAGE_MINIMUM(1), 0x1, - USAGE_MAXIMUM(1), 0x3, - LOGICAL_MINIMUM(1), 0x00, - LOGICAL_MAXIMUM(1), 0x01, - INPUT(1), 0x02, - REPORT_COUNT(1), 0x01, - REPORT_SIZE(1), 0x05, - INPUT(1), 0x01, - REPORT_COUNT(1), 0x03, - REPORT_SIZE(1), 0x08, - USAGE_PAGE(1), 0x01, - USAGE(1), 0x30, // X - USAGE(1), 0x31, // Y - USAGE(1), 0x38, // scroll - LOGICAL_MINIMUM(1), 0x81, - LOGICAL_MAXIMUM(1), 0x7f, - INPUT(1), 0x06, - END_COLLECTION(0), - END_COLLECTION(0), - - - // Media Control - USAGE_PAGE(1), 0x0C, - USAGE(1), 0x01, - COLLECTION(1), 0x01, - REPORT_ID(1), REPORT_ID_VOLUME, - USAGE_PAGE(1), 0x0C, - LOGICAL_MINIMUM(1), 0x00, - LOGICAL_MAXIMUM(1), 0x01, - REPORT_SIZE(1), 0x01, - REPORT_COUNT(1), 0x07, - USAGE(1), 0xB5, // Next Track - USAGE(1), 0xB6, // Previous Track - USAGE(1), 0xB7, // Stop - USAGE(1), 0xCD, // Play / Pause - USAGE(1), 0xE2, // Mute - USAGE(1), 0xE9, // Volume Up - USAGE(1), 0xEA, // Volume Down - INPUT(1), 0x02, // Input (Data, Variable, Absolute) - REPORT_COUNT(1), 0x01, - INPUT(1), 0x01, - END_COLLECTION(0), - }; - reportLength = sizeof(reportDescriptor); - return reportDescriptor; - } else if (mouse_type == ABS_MOUSE) { - static uint8_t reportDescriptor[] = { - - // Keyboard - USAGE_PAGE(1), 0x01, - USAGE(1), 0x06, - COLLECTION(1), 0x01, - REPORT_ID(1), REPORT_ID_KEYBOARD, - USAGE_PAGE(1), 0x07, - USAGE_MINIMUM(1), 0xE0, - USAGE_MAXIMUM(1), 0xE7, - LOGICAL_MINIMUM(1), 0x00, - LOGICAL_MAXIMUM(1), 0x01, - REPORT_SIZE(1), 0x01, - REPORT_COUNT(1), 0x08, - INPUT(1), 0x02, - REPORT_COUNT(1), 0x01, - REPORT_SIZE(1), 0x08, - INPUT(1), 0x01, - REPORT_COUNT(1), 0x05, - REPORT_SIZE(1), 0x01, - USAGE_PAGE(1), 0x08, - USAGE_MINIMUM(1), 0x01, - USAGE_MAXIMUM(1), 0x05, - OUTPUT(1), 0x02, - REPORT_COUNT(1), 0x01, - REPORT_SIZE(1), 0x03, - OUTPUT(1), 0x01, - REPORT_COUNT(1), 0x06, - REPORT_SIZE(1), 0x08, - LOGICAL_MINIMUM(1), 0x00, - LOGICAL_MAXIMUM(2), 0xff, 0x00, - USAGE_PAGE(1), 0x07, - USAGE_MINIMUM(1), 0x00, - USAGE_MAXIMUM(2), 0xff, 0x00, - INPUT(1), 0x00, - END_COLLECTION(0), - - // Mouse - USAGE_PAGE(1), 0x01, // Generic Desktop - USAGE(1), 0x02, // Mouse - COLLECTION(1), 0x01, // Application - USAGE(1), 0x01, // Pointer - COLLECTION(1), 0x00, // Physical - REPORT_ID(1), REPORT_ID_MOUSE, - - USAGE_PAGE(1), 0x01, // Generic Desktop - USAGE(1), 0x30, // X - USAGE(1), 0x31, // Y - LOGICAL_MINIMUM(1), 0x00, // 0 - LOGICAL_MAXIMUM(2), 0xff, 0x7f, // 32767 - REPORT_SIZE(1), 0x10, - REPORT_COUNT(1), 0x02, - INPUT(1), 0x02, // Data, Variable, Absolute - - USAGE_PAGE(1), 0x01, // Generic Desktop - USAGE(1), 0x38, // scroll - LOGICAL_MINIMUM(1), 0x81, // -127 - LOGICAL_MAXIMUM(1), 0x7f, // 127 - REPORT_SIZE(1), 0x08, - REPORT_COUNT(1), 0x01, - INPUT(1), 0x06, // Data, Variable, Relative - - USAGE_PAGE(1), 0x09, // Buttons - USAGE_MINIMUM(1), 0x01, - USAGE_MAXIMUM(1), 0x03, - LOGICAL_MINIMUM(1), 0x00, // 0 - LOGICAL_MAXIMUM(1), 0x01, // 1 - REPORT_COUNT(1), 0x03, - REPORT_SIZE(1), 0x01, - INPUT(1), 0x02, // Data, Variable, Absolute - REPORT_COUNT(1), 0x01, - REPORT_SIZE(1), 0x05, - INPUT(1), 0x01, // Constant - - END_COLLECTION(0), - END_COLLECTION(0), - - // Media Control - USAGE_PAGE(1), 0x0C, - USAGE(1), 0x01, - COLLECTION(1), 0x01, - REPORT_ID(1), REPORT_ID_VOLUME, - USAGE_PAGE(1), 0x0C, - LOGICAL_MINIMUM(1), 0x00, - LOGICAL_MAXIMUM(1), 0x01, - REPORT_SIZE(1), 0x01, - REPORT_COUNT(1), 0x07, - USAGE(1), 0xB5, // Next Track - USAGE(1), 0xB6, // Previous Track - USAGE(1), 0xB7, // Stop - USAGE(1), 0xCD, // Play / Pause - USAGE(1), 0xE2, // Mute - USAGE(1), 0xE9, // Volume Up - USAGE(1), 0xEA, // Volume Down - INPUT(1), 0x02, // Input (Data, Variable, Absolute) - REPORT_COUNT(1), 0x01, - INPUT(1), 0x01, - END_COLLECTION(0), - }; - reportLength = sizeof(reportDescriptor); - return reportDescriptor; - } - - return NULL; -} - -bool USBMouseKeyboard::EPINT_OUT_callback() { - uint32_t bytesRead = 0; - uint8_t led[65]; - USBDevice::readEP(EPINT_OUT, led, &bytesRead, MAX_HID_REPORT_SIZE); - - // we take led[1] because led[0] is the report ID - lock_status = led[1] & 0x07; - - // We activate the endpoint to be able to recceive data - if (!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE)) - return false; - return true; -} - -uint8_t USBMouseKeyboard::lockStatus() { - return lock_status; -} - -bool USBMouseKeyboard::update(int16_t x, int16_t y, uint8_t button, int8_t z) { - switch (mouse_type) { - case REL_MOUSE: - while (x > 127) { - if (!mouseSend(127, 0, button, z)) return false; - x = x - 127; - } - while (x < -128) { - if (!mouseSend(-128, 0, button, z)) return false; - x = x + 128; - } - while (y > 127) { - if (!mouseSend(0, 127, button, z)) return false; - y = y - 127; - } - while (y < -128) { - if (!mouseSend(0, -128, button, z)) return false; - y = y + 128; - } - return mouseSend(x, y, button, z); - case ABS_MOUSE: - HID_REPORT report; - - report.data[0] = REPORT_ID_MOUSE; - report.data[1] = x & 0xff; - report.data[2] = (x >> 8) & 0xff; - report.data[3] = y & 0xff; - report.data[4] = (y >> 8) & 0xff; - report.data[5] = -z; - report.data[6] = button & 0x07; - - report.length = 7; - - return send(&report); - default: - return false; - } -} - -bool USBMouseKeyboard::mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z) { - HID_REPORT report; - report.data[0] = REPORT_ID_MOUSE; - report.data[1] = buttons & 0x07; - report.data[2] = x; - report.data[3] = y; - report.data[4] = -z; // >0 to scroll down, <0 to scroll up - - report.length = 5; - - return send(&report); -} - -bool USBMouseKeyboard::move(int16_t x, int16_t y) { - return update(x, y, button, 0); -} - -bool USBMouseKeyboard::scroll(int8_t z) { - return update(0, 0, button, z); -} - -bool USBMouseKeyboard::doubleClick() { - if (!click(MOUSE_LEFT)) - return false; - wait(0.1); - return click(MOUSE_LEFT); -} - -bool USBMouseKeyboard::click(uint8_t button) { - if (!update(0, 0, button, 0)) - return false; - wait(0.01); - return update(0, 0, 0, 0); -} - -bool USBMouseKeyboard::press(uint8_t button_) { - button = button_ & 0x07; - return update(0, 0, button, 0); -} - -bool USBMouseKeyboard::release(uint8_t button_) { - button = (button & (~button_)) & 0x07; - return update(0, 0, button, 0); -} - -int USBMouseKeyboard::_putc(int c) { - return keyCode(c, keymap[c].modifier); -} - -bool USBMouseKeyboard::keyCode(uint8_t key, uint8_t modifier) { - // Send a simulated keyboard keypress. Returns true if successful. - - HID_REPORT report; - - report.data[0] = REPORT_ID_KEYBOARD; - report.data[1] = modifier; - report.data[2] = 0; - report.data[3] = keymap[key].usage; - report.data[4] = 0; - report.data[5] = 0; - report.data[6] = 0; - report.data[7] = 0; - report.data[8] = 0; - - report.length = 9; - - if (!send(&report)) { - return false; - } - - report.data[1] = 0; - report.data[3] = 0; - - if (!send(&report)) { - return false; - } - - return true; - -} - - -bool USBMouseKeyboard::mediaControl(MEDIA_KEY key) { - HID_REPORT report; - - report.data[0] = REPORT_ID_VOLUME; - report.data[1] = (1 << key) & 0x7f; - - report.length = 2; - - send(&report); - - report.data[0] = REPORT_ID_VOLUME; - report.data[1] = 0; - - report.length = 2; - - return send(&report); -}
--- a/USBHID/USBMouseKeyboard.h Wed Feb 20 20:54:28 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,220 +0,0 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License -* -* 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. -*/ - -#ifndef USBMOUSEKEYBOARD_H -#define USBMOUSEKEYBOARD_H - -#define REPORT_ID_KEYBOARD 1 -#define REPORT_ID_MOUSE 2 -#define REPORT_ID_VOLUME 3 - -#include "USBMouse.h" -#include "USBKeyboard.h" -#include "Stream.h" -#include "USBHID.h" - -/** - * USBMouseKeyboard example - * @code - * - * #include "mbed.h" - * #include "USBMouseKeyboard.h" - * - * USBMouseKeyboard key_mouse; - * - * int main(void) - * { - * while(1) - * { - * key_mouse.move(20, 0); - * key_mouse.printf("Hello From MBED\r\n"); - * wait(1); - * } - * } - * @endcode - * - * - * @code - * - * #include "mbed.h" - * #include "USBMouseKeyboard.h" - * - * USBMouseKeyboard key_mouse(ABS_MOUSE); - * - * int main(void) - * { - * while(1) - * { - * key_mouse.move(X_MAX_ABS/2, Y_MAX_ABS/2); - * key_mouse.printf("Hello from MBED\r\n"); - * wait(1); - * } - * } - * @endcode - */ -class USBMouseKeyboard: public USBHID, public Stream -{ - public: - - /** - * Constructor - * - * @param mouse_type Mouse type: ABS_MOUSE (absolute mouse) or REL_MOUSE (relative mouse) (default: REL_MOUSE) - * @param leds Leds bus: first: NUM_LOCK, second: CAPS_LOCK, third: SCROLL_LOCK - * @param vendor_id Your vendor_id (default: 0x1234) - * @param product_id Your product_id (default: 0x0001) - * @param product_release Your preoduct_release (default: 0x0001) - * - */ - USBMouseKeyboard(MOUSE_TYPE mouse_type = REL_MOUSE, uint16_t vendor_id = 0x0021, uint16_t product_id = 0x0011, uint16_t product_release = 0x0001): - USBHID(0, 0, vendor_id, product_id, product_release, false) - { - lock_status = 0; - button = 0; - this->mouse_type = mouse_type; - connect(); - }; - - /** - * Write a state of the mouse - * - * @param x x-axis position - * @param y y-axis position - * @param buttons buttons state (first bit represents MOUSE_LEFT, second bit MOUSE_RIGHT and third bit MOUSE_MIDDLE) - * @param z wheel state (>0 to scroll down, <0 to scroll up) - * @returns true if there is no error, false otherwise - */ - bool update(int16_t x, int16_t y, uint8_t buttons, int8_t z); - - - /** - * Move the cursor to (x, y) - * - * @param x x-axis position - * @param y y-axis position - * @returns true if there is no error, false otherwise - */ - bool move(int16_t x, int16_t y); - - /** - * Press one or several buttons - * - * @param button button state (ex: press(MOUSE_LEFT)) - * @returns true if there is no error, false otherwise - */ - bool press(uint8_t button); - - /** - * Release one or several buttons - * - * @param button button state (ex: release(MOUSE_LEFT)) - * @returns true if there is no error, false otherwise - */ - bool release(uint8_t button); - - /** - * Double click (MOUSE_LEFT) - * - * @returns true if there is no error, false otherwise - */ - bool doubleClick(); - - /** - * Click - * - * @param button state of the buttons ( ex: clic(MOUSE_LEFT)) - * @returns true if there is no error, false otherwise - */ - bool click(uint8_t button); - - /** - * Scrolling - * - * @param z value of the wheel (>0 to go down, <0 to go up) - * @returns true if there is no error, false otherwise - */ - bool scroll(int8_t z); - - /** - * To send a character defined by a modifier(CTRL, SHIFT, ALT) and the key - * - * @code - * //To send CTRL + s (save) - * keyboard.keyCode('s', KEY_CTRL); - * @endcode - * - * @param modifier bit 0: KEY_CTRL, bit 1: KEY_SHIFT, bit 2: KEY_ALT (default: 0) - * @param key character to send - * @returns true if there is no error, false otherwise - */ - bool keyCode(uint8_t key, uint8_t modifier = 0); - - /** - * Send a character - * - * @param c character to be sent - * @returns true if there is no error, false otherwise - */ - virtual int _putc(int c); - - /** - * Control media keys - * - * @param key media key pressed (KEY_NEXT_TRACK, KEY_PREVIOUS_TRACK, KEY_STOP, KEY_PLAY_PAUSE, KEY_MUTE, KEY_VOLUME_UP, KEY_VOLUME_DOWN) - * @returns true if there is no error, false otherwise - */ - bool mediaControl(MEDIA_KEY key); - - /** - * Read status of lock keys. Useful to switch-on/off leds according to key pressed. Only the first three bits of the result is important: - * - First bit: NUM_LOCK - * - Second bit: CAPS_LOCK - * - Third bit: SCROLL_LOCK - * - * @returns status of lock keys - */ - uint8_t lockStatus(); - - /* - * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength. - * - * @returns pointer to the report descriptor - */ - virtual uint8_t * reportDesc(); - - /* - * Called when a data is received on the OUT endpoint. Useful to switch on LED of LOCK keys - * - * @returns if handle by subclass, return true - */ - virtual bool EPINT_OUT_callback(); - - - private: - bool mouseWrite(int8_t x, int8_t y, uint8_t buttons, int8_t z); - MOUSE_TYPE mouse_type; - uint8_t button; - bool mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z); - - uint8_t lock_status; - - //dummy otherwise it doesn't compile (we must define all methods of an abstract class) - virtual int _getc() { return -1;} -}; - -#endif
--- a/USBMSD/USBMSD.cpp Wed Feb 20 20:54:28 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,655 +0,0 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License -* -* 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 "stdint.h" -#include "USBMSD.h" - -#define DISK_OK 0x00 -#define NO_INIT 0x01 -#define NO_DISK 0x02 -#define WRITE_PROTECT 0x04 - -#define CBW_Signature 0x43425355 -#define CSW_Signature 0x53425355 - -// SCSI Commands -#define TEST_UNIT_READY 0x00 -#define REQUEST_SENSE 0x03 -#define FORMAT_UNIT 0x04 -#define INQUIRY 0x12 -#define MODE_SELECT6 0x15 -#define MODE_SENSE6 0x1A -#define START_STOP_UNIT 0x1B -#define MEDIA_REMOVAL 0x1E -#define READ_FORMAT_CAPACITIES 0x23 -#define READ_CAPACITY 0x25 -#define READ10 0x28 -#define WRITE10 0x2A -#define VERIFY10 0x2F -#define READ12 0xA8 -#define WRITE12 0xAA -#define MODE_SELECT10 0x55 -#define MODE_SENSE10 0x5A - -// MSC class specific requests -#define MSC_REQUEST_RESET 0xFF -#define MSC_REQUEST_GET_MAX_LUN 0xFE - -#define DEFAULT_CONFIGURATION (1) - -// max packet size -#define MAX_PACKET MAX_PACKET_SIZE_EPBULK - -// CSW Status -enum Status { - CSW_PASSED, - CSW_FAILED, - CSW_ERROR, -}; - - -USBMSD::USBMSD(uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release) { - stage = READ_CBW; - memset((void *)&cbw, 0, sizeof(CBW)); - memset((void *)&csw, 0, sizeof(CSW)); - page = NULL; -} - -USBMSD::~USBMSD() { - disconnect(); -} - - -// Called in ISR context to process a class specific request -bool USBMSD::USBCallback_request(void) { - - bool success = false; - CONTROL_TRANSFER * transfer = getTransferPtr(); - static uint8_t maxLUN[1] = {0}; - - if (transfer->setup.bmRequestType.Type == CLASS_TYPE) { - switch (transfer->setup.bRequest) { - case MSC_REQUEST_RESET: - reset(); - success = true; - break; - case MSC_REQUEST_GET_MAX_LUN: - transfer->remaining = 1; - transfer->ptr = maxLUN; - transfer->direction = DEVICE_TO_HOST; - success = true; - break; - default: - break; - } - } - - return success; -} - - -bool USBMSD::connect(bool blocking) { - //disk initialization - if (disk_status() & NO_INIT) { - if (disk_initialize()) { - return false; - } - } - - // get number of blocks - BlockCount = disk_sectors(); - - // get memory size - MemorySize = disk_size(); - - if (BlockCount > 0) { - BlockSize = MemorySize / BlockCount; - if (BlockSize != 0) { - free(page); - page = (uint8_t *)malloc(BlockSize * sizeof(uint8_t)); - if (page == NULL) - return false; - } - } else { - return false; - } - - //connect the device - USBDevice::connect(blocking); - return true; -} - -void USBMSD::disconnect() { - USBDevice::disconnect(); - //De-allocate MSD page size: - free(page); - page = NULL; -} - -void USBMSD::reset() { - stage = READ_CBW; -} - - -// Called in ISR context called when a data is received -bool USBMSD::EPBULK_OUT_callback() { - uint32_t size = 0; - uint8_t buf[MAX_PACKET_SIZE_EPBULK]; - readEP(EPBULK_OUT, buf, &size, MAX_PACKET_SIZE_EPBULK); - switch (stage) { - // the device has to decode the CBW received - case READ_CBW: - CBWDecode(buf, size); - break; - - // the device has to receive data from the host - case PROCESS_CBW: - switch (cbw.CB[0]) { - case WRITE10: - case WRITE12: - memoryWrite(buf, size); - break; - case VERIFY10: - memoryVerify(buf, size); - break; - } - break; - - // an error has occured: stall endpoint and send CSW - default: - stallEndpoint(EPBULK_OUT); - csw.Status = CSW_ERROR; - sendCSW(); - break; - } - - //reactivate readings on the OUT bulk endpoint - readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); - return true; -} - -// Called in ISR context when a data has been transferred -bool USBMSD::EPBULK_IN_callback() { - switch (stage) { - - // the device has to send data to the host - case PROCESS_CBW: - switch (cbw.CB[0]) { - case READ10: - case READ12: - memoryRead(); - break; - } - break; - - //the device has to send a CSW - case SEND_CSW: - sendCSW(); - break; - - // the host has received the CSW -> we wait a CBW - case WAIT_CSW: - stage = READ_CBW; - break; - - // an error has occured - default: - stallEndpoint(EPBULK_IN); - sendCSW(); - break; - } - return true; -} - - -void USBMSD::memoryWrite (uint8_t * buf, uint16_t size) { - - if ((addr + size) > MemorySize) { - size = MemorySize - addr; - stage = ERROR; - stallEndpoint(EPBULK_OUT); - } - - // we fill an array in RAM of 1 block before writing it in memory - for (int i = 0; i < size; i++) - page[addr%BlockSize + i] = buf[i]; - - // if the array is filled, write it in memory - if (!((addr + size)%BlockSize)) { - if (!(disk_status() & WRITE_PROTECT)) { - disk_write(page, addr/BlockSize, 1); - } - } - - addr += size; - length -= size; - csw.DataResidue -= size; - - if ((!length) || (stage != PROCESS_CBW)) { - csw.Status = (stage == ERROR) ? CSW_FAILED : CSW_PASSED; - sendCSW(); - } -} - -void USBMSD::memoryVerify (uint8_t * buf, uint16_t size) { - uint32_t n; - - if ((addr + size) > MemorySize) { - size = MemorySize - addr; - stage = ERROR; - stallEndpoint(EPBULK_OUT); - } - - // beginning of a new block -> load a whole block in RAM - if (!(addr%BlockSize)) - disk_read(page, addr/BlockSize, 1); - - // info are in RAM -> no need to re-read memory - for (n = 0; n < size; n++) { - if (page[addr%BlockSize + n] != buf[n]) { - memOK = false; - break; - } - } - - addr += size; - length -= size; - csw.DataResidue -= size; - - if ( !length || (stage != PROCESS_CBW)) { - csw.Status = (memOK && (stage == PROCESS_CBW)) ? CSW_PASSED : CSW_FAILED; - sendCSW(); - } -} - - -bool USBMSD::inquiryRequest (void) { - uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01, - 36 - 4, 0x80, 0x00, 0x00, - 'M', 'B', 'E', 'D', '.', 'O', 'R', 'G', - 'M', 'B', 'E', 'D', ' ', 'U', 'S', 'B', ' ', 'D', 'I', 'S', 'K', ' ', ' ', ' ', - '1', '.', '0', ' ', - }; - if (!write(inquiry, sizeof(inquiry))) { - return false; - } - return true; -} - - -bool USBMSD::readFormatCapacity() { - uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08, - (uint8_t)((BlockCount >> 24) & 0xff), - (uint8_t)((BlockCount >> 16) & 0xff), - (uint8_t)((BlockCount >> 8) & 0xff), - (uint8_t)((BlockCount >> 0) & 0xff), - - 0x02, - (uint8_t)((BlockSize >> 16) & 0xff), - (uint8_t)((BlockSize >> 8) & 0xff), - (uint8_t)((BlockSize >> 0) & 0xff), - }; - if (!write(capacity, sizeof(capacity))) { - return false; - } - return true; -} - - -bool USBMSD::readCapacity (void) { - uint8_t capacity[] = { - (uint8_t)(((BlockCount - 1) >> 24) & 0xff), - (uint8_t)(((BlockCount - 1) >> 16) & 0xff), - (uint8_t)(((BlockCount - 1) >> 8) & 0xff), - (uint8_t)(((BlockCount - 1) >> 0) & 0xff), - - (uint8_t)((BlockSize >> 24) & 0xff), - (uint8_t)((BlockSize >> 16) & 0xff), - (uint8_t)((BlockSize >> 8) & 0xff), - (uint8_t)((BlockSize >> 0) & 0xff), - }; - if (!write(capacity, sizeof(capacity))) { - return false; - } - return true; -} - -bool USBMSD::write (uint8_t * buf, uint16_t size) { - - if (size >= cbw.DataLength) { - size = cbw.DataLength; - } - stage = SEND_CSW; - - if (!writeNB(EPBULK_IN, buf, size, MAX_PACKET_SIZE_EPBULK)) { - return false; - } - - csw.DataResidue -= size; - csw.Status = CSW_PASSED; - return true; -} - - -bool USBMSD::modeSense6 (void) { - uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 }; - if (!write(sense6, sizeof(sense6))) { - return false; - } - return true; -} - -void USBMSD::sendCSW() { - csw.Signature = CSW_Signature; - writeNB(EPBULK_IN, (uint8_t *)&csw, sizeof(CSW), MAX_PACKET_SIZE_EPBULK); - stage = WAIT_CSW; -} - -bool USBMSD::requestSense (void) { - uint8_t request_sense[] = { - 0x70, - 0x00, - 0x05, // Sense Key: illegal request - 0x00, - 0x00, - 0x00, - 0x00, - 0x0A, - 0x00, - 0x00, - 0x00, - 0x00, - 0x30, - 0x01, - 0x00, - 0x00, - 0x00, - 0x00, - }; - - if (!write(request_sense, sizeof(request_sense))) { - return false; - } - - return true; -} - -void USBMSD::fail() { - csw.Status = CSW_FAILED; - sendCSW(); -} - - -void USBMSD::CBWDecode(uint8_t * buf, uint16_t size) { - if (size == sizeof(cbw)) { - memcpy((uint8_t *)&cbw, buf, size); - if (cbw.Signature == CBW_Signature) { - csw.Tag = cbw.Tag; - csw.DataResidue = cbw.DataLength; - if ((cbw.CBLength < 1) || (cbw.CBLength > 16) ) { - fail(); - } else { - switch (cbw.CB[0]) { - case TEST_UNIT_READY: - testUnitReady(); - break; - case REQUEST_SENSE: - requestSense(); - break; - case INQUIRY: - inquiryRequest(); - break; - case MODE_SENSE6: - modeSense6(); - break; - case READ_FORMAT_CAPACITIES: - readFormatCapacity(); - break; - case READ_CAPACITY: - readCapacity(); - break; - case READ10: - case READ12: - if (infoTransfer()) { - if ((cbw.Flags & 0x80)) { - stage = PROCESS_CBW; - memoryRead(); - } else { - stallEndpoint(EPBULK_OUT); - csw.Status = CSW_ERROR; - sendCSW(); - } - } - break; - case WRITE10: - case WRITE12: - if (infoTransfer()) { - if (!(cbw.Flags & 0x80)) { - stage = PROCESS_CBW; - } else { - stallEndpoint(EPBULK_IN); - csw.Status = CSW_ERROR; - sendCSW(); - } - } - break; - case VERIFY10: - if (!(cbw.CB[1] & 0x02)) { - csw.Status = CSW_PASSED; - sendCSW(); - break; - } - if (infoTransfer()) { - if (!(cbw.Flags & 0x80)) { - stage = PROCESS_CBW; - memOK = true; - } else { - stallEndpoint(EPBULK_IN); - csw.Status = CSW_ERROR; - sendCSW(); - } - } - break; - case MEDIA_REMOVAL: - csw.Status = CSW_PASSED; - sendCSW(); - break; - default: - fail(); - break; - } - } - } - } -} - -void USBMSD::testUnitReady (void) { - - if (cbw.DataLength != 0) { - if ((cbw.Flags & 0x80) != 0) { - stallEndpoint(EPBULK_IN); - } else { - stallEndpoint(EPBULK_OUT); - } - } - - csw.Status = CSW_PASSED; - sendCSW(); -} - - -void USBMSD::memoryRead (void) { - uint32_t n; - - n = (length > MAX_PACKET) ? MAX_PACKET : length; - - if ((addr + n) > MemorySize) { - n = MemorySize - addr; - stage = ERROR; - } - - // we read an entire block - if (!(addr%BlockSize)) - disk_read(page, addr/BlockSize, 1); - - // write data which are in RAM - writeNB(EPBULK_IN, &page[addr%BlockSize], n, MAX_PACKET_SIZE_EPBULK); - - addr += n; - length -= n; - - csw.DataResidue -= n; - - if ( !length || (stage != PROCESS_CBW)) { - csw.Status = (stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED; - stage = (stage == PROCESS_CBW) ? SEND_CSW : stage; - } -} - - -bool USBMSD::infoTransfer (void) { - uint32_t n; - - // Logical Block Address of First Block - n = (cbw.CB[2] << 24) | (cbw.CB[3] << 16) | (cbw.CB[4] << 8) | (cbw.CB[5] << 0); - - addr = n * BlockSize; - - // Number of Blocks to transfer - switch (cbw.CB[0]) { - case READ10: - case WRITE10: - case VERIFY10: - n = (cbw.CB[7] << 8) | (cbw.CB[8] << 0); - break; - - case READ12: - case WRITE12: - n = (cbw.CB[6] << 24) | (cbw.CB[7] << 16) | (cbw.CB[8] << 8) | (cbw.CB[9] << 0); - break; - } - - length = n * BlockSize; - - if (!cbw.DataLength) { // host requests no data - csw.Status = CSW_FAILED; - sendCSW(); - return false; - } - - if (cbw.DataLength != length) { - if ((cbw.Flags & 0x80) != 0) { - stallEndpoint(EPBULK_IN); - } else { - stallEndpoint(EPBULK_OUT); - } - - csw.Status = CSW_FAILED; - sendCSW(); - return false; - } - - return true; -} - - - - - -// Called in ISR context -// Set configuration. Return false if the -// configuration is not supported. -bool USBMSD::USBCallback_setConfiguration(uint8_t configuration) { - if (configuration != DEFAULT_CONFIGURATION) { - return false; - } - - // Configure endpoints > 0 - addEndpoint(EPBULK_IN, MAX_PACKET_SIZE_EPBULK); - addEndpoint(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); - - //activate readings - readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); - return true; -} - - -uint8_t * USBMSD::stringIinterfaceDesc() { - static uint8_t stringIinterfaceDescriptor[] = { - 0x08, //bLength - STRING_DESCRIPTOR, //bDescriptorType 0x03 - 'M',0,'S',0,'D',0 //bString iInterface - MSD - }; - return stringIinterfaceDescriptor; -} - -uint8_t * USBMSD::stringIproductDesc() { - static uint8_t stringIproductDescriptor[] = { - 0x12, //bLength - STRING_DESCRIPTOR, //bDescriptorType 0x03 - 'M',0,'b',0,'e',0,'d',0,' ',0,'M',0,'S',0,'D',0 //bString iProduct - Mbed Audio - }; - return stringIproductDescriptor; -} - - -uint8_t * USBMSD::configurationDesc() { - static uint8_t configDescriptor[] = { - - // Configuration 1 - 9, // bLength - 2, // bDescriptorType - LSB(9 + 9 + 7 + 7), // wTotalLength - MSB(9 + 9 + 7 + 7), - 0x01, // bNumInterfaces - 0x01, // bConfigurationValue: 0x01 is used to select this configuration - 0x00, // iConfiguration: no string to describe this configuration - 0xC0, // bmAttributes - 100, // bMaxPower, device power consumption is 100 mA - - // Interface 0, Alternate Setting 0, MSC Class - 9, // bLength - 4, // bDescriptorType - 0x00, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x02, // bNumEndpoints - 0x08, // bInterfaceClass - 0x06, // bInterfaceSubClass - 0x50, // bInterfaceProtocol - 0x04, // iInterface - - // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 - 7, // bLength - 5, // bDescriptorType - PHY_TO_DESC(EPBULK_IN), // bEndpointAddress - 0x02, // bmAttributes (0x02=bulk) - LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) - 0, // bInterval - - // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 - 7, // bLength - 5, // bDescriptorType - PHY_TO_DESC(EPBULK_OUT), // bEndpointAddress - 0x02, // bmAttributes (0x02=bulk) - LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) - 0 // bInterval - }; - return configDescriptor; -}
--- a/USBMSD/USBMSD.h Wed Feb 20 20:54:28 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,251 +0,0 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License -* -* 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. -*/ - - -#ifndef USBMSD_H -#define USBMSD_H - -/* These headers are included for child class. */ -#include "USBEndpoints.h" -#include "USBDescriptor.h" -#include "USBDevice_Types.h" - -#include "USBDevice.h" - -/** - * USBMSD class: generic class in order to use all kinds of blocks storage chip - * - * Introduction - * - * The USBMSD implements the MSD protocol. It permits to access a memory chip (flash, sdcard,...) - * from a computer over USB. But this class doesn't work standalone, you need to subclass this class - * and define virtual functions which are called in USBMSD. - * - * How to use this class with your chip ? - * - * You have to inherit and define some pure virtual functions (mandatory step): - * - virtual int disk_read(char * data, int block): function to read a block - * - virtual int disk_write(const char * data, int block): function to write a block - * - virtual int disk_initialize(): function to initialize the memory - * - virtual int disk_sectors(): return the number of blocks - * - virtual int disk_size(): return the memory size - * - virtual int disk_status(): return the status of the storage chip (0: OK, 1: not initialized, 2: no medium in the drive, 4: write protection) - * - * All functions names are compatible with the fat filesystem library. So you can imagine using your own class with - * USBMSD and the fat filesystem library in the same program. Just be careful because there are two different parts which - * will access the sd card. You can do a master/slave system using the disk_status method. - * - * Once these functions defined, you can call connect() (at the end of the constructor of your class for instance) - * of USBMSD to connect your mass storage device. connect() will first call disk_status() to test the status of the disk. - * If disk_status() returns 1 (disk not initialized), then disk_initialize() is called. After this step, connect() will collect information - * such as the number of blocks and the memory size. - */ -class USBMSD: public USBDevice { -public: - - /** - * Constructor - * - * @param vendor_id Your vendor_id - * @param product_id Your product_id - * @param product_release Your preoduct_release - */ - USBMSD(uint16_t vendor_id = 0x0703, uint16_t product_id = 0x0104, uint16_t product_release = 0x0001); - - /** - * Connect the USB MSD device. Establish disk initialization before really connect the device. - * - * @param blocking if not configured - * @returns true if successful - */ - bool connect(bool blocking = true); - - /** - * Disconnect the USB MSD device. - */ - void disconnect(); - - /** - * Destructor - */ - ~USBMSD(); - -protected: - - /* - * read one or more blocks on a storage chip - * - * @param data pointer where will be stored read data - * @param block starting block number - * @param count number of blocks to read - * @returns 0 if successful - */ - virtual int disk_read(uint8_t* data, uint64_t block, uint8_t count) = 0; - - /* - * write one or more blocks on a storage chip - * - * @param data data to write - * @param block starting block number - * @param count number of blocks to write - * @returns 0 if successful - */ - virtual int disk_write(const uint8_t* data, uint64_t block, uint8_t count) = 0; - - /* - * Disk initilization - */ - virtual int disk_initialize() = 0; - - /* - * Return the number of blocks - * - * @returns number of blocks - */ - virtual uint64_t disk_sectors() = 0; - - /* - * Return memory size - * - * @returns memory size - */ - virtual uint64_t disk_size() = 0; - - - /* - * To check the status of the storage chip - * - * @returns status: 0: OK, 1: disk not initialized, 2: no medium in the drive, 4: write protected - */ - virtual int disk_status() = 0; - - /* - * Get string product descriptor - * - * @returns pointer to the string product descriptor - */ - virtual uint8_t * stringIproductDesc(); - - /* - * Get string interface descriptor - * - * @returns pointer to the string interface descriptor - */ - virtual uint8_t * stringIinterfaceDesc(); - - /* - * Get configuration descriptor - * - * @returns pointer to the configuration descriptor - */ - virtual uint8_t * configurationDesc(); - - /* - * Callback called when a packet is received - */ - virtual bool EPBULK_OUT_callback(); - - /* - * Callback called when a packet has been sent - */ - virtual bool EPBULK_IN_callback(); - - /* - * Set configuration of device. Add endpoints - */ - virtual bool USBCallback_setConfiguration(uint8_t configuration); - - /* - * Callback called to process class specific requests - */ - virtual bool USBCallback_request(); - - -private: - - // MSC Bulk-only Stage - enum Stage { - READ_CBW, // wait a CBW - ERROR, // error - PROCESS_CBW, // process a CBW request - SEND_CSW, // send a CSW - WAIT_CSW, // wait that a CSW has been effectively sent - }; - - // Bulk-only CBW - typedef struct { - uint32_t Signature; - uint32_t Tag; - uint32_t DataLength; - uint8_t Flags; - uint8_t LUN; - uint8_t CBLength; - uint8_t CB[16]; - } PACKED CBW; - - // Bulk-only CSW - typedef struct { - uint32_t Signature; - uint32_t Tag; - uint32_t DataResidue; - uint8_t Status; - } PACKED CSW; - - //state of the bulk-only state machine - Stage stage; - - // current CBW - CBW cbw; - - // CSW which will be sent - CSW csw; - - // addr where will be read or written data - uint32_t addr; - - // length of a reading or writing - uint32_t length; - - // memory OK (after a memoryVerify) - bool memOK; - - // cache in RAM before writing in memory. Useful also to read a block. - uint8_t * page; - - int BlockSize; - uint64_t MemorySize; - uint64_t BlockCount; - - void CBWDecode(uint8_t * buf, uint16_t size); - void sendCSW (void); - bool inquiryRequest (void); - bool write (uint8_t * buf, uint16_t size); - bool readFormatCapacity(); - bool readCapacity (void); - bool infoTransfer (void); - void memoryRead (void); - bool modeSense6 (void); - void testUnitReady (void); - bool requestSense (void); - void memoryVerify (uint8_t * buf, uint16_t size); - void memoryWrite (uint8_t * buf, uint16_t size); - void reset(); - void fail(); -}; - -#endif