diff options
author | Andre Eisenbach <andre@broadcom.com> | 2012-02-22 13:18:21 -0800 |
---|---|---|
committer | Matthew Xie <mattx@google.com> | 2012-07-14 11:19:11 -0700 |
commit | e448862a47c08eb23185aaed574b39264f5005fc (patch) | |
tree | 2bc6246e3091315e77224fd798ea2fe8074ef972 /stack/obx/obx_main.c | |
parent | a2ca4b83ab8bbbfd8d5f6693e927ed4b82094624 (diff) | |
download | external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.zip external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.gz external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.bz2 |
Initial Bluedroid stack commit
Diffstat (limited to 'stack/obx/obx_main.c')
-rw-r--r-- | stack/obx/obx_main.c | 946 |
1 files changed, 946 insertions, 0 deletions
diff --git a/stack/obx/obx_main.c b/stack/obx/obx_main.c new file mode 100644 index 0000000..7dc7c97 --- /dev/null +++ b/stack/obx/obx_main.c @@ -0,0 +1,946 @@ +/***************************************************************************** +** +** Name: obx_main.c +** +** File: OBEX common API and interface to other Bluetooth modules +** +** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved. +** Broadcom Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ +#include <string.h> + +#include "bt_target.h" +#include "obx_int.h" +#include "btu.h" /* for timer */ +#include "l2c_api.h" +#include "l2cdefs.h" + +#if (defined (BT_USE_TRACES) && BT_USE_TRACES == TRUE) +const char * const obx_cl_state_name [] = +{ + "NULL", + "NOT_CONN", + "SESS_RS", + "CONN_RS", + "UNAUTH", + "CONN", + "DISCNT_RS", + "OP_UNAUTH", + "SETPATH_RS", + "ACT_RS", + "ABORT_RS", + "PUT_RS", + "GET_RS", + "PUT", + "GET", + "PUT_S", + "GET_S", + "PART", + "Unknown" +}; + +const char * const obx_cl_event_name [] = +{ + "CONN_R", + "SESS_R", + "DISCNT_R", + "PUT_R", + "GET_R", + "SETPATH_R", + "ACT_R", + "ABORT_R", + "OK_C", + "CONT_C", + "FAIL_C", + "PORT_CLS", + "TX_EMPTY", + "FCS_SET", + "STATE", + "TIMEOUT", + "Unknown" +}; + +const char * const obx_sr_state_name [] = +{ + "NULL", + "NOT_CONN", + "SESS_I", + "CONN_I", + "WAIT_AUTH", + "AUTH_I", + "CONN", + "DISCNT_I", + "SETPATH_I", + "ACT_I", + "ABORT_I", + "PUT_I", + "GET_I", + "PUT", + "GET", + "PUT_S", + "GET_S", + "PART", + "WAIT_CLS", + "Unknown" +}; + +const char * const obx_sr_event_name [] = +{ + "CONN_R", + "SESS_R", + "DISCNT_R", + "PUT_R", + "GET_R", + "SETPATH_R", + "ACT_R", + "ABORT_R", + "CONN_C", + "SESS_C", + "DISCNT_C", + "PUT_C", + "GET_C", + "SETPATH_C", + "ACT_C", + "ABORT_C", + "PORT_CLS", + "FCS_SET", + "STATE", + "TIMEOUT", + "BAD_REQ", + "TX_EMPTY", + "Unknown" +}; +#endif + +#if OBX_DYNAMIC_MEMORY == FALSE +OBX_API tOBX_CB obx_cb; +#endif + + +#if (defined (BT_USE_TRACES) && BT_USE_TRACES == TRUE) +#if (OBX_CLIENT_INCLUDED == TRUE) +/******************************************************************************* +** Function obx_cl_get_state_name +** Returns The client state name. +*******************************************************************************/ +const char *obx_cl_get_state_name(tOBX_CL_STATE state) +{ + const char * p_str = obx_cl_state_name[OBX_CS_MAX]; + if (state < OBX_CS_MAX) + { + p_str = obx_cl_state_name[state]; + } + return p_str; +} + +/******************************************************************************* +** Function obx_cl_get_event_name +** Returns The client event name. +*******************************************************************************/ +const char *obx_cl_get_event_name(tOBX_CL_EVENT event) +{ + const char * p_str = obx_cl_event_name[OBX_MAX_CEVT]; + if (event < OBX_MAX_CEVT) + { + p_str = obx_cl_event_name[event]; + } + return p_str; +} +#endif + +#if (OBX_SERVER_INCLUDED == TRUE) +/******************************************************************************* +** Function obx_sr_get_state_name +** Returns The server state name. +*******************************************************************************/ +const char *obx_sr_get_state_name(tOBX_SR_STATE state) +{ + const char * p_str = obx_sr_state_name[OBX_SS_MAX]; + if (state < OBX_SS_MAX) + { + p_str = obx_sr_state_name[state]; + } + return p_str; +} + +/******************************************************************************* +** Function obx_sr_get_event_name +** Returns The server event name. +*******************************************************************************/ +const char *obx_sr_get_event_name(tOBX_SR_EVENT event) +{ + const char * p_str = obx_sr_event_name[OBX_MAX_SEVT]; + if (event < OBX_MAX_SEVT) + { + p_str = obx_sr_event_name[event]; + } + return p_str; +} +#endif +#endif + +/******************************************************************************* +** Function obx_start_timer +** Description start BTU timer. +*******************************************************************************/ +void obx_start_timer(tOBX_COMM_CB *p_pcb) +{ + UINT16 type = 0; + UINT32 timeout = obx_cb.timeout_val; + + if (timeout) + { + if (p_pcb->handle & OBX_CL_HANDLE_MASK) + { + if (p_pcb->p_txmsg && p_pcb->p_txmsg->event == OBX_DISCONNECT_REQ_EVT) + { + timeout = OBX_DISC_TOUT_VALUE; + } + type = BTU_TTYPE_OBX_CLIENT_TO; + } + else + { + if (p_pcb->p_txmsg && p_pcb->p_txmsg->event == (OBX_DISCNT_CFM_SEVT + 1)) + { + timeout = OBX_DISC_TOUT_VALUE; + } + type = BTU_TTYPE_OBX_SERVER_TO; + } + btu_start_timer(&p_pcb->tle, type, timeout); + } + OBX_TRACE_DEBUG3("obx_start_timer type: %d, val:%d, p_tle:0x%x", type, timeout, &p_pcb->tle); +} + +/******************************************************************************* +** Function obx_stop_timer +** Description Stop BTU timer +*******************************************************************************/ +void obx_stop_timer(TIMER_LIST_ENT *p_tle) +{ + btu_stop_timer(p_tle); + OBX_TRACE_DEBUG1("obx_stop_timer p_tle:0x%x", p_tle); +} + +#if (OBX_CLIENT_INCLUDED == TRUE) +/******************************************************************************* +** Function obx_cl_timeout +** Description Get client control block from timer param. Start BTU timer again. +** Call application callback routine with OBX_TIMEOUT_EVT event. +*******************************************************************************/ +void obx_cl_timeout(TIMER_LIST_ENT *p_tle) +{ + tOBX_CL_CB *p_cb = (tOBX_CL_CB *) p_tle->param; + tOBX_EVT_PARAM evtp; + tOBX_HANDLE handle = p_cb->ll_cb.comm.handle; + tOBX_CL_CBACK *p_cback = p_cb->p_cback; + + memset(&evtp, 0, sizeof(tOBX_EVT_PARAM)); + if (obx_cb.timeout_val) + btu_start_timer(p_tle, BTU_TTYPE_OBX_CLIENT_TO, obx_cb.timeout_val); + obx_csm_event(p_cb, OBX_TIMEOUT_CEVT, NULL); + (*p_cback) (handle, OBX_TIMEOUT_EVT, OBX_RSP_DEFAULT, evtp, NULL); +} + +/******************************************************************************* +** +** Function obx_cl_alloc_cb +** +** Description allocate a client control block. +** +*******************************************************************************/ +tOBX_CL_CB *obx_cl_alloc_cb(void) +{ + int xx, yy; + tOBX_CL_CB *p_cb = NULL; + + /* allocate a client control block */ + for (xx=0, yy=obx_cb.next_ind; xx<obx_cb.num_client; xx++, yy++) + { + if (yy >= obx_cb.num_client) + yy = 0; + p_cb = &obx_cb.client[yy]; + + if (p_cb->ll_cb.comm.handle == OBX_HANDLE_NULL) + { + p_cb->ll_cb.comm.handle = OBX_CL_HANDLE_MASK | (yy + 1); + obx_cb.next_ind = yy+1; /* it will be adjusted, so we do not need to check the range now */ + OBX_TRACE_DEBUG3("obx_cl_alloc_cb obx handle:0x%x, yy:%d, next: %d", + p_cb->ll_cb.comm.handle, yy, obx_cb.next_ind); + p_cb->ll_cb.comm.tx_mtu = 0; + p_cb->conn_id = OBX_INVALID_CONN_ID; + + p_cb->ll_cb.comm.tle.param = (UINT32)p_cb; + p_cb->psm = 0; + p_cb->srm = 0; + break; + } + } + + if (xx == obx_cb.num_client) + p_cb = NULL; + return p_cb; +} + +/******************************************************************************* +** +** Function obx_cl_get_cb +** +** Description Returns the pointer to the client control block with given handle. +** +*******************************************************************************/ +tOBX_CL_CB *obx_cl_get_cb(tOBX_HANDLE handle) +{ + tOBX_CL_CB *p_cb = NULL; + UINT8 ind = (handle & OBX_CL_CB_IND_MASK); + + if (handle & OBX_CL_HANDLE_MASK) + { + if (ind <= obx_cb.num_client && ind > 0) + { + if (obx_cb.client[--ind].ll_cb.comm.handle == handle) + p_cb = &obx_cb.client[ind]; + } + } + + return p_cb; +} + +/******************************************************************************* +** +** Function obx_cl_get_suspended_cb +** +** Description Returns the pointer to the client control block with given handle. +** +*******************************************************************************/ +tOBX_CL_CB *obx_cl_get_suspended_cb(tOBX_HANDLE *p_handle, UINT8 *p_session_info) +{ + tOBX_HANDLE handle = *p_handle; + tOBX_CL_CB *p_cb = NULL; + tOBX_CL_CB *p_ccb = NULL; + UINT8 ind = (handle & OBX_CL_CB_IND_MASK); + + OBX_TRACE_DEBUG1("obx_cl_get_suspended_cb handle: 0x%x", handle); + if (handle & OBX_CL_HANDLE_MASK) + { + if (ind <= obx_cb.num_client && ind > 0) + { + if (obx_cb.client[--ind].ll_cb.comm.handle == handle) + { + p_ccb = &obx_cb.client[ind]; + if (p_ccb->sess_st == OBX_SESS_SUSPENDED && + ((p_session_info == p_ccb->sess_info) || (memcmp(p_session_info, p_ccb->sess_info, OBX_SESSION_INFO_SIZE) == 0))) + { + OBX_TRACE_DEBUG0("found a suspended session"); + p_cb = p_ccb; + } + } + } + } + if (p_cb == NULL) /* if the handle is NULL, assume the system was power cycled. attempt to allocate a control block */ + { + p_cb = obx_cl_alloc_cb(); + if (p_cb) + { + *p_handle = p_cb->ll_cb.comm.handle; + p_cb->sess_st = OBX_SESS_SUSPENDED; + memcpy(p_cb->sess_info, p_session_info, OBX_SESSION_INFO_SIZE); + OBX_TRACE_DEBUG1("allocated a suspended session handle: 0x%x", *p_handle); + } + } + + return p_cb; +} + +/******************************************************************************* +** +** Function obx_cl_free_cb +** +** Description Free the given client control block. +** +** Returns void +** +*******************************************************************************/ +void obx_cl_free_cb(tOBX_CL_CB * p_cb) +{ + if (p_cb) + { + OBX_TRACE_DEBUG2("obx_cl_free_cb id: %d, sess_st:%d", p_cb->ll_cb.comm.id, p_cb->sess_st); + + if (p_cb->ll_cb.comm.id>0) + { + if (p_cb->ll_cb.comm.p_send_fn == (tOBX_SEND_FN *)obx_rfc_snd_msg) + obx_cb.hdl_map[p_cb->ll_cb.port.port_handle - 1] = 0; + else + obx_cb.l2c_map[p_cb->ll_cb.l2c.lcid - L2CAP_BASE_APPL_CID] = 0; + } + + /* make sure the GKI buffers are freed */ + if (p_cb->p_next_req) + GKI_freebuf(p_cb->p_next_req); + + if (p_cb->p_saved_req) + GKI_freebuf(p_cb->p_saved_req); + + if (p_cb->p_auth) + GKI_freebuf(p_cb->p_auth); + + obx_free_buf (&p_cb->ll_cb); + + if (p_cb->psm) + L2CA_DEREGISTER (p_cb->psm); + + /* make sure the timer is stopped */ + btu_stop_timer(&p_cb->ll_cb.comm.tle); + + memset(p_cb, 0, sizeof(tOBX_CL_CB) ); + } +} +#endif /* OBX_CLIENT_INCLUDED */ + +#if (OBX_SERVER_INCLUDED == TRUE) +/******************************************************************************* +** Function obx_find_suspended_session +** Description if p_triplet is NULL, +** check if there's still room for a reliable session +** else check if the given session is still in the suspended list +*******************************************************************************/ +tOBX_SPND_CB *obx_find_suspended_session (tOBX_SR_SESS_CB *p_scb, tOBX_TRIPLET *p_triplet, UINT8 num) +{ + UINT8 ind; + BOOLEAN found = FALSE; + BOOLEAN infinite = FALSE; + UINT8 *p, xx; + tOBX_SR_CB *p_cb = obx_sr_get_cb(p_scb->handle); + tOBX_SPND_CB *p_spndcb, *p_ret = NULL; + + OBX_TRACE_DEBUG0("obx_find_suspended_session "); + if (p_triplet == NULL) + { + if (p_cb->p_suspend) + { + for (xx=0, p_spndcb=p_cb->p_suspend; xx<p_cb->max_suspend; xx++, p_spndcb++) + { + if ((p_spndcb->state == OBX_SS_NULL) || (memcmp(p_spndcb->peer_addr, p_scb->peer_addr, BD_ADDR_LEN)==0)) + { + OBX_TRACE_DEBUG3("[%d] state: %d, BDA: %08x", xx, p_spndcb->state, + (p_spndcb->peer_addr[2]<<24)+(p_spndcb->peer_addr[3]<<16)+(p_spndcb->peer_addr[4]<<8)+p_spndcb->peer_addr[5]); + /* this entry is not used yet or overwriting the entry with the same address */ + found = TRUE; + break; + } + else if (p_spndcb->stle.param == 0) + { + infinite = TRUE; + } + } + OBX_TRACE_DEBUG2("found: %d infinite:%d", found, infinite); + if (found == FALSE) + found = infinite; + } + else if (p_cb->max_suspend > 0) + { + found = TRUE; + } + p_ret = (tOBX_SPND_CB *)p_scb; + } + else if (p_cb->p_suspend) + { + ind = obx_read_triplet(p_triplet, num, OBX_TAG_SESS_PARAM_SESS_ID); + if (ind < num && p_triplet[ind].len == OBX_SESSION_ID_SIZE) + { + p = p_triplet[ind].p_array; + for (xx=0, p_spndcb=p_cb->p_suspend; xx<p_cb->max_suspend; xx++, p_spndcb++) + { + OBX_TRACE_DEBUG5("[%d] state: %d/%d, ssn:%d offset:x%x", xx, p_spndcb->state, + p_spndcb->sess_info[OBX_SESSION_INFO_ST_IDX], p_spndcb->ssn, p_spndcb->offset); + if ((p_spndcb->state != OBX_SS_NULL) && + (memcmp (p, p_spndcb->sess_info, OBX_SESSION_ID_SIZE) == 0)) + { + obxu_dump_hex (p_spndcb->sess_info, "sess info", OBX_SESSION_INFO_SIZE); + /* prepare p_scb to the proper state for resume */ + p_ret = p_spndcb; + break; + } + } + } + } + return p_ret; +} + +/******************************************************************************* +** Function obx_sr_sess_timeout +** Description Get suspended session control block from timer param. +** mark the suspended session as NULL +*******************************************************************************/ +void obx_sr_sess_timeout(TIMER_LIST_ENT *p_tle) +{ + tOBX_SPND_CB *p_spndcb = (tOBX_SPND_CB *) p_tle->param; + + OBX_TRACE_DEBUG0("obx_sr_sess_timeout"); + p_spndcb->state = OBX_SS_NULL; +} + +/******************************************************************************* +** Function obx_sr_timeout +** Description Get server control block from timer param. Start BTU timer again. +** Call application callback routine with OBX_TIMEOUT_EVT event. +*******************************************************************************/ +void obx_sr_timeout(TIMER_LIST_ENT *p_tle) +{ + tOBX_SR_SESS_CB *p_scb = (tOBX_SR_SESS_CB *) p_tle->param; + tOBX_EVT_PARAM evtp; + tOBX_HANDLE handle = p_scb->ll_cb.comm.handle; + tOBX_SR_CBACK *p_cback; + tOBX_SR_CB *p_cb; + + memset(&evtp, 0, sizeof(tOBX_EVT_PARAM)); + if (obx_cb.timeout_val) + btu_start_timer(p_tle, BTU_TTYPE_OBX_SERVER_TO, obx_cb.timeout_val); + p_cb = &obx_cb.server[p_scb->handle - 1]; + p_cback = p_cb->p_cback; + obx_ssm_event(p_scb, OBX_TIMEOUT_SEVT, NULL); + (*p_cback) (handle, OBX_TIMEOUT_EVT, evtp, NULL); +} + +/******************************************************************************* +** +** Function obx_sr_alloc_cb +** +** Description allocate a server control block. +** +*******************************************************************************/ +tOBX_HANDLE obx_sr_alloc_cb(tOBX_StartParams *p_params) +{ + int xx, yy, zz; + tOBX_SR_CB *p_cb = &obx_cb.server[0]; + tOBX_SR_SESS_CB *p_scb = &obx_cb.sr_sess[0]; + tOBX_HANDLE obx_handle = OBX_HANDLE_NULL; + + OBX_TRACE_DEBUG1("obx_sr_alloc_cb num sess: %d", p_params->max_sessions); + /* allocate a server control block */ + for (xx=0; xx<obx_cb.num_server; xx++, p_cb++) + { + if (p_cb->scn == 0 && p_cb->psm == 0) + { + obx_handle = xx + 1; + p_cb->scn = p_params->scn; + p_cb->psm = p_params->psm; + break; + } + } + + if (xx != obx_cb.num_server) + { + /* allocate session control blocks */ + zz = 0; + for (yy=0; yy<obx_cb.num_sr_sess && zz < p_params->max_sessions; yy++, p_scb++) + { + if (p_scb->ll_cb.comm.handle == OBX_HANDLE_NULL) + { + p_scb->handle = obx_handle; + if (p_params->get_nonf) + p_scb->srmp = OBX_SRMP_NONF_EVT; + p_cb->sess[zz] = yy + 1; + p_scb->srm = p_params->srm; + p_scb->ll_cb.comm.handle = OBX_ENC_SESS_HANDLE((obx_handle), zz); + p_scb->ll_cb.comm.tx_mtu = 0; + p_scb->ll_cb.comm.tle.param = (UINT32)p_scb; + OBX_TRACE_DEBUG2("[%d]: 0x%x", zz, p_scb->ll_cb.comm.handle); + zz++; + } + } + + if (zz == p_params->max_sessions && L2C_IS_VALID_PSM(p_params->psm)) + { + if (obx_l2c_sr_register(p_cb) != OBX_SUCCESS) + { + OBX_TRACE_ERROR0("Cannot register to L2CAP"); + zz = 0; /* let it fail */ + } + } + + if (zz != p_params->max_sessions) + { + OBX_TRACE_ERROR0("not enough resources: release the allocated ones"); + p_cb->scn = 0; + p_cb->psm = 0; + obx_handle = OBX_HANDLE_NULL; + p_scb = &obx_cb.sr_sess[0]; + for (yy=0; yy<obx_cb.num_sr_sess; yy++, p_scb++) + { + if (p_scb->handle == obx_handle) + { + p_scb->ll_cb.comm.handle = OBX_HANDLE_NULL; + } + } + } + else + { + p_cb->num_sess = p_params->max_sessions; + p_cb->nonce = p_params->nonce; + p_cb->max_suspend = p_params->max_suspend; + if (p_cb->nonce && (p_cb->max_suspend == 0)) + p_cb->max_suspend = 1; + if (p_cb->max_suspend > OBX_MAX_SUSPEND_SESSIONS) + p_cb->max_suspend = OBX_MAX_SUSPEND_SESSIONS; + if ((p_cb->max_suspend * sizeof (tOBX_SPND_CB)) > GKI_MAX_BUF_SIZE) + { + OBX_TRACE_ERROR1("OBX_MAX_SUSPEND_SESSIONS:%d is too big", OBX_MAX_SUSPEND_SESSIONS); + } + } + } + return obx_handle; +} + +/******************************************************************************* +** +** Function obx_sr_get_cb +** +** Description Returns the pointer to the server control block with given handle. +** +*******************************************************************************/ +tOBX_SR_CB * obx_sr_get_cb(tOBX_HANDLE handle) +{ + tOBX_SR_CB *p_cb = NULL; + tOBX_HANDLE obx_handle = OBX_DEC_HANDLE(handle); + + /* check range */ + if (obx_handle <= obx_cb.num_server && obx_handle > 0 && obx_cb.server[obx_handle-1].p_cback) + { + p_cb = &obx_cb.server[obx_handle-1]; + } + + return p_cb; +} + +/******************************************************************************* +** +** Function obx_sr_get_scb +** +** Description Returns the pointer to the server control block with given handle. +** +*******************************************************************************/ +tOBX_SR_SESS_CB * obx_sr_get_scb(tOBX_HANDLE handle) +{ + tOBX_SR_CB *p_cb; + tOBX_SR_SESS_CB *p_scb = NULL; + tOBX_HANDLE obx_handle; + UINT16 sess_ind; + + /* check range */ + obx_handle = OBX_DEC_HANDLE(handle) - 1; + if (obx_handle < obx_cb.num_server) + { + /* make sure the handle is a valid one */ + p_cb = &obx_cb.server[obx_handle]; + sess_ind = OBX_DEC_SESS_IND(handle); + if ((sess_ind < p_cb->num_sess)) + { + if ((obx_cb.sr_sess[p_cb->sess[sess_ind]-1].ll_cb.comm.handle) == handle) + p_scb = &obx_cb.sr_sess[p_cb->sess[sess_ind]-1]; + } + } + + return p_scb; +} + +/******************************************************************************* +** +** Function obx_sr_free_cb +** +** Description Free the given server control block. +** +** Returns void +** +*******************************************************************************/ +void obx_sr_free_cb(tOBX_HANDLE handle) +{ + tOBX_SR_CB * p_cb = obx_sr_get_cb(handle); + tOBX_SR_SESS_CB *p_scb; + int yy; + + OBX_TRACE_DEBUG1("obx_sr_free_cb handle:0x%x", handle); + /* check range */ + if (p_cb) + { + p_scb = &obx_cb.sr_sess[0]; + for (yy=0; yy<obx_cb.num_sr_sess; yy++, p_scb++) + { + if (OBX_DEC_HANDLE(p_scb->handle) == OBX_DEC_HANDLE(handle)) + { + obx_sr_free_scb(p_scb); + if (p_scb->ll_cb.comm.id>0) + { + if (p_scb->ll_cb.comm.p_send_fn == (tOBX_SEND_FN *)obx_rfc_snd_msg) + obx_cb.hdl_map[p_scb->ll_cb.port.port_handle - 1] = 0; + else + obx_cb.l2c_map[p_scb->ll_cb.l2c.lcid - L2CAP_BASE_APPL_CID] = 0; + } + memset(p_scb, 0, sizeof(tOBX_SR_SESS_CB) ); + } + } + + if (p_cb->p_auth) + { + GKI_freebuf(p_cb->p_auth); + p_cb->p_auth = 0; + } + + memset(p_cb, 0, sizeof(tOBX_SR_CB) ); + } +} + +/******************************************************************************* +** +** Function obx_sr_free_scb +** +** Description Free the given server session control block. +** +** Returns void +** +*******************************************************************************/ +void obx_sr_free_scb(tOBX_SR_SESS_CB *p_scb) +{ + OBX_TRACE_DEBUG2("obx_sr_free_scb shandle:0x%x, sess_st:%d", p_scb->ll_cb.comm.handle, p_scb->sess_st); + + /* make sure the GKI buffers are freed */ + if (p_scb->p_saved_msg) + { + GKI_freebuf(p_scb->p_saved_msg); + p_scb->p_saved_msg = 0; + } + + if (p_scb->p_next_req) + { + GKI_freebuf(p_scb->p_next_req); + p_scb->p_next_req = 0; + } + obx_free_buf (&p_scb->ll_cb); + + /* make sure the timer is stopped */ + btu_stop_timer(&p_scb->ll_cb.comm.tle); +} + +/******************************************************************************* +** +** Function obx_sr_get_next_conn_id +** +** Description assigns the next available connection id. It will avoid using +** active conn id instances as well so that we can work with the +** IVT stack bugs. +** +*******************************************************************************/ +UINT32 obx_sr_get_next_conn_id(void) +{ +#if (OBX_CLIENT_INCLUDED == TRUE) + tOBX_CL_CB *p_ccb; + int xx; + BOOLEAN done; + + /* Make sure no client instances are using the value */ + do + { + obx_cb.next_cid++; + + /* Increment the value and make sure it is legal */ + if (obx_cb.next_cid == OBX_INVALID_CONN_ID) + obx_cb.next_cid = OBX_INITIAL_CONN_ID; + + done = TRUE; + for (xx=0, p_ccb = &obx_cb.client[0]; xx < obx_cb.num_client; xx++, p_ccb++) + { + /* If the handle is in use and same as proposed conn_id, increment and restart */ + if (p_ccb->ll_cb.comm.handle != OBX_HANDLE_NULL && p_ccb->conn_id == obx_cb.next_cid) + { + OBX_TRACE_WARNING1(" **** OBX CONN_ID Collision (0x%08x) trying another...", obx_cb.next_cid); + done = FALSE; + break; + } + } + } while (!done); + +#else /* Client code is not compiled in */ + + obx_cb.next_cid++; + + /* Increment the value and make sure it is legal */ + if (obx_cb.next_cid == OBX_INVALID_CONN_ID) + obx_cb.next_cid = OBX_INITIAL_CONN_ID; +#endif + + return obx_cb.next_cid; +} + +#endif /* OBX_SERVER_INCLUDED */ + +/******************************************************************************* +** +** Function obx_port_handle_2cb +** +** Description Given a port handle, return the associated client or server +** control block. +** +** Returns +** +*******************************************************************************/ +tOBX_PORT_CB * obx_port_handle_2cb(UINT16 port_handle) +{ + tOBX_PORT_CB *p_pcb = NULL; + tOBX_HANDLE obx_handle = 0; +#if (OBX_SERVER_INCLUDED == TRUE) + tOBX_SR_CB *p_cb; +#endif + + /* this function is called by obx_rfc_cback() only. + * assume that port_handle is within range */ + obx_handle = obx_cb.hdl_map[port_handle-1]; + OBX_TRACE_DEBUG2("obx_port_handle_2cb port_handle:%d obx_handle:0x%x", port_handle, obx_handle); + + if (obx_handle > 0) + { + if (obx_handle & OBX_CL_HANDLE_MASK) + { +#if (OBX_CLIENT_INCLUDED == TRUE) + obx_handle &= OBX_CL_CB_IND_MASK; + p_pcb = &obx_cb.client[obx_handle - 1].ll_cb.port; +#endif /* OBX_CLIENT_INCLUDED */ + } + else + { +#if (OBX_SERVER_INCLUDED == TRUE) + p_cb = &obx_cb.server[OBX_DEC_HANDLE(obx_handle) - 1]; + p_pcb = &obx_cb.sr_sess[p_cb->sess[OBX_DEC_SESS_IND(obx_handle)]-1].ll_cb.port; + OBX_TRACE_DEBUG1("p_pcb port_handle:%d", p_pcb->port_handle); +#endif /* OBX_SERVER_INCLUDED */ + } + } + + return p_pcb; +} + + + +/******************************************************************************* +** +** Function OBX_Init +** +** Description This function is called to initialize the control block for this +** layer. It must be called before accessing any other of its API +** functions. It is typically called once during the start up of +** the stack. +** +** Returns void. +** +*******************************************************************************/ +void OBX_Init(void) +{ + memset(&obx_cb, 0, sizeof(tOBX_CB)); + +#if defined(OBX_INITIAL_TRACE_LEVEL) + obx_cb.trace_level = OBX_INITIAL_TRACE_LEVEL; +#else + obx_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */ +#endif + +#if (OBX_CLIENT_INCLUDED == TRUE) + obx_cb.next_ind = 0; + obx_cb.num_client = OBX_NUM_CLIENTS; +#endif + +#if (OBX_SERVER_INCLUDED == TRUE) + obx_cb.num_server = OBX_NUM_SERVERS; + obx_cb.num_sr_sess = OBX_NUM_SR_SESSIONS; + obx_cb.next_cid = OBX_INITIAL_CONN_ID; +#endif + obx_cb.timeout_val = OBX_TIMEOUT_VALUE; + obx_cb.sess_tout_val= OBX_SESS_TIMEOUT_VALUE; + obx_cb.max_rx_qcount= OBX_MAX_RX_QUEUE_COUNT; +} + +/******************************************************************************* +** +** Function OBX_SetTraceLevel +** +** Description This function sets the debug trace level for OBX. +** If 0xff is passed, the current trace level is returned. +** +** Input Parameters: +** level: The level to set the OBX tracing to: +** 0xff-returns the current setting. +** 0-turns off tracing. +** >= 1-Errors. +** >= 2-Warnings. +** >= 3-APIs. +** >= 4-Events. +** >= 5-Debug. +** +** Returns The new trace level or current trace level if +** the input parameter is 0xff. +** +*******************************************************************************/ +UINT8 OBX_SetTraceLevel (UINT8 level) +{ + if (level != 0xFF) + obx_cb.trace_level = level; + + return (obx_cb.trace_level); +} + +/******************************************************************************* +** Function OBX_HandleToMtu +** +** Description Given an OBEX handle, return the associated peer MTU. +** +** Returns MTU. +** +*******************************************************************************/ +UINT16 OBX_HandleToMtu(tOBX_HANDLE handle) +{ + UINT16 mtu = OBX_MIN_MTU; + BOOLEAN rx = (handle & OBX_HANDLE_RX_MTU_MASK); +#if (OBX_CLIENT_INCLUDED == TRUE) + int xx; +#endif +#if (OBX_SERVER_INCLUDED == TRUE) + tOBX_SR_SESS_CB *p_scb; +#endif + + handle &= ~OBX_HANDLE_RX_MTU_MASK; + + if (handle != OBX_HANDLE_NULL) + { + if (handle & OBX_CL_HANDLE_MASK) + { +#if (OBX_CLIENT_INCLUDED == TRUE) + /* a client handle */ + for (xx=0; xx<obx_cb.num_client; xx++) + { + if (handle == obx_cb.client[xx].ll_cb.comm.handle) + { + mtu = (rx) ? obx_cb.client[xx].ll_cb.comm.rx_mtu : obx_cb.client[xx].ll_cb.comm.tx_mtu; + break; + } + } +#endif + } + else + { +#if (OBX_SERVER_INCLUDED == TRUE) + /* a server handle */ + p_scb = obx_sr_get_scb(handle); + /* make sure the handle is a valid one */ + if (p_scb && p_scb->ll_cb.comm.handle != OBX_HANDLE_NULL) + { + mtu = (rx) ? p_scb->ll_cb.comm.rx_mtu : p_scb->ll_cb.comm.tx_mtu; + } +#endif + } + } + + if (mtu < OBX_MIN_MTU) + mtu = OBX_MIN_MTU; + OBX_TRACE_DEBUG3("OBX_HandleToMtu handle: 0x%x, rx:%x, mtu:%d", handle, rx, mtu); + return mtu; +} + |