mirror of https://github.com/ARMmbed/mbed-os.git
Update USBHID and USBKeyboard
Update and the USB classes USBHID and USBKeyboard from the unsupported folder.usb_keyboard
parent
9a4eefc1e9
commit
aa5b53358a
|
@ -0,0 +1,493 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "stdint.h"
|
||||
#include "USBHID.h"
|
||||
#include "EndpointResolver.h"
|
||||
|
||||
class USBHID::AsyncSend: public AsyncOp {
|
||||
public:
|
||||
AsyncSend(const HID_REPORT *report): AsyncOp(NULL), report(report), result(false)
|
||||
{
|
||||
|
||||
}
|
||||
const HID_REPORT *report;
|
||||
bool result;
|
||||
};
|
||||
|
||||
class USBHID::AsyncRead: public AsyncOp {
|
||||
public:
|
||||
AsyncRead(HID_REPORT *report): AsyncOp(NULL), report(report), result(false)
|
||||
{
|
||||
|
||||
}
|
||||
HID_REPORT *report;
|
||||
bool result;
|
||||
};
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
_init(output_report_length, input_report_length, connect);
|
||||
}
|
||||
|
||||
USBHID::USBHID(USBPhy *phy, 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(phy, vendor_id, product_id, product_release)
|
||||
{
|
||||
_init(output_report_length, input_report_length, connect);
|
||||
}
|
||||
|
||||
void USBHID::_init(uint8_t output_report_length, uint8_t input_report_length, bool connect)
|
||||
{
|
||||
EndpointResolver resolver(endpoint_table());
|
||||
|
||||
resolver.endpoint_ctrl(64);
|
||||
_int_in = resolver.endpoint_in(USB_EP_TYPE_INT, MAX_HID_REPORT_SIZE);
|
||||
_int_out = resolver.endpoint_out(USB_EP_TYPE_INT, MAX_HID_REPORT_SIZE);
|
||||
MBED_ASSERT(resolver.valid());
|
||||
|
||||
_send_idle = true;
|
||||
_read_idle = true;
|
||||
_output_length = output_report_length;
|
||||
_input_length = input_report_length;
|
||||
init();
|
||||
if (connect) {
|
||||
USBDevice::connect();
|
||||
}
|
||||
}
|
||||
|
||||
void USBHID::wait_connected()
|
||||
{
|
||||
lock();
|
||||
|
||||
AsyncOp wait_op(NULL);
|
||||
wait_op.start(&_connect_list);
|
||||
if (configured()) {
|
||||
wait_op.complete();
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
wait_op.wait();
|
||||
}
|
||||
|
||||
|
||||
bool USBHID::send(const HID_REPORT *report)
|
||||
{
|
||||
lock();
|
||||
|
||||
if (!configured()) {
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (send_nb(report)) {
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
AsyncSend send_op(report);
|
||||
send_op.start(&_send_list);
|
||||
|
||||
unlock();
|
||||
|
||||
send_op.wait();
|
||||
|
||||
return send_op.result;
|
||||
}
|
||||
|
||||
bool USBHID::send_nb(const HID_REPORT *report)
|
||||
{
|
||||
lock();
|
||||
|
||||
if (!configured()) {
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
if (_send_idle) {
|
||||
memcpy(&_input_report, report, sizeof(_input_report));
|
||||
write_start(_int_in, _input_report.data, _input_report.length);
|
||||
_send_idle = false;
|
||||
success = true;
|
||||
}
|
||||
|
||||
unlock();
|
||||
return success;
|
||||
}
|
||||
|
||||
bool USBHID::read(HID_REPORT *report)
|
||||
{
|
||||
lock();
|
||||
|
||||
if (!configured()) {
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (read_nb(report)) {
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
AsyncRead read_op(report);
|
||||
read_op.start(&_read_list);
|
||||
|
||||
unlock();
|
||||
|
||||
read_op.wait();
|
||||
|
||||
return read_op.result;
|
||||
}
|
||||
|
||||
|
||||
bool USBHID::read_nb(HID_REPORT *report)
|
||||
{
|
||||
lock();
|
||||
|
||||
if (!configured()) {
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
if (_read_idle) {
|
||||
memcpy(report, &_output_report, sizeof(_output_report));
|
||||
read_start(_int_out, _output_report.data, MAX_HID_REPORT_SIZE);
|
||||
_read_idle = false;
|
||||
success = true;
|
||||
}
|
||||
|
||||
unlock();
|
||||
return success;
|
||||
}
|
||||
|
||||
void USBHID::_send_isr(usb_ep_t endpoint)
|
||||
{
|
||||
assert_locked();
|
||||
|
||||
write_finish(_int_in);
|
||||
_send_idle = true;
|
||||
|
||||
AsyncSend *send_op = _send_list.head();
|
||||
if (send_op != NULL) {
|
||||
if (send_nb(send_op->report)) {
|
||||
send_op->result = true;
|
||||
send_op->complete();
|
||||
}
|
||||
} else {
|
||||
report_tx();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void USBHID::_read_isr(usb_ep_t endpoint)
|
||||
{
|
||||
assert_locked();
|
||||
|
||||
_output_report.length = read_finish(_int_out);
|
||||
_read_idle = true;
|
||||
|
||||
AsyncRead *read_op = _read_list.head();
|
||||
if (read_op != NULL) {
|
||||
if (read_nb(read_op->report)) {
|
||||
read_op->result = true;
|
||||
read_op->complete();
|
||||
}
|
||||
} else {
|
||||
report_rx();
|
||||
}
|
||||
}
|
||||
|
||||
void USBHID::_connect_wake_all()
|
||||
{
|
||||
assert_locked();
|
||||
|
||||
AsyncOp *wait_op = _connect_list.head();
|
||||
while (wait_op != NULL) {
|
||||
wait_op->complete();
|
||||
wait_op = _connect_list.head();
|
||||
}
|
||||
}
|
||||
|
||||
void USBHID::_send_abort_all()
|
||||
{
|
||||
assert_locked();
|
||||
|
||||
if (!_send_idle) {
|
||||
endpoint_abort(_int_in);
|
||||
_send_idle = true;
|
||||
}
|
||||
AsyncSend *tx_cur = _send_list.head();
|
||||
while (tx_cur != NULL) {
|
||||
tx_cur->result = false;
|
||||
tx_cur->complete();
|
||||
tx_cur = _send_list.head();
|
||||
}
|
||||
}
|
||||
|
||||
void USBHID::_read_abort_all()
|
||||
{
|
||||
assert_locked();
|
||||
|
||||
if (!_read_idle) {
|
||||
endpoint_abort(_int_out);
|
||||
_read_idle = true;
|
||||
}
|
||||
AsyncRead *rx_cur = _read_list.head();
|
||||
while (rx_cur != NULL) {
|
||||
rx_cur->result = false;
|
||||
rx_cur->complete();
|
||||
rx_cur = _read_list.head();
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t USBHID::report_desc_length()
|
||||
{
|
||||
report_desc();
|
||||
return reportLength;
|
||||
}
|
||||
|
||||
|
||||
void USBHID::callback_state_change(DeviceState new_state)
|
||||
{
|
||||
if (new_state == Configured) {
|
||||
_connect_wake_all();
|
||||
} else {
|
||||
_send_abort_all();
|
||||
_read_abort_all();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 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
|
||||
void USBHID::callback_request(const setup_packet_t *setup)
|
||||
{
|
||||
uint8_t *hidDescriptor;
|
||||
RequestResult result = PassThrough;
|
||||
uint8_t *data = NULL;
|
||||
uint32_t size = 0;
|
||||
|
||||
// Process additional standard requests
|
||||
|
||||
if ((setup->bmRequestType.Type == STANDARD_TYPE)) {
|
||||
switch (setup->bRequest) {
|
||||
case GET_DESCRIPTOR:
|
||||
switch (DESCRIPTOR_TYPE(setup->wValue)) {
|
||||
case REPORT_DESCRIPTOR:
|
||||
if ((report_desc() != NULL) \
|
||||
&& (report_desc_length() != 0)) {
|
||||
size = report_desc_length();
|
||||
data = (uint8_t *)report_desc();
|
||||
result = Send;
|
||||
}
|
||||
break;
|
||||
case HID_DESCRIPTOR:
|
||||
// Find the HID descriptor, after the configuration descriptor
|
||||
hidDescriptor = find_descriptor(HID_DESCRIPTOR);
|
||||
if (hidDescriptor != NULL) {
|
||||
size = HID_DESCRIPTOR_LENGTH;
|
||||
data = hidDescriptor;
|
||||
result = Send;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Process class-specific requests
|
||||
|
||||
if (setup->bmRequestType.Type == CLASS_TYPE) {
|
||||
switch (setup->bRequest) {
|
||||
case SET_REPORT:
|
||||
// First byte will be used for report ID
|
||||
_output_report.data[0] = setup->wValue & 0xff;
|
||||
_output_report.length = setup->wLength + 1;
|
||||
|
||||
size = sizeof(_output_report.data) - 1;
|
||||
data = &_output_report.data[1];
|
||||
result = Send;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
complete_request(result, data, size);
|
||||
}
|
||||
|
||||
void USBHID::callback_request_xfer_done(const setup_packet_t *setup, bool aborted)
|
||||
{
|
||||
(void)aborted;
|
||||
complete_request_xfer_done(true);
|
||||
}
|
||||
|
||||
|
||||
#define DEFAULT_CONFIGURATION (1)
|
||||
|
||||
|
||||
// Called in ISR context
|
||||
// Set configuration. Return false if the
|
||||
// configuration is not supported
|
||||
void USBHID::callback_set_configuration(uint8_t configuration)
|
||||
{
|
||||
if (configuration == DEFAULT_CONFIGURATION) {
|
||||
complete_set_configuration(false);
|
||||
}
|
||||
|
||||
// Configure endpoints > 0
|
||||
endpoint_add(_int_in, MAX_HID_REPORT_SIZE, USB_EP_TYPE_INT, &USBHID::_send_isr);
|
||||
endpoint_add(_int_out, MAX_HID_REPORT_SIZE, USB_EP_TYPE_INT, &USBHID::_read_isr);
|
||||
|
||||
// We activate the endpoint to be able to recceive data
|
||||
read_start(_int_out, (uint8_t*)&_output_report, MAX_HID_REPORT_SIZE);
|
||||
_read_idle = false;
|
||||
|
||||
|
||||
complete_set_configuration(true);
|
||||
}
|
||||
|
||||
void USBHID::callback_set_interface(uint16_t interface, uint8_t alternate)
|
||||
{
|
||||
assert_locked();
|
||||
complete_set_interface(true);
|
||||
}
|
||||
|
||||
|
||||
const uint8_t *USBHID::string_iinterface_desc()
|
||||
{
|
||||
static const uint8_t stringIinterfaceDescriptor[] = {
|
||||
0x08, //bLength
|
||||
STRING_DESCRIPTOR, //bDescriptorType 0x03
|
||||
'H', 0, 'I', 0, 'D', 0, //bString iInterface - HID
|
||||
};
|
||||
return stringIinterfaceDescriptor;
|
||||
}
|
||||
|
||||
const uint8_t *USBHID::string_iproduct_desc()
|
||||
{
|
||||
static const 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const uint8_t *USBHID::report_desc()
|
||||
{
|
||||
uint8_t reportDescriptorTemp[] = {
|
||||
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);
|
||||
MBED_ASSERT(sizeof(reportDescriptorTemp) == sizeof(reportDescriptor));
|
||||
memcpy(reportDescriptor, reportDescriptorTemp, 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))
|
||||
|
||||
const uint8_t *USBHID::configuration_desc()
|
||||
{
|
||||
uint8_t configurationDescriptorTemp[] = {
|
||||
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(report_desc_length())), // wDescriptorLength (LSB)
|
||||
(uint8_t)(MSB(report_desc_length())), // wDescriptorLength (MSB)
|
||||
|
||||
ENDPOINT_DESCRIPTOR_LENGTH, // bLength
|
||||
ENDPOINT_DESCRIPTOR, // bDescriptorType
|
||||
_int_in, // bEndpointAddress
|
||||
E_INTERRUPT, // bmAttributes
|
||||
LSB(MAX_HID_REPORT_SIZE), // wMaxPacketSize (LSB)
|
||||
MSB(MAX_HID_REPORT_SIZE), // wMaxPacketSize (MSB)
|
||||
1, // bInterval (milliseconds)
|
||||
|
||||
ENDPOINT_DESCRIPTOR_LENGTH, // bLength
|
||||
ENDPOINT_DESCRIPTOR, // bDescriptorType
|
||||
_int_out, // bEndpointAddress
|
||||
E_INTERRUPT, // bmAttributes
|
||||
LSB(MAX_HID_REPORT_SIZE), // wMaxPacketSize (LSB)
|
||||
MSB(MAX_HID_REPORT_SIZE), // wMaxPacketSize (MSB)
|
||||
1, // bInterval (milliseconds)
|
||||
};
|
||||
MBED_ASSERT(sizeof(configurationDescriptorTemp) == sizeof(_configuration_descriptor));
|
||||
memcpy(_configuration_descriptor, configurationDescriptorTemp, sizeof(_configuration_descriptor));
|
||||
return _configuration_descriptor;
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef USB_HID_H
|
||||
#define USB_HID_H
|
||||
|
||||
/* These headers are included for child class. */
|
||||
#include "USBDescriptor.h"
|
||||
#include "USBDevice.h"
|
||||
|
||||
#include "USBHID_Types.h"
|
||||
#include "AsyncOp.h"
|
||||
#include "LinkedList.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);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param phy USBPhy to use as the backend
|
||||
* @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(USBPhy *phy, uint8_t output_report_length, uint8_t input_report_length, uint16_t vendor_id, uint16_t product_id, uint16_t product_release, bool connect);
|
||||
|
||||
/**
|
||||
* Block until this HID device is configured
|
||||
*/
|
||||
void wait_connected();
|
||||
|
||||
/**
|
||||
* 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(const 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 send_nb(const 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 read_nb(HID_REPORT *report);
|
||||
|
||||
protected:
|
||||
uint16_t reportLength;
|
||||
uint8_t reportDescriptor[27];
|
||||
|
||||
/*
|
||||
* Get the Report descriptor
|
||||
*
|
||||
* @returns pointer to the report descriptor
|
||||
*/
|
||||
virtual const uint8_t *report_desc();
|
||||
|
||||
/*
|
||||
* Get the length of the report descriptor
|
||||
*
|
||||
* @returns the length of the report descriptor
|
||||
*/
|
||||
virtual uint16_t report_desc_length();
|
||||
|
||||
/*
|
||||
* Get string product descriptor
|
||||
*
|
||||
* @returns pointer to the string product descriptor
|
||||
*/
|
||||
virtual const uint8_t *string_iproduct_desc();
|
||||
|
||||
/*
|
||||
* Get string interface descriptor
|
||||
*
|
||||
* @returns pointer to the string interface descriptor
|
||||
*/
|
||||
virtual const uint8_t *string_iinterface_desc();
|
||||
|
||||
/*
|
||||
* Get configuration descriptor
|
||||
*
|
||||
* @returns pointer to the configuration descriptor
|
||||
*/
|
||||
virtual const uint8_t *configuration_desc();
|
||||
|
||||
|
||||
/*
|
||||
* 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 when USB changes state
|
||||
*
|
||||
* @param new_state The new state of the USBDevice
|
||||
*
|
||||
* Warning: Called in ISR context
|
||||
*/
|
||||
virtual void callback_state_change(DeviceState new_state);
|
||||
|
||||
/*
|
||||
* This is used to handle extensions to standard requests
|
||||
* and class specific requests
|
||||
*/
|
||||
virtual void callback_request(const setup_packet_t *setup);
|
||||
|
||||
/*
|
||||
* This is used to handle extensions to standard requests
|
||||
* and class specific requests with a data phase
|
||||
*/
|
||||
virtual void callback_request_xfer_done(const setup_packet_t *setup, bool aborted);
|
||||
|
||||
|
||||
/*
|
||||
* 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 void callback_set_configuration(uint8_t configuration);
|
||||
|
||||
/*
|
||||
* Called by USBDevice layer in response to set_interface.
|
||||
*
|
||||
* Upon reception of this command endpoints of any previous interface
|
||||
* if any must be removed with endpoint_remove and new endpoint added with
|
||||
* endpoint_add.
|
||||
*
|
||||
* @param configuration Number of the configuration
|
||||
*
|
||||
* Warning: Called in ISR context
|
||||
*/
|
||||
virtual void callback_set_interface(uint16_t interface, uint8_t alternate);
|
||||
|
||||
/*
|
||||
* Called when there is a hid report that can be read
|
||||
*/
|
||||
virtual void report_rx() {}
|
||||
|
||||
/*
|
||||
* Called when there is space to send a hid report
|
||||
*/
|
||||
virtual void report_tx() {}
|
||||
|
||||
protected:
|
||||
usb_ep_t _int_in;
|
||||
usb_ep_t _int_out;
|
||||
|
||||
private:
|
||||
void _init(uint8_t output_report_length, uint8_t input_report_length, bool connect);
|
||||
void _send_isr(usb_ep_t endpoint);
|
||||
void _read_isr(usb_ep_t endpoint);
|
||||
|
||||
void _connect_wake_all();
|
||||
void _send_abort_all();
|
||||
void _read_abort_all();
|
||||
|
||||
class AsyncSend;
|
||||
class AsyncRead;
|
||||
|
||||
LinkedList<AsyncOp> _connect_list;
|
||||
LinkedList<AsyncSend> _send_list;
|
||||
bool _send_idle;
|
||||
LinkedList<AsyncRead> _read_list;
|
||||
bool _read_idle;
|
||||
|
||||
uint8_t _configuration_descriptor[41];
|
||||
HID_REPORT _input_report;
|
||||
HID_REPORT _output_report;
|
||||
uint8_t _output_length;
|
||||
uint8_t _input_length;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,92 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#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
|
|
@ -0,0 +1,556 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#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
|
||||
|
||||
const uint8_t *USBKeyboard::report_desc()
|
||||
{
|
||||
static const 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;
|
||||
}
|
||||
|
||||
|
||||
void USBKeyboard::report_rx()
|
||||
{
|
||||
assert_locked();
|
||||
|
||||
HID_REPORT report;
|
||||
read_nb(&report);
|
||||
|
||||
// we take [1] because [0] is the report ID
|
||||
_lock_status = report.data[1] & 0x07;
|
||||
}
|
||||
|
||||
uint8_t USBKeyboard::lock_status()
|
||||
{
|
||||
return _lock_status;
|
||||
}
|
||||
|
||||
int USBKeyboard::_putc(int c)
|
||||
{
|
||||
return key_code(c, keymap[c].modifier);
|
||||
}
|
||||
|
||||
bool USBKeyboard::key_code(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::media_control(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))
|
||||
|
||||
const uint8_t *USBKeyboard::configuration_desc()
|
||||
{
|
||||
uint8_t configurationDescriptorTemp[] = {
|
||||
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(report_desc_length())), // wDescriptorLength (LSB)
|
||||
(uint8_t)(MSB(report_desc_length())), // wDescriptorLength (MSB)
|
||||
|
||||
ENDPOINT_DESCRIPTOR_LENGTH, // bLength
|
||||
ENDPOINT_DESCRIPTOR, // bDescriptorType
|
||||
_int_in, // bEndpointAddress
|
||||
E_INTERRUPT, // bmAttributes
|
||||
LSB(MAX_HID_REPORT_SIZE), // wMaxPacketSize (LSB)
|
||||
MSB(MAX_HID_REPORT_SIZE), // wMaxPacketSize (MSB)
|
||||
1, // bInterval (milliseconds)
|
||||
|
||||
ENDPOINT_DESCRIPTOR_LENGTH, // bLength
|
||||
ENDPOINT_DESCRIPTOR, // bDescriptorType
|
||||
_int_out, // bEndpointAddress
|
||||
E_INTERRUPT, // bmAttributes
|
||||
LSB(MAX_HID_REPORT_SIZE), // wMaxPacketSize (LSB)
|
||||
MSB(MAX_HID_REPORT_SIZE), // wMaxPacketSize (MSB)
|
||||
1, // bInterval (milliseconds)
|
||||
};
|
||||
MBED_ASSERT(sizeof(configurationDescriptorTemp) == sizeof(configurationDescriptor));
|
||||
memcpy(configurationDescriptor, configurationDescriptorTemp, sizeof(configurationDescriptor));
|
||||
return configurationDescriptor;
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#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 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();
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param phy USB phy to use
|
||||
* @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(USBPhy *phy, uint16_t vendor_id = 0x1235, uint16_t product_id = 0x0050, uint16_t product_release = 0x0001):
|
||||
USBHID(phy, 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 key_code(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 media_control(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 const uint8_t * report_desc();
|
||||
|
||||
/*
|
||||
* Called when a data is received on the OUT endpoint. Useful to switch on LED of LOCK keys
|
||||
*/
|
||||
virtual void report_rx();
|
||||
|
||||
/**
|
||||
* 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 lock_status();
|
||||
|
||||
protected:
|
||||
/*
|
||||
* Get configuration descriptor
|
||||
*
|
||||
* @returns pointer to the configuration descriptor
|
||||
*/
|
||||
virtual const uint8_t * configuration_desc();
|
||||
|
||||
private:
|
||||
//dummy otherwise it doesn,t compile (we must define all methods of an abstract class)
|
||||
virtual int _getc() {
|
||||
return -1;
|
||||
};
|
||||
|
||||
uint8_t configurationDescriptor[41];
|
||||
uint8_t _lock_status;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue