]> git.donarmstrong.com Git - kiibohd-controller.git/blobdiff - Debug/cli/cli.c
Adding basic CLI functionality.
[kiibohd-controller.git] / Debug / cli / cli.c
index da657ccc60940ab4b1fc0c601aed377bf3111eeb..b69bdf0dd42a8e2c3cff04deae5fb1881eccd396 100644 (file)
 
 // Project Includes
 #include "cli.h"
+#include <print.h>
+
+
+
+// ----- Variables -----
+
+// Basic command dictionary
+CLIDictItem basicCLIDict[] = {
+       { "help",    "This command :P", cliFunc_help },
+       { "version", "Version information about this firmware.", cliFunc_version },
+       { 0, 0, 0 } // Null entry for dictionary end
+};
 
 
 
 // ----- Functions -----
 
-void init_cli()
+inline void prompt()
+{
+       print(": ");
+}
+
+inline void init_cli()
+{
+       // Reset the Line Buffer
+       CLILineBufferCurrent = 0;
+
+       // Set prompt
+       prompt();
+
+       // Register first dictionary
+       CLIDictionariesUsed = 0;
+       registerDictionary_cli( basicCLIDict );
+}
+
+void process_cli()
+{
+       // Current buffer position
+       uint8_t prev_buf_pos = CLILineBufferCurrent;
+
+       // Process each character while available
+       int result = 0;
+       while ( 1 )
+       {
+               // No more characters to process
+               result = usb_serial_getchar(); // Retrieve from serial module // TODO Make USB agnostic
+               if ( result == -1 )
+                       break;
+
+               char cur_char = (char)result;
+
+               // Make sure buffer isn't full
+               if ( CLILineBufferCurrent >= CLILineBufferMaxSize )
+               {
+                       print( NL );
+                       erro_print("Serial line buffer is full, dropping character and resetting...");
+
+                       // Clear buffer
+                       CLILineBufferCurrent = 0;
+
+                       // Reset the prompt
+                       prompt();
+
+                       return;
+               }
+
+               // Place into line buffer
+               CLILineBuffer[CLILineBufferCurrent++] = cur_char;
+       }
+
+       // If buffer has changed, output to screen while there are still characters in the buffer not displayed
+       while ( CLILineBufferCurrent > prev_buf_pos )
+       {
+               // Check for control characters
+               switch ( CLILineBuffer[prev_buf_pos] )
+               {
+               case 0x0D: // Enter
+                       CLILineBufferCurrent--; // Remove the Enter
+
+                       // Process the current line buffer
+                       commandLookup_cli();
+
+                       // Reset the buffer
+                       CLILineBufferCurrent = 0;
+
+                       // Reset the prompt after processing has finished
+                       print( NL );
+                       prompt();
+
+                       // XXX There is a potential bug here when resetting the buffer (losing valid keypresses)
+                       //     Doesn't look like it will happen *that* often, so not handling it for now -HaaTa
+                       return;
+
+               case 0x09: // Tab
+                       // Tab completion for the current command
+                       // TODO
+                       return;
+
+               case 0x1B: // Esc
+                       // Check for escape sequence
+                       // TODO
+                       return;
+
+               case 0x08:
+               case 0x7F: // Backspace
+                       // TODO - Does not handle case for arrow editing (arrows disabled atm)
+                       CLILineBufferCurrent--; // Remove the backspace
+
+                       // If there are characters in the buffer
+                       if ( CLILineBufferCurrent > 0 )
+                       {
+                               // Remove character from current position in the line buffer
+                               CLILineBufferCurrent--;
+
+                               // Remove character from tty
+                               print("\b \b");
+                       }
+
+                       break;
+
+               default:
+                       // Place a null on the end (to use with string print)
+                       CLILineBuffer[CLILineBufferCurrent] = '\0';
+
+                       // Output buffer to screen
+                       dPrint( &CLILineBuffer[prev_buf_pos] );
+
+                       // Buffer reset
+                       prev_buf_pos++;
+
+                       break;
+               }
+
+               /* TODO Enable via option
+               uint8_t pos = prev_buf_pos;
+               while ( CLILineBuffer[pos] != 0 )
+               {
+                       printHex( CLILineBuffer[pos++] );
+                       print(" ");
+               }
+
+               print( NL );
+               */
+       }
+}
+
+void commandLookup_cli()
+{
+       // Ignore command if buffer is 0 length
+       if ( CLILineBufferCurrent == 0 )
+               return;
+
+       // Set the last+1 character of the buffer to NULL for string processing
+       CLILineBuffer[CLILineBufferCurrent] = '\0';
+
+       // Mark out the first argument
+       // This is done by finding the first space after a list of non-spaces and setting it NULL
+       char* cmdPtr = CLILineBuffer - 1;
+       while ( *++cmdPtr == ' ' ); // Skips leading spaces, and points to first character of cmd
+
+       // Locates first space delimiter, and points to first character of args or a NULL (no args)
+       char* argPtr = cmdPtr;
+       do {
+               argPtr++;
+       } while ( *argPtr != ' ' && *argPtr != '\0' );
+
+       // Set the space delimiter as a NULL
+       argPtr[-1] = '\0';
+
+       // Scan array of dictionaries for a valid command match
+       for ( uint8_t dict = 0; dict < CLIDictionariesUsed; dict++ )
+       {
+               // Parse each cmd until a null command entry is found, or an argument match
+               for ( uint8_t cmd = 0; CLIDict[dict][cmd].name != 0; cmd++ )
+               {
+                       // Compare the first argument and each command entry
+                       if ( eqStr( cmdPtr, CLIDict[dict][cmd].name ) )
+                       {
+                               // Run the specified command function pointer
+                               //   argPtr is already pointing at the first character of the arguments
+                               (*CLIDict[dict][cmd].function)( argPtr );
+
+                               return;
+                       }
+               }
+       }
+
+       // No match for the command...
+       print( NL );
+       erro_dPrint("\"", CLILineBuffer, "\" is not a valid command...try help");
+}
+
+void registerDictionary_cli( CLIDictItem *cmdDict )
+{
+       // Make sure this max limit of dictionaries hasn't been reached
+       if ( CLIDictionariesUsed >= CLIMaxDictionaries )
+       {
+               erro_print("Max number of dictionaries defined already...");
+               return;
+       }
+
+       // Add dictionary
+       CLIDict[CLIDictionariesUsed++] = cmdDict;
+}
+
+
+
+// ----- CLI Command Functions -----
+
+void cliFunc_help( char* args )
+{
+       print( NL );
+       print("Help!");
+       dPrint( args );
+}
+
+void cliFunc_version( char* args )
 {
+       print( NL );
+       print("Version!");
+       dPrint( args );
 }