diff --git a/keyboard/lufa/Descriptors.c b/keyboard/lufa/Descriptors.c index 3195aa77..a4e9defa 100644 --- a/keyboard/lufa/Descriptors.c +++ b/keyboard/lufa/Descriptors.c @@ -1,359 +1,432 @@ -/* - 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 - * - * USB Device Descriptors, for library use when in USB device mode. Descriptors are special - * computer-readable structures which the host requests upon device enumeration, to determine - * the device's capabilities and functions. - */ - -#include "Descriptors.h" - -/** HID class report descriptor. This is a special descriptor constructed with values from the - * USBIF HID class specification to describe the reports and capabilities of the HID device. This - * descriptor is parsed by the host and its contents used to determine what data (and in what encoding) - * the device will send, and what it may be sent back from the host. Refer to the HID specification for - * more details on HID report descriptors. - * - * This descriptor describes the mouse HID interface's report structure. - */ -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), - HID_RI_USAGE_MAXIMUM(8, 0x03), - HID_RI_LOGICAL_MINIMUM(8, 0x00), - HID_RI_LOGICAL_MAXIMUM(8, 0x01), - HID_RI_REPORT_COUNT(8, 0x03), - 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, 0x05), - 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, -1), - HID_RI_LOGICAL_MAXIMUM(8, 1), - HID_RI_PHYSICAL_MINIMUM(8, -1), - HID_RI_PHYSICAL_MAXIMUM(8, 1), - 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_END_COLLECTION(0), - HID_RI_END_COLLECTION(0), -}; - -/** Same as the MouseReport structure, but defines the keyboard HID interface's report structure. */ -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_SIZE(8, 0x01), - HID_RI_REPORT_COUNT(8, 0x08), - 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_LOGICAL_MINIMUM(8, 0x00), - HID_RI_LOGICAL_MAXIMUM(8, 0x65), - HID_RI_USAGE_PAGE(8, 0x07), /* Keyboard */ - HID_RI_USAGE_MINIMUM(8, 0x00), /* Reserved (no event indicated) */ - HID_RI_USAGE_MAXIMUM(8, 0x65), /* Keyboard Application */ - 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), -}; - -/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall - * device characteristics, including the supported USB version, control endpoint size and the - * number of device configurations. The descriptor is read out by the USB host when the enumeration - * process begins. - */ -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 = 0x03EB, - .ProductID = 0x204D, - .ReleaseNumber = VERSION_BCD(00.01), - - .ManufacturerStrIndex = 0x01, - .ProductStrIndex = 0x02, - .SerialNumStrIndex = NO_DESCRIPTOR, - - .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS -}; - -/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage - * of the device in one of its supported configurations, including information about any device interfaces - * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting - * a configuration so that the host may correctly communicate with the USB device. - */ -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 = 2, - - .ConfigurationNumber = 1, - .ConfigurationStrIndex = NO_DESCRIPTOR, - - .ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_SELFPOWERED), - - .MaxPowerConsumption = USB_CONFIG_POWER_MA(100) - }, - - .HID1_KeyboardInterface = - { - .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, - - .InterfaceNumber = 0x00, - .AlternateSetting = 0x00, - - .TotalEndpoints = 2, - - .Class = HID_CSCP_HIDClass, - .SubClass = HID_CSCP_BootSubclass, - .Protocol = HID_CSCP_KeyboardBootProtocol, - - .InterfaceStrIndex = NO_DESCRIPTOR - }, - - .HID1_KeyboardHID = - { - .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) - }, - - .HID1_ReportINEndpoint = - { - .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 = HID_EPSIZE, - .PollingIntervalMS = 0x01 - }, - - .HID1_ReportOUTEndpoint = - { - .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, - - .EndpointAddress = (ENDPOINT_DIR_OUT | KEYBOARD_OUT_EPNUM), - .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), - .EndpointSize = HID_EPSIZE, - .PollingIntervalMS = 0x01 - }, - - .HID2_MouseInterface = - { - .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, - - .InterfaceNumber = 0x01, - .AlternateSetting = 0x00, - - .TotalEndpoints = 1, - - .Class = HID_CSCP_HIDClass, - .SubClass = HID_CSCP_BootSubclass, - .Protocol = HID_CSCP_MouseBootProtocol, - - .InterfaceStrIndex = NO_DESCRIPTOR - }, - - .HID2_MouseHID = - { - .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) - }, - - .HID2_ReportINEndpoint = - { - .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 = HID_EPSIZE, - .PollingIntervalMS = 0x01 - } -}; - -/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests - * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate - * via the language ID table available at USB.org what languages the device supports for its string descriptors. - */ -const USB_Descriptor_String_t PROGMEM LanguageString = -{ - .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String}, - - .UnicodeString = {LANGUAGE_ID_ENG} -}; - -/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable - * form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device - * Descriptor. - */ -const USB_Descriptor_String_t PROGMEM ManufacturerString = -{ - .Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String}, - - .UnicodeString = L"Dean Camera" -}; - -/** Product descriptor string. This is a Unicode string containing the product's details in human readable form, - * and is read out upon request by the host when the appropriate string ID is requested, listed in the Device - * Descriptor. - */ -const USB_Descriptor_String_t PROGMEM ProductString = -{ - .Header = {.Size = USB_STRING_LEN(28), .Type = DTYPE_String}, - - .UnicodeString = L"LUFA Mouse and Keyboard Demo" -}; - -/** 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 DescriptorNumber = (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 (DescriptorNumber) - { - 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: - if (!(wIndex)) - { - Address = &ConfigurationDescriptor.HID1_KeyboardHID; - Size = sizeof(USB_HID_Descriptor_HID_t); - } - else - { - Address = &ConfigurationDescriptor.HID2_MouseHID; - Size = sizeof(USB_HID_Descriptor_HID_t); - } - break; - case HID_DTYPE_Report: - if (!(wIndex)) - { - Address = &KeyboardReport; - Size = sizeof(KeyboardReport); - } - else - { - Address = &MouseReport; - Size = sizeof(MouseReport); - } - - break; - } - - *DescriptorAddress = Address; - return Size; -} - +/* + * Copyright 2012 Jun Wako + * 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 + * + * USB Device Descriptors, for library use when in USB device mode. Descriptors are special + * computer-readable structures which the host requests upon device enumeration, to determine + * the device's capabilities and functions. + */ + +#include "Descriptors.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_SIZE(8, 0x01), + HID_RI_REPORT_COUNT(8, 0x08), + 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_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(8, 0x65), + HID_RI_USAGE_PAGE(8, 0x07), /* Keyboard */ + HID_RI_USAGE_MINIMUM(8, 0x00), /* Reserved (no event indicated) */ + HID_RI_USAGE_MAXIMUM(8, 0x65), /* Keyboard Application */ + 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), + HID_RI_USAGE_MAXIMUM(8, 0x03), + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(8, 0x01), + HID_RI_REPORT_COUNT(8, 0x03), + 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, 0x05), + 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, -1), + HID_RI_LOGICAL_MAXIMUM(8, 1), + HID_RI_PHYSICAL_MINIMUM(8, -1), + HID_RI_PHYSICAL_MAXIMUM(8, 1), + 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_END_COLLECTION(0), + HID_RI_END_COLLECTION(0), +}; + +const USB_Descriptor_HIDReport_Datatype_t PROGMEM GenericReport[] = +{ + HID_RI_USAGE_PAGE(16, 0xFF00), /* Vendor Page 0 */ + HID_RI_USAGE(8, 0x01), /* Vendor Usage 1 */ + HID_RI_COLLECTION(8, 0x01), /* Vendor Usage 1 */ + HID_RI_USAGE(8, 0x02), /* Vendor Usage 2 */ + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(8, 0xFF), + HID_RI_REPORT_SIZE(8, 0x08), + HID_RI_REPORT_COUNT(8, GENERIC_REPORT_SIZE), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), + HID_RI_USAGE(8, 0x03), /* Vendor Usage 3 */ + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(8, 0xFF), + HID_RI_REPORT_SIZE(8, 0x08), + HID_RI_REPORT_COUNT(8, GENERIC_REPORT_SIZE), + HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), + HID_RI_END_COLLECTION(0), +}; + + +/******************************************************************************* + * 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 = 0xFEED, + .ProductID = 0x204D, + .ReleaseNumber = VERSION_BCD(00.02), + + .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 = 3, + + .ConfigurationNumber = 1, + .ConfigurationStrIndex = NO_DESCRIPTOR, + + .ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_SELFPOWERED), //TODO: bus powered? + + .MaxPowerConsumption = USB_CONFIG_POWER_MA(100) + }, + + /* + * Keyboard + */ + .HID1_KeyboardInterface = + { + .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + + .InterfaceNumber = 0x00, + .AlternateSetting = 0x00, + + .TotalEndpoints = 2, + + .Class = HID_CSCP_HIDClass, + .SubClass = HID_CSCP_BootSubclass, + .Protocol = HID_CSCP_KeyboardBootProtocol, + + .InterfaceStrIndex = NO_DESCRIPTOR + }, + + .HID1_KeyboardHID = + { + .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) + }, + + .HID1_ReportINEndpoint = + { + .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 = HID_EPSIZE, + .PollingIntervalMS = 0x01 + }, + + .HID1_ReportOUTEndpoint = + { + .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + + .EndpointAddress = (ENDPOINT_DIR_OUT | KEYBOARD_OUT_EPNUM), + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = HID_EPSIZE, + .PollingIntervalMS = 0x01 + }, + + /* + * Mouse + */ + .HID2_MouseInterface = + { + .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + + .InterfaceNumber = 0x01, + .AlternateSetting = 0x00, + + .TotalEndpoints = 1, + + .Class = HID_CSCP_HIDClass, + .SubClass = HID_CSCP_BootSubclass, + .Protocol = HID_CSCP_MouseBootProtocol, + + .InterfaceStrIndex = NO_DESCRIPTOR + }, + + .HID2_MouseHID = + { + .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) + }, + + .HID2_ReportINEndpoint = + { + .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 = HID_EPSIZE, + .PollingIntervalMS = 0x01 + }, + + /* + * Generic + */ + .HID3_GenericInterface = + { + .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + + .InterfaceNumber = 0x02, + .AlternateSetting = 0x00, + + .TotalEndpoints = 2, + + .Class = HID_CSCP_HIDClass, + .SubClass = HID_CSCP_NonBootSubclass, + .Protocol = HID_CSCP_NonBootProtocol, + + .InterfaceStrIndex = NO_DESCRIPTOR + }, + + .HID3_GenericHID = + { + .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(GenericReport) + }, + + .HID3_ReportINEndpoint = + { + .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + + .EndpointAddress = (ENDPOINT_DIR_IN | GENERIC_IN_EPNUM), + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = GENERIC_EPSIZE, + .PollingIntervalMS = 0x01 + }, + + .HID3_ReportOUTEndpoint = + { + .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + + .EndpointAddress = (ENDPOINT_DIR_OUT | GENERIC_OUT_EPNUM), + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = GENERIC_EPSIZE, + .PollingIntervalMS = 0x01 + } +}; + + +/******************************************************************************* + * 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 = L"Dean Camera" // TODO: +}; + +const USB_Descriptor_String_t PROGMEM ProductString = +{ + .Header = {.Size = USB_STRING_LEN(28), .Type = DTYPE_String}, + + .UnicodeString = L"LUFA Mouse and Keyboard Demo" // TODO: +}; + + +/** 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 0: + Address = &ConfigurationDescriptor.HID1_KeyboardHID; + Size = sizeof(USB_HID_Descriptor_HID_t); + break; + case 1: + Address = &ConfigurationDescriptor.HID2_MouseHID; + Size = sizeof(USB_HID_Descriptor_HID_t); + break; + case 2: + Address = &ConfigurationDescriptor.HID3_GenericHID; + Size = sizeof(USB_HID_Descriptor_HID_t); + break; + } + break; + case HID_DTYPE_Report: + switch (wIndex) { + case 0: + Address = &KeyboardReport; + Size = sizeof(KeyboardReport); + break; + case 1: + Address = &MouseReport; + Size = sizeof(MouseReport); + break; + case 2: + Address = &GenericReport; + Size = sizeof(GenericReport); + break; + } + break; + } + + *DescriptorAddress = Address; + return Size; +} diff --git a/keyboard/lufa/Descriptors.h b/keyboard/lufa/Descriptors.h index 05b2035b..03e2426a 100644 --- a/keyboard/lufa/Descriptors.h +++ b/keyboard/lufa/Descriptors.h @@ -37,51 +37,48 @@ #ifndef _DESCRIPTORS_H_ #define _DESCRIPTORS_H_ - /* Includes: */ - #include +#include +#include - #include - /* Type Defines: */ - /** Type define for the device configuration descriptor structure. This must be defined in the - * application code, as the configuration descriptor contains several sub-descriptors which - * vary between devices, and which describe the device's usage to the host. - */ - typedef struct - { - USB_Descriptor_Configuration_Header_t Config; +typedef struct +{ + USB_Descriptor_Configuration_Header_t Config; - // Keyboard HID Interface - USB_Descriptor_Interface_t HID1_KeyboardInterface; - USB_HID_Descriptor_HID_t HID1_KeyboardHID; - USB_Descriptor_Endpoint_t HID1_ReportINEndpoint; - USB_Descriptor_Endpoint_t HID1_ReportOUTEndpoint; + // Keyboard HID Interface + USB_Descriptor_Interface_t HID1_KeyboardInterface; + USB_HID_Descriptor_HID_t HID1_KeyboardHID; + USB_Descriptor_Endpoint_t HID1_ReportINEndpoint; + USB_Descriptor_Endpoint_t HID1_ReportOUTEndpoint; - // Mouse HID Interface - USB_Descriptor_Interface_t HID2_MouseInterface; - USB_HID_Descriptor_HID_t HID2_MouseHID; - USB_Descriptor_Endpoint_t HID2_ReportINEndpoint; - USB_Descriptor_Endpoint_t HID2_ReportOUTEndpoint; - } USB_Descriptor_Configuration_t; + // Mouse HID Interface + USB_Descriptor_Interface_t HID2_MouseInterface; + USB_HID_Descriptor_HID_t HID2_MouseHID; + USB_Descriptor_Endpoint_t HID2_ReportINEndpoint; - /* Macros: */ - /** Endpoint number of the Keyboard HID reporting IN endpoint. */ - #define KEYBOARD_IN_EPNUM 1 + // Generic HID Interface + USB_Descriptor_Interface_t HID3_GenericInterface; + USB_HID_Descriptor_HID_t HID3_GenericHID; + USB_Descriptor_Endpoint_t HID3_ReportINEndpoint; + USB_Descriptor_Endpoint_t HID3_ReportOUTEndpoint; +} USB_Descriptor_Configuration_t; - /** Endpoint number of the Keyboard HID reporting OUT endpoint. */ - #define KEYBOARD_OUT_EPNUM 2 - /** Endpoint number of the Mouse HID reporting IN endpoint. */ - #define MOUSE_IN_EPNUM 3 +// Endopoint number/size +#define KEYBOARD_IN_EPNUM 1 +#define KEYBOARD_OUT_EPNUM 2 +#define MOUSE_IN_EPNUM 3 +#define GENERIC_IN_EPNUM 4 +#define GENERIC_OUT_EPNUM 5 - /** Size in bytes of each of the HID reporting IN and OUT endpoints. */ - #define HID_EPSIZE 8 +#define HID_EPSIZE 8 +#define GENERIC_EPSIZE 8 +#define GENERIC_REPORT_SIZE 8 - /* Function Prototypes: */ - 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); + +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/keyboard/lufa/Makefile b/keyboard/lufa/Makefile index 1d2f712d..115c7e6e 100644 --- a/keyboard/lufa/Makefile +++ b/keyboard/lufa/Makefile @@ -128,8 +128,7 @@ LSRC = $(TARGET).c \ SRC = $(subst $(LUFA_PATH)/LUFA/,,$(LSRC)) SRC += keymap.c \ matrix.c \ - led.c \ - sendchar_null.c + led.c CONFIG_H = config.h diff --git a/keyboard/lufa/lufa.c b/keyboard/lufa/lufa.c index d7e7c165..d841f45c 100644 --- a/keyboard/lufa/lufa.c +++ b/keyboard/lufa/lufa.c @@ -1,6 +1,8 @@ /* * Copyright 2012 Jun Wako - * This file is based on LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse. + * This file is based on: + * LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse + * LUFA-120219/Demos/Device/Lowlevel/GenericHID */ /* @@ -38,6 +40,8 @@ #include "host.h" #include "host_driver.h" #include "keyboard.h" +#include "sendchar.h" +#include "debug.h" #include "lufa.h" static uint8_t keyboard_led_stats = 0; @@ -64,11 +68,21 @@ int main(void) SetupHardware(); sei(); + print_enable = true; + debug_enable = true; + debug_matrix = true; + debug_keyboard = true; + debug_mouse = true; + + _delay_ms(3000); + print("abcdefg\n"); + keyboard_init(); host_set_driver(&lufa_driver); while (1) { keyboard_proc(); Keyboard_HID_Task(); + Generic_HID_Task(); USB_USBTask(); } } @@ -112,6 +126,12 @@ void EVENT_USB_Device_ConfigurationChanged(void) /* Setup Mouse HID Report Endpoint */ ConfigSuccess &= Endpoint_ConfigureEndpoint(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, HID_EPSIZE, ENDPOINT_BANK_SINGLE); + + /* Setup Generic HID Report Endpoints */ + ConfigSuccess &= Endpoint_ConfigureEndpoint(GENERIC_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, + GENERIC_EPSIZE, ENDPOINT_BANK_SINGLE); + ConfigSuccess &= Endpoint_ConfigureEndpoint(GENERIC_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT, + GENERIC_EPSIZE, ENDPOINT_BANK_SINGLE); } /** Event handler for the USB_ControlRequest event. @@ -119,8 +139,8 @@ void EVENT_USB_Device_ConfigurationChanged(void) */ void EVENT_USB_Device_ControlRequest(void) { - uint8_t* ReportData; - uint8_t ReportSize; + uint8_t* ReportData = NULL; + uint8_t ReportSize = 0; /* Handle HID Class specific requests */ switch (USB_ControlRequest.bRequest) @@ -130,16 +150,18 @@ void EVENT_USB_Device_ControlRequest(void) { Endpoint_ClearSETUP(); - /* Determine if it is the mouse or the keyboard data that is being requested */ - if (!(USB_ControlRequest.wIndex)) - { + // Interface + switch (USB_ControlRequest.wIndex) { + case 1: // Keyboard ReportData = (uint8_t*)&keyboard_report_sent; ReportSize = sizeof(keyboard_report_sent); - } - else - { + break; + case 2: // Mouse ReportData = (uint8_t*)&mouse_report_sent; ReportSize = sizeof(mouse_report_sent); + break; + case 3: // Generic + break; } /* Write the report data to the control endpoint */ @@ -160,8 +182,17 @@ void EVENT_USB_Device_ControlRequest(void) return; } - /* Read in the LED report from the host */ - keyboard_led_stats = Endpoint_Read_8(); + // Interface + switch (USB_ControlRequest.wIndex) { + case 1: // Keyboard + /* Read in the LED report from the host */ + keyboard_led_stats = Endpoint_Read_8(); + break; + case 2: // Mouse + break; + case 3: // Generic + break; + } Endpoint_ClearOUT(); Endpoint_ClearStatusStage(); @@ -176,6 +207,10 @@ void EVENT_USB_Device_ControlRequest(void) */ void Keyboard_HID_Task(void) { + /* Device must be connected and configured for the task to run */ + if (USB_DeviceState != DEVICE_STATE_Configured) + return; + /* Select the Keyboard LED Report Endpoint */ Endpoint_SelectEndpoint(KEYBOARD_OUT_EPNUM); @@ -190,6 +225,40 @@ void Keyboard_HID_Task(void) } } +void Generic_HID_Task(void) +{ + /* Device must be connected and configured for the task to run */ + if (USB_DeviceState != DEVICE_STATE_Configured) + return; + + Endpoint_SelectEndpoint(GENERIC_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 GenericData[GENERIC_REPORT_SIZE]; + + /* Read Generic Report Data */ + Endpoint_Read_Stream_LE(&GenericData, sizeof(GenericData), NULL); + + /* Process Generic Report Data */ + //TODO: ProcessGenericHIDReport(GenericData); + } + + /* Finalize the stream transfer to send the last packet */ + Endpoint_ClearOUT(); + } + + /* IN packet */ + Endpoint_SelectEndpoint(GENERIC_IN_EPNUM); + // send IN packet + if (Endpoint_IsINReady()) + Endpoint_ClearIN(); +} /******************************************************************************* * Host driver @@ -241,3 +310,41 @@ static void send_system(uint16_t data) static void send_consumer(uint16_t data) { } + + +/******************************************************************************* + * sendchar + ******************************************************************************/ +int8_t sendchar(uint8_t c) +{ + if (USB_DeviceState != DEVICE_STATE_Configured) + return -1; + + Endpoint_SelectEndpoint(GENERIC_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; + uint16_t currFN = USB_Device_GetFrameNumber(); + 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/keyboard/lufa/lufa.h b/keyboard/lufa/lufa.h index 74fe0b72..3ba14b36 100644 --- a/keyboard/lufa/lufa.h +++ b/keyboard/lufa/lufa.h @@ -65,7 +65,7 @@ void SetupHardware(void); void Keyboard_ProcessLEDReport(const uint8_t LEDStatus); void Keyboard_HID_Task(void); - void Mouse_HID_Task(void); + void Generic_HID_Task(void); void EVENT_USB_Device_Connect(void); void EVENT_USB_Device_Disconnect(void);