/* * Copyright (c) 2019 - 2024 Stefan Strobel * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ /** * @file main.c * @brief main module to demonstrate use of the shellmatta. * @author Stefan Strobel */ #include "shellmatta.h" #include #include #include #include #include #include #include static bool exitRequest = false; int f; shellmatta_handle_t handle; static shellmatta_retCode_t doSomething(shellmatta_handle_t handle, const char *arguments, uint32_t length) { shellmatta_printf(handle, "%s - length: %u", arguments, length); return SHELLMATTA_OK; } shellmatta_cmd_t doSomethingCmd = {"doSomething", "do", "Function does something", "use me, please", doSomething, NULL, NULL}; static shellmatta_retCode_t doSome(shellmatta_handle_t handle, const char *arguments, uint32_t length) { shellmatta_write(handle, "blubb\r\n", 7u); shellmatta_configure(handle, SHELLMATTA_MODE_INSERT, false, '\r'); (void)arguments; (void)length; return SHELLMATTA_OK; } shellmatta_cmd_t doSomeCmd = {"adoSome2", "adof2", "Function does something", "use me, please", doSome, NULL, NULL}; static shellmatta_retCode_t removeCmdFct(shellmatta_handle_t handle, const char *arguments, uint32_t length) { shellmatta_printf(handle, "removing command: %s\r\n", doSomeCmd.cmd); shellmatta_removeCmd(handle, &doSomeCmd); (void)arguments; (void)length; return SHELLMATTA_OK; } shellmatta_cmd_t removeCommand = {"remove", "r", "Function removes a command", "", removeCmdFct, NULL, NULL}; static shellmatta_retCode_t quit(shellmatta_handle_t handle, const char *arguments, uint32_t length) { exitRequest = true; (void)handle; (void)arguments; (void)length; return SHELLMATTA_OK; } shellmatta_cmd_t quitCommand = {"quit", "q", "Function quits the shell", "", quit, NULL, NULL}; static shellmatta_retCode_t empty(shellmatta_handle_t handle, const char *arguments, uint32_t length) { (void)arguments; (void)length; shellmatta_printf(handle, "empty function called\r\n"); shellmatta_configure(handle, SHELLMATTA_MODE_OVERWRITE, true, '\r'); return SHELLMATTA_OK; } shellmatta_cmd_t emptyCommand = {"empty", NULL, NULL, NULL, empty, NULL, NULL}; static shellmatta_retCode_t reset(shellmatta_handle_t handle, const char *arguments, uint32_t length) { shellmatta_retCode_t ret; (void)arguments; (void)length; char option; char *argument; uint32_t argLen; bool printPrompt = false; static const shellmatta_opt_long_t options[] = { {"prompt", 'p', SHELLMATTA_OPT_ARG_REQUIRED}, {NULL, '\0', SHELLMATTA_OPT_ARG_NONE} }; ret = shellmatta_opt_long(handle, options, &option, &argument, &argLen); while(SHELLMATTA_OK == ret) { switch(option) { case 'p': if(NULL != argument) { if(0 == strncmp("true", argument, 4u)) { printPrompt = true; } } break; default: shellmatta_printf(handle, "Unknown option: %c\r\n", option); break; } ret = shellmatta_opt_long(handle, options, &option, &argument, &argLen); } shellmatta_resetShell(handle, printPrompt); shellmatta_configure(handle, SHELLMATTA_MODE_INSERT, true, '\r'); return SHELLMATTA_OK; } shellmatta_cmd_t resetCommand = {"reset", NULL, "resets the shellmatta instance", "reset [--prompt true/false]", reset, NULL, NULL}; static shellmatta_retCode_t continuous(shellmatta_handle_t handle, const char *arguments, uint32_t length) { (void)arguments; (void)length; shellmatta_retCode_t ret = SHELLMATTA_CONTINUE; uint32_t stdinLength; char *stdinData; shellmatta_read(handle, &stdinData, &stdinLength); if(NULL != stdinData) { if('x' == stdinData[0u]) { ret = SHELLMATTA_OK; } stdinData[0u] ++; shellmatta_write(handle, stdinData, stdinLength); } return ret; } shellmatta_cmd_t continuousCommand = {"continuous", "cont", "prints continously all input bytes", "continuous", continuous, NULL, NULL}; static shellmatta_retCode_t busy(shellmatta_handle_t handle, const char *arguments, uint32_t length) { (void)arguments; (void)length; static uint32_t callCnt = 0u; shellmatta_retCode_t ret = SHELLMATTA_BUSY; if(callCnt < 10u) { callCnt ++; shellmatta_printf(handle, "%s - length %u - callCnt %u\r\n", arguments, length, callCnt); } else { callCnt = 0u; ret = SHELLMATTA_OK; } return ret; } shellmatta_cmd_t busyCommand = {"busy", NULL, NULL, NULL, busy, NULL, NULL}; shellmatta_retCode_t ret = SHELLMATTA_OK; void ymodemCallbackCancel(shellmatta_handle_t handle) { (void)handle; return; } void ymodemCallbackReceiveHeader(shellmatta_handle_t handle, uint32_t fileSize, char* fileName) { (void)handle; printf("Received Packet Header: %u %s\n", fileSize, fileName); return; } void ymodemCallbackReceivePacket(shellmatta_handle_t handle, uint8_t *data, uint32_t packetSize, uint32_t packetNum) { uint32_t i; (void)handle; printf("Received Packet: %u %u\n", packetNum, packetSize); for(i = 0u; i < packetSize; i ++) { printf("0x%02x ", data[i]); if(15u == (i % 16)) { printf("\n"); } } printf("\n"); return; } void ymodemCallbackTransmissionComplete(shellmatta_handle_t handle, shellmatta_retCode_t result) { (void)handle; ret = SHELLMATTA_OK; printf("\nTransmission complete: %s\n", result == SHELLMATTA_OK ? "success" : "error"); return; } uint8_t ymodemBuffer[1024u] = {0}; static shellmatta_retCode_t ymodem(shellmatta_handle_t handle, const char *arguments, uint32_t length) { (void)arguments; (void)length; shellmatta_printf(handle, "Starting ymodem session\r\n"); shellmatta_ymodem_init(handle, ymodemBuffer, ymodemCallbackCancel, ymodemCallbackReceiveHeader, ymodemCallbackReceivePacket, ymodemCallbackTransmissionComplete); return SHELLMATTA_OK; } shellmatta_cmd_t ymodemCommand = {"ymodem", NULL, NULL, NULL, ymodem, NULL, NULL}; shellmatta_retCode_t writeFct(const char* data, uint32_t length) { write(f, data, length); return SHELLMATTA_OK; } int main(int argc, char **argv) { static char buffer[1024]; static char historyBuffer[4096]; static shellmatta_instance_t instance; if(2 != argc) { printf("%s \n", argv[0u]); return -1; } f = open(argv[1u], O_RDWR | O_SYNC); if (f < 0) { printf("failure opening device %s %d\n", argv[1u], errno); return f; } printf("Starting Shellmatta\n"); shellmatta_doInit( &instance, &handle, buffer, sizeof(buffer), historyBuffer, sizeof(historyBuffer), "shellmatta->", NULL, writeFct); shellmatta_addCmd(handle, &doSomethingCmd); shellmatta_addCmd(handle, &doSomeCmd); shellmatta_addCmd(handle, &quitCommand); shellmatta_addCmd(handle, &removeCommand); shellmatta_addCmd(handle, &emptyCommand); shellmatta_addCmd(handle, &resetCommand); shellmatta_addCmd(handle, &continuousCommand); shellmatta_addCmd(handle, &busyCommand); shellmatta_addCmd(handle, &ymodemCommand); shellmatta_auth_user_t userList[] = { {1, false, "shimatta", "12345678"}, {2, false, "not_shimatta", "87654321"} }; uint32_t doSomeCmdPerms[] = {1, 2}; uint32_t removeCommandPerms[] = {1}; shellmatta_auth_perm_t permList[] = { {"adoSome2", doSomeCmdPerms, sizeof(doSomeCmdPerms)/sizeof(doSomeCmdPerms[0])}, {"remove", removeCommandPerms, sizeof(removeCommandPerms)/sizeof(removeCommandPerms[0])} }; shellmatta_auth_init(handle, userList, 2, permList, 2, false, NULL, NULL); int i = 0; while(exitRequest == false) { char c; shellmatta_retCode_t ret; int flags = fcntl(f, F_GETFL, 0); fcntl(f, F_SETFL, flags | O_NONBLOCK); int res = 0; res = read (f, &c, 1); if (res == -1) { i = (i + 1) % 10000; usleep(1); if (i != 0) { continue; } } do { res = res > 0 ? res : 0; ret = shellmatta_processData(handle, &c, res); if(SHELLMATTA_BUSY == ret) { sleep(1); } } while(SHELLMATTA_BUSY == ret); } close(f); return 0; }