2014-02-03 00:19:58 +00:00
/* Teensyduino Core Library
* http : //www.pjrc.com/teensy/
* Copyright ( c ) 2013 PJRC . COM , LLC .
2015-02-21 21:06:28 +00:00
* Modifications by Jacob Alexander 2013 - 2015
2014-02-03 00:19:58 +00:00
*
* 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 :
*
2014-09-21 23:29:53 +00:00
* 1. The above copyright notice and this permission notice shall be
2014-02-03 00:19:58 +00:00
* included in all copies or substantial portions of the Software .
*
2014-09-21 23:29:53 +00:00
* 2. If the Software is incorporated into a build system that allows
2014-02-03 00:19:58 +00:00
* selection among a list of target devices , then similar target
* devices manufactured by PJRC . COM must be included in the list of
* target devices and selectable in the same manner .
*
* 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 .
*/
2014-09-21 23:29:53 +00:00
// ----- Includes -----
// Compiler Includes
# include <string.h> // for memcpy()
// Project Includes
# include <Lib/OutputLib.h>
# include <print.h>
// Local Includes
2013-01-27 06:47:52 +00:00
# include "usb_dev.h"
# include "usb_keyboard.h"
2014-09-21 23:29:53 +00:00
// ----- Defines -----
2013-01-27 06:47:52 +00:00
// Maximum number of transmit packets to queue so we don't starve other endpoints for memory
# define TX_PACKET_LIMIT 4
// When the PC isn't listening, how long do we wait before discarding data?
# define TX_TIMEOUT_MSEC 50
# if F_CPU == 96000000
# define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596)
# elif F_CPU == 48000000
# define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428)
# elif F_CPU == 24000000
# define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262)
# endif
2014-09-21 23:29:53 +00:00
// ----- Variables -----
static uint8_t transmit_previous_timeout = 0 ;
// ----- Functions -----
2013-01-27 06:47:52 +00:00
// send the contents of keyboard_keys and keyboard_modifier_keys
2014-09-21 23:29:53 +00:00
void usb_keyboard_send ( )
2013-01-27 06:47:52 +00:00
{
2014-09-21 23:29:53 +00:00
uint32_t wait_count = 0 ;
2013-01-27 06:47:52 +00:00
usb_packet_t * tx_packet ;
2014-09-29 00:24:52 +00:00
// Wait till ready
2014-09-21 23:29:53 +00:00
while ( 1 )
{
if ( ! usb_configuration )
{
erro_print ( " USB not configured... " ) ;
return ;
2013-01-27 06:47:52 +00:00
}
2014-09-29 00:24:52 +00:00
if ( USBKeys_Protocol = = 0 ) // Boot Mode
{
if ( usb_tx_packet_count ( NKRO_KEYBOARD_ENDPOINT ) < TX_PACKET_LIMIT )
{
tx_packet = usb_malloc ( ) ;
if ( tx_packet )
break ;
}
}
else if ( USBKeys_Protocol = = 1 ) // NKRO Mode
2014-09-21 23:29:53 +00:00
{
2014-09-29 00:24:52 +00:00
if ( usb_tx_packet_count ( KEYBOARD_ENDPOINT ) < TX_PACKET_LIMIT )
{
tx_packet = usb_malloc ( ) ;
if ( tx_packet )
break ;
}
2013-01-27 06:47:52 +00:00
}
2014-09-29 00:24:52 +00:00
2014-09-21 23:29:53 +00:00
if ( + + wait_count > TX_TIMEOUT | | transmit_previous_timeout )
{
2013-01-27 06:47:52 +00:00
transmit_previous_timeout = 1 ;
2014-09-21 23:29:53 +00:00
warn_print ( " USB Transmit Timeout... " ) ;
return ;
2013-01-27 06:47:52 +00:00
}
yield ( ) ;
}
2014-09-21 23:29:53 +00:00
2014-09-29 00:24:52 +00:00
// Pointer to USB tx packet buffer
uint8_t * tx_buf = tx_packet - > buf ;
switch ( USBKeys_Protocol )
{
// Send boot keyboard interrupt packet(s)
case 0 :
2015-02-21 21:06:28 +00:00
// USB Boot Mode debug output
if ( Output_DebugMode )
{
dbug_msg ( " Boot USB: " ) ;
printHex_op ( USBKeys_Modifiers , 2 ) ;
print ( " " ) ;
printHex ( 0 ) ;
print ( " " ) ;
printHex_op ( USBKeys_Keys [ 0 ] , 2 ) ;
printHex_op ( USBKeys_Keys [ 1 ] , 2 ) ;
printHex_op ( USBKeys_Keys [ 2 ] , 2 ) ;
printHex_op ( USBKeys_Keys [ 3 ] , 2 ) ;
printHex_op ( USBKeys_Keys [ 4 ] , 2 ) ;
printHex_op ( USBKeys_Keys [ 5 ] , 2 ) ;
print ( NL ) ;
}
2014-09-29 00:24:52 +00:00
// Boot Mode
* tx_buf + + = USBKeys_Modifiers ;
* tx_buf + + = 0 ;
memcpy ( tx_buf , USBKeys_Keys , USB_BOOT_MAX_KEYS ) ;
tx_packet - > len = 8 ;
// Send USB Packet
usb_tx ( KEYBOARD_ENDPOINT , tx_packet ) ;
USBKeys_Changed = USBKeyChangeState_None ;
break ;
// Send NKRO keyboard interrupts packet(s)
case 1 :
2015-02-21 21:06:28 +00:00
if ( Output_DebugMode )
{
dbug_msg ( " NKRO USB: " ) ;
}
2014-11-13 07:04:50 +00:00
// Check system control keys
if ( USBKeys_Changed & USBKeyChangeState_System )
2014-09-29 00:24:52 +00:00
{
2015-02-21 21:06:28 +00:00
if ( Output_DebugMode )
{
print ( " SysCtrl[ " ) ;
printHex_op ( USBKeys_SysCtrl , 2 ) ;
2015-02-24 06:25:46 +00:00
print ( " ] " NL ) ;
2015-02-21 21:06:28 +00:00
}
2014-11-13 07:04:50 +00:00
* tx_buf + + = 0x02 ; // ID
* tx_buf = USBKeys_SysCtrl ;
2014-09-29 00:24:52 +00:00
tx_packet - > len = 2 ;
// Send USB Packet
usb_tx ( NKRO_KEYBOARD_ENDPOINT , tx_packet ) ;
2014-11-13 07:04:50 +00:00
USBKeys_Changed & = ~ USBKeyChangeState_System ; // Mark sent
2014-09-29 00:24:52 +00:00
}
2014-11-13 07:04:50 +00:00
// Check consumer control keys
if ( USBKeys_Changed & USBKeyChangeState_Consumer )
2014-09-29 00:24:52 +00:00
{
2015-02-21 21:06:28 +00:00
if ( Output_DebugMode )
{
print ( " ConsCtrl[ " ) ;
printHex_op ( USBKeys_ConsCtrl , 2 ) ;
2015-02-24 06:25:46 +00:00
print ( " ] " NL ) ;
2015-02-21 21:06:28 +00:00
}
2014-09-29 00:24:52 +00:00
* tx_buf + + = 0x03 ; // ID
2014-11-13 07:04:50 +00:00
* tx_buf + + = ( uint8_t ) ( USBKeys_ConsCtrl & 0x00FF ) ;
* tx_buf = ( uint8_t ) ( USBKeys_ConsCtrl > > 8 ) ;
tx_packet - > len = 3 ;
2013-01-27 06:47:52 +00:00
2014-09-29 00:24:52 +00:00
// Send USB Packet
usb_tx ( NKRO_KEYBOARD_ENDPOINT , tx_packet ) ;
2014-11-13 07:04:50 +00:00
USBKeys_Changed & = ~ USBKeyChangeState_Consumer ; // Mark sent
2014-09-29 00:24:52 +00:00
}
2014-11-13 07:04:50 +00:00
// Standard HID Keyboard
if ( USBKeys_Changed )
2014-09-29 00:24:52 +00:00
{
2015-02-21 21:06:28 +00:00
// USB NKRO Debug output
if ( Output_DebugMode )
{
printHex_op ( USBKeys_Modifiers , 2 ) ;
print ( " " ) ;
for ( uint8_t c = 0 ; c < 6 ; c + + )
printHex_op ( USBKeys_Keys [ c ] , 2 ) ;
print ( " " ) ;
for ( uint8_t c = 6 ; c < 20 ; c + + )
printHex_op ( USBKeys_Keys [ c ] , 2 ) ;
print ( " " ) ;
printHex_op ( USBKeys_Keys [ 20 ] , 2 ) ;
print ( " " ) ;
for ( uint8_t c = 21 ; c < 27 ; c + + )
printHex_op ( USBKeys_Keys [ c ] , 2 ) ;
print ( NL ) ;
}
2014-11-13 07:04:50 +00:00
tx_packet - > len = 0 ;
// Modifiers
* tx_buf + + = 0x01 ; // ID
* tx_buf + + = USBKeys_Modifiers ;
tx_packet - > len + = 2 ;
// 4-49 (first 6 bytes)
memcpy ( tx_buf , USBKeys_Keys , 6 ) ;
tx_buf + = 6 ;
tx_packet - > len + = 6 ;
2014-09-29 00:24:52 +00:00
2014-11-11 05:02:25 +00:00
// 51-155 (Middle 14 bytes)
memcpy ( tx_buf , USBKeys_Keys + 6 , 14 ) ;
2014-11-13 07:04:50 +00:00
tx_buf + = 14 ;
tx_packet - > len + = 14 ;
2014-10-02 08:40:14 +00:00
2014-11-11 05:02:25 +00:00
// 157-164 (Next byte)
memcpy ( tx_buf , USBKeys_Keys + 20 , 1 ) ;
2014-11-13 07:04:50 +00:00
tx_buf + = 1 ;
tx_packet - > len + = 1 ;
2014-11-11 05:02:25 +00:00
2014-09-29 00:24:52 +00:00
// 176-221 (last 6 bytes)
2014-10-02 08:40:14 +00:00
memcpy ( tx_buf , USBKeys_Keys + 21 , 6 ) ;
2014-11-13 07:04:50 +00:00
tx_packet - > len + = 6 ;
2014-09-29 00:24:52 +00:00
// Send USB Packet
usb_tx ( NKRO_KEYBOARD_ENDPOINT , tx_packet ) ;
2014-11-13 07:04:50 +00:00
USBKeys_Changed = USBKeyChangeState_None ; // Mark sent
2014-09-29 00:24:52 +00:00
}
break ;
}
2014-09-21 23:29:53 +00:00
return ;
2013-01-27 06:47:52 +00:00
}