diff options
Diffstat (limited to 'protocol/lufa')
| -rw-r--r-- | protocol/lufa/descriptor.c | 558 | ||||
| -rw-r--r-- | protocol/lufa/descriptor.h | 122 | ||||
| -rw-r--r-- | protocol/lufa/lufa.c | 408 | ||||
| -rw-r--r-- | protocol/lufa/lufa.h | 58 | 
4 files changed, 1146 insertions, 0 deletions
diff --git a/protocol/lufa/descriptor.c b/protocol/lufa/descriptor.c new file mode 100644 index 0000000000..d3f740bfe6 --- /dev/null +++ b/protocol/lufa/descriptor.c @@ -0,0 +1,558 @@ +/*  + * Copyright 2012 Jun Wako <wakojun@gmail.com> + * This file is based on: + *     LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse + *     LUFA-120219/Demos/Device/Lowlevel/GenericHID + */ + +/* +             LUFA Library +     Copyright (C) Dean Camera, 2012. + +  dean [at] fourwalledcubicle [dot] com +           www.lufa-lib.org +*/ + +/* +  Copyright 2012  Dean Camera (dean [at] fourwalledcubicle [dot] com) +  Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com) + +  Permission to use, copy, modify, distribute, and sell this +  software and its documentation for any purpose is hereby granted +  without fee, provided that the above copyright notice appear in +  all copies and that both that the copyright notice and this +  permission notice and warranty disclaimer appear in supporting +  documentation, and that the name of the author not be used in +  advertising or publicity pertaining to distribution of the +  software without specific, written prior permission. + +  The author disclaim all warranties with regard to this +  software, including all implied warranties of merchantability +  and fitness.  In no event shall the author be liable for any +  special, indirect or consequential damages or any damages +  whatsoever resulting from loss of use, data or profits, whether +  in an action of contract, negligence or other tortious action, +  arising out of or in connection with the use or performance of +  this software. +*/ + +#include "util.h" +#include "report.h" +#include "descriptor.h" + + +/******************************************************************************* + * HID Report Descriptors + ******************************************************************************/ +const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = +{ +    HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ +    HID_RI_USAGE(8, 0x06), /* Keyboard */ +    HID_RI_COLLECTION(8, 0x01), /* Application */ +        HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */ +        HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */ +        HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */ +        HID_RI_LOGICAL_MINIMUM(8, 0x00), +        HID_RI_LOGICAL_MAXIMUM(8, 0x01), +        HID_RI_REPORT_COUNT(8, 0x08), +        HID_RI_REPORT_SIZE(8, 0x01), +        HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), +        HID_RI_REPORT_COUNT(8, 0x01), +        HID_RI_REPORT_SIZE(8, 0x08), +        HID_RI_INPUT(8, HID_IOF_CONSTANT), +        HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */ +        HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */ +        HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */ +        HID_RI_REPORT_COUNT(8, 0x05), +        HID_RI_REPORT_SIZE(8, 0x01), +        HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), +        HID_RI_REPORT_COUNT(8, 0x01), +        HID_RI_REPORT_SIZE(8, 0x03), +        HID_RI_OUTPUT(8, HID_IOF_CONSTANT), +        HID_RI_USAGE_PAGE(8, 0x07), /* Keyboard */ +        HID_RI_USAGE_MINIMUM(8, 0x00), /* Reserved (no event indicated) */ +        HID_RI_USAGE_MAXIMUM(8, 0xFF), /* Keyboard Application */ +        HID_RI_LOGICAL_MINIMUM(8, 0x00), +        HID_RI_LOGICAL_MAXIMUM(8, 0xFF), +        HID_RI_REPORT_COUNT(8, 0x06), +        HID_RI_REPORT_SIZE(8, 0x08), +        HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), +    HID_RI_END_COLLECTION(0), +}; + +const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] = +{ +    HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ +    HID_RI_USAGE(8, 0x02), /* Mouse */ +    HID_RI_COLLECTION(8, 0x01), /* Application */ +        HID_RI_USAGE(8, 0x01), /* Pointer */ +        HID_RI_COLLECTION(8, 0x00), /* Physical */ + +            HID_RI_USAGE_PAGE(8, 0x09), /* Button */ +            HID_RI_USAGE_MINIMUM(8, 0x01),  /* Button 1 */ +            HID_RI_USAGE_MAXIMUM(8, 0x05),  /* Button 5 */ +            HID_RI_LOGICAL_MINIMUM(8, 0x00), +            HID_RI_LOGICAL_MAXIMUM(8, 0x01), +            HID_RI_REPORT_COUNT(8, 0x05), +            HID_RI_REPORT_SIZE(8, 0x01), +            HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), +            HID_RI_REPORT_COUNT(8, 0x01), +            HID_RI_REPORT_SIZE(8, 0x03), +            HID_RI_INPUT(8, HID_IOF_CONSTANT), + +            HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ +            HID_RI_USAGE(8, 0x30), /* Usage X */ +            HID_RI_USAGE(8, 0x31), /* Usage Y */ +            HID_RI_LOGICAL_MINIMUM(8, -127), +            HID_RI_LOGICAL_MAXIMUM(8, 127), +            HID_RI_REPORT_COUNT(8, 0x02), +            HID_RI_REPORT_SIZE(8, 0x08), +            HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), + +            HID_RI_USAGE(8, 0x38), /* Wheel */ +            HID_RI_LOGICAL_MINIMUM(8, -127), +            HID_RI_LOGICAL_MAXIMUM(8, 127), +            HID_RI_REPORT_COUNT(8, 0x01), +            HID_RI_REPORT_SIZE(8, 0x08), +            HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), + +            HID_RI_USAGE_PAGE(8, 0x0C), /* Consumer */ +            HID_RI_USAGE(16, 0x0238), /* AC Pan (Horizontal wheel) */ +            HID_RI_LOGICAL_MINIMUM(8, -127), +            HID_RI_LOGICAL_MAXIMUM(8, 127), +            HID_RI_REPORT_COUNT(8, 0x01), +            HID_RI_REPORT_SIZE(8, 0x08), +            HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), + +        HID_RI_END_COLLECTION(0), +    HID_RI_END_COLLECTION(0), +}; + +const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] = +{ +    HID_RI_USAGE_PAGE(16, 0xFF31), /* Vendor Page(PJRC Teensy compatible) */ +    HID_RI_USAGE(8, 0x74), /* Vendor Usage(PJRC Teensy compatible) */ +    HID_RI_COLLECTION(8, 0x01), /* Application */ +        HID_RI_USAGE(8, 0x75), /* Vendor Usage 0x75 */ +        HID_RI_LOGICAL_MINIMUM(8, 0x00), +        HID_RI_LOGICAL_MAXIMUM(8, 0xFF), +        HID_RI_REPORT_COUNT(8, CONSOLE_EPSIZE), +        HID_RI_REPORT_SIZE(8, 0x08), +        HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), +        HID_RI_USAGE(8, 0x76), /* Vendor Usage 0x76 */ +        HID_RI_LOGICAL_MINIMUM(8, 0x00), +        HID_RI_LOGICAL_MAXIMUM(8, 0xFF), +        HID_RI_REPORT_COUNT(8, CONSOLE_EPSIZE), +        HID_RI_REPORT_SIZE(8, 0x08), +        HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), +    HID_RI_END_COLLECTION(0), +}; + +#ifdef EXTRAKEY_ENABLE +const USB_Descriptor_HIDReport_Datatype_t PROGMEM ExtraReport[] = +{ +    HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ +    HID_RI_USAGE(8, 0x80), /* System Control */ +    HID_RI_COLLECTION(8, 0x01), /* Application */ +        HID_RI_REPORT_ID(8, REPORT_ID_SYSTEM), +        HID_RI_LOGICAL_MINIMUM(16, 0x0081), +        HID_RI_LOGICAL_MAXIMUM(16, 0x00B7), +        HID_RI_USAGE_MINIMUM(16, 0x0081), /* System Power Down */ +        HID_RI_USAGE_MAXIMUM(16, 0x00B7), /* System Display LCD Autoscale */ +        HID_RI_REPORT_SIZE(8, 16), +        HID_RI_REPORT_COUNT(8, 1), +        HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), +    HID_RI_END_COLLECTION(0), + +    HID_RI_USAGE_PAGE(8, 0x0C), /* Consumer */ +    HID_RI_USAGE(8, 0x01), /* Consumer Control */ +    HID_RI_COLLECTION(8, 0x01), /* Application */ +        HID_RI_REPORT_ID(8, REPORT_ID_CONSUMER), +        HID_RI_LOGICAL_MINIMUM(16, 0x0010), +        HID_RI_LOGICAL_MAXIMUM(16, 0x029C), +        HID_RI_USAGE_MINIMUM(16, 0x0010), /* +10 */ +        HID_RI_USAGE_MAXIMUM(16, 0x029C), /* AC Distribute Vertically */ +        HID_RI_REPORT_SIZE(8, 16), +        HID_RI_REPORT_COUNT(8, 1), +        HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), +    HID_RI_END_COLLECTION(0), +}; +#endif + +#ifdef NKRO_ENABLE +const USB_Descriptor_HIDReport_Datatype_t PROGMEM NKROReport[] = +{ +    HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ +    HID_RI_USAGE(8, 0x06), /* Keyboard */ +    HID_RI_COLLECTION(8, 0x01), /* Application */ +        HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */ +        HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */ +        HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */ +        HID_RI_LOGICAL_MINIMUM(8, 0x00), +        HID_RI_LOGICAL_MAXIMUM(8, 0x01), +        HID_RI_REPORT_COUNT(8, 0x08), +        HID_RI_REPORT_SIZE(8, 0x01), +        HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), + +        HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */ +        HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */ +        HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */ +        HID_RI_REPORT_COUNT(8, 0x05), +        HID_RI_REPORT_SIZE(8, 0x01), +        HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), +        HID_RI_REPORT_COUNT(8, 0x01), +        HID_RI_REPORT_SIZE(8, 0x03), +        HID_RI_OUTPUT(8, HID_IOF_CONSTANT), + +        HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */ +        HID_RI_USAGE_MINIMUM(8, 0x00), /* Keyboard 0 */ +        HID_RI_USAGE_MAXIMUM(8, NKRO_SIZE*8-1), /* Keyboard Right GUI */ +        HID_RI_LOGICAL_MINIMUM(8, 0x00), +        HID_RI_LOGICAL_MAXIMUM(8, 0x01), +        HID_RI_REPORT_COUNT(8, NKRO_SIZE*8), +        HID_RI_REPORT_SIZE(8, 0x01), +}; +#endif + +/******************************************************************************* + * Device Descriptors + ******************************************************************************/ +const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = +{ +    .Header                 = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device}, + +    .USBSpecification       = VERSION_BCD(01.10), +    .Class                  = USB_CSCP_NoDeviceClass, +    .SubClass               = USB_CSCP_NoDeviceSubclass, +    .Protocol               = USB_CSCP_NoDeviceProtocol, + +    .Endpoint0Size          = FIXED_CONTROL_ENDPOINT_SIZE, + +    .VendorID               = VENDOR_ID, +    .ProductID              = PRODUCT_ID, +    .ReleaseNumber          = DEVICE_VER, + +    .ManufacturerStrIndex   = 0x01, +    .ProductStrIndex        = 0x02, +    .SerialNumStrIndex      = NO_DESCRIPTOR, + +    .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS +}; + +/******************************************************************************* + * Configuration Descriptors + ******************************************************************************/ +const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = +{ +    .Config = +        { +            .Header                 = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration}, + +            .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t), +            .TotalInterfaces        = TOTAL_INTERFACES, + +            .ConfigurationNumber    = 1, +            .ConfigurationStrIndex  = NO_DESCRIPTOR, + +            .ConfigAttributes       = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_REMOTEWAKEUP), + +            .MaxPowerConsumption    = USB_CONFIG_POWER_MA(100) +        }, + +    /* +     * Keyboard +     */ +    .Keyboard_Interface = +        { +            .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + +            .InterfaceNumber        = KEYBOARD_INTERFACE, +            .AlternateSetting       = 0x00, + +            .TotalEndpoints         = 1, + +            .Class                  = HID_CSCP_HIDClass, +            .SubClass               = HID_CSCP_BootSubclass, +            .Protocol               = HID_CSCP_KeyboardBootProtocol, + +            .InterfaceStrIndex      = NO_DESCRIPTOR +        }, + +    .Keyboard_HID = +        { +            .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, + +            .HIDSpec                = VERSION_BCD(01.11), +            .CountryCode            = 0x00, +            .TotalReportDescriptors = 1, +            .HIDReportType          = HID_DTYPE_Report, +            .HIDReportLength        = sizeof(KeyboardReport) +        }, + +    .Keyboard_INEndpoint = +        { +            .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + +            .EndpointAddress        = (ENDPOINT_DIR_IN | KEYBOARD_IN_EPNUM), +            .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), +            .EndpointSize           = KEYBOARD_EPSIZE, +            .PollingIntervalMS      = 0x01 +        }, + +    /* +     * Mouse +     */ +#ifdef MOUSE_ENABLE +    .Mouse_Interface = +        { +            .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + +            .InterfaceNumber        = MOUSE_INTERFACE, +            .AlternateSetting       = 0x00, + +            .TotalEndpoints         = 1, + +            .Class                  = HID_CSCP_HIDClass, +            .SubClass               = HID_CSCP_BootSubclass, +            .Protocol               = HID_CSCP_MouseBootProtocol, + +            .InterfaceStrIndex      = NO_DESCRIPTOR +        }, + +    .Mouse_HID = +        { +            .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, + +            .HIDSpec                = VERSION_BCD(01.11), +            .CountryCode            = 0x00, +            .TotalReportDescriptors = 1, +            .HIDReportType          = HID_DTYPE_Report, +            .HIDReportLength        = sizeof(MouseReport) +        }, + +    .Mouse_INEndpoint = +        { +            .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + +            .EndpointAddress        = (ENDPOINT_DIR_IN | MOUSE_IN_EPNUM), +            .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), +            .EndpointSize           = MOUSE_EPSIZE, +            .PollingIntervalMS      = 0x01 +        }, +#endif + +    /* +     * Console +     */ +    .Console_Interface = +        { +            .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + +            .InterfaceNumber        = CONSOLE_INTERFACE, +            .AlternateSetting       = 0x00, + +            .TotalEndpoints         = 2, + +            .Class                  = HID_CSCP_HIDClass, +            .SubClass               = HID_CSCP_NonBootSubclass, +            .Protocol               = HID_CSCP_NonBootProtocol, + +            .InterfaceStrIndex      = NO_DESCRIPTOR +        }, + +    .Console_HID = +        { +            .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, + +            .HIDSpec                = VERSION_BCD(01.11), +            .CountryCode            = 0x00, +            .TotalReportDescriptors = 1, +            .HIDReportType          = HID_DTYPE_Report, +            .HIDReportLength        = sizeof(ConsoleReport) +        }, + +    .Console_INEndpoint = +        { +            .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + +            .EndpointAddress        = (ENDPOINT_DIR_IN | CONSOLE_IN_EPNUM), +            .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), +            .EndpointSize           = CONSOLE_EPSIZE, +            .PollingIntervalMS      = 0x01 +        }, + +    .Console_OUTEndpoint = +        { +            .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + +            .EndpointAddress        = (ENDPOINT_DIR_OUT | CONSOLE_OUT_EPNUM), +            .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), +            .EndpointSize           = CONSOLE_EPSIZE, +            .PollingIntervalMS      = 0x01 +        }, + +    /* +     * Extra +     */ +#ifdef EXTRAKEY_ENABLE +    .Extra_Interface = +        { +            .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + +            .InterfaceNumber        = EXTRA_INTERFACE, +            .AlternateSetting       = 0x00, + +            .TotalEndpoints         = 1, + +            .Class                  = HID_CSCP_HIDClass, +            .SubClass               = HID_CSCP_NonBootSubclass, +            .Protocol               = HID_CSCP_NonBootProtocol, + +            .InterfaceStrIndex      = NO_DESCRIPTOR +        }, + +    .Extra_HID = +        { +            .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, + +            .HIDSpec                = VERSION_BCD(01.11), +            .CountryCode            = 0x00, +            .TotalReportDescriptors = 1, +            .HIDReportType          = HID_DTYPE_Report, +            .HIDReportLength        = sizeof(ExtraReport) +        }, + +    .Extra_INEndpoint = +        { +            .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + +            .EndpointAddress        = (ENDPOINT_DIR_IN | EXTRA_IN_EPNUM), +            .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), +            .EndpointSize           = EXTRA_EPSIZE, +            .PollingIntervalMS      = 0x01 +        }, +#endif +}; + + +/******************************************************************************* + * String Descriptors + ******************************************************************************/ +const USB_Descriptor_String_t PROGMEM LanguageString = +{ +    .Header                 = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String}, + +    .UnicodeString          = {LANGUAGE_ID_ENG} +}; + +const USB_Descriptor_String_t PROGMEM ManufacturerString = +{ +    .Header                 = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String}, + +    .UnicodeString          = LSTR(MANUFACTURER) +}; + +const USB_Descriptor_String_t PROGMEM ProductString = +{ +    .Header                 = {.Size = USB_STRING_LEN(28), .Type = DTYPE_String}, + +    .UnicodeString          = LSTR(PRODUCT) +}; + + +/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors" + *  documentation) by the application code so that the address and size of a requested descriptor can be given + *  to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function + *  is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the + *  USB host. + */ +uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, +                                    const uint8_t wIndex, +                                    const void** const DescriptorAddress) +{ +    const uint8_t  DescriptorType   = (wValue >> 8); +    const uint8_t  DescriptorIndex  = (wValue & 0xFF); + +    const void* Address = NULL; +    uint16_t    Size    = NO_DESCRIPTOR; + +    switch (DescriptorType) +    { +        case DTYPE_Device: +            Address = &DeviceDescriptor; +            Size    = sizeof(USB_Descriptor_Device_t); +            break; +        case DTYPE_Configuration: +            Address = &ConfigurationDescriptor; +            Size    = sizeof(USB_Descriptor_Configuration_t); +            break; +        case DTYPE_String: +            switch (DescriptorIndex ) +            { +                case 0x00: +                    Address = &LanguageString; +                    Size    = pgm_read_byte(&LanguageString.Header.Size); +                    break; +                case 0x01: +                    Address = &ManufacturerString; +                    Size    = pgm_read_byte(&ManufacturerString.Header.Size); +                    break; +                case 0x02: +                    Address = &ProductString; +                    Size    = pgm_read_byte(&ProductString.Header.Size); +                    break; +            } +            break; +        case HID_DTYPE_HID: +            switch (wIndex) { +            case KEYBOARD_INTERFACE: +                Address = &ConfigurationDescriptor.Keyboard_HID; +                Size    = sizeof(USB_HID_Descriptor_HID_t); +                break; +#ifdef MOUSE_ENABLE +            case MOUSE_INTERFACE: +                Address = &ConfigurationDescriptor.Mouse_HID; +                Size    = sizeof(USB_HID_Descriptor_HID_t); +                break; +#endif +            case CONSOLE_INTERFACE: +                Address = &ConfigurationDescriptor.Console_HID; +                Size    = sizeof(USB_HID_Descriptor_HID_t); +                break; +#ifdef EXTRAKEY_ENABLE +            case EXTRA_INTERFACE: +                Address = &ConfigurationDescriptor.Extra_HID; +                Size    = sizeof(USB_HID_Descriptor_HID_t); +                break; +#endif +            } +            break; +        case HID_DTYPE_Report: +            switch (wIndex) { +            case KEYBOARD_INTERFACE: +                Address = &KeyboardReport; +                Size    = sizeof(KeyboardReport); +                break; +#ifdef MOUSE_ENABLE +            case MOUSE_INTERFACE: +                Address = &MouseReport; +                Size    = sizeof(MouseReport); +                break; +#endif +            case CONSOLE_INTERFACE: +                Address = &ConsoleReport; +                Size    = sizeof(ConsoleReport); +                break; +#ifdef EXTRAKEY_ENABLE +            case EXTRA_INTERFACE: +                Address = &ExtraReport; +                Size    = sizeof(ExtraReport); +                break; +#endif +            } +            break; +    } + +    *DescriptorAddress = Address; +    return Size; +} diff --git a/protocol/lufa/descriptor.h b/protocol/lufa/descriptor.h new file mode 100644 index 0000000000..001e072e6a --- /dev/null +++ b/protocol/lufa/descriptor.h @@ -0,0 +1,122 @@ +/*  + * Copyright 2012 Jun Wako <wakojun@gmail.com> + * This file is based on: + *     LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse + *     LUFA-120219/Demos/Device/Lowlevel/GenericHID + */ + +/* +             LUFA Library +     Copyright (C) Dean Camera, 2012. + +  dean [at] fourwalledcubicle [dot] com +           www.lufa-lib.org +*/ + +/* +  Copyright 2012  Dean Camera (dean [at] fourwalledcubicle [dot] com) +  Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com) + +  Permission to use, copy, modify, distribute, and sell this +  software and its documentation for any purpose is hereby granted +  without fee, provided that the above copyright notice appear in +  all copies and that both that the copyright notice and this +  permission notice and warranty disclaimer appear in supporting +  documentation, and that the name of the author not be used in +  advertising or publicity pertaining to distribution of the +  software without specific, written prior permission. + +  The author disclaim all warranties with regard to this +  software, including all implied warranties of merchantability +  and fitness.  In no event shall the author be liable for any +  special, indirect or consequential damages or any damages +  whatsoever resulting from loss of use, data or profits, whether +  in an action of contract, negligence or other tortious action, +  arising out of or in connection with the use or performance of +  this software. +*/ + +/** \file + * + *  Header file for Descriptors.c. + */ + +#ifndef _DESCRIPTORS_H_ +#define _DESCRIPTORS_H_ + +#include <LUFA/Drivers/USB/USB.h> +#include <avr/pgmspace.h> + + +typedef struct +{ +    USB_Descriptor_Configuration_Header_t Config; + +    // Keyboard HID Interface +    USB_Descriptor_Interface_t            Keyboard_Interface; +    USB_HID_Descriptor_HID_t              Keyboard_HID; +    USB_Descriptor_Endpoint_t             Keyboard_INEndpoint; + +    // Mouse HID Interface +#ifdef MOUSE_ENABLE +    USB_Descriptor_Interface_t            Mouse_Interface; +    USB_HID_Descriptor_HID_t              Mouse_HID; +    USB_Descriptor_Endpoint_t             Mouse_INEndpoint; +#endif + +    // Console HID Interface +    USB_Descriptor_Interface_t            Console_Interface; +    USB_HID_Descriptor_HID_t              Console_HID; +    USB_Descriptor_Endpoint_t             Console_INEndpoint; +    USB_Descriptor_Endpoint_t             Console_OUTEndpoint; + +    // Extra HID Interface +#ifdef EXTRAKEY_ENABLE +    USB_Descriptor_Interface_t            Extra_Interface; +    USB_HID_Descriptor_HID_t              Extra_HID; +    USB_Descriptor_Endpoint_t             Extra_INEndpoint; +#endif +} USB_Descriptor_Configuration_t; + + +/* index of interface */ +#define KEYBOARD_INTERFACE          0 + +#ifdef MOUSE_ENABLE +#   define MOUSE_INTERFACE          (KEYBOARD_INTERFACE + 1) +#else +#   define MOUSE_INTERFACE          KEYBOARD_INTERFACE +#endif  + +#ifdef EXTRAKEY_ENABLE +#   define EXTRA_INTERFACE          (MOUSE_INTERFACE + 1) +#else +#   define EXTRA_INTERFACE          MOUSE_INTERFACE +#endif  + +#define CONSOLE_INTERFACE           (EXTRA_INTERFACE + 1) + + +/* nubmer of interfaces */ +#define TOTAL_INTERFACES            (CONSOLE_INTERFACE + 1) + + +// Endopoint number and size +#define KEYBOARD_IN_EPNUM           1 +#define MOUSE_IN_EPNUM              2 +#define CONSOLE_IN_EPNUM            3 +#define CONSOLE_OUT_EPNUM           4 +#define EXTRA_IN_EPNUM              5 + +#define KEYBOARD_EPSIZE             8 +#define MOUSE_EPSIZE                8 +#define CONSOLE_EPSIZE              8 +#define EXTRA_EPSIZE                8 + + +uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, +                                    const uint8_t wIndex, +                                    const void** const DescriptorAddress) +                                    ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3); + +#endif diff --git a/protocol/lufa/lufa.c b/protocol/lufa/lufa.c new file mode 100644 index 0000000000..8fa719bc95 --- /dev/null +++ b/protocol/lufa/lufa.c @@ -0,0 +1,408 @@ +/*  + * Copyright 2012 Jun Wako <wakojun@gmail.com> + * This file is based on: + *     LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse + *     LUFA-120219/Demos/Device/Lowlevel/GenericHID + */ + +/* +             LUFA Library +     Copyright (C) Dean Camera, 2012. + +  dean [at] fourwalledcubicle [dot] com +           www.lufa-lib.org +*/ + +/* +  Copyright 2012  Dean Camera (dean [at] fourwalledcubicle [dot] com) +  Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com) + +  Permission to use, copy, modify, distribute, and sell this +  software and its documentation for any purpose is hereby granted +  without fee, provided that the above copyright notice appear in +  all copies and that both that the copyright notice and this +  permission notice and warranty disclaimer appear in supporting +  documentation, and that the name of the author not be used in +  advertising or publicity pertaining to distribution of the +  software without specific, written prior permission. + +  The author disclaim all warranties with regard to this +  software, including all implied warranties of merchantability +  and fitness.  In no event shall the author be liable for any +  special, indirect or consequential damages or any damages +  whatsoever resulting from loss of use, data or profits, whether +  in an action of contract, negligence or other tortious action, +  arising out of or in connection with the use or performance of +  this software. +*/ + +#include "report.h" +#include "host.h" +#include "host_driver.h" +#include "keyboard.h" +#include "sendchar.h" +#include "debug.h" + +#include "descriptor.h" +#include "lufa.h" + +static uint8_t idle_duration = 0; +static uint8_t protocol_report = 1; +static uint8_t keyboard_led_stats = 0; + +static report_keyboard_t keyboard_report_sent; + + +/* Host driver */ +static uint8_t keyboard_leds(void); +static void send_keyboard(report_keyboard_t *report); +static void send_mouse(report_mouse_t *report); +static void send_system(uint16_t data); +static void send_consumer(uint16_t data); +static host_driver_t lufa_driver = { +    keyboard_leds, +    send_keyboard, +    send_mouse, +    send_system, +    send_consumer +}; + + +static void SetupHardware(void); +static void Console_HID_Task(void); + +int main(void) +{ +    SetupHardware(); +    sei(); + +    print_enable = true; +    debug_enable = true; +    debug_matrix = true; +    debug_keyboard = true; +    debug_mouse = true; + +    // TODO: can't print here +    debug("LUFA init\n"); + +    keyboard_init(); +    host_set_driver(&lufa_driver); +    while (1) { +        keyboard_proc(); + +        Console_HID_Task(); +        USB_USBTask(); +    } +} + +void SetupHardware(void) +{ +    /* Disable watchdog if enabled by bootloader/fuses */ +    MCUSR &= ~(1 << WDRF); +    wdt_disable(); + +    /* Disable clock division */ +    clock_prescale_set(clock_div_1); + +    USB_Init(); +} + +static void Console_HID_Task(void) +{ +	/* Device must be connected and configured for the task to run */ +	if (USB_DeviceState != DEVICE_STATE_Configured) +	  return; + +        // TODO: impl receivechar()/recvchar() +	Endpoint_SelectEndpoint(CONSOLE_OUT_EPNUM); + +	/* Check to see if a packet has been sent from the host */ +	if (Endpoint_IsOUTReceived()) +	{ +		/* Check to see if the packet contains data */ +		if (Endpoint_IsReadWriteAllowed()) +		{ +			/* Create a temporary buffer to hold the read in report from the host */ +			uint8_t ConsoleData[CONSOLE_EPSIZE]; + +			/* Read Console Report Data */ +			Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL); + +			/* Process Console Report Data */ +			//ProcessConsoleHIDReport(ConsoleData); +		} + +		/* Finalize the stream transfer to send the last packet */ +		Endpoint_ClearOUT(); +	} + +        /* IN packet */ +	Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM); +        // send IN packet +	if (Endpoint_IsINReady()) +            Endpoint_ClearIN(); +} + + +/******************************************************************************* + * USB Events + ******************************************************************************/ +/** Event handler for the USB_Connect event. */ +void EVENT_USB_Device_Connect(void) +{ +} + +/** Event handler for the USB_Disconnect event. */ +void EVENT_USB_Device_Disconnect(void) +{ +} + +/** Event handler for the USB_ConfigurationChanged event. + * This is fired when the host sets the current configuration of the USB device after enumeration. + */ +void EVENT_USB_Device_ConfigurationChanged(void) +{ +    bool ConfigSuccess = true; + +    /* Setup Keyboard HID Report Endpoints */ +    ConfigSuccess &= Endpoint_ConfigureEndpoint(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, +                                                KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE); + +#ifdef MOUSE_ENABLE +    /* Setup Mouse HID Report Endpoint */ +    ConfigSuccess &= Endpoint_ConfigureEndpoint(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, +                                                MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE); +#endif + +#ifdef EXTRAKEY_ENABLE +    /* Setup Extra HID Report Endpoint */ +    ConfigSuccess &= Endpoint_ConfigureEndpoint(EXTRA_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, +                                                EXTRA_EPSIZE, ENDPOINT_BANK_SINGLE); +#endif + +    /* Setup Console HID Report Endpoints */ +    ConfigSuccess &= Endpoint_ConfigureEndpoint(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, +                                                CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE); +    ConfigSuccess &= Endpoint_ConfigureEndpoint(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT, +                                                CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE); +} + +/* +Appendix G: HID Request Support Requirements + +The following table enumerates the requests that need to be supported by various types of HID class devices. + +Device type     GetReport   SetReport   GetIdle     SetIdle     GetProtocol SetProtocol +------------------------------------------------------------------------------------------ +Boot Mouse      Required    Optional    Optional    Optional    Required    Required +Non-Boot Mouse  Required    Optional    Optional    Optional    Optional    Optional +Boot Keyboard   Required    Optional    Required    Required    Required    Required +Non-Boot Keybrd Required    Optional    Required    Required    Optional    Optional +Other Device    Required    Optional    Optional    Optional    Optional    Optional +*/ +/** Event handler for the USB_ControlRequest event. + *  This is fired before passing along unhandled control requests to the library for processing internally. + */ +void EVENT_USB_Device_ControlRequest(void) +{ +    uint8_t* ReportData = NULL; +    uint8_t  ReportSize = 0; + +    /* Handle HID Class specific requests */ +    switch (USB_ControlRequest.bRequest) +    { +        case HID_REQ_GetReport: +            if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) +            { +                Endpoint_ClearSETUP(); + +                // Interface +                switch (USB_ControlRequest.wIndex) { +                case KEYBOARD_INTERFACE: +                    // TODO: test/check +                    ReportData = (uint8_t*)&keyboard_report_sent; +                    ReportSize = sizeof(keyboard_report_sent); +                    break; +                } + +                /* Write the report data to the control endpoint */ +                Endpoint_Write_Control_Stream_LE(ReportData, ReportSize); +                Endpoint_ClearOUT(); +            } + +            break; +        case HID_REQ_SetReport: +            if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) +            { + +                // Interface +                switch (USB_ControlRequest.wIndex) { +                case KEYBOARD_INTERFACE: +                    Endpoint_ClearSETUP(); + +                    while (!(Endpoint_IsOUTReceived())) { +                        if (USB_DeviceState == DEVICE_STATE_Unattached) +                          return; +                    } +                    keyboard_led_stats = Endpoint_Read_8(); + +                    Endpoint_ClearOUT(); +                    Endpoint_ClearStatusStage(); +                    break; +                } + +            } + +            break; + +        case HID_REQ_GetProtocol: +            if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) +            { +                Endpoint_ClearSETUP(); +                while (!(Endpoint_IsINReady())); +                Endpoint_Write_8(protocol_report); +                Endpoint_ClearIN(); +                Endpoint_ClearStatusStage(); +            } + +            break; +        case HID_REQ_SetProtocol: +            if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) +            { +                Endpoint_ClearSETUP(); +                Endpoint_ClearStatusStage(); + +                protocol_report = ((USB_ControlRequest.wValue & 0xFF) != 0x00); +            } + +            break; +        case HID_REQ_SetIdle: +            if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) +            { +                Endpoint_ClearSETUP(); +                Endpoint_ClearStatusStage(); + +                idle_duration = ((USB_ControlRequest.wValue & 0xFF00) >> 8); +            } + +            break; +        case HID_REQ_GetIdle: +            if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) +            { +                Endpoint_ClearSETUP(); +                while (!(Endpoint_IsINReady())); +                Endpoint_Write_8(idle_duration); +                Endpoint_ClearIN(); +                Endpoint_ClearStatusStage(); +            } + +            break; +    } +} + +/******************************************************************************* + * Host driver  + ******************************************************************************/ +static uint8_t keyboard_leds(void) +{ +    return keyboard_led_stats; +} + +static void send_keyboard(report_keyboard_t *report) +{ +    // TODO: handle NKRO report +    /* Select the Keyboard Report Endpoint */ +    Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM); + +    /* Check if Keyboard Endpoint Ready for Read/Write */ +    if (Endpoint_IsReadWriteAllowed()) +    { +        /* Write Keyboard Report Data */ +        Endpoint_Write_Stream_LE(report, sizeof(report_keyboard_t), NULL); + +        /* Finalize the stream transfer to send the last packet */ +        Endpoint_ClearIN(); +    } +    keyboard_report_sent = *report; +} + +static void send_mouse(report_mouse_t *report) +{ +#ifdef MOUSE_ENABLE +    /* Select the Mouse Report Endpoint */ +    Endpoint_SelectEndpoint(MOUSE_IN_EPNUM); + +    /* Check if Mouse Endpoint Ready for Read/Write */ +    if (Endpoint_IsReadWriteAllowed()) +    { +        /* Write Mouse Report Data */ +        Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL); + +        /* Finalize the stream transfer to send the last packet */ +        Endpoint_ClearIN(); +    } +#endif +} + +static void send_system(uint16_t data) +{ +    report_extra_t r = { +        .report_id = REPORT_ID_SYSTEM, +        .usage = data +    }; +    Endpoint_SelectEndpoint(EXTRA_IN_EPNUM); +    if (Endpoint_IsReadWriteAllowed()) { +        Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL); +        Endpoint_ClearIN(); +    } +} + +static void send_consumer(uint16_t data) +{ +    report_extra_t r = { +        .report_id = REPORT_ID_CONSUMER, +        .usage = data +    }; +    Endpoint_SelectEndpoint(EXTRA_IN_EPNUM); +    if (Endpoint_IsReadWriteAllowed()) { +        Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL); +        Endpoint_ClearIN(); +    } +} + + +/******************************************************************************* + * sendchar + ******************************************************************************/ +int8_t sendchar(uint8_t c) +{ +    if (USB_DeviceState != DEVICE_STATE_Configured) +      return -1; + +    Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM); + +    uint8_t timeout = 10; +    uint16_t prevFN = USB_Device_GetFrameNumber(); +    while (!Endpoint_IsINReady()) { +        switch (USB_DeviceState) { +        case DEVICE_STATE_Unattached: +        case DEVICE_STATE_Suspended: +            return -1; +        } +        if (Endpoint_IsStalled()) +            return -1; +        if (prevFN != USB_Device_GetFrameNumber()) { +            if (!(timeout--)) +                return -1; +            prevFN = USB_Device_GetFrameNumber(); +        } +    } + +    Endpoint_Write_8(c); + +    // send when packet is full +    if (!Endpoint_IsReadWriteAllowed()) +        Endpoint_ClearIN(); + +    return 0; +} diff --git a/protocol/lufa/lufa.h b/protocol/lufa/lufa.h new file mode 100644 index 0000000000..71c279b0dc --- /dev/null +++ b/protocol/lufa/lufa.h @@ -0,0 +1,58 @@ +/*  + * Copyright 2012 Jun Wako <wakojun@gmail.com> + * This file is based on: + *     LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse + *     LUFA-120219/Demos/Device/Lowlevel/GenericHID + */ + +/* +             LUFA Library +     Copyright (C) Dean Camera, 2012. + +  dean [at] fourwalledcubicle [dot] com +           www.lufa-lib.org +*/ + +/* +  Copyright 2012  Dean Camera (dean [at] fourwalledcubicle [dot] com) +  Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com) + +  Permission to use, copy, modify, distribute, and sell this +  software and its documentation for any purpose is hereby granted +  without fee, provided that the above copyright notice appear in +  all copies and that both that the copyright notice and this +  permission notice and warranty disclaimer appear in supporting +  documentation, and that the name of the author not be used in +  advertising or publicity pertaining to distribution of the +  software without specific, written prior permission. + +  The author disclaim all warranties with regard to this +  software, including all implied warranties of merchantability +  and fitness.  In no event shall the author be liable for any +  special, indirect or consequential damages or any damages +  whatsoever resulting from loss of use, data or profits, whether +  in an action of contract, negligence or other tortious action, +  arising out of or in connection with the use or performance of +  this software. +*/ + +#ifndef _LUFA_H_ +#define _LUFA_H_ + +#include <avr/io.h> +#include <avr/wdt.h> +#include <avr/power.h> +#include <avr/interrupt.h> +#include <stdbool.h> +#include <string.h> +#include <LUFA/Version.h> +#include <LUFA/Drivers/USB/USB.h> + + +/* extra report structure */ +typedef struct { +    uint8_t  report_id; +    uint16_t usage; +} __attribute__ ((packed)) report_extra_t; + +#endif  | 
