]> git.donarmstrong.com Git - kiibohd-controller.git/blobdiff - Output/pjrcUSB/avr/usb_keyboard_serial.c
Initial code for USB cable detection
[kiibohd-controller.git] / Output / pjrcUSB / avr / usb_keyboard_serial.c
index cbd9324573d6414b0336cfb490526646ac384ce9..1403c9ae3ca06d83d7a5f72f26cbdcff11c83fca 100644 (file)
@@ -24,6 +24,7 @@
 
 // Local Includes
 #include "usb_keyboard_serial.h"
+#include <print.h>
 
 
 // ----- Variables -----
@@ -54,43 +55,19 @@ void usb_keyboard_toHost()
        // 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;
 
@@ -104,7 +81,10 @@ int8_t usb_keyboard_send()
 
                // 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;
@@ -114,15 +94,71 @@ int8_t usb_keyboard_send()
                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;
 }
 
 
@@ -130,7 +166,7 @@ int8_t usb_keyboard_send()
 // ----- 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;
 
@@ -164,7 +200,7 @@ int16_t usb_serial_getchar(void)
 }
 
 // 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;
 
@@ -183,7 +219,7 @@ uint8_t usb_serial_available(void)
 }
 
 // discard any buffered input
-void usb_serial_flush_input(void)
+void usb_serial_flush_input()
 {
        uint8_t intr_state;
 
@@ -199,7 +235,7 @@ void usb_serial_flush_input(void)
 }
 
 // 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;
 
@@ -250,7 +286,7 @@ int8_t usb_serial_putchar(uint8_t c)
 
 // 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;
 
@@ -284,7 +320,7 @@ int8_t usb_serial_putchar_nowait(uint8_t c)
 // 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;
 
@@ -297,7 +333,7 @@ int8_t usb_serial_write(const char *buffer, uint16_t 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;
@@ -305,7 +341,7 @@ int8_t usb_serial_write(const char *buffer, uint16_t size)
                }
                transmit_previous_timeout = 0;
        }
-       */
+
        // each iteration of this loop transmits a packet
        while (size) {
                // wait for the FIFO to be ready to accept data
@@ -420,7 +456,7 @@ int8_t usb_serial_write(const char *buffer, uint16_t size)
 // 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;
 
@@ -439,24 +475,24 @@ void usb_serial_flush_output(void)
 // 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;
 }
@@ -467,7 +503,7 @@ uint8_t usb_serial_get_control(void)
 // 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;
 
@@ -506,7 +542,7 @@ int8_t usb_serial_set_control(uint8_t signals)
 // ----- General USB Functions -----
 
 // Set the avr into firmware reload mode
-void usb_debug_reload()
+void usb_device_reload()
 {
        cli();
        // Disable watchdog, if enabled
@@ -546,7 +582,7 @@ void usb_debug_reload()
 
 
 // WDT Setup for software reset the chip
-void wdt_init(void)
+void wdt_init()
 {
        MCUSR = 0;
        wdt_disable();
@@ -554,8 +590,13 @@ void wdt_init(void)
 
 
 // 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
@@ -568,6 +609,8 @@ void usb_init(void)
 
        // 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
@@ -617,7 +660,14 @@ ISR( USB_GEN_vect )
                                // 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");
                        }
                }
        }
@@ -626,19 +676,19 @@ ISR( USB_GEN_vect )
 
 
 // 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);
 }
@@ -649,7 +699,7 @@ static inline void usb_ack_out(void)
 // 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;
@@ -667,7 +717,8 @@ ISR(USB_COM_vect)
 
         UENUM = 0;
        intbits = UEINTX;
-        if (intbits & (1<<RXSTPI)) {
+       if (intbits & (1<<RXSTPI))
+       {
                 bmRequestType = UEDATX;
                 bRequest = UEDATX;
                 wValue = UEDATX;
@@ -764,8 +815,8 @@ ISR(USB_COM_vect)
                        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)
                        {
@@ -773,9 +824,14 @@ ISR(USB_COM_vect)
                                {
                                        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;
@@ -794,7 +850,6 @@ ISR(USB_COM_vect)
                                        usb_send_in();
                                        return;
                                }
-                       USBKeys_Protocol = bRequest;
                        }
                        if ( bmRequestType == 0x21 )
                        {
@@ -808,17 +863,19 @@ ISR(USB_COM_vect)
                                }
                                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;
                                }
                        }