]> 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 d7e7c1654dcfc1d5e52cfc5e2bf437ed7c00e11a..09da96b2e572860d640e08a378c92d9a8fee1b26 100644 (file)
@@ -1,6 +1,8 @@
 /* 
  * Copyright 2012 Jun Wako <wakojun@gmail.com>
- * 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
  */
 
 /*
 #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;
-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);
@@ -59,21 +67,37 @@ static host_driver_t lufa_driver = {
 };
 
 
+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();
-        Keyboard_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 */
@@ -86,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)
 {
@@ -105,22 +169,43 @@ 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 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;
-    uint8_t  ReportSize;
+    uint8_t* ReportData = NULL;
+    uint8_t  ReportSize = 0;
 
     /* Handle HID Class specific requests */
     switch (USB_ControlRequest.bRequest)
@@ -130,16 +215,22 @@ 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 KEYBOARD_INTERFACE:
+                    // TODO: test/check
                     ReportData = (uint8_t*)&keyboard_report_sent;
                     ReportSize = sizeof(keyboard_report_sent);
-                }
-                else
-                {
+                    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 */
@@ -160,8 +251,20 @@ 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 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();
@@ -171,26 +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)
-{
-    /* 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();
-    }
-}
-
-
 /*******************************************************************************
  * Host driver 
  ******************************************************************************/
@@ -234,10 +317,70 @@ 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();
+    }
+}
+
+
+/*******************************************************************************
+ * 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;
 }