ASR_BASE
Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/lte-telephony/apps/diag/command_api.c b/marvell/lte-telephony/apps/diag/command_api.c
new file mode 100644
index 0000000..3a541fe
--- /dev/null
+++ b/marvell/lte-telephony/apps/diag/command_api.c
@@ -0,0 +1,380 @@
+/******************************************************************************
+*(C) Copyright 2011 Marvell International Ltd.
+* All Rights Reserved
+******************************************************************************/
+/*--------------------------------------------------------------------------------------------------------------------
+ * -------------------------------------------------------------------------------------------------------------------
+ *
+ * Filename: command_api.c
+ *
+ * Description: The APIs to remotely control DIAG internal behaviors.
+ *
+ * History:
+ * Aug, 13 2012 - Haili Wang(hlw@marvell.com) Creation of file
+ *
+ * Notes:
+ *
+ ******************************************************************************/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#ifdef ANDROID
+#include <cutils/sockets.h>
+#endif
+
+#include "utlEventHandler.h"
+#include "media_manager.h"
+#include "diag_state_machine.h"
+#include "sd_api.h"
+#include "pxa_dbg.h"
+#include "diag_al.h"
+#include "diag_api.h"
+
+static const char response_error[] = "ERROR";
+static const char response_invalid[] = "INVALID";
+static const char response_success[] = "SUCCESS";
+
+static int cmdfd = -1;
+static utlEventHandlerId_T cmdHandler;
+
+
+struct command_client{
+ int fd;
+ utlEventHandlerId_T handle_id;
+};
+
+#define MAX_CLIENT_NUMBER 10
+static struct command_client clients[MAX_CLIENT_NUMBER];
+
+#ifdef ANDROID
+#define DIAG_CMD_SOCKET "diagcmd"
+#else
+#define DIAG_CMD_SOCKET "/tmp/diagcmd"
+#endif
+
+static void init_clients(void)
+{
+ int i;
+ for(i = 0; i < MAX_CLIENT_NUMBER; i ++)
+ {
+ clients[i].fd = -1;
+ clients[i].handle_id = 0;
+ }
+}
+
+static int client_id_is_valid(int id)
+{
+ if((id >= 0) && (id < MAX_CLIENT_NUMBER))
+ return 1;
+ else
+ return 0;
+}
+
+static void close_client(int i)
+{
+ if(client_id_is_valid(i))
+ {
+ if(clients[i].handle_id > 0)
+ utlDeleteEventHandler(clients[i].handle_id);
+ if(clients[i].fd > 0)
+ close(clients[i].fd);
+ clients[i].handle_id = 0;
+ clients[i].fd = -1;
+ }
+}
+
+static void close_clients(void)
+{
+ int i;
+ for(i = 0; i < MAX_CLIENT_NUMBER; i ++)
+ {
+ close_client(i);
+ }
+}
+
+static int get_free_client_id(void)
+{
+ int i;
+ for(i = 0; i < MAX_CLIENT_NUMBER; i ++)
+ {
+ if(clients[i].fd == -1)
+ return i;
+ }
+ return -1;
+}
+
+static int get_client_id_by_fd(int fd)
+{
+ int i;
+ if(fd < 0)
+ return -1;
+ for(i = 0; i < MAX_CLIENT_NUMBER; i ++)
+ {
+ if(clients[i].fd == fd)
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static int sendReply(int fd, const char* cmd, const char* arg)
+{
+ char buf[128];
+ int len;
+
+ strncpy(buf, cmd, sizeof(buf) - 1);
+ if(arg)
+ {
+ len = strlen(cmd) + 1;
+ buf[len - 1] = ' ';
+ strncpy(buf + len, arg , sizeof(buf) - len - 1);
+ }
+
+ return send(fd, buf, strlen(buf) + 1, MSG_NOSIGNAL);
+}
+
+static void parseCommand(char* cmd, int client_id)
+{
+ char* command, *arg;
+ const char *reply = response_invalid, *reply_arg = NULL;
+ char media_list[32];
+ int ret;
+
+ arg = strchr(cmd, ' ');
+ if(arg != NULL)
+ *arg++ = '\0';
+ else
+ arg = "";
+ command = cmd;
+ DBGMSG("command:%s, arg:%s\n", command, arg);
+ if(strcasecmp(command,"start") == 0)
+ {
+ ret = getMediaByName(arg);
+ if(ret >= 0)
+ {
+ if(startMediaMachine(ret) == 0)
+ reply = response_success;
+ else
+ reply = response_error;
+ }
+ }
+ else if(strcasecmp(command,"folder") == 0)
+ {
+#if CONFIG_DIAG_ALL
+ if(switchSDFolder(arg) == 0)
+ reply = response_success;
+ else
+ reply = response_error;
+#endif
+ }
+ else if(strcasecmp(command,"switch") == 0)
+ {
+ ret = getMediaByName(arg);
+ if(ret >= 0)
+ {
+ if(switchMediaMachine(ret) == 0)
+ reply = response_success;
+ else
+ reply = response_error;
+ }
+ }
+ else if (strcasecmp(command,"stop") == 0)
+ {
+ ret = getMediaByName(arg);
+ if(ret >= 0)
+ {
+ if(stopMediaMachine(ret) == 0)
+ reply = response_success;
+ else
+ reply = response_error;
+ }
+ }
+ else if(strcasecmp(command,"dump") == 0)
+ {
+ if(dumpCPBuffer(arg) == 0)
+ reply = response_success;
+ else
+ reply = response_error;
+ }
+ else if(strcasecmp(command, "print") == 0)
+ {
+ if(strcasecmp(arg, "active") == 0)
+ {
+ if(getActiveMedia(media_list))
+ reply_arg = media_list;
+ reply = response_success;
+ }
+ else if(strcasecmp(arg, "status") == 0)
+ {
+ dumpMediaMachine();
+ reply = response_success;
+ }
+ }
+ else if(strcasecmp(command,"exit") == 0)
+ {
+ stopAllMediaMachine();
+ (void)sendReply(clients[client_id].fd, response_success, NULL);
+ sleep(3); // wait for CP to disconnect
+ exit(0);
+ }
+
+ (void)sendReply(clients[client_id].fd, reply, reply_arg);
+}
+
+static utlReturnCode_T ReceiveDataFromUtility(const utlEventHandlerType_T handler_type UNUSED,
+ const utlEventHandlerType_T event_type UNUSED,
+ const int fd,
+ const utlRelativeTime_P2c period_p UNUSED,
+ void *arg_p UNUSED)
+{
+ int received, offset, client_id;
+ char* current;
+ char cmdBuffer[512];
+
+ client_id = get_client_id_by_fd(fd);
+ if(client_id < 0)
+ return utlFAILED;
+
+ received = recv (fd, &cmdBuffer, sizeof(cmdBuffer), 0);
+
+ if(received == 0)
+ {
+ DBGMSG("***** DIAG Command Client %d Connection closed by peer *****\r\n", client_id);
+ close_client(client_id);
+ return utlSUCCESS;
+ }
+
+ else if(received < 0)
+ {
+ DBGMSG("***** DIAG Command Client %d Read failed:%s. *****\r\n", client_id, strerror(errno));
+ close_client(client_id);
+ return utlSUCCESS;
+ }
+
+ DBGMSG("Receive Diag Command from Client(%d) %d bytes!",client_id,received);
+ current = cmdBuffer;
+ for(offset = 0; received != 0; --received)
+ {
+ /* Each cmd message is terminated by '\0' */
+ if( current[offset] == '\0')
+ {//coverity[path_manipulation_sink:SUPPRESS]
+ parseCommand(current, client_id);
+ current += offset + 1;
+ offset = 0;
+ }
+ else ++offset;
+ }
+ if(offset != 0) //number of bytes left
+ {
+ ERRMSG("Fragmented packet received from DIAG command socket");
+ }
+ return utlSUCCESS;
+}
+
+
+static int acceptCmdPort(const utlEventHandlerType_T handler_type UNUSED,
+ const utlEventHandlerType_T event_type UNUSED,
+ const int fd UNUSED,
+ const utlRelativeTime_P2c period_p UNUSED,
+ void *arg_p UNUSED)
+{
+ int ret;
+ int flags;
+ int client_id;
+
+ ret = accept(cmdfd, NULL, NULL);
+ if( ret < 0)
+ {
+ ERRMSG("***** DIAG Command Port: accept control socket Error: %s *****\r\n",strerror(errno));
+ return utlFAILED;
+ }
+ else
+ {
+ flags = fcntl(ret,F_GETFL, 0);
+ (void)fcntl(ret,F_SETFL, flags | O_NONBLOCK);
+ client_id = get_free_client_id();
+ DBGMSG("Accept Diag Command Client:%d!",client_id);
+ if(client_id_is_valid(client_id))
+ {
+ clients[client_id].fd = ret;
+ clients[client_id].handle_id = utlSetFdEventHandler(utlEVENT_HANDLER_TYPE_READ, utlEVENT_HANDLER_PRIORITY_LOW, ret, ReceiveDataFromUtility, NULL);
+ }
+ else
+ {
+ DBGMSG("Diag Command Clients reach max number! Connection will be closed");
+ close(ret);
+ }
+ }
+ return utlSUCCESS;
+}
+
+int openCmdPort(void)
+{
+ int len;
+ struct sockaddr_un socket_name;
+ init_clients();
+ socket_name.sun_family = AF_UNIX;
+#ifdef ANDROID
+ cmdfd = android_get_control_socket(DIAG_CMD_SOCKET);
+ if (cmdfd < 0 )
+ {
+ ERRMSG("***** DIAG Command Port: control socket Error: %s *****\r\n",strerror(errno));
+ return -1;
+ }
+#else
+ if (strlen(DIAG_CMD_SOCKET) < sizeof(socket_name.sun_path))
+ strcpy (socket_name.sun_path, DIAG_CMD_SOCKET);
+ else
+ {
+ /* socket path is TOO big for the socket name */
+ ERRMSG("socket path is TOO big for the socket name\n");
+ return -1;
+ }
+
+ cmdfd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if ( cmdfd < 0 )
+ {
+ ERRMSG("***** DIAG Command Port: control socket Error: %s *****\r\n",strerror(errno));
+ return -1;
+ }
+
+ /* unlink to make sure the bind operation won't fail */
+ unlink(DIAG_CMD_SOCKET);
+
+ /* calculate length */
+ len = sizeof(socket_name.sun_family) + strlen(socket_name.sun_path);
+ if ( bind(cmdfd, (const struct sockaddr*) &socket_name, len) < 0 )
+ {
+ ERRMSG("***** DIAG Command Port: bind control socket Error: %s *****\r\n",strerror(errno));
+ close(cmdfd);
+ return -1;
+ }
+ (void)chmod(socket_name.sun_path, 0660);
+#endif
+
+ if( listen(cmdfd, MAX_CLIENT_NUMBER) < 0)
+ {
+ ERRMSG("***** DIAG Command Port: listen control socket Error: %s *****\r\n",strerror(errno));
+ close(cmdfd);
+ return -1;
+ }
+
+ cmdHandler = utlSetFdEventHandler(utlEVENT_HANDLER_TYPE_READ, utlEVENT_HANDLER_PRIORITY_LOW, cmdfd, acceptCmdPort, NULL);
+ return 0;
+}
+
+
+void closeCmdPort(void)
+{
+ utlDeleteEventHandler(cmdHandler);
+ close(cmdfd);
+ close_clients();
+ cmdfd = -1;
+}
+