diff options
author | Mattias Agren <magren@broadcom.com> | 2012-03-26 08:25:00 -0700 |
---|---|---|
committer | Matthew Xie <mattx@google.com> | 2012-07-14 11:19:13 -0700 |
commit | 254588bfe6c3e70625b0f725b908598f30f476c8 (patch) | |
tree | 259c87422e70b74abeab96b3e3155c88791e5b6d /udrv | |
parent | 3e6f399bdbaca7f8ab0a8b1c6eab7cc1088ab74a (diff) | |
download | external_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.h | 68 | ||||
-rw-r--r-- | udrv/include/unv.h | 80 | ||||
-rw-r--r-- | udrv/ulinux/uipc.c | 782 | ||||
-rw-r--r-- | udrv/ulinux/unv_linux.c | 204 |
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); } |