260 lines
		
	
	
	
		
			9.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			260 lines
		
	
	
	
		
			9.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <stdint.h>
 | |
| #include "USBHID.h"
 | |
| #include "USBHID_Types.h"
 | |
| #include "USBDescriptor.h"
 | |
| #include "HIDKeyboard.h"
 | |
| 
 | |
| #define DEFAULT_CONFIGURATION (1)
 | |
| 
 | |
| HIDKeyboard::HIDKeyboard(uint16_t vendor_id, uint16_t product_id, uint16_t product_release) : USBDevice(vendor_id, product_id, product_release) { USBDevice::connect(); }
 | |
| 
 | |
| bool HIDKeyboard::sendReport(report_keyboard_t report) {
 | |
|     USBDevice::write(EP1IN, report.raw, sizeof(report), MAX_PACKET_SIZE_EP1);
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| uint8_t HIDKeyboard::leds() { return led_state; }
 | |
| 
 | |
| bool HIDKeyboard::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 *HIDKeyboard::stringImanufacturerDesc() {
 | |
|     static uint8_t stringImanufacturerDescriptor[] = {
 | |
|         0x18,              /*bLength*/
 | |
|         STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
 | |
|         't',
 | |
|         0,
 | |
|         'm',
 | |
|         0,
 | |
|         'k',
 | |
|         0,
 | |
|         '-',
 | |
|         0,
 | |
|         'k',
 | |
|         0,
 | |
|         'b',
 | |
|         0,
 | |
|         'd',
 | |
|         0,
 | |
|         '.',
 | |
|         0,
 | |
|         'c',
 | |
|         0,
 | |
|         'o',
 | |
|         0,
 | |
|         'm',
 | |
|         0 /*bString iManufacturer*/
 | |
|     };
 | |
|     return stringImanufacturerDescriptor;
 | |
| }
 | |
| 
 | |
| uint8_t *HIDKeyboard::stringIproductDesc() {
 | |
|     static uint8_t stringIproductDescriptor[] = {
 | |
|         0x0a,              /*bLength*/
 | |
|         STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
 | |
|         'm',
 | |
|         0,
 | |
|         'b',
 | |
|         0,
 | |
|         'e',
 | |
|         0,
 | |
|         'd',
 | |
|         0 /*bString iProduct*/
 | |
|     };
 | |
|     return stringIproductDescriptor;
 | |
| }
 | |
| 
 | |
| uint8_t *HIDKeyboard::stringIserialDesc() {
 | |
|     static uint8_t stringIserialDescriptor[] = {
 | |
|         0x04,              /*bLength*/
 | |
|         STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
 | |
|         '0', 0             /*bString iSerial*/
 | |
|     };
 | |
|     return stringIserialDescriptor;
 | |
| }
 | |
| 
 | |
| uint8_t *HIDKeyboard::reportDesc() {
 | |
|     static uint8_t reportDescriptor[] = {
 | |
|         USAGE_PAGE(1),     0x01,  // Generic Desktop
 | |
|         USAGE(1),          0x06,  // Keyboard
 | |
|         COLLECTION(1),     0x01,  // Application
 | |
| 
 | |
|         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), 0xFF, USAGE_PAGE(1),  0x07,  // Key Codes
 | |
|         USAGE_MINIMUM(1),  0x00, USAGE_MAXIMUM(1), 0xFF, INPUT(1),           0x00,                                                  // Data, Array
 | |
|         END_COLLECTION(0),
 | |
|     };
 | |
|     reportLength = sizeof(reportDescriptor);
 | |
|     return reportDescriptor;
 | |
| }
 | |
| 
 | |
| uint16_t HIDKeyboard::reportDescLength() {
 | |
|     reportDesc();
 | |
|     return reportLength;
 | |
| }
 | |
| 
 | |
| #define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) + (1 * INTERFACE_DESCRIPTOR_LENGTH) + (1 * HID_DESCRIPTOR_LENGTH) + (1 * ENDPOINT_DESCRIPTOR_LENGTH))
 | |
| uint8_t *HIDKeyboard::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_REMOTE_WAKEUP,     // bmAttributes
 | |
|         C_POWER(100),                     // bMaxPowerHello World from Mbed
 | |
| 
 | |
|         INTERFACE_DESCRIPTOR_LENGTH,  // bLength
 | |
|         INTERFACE_DESCRIPTOR,         // bDescriptorType
 | |
|         0x00,                         // bInterfaceNumber
 | |
|         0x00,                         // bAlternateSetting
 | |
|         0x01,                         // bNumEndpoints
 | |
|         HID_CLASS,                    // bInterfaceClass
 | |
|         1,                            // bInterfaceSubClass (boot)
 | |
|         1,                            // bInterfaceProtocol (keyboard)
 | |
|         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(EP1IN),          // bEndpointAddress
 | |
|         E_INTERRUPT,                 // bmAttributes
 | |
|         LSB(MAX_PACKET_SIZE_EPINT),  // wMaxPacketSize (LSB)
 | |
|         MSB(MAX_PACKET_SIZE_EPINT),  // wMaxPacketSize (MSB)
 | |
|         1,                           // bInterval (milliseconds)
 | |
|     };
 | |
|     return configurationDescriptor;
 | |
| }
 | |
| 
 | |
| #if 0
 | |
| uint8_t * HIDKeyboard::deviceDesc() {
 | |
|     static uint8_t deviceDescriptor[] = {
 | |
|         DEVICE_DESCRIPTOR_LENGTH,       /* bLength */
 | |
|         DEVICE_DESCRIPTOR,              /* bDescriptorType */
 | |
|         LSB(USB_VERSION_2_0),           /* bcdUSB (LSB) */
 | |
|         MSB(USB_VERSION_2_0),           /* bcdUSB (MSB) */
 | |
|         0x00,                           /* bDeviceClass */
 | |
|         0x00,                           /* bDeviceSubClass */
 | |
|         0x00,                           /* bDeviceprotocol */
 | |
|         MAX_PACKET_SIZE_EP0,            /* bMaxPacketSize0 */
 | |
|         (uint8_t)(LSB(0xfeed)),                 /* idVendor (LSB) */
 | |
|         (uint8_t)(MSB(0xfeed)),                 /* idVendor (MSB) */
 | |
|         (uint8_t)(LSB(0x1bed)),                /* idProduct (LSB) */
 | |
|         (uint8_t)(MSB(0x1bed)),                /* idProduct (MSB) */
 | |
|         (uint8_t)(LSB(0x0002)),           /* bcdDevice (LSB) */
 | |
|         (uint8_t)(MSB(0x0002)),           /* bcdDevice (MSB) */
 | |
|         0,    /* iManufacturer */
 | |
|         0,         /* iProduct */
 | |
|         0,          /* iSerialNumber */
 | |
|         0x01                            /* bNumConfigurations */
 | |
|     };
 | |
|     return deviceDescriptor;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| bool HIDKeyboard::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:
 | |
|                 // LED indicator
 | |
|                 // TODO: check Interface and Report length?
 | |
|                 // if (transfer->setup.wIndex == INTERFACE_KEYBOAD) { }
 | |
|                 // if (transfer->setup.wLength == 1)
 | |
| 
 | |
|                 transfer->remaining = 1;
 | |
|                 // transfer->ptr = ?? what ptr should be set when OUT(not used?)
 | |
|                 transfer->direction = HOST_TO_DEVICE;
 | |
|                 transfer->notify    = true; /* notify with USBCallback_requestCompleted */
 | |
|                 success             = true;
 | |
|             default:
 | |
|                 break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return success;
 | |
| }
 | |
| 
 | |
| void HIDKeyboard::USBCallback_requestCompleted(uint8_t *buf, uint32_t length) {
 | |
|     if (length > 0) {
 | |
|         CONTROL_TRANSFER *transfer = getTransferPtr();
 | |
|         if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
 | |
|             switch (transfer->setup.bRequest) {
 | |
|                 case SET_REPORT:
 | |
|                     led_state = buf[0];
 | |
|                     break;
 | |
|                 default:
 | |
|                     break;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | 
