diff options
Diffstat (limited to 'camera/smdk4x12_param.c')
-rw-r--r-- | camera/smdk4x12_param.c | 492 |
1 files changed, 492 insertions, 0 deletions
diff --git a/camera/smdk4x12_param.c b/camera/smdk4x12_param.c new file mode 100644 index 0000000..b39ec7e --- /dev/null +++ b/camera/smdk4x12_param.c @@ -0,0 +1,492 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * 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 "smdk4x12_param" +#include <utils/Log.h> + +#include "smdk4x12_camera.h" + +int smdk4x12_param_register(struct smdk4x12_camera *smdk4x12_camera, char *key, + union smdk4x12_param_data data, enum smdk4x12_param_type type) +{ + struct list_head *list_end; + struct list_head *list; + struct smdk4x12_param *param; + + if (smdk4x12_camera == NULL || key == NULL) + return -EINVAL; + + param = (struct smdk4x12_param *) calloc(1, sizeof(struct smdk4x12_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: + ALOGE("%s: Invalid type", __func__); + goto error; + } + param->type = type; + + list_end = (struct list_head *) smdk4x12_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 (smdk4x12_camera->params == NULL) + smdk4x12_camera->params = param; + + return 0; + +error: + if (param != NULL) { + if (param->key != NULL) + free(param->key); + + free(param); + } + + return -1; +} + +void smdk4x12_param_unregister(struct smdk4x12_camera *smdk4x12_camera, + struct smdk4x12_param *param) +{ + struct list_head *list; + + if (smdk4x12_camera == NULL || param == NULL) + return; + + list = (struct list_head *) smdk4x12_camera->params; + while (list != NULL) { + if ((void *) list == (void *) param) { + list_head_remove(list); + + if ((void *) list == (void *) smdk4x12_camera->params) + smdk4x12_camera->params = (struct smdk4x12_param *) list->next; + + if (param->type == EXYNOS_PARAM_STRING && param->data.string != NULL) + free(param->data.string); + + memset(param, 0, sizeof(struct smdk4x12_param)); + free(param); + + break; + } + +list_continue: + list = list->next; + } +} + +struct smdk4x12_param *smdk4x12_param_find_key(struct smdk4x12_camera *smdk4x12_camera, + char *key) +{ + struct smdk4x12_param *param; + struct list_head *list; + + if (smdk4x12_camera == NULL || key == NULL) + return NULL; + + list = (struct list_head *) smdk4x12_camera->params; + while (list != NULL) { + param = (struct smdk4x12_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 smdk4x12_param_data_set(struct smdk4x12_camera *smdk4x12_camera, char *key, + union smdk4x12_param_data data, enum smdk4x12_param_type type) +{ + struct smdk4x12_param *param; + + if (smdk4x12_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 = smdk4x12_param_find_key(smdk4x12_camera, key); + if (param == NULL) { + // The key isn't in the list yet + smdk4x12_param_register(smdk4x12_camera, key, data, type); + return 0; + } + + if (param->type != type) + ALOGE("%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: + ALOGE("%s: Invalid type", __func__); + return -1; + } + param->type = type; + + return 0; +} + +int smdk4x12_param_data_get(struct smdk4x12_camera *smdk4x12_camera, char *key, + union smdk4x12_param_data *data, enum smdk4x12_param_type type) +{ + struct smdk4x12_param *param; + + if (smdk4x12_camera == NULL || key == NULL || data == NULL) + return -EINVAL; + + param = smdk4x12_param_find_key(smdk4x12_camera, key); + if (param == NULL || param->type != type) + return -1; + + memcpy(data, ¶m->data, sizeof(param->data)); + + return 0; +} + +int smdk4x12_param_int_get(struct smdk4x12_camera *smdk4x12_camera, + char *key) +{ + union smdk4x12_param_data data; + int rc; + + if (smdk4x12_camera == NULL || key == NULL) + return -EINVAL; + + rc = smdk4x12_param_data_get(smdk4x12_camera, key, &data, EXYNOS_PARAM_INT); + if (rc < 0) { + ALOGE("%s: Unable to get data for key %s", __func__, key); + return -1; + } + + return data.integer; +} + +float smdk4x12_param_float_get(struct smdk4x12_camera *smdk4x12_camera, + char *key) +{ + union smdk4x12_param_data data; + int rc; + + if (smdk4x12_camera == NULL || key == NULL) + return -EINVAL; + + rc = smdk4x12_param_data_get(smdk4x12_camera, key, &data, EXYNOS_PARAM_FLOAT); + if (rc < 0) { + ALOGE("%s: Unable to get data for key %s", __func__, key); + return -1; + } + + return data.floating; +} + +char *smdk4x12_param_string_get(struct smdk4x12_camera *smdk4x12_camera, + char *key) +{ + union smdk4x12_param_data data; + int rc; + + if (smdk4x12_camera == NULL || key == NULL) + return NULL; + + rc = smdk4x12_param_data_get(smdk4x12_camera, key, &data, EXYNOS_PARAM_STRING); + if (rc < 0) { + ALOGE("%s: Unable to get data for key %s", __func__, key); + return NULL; + } + + return data.string; +} + +int smdk4x12_param_int_set(struct smdk4x12_camera *smdk4x12_camera, + char *key, int integer) +{ + union smdk4x12_param_data data; + int rc; + + if (smdk4x12_camera == NULL || key == NULL) + return -EINVAL; + + data.integer = integer; + + rc = smdk4x12_param_data_set(smdk4x12_camera, key, data, EXYNOS_PARAM_INT); + if (rc < 0) { + ALOGE("%s: Unable to set data for key %s", __func__, key); + return -1; + } + + return 0; +} + +int smdk4x12_param_float_set(struct smdk4x12_camera *smdk4x12_camera, + char *key, float floating) +{ + union smdk4x12_param_data data; + int rc; + + if (smdk4x12_camera == NULL || key == NULL) + return -EINVAL; + + data.floating = floating; + + rc = smdk4x12_param_data_set(smdk4x12_camera, key, data, EXYNOS_PARAM_FLOAT); + if (rc < 0) { + ALOGE("%s: Unable to set data for key %s", __func__, key); + return -1; + } + + return 0; +} + +int smdk4x12_param_string_set(struct smdk4x12_camera *smdk4x12_camera, + char *key, char *string) +{ + union smdk4x12_param_data data; + int rc; + + if (smdk4x12_camera == NULL || key == NULL || string == NULL) + return -EINVAL; + + data.string = string; + + rc = smdk4x12_param_data_set(smdk4x12_camera, key, data, EXYNOS_PARAM_STRING); + if (rc < 0) { + ALOGE("%s: Unable to set data for key %s", __func__, key); + return -1; + } + + return 0; +} + +char *smdk4x12_params_string_get(struct smdk4x12_camera *smdk4x12_camera) +{ + struct smdk4x12_param *param; + struct list_head *list; + char *string = NULL; + char *s = NULL; + int length = 0; + int l = 0; + + if (smdk4x12_camera == NULL) + return NULL; + + list = (struct list_head *) smdk4x12_camera->params; + while (list != NULL) { + param = (struct smdk4x12_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: + ALOGE("%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 *) smdk4x12_camera->params; + while (list != NULL) { + param = (struct smdk4x12_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: + ALOGE("%s: Invalid type", __func__); + return NULL; + } + + if (list->next != NULL) { + *s = ';'; + s++; + } else { + *s = '\0'; + break; + } + +list_continue: + list = list->next; + } + + return string; +} + +int smdk4x12_params_string_set(struct smdk4x12_camera *smdk4x12_camera, char *string) +{ + union smdk4x12_param_data data; + enum smdk4x12_param_type type; + + char *d = NULL; + char *s = NULL; + char *k = NULL; + char *v = NULL; + + char *key; + char *value; + + int rc; + int i; + + if (smdk4x12_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: + ALOGE("%s: Invalid type", __func__); + goto error; + } + + rc = smdk4x12_param_data_set(smdk4x12_camera, key, data, type); + if (rc < 0) { + ALOGE("%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; +} |