]> git.friedersdorff.com Git - max/tmk_keyboard.git/blobdiff - keyboard/lufa/lufa.c
Add consumer/system control feature to LUFA.
[max/tmk_keyboard.git] / keyboard / lufa / lufa.c
index d841f45c6aaa8cea7b30411b22a01cf6154d6014..09da96b2e572860d640e08a378c92d9a8fee1b26 100644 (file)
 #include "keyboard.h"
 #include "sendchar.h"
 #include "debug.h"
+
+#include "descriptor.h"
 #include "lufa.h"
 
 static uint8_t keyboard_led_stats = 0;
-report_keyboard_t keyboard_report_sent;
-report_mouse_t mouse_report_sent;
+
+// 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);
@@ -63,6 +67,9 @@ static host_driver_t lufa_driver = {
 };
 
 
+static void SetupHardware(void);
+static void Console_HID_Task(void);
+
 int main(void)
 {
     SetupHardware();
@@ -74,20 +81,23 @@ int main(void)
     debug_keyboard = true;
     debug_mouse = true;
 
-    _delay_ms(3000);
+/* 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();
-        Keyboard_HID_Task();
-        Generic_HID_Task();
+
+        Console_HID_Task();
         USB_USBTask();
     }
 }
 
-/** Configures the board hardware and chip peripherals for the demo's functionality. */
 void SetupHardware(void)
 {
     /* Disable watchdog if enabled by bootloader/fuses */
@@ -100,6 +110,46 @@ void SetupHardware(void)
     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)
 {
@@ -119,21 +169,36 @@ void EVENT_USB_Device_ConfigurationChanged(void)
 
     /* Setup Keyboard HID Report Endpoints */
     ConfigSuccess &= Endpoint_ConfigureEndpoint(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
-                                                HID_EPSIZE, ENDPOINT_BANK_SINGLE);
-    ConfigSuccess &= Endpoint_ConfigureEndpoint(KEYBOARD_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
-                                                HID_EPSIZE, ENDPOINT_BANK_SINGLE);
+                                                KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
 
     /* Setup Mouse HID Report Endpoint */
     ConfigSuccess &= Endpoint_ConfigureEndpoint(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
-                                                HID_EPSIZE, ENDPOINT_BANK_SINGLE);
+                                                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 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);
+    /* 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.
  */
@@ -152,15 +217,19 @@ void EVENT_USB_Device_ControlRequest(void)
 
                 // Interface
                 switch (USB_ControlRequest.wIndex) {
-                case 1: // Keyboard
+                case KEYBOARD_INTERFACE:
+                    // TODO: test/check
                     ReportData = (uint8_t*)&keyboard_report_sent;
                     ReportSize = sizeof(keyboard_report_sent);
                     break;
-                case 2: // Mouse
+                case MOUSE_INTERFACE:
+                    // TODO: test/check
                     ReportData = (uint8_t*)&mouse_report_sent;
                     ReportSize = sizeof(mouse_report_sent);
                     break;
-                case 3: // Generic
+                case CONSOLE_INTERFACE:
+                    break;
+                case EXTRA_INTERFACE:
                     break;
                 }
 
@@ -184,13 +253,16 @@ void EVENT_USB_Device_ControlRequest(void)
 
                 // Interface
                 switch (USB_ControlRequest.wIndex) {
-                case 1: // Keyboard
+                case KEYBOARD_INTERFACE:
+                    // TODO: test/check
                     /* Read in the LED report from the host */
                     keyboard_led_stats = Endpoint_Read_8();
                     break;
-                case 2: // Mouse
+                case MOUSE_INTERFACE:
+                    break;
+                case CONSOLE_INTERFACE:
                     break;
-                case 3: // Generic
+                case EXTRA_INTERFACE:
                     break;
                 }
 
@@ -202,64 +274,6 @@ void EVENT_USB_Device_ControlRequest(void)
     }
 }
 
-/** Keyboard task.
- *  This processes host LED status reports sent to the device via the keyboard OUT reporting endpoint.
- */
-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);
-
-    /* Check if Keyboard LED Endpoint Ready for Read/Write */
-    if (Endpoint_IsReadWriteAllowed())
-    {
-        /* Read in the LED report from the host */
-        keyboard_led_stats = Endpoint_Read_8();
-
-        /* Handshake the OUT Endpoint - clear endpoint and ready for next report */
-        Endpoint_ClearOUT();
-    }
-}
-
-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 
  ******************************************************************************/
@@ -303,12 +317,35 @@ static void send_mouse(report_mouse_t *report)
     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();
+    }
 }
 
 
@@ -320,7 +357,7 @@ int8_t sendchar(uint8_t c)
     if (USB_DeviceState != DEVICE_STATE_Configured)
       return -1;
 
-    Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);
+    Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
 
     uint8_t timeout = 10;
     uint16_t prevFN = USB_Device_GetFrameNumber();
@@ -332,7 +369,6 @@ int8_t sendchar(uint8_t c)
         }
         if (Endpoint_IsStalled())
             return -1;
-        uint16_t currFN = USB_Device_GetFrameNumber();
         if (prevFN != USB_Device_GetFrameNumber()) {
             if (!(timeout--))
                 return -1;