Beispiel #1
1
bool btc_a2dp_sink_startup(void)
{
    if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_OFF) {
        APPL_TRACE_ERROR("warning : media task already running");
        return false;
    }

    APPL_TRACE_EVENT("## A2DP SINK START MEDIA THREAD ##");

    btc_aa_snk_queue_set = xQueueCreateSet(BTC_A2DP_SINK_TASK_QUEUE_SET_LEN);
    configASSERT(btc_aa_snk_queue_set);
    btc_aa_snk_data_queue = xQueueCreate(BTC_A2DP_SINK_DATA_QUEUE_LEN, sizeof(int32_t));
    configASSERT(btc_aa_snk_data_queue);
    xQueueAddToSet(btc_aa_snk_data_queue, btc_aa_snk_queue_set);

    btc_aa_snk_ctrl_queue = xQueueCreate(BTC_A2DP_SINK_CTRL_QUEUE_LEN, sizeof(void *));
    configASSERT(btc_aa_snk_ctrl_queue);
    xQueueAddToSet(btc_aa_snk_ctrl_queue, btc_aa_snk_queue_set);

    if (!btc_aa_snk_data_queue || !btc_aa_snk_ctrl_queue || !btc_aa_snk_queue_set ) {
        goto error_exit;
    }

    xTaskCreatePinnedToCore(btc_a2dp_sink_task_handler, BTC_A2DP_SINK_TASK_NAME, BTC_A2DP_SINK_TASK_STACK_SIZE, NULL, BTC_A2DP_SINK_TASK_PRIO, &btc_aa_snk_task_hdl, BTC_A2DP_SINK_TASK_PINNED_TO_CORE);
    if (btc_aa_snk_task_hdl == NULL) {
        goto error_exit;
    }

    btc_a2dp_sink_ctrl_post(BTC_MEDIA_TASK_SINK_INIT, NULL);

    APPL_TRACE_EVENT("## A2DP SINK MEDIA THREAD STARTED ##\n");

    return true;

error_exit:;
    APPL_TRACE_ERROR("%s unable to start up media thread\n", __func__);

    if (btc_aa_snk_task_hdl != NULL) {
        vTaskDelete(btc_aa_snk_task_hdl);
        btc_aa_snk_task_hdl = NULL;
    }

    if (btc_aa_snk_data_queue) {
        vQueueDelete(btc_aa_snk_data_queue);
        btc_aa_snk_data_queue = NULL;
    }
    if (btc_aa_snk_ctrl_queue) {
        vQueueDelete(btc_aa_snk_ctrl_queue);
        btc_aa_snk_ctrl_queue = NULL;
    }

    return false;
}
int btsock_thread_add_fd(int h, int fd, int type, int flags, uint32_t user_id)
{
    if(h < 0 || h >= MAX_THREAD)
    {
        APPL_TRACE_ERROR("invalid bt thread handle:%d", h);
        return FALSE;
    }
    if(ts[h].cmd_fdw == -1)
    {
        APPL_TRACE_ERROR("cmd socket is not created. socket thread may not initialized");
        return FALSE;
    }
    if(flags & SOCK_THREAD_ADD_FD_SYNC)
    {
        //must executed in socket poll thread
        if(ts[h].thread_id == pthread_self())
        {
            //cleanup one-time flags
            flags &= ~SOCK_THREAD_ADD_FD_SYNC;
            add_poll(h, fd, type, flags, user_id);
            return TRUE;
        }
        APPL_TRACE_DEBUG("THREAD_ADD_FD_SYNC is not called in poll thread, fallback to async");
    }
    sock_cmd_t cmd = {CMD_ADD_FD, fd, type, flags, user_id};
    APPL_TRACE_DEBUG("adding fd:%d, flags:0x%x", fd, flags);
    return send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd);
}
Beispiel #3
0
/*******************************************************************************
**
** Function         BTA_GATTC_DeregisterForNotifications
**
** Description      This function is called to de-register for notification of a service.
**
** Parameters       client_if - client interface.
**                  remote_bda - target GATT server.
**                  handle - GATT characteristic handle.
**
** Returns          OK if deregistration succeed, otherwise failed.
**
*******************************************************************************/
tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications (tBTA_GATTC_IF client_if,
                                                       BD_ADDR bda, UINT16 handle)
{
    if (!handle) {
        APPL_TRACE_ERROR("%s: deregistration failed, handle is 0", __func__);
        return BTA_GATT_ILLEGAL_PARAMETER;
    }

    tBTA_GATTC_RCB *p_clreg = bta_gattc_cl_get_regcb(client_if);
    if (p_clreg == NULL) {
        APPL_TRACE_ERROR("%s client_if: %d not registered bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
            __func__, client_if, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
        return BTA_GATT_ILLEGAL_PARAMETER;
    }

    for (int i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++) {
        if (p_clreg->notif_reg[i].in_use &&
            !memcmp(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN) &&
            p_clreg->notif_reg[i].handle == handle) {
            APPL_TRACE_DEBUG("%s deregistered bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
                __func__, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
            memset(&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
            return BTA_GATT_OK;
        }
    }

    APPL_TRACE_ERROR("%s registration not found bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
        __func__, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
    return BTA_GATT_ERROR;
}
/*******************************************************************************
**
** Function         BTA_GATTC_RegisterForNotifications
**
** Description      This function is called to register for notification of a service.
**
** Parameters       client_if - client interface.
**                  bda - target GATT server.
**                  p_char_id - pointer to GATT characteristic ID.
**
** Returns          OK if registration succeed, otherwise failed.
**
*******************************************************************************/
tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF client_if,
                                                     BD_ADDR bda,
                                                     tBTA_GATTC_CHAR_ID *p_char_id)
{
    tBTA_GATTC_RCB      *p_clreg;
    tBTA_GATT_STATUS    status = BTA_GATT_ILLEGAL_PARAMETER;
    UINT8               i;

    if (!p_char_id)
    {
        APPL_TRACE_ERROR("deregistration failed, unknow char id");
        return status;
    }

    if ((p_clreg = bta_gattc_cl_get_regcb(client_if)) != NULL)
    {
        for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
        {
            if ( p_clreg->notif_reg[i].in_use &&
                 !memcmp(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN) &&
                  bta_gattc_charid_compare(&p_clreg->notif_reg[i].char_id, p_char_id))
            {
                APPL_TRACE_WARNING("notification already registered");
                status = BTA_GATT_OK;
                break;
            }
        }
        if (status != BTA_GATT_OK)
        {
            for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
            {
                if (!p_clreg->notif_reg[i].in_use)
                {
                    memset((void *)&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));

                    p_clreg->notif_reg[i].in_use = TRUE;
                    memcpy(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN);

                    p_clreg->notif_reg[i].char_id.srvc_id.is_primary = p_char_id->srvc_id.is_primary;
                    bta_gattc_cpygattid(&p_clreg->notif_reg[i].char_id.srvc_id.id, &p_char_id->srvc_id.id);
                    bta_gattc_cpygattid(&p_clreg->notif_reg[i].char_id.char_id, &p_char_id->char_id);

                    status = BTA_GATT_OK;
                    break;
                }
            }
            if (i == BTA_GATTC_NOTIF_REG_MAX)
            {
                status = BTA_GATT_NO_RESOURCES;
                APPL_TRACE_ERROR("Max Notification Reached, registration failed.");
            }
        }
    }
    else
    {
        APPL_TRACE_ERROR("Client_if: %d Not Registered", client_if);
    }

    return status;
}
int btsock_thread_post_cmd(int h, int type, const unsigned char* data, int size, uint32_t user_id)
{
    if(h < 0 || h >= MAX_THREAD)
    {
        APPL_TRACE_ERROR("invalid bt thread handle:%d", h);
        return FALSE;
    }
    if(ts[h].cmd_fdw == -1)
    {
        APPL_TRACE_ERROR("cmd socket is not created. socket thread may not initialized");
        return FALSE;
    }
    sock_cmd_t cmd = {CMD_USER_PRIVATE, 0, type, size, user_id};
    APPL_TRACE_DEBUG("post cmd type:%d, size:%d, h:%d, ", type, size, h);
    sock_cmd_t* cmd_send = &cmd;
    int size_send = sizeof(cmd);
    if(data && size)
    {
        size_send = sizeof(cmd) + size;
        cmd_send = (sock_cmd_t*)alloca(size_send);
        if(cmd_send)
        {
            *cmd_send = cmd;
            memcpy(cmd_send + 1, data, size);
        }
        else
        {
            APPL_TRACE_ERROR("alloca failed at h:%d, cmd type:%d, size:%d", h, type, size_send);
            return FALSE;
        }
    }
    return send(ts[h].cmd_fdw, cmd_send, size_send, 0) == size_send;
}
Beispiel #6
0
/******************************************************************************
**
**          MAIN PARSING FUNCTION
**
**
*******************************************************************************/
void bta_hf_client_at_parse(char *buf, unsigned int len)
{
    APPL_TRACE_DEBUG("%s offset: %u len: %u", __FUNCTION__, bta_hf_client_cb.scb.at_cb.offset, len);

    if (len + bta_hf_client_cb.scb.at_cb.offset > BTA_HF_CLIENT_AT_PARSER_MAX_LEN) {
        unsigned int tmp = bta_hf_client_cb.scb.at_cb.offset;
        unsigned int space_left = BTA_HF_CLIENT_AT_PARSER_MAX_LEN - bta_hf_client_cb.scb.at_cb.offset;
        char *tmp_buff = osi_malloc(BTA_HF_CLIENT_AT_PARSER_MAX_LEN);
        if (tmp_buff == NULL) {
            APPL_TRACE_ERROR("No mem %s", __FUNCTION__);
            return;
        }
        APPL_TRACE_DEBUG("%s overrun, trying to recover", __FUNCTION__);

        /* fill up parser buffer */
        memcpy(bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, buf, space_left);
        len -= space_left;
        buf += space_left;
        bta_hf_client_cb.scb.at_cb.offset += space_left;

        /* find end of last complete command before proceeding */
        while (bta_hf_client_check_at_complete() == FALSE) {
            if (bta_hf_client_cb.scb.at_cb.offset == 0) {
                APPL_TRACE_ERROR("HFPClient: AT parser buffer overrun, disconnecting");

                bta_hf_client_at_reset();
                bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL);
                osi_free(tmp_buff);
                return;
            }

            bta_hf_client_cb.scb.at_cb.offset--;
        }

        /* cut buffer to complete AT event and keep cut data */
        tmp += space_left - bta_hf_client_cb.scb.at_cb.offset;
        memcpy(tmp_buff, bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, tmp);
        bta_hf_client_cb.scb.at_cb.buf[bta_hf_client_cb.scb.at_cb.offset] = '\0';

        /* parse */
        bta_hf_client_at_parse_start();
        bta_hf_client_at_clear_buf();

        /* recover cut data */
        memcpy(bta_hf_client_cb.scb.at_cb.buf, tmp_buff, tmp);
        bta_hf_client_cb.scb.at_cb.offset += tmp;

        osi_free(tmp_buff);
    }

    memcpy(bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, buf, len);
    bta_hf_client_cb.scb.at_cb.offset += len;

    /* If last event is complete, parsing can be started */
    if (bta_hf_client_check_at_complete() == TRUE) {
        bta_hf_client_at_parse_start();
        bta_hf_client_at_clear_buf();
    }
}
int btsock_thread_wakeup(int h)
{
    if(h < 0 || h >= MAX_THREAD)
    {
        APPL_TRACE_ERROR("invalid bt thread handle:%d", h);
        return FALSE;
    }
    if(ts[h].cmd_fdw == -1)
    {
        APPL_TRACE_ERROR("thread handle:%d, cmd socket is not created", h);
        return FALSE;
    }
    sock_cmd_t cmd = {CMD_WAKEUP, 0, 0, 0, 0};
    return send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd);
}
static BOOLEAN send_app_connect_signal(int fd, const bt_bdaddr_t* addr, int channel, int status, int send_fd)
{
/*
    typedef struct {
    short size;
    bt_bdaddr_t bd_addr;
    int channel;
    int status;
} __attribute__((packed)) sock_connect_signal_t;
*/
    sock_connect_signal_t cs;
    cs.size = sizeof(cs);
    cs.bd_addr = *addr;
    cs.channel = channel;
    cs.status = status;
    if(send_fd != -1)
    {
        if(sock_send_fd(fd, (const uint8_t*)&cs, sizeof(cs), send_fd) == sizeof(cs))
            return TRUE;
        else APPL_TRACE_ERROR("sock_send_fd failed, fd:%d, send_fd:%d", fd, send_fd);
    }
    else if(sock_send_all(fd, (const uint8_t*)&cs, sizeof(cs)) == sizeof(cs))
    {
        return TRUE;
    }
    return FALSE;
}
// l2c_slot_t* accept_ls = create_srv_accept_l2c_slot(srv_ls, p_open->rem_bda,p_opne->handle,  p_open->new_listen_handle);
static inline l2c_slot_t* create_srv_accept_l2c_slot(l2c_slot_t* srv_ls, const bt_bdaddr_t* addr,
                                        int open_handle, int new_listen_handle)
{
    l2c_slot_t *accept_ls = alloc_l2c_slot(addr, srv_ls->service_name, srv_ls->service_uuid, srv_ls->psm, 0, FALSE);
    if( accept_ls)
    {
        clear_slot_flag(&accept_ls->f);
        accept_ls->f.server = FALSE;
        accept_ls->f.connected = TRUE;
        accept_ls->security = srv_ls->security;
        accept_ls->put_size = srv_ls->put_size;
        accept_ls->role = srv_ls->role;
        accept_ls->l2c_handle = open_handle;
        //now update listen l2c_handle of server slot
        srv_ls->l2c_handle = new_listen_handle;
        //now swap the slot id
        uint32_t new_listen_id = accept_ls->id;
        accept_ls->id = srv_ls->id;
        srv_ls->id = new_listen_id;

        return accept_ls;
    }
    else
    {
        APPL_TRACE_ERROR(" accept_ls is NULL %s", __FUNCTION__);
        return NULL;
    }
}
static l2c_slot_t* alloc_l2c_slot(const bt_bdaddr_t *addr, const char* name, const uint8_t* uuid, int channel, int flags, BOOLEAN server)
{
    int security = 0;
    if(flags & BTSOCK_FLAG_ENCRYPT)
        security |= server ? BTM_SEC_IN_ENCRYPT : BTM_SEC_OUT_ENCRYPT;
    if(flags & BTSOCK_FLAG_AUTH) {
        security |= server ? BTM_SEC_IN_AUTHENTICATE : BTM_SEC_OUT_AUTHENTICATE;
    }
    l2c_slot_t* ls = find_free_slot();
    if(ls)
    {
        int fds[2] = {-1, -1};
        if(socketpair(AF_LOCAL, SOCK_STREAM, 0, fds))
        {
            APPL_TRACE_ERROR("socketpair failed, errno:%d", errno);
            return NULL;
        }
        ls->fd = fds[0];
        ls->app_fd = fds[1];

        APPL_TRACE_DEBUG("alloc_l2c_slot fd %d and app fd  %d is_server %d", ls->fd, ls->app_fd, server);
        ls->security = security;
        ls->psm = channel;
        if(uuid)
            memcpy(ls->service_uuid, uuid, sizeof(ls->service_uuid));
        else memset(ls->service_uuid, 0, sizeof(ls->service_uuid));
        if(name && *name)
            strlcpy(ls->service_name, name, sizeof(ls->service_name) -1);
        if(addr)
            ls->addr = *addr;
        ls->in_use = TRUE;
        ls->f.server = server;
    }
    return ls;
}
/*******************************************************************************
**
** Function         bta_gattc_clear_notif_registration
**
** Description      clear up the notification registration information by BD_ADDR.
**
** Returns          None.
**
*******************************************************************************/
void bta_gattc_clear_notif_registration(UINT16 conn_id)
{
    BD_ADDR             remote_bda;
    tBTA_GATTC_IF       gatt_if;
    tBTA_GATTC_RCB      *p_clrcb ;
    UINT8       i;
    tGATT_TRANSPORT     transport;

    if (GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda, &transport))
    {
        if ((p_clrcb = bta_gattc_cl_get_regcb(gatt_if)) != NULL)
        {
            for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
            {
                if (p_clrcb->notif_reg[i].in_use &&
                    !bdcmp(p_clrcb->notif_reg[i].remote_bda, remote_bda))
                    memset(&p_clrcb->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
            }
        }
    }
    else
    {
        APPL_TRACE_ERROR("can not clear indication/notif registration for unknown app");
    }
    return;
}
static inline void add_poll(int h, int fd, int type, int flags, uint32_t user_id)
{
    asrt(fd != -1);
    int i;
    int empty = -1;
    poll_slot_t* ps = ts[h].ps;

    for(i = 0; i < MAX_POLL; i++)
    {
        if(ps[i].pfd.fd == fd)
        {
            asrt(ts[h].poll_count < MAX_POLL);

            set_poll(&ps[i], fd, type, flags | ps[i].flags, user_id);
            return;
        }
        else if(empty < 0 && ps[i].pfd.fd == -1)
            empty = i;
    }
    if(empty >= 0)
    {
        asrt(ts[h].poll_count < MAX_POLL);
        set_poll(&ps[empty], fd, type, flags, user_id);
        ++ts[h].poll_count;
        return;
    }
    APPL_TRACE_ERROR("exceeded max poll slot:%d!", MAX_POLL);
}
Beispiel #13
0
/*******************************************************************************
**
** Function         BTA_AgEnable
**
** Description      Enable the audio gateway service. When the enable
**                  operation is complete the callback function will be
**                  called with a BTA_AG_ENABLE_EVT. This function must
**                  be called before other function in the AG API are
**                  called.
**
** Returns          BTA_SUCCESS if OK, BTA_FAILURE otherwise.
**
*******************************************************************************/
tBTA_STATUS BTA_AgEnable(tBTA_AG_PARSE_MODE parse_mode, tBTA_AG_CBACK *p_cback)
{
    tBTA_AG_API_ENABLE  *p_buf;
    UINT8       idx;

    /* Error if AG is already enabled, or AG is in the middle of disabling. */
    for (idx = 0; idx < BTA_AG_NUM_SCB; idx++)
    {
        if (bta_ag_cb.scb[idx].in_use)
        {
            APPL_TRACE_ERROR ("BTA_AgEnable: FAILED, AG already enabled.");
            return BTA_FAILURE;
        }
    }

    /* register with BTA system manager */
    bta_sys_register(BTA_ID_AG, &bta_ag_reg);

    if ((p_buf = (tBTA_AG_API_ENABLE *) GKI_getbuf(sizeof(tBTA_AG_API_ENABLE))) != NULL)
    {
        p_buf->hdr.event = BTA_AG_API_ENABLE_EVT;
        p_buf->parse_mode = parse_mode;
        p_buf->p_cback = p_cback;
        bta_sys_sendmsg(p_buf);
    }

    return BTA_SUCCESS;

}
Beispiel #14
0
/*******************************************************************************
**
** Function         bta_ag_api_disable
**
** Description      Handle an API disable event.
**
**
** Returns          void
**
*******************************************************************************/
static void bta_ag_api_disable(tBTA_AG_DATA *p_data)
{
    /* deregister all scbs in use */
    tBTA_AG_SCB     *p_scb = &bta_ag_cb.scb[0];
    BOOLEAN         do_dereg = FALSE;
    int             i;

    if (!bta_sys_is_register (BTA_ID_AG))
    {
        APPL_TRACE_ERROR("BTA AG is already disabled, ignoring ...");
        return;
    }

    /* De-register with BTA system manager */
    bta_sys_deregister(BTA_ID_AG);

    for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++)
    {
        if (p_scb->in_use)
        {
            bta_ag_sm_execute(p_scb, BTA_AG_API_DEREGISTER_EVT, p_data);
            do_dereg = TRUE;
        }
    }

    if (!do_dereg)
    {
        /* Done, send callback evt to app */
        (*bta_ag_cb.p_cback)(BTA_AG_DISABLE_EVT, NULL);
    }

    bta_sys_collision_register (BTA_ID_AG, NULL);
}
/*******************************************************************************
**
** Function         bta_gattc_clcb_dealloc
**
** Description      Deallocte a clcb
**
** Returns          pointer to the clcb
**
*******************************************************************************/
void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb)
{
    tBTA_GATTC_SERV     *p_srcb = NULL;

    if (p_clcb)
    {
        p_srcb = p_clcb->p_srcb;
        if (p_srcb->num_clcb)
            p_srcb->num_clcb --;

        if (p_clcb->p_rcb->num_clcb)
            p_clcb->p_rcb->num_clcb --;

        /* if the srcb is no longer needed, reset the state */
        if ( p_srcb->num_clcb == 0)
        {
            p_srcb->connected = FALSE;
            p_srcb->state = BTA_GATTC_SERV_IDLE;
            p_srcb->mtu = 0;
        }

        utl_freebuf((void **)&p_clcb->p_q_cmd);

        memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB));
    }
    else
    {
        APPL_TRACE_ERROR("bta_gattc_clcb_dealloc p_clcb=NULL");
    }
}
Beispiel #16
0
void bta_hf_client_send_at_bia(void)
{
    char *buf;
    int at_len;
    int i;

    APPL_TRACE_DEBUG("%s", __FUNCTION__);
    if (bta_hf_client_cb.scb.peer_version < HFP_VERSION_1_6) {
        APPL_TRACE_DEBUG("Remote does not Support AT+BIA");
        return;
    }

    buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN);
    if (buf == NULL) {
        APPL_TRACE_ERROR("No mem %s", __FUNCTION__);
        return;
    }
    at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+BIA=");

    for (i = 0; i < BTA_HF_CLIENT_AT_INDICATOR_COUNT; i++) {
        int sup = bta_hf_client_cb.scb.at_cb.indicator_lookup[i] == -1 ? 0 : 1;

        at_len += snprintf(buf + at_len, BTA_HF_CLIENT_AT_MAX_LEN - at_len, "%u,", sup);
    }

    buf[at_len - 1] = '\r';

    bta_hf_client_send_at(BTA_HF_CLIENT_AT_BIA, buf, at_len);
    osi_free(buf);
}
Beispiel #17
0
static char *bta_hf_client_parse_cind_list(char *buffer)
{
    int offset;
    char *name = osi_malloc(129);
    UINT32 min, max;
    UINT32 index = 0;
    int res;

    if (name == NULL) {
        APPL_TRACE_ERROR("No mem %s", __FUNCTION__);
        return NULL;
    }

    while ((res = sscanf(buffer, "(\"%128[^\"]\",(%u%*[-,]%u))%n", name, &min, &max, &offset)) > 2) {
        bta_hf_client_handle_cind_list_item(name, min, max, index);
        buffer += offset;
        index++;

        if (*buffer != ',') {
            break;
        }

        buffer++;
    }

    osi_free(name);

    if (res > 2) {
        AT_CHECK_RN(buffer);
        return buffer;
    }

    return NULL;
}
static int process_cmd_sock(int h)
{
    sock_cmd_t cmd = {-1, 0, 0, 0, 0};
    int fd = ts[h].cmd_fdr;
    if(recv(fd, &cmd, sizeof(cmd), MSG_WAITALL) != sizeof(cmd))
    {
        APPL_TRACE_ERROR("recv cmd errno:%d", errno);
        return FALSE;
    }
    APPL_TRACE_DEBUG("cmd.id:%d", cmd.id);
    switch(cmd.id)
    {
        case CMD_ADD_FD:
            add_poll(h, cmd.fd, cmd.type, cmd.flags, cmd.user_id);
            break;
        case CMD_WAKEUP:
            break;
        case CMD_USER_PRIVATE:
            asrt(ts[h].cmd_callback);
            if(ts[h].cmd_callback)
                ts[h].cmd_callback(fd, cmd.type, cmd.flags, cmd.user_id);
            break;
        case CMD_EXIT:
            return FALSE;
        default:
            APPL_TRACE_DEBUG("unknown cmd: %d", cmd.id);
             break;
    }
    return TRUE;
}
static void prepare_poll_fds(int h, struct pollfd* pfds)
{
    int count = 0;
    int ps_i = 0;
    int pfd_i = 0;
    asrt(ts[h].poll_count <= MAX_POLL);
    memset(pfds, 0, sizeof(pfds[0])*ts[h].poll_count);
    while(count < ts[h].poll_count)
    {
        if(ps_i >= MAX_POLL)
        {
            APPL_TRACE_ERROR("exceed max poll range, ps_i:%d, MAX_POLL:%d, count:%d, ts[h].poll_count:%d",
                    ps_i, MAX_POLL, count, ts[h].poll_count);
            return;
        }
        if(ts[h].ps[ps_i].pfd.fd >= 0)
        {
            pfds[pfd_i] =  ts[h].ps[ps_i].pfd;
            ts[h].psi[pfd_i] = ps_i;
            count++;
            pfd_i++;
        }
        ps_i++;
    }
}
Beispiel #20
0
/*******************************************************************************
**
** Function         BTA_GATTC_RegisterForNotifications
**
** Description      This function is called to register for notification of a service.
**
** Parameters       client_if - client interface.
**                  bda - target GATT server.
**                  handle - GATT characteristic handle.
**
** Returns          OK if registration succeed, otherwise failed.
**
*******************************************************************************/
tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF client_if,
                                                     BD_ADDR bda, UINT16 handle)
{
    tBTA_GATTC_RCB      *p_clreg;
    tBTA_GATT_STATUS    status = BTA_GATT_ILLEGAL_PARAMETER;
    UINT8               i;

    if (!handle)
    {
        APPL_TRACE_ERROR("deregistration failed, handle is 0");
        return status;
    }

    if ((p_clreg = bta_gattc_cl_get_regcb(client_if)) != NULL) {
        for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++) {
            if ( p_clreg->notif_reg[i].in_use &&
                    !memcmp(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN) &&
                  p_clreg->notif_reg[i].handle == handle) {
                APPL_TRACE_DEBUG("notification already registered");
                status = BTA_GATT_OK;
                break;
            }
        }
        if (status != BTA_GATT_OK) {
            for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++) {
                if (!p_clreg->notif_reg[i].in_use) {
                    memset((void *)&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));

                    p_clreg->notif_reg[i].in_use = TRUE;
                    memcpy(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN);

                    p_clreg->notif_reg[i].handle = handle;
                    status = BTA_GATT_OK;
                    break;
                }
            }
            if (i == BTA_GATTC_NOTIF_REG_MAX) {
                status = BTA_GATT_NO_RESOURCES;
                APPL_TRACE_ERROR("Max Notification Reached, registration failed.");
            }
        }
    } else {
        APPL_TRACE_ERROR("Client_if: %d Not Registered", client_if);
    }

    return status;
}
/*******************************************************************************
**
** Function         bta_ag_pm_sniff
**
** Description      Switch to sniff mode.
**
**
** Returns          TRUE if sniff attempted, FALSE otherwise.
**
*******************************************************************************/
static BOOLEAN bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE *p_peer_dev, UINT8 index)
{
    tBTM_PM_MODE    mode = BTM_PM_STS_ACTIVE;
    tBTM_PM_PWR_MD  pwr_md;
    tBTM_STATUS     status;
    UINT8* p = NULL;
    BTM_ReadPowerMode(p_peer_dev->peer_bdaddr, &mode);

#if (BTM_SSR_INCLUDED == TRUE)
    APPL_TRACE_DEBUG("bta_dm_pm_sniff cur:%d, idx:%d, info:x%x", mode, index, p_peer_dev->info);
    if (mode != BTM_PM_MD_SNIFF ||
        (HCI_SNIFF_SUB_RATE_SUPPORTED(BTM_ReadLocalFeatures ()) &&
         (((p = BTM_ReadRemoteFeatures(p_peer_dev->peer_bdaddr)) != NULL) &&
           HCI_SNIFF_SUB_RATE_SUPPORTED(p)) && !(p_peer_dev->info & BTA_DM_DI_USE_SSR)))
#else
    APPL_TRACE_DEBUG("bta_dm_pm_sniff cur:%d, idx:%d", mode, index);
    if(mode != BTM_PM_MD_SNIFF)
#endif
    {
#if (BTM_SSR_INCLUDED == TRUE)
        /* Dont initiate Sniff if controller has alreay accepted
         * remote sniff params. This avoid sniff loop issue with
         * some agrresive headsets who use sniff latencies more than
         * DUT supported range of Sniff intervals.*/
        if ((mode == BTM_PM_MD_SNIFF) && (p_peer_dev->info & BTA_DM_DI_ACP_SNIFF))
        {
            APPL_TRACE_DEBUG("bta_dm_pm_sniff: already in remote initiate sniff");
            return TRUE;
        }
#endif
        /* if the current mode is not sniff, issue the sniff command.
         * If sniff, but SSR is not used in this link, still issue the command */
        memcpy(&pwr_md, &p_bta_dm_pm_md[index], sizeof (tBTM_PM_PWR_MD));
        if (p_peer_dev->info & BTA_DM_DI_INT_SNIFF)
        {
            pwr_md.mode |= BTM_PM_MD_FORCE;
        }
        status = BTM_SetPowerMode (bta_dm_cb.pm_id, p_peer_dev->peer_bdaddr, &pwr_md);
        if (status == BTM_CMD_STORED|| status == BTM_CMD_STARTED)
        {
            p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF);
            p_peer_dev->info |= BTA_DM_DI_SET_SNIFF;
        }
        else if (status == BTM_SUCCESS)
        {
            APPL_TRACE_DEBUG("bta_dm_pm_sniff BTM_SetPowerMode() returns BTM_SUCCESS");
            p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF|BTA_DM_DI_SET_SNIFF);
        }
        else /* error */
        {
            APPL_TRACE_ERROR("bta_dm_pm_sniff BTM_SetPowerMode() returns ERROR status=%d", status);
            p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF|BTA_DM_DI_SET_SNIFF);
        }
    }
    /* else already in sniff and is using SSR, do nothing */

    return TRUE;

}
/*******************************************************************************
**
** Function         bta_ag_sm_execute
**
** Description      State machine event handling function for AG
**
**
** Returns          void
**
*******************************************************************************/
void bta_ag_sm_execute(tBTA_AG_SCB *p_scb, UINT16 event, tBTA_AG_DATA *p_data)
{
    tBTA_AG_ST_TBL      state_table;
    UINT8               action;
    int                 i;
    UINT16  in_event = event;
    UINT8   in_state = p_scb->state;

    if (in_event != BTA_AG_API_RESULT_EVT || p_scb->state == BTA_AG_OPEN_ST)
    {
        #if BTA_AG_DEBUG == TRUE
            APPL_TRACE_IMP("AG evt (hdl 0x%04x): State %d (%s), Event 0x%04x (%s)",
                           bta_ag_scb_to_idx(p_scb),
                           p_scb->state, bta_ag_state_str(p_scb->state),
                           event, bta_ag_evt_str(event, p_data->api_result.result));
        #else
           APPL_TRACE_IMP("AG evt (hdl 0x%04x): State %d, Event 0x%04x",
                      bta_ag_scb_to_idx(p_scb), p_scb->state, event);
        #endif
    }

    event &= 0x00FF;
    if (event >= (BTA_AG_MAX_EVT & 0x00FF))
    {
        APPL_TRACE_ERROR("AG evt out of range, ignoring...");
        return;
    }

    /* look up the state table for the current state */
    state_table = bta_ag_st_tbl[p_scb->state];

    /* set next state */
    p_scb->state = state_table[event][BTA_AG_NEXT_STATE];

    /* execute action functions */
    for (i = 0; i < BTA_AG_ACTIONS; i++)
    {
        if ((action = state_table[event][i]) != BTA_AG_IGNORE)
        {
            (*bta_ag_action[action])(p_scb, p_data);
        }
        else
        {
            break;
        }
    }
    if (p_scb->state != in_state)
    {
        #if BTA_AG_DEBUG == TRUE
            APPL_TRACE_IMP("BTA AG State Change: [%s] -> [%s] after Event [%s]",
                      bta_ag_state_str(in_state),
                      bta_ag_state_str(p_scb->state),
                      bta_ag_evt_str(in_event, p_data->api_result.result));
        #else
            APPL_TRACE_IMP("BTA AG State Change: [%d] -> [%d]",
                              in_state, p_scb->state);
        #endif
    }
}
Beispiel #23
0
/******************************************************************************
**
** Function         bta_ag_at_parse
**
** Description      Parse AT commands.  This function will take the input
**                  character string and parse it for AT commands according to
**                  the AT command table passed in the control block.
**
**
** Returns          void
**
******************************************************************************/
void bta_ag_at_parse(tBTA_AG_AT_CB *p_cb, char *p_buf, UINT16 len)
{
    int i = 0;
    char* p_save;

    if (p_cb->p_cmd_buf == NULL)
    {
        if ((p_cb->p_cmd_buf = (char *) GKI_getbuf(p_cb->cmd_max_len)) == NULL)
        {
            APPL_TRACE_ERROR("%s: GKI_getbuf() failed allocation", __func__);
            return;
        }
        p_cb->cmd_pos = 0;
    }

    for (i = 0; i < len;)
    {
        while (p_cb->cmd_pos < p_cb->cmd_max_len-1 && i < len)
        {
            /* Skip null characters between AT commands. */
            if ((p_cb->cmd_pos == 0) && (p_buf[i] == 0))
            {
                i++;
                continue;
            }

            p_cb->p_cmd_buf[p_cb->cmd_pos] = p_buf[i++];
            if ( p_cb->p_cmd_buf[p_cb->cmd_pos] == '\r' || p_cb->p_cmd_buf[p_cb->cmd_pos] == '\n')
            {
                p_cb->p_cmd_buf[p_cb->cmd_pos] = 0;
                if ((p_cb->cmd_pos > 2)                                      &&
                        (p_cb->p_cmd_buf[0] == 'A' || p_cb->p_cmd_buf[0] == 'a') &&
                        (p_cb->p_cmd_buf[1] == 'T' || p_cb->p_cmd_buf[1] == 't'))
                {
                    p_save = p_cb->p_cmd_buf;
                    p_cb->p_cmd_buf += 2;
                    bta_ag_process_at(p_cb);
                    p_cb->p_cmd_buf = p_save;
                }

                p_cb->cmd_pos = 0;

            }
            else if( p_cb->p_cmd_buf[p_cb->cmd_pos] == 0x1A || p_cb->p_cmd_buf[p_cb->cmd_pos] == 0x1B )
            {
                p_cb->p_cmd_buf[++p_cb->cmd_pos] = 0;
                (*p_cb->p_err_cback)(p_cb->p_user, TRUE, p_cb->p_cmd_buf);
                p_cb->cmd_pos = 0;
            }
            else
            {
                ++p_cb->cmd_pos;
            }
        }

        if (i < len)
            p_cb->cmd_pos = 0;
    }
}
static inline int create_server_socket(const char* name)
{
    int s = socket(AF_LOCAL, SOCK_STREAM, 0);
    APPL_TRACE_DEBUG("covert name to android abstract name:%s", name);
    if(socket_local_server_bind(s, name, ANDROID_SOCKET_NAMESPACE_ABSTRACT) >= 0)
    {
        if(listen(s, 5) == 0)
        {
            APPL_TRACE_DEBUG("listen to local socket:%s, fd:%d", name, s);
            return s;
        }
        else APPL_TRACE_ERROR("listen to local socket:%s, fd:%d failed, errno:%d", name, s, errno);
    }
    else APPL_TRACE_ERROR("create local socket:%s fd:%d, failed, errno:%d", name, s, errno);
    close(s);
    return -1;
}
static void bta_hf_client_at_parse_start(void)
{
    char *buf = bta_hf_client_cb.scb.at_cb.buf;

    APPL_TRACE_DEBUG("%s", __FUNCTION__);

#ifdef BTA_HF_CLIENT_AT_DUMP
    bta_hf_client_dump_at();
#endif

    while(*buf != '\0')
    {
        int i;
        char *tmp = NULL;

        for(i = 0; i < bta_hf_client_psraser_cb_count; i++)
        {
            tmp = bta_hf_client_parser_cb[i](buf);
            if (tmp == NULL)
            {
                APPL_TRACE_ERROR("HFPCient: AT event/reply parsing failed, skipping");
                tmp = bta_hf_client_skip_unknown(buf);
                break;
            }

            /* matched or unknown skipped, if unknown failed tmp is NULL so
               this is also handled */
            if (tmp != buf)
            {
                buf = tmp;
                break;
            }
        }

        /* could not skip unknown (received garbage?)... disconnect */
        if (tmp == NULL)
        {
            APPL_TRACE_ERROR("HFPCient: could not skip unknown AT event, disconnecting");
            bta_hf_client_at_reset();
            bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL);
            return;
        }

        buf = tmp;
    }
}
static void free_thread_slot(int h)
{
    if(0 <= h && h < MAX_THREAD)
    {
        close_cmd_fd(h);
        ts[h].used = 0;
    }
    else APPL_TRACE_ERROR("invalid thread handle:%d", h);
}
Beispiel #27
0
static void bta_hf_client_at_resp_timer_cback (TIMER_LIST_ENT *p_tle)
{
    if (p_tle) {
        bta_hf_client_cb.scb.at_cb.resp_timer_on = FALSE;

        APPL_TRACE_ERROR("HFPClient: AT response timeout, disconnecting");

        bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL);
    }
}
Beispiel #28
0
void bta_dm_co_ble_set_io_cap(UINT8 ble_io_cap)
{
#if (SMP_INCLUDED == TRUE)
    if(ble_io_cap < BTM_IO_CAP_MAX ) {
        bte_appl_cfg.ble_io_cap = ble_io_cap;
    } else {
        APPL_TRACE_ERROR("%s error:Invalid io cap value.",__func__);
    }
#endif  ///SMP_INCLUDED == TRUE
}
Beispiel #29
0
void bta_dm_co_ble_set_max_key_size(UINT8 ble_key_size)
{
#if (SMP_INCLUDED == TRUE)
    if(ble_key_size >= BTM_BLE_MIN_KEY_SIZE && ble_key_size <= BTM_BLE_MAX_KEY_SIZE) {
        bte_appl_cfg.ble_max_key_size = ble_key_size;
    } else {
        APPL_TRACE_ERROR("%s error:Invalid key size value, key_size =%d",__func__, ble_key_size);
    }
#endif  ///SMP_INCLUDED == TRUE
}
static inline void set_socket_blocking(int s, int blocking)
{
    int opts;
    opts = fcntl(s, F_GETFL);
    if (opts<0) APPL_TRACE_ERROR("set blocking (%s)", strerror(errno));
    if(blocking)
        opts &= ~O_NONBLOCK;
    else opts |= O_NONBLOCK;
    fcntl(s, F_SETFL, opts);
}