summaryrefslogtreecommitdiffstats
path: root/udrv
diff options
context:
space:
mode:
authorMattias Agren <magren@broadcom.com>2012-03-26 08:25:00 -0700
committerMatthew Xie <mattx@google.com>2012-07-14 11:19:13 -0700
commit254588bfe6c3e70625b0f725b908598f30f476c8 (patch)
tree259c87422e70b74abeab96b3e3155c88791e5b6d /udrv
parent3e6f399bdbaca7f8ab0a8b1c6eab7cc1088ab74a (diff)
downloadexternal_bluetooth_bluedroid-254588bfe6c3e70625b0f725b908598f30f476c8.zip
external_bluetooth_bluedroid-254588bfe6c3e70625b0f725b908598f30f476c8.tar.gz
external_bluetooth_bluedroid-254588bfe6c3e70625b0f725b908598f30f476c8.tar.bz2
Added new control and data path interface between audioflinger a2dp HAL
and stack. Added support for suspend and a dedicated HAL callback notifying framework on audiopath events. Cleanup. Change-Id: I3b738611bc8e1d84794f7207413fd9e7dd1fc668
Diffstat (limited to 'udrv')
-rw-r--r--udrv/include/uipc.h68
-rw-r--r--udrv/include/unv.h80
-rw-r--r--udrv/ulinux/uipc.c782
-rw-r--r--udrv/ulinux/unv_linux.c204
4 files changed, 872 insertions, 262 deletions
diff --git a/udrv/include/uipc.h b/udrv/include/uipc.h
index 9fa6fbd..f5847c9 100644
--- a/udrv/include/uipc.h
+++ b/udrv/include/uipc.h
@@ -16,65 +16,44 @@
#define UDRV_API
#endif
+#define UIPC_CH_ID_AV_CTRL 0
+#define UIPC_CH_ID_AV_AUDIO 1
+#define UIPC_CH_NUM 2
-#define UIPC_CH_ID_ALL 0 /* used to address all the ch id at once */
-#define UIPC_CH_ID_0 1 /* shared mem interface */
-#define UIPC_CH_ID_1 2 /* TCP socket (GPS) */
-#define UIPC_CH_ID_2 3 /* BTIF control socket */
-#define UIPC_CH_ID_3 4 /* BTIF HH */
-#define UIPC_CH_ID_4 5 /* Future usage */
-#define UIPC_CH_ID_5 6 /* Future usage */
-#define UIPC_CH_ID_6 7 /* Future usage */
-#define UIPC_CH_ID_7 8 /* Future usage */
-#define UIPC_CH_ID_8 9 /* Future usage */
-#define UIPC_CH_ID_9 10 /* Future usage */
-#define UIPC_CH_ID_10 11 /* Future usage */
-#define UIPC_CH_ID_11 12 /* Future usage */
-#define UIPC_CH_ID_12 13 /* Future usage */
-#define UIPC_CH_ID_13 14 /* Future usage */
-#define UIPC_CH_ID_14 15 /* Future usage */
-#define UIPC_CH_ID_15 16 /* Future usage */
-#define UIPC_CH_ID_16 17 /* Future usage */
-#define UIPC_CH_ID_17 18 /* Future usage */
-#define UIPC_CH_ID_18 19 /* Future usage */
-#define UIPC_CH_ID_19 20 /* Future usage */
-#define UIPC_CH_ID_20 21 /* Future usage */
-#define UIPC_CH_ID_21 22 /* Future usage */
-#define UIPC_CH_ID_22 23 /* Future usage */
-#define UIPC_CH_ID_23 24 /* Future usage */
-#define UIPC_CH_ID_24 25 /* Future usage */
-
-
-
-#define UIPC_CH_NUM 25
+#define UIPC_CH_ID_ALL 3 /* used to address all the ch id at once */
+
+#define DEFAULT_READ_POLL_TMO_MS 100
typedef UINT8 tUIPC_CH_ID;
+/* Events generated */
+typedef enum {
+ UIPC_OPEN_EVT = 0x0001,
+ UIPC_CLOSE_EVT = 0x0002,
+ UIPC_RX_DATA_EVT = 0x0004,
+ UIPC_RX_DATA_READY_EVT = 0x0008,
+ UIPC_TX_DATA_READY_EVT = 0x0010
+} tUIPC_EVENT;
+
/*
* UIPC IOCTL Requests
*/
-enum
-{
- UIPC_REQ_TX_FLUSH = 1, /* Request to flush the TX FIFO */
- UIPC_REQ_RX_FLUSH, /* Request to flush the RX FIFO */
-
- UIPC_WRITE_BLOCK, /* Make write blocking */
- UIPC_WRITE_NONBLOCK, /* Make write non blocking */
- UIPC_REG_CBACK, /* Set a new call back */
- UIPC_SET_RX_WM, /* Set Rx water mark */
+#define UIPC_REQ_RX_FLUSH 1
+#define UIPC_REG_CBACK 2
+#define UIPC_REG_REMOVE_ACTIVE_READSET 3
+#define UIPC_SET_READ_POLL_TMO 4
- UIPC_REQ_TX_READY, /* Request an indication when Tx ready */
- UIPC_REQ_RX_READY /* Request an indication when Rx data ready */
-};
-
-typedef void (tUIPC_RCV_CBACK)(BT_HDR *p_msg); /* points to BT_HDR which describes event type and length of data; len contains the number of bytes of entire message (sizeof(BT_HDR) + offset + size of data) */
+typedef void (tUIPC_RCV_CBACK)(tUIPC_CH_ID ch_id, tUIPC_EVENT event); /* points to BT_HDR which describes event type and length of data; len contains the number of bytes of entire message (sizeof(BT_HDR) + offset + size of data) */
#ifdef __cplusplus
extern "C"
{
#endif
+const char* dump_uipc_event(tUIPC_EVENT event);
+
+
/*******************************************************************************
**
** Function UIPC_Init
@@ -153,6 +132,7 @@ UDRV_API extern UINT32 UIPC_Read(tUIPC_CH_ID ch_id, UINT16 *p_msg_evt, UINT8 *p_
*******************************************************************************/
UDRV_API extern BOOLEAN UIPC_Ioctl(tUIPC_CH_ID ch_id, UINT32 request, void *param);
+
#ifdef __cplusplus
}
#endif
diff --git a/udrv/include/unv.h b/udrv/include/unv.h
index 9e85bc8..87983da 100644
--- a/udrv/include/unv.h
+++ b/udrv/include/unv.h
@@ -3,44 +3,44 @@
* 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.
+ * 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
+ * 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
+ * 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
+ * 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.
*
************************************************************************************/
@@ -50,7 +50,7 @@
* Filename: unv.h
*
* Description: Universal NV Ram API
- *
+ *
***********************************************************************************/
#ifndef UNV_H
@@ -84,7 +84,7 @@ typedef int (*unv_iter_cb)(char *key, char *val, void *userdata);
**
** Function unv_create_directory
**
-** Description Creates directory, if full path is not available it
+** Description Creates directory, if full path is not available it
** will construct it. Must be called from BTIF task context.
**
** Parameters
@@ -107,7 +107,7 @@ int unv_create_directory(const char *path);
** Parameters
** filename : file path to be created
**
-** Returns 0 if successful, -1 if failure
+** Returns 0 if successful, -1 if failure
**
*******************************************************************************/
@@ -131,7 +131,7 @@ int unv_create_file(const char *filename);
**
*******************************************************************************/
-char* unv_read_key( const char *path,
+char* unv_read_key( const char *path,
const char *key,
char *p_out,
int out_len);
@@ -154,8 +154,8 @@ char* unv_read_key( const char *path,
**
*******************************************************************************/
-int unv_read_key_iter( const char *path,
- unv_iter_cb cb,
+int unv_read_key_iter( const char *path,
+ unv_iter_cb cb,
void *userdata );
@@ -163,7 +163,7 @@ int unv_read_key_iter( const char *path,
**
** Function unv_write_key
**
-** Description Writes key to file. If key value exists it will be updated
+** 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
**
@@ -172,12 +172,12 @@ int unv_read_key_iter( const char *path,
** key : key string to write
** value : value string to set for this key
**
-** Returns 0 if successful, -1 if failure
+** Returns 0 if successful, -1 if failure
**
*******************************************************************************/
-int unv_write_key( const char *path,
- const char *key,
+int unv_write_key( const char *path,
+ const char *key,
const char *value );
@@ -197,7 +197,7 @@ int unv_write_key( const char *path,
**
*******************************************************************************/
-int unv_remove_key( const char *path,
+int unv_remove_key( const char *path,
const char *key );
#endif /* UNV_H */
diff --git a/udrv/ulinux/uipc.c b/udrv/ulinux/uipc.c
index a06a057..8af45f1 100644
--- a/udrv/ulinux/uipc.c
+++ b/udrv/ulinux/uipc.c
@@ -1,12 +1,56 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************/
+
/*****************************************************************************
- **
- ** Name: uipc.c
- **
- ** Description: UIPC wrapper interface definition
- **
- ** Copyright (c) 2009-2011, Broadcom Corp., All Rights Reserved.
- ** Broadcom Bluetooth Core. Proprietary and confidential.
- **
+ *
+ * Filename: uipc.c
+ *
+ * Description: UIPC implementation for bluedroid
+ *
*****************************************************************************/
#include <stdio.h>
@@ -17,98 +61,541 @@
#include <unistd.h>
#include <fcntl.h>
-#include <cutils/sockets.h>
-
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
#include <errno.h>
+#include <pthread.h>
+#include <sys/select.h>
+#include <sys/poll.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/prctl.h>
+
#include "gki.h"
#include "data_types.h"
#include "uipc.h"
+#include <cutils/sockets.h>
+#include "audio_a2dp_hw.h"
+
+/*****************************************************************************
+** Constants & Macros
+******************************************************************************/
+
#define PCM_FILENAME "/data/test.pcm"
-#define SOCKPATH "/data/misc/bluedroid/.a2dp_sock"
-/* TEST CODE TO VERIFY DATAPATH */
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
+#define CASE_RETURN_STR(const) case const: return #const;
+
+#define UIPC_DISCONNECTED (-1)
+
+#define UIPC_LOCK() /*BTIF_TRACE_EVENT1(" %s lock", __FUNCTION__);*/ pthread_mutex_lock(&uipc_main.mutex);
+#define UIPC_UNLOCK() /*BTIF_TRACE_EVENT1("%s unlock", __FUNCTION__);*/ pthread_mutex_unlock(&uipc_main.mutex);
+
+/*****************************************************************************
+** Local type definitions
+******************************************************************************/
+
+typedef enum {
+ UIPC_TASK_FLAG_DISCONNECT_CHAN = 0x1,
+} tUIPC_TASK_FLAGS;
+
+typedef struct {
+ int srvfd;
+ int fd;
+ int read_poll_tmo_ms;
+ int task_evt_flags; /* event flags pending to be processed in read task */
+ tUIPC_EVENT cond_flags;
+ pthread_mutex_t cond_mutex;
+ pthread_cond_t cond;
+ tUIPC_RCV_CBACK *cback;
+} tUIPC_CHAN;
+
+typedef struct {
+ pthread_t tid; /* main thread id */
+ int running;
+ pthread_mutex_t mutex;
+
+ fd_set active_set;
+ fd_set read_set;
+ int max_fd;
+ int signal_fds[2];
+
+ tUIPC_CHAN ch[UIPC_CH_NUM];
+} tUIPC_MAIN;
+
+
+/*****************************************************************************
+** Static variables
+******************************************************************************/
+
+static tUIPC_MAIN uipc_main;
+
+
+/*****************************************************************************
+** Static functions
+******************************************************************************/
+
+static int uipc_close_ch_locked(tUIPC_CH_ID ch_id);
+
+/*****************************************************************************
+** Externs
+******************************************************************************/
+
+
+/*****************************************************************************
+** Helper functions
+******************************************************************************/
+
+
+const char* dump_uipc_event(tUIPC_EVENT event)
+{
+ switch(event)
+ {
+ CASE_RETURN_STR(UIPC_OPEN_EVT)
+ CASE_RETURN_STR(UIPC_CLOSE_EVT)
+ CASE_RETURN_STR(UIPC_RX_DATA_EVT)
+ CASE_RETURN_STR(UIPC_RX_DATA_READY_EVT)
+ CASE_RETURN_STR(UIPC_TX_DATA_READY_EVT)
+ default:
+ return "UNKNOWN MSG ID";
+ }
+}
+
+/*****************************************************************************
+**
+** Function
+**
+** Description
+**
+** Returns
+**
+*******************************************************************************/
+
+static void uipc_wait(tUIPC_CH_ID ch_id, tUIPC_EVENT wait_event_flags)
+{
+ int ret;
+ tUIPC_CHAN *p = &uipc_main.ch[ch_id];
+
+ //BTIF_TRACE_EVENT2("WAIT UIPC CH %d EVT %x BEGIN", ch_id, wait_event_flags);
+ pthread_mutex_lock(&p->cond_mutex);
+ p->cond_flags |= wait_event_flags;
+ ret = pthread_cond_wait(&p->cond, &p->cond_mutex);
+ pthread_mutex_unlock(&p->cond_mutex);
+ //BTIF_TRACE_EVENT2("WAIT UIPC CH %d EVT %x DONE", ch_id, wait_event_flags);
+}
-#define SOURCE_MODE_PCMFILE 1
-#define SOURCE_MODE_A2DP_SOCKET 2
-#define SOURCE_MODE SOURCE_MODE_A2DP_SOCKET
+static void uipc_signal(tUIPC_CH_ID ch_id, tUIPC_EVENT event)
+{
+ int ret;
+ tUIPC_CHAN *p = &uipc_main.ch[ch_id];
-static int listen_fd = -1;
-static int sock_fd = -1;
-static int source_fd = -1;
+ //BTIF_TRACE_EVENT2("SIGNAL UIPC CH %d EVT %x BEGIN", ch_id, dump_uipc_event(event));
+ pthread_mutex_lock(&p->cond_mutex);
+
+ if (event & p->cond_flags)
+ {
+ //BTIF_TRACE_EVENT0("UNBLOCK");
+ ret = pthread_cond_signal(&p->cond);
+ p->cond_flags = 0;
+ }
+
+ pthread_mutex_unlock(&p->cond_mutex);
+}
+
+
+
+/*****************************************************************************
+** socket helper functions
+*****************************************************************************/
static inline int create_server_socket(const char* name)
{
int s = socket(AF_LOCAL, SOCK_STREAM, 0);
-
- if(socket_local_server_bind(s, name, ANDROID_SOCKET_NAMESPACE_ABSTRACT) >= 0)
+
+ BTIF_TRACE_EVENT1("create_server_socket %s", name);
+
+ if(socket_local_server_bind(s, name, ANDROID_SOCKET_NAMESPACE_ABSTRACT) < 0)
{
- if(listen(s, 5) == 0)
- {
- APPL_TRACE_EVENT2("listen to local socket:%s, fd:%d", name, s);
- return s;
- }
- else
- APPL_TRACE_EVENT3("listen to local socket:%s, fd:%d failed, errno:%d", name, s, errno);
+ BTIF_TRACE_EVENT1("socket failed to create (%s)", strerror(errno));
+ return -1;
}
- else
- APPL_TRACE_EVENT3("create local socket:%s fd:%d, failed, errno:%d", name, s, errno);
- close(s);
- return -1;
+
+ if(listen(s, 5) < 0)
+ {
+ BTIF_TRACE_EVENT1("listen failed", strerror(errno));
+ close(s);
+ return -1;
+ }
+
+ BTIF_TRACE_EVENT1("created socket fd %d", s);
+ return s;
}
-int wait_socket(void)
+static int accept_server_socket(int sfd)
{
struct sockaddr_un remote;
+ int fd;
int t;
- APPL_TRACE_DEBUG0("wait socket");
+ //BTIF_TRACE_EVENT1("accept fd %d", sfd);
+
+ if ((fd = accept(sfd, (struct sockaddr *)&remote, &t)) == -1) {
+ BTIF_TRACE_ERROR1("sock accept failed (%s)", strerror(errno));
+ return -1;
+ }
+
+ //BTIF_TRACE_EVENT1("new fd %d", fd);
+
+ return fd;
+}
+
+/*****************************************************************************
+**
+** uipc helper functions
+**
+*****************************************************************************/
+
+static int uipc_main_init(void)
+{
+ int i;
+ const pthread_mutexattr_t attr = PTHREAD_MUTEX_RECURSIVE;
+ pthread_mutex_init(&uipc_main.mutex, &attr);
+
+ BTIF_TRACE_EVENT0("### uipc_main_init ###");
+
+ /* setup interrupt socket pair */
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, uipc_main.signal_fds) < 0)
+ {
+ return -1;
+ }
+
+ FD_SET(uipc_main.signal_fds[0], &uipc_main.active_set);
+ uipc_main.max_fd = MAX(uipc_main.max_fd, uipc_main.signal_fds[0]);
+
+ for (i=0; i< UIPC_CH_NUM; i++)
+ {
+ tUIPC_CHAN *p = &uipc_main.ch[i];
+ p->srvfd = UIPC_DISCONNECTED;
+ p->fd = UIPC_DISCONNECTED;
+ p->task_evt_flags = 0;
+ pthread_cond_init(&p->cond, NULL);
+ pthread_mutex_init(&p->cond_mutex, NULL);
+ p->cback = NULL;
+ }
+
+ return 0;
+}
+
+void uipc_main_cleanup(void)
+{
+ int i;
+
+ close(uipc_main.signal_fds[0]);
+ close(uipc_main.signal_fds[1]);
+
+ /* close any open channels */
+ for (i=0; i<UIPC_CH_NUM; i++)
+ UIPC_Close(i);
+}
+
+
+
+/* check pending events in read task */
+static void uipc_check_task_flags_locked(void)
+{
+ int i;
+
+ for (i=0; i<UIPC_CH_NUM; i++)
+ {
+ //BTIF_TRACE_EVENT2("CHECK TASK FLAGS %x %x", uipc_main.ch[i].task_evt_flags, UIPC_TASK_FLAG_DISCONNECT_CHAN);
+ if (uipc_main.ch[i].task_evt_flags & UIPC_TASK_FLAG_DISCONNECT_CHAN)
+ {
+ uipc_main.ch[i].task_evt_flags &= ~UIPC_TASK_FLAG_DISCONNECT_CHAN;
+ uipc_close_ch_locked(i);
+ }
+
+ /* add here */
+
+ }
+}
+
+
+static int uipc_check_fd_locked(tUIPC_CH_ID ch_id)
+{
+ if (ch_id >= UIPC_CH_NUM)
+ return -1;
+
+ //BTIF_TRACE_EVENT2("CHECK SRVFD %d (ch %d)", uipc_main.ch[ch_id].srvfd, ch_id);
+
+ if (FD_ISSET(uipc_main.ch[ch_id].srvfd, &uipc_main.read_set))
+ {
+ BTIF_TRACE_EVENT1("INCOMING CONNECTION ON CH %d", ch_id);
+
+ uipc_main.ch[ch_id].fd = accept_server_socket(uipc_main.ch[ch_id].srvfd);
+
+ //BTIF_TRACE_EVENT1("NEW FD %d", uipc_main.ch[ch_id].fd);
+
+ if (uipc_main.ch[ch_id].cback)
+ {
+ /* if we have a callback we should add this fd to the active set
+ and notify user with callback event */
+ BTIF_TRACE_EVENT1("ADD FD %d TO ACTIVE SET", uipc_main.ch[ch_id].fd);
+ FD_SET(uipc_main.ch[ch_id].fd, &uipc_main.active_set);
+ uipc_main.max_fd = MAX(uipc_main.max_fd, uipc_main.ch[ch_id].fd);
+ }
+
+ if (uipc_main.ch[ch_id].fd < 0)
+ {
+ BTIF_TRACE_ERROR2("FAILED TO ACCEPT CH %d (%s)", ch_id, strerror(errno));
+ return -1;
+ }
+
+ if (uipc_main.ch[ch_id].cback)
+ uipc_main.ch[ch_id].cback(ch_id, UIPC_OPEN_EVT);
+ }
+
+ //BTIF_TRACE_EVENT2("CHECK FD %d (ch %d)", uipc_main.ch[ch_id].fd, ch_id);
+
+ if (FD_ISSET(uipc_main.ch[ch_id].fd, &uipc_main.read_set))
+ {
+ //BTIF_TRACE_EVENT1("INCOMING DATA ON CH %d", ch_id);
+
+ if (uipc_main.ch[ch_id].cback)
+ uipc_main.ch[ch_id].cback(ch_id, UIPC_RX_DATA_READY_EVT);
+ }
+ return 0;
+}
+
+static void uipc_check_interrupt_locked(void)
+{
+ if (FD_ISSET(uipc_main.signal_fds[0], &uipc_main.read_set))
+ {
+ char sig_recv = 0;
+ //BTIF_TRACE_EVENT0("UIPC INTERRUPT");
+ recv(uipc_main.signal_fds[0], &sig_recv, sizeof(sig_recv), MSG_WAITALL);
+ }
+}
+
+static inline void uipc_wakeup_locked(void)
+{
+ char sig_on = 1;
+ BTIF_TRACE_EVENT0("UIPC SEND WAKE UP");
+ send(uipc_main.signal_fds[1], &sig_on, sizeof(sig_on), 0);
+}
+
+static int uipc_setup_server_locked(tUIPC_CH_ID ch_id, char *name, tUIPC_RCV_CBACK *cback)
+{
+ int fd;
+
+ BTIF_TRACE_EVENT1("SETUP CHANNEL SERVER %d", ch_id);
- listen_fd = create_server_socket(SOCKPATH);
+ if (ch_id >= UIPC_CH_NUM)
+ return -1;
- if ((sock_fd = accept(listen_fd, (struct sockaddr *)&remote, &t)) == -1) {
- APPL_TRACE_ERROR1("a2dp sock accept failed (%d)", errno);
+ UIPC_LOCK();
+
+ fd = create_server_socket(name);
+
+ if (fd < 0)
+ {
+ BTIF_TRACE_ERROR2("failed to setup %s", name, strerror(errno));
+ UIPC_UNLOCK();
return -1;
}
- return sock_fd;
+ BTIF_TRACE_EVENT1("ADD SERVER FD TO ACTIVE SET %d", fd);
+ FD_SET(fd, &uipc_main.active_set);
+ uipc_main.max_fd = MAX(uipc_main.max_fd, fd);
+
+ uipc_main.ch[ch_id].srvfd = fd;
+ uipc_main.ch[ch_id].cback = cback;
+ uipc_main.ch[ch_id].read_poll_tmo_ms = DEFAULT_READ_POLL_TMO_MS;
+
+ /* trigger main thread to update read set */
+ uipc_wakeup_locked();
+
+ UIPC_UNLOCK();
+
+ return 0;
}
-int open_source(void)
+static void uipc_flush_ch_locked(tUIPC_CH_ID ch_id)
{
- int s;
-#if (SOURCE_MODE == SOURCE_MODE_PCMFILE)
- s = open((char*)PCM_FILENAME , O_RDONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+ char buf;
+ struct pollfd pfd;
+ int ret;
+
+ pfd.events = POLLIN|POLLHUP;
+ pfd.fd = uipc_main.ch[ch_id].fd;
+
+ if (uipc_main.ch[ch_id].fd == UIPC_DISCONNECTED)
+ return;
- if (s == -1)
+ while (1)
{
- APPL_TRACE_ERROR0("unable to open pcm file\n");
- s = -1;
+ ret = poll(&pfd, 1, 1);
+ BTIF_TRACE_EVENT3("uipc_flush_ch_locked polling : fd %d, rxev %x, ret %d", pfd.fd, pfd.revents, ret);
+
+ if (pfd.revents | (POLLERR|POLLHUP))
+ return;
+
+ if (ret <= 0)
+ {
+ BTIF_TRACE_EVENT1("uipc_flush_ch_locked : error (%d)", ret);
+ return;
+ }
+ read(pfd.fd, &buf, 1);
+ }
+}
+
+
+static void uipc_flush_locked(tUIPC_CH_ID ch_id)
+{
+ if (ch_id >= UIPC_CH_NUM)
+ return;
+
+ switch(ch_id)
+ {
+ case UIPC_CH_ID_AV_CTRL:
+ uipc_flush_ch_locked(UIPC_CH_ID_AV_CTRL);
+ break;
+
+ case UIPC_CH_ID_AV_AUDIO:
+ uipc_flush_ch_locked(UIPC_CH_ID_AV_AUDIO);
+ break;
+ }
+}
+
+
+static int uipc_close_ch_locked(tUIPC_CH_ID ch_id)
+{
+ int wakeup = 0;
+
+ BTIF_TRACE_EVENT1("CLOSE CHANNEL %d", ch_id);
+
+ if (ch_id >= UIPC_CH_NUM)
+ return -1;
+
+ if (ch_id == UIPC_CH_ID_ALL)
+ {
+ /* shutdown read thread */
+ uipc_main.running = 0;
+ uipc_wakeup_locked();
return 0;
}
-#endif
-#if (SOURCE_MODE == SOURCE_MODE_A2DP_SOCKET)
- s = wait_socket();
-#endif
- return s;
+ if (uipc_main.ch[ch_id].srvfd != UIPC_DISCONNECTED)
+ {
+ BTIF_TRACE_EVENT1("CLOSE SERVER (FD %d)", uipc_main.ch[ch_id].srvfd);
+ close(uipc_main.ch[ch_id].srvfd);
+ FD_CLR(uipc_main.ch[ch_id].srvfd, &uipc_main.active_set);
+ uipc_main.ch[ch_id].srvfd = UIPC_DISCONNECTED;
+ wakeup = 1;
+ }
+
+ if (uipc_main.ch[ch_id].fd != UIPC_DISCONNECTED)
+ {
+ BTIF_TRACE_EVENT1("CLOSE CONNECTION (FD %d)", uipc_main.ch[ch_id].fd);
+ close(uipc_main.ch[ch_id].fd);
+ FD_CLR(uipc_main.ch[ch_id].fd, &uipc_main.active_set);
+ uipc_main.ch[ch_id].fd = UIPC_DISCONNECTED;
+ wakeup = 1;
+ }
+
+ /* notify this connection is closed */
+ if (uipc_main.ch[ch_id].cback)
+ uipc_main.ch[ch_id].cback(ch_id, UIPC_CLOSE_EVT);
+
+ /* trigger main thread update if something was updated */
+ if (wakeup)
+ uipc_wakeup_locked();
+
+ return 0;
}
-void close_source(int fd)
+
+void uipc_close_locked(tUIPC_CH_ID ch_id)
{
- close(fd);
+ if (uipc_main.ch[ch_id].srvfd == UIPC_DISCONNECTED)
+ {
+ BTIF_TRACE_EVENT1("CHANNEL %d ALREADY CLOSED", ch_id);
+ return;
+ }
+
+ /* schedule close on this channel */
+ uipc_main.ch[ch_id].task_evt_flags |= UIPC_TASK_FLAG_DISCONNECT_CHAN;
+ uipc_wakeup_locked();
+}
+
+
+static void uipc_read_task(void *arg)
+{
+ int ch_id;
+ int result;
+
+ prctl(PR_SET_NAME, (unsigned long)"uipc-main", 0, 0, 0);
+
+ while (uipc_main.running)
+ {
+ uipc_main.read_set = uipc_main.active_set;
+
+ result = select(uipc_main.max_fd+1, &uipc_main.read_set, NULL, NULL, NULL);
+
+ if (result == 0)
+ {
+ BTIF_TRACE_EVENT0("select timeout");
+ continue;
+ }
+ else if (result < 0)
+ {
+ BTIF_TRACE_EVENT1("select failed %s", strerror(errno));
+ continue;
+ }
+
+ UIPC_LOCK();
-#if (SOURCE_MODE == SOURCE_MODE_A2DP_SOCKET)
- close(listen_fd);
- listen_fd = -1;
-#endif
+ /* clear any wakeup interrupt */
+ uipc_check_interrupt_locked();
+
+ /* check pending task events */
+ uipc_check_task_flags_locked();
+
+ /* make sure we service audio channel first */
+ uipc_check_fd_locked(UIPC_CH_ID_AV_AUDIO);
+
+ /* check for other connections */
+ for (ch_id = 0; ch_id < UIPC_CH_NUM; ch_id++)
+ {
+ if (ch_id != UIPC_CH_ID_AV_AUDIO)
+ uipc_check_fd_locked(ch_id);
+ }
+
+ UIPC_UNLOCK();
+ }
+
+ BTIF_TRACE_EVENT0("UIPC READ THEAD EXITING");
+
+ uipc_main_cleanup();
}
+int uipc_start_main_server_thread(void)
+{
+ uipc_main.running = 1;
+
+ if (pthread_create(&uipc_main.tid, (const pthread_attr_t *) NULL, (void*)uipc_read_task, NULL) < 0)
+ {
+ BTIF_TRACE_ERROR1("uipc_thread_create pthread_create failed:%d", errno);
+ return -1;
+ }
+
+ return 0;
+}
+
/*******************************************************************************
**
** Function UIPC_Init
@@ -121,7 +608,13 @@ void close_source(int fd)
UDRV_API void UIPC_Init(void *p_data)
{
- APPL_TRACE_DEBUG0("UIPC_Init");
+ BTIF_TRACE_DEBUG0("UIPC_Init");
+
+ memset(&uipc_main, 0, sizeof(tUIPC_MAIN));
+
+ uipc_main_init();
+
+ uipc_start_main_server_thread();
}
/*******************************************************************************
@@ -135,9 +628,37 @@ UDRV_API void UIPC_Init(void *p_data)
*******************************************************************************/
UDRV_API BOOLEAN UIPC_Open(tUIPC_CH_ID ch_id, tUIPC_RCV_CBACK *p_cback)
{
- APPL_TRACE_DEBUG2("UIPC_Open : ch_id %d, p_cback %x", ch_id, p_cback);
+ BTIF_TRACE_DEBUG2("UIPC_Open : ch_id %d, p_cback %x", ch_id, p_cback);
- return FALSE;
+ UIPC_LOCK();
+
+ if (ch_id >= UIPC_CH_NUM)
+ {
+ UIPC_UNLOCK();
+ return FALSE;
+ }
+
+ if (uipc_main.ch[ch_id].srvfd != UIPC_DISCONNECTED)
+ {
+ BTIF_TRACE_EVENT1("CHANNEL %d ALREADY OPEN", ch_id);
+ UIPC_UNLOCK();
+ return 0;
+ }
+
+ switch(ch_id)
+ {
+ case UIPC_CH_ID_AV_CTRL:
+ uipc_setup_server_locked(ch_id, A2DP_CTRL_PATH, p_cback);
+ break;
+
+ case UIPC_CH_ID_AV_AUDIO:
+ uipc_setup_server_locked(ch_id, A2DP_DATA_PATH, p_cback);
+ break;
+ }
+
+ UIPC_UNLOCK();
+
+ return TRUE;
}
/*******************************************************************************
@@ -149,11 +670,14 @@ UDRV_API BOOLEAN UIPC_Open(tUIPC_CH_ID ch_id, tUIPC_RCV_CBACK *p_cback)
** Returns void
**
*******************************************************************************/
+
UDRV_API void UIPC_Close(tUIPC_CH_ID ch_id)
{
- APPL_TRACE_DEBUG1("UIPC_Close : ch_id %d", ch_id);
- close_source(source_fd);
- source_fd = -1;
+ BTIF_TRACE_DEBUG1("UIPC_Close : ch_id %d", ch_id);
+
+ UIPC_LOCK();
+ uipc_close_locked(ch_id);
+ UIPC_UNLOCK();
}
/*******************************************************************************
@@ -168,7 +692,14 @@ UDRV_API void UIPC_Close(tUIPC_CH_ID ch_id)
*******************************************************************************/
UDRV_API BOOLEAN UIPC_SendBuf(tUIPC_CH_ID ch_id, BT_HDR *p_msg)
{
- APPL_TRACE_DEBUG1("UIPC_SendBuf : ch_id %d", ch_id);
+ BTIF_TRACE_DEBUG1("UIPC_SendBuf : ch_id %d NOT IMPLEMENTED", ch_id);
+
+ UIPC_LOCK();
+
+ /* currently not used */
+
+ UIPC_UNLOCK();
+
return FALSE;
}
@@ -184,7 +715,19 @@ UDRV_API BOOLEAN UIPC_SendBuf(tUIPC_CH_ID ch_id, BT_HDR *p_msg)
UDRV_API BOOLEAN UIPC_Send(tUIPC_CH_ID ch_id, UINT16 msg_evt, UINT8 *p_buf,
UINT16 msglen)
{
- APPL_TRACE_DEBUG1("UIPC_Send : ch_id:%d", ch_id);
+ int n;
+
+ BTIF_TRACE_DEBUG2("UIPC_Send : ch_id:%d %d bytes", ch_id, msglen);
+
+ UIPC_LOCK();
+
+ if (write(uipc_main.ch[ch_id].fd, p_buf, msglen) < 0)
+ {
+ BTIF_TRACE_ERROR1("failed to write (%s)", strerror(errno));
+ }
+
+ UIPC_UNLOCK();
+
return FALSE;
}
@@ -199,7 +742,10 @@ UDRV_API BOOLEAN UIPC_Send(tUIPC_CH_ID ch_id, UINT16 msg_evt, UINT8 *p_buf,
*******************************************************************************/
UDRV_API void UIPC_ReadBuf(tUIPC_CH_ID ch_id, BT_HDR *p_msg)
{
- APPL_TRACE_DEBUG1("UIPC_ReadBuf : ch_id:%d", ch_id);
+ BTIF_TRACE_DEBUG1("UIPC_ReadBuf : ch_id:%d NOT IMPLEMENTED", ch_id);
+
+ UIPC_LOCK();
+ UIPC_UNLOCK();
}
/*******************************************************************************
@@ -211,31 +757,75 @@ UDRV_API void UIPC_ReadBuf(tUIPC_CH_ID ch_id, BT_HDR *p_msg)
** Returns return the number of bytes read.
**
*******************************************************************************/
-UDRV_API UINT32 UIPC_Read(tUIPC_CH_ID ch_id, UINT16 *p_msg_evt, UINT8 *p_buf,
- UINT32 len)
+
+UDRV_API UINT32 UIPC_Read(tUIPC_CH_ID ch_id, UINT16 *p_msg_evt, UINT8 *p_buf, UINT32 len)
{
int n;
int n_read = 0;
+ int fd = uipc_main.ch[ch_id].fd;
+ struct pollfd pfd;
- //APPL_TRACE_DEBUG1("UIPC_Read : ch_id %d", ch_id);
+ if (ch_id >= UIPC_CH_NUM)
+ {
+ BTIF_TRACE_ERROR1("UIPC_Read : invalid ch id %d", ch_id);
+ return 0;
+ }
- if (source_fd == -1)
+ if (fd == UIPC_DISCONNECTED)
{
- source_fd = open_source();
- }
+ BTIF_TRACE_ERROR1("UIPC_Read : channel %d closed", ch_id);
+ return 0;
+ }
+
+ BTIF_TRACE_DEBUG4("UIPC_Read : ch_id %d, len %d, fd %d, polltmo %d", ch_id, len,
+ fd, uipc_main.ch[ch_id].read_poll_tmo_ms);
while (n_read < (int)len)
{
- n = read(source_fd, p_buf, len);
-
+ pfd.fd = fd;
+ pfd.events = POLLIN|POLLHUP;
+
+ /* make sure there is data prior to attempting read */
+ if (poll(&pfd, 1, uipc_main.ch[ch_id].read_poll_tmo_ms) == 0)
+ {
+ BTIF_TRACE_EVENT1("poll timeout (%d ms)", uipc_main.ch[ch_id].read_poll_tmo_ms);
+ return 0;
+ }
+
+ BTIF_TRACE_EVENT1("poll revents %x", pfd.revents);
+
+ if (pfd.revents & (POLLHUP|POLLNVAL) )
+ {
+ BTIF_TRACE_EVENT0("poll : channel detached remotely");
+ UIPC_LOCK();
+ uipc_close_locked(ch_id);
+ UIPC_UNLOCK();
+ return 0;
+ }
+
+ UIPC_UNLOCK();
+
+ n = recv(fd, p_buf, len, 0);
+
+ //BTIF_TRACE_EVENT1("read %d bytes", n);
+
if (n == 0)
{
- APPL_TRACE_EVENT0("remote source detached");
- source_fd = -1;
+ BTIF_TRACE_EVENT0("UIPC_Read : channel detached remotely");
+ UIPC_LOCK();
+ uipc_close_locked(ch_id);
+ UIPC_UNLOCK();
return 0;
}
+
+ if (n < 0)
+ {
+ BTIF_TRACE_EVENT1("UIPC_Read : read failed (%s)", strerror(errno));
+ return 0;
+ }
+
n_read+=n;
- //APPL_TRACE_EVENT1("read %d bytes", n_read);
+
}
return n_read;
@@ -250,9 +840,49 @@ UDRV_API UINT32 UIPC_Read(tUIPC_CH_ID ch_id, UINT16 *p_msg_evt, UINT8 *p_buf,
** Returns void
**
*******************************************************************************/
+
UDRV_API extern BOOLEAN UIPC_Ioctl(tUIPC_CH_ID ch_id, UINT32 request, void *param)
{
- APPL_TRACE_DEBUG2("#### UIPC_Ioctl : ch_ud %d, request %d ####", ch_id, request);
+ BTIF_TRACE_DEBUG2("#### UIPC_Ioctl : ch_id %d, request %d ####", ch_id, request);
+
+ UIPC_LOCK();
+
+ switch(request)
+ {
+ case UIPC_REQ_RX_FLUSH:
+ uipc_flush_locked(ch_id);
+ break;
+
+ case UIPC_REG_CBACK:
+ //BTIF_TRACE_EVENT3("register callback ch %d srvfd %d, fd %d", ch_id, uipc_main.ch[ch_id].srvfd, uipc_main.ch[ch_id].fd);
+ uipc_main.ch[ch_id].cback = (tUIPC_RCV_CBACK*)param;
+ break;
+
+ case UIPC_REG_REMOVE_ACTIVE_READSET:
+
+ /* user will read data directly and not use select loop */
+ if (uipc_main.ch[ch_id].fd != UIPC_DISCONNECTED)
+ {
+ /* remove this channel from active set */
+ FD_CLR(uipc_main.ch[ch_id].fd, &uipc_main.active_set);
+
+ /* refresh active set */
+ uipc_wakeup_locked();
+ }
+ break;
+
+ case UIPC_SET_READ_POLL_TMO:
+ uipc_main.ch[ch_id].read_poll_tmo_ms = (int)param;
+ BTIF_TRACE_EVENT2("UIPC_SET_READ_POLL_TMO : CH %d, TMO %d ms", ch_id, uipc_main.ch[ch_id].read_poll_tmo_ms );
+ break;
+
+ default:
+ BTIF_TRACE_EVENT1("UIPC_Ioctl : request not handled (%d)", request);
+ break;
+ }
+
+ UIPC_UNLOCK();
+
return FALSE;
}
diff --git a/udrv/ulinux/unv_linux.c b/udrv/ulinux/unv_linux.c
index 6737ca0..dc79fa4 100644
--- a/udrv/ulinux/unv_linux.c
+++ b/udrv/ulinux/unv_linux.c
@@ -3,44 +3,44 @@
* 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.
+ * 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
+ * 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
+ * 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
+ * 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.
*
************************************************************************************/
@@ -50,11 +50,11 @@
* Filename: unv_linux.c
*
* Description: Universal NV Ram API.
- * Manages all non volatile (file) database entries used by
+ * Manages all non volatile (file) database entries used by
* bluetooth upper layer stack.
- *
+ *
***********************************************************************************/
-
+
#include "unv.h"
#include <stdio.h>
@@ -68,7 +68,7 @@
#include <sys/mman.h>
#include <stdlib.h>
#include <sys/prctl.h>
-#include <pthread.h>
+#include <pthread.h>
#define LOG_TAG "UNV_LINUX"
#include <utils/Log.h>
@@ -118,7 +118,7 @@
/*******************************************************************************
**
-** Function check_caller_context
+** Function check_caller_context
**
** Description Checks pthread name of caller. Currently only BTIF thread
** is allowed to call in here to avoid multithreading issues
@@ -132,7 +132,7 @@ 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);
@@ -143,7 +143,7 @@ static int check_caller_context(void)
/*******************************************************************************
**
-** Function mk_dir
+** Function mk_dir
**
** Description Create directory
**
@@ -154,7 +154,7 @@ static int check_caller_context(void)
static int mk_dir(const char *path)
{
struct stat st;
-
+
if (stat(path, &st) == 0)
{
if (!S_ISDIR(st.st_mode))
@@ -163,11 +163,11 @@ static int mk_dir(const char *path)
error("directory path %s is not a directory (%s)", path, strerror(errno));
return -1;
}
-
+
/* already exist */
- return 0;
- }
-
+ return 0;
+ }
+
/* no existing dir path, try creating it */
if (mkdir(path, DIR_MODE) != 0)
{
@@ -197,7 +197,7 @@ static int rm_dir(const char *path)
error("rmdir %s failed (%s)", path, strerror(errno));
return -1;
}
- return 0;
+ return 0;
}
/*******************************************************************************
@@ -210,8 +210,8 @@ static int rm_dir(const char *path)
**
*******************************************************************************/
-static int write_keyval( int fd,
- const char *key,
+static int write_keyval( int fd,
+ const char *key,
const char *val )
{
int len = 0;
@@ -230,16 +230,16 @@ static int write_keyval( int fd,
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);
+ //info("write_keyval %s %s (%d bytes)", key, val, len);
/* update line */
written = write(fd, line, len);
free(line);
-
+
return written;
}
@@ -258,10 +258,10 @@ static int write_keyval( int fd,
**
*******************************************************************************/
-static int update_key( int fd,
- const char *key,
- const char *value,
- int pos_start,
+static int update_key( int fd,
+ const char *key,
+ const char *value,
+ int pos_start,
int pos_stop )
{
char *line;
@@ -278,7 +278,7 @@ static int update_key( int fd,
{
verbose("remove key [%s]", key);
}
-
+
/* update file with new value for this key */
if (fstat(fd, &st) != 0)
@@ -286,7 +286,7 @@ static int update_key( int fd,
error("stat failed (%s)", strerror(errno));
return -1;
}
-
+
tail_sz = st.st_size-pos_stop;
if (tail_sz > 0)
@@ -312,7 +312,7 @@ static int update_key( int fd,
}
/* rewind and update new line */
- lseek(fd, pos_start, SEEK_SET);
+ lseek(fd, pos_start, SEEK_SET);
len = pos_start;
/* a null key means remove entry */
@@ -320,14 +320,14 @@ static int update_key( int fd,
{
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);
@@ -345,18 +345,18 @@ static int update_key( int fd,
** 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_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,
+ const char *key,
char *p_out,
int out_len,
- int *pos_begin,
+ int *pos_begin,
int *pos_end)
{
char *p_value = NULL;
@@ -373,7 +373,7 @@ static char *get_keyval( int fd,
p_buf = malloc(st.st_size + 1);
- if (!p_buf)
+ if (!p_buf)
return NULL;
p = p_buf;
@@ -387,9 +387,9 @@ static char *get_keyval( int fd,
/* tokenize first line */
line = strtok(p, UNV_DELIM);
-
+
while (line && (p_value == NULL))
- {
+ {
/* check for match */
if (strncmp(line, key, strlen(key)) == 0)
{
@@ -409,25 +409,25 @@ static char *get_keyval( int fd,
p_value = p_out;
/* should be ok to just strcpy from 'line' as
- * strrok shall null-terminate the token
+ * 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);
+ line = strtok(NULL, UNV_DELIM);
}
-
+
free(p_buf);
/* rewind */
lseek(fd, 0, SEEK_SET);
-
+
return p_value;
}
@@ -446,7 +446,7 @@ static char *get_keyval( int fd,
**
** Function unv_create_directory
**
-** Description Creates directory, if full path is not available it
+** Description Creates directory, if full path is not available it
** will construct it. Must be called from BTIF task context.
**
** Parameters
@@ -467,14 +467,14 @@ int unv_create_directory(const char *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;
@@ -493,11 +493,11 @@ int unv_create_directory(const char *path)
p = strchr(p_copy+1, '/'); /* skip root */
while ((status == 0) && p)
- {
- /*
- * temporarily null terminate to allow creating
+ {
+ /*
+ * temporarily null terminate to allow creating
* directories up to this point
- */
+ */
*p= '\0';
status = mk_dir(p_copy);
*p= '/';
@@ -519,7 +519,7 @@ int unv_create_directory(const char *path)
** Parameters
** filename : file path to be created
**
-** Returns 0 if successful, -1 if failure
+** Returns 0 if successful, -1 if failure
**
*******************************************************************************/
@@ -534,7 +534,7 @@ int unv_create_file(const char *filename)
/* separate path from filename */
p = strrchr(path, '/');
-
+
if (p)
{
*p = '\0';
@@ -544,21 +544,21 @@ int unv_create_file(const char *filename)
return -1;
}
}
-
+
free(path);
-
+
verbose("CREATE FILE %s", filename);
-
+
fd = open(filename, O_RDWR|O_CREAT, FILE_MODE);
- if (fd < 0)
+ if (fd < 0)
{
error("file failed to create %s errno: (%s)", filename, strerror(errno));
return -1;
}
close(fd);
-
+
return 0;
}
@@ -581,14 +581,14 @@ int unv_create_file(const char *filename)
**
******************************************************************************/
-char* unv_read_key( const char *path,
+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 */
@@ -597,7 +597,7 @@ char* unv_read_key( const char *path,
if (check_caller_context() == 0)
return NULL;
-
+
fd = open(path, O_RDONLY, FILE_MODE);
if (fd < 0) {
@@ -608,7 +608,7 @@ char* unv_read_key( const char *path,
p_search = get_keyval(fd, key, p_out, out_len, NULL, NULL);
close(fd);
-
+
return p_search;
}
@@ -629,8 +629,8 @@ char* unv_read_key( const char *path,
**
*******************************************************************************/
-int unv_read_key_iter( const char *path,
- unv_iter_cb cb,
+int unv_read_key_iter( const char *path,
+ unv_iter_cb cb,
void *userdata )
{
int fd;
@@ -703,7 +703,7 @@ int unv_read_key_iter( const char *path,
**
** Function unv_write_key
**
-** Description Writes key to file. If key value exists it will be updated
+** 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
**
@@ -712,12 +712,12 @@ int unv_read_key_iter( const char *path,
** key : key string to write
** value : value string to set for this key
**
-** Returns 0 if successful, -1 if failure
+** Returns 0 if successful, -1 if failure
**
*******************************************************************************/
-int unv_write_key( const char *path,
- const char *key,
+int unv_write_key( const char *path,
+ const char *key,
const char *value )
{
int fd;
@@ -737,7 +737,7 @@ int unv_write_key( const char *path,
fd = open(path, O_RDWR, FILE_MODE);
- if (fd < 0)
+ if (fd < 0)
{
error("file failed to create %s (%s)", path, strerror(errno));
return -1;
@@ -748,18 +748,18 @@ int unv_write_key( const char *path,
if (keyval)
{
- update_key(fd, key, value, pos_start, pos_stop);
+ 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;
}
@@ -779,7 +779,7 @@ int unv_write_key( const char *path,
**
*******************************************************************************/
-int unv_remove_key( const char *path,
+int unv_remove_key( const char *path,
const char *key )
{
int fd;
@@ -787,7 +787,7 @@ int unv_remove_key( const char *path,
int pos_begin = 0;
int pos_stop = 0;
char *p_line = malloc(UNV_MAXLINE_LENGTH);
-
+
verbose("READ KEY [%s]", key);
/* sanity check */
@@ -796,7 +796,7 @@ int unv_remove_key( const char *path,
if (check_caller_context() == 0)
return -1;
-
+
fd = open(path, O_RDWR, FILE_MODE);
if (fd < 0) {
@@ -804,14 +804,14 @@ int unv_remove_key( const char *path,
return -1;
}
- p_search = get_keyval(fd, key, p_line, UNV_MAXLINE_LENGTH, &pos_begin, &pos_stop);
+ 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);
+ update_key(fd, key, NULL, pos_begin, pos_stop);
}
-
+
return (p_search ? 0 : -1);
}