summaryrefslogtreecommitdiffstats
path: root/camera/exynos_param.c
diff options
context:
space:
mode:
Diffstat (limited to 'camera/exynos_param.c')
-rw-r--r--camera/exynos_param.c520
1 files changed, 520 insertions, 0 deletions
diff --git a/camera/exynos_param.c b/camera/exynos_param.c
new file mode 100644
index 0000000..17b0450
--- /dev/null
+++ b/camera/exynos_param.c
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) 2013 Paul Kocialkowski
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <malloc.h>
+#include <ctype.h>
+
+#define LOG_TAG "exynos_param"
+#include <utils/Log.h>
+
+#include "exynos_camera.h"
+
+int list_head_insert(struct list_head *list, struct list_head *prev,
+ struct list_head *next)
+{
+ if (list == NULL)
+ return -EINVAL;
+
+ list->prev = prev;
+ list->next = next;
+
+ if(prev != NULL)
+ prev->next = list;
+ if(next != NULL)
+ next->prev = list;
+
+ return 0;
+}
+
+void list_head_remove(struct list_head *list)
+{
+ if(list == NULL)
+ return;
+
+ if(list->next != NULL)
+ list->next->prev = list->prev;
+ if(list->prev != NULL)
+ list->prev->next = list->next;
+}
+
+int exynos_param_register(struct exynos_camera *exynos_camera, char *key,
+ union exynos_param_data data, enum exynos_param_type type)
+{
+ struct list_head *list_end;
+ struct list_head *list;
+ struct exynos_param *param;
+
+ if (exynos_camera == NULL || key == NULL)
+ return -EINVAL;
+
+ param = (struct exynos_param *) calloc(1, sizeof(struct exynos_param));
+ if (param == NULL)
+ return -ENOMEM;
+
+ param->key = strdup(key);
+ switch (type) {
+ case EXYNOS_PARAM_INT:
+ param->data.integer = data.integer;
+ break;
+ case EXYNOS_PARAM_FLOAT:
+ param->data.floating = data.floating;
+ break;
+ case EXYNOS_PARAM_STRING:
+ param->data.string = strdup(data.string);
+ break;
+ default:
+ LOGE("%s: Invalid type", __func__);
+ goto error;
+ }
+ param->type = type;
+
+ list_end = (struct list_head *) exynos_camera->params;
+ while (list_end != NULL && list_end->next != NULL)
+ list_end = list_end->next;
+
+ list = (struct list_head *) param;
+ list_head_insert(list, list_end, NULL);
+
+ if (exynos_camera->params == NULL)
+ exynos_camera->params = param;
+
+ return 0;
+
+error:
+ if (param != NULL) {
+ if (param->key != NULL)
+ free(param->key);
+
+ free(param);
+ }
+
+ return -1;
+}
+
+void exynos_param_unregister(struct exynos_camera *exynos_camera,
+ struct exynos_param *param)
+{
+ struct list_head *list;
+
+ if (exynos_camera == NULL || param == NULL)
+ return;
+
+ list = (struct list_head *) exynos_camera->params;
+ while (list != NULL) {
+ if ((void *) list == (void *) param) {
+ list_head_remove(list);
+
+ if ((void *) list == (void *) exynos_camera->params)
+ exynos_camera->params = (struct exynos_param *) list->next;
+
+ if (param->type == EXYNOS_PARAM_STRING && param->data.string != NULL)
+ free(param->data.string);
+
+ memset(param, 0, sizeof(struct exynos_param));
+ free(param);
+
+ break;
+ }
+
+list_continue:
+ list = list->next;
+ }
+}
+
+struct exynos_param *exynos_param_find_key(struct exynos_camera *exynos_camera,
+ char *key)
+{
+ struct exynos_param *param;
+ struct list_head *list;
+
+ if (exynos_camera == NULL || key == NULL)
+ return NULL;
+
+ list = (struct list_head *) exynos_camera->params;
+ while (list != NULL) {
+ param = (struct exynos_param *) list;
+ if (param->key == NULL)
+ goto list_continue;
+
+ if (strcmp(param->key, key) == 0)
+ return param;
+
+list_continue:
+ list = list->next;
+ }
+
+ return NULL;
+}
+
+int exynos_param_data_set(struct exynos_camera *exynos_camera, char *key,
+ union exynos_param_data data, enum exynos_param_type type)
+{
+ struct exynos_param *param;
+
+ if (exynos_camera == NULL || key == NULL)
+ return -EINVAL;
+
+ if (strchr(key, '=') || strchr(key, ';'))
+ return -EINVAL;
+
+ if (type == EXYNOS_PARAM_STRING && data.string != NULL &&
+ (strchr(data.string, '=') || strchr(data.string, ';')))
+ return -EINVAL;
+
+ param = exynos_param_find_key(exynos_camera, key);
+ if (param == NULL) {
+ // The key isn't in the list yet
+ exynos_param_register(exynos_camera, key, data, type);
+ return 0;
+ }
+
+ if (param->type != type)
+ LOGE("%s: Mismatching types for key %s", __func__, key);
+
+ if (param->type == EXYNOS_PARAM_STRING && param->data.string != NULL)
+ free(param->data.string);
+
+ switch (type) {
+ case EXYNOS_PARAM_INT:
+ param->data.integer = data.integer;
+ break;
+ case EXYNOS_PARAM_FLOAT:
+ param->data.floating = data.floating;
+ break;
+ case EXYNOS_PARAM_STRING:
+ param->data.string = strdup(data.string);
+ break;
+ default:
+ LOGE("%s: Invalid type", __func__);
+ return -1;
+ }
+ param->type = type;
+
+ return 0;
+}
+
+int exynos_param_data_get(struct exynos_camera *exynos_camera, char *key,
+ union exynos_param_data *data, enum exynos_param_type type)
+{
+ struct exynos_param *param;
+
+ if (exynos_camera == NULL || key == NULL || data == NULL)
+ return -EINVAL;
+
+ param = exynos_param_find_key(exynos_camera, key);
+ if (param == NULL || param->type != type)
+ return -1;
+
+ memcpy(data, &param->data, sizeof(param->data));
+
+ return 0;
+}
+
+int exynos_param_int_get(struct exynos_camera *exynos_camera,
+ char *key)
+{
+ union exynos_param_data data;
+ int rc;
+
+ if (exynos_camera == NULL || key == NULL)
+ return -EINVAL;
+
+ rc = exynos_param_data_get(exynos_camera, key, &data, EXYNOS_PARAM_INT);
+ if (rc < 0) {
+ LOGE("%s: Unable to get data for key %s", __func__, key);
+ return -1;
+ }
+
+ return data.integer;
+}
+
+float exynos_param_float_get(struct exynos_camera *exynos_camera,
+ char *key)
+{
+ union exynos_param_data data;
+ int rc;
+
+ if (exynos_camera == NULL || key == NULL)
+ return -EINVAL;
+
+ rc = exynos_param_data_get(exynos_camera, key, &data, EXYNOS_PARAM_FLOAT);
+ if (rc < 0) {
+ LOGE("%s: Unable to get data for key %s", __func__, key);
+ return -1;
+ }
+
+ return data.floating;
+}
+
+char *exynos_param_string_get(struct exynos_camera *exynos_camera,
+ char *key)
+{
+ union exynos_param_data data;
+ int rc;
+
+ if (exynos_camera == NULL || key == NULL)
+ return NULL;
+
+ rc = exynos_param_data_get(exynos_camera, key, &data, EXYNOS_PARAM_STRING);
+ if (rc < 0) {
+ LOGE("%s: Unable to get data for key %s", __func__, key);
+ return NULL;
+ }
+
+ return data.string;
+}
+
+int exynos_param_int_set(struct exynos_camera *exynos_camera,
+ char *key, int integer)
+{
+ union exynos_param_data data;
+ int rc;
+
+ if (exynos_camera == NULL || key == NULL)
+ return -EINVAL;
+
+ data.integer = integer;
+
+ rc = exynos_param_data_set(exynos_camera, key, data, EXYNOS_PARAM_INT);
+ if (rc < 0) {
+ LOGE("%s: Unable to set data for key %s", __func__, key);
+ return -1;
+ }
+
+ return 0;
+}
+
+int exynos_param_float_set(struct exynos_camera *exynos_camera,
+ char *key, float floating)
+{
+ union exynos_param_data data;
+ int rc;
+
+ if (exynos_camera == NULL || key == NULL)
+ return -EINVAL;
+
+ data.floating = floating;
+
+ rc = exynos_param_data_set(exynos_camera, key, data, EXYNOS_PARAM_FLOAT);
+ if (rc < 0) {
+ LOGE("%s: Unable to set data for key %s", __func__, key);
+ return -1;
+ }
+
+ return 0;
+}
+
+int exynos_param_string_set(struct exynos_camera *exynos_camera,
+ char *key, char *string)
+{
+ union exynos_param_data data;
+ int rc;
+
+ if (exynos_camera == NULL || key == NULL || string == NULL)
+ return -EINVAL;
+
+ data.string = string;
+
+ rc = exynos_param_data_set(exynos_camera, key, data, EXYNOS_PARAM_STRING);
+ if (rc < 0) {
+ LOGE("%s: Unable to set data for key %s", __func__, key);
+ return -1;
+ }
+
+ return 0;
+}
+
+char *exynos_params_string_get(struct exynos_camera *exynos_camera)
+{
+ struct exynos_param *param;
+ struct list_head *list;
+ char *string = NULL;
+ char *s = NULL;
+ int length = 0;
+ int l = 0;
+
+ if (exynos_camera == NULL)
+ return NULL;
+
+ list = (struct list_head *) exynos_camera->params;
+ while (list != NULL) {
+ param = (struct exynos_param *) list;
+ if (param->key == NULL)
+ goto list_continue_length;
+
+ length += strlen(param->key);
+ length++;
+
+ switch (param->type) {
+ case EXYNOS_PARAM_INT:
+ case EXYNOS_PARAM_FLOAT:
+ length += 16;
+ break;
+ case EXYNOS_PARAM_STRING:
+ length += strlen(param->data.string);
+ break;
+ default:
+ LOGE("%s: Invalid type", __func__);
+ return NULL;
+ }
+
+ length++;
+
+list_continue_length:
+ list = list->next;
+ }
+
+ if (length == 0)
+ return NULL;
+
+ string = calloc(1, length);
+ s = string;
+
+ list = (struct list_head *) exynos_camera->params;
+ while (list != NULL) {
+ param = (struct exynos_param *) list;
+ if (param->key == NULL)
+ goto list_continue;
+
+ l = sprintf(s, "%s=", param->key);
+ s += l;
+
+ switch (param->type) {
+ case EXYNOS_PARAM_INT:
+ l = snprintf(s, 16, "%d", param->data.integer);
+ s += l;
+ break;
+ case EXYNOS_PARAM_FLOAT:
+ l = snprintf(s, 16, "%g", param->data.floating);
+ s += l;
+ break;
+ case EXYNOS_PARAM_STRING:
+ l = sprintf(s, "%s", param->data.string);
+ s += l;
+ break;
+ default:
+ LOGE("%s: Invalid type", __func__);
+ return NULL;
+ }
+
+ if (list->next != NULL) {
+ *s = ';';
+ s++;
+ } else {
+ *s = '\0';
+ break;
+ }
+
+list_continue:
+ list = list->next;
+ }
+
+ return string;
+}
+
+int exynos_params_string_set(struct exynos_camera *exynos_camera, char *string)
+{
+ union exynos_param_data data;
+ enum exynos_param_type type;
+
+ char *d = NULL;
+ char *s = NULL;
+ char *k = NULL;
+ char *v = NULL;
+
+ char *key;
+ char *value;
+
+ int rc;
+ int i;
+
+ if (exynos_camera == NULL || string == NULL)
+ return -1;
+
+ d = strdup(string);
+ s = d;
+
+ while (1) {
+ k = strchr(s, '=');
+ if (k == NULL)
+ break;
+ *k = '\0';
+ key = s;
+
+ v = strchr(k+1, ';');
+ if (v != NULL)
+ *v = '\0';
+ value = k+1;
+
+ k = value;
+ if (isdigit(k[0]) || k[0] == '-') {
+ type = EXYNOS_PARAM_INT;
+
+ for (i=1 ; k[i] != '\0' ; i++) {
+ if (k[i] == '.') {
+ type = EXYNOS_PARAM_FLOAT;
+ } else if (!isdigit(k[i])) {
+ type = EXYNOS_PARAM_STRING;
+ break;
+ }
+ }
+ } else {
+ type = EXYNOS_PARAM_STRING;
+ }
+
+ switch (type) {
+ case EXYNOS_PARAM_INT:
+ data.integer = atoi(value);
+ break;
+ case EXYNOS_PARAM_FLOAT:
+ data.floating = atof(value);
+ break;
+ case EXYNOS_PARAM_STRING:
+ data.string = value;
+ break;
+ default:
+ LOGE("%s: Invalid type", __func__);
+ goto error;
+ }
+
+ rc = exynos_param_data_set(exynos_camera, key, data, type);
+ if (rc < 0) {
+ LOGE("%s: Unable to set data for key %s", __func__, key);
+ goto error;
+ }
+
+ if (v == NULL)
+ break;
+
+ s = v+1;
+ }
+
+ if (d != NULL)
+ free(d);
+
+ return 0;
+
+error:
+ if (d != NULL)
+ free(d);
+
+ return -1;
+}