d1290a670cbb0224b3d139241caf6cbafcfb9a64
[adaptation/xorg/driver/xserver-xorg-module-xdbg.git] / module / xdbg_module_command.c
1 /**************************************************************************
2
3 xdbg
4
5 Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
6
7 Contact: Boram Park <boram1288.park@samsung.com>
8          Sangjin LEE <lsj119@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <fcntl.h>
41 #include <unistd.h>
42 #include <windowstr.h>
43 #include <xacestr.h>
44 #include <xdbg.h>
45 #include "xdbg_types.h"
46 #include <xf86Priv.h>
47 #include "xdbg_module.h"
48 #include "xdbg_module_clist.h"
49 #include "xdbg_module_plist.h"
50 #include "xdbg_module_evlog.h"
51 #include "xdbg_module_drmevent.h"
52 #include "xdbg_module_fpsdebug.h"
53 #include "xdbg_module_command.h"
54
55 static void
56 _CommandDLog (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
57 {
58     int on;
59
60     if (argc != 3)
61     {
62         XDBG_REPLY ("DLog level: %d\n", xDbgGetLogEnableDlog() ? 1 : 0);
63         return;
64     }
65
66     on = atoi (argv[2]);
67
68     xDbgLogEnableDlog (on);
69
70     XDBG_REPLY ("Success\n");
71 }
72
73 static Bool
74 _CommandSetLogFile (int pid, char *path, char *reply, int *len, XDbgModule *pMod)
75 {
76     static int old_stderr = -1;
77     char fd_name[XDBG_PATH_MAX];
78     int  log_fd = -1;
79
80     if (!path || strlen (path) <= 0)
81     {
82         XDBG_REPLY ("failed: logpath is invalid\n");
83         return FALSE;
84     }
85
86     if (old_stderr == -1)
87         old_stderr = dup (STDERR_FILENO);
88
89     if (!strcmp (path, "console"))
90         snprintf (fd_name, XDBG_PATH_MAX, "/proc/%d/fd/1", pid);
91     else
92     {
93         if (path[0] == '/')
94             snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
95         else
96         {
97             if (pMod->cwd)
98                 snprintf (fd_name, XDBG_PATH_MAX, "%s/%s", pMod->cwd, path);
99             else
100                 snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
101         }
102     }
103
104     log_fd = open (fd_name, O_CREAT|O_RDWR|O_APPEND, 0755);
105     if (log_fd < 0)
106     {
107         XDBG_REPLY ("failed: open file(%s)\n", fd_name);
108         return FALSE;
109     }
110
111     fflush (stderr);
112     close (STDERR_FILENO);
113     dup2 (log_fd, STDERR_FILENO);
114     close (log_fd);
115
116     if (pMod->real_log_path)
117         free (pMod->real_log_path);
118
119     pMod->real_log_path = strdup (fd_name);
120     XDBG_RETURN_VAL_IF_FAIL (pMod->real_log_path != NULL, FALSE);
121
122     XDBG_REPLY ("log path: %s\n", pMod->real_log_path);
123
124     return TRUE;
125 }
126
127
128 static void
129 _CommandLogPath (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
130 {
131     if (argc != 3)
132     {
133         XDBG_REPLY ("log path: %s\n", (pMod->real_log_path)?pMod->real_log_path:"stderr");
134         return;
135     }
136
137     _CommandSetLogFile (pid, argv[2], reply, len, pMod);
138 }
139
140 static void
141 _CommandSetLogLevel (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
142 {
143     Bool ret;
144     char *module_name;
145     int level;
146
147     if (argc < 4)
148     {
149         xDbgLogEnumModules (MODE_WITH_STATUS, reply, len);
150         return;
151     }
152
153     module_name = argv[2];
154     level = atoi (argv[3]);
155
156     if (level < 0 || level >= 5)
157     {
158         XDBG_REPLY ("Error : Not valid log level %d.\n", level);
159         return;
160     }
161
162     ret = xDbgLogSetLevel (xDbgLogGetModule (module_name), level);
163
164     if (ret)
165         XDBG_REPLY ("Log level for module %s was successfully set to %d\n",
166                   module_name, level);
167     else
168         XDBG_REPLY ("Error : An error was occured during log level setting\n");
169 }
170
171 static void
172 _CommandClientList (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
173 {
174     if (argc != 2)
175     {
176         XDBG_REPLY ("Error : too few arguments\n");
177         return;
178     }
179
180     xDbgModuleCList (pMod, reply, len);
181 }
182
183 static void
184 _CommandPixmapList (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
185 {
186     if (argc != 2)
187     {
188         XDBG_REPLY ("Error : too few arguments\n");
189         return;
190     }
191
192     xDbgModulePList (pMod, reply, len);
193 }
194
195 static void
196 _CommandEvlog (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
197 {
198     int on;
199     extern Bool xev_trace_on;
200
201     if (argc != 3)
202     {
203         XDBG_REPLY ("Evlog level: %d\n", xev_trace_on ? 1 : 0);
204         return;
205     }
206
207     on = atoi (argv[2]);
208
209     xDbgModuleEvlogPrintEvents (pMod, on, argv[0], reply, len);
210
211     XDBG_REPLY ("Success\n");
212 }
213
214 static void
215 _CommandEvlogDetail (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
216 {
217     int level;
218     extern int xev_trace_detail_level;
219
220     if (argc != 3)
221     {
222         XDBG_REPLY ("Detail Level: %d\n", xev_trace_detail_level);
223         return;
224     }
225
226     level = atoi(argv[2]);
227
228     xDbgModuleEvlogDetail (pMod, level, reply, len);
229     XDBG_REPLY ("Success\n");
230 }
231
232 static void
233 _CommandSetEvlogRule (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
234 {
235     if (argc < 2)
236     {
237         XDBG_REPLY ("Error : invalid number of arguments.\n");
238         return;
239     }
240
241     xDbgModuleEvlogInfoSetRule (pMod, argc - 2, (const char**)&(argv[2]), reply, len);
242 }
243
244 static void
245 _CommandSetEvlogPath (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
246 {
247     if (argc != 3)
248     {
249         XDBG_REPLY ("evlog path: %s\n", (pMod->evlog_path)?pMod->evlog_path:"none");
250         return;
251     }
252
253     if (!argv[2] || strlen (argv[2]) <= 0)
254     {
255         XDBG_REPLY ("invalid option\n");
256         return;
257     }
258
259     if (pMod->evlog_path)
260     {
261         free (pMod->evlog_path);
262         pMod->evlog_path=NULL;
263     }
264
265     if (!xDbgModuleEvlogSetEvlogPath (pMod, pid, argv[2], reply, len))
266     {
267         XDBG_REPLY ("Error: evlog path(%s)\n", argv[2]);
268         return;
269     }
270
271     pMod->evlog_path = strdup (argv[2]);
272
273     if (!strcmp (pMod->evlog_path, "console"))
274         XDBG_REPLY ("/proc/%d/fd/1", pid);
275     else if (pMod->evlog_path[0] == '/')
276         XDBG_REPLY ("evlog path: %s\n", pMod->evlog_path);
277     else
278         XDBG_REPLY ("evlog path: %s/%s\n", pMod->cwd, pMod->evlog_path);
279 }
280
281 static void
282 _CommandDrmEventPending (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
283 {
284     if (argc != 2)
285     {
286         XDBG_REPLY ("Error : too few arguments\n");
287         return;
288     }
289
290     xDbgModuleDrmEventPending (pMod, reply, len);
291 }
292
293 static void
294 _CommandFpsDebug (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
295 {
296     int on;
297
298     if (argc != 3)
299     {
300         XDBG_REPLY ("Error : too few arguments\n");
301         return;
302     }
303
304     on = atoi (argv[2]);
305
306     xDbgModuleFpsDebug (pMod, on, reply, len);
307
308     XDBG_REPLY ("Success\n");
309 }
310
311 static struct
312 {
313     const char *Cmd;
314     const char *Description;
315     const char *Options;
316
317     int       (*DynamicUsage) (int, char*, int *);
318     const char *DetailedUsage;
319
320     void (*func) (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod);
321 } command_proc[] =
322 {
323     {
324         "dlog", "to enable dlog", "[0-1]",
325         NULL, "[OFF:0/ON:1]",
326         _CommandDLog
327     },
328
329     {
330         "log_path", "to set log path", "[console/filepath]",
331         NULL, "[console/filepath]",
332         _CommandLogPath
333     },
334
335     {
336         "log", "to set loglevel", "[MODULE] [0-4]",
337         (int(*)(int, char*, int*))xDbgLogEnumModules, "[DEBUG:0/TRACE:1/INFO:2/WARNING:3/ERROR:4]",
338         _CommandSetLogLevel
339     },
340
341     {
342         "clist", "to print clients", "",
343         NULL, "",
344         _CommandClientList
345     },
346
347     {
348         "plist", "to print pixmap list", "",
349         NULL, "",
350         _CommandPixmapList
351     },
352
353     {
354         "evlog", "to print x events", "[0-1]",
355         NULL, "[OFF:0/ON:1]",
356         _CommandEvlog
357     },
358
359     {
360         "evlog_detail", "to set printing detail log level", "[0-2]",
361         NULL, "[Primary logs:0/ More detail logs:1/ Supplementary Reply logs:2]",
362         _CommandEvlogDetail
363     },
364
365     {
366         "evlog_rule", "to set evlog rules", "[add/remove/file/print/help]",
367         NULL, "[add allow/deny rules / remove (index) / file(file_name) / print / help]",
368         _CommandSetEvlogRule
369     },
370
371     {
372         "evlog_path", "to set filepath of evlog", "[console/filepath]",
373         NULL, "[console/filepath]",
374         _CommandSetEvlogPath
375     },
376
377     {
378         "drmevent_pending", "to print pending drmvents", "",
379         NULL, "",
380         _CommandDrmEventPending
381     },
382
383     {
384         "fpsdebug", "to print fps", "[0-1]",
385         NULL, "[OFF:0/ON:1]",
386         _CommandFpsDebug
387     },
388 };
389
390 static void _CommandPrintUsage (char *reply, int *len, const char * exec)
391 {
392     int option_cnt = sizeof (command_proc) / sizeof (command_proc[0]);
393     int i;
394
395     XDBG_REPLY ("Usage : %s [cmd] [options]\n", exec);
396     XDBG_REPLY ("     ex)\n");
397
398     for (i=0; i<option_cnt; i++)
399         XDBG_REPLY ("           %s %s %s\n", exec, command_proc[i].Cmd, command_proc[i].Options);
400
401     XDBG_REPLY (" options :\n");
402
403     for (i=0; i<option_cnt; i++)
404     {
405         if (command_proc[i].Cmd && command_proc[i].Description)
406             XDBG_REPLY ("  %s (%s)\n", command_proc[i].Cmd, command_proc[i].Description);
407         else
408             XDBG_REPLY ("  Cmd(%p) or Descriptiont(%p).\n", command_proc[i].Cmd, command_proc[i].Description);
409
410         if (command_proc[i].DynamicUsage)
411         {
412             char dyn[1024];
413             int  dynlen = sizeof (dyn);
414             command_proc[i].DynamicUsage (MODE_NAME_ONLY, dyn, &dynlen);
415             XDBG_REPLY ("     [MODULE:%s]\n", dyn);
416         }
417
418         if (command_proc[i].DetailedUsage)
419             XDBG_REPLY ("     %s\n", command_proc[i].DetailedUsage);
420         else
421             XDBG_REPLY ("  DetailedUsage(%p).\n", command_proc[i].DetailedUsage);
422     }
423 }
424
425 void
426 xDbgModuleCommand (void *data, int argc, char **argv, char *reply, int *len)
427 {
428     XDbgModule *pMod = (XDbgModule*)data;
429     int nproc = sizeof (command_proc) / sizeof (command_proc[0]);
430     int i, pid, new_argc;
431     char **new_argv;
432
433     pid = atoi (argv[0]);
434     pMod->cwd = strdup (argv[1]);
435
436     new_argc = argc - 2;
437     new_argv = (char**)malloc (new_argc * sizeof (char*));
438     if (!new_argv)
439     {
440         XDBG_REPLY ("Error : malloc new_argv\n");
441         return;
442     }
443
444     for (i = 0; i < new_argc; i++)
445         new_argv[i] = argv[i+2];
446
447     if (argc < 4)
448     {
449         _CommandPrintUsage (reply, len, new_argv[0]);
450         free (new_argv);
451         return;
452     }
453
454     for (i = 0; i < nproc; i++)
455     {
456         if (!strcmp (new_argv[1], command_proc[i].Cmd) ||
457             (new_argv[1][0] == '-' && !strcmp (1 + new_argv[1], command_proc[i].Cmd)))
458         {
459             command_proc[i].func (pid, new_argc, new_argv, reply, len, pMod);
460             free (new_argv);
461             return;
462         }
463     }
464
465     _CommandPrintUsage (reply, len, new_argv[0]);
466
467     free (new_argv);
468 }
469
470 Bool
471 xDbgModuleCommandInitLogPath (XDbgModule *pMod)
472 {
473     char reply[1024];
474     int len = sizeof (reply);
475
476     if (pMod->log_path && strlen (pMod->log_path) > 0)
477     {
478         char newname[XDBG_PATH_MAX];
479         char filename[XDBG_PATH_MAX];
480         struct stat status;
481         char *p = NULL, *last = NULL;
482         int i;
483
484         snprintf (newname, XDBG_PATH_MAX, "%s", pMod->log_path);
485
486         for (i = 0; i < strlen (newname); i++)
487         {
488             p = newname + i;
489             if (*p == '/')
490                 last = p;
491         }
492
493         snprintf (filename, XDBG_PATH_MAX, "%s", last + 1);
494         snprintf (last, XDBG_PATH_MAX - (last - newname), "/prev.%s", filename);
495
496         if (!stat (pMod->log_path, &status))
497         {
498             if (rename (pMod->log_path, newname))
499             {
500                 XDBG_ERROR (MXDBG, "Failed: rename %s -> %s\n", pMod->log_path, newname);
501                 return FALSE;
502             }
503         }
504     }
505
506     if (pMod->log_path)
507         _CommandSetLogFile (0, pMod->log_path, reply, &len, pMod);
508     else
509         _CommandSetLogFile (0, "console", reply, &len, pMod);
510
511     return TRUE;
512 }