|
@@ -28,6 +28,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
#include "vusb.h"
|
|
|
#include <util/delay.h>
|
|
|
|
|
|
+#if defined(RAW_ENABLE)
|
|
|
+# include "raw_hid.h"
|
|
|
+#endif
|
|
|
+
|
|
|
+#if (defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)) && defined(RAW_ENABLE)
|
|
|
+# error "Enabling Mousekeys/Extrakeys and Raw HID at the same time is not currently supported on V-USB."
|
|
|
+#endif
|
|
|
+
|
|
|
static uint8_t vusb_keyboard_leds = 0;
|
|
|
static uint8_t vusb_idle_rate = 0;
|
|
|
|
|
@@ -71,6 +79,52 @@ void vusb_transfer_keyboard(void) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/*------------------------------------------------------------------*
|
|
|
+ * RAW HID
|
|
|
+ *------------------------------------------------------------------*/
|
|
|
+#ifdef RAW_ENABLE
|
|
|
+# define RAW_BUFFER_SIZE 32
|
|
|
+# define RAW_EPSIZE 8
|
|
|
+
|
|
|
+static uint8_t raw_output_buffer[RAW_BUFFER_SIZE];
|
|
|
+static uint8_t raw_output_received_bytes = 0;
|
|
|
+
|
|
|
+void raw_hid_send(uint8_t *data, uint8_t length) {
|
|
|
+ if (length != RAW_BUFFER_SIZE) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ uint8_t *temp = data;
|
|
|
+ for (uint8_t i = 0; i < 4; i++) {
|
|
|
+ while (!usbInterruptIsReady3()) {
|
|
|
+ usbPoll();
|
|
|
+ }
|
|
|
+ usbSetInterrupt3(temp, 8);
|
|
|
+ temp += 8;
|
|
|
+ }
|
|
|
+ while (!usbInterruptIsReady3()) {
|
|
|
+ usbPoll();
|
|
|
+ }
|
|
|
+ usbSetInterrupt3(0, 0);
|
|
|
+ usbPoll();
|
|
|
+ _delay_ms(1);
|
|
|
+}
|
|
|
+
|
|
|
+__attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) {
|
|
|
+ // Users should #include "raw_hid.h" in their own code
|
|
|
+ // and implement this function there. Leave this as weak linkage
|
|
|
+ // so users can opt to not handle data coming in.
|
|
|
+}
|
|
|
+
|
|
|
+void raw_hid_task(void) {
|
|
|
+ if (raw_output_received_bytes == RAW_BUFFER_SIZE) {
|
|
|
+ raw_hid_receive(raw_output_buffer, RAW_BUFFER_SIZE);
|
|
|
+ raw_output_received_bytes = 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
/*------------------------------------------------------------------*
|
|
|
* Host driver
|
|
|
*------------------------------------------------------------------*/
|
|
@@ -206,6 +260,27 @@ uchar usbFunctionWrite(uchar *data, uchar len) {
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
+void usbFunctionWriteOut(uchar *data, uchar len) {
|
|
|
+#ifdef RAW_ENABLE
|
|
|
+ // Data from host must be divided every 8bytes
|
|
|
+ if (len != 8) {
|
|
|
+ debug("RAW: invalid length");
|
|
|
+ raw_output_received_bytes = 0;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (raw_output_received_bytes + len > RAW_BUFFER_SIZE) {
|
|
|
+ debug("RAW: buffer full");
|
|
|
+ raw_output_received_bytes = 0;
|
|
|
+ } else {
|
|
|
+ for (uint8_t i = 0; i < 8; i++) {
|
|
|
+ raw_output_buffer[raw_output_received_bytes + i] = data[i];
|
|
|
+ }
|
|
|
+ raw_output_received_bytes += len;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
/*------------------------------------------------------------------*
|
|
|
* Descriptors *
|
|
|
*------------------------------------------------------------------*/
|
|
@@ -335,6 +410,29 @@ const PROGMEM uchar mouse_extra_hid_report[] = {
|
|
|
};
|
|
|
#endif
|
|
|
|
|
|
+#if defined(RAW_ENABLE)
|
|
|
+const PROGMEM uchar raw_hid_report[] = {
|
|
|
+ 0x06, 0x60, 0xFF, // Usage Page (Vendor Defined)
|
|
|
+ 0x09, 0x61, // Usage (Vendor Defined)
|
|
|
+ 0xA1, 0x01, // Collection (Application)
|
|
|
+ // Data to host
|
|
|
+ 0x09, 0x62, // Usage (Vendor Defined)
|
|
|
+ 0x15, 0x00, // Logical Minimum (0)
|
|
|
+ 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
|
+ 0x95, RAW_BUFFER_SIZE, // Report Count
|
|
|
+ 0x75, 0x08, // Report Size (8)
|
|
|
+ 0x81, 0x02, // Input (Data, Variable, Absolute)
|
|
|
+ // Data from host
|
|
|
+ 0x09, 0x63, // Usage (Vendor Defined)
|
|
|
+ 0x15, 0x00, // Logical Minimum (0)
|
|
|
+ 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
|
+ 0x95, RAW_BUFFER_SIZE, // Report Count
|
|
|
+ 0x75, 0x08, // Report Size (8)
|
|
|
+ 0x91, 0x02, // Output (Data, Variable, Absolute)
|
|
|
+ 0xC0, // End Collection
|
|
|
+};
|
|
|
+#endif
|
|
|
+
|
|
|
#ifndef SERIAL_NUMBER
|
|
|
# define SERIAL_NUMBER 0
|
|
|
#endif
|
|
@@ -416,7 +514,7 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
|
|
|
.bDescriptorType = USBDESCR_CONFIG
|
|
|
},
|
|
|
.wTotalLength = sizeof(usbConfigurationDescriptor_t),
|
|
|
-# if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
|
|
|
+# if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) || defined(RAW_ENABLE)
|
|
|
.bNumInterfaces = 2,
|
|
|
# else
|
|
|
.bNumInterfaces = 1,
|
|
@@ -511,6 +609,53 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
|
|
|
.bInterval = USB_POLLING_INTERVAL_MS
|
|
|
}
|
|
|
# endif
|
|
|
+# elif defined(RAW_ENABLE)
|
|
|
+ .rawInterface = {
|
|
|
+ .header = {
|
|
|
+ .bLength = sizeof(usbInterfaceDescriptor_t),
|
|
|
+ .bDescriptorType = USBDESCR_INTERFACE
|
|
|
+ },
|
|
|
+ .bInterfaceNumber = 1,
|
|
|
+ .bAlternateSetting = 0x00,
|
|
|
+ .bNumEndpoints = 2,
|
|
|
+ .bInterfaceClass = 0x03,
|
|
|
+ .bInterfaceSubClass = 0x00,
|
|
|
+ .bInterfaceProtocol = 0x00,
|
|
|
+ .iInterface = 0x00
|
|
|
+ },
|
|
|
+ .rawHID = {
|
|
|
+ .header = {
|
|
|
+ .bLength = sizeof(usbHIDDescriptor_t),
|
|
|
+ .bDescriptorType = USBDESCR_HID
|
|
|
+ },
|
|
|
+ .bcdHID = 0x0101,
|
|
|
+ .bCountryCode = 0x00,
|
|
|
+ .bNumDescriptors = 2,
|
|
|
+ .bDescriptorType = USBDESCR_HID_REPORT,
|
|
|
+ .wDescriptorLength = sizeof(raw_hid_report)
|
|
|
+ },
|
|
|
+# if USB_CFG_HAVE_INTRIN_ENDPOINT3
|
|
|
+ .rawINEndpoint = {
|
|
|
+ .header = {
|
|
|
+ .bLength = sizeof(usbEndpointDescriptor_t),
|
|
|
+ .bDescriptorType = USBDESCR_ENDPOINT
|
|
|
+ },
|
|
|
+ .bEndpointAddress = (USBRQ_DIR_DEVICE_TO_HOST | USB_CFG_EP3_NUMBER),
|
|
|
+ .bmAttributes = 0x03,
|
|
|
+ .wMaxPacketSize = RAW_EPSIZE,
|
|
|
+ .bInterval = USB_POLLING_INTERVAL_MS
|
|
|
+ },
|
|
|
+ .rawOUTEndpoint = {
|
|
|
+ .header = {
|
|
|
+ .bLength = sizeof(usbEndpointDescriptor_t),
|
|
|
+ .bDescriptorType = USBDESCR_ENDPOINT
|
|
|
+ },
|
|
|
+ .bEndpointAddress = (USBRQ_DIR_HOST_TO_DEVICE | USB_CFG_EP3_NUMBER),
|
|
|
+ .bmAttributes = 0x03,
|
|
|
+ .wMaxPacketSize = RAW_EPSIZE,
|
|
|
+ .bInterval = USB_POLLING_INTERVAL_MS
|
|
|
+ }
|
|
|
+# endif
|
|
|
# endif
|
|
|
};
|
|
|
#endif
|
|
@@ -572,6 +717,11 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) {
|
|
|
usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.mouseExtraHID;
|
|
|
len = sizeof(usbHIDDescriptor_t);
|
|
|
break;
|
|
|
+#elif defined(RAW_ENABLE)
|
|
|
+ case 1:
|
|
|
+ usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.rawHID;
|
|
|
+ len = sizeof(usbHIDDescriptor_t);
|
|
|
+ break;
|
|
|
#endif
|
|
|
}
|
|
|
break;
|
|
@@ -587,6 +737,11 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) {
|
|
|
usbMsgPtr = (unsigned char *)mouse_extra_hid_report;
|
|
|
len = sizeof(mouse_extra_hid_report);
|
|
|
break;
|
|
|
+#elif defined(RAW_ENABLE)
|
|
|
+ case 1:
|
|
|
+ usbMsgPtr = (unsigned char *)raw_hid_report;
|
|
|
+ len = sizeof(raw_hid_report);
|
|
|
+ break;
|
|
|
#endif
|
|
|
}
|
|
|
break;
|