summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorRyan Harkin <ryan.harkin@linaro.org>2012-05-25 08:36:24 +0000
committerRyan Harkin <ryan.harkin@linaro.org>2012-05-25 08:36:24 +0000
commit05488cad0e381dc10f54d6d9909ab7eab30f262e (patch)
treea627a02346562fcf4a29f56c4eee8fcd7f0b535c /main.c
Initial commitHEADmaster
Diffstat (limited to 'main.c')
-rw-r--r--main.c326
1 files changed, 326 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..da59887
--- /dev/null
+++ b/main.c
@@ -0,0 +1,326 @@
+/* Test application of STM Framework and driver
+ *
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <dirent.h>
+#include <pthread.h>
+
+#include "test_commands.h"
+
+/* global const */
+#define LOCAL_TEST_STUB
+#ifdef LOCAL_TEST_STUB
+const char* DEBUGFS_STM = "./debug_stm/";
+#else
+const char* DEBUGFS_STM = "/sys/kernel/debug/stm/";
+#endif
+
+pthread_mutex_t mux;
+
+command_list stm_test_command_list[] = {
+ {
+ "create_chan",
+ stm_create_channel,
+ true,
+ false,
+ stm_create_channel_sync_verify,
+ NULL,
+ },
+ {
+ "info",
+ stm_info,
+ true,
+ false,
+ stm_info_sync_verify,
+ NULL,
+ }
+};
+
+/* to check and return command index of stm_test_command_list[]
+ * Input:
+ * - command_name: null terminated string of STM test command_name
+ * Return:
+ * - 0 or positive: index of command_name
+ * - negative value: error
+ */
+int check_command_index(const char* command_name)
+{
+ int index = -1;
+ int total_commands = 0;
+
+ total_commands = (int) (sizeof(stm_test_command_list)/sizeof(command_list));
+
+ for(index = 0; index < total_commands; index ++) {
+ if(!strcmp(command_name, stm_test_command_list[index].command_name)) {
+ TDBG("command match found, index=%d, command_name=%s\n",
+ index, command_name);
+ return index;
+ }
+ }
+
+ /* in case there is no match, return an error. */
+ index = -1;
+ TDBG("no command match. command_name=%s\n", command_name);
+ return index;
+}
+
+/* to create one STM channel
+ * Input:
+ * - param_num: total number of parameters, incl. command_name, in param_array
+ * - param_array: an char string array to host all parameters, w/ command_name
+ * being the first.
+ * Return:
+ * - 0: success
+ * - negartive value: error
+ */
+int stm_create_channel(int param_num, char** param_array, command_result_type* ptr_command_result)
+{
+ int ret = -1;
+ char shell_command[MAX_SHELL_COMMAND_LINE_SIZE];
+
+ TDBG("In %s()\n", __FUNCTION__);
+
+ /* check validity of input parameters */
+ if(param_num != 2) {
+ TDBG("Invalid parameter numbers in %s.\n", __FUNCTION__);
+ return ret;
+ }
+
+ /* compose a shell command */
+ ret = snprintf(shell_command, MAX_SHELL_COMMAND_LINE_SIZE,
+ "echo -n \"user %s\\0\" > %srequest", param_array[1], DEBUGFS_STM);
+ if( ret >= MAX_SHELL_COMMAND_LINE_SIZE ) {
+ /* a return value of size or more means that the output
+ * was truncated. */
+ TDBG("Command line too long. %d\n", ret);
+ printf("Command line too long. Try to use shorter strings.\n");
+ return -ret;
+ }
+
+ /* send this command to shell */
+ ret = system(shell_command);
+ TDBG("system(\"%s\") returns %d, RAW ret = 0x%x\n", shell_command, WEXITSTATUS(ret), ret);
+ if( ret == -1 ) {
+ printf("system() returns error %d.", ret);
+ return ret;
+ }
+ switch( WEXITSTATUS(ret) ) {
+ case 0:
+ ptr_command_result->command_execution_result = COMMAND_EXEC_SUCCESS;
+ break;
+ case 2:
+
+ /* TODO
+ * more checks about error conditions
+ *
+ * 2 means: sh: cannot create /sys/kernel/debug/stm/request: Permission denied system(echo -n -e "user xx" > /sys/kernel/debug/stm/request) returns 2.
+ */
+ ptr_command_result->command_execution_result = COMMAND_EXEC_FAILURE;
+ break;
+ default:
+ ptr_command_result->command_execution_result = COMMAND_EXEC_FAILURE;
+ break;
+ }
+
+ return WEXITSTATUS(ret);
+}
+
+
+/* to verify the creation of one STM channel
+ * Input:
+ * - param_num: total number of parameters, incl. command_name, in param_array
+ * - param_array: an char string array to host all parameters, w/ command_name
+ * being the first.
+ * Return:
+ * - 0: success
+ * - -1: only <channel_name>, no <channel_name>_config;
+ * - -2: only <channel_name>_config, no <channel_name>;
+ * - -3: neither of <channel_name> and <channel_name>_config exist;
+ * - negartive value: error, other
+ */
+int stm_create_channel_sync_verify(int param_num, char** param_array, command_result_type* ptr_command_result)
+{
+ int ret = -1;
+ bool exist_channel_name = false;
+ bool exist_channel_config = false;
+ char channel_config_name[MAX_CONFIG_NAME_LENGTH];
+ char* channel_name = param_array[1];
+
+ TDBG("In %s: channel_name is %s.\n", __FUNCTION__, channel_name);
+
+ /* set verification result as failure */
+ ptr_command_result->sync_veri_result = SYNC_VERIFICATION_FAILURE;
+
+ /* to check two new nodes under stm/: <channel_name> and <channel_name>_config */
+ if (search_file(DEBUGFS_STM, channel_name) == 1)
+ exist_channel_name = true;
+
+ ret = snprintf(channel_config_name, MAX_CONFIG_NAME_LENGTH, "%s_config", channel_name);
+ /* check if truncated */
+ if (ret >= MAX_CONFIG_NAME_LENGTH ) {
+ printf("config file name exceeds maximum allowed length %d. %s.",
+ MAX_CONFIG_NAME_LENGTH, channel_name);
+ goto verify_result;
+ }
+ if (search_file(DEBUGFS_STM, channel_config_name) == 1)
+ exist_channel_config = true;
+
+verify_result:
+ if (exist_channel_name) {
+ if (exist_channel_config) {
+ ptr_command_result->sync_veri_result = SYNC_VERIFICATION_SUCCESS;
+ return 0;
+ }
+ else
+ return -1;
+ } else {
+ if (exist_channel_config)
+ return -2;
+ else
+ return -3;
+ }
+
+ return -4; /* should never been here*/
+}
+
+/* to get general STM information by reading <debugfs>/stm/request
+ * Input:
+ * - param_num: total number of parameters, incl. command_name, in param_array
+ * - param_array: an char string array to host all parameters, w/ command_name
+ * being the first.
+ * Return:
+ * - 0: success
+ * - -1: failure
+ */
+int stm_info(int param_num, char** param_array, command_result_type* ptr_command_result)
+{
+ int ret = -1;
+ char request_filename[MAX_CONFIG_NAME_LENGTH] = "";
+ unsigned char* stm_information;
+ FILE* fd;
+ int offset = 0;
+
+ /* compose the filename */
+ ret = snprintf(request_filename, MAX_CONFIG_NAME_LENGTH, "%srequest", DEBUGFS_STM);
+ if (ret >= MAX_CONFIG_NAME_LENGTH) {
+ TDBG("STM request fileanme is longer than %d byte in length. Which should not happen.\n", MAX_CONFIG_NAME_LENGTH);
+ return -1;
+ }
+
+ /* open <debugfs>/request */
+ fd = fopen(request_filename, "rb");
+
+ /* allocate memory for file reading */
+ stm_information = (unsigned char *)malloc(MAX_SIZE_STM_REQUEST);
+ if (stm_information == NULL) {
+ printf("Memory allocation error in func: %s\n", __FUNCTION__);
+ return -1;
+ }
+ memset(stm_information, '\0', MAX_SIZE_STM_REQUEST);
+
+ /* read file contents */
+ ret = fread(stm_information, sizeof(unsigned char), MAX_SIZE_STM_REQUEST, fd);
+ TDBG("STM request %s file length: %d byte\n", request_filename, ret);
+
+ if (!feof(fd)) {
+ printf("STM request reading returns more than %d bytes. Need to modify the source code to fix this.\n", MAX_SIZE_STM_REQUEST);
+ return -1;
+ }
+
+ /* for debugging purpose only, dump file contents */
+ TDBG("Dump of STM request file:\n");
+ {
+ int i;
+ unsigned char* c;
+ for(i = 0, c = stm_information; i < ret; i ++, c ++) {
+ TDBG("%c", *c);
+ }
+ TDBG("\n");
+ }
+
+ /* link the memory space to private_data */
+ ptr_command_result->private_data = stm_information;
+ return 0;
+}
+
+int stm_info_sync_verify()
+{
+ return 0;
+}
+
+static int command_sequencial_count = 0; /* to record total number of commands executed */
+
+int main(int argc, char** argv)
+{
+ int ret = 0;
+ bool succ = true;
+ int cmd_index = -1;
+ command_list* current_command = NULL;
+ command_result_type current_command_result;
+
+/*
+ pthread_mutex_init(&mux, NULL);
+ pthread_mutex_lock(&mux);
+ TDBG("pthread_mutex testing.\n");
+ pthread_mutex_unlock(&mux);
+*/
+
+ /* check command line information */
+ if (argc == 1) {
+ TDBG("Test commands come from standard input.\n");
+ /* read test commands from standard input */
+ /* TODO */
+ return ret;
+ }
+
+ /* check index of test command */
+ cmd_index = check_command_index(argv[1]);
+ if (cmd_index < 0) {
+ printf("Invaild test command. Type in \" %s help\" to get guidance.\n", argv[0]);
+ return ret;
+ }
+
+ current_command = &stm_test_command_list[cmd_index];
+
+ /* initialize current_command_result */
+ INIT_COMMAND_RESULT(&current_command_result);
+ current_command_result.current_command = &stm_test_command_list[cmd_index];
+ current_command_result.sequencial_id = command_sequencial_count;
+
+ /* increase the global command seq count by 1 */
+ command_sequencial_count ++;
+
+ /* make and send shell command */
+ (* current_command->command_consumer_callback)(argc - 1, argv + 1, &current_command_result);
+
+ /* to call sync_verification API if proper */
+ if (current_command->is_sync == true && current_command->sync_verification_callback != NULL) {
+ TDBG("to call sync_verification API.\n");
+ (* current_command->sync_verification_callback)(argc - 1, argv +1, &current_command_result);
+ }
+
+ /* to call async_verification API if proper */
+ if (current_command->is_async == true && current_command->async_verification_callback != NULL) {
+ TDBG("to call async_verification API.\n");
+ (* current_command->async_verification_callback)();
+ }
+
+ /* to record the command result */
+ /* TODO */
+
+ /* to free memory before exit */
+ /* TODO */
+ if (current_command_result.private_data != NULL) {
+ /* TODO: double check here. what if the private_data is not one single block allocated by malloc? should we define a command specific private_data freeing API? */
+ free(current_command_result.private_data);
+ }
+
+ return ret;
+}
+