summaryrefslogtreecommitdiffstats
path: root/udrv
diff options
context:
space:
mode:
authorAndre Eisenbach <andre@broadcom.com>2012-02-22 13:18:21 -0800
committerMatthew Xie <mattx@google.com>2012-07-14 11:19:11 -0700
commite448862a47c08eb23185aaed574b39264f5005fc (patch)
tree2bc6246e3091315e77224fd798ea2fe8074ef972 /udrv
parenta2ca4b83ab8bbbfd8d5f6693e927ed4b82094624 (diff)
downloadexternal_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.zip
external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.gz
external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.bz2
Initial Bluedroid stack commit
Diffstat (limited to 'udrv')
-rw-r--r--udrv/include/unv.h205
-rw-r--r--udrv/ulinux/uipc_linux.h36
-rw-r--r--udrv/ulinux/unv_linux.c818
3 files changed, 1059 insertions, 0 deletions
diff --git a/udrv/include/unv.h b/udrv/include/unv.h
new file mode 100644
index 0000000..9e85bc8
--- /dev/null
+++ b/udrv/include/unv.h
@@ -0,0 +1,205 @@
+/************************************************************************************
+ *
+ * Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ * This program is the proprietary software of Broadcom Corporation and/or its
+ * licensors, and may only be used, duplicated, modified or distributed
+ * pursuant to the terms and conditions of a separate, written license
+ * agreement executed between you and Broadcom (an "Authorized License").
+ * Except as set forth in an Authorized License, Broadcom grants no license
+ * (express or implied), right to use, or waiver of any kind with respect to
+ * the Software, and Broadcom expressly reserves all rights in and to the
+ * Software and all intellectual property rights therein.
+ * IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS
+ * SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE
+ * ALL USE OF THE SOFTWARE.
+ *
+ * Except as expressly set forth in the Authorized License,
+ *
+ * 1. This program, including its structure, sequence and organization,
+ * constitutes the valuable trade secrets of Broadcom, and you shall
+ * use all reasonable efforts to protect the confidentiality thereof,
+ * and to use this information only in connection with your use of
+ * Broadcom integrated circuit products.
+ *
+ * 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED
+ * "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES,
+ * REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY,
+ * OR OTHERWISE, WITH RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY
+ * DISCLAIMS ANY AND ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
+ * NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES,
+ * ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
+ * CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT
+ * OF USE OR PERFORMANCE OF THE SOFTWARE.
+ *
+ * 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR
+ * ITS LICENSORS BE LIABLE FOR
+ * (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR EXEMPLARY
+ * DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO
+ * YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM
+ * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES; OR
+ * (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT ACTUALLY PAID FOR THE
+ * SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
+ * LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF
+ * ESSENTIAL PURPOSE OF ANY LIMITED REMEDY.
+ *
+ ************************************************************************************/
+
+/************************************************************************************
+ *
+ * Filename: unv.h
+ *
+ * Description: Universal NV Ram API
+ *
+ ***********************************************************************************/
+
+#ifndef UNV_H
+#define UNV_H
+
+/************************************************************************************
+** Constants & Macros
+************************************************************************************/
+
+/* any keyfile line cannot exceed this length */
+#define UNV_MAXLINE_LENGTH (2048)
+
+/************************************************************************************
+** Type definitions for callback functions
+************************************************************************************/
+typedef int (*unv_iter_cb)(char *key, char *val, void *userdata);
+
+/************************************************************************************
+** Type definitions and return values
+************************************************************************************/
+
+/************************************************************************************
+** Extern variables and functions
+************************************************************************************/
+
+/************************************************************************************
+** Functions
+************************************************************************************/
+
+/******************************************************************************
+**
+** Function unv_create_directory
+**
+** Description Creates directory, if full path is not available it
+** will construct it. Must be called from BTIF task context.
+**
+** Parameters
+** path : directory path to be created
+**
+** Returns 0 if successful, -1 if failure
+**
+*******************************************************************************/
+
+int unv_create_directory(const char *path);
+
+
+/*******************************************************************************
+**
+** Function unv_create_file
+**
+** Description Creates file
+** Must be called from BTIF task context
+**
+** Parameters
+** filename : file path to be created
+**
+** Returns 0 if successful, -1 if failure
+**
+*******************************************************************************/
+
+int unv_create_file(const char *filename);
+
+/*******************************************************************************
+**
+** Function unv_read_key
+**
+** Description Reads keyvalue from file
+** Path must be an existing absolute path
+** Must be called from BTIF task context
+**
+** Parameters
+** path : path of keyfile
+** key : key string to query for
+** p_out : output line buffer supplied by caller
+** out_len : max length of output buffer
+**
+** Returns Returns buffer of key value.
+**
+*******************************************************************************/
+
+char* unv_read_key( const char *path,
+ const char *key,
+ char *p_out,
+ int out_len);
+
+/*******************************************************************************
+**
+** Function unv_read_key_iter
+**
+** Description Reads keyvalue from file iteratively
+** Path must be an existing absolute path
+** cb is the callback that is invoked for each entry read
+** Must be called from BTIF task context
+**
+** Parameters
+** path : path of keyfile
+** cb : iteration callback
+** userdata : context specific userdata passed onto callback
+**
+** Returns 0 if successful, -1 if failure
+**
+*******************************************************************************/
+
+int unv_read_key_iter( const char *path,
+ unv_iter_cb cb,
+ void *userdata );
+
+
+/*******************************************************************************
+**
+** Function unv_write_key
+**
+** Description Writes key to file. If key value exists it will be updated
+** Path must be an existing absolute path
+** Must be called from BTIF task context
+**
+** Parameters
+** path : path of keyfile
+** key : key string to write
+** value : value string to set for this key
+**
+** Returns 0 if successful, -1 if failure
+**
+*******************************************************************************/
+
+int unv_write_key( const char *path,
+ const char *key,
+ const char *value );
+
+
+/*******************************************************************************
+**
+** Function unv_remove_key
+**
+** Description Removes keyvalue from file
+** Path must be an existing absolute path
+** Must be called from BTIF task context
+**
+** Parameters
+** path : path of keyfile
+** key : key string to delete
+**
+** Returns 0 if successful, -1 if failure
+**
+*******************************************************************************/
+
+int unv_remove_key( const char *path,
+ const char *key );
+
+#endif /* UNV_H */
+
+
diff --git a/udrv/ulinux/uipc_linux.h b/udrv/ulinux/uipc_linux.h
new file mode 100644
index 0000000..5365806
--- /dev/null
+++ b/udrv/ulinux/uipc_linux.h
@@ -0,0 +1,36 @@
+/********************************************************************************
+** *
+** Name uipc_linux.h *
+** *
+** Function Linux specific UIPC definitions *
+** *
+** *
+** Copyright (c) 2007-2010, Broadcom Corp., All Rights Reserved. *
+** Proprietary and confidential. *
+** *
+*********************************************************************************/
+#ifndef _UIPC_LINUX_H_
+#define _UIPC_LINUX_H_
+
+typedef int SOCKET;
+#define INVALID_SOCKET (SOCKET)(-1)
+#define SOCKET_ERROR (-1)
+
+/* tcp/ip socket configuration */
+typedef struct {
+ char *p_address;
+ unsigned int port;
+} tUIPC_LINUX_CFG_TCP ;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Socket configuration for GLGPS interface */
+extern tUIPC_LINUX_CFG_TCP uipc_linux_cfg_glgps;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _UIPC_LINUX_H_ */
diff --git a/udrv/ulinux/unv_linux.c b/udrv/ulinux/unv_linux.c
new file mode 100644
index 0000000..6737ca0
--- /dev/null
+++ b/udrv/ulinux/unv_linux.c
@@ -0,0 +1,818 @@
+/************************************************************************************
+ *
+ * Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ * This program is the proprietary software of Broadcom Corporation and/or its
+ * licensors, and may only be used, duplicated, modified or distributed
+ * pursuant to the terms and conditions of a separate, written license
+ * agreement executed between you and Broadcom (an "Authorized License").
+ * Except as set forth in an Authorized License, Broadcom grants no license
+ * (express or implied), right to use, or waiver of any kind with respect to
+ * the Software, and Broadcom expressly reserves all rights in and to the
+ * Software and all intellectual property rights therein.
+ * IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS
+ * SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE
+ * ALL USE OF THE SOFTWARE.
+ *
+ * Except as expressly set forth in the Authorized License,
+ *
+ * 1. This program, including its structure, sequence and organization,
+ * constitutes the valuable trade secrets of Broadcom, and you shall
+ * use all reasonable efforts to protect the confidentiality thereof,
+ * and to use this information only in connection with your use of
+ * Broadcom integrated circuit products.
+ *
+ * 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED
+ * "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES,
+ * REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY,
+ * OR OTHERWISE, WITH RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY
+ * DISCLAIMS ANY AND ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
+ * NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES,
+ * ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
+ * CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT
+ * OF USE OR PERFORMANCE OF THE SOFTWARE.
+ *
+ * 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR
+ * ITS LICENSORS BE LIABLE FOR
+ * (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR EXEMPLARY
+ * DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO
+ * YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM
+ * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES; OR
+ * (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT ACTUALLY PAID FOR THE
+ * SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
+ * LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF
+ * ESSENTIAL PURPOSE OF ANY LIMITED REMEDY.
+ *
+ ************************************************************************************/
+
+/************************************************************************************
+ *
+ * Filename: unv_linux.c
+ *
+ * Description: Universal NV Ram API.
+ * Manages all non volatile (file) database entries used by
+ * bluetooth upper layer stack.
+ *
+ ***********************************************************************************/
+
+#include "unv.h"
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <sys/prctl.h>
+#include <pthread.h>
+
+#define LOG_TAG "UNV_LINUX"
+#include <utils/Log.h>
+
+/************************************************************************************
+** Constants & Macros
+************************************************************************************/
+
+#define info(fmt, ...) LOGI ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
+#define debug(fmt, ...) LOGD ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
+#define verbose(fmt, ...) //LOGD ("%s: " fmt, __FUNCTION__, ## __VA_ARGS__)
+#define error(fmt, ...) LOGE ("##### ERROR : %s: " fmt "#####", __FUNCTION__, ## __VA_ARGS__)
+
+#define UNV_DELIM "\r\n"
+
+/* fixme -- incorporate field delim definition */
+#define UNV_FIELD_DELIM " "
+
+/* keystring + space + valuestring + null terminate */
+#define KEYVAL_SZ(key, val) (strlen(key) + 1 + strlen(val) + strlen(UNV_DELIM) + 1)
+
+#define DIR_MODE 0740
+#define FILE_MODE 0644
+
+#define BTIF_TASK_STR "BTIF"
+
+/************************************************************************************
+** Local type definitions
+************************************************************************************/
+
+
+/************************************************************************************
+** Static variables
+************************************************************************************/
+
+/************************************************************************************
+** Static functions
+************************************************************************************/
+
+/************************************************************************************
+** Externs
+************************************************************************************/
+
+/************************************************************************************
+** Functions
+************************************************************************************/
+
+/*******************************************************************************
+**
+** Function check_caller_context
+**
+** Description Checks pthread name of caller. Currently only BTIF thread
+** is allowed to call in here to avoid multithreading issues
+**
+** Returns 1 if correct context, 0 otherwise
+**
+*******************************************************************************/
+
+static int check_caller_context(void)
+{
+ char name[16];
+
+ prctl(PR_GET_NAME, name, 0, 0, 0);
+
+ if (strncmp(name, BTIF_TASK_STR, strlen(BTIF_TASK_STR)) != 0)
+ {
+ error("only btif context allowed (%s)", name);
+ return 0;
+ }
+ return 1;
+}
+
+/*******************************************************************************
+**
+** Function mk_dir
+**
+** Description Create directory
+**
+** Returns 0 if successful, -1 if failure
+**
+*******************************************************************************/
+
+static int mk_dir(const char *path)
+{
+ struct stat st;
+
+ if (stat(path, &st) == 0)
+ {
+ if (!S_ISDIR(st.st_mode))
+ {
+ /* path is not a directory */
+ error("directory path %s is not a directory (%s)", path, strerror(errno));
+ return -1;
+ }
+
+ /* already exist */
+ return 0;
+ }
+
+ /* no existing dir path, try creating it */
+ if (mkdir(path, DIR_MODE) != 0)
+ {
+ error("failed to create dir [%s] (%s)", path, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function rm_dir
+**
+** Description Removes directory. Assumes empty directory
+**
+** Returns 0 if successful, -1 if failure
+**
+*******************************************************************************/
+
+static int rm_dir(const char *path)
+{
+ int status;
+
+ status = rmdir(path);
+
+ if (status < 0) {
+ error("rmdir %s failed (%s)", path, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function write_keyval
+**
+** Description Writes a key and value string to file descriptor
+**
+** Returns Nbr bytes written, -1 if failure
+**
+*******************************************************************************/
+
+static int write_keyval( int fd,
+ const char *key,
+ const char *val )
+{
+ int len = 0;
+ int written = 0;
+ int linesz = KEYVAL_SZ(key, val);
+ char *line;
+
+ /* check if written line would exceed the max read size of a line */
+ if (linesz > UNV_MAXLINE_LENGTH)
+ return -1;
+
+ line = malloc(linesz);
+
+ if (!line)
+ {
+ error("alloc failed (%s)", strerror(errno));
+ return -1;
+ }
+
+ len = sprintf(line, "%s %s%s", key, val, UNV_DELIM);
+
+ //info("write_keyval %s %s (%d bytes)", key, val, len);
+
+ /* update line */
+ written = write(fd, line, len);
+
+ free(line);
+
+ return written;
+}
+
+/*******************************************************************************
+**
+** Function update_key
+**
+** Description Updates existing keyvalue in file
+**
+** key : key string to be updated
+** value : updated value string, NULL removes line
+** pos_start : start offset of string to be updated
+** pos_stop : end offset of string to be updated
+**
+** Returns returns bytes written, -1 if failure
+**
+*******************************************************************************/
+
+static int update_key( int fd,
+ const char *key,
+ const char *value,
+ int pos_start,
+ int pos_stop )
+{
+ char *line;
+ char *p_tail = NULL;
+ int tail_sz;
+ struct stat st;
+ int len = 0;
+
+ if (value)
+ {
+ verbose("update key [%s %s]", key, value);
+ }
+ else
+ {
+ verbose("remove key [%s]", key);
+ }
+
+ /* update file with new value for this key */
+
+ if (fstat(fd, &st) != 0)
+ {
+ error("stat failed (%s)", strerror(errno));
+ return -1;
+ }
+
+ tail_sz = st.st_size-pos_stop;
+
+ if (tail_sz > 0)
+ {
+ /* allocate working area */
+ p_tail = malloc(tail_sz);
+
+ if (!p_tail)
+ {
+ error("malloc failed (%s)", strerror(errno));
+ return -1;
+ }
+
+ /* copy anything after updated line */
+ lseek(fd, pos_stop, SEEK_SET);
+
+ /* read reamining portion into cache */
+ if (read(fd, p_tail, tail_sz) < 0)
+ {
+ error("read failed %s", strerror(errno));
+ return -1;
+ }
+ }
+
+ /* rewind and update new line */
+ lseek(fd, pos_start, SEEK_SET);
+ len = pos_start;
+
+ /* a null key means remove entry */
+ if (value)
+ {
+ len += write_keyval(fd, key, value);
+ }
+
+ /* write tail content */
+ if (p_tail)
+ {
+ len += write(fd, p_tail, tail_sz);
+ free(p_tail);
+ }
+
+ /* finally truncate file to new length */
+ ftruncate(fd, len);
+
+ return len;
+}
+
+/******************************************************************************
+**
+** Function get_keyval
+**
+** Description Reads keyvalue from filedescriptor
+**
+** Parameters
+** fd : file descriptor of file to search
+** key : string to search for in keyfile
+** p_out : output buffer supplied by caller
+** out_len : max length of output line buffer
+** pos_begin : returns keyvalue start offset in file
+** pos_end : returns keyvalue end offset in file
+**
+** Returns String of key value, NULL if not found
+**
+******************************************************************************/
+
+static char *get_keyval( int fd,
+ const char *key,
+ char *p_out,
+ int out_len,
+ int *pos_begin,
+ int *pos_end)
+{
+ char *p_value = NULL;
+ struct stat st;
+ char *p_buf;
+ char *line;
+ char *p;
+
+ if (fstat(fd, &st) != 0)
+ {
+ error("stat failed (%s)", strerror(errno));
+ return NULL;
+ }
+
+ p_buf = malloc(st.st_size + 1);
+
+ if (!p_buf)
+ return NULL;
+
+ p = p_buf;
+
+ if (read(fd, p, st.st_size) < 0)
+ {
+ error("read failed %s", strerror(errno));
+ return NULL;
+ }
+ *(p_buf + st.st_size) = 0;
+
+ /* tokenize first line */
+ line = strtok(p, UNV_DELIM);
+
+ while (line && (p_value == NULL))
+ {
+ /* check for match */
+ if (strncmp(line, key, strlen(key)) == 0)
+ {
+ if (pos_begin)
+ *pos_begin = (line-p_buf);
+
+ /* point line to key value */
+ line += strlen(key) + 1;
+
+ /* make sure supplied buffer isn't overflowed */
+ if (out_len < (int)strlen(line))
+ {
+ error("output buffer too small (%d %d)", out_len, (int)strlen(line));
+ info("line %s\n", line);
+ return NULL;
+ }
+
+ p_value = p_out;
+ /* should be ok to just strcpy from 'line' as
+ * strrok shall null-terminate the token
+ * in the above call */
+ strcpy(p_value, line);
+
+ verbose("found [%s=%s]", key, p_value);
+
+ if (pos_end)
+ *pos_end = (line-p_buf) + strlen(line) + strlen(UNV_DELIM);
+ }
+
+ /* check next line */
+ line = strtok(NULL, UNV_DELIM);
+ }
+
+ free(p_buf);
+
+ /* rewind */
+ lseek(fd, 0, SEEK_SET);
+
+ return p_value;
+}
+
+
+/*****************************************************************************
+**
+** MAIN API
+**
+******************************************************************************/
+
+
+
+
+
+/******************************************************************************
+**
+** Function unv_create_directory
+**
+** Description Creates directory, if full path is not available it
+** will construct it. Must be called from BTIF task context.
+**
+** Parameters
+** path : directory path to be created
+**
+** Returns 0 if successful, -1 if failure
+**
+*******************************************************************************/
+
+int unv_create_directory(const char *path)
+{
+ int status = 0;
+ char tmpbuf[128];
+ char *p_copy;
+ char *p;
+
+ verbose("CREATE DIR %s", path);
+
+ if (check_caller_context() == 0)
+ return -1;
+
+ /* assumes absolute paths */
+ if (strncmp(path, "./", 2) == 0)
+ {
+ error("%s not an absolute path", path);
+ return -1;
+ }
+
+ /* try creating dir directly */
+ if (mk_dir(path) == 0)
+ return 0;
+
+ /* directory does not exit, create it */
+
+ /* first make sure we won't overflow the path buffer */
+ if ((strlen(path)+1) > sizeof(tmpbuf))
+ return -1;
+
+ /* setup scratch buffer, make sure path is ended with / */
+ sprintf(tmpbuf, "%s/", path);
+
+ p_copy = tmpbuf;
+
+ p = strchr(p_copy+1, '/'); /* skip root */
+
+ while ((status == 0) && p)
+ {
+ /*
+ * temporarily null terminate to allow creating
+ * directories up to this point
+ */
+ *p= '\0';
+ status = mk_dir(p_copy);
+ *p= '/';
+
+ /* find next */
+ p = strchr(++p, '/');
+ }
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function unv_create_file
+**
+** Description Creates file
+** Must be called from BTIF task context
+**
+** Parameters
+** filename : file path to be created
+**
+** Returns 0 if successful, -1 if failure
+**
+*******************************************************************************/
+
+int unv_create_file(const char *filename)
+{
+ int fd;
+ char *p;
+ char *path = strdup(filename); /* rw copy */
+
+ if (check_caller_context() == 0)
+ return -1;
+
+ /* separate path from filename */
+ p = strrchr(path, '/');
+
+ if (p)
+ {
+ *p = '\0';
+ if (unv_create_directory(path) < 0)
+ {
+ free(path);
+ return -1;
+ }
+ }
+
+ free(path);
+
+ verbose("CREATE FILE %s", filename);
+
+ fd = open(filename, O_RDWR|O_CREAT, FILE_MODE);
+
+ if (fd < 0)
+ {
+ error("file failed to create %s errno: (%s)", filename, strerror(errno));
+ return -1;
+ }
+
+ close(fd);
+
+ return 0;
+}
+
+
+/*******************************************************************************
+**
+** Function unv_read_key
+**
+** Description Reads keyvalue from file
+** Path must be an existing absolute path
+** Must be called from BTIF task context
+**
+** Parameters
+** path : path of keyfile
+** key : key string to query for
+** p_out : output line buffer supplied by caller
+** out_len : max length of output buffer
+**
+** Returns Returns buffer of key value.
+**
+******************************************************************************/
+
+char* unv_read_key( const char *path,
+ const char *key,
+ char *p_out,
+ int out_len)
+{
+ int fd;
+ char *p_search;
+
+ verbose("READ KEY [%s]", key);
+
+ /* sanity check */
+ if (key == NULL)
+ return NULL;
+
+ if (check_caller_context() == 0)
+ return NULL;
+
+ fd = open(path, O_RDONLY, FILE_MODE);
+
+ if (fd < 0) {
+ error("file failed to open %s (%s)", path, strerror(errno));
+ return NULL;
+ }
+
+ p_search = get_keyval(fd, key, p_out, out_len, NULL, NULL);
+
+ close(fd);
+
+ return p_search;
+}
+
+/*******************************************************************************
+**
+** Function unv_read_key_iter
+**
+** Description Reads keyvalue from file iteratively
+** Path must be an existing absolute path
+** Must be called from BTIF task context
+**
+** Parameters
+** path : path of keyfile
+** cb : iteration callback invoked for each entry read
+** userdata : context specific userdata passed onto callback
+**
+** Returns 0 if successful, -1 if failure
+**
+*******************************************************************************/
+
+int unv_read_key_iter( const char *path,
+ unv_iter_cb cb,
+ void *userdata )
+{
+ int fd;
+ char *p, *p_buf;
+ struct stat st;
+ char *line;
+ int cnt = 0;
+
+ verbose("READ KEY ITER");
+
+ if (check_caller_context() == 0)
+ return -1;
+
+ fd = open(path, O_RDONLY, FILE_MODE);
+
+ if (fd < 0) {
+ error("file failed to open %s (%s)", path, strerror(errno));
+ return -1;
+ }
+
+ if (fstat(fd, &st) != 0)
+ {
+ error("stat failed (%s)", strerror(errno));
+ return -1;
+ }
+
+ p_buf = malloc(st.st_size + 1);
+
+ if (!p_buf)
+ return -1;
+
+ p = p_buf;
+
+ if (read(fd, p, st.st_size) < 0)
+ {
+ error("read failed %s", strerror(errno));
+ free(p_buf);
+ return -1;
+ }
+
+ *(p + st.st_size) = 0;
+
+ /* tokenize first line */
+ line = strtok(p, UNV_DELIM);
+ while (line)
+ {
+ char key[128], value[128];
+ char *needle;
+
+ needle = strchr(line, ' ');
+ memset(key, 0, sizeof(key));
+ memcpy(key, line, (needle-line));
+ needle++;
+ strcpy(value, needle);
+
+ cb(key, value, userdata);
+ cnt++;
+
+ line = strtok(NULL, UNV_DELIM);
+ }
+
+ free(p_buf);
+
+ close(fd);
+
+ return cnt;
+}
+
+/*******************************************************************************
+**
+** Function unv_write_key
+**
+** Description Writes key to file. If key value exists it will be updated
+** Path must be an existing absolute path
+** Must be called from BTIF task context
+**
+** Parameters
+** path : path of keyfile
+** key : key string to write
+** value : value string to set for this key
+**
+** Returns 0 if successful, -1 if failure
+**
+*******************************************************************************/
+
+int unv_write_key( const char *path,
+ const char *key,
+ const char *value )
+{
+ int fd;
+ int pos_start = 0;
+ int pos_stop = 0;
+ char *keyval = NULL;
+ char *p_line = malloc(UNV_MAXLINE_LENGTH);
+
+ verbose("WRITE KEY [%s %s]", key, value);
+
+ /* sanity check */
+ if (key == NULL)
+ return -1;
+
+ if (check_caller_context() == 0)
+ return -1;
+
+ fd = open(path, O_RDWR, FILE_MODE);
+
+ if (fd < 0)
+ {
+ error("file failed to create %s (%s)", path, strerror(errno));
+ return -1;
+ }
+
+ /* check if key already present */
+ keyval = get_keyval(fd, key, p_line, UNV_MAXLINE_LENGTH, &pos_start, &pos_stop);
+
+ if (keyval)
+ {
+ update_key(fd, key, value, pos_start, pos_stop);
+ }
+ else
+ {
+ /* append at end of file */
+ lseek(fd, 0, SEEK_END);
+ write_keyval(fd, key, value);
+ }
+
+ free(p_line);
+ close(fd);
+
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function unv_remove_key
+**
+** Description Removes keyvalue from file
+** Path must be an existing absolute path
+** Must be called from BTIF task context
+**
+** Parameters
+** path : path of keyfile
+** key : key string to delete
+**
+** Returns 0 if successful, -1 if failure
+**
+*******************************************************************************/
+
+int unv_remove_key( const char *path,
+ const char *key )
+{
+ int fd;
+ char *p_search;
+ int pos_begin = 0;
+ int pos_stop = 0;
+ char *p_line = malloc(UNV_MAXLINE_LENGTH);
+
+ verbose("READ KEY [%s]", key);
+
+ /* sanity check */
+ if (key == NULL)
+ return -1;
+
+ if (check_caller_context() == 0)
+ return -1;
+
+ fd = open(path, O_RDWR, FILE_MODE);
+
+ if (fd < 0) {
+ error("file failed to open %s (%s)", path, strerror(errno));
+ return -1;
+ }
+
+ p_search = get_keyval(fd, key, p_line, UNV_MAXLINE_LENGTH, &pos_begin, &pos_stop);
+
+ if (p_search)
+ {
+ /* NULL value entry means remove key/val line in file */
+ update_key(fd, key, NULL, pos_begin, pos_stop);
+ }
+
+ return (p_search ? 0 : -1);
+}
+
+