ArDrone SDK 1.8 added
[mardrone] / mardrone / ARDrone_SDK_Version_1_8_20110726 / Examples / Linux / Navigation / Sources / UI / ardrone_ini.c
1 #include <linux/joystick.h>
2 #include <ardrone_api.h>
3 #include <VP_Os/vp_os_print.h>
4
5 #include "ardrone_ini.h"
6
7 Controller_info *control;
8 Controller_info *default_control;
9 GList *devices;
10
11 typedef struct {
12   int32_t bus;
13   int32_t vendor;
14   int32_t product;
15   int32_t version;
16   char    name[MAX_NAME_LENGTH];
17   char    handlers[MAX_NAME_LENGTH];
18 } device_t;
19
20 extern int32_t MiscVar[];
21
22 input_device_t control_device = {
23   "Control",
24   open_control_device,
25   update_control_device,
26   close_control_device
27 };
28
29 static int32_t joy_dev = 0;
30
31 C_RESULT open_control_device(void) {
32   C_RESULT res = C_FAIL;
33
34   printf("%s\n", default_control->filename);
35   if (default_control->serial) {
36     gchar **str;
37     str = g_strsplit(default_control->filename, "/", -1);
38     strncpy(control_device.name, str[3], MAX_NAME_LENGTH);
39   } else {
40     strncpy(control_device.name, "strdup", MAX_NAME_LENGTH);
41   }
42   joy_dev = open(default_control->filename, O_NONBLOCK | O_RDONLY);
43
44   res = C_OK;
45   
46   return res;
47 }
48
49 C_RESULT update_control_device(void) {
50   static int32_t stick1LR = 0, stick1UD = 0 , stick2LR = 0 , stick2UD = 0;
51   //static int32_t x = 0, y = 0;
52   static bool_t refresh_values = FALSE;
53   ssize_t res;
54   static struct js_event js_e_buffer[64];
55   static int32_t start = 0;
56   input_state_t* input_state;
57   
58   static int center_x1=0;
59   static int center_y1=0;
60   static int center_x2=0;
61   static int center_y2=0;
62
63 /*  static int32_t theta_trim = 0;
64   static int32_t phi_trim   = 0;
65   static int32_t yaw_trim   = 0;*/
66
67   if (default_control->config)
68     return C_OK;
69   
70   res = read(joy_dev, js_e_buffer, sizeof(struct js_event) * 64);
71
72   if( !res || (res < 0 && errno == EAGAIN) )
73     return C_OK;
74
75   if( res < 0 )
76     return C_FAIL;
77     
78   if (res < (int) sizeof(struct js_event)) // If non-complete bloc: ignored
79     return C_OK;
80
81   // Buffer decomposition in blocs (if the last is incomplete, it's ignored)
82   int32_t idx = 0;
83   refresh_values = FALSE;
84   input_state = ardrone_tool_get_input_state();
85   for (idx = 0; idx < res / sizeof(struct js_event); idx++) {
86     if (js_e_buffer[idx].type & JS_EVENT_INIT ) { // If Init, the first values are ignored
87       break;
88     } else if(js_e_buffer[idx].type & JS_EVENT_BUTTON ) { // Event Button detected
89       if ((js_e_buffer[idx].number == default_control->commands[ROLL_LEFT].value) && (default_control->commands[ROLL_LEFT].type == BUTTON)) {
90           //printf("buttons.control_ag : %d => %d\n", js_e_buffer[idx].number, js_e_buffer[idx].value);
91           stick1LR = -32767 * js_e_buffer[idx].value;
92                   } else if ((js_e_buffer[idx].number == default_control->commands[SPEED_DOWN].value) && (default_control->commands[SPEED_DOWN].type == BUTTON)) {
93           //printf("buttons.control_ab : %d => %d\n", js_e_buffer[idx].number, js_e_buffer[idx].value);
94           stick2UD = 32767 * js_e_buffer[idx].value;
95                   } else if ((js_e_buffer[idx].number == default_control->commands[ROLL_RIGHT].value) && (default_control->commands[ROLL_RIGHT].type == BUTTON)) {
96           //printf("buttons.control_ad : %d => %d\n", js_e_buffer[idx].number, js_e_buffer[idx].value);
97           stick1LR = 32767 * js_e_buffer[idx].value;
98                   } else if ((js_e_buffer[idx].number == default_control->commands[SPEED_UP].value) && (default_control->commands[SPEED_UP].type == BUTTON)) {
99           //printf("buttons.control_ah : %d => %d\n", js_e_buffer[idx].number, js_e_buffer[idx].value);
100           stick2UD = -32767 * js_e_buffer[idx].value;
101                   } else if ((js_e_buffer[idx].number == default_control->commands[YAW_LEFT].value) && (default_control->commands[YAW_LEFT].type == BUTTON)) {
102           //printf("buttons.control_l1 : %d => %d\n", js_e_buffer[idx].number, js_e_buffer[idx].value);
103           stick2LR = -32767 * js_e_buffer[idx].value;
104                   } else if ((js_e_buffer[idx].number == default_control->commands[YAW_RIGHT].value) && (default_control->commands[YAW_RIGHT].type == BUTTON)) {
105           //printf("buttons.control_r1 : %d => %d\n", js_e_buffer[idx].number, js_e_buffer[idx].value);
106           stick2LR = 32767 * js_e_buffer[idx].value;
107                   } else if ((js_e_buffer[idx].number == default_control->commands[EMERGENCY].value) && (default_control->commands[EMERGENCY].type == BUTTON)) {
108           //printf("buttons.control_select : %d => %d\n", js_e_buffer[idx].number, js_e_buffer[idx].value);
109           ardrone_tool_set_ui_pad_select(js_e_buffer[idx].value);
110                   } else if ((js_e_buffer[idx].number == default_control->commands[START].value) && (default_control->commands[START].type == BUTTON)) {
111           //printf("buttons.control_start : %d => %d\n", js_e_buffer[idx].number, js_e_buffer[idx].value);
112           if( js_e_buffer[idx].value ) {
113             start ^= 1;
114             ardrone_tool_set_ui_pad_start( start );
115                     }
116                   } else if ((js_e_buffer[idx].number == default_control->commands[PITCH_FRONT].value) && (default_control->commands[PITCH_FRONT].type == BUTTON)) {
117           //printf("buttons.pitch_front : %d => %d\n", js_e_buffer[idx].number, js_e_buffer[idx].value);
118                       stick1UD = -32767;
119                   } else if ((js_e_buffer[idx].number == default_control->commands[PITCH_BACK].value) && (default_control->commands[PITCH_BACK].type == BUTTON)) {
120           //printf("buttons.pitch_back : %d => %d\n", js_e_buffer[idx].number, js_e_buffer[idx].value);
121                       stick1UD = 32767;
122       }
123     } else if(js_e_buffer[idx].type & JS_EVENT_AXIS ) { // Event Axis detected
124       refresh_values = TRUE;
125       int axis_value = (js_e_buffer[idx].number + 1) * (js_e_buffer[idx].value > 0 ? 1 : -1);
126       if ((axis_value == default_control->commands[PITCH_FRONT].value) && (default_control->commands[PITCH_FRONT].type == AXIS)) {
127         //printf("axis.pitch_front : %d => %d (%d)\n", js_e_buffer[idx].number, js_e_buffer[idx].value, ( js_e_buffer[idx].value + 1 ) >> 15);
128         stick1UD = ( js_e_buffer[idx].value );
129                   } else if ((axis_value == default_control->commands[PITCH_BACK].value) && (default_control->commands[PITCH_BACK].type == AXIS)) {
130         //printf("axis.pitch_back : %d => %d (%d)\n", js_e_buffer[idx].number, js_e_buffer[idx].value, ( js_e_buffer[idx].value + 1 ) >> 15);
131         stick1UD = ( js_e_buffer[idx].value );
132                   } else if ((axis_value == default_control->commands[ROLL_LEFT].value) && (default_control->commands[ROLL_LEFT].type == AXIS)) {
133         //printf("axis.roll_left : %d => %d (%d)\n", js_e_buffer[idx].number, js_e_buffer[idx].value, ( js_e_buffer[idx].value + 1 ) >> 15);
134         stick1LR = ( js_e_buffer[idx].value );
135                   } else if ((axis_value == default_control->commands[ROLL_RIGHT].value) && (default_control->commands[ROLL_RIGHT].type == AXIS)) {
136         //printf("axis.roll_right : %d => %d (%d)\n", js_e_buffer[idx].number, js_e_buffer[idx].value, ( js_e_buffer[idx].value + 1 ) >> 15);
137         stick1LR = ( js_e_buffer[idx].value );
138                   } else if ((axis_value == default_control->commands[SPEED_UP].value) && (default_control->commands[SPEED_UP].type == AXIS)) {
139         //printf("axis.speed_up : %d => %d (%d)\n", js_e_buffer[idx].number, js_e_buffer[idx].value, ( js_e_buffer[idx].value + 1 ) >> 15);
140         stick2UD = ( js_e_buffer[idx].value );
141                   } else if ((axis_value == default_control->commands[SPEED_DOWN].value) && (default_control->commands[SPEED_DOWN].type == AXIS)) {
142         //printf("axis.speed_down : %d => %d (%d)\n", js_e_buffer[idx].number, js_e_buffer[idx].value, ( js_e_buffer[idx].value + 1 ) >> 15);
143         stick2UD = ( js_e_buffer[idx].value );
144                   } else if ((axis_value == default_control->commands[YAW_LEFT].value) && (default_control->commands[YAW_LEFT].type == AXIS)) {
145         //printf("axis.yaw_left : %d => %d (%d)\n", js_e_buffer[idx].number, js_e_buffer[idx].value, ( js_e_buffer[idx].value + 1 ) >> 15);
146         stick2LR = ( js_e_buffer[idx].value );
147                   } else if ((axis_value == default_control->commands[YAW_RIGHT].value) && (default_control->commands[YAW_RIGHT].type == AXIS)) {
148         //printf("axis.yaw_right : %d => %d (%d)\n", js_e_buffer[idx].number, js_e_buffer[idx].value, ( js_e_buffer[idx].value + 1 ) >> 15);
149         stick2LR = ( js_e_buffer[idx].value );
150       }
151
152     } else {
153       // TODO: default: ERROR (non-supported)
154     }
155   }
156
157   //if(refresh_values)// Axis values to refresh
158     {
159     //printf("roll : %f, pitch : %f, gaz : %f, yaw : %f\n", 
160     //                                /*roll*/(float)(stick1LR-center_x1)/32767.0f,
161     //                                /*pitch*/(float)(stick1UD-center_y1)/32767.0f,
162     //                                /*gaz*/-(float)(stick2UD-center_x2)/32767.0f,
163     //                                /*yaw*/(float)(stick2LR-center_y2)/32767.0f);
164       int enable = 1;
165         if (    327 > stick1LR && -327 < stick1LR &&
166                 327 > stick1UD && -327 < stick1UD &&
167                 327 > stick2LR && -327 < stick2LR &&
168                 327 > stick2UD && -327 < stick2UD) 
169         {
170                 enable = 0;
171         }
172       ardrone_at_set_progress_cmd( enable,
173                                     /*roll*/(float)(stick1LR-center_x1)/32767.0f,
174                                     /*pitch*/(float)(stick1UD-center_y1)/32767.0f,
175                                     /*gaz*/-(float)(stick2UD-center_x2)/32767.0f,
176                                     /*yaw*/(float)(stick2LR-center_y2)/32767.0f );
177     }
178
179   return C_OK;
180 }
181
182 C_RESULT close_control_device(void) {
183   close( joy_dev );
184
185   return C_OK;
186 }
187
188 uint32_t uint32_atoi(char* buf){
189         uint32_t ret = 0;
190         char tmp;
191         while((*buf >= '0' && *buf <= '9') || (*buf >= 'a' && *buf <= 'f') || (*buf >= 'A' && *buf <= 'F')){
192                 tmp = *buf;
193                 if(tmp >= 'a' && tmp <= 'f')
194                         tmp -= 'a' - 'A';
195                 if(tmp >= 'A' && tmp <= 'F')
196                         tmp -= 0x7;
197                 tmp -= 0x30;
198                 
199                 ret = ret << 4;
200                 ret |= tmp;
201                 
202                 buf++;
203         }
204         return ret;
205 }
206
207 /**
208  * Search all Joystick devices
209  */
210 gboolean search_devices(GList **list_controllers) {
211   int i;
212   Controller_info *ctrl_info;
213   struct udev *udev;
214   struct udev_device *dev;
215
216   for(i = 0; i < 32; ++i) {
217     gchar *str = NULL;
218     str = g_strdup_printf("/dev/input/js%d", i);
219     int fd = open(str, O_RDONLY);
220     if (fd < 0) {
221       //printf("Could not found joystick: %s\n", str->str);
222       break;
223     } else {
224       ctrl_info = g_malloc(sizeof(Controller_info));
225       uint8_t num_axis   = 0;
226       uint8_t num_button = 0;
227       ioctl(fd, JSIOCGAXES,    &num_axis);
228       ioctl(fd, JSIOCGBUTTONS, &num_button);
229       ctrl_info->filename    = g_strdup(str);
230       ctrl_info->num_axis    = num_axis;
231       ctrl_info->num_buttons = num_button;
232       // Get Name 
233       char name_c_str[1024];
234       if (ioctl(fd, JSIOCGNAME(sizeof(name_c_str)), name_c_str) < 0) {
235           printf("%s : %s", str, strerror(errno));
236           break;
237       } else {
238          ctrl_info->name = g_convert_with_fallback(name_c_str, sizeof(name_c_str), "UTF-8", "ISO-8859-1", NULL, NULL, NULL, NULL);
239       }
240
241       /* Create the udev object */
242       udev = udev_new();
243       if (!udev) {
244         printf("Can't create udev\n");
245         exit(0);
246       }
247
248       dev = udev_device_new_from_subsystem_sysname(udev, "input", g_strdup_printf("js%d", i));
249       if (dev == NULL)
250             break;
251
252       ctrl_info->serial = uint32_atoi(g_strdup_printf("%s%s", udev_list_entry_get_value(udev_list_entry_get_by_name(udev_device_get_properties_list_entry(dev), "ID_VENDOR_ID")), udev_list_entry_get_value(udev_list_entry_get_by_name(udev_device_get_properties_list_entry(dev), "ID_MODEL_ID"))));
253
254       udev_device_unref(dev);
255       udev_unref(udev);
256       printf("%s : %d, %d, 0x%08x\n", ctrl_info->name, ctrl_info->num_axis, ctrl_info->num_buttons, ctrl_info->serial);
257     }
258     *list_controllers = g_list_append(*list_controllers, ctrl_info);
259     close(fd);
260   }
261
262   return TRUE;
263 }
264
265 void parseControls(xmlDocPtr doc, xmlNodePtr cur) {
266   cur = cur->xmlChildrenNode;
267   while (cur != NULL) {
268     if ((!xmlStrcmp(cur->name, (const xmlChar *)"control"))) {
269       if ((!xmlStrcmp(xmlGetProp(cur, BAD_CAST "name"), (const xmlChar *) "takeoff"))) {
270         control->commands[START].value = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "value")));
271         control->commands[START].type = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "type")));
272       } else if ((!xmlStrcmp(xmlGetProp(cur, BAD_CAST "name"), (const xmlChar *) "emergency"))) {
273         control->commands[EMERGENCY].value = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "value")));
274         control->commands[EMERGENCY].type = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "type")));
275       } else if ((!xmlStrcmp(xmlGetProp(cur, BAD_CAST "name"), (const xmlChar *) "pitch_front"))) {
276         control->commands[PITCH_FRONT].value = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "value")));
277         control->commands[PITCH_FRONT].type = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "type")));
278       } else if ((!xmlStrcmp(xmlGetProp(cur, BAD_CAST "name"), (const xmlChar *) "pitch_back"))) {
279         control->commands[PITCH_BACK].value = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "value")));
280         control->commands[PITCH_BACK].type = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "type")));
281       } else if ((!xmlStrcmp(xmlGetProp(cur, BAD_CAST "name"), (const xmlChar *) "roll_left"))) {
282         control->commands[ROLL_LEFT].value = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "value")));
283         control->commands[ROLL_LEFT].type = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "type")));
284       } else if ((!xmlStrcmp(xmlGetProp(cur, BAD_CAST "name"), (const xmlChar *) "roll_right"))) {
285         control->commands[ROLL_RIGHT].value = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "value")));
286         control->commands[ROLL_RIGHT].type = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "type")));
287       } else if ((!xmlStrcmp(xmlGetProp(cur, BAD_CAST "name"), (const xmlChar *) "yaw_left"))) {
288         control->commands[YAW_LEFT].value = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "value")));
289         control->commands[YAW_LEFT].type = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "type")));
290       } else if ((!xmlStrcmp(xmlGetProp(cur, BAD_CAST "name"), (const xmlChar *) "yaw_right"))) {
291         control->commands[YAW_RIGHT].value = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "value")));
292         control->commands[YAW_RIGHT].type = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "type")));
293       } else if ((!xmlStrcmp(xmlGetProp(cur, BAD_CAST "name"), (const xmlChar *) "speed_up"))) {
294         control->commands[SPEED_UP].value = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "value")));
295         control->commands[SPEED_UP].type = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "type")));
296       } else if ((!xmlStrcmp(xmlGetProp(cur, BAD_CAST "name"), (const xmlChar *) "speed_down"))) {
297         control->commands[SPEED_DOWN].value = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "value")));
298         control->commands[SPEED_DOWN].type = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "type")));
299       } 
300     }
301     cur = cur->next;
302   }
303 }
304
305 void parseDevice(xmlDocPtr doc, xmlNodePtr cur) {
306   cur = cur->xmlChildrenNode;
307   while (cur != NULL) {
308     if ((!xmlStrcmp(cur->name, (const xmlChar *)"controls"))) {
309       parseControls(doc, cur);
310     }
311     cur = cur->next;
312   }
313 }
314
315 void parseDevices(xmlDocPtr doc, xmlNodePtr cur) {
316   cur = cur->xmlChildrenNode;
317   while (cur != NULL) {
318     if ((!xmlStrcmp(cur->name, (const xmlChar *)"device"))) {
319       control = g_malloc(sizeof(Controller_info));
320       control->serial = atoi(g_strdup((const char *) xmlGetProp(cur, BAD_CAST "id")));
321       control->name = g_strdup((const char *) xmlGetProp(cur, BAD_CAST "name"));
322       control->def = xmlStrEqual(xmlGetProp(cur, BAD_CAST "default"), (const xmlChar *)"yes") ? TRUE : FALSE;
323       control->config = FALSE;
324       if (!control->serial)
325         control->filename = g_strdup("/dev/stdin");
326       else
327         control->filename = g_strdup("");
328       printf("Device 0x%08x : %s (%s) (%s)\n", control->serial, control->name, (control->def)?"yes":"no", control->filename);
329       parseDevice(doc, cur);
330       devices = g_list_append(devices, control);
331       if (control->def)
332         default_control = control;
333     }
334     cur = cur->next;
335   }
336 }
337
338 void load_ini() {
339   xmlDocPtr doc;
340   xmlNodePtr cur;
341   GList* list_controllers = NULL;
342   
343   printf("Loading configuration file %s\n", FILENAME);
344
345   doc = xmlParseFile(FILENAME);
346   
347   if (doc == NULL ) {
348     printf("Document not parsed successfully. \n");
349     create_ini();
350     goto suite;
351   }
352
353   cur = xmlDocGetRootElement(doc);
354   if (cur == NULL) {
355     printf("Empty document\n");
356     xmlFreeDoc(doc);
357     create_ini();
358     goto suite;
359   }
360   
361   if (xmlStrcmp(cur->name, (const xmlChar *) "ardrone")) {
362     printf("Document of the wrong type, root node != ardrone");
363     xmlFreeDoc(doc);
364     create_ini();
365     goto suite;
366   }
367   
368   cur = cur->xmlChildrenNode;
369   while (cur != NULL) {
370     if ((!xmlStrcmp(cur->name, (const xmlChar *)"devices"))){
371       parseDevices (doc, cur);
372     }
373      
374     cur = cur->next;
375   }
376   
377   xmlFreeDoc(doc);
378
379 suite:
380   search_devices(&list_controllers);
381   GList *it, *it2;
382   for (it = devices; it; it = it->next) {
383     Controller_info *c;
384     c = (Controller_info *) it->data;
385     for (it2 = list_controllers; it2; it2 = it2->next) {
386       Controller_info *c2;
387       c2 = (Controller_info *) it2->data;
388       if (c->serial == c2->serial) {
389         c->filename = strdup(c2->filename);
390         break;
391       }
392     }
393   }
394   for (it = list_controllers; it; it = it->next) {
395     Controller_info *c;
396     c = (Controller_info *) it->data;
397     if (c->serial == default_control->serial)
398       break;
399   }
400   if (!it) {
401     default_control->def = FALSE;
402     default_control = devices->data;
403     default_control->def = TRUE;
404   }
405   
406   printf("Loading complete\n");
407 }
408
409 void save_init(Controller_info *def) {
410   xmlDocPtr doc;
411   xmlNodePtr devices_xml, device_xml, controls_xml, control_xml;
412
413   printf("Beginning writing %s\n", FILENAME);
414
415   doc = xmlNewDoc(BAD_CAST "1.0");
416   doc->children = xmlNewDocNode(doc, NULL, BAD_CAST "ardrone", NULL);
417   devices_xml = xmlNewChild(doc->children, NULL, BAD_CAST "devices", NULL);
418
419   GList *it;
420   for (it = devices; it; it = it->next) {
421     Controller_info *c;
422     c = (Controller_info *) it->data;
423
424     device_xml = xmlNewChild(devices_xml, NULL, BAD_CAST "device", NULL);
425     xmlSetProp(device_xml, BAD_CAST "id", BAD_CAST g_strdup_printf("%u", c->serial));
426     xmlSetProp(device_xml, BAD_CAST "name", BAD_CAST c->name);
427     xmlSetProp(device_xml, BAD_CAST "default", BAD_CAST (c == def ? "yes" : "no"));
428     controls_xml = xmlNewChild(device_xml, NULL, BAD_CAST "controls", NULL);
429     control_xml = xmlNewChild(controls_xml, NULL, BAD_CAST "control", NULL);
430     xmlSetProp(control_xml, BAD_CAST "name", BAD_CAST "takeoff");
431     xmlSetProp(control_xml, BAD_CAST "value", BAD_CAST g_strdup_printf("%d", c->commands[START].value));
432     xmlSetProp(control_xml, BAD_CAST "type", BAD_CAST g_strdup_printf("%d", c->commands[START].type));
433     control_xml = xmlNewChild(controls_xml, NULL, BAD_CAST "control", NULL);
434     xmlSetProp(control_xml, BAD_CAST "name", BAD_CAST "emergency");
435     xmlSetProp(control_xml, BAD_CAST "value", BAD_CAST g_strdup_printf("%d", c->commands[EMERGENCY].value));
436     xmlSetProp(control_xml, BAD_CAST "type", BAD_CAST g_strdup_printf("%d", c->commands[EMERGENCY].type));
437     control_xml = xmlNewChild(controls_xml, NULL, BAD_CAST "control", NULL);
438     xmlSetProp(control_xml, BAD_CAST "name", BAD_CAST "pitch_front");
439     xmlSetProp(control_xml, BAD_CAST "value", BAD_CAST g_strdup_printf("%d", c->commands[PITCH_FRONT].value));
440     xmlSetProp(control_xml, BAD_CAST "type", BAD_CAST g_strdup_printf("%d", c->commands[PITCH_FRONT].type));
441     control_xml = xmlNewChild(controls_xml, NULL, BAD_CAST "control", NULL);
442     xmlSetProp(control_xml, BAD_CAST "name", BAD_CAST "pitch_back");
443     xmlSetProp(control_xml, BAD_CAST "value", BAD_CAST g_strdup_printf("%d", c->commands[PITCH_BACK].value));
444     xmlSetProp(control_xml, BAD_CAST "type", BAD_CAST g_strdup_printf("%d", c->commands[PITCH_BACK].type));
445     control_xml = xmlNewChild(controls_xml, NULL, BAD_CAST "control", NULL);
446     xmlSetProp(control_xml, BAD_CAST "name", BAD_CAST "roll_left");
447     xmlSetProp(control_xml, BAD_CAST "value", BAD_CAST g_strdup_printf("%d", c->commands[ROLL_LEFT].value));
448     xmlSetProp(control_xml, BAD_CAST "type", BAD_CAST g_strdup_printf("%d", c->commands[ROLL_LEFT].type));
449     control_xml = xmlNewChild(controls_xml, NULL, BAD_CAST "control", NULL);
450     xmlSetProp(control_xml, BAD_CAST "name", BAD_CAST "roll_right");
451     xmlSetProp(control_xml, BAD_CAST "value", BAD_CAST g_strdup_printf("%d", c->commands[ROLL_RIGHT].value));
452     xmlSetProp(control_xml, BAD_CAST "type", BAD_CAST g_strdup_printf("%d", c->commands[ROLL_RIGHT].type));
453     control_xml = xmlNewChild(controls_xml, NULL, BAD_CAST "control", NULL);
454     xmlSetProp(control_xml, BAD_CAST "name", BAD_CAST "yaw_left");
455     xmlSetProp(control_xml, BAD_CAST "value", BAD_CAST g_strdup_printf("%d", c->commands[YAW_LEFT].value));
456     xmlSetProp(control_xml, BAD_CAST "type", BAD_CAST g_strdup_printf("%d", c->commands[YAW_LEFT].type));
457     control_xml = xmlNewChild(controls_xml, NULL, BAD_CAST "control", NULL);
458     xmlSetProp(control_xml, BAD_CAST "name", BAD_CAST "yaw_right");
459     xmlSetProp(control_xml, BAD_CAST "value", BAD_CAST g_strdup_printf("%d", c->commands[YAW_RIGHT].value));
460     xmlSetProp(control_xml, BAD_CAST "type", BAD_CAST g_strdup_printf("%d", c->commands[YAW_RIGHT].type));
461     control_xml = xmlNewChild(controls_xml, NULL, BAD_CAST "control", NULL);
462     xmlSetProp(control_xml, BAD_CAST "name", BAD_CAST "speed_up");
463     xmlSetProp(control_xml, BAD_CAST "value", BAD_CAST g_strdup_printf("%d", c->commands[SPEED_UP].value));
464     xmlSetProp(control_xml, BAD_CAST "type", BAD_CAST g_strdup_printf("%d", c->commands[SPEED_UP].type));
465     control_xml = xmlNewChild(controls_xml, NULL, BAD_CAST "control", NULL);
466     xmlSetProp(control_xml, BAD_CAST "name", BAD_CAST "speed_down");
467     xmlSetProp(control_xml, BAD_CAST "value", BAD_CAST g_strdup_printf("%d", c->commands[SPEED_DOWN].value));
468     xmlSetProp(control_xml, BAD_CAST "type", BAD_CAST g_strdup_printf("%d", c->commands[SPEED_DOWN].type));
469   }
470   xmlKeepBlanksDefault(0);
471   xmlSaveFormatFile(FILENAME, doc, 1);
472
473   default_control = def;
474   printf("Writing %s OK\n", FILENAME);
475 }
476
477 /**
478  * Create the initial configuration file with default keyboard values
479  */
480 void create_ini() {
481   int i;
482   
483   control = g_malloc(sizeof(Controller_info));
484   control->serial = 0;
485   control->name = g_strdup("Keyboard");
486   control->def = TRUE;
487   control->config = FALSE;
488   control->filename = g_strdup("/dev/stdin");
489   control->commands[START].value = 13;           // start decollage / atterissage
490   control->commands[EMERGENCY].value = 32;       // emergency coupe les moteurs
491   control->commands[SPEED_DOWN].value = 88;      // descendre
492   control->commands[SPEED_UP].value = 90;        // monter
493   control->commands[ROLL_LEFT].value = 81;       // tourner a gauche
494   control->commands[ROLL_RIGHT].value = 68;      // tourner a droite
495   control->commands[YAW_LEFT].value = 65361;     // pivoter a gauche
496   control->commands[YAW_RIGHT].value = 65363;    // pivoter a droite
497   control->commands[PITCH_FRONT].value = 65362;  // deplacement en avant
498   control->commands[PITCH_BACK].value = 65364;   // deplacement en arriere
499   for (i = 0; i < NUM_COMMAND; i++) {
500     control->commands[i].type = NONE;
501   }
502   
503   devices = g_list_append(devices, control);
504   default_control = control;
505
506   save_init(default_control);
507 }