- add LUFA boot mouse feature - remove report_id from mouse report - fix LUFA descriptortags/v1.9
uint8_t mods; | uint8_t mods; | ||||
uint8_t rserved; | uint8_t rserved; | ||||
uint8_t keys[REPORT_KEYS]; | uint8_t keys[REPORT_KEYS]; | ||||
} report_keyboard_t; | |||||
} __attribute__ ((packed)) report_keyboard_t; | |||||
typedef struct { | typedef struct { | ||||
uint8_t report_id; | |||||
uint8_t buttons; | uint8_t buttons; | ||||
int8_t x; | int8_t x; | ||||
int8_t y; | int8_t y; | ||||
int8_t v; | int8_t v; | ||||
int8_t h; | int8_t h; | ||||
} report_mouse_t; | |||||
} __attribute__ ((packed)) report_mouse_t; | |||||
#endif | #endif |
CONFIG_H = config.h | CONFIG_H = config.h | ||||
# Build Options | |||||
# comment out to disable the options. | |||||
# | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||||
#EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
#NKRO_ENABLE = yes # USB Nkey Rollover | |||||
# LUFA library compile-time options and predefined tokens | # LUFA library compile-time options and predefined tokens | ||||
LUFA_OPTS = -D USB_DEVICE_ONLY | LUFA_OPTS = -D USB_DEVICE_ONLY |
HID_RI_END_COLLECTION(0), | HID_RI_END_COLLECTION(0), | ||||
}; | }; | ||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM GenericReport[] = | |||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] = | |||||
{ | { | ||||
HID_RI_USAGE_PAGE(16, 0xFF00), /* Vendor Page 0 */ | HID_RI_USAGE_PAGE(16, 0xFF00), /* Vendor Page 0 */ | ||||
HID_RI_USAGE(8, 0x01), /* Vendor Usage 1 */ | HID_RI_USAGE(8, 0x01), /* Vendor Usage 1 */ | ||||
/* | /* | ||||
* Keyboard | * Keyboard | ||||
*/ | */ | ||||
.HID0_KeyboardInterface = | |||||
.Keyboard_Interface = | |||||
{ | { | ||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, | .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, | ||||
.InterfaceStrIndex = NO_DESCRIPTOR | .InterfaceStrIndex = NO_DESCRIPTOR | ||||
}, | }, | ||||
.HID0_KeyboardHID = | |||||
.Keyboard_HID = | |||||
{ | { | ||||
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, | .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, | ||||
.HIDReportLength = sizeof(KeyboardReport) | .HIDReportLength = sizeof(KeyboardReport) | ||||
}, | }, | ||||
.HID0_ReportINEndpoint = | |||||
.Keyboard_INEndpoint = | |||||
{ | { | ||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, | .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, | ||||
/* | /* | ||||
* Mouse | * Mouse | ||||
*/ | */ | ||||
.HID1_MouseInterface = | |||||
.Mouse_Interface = | |||||
{ | { | ||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, | .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, | ||||
.InterfaceStrIndex = NO_DESCRIPTOR | .InterfaceStrIndex = NO_DESCRIPTOR | ||||
}, | }, | ||||
.HID1_MouseHID = | |||||
.Mouse_HID = | |||||
{ | { | ||||
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, | .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, | ||||
.HIDReportLength = sizeof(MouseReport) | .HIDReportLength = sizeof(MouseReport) | ||||
}, | }, | ||||
.HID1_ReportINEndpoint = | |||||
.Mouse_INEndpoint = | |||||
{ | { | ||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, | .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, | ||||
}, | }, | ||||
/* | /* | ||||
* Generic | |||||
* Console | |||||
*/ | */ | ||||
.HID2_GenericInterface = | |||||
.Console_Interface = | |||||
{ | { | ||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, | .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, | ||||
.InterfaceStrIndex = NO_DESCRIPTOR | .InterfaceStrIndex = NO_DESCRIPTOR | ||||
}, | }, | ||||
.HID2_GenericHID = | |||||
.Console_HID = | |||||
{ | { | ||||
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, | .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, | ||||
.CountryCode = 0x00, | .CountryCode = 0x00, | ||||
.TotalReportDescriptors = 1, | .TotalReportDescriptors = 1, | ||||
.HIDReportType = HID_DTYPE_Report, | .HIDReportType = HID_DTYPE_Report, | ||||
.HIDReportLength = sizeof(GenericReport) | |||||
.HIDReportLength = sizeof(ConsoleReport) | |||||
}, | }, | ||||
.HID2_ReportINEndpoint = | |||||
.Console_INEndpoint = | |||||
{ | { | ||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, | .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, | ||||
.PollingIntervalMS = 0x01 | .PollingIntervalMS = 0x01 | ||||
}, | }, | ||||
.HID2_ReportOUTEndpoint = | |||||
.Console_OUTEndpoint = | |||||
{ | { | ||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, | .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, | ||||
case HID_DTYPE_HID: | case HID_DTYPE_HID: | ||||
switch (wIndex) { | switch (wIndex) { | ||||
case KEYBOARD_INTERFACE: | case KEYBOARD_INTERFACE: | ||||
Address = &ConfigurationDescriptor.HID0_KeyboardHID; | |||||
Address = &ConfigurationDescriptor.Keyboard_HID; | |||||
Size = sizeof(USB_HID_Descriptor_HID_t); | Size = sizeof(USB_HID_Descriptor_HID_t); | ||||
break; | break; | ||||
case MOUSE_INTERFACE: | case MOUSE_INTERFACE: | ||||
Address = &ConfigurationDescriptor.HID1_MouseHID; | |||||
Address = &ConfigurationDescriptor.Mouse_HID; | |||||
Size = sizeof(USB_HID_Descriptor_HID_t); | Size = sizeof(USB_HID_Descriptor_HID_t); | ||||
break; | break; | ||||
case GENERIC_INTERFACE: | case GENERIC_INTERFACE: | ||||
Address = &ConfigurationDescriptor.HID2_GenericHID; | |||||
Address = &ConfigurationDescriptor.Console_HID; | |||||
Size = sizeof(USB_HID_Descriptor_HID_t); | Size = sizeof(USB_HID_Descriptor_HID_t); | ||||
break; | break; | ||||
} | } | ||||
Size = sizeof(MouseReport); | Size = sizeof(MouseReport); | ||||
break; | break; | ||||
case GENERIC_INTERFACE: | case GENERIC_INTERFACE: | ||||
Address = &GenericReport; | |||||
Size = sizeof(GenericReport); | |||||
Address = &ConsoleReport; | |||||
Size = sizeof(ConsoleReport); | |||||
break; | break; | ||||
} | } | ||||
break; | break; |
USB_Descriptor_Configuration_Header_t Config; | USB_Descriptor_Configuration_Header_t Config; | ||||
// Keyboard HID Interface | // Keyboard HID Interface | ||||
USB_Descriptor_Interface_t HID0_KeyboardInterface; | |||||
USB_HID_Descriptor_HID_t HID0_KeyboardHID; | |||||
USB_Descriptor_Endpoint_t HID0_ReportINEndpoint; | |||||
USB_Descriptor_Interface_t Keyboard_Interface; | |||||
USB_HID_Descriptor_HID_t Keyboard_HID; | |||||
USB_Descriptor_Endpoint_t Keyboard_INEndpoint; | |||||
// Mouse HID Interface | // Mouse HID Interface | ||||
USB_Descriptor_Interface_t HID1_MouseInterface; | |||||
USB_HID_Descriptor_HID_t HID1_MouseHID; | |||||
USB_Descriptor_Endpoint_t HID1_ReportINEndpoint; | |||||
// Generic HID Interface | |||||
USB_Descriptor_Interface_t HID2_GenericInterface; | |||||
USB_HID_Descriptor_HID_t HID2_GenericHID; | |||||
USB_Descriptor_Endpoint_t HID2_ReportINEndpoint; | |||||
USB_Descriptor_Endpoint_t HID2_ReportOUTEndpoint; | |||||
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; | |||||
} USB_Descriptor_Configuration_t; | } USB_Descriptor_Configuration_t; | ||||
static void SetupHardware(void); | static void SetupHardware(void); | ||||
static void Generic_HID_Task(void); | |||||
static void Console_HID_Task(void); | |||||
int main(void) | int main(void) | ||||
{ | { | ||||
while (1) { | while (1) { | ||||
keyboard_proc(); | keyboard_proc(); | ||||
Generic_HID_Task(); | |||||
Console_HID_Task(); | |||||
USB_USBTask(); | USB_USBTask(); | ||||
} | } | ||||
} | } | ||||
USB_Init(); | USB_Init(); | ||||
} | } | ||||
static void Generic_HID_Task(void) | |||||
static void Console_HID_Task(void) | |||||
{ | { | ||||
/* Device must be connected and configured for the task to run */ | /* Device must be connected and configured for the task to run */ | ||||
if (USB_DeviceState != DEVICE_STATE_Configured) | if (USB_DeviceState != DEVICE_STATE_Configured) | ||||
if (Endpoint_IsReadWriteAllowed()) | if (Endpoint_IsReadWriteAllowed()) | ||||
{ | { | ||||
/* Create a temporary buffer to hold the read in report from the host */ | /* Create a temporary buffer to hold the read in report from the host */ | ||||
uint8_t GenericData[GENERIC_REPORT_SIZE]; | |||||
uint8_t ConsoleData[GENERIC_REPORT_SIZE]; | |||||
/* Read Generic Report Data */ | |||||
Endpoint_Read_Stream_LE(&GenericData, sizeof(GenericData), NULL); | |||||
/* Read Console Report Data */ | |||||
Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL); | |||||
/* Process Generic Report Data */ | |||||
//ProcessGenericHIDReport(GenericData); | |||||
/* Process Console Report Data */ | |||||
//ProcessConsoleHIDReport(ConsoleData); | |||||
} | } | ||||
/* Finalize the stream transfer to send the last packet */ | /* Finalize the stream transfer to send the last packet */ | ||||
ConfigSuccess &= Endpoint_ConfigureEndpoint(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, | ConfigSuccess &= Endpoint_ConfigureEndpoint(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, | ||||
HID_EPSIZE, ENDPOINT_BANK_SINGLE); | HID_EPSIZE, ENDPOINT_BANK_SINGLE); | ||||
/* Setup Generic HID Report Endpoints */ | |||||
/* Setup Console HID Report Endpoints */ | |||||
ConfigSuccess &= Endpoint_ConfigureEndpoint(GENERIC_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, | ConfigSuccess &= Endpoint_ConfigureEndpoint(GENERIC_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, | ||||
GENERIC_EPSIZE, ENDPOINT_BANK_SINGLE); | GENERIC_EPSIZE, ENDPOINT_BANK_SINGLE); | ||||
ConfigSuccess &= Endpoint_ConfigureEndpoint(GENERIC_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT, | ConfigSuccess &= Endpoint_ConfigureEndpoint(GENERIC_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT, | ||||
GENERIC_EPSIZE, ENDPOINT_BANK_SINGLE); | GENERIC_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. | /** Event handler for the USB_ControlRequest event. | ||||
* This is fired before passing along unhandled control requests to the library for processing internally. | * This is fired before passing along unhandled control requests to the library for processing internally. | ||||
*/ | */ | ||||
if (Endpoint_IsReadWriteAllowed()) | if (Endpoint_IsReadWriteAllowed()) | ||||
{ | { | ||||
/* Write Mouse Report Data */ | /* Write Mouse Report Data */ | ||||
Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL); | |||||
/* Mouse report data structure | |||||
* LUFA: { buttons, x, y } | |||||
* tmk: { buttons, x, y, v, h } | |||||
*/ | |||||
//Endpoint_Write_Stream_LE((uint8_t *)report+1, 3, NULL); | |||||
Endpoint_Write_Stream_LE(report, 3, NULL); | |||||
/* Finalize the stream transfer to send the last packet */ | /* Finalize the stream transfer to send the last packet */ | ||||
Endpoint_ClearIN(); | Endpoint_ClearIN(); |
debug("initForUsbConnectivity()\n"); | debug("initForUsbConnectivity()\n"); | ||||
initForUsbConnectivity(); | initForUsbConnectivity(); | ||||
int i; | |||||
while(--i){ /* To configured */ | |||||
usbPoll(); | |||||
_delay_ms(1); | |||||
} | |||||
debug("main loop\n"); | debug("main loop\n"); | ||||
while (1) { | while (1) { | ||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
if (!suspended) | |||||
if (!suspended) { | |||||
usbPoll(); | usbPoll(); | ||||
keyboard_proc(); | |||||
if (!suspended) | |||||
// TODO: configuration process is incosistent. it sometime fails. | |||||
// To prevent failing to configure NOT scan keyboard during configuration | |||||
if (usbConfiguration && usbInterruptIsReady()) { | |||||
keyboard_proc(); | |||||
} | |||||
vusb_transfer_keyboard(); | vusb_transfer_keyboard(); | ||||
} | |||||
} | } | ||||
} | } |
} | } | ||||
typedef struct { | |||||
uint8_t report_id; | |||||
report_mouse_t report; | |||||
} __attribute__ ((packed)) vusb_mouse_report_t; | |||||
static void send_mouse(report_mouse_t *report) | static void send_mouse(report_mouse_t *report) | ||||
{ | { | ||||
report->report_id = REPORT_ID_MOUSE; | |||||
vusb_mouse_report_t r = { | |||||
.report_id = REPORT_ID_MOUSE, | |||||
.report = *report | |||||
}; | |||||
if (usbInterruptIsReady3()) { | if (usbInterruptIsReady3()) { | ||||
usbSetInterrupt3((void *)report, sizeof(*report)); | |||||
usbSetInterrupt3((void *)&r, sizeof(vusb_mouse_report_t)); | |||||
} | } | ||||
} | } | ||||
/* | |||||
typedef struct { | |||||
uint8_t report_id; | |||||
uint8_t data0; | |||||
uint8_t data1; | |||||
} __attribute__ ((packed)) vusb_system_report_t; | |||||
*/ | |||||
static void send_system(uint16_t data) | static void send_system(uint16_t data) | ||||
{ | { | ||||
/* | |||||
// Not need static? | // Not need static? | ||||
static uint8_t report[] = { REPORT_ID_SYSTEM, 0, 0 }; | static uint8_t report[] = { REPORT_ID_SYSTEM, 0, 0 }; | ||||
report[1] = data&0xFF; | report[1] = data&0xFF; | ||||
report[2] = (data>>8)&0xFF; | report[2] = (data>>8)&0xFF; | ||||
*/ | |||||
/* | |||||
vusb_system_report_t r = { | |||||
.report_id = REPORT_ID_SYSTEM, | |||||
.data0 = data&0xFF, | |||||
.data1 = (data>>8)&0xFF | |||||
}; | |||||
if (usbInterruptIsReady3()) { | if (usbInterruptIsReady3()) { | ||||
usbSetInterrupt3((void *)&report, sizeof(report)); | |||||
usbSetInterrupt3((void *)&r, sizeof(vusb_system_report_t)); | |||||
} | } | ||||
*/ | |||||
} | } | ||||
static void send_consumer(uint16_t data) | static void send_consumer(uint16_t data) |