// Local Includes
#include "usb_keyboard_serial.h"
+#include <print.h>
// ----- Variables -----
// Modifiers
UEDATX = USBKeys_Modifiers;
- // Normal Keys
- for ( i = 0; i < 6; i++)
- {
- UEDATX = USBKeys_Array[i];
- }
- UEINTX = 0x3A;
-}
-
-// Sends NKRO keyboard out to host
-// NOTE: Make sure to match the descriptor
-void usb_nkrokeyboard_toHost()
-{
- uint8_t i;
-
- // Modifiers
- /*
- UEDATX = 0x02;
- UEDATX = USBKeys_Modifiers;
- UEINTX = 0x3A;
- */
+ // Reserved Byte
+ UEDATX = 0x00;
- // Media Keys
- UEDATX = 0x03;
- UEDATX = 0;
- UEINTX = 0x3A;
-
- // Normal Keys
- UEDATX = 0x04;
+ // Normal Keys, only supports 6 in Boot mode
for ( i = 0; i < 6; i++)
{
- UEDATX = USBKeys_Array[i];
+ UEDATX = USBKeys_Keys[i];
}
- UEINTX = 0x3A;
+ UEINTX = 0x00;
}
-// send the contents of USBKeys_Array and USBKeys_Modifiers
-int8_t usb_keyboard_send()
+// send the contents of USBKeys_Keys and USBKeys_Modifiers
+inline void usb_keyboard_send()
{
uint8_t intr_state, timeout;
// has the USB gone offline? or exceeded timeout?
if ( !usb_configuration || UDFNUML == timeout )
- return -1;
+ {
+ erro_print("USB Offline? Timeout?");
+ return;
+ }
// get ready to try checking again
intr_state = SREG;
UENUM = USBKeys_Protocol ? KEYBOARD_NKRO_ENDPOINT : KEYBOARD_ENDPOINT;
} while ( !( UEINTX & (1 << RWAL) ) );
- // Send normal keyboard interrupt packet(s)
switch ( USBKeys_Protocol )
{
+ // Send boot keyboard interrupt packet(s)
+ case 0:
+ usb_keyboard_toHost();
+ USBKeys_Changed = USBKeyChangeState_None;
+ break;
+
+ // Send NKRO keyboard interrupts packet(s)
+ case 1:
+ // Check system control keys
+ if ( USBKeys_Changed & USBKeyChangeState_System )
+ {
+ UEDATX = 0x02; // ID
+ UEDATX = USBKeys_SysCtrl;
+ UEINTX = 0; // Finished with ID
+
+ USBKeys_Changed &= ~USBKeyChangeState_System; // Mark sent
+ }
+
+ // Check consumer control keys
+ if ( USBKeys_Changed & USBKeyChangeState_Consumer )
+ {
+ UEDATX = 0x03; // ID
+ UEDATX = (uint8_t)(USBKeys_ConsCtrl & 0x00FF);
+ UEDATX = (uint8_t)(USBKeys_ConsCtrl >> 8);
+ UEINTX = 0; // Finished with ID
+
+ USBKeys_Changed &= ~USBKeyChangeState_Consumer; // Mark sent
+ }
+
+ // Standard HID Keyboard
+ if ( USBKeys_Changed )
+ {
+ UEDATX = 0x01; // ID
+
+ // Modifiers
+ UEDATX = USBKeys_Modifiers;
+
+ // 4-49 (first 6 bytes)
+ for ( uint8_t byte = 0; byte < 6; byte++ )
+ UEDATX = USBKeys_Keys[ byte ];
+
+ // 51-155 (Middle 14 bytes)
+ for ( uint8_t byte = 6; byte < 20; byte++ )
+ UEDATX = USBKeys_Keys[ byte ];
+
+ // 157-164 (Next byte)
+ for ( uint8_t byte = 20; byte < 21; byte++ )
+ UEDATX = USBKeys_Keys[ byte ];
+
+ // 176-221 (last 6 bytes)
+ for ( uint8_t byte = 21; byte < 27; byte++ )
+ UEDATX = USBKeys_Keys[ byte ];
+
+ UEINTX = 0; // Finished with ID
+
+ USBKeys_Changed = USBKeyChangeState_None; // Mark sent
+ }
+
+ break;
}
- usb_keyboard_toHost();
USBKeys_Idle_Count = 0;
SREG = intr_state;
- return 0;
}
// ----- USB Virtual Serial Port (CDC) Functions -----
// get the next character, or -1 if nothing received
-int16_t usb_serial_getchar(void)
+int16_t usb_serial_getchar()
{
uint8_t c, intr_state;
}
// number of bytes available in the receive buffer
-uint8_t usb_serial_available(void)
+uint8_t usb_serial_available()
{
uint8_t n=0, i, intr_state;
}
// discard any buffered input
-void usb_serial_flush_input(void)
+void usb_serial_flush_input()
{
uint8_t intr_state;
}
// transmit a character. 0 returned on success, -1 on error
-int8_t usb_serial_putchar(uint8_t c)
+int8_t usb_serial_putchar( uint8_t c )
{
uint8_t timeout, intr_state;
// transmit a character, but do not wait if the buffer is full,
// 0 returned on success, -1 on buffer full or error
-int8_t usb_serial_putchar_nowait(uint8_t c)
+int8_t usb_serial_putchar_nowait( uint8_t c )
{
uint8_t intr_state;
// controller in the PC will not allocate bandwitdh without a pending read request.
// (thanks to Victor Suarez for testing and feedback and initial code)
-int8_t usb_serial_write(const char *buffer, uint16_t size)
+int8_t usb_serial_write( const char *buffer, uint16_t size )
{
uint8_t timeout, intr_state, write_size;
cli();
UENUM = CDC_TX_ENDPOINT;
// if we gave up due to timeout before, don't wait again
- /*
+
if (transmit_previous_timeout) {
if (!(UEINTX & (1<<RWAL))) {
SREG = intr_state;
}
transmit_previous_timeout = 0;
}
- */
+
// each iteration of this loop transmits a packet
while (size) {
// wait for the FIFO to be ready to accept data
// This doesn't actually transmit the data - that is impossible!
// USB devices only transmit when the host allows, so the best
// we can do is release the FIFO buffer for when the host wants it
-void usb_serial_flush_output(void)
+void usb_serial_flush_output()
{
uint8_t intr_state;
// at full USB speed), but they are set by the host so we can
// set them properly if we're converting the USB to a real serial
// communication
-uint32_t usb_serial_get_baud(void)
+uint32_t usb_serial_get_baud()
{
uint32_t *baud = (uint32_t*)cdc_line_coding;
return *baud;
}
-uint8_t usb_serial_get_stopbits(void)
+uint8_t usb_serial_get_stopbits()
{
return cdc_line_coding[4];
}
-uint8_t usb_serial_get_paritytype(void)
+uint8_t usb_serial_get_paritytype()
{
return cdc_line_coding[5];
}
-uint8_t usb_serial_get_numbits(void)
+uint8_t usb_serial_get_numbits()
{
return cdc_line_coding[6];
}
-uint8_t usb_serial_get_control(void)
+uint8_t usb_serial_get_control()
{
return cdc_line_rtsdtr;
}
// it remains buffered (either here or on the host) and can not be
// lost because you weren't listening at the right time, like it
// would in real serial communication.
-int8_t usb_serial_set_control(uint8_t signals)
+int8_t usb_serial_set_control( uint8_t signals )
{
uint8_t intr_state;
// ----- General USB Functions -----
// Set the avr into firmware reload mode
-void usb_debug_reload()
+void usb_device_reload()
{
cli();
// Disable watchdog, if enabled
// WDT Setup for software reset the chip
-void wdt_init(void)
+void wdt_init()
{
MCUSR = 0;
wdt_disable();
// initialize USB
-void usb_init(void)
+uint8_t usb_init()
{
+ // Check to see if a usb cable has been plugged in
+ // XXX Not tested (also, not currently needed) -HaaTa
+ //if ( USB0_STAT & (1 << 1)
+ // return 0;
+
HW_CONFIG();
USB_FREEZE(); // enable USB
PLL_CONFIG(); // config PLL
// Disable watchdog timer after possible software reset
//wdt_init(); // XXX Not working...seems to be ok without this, not sure though
+
+ return 1;
}
// return 0 if the USB is not configured, or the configuration
// XXX TODO Is this even used? If so, when? -Jacob
// From hasu's code, this section looks like it could fix the Mac SET_IDLE problem
// Send normal keyboard interrupt packet(s)
- //usb_keyboard_toHost();
+ switch ( USBKeys_Protocol )
+ {
+ // Send boot keyboard interrupt packet(s)
+ case 0: usb_keyboard_toHost(); break;
+ // Send NKRO keyboard interrupts packet(s)
+ //case 1: usb_nkrokeyboard_toHost(); break; // XXX Not valid anymore
+ }
+ print("IDLE");
}
}
}
// Misc functions to wait for ready and send/receive packets
-static inline void usb_wait_in_ready(void)
+static inline void usb_wait_in_ready()
{
while (!(UEINTX & (1<<TXINI))) ;
}
-static inline void usb_send_in(void)
+static inline void usb_send_in()
{
UEINTX = ~(1<<TXINI);
}
-static inline void usb_wait_receive_out(void)
+static inline void usb_wait_receive_out()
{
while (!(UEINTX & (1<<RXOUTI))) ;
}
-static inline void usb_ack_out(void)
+static inline void usb_ack_out()
{
UEINTX = ~(1<<RXOUTI);
}
// other endpoints are manipulated by the user-callable
// functions, and the start-of-frame interrupt.
//
-ISR(USB_COM_vect)
+ISR( USB_COM_vect )
{
uint8_t intbits;
const uint8_t *list;
UENUM = 0;
intbits = UEINTX;
- if (intbits & (1<<RXSTPI)) {
+ if (intbits & (1<<RXSTPI))
+ {
bmRequestType = UEDATX;
bRequest = UEDATX;
wValue = UEDATX;
return;
}
- //if ( wIndex == KEYBOARD_INTERFACE )
- if ( wIndex == KEYBOARD_INTERFACE || wIndex == KEYBOARD_NKRO_INTERFACE )
+ if ( ( wIndex == KEYBOARD_INTERFACE && USBKeys_Protocol == 0 )
+ || ( wIndex == KEYBOARD_NKRO_INTERFACE && USBKeys_Protocol == 1 ) )
{
if ( bmRequestType == 0xA1)
{
{
usb_wait_in_ready();
- // XXX TODO Is this even used? If so, when? -Jacob
// Send normal keyboard interrupt packet(s)
- //usb_keyboard_toHost();
+ switch ( USBKeys_Protocol )
+ {
+ // Send boot keyboard interrupt packet(s)
+ case 0: usb_keyboard_toHost(); break;
+ // Send NKRO keyboard interrupts packet(s)
+ //case 1: usb_nkrokeyboard_toHost(); break; // XXX Not valid anymore
+ }
usb_send_in();
return;
usb_send_in();
return;
}
- USBKeys_Protocol = bRequest;
}
if ( bmRequestType == 0x21 )
{
}
if ( bRequest == HID_SET_IDLE )
{
+ usb_wait_in_ready();
USBKeys_Idle_Config = (wValue >> 8);
USBKeys_Idle_Count = 0;
- //usb_wait_in_ready();
usb_send_in();
+ //print("HID IDLE");
return;
}
if ( bRequest == HID_SET_PROTOCOL )
{
+ usb_wait_in_ready();
USBKeys_Protocol = wValue; // 0 - Boot Mode, 1 - NKRO Mode
- //usb_wait_in_ready();
usb_send_in();
+ //print("HID SET");
return;
}
}