wigig: Adding debug tools
Adding the debug tools package for 11ad
Change-Id: I171d7534614ec8941e0b48bb01d757ccd3be8960
Signed-off-by: Vadim Iosevich <vadimi@codeaurora.org>
diff --git a/debug-tools/remoteserver/servercmd.cpp b/debug-tools/remoteserver/servercmd.cpp
new file mode 100644
index 0000000..bfc180b
--- /dev/null
+++ b/debug-tools/remoteserver/servercmd.cpp
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sstream>
+
+#include "servercmd.h"
+#include "debug.h"
+
+#define EXP_NON 0
+#define EXP_CMD (-1)
+#define EXP_IFC 1
+#define EXP_NUM 2
+#define EXP_HEX 3
+#define EXP_SEP 4
+#define EXP_END 5
+
+const char* parser_state_to_string(int parserState)
+{
+ switch (parserState)
+ {
+ case EXP_NON: return "EXP_NON";
+ case EXP_CMD: return "EXP_CMD";
+ case EXP_IFC: return "EXP_IFC";
+ case EXP_NUM: return "EXP_NUM";
+ case EXP_HEX: return "EXP_HEX";
+ case EXP_SEP: return "EXP_SEP";
+ case EXP_END: return "EXP_END";
+ default: return "<unknown>";
+ }
+}
+
+
+static int states_table[][5] =
+{
+ { EXP_END, 0, 0, 0, 0 }, // 0 - get_interfaces
+ { EXP_IFC, EXP_END, 0, 0, 0 }, // 1 - open_interface name
+ { EXP_IFC, EXP_END, 0, 0, 0 }, // 2 - close_interface name
+ { EXP_IFC, EXP_NUM, EXP_END, 0, 0 }, // 3 - r name address
+ { EXP_IFC, EXP_NUM, EXP_NUM, EXP_END, 0 }, // 4 - rb name address count
+ { EXP_IFC, EXP_NUM, EXP_NUM, EXP_END, 0 }, // 5 - w name address value
+ { EXP_IFC, EXP_NUM, EXP_HEX, EXP_END, 0 }, // 6 - wb name address hexstring
+ { EXP_IFC, EXP_END, 0, 0, 0 }, // 7 - interface_reset name
+ { EXP_IFC, EXP_END, 0, 0, 0 }, // 8 - sw_reset name
+ { EXP_END, 0, 0, 0, 0 }, // 9 - exit
+ { EXP_IFC, EXP_NUM, EXP_NUM, EXP_END, 0 }, // 10 - Alloc_PMC name number_of_descriptors size_of_descriptors
+ { EXP_IFC, EXP_NUM, EXP_END, 0, 0 }, // 11 - read_pmc interface requestReferenceNumber
+ { EXP_NUM, EXP_END, 0, 0, 0 }, // 12 - read_pmc_file requestReferenceNumber
+ { EXP_IFC, EXP_END, 0, 0, 0 }, // 13 - set_host_alias
+};
+
+
+// The return value is copied because std::stringstream::str() returns a temporary object
+std::string parser_state_machine_to_string(int* pStateMachine)
+{
+ if (!pStateMachine)
+ {
+ return std::string("{}");
+ }
+
+ std::stringstream ss;
+
+ ss << "{ ";
+
+ size_t numStates = sizeof(states_table[0])/sizeof(int);
+ for (size_t i = 0; i < numStates; ++i)
+ {
+ ss << parser_state_to_string(pStateMachine[i]) << " ";
+ }
+ ss << "}";
+
+ return ss.str();
+}
+
+
+const char* command_to_string(int cmdCode)
+{
+ switch (cmdCode)
+ {
+ case CMD_COMMAND_UNKNOWN: return "CMD_COMMAND_UNKNOWN";
+ case CMD_GET_INTERFACES: return "CMD_GET_INTERFACES";
+ case CMD_OPEN_INTERFACE: return "CMD_OPEN_INTERFACE";
+ case CMD_CLOSE_INTERFACE: return "CMD_CLOSE_INTERFACE";
+ case CMD_R: return "CMD_R";
+ case CMD_RB: return "CMD_RB";
+ case CMD_W: return "CMD_W";
+ case CMD_WB: return "CMD_WB";
+ case CMD_INTERFACE_RESET: return "CMD_INTERFACE_RESET";
+ case CMD_SW_RESET: return "CMD_SW_RESET";
+ case CMD_EXIT: return "CMD_EXIT";
+ case CMD_ALLOC_PMC: return "CMD_ALLOC_PMC";
+ case CMD_READ_PMC: return "CMD_READ_PMC";
+ case CMD_READ_PMC_FILE: return "CMD_READ_PMC_FILE";
+ case CMD_SET_HOST_ALIAS: return "CMD_SET_HOST_ALIAS";
+ default: return "<unknown>";
+ }
+}
+
+
+const char* parser_error_to_string(int parserError)
+{
+ switch (parserError)
+ {
+ case ERR_BAD_TOKEN: return "ERR_BAD_TOKEN";
+ case ERR_BAD_VALUE: return "VALUE";
+ case ERR_UNTERMINATED_STRING: return "ERR_UNTERMINATED_STRING";
+ case ERR_BAD_HEX_VALUE: return "ERR_BAD_HEX_VALUE";
+ case ERR_CMD_NOT_EXPECTED: return "ERR_CMD_NOT_EXPECTED";
+ case ERR_IFACE_NOT_EXPECTED: return "ERR_IFACE_NOT_EXPECTED";
+ case ERR_VALUE_NOT_EXPECTED: return "ERR_VALUE_NOT_EXPECTED";
+ case ERR_HEX_NOT_EXPECTED: return "ERR_HEX_NOT_EXPECTED";
+ case ERR_END_NOT_EXPECTED: return "ERR_END_NOT_EXPECTED";
+ default: return "<unknown>";
+ }
+}
+
+
+
+/*
+ Callback on parser start.
+ Returns the handler to be used in all subsequent callbacks
+ or NULL in case of error, the parsing will be aborted then
+*/
+void cb_parser_start(servercmd_t *s)
+{
+ s->states = NULL;
+ s->state = EXP_CMD; // We start with expecting a command
+ s->cmd = CMD_COMMAND_UNKNOWN;
+ s->error = 0;
+ s->address = (unsigned int)-1;
+ s->value = (unsigned int)-1;
+ s->hexdata_len = 0;
+ s->hexdata = (unsigned int*)malloc (sizeof(int)*MAX_REGS_LEN);
+}
+
+/*
+ Callback on a command. Gets the command code.
+ Returns 0 if ok, 1 if error, the parsing will be aborted then
+*/
+int cb_cmd(servercmd_t *s, int cmd)
+{
+ LOG_VERBOSE <<"cb_cmd(" << cmd << ") state index = " << s->state << std::endl;
+ LOG_VERBOSE << "State Machine: " << parser_state_machine_to_string(s->states) << std::endl;
+
+ if(s->state != EXP_CMD) {
+ s->error = ERR_CMD_NOT_EXPECTED;
+ LOG_ERROR << "Command not expected, expecting " << s->state << std::endl;
+ return -1;
+ }
+ LOG_VERBOSE << "Parsed Command: " << cmd << "(" << command_to_string(cmd) << ")" << std::endl;
+ s->cmd = cmd;
+ s->states = states_table[cmd];
+ s->state++;
+
+ return 0;
+}
+
+
+/*
+ Returns 0 if ok, 1 if error, the parsing will be aborted then
+*/
+int cb_id(servercmd_t *s, const char *id)
+{
+ LOG_VERBOSE << "cb_id(" << id << ") state index = " << s->state << std::endl;
+ LOG_VERBOSE << "State Machine: " << parser_state_machine_to_string(s->states) << std::endl;
+
+ if((s->states == NULL) || (s->states[s->state] != EXP_IFC)) {
+ s->error = ERR_IFACE_NOT_EXPECTED;
+ LOG_ERROR << "Interface not expected, expecting: "
+ << (s->states?s->states[s->state]:-1) << std::endl;
+ return -1;
+ }
+
+ LOG_VERBOSE << "Interface id: " << id << std::endl;
+ snprintf(s->interface, MAX_INTERFACE_NAME, "%s", id);
+ s->state++;
+ return 0;
+}
+
+/*
+ Returns 0 if ok, 1 if error, the parsing will be aborted then
+*/
+int cb_number(servercmd_t *s, const char *id)
+{
+ LOG_VERBOSE << "cb_number(" << id << ") state index = " << s->state << std::endl;
+ LOG_VERBOSE << "State Machine: " << parser_state_machine_to_string(s->states) << std::endl;
+
+ if((s->states == NULL) || (s->states[s->state] != EXP_NUM)) {
+ s->error = ERR_VALUE_NOT_EXPECTED;
+ LOG_ERROR << "Number not expected, expecting " << (s->states?s->states[s->state]:-1) << std::endl;
+ return -1;
+ }
+
+ // A hack now. if address already set, the number is for data
+ LOG_VERBOSE << "string number " << id << std::endl;
+
+ if(s->address != (unsigned int)-1){
+ sscanf(id, "%u", &(s->value));
+ //s->value = strtoul(id, tmp, 10); //10 is the base for conversion
+ // dprint("str to uint Parsed val %u\n", strtoul(id, tmp, 10));
+ // dprint("str to int Parsed val %u\n", atol(id));//s->value = atol(id);
+ LOG_VERBOSE << "scanf Parsed value: " << s->value << std::endl;
+ }
+ else{
+ // s->address = atol(id);
+ sscanf(id, "%u", &(s->address));
+ LOG_VERBOSE << "Parsed addr " << s->address << std::endl;
+ }
+ s->state++;
+ return 0;
+}
+
+/*
+ Callback on hex data
+ Returns 0 if ok, 1 if error, the parsing will be aborted then
+*/
+int cb_hexbyte(servercmd_t *s, int b)
+{
+ LOG_VERBOSE << "cb_hexbyte(0x" << std::hex << b << std::dec << ") state index = " << s->state << std::endl;
+ LOG_VERBOSE << "State Machine: " << parser_state_machine_to_string(s->states) << std::endl;
+
+ if((s->states == NULL) || (s->states[s->state] != EXP_HEX)) {
+ s->error = ERR_HEX_NOT_EXPECTED;
+ LOG_ERROR << "Hex not expected, expecting " << (s->states?s->states[s->state]:-1) << std::endl;
+ return -1;
+ }
+ if(s->hexdata_len == MAX_REGS_LEN) {
+ s->error = ERR_BAD_HEX_VALUE;
+ LOG_ERROR << "Too long hex data" << std::endl;
+ return -1;
+ }
+ LOG_VERBOSE << "Hex byte 0x" << std::hex << b << std::dec << std::endl;
+ s->hexdata[s->hexdata_len] = b;
+ s->hexdata_len++;
+ // Do not change the s->state here, we are still expecting hex data. cb_endhex will change the state
+ return 0;
+}
+
+/*
+ Callback on end of hex data string
+ Returns 0 if ok, 1 if error, the parsing will be aborted then
+*/
+
+int cb_endhex(servercmd_t *s)
+{
+ LOG_VERBOSE << "cb_endhex() state index = " << s->state << std::endl;
+ LOG_VERBOSE << "State Machine: " << parser_state_machine_to_string(s->states) << std::endl;
+
+ if((s->states == NULL) || (s->states[s->state] != EXP_HEX)) {
+ s->error = ERR_HEX_NOT_EXPECTED;
+ LOG_ERROR << "Hex not expected, expecting " << (s->states?s->states[s->state]:-1) << std::endl;
+ return -1;
+ }
+ s->state++;
+ return 0;
+}
+
+/*
+ Callback on a separator, not used.
+ Returns 0 if ok, 1 if error, the parsing will be aborted then
+*/
+int cb_separator(servercmd_t *s)
+{
+ (void)s;
+ return 0;
+}
+
+/*
+ Callback on the parser end
+ Returns the parser result: 0 if ok, error otherwise
+*/
+void cb_parser_end(servercmd_t *s)
+{
+ LOG_VERBOSE << "cb_parser_end() state index = " << s->state << std::endl;
+ LOG_VERBOSE << "State Machine: " << parser_state_machine_to_string(s->states) << std::endl;
+
+ if((s->error == 0) && ((s->states == NULL) || (s->states[s->state] != EXP_END))) {
+ LOG_ERROR << "End of parser while still expecting " << (s->states?s->states[s->state]:-1) << std::endl;
+ s->error = ERR_END_NOT_EXPECTED;
+ }
+
+ free(s->hexdata);
+}
+
+/*
+ Callback on parser error
+*/
+void cb_error(servercmd_t *s, int error, const char *str)
+{
+ (void)str;
+ s->error = error;
+ LOG_ERROR << "Parser error: " << error << std::endl;
+}
+
+/*
+ Service function. Converting a hex digit from a character.
+*/
+int hexdigit(char d)
+{
+ if((d >= '0') && (d <= '9'))
+ return d-'0';
+ else if((d >= 'A') && (d <= 'F'))
+ return d-'A'+10;
+ else if((d >- 'a') && (d <= 'f'))
+ return d-'a'+10;
+ else // This shouldn't happen, it's the parser's responsibility to parse valid hex digits
+ return 0;
+}