Galaxy S2 camera module
[exynos_camera.git] / exynos_param.c
1 /*
2  * Copyright (C) 2013 Paul Kocialkowski
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <stdlib.h>
21 #include <errno.h>
22 #include <malloc.h>
23 #include <ctype.h>
24
25 #define LOG_TAG "exynos_param"
26 #include <utils/Log.h>
27
28 #include "exynos_camera.h"
29
30 int list_head_insert(struct list_head *list, struct list_head *prev,
31         struct list_head *next)
32 {
33         if (list == NULL)
34                 return -EINVAL;
35
36         list->prev = prev;
37         list->next = next;
38
39         if(prev != NULL)
40                 prev->next = list;
41         if(next != NULL)
42                 next->prev = list;
43
44         return 0;
45 }
46
47 void list_head_remove(struct list_head *list)
48 {
49         if(list == NULL)
50                 return;
51
52         if(list->next != NULL)
53                 list->next->prev = list->prev;
54         if(list->prev != NULL)
55                 list->prev->next = list->next;
56 }
57
58 int exynos_param_register(struct exynos_camera *exynos_camera, char *key,
59         union exynos_param_data data, enum exynos_param_type type)
60 {
61         struct list_head *list_end;
62         struct list_head *list;
63         struct exynos_param *param;
64
65         if (exynos_camera == NULL || key == NULL)
66                 return -EINVAL;
67
68         param = (struct exynos_param *) calloc(1, sizeof(struct exynos_param));
69         if (param == NULL)
70                 return -ENOMEM;
71
72         param->key = strdup(key);
73         switch (type) {
74                 case EXYNOS_PARAM_INT:
75                         param->data.integer = data.integer;
76                         break;
77                 case EXYNOS_PARAM_FLOAT:
78                         param->data.floating = data.floating;
79                         break;
80                 case EXYNOS_PARAM_STRING:
81                         param->data.string = strdup(data.string);
82                         break;
83                 default:
84                         LOGE("%s: Invalid type", __func__);
85                         goto error;
86         }
87         param->type = type;
88
89         list_end = (struct list_head *) exynos_camera->params;
90         while (list_end != NULL && list_end->next != NULL)
91                 list_end = list_end->next;
92
93         list = (struct list_head *) param;
94         list_head_insert(list, list_end, NULL);
95
96         if (exynos_camera->params == NULL)
97                 exynos_camera->params = param;
98
99         return 0;
100
101 error:
102         if (param != NULL) {
103                 if (param->key != NULL)
104                         free(param->key);
105
106                 free(param);
107         }
108
109         return -1;
110 }
111
112 void exynos_param_unregister(struct exynos_camera *exynos_camera,
113         struct exynos_param *param)
114 {
115         struct list_head *list;
116
117         if (exynos_camera == NULL || param == NULL)
118                 return;
119
120         list = (struct list_head *) exynos_camera->params;
121         while (list != NULL) {
122                 if ((void *) list == (void *) param) {
123                         list_head_remove(list);
124
125                         if ((void *) list == (void *) exynos_camera->params)
126                                 exynos_camera->params = (struct exynos_param *) list->next;
127
128                         if (param->type == EXYNOS_PARAM_STRING && param->data.string != NULL)
129                                 free(param->data.string);
130
131                         memset(param, 0, sizeof(struct exynos_param));
132                         free(param);
133
134                         break;
135                 }
136
137 list_continue:
138                 list = list->next;
139         }
140 }
141
142 struct exynos_param *exynos_param_find_key(struct exynos_camera *exynos_camera,
143         char *key)
144 {
145         struct exynos_param *param;
146         struct list_head *list;
147
148         if (exynos_camera == NULL || key == NULL)
149                 return NULL;
150
151         list = (struct list_head *) exynos_camera->params;
152         while (list != NULL) {
153                 param = (struct exynos_param *) list;
154                 if (param->key == NULL)
155                         goto list_continue;
156
157                 if (strcmp(param->key, key) == 0)
158                         return param;
159
160 list_continue:
161                 list = list->next;
162         }
163
164         return NULL;
165 }
166
167 int exynos_param_data_set(struct exynos_camera *exynos_camera, char *key,
168         union exynos_param_data data, enum exynos_param_type type)
169 {
170         struct exynos_param *param;
171
172         if (exynos_camera == NULL || key == NULL)
173                 return -EINVAL;
174
175         if (strchr(key, '=') || strchr(key, ';'))
176                 return -EINVAL;
177
178         if (type == EXYNOS_PARAM_STRING && data.string != NULL &&
179                 (strchr(data.string, '=') || strchr(data.string, ';')))
180                 return -EINVAL;
181
182         param = exynos_param_find_key(exynos_camera, key);
183         if (param == NULL) {
184                 // The key isn't in the list yet
185                 exynos_param_register(exynos_camera, key, data, type);
186                 return 0;
187         }
188
189         if (param->type != type)
190                 LOGE("%s: Mismatching types for key %s", __func__, key);
191
192         if (param->type == EXYNOS_PARAM_STRING && param->data.string != NULL)
193                 free(param->data.string);
194
195         switch (type) {
196                 case EXYNOS_PARAM_INT:
197                         param->data.integer = data.integer;
198                         break;
199                 case EXYNOS_PARAM_FLOAT:
200                         param->data.floating = data.floating;
201                         break;
202                 case EXYNOS_PARAM_STRING:
203                         param->data.string = strdup(data.string);
204                         break;
205                 default:
206                         LOGE("%s: Invalid type", __func__);
207                         return -1;
208         }
209         param->type = type;
210
211         return 0;
212 }
213
214 int exynos_param_data_get(struct exynos_camera *exynos_camera, char *key,
215         union exynos_param_data *data, enum exynos_param_type type)
216 {
217         struct exynos_param *param;
218
219         if (exynos_camera == NULL || key == NULL || data == NULL)
220                 return -EINVAL;
221
222         param = exynos_param_find_key(exynos_camera, key);
223         if (param == NULL || param->type != type)
224                 return -1;
225
226         memcpy(data, &param->data, sizeof(param->data));
227
228         return 0;
229 }
230
231 int exynos_param_int_get(struct exynos_camera *exynos_camera,
232         char *key)
233 {
234         union exynos_param_data data;
235         int rc;
236
237         if (exynos_camera == NULL || key == NULL)
238                 return -EINVAL;
239
240         rc = exynos_param_data_get(exynos_camera, key, &data, EXYNOS_PARAM_INT);
241         if (rc < 0) {
242                 LOGE("%s: Unable to get data for key %s", __func__, key);
243                 return -1;
244         }
245
246         return data.integer;
247 }
248
249 float exynos_param_float_get(struct exynos_camera *exynos_camera,
250         char *key)
251 {
252         union exynos_param_data data;
253         int rc;
254
255         if (exynos_camera == NULL || key == NULL)
256                 return -EINVAL;
257
258         rc = exynos_param_data_get(exynos_camera, key, &data, EXYNOS_PARAM_FLOAT);
259         if (rc < 0) {
260                 LOGE("%s: Unable to get data for key %s", __func__, key);
261                 return -1;
262         }
263
264         return data.floating;
265 }
266
267 char *exynos_param_string_get(struct exynos_camera *exynos_camera,
268         char *key)
269 {
270         union exynos_param_data data;
271         int rc;
272
273         if (exynos_camera == NULL || key == NULL)
274                 return NULL;
275
276         rc = exynos_param_data_get(exynos_camera, key, &data, EXYNOS_PARAM_STRING);
277         if (rc < 0) {
278                 LOGE("%s: Unable to get data for key %s", __func__, key);
279                 return NULL;
280         }
281
282         return data.string;
283 }
284
285 int exynos_param_int_set(struct exynos_camera *exynos_camera,
286         char *key, int integer)
287 {
288         union exynos_param_data data;
289         int rc;
290
291         if (exynos_camera == NULL || key == NULL)
292                 return -EINVAL;
293
294         data.integer = integer;
295
296         rc = exynos_param_data_set(exynos_camera, key, data, EXYNOS_PARAM_INT);
297         if (rc < 0) {
298                 LOGE("%s: Unable to set data for key %s", __func__, key);
299                 return -1;
300         }
301
302         return 0;
303 }
304
305 int exynos_param_float_set(struct exynos_camera *exynos_camera,
306         char *key, float floating)
307 {
308         union exynos_param_data data;
309         int rc;
310
311         if (exynos_camera == NULL || key == NULL)
312                 return -EINVAL;
313
314         data.floating = floating;
315
316         rc = exynos_param_data_set(exynos_camera, key, data, EXYNOS_PARAM_FLOAT);
317         if (rc < 0) {
318                 LOGE("%s: Unable to set data for key %s", __func__, key);
319                 return -1;
320         }
321
322         return 0;
323 }
324
325 int exynos_param_string_set(struct exynos_camera *exynos_camera,
326         char *key, char *string)
327 {
328         union exynos_param_data data;
329         int rc;
330
331         if (exynos_camera == NULL || key == NULL || string == NULL)
332                 return -EINVAL;
333
334         data.string = string;
335
336         rc = exynos_param_data_set(exynos_camera, key, data, EXYNOS_PARAM_STRING);
337         if (rc < 0) {
338                 LOGE("%s: Unable to set data for key %s", __func__, key);
339                 return -1;
340         }
341
342         return 0;
343 }
344
345 char *exynos_params_string_get(struct exynos_camera *exynos_camera)
346 {
347         struct exynos_param *param;
348         struct list_head *list;
349         char *string = NULL;
350         char *s = NULL;
351         int length = 0;
352         int l = 0;
353
354         if (exynos_camera == NULL)
355                 return NULL;
356
357         list = (struct list_head *) exynos_camera->params;
358         while (list != NULL) {
359                 param = (struct exynos_param *) list;
360                 if (param->key == NULL)
361                         goto list_continue_length;
362
363                 length += strlen(param->key);
364                 length++;
365
366                 switch (param->type) {
367                         case EXYNOS_PARAM_INT:
368                         case EXYNOS_PARAM_FLOAT:
369                                 length += 16;
370                                 break;
371                         case EXYNOS_PARAM_STRING:
372                                 length += strlen(param->data.string);
373                                 break;
374                         default:
375                                 LOGE("%s: Invalid type", __func__);
376                                 return NULL;
377                 }
378
379                 length++;
380
381 list_continue_length:
382                 list = list->next;
383         }
384
385         if (length == 0)
386                 return NULL;
387
388         string = calloc(1, length);
389         s = string;
390
391         list = (struct list_head *) exynos_camera->params;
392         while (list != NULL) {
393                 param = (struct exynos_param *) list;
394                 if (param->key == NULL)
395                         goto list_continue;
396
397                 l = sprintf(s, "%s=", param->key);
398                 s += l;
399
400                 switch (param->type) {
401                         case EXYNOS_PARAM_INT:
402                                 l = snprintf(s, 16, "%d", param->data.integer);
403                                 s += l;
404                                 break;
405                         case EXYNOS_PARAM_FLOAT:
406                                 l = snprintf(s, 16, "%g", param->data.floating);
407                                 s += l;
408                                 break;
409                         case EXYNOS_PARAM_STRING:
410                                 l = sprintf(s, "%s", param->data.string);
411                                 s += l;
412                                 break;
413                         default:
414                                 LOGE("%s: Invalid type", __func__);
415                                 return NULL;
416                 }
417
418                 if (list->next != NULL) {
419                         *s = ';';
420                         s++;
421                 } else {
422                         *s = '\0';
423                         break;
424                 }
425
426 list_continue:
427                 list = list->next;
428         }
429
430         return string;
431 }
432
433 int exynos_params_string_set(struct exynos_camera *exynos_camera, char *string)
434 {
435         union exynos_param_data data;
436         enum exynos_param_type type;
437
438         char *d = NULL;
439         char *s = NULL;
440         char *k = NULL;
441         char *v = NULL;
442
443         char *key;
444         char *value;
445
446         int rc;
447         int i;
448
449         if (exynos_camera == NULL || string == NULL)
450                 return -1;
451
452         d = strdup(string);
453         s = d;
454
455         while (1) {
456                 k = strchr(s, '=');
457                 if (k == NULL)
458                         break;
459                 *k = '\0';
460                 key = s;
461
462                 v = strchr(k+1, ';');
463                 if (v != NULL)
464                         *v = '\0';
465                 value = k+1;
466
467                 k = value;
468                 if (isdigit(k[0]) || k[0] == '-') {
469                         type = EXYNOS_PARAM_INT;
470
471                         for (i=1 ; k[i] != '\0' ; i++) {
472                                 if (k[i] == '.') {
473                                         type = EXYNOS_PARAM_FLOAT;
474                                 } else if (!isdigit(k[i])) {
475                                         type = EXYNOS_PARAM_STRING;
476                                         break;
477                                 }
478                         }
479                 } else {
480                         type = EXYNOS_PARAM_STRING;
481                 }
482
483                 switch (type) {
484                         case EXYNOS_PARAM_INT:
485                                 data.integer = atoi(value);
486                                 break;
487                         case EXYNOS_PARAM_FLOAT:
488                                 data.floating = atof(value);
489                                 break;
490                         case EXYNOS_PARAM_STRING:
491                                 data.string = value;
492                                 break;
493                         default:
494                                 LOGE("%s: Invalid type", __func__);
495                                 goto error;
496                 }
497
498                 rc = exynos_param_data_set(exynos_camera, key, data, type);
499                 if (rc < 0) {
500                         LOGE("%s: Unable to set data for key %s", __func__, key);
501                         goto error;
502                 }
503
504                 if (v == NULL)
505                         break;
506
507                 s = v+1;
508         }
509
510         if (d != NULL)
511                 free(d);
512
513         return 0;
514
515 error:
516         if (d != NULL)
517                 free(d);
518
519         return -1;
520 }