1 /*******************************************************************************
2 
3     KHOMP generic endpoint/channel library.
4     Copyright (C) 2007-2010 Khomp Ind. & Com.
5 
6   The contents of this file are subject to the Mozilla Public License
7   Version 1.1 (the "License"); you may not use this file except in compliance
8   with the License. You may obtain a copy of the License at
9   http://www.mozilla.org/MPL/
10 
11   Software distributed under the License is distributed on an "AS IS" basis,
12   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
13   the specific language governing rights and limitations under the License.
14 
15   Alternatively, the contents of this file may be used under the terms of the
16   "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
17   case the provisions of "LGPL License" are applicable instead of those above.
18 
19   If you wish to allow use of your version of this file only under the terms of
20   the LGPL License and not to allow others to use your version of this file
21   under the MPL, indicate your decision by deleting the provisions above and
22   replace them with the notice and other provisions required by the LGPL
23   License. If you do not delete the provisions above, a recipient may use your
24   version of this file under either the MPL or the LGPL License.
25 
26   The LGPL header follows below:
27 
28     This library is free software; you can redistribute it and/or
29     modify it under the terms of the GNU Lesser General Public
30     License as published by the Free Software Foundation; either
31     version 2.1 of the License, or (at your option) any later version.
32 
33     This library is distributed in the hope that it will be useful,
34     but WITHOUT ANY WARRANTY; without even the implied warranty of
35     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
36     Lesser General Public License for more details.
37 
38     You should have received a copy of the GNU Lesser General Public License
39     along with this library; if not, write to the Free Software Foundation,
40     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
41 
42 *******************************************************************************/
43 
44 #include "cli.h"
45 #include "k3l.h"
46 #include "lock.h"
47 #include "khomp_pvt.h"
48 #include "spec.h"
49 
50 /* our stream and interface handlers */
51 switch_stream_handle_t *Cli::stream;
52 switch_loadable_module_interface_t **Cli::module_interface;
53 
54 /* contains all commands */
55 Cli::Commands Cli::_commands;
56 
57 /* khomp all commands usage */
58 std::string Cli::_khomp_usage;
59 
60 /* register our commands, but you must create the command function */
registerCommands(APIFunc func,switch_loadable_module_interface_t ** mod_int)61 void Cli::registerCommands(APIFunc func,switch_loadable_module_interface_t **mod_int)
62 {
63     if(!mod_int || !*mod_int)
64     {
65         LOG(ERROR,"Invalid module passed");
66         return;
67     }
68 
69     /* the manual */
70     _khomp_usage =                                                             \
71 "---------------------------------------------------------------------------\n"\
72 "---------------------------------- HELP -----------------------------------\n"\
73 "---------------------------------------------------------------------------\n"\
74 " khomp channels disconnect {all | <board> all | <board> <channel>}\n"         \
75 " khomp channels unblock {all | <board> all | <board> <channel>}\n"            \
76 " khomp clear links [<board> [<link>]]\n"                                      \
77 " khomp clear statistics [<board> [<channel>]]\n"                              \
78 " khomp dump config\n"                                                         \
79 " khomp get <option>\n"                                                        \
80 " khomp kommuter {on|off}\n"                                                   \
81 " khomp kommuter count\n"                                                      \
82 " khomp log console <options>\n"                                               \
83 " khomp log disk <options>\n"                                                  \
84 " khomp log rotate\n"                                                          \
85 " khomp log status\n"                                                          \
86 " khomp log trace isdn <what>[,<what2>[,..]]\n"                                \
87 " khomp log trace k3l {on|off}\n"                                              \
88 " khomp log trace r2 {on|off}\n"                                               \
89 " khomp reset links [<board> [<link>]]\n"                                      \
90 " khomp revision\n"                                                            \
91 " khomp select sim <board> <channel> <sim_card>\n"                             \
92 " khomp send command <board> <channel> <command> [argument]\n"                 \
93 " khomp send raw command <board> <dsp> <c0> <c1> [...]\n"                      \
94 " khomp set <option> <value>\n"                                                \
95 " khomp show calls [<board> [<channel>]]\n"                                    \
96 " khomp show channels [{<board> [<channel>]} | \n"                             \
97 "                      {{concise|verbose|xml} [<board> [<channel>]]}]\n"       \
98 " khomp show links [[errors] [{<board>} | {{concise|verbose|xml}[<board>]}]]\n"\
99 " khomp show statistics [{{verbose|xml} [<board> [<channel>]]} | \n"           \
100 "                        {detailed <board> <channel>}]\n"                      \
101 " khomp sms <device> <destination> <message..>\n"                              \
102 " khomp summary [concise|verbose|xml]\n"                                       \
103 "---------------------------------------------------------------------------\n\n";
104 
105     /* we need this module_inteface, is used by SWITCH_ADD_API, there's no escape */
106     module_interface = mod_int;
107 
108     /* khomp cli commands */
109     SWITCH_ADD_API(Globals::api_interface, "khomp", "Khomp Menu", func, _khomp_usage.c_str());
110 
111     /* insert commands in list */
112     for(Commands::iterator itr = _commands.begin();itr != _commands.end();itr++)
113     {
114         switch_console_set_complete(STR(FMT("add khomp %s") % (*itr)->complete_name));
115 
116         /* if we have options, let's insert them */
117         if((*itr)->options.size() > 0)
118         {
119             std::vector<std::string>::iterator itr_option = (*itr)->options.begin();
120             while(itr_option != (*itr)->options.end())
121             {
122                 switch_console_set_complete(STR(FMT("add khomp %s %s") % (*itr)->complete_name % *itr_option));
123                 itr_option++;
124             }
125         }
126     }
127 }
128 
129 /* is responsible for parse and execute all commands */
parseCommands(int argc,char * argv[])130 bool Cli::parseCommands(int argc, char *argv[])
131 {
132     /*
133      * DEBUG_CLI_CMD();
134      */
135 
136     /* khomp summary */
137     if (ARG_CMP(0, "summary"))
138         return EXEC_CLI_CMD(Cli::KhompSummary);
139 
140     /* khomp show */
141     else if(ARG_CMP(0, "show"))
142     {
143         /* khomp show calls */
144         if(ARG_CMP(1, "calls"))
145             return EXEC_CLI_CMD(Cli::KhompShowCalls);
146 
147         /* khomp show channels */
148         if(ARG_CMP(1, "channels"))
149             return EXEC_CLI_CMD(Cli::KhompShowChannels);
150 
151         /* khomp show links */
152         if(ARG_CMP(1, "links"))
153             return EXEC_CLI_CMD(Cli::KhompShowLinks);
154 
155         /* khomp show statistics */
156         if(ARG_CMP(1, "statistics"))
157             return EXEC_CLI_CMD(Cli::KhompShowStatistics);
158     }
159 
160     /* khomp clear */
161     else if(ARG_CMP(0, "clear"))
162     {
163         /* khomp clear links */
164         if(ARG_CMP(1, "links"))
165             return EXEC_CLI_CMD(Cli::KhompClearLinks);
166 
167         /* khomp clear statistics */
168         if(ARG_CMP(1, "statistics"))
169             return EXEC_CLI_CMD(Cli::KhompClearStatistics);
170     }
171 
172     /* khomp dump */
173     else if(ARG_CMP(0, "dump"))
174     {
175         /* khomp dump config */
176         if(ARG_CMP(1, "config"))
177             return EXEC_CLI_CMD(Cli::KhompDumpConfig);
178     }
179 
180     /* khomp reset */
181     else if(ARG_CMP(0, "reset"))
182     {
183         /* khomp reset links */
184         if(ARG_CMP(1, "links"))
185             return EXEC_CLI_CMD(Cli::KhompResetLinks);
186 
187     }
188 
189     /* khomp sms */
190     else if(ARG_CMP(0, "sms"))
191     {
192         return EXEC_CLI_CMD(Cli::KhompSMS);
193     }
194 
195     /* khomp log */
196     else if(ARG_CMP(0, "log"))
197     {
198         /* khomp log console */
199         if(ARG_CMP(1, "console"))
200             return EXEC_CLI_CMD(Cli::KhompLogConsole);
201 
202         /* khomp log  disk */
203         if(ARG_CMP(1, "disk"))
204             return EXEC_CLI_CMD(Cli::KhompLogDisk);
205 
206         /* khomp log status */
207         if(ARG_CMP(1, "status"))
208             return EXEC_CLI_CMD(Cli::KhompLogStatus);
209 
210         /* khomp log rotate */
211         if(ARG_CMP(1, "rotate"))
212             return EXEC_CLI_CMD(Cli::KhompLogRotate);
213 
214         /* khomp log trace */
215         if(ARG_CMP(1, "trace"))
216         {
217             /* khomp log trace k3l */
218             if(ARG_CMP(2, "k3l"))
219                 return EXEC_CLI_CMD(Cli::KhompLogTraceK3L);
220 
221             /* khomp log trace isdn */
222             if(ARG_CMP(2, "isdn"))
223                 return EXEC_CLI_CMD(Cli::KhompLogTraceISDN);
224 
225             /* khomp log trace r2 */
226             if(ARG_CMP(2, "r2"))
227                 return EXEC_CLI_CMD(Cli::KhompLogTraceR2);
228         }
229     }
230 
231     /* khomp channels */
232     else if(ARG_CMP(0, "channels"))
233     {
234         /* khomp channels disconnect */
235         if(ARG_CMP(1, "disconnect"))
236             return EXEC_CLI_CMD(Cli::KhompChannelsDisconnect);
237 
238         /* khomp channels unblock */
239         if(ARG_CMP(1, "unblock"))
240             return EXEC_CLI_CMD(Cli::KhompChannelsUnblock);
241     }
242 
243     /* khomp get */
244     else if(ARG_CMP(0, "get"))
245         return EXEC_CLI_CMD(Cli::KhompGet);
246 
247     /* khomp set */
248     else if(ARG_CMP(0, "set"))
249         return EXEC_CLI_CMD(Cli::KhompSet);
250 
251     /* khomp reivision */
252     else if(ARG_CMP(0, "revision"))
253         return EXEC_CLI_CMD(Cli::KhompRevision);
254 
255     /* khomp send */
256     else if(ARG_CMP(0, "send"))
257     {
258         /* khomp send command */
259         if(ARG_CMP(1, "command"))
260             return EXEC_CLI_CMD(Cli::KhompSendCommand);
261 
262         /* khomp send raw */
263         if(ARG_CMP(1, "raw"))
264             return EXEC_CLI_CMD(Cli::KhompSendRawCommand);
265     }
266 
267     /* khomp select */
268     else if(ARG_CMP(0, "select"))
269     {
270         /* khomp select sim */
271         if(ARG_CMP(1, "sim"))
272             return EXEC_CLI_CMD(Cli::KhompSelectSim);
273 
274     }
275 
276     /* khomp kommuter */
277     else if(ARG_CMP(0, "kommuter"))
278     {
279         if(ARG_CMP(1, "on") || ARG_CMP(1, "off"))
280             return EXEC_CLI_CMD(Cli::KhompKommuterOnOff);
281 
282         if(ARG_CMP(1, "count"))
283             return EXEC_CLI_CMD(Cli::KhompKommuterCount);
284     }
285 
286     /* if everything fails, i'm here to support */
287     printKhompUsage();
288 
289     return false;
290 }
291 
292 /******************************************************************************/
293 /******************** Defining the static initialization **********************/
294 
295 Cli::_KhompSummary            Cli::KhompSummary;
296 Cli::_KhompShowCalls          Cli::KhompShowCalls;
297 Cli::_KhompShowChannels       Cli::KhompShowChannels;
298 Cli::_KhompShowLinks          Cli::KhompShowLinks;
299 Cli::_KhompShowStatistics     Cli::KhompShowStatistics;
300 Cli::_KhompClearLinks         Cli::KhompClearLinks;
301 Cli::_KhompDumpConfig         Cli::KhompDumpConfig;
302 Cli::_KhompClearStatistics    Cli::KhompClearStatistics;
303 Cli::_KhompResetLinks         Cli::KhompResetLinks;
304 Cli::_KhompChannelsDisconnect Cli::KhompChannelsDisconnect;
305 Cli::_KhompChannelsUnblock    Cli::KhompChannelsUnblock;
306 Cli::_KhompSMS                Cli::KhompSMS;
307 Cli::_KhompLogConsole         Cli::KhompLogConsole;
308 Cli::_KhompLogDisk            Cli::KhompLogDisk;
309 Cli::_KhompLogStatus          Cli::KhompLogStatus;
310 Cli::_KhompLogRotate          Cli::KhompLogRotate;
311 Cli::_KhompLogTraceK3L        Cli::KhompLogTraceK3L;
312 Cli::_KhompLogTraceISDN       Cli::KhompLogTraceISDN;
313 Cli::_KhompLogTraceR2         Cli::KhompLogTraceR2;
314 Cli::_KhompGet                Cli::KhompGet;
315 Cli::_KhompSet                Cli::KhompSet;
316 Cli::_KhompRevision           Cli::KhompRevision;
317 Cli::_KhompSendCommand        Cli::KhompSendCommand;
318 Cli::_KhompSendRawCommand     Cli::KhompSendRawCommand;
319 Cli::_KhompSelectSim          Cli::KhompSelectSim;
320 Cli::_KhompKommuterOnOff      Cli::KhompKommuterOnOff;
321 Cli::_KhompKommuterCount      Cli::KhompKommuterCount;
322 
323 /******************************************************************************/
324 /*************************** Defining the commands ****************************/
325 /*!
326  \brief Print a system summary for all the boards. [khomp summary]
327  */
execute(int argc,char * argv[])328 bool Cli::_KhompSummary::execute(int argc, char *argv[])
329 {
330     if(argc < 1 || argc > 2)
331     {
332         printUsage(stream);
333         return false;
334     }
335 
336     Cli::OutputType output_type = Cli::VERBOSE;
337     if(ARG_CMP(1, "concise")) output_type = Cli::CONCISE;
338     if(ARG_CMP(1, "xml"))
339     {
340         output_type = Cli::XML;
341         createRoot("summary");
342     }
343 
344     class_type classe = ( !_on_cli_term ? C_MESSAGE : C_CLI );
345     K3L_API_CONFIG apiCfg;
346 
347     if (output_type == Cli::VERBOSE)
348     {
349         K::Logger::Logg2(classe, stream, " ------------------------------------------------------------------");
350         K::Logger::Logg2(classe, stream, "|---------------------- Khomp System Summary ----------------------|");
351         K::Logger::Logg2(classe, stream, "|------------------------------------------------------------------|");
352     }
353 
354     const bool running = (k3lGetDeviceConfig(-1, ksoAPI, &apiCfg, sizeof(apiCfg)) == ksSuccess);
355 
356     if(running)
357     {
358         switch(output_type)
359         {
360             case Cli::VERBOSE:
361             {
362                 K::Logger::Logg2(classe, stream, FMT("| K3L API %d.%d.%d [m.VPD %d] - %-38s |")
363                         % apiCfg.MajorVersion % apiCfg.MinorVersion % apiCfg.BuildVersion
364                         % apiCfg.VpdVersionNeeded % apiCfg.StrVersion);
365             } break;
366 
367             case Cli::CONCISE:
368             {
369                 K::Logger::Logg2(classe, stream, FMT("%d.%d.%d;%d;%s")
370                         % apiCfg.MajorVersion % apiCfg.MinorVersion % apiCfg.BuildVersion
371                         % apiCfg.VpdVersionNeeded % apiCfg.StrVersion);
372             } break;
373 
374             case Cli::XML:
375             {
376                 /* summary/k3lapi */
377                 switch_xml_t xk3lapi = switch_xml_add_child_d(root, "k3lapi",0);
378 
379                 /* summary/k3lapi/version */
380                 switch_xml_t xk3l_version = switch_xml_add_child_d(xk3lapi,"version", 0);
381                 switch_xml_set_attr_d(xk3l_version,"major",STR(FMT("%d") % apiCfg.MajorVersion));
382                 switch_xml_set_attr_d(xk3l_version,"minor",STR(FMT("%d") % apiCfg.MinorVersion));
383                 switch_xml_set_attr_d(xk3l_version,"build",STR(FMT("%d") % apiCfg.BuildVersion));
384                 switch_xml_set_attr_d(xk3l_version,"vpd",STR(FMT("%d")   % apiCfg.VpdVersionNeeded));
385 
386                 /* summary/k3lapi/version/revision */
387                 switch_xml_t xk3l_rev = switch_xml_add_child_d(xk3l_version,"revision",0);
388                 switch_xml_set_txt_d(xk3l_rev,STR(FMT("%s") % apiCfg.StrVersion));
389             } break;
390 
391             default:
392                 break;
393         }
394     }
395     else
396     {
397         switch(output_type)
398         {
399             case Cli::VERBOSE:
400             {
401                 K::Logger::Logg2(classe, stream, "| Connection to KServer broken, please check system logs!          |");
402             } break;
403 
404             case Cli::CONCISE:
405             {
406                 K::Logger::Logg2(classe, stream, "CONNECTION BROKEN");
407             } break;
408 
409             case Cli::XML:
410             {
411                  /* summary/k3lapi */
412                 switch_xml_t xk3lapi = switch_xml_add_child_d(root, "k3lapi",0);
413                 switch_xml_set_txt_d(xk3lapi, "CONNECTION BROKEN");
414             } break;
415         }
416     }
417 
418 #ifndef MOD_KHOMP_VERSION
419 #define MOD_KHOMP_VERSION "unknown"
420 #endif
421 
422 #ifndef SWITCH_VERSION_FULL
423 #define SWITCH_VERSION_FULL "unknown"
424 #endif
425 
426     std::string khomp_endpoint_rev(MOD_KHOMP_VERSION);
427     std::string freeswitch_rev(SWITCH_VERSION_FULL);
428 
429     switch(output_type)
430     {
431         case Cli::VERBOSE:
432         {
433             K::Logger::Logg2(classe, stream, FMT("| Khomp Endpoint - %-47s |") % khomp_endpoint_rev);
434             K::Logger::Logg2(classe, stream, FMT("| FreeSWITCH - %-51s |") % freeswitch_rev);
435         } break;
436 
437         case Cli::CONCISE:
438         {
439             K::Logger::Logg2(classe, stream, FMT("%s") % khomp_endpoint_rev);
440             K::Logger::Logg2(classe, stream, FMT("%s") % freeswitch_rev);
441         } break;
442 
443         case Cli::XML:
444         {
445             /* summary/mod_khomp */
446             switch_xml_t xmod_khomp = switch_xml_add_child_d(root,"mod_khomp",0);
447 
448             /* summary/mod_khomp/revision */
449             switch_xml_t xrevision  = switch_xml_add_child_d(xmod_khomp,"revision",0);
450             switch_xml_set_txt_d(xrevision, khomp_endpoint_rev.c_str());
451 
452             /* summary/freeswitch */
453             switch_xml_t xfs = switch_xml_add_child_d(root,"freeswitch",0);
454 
455             /* summary/freeswitch/revision */
456             switch_xml_t xfs_rev = switch_xml_add_child_d(xfs,"revision",0);
457             switch_xml_set_txt_d(xfs_rev, freeswitch_rev.c_str());
458         } break;
459 
460         default:
461             break;
462     }
463 
464     if(!running)
465     {
466         if (output_type == Cli::VERBOSE)
467             K::Logger::Logg2(classe,stream, " ------------------------------------------------------------------");
468 
469         if (output_type == Cli::XML)
470         {
471             printXMLOutput(stream);
472             clearRoot();
473         }
474 
475         return false;
476     }
477 
478     if (output_type == Cli::XML)
479     {
480         /* summary/board */
481         xdevs = switch_xml_add_child_d(root,"devices",0);
482     }
483 
484     for (unsigned int i = 0; i < Globals::k3lapi.device_count(); i++)
485     {
486         const K3L_DEVICE_CONFIG & devCfg = Globals::k3lapi.device_config(i);
487 
488         std::string tipo = Verbose::deviceName((KDeviceType)Globals::k3lapi.device_type(i), devCfg.DeviceModel);
489 
490         if (output_type == Cli::VERBOSE)
491             K::Logger::Logg2(classe, stream, " ------------------------------------------------------------------");
492 
493         switch (Globals::k3lapi.device_type(i))
494         {
495             /* E1 boards */
496             case kdtE1:
497             case kdtConf:
498             case kdtPR:
499             case kdtE1GW:
500             case kdtE1IP:
501             case kdtE1Spx:
502             case kdtGWIP:
503             case kdtFXS:
504             case kdtFXSSpx:
505             case kdtE1FXSSpx:
506             {
507                 K3L_E1600A_FW_CONFIG dspAcfg;
508                 K3L_E1600B_FW_CONFIG dspBcfg;
509 
510                 if ((k3lGetDeviceConfig(i, ksoFirmware + kfiE1600A, &dspAcfg, sizeof(dspAcfg)) == ksSuccess) &&
511                     (k3lGetDeviceConfig(i, ksoFirmware + kfiE1600B, &dspBcfg, sizeof(dspBcfg)) == ksSuccess))
512                 {
513                     switch(output_type)
514                     {
515                         case Cli::VERBOSE:
516                         {
517                             K::Logger::Logg2(classe, stream, FMT("| [[ %02u ]] %s, serial '%s', %02d channels, %d links.%s|")
518                                     % i % tipo % devCfg.SerialNumber % devCfg.ChannelCount % devCfg.LinkCount
519                                     % std::string(std::max<int>(0, 22 - tipo.size() - strlen(devCfg.SerialNumber)), ' '));
520                             K::Logger::Logg2(classe, stream, FMT("| * DSP A: %s, DSP B: %s - PCI bus: %02d, PCI slot: %02d %s|")
521                                     % dspAcfg.DspVersion % dspBcfg.DspVersion % devCfg.PciBus % devCfg.PciSlot
522                                     % std::string(18 - strlen(dspAcfg.DspVersion) - strlen(dspBcfg.DspVersion), ' '));
523                             K::Logger::Logg2(classe, stream, FMT("| * %-62s |") % dspAcfg.FwVersion);
524                             K::Logger::Logg2(classe, stream, FMT("| * %-62s |") % dspBcfg.FwVersion);
525 
526                             K::Logger::Logg2(classe, stream, FMT("| * Echo Canceller: %-20s - Location: %-12s  |")
527                                     % Verbose::echoCancellerConfig(devCfg.EchoConfig)
528                                     % Verbose::echoLocation(devCfg.EchoLocation));
529                         } break;
530 
531                         case Cli::CONCISE:
532                         {
533                             K::Logger::Logg2(classe, stream, FMT("%02u;%s;%d;%d;%d;%s;%s;%02d;%02d;%s;%s;%s;%s")
534                                     % i % tipo % atoi(devCfg.SerialNumber) % devCfg.ChannelCount % devCfg.LinkCount
535                                     % dspAcfg.DspVersion % dspBcfg.DspVersion % devCfg.PciBus % devCfg.PciSlot
536                                     % dspAcfg.FwVersion % dspBcfg.FwVersion
537                                     % Verbose::echoCancellerConfig(devCfg.EchoConfig)
538                                     % Verbose::echoLocation(devCfg.EchoLocation));
539                         } break;
540 
541                         case Cli::XML:
542                         {
543                             /* boards/board */
544                             switch_xml_t xdev = switch_xml_add_child_d(xdevs,"device",0);
545                             switch_xml_set_attr_d(xdev,"id",STR(FMT("%02u") % i));
546 
547                             /* boards/board/general */
548                             switch_xml_t xgeneral = switch_xml_add_child_d(xdev,"general",0);
549 
550                             /* boards/board/general/type */
551                             switch_xml_t xtype = switch_xml_add_child_d(xgeneral,"type",0);
552                             switch_xml_set_txt_d(xtype,tipo.c_str());
553 
554                             /* boards/board/general/serial */
555                             switch_xml_t xserial = switch_xml_add_child_d(xgeneral,"serial",0);
556                             switch_xml_set_txt_d(xserial, devCfg.SerialNumber);
557 
558                             /* boards/board/general/channels */
559                             switch_xml_t xchannels = switch_xml_add_child_d(xgeneral,"channels",0);
560                             switch_xml_set_txt_d(xchannels, STR(FMT("%02d") % devCfg.ChannelCount));
561 
562                             /* boards/board/general/links */
563                             switch_xml_t xlinks = switch_xml_add_child_d(xgeneral,"links",0);
564                             switch_xml_set_txt_d(xlinks, STR(FMT("%d") % devCfg.LinkCount));
565 
566                             /* boards/board/hardware */
567                             switch_xml_t xhardware = switch_xml_add_child_d(xdev,"hardware",0);
568 
569                             /* boards/board/hardware/dsps */
570                             switch_xml_t xdsps = switch_xml_add_child_d(xhardware,"dsps",0);
571 
572                             /* boards/board/hardware/dsps/dsp (0) */
573                             switch_xml_t xdsp0 = switch_xml_add_child_d(xdsps,"dsp",0);
574                             switch_xml_set_attr_d(xdsp0,"id","0");
575 
576                             /* boards/board/hardware/dsps/dsp/version */
577                             switch_xml_t xversion0 = switch_xml_add_child_d(xdsp0,"version",0);
578                             switch_xml_set_txt_d(xversion0, dspAcfg.DspVersion);
579 
580                             /* boards/board/hardware/dsps/dsp/firmware */
581                             switch_xml_t xfirmware0 = switch_xml_add_child_d(xdsp0,"firmware",0);
582                             switch_xml_set_txt_d(xfirmware0,dspAcfg.FwVersion);
583 
584                             /* boards/board/hardware/dsps/dsp (1) */
585                             switch_xml_t xdsp1 = switch_xml_add_child_d(xdsps,"dsp",0);
586                             switch_xml_set_attr_d(xdsp1,"id","1");
587 
588                             /* boards/board/hardware/dsps/dsp/version */
589                             switch_xml_t xversion1 = switch_xml_add_child_d(xdsp1,"version",0);
590                             switch_xml_set_txt_d(xversion1, dspBcfg.DspVersion);
591 
592                             /* boards/board/hardware/dsps/dsp/firmware */
593                             switch_xml_t xfirmware1 = switch_xml_add_child_d(xdsp1,"firmware",0);
594                             switch_xml_set_txt_d(xfirmware1,dspBcfg.FwVersion);
595                         } break;
596 
597                         default:
598                             break;
599                     }
600                 }
601 
602                 break;
603             }
604 
605             /* analog boards */
606             case kdtFXO:
607             case kdtFXOVoIP:
608             /*
609             TODO: This not found
610             case kdtFX:
611             case kdtFXVoIP:
612             */
613             {
614                 K3L_FXO80_FW_CONFIG dspCfg;
615 
616                 if (k3lGetDeviceConfig(i, ksoFirmware + kfiFXO80, &dspCfg, sizeof(dspCfg)) == ksSuccess)
617                 {
618                     switch(output_type)
619                     {
620                         case Cli::VERBOSE:
621                         {
622                             K::Logger::Logg2(classe, stream, FMT("| [[ %02u ]] %s, serial '%s', %02d channels. %s|")
623                                         % i % tipo % devCfg.SerialNumber % devCfg.ChannelCount
624                                         % std::string(std::max<int>(0, 30 - tipo.size() - strlen(devCfg.SerialNumber)), ' '));
625                             K::Logger::Logg2(classe, stream, FMT("| * DSP: %s - PCI bus: %02d, PCI slot: %02d%s|")
626                                         % dspCfg.DspVersion % devCfg.PciBus % devCfg.PciSlot
627                                         % std::string(30 - strlen(dspCfg.DspVersion), ' '));
628                             K::Logger::Logg2(classe, stream, FMT("| * %-63s|") % dspCfg.FwVersion);
629                         } break;
630 
631                         case Cli::CONCISE:
632                         {
633                             K::Logger::Logg2(classe, stream, FMT("%02u;%s;%d;%d;%s;%02d;%02d;%s")
634                                         % i % tipo % atoi(devCfg.SerialNumber) % devCfg.ChannelCount
635                                         % dspCfg.DspVersion % devCfg.PciBus % devCfg.PciSlot
636                                         % dspCfg.FwVersion);
637                         } break;
638 
639                         case Cli::XML:
640                         {
641                             /* boards/board  */
642                             switch_xml_t xdev = switch_xml_add_child_d(xdevs,"device",0);
643                             switch_xml_set_attr_d(xdev,"id",STR(FMT("%02u") % i));
644 
645                             /* boards/board/general  */
646                             switch_xml_t xgeneral = switch_xml_add_child_d(xdev,"general",0);
647 
648                             /* boards/board/general/type  */
649                             switch_xml_t xtype = switch_xml_add_child_d(xgeneral,"type",0);
650                             switch_xml_set_txt_d(xtype,tipo.c_str());
651 
652                             /* boards/board/general/serial */
653                             switch_xml_t xserial = switch_xml_add_child_d(xgeneral,"serial",0);
654                             switch_xml_set_txt_d(xserial, devCfg.SerialNumber);
655 
656                             /* boards/board/general/channels */
657                             switch_xml_t xchannels = switch_xml_add_child_d(xgeneral,"channels",0);
658                             switch_xml_set_txt_d(xchannels, STR(FMT("%02d") % devCfg.ChannelCount));
659 
660                             /* boards/board/general/links */
661                             switch_xml_t xlinks = switch_xml_add_child_d(xgeneral,"links",0);
662                             switch_xml_set_txt_d(xlinks, STR(FMT("%d") % devCfg.LinkCount));
663 
664                             /* boards/hardware */
665                             switch_xml_t xhardware = switch_xml_add_child_d(xdev,"hardware",0);
666 
667                             /* boards/board/hardware/dsps */
668                             switch_xml_t xdsps = switch_xml_add_child_d(xhardware,"dsps",0);
669 
670                             /* boards/board/hardware/dsps/dsp */
671                             switch_xml_t xdsp = switch_xml_add_child_d(xdsps,"dsp",0);
672                             switch_xml_set_attr_d(xdsp,"id","0");
673 
674                             /* boards/board/hardware/dsps/dsps/version */
675                             switch_xml_t xversion_a = switch_xml_add_child_d(xdsp,"version",0);
676                             switch_xml_set_txt_d(xversion_a, dspCfg.DspVersion);
677 
678                             /* boards/board/hardware/dsps/dsps/firmare */
679                             switch_xml_t xfirmware = switch_xml_add_child_d(xdsp,"firmware",0);
680                             switch_xml_set_txt_d(xfirmware,dspCfg.FwVersion);
681 
682                             /* boards/board/hardware/pci */
683                             switch_xml_t xpci = switch_xml_add_child_d(xhardware,"pci",0);
684                             switch_xml_set_attr_d(xpci,"bus" ,STR(FMT("%02d") % devCfg.PciBus ));
685                             switch_xml_set_attr_d(xpci,"slot",STR(FMT("%02d") % devCfg.PciSlot));
686                         } break;
687 
688                         default:
689                             break;
690                     }
691                 }
692 
693                 if (Globals::k3lapi.device_type(i) == kdtFXOVoIP)
694                 {
695                     if (output_type == Cli::VERBOSE)
696                     {
697                         K::Logger::Logg2(classe, stream, FMT("| * Echo Canceller: %-20s - Location: %-12s  |")
698                             % Verbose::echoCancellerConfig(devCfg.EchoConfig)
699                             % Verbose::echoLocation(devCfg.EchoLocation));
700                     }
701                 }
702 
703                 break;
704             }
705             case kdtGSM:
706             case kdtGSMSpx:
707             {
708                 K3L_GSM40_FW_CONFIG dspCfg;
709 
710                 if (k3lGetDeviceConfig(i, ksoFirmware + kfiGSM40, &dspCfg, sizeof(dspCfg)) == ksSuccess)
711                 {
712                     switch(output_type)
713                     {
714                         case Cli::VERBOSE:
715                         {
716                             K::Logger::Logg2(classe, stream, FMT("| [[ %02d ]] %s, serial '%s', %02d channels. %s|")
717                                 % i % tipo % devCfg.SerialNumber % devCfg.ChannelCount
718                                 % std::string(std::max<int>(0, 30 - tipo.size() - strlen(devCfg.SerialNumber)), ' '));
719 
720                             K::Logger::Logg2(classe, stream, FMT("| * DSP: %s - PCI bus: %02d, PCI slot: %02d%s|")
721                                         % dspCfg.DspVersion % devCfg.PciBus % devCfg.PciSlot
722                                         % std::string(std::max<int>(30 - strlen(dspCfg.DspVersion), 0), ' '));
723 
724                             K::Logger::Logg2(classe, stream, FMT("| * %-62s |") % dspCfg.FwVersion);
725                         } break;
726 
727                         case Cli::CONCISE:
728                         {
729                             K::Logger::Logg2(classe, stream, FMT("%02d;%s;%d;%d;%s;%02d;%02d;%s")
730                                         % i % tipo % atoi(devCfg.SerialNumber) % devCfg.ChannelCount
731                                         % dspCfg.DspVersion % devCfg.PciBus % devCfg.PciSlot
732                                         % dspCfg.FwVersion);
733                         } break;
734 
735                         case Cli::XML:
736                         {
737                             /* boards/board */
738                             switch_xml_t xdev = switch_xml_add_child_d(xdev,"device",0);
739                             switch_xml_set_attr_d(xdev,"id",STR(FMT("%02u") % i));
740 
741                             /* boards/board/general */
742                             switch_xml_t xgeneral = switch_xml_add_child_d(xdev,"general",0);
743 
744                             /* boards/board/general/type */
745                             switch_xml_t xtype = switch_xml_add_child_d(xgeneral,"type",0);
746                             switch_xml_set_txt_d(xtype,tipo.c_str());
747 
748                             /* boards/board/general/serial */
749                             switch_xml_t xserial = switch_xml_add_child_d(xgeneral,"serial",0);
750                             switch_xml_set_txt_d(xserial, devCfg.SerialNumber);
751 
752                             /* boards/board/general/channels */
753                             switch_xml_t xchannels = switch_xml_add_child_d(xgeneral,"channels",0);
754                             switch_xml_set_txt_d(xchannels, STR(FMT("%02d") % devCfg.ChannelCount));
755 
756                             /* boards/board/general/links */
757                             switch_xml_t xlinks = switch_xml_add_child_d(xgeneral,"links",0);
758                             switch_xml_set_txt_d(xlinks, STR(FMT("%d") % devCfg.LinkCount));
759 
760                             /* boards/board/hardware */
761                             switch_xml_t xhardware = switch_xml_add_child_d(xdev,"hardware",0);
762 
763                             /* boards/board/hardware/dsps */
764                             switch_xml_t xdsps = switch_xml_add_child_d(xhardware,"dsps",0);
765 
766                             /* boards/board/hardware/dsps/dsp */
767                             switch_xml_t xdsp = switch_xml_add_child_d(xdsps,"dsp",0);
768                             switch_xml_set_attr_d(xdsp,"id","0");
769 
770                             /* boards/board/hardware/dsps/dsp/version */
771                             switch_xml_t xversion_a = switch_xml_add_child_d(xdsp,"version",0);
772                             switch_xml_set_txt_d(xversion_a, dspCfg.DspVersion);
773 
774                             /* boards/board/hardware/dsps/dsp/firmware*/
775                             switch_xml_t xfirmware = switch_xml_add_child_d(xdsp,"firmware",0);
776                             switch_xml_set_txt_d(xfirmware,dspCfg.FwVersion);
777 
778                             /* boards/board/hardware/dsps/dsp/pci */
779                             switch_xml_t xpci = switch_xml_add_child_d(xhardware,"pci",0);
780                             switch_xml_set_attr_d(xpci,"bus" ,STR(FMT("%02d") % devCfg.PciBus ));
781                             switch_xml_set_attr_d(xpci,"slot",STR(FMT("%02d") % devCfg.PciSlot));
782                         } break;
783 
784                         default:
785                             break;
786                     }
787                 }
788 
789                 break;
790             }
791             case kdtGSMUSB:
792             case kdtGSMUSBSpx:
793             {
794                 K3L_GSMUSB_FW_CONFIG dspCfg;
795 
796                 if (k3lGetDeviceConfig(i, ksoFirmware + kfiGSMUSB, &dspCfg, sizeof(dspCfg)) == ksSuccess)
797                 {
798                     switch(output_type)
799                     {
800                         case Cli::VERBOSE:
801                         {
802                             K::Logger::Logg2(classe, stream, FMT("| [[ %02d ]] %s, serial '%s', %02d channels. %s|")
803                                 % i % tipo % devCfg.SerialNumber % devCfg.ChannelCount
804                                 % std::string(std::max<int>(0, 30 - tipo.size() - strlen(devCfg.SerialNumber)), ' '));
805 
806                             int size = strlen(dspCfg.DspVersion) + strlen(dspCfg.FwVersion);
807 
808                             K::Logger::Logg2(classe, stream, FMT("| * DSP: %s - %s%s|")
809                                 % dspCfg.DspVersion % dspCfg.FwVersion
810                                 % std::string(std::max<int>(55 - size, 0), ' '));
811 
812                         } break;
813 
814                         case Cli::CONCISE:
815                         {
816                             K::Logger::Logg2(classe, stream, FMT("%02d;%s;%d;%d;%s;%s")
817                                         % i % tipo % atoi(devCfg.SerialNumber) % devCfg.ChannelCount
818                                         % dspCfg.DspVersion % dspCfg.FwVersion);
819                         } break;
820 
821                         case Cli::XML:
822                         {
823                             /* boards/board */
824                             switch_xml_t xdev = switch_xml_add_child_d(xdev,"device",0);
825                             switch_xml_set_attr_d(xdev,"id",STR(FMT("%02u") % i));
826 
827                             /* boards/board/general */
828                             switch_xml_t xgeneral = switch_xml_add_child_d(xdev,"general",0);
829 
830                             /* boards/board/general/type */
831                             switch_xml_t xtype = switch_xml_add_child_d(xgeneral,"type",0);
832                             switch_xml_set_txt_d(xtype,tipo.c_str());
833 
834                             /* boards/board/general/serial */
835                             switch_xml_t xserial = switch_xml_add_child_d(xgeneral,"serial",0);
836                             switch_xml_set_txt_d(xserial, devCfg.SerialNumber);
837 
838                             /* boards/board/general/channels */
839                             switch_xml_t xchannels = switch_xml_add_child_d(xgeneral,"channels",0);
840                             switch_xml_set_txt_d(xchannels, STR(FMT("%02d") % devCfg.ChannelCount));
841 
842                             /* boards/board/hardware */
843                             switch_xml_t xhardware = switch_xml_add_child_d(xdev,"hardware",0);
844 
845                             /* boards/board/hardware/dsps */
846                             switch_xml_t xdsps = switch_xml_add_child_d(xhardware,"dsps",0);
847 
848                             /* boards/board/hardware/dsp */
849                             switch_xml_t xdsp = switch_xml_add_child_d(xdsps,"dsp",0);
850                             switch_xml_set_attr_d(xdsp,"id","0");
851 
852                             /* boards/board/hardware/dsps/dsp/version */
853                             switch_xml_t xversion_a = switch_xml_add_child_d(xdsp,"version",0);
854                             switch_xml_set_txt_d(xversion_a, dspCfg.DspVersion);
855 
856                             /* boards/board/hardware/dsps/dsp/firmware */
857                             switch_xml_t xfirmware = switch_xml_add_child_d(xdsp,"firmware",0);
858                             switch_xml_set_txt_d(xfirmware,dspCfg.FwVersion);
859                         } break;
860 
861                         default:
862                             break;
863                     }
864                 }
865 
866                 break;
867             }
868 
869             default:
870                 K::Logger::Logg2(classe, stream, FMT("| [[ %02d ]] Unknown type '%02d'! Please contact Khomp support for help! |")
871                     % i % Globals::k3lapi.device_type(i));
872                 break;
873         }
874     }
875 
876     if (output_type == Cli::VERBOSE)
877         K::Logger::Logg2(classe,stream, " ------------------------------------------------------------------");
878 
879     if (output_type == Cli::XML)
880     {
881         printXMLOutput(stream);
882         clearRoot();
883     }
884 
885     return true;
886 }
887 
888 /* support function for _KhompShowCalls */
showCalls(unsigned int d,unsigned int o,std::string & buffer)889 void Cli::_KhompShowCalls::showCalls(unsigned int d, unsigned int o, std::string &buffer)
890 {
891     buffer += STR(FMT("| %d,%02d |   unused   | %11s | %-36s |\n")
892              % d
893              % o
894              % Globals::k3lutil.callStatus(d,o)
895              % Globals::k3lutil.channelStatus(d,o));
896 }
897 
execute(int argc,char * argv[])898 bool Cli::_KhompShowCalls::execute(int argc, char *argv[])
899 {
900     if(argc > 4)
901     {
902         printUsage(stream);
903         return false;
904     }
905 
906     int device = argv[2] ? atoi(argv[2]) : -1;
907     int object = argv[3] ? atoi(argv[3]) : -1;
908 
909     int d = -1;
910     int o = -1;
911 
912     if (device != -1)
913     {
914         d = device;
915 
916         if (!Globals::k3lapi.valid_device(d))
917         {
918             K::Logger::Logg2(C_CLI, stream, FMT("ERROR: No such device %d!") % d);
919             return false;
920         }
921     }
922 
923     if (object != -1)
924     {
925         o = object;
926 
927         if (!Globals::k3lapi.valid_channel(d,o))
928         {
929             K::Logger::Logg2(C_CLI, stream, FMT("ERROR: No such chanel %d for device %d!") % o % d);
930             return false;
931         }
932     }
933 
934     /* keep the channels reponse */
935     std::string buffer("");
936 
937     try
938     {
939         /**/ if (d != -1 && o != -1)
940         {
941             showCalls(d,o,buffer);
942         }
943         else if (d != -1 && o == -1)
944         {
945             for (unsigned int i = 0; i < Globals::k3lapi.channel_count(d); i++)
946             {
947                 buffer += " ------------------------------------------------------------------------\n";
948                 showCalls(d,i,buffer);
949             }
950         }
951         else if (d == -1 && o == -1)
952         {
953             for (unsigned int i = 0; i < Globals::k3lapi.device_count(); i++)
954             {
955                 buffer += " ------------------------------------------------------------------------\n";
956                 for (unsigned int j = 0; j < Globals::k3lapi.channel_count(i); j++)
957                 {
958                     showCalls(i,j,buffer);
959                 }
960             }
961         }
962     }
963     catch(K3LAPITraits::invalid_channel & err)
964     {
965         K::Logger::Logg2(C_CLI, stream, "ERROR: No such chanel");
966         return false;
967     }
968 
969     //TODO: The information shown here, must be reviewed cuz is the same of show channels
970     K::Logger::Logg2(C_CLI, stream, " ------------------------------------------------------------------------");
971     K::Logger::Logg2(C_CLI, stream, "|------------------------------- Khomp Calls ----------------------------|");
972     K::Logger::Logg2(C_CLI, stream, " ------------------------------------------------------------------------ ");
973     K::Logger::Logg2(C_CLI, stream, "|  hw  | freeSWITCH |  khomp call |             khomp channel            |");
974     K::Logger::Logg2(C_CLI, stream, "|  id  |   status   |    status   |                status                |");
975     K::Logger::Logg2(C_CLI, stream, "%s", (char*) buffer.c_str());
976     K::Logger::Logg2(C_CLI, stream, " ------------------------------------------------------------------------");
977 
978     return true;
979 }
980 
forceDisconnect(unsigned int device,unsigned int channel)981 bool Cli::_KhompChannelsDisconnect::forceDisconnect(unsigned int device, unsigned int channel)
982 {
983     bool ret = false;
984     Board::KhompPvt *pvt = NULL;
985 
986     try
987     {
988         pvt = Board::get(device,channel);
989         ScopedPvtLock lock(pvt);
990 
991         ret = pvt->command(KHOMP_LOG,CM_DISCONNECT);
992         DBG(FUNC,PVT_FMT(pvt->target(),"Command CM_DISCONNECT sent!"));
993     }
994     catch (K3LAPITraits::invalid_channel & err)
995     {
996         K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % err.object % err.device );
997     }
998     catch (ScopedLockFailed & err)
999     {
1000         K::Logger::Logg2(C_CLI,stream,FMT("error: channel %d at device %d could not be locked: %s!")
1001         % channel
1002         % device
1003         % err._msg.c_str());
1004     }
1005 
1006     return ret;
1007 }
1008 
execute(int argc,char * argv[])1009 bool Cli::_KhompChannelsDisconnect::execute(int argc, char *argv[])
1010 {
1011     if (argc < 3 || argc > 4)
1012     {
1013         printUsage(stream);
1014         return false;
1015     }
1016 
1017     switch (argc)
1018     {
1019         case 3:
1020         {
1021             if (!ARG_CMP(2, "all"))
1022             {
1023                 K::Logger::Logg2(C_CLI, stream, "usage: khomp channels disconnect < all | <boardid> < all | <channelid> > >");
1024                 return false;
1025             }
1026 
1027             K::Logger::Logg2(C_CLI, stream, "NOTICE: Disconnecting all channels on all boards!");
1028 
1029             for (unsigned int dev = 0; dev < Globals::k3lapi.device_count(); dev++)
1030             {
1031                 for (unsigned int chan = 0; chan < Globals::k3lapi.channel_count(dev); chan++)
1032                     forceDisconnect(dev,chan);
1033             }
1034             break;
1035         }
1036         case 4:
1037         {
1038             unsigned int dev = atoi(argv[2]);
1039 
1040             if (ARG_CMP(3, "all"))
1041             {
1042                 K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: Disconnecting all channels on board %d!") % dev);
1043 
1044                 for (unsigned int chan = 0; chan < Globals::k3lapi.channel_count(dev); chan++)
1045                     forceDisconnect(dev,chan);
1046             }
1047 
1048             unsigned int channel = atoi(argv[3]);
1049 
1050             if (dev >= Globals::k3lapi.device_count())
1051             {
1052                 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: No such device: %d!") % dev);
1053                 return false;
1054             }
1055 
1056 
1057             K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: Disconnecting channel %d on board %d!") % channel % dev);
1058 
1059             forceDisconnect(dev,channel);
1060             break;
1061         }
1062 
1063         default:
1064             break;
1065     }
1066 
1067     return true;
1068 }
1069 
execute(int argc,char * argv[])1070 bool Cli::_KhompChannelsUnblock::execute(int argc, char *argv[])
1071 {
1072     if (argc != 4 && argc != 3)
1073     {
1074         printUsage(stream);
1075         return false;
1076     }
1077 
1078     switch (argc)
1079     {
1080         case 3:
1081         {
1082             K::Logger::Logg2(C_CLI, stream, "NOTICE: Unblocking all channels on all devices!");
1083             for (unsigned int dev = 0; dev < Globals::k3lapi.device_count(); dev++)
1084             {
1085                 for (unsigned int chan = 0; chan < Globals::k3lapi.channel_count(dev); chan++)
1086                 {
1087                     try
1088                     {
1089                         Globals::k3lapi.command(dev,chan,CM_UNLOCK_INCOMING);
1090                         Globals::k3lapi.command(dev,chan,CM_UNLOCK_OUTGOING);
1091                     }
1092                     catch(K3LAPI::failed_command &e)
1093                     {
1094                         if (K::Logger::Logg.classe(C_WARNING).enabled())
1095                         {
1096                             LOG(WARNING, FMT("Command '%s' has failed with error '%s'.")
1097                                     % Verbose::commandName(e.code) % Verbose::status((KLibraryStatus)e.rc));
1098                         }
1099 
1100                         return false;
1101                     }
1102                 }
1103             }
1104             break;
1105         }
1106         case 4:
1107         {
1108             int dev = atoi (argv[2]);
1109 
1110             if ( !SAFE_strcasecmp(argv[3], "all") )
1111             {
1112                 if (!Globals::k3lapi.valid_device( dev ))
1113                 {
1114                     K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find device: %d!") % dev );
1115                     return false;
1116                 }
1117 
1118                 K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: Unblocking all channels on device %d!") % dev);
1119 
1120                 for (unsigned int i = 0; i < Globals::k3lapi.channel_count(dev); i++)
1121                 {
1122                     try
1123                     {
1124                         Globals::k3lapi.command(dev,i,CM_UNLOCK_INCOMING);
1125                         Globals::k3lapi.command(dev,i,CM_UNLOCK_OUTGOING);
1126                     }
1127                     catch(K3LAPI::failed_command &e)
1128                     {
1129                         if (K::Logger::Logg.classe(C_WARNING).enabled())
1130                         {
1131                             LOG(WARNING, FMT("Command '%s' has failed with error '%s'.")
1132                                     % Verbose::commandName(e.code) % Verbose::status((KLibraryStatus)e.rc));
1133                         }
1134 
1135                         return false;
1136                     }
1137                 }
1138             }
1139             else
1140             {
1141                 int obj = atoi (argv[3]);
1142 
1143                 if (!Globals::k3lapi.valid_channel(dev, obj))
1144                 {
1145                     K::Logger::Logg2(C_CLI, stream, FMT("ERROR: No such channel %d at device %d!") % obj % dev);
1146                     return false;
1147                 }
1148 
1149                 K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: Unblocking channel %d on device %d!") % obj % dev);
1150 
1151                 try
1152                 {
1153                     Globals::k3lapi.command(dev,obj,CM_UNLOCK_INCOMING);
1154                     Globals::k3lapi.command(dev,obj,CM_UNLOCK_OUTGOING);
1155                 }
1156                 catch(K3LAPI::failed_command &e)
1157                 {
1158                     if (K::Logger::Logg.classe(C_WARNING).enabled())
1159                     {
1160                         LOG(WARNING, FMT("Command '%s' has failed with error '%s'.")
1161                                 % Verbose::commandName(e.code) % Verbose::status((KLibraryStatus)e.rc));
1162                     }
1163 
1164                     return false;
1165                 }
1166             }
1167             break;
1168         }
1169         default:
1170             break;
1171     }
1172 
1173     return true;
1174 }
1175 
cliStatistics(unsigned int device,OutputType output_type)1176 void Cli::_KhompShowStatistics::cliStatistics(unsigned int device, OutputType output_type)
1177 {
1178     if(output_type == Cli::XML)
1179     {
1180         /* device */
1181         xdevs = switch_xml_add_child_d(root,"device",0);
1182         switch_xml_set_attr_d(xdevs,"id",STR(FMT("%d") % device));
1183     }
1184 
1185     for (unsigned int channel = 0; channel < Globals::k3lapi.channel_count(device); channel++)
1186     {
1187         try
1188         {
1189             Board::KhompPvt *pvt = Board::get(device, channel);
1190             switch(output_type)
1191             {
1192                 case Cli::VERBOSE:
1193                     K::Logger::Logg2(C_CLI,stream,pvt->getStatistics(Statistics::ROW).c_str());
1194                     break;
1195                 case Cli::CONCISE:
1196                     /* do we need concise ? */
1197                     break;
1198                 case Cli::XML:
1199                     switch_xml_insert(pvt->getStatisticsXML(Statistics::ROW),xdevs,0);
1200                     break;
1201             }
1202         }
1203         catch (K3LAPITraits::invalid_channel & err)
1204         {
1205             K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % err.object % err.device );
1206         }
1207     }
1208 }
1209 
cliDetailedStatistics(unsigned int device,unsigned int channel,OutputType output_type)1210 void Cli::_KhompShowStatistics::cliDetailedStatistics(unsigned int device, unsigned int channel, OutputType output_type)
1211 {
1212     try
1213     {
1214         Board::KhompPvt *pvt = Board::get(device, channel);
1215         switch(output_type)
1216         {
1217             case Cli::DETAILED:
1218             {
1219                 K::Logger::Logg2(C_CLI,stream,"----------------------------------------------");
1220                 K::Logger::Logg2(C_CLI,stream,FMT("Detailed statistics of: Device %02d - Channel %02d") % pvt->target().device % pvt->target().object);
1221                 K::Logger::Logg2(C_CLI,stream,pvt->getStatistics(Statistics::DETAILED).c_str());
1222                 K::Logger::Logg2(C_CLI,stream,"----------------------------------------------");
1223             } break;
1224 
1225             case Cli::CONCISE:
1226             {
1227                 /* We don't have xml, need concise yet ? */
1228             } break;
1229 
1230             case Cli::XML:
1231             {
1232                 /* We don't have concise, need XML yet ? */
1233             } break;
1234         }
1235     }
1236     catch (K3LAPITraits::invalid_channel & err)
1237     {
1238         K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % err.object % err.device );
1239     }
1240 }
1241 
execute(int argc,char * argv[])1242 bool Cli::_KhompShowStatistics::execute(int argc, char *argv[])
1243 {
1244     if (argc < 2 || argc > 5)
1245     {
1246         printUsage(stream);
1247         return false;
1248     }
1249 
1250     unsigned int dev = UINT_MAX;
1251     unsigned int obj = UINT_MAX;
1252     int detailed = 0, verbose  = 0, as_xml = 0;
1253     OutputType output_type = Cli::VERBOSE;
1254 
1255     detailed = ((argc > 2)  && (!strcasecmp(argv[2], "detailed")) ? 1 : 0 );
1256     verbose  = ((argc > 2)  && (!strcasecmp(argv[2], "verbose"))  ? 1 : 0 );
1257     as_xml   = ((argc > 2)  && (!strcasecmp(argv[2], "xml"))      ? 1 : 0 );
1258 
1259     try
1260     {
1261         if(argc > (2+detailed+verbose+as_xml))
1262         {
1263             dev = Strings::tolong(argv[2+detailed+verbose+as_xml]);
1264             if (!Globals::k3lapi.valid_device(dev))
1265             {
1266                 K::Logger::Logg2(C_CLI, stream, "ERROR: No such device!");
1267                 return false;
1268             }
1269         }
1270 
1271         if (argc > (3+detailed+verbose+as_xml))
1272         {
1273             std::string object(argv[3+detailed+verbose+as_xml]);
1274             obj = Strings::tolong(object);
1275 
1276             if (!Globals::k3lapi.valid_channel(dev, obj))
1277             {
1278                 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % obj % dev );
1279                 return false;
1280             }
1281         }
1282     }
1283     catch (Strings::invalid_value e)
1284     {
1285         K::Logger::Logg2(C_CLI, stream, "ERROR: Invalid numeric value!");
1286         return false;
1287     }
1288 
1289     if(detailed) output_type = Cli::DETAILED;
1290     if(as_xml)
1291     {
1292         createRoot("statistics");
1293         output_type = Cli::XML;
1294     }
1295 
1296     std::string header;
1297     header.append( " ------------------------------------------------------------------------------------\n");
1298     header.append( "|----------------------------- Khomp Endpoint Statistics ----------------------------|\n");
1299     header.append( "|------------------------------------------------------------------------------------|\n");
1300     header.append( "|  hw  |          total calls           | channel | FreeSWITCH | channel  |  status  |\n");
1301     header.append( "|  id  | incoming | outgoing |  failed  |  fails  |   status   |  state   |   time   |\n");
1302     header.append( " ------------------------------------------------------------------------------------");
1303     std::string footer;
1304     footer.append( " ------------------------------------------------------------------------------------");
1305 
1306     try
1307     {
1308         if (obj != UINT_MAX)
1309         {
1310             switch(output_type)
1311             {
1312                 case Cli::VERBOSE:
1313                 {
1314                     K::Logger::Logg2(C_CLI,stream,header.c_str());
1315                     Board::KhompPvt *pvt = Board::get(dev, obj);
1316                     K::Logger::Logg2(C_CLI,stream,pvt->getStatistics(Statistics::ROW).c_str());
1317                     K::Logger::Logg2(C_CLI,stream,footer.c_str());
1318                 } break;
1319 
1320                 case Cli::DETAILED:
1321                 {
1322                     cliDetailedStatistics (dev, obj, output_type);
1323                 } break;
1324 
1325                 case Cli::XML:
1326                 {
1327                     /* no problem, nothing created */
1328                     switch_xml_t xboard = NULL;
1329 
1330                     /* device */
1331                     xdevs = switch_xml_add_child_d(root,"device",0);
1332                     switch_xml_set_attr_d(xdevs,"id",STR(FMT("%d") % dev));
1333 
1334                     try
1335                     {
1336                         Board::KhompPvt *pvt = Board::get(dev, obj);
1337                         switch_xml_insert(pvt->getStatisticsXML(Statistics::ROW),xdevs,0);
1338                     }
1339                     catch (K3LAPITraits::invalid_channel & err)
1340                     {
1341                         K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % err.object % err.device );
1342                     }
1343 
1344                     printXMLOutput(stream);
1345                     clearRoot();
1346                 } break;
1347             }
1348         }
1349         else
1350         {
1351             switch(output_type)
1352             {
1353                 case Cli::VERBOSE:
1354                 {
1355                     K::Logger::Logg2(C_CLI,stream,header.c_str());
1356 
1357                     if (dev == UINT_MAX)
1358                     {
1359                         for (dev = 0; dev < Globals::k3lapi.device_count(); dev++)
1360                             cliStatistics (dev, output_type);
1361                     }
1362                     else
1363                     {
1364                         cliStatistics (dev, output_type);
1365                     }
1366 
1367                     K::Logger::Logg2(C_CLI,stream,footer.c_str());
1368                 } break;
1369 
1370                 case Cli::XML:
1371                 {
1372                     if (dev == UINT_MAX)
1373                     {
1374                         for (dev = 0; dev < Globals::k3lapi.device_count(); dev++)
1375                             cliStatistics (dev, output_type);
1376                     }
1377                     else
1378                     {
1379                         cliStatistics (dev, output_type);
1380                     }
1381 
1382                     printXMLOutput(stream);
1383                     clearRoot();
1384 
1385                 } break;
1386 
1387                 case Cli::DETAILED:
1388                 {
1389                     printUsage(stream);
1390                     return false;
1391                 } break;
1392             }
1393         }
1394     }
1395     catch(K3LAPITraits::invalid_channel &e)
1396     {
1397         K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % obj % dev );
1398     }
1399 
1400     return true;
1401 }
1402 
showChannel(unsigned int device,unsigned int channel,OutputType output_type)1403 void Cli::_KhompShowChannels::showChannel(unsigned int device, unsigned int channel, OutputType output_type)
1404 {
1405     try
1406     {
1407         Board::KhompPvt *pvt = Board::get(device, channel);
1408 
1409         DBG(FUNC, PVT_FMT(pvt->target(), "found channel.."));
1410 
1411         /* skip inactive channels */
1412         if (pvt->getSignaling() == ksigInactive)
1413             return;
1414 
1415         DBG(FUNC, PVT_FMT(pvt->target(), "is valid.."));
1416 
1417         /* make sure the states wont start 'dancing' at random.. */
1418         ScopedPvtLock lock(pvt);
1419 
1420         std::string tmp_call = Globals::k3lutil.callStatus(
1421                 pvt->target().device,
1422                 pvt->target().object,
1423                 (output_type == Cli::CONCISE ? Verbose::EXACT : Verbose::HUMAN));
1424 
1425         std::string tmp_chan = Globals::k3lutil.channelStatus(
1426                 pvt->target().device,
1427                 pvt->target().object,
1428                 (output_type == Cli::CONCISE ? Verbose::EXACT : Verbose::HUMAN));
1429 
1430 
1431         switch(output_type)
1432         {
1433             case Cli::VERBOSE:
1434             {
1435                 if (pvt->getSignaling() == ksigGSM)
1436                 {
1437                     K3L_GSM_CHANNEL_STATUS gsmStatus;
1438 
1439                     if (k3lGetDeviceStatus(device, channel + ksoGsmChannel, &gsmStatus, sizeof(gsmStatus)) != ksSuccess)
1440                         return;
1441 
1442                     const unsigned int sign_numb = (gsmStatus.SignalStrength != 255 ? gsmStatus.SignalStrength : 0);
1443 
1444                     const unsigned int full_size = 10;
1445                     const unsigned int sign_size = std::min((sign_numb * full_size) / 100, full_size);
1446 
1447                     std::string tmp_antenna_level;
1448 
1449                     for (unsigned int i = 0; i < sign_size; i++)
1450                         tmp_antenna_level += '*';
1451 
1452                     for (unsigned int i = sign_size; i < full_size; i++)
1453                         tmp_antenna_level += ' ';
1454 
1455                     tmp_chan += " (";
1456                     tmp_chan += (strlen(gsmStatus.OperName) != 0 ? gsmStatus.OperName : "...");
1457                     tmp_chan += ")";
1458 
1459                     K::Logger::Logg2(C_CLI, stream, FMT("| %d,%02d | %8s | %8s | %-23s | %02d%% |%s|")
1460                             % device % channel %  pvt->getStateString() % tmp_call % tmp_chan
1461                             % sign_numb % tmp_antenna_level);
1462                 }
1463                 else
1464                 {
1465                     K::Logger::Logg2(C_CLI, stream, FMT("| %d,%02d | %8s | %8s | %-40s |")
1466                             % device % channel % pvt->getStateString() % tmp_call % tmp_chan);
1467                 }
1468 
1469             } break;
1470 
1471             case Cli::CONCISE:
1472             {
1473                 std::string state = pvt->getStateString();
1474 
1475                 if (pvt->getSignaling() == ksigGSM)
1476                 {
1477                     K3L_GSM_CHANNEL_STATUS gsmStatus;
1478 
1479                     if (k3lGetDeviceStatus(device, channel + ksoGsmChannel, &gsmStatus, sizeof(gsmStatus)) != ksSuccess)
1480                         return;
1481 
1482                     const unsigned int sign_numb = (gsmStatus.SignalStrength != 255 ? gsmStatus.SignalStrength : 0);
1483 
1484                     std::string gsm_registry = (strlen(gsmStatus.OperName) != 0 ? gsmStatus.OperName : "<none>");
1485 
1486                     K::Logger::Logg2(C_CLI, stream, FMT("B%02dC%02d:%s:%s:%s:%d%%:%s")
1487                             % device % channel % state % tmp_call % tmp_chan
1488                             % sign_numb % gsm_registry);
1489                 }
1490                 else
1491                 {
1492                     K::Logger::Logg2(C_CLI, stream, FMT("B%02dC%02d:%s:%s:%s")
1493                             % device % channel %  state % tmp_call % tmp_chan);
1494                 }
1495 
1496             } break;
1497 
1498             case Cli::XML:
1499             {
1500                 /* device/channel */
1501                 switch_xml_t xchannel = switch_xml_add_child_d(xdev,"channel",0);
1502                 switch_xml_set_attr_d(xchannel,"id",STR(FMT("%d") % channel));
1503 
1504                 /* device/channel/fs_state */
1505                 switch_xml_t xstate = switch_xml_add_child_d(xchannel,"fs_state",0);
1506                 switch_xml_set_txt_d(xstate, pvt->getStateString().c_str());
1507 
1508                 /* device/channel/call */
1509                 switch_xml_t xcall = switch_xml_add_child_d(xchannel,"call",0);
1510                 switch_xml_set_txt_d(xcall, tmp_call.c_str());
1511 
1512                 /* device/channel/status */
1513                 switch_xml_t xstatus = switch_xml_add_child_d(xchannel,"status",0);
1514                 switch_xml_set_txt_d(xstatus, tmp_chan.c_str());
1515 
1516                 if (pvt->getSignaling() == ksigGSM)
1517                 {
1518                     K3L_GSM_CHANNEL_STATUS gsmStatus;
1519 
1520                     if (k3lGetDeviceStatus(device, channel + ksoGsmChannel, &gsmStatus, sizeof(gsmStatus)) != ksSuccess)
1521                         return;
1522 
1523                     const unsigned int sign_numb = (gsmStatus.SignalStrength != 255 ? gsmStatus.SignalStrength : 0);
1524                     std::string gsm_registry = (strlen(gsmStatus.OperName) != 0 ? gsmStatus.OperName : "<none>");
1525 
1526                     /* device/channel/signal */
1527                     switch_xml_t xsign_numb = switch_xml_add_child_d(xchannel, "signal", 0);
1528                     switch_xml_set_txt_d(xsign_numb, STR(FMT("%d") % sign_numb));
1529 
1530                     /* device/channel/registry */
1531                     switch_xml_t xgsm_registry = switch_xml_add_child_d(xchannel, "registry", 9);
1532                     switch_xml_set_txt_d(xgsm_registry, gsm_registry.c_str());
1533                 }
1534 
1535             } break;
1536 
1537             default:
1538                 /* do nothing */
1539                 break;
1540         }
1541 
1542     }
1543     catch (K3LAPITraits::invalid_channel & err)
1544     {
1545         K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % err.object % err.device );
1546     }
1547     catch (...)
1548     {
1549         K::Logger::Logg2(C_CLI, stream, "ERROR: Unexpected error..., skipping");
1550     }
1551 }
1552 
showChannels(unsigned int device,OutputType output_type)1553 void Cli::_KhompShowChannels::showChannels(unsigned int device, OutputType output_type)
1554 {
1555     if(output_type == Cli::XML)
1556     {
1557         /* channels/device */
1558         xdev = switch_xml_add_child_d(root,"device",0);
1559         switch_xml_set_attr_d(xdev, "id", STR(FMT("%d") % device));
1560     }
1561 
1562     for (unsigned int channel = 0; channel < Globals::k3lapi.channel_count(device); channel++)
1563     {
1564         showChannel(device, channel, output_type);
1565     }
1566 }
1567 
execute(int argc,char * argv[])1568 bool Cli::_KhompShowChannels::execute(int argc, char *argv[])
1569 {
1570     unsigned int dev = UINT_MAX;
1571     int concise = 0, verbose = 0, as_xml = 0;
1572     OutputType output_type = Cli::VERBOSE;
1573 
1574     bool onlyShowOneChannel = false;
1575     unsigned int channelToShow = 0;
1576 
1577     if (argc > 5)
1578     {
1579         Cli::KhompShowChannels.printUsage(stream);
1580         return false;
1581     }
1582 
1583     concise = ( ((argc == 3) || (argc == 4) || (argc == 5) ) && (ARG_CMP(2, "concise")) ? 1 : 0 );
1584     verbose = ( ((argc == 3) || (argc == 4) || (argc == 5) ) && (ARG_CMP(2, "verbose")) ? 1 : 0 );
1585     as_xml  = ( ((argc == 3) || (argc == 4) || (argc == 5) ) && (ARG_CMP(2, "xml"))     ? 1 : 0 );
1586 
1587     if (argc >= (3 + concise + verbose + as_xml))
1588     {
1589         dev = atoi (argv[2 + concise + verbose + as_xml]);
1590 
1591         if (!Globals::k3lapi.valid_device(dev))
1592         {
1593             K::Logger::Logg2(C_CLI, stream, "ERROR: no such device!");
1594             return false;
1595         }
1596 
1597         if (argc == ( 4 + concise + verbose + as_xml))
1598         {
1599             onlyShowOneChannel = true;
1600             channelToShow = atoi (argv[3 + concise + verbose + as_xml]);
1601         }
1602     }
1603 
1604     if (concise == 0 && as_xml == 0)
1605     {
1606         K::Logger::Logg2(C_CLI, stream, " -----------------------------------------------------------------------");
1607         K::Logger::Logg2(C_CLI, stream, "|-------------------- Khomp Channels and Connections -------------------|");
1608         K::Logger::Logg2(C_CLI, stream, "|-----------------------------------------------------------------------|");
1609         K::Logger::Logg2(C_CLI, stream, "|  hw  |freeSWITCH|   call   |                   channel                |");
1610         K::Logger::Logg2(C_CLI, stream, "|  id  |  status  |  status  |                   status                 |");
1611         K::Logger::Logg2(C_CLI, stream, " -----------------------------------------------------------------------");
1612     }
1613 
1614     if (concise != 0) output_type = Cli::CONCISE;
1615     if (as_xml  != 0)
1616     {
1617         output_type = Cli::XML;
1618 
1619         /* channels */
1620         createRoot("channels");
1621     }
1622 
1623     if ( onlyShowOneChannel )
1624     {
1625         if ( channelToShow <  Globals::k3lapi.channel_count(dev) )
1626         {
1627             if(output_type == Cli::XML)
1628             {
1629                 /* channels/device */
1630                 xdev = switch_xml_add_child_d(root,"device",0);
1631                 switch_xml_set_attr_d(xdev, "id", STR(FMT("%d") % dev));
1632             }
1633 
1634             showChannel (dev, channelToShow, output_type);
1635         }
1636         else
1637         {
1638             K::Logger::Logg2(C_CLI, stream, "ERROR: no such channel!");
1639         }
1640     }
1641     else if (dev == UINT_MAX)
1642     {
1643         for (dev = 0; dev < Globals::k3lapi.device_count(); dev++)
1644         {
1645             showChannels(dev, output_type);
1646         }
1647     }
1648     else
1649     {
1650         showChannels ( dev, output_type);
1651     }
1652 
1653     if (concise == 0 && as_xml == 0)
1654         K::Logger::Logg2(C_CLI, stream, " -----------------------------------------------------------------------");
1655 
1656     if(output_type == Cli::XML)
1657     {
1658         printXMLOutput(stream);
1659         clearRoot();
1660     }
1661 
1662     return true;
1663 }
1664 
getLinkStatus(int dev,int obj,Verbose::Presentation fmt)1665 std::string Cli::_KhompShowLinks::getLinkStatus(int dev, int obj, Verbose::Presentation fmt)
1666 {
1667     switch(Globals::k3lapi.device_type(dev))
1668     {
1669         case kdtE1FXSSpx:
1670             if (obj == 1)
1671                 return Globals::k3lutil.linkStatus(dev, obj, fmt, ksigAnalogTerminal, true);
1672         default:
1673             break;
1674     }
1675 
1676     std::string res;
1677 
1678     try
1679     {
1680         const K3L_LINK_CONFIG & conf = Globals::k3lapi.link_config(dev, obj);
1681 
1682         res = Globals::k3lutil.linkStatus(dev, obj, fmt);
1683 
1684         if (conf.ReceivingClock & 0x01)
1685            res += (fmt == Verbose::EXACT ? ",sync" : " (sync)");
1686     }
1687     catch (K3LAPITraits::invalid_target & e)
1688     {
1689         res = "<error>";
1690     }
1691 
1692     return res;
1693 }
1694 
showLinks(unsigned int device,OutputType output_type)1695 void Cli::_KhompShowLinks::showLinks(unsigned int device, OutputType output_type)
1696 {
1697     if (output_type != Cli::CONCISE && output_type != Cli::XML)
1698         K::Logger::Logg2(C_CLI, stream, "|------------------------------------------------------------------------|");
1699 
1700     switch (Globals::k3lutil.physicalLinkCount(device, true))
1701     {
1702         case 1:
1703         {
1704             std::string str_link0 = getLinkStatus(device, 0, (output_type == Cli::CONCISE ? Verbose::EXACT : Verbose::HUMAN));
1705 
1706             switch(output_type)
1707             {
1708                 case Cli::VERBOSE:
1709                 {
1710                     K::Logger::Logg2(C_CLI, stream, FMT("| Link '0' on board '%d': %-47s |") % device % str_link0);
1711                 } break;
1712 
1713                 case Cli::CONCISE:
1714                 {
1715                     K::Logger::Logg2(C_MESSAGE, stream, FMT("B%02dL00:%s") % device % str_link0);
1716                 } break;
1717 
1718                 case Cli::XML:
1719                 {
1720                     /* device */
1721                     xdev = switch_xml_add_child_d(root,"device",0);
1722                     switch_xml_set_attr_d(xdev,"id",STR(FMT("%d") % device));
1723 
1724                     /* device/links */
1725                     switch_xml_t xlinks = switch_xml_add_child_d(xdev,"links",0);
1726 
1727                     /* device/links/link */
1728                     switch_xml_t xlink = switch_xml_add_child_d(xlinks,"link",0);
1729                     switch_xml_set_attr_d(xlink, "id", "0");
1730                     switch_xml_set_txt_d(xlink, str_link0.c_str());
1731                 } break;
1732             }
1733 
1734             break;
1735         }
1736 
1737         case 2:
1738         {
1739             std::string str_link0 = getLinkStatus(device, 0, (output_type == Cli::CONCISE ? Verbose::EXACT : Verbose::HUMAN));
1740             std::string str_link1 = getLinkStatus(device, 1, (output_type == Cli::CONCISE ? Verbose::EXACT : Verbose::HUMAN));
1741 
1742             switch(output_type)
1743             {
1744                 case Cli::VERBOSE:
1745                 {
1746                     K::Logger::Logg2(C_CLI, stream, FMT("|------ Link '0' on board '%d' ------||------ Link '1' on board '%d' ------|")
1747                         % device % device);
1748 
1749                     K::Logger::Logg2(C_CLI, stream, FMT("| %-33s || %-33s |") % str_link0 % str_link1);
1750                 } break;
1751 
1752                 case Cli::CONCISE:
1753                 {
1754                     K::Logger::Logg2(C_MESSAGE, stream, FMT("B%02dL00:%s") % device % str_link0);
1755                     K::Logger::Logg2(C_MESSAGE, stream, FMT("B%02dL01:%s") % device % str_link1);
1756                 } break;
1757 
1758                 case Cli::XML:
1759                 {
1760                     /* device */
1761                     xdev = switch_xml_add_child_d(root,"device",0);
1762                     switch_xml_set_attr_d(xdev,"id",STR(FMT("%d") % device));
1763 
1764                     /* device/links */
1765                     switch_xml_t xlinks = switch_xml_add_child_d(xdev,"links",0);
1766 
1767                     /* device/links/link (0) */
1768                     switch_xml_t xlink = switch_xml_add_child_d(xlinks,"link",0);
1769                     switch_xml_set_attr_d(xlink, "id", "0");
1770                     switch_xml_set_txt_d(xlink, str_link0.c_str());
1771 
1772                     /* device/links/link (1) */
1773                     switch_xml_t xlink1 = switch_xml_add_child_d(xlinks,"link",0);
1774                     switch_xml_set_attr_d(xlink1, "id", "1");
1775                     switch_xml_set_txt_d(xlink1, str_link0.c_str());
1776                 } break;
1777             }
1778 
1779             break;
1780         }
1781         default:
1782         {
1783             switch(output_type)
1784             {
1785                 case Cli::VERBOSE:
1786                 {
1787                     K::Logger::Logg2(C_CLI, stream, FMT("| Board '%d': %-59s |") % device % "No links available.");
1788                 } break;
1789 
1790                 case Cli::CONCISE:
1791                 {
1792                     K::Logger::Logg2(C_MESSAGE, stream, FMT("B%02dLXX:NoLinksAvailable") % device);
1793                 } break;
1794 
1795                 case Cli::XML:
1796                 {
1797                     /* device */
1798                     xdev = switch_xml_add_child_d(root,"device",0);
1799                     switch_xml_set_attr_d(xdev,"id",STR(FMT("%d") % device));
1800                     switch_xml_set_txt_d(xdev,"NoLinksAvailable");
1801                 } break;
1802             }
1803 
1804             break;
1805         }
1806     }
1807 }
1808 
showErrors(unsigned int device,OutputType output_type)1809 void Cli::_KhompShowLinks::showErrors(unsigned int device, OutputType output_type)
1810 {
1811     if (output_type != Cli::CONCISE && output_type != Cli::XML)
1812         K::Logger::Logg2(C_CLI, stream, "|-----------------------------------------------------------------------|");
1813 
1814     switch (Globals::k3lutil.physicalLinkCount(device, true))
1815     {
1816         case 2:
1817         {
1818             K3LUtil::ErrorCountType link0 = Globals::k3lutil.linkErrorCount(
1819                     device, 0, (output_type == Cli::CONCISE ? Verbose::EXACT : Verbose::HUMAN));
1820             K3LUtil::ErrorCountType link1 = Globals::k3lutil.linkErrorCount(
1821                     device, 1, (output_type == Cli::CONCISE ? Verbose::EXACT : Verbose::HUMAN));
1822 
1823             switch(output_type)
1824             {
1825                 case Cli::VERBOSE:
1826                 {
1827                     K::Logger::Logg2(C_CLI, stream, FMT("|----- Link '0' on board '%d' ------| |----- Link '1' on board '%d' ------|") % device % device);
1828                     K::Logger::Logg2(C_CLI, stream, "|----------------------------------| |----------------------------------|");
1829                     K::Logger::Logg2(C_CLI, stream, "|       Error type       | Number  | |       Error type       | Number  |");
1830                     K::Logger::Logg2(C_CLI, stream, "|----------------------------------| |----------------------------------|");
1831 
1832                     K3LUtil::ErrorCountType::iterator i = link0.begin();
1833                     K3LUtil::ErrorCountType::iterator j = link1.begin();
1834 
1835                     for (; i != link0.end() && j != link1.end(); i++, j++)
1836                     {
1837                         K::Logger::Logg2(C_CLI, stream, FMT("| %22s | %-7d | | %22s | %-7d |")
1838                            % i->first % i->second % j->first % j->second);
1839                     }
1840                 } break;
1841 
1842                 case Cli::CONCISE:
1843                 {
1844                     for (K3LUtil::ErrorCountType::iterator i = link0.begin(); i != link0.end(); i++)
1845                         K::Logger::Logg2(C_CLI, stream, FMT("%d:0:%s:%d") % device % i->first % i->second);
1846 
1847                     for (K3LUtil::ErrorCountType::iterator i = link1.begin(); i != link1.end(); i++)
1848                         K::Logger::Logg2(C_CLI, stream, FMT("%d:1:%s:%d") % device % i->first % i->second);
1849                 } break;
1850 
1851                 case Cli::XML:
1852                 {
1853                     /* device */
1854                     xdev = switch_xml_add_child_d(root,"device",0);
1855                     switch_xml_set_attr_d(xdev,"id",STR(FMT("%d") % device));
1856 
1857                     /* device/errors */
1858                     switch_xml_t xerrors = switch_xml_add_child_d(xdev,"errors",0);
1859 
1860                     /* device/errors/link (0) */
1861                     switch_xml_t xlinks0 = switch_xml_add_child_d(xerrors,"link",0);
1862                     switch_xml_set_attr_d(xlinks0,"id","0");
1863 
1864                     for (K3LUtil::ErrorCountType::iterator i = link0.begin(); i != link0.end(); i++)
1865                     {
1866                         /* device/errors/link/type */
1867                         switch_xml_t xtype0 = switch_xml_add_child_d(xlinks0,"type",0);
1868                         switch_xml_set_txt_d(xtype0,i->first.c_str());
1869 
1870                         /* device/errors/link/number */
1871                         switch_xml_t xnumber0  = switch_xml_add_child_d(xlinks0,"number",0);
1872                         switch_xml_set_txt_d(xnumber0,STR(FMT("%d") % i->second));
1873                     }
1874 
1875                     /* device/errors/link (1) */
1876                     switch_xml_t xlinks1 = switch_xml_add_child_d(xerrors,"link",0);
1877                     switch_xml_set_attr_d(xlinks1,"id","1");
1878 
1879                     for (K3LUtil::ErrorCountType::iterator i = link1.begin(); i != link1.end(); i++)
1880                     {
1881                         /* device/errors/link/type */
1882                         switch_xml_t xtype1 = switch_xml_add_child_d(xlinks1,"type",0);
1883                         switch_xml_set_txt_d(xtype1,i->first.c_str());
1884 
1885                         /* device/errors/link/number */
1886                         switch_xml_t xnumber1  = switch_xml_add_child_d(xlinks1,"number",0);
1887                         switch_xml_set_txt_d(xnumber1,STR(FMT("%d") % i->second));
1888                     }
1889                 } break;
1890             }
1891 
1892             break;
1893         }
1894 
1895         case 1:
1896         {
1897             K3LUtil::ErrorCountType link0 = Globals::k3lutil.linkErrorCount(device, 0, (output_type == Cli::CONCISE ? Verbose::EXACT : Verbose::HUMAN));
1898 
1899             switch(output_type)
1900             {
1901                 case Cli::VERBOSE:
1902                 {
1903                     K::Logger::Logg2(C_CLI, stream, FMT("|------------------------ Link '0' on board '%d' ------------------------|") % device);
1904                     K::Logger::Logg2(C_CLI, stream, "|-----------------------------------------------------------------------|");
1905                     K::Logger::Logg2(C_CLI, stream, "|                      Error type                      |     Number     |");
1906                     K::Logger::Logg2(C_CLI, stream, "|-----------------------------------------------------------------------|");
1907 
1908                     for (K3LUtil::ErrorCountType::iterator i = link0.begin(); i != link0.end(); i++)
1909                         K::Logger::Logg2(C_CLI, stream, FMT("| %52s | %-14d |") % i->first % i->second);
1910                 } break;
1911 
1912                 case Cli::CONCISE:
1913                 {
1914                     for (K3LUtil::ErrorCountType::iterator i = link0.begin(); i != link0.end(); i++)
1915                         K::Logger::Logg2(C_CLI, stream, FMT("%d:0:%s:%d") % device % i->first % i->second);
1916                 } break;
1917 
1918                 case Cli::XML:
1919                 {
1920                     /* device */
1921                     xdev = switch_xml_add_child_d(root,"device",0);
1922                     switch_xml_set_attr_d(xdev,"id",STR(FMT("%d") % device));
1923 
1924                     /* device/errors */
1925                     switch_xml_t xerrors = switch_xml_add_child_d(xdev,"errors",0);
1926 
1927                     /* device/errors/link (0) */
1928                     switch_xml_t xlinks0 = switch_xml_add_child_d(xerrors,"link",0);
1929                     switch_xml_set_attr_d(xlinks0,"id","0");
1930 
1931                     for (K3LUtil::ErrorCountType::iterator i = link0.begin(); i != link0.end(); i++)
1932                     {
1933                         /* device/errors/link/type */
1934                         switch_xml_t xtype0 = switch_xml_add_child_d(xlinks0,"type",0);
1935                         switch_xml_set_txt_d(xtype0,i->first.c_str());
1936 
1937                         /* device/errors/link/number */
1938                         switch_xml_t xnumber0  = switch_xml_add_child_d(xlinks0,"number",0);
1939                         switch_xml_set_txt_d(xnumber0,STR(FMT("%d") % i->second));
1940                     }
1941                 } break;
1942             }
1943 
1944             break;
1945         }
1946 
1947         case 0:
1948         {
1949             if (output_type != Cli::XML && output_type != Cli::CONCISE)
1950                 K::Logger::Logg2(C_CLI, stream, FMT("|                     No links detected on board %d!                     |") % device);
1951 
1952             break;
1953         }
1954     }
1955 }
1956 
execute(int argc,char * argv[])1957 bool Cli::_KhompShowLinks::execute(int argc, char *argv[])
1958 {
1959     if(argc < 2 || argc > 5)
1960     {
1961         printUsage(stream);
1962         return false;
1963     }
1964 
1965     unsigned int dev = UINT_MAX;
1966     int concise = 0, verbose = 0, as_xml = 0, errors = 0;
1967     OutputType output_type = Cli::VERBOSE;
1968 
1969     errors = ( (argc > 2) && (!strcasecmp(argv[2],"errors")) ? 1 : 0 );
1970 
1971     concise = ( (argc > (2+errors)) && (!strcasecmp(argv[(2+errors)],"concise")) ? 1 : 0 );
1972     verbose = ( (argc > (2+errors)) && (!strcasecmp(argv[(2+errors)],"verbose")) ? 1 : 0 );
1973     as_xml  = ( (argc > (2+errors)) && (!strcasecmp(argv[(2+errors)],"xml"))     ? 1 : 0 );
1974 
1975     if(argc > (2+errors+concise+verbose+as_xml))
1976     {
1977         dev = atoi(argv[(2+errors+concise+verbose+as_xml)]);
1978 
1979         if (!Globals::k3lapi.valid_device(dev))
1980         {
1981             K::Logger::Logg2(C_CLI, stream, "ERROR: no such device!");
1982             return false;
1983         }
1984     }
1985 
1986 
1987     if (!concise && !as_xml)
1988     {
1989         K::Logger::Logg2(C_CLI, stream, " ------------------------------------------------------------------------");
1990         if(!errors)
1991         {
1992             K::Logger::Logg2(C_CLI, stream, "|--------------------------- Khomp Links List ---------------------------|");
1993         }
1994         else
1995         {
1996             K::Logger::Logg2(C_CLI, stream, "|-------------------- Khomp Errors Counters on Links -------------------|");
1997         }
1998     }
1999 
2000     if(concise) output_type = Cli::CONCISE;
2001     if(as_xml)
2002     {
2003         output_type = Cli::XML;
2004         createRoot("links");
2005     }
2006 
2007     if (dev == UINT_MAX)
2008     {
2009         for (dev = 0; dev < Globals::k3lapi.device_count(); dev++)
2010         {
2011             if(!errors)
2012             {
2013                 showLinks (dev, output_type);
2014             }
2015             else
2016             {
2017                 showErrors(dev, output_type);
2018             }
2019         }
2020     }
2021     else
2022     {
2023         if(!errors)
2024         {
2025             showLinks (dev, output_type);
2026         }
2027         else
2028         {
2029             showErrors(dev, output_type);
2030         }
2031     }
2032 
2033     if (!concise && !as_xml)
2034     {
2035         K::Logger::Logg2(C_CLI, stream, " ------------------------------------------------------------------------");
2036     }
2037 
2038     if (as_xml)
2039     {
2040         printXMLOutput(stream);
2041         clearRoot();
2042     }
2043 
2044     return true;
2045 }
2046 
clearLink(unsigned int device,unsigned int link)2047 void Cli::_KhompClearLinks::clearLink(unsigned int device, unsigned int link)
2048 {
2049     try
2050     {
2051         Globals::k3lapi.command(device, link, CM_CLEAR_LINK_ERROR_COUNTER);
2052     }
2053     catch(K3LAPI::failed_command & e)
2054     {
2055         K::Logger::Logg2(C_CLI, stream,
2056                 FMT("ERROR: Command has failed with error '%s'")
2057                 % Verbose::status((KLibraryStatus)e.rc).c_str());
2058     }
2059 }
2060 
execute(int argc,char * argv[])2061 bool Cli::_KhompClearLinks::execute(int argc, char *argv[])
2062 {
2063     if(argc < 2 || argc > 4)
2064     {
2065         printUsage(stream);
2066         return false;
2067     }
2068 
2069     unsigned int dev = UINT_MAX;
2070     unsigned int obj = UINT_MAX;
2071 
2072     if(argc > 2)
2073     {
2074         dev = atoi(argv[2]);
2075 
2076         if (!Globals::k3lapi.valid_device(dev))
2077         {
2078             K::Logger::Logg2(C_CLI, stream,
2079                     FMT("ERROR: no such device %d!") % dev);
2080             return false;
2081         }
2082 
2083         if(argc > 3)
2084         {
2085             obj = atoi(argv[3]);
2086 
2087             if(!Globals::k3lapi.valid_link(dev, obj))
2088             {
2089                 K::Logger::Logg2(C_CLI, stream,
2090                       FMT("ERROR: No such link %d on device %d!") % obj % dev);
2091                 return false;
2092             }
2093         }
2094     }
2095 
2096     if(dev == UINT_MAX)
2097     {
2098         K::Logger::Logg2(C_CLI, stream,
2099                 "NOTICE: Reseting error count of all links...");
2100 
2101         for (unsigned int d = 0; d < Globals::k3lapi.device_count(); d++)
2102         {
2103             unsigned int link_count = Globals::k3lutil.physicalLinkCount(d, true);
2104 
2105             for (unsigned int o = 0; o < link_count; o++)
2106                 clearLink(d, o);
2107         }
2108     }
2109     else
2110     {
2111         if (obj == UINT_MAX)
2112         {
2113             K::Logger::Logg2(C_CLI, stream,
2114                 FMT("NOTICE: Reseting error count of all links on device %d...")
2115                 % dev);
2116             unsigned int link_count = Globals::k3lutil.physicalLinkCount(dev, true);
2117 
2118             for (unsigned int o = 0; o < link_count; o++)
2119                 clearLink(dev, o);
2120         }
2121         else
2122         {
2123             K::Logger::Logg2(C_CLI, stream,
2124                 FMT("NOTICE: Reseting error count of link %d on device %d...")
2125                 % obj % dev);
2126 
2127             clearLink(dev, obj);
2128         }
2129     }
2130 
2131     return true;
2132 }
2133 
execute(int argc,char * argv[])2134 bool Cli::_KhompClearStatistics::execute(int argc, char *argv[])
2135 {
2136     if(argc < 2 || argc > 4)
2137     {
2138         printUsage(stream);
2139         return false;
2140     }
2141 
2142     try
2143     {
2144 
2145     unsigned int dev = UINT_MAX;
2146     unsigned int obj = UINT_MAX;
2147 
2148     if(argc > 2)
2149     {
2150         dev = atoi(argv[2]);
2151 
2152         if (!Globals::k3lapi.valid_device(dev))
2153         {
2154             K::Logger::Logg2(C_CLI, stream,
2155                     FMT("ERROR: no such device %d!") % dev);
2156             return false;
2157         }
2158 
2159         if(argc > 3)
2160         {
2161             obj = atoi(argv[3]);
2162 
2163 
2164             if(!Globals::k3lapi.valid_channel(dev, obj))
2165             {
2166                 K::Logger::Logg2(C_CLI, stream,
2167                       FMT("ERROR: No such channel %d on device %d!") % obj % dev);
2168                 return false;
2169             }
2170         }
2171     }
2172 
2173     if(dev == UINT_MAX)
2174     {
2175         K::Logger::Logg2(C_CLI, stream, "NOTICE: Reseting statistics of all channels...");
2176 
2177         for (unsigned int d = 0; d < Globals::k3lapi.device_count(); d++)
2178         {
2179             for (unsigned int o = 0; o < Globals::k3lapi.channel_count(d); o++)
2180                 Board::get(d, o)->clearStatistics();
2181         }
2182     }
2183     else
2184     {
2185         if (obj == UINT_MAX)
2186         {
2187             K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: Reseting statistics of all channels from board %d...") % dev);
2188 
2189             for (unsigned int o = 0; o < Globals::k3lapi.channel_count(dev); o++)
2190                 Board::get(dev, o)->clearStatistics();
2191         }
2192         else
2193         {
2194             K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: Reseting statistics of channel %d from board %d") % obj % dev);
2195             Board::get(dev, obj)->clearStatistics();
2196         }
2197     }
2198 
2199     }
2200     catch (K3LAPITraits::invalid_channel & err)
2201     {
2202         K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % err.object % err.device );
2203         return false;
2204     }
2205 
2206     return true;
2207 }
2208 
execute(int argc,char * argv[])2209 bool Cli::_KhompDumpConfig::execute(int argc, char *argv[])
2210 {
2211     if (argc != 2)
2212     {
2213         printUsage(stream);
2214         return false;
2215     }
2216 
2217     const Config::StringSet opts = Globals::options.options();
2218 
2219     K::Logger::Logg2(C_CLI, stream, " ------------------------------------------------------------------------");
2220     K::Logger::Logg2(C_CLI, stream, "|--------------------------- Khomp Options Dump -------------------------|");
2221     K::Logger::Logg2(C_CLI, stream, "|------------------------------------------------------------------------|");
2222 
2223     for (Config::StringSet::const_iterator itr = opts.begin(); itr != opts.end(); ++itr)
2224     {   try
2225         {
2226             if(removeUnavaible((*itr))) continue;
2227             K::Logger::Logg2(C_CLI, stream, FMT("| %-24s => %42s |")
2228                     % (*itr) % Globals::options.get(&(Opt::_options), (*itr)));
2229         }
2230         catch(Config::EmptyValue &e)
2231         {
2232             K::Logger::Logg(C_ERROR, FMT("%s (%s)") % e.what() % (*itr));
2233         }
2234     }
2235 
2236     K::Logger::Logg2(C_CLI, stream, " ------------------------------------------------------------------------");
2237 
2238     return true;
2239 }
2240 
resetLink(unsigned int device,unsigned int link)2241 void Cli::_KhompResetLinks::resetLink(unsigned int device, unsigned int link)
2242 {
2243     try
2244     {
2245         Globals::k3lapi.command(device, link, CM_RESET_LINK);
2246     }
2247     catch(K3LAPI::failed_command & e)
2248     {
2249         K::Logger::Logg2(C_CLI, stream,
2250                 FMT("ERROR: Command has failed with error '%s'")
2251                 % Verbose::status((KLibraryStatus)e.rc).c_str());
2252     }
2253 }
2254 
execute(int argc,char * argv[])2255 bool Cli::_KhompResetLinks::execute(int argc, char *argv[])
2256 {
2257     if(argc < 2 || argc > 4)
2258     {
2259         printUsage(stream);
2260         return false;
2261     }
2262 
2263     unsigned int dev = UINT_MAX;
2264     unsigned int obj = UINT_MAX;
2265 
2266     if(argc > 2)
2267     {
2268         dev = atoi(argv[2]);
2269 
2270         if (!Globals::k3lapi.valid_device(dev))
2271         {
2272             K::Logger::Logg2(C_CLI, stream,
2273                     FMT("ERROR: no such device %d!") % dev);
2274             return false;
2275         }
2276 
2277         if(argc > 3)
2278         {
2279             obj = atoi(argv[3]);
2280 
2281             if(!Globals::k3lapi.valid_link(dev, obj))
2282             {
2283                 K::Logger::Logg2(C_CLI, stream,
2284                       FMT("ERROR: No such link %d on device %d!") % obj % dev);
2285                 return false;
2286             }
2287         }
2288     }
2289 
2290     if(dev == UINT_MAX)
2291     {
2292         K::Logger::Logg2(C_CLI, stream,
2293                 "NOTICE: Reseting all links...");
2294 
2295         for (unsigned int d = 0; d < Globals::k3lapi.device_count(); d++)
2296         {
2297             unsigned int link_count = Globals::k3lutil.physicalLinkCount(d, true);
2298 
2299             for (unsigned int o = 0; o < link_count; o++)
2300                 resetLink(d, o);
2301         }
2302     }
2303     else
2304     {
2305         if (obj == UINT_MAX)
2306         {
2307             K::Logger::Logg2(C_CLI, stream,
2308                 FMT("NOTICE: Reseting all links on device %d...")
2309                 % dev);
2310             unsigned int link_count = Globals::k3lutil.physicalLinkCount(dev, true);
2311 
2312             for (unsigned int o = 0; o < link_count; o++)
2313                 resetLink(dev, o);
2314         }
2315         else
2316         {
2317             K::Logger::Logg2(C_CLI, stream,
2318                 FMT("NOTICE: Reseting link %d on device %d...")
2319                 % obj % dev);
2320 
2321             resetLink(dev, obj);
2322         }
2323     }
2324 
2325     return true;
2326 }
2327 
execute(int argc,char * argv[])2328 bool Cli::_KhompSMS::execute(int argc, char *argv[])
2329 {
2330     if(argc < 4)
2331     {
2332         printUsage(stream);
2333         return false;
2334     }
2335 
2336     std::string devs(argv[1]);
2337     std::string numb(argv[2]);
2338     std::string mesg(argv[3]);
2339 
2340     for (unsigned int i = 4; i < (unsigned int)argc; i++)
2341     {
2342         mesg += " ";
2343         mesg += argv[i];
2344     }
2345 
2346     Board::KhompPvt * pvt = NULL;
2347 
2348     bool enable_retry = false;
2349 
2350     size_t pos = numb.find('r');
2351     if (pos != std::string::npos)
2352     {
2353         numb.erase(pos,1);
2354         enable_retry = true;
2355     }
2356 
2357     std::string begin;
2358 
2359     if(devs[0] != 'b' && devs[0] != 'B')
2360     {
2361         begin = "b";
2362     }
2363 
2364     std::string complete = begin + devs + "/" + numb + "/" + mesg;
2365     int cause = (int)SWITCH_CAUSE_NONE;
2366 
2367     try
2368     {
2369         for (unsigned int ntry = 0; ntry < 15; ++ntry)
2370         {
2371             ScopedAllocLock alloc_lock;
2372 
2373             pvt = processSMSString(complete.c_str(), &cause);
2374 
2375             /* NOTE: go directly to the pvt check below! */
2376             if (!enable_retry || pvt)
2377                 break;
2378 
2379             alloc_lock.unlock();
2380 
2381             K::Logger::Logg2(C_CLI, stream, FMT("WARNING: '%s': No available channel, trying again...") % devs);
2382             usleep(2500000);
2383         }
2384 
2385         if (!pvt)
2386         {
2387             K::Logger::Logg2(C_CLI, stream, FMT("ERROR: '%s': No available channel %s") % devs % (enable_retry ? "after 15 retries, giving up!" : ""));
2388             return false;
2389         }
2390 
2391         ScopedPvtLock lock(pvt);
2392 
2393         if(!pvt->application(SMS_SEND, NULL, complete.c_str()))
2394         {
2395             K::Logger::Logg2(C_CLI, stream, "ERROR: Message could not be sent");
2396             return false;
2397         }
2398 
2399     }
2400     catch(ScopedLockFailed & err)
2401     {
2402         if(err._fail == ScopedLockFailed::ALLOC_FAILED)
2403         {
2404             K::Logger::Logg2(C_CLI, stream, "ERROR: unable to global alloc lock");
2405         }
2406         else
2407         {
2408             K::Logger::Logg2(C_CLI, stream, FMT("ERROR: unable to lock: %s!") % err._msg.c_str());
2409         }
2410         return false;
2411     }
2412 
2413     K::Logger::Logg2(C_CLI, stream, "Message sent successfully!");
2414 
2415     return true;
2416 }
2417 
execute(int argc,char * argv[])2418 bool Cli::_KhompLogConsole::execute(int argc, char *argv[])
2419 {
2420     if (argc < 3)
2421     {
2422         printUsage(stream);
2423         return false;
2424     }
2425 
2426     bool invert = false;
2427     bool unique = false;
2428 
2429     std::string extra(argv[2]);
2430 
2431     unsigned int total_args = argc - 2; /* remove "khomp log console" */
2432 
2433     if (extra == "no")
2434     {
2435         invert = true;
2436         --total_args;
2437     }
2438     else if (extra == "just")
2439     {
2440         unique = true;
2441         --total_args;
2442     }
2443 
2444     unsigned int first_args = argc - total_args;
2445 
2446     std::string options;
2447 
2448     for (unsigned int i = first_args; i < (unsigned int)argc; i++)
2449     {
2450         options += argv[i];
2451         options += ",";
2452     }
2453 
2454     K::Logger::processLogConsole(stream, options, invert, unique);
2455     return true;
2456 }
2457 
execute(int argc,char * argv[])2458 bool Cli::_KhompLogDisk::execute(int argc, char *argv[])
2459 {
2460     if (argc < 3)
2461     {
2462         printUsage(stream);
2463         return false;
2464     }
2465 
2466     bool invert = false;
2467     bool unique = false;
2468 
2469     std::string extra(argv[2]);
2470 
2471     unsigned int total_args = argc - 2; /* remove "khomp log disk" */
2472 
2473     if (extra == "no")
2474     {
2475         invert = true;
2476         --total_args;
2477     }
2478     else if (extra == "just")
2479     {
2480         unique = true;
2481         --total_args;
2482     }
2483 
2484     unsigned int first_args = argc - total_args;
2485 
2486     std::string options;
2487 
2488     for (unsigned int i = first_args; i < (unsigned int)argc; i++)
2489     {
2490         options += argv[i];
2491         options += ",";
2492     }
2493 
2494     K::Logger::processLogDisk(stream, options, invert, unique);
2495     return true;
2496 }
2497 
execute(int argc,char * argv[])2498 bool Cli::_KhompLogStatus::execute(int argc, char *argv[])
2499 {
2500     if(argc != 2)
2501     {
2502         printUsage(stream);
2503         return false;
2504     }
2505 
2506     Strings::Merger m1;
2507 
2508     bool flag1_errors   = K::Logger::Logg.classe(C_ERROR).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2509     bool flag1_warnings = K::Logger::Logg.classe(C_WARNING).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2510     bool flag1_messages = K::Logger::Logg.classe(C_MESSAGE).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2511     bool flag1_events   = K::Logger::Logg.classe(C_EVENT).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2512     bool flag1_commands = K::Logger::Logg.classe(C_COMMAND).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2513     bool flag1_audio    = K::Logger::Logg.classe(C_AUDIO_EV).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2514     bool flag1_modem    = K::Logger::Logg.classe(C_MODEM_EV).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2515     bool flag1_links    = K::Logger::Logg.classe(C_LINK_STT).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2516     bool flag1_cas      = K::Logger::Logg.classe(C_CAS_MSGS).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2517 
2518     if (flag1_errors)   m1.add("errors");
2519     if (flag1_warnings) m1.add("warnings");
2520     if (flag1_messages) m1.add("messages");
2521     if (flag1_events)   m1.add("events");
2522     if (flag1_commands) m1.add("commands");
2523     if (flag1_audio)    m1.add("audio");
2524     if (flag1_modem)    m1.add("modem");
2525     if (flag1_links)    m1.add("link");
2526     if (flag1_cas)      m1.add("cas");
2527 
2528     K::Logger::Logg2(C_CLI, stream, "             ");
2529 
2530     if (!m1.empty()) K::Logger::Logg2(C_CLI, stream, FMT("Enabled console messages: %s.") % m1.merge(", "));
2531     else /* ----- */ K::Logger::Logg2(C_CLI, stream, "There are no console messages enabled.");
2532 
2533     bool flag2_errors    = K::Logger::Logg.classe(C_ERROR).get(O_GENERIC, K::LogManager::Option::ENABLED);
2534     bool flag2_warnings  = K::Logger::Logg.classe(C_WARNING).get(O_GENERIC, K::LogManager::Option::ENABLED);
2535     bool flag2_messages  = K::Logger::Logg.classe(C_MESSAGE).get(O_GENERIC, K::LogManager::Option::ENABLED);
2536     bool flag2_events    = K::Logger::Logg.classe(C_EVENT).get(O_GENERIC, K::LogManager::Option::ENABLED);
2537     bool flag2_commands  = K::Logger::Logg.classe(C_COMMAND).get(O_GENERIC, K::LogManager::Option::ENABLED);
2538     bool flag2_audio     = K::Logger::Logg.classe(C_AUDIO_EV).get(O_GENERIC, K::LogManager::Option::ENABLED);
2539     bool flag2_modem     = K::Logger::Logg.classe(C_MODEM_EV).get(O_GENERIC, K::LogManager::Option::ENABLED);
2540     bool flag2_links     = K::Logger::Logg.classe(C_LINK_STT).get(O_GENERIC, K::LogManager::Option::ENABLED);
2541     bool flag2_cas       = K::Logger::Logg.classe(C_CAS_MSGS).get(O_GENERIC, K::LogManager::Option::ENABLED);
2542     bool flag2_functions = K::Logger::Logg.classe(C_DBG_FUNC).enabled();
2543     bool flag2_threads   = K::Logger::Logg.classe(C_DBG_THRD).enabled();
2544     bool flag2_locks     = K::Logger::Logg.classe(C_DBG_LOCK).enabled();
2545     bool flag2_streams   = K::Logger::Logg.classe(C_DBG_STRM).enabled();
2546 
2547     Strings::Merger m2;
2548 
2549     if (flag2_errors)    m2.add("errors");
2550     if (flag2_warnings)  m2.add("warnings");
2551     if (flag2_messages)  m2.add("messages");
2552     if (flag2_events)    m2.add("events");
2553     if (flag2_commands)  m2.add("commands");
2554     if (flag2_audio)     m2.add("audio");
2555     if (flag2_modem)     m2.add("modem");
2556     if (flag2_links)     m2.add("link");
2557     if (flag2_cas)       m2.add("cas");
2558     if (flag2_functions) m2.add("functions");
2559     if (flag2_threads)   m2.add("threads");
2560     if (flag2_locks)     m2.add("locks");
2561     if (flag2_streams)   m2.add("streams");
2562 
2563     if (!m2.empty()) K::Logger::Logg2(C_CLI, stream, FMT("Enabled log-on-disk messages: %s.") % m2.merge(", "));
2564     else /* ----- */ K::Logger::Logg2(C_CLI, stream, "There are no log-on-disk messages enabled.");
2565 
2566     if (Globals::flag_trace_rdsi) K::Logger::Logg2(C_CLI, stream, "The ISDN (RDSI) low-level tracing is enabled.");
2567 
2568     K::Logger::Logg2(C_CLI, stream, "             ");
2569 
2570     return true;
2571 }
2572 
execute(int argc,char * argv[])2573 bool Cli::_KhompLogRotate::execute(int argc, char *argv[])
2574 {
2575     if (argc != 2)
2576     {
2577         printUsage(stream);
2578         return false;
2579     }
2580 
2581     if (!K::Logger::rotate())
2582     {
2583         return false;
2584     }
2585 
2586     return true;
2587 }
2588 
execute(int argc,char * argv[])2589 bool Cli::_KhompLogTraceK3L::execute(int argc, char *argv[])
2590 {
2591     if (argc != 4)
2592     {
2593         printUsage(stream);
2594         return false;
2595     }
2596 
2597     std::string str_on("on");
2598     std::string str_off("off");
2599 
2600     bool value = false;
2601 
2602          if (str_on  == argv[3]) value = true;
2603     else if (str_off == argv[3]) value = false;
2604     else
2605     {
2606         K::Logger::Logg2(C_CLI, stream, "ERROR: Please use 'on' or 'off' to enable or disable.");
2607         return false;
2608     }
2609 
2610     K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: %sbling k3l debug messages.") % (value ? "Ena" : "Disa"));
2611 
2612     Logfile logfile;
2613 
2614     K::LogConfig::set(logfile, "K3L", "Value",        value);
2615     K::LogConfig::set(logfile, "K3L", "CallProgress", value);
2616     K::LogConfig::set(logfile, "K3L", "CallAnalyzer", value);
2617     K::LogConfig::set(logfile, "K3L", "CadenceRecog", value);
2618     K::LogConfig::set(logfile, "K3L", "CallControl",  value);
2619     K::LogConfig::set(logfile, "K3L", "Fax",          value);
2620 
2621     if (K::LogConfig::commit(logfile))
2622     {
2623         try
2624         {
2625             Globals::k3lapi.command(-1, -1, CM_LOG_UPDATE);
2626         }
2627         catch(...)
2628         {
2629             LOG(ERROR,"Error while send command CM_LOG_UPDATE");
2630         }
2631     }
2632 
2633     return true;
2634 }
2635 
execute(int argc,char * argv[])2636 bool Cli::_KhompLogTraceISDN::execute(int argc, char *argv[])
2637 {
2638     if (argc < 4)
2639     {
2640         printUsage(stream);
2641         return false;
2642     }
2643 
2644     bool active = true;
2645 
2646     bool change_lapd = false;
2647     bool change_q931 = false;
2648 
2649     std::string what;
2650 
2651     for (unsigned int i = 3; i < (unsigned int)argc; i++)
2652     {
2653         what += argv[i];
2654         what += ",";
2655     }
2656 
2657     Strings::vector_type values;
2658     Strings::tokenize(what, values, ",");
2659 
2660     for (Strings::vector_type::iterator i = values.begin(); i != values.end(); i++)
2661     {
2662         if ((*i) == "q931") change_q931 = true;
2663         if ((*i) == "lapd") change_lapd = true;
2664         if ((*i) == "off")  active = false;
2665     }
2666 
2667     Logfile logfile;
2668 
2669     K::LogConfig::set(logfile, "ISDN", "Value", active);
2670 
2671     if (change_lapd || !active)
2672         K::LogConfig::set(logfile, "ISDN", "Lapd", active);
2673 
2674     if (change_q931 || !active)
2675         K::LogConfig::set(logfile, "ISDN", "Q931", active);
2676 
2677     if (K::LogConfig::commit(logfile))
2678     {
2679         try
2680         {
2681             Globals::k3lapi.command(-1, -1, CM_LOG_UPDATE);
2682 
2683             if (active)
2684             {
2685                 K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: Activating the following ISDN debug option(s): %s") % what);
2686                 Globals::flag_trace_rdsi = true;
2687             }
2688             else
2689             {
2690                 K::Logger::Logg2(C_CLI, stream, "NOTICE: Deactivating ISDN debug options");
2691                 Globals::flag_trace_rdsi = false;
2692             }
2693         }
2694         catch(...)
2695         {
2696             if (active)
2697                 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to activate the following ISDN debug option(s): %s") % what);
2698             else
2699                 K::Logger::Logg2(C_CLI, stream, "ERROR: Unable to deactivate ISDN debug options");
2700         }
2701 
2702         return false;
2703     }
2704 
2705     return true;
2706 }
2707 
execute(int argc,char * argv[])2708 bool Cli::_KhompLogTraceR2::execute(int argc, char *argv[])
2709 {
2710     if (argc != 4)
2711     {
2712         printUsage(stream);
2713         return false;
2714     }
2715 
2716     try
2717     {
2718         std::string str_off("off");
2719         std::string str_on("on" );
2720 
2721         bool enable = false;
2722 
2723         if (str_on   == argv[3]) enable = true;
2724         else if (str_off  == argv[3]) enable = false;
2725 
2726         if (enable)
2727         {
2728             K::Logger::Logg2(C_CLI, stream, "NOTICE: All channels of all devices will be monitored!" );
2729         }
2730         else
2731         {
2732             K::Logger::Logg2(C_CLI, stream, "NOTICE: Deactivating R2 debug options" );
2733         }
2734 
2735         Logfile logfile;
2736 
2737         K::LogConfig::set(logfile, "R2", "Value",     enable);
2738         K::LogConfig::set(logfile, "R2", "Signaling", enable);
2739         K::LogConfig::set(logfile, "R2", "States",    enable);
2740 
2741         if (K::LogConfig::commit(logfile))
2742         {
2743             try
2744             {
2745                 Globals::k3lapi.command(-1, -1, CM_LOG_UPDATE);
2746             }
2747             catch(...)
2748             {
2749                 LOG(ERROR,"Error while send command CM_LOG_UPDATE");
2750             }
2751         }
2752     }
2753     catch (Strings::invalid_value e)
2754     {
2755         K::Logger::Logg2(C_CLI, stream, "ERROR: Invalid numeric value in arguments.");
2756         return false;
2757     }
2758 
2759     return true;
2760 }
2761 
execute(int argc,char * argv[])2762 bool Cli::_KhompGet::execute(int argc, char *argv[])
2763 {
2764     if (argc < 2)
2765     {
2766         printUsage(stream);
2767         return false;
2768     }
2769 
2770     std::string arg(argv[1]);
2771 
2772     try
2773     {
2774        std::string res = Globals::options.get(&Opt::_options, (const char*) argv[1]);
2775        K::Logger::Logg2(C_CLI, stream, FMT("Result for command %s is %s.") % std::string(argv[1]) % res);
2776     }catch(Config::Failure &e){
2777        K::Logger::Logg2(C_CLI, stream, e.what());
2778     }
2779 
2780     return true;
2781 }
2782 
execute(int argc,char * argv[])2783 bool Cli::_KhompSet::execute(int argc, char *argv[])
2784 {
2785     if (argc < 3)
2786     {
2787         printUsage(stream);
2788         return false;
2789     }
2790 
2791     std::string args;
2792 
2793     const unsigned int first = 2;
2794 
2795     for (unsigned int i = first; i < (unsigned int)argc; i++)
2796     {
2797         if (i != first) { args += " "; }
2798 
2799         args += argv[i];
2800     }
2801 
2802     try
2803     {
2804         Globals::options.process(&Opt::_options, (const char *) argv[1], (const char *) args.c_str());
2805         const Config::Options::Messages msgs = Globals::options.commit(&Opt::_options, (const char *)argv[1]);
2806 
2807         for (Config::Options::Messages::const_iterator i = msgs.begin(); i != msgs.end(); ++i)
2808         {
2809             K::Logger::Logg2(C_ERROR, stream, FMT("%s.") % (*i));
2810         }
2811 
2812         K::Logger::Logg2(C_CLI, stream, FMT("Setting %s for value %s") % argv[1] % argv[2]);
2813     }
2814     catch (Config::Failure &e)
2815     {
2816         K::Logger::Logg2(C_ERROR,stream, FMT("config processing error: %s.") % e.what());
2817     }
2818 
2819     return true;
2820 }
2821 
execute(int argc,char * argv[])2822 bool Cli::_KhompRevision::execute(int argc, char *argv[])
2823 {
2824 #ifndef MOD_KHOMP_VERSION
2825 #define MOD_KHOMP_VERSION "unknown"
2826 #endif
2827 
2828 #ifndef SWITCH_VERSION_FULL
2829 #define SWITCH_VERSION_FULL "unknown"
2830 #endif
2831 
2832     std::string khomp_endpoint_rev(MOD_KHOMP_VERSION);
2833     std::string freeswitch_rev(SWITCH_VERSION_FULL);
2834 
2835     K::Logger::Logg2(C_CLI, stream, FMT("Khomp Endpoint - %s") % khomp_endpoint_rev);
2836     K::Logger::Logg2(C_CLI, stream, FMT("FreeSWITCH - %s") % freeswitch_rev);
2837     return true;
2838 }
2839 
execute(int argc,char * argv[])2840 bool Cli::_KhompSendCommand::execute(int argc, char *argv[])
2841 {
2842     if (argc < 5 || argc > 6)
2843     {
2844         printUsage(stream);
2845         return false;
2846     }
2847 
2848     unsigned int dev = atoi (argv[2]);
2849 
2850     if (dev >= Globals::k3lapi.device_count())
2851     {
2852         K::Logger::Logg2(C_CLI, stream, FMT("ERROR: No such device: %d!") % dev);
2853         return false;
2854     }
2855 
2856     unsigned int num = atoi (argv[4]);
2857 
2858     if (num >= 256)
2859     {
2860         K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Invalid command number: %d!") % num);
2861         return false;
2862     }
2863 
2864     unsigned int obj = atoi (argv[3]);
2865 
2866     try
2867     {
2868         switch (argc)
2869         {
2870             case 5:    Globals::k3lapi.command(dev,obj, num);         break;
2871             case 6:    Globals::k3lapi.command(dev,obj, num,argv[5]); break;
2872             default:   /*               what-a-hell ?!             */ break;
2873         }
2874     }
2875     catch(K3LAPI::failed_command &e)
2876     {
2877         if (K::Logger::Logg.classe(C_WARNING).enabled())
2878         {
2879             LOG(WARNING, FMT("Command '%s' has failed with error '%s'.")
2880                 % Verbose::commandName(e.code) % Verbose::status((KLibraryStatus)e.rc));
2881         }
2882 
2883         return false;
2884     }
2885 
2886     return true;
2887 }
2888 
execute(int argc,char * argv[])2889 bool Cli::_KhompSendRawCommand::execute(int argc, char *argv[])
2890 {
2891     if (argc < 6)
2892     {
2893         printUsage(stream);
2894         return false;
2895     }
2896 
2897     unsigned int dev = atoi (argv[3]);
2898 
2899     if (dev >= Globals::k3lapi.device_count())
2900     {
2901         K::Logger::Logg2(C_CLI, stream, FMT("ERROR: No such device: %d!") % dev);
2902         return false;
2903     }
2904 
2905     unsigned int dsp = atoi (argv[4]);
2906 
2907     if (dsp >= 2)
2908     {
2909         K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Invalid DSP number: %d!") % dsp);
2910         return false;
2911     }
2912 
2913     const unsigned int base = 5;
2914     char commands[(argc - base)];
2915 
2916     for (int i = base, j = 0; i < argc; i++, j++)
2917     {
2918         if (sscanf(argv[i], "%hhx", &(commands[j])) != 1)
2919         {
2920             K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Invalid hexadecimal sequence: '%s'!") % argv[i]);
2921             return false;
2922         }
2923     }
2924 
2925     try
2926     {
2927         Globals::k3lapi.raw_command(dev, dsp, commands, (argc - base));
2928     }
2929     catch(K3LAPI::failed_raw_command &e)
2930     {
2931         if (K::Logger::Logg.classe(C_WARNING).enabled())
2932         {
2933             LOG(WARNING, FMT("(dev=%d,dsp=%d): Raw command '%s' has failed with error '%s'.")
2934             % e.dev
2935             % e.dsp
2936             % Strings::hexadecimal(std::string((char*) commands,(argc - base)))
2937             % Verbose::status((KLibraryStatus)e.rc));
2938         }
2939 
2940         return false;
2941     }
2942 
2943    return true;
2944 }
2945 
execute(int argc,char * argv[])2946 bool Cli::_KhompSelectSim::execute(int argc, char *argv[])
2947 {
2948     if(argc != 5)
2949     {
2950         printUsage(stream);
2951         return false;
2952     }
2953 
2954     std::string dev_str(argv[2]);
2955     std::string obj_str(argv[3]);
2956     std::string num_str(argv[4]);
2957 
2958     try
2959     {
2960         unsigned int dev = Strings::tolong(dev_str);
2961         unsigned int obj = Strings::tolong(obj_str);
2962 
2963         if (!Globals::k3lapi.valid_device(dev))
2964         {
2965             K::Logger::Logg2(C_CLI, stream,
2966                     FMT("ERROR: no such device %d!") % dev);
2967             return false;
2968         }
2969 
2970         if (!Globals::k3lapi.valid_channel(dev, obj))
2971         {
2972             K::Logger::Logg2(C_CLI, stream,
2973                     FMT("ERROR: No such channel %d on device %d!") % obj % dev);
2974             return false;
2975         }
2976 
2977         /* just check for validity */
2978         (void)Strings::tolong(num_str);
2979 
2980 
2981         if(!Board::get(dev, obj)->application(SELECT_SIM_CARD, NULL, num_str.c_str()))
2982         {
2983             K::Logger::Logg2(C_CLI, stream, "ERROR: Unable to select sim card");
2984             return false;
2985         }
2986     }
2987     catch (Strings::invalid_value & e)
2988     {
2989         K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Invalid number '%s'!") % e.value());
2990         return false;
2991     }
2992     catch (K3LAPITraits::invalid_channel & err)
2993     {
2994         K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % err.object % err.device );
2995         return false;
2996     }
2997     catch(...)
2998     {
2999         K::Logger::Logg2(C_CLI, stream, "ERROR: Unable to select sim card");
3000         return false;
3001     }
3002 
3003     return true;
3004 }
3005 
execute(int argc,char * argv[])3006 bool Cli::_KhompKommuterOnOff::execute(int argc, char *argv[])
3007 {
3008     if(argc != 2)
3009     {
3010         printUsage(stream);
3011         return false;
3012     }
3013 
3014     switch (Board::kommuter._kommuter_count)
3015     {
3016         case -1: K::Logger::Logg2(C_CLI, stream, "ERROR: libkwd.so required for kommuter could not be found." ); return false;
3017         case 0:  K::Logger::Logg2(C_CLI, stream, "ERROR: none Kommuter was found on the system." );              return false;
3018     }
3019 
3020     if (Opt::_options._kommuter_activation() == "auto")
3021     {
3022         K::Logger::Logg2(C_CLI, stream, "ERROR: Kommuter is set to be started automatically by kommuter-activation configuration.");
3023         return false;
3024     }
3025 
3026     bool on_off = ARG_CMP(1, "on") ? true : false;
3027 
3028     int ret = 0;
3029     if (on_off)
3030     {
3031         int timeout = Opt::_options._kommuter_timeout();
3032         K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: Activating Kommuters with timeout of %d seconds .") % timeout);
3033         bool start_timer = false;
3034 
3035         std::string param= STG(FMT("timeout=%d") % timeout);
3036 
3037         for (int kommuter = 0; kommuter < Board::kommuter._kommuter_count; kommuter++)
3038         {
3039             try
3040             {
3041                 Globals::k3lapi.command(-1, kommuter, CM_START_WATCHDOG, (char*) param.c_str());
3042                 start_timer = true;
3043             }
3044             catch(K3LAPI::failed_command & e)
3045             {
3046                 switch(e.rc)
3047                 {
3048                 case ksInvalidParams:
3049                     K::Logger::Logg2(C_CLI,stream,FMT("ERROR: invalid timeout '%d' for Kommuter device '%d' timeout. Mininum is 0, maximum is 255.")
3050                 % timeout % kommuter);
3051                     break;
3052                 default:
3053                     K::Logger::Logg2(C_CLI,stream,FMT("ERROR: could not start the kommuter device number '%d'.") % kommuter);
3054                     break;
3055                 }
3056             }
3057             catch(...)
3058             {
3059                 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: could not start the Kommuter device number '%d'.") % kommuter);
3060             }
3061         }
3062 
3063         if (timeout == 0)
3064         {
3065             DBG(FUNC, D("kommuter watchdog timer not created because timeout is 0."));
3066             return false;
3067         }
3068 
3069         if (start_timer)
3070         {
3071             if (!Globals::global_timer)
3072             {
3073                 K::Logger::Logg2(C_CLI, stream , "Error creating the timer for kommuter.");
3074                 return true;
3075             }
3076             else if (Board::kommuter._kwtd_timer_on)
3077             {
3078                 Globals::global_timer->restart( Board::kommuter._kwtd_timer_index, true );
3079                 DBG(FUNC, D("kommuter watchdog timer restarted."));
3080             }
3081             else
3082             {
3083                 Board::kommuter._kwtd_timer_index = Globals::global_timer->add(((timeout < 5) ? (timeout*500) : 2000), &Kommuter::wtdKickTimer);
3084                 Board::kommuter._kwtd_timer_on = true;
3085                 DBG(FUNC, D("kommuter watchdog timer created and started."));
3086             }
3087         }
3088     }
3089     else
3090     {
3091         K::Logger::Logg2(C_CLI, stream, "NOTICE: Deactivating Kommuters.");
3092 
3093         if (Board::kommuter._kwtd_timer_on)
3094         {
3095             Globals::global_timer->del( Board::kommuter._kwtd_timer_index);
3096             Board::kommuter._kwtd_timer_on = false;
3097         }
3098 
3099         for(int kommuter = 0; kommuter < Board::kommuter._kommuter_count; kommuter++)
3100         {
3101             try
3102             {
3103                 Globals::k3lapi.command(-1, kommuter, CM_STOP_WATCHDOG);
3104                 return true;
3105             }
3106             catch(K3LAPI::failed_command & e)
3107             {
3108                 K::Logger::Logg2(C_CLI,stream,FMT("ERROR: Kommuter device '%d' was not initialized.") % kommuter);
3109             }
3110             catch(...)
3111             {
3112                 K::Logger::Logg2(C_CLI, stream,FMT("ERROR: could not disable kommuter device '%d' for some unknow reason.") % kommuter);
3113             }
3114         }
3115     }
3116 
3117     return false;
3118 }
3119 
execute(int argc,char * argv[])3120 bool Cli::_KhompKommuterCount::execute(int argc, char *argv[])
3121 {
3122     if(argc != 2)
3123     {
3124         printUsage(stream);
3125         return false;
3126     }
3127 
3128     if(Board::kommuter._kommuter_count == -1)
3129     {
3130         K::Logger::Logg2(C_CLI, stream,
3131                 "ERROR: libkwd.so required for kommuter could not be found." );
3132         return false;
3133     }
3134 
3135     K::Logger::Logg2(C_CLI, stream,
3136             FMT("Kommuter devices detected = [%d]")
3137             % Board::kommuter._kommuter_count);
3138 
3139     return true;
3140 }
3141 
3142