2016-02-22 03:56:52 +00:00
/* Copyright (C) 2014-2016 by Jacob Alexander
2014-06-28 17:35:54 +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 :
*
* 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 .
*/
// ----- Includes -----
// Compiler Includes
# include <Lib/OutputLib.h>
// Project Includes
# include <cli.h>
2014-09-28 17:56:01 +00:00
# include <led.h>
2014-06-28 17:35:54 +00:00
# include <print.h>
# include <scan_loop.h>
// USB Includes
# if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
2015-01-01 01:13:44 +00:00
# elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
2015-03-07 07:37:09 +00:00
# include <arm/uart_serial.h>
# include <arm/usb_dev.h>
# include <arm/usb_keyboard.h>
# include <arm/usb_serial.h>
2014-06-28 17:35:54 +00:00
# endif
2016-05-17 06:25:08 +00:00
// KLL
# include <kll_defs.h>
2014-06-28 17:35:54 +00:00
// Local Includes
# include "output_com.h"
2014-09-28 17:56:01 +00:00
// ----- Macros -----
// Used to build a bitmap lookup table from a byte addressable array
# define byteLookup( byte ) case (( byte ) * ( 8 )): bytePosition = byte; byteShift = 0; break; \
2015-03-09 04:07:59 +00:00
case ( ( byte ) * ( 8 ) + ( 1 ) ) : bytePosition = byte ; byteShift = 1 ; break ; \
case ( ( byte ) * ( 8 ) + ( 2 ) ) : bytePosition = byte ; byteShift = 2 ; break ; \
case ( ( byte ) * ( 8 ) + ( 3 ) ) : bytePosition = byte ; byteShift = 3 ; break ; \
case ( ( byte ) * ( 8 ) + ( 4 ) ) : bytePosition = byte ; byteShift = 4 ; break ; \
case ( ( byte ) * ( 8 ) + ( 5 ) ) : bytePosition = byte ; byteShift = 5 ; break ; \
case ( ( byte ) * ( 8 ) + ( 6 ) ) : bytePosition = byte ; byteShift = 6 ; break ; \
case ( ( byte ) * ( 8 ) + ( 7 ) ) : bytePosition = byte ; byteShift = 7 ; break
2014-09-28 17:56:01 +00:00
2014-06-28 17:35:54 +00:00
// ----- Function Declarations -----
void cliFunc_kbdProtocol ( char * args ) ;
2015-07-19 01:53:21 +00:00
void cliFunc_outputDebug ( char * args ) ;
2014-06-28 17:35:54 +00:00
void cliFunc_readLEDs ( char * args ) ;
void cliFunc_readUART ( char * args ) ;
void cliFunc_sendKeys ( char * args ) ;
void cliFunc_sendUART ( char * args ) ;
void cliFunc_setKeys ( char * args ) ;
void cliFunc_setMod ( char * args ) ;
2014-09-28 17:56:01 +00:00
2014-06-28 17:35:54 +00:00
// ----- Variables -----
// Output Module command dictionary
2014-10-03 05:09:34 +00:00
CLIDict_Entry ( kbdProtocol , " Keyboard Protocol Mode: 0 - Boot, 1 - OS/NKRO Mode " ) ;
2015-07-19 01:53:21 +00:00
CLIDict_Entry ( outputDebug , " Toggle Output Debug mode. " ) ;
2014-10-03 05:09:34 +00:00
CLIDict_Entry ( readLEDs , " Read LED byte: " NL " \t \t 1 NumLck, 2 CapsLck, 4 ScrlLck, 16 Kana, etc. " ) ;
CLIDict_Entry ( readUART , " Read UART buffer until empty. " ) ;
CLIDict_Entry ( sendKeys , " Send the prepared list of USB codes and modifier byte. " ) ;
CLIDict_Entry ( sendUART , " Send characters over UART0. " ) ;
CLIDict_Entry ( setKeys , " Prepare a space separated list of USB codes (decimal). Waits until \033 [35msendKeys \033 [0m. " ) ;
CLIDict_Entry ( setMod , " Set the modfier byte: " NL " \t \t 1 LCtrl, 2 LShft, 4 LAlt, 8 LGUI, 16 RCtrl, 32 RShft, 64 RAlt, 128 RGUI " ) ;
CLIDict_Def ( outputCLIDict , " USB Module Commands " ) = {
CLIDict_Item ( kbdProtocol ) ,
2015-07-19 01:53:21 +00:00
CLIDict_Item ( outputDebug ) ,
2014-10-03 05:09:34 +00:00
CLIDict_Item ( readLEDs ) ,
CLIDict_Item ( readUART ) ,
CLIDict_Item ( sendKeys ) ,
CLIDict_Item ( sendUART ) ,
CLIDict_Item ( setKeys ) ,
CLIDict_Item ( setMod ) ,
2014-06-28 17:35:54 +00:00
{ 0 , 0 , 0 } // Null entry for dictionary end
} ;
// Which modifier keys are currently pressed
// 1=left ctrl, 2=left shift, 4=left alt, 8=left gui
// 16=right ctrl, 32=right shift, 64=right alt, 128=right gui
2015-07-19 01:53:21 +00:00
uint8_t USBKeys_Modifiers = 0 ;
uint8_t USBKeys_ModifiersCLI = 0 ; // Separate CLI send buffer
2014-06-28 17:35:54 +00:00
// Currently pressed keys, max is defined by USB_MAX_KEY_SEND
2015-07-19 01:53:21 +00:00
uint8_t USBKeys_Keys [ USB_NKRO_BITFIELD_SIZE_KEYS ] ;
uint8_t USBKeys_KeysCLI [ USB_NKRO_BITFIELD_SIZE_KEYS ] ; // Separate CLI send buffer
2014-09-28 17:56:01 +00:00
// System Control and Consumer Control 1KRO containers
2015-07-19 01:53:21 +00:00
uint8_t USBKeys_SysCtrl ;
uint16_t USBKeys_ConsCtrl ;
2014-06-28 17:35:54 +00:00
// The number of keys sent to the usb in the array
2015-07-19 01:53:21 +00:00
uint8_t USBKeys_Sent = 0 ;
uint8_t USBKeys_SentCLI = 0 ;
2014-06-28 17:35:54 +00:00
// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
2014-09-28 17:56:01 +00:00
volatile uint8_t USBKeys_LEDs = 0 ;
2014-06-28 17:35:54 +00:00
2016-05-17 06:25:08 +00:00
// Currently pressed mouse buttons, bitmask, 0 represents no buttons pressed
volatile uint16_t USBMouse_Buttons = 0 ;
// Relative mouse axis movement, stores pending movement
volatile uint16_t USBMouse_Relative_x = 0 ;
volatile uint16_t USBMouse_Relative_y = 0 ;
2014-06-28 17:35:54 +00:00
// Protocol setting from the host.
2014-09-28 17:56:01 +00:00
// 0 - Boot Mode
// 1 - NKRO Mode (Default, unless set by a BIOS or boot interface)
2016-05-17 06:25:08 +00:00
volatile uint8_t USBKeys_Protocol = USBProtocol_define ;
2014-09-28 17:56:01 +00:00
// Indicate if USB should send update
// OS only needs update if there has been a change in state
USBKeyChangeState USBKeys_Changed = USBKeyChangeState_None ;
2014-06-28 17:35:54 +00:00
2016-05-17 06:25:08 +00:00
// Indicate if USB should send update
USBMouseChangeState USBMouse_Changed = 0 ;
2014-06-28 17:35:54 +00:00
// the idle configuration, how often we send the report to the
// host (ms * 4) even when it hasn't changed
2015-07-19 01:53:21 +00:00
uint8_t USBKeys_Idle_Config = 125 ;
2014-06-28 17:35:54 +00:00
// count until idle timeout
2015-07-19 01:53:21 +00:00
uint8_t USBKeys_Idle_Count = 0 ;
2014-09-28 17:56:01 +00:00
2015-02-09 21:21:23 +00:00
// Indicates whether the Output module is fully functional
// 0 - Not fully functional, 1 - Fully functional
// 0 is often used to show that a USB cable is not plugged in (but has power)
2015-07-19 01:53:21 +00:00
volatile uint8_t Output_Available = 0 ;
2015-02-09 21:21:23 +00:00
2015-03-07 07:37:09 +00:00
// Debug control variable for Output modules
// 0 - Debug disabled (default)
// 1 - Debug enabled
2015-07-19 01:53:21 +00:00
uint8_t Output_DebugMode = 0 ;
2015-03-07 07:37:09 +00:00
2016-02-22 03:56:52 +00:00
// mA - Set by outside module if not using USB (i.e. Interconnect)
// Generally set to 100 mA (low power) or 500 mA (high power)
uint16_t Output_ExtCurrent_Available = 0 ;
// mA - Set by USB module (if exists)
// Initially 100 mA, but may be negotiated higher (e.g. 500 mA)
uint16_t Output_USBCurrent_Available = 0 ;
2014-09-28 17:56:01 +00:00
// ----- Capabilities -----
2015-03-07 07:37:09 +00:00
// Set Boot Keyboard Protocol
void Output_kbdProtocolBoot_capability ( uint8_t state , uint8_t stateType , uint8_t * args )
{
// Display capability name
if ( stateType = = 0xFF & & state = = 0xFF )
{
print ( " Output_kbdProtocolBoot() " ) ;
return ;
}
// Only set if necessary
if ( USBKeys_Protocol = = 0 )
return ;
// TODO Analog inputs
// Only set on key press
if ( stateType ! = 0x01 )
return ;
// Flush the key buffers
Output_flushBuffers ( ) ;
// Set the keyboard protocol to Boot Mode
USBKeys_Protocol = 0 ;
}
// Set NKRO Keyboard Protocol
void Output_kbdProtocolNKRO_capability ( uint8_t state , uint8_t stateType , uint8_t * args )
{
// Display capability name
if ( stateType = = 0xFF & & state = = 0xFF )
{
print ( " Output_kbdProtocolNKRO() " ) ;
return ;
}
// Only set if necessary
if ( USBKeys_Protocol = = 1 )
return ;
// TODO Analog inputs
// Only set on key press
if ( stateType ! = 0x01 )
return ;
// Flush the key buffers
Output_flushBuffers ( ) ;
// Set the keyboard protocol to NKRO Mode
USBKeys_Protocol = 1 ;
}
2016-05-26 11:06:12 +00:00
// Toggle Keyboard Protocol
void Output_toggleKbdProtocol_capability ( uint8_t state , uint8_t stateType , uint8_t * args )
{
// Display capability name
if ( stateType = = 0xFF & & state = = 0xFF )
{
print ( " Output_toggleKbdProtocol() " ) ;
return ;
}
// Only toggle protocol if release state
if ( stateType = = 0x00 & & state = = 0x03 )
{
// Flush the key buffers
Output_flushBuffers ( ) ;
// Toggle the keyboard protocol Mode
USBKeys_Protocol = ! USBKeys_Protocol ;
}
}
2014-09-28 17:56:01 +00:00
// Sends a Consumer Control code to the USB Output buffer
void Output_consCtrlSend_capability ( uint8_t state , uint8_t stateType , uint8_t * args )
{
// Display capability name
if ( stateType = = 0xFF & & state = = 0xFF )
{
print ( " Output_consCtrlSend(consCode) " ) ;
return ;
}
// Not implemented in Boot Mode
if ( USBKeys_Protocol = = 0 )
{
warn_print ( " Consumer Control is not implemented for Boot Mode " ) ;
return ;
}
// TODO Analog inputs
// Only indicate USB has changed if either a press or release has occured
if ( state = = 0x01 | | state = = 0x03 )
USBKeys_Changed | = USBKeyChangeState_Consumer ;
// Only send keypresses if press or hold state
if ( stateType = = 0x00 & & state = = 0x03 ) // Release state
2015-07-19 01:53:21 +00:00
{
USBKeys_ConsCtrl = 0 ;
2014-09-28 17:56:01 +00:00
return ;
2015-07-19 01:53:21 +00:00
}
2014-09-28 17:56:01 +00:00
// Set consumer control code
USBKeys_ConsCtrl = * ( uint16_t * ) ( & args [ 0 ] ) ;
}
2015-06-14 03:42:12 +00:00
// Ignores the given key status update
// Used to prevent fall-through, this is the None keyword in KLL
void Output_noneSend_capability ( uint8_t state , uint8_t stateType , uint8_t * args )
{
// Display capability name
if ( stateType = = 0xFF & & state = = 0xFF )
{
print ( " Output_noneSend() " ) ;
return ;
}
// Nothing to do, because that's the point :P
}
2014-09-28 17:56:01 +00:00
// Sends a System Control code to the USB Output buffer
void Output_sysCtrlSend_capability ( uint8_t state , uint8_t stateType , uint8_t * args )
{
// Display capability name
if ( stateType = = 0xFF & & state = = 0xFF )
{
print ( " Output_sysCtrlSend(sysCode) " ) ;
return ;
}
// Not implemented in Boot Mode
if ( USBKeys_Protocol = = 0 )
{
warn_print ( " System Control is not implemented for Boot Mode " ) ;
return ;
}
// TODO Analog inputs
// Only indicate USB has changed if either a press or release has occured
if ( state = = 0x01 | | state = = 0x03 )
USBKeys_Changed | = USBKeyChangeState_System ;
// Only send keypresses if press or hold state
if ( stateType = = 0x00 & & state = = 0x03 ) // Release state
2015-07-19 01:53:21 +00:00
{
USBKeys_SysCtrl = 0 ;
2014-09-28 17:56:01 +00:00
return ;
2015-07-19 01:53:21 +00:00
}
2014-09-28 17:56:01 +00:00
// Set system control code
USBKeys_SysCtrl = args [ 0 ] ;
}
// Adds a single USB Code to the USB Output buffer
// Argument #1: USB Code
void Output_usbCodeSend_capability ( uint8_t state , uint8_t stateType , uint8_t * args )
{
// Display capability name
if ( stateType = = 0xFF & & state = = 0xFF )
{
print ( " Output_usbCodeSend(usbCode) " ) ;
return ;
}
// Depending on which mode the keyboard is in the USB needs Press/Hold/Release events
uint8_t keyPress = 0 ; // Default to key release, only used for NKRO
switch ( USBKeys_Protocol )
{
case 0 : // Boot Mode
// TODO Analog inputs
// Only indicate USB has changed if either a press or release has occured
if ( state = = 0x01 | | state = = 0x03 )
USBKeys_Changed = USBKeyChangeState_MainKeys ;
// Only send keypresses if press or hold state
if ( stateType = = 0x00 & & state = = 0x03 ) // Release state
return ;
break ;
case 1 : // NKRO Mode
// Only send press and release events
if ( stateType = = 0x00 & & state = = 0x02 ) // Hold state
return ;
// Determine if setting or unsetting the bitfield (press == set)
if ( stateType = = 0x00 & & state = = 0x01 ) // Press state
keyPress = 1 ;
break ;
}
// Get the keycode from arguments
uint8_t key = args [ 0 ] ;
// Depending on which mode the keyboard is in, USBKeys_Keys array is used differently
// Boot mode - Maximum of 6 byte codes
// NKRO mode - Each bit of the 26 byte corresponds to a key
2015-07-19 01:53:21 +00:00
// Bits 0 - 45 (bytes 0 - 5) correspond to USB Codes 4 - 49 (Main)
// Bits 48 - 161 (bytes 6 - 20) correspond to USB Codes 51 - 164 (Secondary)
// Bits 168 - 213 (bytes 21 - 26) correspond to USB Codes 176 - 221 (Tertiary)
// Bits 214 - 216 unused
2014-09-28 17:56:01 +00:00
uint8_t bytePosition = 0 ;
uint8_t byteShift = 0 ;
switch ( USBKeys_Protocol )
{
case 0 : // Boot Mode
// Set the modifier bit if this key is a modifier
if ( ( key & 0xE0 ) = = 0xE0 ) // AND with 0xE0 (Left Ctrl, first modifier)
{
USBKeys_Modifiers | = 1 < < ( key ^ 0xE0 ) ; // Left shift 1 by key XOR 0xE0
}
// Normal USB Code
else
{
// USB Key limit reached
if ( USBKeys_Sent > = USB_BOOT_MAX_KEYS )
{
warn_print ( " USB Key limit reached " ) ;
return ;
}
// Make sure key is within the USB HID range
if ( key < = 104 )
{
USBKeys_Keys [ USBKeys_Sent + + ] = key ;
}
// Invalid key
else
{
warn_msg ( " USB Code above 104/0x68 in Boot Mode: " ) ;
printHex ( key ) ;
print ( NL ) ;
}
}
break ;
case 1 : // NKRO Mode
// Set the modifier bit if this key is a modifier
if ( ( key & 0xE0 ) = = 0xE0 ) // AND with 0xE0 (Left Ctrl, first modifier)
{
if ( keyPress )
{
USBKeys_Modifiers | = 1 < < ( key ^ 0xE0 ) ; // Left shift 1 by key XOR 0xE0
}
else // Release
{
USBKeys_Modifiers & = ~ ( 1 < < ( key ^ 0xE0 ) ) ; // Left shift 1 by key XOR 0xE0
}
USBKeys_Changed | = USBKeyChangeState_Modifiers ;
break ;
}
2015-07-19 01:53:21 +00:00
// First 6 bytes
else if ( key > = 4 & & key < = 49 )
2014-09-28 17:56:01 +00:00
{
// Lookup (otherwise division or multiple checks are needed to do alignment)
2015-07-19 01:53:21 +00:00
// Starting at 0th position, each byte has 8 bits, starting at 4th bit
uint8_t keyPos = key + ( 0 * 8 - 4 ) ; // Starting position in array, Ignoring 4 keys
2014-09-28 17:56:01 +00:00
switch ( keyPos )
{
byteLookup ( 0 ) ;
byteLookup ( 1 ) ;
byteLookup ( 2 ) ;
byteLookup ( 3 ) ;
byteLookup ( 4 ) ;
byteLookup ( 5 ) ;
2015-07-19 01:53:21 +00:00
}
USBKeys_Changed | = USBKeyChangeState_MainKeys ;
}
// Next 14 bytes
else if ( key > = 51 & & key < = 155 )
{
// Lookup (otherwise division or multiple checks are needed to do alignment)
// Starting at 6th byte position, each byte has 8 bits, starting at 51st bit
uint8_t keyPos = key + ( 6 * 8 - 51 ) ; // Starting position in array
switch ( keyPos )
{
2014-09-28 17:56:01 +00:00
byteLookup ( 6 ) ;
byteLookup ( 7 ) ;
byteLookup ( 8 ) ;
byteLookup ( 9 ) ;
byteLookup ( 10 ) ;
byteLookup ( 11 ) ;
byteLookup ( 12 ) ;
byteLookup ( 13 ) ;
byteLookup ( 14 ) ;
byteLookup ( 15 ) ;
byteLookup ( 16 ) ;
byteLookup ( 17 ) ;
byteLookup ( 18 ) ;
byteLookup ( 19 ) ;
}
2015-07-19 01:53:21 +00:00
USBKeys_Changed | = USBKeyChangeState_SecondaryKeys ;
}
// Next byte
else if ( key > = 157 & & key < = 164 )
{
// Lookup (otherwise division or multiple checks are needed to do alignment)
uint8_t keyPos = key + ( 20 * 8 - 157 ) ; // Starting position in array, Ignoring 6 keys
switch ( keyPos )
{
byteLookup ( 20 ) ;
}
USBKeys_Changed | = USBKeyChangeState_TertiaryKeys ;
2014-09-28 17:56:01 +00:00
}
// Last 6 bytes
else if ( key > = 176 & & key < = 221 )
{
// Lookup (otherwise division or multiple checks are needed to do alignment)
2015-07-19 01:53:21 +00:00
uint8_t keyPos = key + ( 21 * 8 - 176 ) ; // Starting position in array
2014-09-28 17:56:01 +00:00
switch ( keyPos )
{
byteLookup ( 21 ) ;
byteLookup ( 22 ) ;
byteLookup ( 23 ) ;
byteLookup ( 24 ) ;
byteLookup ( 25 ) ;
2015-07-19 01:53:21 +00:00
byteLookup ( 26 ) ;
2014-09-28 17:56:01 +00:00
}
2015-07-19 01:53:21 +00:00
USBKeys_Changed | = USBKeyChangeState_QuartiaryKeys ;
}
// Received 0x00
// This is a special USB Code that internally indicates a "break"
// It is used to send "nothing" in order to break up sequences of USB Codes
else if ( key = = 0x00 )
{
USBKeys_Changed | = USBKeyChangeState_MainKeys ;
// Also flush out buffers just in case
Output_flushBuffers ( ) ;
break ;
2014-09-28 17:56:01 +00:00
}
// Invalid key
else
{
2015-07-19 01:53:21 +00:00
warn_msg ( " USB Code not within 4-49 (0x4-0x31), 51-155 (0x33-0x9B), 157-164 (0x9D-0xA4), 176-221 (0xB0-0xDD) or 224-231 (0xE0-0xE7) NKRO Mode: " ) ;
2014-09-28 17:56:01 +00:00
printHex ( key ) ;
print ( NL ) ;
break ;
}
// Set/Unset
if ( keyPress )
{
USBKeys_Keys [ bytePosition ] | = ( 1 < < byteShift ) ;
USBKeys_Sent + + ;
}
else // Release
{
USBKeys_Keys [ bytePosition ] & = ~ ( 1 < < byteShift ) ;
USBKeys_Sent + + ;
}
break ;
}
}
2015-08-22 02:43:45 +00:00
void Output_flashMode_capability ( uint8_t state , uint8_t stateType , uint8_t * args )
{
// Display capability name
if ( stateType = = 0xFF & & state = = 0xFF )
{
2015-10-12 05:07:11 +00:00
print ( " Output_flashMode() " ) ;
2015-08-22 02:43:45 +00:00
return ;
}
// Start flash mode
Output_firmwareReload ( ) ;
}
2016-05-17 06:25:08 +00:00
// Sends a mouse command over the USB Output buffer
// XXX This function *will* be changing in the future
// If you use it, be prepared that your .kll files will break in the future (post KLL 0.5)
// Argument #1: USB Mouse Button (16 bit)
// Argument #2: USB X Axis (16 bit) relative
// Argument #3: USB Y Axis (16 bit) relative
void Output_usbMouse_capability ( uint8_t state , uint8_t stateType , uint8_t * args )
{
// Display capability name
if ( stateType = = 0xFF & & state = = 0xFF )
{
print ( " Output_usbMouse(mouseButton,relX,relY) " ) ;
return ;
}
// Determine which mouse button was sent
// The USB spec defines up to a max of 0xFFFF buttons
// The usual are:
// 1 - Button 1 - (Primary)
// 2 - Button 2 - (Secondary)
// 3 - Button 3 - (Tertiary)
uint16_t mouse_button = * ( uint16_t * ) ( & args [ 0 ] ) ;
// X/Y Relative Axis
uint16_t mouse_x = * ( uint16_t * ) ( & args [ 2 ] ) ;
uint16_t mouse_y = * ( uint16_t * ) ( & args [ 4 ] ) ;
// Adjust for bit shift
uint16_t mouse_button_shift = mouse_button - 1 ;
// Only send mouse button if in press or hold state
if ( stateType = = 0x00 & & state = = 0x03 ) // Release state
{
// Release
if ( mouse_button )
USBMouse_Buttons & = ~ ( 1 < < mouse_button_shift ) ;
}
else
{
// Press or hold
if ( mouse_button )
USBMouse_Buttons | = ( 1 < < mouse_button_shift ) ;
if ( mouse_x )
USBMouse_Relative_x = mouse_x ;
if ( mouse_y )
USBMouse_Relative_y = mouse_y ;
}
// Trigger updates
if ( mouse_button )
USBMouse_Changed | = USBMouseChangeState_Buttons ;
if ( mouse_x | | mouse_y )
USBMouse_Changed | = USBMouseChangeState_Relative ;
}
2014-06-28 17:35:54 +00:00
// ----- Functions -----
2015-03-07 07:37:09 +00:00
// Flush Key buffers
void Output_flushBuffers ( )
{
// Zero out USBKeys_Keys array
for ( uint8_t c = 0 ; c < USB_NKRO_BITFIELD_SIZE_KEYS ; c + + )
USBKeys_Keys [ c ] = 0 ;
// Zero out other key buffers
USBKeys_ConsCtrl = 0 ;
USBKeys_Modifiers = 0 ;
USBKeys_SysCtrl = 0 ;
}
2014-06-28 17:35:54 +00:00
// USB Module Setup
inline void Output_setup ( )
{
2014-09-28 23:43:40 +00:00
// Setup UART
uart_serial_setup ( ) ;
2015-07-19 01:53:21 +00:00
// Initialize the USB
// If a USB connection does not exist, just ignore it
// All usb related functions will non-fatally fail if called
// If the USB initialization is delayed, then functionality will just be delayed
2014-06-28 17:35:54 +00:00
usb_init ( ) ;
2014-07-15 07:28:12 +00:00
2014-06-28 17:35:54 +00:00
// Register USB Output CLI dictionary
CLI_registerDictionary ( outputCLIDict , outputCLIDictName ) ;
2014-09-28 17:56:01 +00:00
2015-07-19 01:53:21 +00:00
// Flush key buffers
Output_flushBuffers ( ) ;
2014-06-28 17:35:54 +00:00
}
// USB Data Send
2014-09-28 17:56:01 +00:00
inline void Output_send ( )
2014-06-28 17:35:54 +00:00
{
2016-02-22 03:56:52 +00:00
// USB status checks
// Non-standard USB state manipulation, usually does nothing
usb_device_check ( ) ;
2014-09-28 17:56:01 +00:00
// Boot Mode Only, unset stale keys
if ( USBKeys_Protocol = = 0 )
for ( uint8_t c = USBKeys_Sent ; c < USB_BOOT_MAX_KEYS ; c + + )
USBKeys_Keys [ c ] = 0 ;
2014-06-28 17:35:54 +00:00
2014-09-28 17:56:01 +00:00
// Send keypresses while there are pending changes
while ( USBKeys_Changed )
usb_keyboard_send ( ) ;
2014-06-28 17:35:54 +00:00
2015-07-19 01:53:21 +00:00
// Clear keys sent
USBKeys_Sent = 0 ;
2014-06-28 17:35:54 +00:00
2014-08-01 08:26:25 +00:00
// Signal Scan Module we are finished
2014-09-28 17:56:01 +00:00
switch ( USBKeys_Protocol )
{
case 0 : // Boot Mode
2015-07-19 01:53:21 +00:00
// Clear modifiers only in boot mode
USBKeys_Modifiers = 0 ;
2014-09-28 17:56:01 +00:00
Scan_finishedWithOutput ( USBKeys_Sent < = USB_BOOT_MAX_KEYS ? USBKeys_Sent : USB_BOOT_MAX_KEYS ) ;
break ;
case 1 : // NKRO Mode
Scan_finishedWithOutput ( USBKeys_Sent ) ;
break ;
}
2014-06-28 17:35:54 +00:00
}
// Sets the device into firmware reload mode
2015-07-19 01:53:21 +00:00
void Output_firmwareReload ( )
2014-06-28 17:35:54 +00:00
{
2015-07-19 01:53:21 +00:00
usb_device_reload ( ) ;
2014-06-28 17:35:54 +00:00
}
// USB Input buffer available
inline unsigned int Output_availablechar ( )
{
return usb_serial_available ( ) + uart_serial_available ( ) ;
}
// USB Get Character from input buffer
inline int Output_getchar ( )
{
2014-07-19 16:31:04 +00:00
// XXX Make sure to check output_availablechar() first! Information is lost with the cast (error codes) (AVR)
2014-06-28 17:35:54 +00:00
if ( usb_serial_available ( ) > 0 )
{
2014-07-19 16:31:04 +00:00
return ( int ) usb_serial_getchar ( ) ;
2014-06-28 17:35:54 +00:00
}
if ( uart_serial_available ( ) > 0 )
{
2014-07-19 16:31:04 +00:00
return ( int ) uart_serial_getchar ( ) ;
2014-06-28 17:35:54 +00:00
}
return - 1 ;
}
// USB Send Character to output buffer
inline int Output_putchar ( char c )
{
// First send to UART
uart_serial_putchar ( c ) ;
// Then send to USB
return usb_serial_putchar ( c ) ;
}
// USB Send String to output buffer, null terminated
inline int Output_putstr ( char * str )
{
# if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
2014-07-19 16:31:04 +00:00
uint16_t count = 0 ;
2015-01-01 01:13:44 +00:00
# elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM
2014-06-28 17:35:54 +00:00
uint32_t count = 0 ;
# endif
// Count characters until NULL character, then send the amount counted
while ( str [ count ] ! = ' \0 ' )
count + + ;
2014-06-28 21:12:56 +00:00
// First send to UART
uart_serial_write ( str , count ) ;
2014-06-28 17:35:54 +00:00
// Then send to USB
return usb_serial_write ( str , count ) ;
}
// Soft Chip Reset
inline void Output_softReset ( )
{
2014-07-19 16:31:04 +00:00
usb_device_software_reset ( ) ;
2014-06-28 17:35:54 +00:00
}
2016-02-22 03:56:52 +00:00
// Update USB current (mA)
// Triggers power change event
void Output_update_usb_current ( unsigned int current )
{
// Only signal if changed
if ( current = = Output_USBCurrent_Available )
return ;
// Update USB current
Output_USBCurrent_Available = current ;
2016-05-17 08:18:14 +00:00
/* XXX Affects sleep states due to USB messages
2016-02-22 03:56:52 +00:00
unsigned int total_current = Output_current_available ( ) ;
info_msg ( " USB Available Current Changed. Total Available: " ) ;
printInt32 ( total_current ) ;
print ( " mA " NL ) ;
2016-05-17 08:18:14 +00:00
*/
2016-02-22 03:56:52 +00:00
// Send new total current to the Scan Modules
Scan_currentChange ( Output_current_available ( ) ) ;
}
// Update external current (mA)
// Triggers power change event
void Output_update_external_current ( unsigned int current )
{
// Only signal if changed
if ( current = = Output_ExtCurrent_Available )
return ;
// Update external current
Output_ExtCurrent_Available = current ;
unsigned int total_current = Output_current_available ( ) ;
info_msg ( " External Available Current Changed. Total Available: " ) ;
printInt32 ( total_current ) ;
print ( " mA " NL ) ;
// Send new total current to the Scan Modules
Scan_currentChange ( Output_current_available ( ) ) ;
}
// Power/Current Available
unsigned int Output_current_available ( )
{
unsigned int total_current = 0 ;
// Check for USB current source
total_current + = Output_USBCurrent_Available ;
// Check for external current source
total_current + = Output_ExtCurrent_Available ;
// XXX If the total available current is still 0
// Set to 100 mA, which is generally a safe assumption at startup
// before we've been able to determine actual available current
if ( total_current = = 0 )
{
total_current = 100 ;
}
return total_current ;
}
2014-06-28 17:35:54 +00:00
// ----- CLI Command Functions -----
void cliFunc_kbdProtocol ( char * args )
{
print ( NL ) ;
info_msg ( " Keyboard Protocol: " ) ;
printInt8 ( USBKeys_Protocol ) ;
}
2015-07-19 01:53:21 +00:00
void cliFunc_outputDebug ( char * args )
{
// Parse number from argument
// NOTE: Only first argument is used
char * arg1Ptr ;
char * arg2Ptr ;
CLI_argumentIsolation ( args , & arg1Ptr , & arg2Ptr ) ;
// Default to 1 if no argument is given
Output_DebugMode = 1 ;
if ( arg1Ptr [ 0 ] ! = ' \0 ' )
{
Output_DebugMode = ( uint16_t ) numToInt ( arg1Ptr ) ;
}
}
2014-06-28 17:35:54 +00:00
void cliFunc_readLEDs ( char * args )
{
print ( NL ) ;
2014-09-28 17:56:01 +00:00
info_msg ( " LED State: " ) ;
2014-06-28 17:35:54 +00:00
printInt8 ( USBKeys_LEDs ) ;
}
void cliFunc_readUART ( char * args )
{
print ( NL ) ;
// Read UART buffer until empty
while ( uart_serial_available ( ) > 0 )
{
char out [ ] = { ( char ) uart_serial_getchar ( ) , ' \0 ' } ;
dPrint ( out ) ;
}
}
void cliFunc_sendKeys ( char * args )
{
2014-09-28 17:56:01 +00:00
// Copy USBKeys_KeysCLI to USBKeys_Keys
2014-06-28 17:35:54 +00:00
for ( uint8_t key = 0 ; key < USBKeys_SentCLI ; + + key )
{
2014-09-28 17:56:01 +00:00
// TODO
//USBKeys_Keys[key] = USBKeys_KeysCLI[key];
2014-06-28 17:35:54 +00:00
}
USBKeys_Sent = USBKeys_SentCLI ;
// Set modifier byte
USBKeys_Modifiers = USBKeys_ModifiersCLI ;
}
void cliFunc_sendUART ( char * args )
{
// Write all args to UART
uart_serial_write ( args , lenStr ( args ) ) ;
}
void cliFunc_setKeys ( char * args )
{
char * curArgs ;
char * arg1Ptr ;
char * arg2Ptr = args ;
// Parse up to USBKeys_MaxSize args (whichever is least)
2014-09-28 17:56:01 +00:00
for ( USBKeys_SentCLI = 0 ; USBKeys_SentCLI < USB_BOOT_MAX_KEYS ; + + USBKeys_SentCLI )
2014-06-28 17:35:54 +00:00
{
curArgs = arg2Ptr ;
CLI_argumentIsolation ( curArgs , & arg1Ptr , & arg2Ptr ) ;
// Stop processing args if no more are found
if ( * arg1Ptr = = ' \0 ' )
break ;
// Add the USB code to be sent
2014-09-28 17:56:01 +00:00
// TODO
//USBKeys_KeysCLI[USBKeys_SentCLI] = numToInt( arg1Ptr );
2014-06-28 17:35:54 +00:00
}
}
void cliFunc_setMod ( char * args )
{
// Parse number from argument
// NOTE: Only first argument is used
char * arg1Ptr ;
char * arg2Ptr ;
CLI_argumentIsolation ( args , & arg1Ptr , & arg2Ptr ) ;
2014-08-16 19:07:25 +00:00
USBKeys_ModifiersCLI = numToInt ( arg1Ptr ) ;
2014-06-28 17:35:54 +00:00
}