diff options
author | tmk <nobody@nowhere> | 2012-06-28 23:05:21 +0900 |
---|---|---|
committer | tmk <nobody@nowhere> | 2012-06-28 23:05:21 +0900 |
commit | cc68adeb5744cba9e8650bab04ff0f0a4033db9f (patch) | |
tree | e853b1e6e48cf61b7763615a7259765a2095b621 /protocol/lufa | |
parent | 3d81d5221eac9ca9620ba9043a250dcb8371b22e (diff) |
Add protocol/lufa. LUFA supported now.
Diffstat (limited to 'protocol/lufa')
-rw-r--r-- | protocol/lufa/descriptor.c | 509 | ||||
-rw-r--r-- | protocol/lufa/descriptor.h | 98 | ||||
-rw-r--r-- | protocol/lufa/lufa.c | 386 | ||||
-rw-r--r-- | protocol/lufa/lufa.h | 45 |
4 files changed, 1038 insertions, 0 deletions
diff --git a/protocol/lufa/descriptor.c b/protocol/lufa/descriptor.c new file mode 100644 index 0000000000..e9925cca29 --- /dev/null +++ b/protocol/lufa/descriptor.c @@ -0,0 +1,509 @@ +/* + * 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_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), /* 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, 0xFF00), /* Vendor Page 0 */ + HID_RI_USAGE(8, 0x01), /* Vendor Usage 1 */ + HID_RI_COLLECTION(8, 0x01), /* Application */ + 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, CONSOLE_EPSIZE), + 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, CONSOLE_EPSIZE), + HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), + HID_RI_END_COLLECTION(0), +}; + +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), +}; + +/******************************************************************************* + * 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 + */ + .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 + }, + + /* + * 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 + */ + .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 + }, +}; + + +/******************************************************************************* + * 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; + case MOUSE_INTERFACE: + Address = &ConfigurationDescriptor.Mouse_HID; + Size = sizeof(USB_HID_Descriptor_HID_t); + break; + case CONSOLE_INTERFACE: + Address = &ConfigurationDescriptor.Console_HID; + Size = sizeof(USB_HID_Descriptor_HID_t); + break; + case EXTRA_INTERFACE: + Address = &ConfigurationDescriptor.Extra_HID; + Size = sizeof(USB_HID_Descriptor_HID_t); + break; + } + break; + case HID_DTYPE_Report: + switch (wIndex) { + case KEYBOARD_INTERFACE: + Address = &KeyboardReport; + Size = sizeof(KeyboardReport); + break; + case MOUSE_INTERFACE: + Address = &MouseReport; + Size = sizeof(MouseReport); + break; + case CONSOLE_INTERFACE: + Address = &ConsoleReport; + Size = sizeof(ConsoleReport); + break; + case EXTRA_INTERFACE: + Address = &ExtraReport; + Size = sizeof(ExtraReport); + break; + } + break; + } + + *DescriptorAddress = Address; + return Size; +} diff --git a/protocol/lufa/descriptor.h b/protocol/lufa/descriptor.h new file mode 100644 index 0000000000..6b1b4d4845 --- /dev/null +++ b/protocol/lufa/descriptor.h @@ -0,0 +1,98 @@ +/* + 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 + USB_Descriptor_Interface_t Mouse_Interface; + USB_HID_Descriptor_HID_t Mouse_HID; + USB_Descriptor_Endpoint_t Mouse_INEndpoint; + + // 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 + USB_Descriptor_Interface_t Extra_Interface; + USB_HID_Descriptor_HID_t Extra_HID; + USB_Descriptor_Endpoint_t Extra_INEndpoint; +} USB_Descriptor_Configuration_t; + + +/* nubmer of interfaces */ +#define TOTAL_INTERFACES 4 + +/* index of interface */ +#define KEYBOARD_INTERFACE 0 +#define MOUSE_INTERFACE 1 +#define CONSOLE_INTERFACE 2 +#define EXTRA_INTERFACE 3 + +// 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..09da96b2e5 --- /dev/null +++ b/protocol/lufa/lufa.c @@ -0,0 +1,386 @@ +/* + * 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 keyboard_led_stats = 0; + +// TODO: impl Control Request GET_REPORT +static report_keyboard_t keyboard_report_sent; +static report_mouse_t mouse_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 + _delay_ms(5000); + USB_USBTask(); + print("abcdefg\n"); + USB_USBTask(); +*/ + + 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); + + /* Setup Mouse HID Report Endpoint */ + ConfigSuccess &= Endpoint_ConfigureEndpoint(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, + MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE); + + /* 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); + + /* Setup Extra HID Report Endpoint */ + ConfigSuccess &= Endpoint_ConfigureEndpoint(EXTRA_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, + EXTRA_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; + case MOUSE_INTERFACE: + // TODO: test/check + ReportData = (uint8_t*)&mouse_report_sent; + ReportSize = sizeof(mouse_report_sent); + break; + case CONSOLE_INTERFACE: + break; + case EXTRA_INTERFACE: + 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)) + { + Endpoint_ClearSETUP(); + + /* Wait until the LED report has been sent by the host */ + while (!(Endpoint_IsOUTReceived())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } + + // Interface + switch (USB_ControlRequest.wIndex) { + case KEYBOARD_INTERFACE: + // TODO: test/check + /* Read in the LED report from the host */ + keyboard_led_stats = Endpoint_Read_8(); + break; + case MOUSE_INTERFACE: + break; + case CONSOLE_INTERFACE: + break; + case EXTRA_INTERFACE: + break; + } + + Endpoint_ClearOUT(); + 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) +{ + /* 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(); + } + mouse_report_sent = *report; +} + +typedef struct { + uint8_t report_id; + uint16_t usage; +} __attribute__ ((packed)) report_extra_t; + +static void send_system(uint16_t data) +{ + Endpoint_SelectEndpoint(EXTRA_IN_EPNUM); + if (Endpoint_IsReadWriteAllowed()) { + report_extra_t r = { + .report_id = REPORT_ID_SYSTEM, + .usage = data + }; + Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL); + Endpoint_ClearIN(); + } +} + +static void send_consumer(uint16_t data) +{ + Endpoint_SelectEndpoint(EXTRA_IN_EPNUM); + if (Endpoint_IsReadWriteAllowed()) { + report_extra_t r = { + .report_id = REPORT_ID_CONSUMER, + .usage = data + }; + 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; |