2011-07-20 15:32:52 +00:00
/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board
* http : //www.pjrc.com/teensy/usb_keyboard.html
* Copyright ( c ) 2009 PJRC . COM , LLC
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*/
2010-09-23 11:23:50 +00:00
# include <avr/interrupt.h>
# include <avr/pgmspace.h>
2012-10-17 12:43:44 +00:00
# include "keycode.h"
2010-09-23 11:23:50 +00:00
# include "usb_keyboard.h"
2010-10-23 16:17:26 +00:00
# include "print.h"
2010-10-26 12:32:45 +00:00
# include "debug.h"
2010-12-07 16:47:57 +00:00
# include "util.h"
2011-02-12 15:15:51 +00:00
# include "host.h"
2010-09-23 11:23:50 +00:00
// protocol setting from the host. We use exactly the same report
// either way, so this variable only stores the setting since we
// are required to be able to report which setting is in use.
2010-11-03 08:33:20 +00:00
uint8_t usb_keyboard_protocol = 1 ;
2010-09-23 11:23:50 +00:00
// the idle configuration, how often we send the report to the
// host (ms * 4) even when it hasn't changed
2011-03-09 15:50:27 +00:00
// Windows and Linux set 0 while OS X sets 6(24ms) by SET_IDLE request.
2010-11-03 08:33:20 +00:00
uint8_t usb_keyboard_idle_config = 125 ;
2010-09-23 11:23:50 +00:00
// count until idle timeout
2010-11-03 08:33:20 +00:00
uint8_t usb_keyboard_idle_count = 0 ;
2010-09-23 11:23:50 +00:00
// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
2010-11-03 08:33:20 +00:00
volatile uint8_t usb_keyboard_leds = 0 ;
2010-09-23 11:23:50 +00:00
2010-12-07 16:47:57 +00:00
2011-02-12 15:15:51 +00:00
static inline int8_t send_report ( report_keyboard_t * report , uint8_t endpoint , uint8_t keys_start , uint8_t keys_end ) ;
2010-09-23 11:23:50 +00:00
2011-02-12 15:15:51 +00:00
int8_t usb_keyboard_send_report ( report_keyboard_t * report )
2010-09-23 11:23:50 +00:00
{
2010-12-07 16:47:57 +00:00
int8_t result = 0 ;
2011-09-17 13:39:50 +00:00
# ifdef NKRO_ENABLE
2011-02-12 15:15:51 +00:00
if ( keyboard_nkro )
result = send_report ( report , KBD2_ENDPOINT , 0 , KBD2_REPORT_KEYS ) ;
2010-12-07 16:47:57 +00:00
else
2010-11-25 16:56:21 +00:00
# endif
2010-12-07 16:47:57 +00:00
{
if ( usb_keyboard_protocol )
2011-02-12 15:15:51 +00:00
result = send_report ( report , KBD_ENDPOINT , 0 , KBD_REPORT_KEYS ) ;
2010-12-07 16:47:57 +00:00
else
2011-02-12 15:15:51 +00:00
result = send_report ( report , KBD_ENDPOINT , 0 , 6 ) ;
2010-12-07 16:47:57 +00:00
}
2010-11-03 08:33:20 +00:00
2010-12-07 16:47:57 +00:00
if ( result ) return result ;
usb_keyboard_idle_count = 0 ;
usb_keyboard_print_report ( report ) ;
return 0 ;
2010-09-23 11:23:50 +00:00
}
2010-10-23 16:17:26 +00:00
2011-02-12 15:15:51 +00:00
void usb_keyboard_print_report ( report_keyboard_t * report )
2010-11-03 08:33:20 +00:00
{
2010-10-26 12:32:45 +00:00
if ( ! debug_keyboard ) return ;
2010-11-03 08:33:20 +00:00
print ( " keys: " ) ;
2011-02-12 15:15:51 +00:00
for ( int i = 0 ; i < REPORT_KEYS ; i + + ) { phex ( report - > keys [ i ] ) ; print ( " " ) ; }
2010-11-03 08:33:20 +00:00
print ( " mods: " ) ; phex ( report - > mods ) ; print ( " \n " ) ;
2010-10-23 16:17:26 +00:00
}
2010-12-07 16:47:57 +00:00
2011-02-12 15:15:51 +00:00
static inline int8_t send_report ( report_keyboard_t * report , uint8_t endpoint , uint8_t keys_start , uint8_t keys_end )
2010-12-07 16:47:57 +00:00
{
uint8_t intr_state , timeout ;
if ( ! usb_configured ( ) ) return - 1 ;
intr_state = SREG ;
cli ( ) ;
UENUM = endpoint ;
timeout = UDFNUML + 50 ;
while ( 1 ) {
// are we ready to transmit?
if ( UEINTX & ( 1 < < RWAL ) ) break ;
SREG = intr_state ;
// has the USB gone offline?
if ( ! usb_configured ( ) ) return - 1 ;
// have we waited too long?
if ( UDFNUML = = timeout ) return - 1 ;
// get ready to try checking again
intr_state = SREG ;
cli ( ) ;
UENUM = endpoint ;
}
UEDATX = report - > mods ;
2011-09-17 13:39:50 +00:00
# ifdef NKRO_ENABLE
2011-02-12 15:15:51 +00:00
if ( ! keyboard_nkro )
2010-12-11 14:20:49 +00:00
UEDATX = 0 ;
2011-02-21 14:05:28 +00:00
# else
UEDATX = 0 ;
# endif
2010-12-07 16:47:57 +00:00
for ( uint8_t i = keys_start ; i < keys_end ; i + + ) {
UEDATX = report - > keys [ i ] ;
}
UEINTX = 0x3A ;
SREG = intr_state ;
return 0 ;
}