271 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			271 lines
		
	
	
	
		
			10 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;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | 
