Initialize Tizen 2.3
[framework/system/deviced.git] / src / usb / usb-client-xml.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <vconf.h>
20 #include <stdbool.h>
21 #include <stdlib.h>
22 #include <libxml/parser.h>
23 #include "core/log.h"
24 #include "core/list.h"
25 #include "usb-client.h"
26
27 #define BUF_MAX 256
28
29 #define DEFAULT_IPRODUCT_NAME "TIZEN"
30
31 #define CONF_PATH                "/usr/share/deviced/usb-configurations"
32 #define SUPPORTED_CONF_PATH      CONF_PATH"/conf-supported.xml"
33 #define USB_CONFIGURATIONS_PATH  CONF_PATH"/usb-configurations.xml"
34
35 #define USB_CON_SET             "set"
36 #define USB_CON_UNSET           "unset"
37
38 #define NODE_NAME_TEXT          "text"
39 #define NODE_NAME_COMMENT       "comment"
40 #define NODE_NAME_CONFIG_NODES  "config-nodes"
41 #define NODE_NAME_CONFIG_files  "config-files"
42 #define NODE_NAME_USB_CONFIG    "usb-config"
43 #define NODE_NAME_CONF_FILE     "conf-file"
44 #define NODE_NAME_USB_CONFS     "usb-configurations"
45 #define NODE_NAME_USB_OPERS     "usb-operations"
46 #define NODE_NAME_DRIVER        "driver"
47 #define NODE_NAME_USB_DRV       "usb-drv"
48 #define NODE_NAME_MODE          "mode"
49 #define NODE_NAME_ACTION        "action"
50 #define NODE_NAME_IPRODUCT      "iProduct"
51 #define ATTR_VALUE              "value"
52 #define ATTR_VERSION            "ver"
53 #define ATTR_BACKGROUND         "background"
54
55 static dd_list *supported_list;  /* Supported Configurations */
56 static dd_list *oper_list;       /* Operations for USB mode */
57 static dd_list *conf_list;       /* Configurations for usb mode */
58 static char *driver;             /* usb driver version (ex. 1.0, 1.1, none, ... ) */
59
60 int get_operations_list(dd_list **list)
61 {
62         if (!list)
63                 return -EINVAL;
64
65         *list = oper_list;
66         return 0;
67 }
68
69 int get_configurations_list(dd_list **list)
70 {
71         if (!list)
72                 return -EINVAL;
73
74         *list = conf_list;
75         return 0;
76 }
77
78 #ifdef USB_DEBUG
79 static void show_supported_confs_list(void)
80 {
81         int i;
82         dd_list *l;
83         struct xmlSupported *sp;
84         void *mode;
85
86         if (!supported_list) {
87                 _D("Supported Confs list is empty");
88                 return;
89         }
90
91         _D("********************************");
92         _D("** Supported Confs list");
93         _D("********************************");
94
95         DD_LIST_FOREACH(supported_list, l, sp) {
96                 _D("** Mode      : %d", sp->mode);
97                 _D("********************************");
98         }
99 }
100
101 static void show_operation_list(void)
102 {
103         int i;
104         dd_list *l;
105         struct xmlOperation *oper;
106
107         _D("********************************");
108         _D("** Operation list");
109         _D("********************************");
110         if (!oper_list) {
111                 _D("Operation list is empty");
112                 _D("********************************");
113                 return;
114         }
115
116         i = 0;
117         DD_LIST_FOREACH(oper_list, l, oper) {
118                 _D("** Number    : %d", i++);
119                 _D("** Name      : %s", oper->name);
120                 _D("** Operation : %s", oper->oper);
121                 _D("** Background: %d", oper->background);
122                 _D("********************************");
123         }
124 }
125
126 static void show_configuration_list(void)
127 {
128         int i;
129         dd_list *l;
130         struct xmlConfiguration *conf;
131
132         if (!conf_list) {
133                 _D("Configuration list is empty");
134                 return;
135         }
136
137         _D("********************************");
138         _D("** Configuration list");
139         _D("********************************");
140
141         i = 0;
142         DD_LIST_FOREACH(conf_list, l, conf) {
143                 _D("** Number: %d", i++);
144                 _D("** Name  : %s", conf->name);
145                 _D("** Path  : %s", conf->path);
146                 _D("** Value : %s", conf->value);
147                 _D("********************************");
148         }
149 }
150 #else
151 #define show_supported_confs_list() do {} while(0)
152 #define show_operation_list() do {} while(0)
153 #define show_configuration_list() do {} while(0)
154 #endif
155
156 static xmlDocPtr xml_open(const char *xml)
157 {
158         if (!xml)
159                 return NULL;
160
161         return xmlReadFile(xml, NULL, 0);
162 }
163
164 static void xml_close(xmlDocPtr doc)
165 {
166         xmlFreeDoc(doc);
167 }
168
169 static bool skip_node(xmlNodePtr node)
170 {
171         if (!node)
172                 return true;
173
174         if (!xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_TEXT))
175                 return true;
176         if (!xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_COMMENT))
177                 return true;
178
179         return false;
180 }
181
182 static int get_xml_property(xmlNodePtr node, char *property, char *value, int len)
183 {
184         xmlChar *xmlprop;
185
186         xmlprop = xmlGetProp(node, (const xmlChar *)property);
187         if (!xmlprop)
188                 return -ENOMEM;
189
190         snprintf(value, len, "%s", (char *)xmlprop);
191         xmlFree(xmlprop);
192
193         return 0;
194 }
195
196 static bool is_usb_mode_supported(int usb_mode)
197 {
198         dd_list *l;
199         struct xmlSupported *sp;
200
201         DD_LIST_FOREACH(supported_list, l, sp) {
202                 if (sp->mode == usb_mode)
203                         return true;
204         }
205
206         return false;
207 }
208
209 static int get_iproduct_name(char *name, int size)
210 {
211         if (!name)
212                 return -EINVAL;
213
214         /* TODO: Product name should be set using device model
215          * ex) TIZEN_SM-Z9005 */
216
217         snprintf(name, size, "%s", DEFAULT_IPRODUCT_NAME);
218         return 0;
219 }
220
221 static int get_driver_version(xmlNodePtr root)
222 {
223         int ret;
224         xmlNodePtr node;
225         FILE *fp;
226         char buf[BUF_MAX];
227         char path[BUF_MAX];
228
229         if (!root)
230                 return -EINVAL;
231
232         for (node = root->children ; node ; node = node->next) {
233                 if (skip_node(node))
234                         continue;
235
236                 if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_DRIVER))
237                         continue;
238
239                 ret = get_xml_property(node, ATTR_VALUE, path, sizeof(path));
240                 if (ret < 0) {
241                         _E("Failed to get property(%d)", ret);
242                         return ret;
243                 }
244
245                 if (access(path, F_OK) != 0) {
246                         /* TODO: If the path does not exist,
247                          * usb gadgets are not from Galaxy, but from Linux Kernel */
248                         driver = NULL;
249                         return 0;
250                 }
251
252                 fp = fopen(path, "r");
253                 if (!fp) {
254                         _E("fopen() failed(%s)", path);
255                         return -ENOMEM;
256                 }
257
258                 if (!fgets(buf, sizeof(buf), fp)) {
259                         _E("fgets() failed");
260                         fclose(fp);
261                         return -ENOMEM;
262                 }
263
264                 fclose(fp);
265
266                 driver = strdup(buf);
267                 break;
268         }
269         return 0;
270 }
271
272 /* Getting sysfs nodes to set usb configurations */
273 static int add_conf_nodes_to_list(xmlNodePtr root)
274 {
275         int ret;
276         xmlNodePtr node;
277         struct xmlConfiguration *conf;
278         char path[BUF_MAX];
279
280         if (!root)
281                 return -EINVAL;
282
283         for (node = root->children ; node ; node = node->next) {
284                 if (skip_node(node))
285                         continue;
286
287                 ret = get_xml_property(node, ATTR_VALUE, path, sizeof(path));
288                 if (ret < 0) {
289                         _E("Failed to get property(%d)", ret);
290                         return ret;
291                 }
292
293                 conf = (struct xmlConfiguration *)malloc(sizeof(struct xmlConfiguration));
294                 if (!conf) {
295                         _E("malloc() failed");
296                         return -ENOMEM;
297                 }
298
299                 conf->name = strdup((const char *)(node->name));
300                 conf->path = strdup(path);
301                 conf->value = NULL;
302
303                 if (!(conf->name) || !(conf->path)) {
304                         _E("strdup() failed");
305                         if (conf->name)
306                                 free(conf->name);
307                         if (conf->path)
308                                 free(conf->path);
309                         free(conf);
310                         continue;
311                 }
312
313                 DD_LIST_APPEND(conf_list, conf);
314         }
315
316         return 0;
317 }
318
319 static int get_configuration_nodes(xmlNodePtr root)
320 {
321         int ret;
322         xmlNodePtr node;
323         char ver[BUF_MAX];
324
325         if (!root)
326                 return -EINVAL;
327
328         for (node = root->children ; node ; node = node->next) {
329                 if (skip_node(node))
330                         continue;
331
332                 if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_USB_DRV))
333                         continue;
334
335                 ret = get_xml_property(node, ATTR_VERSION, ver, sizeof(ver));
336                 if (ret < 0) {
337                         _E("Failed to get property(%d)", ret);
338                         return ret;
339                 }
340
341                 if (strncmp(ver, driver, strlen(ver)))
342                         continue;
343
344                 return add_conf_nodes_to_list(node);
345         }
346
347         return -ENOMEM;
348 }
349
350 int make_empty_configuration_list(void)
351 {
352         int ret;
353         xmlDocPtr doc;
354         xmlNodePtr root;
355         xmlNodePtr node;
356
357         doc = xml_open(USB_CONFIGURATIONS_PATH);
358         if (!doc) {
359                 _E("fail to open xml file (%s)", USB_CONFIGURATIONS_PATH);
360                 return -ENOMEM;
361         }
362
363         root = xmlDocGetRootElement(doc);
364         if (!root) {
365                 _E("FAIL: xmlDocGetRootElement()");
366                 ret = -ENOMEM;
367                 goto out;
368         }
369
370         for (node = root->children ; node ; node = node->next) {
371                 if (skip_node(node))
372                         continue;
373
374                 if (!xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_CONFIG_NODES)) {
375                         ret = get_driver_version(node);
376                         if (ret < 0) {
377                                 _E("Failed to get usb driver version");
378                                 ret = -ENOMEM;
379                                 goto out;
380                         }
381
382                         ret = get_configuration_nodes(node);
383                         if (ret < 0) {
384                                 _E("Failed to get conf nodes");
385                                 ret = -ENOMEM;
386                                 goto out;
387                         }
388
389                         show_configuration_list();
390                         break;
391                 }
392         }
393
394         ret = 0;
395
396 out:
397         xml_close(doc);
398         return ret;
399 }
400
401 static int add_configurations_to_list(xmlNodePtr root)
402 {
403         int ret;
404         dd_list *l;
405         struct xmlConfiguration *conf;
406         xmlNodePtr node;
407         char buf[BUF_MAX];
408         char value[BUF_MAX];
409
410         if (!root)
411                 return -EINVAL;
412
413         DD_LIST_FOREACH(conf_list, l, conf) {
414                 if (conf->value) {
415                         free(conf->value);
416                         conf->value = NULL;
417                 }
418
419                 if (!strncmp(conf->name, NODE_NAME_IPRODUCT, strlen(NODE_NAME_IPRODUCT))) {
420                         ret = get_iproduct_name(buf, sizeof(buf));
421                         if (ret == 0)
422                                 conf->value = strdup(buf);
423                         continue;
424                 }
425
426                 for (node = root->children ; node ; node = node->next) {
427                         if (skip_node(node))
428                                 continue;
429
430                         if (xmlStrcmp((const xmlChar *)conf->name, node->name))
431                                 continue;
432
433                         ret = get_xml_property(node, ATTR_VALUE, value, sizeof(value));
434                         if (ret < 0) {
435                                 _E("Failed to get property(%d)", ret);
436                                 return ret;
437                         }
438
439                         conf->value = strdup(value);
440                         break;
441                 }
442         }
443
444         return 0;
445 }
446
447 static int get_configurations_by_usb_mode(xmlNodePtr root, int mode)
448 {
449         xmlNodePtr node;
450         char cMode[BUF_MAX];
451         int iMode, ret;
452
453         if (!root)
454                 return -EINVAL;
455
456         for (node = root->children ; node ; node = node->next) {
457                 if (skip_node(node))
458                         continue;
459
460                 if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_MODE))
461                         continue;
462
463                 ret = get_xml_property(node, ATTR_VALUE, cMode, sizeof(cMode));
464                 if (ret < 0) {
465                         _E("Failed to get property(%d)", ret);
466                         return ret;
467                 }
468
469                 iMode = atoi(cMode);
470                 if (mode != iMode)
471                         continue;
472
473                 return add_configurations_to_list(node);
474         }
475         return -EINVAL;
476 }
477
478 static int get_configurations_by_version(xmlNodePtr root, int mode)
479 {
480         xmlNodePtr node;
481         char ver[BUF_MAX];
482         int ret;
483
484         if (!root)
485                 return -EINVAL;
486
487         for (node = root->children ; node ; node = node->next) {
488                 if (skip_node(node))
489                         continue;
490
491                 if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_USB_DRV))
492                         continue;
493
494                 ret = get_xml_property(node, ATTR_VERSION, ver, sizeof(ver));
495                 if (ret < 0) {
496                         _E("Failed to get property(%d)", ret);
497                         return ret;
498                 }
499
500                 if (strncmp(ver, driver, strlen(ver)))
501                         continue;
502
503                 return get_configurations_by_usb_mode(node, mode);
504         }
505
506         return -EINVAL;
507 }
508
509 static int get_configurations_info(xmlNodePtr root, int mode)
510 {
511         xmlNodePtr node;
512
513         if (!root)
514                 return -EINVAL;
515
516         for (node = root->children ; node ; node = node->next) {
517                 if (skip_node(node))
518                         continue;
519
520                 if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_USB_CONFS))
521                         continue;
522
523                 return get_configurations_by_version(node, mode);
524         }
525
526         return -EINVAL;
527 }
528
529 int make_configuration_list(int usb_mode)
530 {
531         int ret;
532         xmlDocPtr doc;
533         xmlNodePtr root;
534         xmlNodePtr node;
535
536         if (!is_usb_mode_supported(usb_mode)) {
537                 _E("USB mode (%d) is not supported", usb_mode);
538                 return -EINVAL;
539         }
540
541         doc = xml_open(USB_CONFIGURATIONS_PATH);
542         if (!doc) {
543                 _E("fail to open xml file (%s)", USB_CONFIGURATIONS_PATH);
544                 return -ENOMEM;
545         }
546
547         root = xmlDocGetRootElement(doc);
548         if (!root) {
549                 _E("FAIL: xmlDocGetRootElement()");
550                 ret = -ENOMEM;
551                 goto out;
552         }
553
554         ret = get_configurations_info(root, usb_mode);
555         if (ret < 0) {
556                 _E("Failed to get operations for usb mode(%d)", usb_mode);
557                 ret = -ENOMEM;
558                 goto out;
559         }
560
561         show_configuration_list();
562         ret = 0;
563
564 out:
565         xml_close(doc);
566         return ret;
567 }
568
569
570 void release_configuration_list(void)
571 {
572         dd_list *l;
573         struct xmlConfiguration *conf;
574
575         if (!conf_list)
576                 return;
577
578         DD_LIST_FOREACH(conf_list, l, conf) {
579                 if (conf->name)
580                         free(conf->name);
581                 if (conf->path)
582                         free(conf->path);
583                 if (conf->value)
584                         free(conf->value);
585                 if (conf)
586                         free(conf);
587         }
588
589         DD_LIST_FREE_LIST(conf_list);
590         conf_list = NULL;
591 }
592
593 /* Getting configurations supported */
594 static int get_supported_confs(xmlNodePtr root)
595 {
596         int ret;
597         xmlNodePtr node;
598         char cMode[BUF_MAX];
599         int iMode;
600         struct xmlSupported *sp;
601
602         if (!root)
603                 return -EINVAL;
604
605         for (node = root->children ; node ; node = node->next) {
606                 if (skip_node(node))
607                         continue;
608
609                 if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_MODE))
610                         continue;
611
612                 ret = get_xml_property(node, ATTR_VALUE, cMode, sizeof(cMode));
613                 if (ret < 0) {
614                         _E("Failed to get property(%d)", ret);
615                         return ret;
616                 }
617
618                 iMode = atoi(cMode);
619
620                 sp = (struct xmlSupported *)malloc(sizeof(struct xmlSupported));
621                 if (!sp) {
622                         _E("malloc() failed");
623                         return -ENOMEM;
624                 }
625
626                 sp->mode = iMode;
627
628                 DD_LIST_APPEND(supported_list, sp);
629         }
630
631         return 0;
632 }
633
634 int make_supported_confs_list(void)
635 {
636         int ret;
637         xmlDocPtr doc;
638         xmlNodePtr root;
639         xmlNodePtr node;
640
641         doc = xml_open(SUPPORTED_CONF_PATH);
642         if (!doc) {
643                 _E("fail to open xml file (%s)", SUPPORTED_CONF_PATH);
644                 return -ENOMEM;
645         }
646
647         root = xmlDocGetRootElement(doc);
648         if (!root) {
649                 _E("FAIL: xmlDocGetRootElement()");
650                 ret = -ENOMEM;
651                 goto out;
652         }
653
654         ret = get_supported_confs(root);
655         if (ret < 0) {
656                 _E("Failed to get supported confs");
657                 ret = -ENOMEM;
658                 goto out;
659         }
660
661         show_supported_confs_list();
662         ret = 0;
663
664 out:
665         xml_close(doc);
666         return ret;
667 }
668
669 void release_supported_confs_list(void)
670 {
671         struct xmlSupported *sp;
672         dd_list *l;
673
674         if (!supported_list)
675                 return;
676
677         DD_LIST_FOREACH(supported_list, l, sp) {
678                 free(sp);
679         }
680
681         DD_LIST_FREE_LIST(supported_list);
682         supported_list = NULL;
683 }
684
685 /* Getting operations for each usb mode */
686 static int get_operations_info(xmlNodePtr node, struct xmlOperation **oper)
687 {
688         int ret;
689         char background[BUF_MAX];
690         char operation[BUF_MAX];
691
692         if (!node || !oper)
693                 return -EINVAL;
694
695         ret = get_xml_property(node, ATTR_VALUE, operation, sizeof(operation));
696         if (ret < 0) {
697                 _E("Failed to get property(%d)", ret);
698                 return ret;
699         }
700
701         *oper = (struct xmlOperation *)malloc(sizeof(struct xmlOperation));
702         if (!(*oper)) {
703                 _E("malloc() failed");
704                 return -ENOMEM;
705         }
706
707         (*oper)->name = strdup((const char *)(node->name));
708         (*oper)->oper = strdup(operation);
709
710         if (!((*oper)->name) || !((*oper)->oper)) {
711                 if ((*oper)->name)
712                         free((*oper)->name);
713                 if ((*oper)->oper)
714                         free((*oper)->oper);
715                 if (*oper) {
716                         free(*oper);
717                         *oper = NULL;
718                 }
719                 return -ENOMEM;
720         }
721
722         ret = get_xml_property(node, ATTR_BACKGROUND, background, sizeof(background));
723         if (ret < 0) {
724                 (*oper)->background = false;
725                 return 0;
726         }
727
728         if (strncmp(background, "true", strlen(background)))
729                 (*oper)->background = false;
730         else
731                 (*oper)->background = true;
732
733         return 0;
734 }
735
736 static int add_operations_to_list(xmlNodePtr root)
737 {
738         int ret;
739         xmlNodePtr node;
740         struct xmlOperation *oper;
741
742         if (!root)
743                 return -EINVAL;
744
745         for (node = root->children ; node ; node = node->next) {
746                 if (skip_node(node))
747                         continue;
748
749                 ret = get_operations_info(node, &oper);
750                 if (ret < 0 || !oper) {
751                         _E("Failed to get operations info");
752                         return -ENOMEM;
753                 }
754
755                 DD_LIST_APPEND(oper_list, oper);
756         }
757
758         return 0;
759 }
760
761 static int get_operations_by_usb_mode(xmlNodePtr root, int usb_mode)
762 {
763         int ret;
764         xmlNodePtr node;
765         char cMode[BUF_MAX];
766         int iMode;
767
768         if (!root)
769                 return -EINVAL;
770
771         for (node = root->children ; node ; node = node->next) {
772                 if (skip_node(node))
773                         continue;
774
775                 if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_MODE))
776                         continue;
777
778                 ret = get_xml_property(node, ATTR_VALUE, cMode, sizeof(cMode));
779                 if (ret < 0) {
780                         _E("Failed to get property(%d)", ret);
781                         return ret;
782                 }
783
784                 iMode = atoi(cMode);
785
786                 if (usb_mode != iMode)
787                         continue;
788
789                 ret = add_operations_to_list(node);
790                 if (ret < 0) {
791                         _E("Failed to add operations to list ");
792                         return -ENOMEM;
793                 }
794                 break;
795         }
796
797         return 0;
798 }
799
800 static int get_operations_by_action(xmlNodePtr root, int usb_mode, char *action)
801 {
802         int ret;
803         xmlNodePtr node;
804         char act[BUF_MAX];
805
806         if (!root || !action)
807                 return -EINVAL;
808
809         for (node = root->children ; node ; node = node->next) {
810                 if (skip_node(node))
811                         continue;
812
813                 if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_ACTION))
814                         continue;
815
816                 ret = get_xml_property(node, ATTR_VALUE, act, sizeof(act));
817                 if (ret < 0) {
818                         _E("Failed to get property(%d)", ret);
819                         return ret;
820                 }
821
822                 if (strncmp(act, action, strlen(act)))
823                         continue;
824
825                 ret = get_operations_by_usb_mode(node, usb_mode);
826                 if (ret < 0) {
827                         _E("Failed to get operations for usb_mode (%d)", usb_mode);
828                         return -ENOMEM;
829                 }
830                 break;
831         }
832
833         return 0;
834 }
835
836 static int get_usb_operations(xmlNodePtr root, int usb_mode, char *action)
837 {
838         xmlNodePtr node;
839
840         if (!root || !action)
841                 return -EINVAL;
842
843         for (node = root->children ; node ; node = node->next) {
844                 if (skip_node(node))
845                         continue;
846
847                 if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_USB_OPERS))
848                         continue;
849
850                 return get_operations_by_action(node, usb_mode, action);
851         }
852
853         return -ENOMEM;
854 }
855
856 int make_operation_list(int usb_mode, char *action)
857 {
858         int ret;
859         xmlDocPtr doc;
860         xmlNodePtr root;
861         xmlNodePtr node;
862         char conf_file_path[BUF_MAX];
863
864         if (!action)
865                 return -EINVAL;
866
867         if (!is_usb_mode_supported(usb_mode)) {
868                 _E("USB mode (%d) is not supported", usb_mode);
869                 return -EINVAL;
870         }
871
872         doc = xml_open(USB_CONFIGURATIONS_PATH);
873         if (!doc) {
874                 _E("fail to open xml file (%s)", USB_CONFIGURATIONS_PATH);
875                 return -ENOMEM;
876         }
877
878         root = xmlDocGetRootElement(doc);
879         if (!root) {
880                 _E("FAIL: xmlDocGetRootElement()");
881                 ret = -ENOMEM;
882                 goto out;
883         }
884
885         ret = get_usb_operations(root, usb_mode, action);
886         if (ret < 0) {
887                 _E("Failed to get operations info(%d, %s)", usb_mode, action);
888                 ret = -ENOMEM;
889                 goto out;
890         }
891
892         show_operation_list();
893         ret = 0;
894
895 out:
896         xml_close(doc);
897         return ret;
898 }
899
900 void release_operations_list(void)
901 {
902         dd_list *l;
903         struct xmlOperation *oper;
904
905         if (!oper_list)
906                 return;
907
908         DD_LIST_FOREACH(oper_list, l, oper) {
909                 if (oper->name)
910                         free(oper->name);
911                 if (oper->oper)
912                         free(oper->oper);
913                 if (oper)
914                         free(oper);
915         }
916
917         DD_LIST_FREE_LIST(oper_list);
918         oper_list = NULL;
919 }