blob: 1e54ea26d57219e2e5f8705bd47c900eadc60602 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/******************************************************************************
2*(C) Copyright 2011 Marvell International Ltd.
3* All Rights Reserved
4******************************************************************************/
5/*--------------------------------------------------------------------------------------------------------------------
6 * -------------------------------------------------------------------------------------------------------------------
7 *
8 * Filename: command_api.c
9 *
10 * Description: The APIs to remotely control DIAG internal behaviors.
11 *
12 * History:
13 * Aug, 13 2012 - Haili Wang(hlw@marvell.com) Creation of file
14 *
15 * Notes:
16 *
17 ******************************************************************************/
18
19#include <unistd.h>
20#include <stdlib.h>
21#include <fcntl.h>
22#include <errno.h>
23#include <sys/socket.h>
24#include <sys/un.h>
25#include <sys/stat.h>
26#ifdef ANDROID
27#include <cutils/sockets.h>
28#endif
29
30#include "utlEventHandler.h"
31#include "media_manager.h"
32#include "diag_state_machine.h"
33#include "sd_api.h"
34#include "pxa_dbg.h"
35#include "diag_al.h"
36#include "diag_api.h"
37
38static const char response_error[] = "ERROR";
39static const char response_invalid[] = "INVALID";
40static const char response_success[] = "SUCCESS";
41
42static int cmdfd = -1;
43static utlEventHandlerId_T cmdHandler;
44
45
46struct command_client{
47 int fd;
48 utlEventHandlerId_T handle_id;
49};
50
51#define MAX_CLIENT_NUMBER 10
52static struct command_client clients[MAX_CLIENT_NUMBER];
53
54#ifdef ANDROID
55#define DIAG_CMD_SOCKET "diagcmd"
56#else
57#define DIAG_CMD_SOCKET "/tmp/diagcmd"
58#endif
59
60static void init_clients(void)
61{
62 int i;
63 for(i = 0; i < MAX_CLIENT_NUMBER; i ++)
64 {
65 clients[i].fd = -1;
66 clients[i].handle_id = 0;
67 }
68}
69
70static int client_id_is_valid(int id)
71{
72 if((id >= 0) && (id < MAX_CLIENT_NUMBER))
73 return 1;
74 else
75 return 0;
76}
77
78static void close_client(int i)
79{
80 if(client_id_is_valid(i))
81 {
82 if(clients[i].handle_id > 0)
83 utlDeleteEventHandler(clients[i].handle_id);
84 if(clients[i].fd > 0)
85 close(clients[i].fd);
86 clients[i].handle_id = 0;
87 clients[i].fd = -1;
88 }
89}
90
91static void close_clients(void)
92{
93 int i;
94 for(i = 0; i < MAX_CLIENT_NUMBER; i ++)
95 {
96 close_client(i);
97 }
98}
99
100static int get_free_client_id(void)
101{
102 int i;
103 for(i = 0; i < MAX_CLIENT_NUMBER; i ++)
104 {
105 if(clients[i].fd == -1)
106 return i;
107 }
108 return -1;
109}
110
111static int get_client_id_by_fd(int fd)
112{
113 int i;
114 if(fd < 0)
115 return -1;
116 for(i = 0; i < MAX_CLIENT_NUMBER; i ++)
117 {
118 if(clients[i].fd == fd)
119 {
120 return i;
121 }
122 }
123 return -1;
124}
125
126static int sendReply(int fd, const char* cmd, const char* arg)
127{
128 char buf[128];
129 int len;
130
131 strncpy(buf, cmd, sizeof(buf) - 1);
132 if(arg)
133 {
134 len = strlen(cmd) + 1;
135 buf[len - 1] = ' ';
136 strncpy(buf + len, arg , sizeof(buf) - len - 1);
137 }
138
139 return send(fd, buf, strlen(buf) + 1, MSG_NOSIGNAL);
140}
141
142static void parseCommand(char* cmd, int client_id)
143{
144 char* command, *arg;
145 const char *reply = response_invalid, *reply_arg = NULL;
146 char media_list[32];
147 int ret;
148
149 arg = strchr(cmd, ' ');
150 if(arg != NULL)
151 *arg++ = '\0';
152 else
153 arg = "";
154 command = cmd;
155 DBGMSG("command:%s, arg:%s\n", command, arg);
156 if(strcasecmp(command,"start") == 0)
157 {
158 ret = getMediaByName(arg);
159 if(ret >= 0)
160 {
161 if(startMediaMachine(ret) == 0)
162 reply = response_success;
163 else
164 reply = response_error;
165 }
166 }
167 else if(strcasecmp(command,"folder") == 0)
168 {
169#if CONFIG_DIAG_ALL
170 if(switchSDFolder(arg) == 0)
171 reply = response_success;
172 else
173 reply = response_error;
174#endif
175 }
176 else if(strcasecmp(command,"switch") == 0)
177 {
178 ret = getMediaByName(arg);
179 if(ret >= 0)
180 {
181 if(switchMediaMachine(ret) == 0)
182 reply = response_success;
183 else
184 reply = response_error;
185 }
186 }
187 else if (strcasecmp(command,"stop") == 0)
188 {
189 ret = getMediaByName(arg);
190 if(ret >= 0)
191 {
192 if(stopMediaMachine(ret) == 0)
193 reply = response_success;
194 else
195 reply = response_error;
196 }
197 }
198 else if(strcasecmp(command,"dump") == 0)
199 {
200 if(dumpCPBuffer(arg) == 0)
201 reply = response_success;
202 else
203 reply = response_error;
204 }
205 else if(strcasecmp(command, "print") == 0)
206 {
207 if(strcasecmp(arg, "active") == 0)
208 {
209 if(getActiveMedia(media_list))
210 reply_arg = media_list;
211 reply = response_success;
212 }
213 else if(strcasecmp(arg, "status") == 0)
214 {
215 dumpMediaMachine();
216 reply = response_success;
217 }
218 }
219 else if(strcasecmp(command,"exit") == 0)
220 {
221 stopAllMediaMachine();
222 (void)sendReply(clients[client_id].fd, response_success, NULL);
223 sleep(3); // wait for CP to disconnect
224 exit(0);
225 }
qs.xiong68079a32025-08-15 11:29:57 +0800226 else if (strcasecmp(command,"save") == 0) /* save default media */
227 {
228 ret = getMediaByName(arg);
229 if(ret >= 0)
230 {
231 save_diag_default_media_config(ret);
232 reply = response_success;
233 }
234 else
235 {
236 reply = response_error;
237 }
238 }
b.liue9582032025-04-17 19:18:16 +0800239 (void)sendReply(clients[client_id].fd, reply, reply_arg);
240}
241
242static utlReturnCode_T ReceiveDataFromUtility(const utlEventHandlerType_T handler_type UNUSED,
243 const utlEventHandlerType_T event_type UNUSED,
244 const int fd,
245 const utlRelativeTime_P2c period_p UNUSED,
246 void *arg_p UNUSED)
247{
248 int received, offset, client_id;
249 char* current;
250 char cmdBuffer[512];
251
252 client_id = get_client_id_by_fd(fd);
253 if(client_id < 0)
254 return utlFAILED;
255
256 received = recv (fd, &cmdBuffer, sizeof(cmdBuffer), 0);
257
258 if(received == 0)
259 {
260 DBGMSG("***** DIAG Command Client %d Connection closed by peer *****\r\n", client_id);
261 close_client(client_id);
262 return utlSUCCESS;
263 }
264
265 else if(received < 0)
266 {
267 DBGMSG("***** DIAG Command Client %d Read failed:%s. *****\r\n", client_id, strerror(errno));
268 close_client(client_id);
269 return utlSUCCESS;
270 }
271
272 DBGMSG("Receive Diag Command from Client(%d) %d bytes!",client_id,received);
273 current = cmdBuffer;
274 for(offset = 0; received != 0; --received)
275 {
276 /* Each cmd message is terminated by '\0' */
277 if( current[offset] == '\0')
278 {//coverity[path_manipulation_sink:SUPPRESS]
279 parseCommand(current, client_id);
280 current += offset + 1;
281 offset = 0;
282 }
283 else ++offset;
284 }
285 if(offset != 0) //number of bytes left
286 {
287 ERRMSG("Fragmented packet received from DIAG command socket");
288 }
289 return utlSUCCESS;
290}
291
292
293static int acceptCmdPort(const utlEventHandlerType_T handler_type UNUSED,
294 const utlEventHandlerType_T event_type UNUSED,
295 const int fd UNUSED,
296 const utlRelativeTime_P2c period_p UNUSED,
297 void *arg_p UNUSED)
298{
299 int ret;
300 int flags;
301 int client_id;
302
303 ret = accept(cmdfd, NULL, NULL);
304 if( ret < 0)
305 {
306 ERRMSG("***** DIAG Command Port: accept control socket Error: %s *****\r\n",strerror(errno));
307 return utlFAILED;
308 }
309 else
310 {
311 flags = fcntl(ret,F_GETFL, 0);
312 (void)fcntl(ret,F_SETFL, flags | O_NONBLOCK);
313 client_id = get_free_client_id();
314 DBGMSG("Accept Diag Command Client:%d!",client_id);
315 if(client_id_is_valid(client_id))
316 {
317 clients[client_id].fd = ret;
318 clients[client_id].handle_id = utlSetFdEventHandler(utlEVENT_HANDLER_TYPE_READ, utlEVENT_HANDLER_PRIORITY_LOW, ret, ReceiveDataFromUtility, NULL);
319 }
320 else
321 {
322 DBGMSG("Diag Command Clients reach max number! Connection will be closed");
323 close(ret);
324 }
325 }
326 return utlSUCCESS;
327}
328
329int openCmdPort(void)
330{
331 int len;
332 struct sockaddr_un socket_name;
333 init_clients();
334 socket_name.sun_family = AF_UNIX;
335#ifdef ANDROID
336 cmdfd = android_get_control_socket(DIAG_CMD_SOCKET);
337 if (cmdfd < 0 )
338 {
339 ERRMSG("***** DIAG Command Port: control socket Error: %s *****\r\n",strerror(errno));
340 return -1;
341 }
342#else
343 if (strlen(DIAG_CMD_SOCKET) < sizeof(socket_name.sun_path))
344 strcpy (socket_name.sun_path, DIAG_CMD_SOCKET);
345 else
346 {
347 /* socket path is TOO big for the socket name */
348 ERRMSG("socket path is TOO big for the socket name\n");
349 return -1;
350 }
351
352 cmdfd = socket(PF_UNIX, SOCK_STREAM, 0);
353 if ( cmdfd < 0 )
354 {
355 ERRMSG("***** DIAG Command Port: control socket Error: %s *****\r\n",strerror(errno));
356 return -1;
357 }
358
359 /* unlink to make sure the bind operation won't fail */
360 unlink(DIAG_CMD_SOCKET);
361
362 /* calculate length */
363 len = sizeof(socket_name.sun_family) + strlen(socket_name.sun_path);
364 if ( bind(cmdfd, (const struct sockaddr*) &socket_name, len) < 0 )
365 {
366 ERRMSG("***** DIAG Command Port: bind control socket Error: %s *****\r\n",strerror(errno));
367 close(cmdfd);
368 return -1;
369 }
370 (void)chmod(socket_name.sun_path, 0660);
371#endif
372
373 if( listen(cmdfd, MAX_CLIENT_NUMBER) < 0)
374 {
375 ERRMSG("***** DIAG Command Port: listen control socket Error: %s *****\r\n",strerror(errno));
376 close(cmdfd);
377 return -1;
378 }
379
380 cmdHandler = utlSetFdEventHandler(utlEVENT_HANDLER_TYPE_READ, utlEVENT_HANDLER_PRIORITY_LOW, cmdfd, acceptCmdPort, NULL);
381 return 0;
382}
383
384
385void closeCmdPort(void)
386{
387 utlDeleteEventHandler(cmdHandler);
388 close(cmdfd);
389 close_clients();
390 cmdfd = -1;
391}
392