From 8aae7556993cdba8995146be134f8b77a8e15ba4 Mon Sep 17 00:00:00 2001 From: zzy Date: Thu, 11 Oct 2012 14:48:58 -0700 Subject: Add serial port profile support and allow to connect to rfcomm channel without sdp discovery bug 7272974 Change-Id: Idc10edc056b48da2fd96bea84eba3fb73b97bab1 --- btif/include/btif_sock_sdp.h | 8 ++++- btif/src/btif_sock_rfc.c | 80 ++++++++++++++++++++++++++++---------------- btif/src/btif_sock_sdp.c | 57 +++++++++++++++++++++++++------ 3 files changed, 106 insertions(+), 39 deletions(-) diff --git a/btif/include/btif_sock_sdp.h b/btif/include/btif_sock_sdp.h index 5ca9959..9fe4768 100644 --- a/btif/include/btif_sock_sdp.h +++ b/btif/include/btif_sock_sdp.h @@ -18,11 +18,17 @@ #ifndef BTIF_SOCK_SDP_H #define BTIF_SOCK_SDP_H +static const UINT8 UUID_OBEX_OBJECT_PUSH[] = {0x00, 0x00, 0x11, 0x05, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB}; +static const UINT8 UUID_PBAP_PSE[] = {0x00, 0x00, 0x11, 0x2F, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB}; +static const UINT8 UUID_SPP[] = {0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB}; static inline BOOLEAN is_uuid_empty(const uint8_t* uuid) { static uint8_t empty_uuid[16]; - return memcmp(uuid, empty_uuid, sizeof(empty_uuid)) == 0; + return uuid == NULL || memcmp(uuid, empty_uuid, sizeof(empty_uuid)) == 0; } int add_rfc_sdp_rec(const char* name, const uint8_t* uuid, int scn); diff --git a/btif/src/btif_sock_rfc.c b/btif/src/btif_sock_rfc.c index b77ce4a..6202ca4 100644 --- a/btif/src/btif_sock_rfc.c +++ b/btif/src/btif_sock_rfc.c @@ -110,7 +110,8 @@ static void cleanup_rfc_slot(rfc_slot_t* rs); static inline void close_rfc_connection(int rfc_handle, int server); static bt_status_t dm_get_remote_service_record(bt_bdaddr_t *remote_addr, bt_uuid_t *uuid); - +static void *rfcomm_cback(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data); +static inline BOOLEAN send_app_scn(rfc_slot_t* rs); static pthread_mutex_t slot_lock; #define is_init_done() (pth != -1) static inline void clear_slot_flag(flags_t* f) @@ -271,6 +272,7 @@ static rfc_slot_t* alloc_rfc_slot(const bt_bdaddr_t *addr, const char* name, con rs->scn = channel; if(uuid) memcpy(rs->service_uuid, uuid, sizeof(rs->service_uuid)); + else memset(rs->service_uuid, 0, sizeof(rs->service_uuid)); if(name && *name) strncpy(rs->service_name, name, sizeof(rs->service_name) -1); if(addr) @@ -310,7 +312,7 @@ static inline rfc_slot_t* create_srv_accept_rfc_slot(rfc_slot_t* srv_rs, const b bt_status_t btsock_rfc_listen(const char* service_name, const uint8_t* service_uuid, int channel, int* sock_fd, int flags) { - if(sock_fd == NULL || (service_uuid == NULL && !is_reserved_rfc_channel(channel))) + if(sock_fd == NULL || (service_uuid == NULL && (channel < 1 || channel > 30))) { error("invalid rfc channel:%d or sock_fd:%p, uuid:%p", channel, sock_fd, service_uuid); return BT_STATUS_PARM_INVALID; @@ -318,13 +320,17 @@ bt_status_t btsock_rfc_listen(const char* service_name, const uint8_t* service_u *sock_fd = -1; if(!is_init_done()) return BT_STATUS_NOT_READY; - //Check the service_uuid. If it uses a reserved channel number, use it - int reserved_channel = get_reserved_rfc_channel(service_uuid); - if(reserved_channel >0) + if(is_uuid_empty(service_uuid)) + service_uuid = UUID_SPP; //use serial port profile to listen to specified channel + else { - channel = reserved_channel; + //Check the service_uuid. overwrite the channel # if reserved + int reserved_channel = get_reserved_rfc_channel(service_uuid); + if(reserved_channel > 0) + { + channel = reserved_channel; + } } - int status = BT_STATUS_FAIL; lock_slot(&slot_lock); rfc_slot_t* rs = alloc_rfc_slot(NULL, service_name, service_uuid, channel, flags, TRUE); @@ -344,7 +350,7 @@ bt_status_t btsock_rfc_listen(const char* service_name, const uint8_t* service_u bt_status_t btsock_rfc_connect(const bt_bdaddr_t *bd_addr, const uint8_t* service_uuid, int channel, int* sock_fd, int flags) { - if(sock_fd == NULL || (service_uuid == NULL && !is_reserved_rfc_channel(channel))) + if(sock_fd == NULL || (service_uuid == NULL && (channel < 1 || channel > 30))) { error("invalid rfc channel:%d or sock_fd:%p, uuid:%p", channel, sock_fd, service_uuid); return BT_STATUS_PARM_INVALID; @@ -357,31 +363,49 @@ bt_status_t btsock_rfc_connect(const bt_bdaddr_t *bd_addr, const uint8_t* servic rfc_slot_t* rs = alloc_rfc_slot(bd_addr, NULL, service_uuid, channel, flags, FALSE); if(rs) { - - //BTA_API extern tBTA_JV_STATUS BTA_JvStartDiscovery(BD_ADDR bd_addr, UINT16 num_uuid, - // tSDP_UUID *p_uuid_list, void* user_data); - tSDP_UUID sdp_uuid; - sdp_uuid.len = 16; - memcpy(sdp_uuid.uu.uuid128, service_uuid, sizeof(sdp_uuid.uu.uuid128)); - debug("start service channel discovery, slot id:%d, fd:%d, app_fd:%d, security:0x%x, scn:%d", - rs->id, rs->fd, rs->app_fd, rs->security, rs->scn); - logu("service_uuid", service_uuid); - *sock_fd = rs->app_fd; - rs->app_fd = -1; //the fd ownership is transferred to app - status = BT_STATUS_SUCCESS; - rfc_slot_t* rs_doing_sdp = find_rfc_slot_requesting_sdp(); - if(rs_doing_sdp == NULL) + if(is_uuid_empty(service_uuid)) { - BTA_JvStartDiscovery((UINT8*)bd_addr->address, 1, &sdp_uuid, (void*)rs->id); - rs->f.pending_sdp_request = FALSE; - rs->f.doing_sdp_request = TRUE; + debug("connecting to rfcomm channel:%d without service discovery", channel); + if(BTA_JvRfcommConnect(rs->security, rs->role, rs->scn, rs->addr.address, + rfcomm_cback, (void*)rs->id) == BTA_JV_SUCCESS) + { + if(send_app_scn(rs)) + { + btsock_thread_add_fd(pth, rs->fd, BTSOCK_RFCOMM, + SOCK_THREAD_FD_RD, rs->id); + *sock_fd = rs->app_fd; + rs->app_fd = -1; //the fd ownership is transferred to app + status = BT_STATUS_SUCCESS; + } + else cleanup_rfc_slot(rs); + } + else cleanup_rfc_slot(rs); } else { - rs->f.pending_sdp_request = TRUE; - rs->f.doing_sdp_request = FALSE; + tSDP_UUID sdp_uuid; + sdp_uuid.len = 16; + memcpy(sdp_uuid.uu.uuid128, service_uuid, sizeof(sdp_uuid.uu.uuid128)); + debug("start service channel discovery, slot id:%d, fd:%d, app_fd:%d, security:0x%x, scn:%d", + rs->id, rs->fd, rs->app_fd, rs->security, rs->scn); + logu("service_uuid", service_uuid); + *sock_fd = rs->app_fd; + rs->app_fd = -1; //the fd ownership is transferred to app + status = BT_STATUS_SUCCESS; + rfc_slot_t* rs_doing_sdp = find_rfc_slot_requesting_sdp(); + if(rs_doing_sdp == NULL) + { + BTA_JvStartDiscovery((UINT8*)bd_addr->address, 1, &sdp_uuid, (void*)rs->id); + rs->f.pending_sdp_request = FALSE; + rs->f.doing_sdp_request = TRUE; + } + else + { + rs->f.pending_sdp_request = TRUE; + rs->f.doing_sdp_request = FALSE; + } + btsock_thread_add_fd(pth, rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_RD, rs->id); } - btsock_thread_add_fd(pth, rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_RD, rs->id); } unlock_slot(&slot_lock); return status; diff --git a/btif/src/btif_sock_sdp.c b/btif/src/btif_sock_sdp.c index 2dfc526..12adb6b 100644 --- a/btif/src/btif_sock_sdp.c +++ b/btif/src/btif_sock_sdp.c @@ -64,12 +64,6 @@ #define RESERVED_SCN_OPS 12 #define UUID_MAX_LENGTH 16 -static const UINT8 UUID_OBEX_OBJECT_PUSH[] = {0x00, 0x00, 0x11, 0x05, 0x00, 0x00, 0x10, 0x00, - 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB}; - -static const UINT8 UUID_PBAP_PSE[] = {0x00, 0x00, 0x11, 0x2F, 0x00, 0x00, 0x10, 0x00, - 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB}; - #define IS_UUID(u1,u2) !memcmp(u1,u2,UUID_MAX_LENGTH) @@ -317,6 +311,45 @@ static int add_ops_sdp(const char *p_service_name,int scn) return sdp_handle; } +#define SPP_NUM_PROTO_ELEMS 2 +static int add_spp_sdp(const char *service_name, int scn) +{ + UINT16 serviceclassid = UUID_SERVCLASS_SERIAL_PORT; + tSDP_PROTOCOL_ELEM proto_elem_list[SPP_NUM_PROTO_ELEMS]; + int sdp_handle; + + info("scn %d, service name %s", scn, service_name); + + /* register the service */ + if ((sdp_handle = SDP_CreateRecord()) != FALSE) + { + /*** Fill out the protocol element sequence for SDP ***/ + proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + proto_elem_list[0].num_params = 0; + proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + proto_elem_list[1].num_params = 1; + + proto_elem_list[1].params[0] = scn; + + if (SDP_AddProtocolList(sdp_handle, SPP_NUM_PROTO_ELEMS, proto_elem_list)) + { + if (SDP_AddServiceClassIdList(sdp_handle, 1, &serviceclassid)) + { + if ((SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME, + TEXT_STR_DESC_TYPE, (UINT32)(strlen(service_name)+1), + (UINT8 *)service_name))) + { + UINT16 list[1]; + /* Make the service browseable */ + list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, + 1, list); + } + } + } + } + return sdp_handle; +} @@ -351,6 +384,10 @@ static int add_rfc_sdp_by_uuid(const char* name, const uint8_t* uuid, int scn) { handle = add_pbap_sdp(name, final_scn); //PBAP Server is always 19 } + else if (IS_UUID(UUID_SPP, uuid)) + { + handle = add_spp_sdp(name, final_scn); + } else { handle = add_sdp_by_uuid(name, uuid, final_scn); @@ -391,17 +428,17 @@ int add_rfc_sdp_rec(const char* name, const uint8_t* uuid, int scn) switch(scn) { case RESERVED_SCN_PBS: // PBAP Reserved port - add_pbap_sdp(name, scn); + uuid = UUID_PBAP_PSE; break; case RESERVED_SCN_OPS: - add_ops_sdp(name,scn); + uuid = UUID_OBEX_OBJECT_PUSH; break; default: + uuid = UUID_SPP; break; } } - else - sdp_handle = add_rfc_sdp_by_uuid(name, uuid, scn); + sdp_handle = add_rfc_sdp_by_uuid(name, uuid, scn); return sdp_handle; } -- cgit v1.1