fix: add correct backend in "create gadget" for libusbg
[platform/upstream/gt.git] / source / gadget / src / gadget.c
1 /*
2  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <strings.h>
21 #include <unistd.h>
22 #include <getopt.h>
23 #include <errno.h>
24
25 #include "gadget.h"
26 #include "common.h"
27 #include "parser.h"
28 #include "backend.h"
29
30 static const struct {
31         char *name;
32         int (*set_fn)(usbg_gadget *, int, const char *);
33 } strs[] = {
34         { "product", usbg_set_gadget_product },
35         { "manufacturer", usbg_set_gadget_manufacturer },
36         { "serialnumber", usbg_set_gadget_product },
37 };
38
39 struct gt_gadget_create_data {
40         const char *name;
41         struct gt_setting *attrs;
42         int opts;
43 };
44
45 static void gt_gadget_create_destructor(void *data)
46 {
47         struct gt_gadget_create_data *dt;
48
49         if (data == NULL)
50                 return;
51         dt = (struct gt_gadget_create_data *)data;
52         gt_setting_list_cleanup(dt->attrs);
53         free(dt);
54 }
55
56 static char *attr_type_get(usbg_gadget_attr a)
57 {
58         switch (a) {
59         case B_DEVICE_CLASS:
60         case B_DEVICE_SUB_CLASS:
61         case B_DEVICE_PROTOCOL:
62         case B_MAX_PACKET_SIZE_0:
63                 return "y";
64
65         case BCD_USB:
66         case ID_VENDOR:
67         case ID_PRODUCT:
68         case BCD_DEVICE:
69                 return "q";
70
71         default:
72                 return NULL;
73         }
74 }
75
76 static int attr_val_in_range(usbg_gadget_attr a, unsigned long int val)
77 {
78         char *type = attr_type_get(a);
79
80         if (!type)
81                 return 0;
82
83         if (type[0] == 'y')
84                 return val <= UINT8_MAX;
85         else if (type[0] == 'q')
86                 return val <= UINT16_MAX;
87         else
88                 return 0;
89 }
90
91
92 static int gt_gadget_create_func(void *data)
93 {
94         struct gt_gadget_create_data *dt;
95         struct gt_setting *setting;
96         int attr_val[USBG_GADGET_ATTR_MAX];
97         char *str_val[G_N_ELEMENTS(strs)];
98         _Bool iter;
99         int i;
100         int r;
101
102         for (i = 0; i < G_N_ELEMENTS(attr_val); i++)
103                 attr_val[i] = -1;
104         memset(str_val, 0, sizeof(str_val));
105
106         dt = (struct gt_gadget_create_data *)data;
107
108         for (setting = dt->attrs; setting->variable; setting++) {
109                 int attr_id;
110
111                 iter = TRUE;
112
113                 attr_id = usbg_lookup_gadget_attr(setting->variable);
114                 if (attr_id >= 0) {
115                         unsigned long int val;
116                         char *endptr = NULL;
117
118                         errno = 0;
119                         val = strtoul(setting->value, &endptr, 0);
120                         if (errno
121                             || *setting->value == 0
122                             || (endptr && *endptr != 0)
123                             || attr_val_in_range(attr_id, val) == 0) {
124
125                                 fprintf(stderr, "Invalid value '%s' for attribute '%s'\n",
126                                         setting->value, setting->variable);
127                                 return -1;
128                         }
129
130                         attr_val[attr_id] = val;
131                         iter = FALSE;
132                 }
133                 for (i = 0; iter && i < G_N_ELEMENTS(strs); i++) {
134                         if (streq(setting->variable, strs[i].name)) {
135                                 str_val[i] = setting->value;
136                                 iter = FALSE;
137                                 break;
138                         }
139                 }
140
141                 if (iter) {
142                         fprintf(stderr, "Unknown attribute passed: %s\n", setting->variable);
143                         return -1;
144                 }
145         }
146
147         if (backend_ctx.backend == GT_BACKEND_GADGETD) {
148
149                 GVariantBuilder *b;
150                 GVariant *gattrs;
151                 GVariant *gstrs;
152                 GVariant *v;
153                 GError *err = NULL;
154
155                 b = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
156                 for (i = USBG_GADGET_ATTR_MIN; i < USBG_GADGET_ATTR_MAX; i++) {
157                         if (attr_val[i] == -1)
158                                 continue;
159
160                         g_variant_builder_add(b, "{sv}",
161                                               usbg_get_gadget_attr_str(i),
162                                               g_variant_new(attr_type_get(i), attr_val[i]));
163                 }
164                 gattrs = g_variant_builder_end(b);
165
166                 b = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
167                 for (i = 0; i < G_N_ELEMENTS(strs); i++) {
168                         if (str_val[i] == NULL)
169                                 continue;
170
171                         g_variant_builder_add(b, "{sv}",
172                                               strs[i].name,
173                                               g_variant_new("s", str_val[i]));
174                 }
175                 gstrs = g_variant_builder_end(b);
176
177                 v = g_dbus_connection_call_sync(backend_ctx.gadgetd_conn,
178                                                 "org.usb.gadgetd",
179                                                 "/org/usb/Gadget",
180                                                 "org.usb.device.GadgetManager",
181                                                 "CreateGadget",
182                                                 g_variant_new("(s@a{sv}@a{sv})",
183                                                               dt->name,
184                                                               gattrs,
185                                                               gstrs),
186                                                 NULL,
187                                                 G_DBUS_CALL_FLAGS_NONE,
188                                                 -1,
189                                                 NULL,
190                                                 &err);
191
192                 if (err) {
193                         fprintf(stderr, "Unable to create gadget: %s\n", err->message);
194                         return -1;
195                 }
196
197                 g_variant_unref(v);
198                 return 0;
199
200         } else if (backend_ctx.backend == GT_BACKEND_LIBUSBG) {
201                 usbg_gadget *g;
202
203                 r = usbg_create_gadget(backend_ctx.libusbg_state,
204                                        dt->name,
205                                        NULL,
206                                        NULL,
207                                        &g);
208                 if (r != USBG_SUCCESS) {
209                         fprintf(stderr, "Unable to create gadget %s: %s\n",
210                                 dt->name, usbg_strerror(r));
211                         return -1;
212                 }
213
214                 for (i = USBG_GADGET_ATTR_MIN; i < USBG_GADGET_ATTR_MAX; i++) {
215                         if (attr_val[i] == -1)
216                                 continue;
217
218                         r = usbg_set_gadget_attr(g, i, attr_val[i]);
219                         if (r != USBG_SUCCESS) {
220                                 fprintf(stderr, "Unable to set attribute %s: %s\n",
221                                         usbg_get_gadget_attr_str(i),
222                                         usbg_strerror(r));
223                                 goto err_usbg;
224                         }
225                 }
226
227                 for (i = 0; i < G_N_ELEMENTS(str_val); i++) {
228                         if (str_val[i] == NULL)
229                                 continue;
230
231                         r = strs[i].set_fn(g, LANG_US_ENG, str_val[i]);
232                         if (r != USBG_SUCCESS) {
233                                 fprintf(stderr, "Unable to set string %s: %s\n",
234                                         strs[i].name,
235                                         usbg_strerror(r));
236                                 goto err_usbg;
237                         }
238                 }
239
240                 return 0;
241
242         err_usbg:
243                 usbg_rm_gadget(g, USBG_RM_RECURSE);
244                 return -1;
245         }
246
247         return -1;
248 }
249
250 static int gt_gadget_create_help(void *data)
251 {
252         int i;
253
254         printf("usage: %s create NAME [attr=value]...\n"
255                "Create new gadget of specified name, attributes and language strings.\n"
256                "\n"
257                "Attributes:\n",
258                program_name);
259
260         for (i = USBG_GADGET_ATTR_MIN; i < USBG_GADGET_ATTR_MAX; i++)
261                 printf("  %s\n", usbg_get_gadget_attr_str(i));
262
263         printf("Device strings (en_US locale):\n");
264
265         for (i = 0; i < G_N_ELEMENTS(strs); i++)
266                 printf("  %s\n", strs[i].name);
267
268         return 0;
269 }
270
271 static void gt_parse_gadget_create(const Command *cmd, int argc, char **argv,
272                 ExecutableCommand *exec, void *data)
273 {
274         struct gt_gadget_create_data *dt;
275         int ind;
276         int c;
277         int avaible_opts = GT_FORCE;
278
279         dt = zalloc(sizeof(*dt));
280         if (dt == NULL)
281                 goto out;
282
283         ind = gt_get_options(&dt->opts, avaible_opts, argc, argv);
284         if (ind < 0)
285                 goto out;
286
287         if (ind == argc)
288                 goto out;
289
290         dt->name = argv[ind++];
291
292         c = gt_parse_setting_list(&dt->attrs, argc - ind, argv + ind);
293         if (c < 0)
294                 goto out;
295
296         executable_command_set(exec, gt_gadget_create_func,
297                                 (void *)dt, gt_gadget_create_destructor);
298         return;
299 out:
300         gt_gadget_create_destructor((void *)dt);
301         executable_command_set(exec, cmd->printHelp, data, NULL);
302 }
303
304 struct gt_gadget_rm_data {
305         const char *name;
306         int opts;
307 };
308
309 static int gt_gadget_rm_help(void *data)
310 {
311         printf("Gadget rm help.\n");
312         return -1;
313 }
314
315 static int gt_gadget_rm_func(void *data)
316 {
317         struct gt_gadget_rm_data *dt;
318
319         dt = (struct gt_gadget_rm_data *)data;
320         printf("Gadget rm called successfully. Not implemented.\n");
321         printf("name = %s, force = %d, recursive = %d\n",
322                 dt->name, !!(dt->opts & GT_FORCE), !!(dt->opts & GT_RECURSIVE));
323         return 0;
324 }
325
326 static void gt_parse_gadget_rm(const Command *cmd, int argc, char **argv,
327                 ExecutableCommand *exec, void *data)
328 {
329         struct gt_gadget_rm_data *dt;
330         int ind;
331         int avaible_opts = GT_FORCE | GT_RECURSIVE;
332
333         dt = zalloc(sizeof(*dt));
334         if (dt == NULL)
335                 goto out;
336
337         ind = gt_get_options(&dt->opts, avaible_opts, argc, argv);
338         if (ind < 0)
339                 goto out;
340
341         if (argc - ind != 1)
342                 goto out;
343         dt->name = argv[ind];
344         executable_command_set(exec, gt_gadget_rm_func, (void *)dt,
345                         free);
346         return;
347 out:
348         free(dt);
349         executable_command_set(exec, cmd->printHelp, data, NULL);
350 }
351
352 struct gt_gadget_get_data {
353         const char *name;
354         const char **attrs;
355 };
356
357 static void gt_gadget_get_destructor(void *data)
358 {
359         struct gt_gadget_get_data *dt;
360
361         if (data == NULL)
362                 return;
363         dt = (struct gt_gadget_get_data *)data;
364
365         free(dt->attrs);
366         free(dt);
367 }
368
369 static int gt_gadget_get_func(void *data)
370 {
371         struct gt_gadget_get_data *dt;
372         const char **ptr;
373
374         dt = (struct gt_gadget_get_data *)data;
375         printf("Gadget get called successfully. Not implemented yet.\n");
376         printf("name = %s, attrs = ", dt->name);
377
378         ptr = dt->attrs;
379         while (*ptr) {
380                 printf("%s, ", *ptr);
381                 ptr++;
382         }
383
384         putchar('\n');
385         return 0;
386 }
387
388 static int gt_gadget_get_help(void *data)
389 {
390         printf("Gadget get help.\n");
391         return -1;
392 }
393
394 static void gt_parse_gadget_get(const Command *cmd, int argc, char **argv,
395                 ExecutableCommand *exec, void * data)
396 {
397         struct gt_gadget_get_data *dt = NULL;
398         int i;
399
400         if (argc == 0)
401                 goto out;
402
403         dt = zalloc(sizeof(*dt));
404         if (dt == NULL)
405                 goto out;
406
407         dt->name = argv[0];
408         dt->attrs = calloc(argc, sizeof(char *));
409         if (dt->attrs == NULL)
410                 goto out;
411
412         argv++;
413         for (i = 0; i < argc; i++) {
414                 dt->attrs[i] = argv[i];
415         }
416
417         executable_command_set(exec, gt_gadget_get_func, (void *)dt,
418                         gt_gadget_get_destructor);
419
420         return;
421 out:
422         gt_gadget_get_destructor((void *)dt);
423         executable_command_set(exec, cmd->printHelp, data, NULL);
424 }
425
426 struct gt_gadget_set_data {
427         const char *name;
428         struct gt_setting *attrs;
429 };
430
431 static void gt_gadget_set_destructor(void *data)
432 {
433         struct gt_gadget_set_data *dt;
434
435         if (data == NULL)
436                 return;
437         dt = (struct gt_gadget_set_data *)data;
438         gt_setting_list_cleanup(dt->attrs);
439         free(dt);
440 }
441
442 static int gt_gadget_set_func(void *data)
443 {
444         struct gt_gadget_set_data *dt;
445         struct gt_setting *ptr;
446
447         dt = (struct gt_gadget_set_data *)data;
448         printf("Gadget set called successfully. Not implemented.\n");
449         printf("name = %s", dt->name);
450         ptr = dt->attrs;
451         while (ptr->variable) {
452                 printf(", %s = %s", ptr->variable, ptr->value);
453                 ptr++;
454         }
455         putchar('\n');
456         return 0;
457 }
458
459 static int gt_gadget_set_help(void *data)
460 {
461         printf("Gadget set help.\n");
462         return -1;
463 }
464
465 static void gt_parse_gadget_set(const Command *cmd, int argc, char **argv,
466                 ExecutableCommand *exec, void * data)
467 {
468         struct gt_gadget_set_data *dt = NULL;
469         int tmp;
470
471         if (argc < 2)
472                 goto out;
473
474         dt = zalloc(sizeof(*dt));
475         if (dt == NULL)
476                 goto out;
477
478         dt->name = argv[0];
479         tmp = gt_parse_setting_list(&dt->attrs, argc-1, argv+1);
480         if (tmp < 0)
481                 goto out;
482
483         executable_command_set(exec, gt_gadget_set_func, (void *)dt,
484                         gt_gadget_set_destructor);
485         return;
486 out:
487         gt_gadget_set_destructor((void *)dt);
488         executable_command_set(exec, cmd->printHelp, data, NULL);
489 }
490
491 struct gt_gadget_enable_data {
492         const char *gadget;
493         const char *udc;
494 };
495
496 static int gt_gadget_enable_func(void *data)
497 {
498         struct gt_gadget_enable_data *dt;
499
500         dt = (struct gt_gadget_enable_data *)data;
501         printf("Gadget enable called successfully. Not implemented.\n");
502         if (dt->gadget)
503                 printf("gadget = %s, ", dt->gadget);
504         if (dt->udc)
505                 printf("udc = %s", dt->udc);
506         putchar('\n');
507         return 0;
508 }
509
510 static int gt_gadget_enable_help(void *data)
511 {
512         printf("Gadget enable help.\n");
513         return -1;
514 }
515
516 static void gt_parse_gadget_enable(const Command *cmd, int argc,
517                 char **argv, ExecutableCommand *exec, void * data)
518 {
519         struct gt_gadget_enable_data *dt;
520         char c;
521         struct option opts[] = {
522                 {"gadget", required_argument, 0, 'g'},
523                 {"udc", required_argument, 0, 'u'},
524                 {0, 0, 0, 0}
525         };
526
527         dt = zalloc(sizeof(*dt));
528         if (dt == NULL)
529                 goto out;
530         argv--;
531         argc++;
532         while (1) {
533                 int opt_index = 0;
534                 c = getopt_long(argc, argv, "g:u:", opts, &opt_index);
535                 if (c == -1)
536                         break;
537                 switch (c) {
538                 case 'g':
539                         dt->gadget = optarg;
540                         break;
541                 case 'u':
542                         dt->udc = optarg;
543                         break;
544                 default:
545                         goto out;
546                 }
547         }
548
549         executable_command_set(exec, gt_gadget_enable_func, (void *)dt, free);
550         return;
551 out:
552         free(dt);
553         executable_command_set(exec, cmd->printHelp, data, NULL);
554 }
555
556 struct gt_gadget_disable_data {
557         const char *gadget;
558         const char *udc;
559 };
560
561 static int gt_gadget_disable_func(void *data)
562 {
563         struct gt_gadget_disable_data *dt;
564
565         dt = (struct gt_gadget_disable_data *)data;
566         printf("Gadget disable called successfully. Not implemented.\n");
567         if (dt->gadget)
568                 printf("gadget = %s, ", dt->gadget);
569         if (dt->udc)
570                 printf("udc = %s", dt->udc);
571         putchar('\n');
572         return 0;
573 }
574
575 static int gt_gadget_disable_help(void *data)
576 {
577         printf("Gadget disable help.\n");
578         return -1;
579 }
580
581 static void gt_parse_gadget_disable(const Command *cmd, int argc,
582                 char **argv, ExecutableCommand *exec, void * data)
583 {
584         struct gt_gadget_disable_data *dt;
585         char c;
586         struct option opts[] = {
587                 {"udc", required_argument, 0, 'u'},
588                 {0, 0, 0, 0}
589         };
590
591         dt = zalloc(sizeof(*dt));
592         if (dt == NULL)
593                 goto out;
594         argv--;
595         argc++;
596         while (1) {
597                 int opt_index = 0;
598                 c = getopt_long(argc, argv, "u:", opts, &opt_index);
599                 if (c == -1)
600                         break;
601                 switch (c) {
602                 case 'u':
603                         dt->udc = optarg;
604                         break;
605                 default:
606                         goto out;
607                 }
608         }
609
610         if (optind < argc - 1 || (dt->udc && optind < argc)) {
611                 printf("Too many arguments\n");
612                 goto out;
613         }
614
615         dt->gadget = argv[optind];
616         executable_command_set(exec, gt_gadget_disable_func, (void *)dt, free);
617         return;
618 out:
619         free(dt);
620         executable_command_set(exec, cmd->printHelp, data, NULL);
621 }
622
623 struct gt_gadget_gadget_data {
624         const char *name;
625         int opts;
626 };
627
628 static int gt_gadget_gadget_func(void *data)
629 {
630         struct gt_gadget_gadget_data *dt;
631
632         dt = (struct gt_gadget_gadget_data *)data;
633         printf("Gadget gadget called successfully. Not implemented.\n");
634         if (dt->name)
635                 printf("name = %s, ", dt->name);
636         printf("recursive = %d, verbose = %d\n",
637                 !!(dt->opts & GT_RECURSIVE), !!(dt->opts & GT_VERBOSE));
638         return 0;
639 }
640
641 static int gt_gadget_gadget_help(void *data)
642 {
643         printf("Gadget gadget help.\n");
644         return -1;
645 }
646
647 static void gt_parse_gadget_gadget(const Command *cmd, int argc,
648                 char **argv, ExecutableCommand *exec, void * data)
649 {
650         struct gt_gadget_gadget_data *dt;
651         int ind;
652         int avaible_opts = GT_RECURSIVE | GT_VERBOSE;
653
654         dt = zalloc(sizeof(*dt));
655         if (dt == NULL)
656                 goto out;
657
658         ind = gt_get_options(&dt->opts, avaible_opts, argc, argv);
659         if (ind < 0)
660                 goto out;
661
662         switch (argc - ind) {
663         case 0:
664                 break;
665         case 1:
666                 dt->name = argv[ind];
667                 break;
668         default:
669                 goto out;
670         }
671
672         executable_command_set(exec, gt_gadget_gadget_func, (void *)dt,
673                 free);
674         return;
675 out:
676         free(dt);
677         executable_command_set(exec, cmd->printHelp, data, NULL);
678 }
679
680 struct gt_gadget_load_data {
681         const char *name;
682         const char *gadget_name;
683         const char *file;
684         const char *path;
685         int opts;
686 };
687
688 static int gt_gadget_load_func(void *data)
689 {
690         struct gt_gadget_load_data *dt;
691
692         dt = (struct gt_gadget_load_data *)data;
693         printf("Gadget load called successfully. Not implemented.\n");
694         if (dt->name)
695                 printf("name = %s, ", dt->name);
696         if (dt->gadget_name)
697                 printf("gadget = %s, ", dt->gadget_name);
698         if (dt->file)
699                 printf("file %s, ", dt->file);
700         if (dt->path)
701                 printf("path = %s, ", dt->path);
702
703         printf("off = %d, stdin = %d\n",
704                 !!(dt->opts & GT_OFF), !!(dt->opts & GT_STDIN));
705
706         return 0;
707 }
708
709 static int gt_gadget_load_help(void *data)
710 {
711         printf("Gadget load help\n");
712         return -1;
713 }
714
715 static void gt_parse_gadget_load(const Command *cmd, int argc,
716                 char **argv, ExecutableCommand *exec, void * data)
717 {
718         char c;
719         struct gt_gadget_load_data *dt;
720         struct option opts[] = {
721                 {"off", no_argument, 0, 'o'},
722                 {"file", required_argument, 0, 1},
723                 {"stdin", no_argument, 0, 2},
724                 {"path", required_argument, 0, 3},
725                 {0, 0, 0, 0}
726         };
727
728         dt = zalloc(sizeof(*dt));
729         if (dt == NULL)
730                 goto out;
731         argv--;
732         argc++;
733         while (1) {
734                 int opt_index = 0;
735                 c = getopt_long(argc, argv, "o", opts, &opt_index);
736                 if (c == -1)
737                         break;
738                 switch (c) {
739                 case 'o':
740                         dt->opts |= GT_OFF;
741                         break;
742                 case 1:
743                         if (dt->path || dt->opts & GT_STDIN)
744                                 goto out;
745                         dt->file = optarg;
746                         break;
747                 case 2:
748                         if (dt->path || dt->file)
749                                 goto out;
750                         dt->opts |= GT_STDIN;
751                         break;
752                 case 3:
753                         if (dt->file || dt->opts & GT_STDIN)
754                                 goto out;
755                         dt->path = optarg;
756                         break;
757                 default:
758                         goto out;
759                 }
760         }
761
762         if (optind == argc || optind < argc - 2)
763                 goto out;
764
765         dt->name = argv[optind++];
766         if (dt->opts & GT_STDIN || dt->file) {
767                 dt->gadget_name = dt->name;
768                 dt->name = NULL;
769                 if (optind < argc)
770                         goto out;
771         }
772
773         if (optind < argc)
774                 dt->gadget_name = argv[optind++];
775
776         executable_command_set(exec, gt_gadget_load_func, (void *)dt, free);
777         return;
778 out:
779         free(dt);
780         executable_command_set(exec, cmd->printHelp, data, NULL);
781 }
782
783 struct gt_gadget_save_data {
784         const char *gadget;
785         const char *name;
786         const char *file;
787         const char *path;
788         struct gt_setting *attrs;
789         int opts;
790 };
791
792 static void gt_gadget_save_destructor(void *data)
793 {
794         struct gt_gadget_save_data *dt;
795
796         if (data == NULL)
797                 return;
798         dt = (struct gt_gadget_save_data *)data;
799         gt_setting_list_cleanup(dt->attrs);
800         free(dt);
801 }
802
803 static int gt_gadget_save_func(void *data)
804 {
805         struct gt_gadget_save_data *dt;
806         struct gt_setting *ptr;
807
808         dt = (struct gt_gadget_save_data *)data;
809         printf("Gadget save called successfully. Not implemented\n");
810         if (dt->gadget)
811                 printf("gadget = %s, ", dt->gadget);
812         if (dt->name)
813                 printf("name = %s, ", dt->name);
814         if (dt->file)
815                 printf("file = %s, ", dt->file);
816         if (dt->path)
817                 printf("path = %s, ", dt->path);
818         printf("force = %d, stdout = %d",
819                 !!(dt->opts & GT_FORCE), !!(dt->opts & GT_STDOUT));
820
821         ptr = dt->attrs;
822         while (ptr->variable) {
823                 printf(", %s = %s", ptr->variable, ptr->value);
824                 ptr++;
825         }
826
827         putchar('\n');
828         return 0;
829 }
830
831 static int gt_gadget_save_help(void *data)
832 {
833         printf("Gadget save help.\n");
834         return -1;
835 }
836
837 static void gt_parse_gadget_save(const Command *cmd, int argc,
838                 char **argv, ExecutableCommand *exec, void * data)
839 {
840         int c;
841         struct gt_gadget_save_data *dt;
842         struct option opts[] = {
843                 {"force", no_argument, 0, 'f'},
844                 {"file", required_argument, 0, 1},
845                 {"stdout", no_argument, 0, 2},
846                 {"path", required_argument, 0, 3},
847                 {0, 0, 0, 0}
848         };
849
850         dt = zalloc(sizeof(*dt));
851         if (dt == NULL)
852                 goto out;
853         argv--;
854         argc++;
855         while (1) {
856                 int opt_index = 0;
857                 c = getopt_long(argc, argv, "f", opts, &opt_index);
858                 if (c == -1)
859                         break;
860                 switch (c) {
861                 case 'f':
862                         dt->opts |= GT_FORCE;
863                         break;
864                 case 1:
865                         if (dt->path || dt->opts & GT_STDOUT)
866                                 goto out;
867                         dt->file = optarg;
868                         break;
869                 case 2:
870                         if (dt->file || dt->path)
871                                 goto out;
872                         dt->opts |= GT_STDOUT;
873                         break;
874                 case 3:
875                         if (dt->file || dt->opts & GT_STDOUT)
876                                 goto out;
877                         dt->path = optarg;
878                         break;
879                 default:
880                         goto out;
881                 }
882         }
883
884         if (optind == argc)
885                 goto out;
886
887         dt->gadget = argv[optind++];
888
889         if(optind < argc
890           && !dt->file
891           && !(dt->opts & GT_STDOUT)
892           && strchr(argv[optind], '=') == NULL)
893                 dt->name = argv[optind++];
894
895         c = gt_parse_setting_list(&dt->attrs, argc - optind,
896                         argv + optind);
897         if (c < 0)
898                 goto out;
899
900         executable_command_set(exec, gt_gadget_save_func, (void *)dt,
901                 gt_gadget_save_destructor);
902
903         return;
904 out:
905         gt_gadget_save_destructor((void *)dt);
906         executable_command_set(exec, cmd->printHelp, data, NULL);
907 }
908
909 struct gt_gadget_template_data {
910         const char *name;
911         int opts;
912 };
913
914 static int gt_gadget_template_func(void *data)
915 {
916         struct gt_gadget_template_data *dt;
917
918         dt = (struct gt_gadget_template_data *)data;
919         printf("Gadget template called successfully. Not implemented.\n");
920         if (dt->name)
921                 printf("name = %s, ", dt->name);
922         printf("verbose = %d, recursive = %d\n",
923                 !!(dt->opts & GT_VERBOSE), !!(dt->opts & GT_RECURSIVE));
924         return 0;
925 }
926
927 static int gt_gadget_template_help(void *data)
928 {
929         printf("Gadget template help.\n");
930         return -1;
931 }
932
933 static void gt_parse_gadget_template(const Command *cmd, int argc,
934                 char **argv, ExecutableCommand *exec, void * data)
935 {
936         int ind;
937         struct gt_gadget_template_data *dt;
938         int avaible_opts = GT_VERBOSE | GT_RECURSIVE;
939
940         dt = zalloc(sizeof(*dt));
941         if (dt == NULL)
942                 goto out;
943         ind = gt_get_options(&dt->opts, avaible_opts, argc, argv);
944         if (ind < 0)
945                 goto out;
946
947         if (argc - ind > 1)
948                 goto out;
949
950         if (argv[ind])
951                 dt->name = argv[ind];
952
953         executable_command_set(exec, gt_gadget_template_func, (void *)dt,
954                 free);
955
956         return;
957 out:
958         free(dt);
959         executable_command_set(exec, cmd->printHelp, data, NULL);
960 }
961
962 static int gt_gadget_template_rm_func(void *data)
963 {
964         char *dt;
965
966         dt = (char *)data;
967         printf("Gadget template rm called successfully. Not implemented.\n");
968         printf("name = %s\n", dt);
969         return 0;
970 }
971
972 static int gt_gadget_template_rm_help(void *data)
973 {
974         printf("Gadget template rm help.\n");
975         return -1;
976 }
977
978 static void gt_parse_gadget_template_rm(const Command *cmd, int argc,
979                 char **argv, ExecutableCommand *exec, void * data)
980 {
981         const char *dt = NULL;
982
983         if (argc != 1)
984                 goto out;
985
986         dt = argv[0];
987         executable_command_set(exec, gt_gadget_template_rm_func, (void *)dt,
988                 NULL);
989
990         return;
991 out:
992         executable_command_set(exec, cmd->printHelp, data, NULL);
993 }
994
995 struct gt_gadget_template_set_data {
996         const char *name;
997         struct gt_setting *attr;
998 };
999
1000 static void gt_gadget_template_set_destructor(void *data)
1001 {
1002         struct gt_gadget_template_set_data *dt;
1003
1004         if (data == NULL)
1005                 return;
1006         dt = (struct gt_gadget_template_set_data *)data;
1007         gt_setting_list_cleanup(dt->attr);
1008         free(dt);
1009 }
1010
1011 static int gt_gadget_template_set_func(void *data)
1012 {
1013         struct gt_gadget_template_set_data *dt;
1014         struct gt_setting *ptr;
1015
1016         dt = (struct gt_gadget_template_set_data *)data;
1017         printf("Gadget template set called successfully. Not implemened.\n");
1018         printf("name = %s", dt->name);
1019         ptr = dt->attr;
1020         while (ptr->variable) {
1021                 printf(", %s = %s", ptr->variable, ptr->value);
1022                 ptr++;
1023         }
1024
1025         putchar('\n');
1026         return 0;
1027 }
1028
1029 static int gt_gadget_template_set_help(void *data)
1030 {
1031         printf("Gadget template set help.\n");
1032         return -1;
1033 }
1034
1035 static void gt_parse_gadget_template_set(const Command *cmd, int argc,
1036                 char **argv, ExecutableCommand *exec, void * data)
1037 {
1038         int tmp;
1039         struct gt_gadget_template_set_data *dt;
1040
1041         dt = zalloc(sizeof(*dt));
1042         if (dt == NULL)
1043                 goto out;
1044
1045         if (argc != 2)
1046                 goto out;
1047
1048         dt->name = argv[0];
1049         tmp = gt_parse_setting_list(&dt->attr, argc-1, argv+1);
1050         if (tmp < 0)
1051                 goto out;
1052
1053         executable_command_set(exec, gt_gadget_template_set_func, (void *)dt,
1054                 gt_gadget_template_set_destructor);
1055
1056         return;
1057 out:
1058         gt_gadget_template_set_destructor((void *)dt);
1059         executable_command_set(exec, cmd->printHelp, data, NULL);
1060 }
1061
1062 struct gt_gadget_template_get_data {
1063         const char *name;
1064         const char **attr;
1065 };
1066
1067 static void gt_gadget_template_get_destructor(void *data)
1068 {
1069         struct gt_gadget_template_get_data *dt;
1070
1071         if (data == NULL)
1072                 return;
1073         dt = (struct gt_gadget_template_get_data *)data;
1074         free(dt->attr);
1075         free(dt);
1076 }
1077
1078 static int gt_gadget_template_get_func(void *data)
1079 {
1080         struct gt_gadget_template_get_data *dt;
1081         const char **ptr;
1082
1083         dt = (struct gt_gadget_template_get_data *)data;
1084         printf("Gadget template get called successfully. Not implemented.\n");
1085         printf("name = %s, attr = ", dt->name);
1086         ptr = dt->attr;
1087         while (*ptr) {
1088                 printf("%s, ", *ptr);
1089                 ptr++;
1090         }
1091
1092         putchar('\n');
1093         return 0;
1094 }
1095
1096 static int gt_gadget_template_get_help(void *data)
1097 {
1098         printf("Gadget template get help.\n");
1099         return -1;
1100 }
1101
1102 static void gt_parse_gadget_template_get(const Command *cmd, int argc,
1103                 char **argv, ExecutableCommand *exec, void * data)
1104 {
1105         int i;
1106         struct gt_gadget_template_get_data *dt;
1107
1108         dt = zalloc(sizeof(*dt));
1109         if (dt == NULL)
1110                 goto out;
1111
1112         if (argc < 1)
1113                 goto out;
1114
1115         dt->name = argv[0];
1116         dt->attr = calloc(argc, sizeof(char *));
1117         if (dt->attr == NULL)
1118                 goto out;
1119
1120         argv++;
1121         argc--;
1122         for (i = 0; i < argc; i++)
1123                 dt->attr[i] = argv[i];
1124
1125         executable_command_set(exec, gt_gadget_template_get_func, (void *)dt,
1126                 gt_gadget_template_get_destructor);
1127
1128         return;
1129 out:
1130         gt_gadget_template_get_destructor((void *)dt);
1131         executable_command_set(exec, cmd->printHelp, data, NULL);
1132 }
1133
1134 const Command *get_gadget_template_children(const Command *cmd)
1135 {
1136         static Command commands[] = {
1137                 {"get", NEXT, gt_parse_gadget_template_get, NULL,
1138                         gt_gadget_template_get_help},
1139                 {"set", NEXT, gt_parse_gadget_template_set, NULL,
1140                         gt_gadget_template_set_help},
1141                 {"rm", NEXT, gt_parse_gadget_template_rm, NULL,
1142                         gt_gadget_template_rm_help},
1143                 {NULL, AGAIN, gt_parse_gadget_template, NULL,
1144                         gt_gadget_template_help},
1145                 CMD_LIST_END
1146         };
1147
1148         return commands;
1149 }
1150
1151 const Command *get_gadget_children(const Command *cmd)
1152 {
1153         static Command commands[] = {
1154                 {"create", NEXT, gt_parse_gadget_create, NULL,
1155                         gt_gadget_create_help},
1156                 {"rm", NEXT, gt_parse_gadget_rm, NULL, gt_gadget_rm_help},
1157                 {"get", NEXT, gt_parse_gadget_get, NULL, gt_gadget_get_help},
1158                 {"set", NEXT, gt_parse_gadget_set, NULL, gt_gadget_set_help},
1159                 {"enable", NEXT, gt_parse_gadget_enable, NULL,
1160                         gt_gadget_enable_help},
1161                 {"disable", NEXT, gt_parse_gadget_disable, NULL,
1162                         gt_gadget_disable_help},
1163                 {"gadget", NEXT, gt_parse_gadget_gadget, NULL,
1164                         gt_gadget_gadget_help},
1165                 {"template", NEXT, command_parse, get_gadget_template_children,
1166                         gt_gadget_template_help},
1167                 {"load", NEXT, gt_parse_gadget_load, NULL,
1168                         gt_gadget_load_help},
1169                 {"save", NEXT, gt_parse_gadget_save, NULL,
1170                         gt_gadget_save_help},
1171                 CMD_LIST_END
1172         };
1173
1174         return commands;
1175 }
1176
1177 int gt_gadget_help(void *data)
1178 {
1179         printf("Gadget help function\n");
1180         return -1;
1181 }