|
@@ -15,25 +15,50 @@ You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
*/
|
|
|
|
|
|
-#include <avr/eeprom.h>
|
|
|
|
#include <avr/wdt.h>
|
|
#include <avr/wdt.h>
|
|
|
|
+#include <util/delay.h>
|
|
#include <stdint.h>
|
|
#include <stdint.h>
|
|
#include "usbdrv.h"
|
|
#include "usbdrv.h"
|
|
#include "usbconfig.h"
|
|
#include "usbconfig.h"
|
|
#include "host.h"
|
|
#include "host.h"
|
|
#include "report.h"
|
|
#include "report.h"
|
|
-#include "print.h"
|
|
|
|
-#include "debug.h"
|
|
|
|
#include "host_driver.h"
|
|
#include "host_driver.h"
|
|
#include "vusb.h"
|
|
#include "vusb.h"
|
|
-#include <util/delay.h>
|
|
|
|
|
|
+#include "print.h"
|
|
|
|
+#include "debug.h"
|
|
|
|
|
|
#ifdef RAW_ENABLE
|
|
#ifdef RAW_ENABLE
|
|
# include "raw_hid.h"
|
|
# include "raw_hid.h"
|
|
#endif
|
|
#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."
|
|
|
|
|
|
+#if defined(CONSOLE_ENABLE)
|
|
|
|
+# define RBUF_SIZE 128
|
|
|
|
+# include "ring_buffer.h"
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#define NEXT_INTERFACE __COUNTER__
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Interface indexes
|
|
|
|
+ */
|
|
|
|
+enum usb_interfaces {
|
|
|
|
+ KEYBOARD_INTERFACE = NEXT_INTERFACE,
|
|
|
|
+#if (defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE))
|
|
|
|
+ MOUSE_EXTRA_INTERFACE = NEXT_INTERFACE,
|
|
|
|
+#endif
|
|
|
|
+#ifdef RAW_ENABLE
|
|
|
|
+ RAW_INTERFACE = NEXT_INTERFACE,
|
|
|
|
+#endif
|
|
|
|
+#ifdef CONSOLE_ENABLE
|
|
|
|
+ CONSOLE_INTERFACE = NEXT_INTERFACE,
|
|
|
|
+#endif
|
|
|
|
+ TOTAL_INTERFACES = NEXT_INTERFACE,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+#define MAX_INTERFACES 2
|
|
|
|
+
|
|
|
|
+#if (NEXT_INTERFACE - 1) > MAX_INTERFACES
|
|
|
|
+# error There are not enough available interfaces to support all functions. Please disable one or more of the following: Mouse Keys, Extra Keys, Raw HID, Console
|
|
#endif
|
|
#endif
|
|
|
|
|
|
static uint8_t vusb_keyboard_leds = 0;
|
|
static uint8_t vusb_keyboard_leds = 0;
|
|
@@ -120,7 +145,60 @@ void raw_hid_task(void) {
|
|
raw_output_received_bytes = 0;
|
|
raw_output_received_bytes = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+/*------------------------------------------------------------------*
|
|
|
|
+ * Console
|
|
|
|
+ *------------------------------------------------------------------*/
|
|
|
|
+#ifdef CONSOLE_ENABLE
|
|
|
|
+# define CONSOLE_BUFFER_SIZE 32
|
|
|
|
+# define CONSOLE_EPSIZE 8
|
|
|
|
+
|
|
|
|
+int8_t sendchar(uint8_t c) {
|
|
|
|
+ rbuf_enqueue(c);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline bool usbSendData3(char *data, uint8_t len) {
|
|
|
|
+ uint8_t retries = 5;
|
|
|
|
+ while (!usbInterruptIsReady3()) {
|
|
|
|
+ if (!(retries--)) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ usbPoll();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ usbSetInterrupt3((unsigned char *)data, len);
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void console_task(void) {
|
|
|
|
+ if (!usbConfiguration) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!rbuf_has_data()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Send in chunks of 8 padded to 32
|
|
|
|
+ char send_buf[CONSOLE_BUFFER_SIZE] = {0};
|
|
|
|
+ uint8_t send_buf_count = 0;
|
|
|
|
+ while (rbuf_has_data() && send_buf_count < CONSOLE_EPSIZE) {
|
|
|
|
+ send_buf[send_buf_count++] = rbuf_dequeue();
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ char *temp = send_buf;
|
|
|
|
+ for (uint8_t i = 0; i < 4; i++) {
|
|
|
|
+ if (!usbSendData3(temp, 8)) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ temp += 8;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ usbSendData3(0, 0);
|
|
|
|
+ usbPoll();
|
|
|
|
+}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/*------------------------------------------------------------------*
|
|
/*------------------------------------------------------------------*
|
|
@@ -429,7 +507,30 @@ const PROGMEM uchar raw_hid_report[] = {
|
|
0x95, RAW_BUFFER_SIZE, // Report Count
|
|
0x95, RAW_BUFFER_SIZE, // Report Count
|
|
0x75, 0x08, // Report Size (8)
|
|
0x75, 0x08, // Report Size (8)
|
|
0x91, 0x02, // Output (Data, Variable, Absolute)
|
|
0x91, 0x02, // Output (Data, Variable, Absolute)
|
|
- 0xC0, // End Collection
|
|
|
|
|
|
+ 0xC0 // End Collection
|
|
|
|
+};
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#if defined(CONSOLE_ENABLE)
|
|
|
|
+const PROGMEM uchar console_hid_report[] = {
|
|
|
|
+ 0x06, 0x31, 0xFF, // Usage Page (Vendor Defined - PJRC Teensy compatible)
|
|
|
|
+ 0x09, 0x74, // Usage (Vendor Defined - PJRC Teensy compatible)
|
|
|
|
+ 0xA1, 0x01, // Collection (Application)
|
|
|
|
+ // Data to host
|
|
|
|
+ 0x09, 0x75, // Usage (Vendor Defined)
|
|
|
|
+ 0x15, 0x00, // Logical Minimum (0x00)
|
|
|
|
+ 0x26, 0xFF, 0x00, // Logical Maximum (0x00FF)
|
|
|
|
+ 0x95, CONSOLE_BUFFER_SIZE, // Report Count
|
|
|
|
+ 0x75, 0x08, // Report Size (8)
|
|
|
|
+ 0x81, 0x02, // Input (Data, Variable, Absolute)
|
|
|
|
+ // Data from host
|
|
|
|
+ 0x09, 0x76, // Usage (Vendor Defined)
|
|
|
|
+ 0x15, 0x00, // Logical Minimum (0x00)
|
|
|
|
+ 0x26, 0xFF, 0x00, // Logical Maximum (0x00FF)
|
|
|
|
+ 0x95, CONSOLE_BUFFER_SIZE, // Report Count
|
|
|
|
+ 0x75, 0x08, // Report Size (8)
|
|
|
|
+ 0x91, 0x02, // Output (Data)
|
|
|
|
+ 0xC0 // End Collection
|
|
};
|
|
};
|
|
#endif
|
|
#endif
|
|
|
|
|
|
@@ -511,11 +612,7 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
|
|
.bDescriptorType = USBDESCR_CONFIG
|
|
.bDescriptorType = USBDESCR_CONFIG
|
|
},
|
|
},
|
|
.wTotalLength = sizeof(usbConfigurationDescriptor_t),
|
|
.wTotalLength = sizeof(usbConfigurationDescriptor_t),
|
|
-# if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) || defined(RAW_ENABLE)
|
|
|
|
- .bNumInterfaces = 2,
|
|
|
|
-# else
|
|
|
|
- .bNumInterfaces = 1,
|
|
|
|
-# endif
|
|
|
|
|
|
+ .bNumInterfaces = TOTAL_INTERFACES,
|
|
.bConfigurationValue = 0x01,
|
|
.bConfigurationValue = 0x01,
|
|
.iConfiguration = 0x00,
|
|
.iConfiguration = 0x00,
|
|
.bmAttributes = (1 << 7) | USBATTR_REMOTEWAKE,
|
|
.bmAttributes = (1 << 7) | USBATTR_REMOTEWAKE,
|
|
@@ -530,7 +627,7 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
|
|
.bLength = sizeof(usbInterfaceDescriptor_t),
|
|
.bLength = sizeof(usbInterfaceDescriptor_t),
|
|
.bDescriptorType = USBDESCR_INTERFACE
|
|
.bDescriptorType = USBDESCR_INTERFACE
|
|
},
|
|
},
|
|
- .bInterfaceNumber = 0,
|
|
|
|
|
|
+ .bInterfaceNumber = KEYBOARD_INTERFACE,
|
|
.bAlternateSetting = 0x00,
|
|
.bAlternateSetting = 0x00,
|
|
.bNumEndpoints = 1,
|
|
.bNumEndpoints = 1,
|
|
.bInterfaceClass = 0x03,
|
|
.bInterfaceClass = 0x03,
|
|
@@ -569,7 +666,7 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
|
|
.bLength = sizeof(usbInterfaceDescriptor_t),
|
|
.bLength = sizeof(usbInterfaceDescriptor_t),
|
|
.bDescriptorType = USBDESCR_INTERFACE
|
|
.bDescriptorType = USBDESCR_INTERFACE
|
|
},
|
|
},
|
|
- .bInterfaceNumber = 1,
|
|
|
|
|
|
+ .bInterfaceNumber = MOUSE_EXTRA_INTERFACE,
|
|
.bAlternateSetting = 0x00,
|
|
.bAlternateSetting = 0x00,
|
|
.bNumEndpoints = 1,
|
|
.bNumEndpoints = 1,
|
|
.bInterfaceClass = 0x03,
|
|
.bInterfaceClass = 0x03,
|
|
@@ -597,14 +694,15 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
|
|
.bmAttributes = 0x03,
|
|
.bmAttributes = 0x03,
|
|
.wMaxPacketSize = 8,
|
|
.wMaxPacketSize = 8,
|
|
.bInterval = USB_POLLING_INTERVAL_MS
|
|
.bInterval = USB_POLLING_INTERVAL_MS
|
|
- }
|
|
|
|
-# elif defined(RAW_ENABLE)
|
|
|
|
|
|
+ },
|
|
|
|
+# endif
|
|
|
|
+# if defined(RAW_ENABLE)
|
|
.rawInterface = {
|
|
.rawInterface = {
|
|
.header = {
|
|
.header = {
|
|
.bLength = sizeof(usbInterfaceDescriptor_t),
|
|
.bLength = sizeof(usbInterfaceDescriptor_t),
|
|
.bDescriptorType = USBDESCR_INTERFACE
|
|
.bDescriptorType = USBDESCR_INTERFACE
|
|
},
|
|
},
|
|
- .bInterfaceNumber = 1,
|
|
|
|
|
|
+ .bInterfaceNumber = RAW_INTERFACE,
|
|
.bAlternateSetting = 0x00,
|
|
.bAlternateSetting = 0x00,
|
|
.bNumEndpoints = 2,
|
|
.bNumEndpoints = 2,
|
|
.bInterfaceClass = 0x03,
|
|
.bInterfaceClass = 0x03,
|
|
@@ -642,7 +740,56 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
|
|
.bmAttributes = 0x03,
|
|
.bmAttributes = 0x03,
|
|
.wMaxPacketSize = RAW_EPSIZE,
|
|
.wMaxPacketSize = RAW_EPSIZE,
|
|
.bInterval = USB_POLLING_INTERVAL_MS
|
|
.bInterval = USB_POLLING_INTERVAL_MS
|
|
- }
|
|
|
|
|
|
+ },
|
|
|
|
+# endif
|
|
|
|
+# if defined(CONSOLE_ENABLE)
|
|
|
|
+ /*
|
|
|
|
+ * Console
|
|
|
|
+ */
|
|
|
|
+ .consoleInterface = {
|
|
|
|
+ .header = {
|
|
|
|
+ .bLength = sizeof(usbInterfaceDescriptor_t),
|
|
|
|
+ .bDescriptorType = USBDESCR_INTERFACE
|
|
|
|
+ },
|
|
|
|
+ .bInterfaceNumber = CONSOLE_INTERFACE,
|
|
|
|
+ .bAlternateSetting = 0x00,
|
|
|
|
+ .bNumEndpoints = 2,
|
|
|
|
+ .bInterfaceClass = 0x03,
|
|
|
|
+ .bInterfaceSubClass = 0x00,
|
|
|
|
+ .bInterfaceProtocol = 0x00,
|
|
|
|
+ .iInterface = 0x00
|
|
|
|
+ },
|
|
|
|
+ .consoleHID = {
|
|
|
|
+ .header = {
|
|
|
|
+ .bLength = sizeof(usbHIDDescriptor_t),
|
|
|
|
+ .bDescriptorType = USBDESCR_HID
|
|
|
|
+ },
|
|
|
|
+ .bcdHID = 0x0111,
|
|
|
|
+ .bCountryCode = 0x00,
|
|
|
|
+ .bNumDescriptors = 1,
|
|
|
|
+ .bDescriptorType = USBDESCR_HID_REPORT,
|
|
|
|
+ .wDescriptorLength = sizeof(console_hid_report)
|
|
|
|
+ },
|
|
|
|
+ .consoleINEndpoint = {
|
|
|
|
+ .header = {
|
|
|
|
+ .bLength = sizeof(usbEndpointDescriptor_t),
|
|
|
|
+ .bDescriptorType = USBDESCR_ENDPOINT
|
|
|
|
+ },
|
|
|
|
+ .bEndpointAddress = (USBRQ_DIR_DEVICE_TO_HOST | USB_CFG_EP3_NUMBER),
|
|
|
|
+ .bmAttributes = 0x03,
|
|
|
|
+ .wMaxPacketSize = CONSOLE_EPSIZE,
|
|
|
|
+ .bInterval = 0x01
|
|
|
|
+ },
|
|
|
|
+ .consoleOUTEndpoint = {
|
|
|
|
+ .header = {
|
|
|
|
+ .bLength = sizeof(usbEndpointDescriptor_t),
|
|
|
|
+ .bDescriptorType = USBDESCR_ENDPOINT
|
|
|
|
+ },
|
|
|
|
+ .bEndpointAddress = (USBRQ_DIR_HOST_TO_DEVICE | USB_CFG_EP3_NUMBER),
|
|
|
|
+ .bmAttributes = 0x03,
|
|
|
|
+ .wMaxPacketSize = CONSOLE_EPSIZE,
|
|
|
|
+ .bInterval = 0x01
|
|
|
|
+ },
|
|
# endif
|
|
# endif
|
|
};
|
|
};
|
|
|
|
|
|
@@ -690,40 +837,54 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) {
|
|
break;
|
|
break;
|
|
case USBDESCR_HID:
|
|
case USBDESCR_HID:
|
|
switch (rq->wValue.bytes[0]) {
|
|
switch (rq->wValue.bytes[0]) {
|
|
- case 0:
|
|
|
|
|
|
+ case KEYBOARD_INTERFACE:
|
|
usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.keyboardHID;
|
|
usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.keyboardHID;
|
|
len = sizeof(usbHIDDescriptor_t);
|
|
len = sizeof(usbHIDDescriptor_t);
|
|
break;
|
|
break;
|
|
#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
|
|
#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
|
|
- case 1:
|
|
|
|
|
|
+ case MOUSE_EXTRA_INTERFACE:
|
|
usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.mouseExtraHID;
|
|
usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.mouseExtraHID;
|
|
len = sizeof(usbHIDDescriptor_t);
|
|
len = sizeof(usbHIDDescriptor_t);
|
|
break;
|
|
break;
|
|
-#elif defined(RAW_ENABLE)
|
|
|
|
- case 1:
|
|
|
|
|
|
+#endif
|
|
|
|
+#if defined(RAW_ENABLE)
|
|
|
|
+ case RAW_INTERFACE:
|
|
usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.rawHID;
|
|
usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.rawHID;
|
|
len = sizeof(usbHIDDescriptor_t);
|
|
len = sizeof(usbHIDDescriptor_t);
|
|
break;
|
|
break;
|
|
|
|
+#endif
|
|
|
|
+#if defined(CONSOLE_ENABLE)
|
|
|
|
+ case CONSOLE_INTERFACE:
|
|
|
|
+ usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.consoleHID;
|
|
|
|
+ len = sizeof(usbHIDDescriptor_t);
|
|
|
|
+ break;
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
case USBDESCR_HID_REPORT:
|
|
case USBDESCR_HID_REPORT:
|
|
/* interface index */
|
|
/* interface index */
|
|
switch (rq->wIndex.word) {
|
|
switch (rq->wIndex.word) {
|
|
- case 0:
|
|
|
|
|
|
+ case KEYBOARD_INTERFACE:
|
|
usbMsgPtr = (unsigned char *)keyboard_hid_report;
|
|
usbMsgPtr = (unsigned char *)keyboard_hid_report;
|
|
len = sizeof(keyboard_hid_report);
|
|
len = sizeof(keyboard_hid_report);
|
|
break;
|
|
break;
|
|
#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
|
|
#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
|
|
- case 1:
|
|
|
|
|
|
+ case MOUSE_EXTRA_INTERFACE:
|
|
usbMsgPtr = (unsigned char *)mouse_extra_hid_report;
|
|
usbMsgPtr = (unsigned char *)mouse_extra_hid_report;
|
|
len = sizeof(mouse_extra_hid_report);
|
|
len = sizeof(mouse_extra_hid_report);
|
|
break;
|
|
break;
|
|
-#elif defined(RAW_ENABLE)
|
|
|
|
- case 1:
|
|
|
|
|
|
+#endif
|
|
|
|
+#if defined(RAW_ENABLE)
|
|
|
|
+ case RAW_INTERFACE:
|
|
usbMsgPtr = (unsigned char *)raw_hid_report;
|
|
usbMsgPtr = (unsigned char *)raw_hid_report;
|
|
len = sizeof(raw_hid_report);
|
|
len = sizeof(raw_hid_report);
|
|
break;
|
|
break;
|
|
|
|
+#endif
|
|
|
|
+#if defined(CONSOLE_ENABLE)
|
|
|
|
+ case CONSOLE_INTERFACE:
|
|
|
|
+ usbMsgPtr = (unsigned char *)console_hid_report;
|
|
|
|
+ len = sizeof(console_hid_report);
|
|
|
|
+ break;
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
break;
|
|
break;
|