fix: fix serial number set for libusbg backend
[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_serial_number },
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
502         if (backend_ctx.backend == GT_BACKEND_GADGETD) {
503                 /* TODO add support for enabling well known UDC */
504                 GVariant *gret;
505                 GError *error = NULL;
506                 GDBusObjectManager *manager;
507                 GList *objects;
508                 GList *l;
509                 const gchar *obj_path = NULL;
510                 _cleanup_g_free_ gchar *g_path = NULL;
511                 const gchar *msg = NULL;
512                 gboolean out_gadget_enabled = 0;
513
514                 gret = g_dbus_connection_call_sync(backend_ctx.gadgetd_conn,
515                                                    "org.usb.gadgetd",
516                                                    "/org/usb/Gadget",
517                                                    "org.usb.device.GadgetManager",
518                                                    "FindGadgetByName",
519                                                    g_variant_new("(s)",
520                                                                  dt->gadget),
521                                                    NULL,
522                                                    G_DBUS_CALL_FLAGS_NONE,
523                                                    -1,
524                                                    NULL,
525                                                    &error);
526
527                 if (error) {
528                         fprintf(stderr, "Failed to get gadget, %s\n", error->message);
529                         return -1;
530                 }
531
532                 g_variant_get(gret, "(o)", &g_path);
533                 g_variant_unref(gret);
534
535                 manager = g_dbus_object_manager_client_new_sync(backend_ctx.gadgetd_conn,
536                                                        G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
537                                                        "org.usb.gadgetd",
538                                                        "/org/usb/Gadget",
539                                                        NULL,
540                                                        NULL,
541                                                        NULL,
542                                                        NULL,
543                                                        &error);
544
545                 if (error) {
546                         fprintf(stderr, "Failed to get dbus object manager, %s\n", error->message);
547                         return -1;
548                 }
549
550                 /* get first "free" udc and enable gadget */
551                 objects = g_dbus_object_manager_get_objects(manager);
552                 for (l = objects; l != NULL; l = l->next)
553                 {
554                         GDBusObject *object = G_DBUS_OBJECT(l->data);
555                         obj_path = g_dbus_object_get_object_path(G_DBUS_OBJECT(object));
556
557                         if (g_str_has_prefix(obj_path, "/org/usb/Gadget/UDC")) {
558                                 obj_path = g_dbus_object_get_object_path(G_DBUS_OBJECT(object));
559
560                                 gret = g_dbus_connection_call_sync(backend_ctx.gadgetd_conn,
561                                                                    "org.usb.gadgetd",
562                                                                    obj_path,
563                                                                    "org.usb.device.UDC",
564                                                                    "EnableGadget",
565                                                                    g_variant_new("(o)",
566                                                                                  g_path),
567                                                                    NULL,
568                                                                    G_DBUS_CALL_FLAGS_NONE,
569                                                                    -1,
570                                                                    NULL,
571                                                                    &error);
572                                 if (error) {
573                                         msg = error->message;
574                                         goto out;
575                                 }
576                                 g_variant_get(gret, "(b)", &out_gadget_enabled);
577                                 if (out_gadget_enabled) {
578                                         g_variant_unref(gret);
579                                         goto out;
580                                 }
581                         }
582                 }
583 out:
584                 g_list_foreach(objects, (GFunc)g_object_unref, NULL);
585                 g_list_free(objects);
586                 g_object_unref(manager);
587
588                 if (msg != NULL) {
589                         fprintf(stderr, "Failed to enable gadget, %s\n", msg);
590                         return -1;
591                 }
592
593         } else if (backend_ctx.backend == GT_BACKEND_LIBUSBG) {
594                 usbg_gadget *g;
595                 usbg_udc *udc = NULL;
596                 int usbg_ret;
597
598                 if (dt->udc != NULL) {
599                         udc = usbg_get_udc(backend_ctx.libusbg_state, dt->udc);
600                         if (udc == NULL) {
601                                 fprintf(stderr, "Failed to get udc\n");
602                                 return -1;
603                         }
604                 }
605
606                 g = usbg_get_gadget(backend_ctx.libusbg_state, dt->gadget);
607                 if (g == NULL) {
608                         fprintf(stderr, "Failed to get gadget\n");
609                         return -1;
610                 }
611
612                 usbg_ret = usbg_enable_gadget(g, udc);
613                 if (usbg_ret != USBG_SUCCESS) {
614                         fprintf(stderr, "Failed to get gadget %s\n", usbg_strerror(usbg_ret));
615                         return -1;
616                 }
617         }
618
619         return 0;
620 }
621
622 static int gt_gadget_enable_help(void *data)
623 {
624         printf("Gadget enable help.\n");
625         return -1;
626 }
627
628 static void gt_parse_gadget_enable(const Command *cmd, int argc,
629                 char **argv, ExecutableCommand *exec, void * data)
630 {
631         struct gt_gadget_enable_data *dt;
632
633         dt = zalloc(sizeof(*dt));
634         if (dt == NULL)
635                 goto out;
636
637         switch (argc) {
638         case 1:
639                 dt->gadget = argv[0];
640                 break;
641         case 2:
642                 dt->gadget = argv[0];
643                 dt->udc = argv[1];
644                 break;
645         default:
646                 goto out;
647         }
648
649         executable_command_set(exec, gt_gadget_enable_func,
650                                 (void *)dt, free);
651         return;
652 out:
653         free((void *)dt);
654         executable_command_set(exec, cmd->printHelp, data, NULL);
655 }
656
657 struct gt_gadget_disable_data {
658         const char *gadget;
659         const char *udc;
660 };
661
662 static int gt_gadget_disable_func(void *data)
663 {
664         struct gt_gadget_disable_data *dt;
665
666         dt = (struct gt_gadget_disable_data *)data;
667         printf("Gadget disable called successfully. Not implemented.\n");
668         if (dt->gadget)
669                 printf("gadget = %s, ", dt->gadget);
670         if (dt->udc)
671                 printf("udc = %s", dt->udc);
672         putchar('\n');
673         return 0;
674 }
675
676 static int gt_gadget_disable_help(void *data)
677 {
678         printf("Gadget disable help.\n");
679         return -1;
680 }
681
682 static void gt_parse_gadget_disable(const Command *cmd, int argc,
683                 char **argv, ExecutableCommand *exec, void * data)
684 {
685         struct gt_gadget_disable_data *dt;
686         char c;
687         struct option opts[] = {
688                 {"udc", required_argument, 0, 'u'},
689                 {0, 0, 0, 0}
690         };
691
692         dt = zalloc(sizeof(*dt));
693         if (dt == NULL)
694                 goto out;
695         argv--;
696         argc++;
697         while (1) {
698                 int opt_index = 0;
699                 c = getopt_long(argc, argv, "u:", opts, &opt_index);
700                 if (c == -1)
701                         break;
702                 switch (c) {
703                 case 'u':
704                         dt->udc = optarg;
705                         break;
706                 default:
707                         goto out;
708                 }
709         }
710
711         if (optind < argc - 1 || (dt->udc && optind < argc)) {
712                 printf("Too many arguments\n");
713                 goto out;
714         }
715
716         dt->gadget = argv[optind];
717         executable_command_set(exec, gt_gadget_disable_func, (void *)dt, free);
718         return;
719 out:
720         free(dt);
721         executable_command_set(exec, cmd->printHelp, data, NULL);
722 }
723
724 struct gt_gadget_gadget_data {
725         const char *name;
726         int opts;
727 };
728
729 static int gt_gadget_gadget_func(void *data)
730 {
731         struct gt_gadget_gadget_data *dt;
732
733         dt = (struct gt_gadget_gadget_data *)data;
734         printf("Gadget gadget called successfully. Not implemented.\n");
735         if (dt->name)
736                 printf("name = %s, ", dt->name);
737         printf("recursive = %d, verbose = %d\n",
738                 !!(dt->opts & GT_RECURSIVE), !!(dt->opts & GT_VERBOSE));
739         return 0;
740 }
741
742 static int gt_gadget_gadget_help(void *data)
743 {
744         printf("Gadget gadget help.\n");
745         return -1;
746 }
747
748 static void gt_parse_gadget_gadget(const Command *cmd, int argc,
749                 char **argv, ExecutableCommand *exec, void * data)
750 {
751         struct gt_gadget_gadget_data *dt;
752         int ind;
753         int avaible_opts = GT_RECURSIVE | GT_VERBOSE;
754
755         dt = zalloc(sizeof(*dt));
756         if (dt == NULL)
757                 goto out;
758
759         ind = gt_get_options(&dt->opts, avaible_opts, argc, argv);
760         if (ind < 0)
761                 goto out;
762
763         switch (argc - ind) {
764         case 0:
765                 break;
766         case 1:
767                 dt->name = argv[ind];
768                 break;
769         default:
770                 goto out;
771         }
772
773         executable_command_set(exec, gt_gadget_gadget_func, (void *)dt,
774                 free);
775         return;
776 out:
777         free(dt);
778         executable_command_set(exec, cmd->printHelp, data, NULL);
779 }
780
781 struct gt_gadget_load_data {
782         const char *name;
783         const char *gadget_name;
784         const char *file;
785         const char *path;
786         int opts;
787 };
788
789 static int gt_gadget_load_func(void *data)
790 {
791         struct gt_gadget_load_data *dt;
792
793         dt = (struct gt_gadget_load_data *)data;
794         printf("Gadget load called successfully. Not implemented.\n");
795         if (dt->name)
796                 printf("name = %s, ", dt->name);
797         if (dt->gadget_name)
798                 printf("gadget = %s, ", dt->gadget_name);
799         if (dt->file)
800                 printf("file %s, ", dt->file);
801         if (dt->path)
802                 printf("path = %s, ", dt->path);
803
804         printf("off = %d, stdin = %d\n",
805                 !!(dt->opts & GT_OFF), !!(dt->opts & GT_STDIN));
806
807         return 0;
808 }
809
810 static int gt_gadget_load_help(void *data)
811 {
812         printf("Gadget load help\n");
813         return -1;
814 }
815
816 static void gt_parse_gadget_load(const Command *cmd, int argc,
817                 char **argv, ExecutableCommand *exec, void * data)
818 {
819         char c;
820         struct gt_gadget_load_data *dt;
821         struct option opts[] = {
822                 {"off", no_argument, 0, 'o'},
823                 {"file", required_argument, 0, 1},
824                 {"stdin", no_argument, 0, 2},
825                 {"path", required_argument, 0, 3},
826                 {0, 0, 0, 0}
827         };
828
829         dt = zalloc(sizeof(*dt));
830         if (dt == NULL)
831                 goto out;
832         argv--;
833         argc++;
834         while (1) {
835                 int opt_index = 0;
836                 c = getopt_long(argc, argv, "o", opts, &opt_index);
837                 if (c == -1)
838                         break;
839                 switch (c) {
840                 case 'o':
841                         dt->opts |= GT_OFF;
842                         break;
843                 case 1:
844                         if (dt->path || dt->opts & GT_STDIN)
845                                 goto out;
846                         dt->file = optarg;
847                         break;
848                 case 2:
849                         if (dt->path || dt->file)
850                                 goto out;
851                         dt->opts |= GT_STDIN;
852                         break;
853                 case 3:
854                         if (dt->file || dt->opts & GT_STDIN)
855                                 goto out;
856                         dt->path = optarg;
857                         break;
858                 default:
859                         goto out;
860                 }
861         }
862
863         if (optind == argc || optind < argc - 2)
864                 goto out;
865
866         dt->name = argv[optind++];
867         if (dt->opts & GT_STDIN || dt->file) {
868                 dt->gadget_name = dt->name;
869                 dt->name = NULL;
870                 if (optind < argc)
871                         goto out;
872         }
873
874         if (optind < argc)
875                 dt->gadget_name = argv[optind++];
876
877         executable_command_set(exec, gt_gadget_load_func, (void *)dt, free);
878         return;
879 out:
880         free(dt);
881         executable_command_set(exec, cmd->printHelp, data, NULL);
882 }
883
884 struct gt_gadget_save_data {
885         const char *gadget;
886         const char *name;
887         const char *file;
888         const char *path;
889         struct gt_setting *attrs;
890         int opts;
891 };
892
893 static void gt_gadget_save_destructor(void *data)
894 {
895         struct gt_gadget_save_data *dt;
896
897         if (data == NULL)
898                 return;
899         dt = (struct gt_gadget_save_data *)data;
900         gt_setting_list_cleanup(dt->attrs);
901         free(dt);
902 }
903
904 static int gt_gadget_save_func(void *data)
905 {
906         struct gt_gadget_save_data *dt;
907         struct gt_setting *ptr;
908
909         dt = (struct gt_gadget_save_data *)data;
910         printf("Gadget save called successfully. Not implemented\n");
911         if (dt->gadget)
912                 printf("gadget = %s, ", dt->gadget);
913         if (dt->name)
914                 printf("name = %s, ", dt->name);
915         if (dt->file)
916                 printf("file = %s, ", dt->file);
917         if (dt->path)
918                 printf("path = %s, ", dt->path);
919         printf("force = %d, stdout = %d",
920                 !!(dt->opts & GT_FORCE), !!(dt->opts & GT_STDOUT));
921
922         ptr = dt->attrs;
923         while (ptr->variable) {
924                 printf(", %s = %s", ptr->variable, ptr->value);
925                 ptr++;
926         }
927
928         putchar('\n');
929         return 0;
930 }
931
932 static int gt_gadget_save_help(void *data)
933 {
934         printf("Gadget save help.\n");
935         return -1;
936 }
937
938 static void gt_parse_gadget_save(const Command *cmd, int argc,
939                 char **argv, ExecutableCommand *exec, void * data)
940 {
941         int c;
942         struct gt_gadget_save_data *dt;
943         struct option opts[] = {
944                 {"force", no_argument, 0, 'f'},
945                 {"file", required_argument, 0, 1},
946                 {"stdout", no_argument, 0, 2},
947                 {"path", required_argument, 0, 3},
948                 {0, 0, 0, 0}
949         };
950
951         dt = zalloc(sizeof(*dt));
952         if (dt == NULL)
953                 goto out;
954         argv--;
955         argc++;
956         while (1) {
957                 int opt_index = 0;
958                 c = getopt_long(argc, argv, "f", opts, &opt_index);
959                 if (c == -1)
960                         break;
961                 switch (c) {
962                 case 'f':
963                         dt->opts |= GT_FORCE;
964                         break;
965                 case 1:
966                         if (dt->path || dt->opts & GT_STDOUT)
967                                 goto out;
968                         dt->file = optarg;
969                         break;
970                 case 2:
971                         if (dt->file || dt->path)
972                                 goto out;
973                         dt->opts |= GT_STDOUT;
974                         break;
975                 case 3:
976                         if (dt->file || dt->opts & GT_STDOUT)
977                                 goto out;
978                         dt->path = optarg;
979                         break;
980                 default:
981                         goto out;
982                 }
983         }
984
985         if (optind == argc)
986                 goto out;
987
988         dt->gadget = argv[optind++];
989
990         if(optind < argc
991           && !dt->file
992           && !(dt->opts & GT_STDOUT)
993           && strchr(argv[optind], '=') == NULL)
994                 dt->name = argv[optind++];
995
996         c = gt_parse_setting_list(&dt->attrs, argc - optind,
997                         argv + optind);
998         if (c < 0)
999                 goto out;
1000
1001         executable_command_set(exec, gt_gadget_save_func, (void *)dt,
1002                 gt_gadget_save_destructor);
1003
1004         return;
1005 out:
1006         gt_gadget_save_destructor((void *)dt);
1007         executable_command_set(exec, cmd->printHelp, data, NULL);
1008 }
1009
1010 struct gt_gadget_template_data {
1011         const char *name;
1012         int opts;
1013 };
1014
1015 static int gt_gadget_template_func(void *data)
1016 {
1017         struct gt_gadget_template_data *dt;
1018
1019         dt = (struct gt_gadget_template_data *)data;
1020         printf("Gadget template called successfully. Not implemented.\n");
1021         if (dt->name)
1022                 printf("name = %s, ", dt->name);
1023         printf("verbose = %d, recursive = %d\n",
1024                 !!(dt->opts & GT_VERBOSE), !!(dt->opts & GT_RECURSIVE));
1025         return 0;
1026 }
1027
1028 static int gt_gadget_template_help(void *data)
1029 {
1030         printf("Gadget template help.\n");
1031         return -1;
1032 }
1033
1034 static void gt_parse_gadget_template(const Command *cmd, int argc,
1035                 char **argv, ExecutableCommand *exec, void * data)
1036 {
1037         int ind;
1038         struct gt_gadget_template_data *dt;
1039         int avaible_opts = GT_VERBOSE | GT_RECURSIVE;
1040
1041         dt = zalloc(sizeof(*dt));
1042         if (dt == NULL)
1043                 goto out;
1044         ind = gt_get_options(&dt->opts, avaible_opts, argc, argv);
1045         if (ind < 0)
1046                 goto out;
1047
1048         if (argc - ind > 1)
1049                 goto out;
1050
1051         if (argv[ind])
1052                 dt->name = argv[ind];
1053
1054         executable_command_set(exec, gt_gadget_template_func, (void *)dt,
1055                 free);
1056
1057         return;
1058 out:
1059         free(dt);
1060         executable_command_set(exec, cmd->printHelp, data, NULL);
1061 }
1062
1063 static int gt_gadget_template_rm_func(void *data)
1064 {
1065         char *dt;
1066
1067         dt = (char *)data;
1068         printf("Gadget template rm called successfully. Not implemented.\n");
1069         printf("name = %s\n", dt);
1070         return 0;
1071 }
1072
1073 static int gt_gadget_template_rm_help(void *data)
1074 {
1075         printf("Gadget template rm help.\n");
1076         return -1;
1077 }
1078
1079 static void gt_parse_gadget_template_rm(const Command *cmd, int argc,
1080                 char **argv, ExecutableCommand *exec, void * data)
1081 {
1082         const char *dt = NULL;
1083
1084         if (argc != 1)
1085                 goto out;
1086
1087         dt = argv[0];
1088         executable_command_set(exec, gt_gadget_template_rm_func, (void *)dt,
1089                 NULL);
1090
1091         return;
1092 out:
1093         executable_command_set(exec, cmd->printHelp, data, NULL);
1094 }
1095
1096 struct gt_gadget_template_set_data {
1097         const char *name;
1098         struct gt_setting *attr;
1099 };
1100
1101 static void gt_gadget_template_set_destructor(void *data)
1102 {
1103         struct gt_gadget_template_set_data *dt;
1104
1105         if (data == NULL)
1106                 return;
1107         dt = (struct gt_gadget_template_set_data *)data;
1108         gt_setting_list_cleanup(dt->attr);
1109         free(dt);
1110 }
1111
1112 static int gt_gadget_template_set_func(void *data)
1113 {
1114         struct gt_gadget_template_set_data *dt;
1115         struct gt_setting *ptr;
1116
1117         dt = (struct gt_gadget_template_set_data *)data;
1118         printf("Gadget template set called successfully. Not implemened.\n");
1119         printf("name = %s", dt->name);
1120         ptr = dt->attr;
1121         while (ptr->variable) {
1122                 printf(", %s = %s", ptr->variable, ptr->value);
1123                 ptr++;
1124         }
1125
1126         putchar('\n');
1127         return 0;
1128 }
1129
1130 static int gt_gadget_template_set_help(void *data)
1131 {
1132         printf("Gadget template set help.\n");
1133         return -1;
1134 }
1135
1136 static void gt_parse_gadget_template_set(const Command *cmd, int argc,
1137                 char **argv, ExecutableCommand *exec, void * data)
1138 {
1139         int tmp;
1140         struct gt_gadget_template_set_data *dt;
1141
1142         dt = zalloc(sizeof(*dt));
1143         if (dt == NULL)
1144                 goto out;
1145
1146         if (argc != 2)
1147                 goto out;
1148
1149         dt->name = argv[0];
1150         tmp = gt_parse_setting_list(&dt->attr, argc-1, argv+1);
1151         if (tmp < 0)
1152                 goto out;
1153
1154         executable_command_set(exec, gt_gadget_template_set_func, (void *)dt,
1155                 gt_gadget_template_set_destructor);
1156
1157         return;
1158 out:
1159         gt_gadget_template_set_destructor((void *)dt);
1160         executable_command_set(exec, cmd->printHelp, data, NULL);
1161 }
1162
1163 struct gt_gadget_template_get_data {
1164         const char *name;
1165         const char **attr;
1166 };
1167
1168 static void gt_gadget_template_get_destructor(void *data)
1169 {
1170         struct gt_gadget_template_get_data *dt;
1171
1172         if (data == NULL)
1173                 return;
1174         dt = (struct gt_gadget_template_get_data *)data;
1175         free(dt->attr);
1176         free(dt);
1177 }
1178
1179 static int gt_gadget_template_get_func(void *data)
1180 {
1181         struct gt_gadget_template_get_data *dt;
1182         const char **ptr;
1183
1184         dt = (struct gt_gadget_template_get_data *)data;
1185         printf("Gadget template get called successfully. Not implemented.\n");
1186         printf("name = %s, attr = ", dt->name);
1187         ptr = dt->attr;
1188         while (*ptr) {
1189                 printf("%s, ", *ptr);
1190                 ptr++;
1191         }
1192
1193         putchar('\n');
1194         return 0;
1195 }
1196
1197 static int gt_gadget_template_get_help(void *data)
1198 {
1199         printf("Gadget template get help.\n");
1200         return -1;
1201 }
1202
1203 static void gt_parse_gadget_template_get(const Command *cmd, int argc,
1204                 char **argv, ExecutableCommand *exec, void * data)
1205 {
1206         int i;
1207         struct gt_gadget_template_get_data *dt;
1208
1209         dt = zalloc(sizeof(*dt));
1210         if (dt == NULL)
1211                 goto out;
1212
1213         if (argc < 1)
1214                 goto out;
1215
1216         dt->name = argv[0];
1217         dt->attr = calloc(argc, sizeof(char *));
1218         if (dt->attr == NULL)
1219                 goto out;
1220
1221         argv++;
1222         argc--;
1223         for (i = 0; i < argc; i++)
1224                 dt->attr[i] = argv[i];
1225
1226         executable_command_set(exec, gt_gadget_template_get_func, (void *)dt,
1227                 gt_gadget_template_get_destructor);
1228
1229         return;
1230 out:
1231         gt_gadget_template_get_destructor((void *)dt);
1232         executable_command_set(exec, cmd->printHelp, data, NULL);
1233 }
1234
1235 const Command *get_gadget_template_children(const Command *cmd)
1236 {
1237         static Command commands[] = {
1238                 {"get", NEXT, gt_parse_gadget_template_get, NULL,
1239                         gt_gadget_template_get_help},
1240                 {"set", NEXT, gt_parse_gadget_template_set, NULL,
1241                         gt_gadget_template_set_help},
1242                 {"rm", NEXT, gt_parse_gadget_template_rm, NULL,
1243                         gt_gadget_template_rm_help},
1244                 {NULL, AGAIN, gt_parse_gadget_template, NULL,
1245                         gt_gadget_template_help},
1246                 CMD_LIST_END
1247         };
1248
1249         return commands;
1250 }
1251
1252 const Command *get_gadget_children(const Command *cmd)
1253 {
1254         static Command commands[] = {
1255                 {"create", NEXT, gt_parse_gadget_create, NULL,
1256                         gt_gadget_create_help},
1257                 {"rm", NEXT, gt_parse_gadget_rm, NULL, gt_gadget_rm_help},
1258                 {"get", NEXT, gt_parse_gadget_get, NULL, gt_gadget_get_help},
1259                 {"set", NEXT, gt_parse_gadget_set, NULL, gt_gadget_set_help},
1260                 {"enable", NEXT, gt_parse_gadget_enable, NULL,
1261                         gt_gadget_enable_help},
1262                 {"disable", NEXT, gt_parse_gadget_disable, NULL,
1263                         gt_gadget_disable_help},
1264                 {"gadget", NEXT, gt_parse_gadget_gadget, NULL,
1265                         gt_gadget_gadget_help},
1266                 {"template", NEXT, command_parse, get_gadget_template_children,
1267                         gt_gadget_template_help},
1268                 {"load", NEXT, gt_parse_gadget_load, NULL,
1269                         gt_gadget_load_help},
1270                 {"save", NEXT, gt_parse_gadget_save, NULL,
1271                         gt_gadget_save_help},
1272                 CMD_LIST_END
1273         };
1274
1275         return commands;
1276 }
1277
1278 int gt_gadget_help(void *data)
1279 {
1280         printf("Gadget help function\n");
1281         return -1;
1282 }