btif_sock_sdp.c revision d0cbb2ed7abda2ca15e04c10dbf8de9bfc91369a
1/******************************************************************************
2 *
3 *  Copyright (C) 2009-2012 Broadcom Corporation
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18
19/************************************************************************************
20 *
21 *  Filename:      btif_hf.c
22 *
23 *  Description:   Handsfree Profile Bluetooth Interface
24 *
25 *
26 ***********************************************************************************/
27
28#include <hardware/bluetooth.h>
29#include <hardware/bt_sock.h>
30#include <sys/types.h>
31#include <sys/socket.h>
32#include <errno.h>
33
34#define LOG_TAG "BTIF_SOCK_SDP"
35#include "btif_common.h"
36#include "btif_util.h"
37
38#include "bd.h"
39
40#include "bta_api.h"
41
42
43#include "bt_target.h"
44#include "gki.h"
45#include "hcimsgs.h"
46#include "sdp_api.h"
47#include "btu.h"
48#include "btm_api.h"
49#include "btm_int.h"
50#include "btif_sock_sdp.h"
51#include "utl.h"
52#include "../bta/pb/bta_pbs_int.h"
53#include "../include/bta_op_api.h"
54#include "bta_jv_api.h"
55#include <cutils/log.h>
56
57#define RESERVED_SCN_PBS 19
58#define RESERVED_SCN_OPS 12
59
60#define UUID_MAX_LENGTH 16
61
62
63#define IS_UUID(u1,u2)  !memcmp(u1,u2,UUID_MAX_LENGTH)
64
65
66#define BTM_NUM_PROTO_ELEMS 2
67static int add_sdp_by_uuid(const char *name,  const uint8_t *service_uuid, UINT16 channel)
68{
69
70    UINT32 btm_sdp_handle;
71
72    tSDP_PROTOCOL_ELEM  proto_elem_list[BTM_NUM_PROTO_ELEMS];
73
74    /* register the service */
75    if ((btm_sdp_handle = SDP_CreateRecord()) != FALSE)
76    {
77        /*** Fill out the protocol element sequence for SDP ***/
78        proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
79        proto_elem_list[0].num_params = 0;
80        proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
81        proto_elem_list[1].num_params = 1;
82
83        proto_elem_list[1].params[0] = channel;
84
85        if (SDP_AddProtocolList(btm_sdp_handle, BTM_NUM_PROTO_ELEMS,
86            proto_elem_list))
87        {
88            UINT8           buff[48];
89            UINT8           *p, *type_buf[1];
90            UINT8       type[1], type_len[1];
91         p = type_buf[0] = buff;
92         type[0] = UUID_DESC_TYPE;
93
94//         UINT8_TO_BE_STREAM  (p, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES);
95         ARRAY_TO_BE_STREAM (p, service_uuid, 16);
96            type_len[0] = 16;
97            if( SDP_AddSequence(btm_sdp_handle, (UINT16) ATTR_ID_SERVICE_CLASS_ID_LIST,
98                          1, type, type_len, type_buf) )
99//            if (SDP_AddServiceClassIdList(btm_sdp_handle, 1, &service_uuid))
100            {
101                if ((SDP_AddAttribute(btm_sdp_handle, ATTR_ID_SERVICE_NAME,
102                    TEXT_STR_DESC_TYPE, (UINT32)(strlen(name)+1),
103                    (UINT8 *)name)) )
104                {
105                    UINT16  list[1];
106
107                    /* Make the service browseable */
108                    list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
109                    if ((SDP_AddUuidSequence (btm_sdp_handle,  ATTR_ID_BROWSE_GROUP_LIST,
110                        1, list)) )
111
112                        return btm_sdp_handle;
113                }
114            }
115        }
116    }
117    else APPL_TRACE_ERROR1("failed to create sdp record, service_name:%s", name);
118    return 0;
119}
120
121
122/* Realm Character Set */
123#define BTA_PBS_REALM_CHARSET   0       /* ASCII */
124
125/* Specifies whether or not client's user id is required during obex authentication */
126#define BTA_PBS_USERID_REQ      FALSE
127extern const tBTA_PBS_CFG bta_pbs_cfg;
128const tBTA_PBS_CFG bta_pbs_cfg =
129{
130    BTA_PBS_REALM_CHARSET,      /* Server only */
131    BTA_PBS_USERID_REQ,         /* Server only */
132    (BTA_PBS_SUPF_DOWNLOAD | BTA_PBS_SURF_BROWSE),
133    BTA_PBS_REPOSIT_LOCAL,
134};
135
136static int add_pbap_sdp(const char* p_service_name, int scn)
137{
138
139    tSDP_PROTOCOL_ELEM  protoList [3];
140    UINT16              pbs_service = UUID_SERVCLASS_PBAP_PSE;
141    UINT16              browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
142    BOOLEAN             status = FALSE;
143    UINT32              sdp_handle = 0;
144    tBTA_PBS_CFG *p_bta_pbs_cfg = (tBTA_PBS_CFG *)&bta_pbs_cfg;
145
146    APPL_TRACE_DEBUG2("add_pbap_sdd:scn %d, service name %s", scn, p_service_name);
147
148    if ((sdp_handle = SDP_CreateRecord()) == 0)
149    {
150        APPL_TRACE_ERROR0("PBS SDP: Unable to register PBS Service");
151        return sdp_handle;
152    }
153
154    /* add service class */
155    if (SDP_AddServiceClassIdList(sdp_handle, 1, &pbs_service))
156    {
157        memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) );
158        /* add protocol list, including RFCOMM scn */
159        protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
160        protoList[0].num_params = 0;
161        protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
162        protoList[1].num_params = 1;
163        protoList[1].params[0] = scn;
164        protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
165        protoList[2].num_params = 0;
166
167        if (SDP_AddProtocolList(sdp_handle, 3, protoList))
168        {
169            status = TRUE;  /* All mandatory fields were successful */
170
171            /* optional:  if name is not "", add a name entry */
172            if (*p_service_name != '\0')
173                SDP_AddAttribute(sdp_handle,
174                                 (UINT16)ATTR_ID_SERVICE_NAME,
175                                 (UINT8)TEXT_STR_DESC_TYPE,
176                                 (UINT32)(strlen(p_service_name) + 1),
177                                 (UINT8 *)p_service_name);
178
179            /* Add in the Bluetooth Profile Descriptor List */
180            SDP_AddProfileDescriptorList(sdp_handle,
181                                             UUID_SERVCLASS_PHONE_ACCESS,
182                                             BTA_PBS_DEFAULT_VERSION);
183
184        } /* end of setting mandatory protocol list */
185    } /* end of setting mandatory service class */
186
187    /* add supported feature and repositories */
188    if (status)
189    {
190        SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE,
191                  (UINT32)1, (UINT8*)&p_bta_pbs_cfg->supported_repositories);
192
193        /* Make the service browseable */
194        SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
195    }
196
197    if (!status)
198    {
199        SDP_DeleteRecord(sdp_handle);
200        sdp_handle = 0;
201        APPL_TRACE_ERROR0("bta_pbs_sdp_register FAILED");
202    }
203    else
204    {
205        bta_sys_add_uuid(pbs_service);  /* UUID_SERVCLASS_PBAP_PSE */
206        APPL_TRACE_DEBUG1("PBS:  SDP Registered (handle 0x%08x)", sdp_handle);
207    }
208
209    return sdp_handle;
210}
211
212/* This is horrible design - to reserve channel ID's and use them to magically link
213 * a channel number to a hard coded SDP entry.
214 * TODO: expose a prober SDP API, to avoid hacks like this, and make it possible
215 *        to set useful names for the ServiceName */
216#define BTA_MAP_MSG_TYPE_EMAIL    0x01
217#define BTA_MAP_MSG_TYPE_SMS_GSM  0x02
218#define BTA_MAP_MSG_TYPE_SMS_CDMA 0x04
219#define BTA_MAP_MSG_TYPE_MMS      0x08
220
221#define BTA_MAPS_DEFAULT_VERSION 0x0100
222typedef struct
223{
224    UINT8       mas_id;                /* the MAS instance id */
225    const char* service_name;          /* Description of the MAS instance */
226    UINT8       supported_message_types; /* Server supported message types - SMS/MMS/EMAIL */
227} tBTA_MAPS_CFG;
228const tBTA_MAPS_CFG bta_maps_cfg_sms_mms =
229{
230    0,                                /* Mas id 0 is for SMS/MMS */
231    "MAP SMS/MMS",
232    BTA_MAP_MSG_TYPE_SMS_GSM | BTA_MAP_MSG_TYPE_SMS_CDMA | BTA_MAP_MSG_TYPE_MMS
233};
234const tBTA_MAPS_CFG bta_maps_cfg_email =
235{
236    1,                                /* Mas id 1 is for EMAIL */
237    "MAP EMAIL",
238    BTA_MAP_MSG_TYPE_EMAIL
239};
240static int add_maps_sdp(const char* p_service_name, int scn)
241{
242
243    tSDP_PROTOCOL_ELEM  protoList [3];
244    UINT16              service = UUID_SERVCLASS_MESSAGE_ACCESS;
245    UINT16              browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
246    BOOLEAN             status = FALSE;
247    UINT32              sdp_handle = 0;
248    // TODO: To add support for EMAIL set below depending on the scn to either SMS or Email
249    const tBTA_MAPS_CFG *p_bta_maps_cfg = &bta_maps_cfg_sms_mms;
250
251    APPL_TRACE_DEBUG2("add_maps_sdd:scn %d, service name %s", scn, p_service_name);
252
253    if ((sdp_handle = SDP_CreateRecord()) == 0)
254    {
255        APPL_TRACE_ERROR0("MAPS SDP: Unable to register MAPS Service");
256        return sdp_handle;
257    }
258
259    /* add service class */
260    if (SDP_AddServiceClassIdList(sdp_handle, 1, &service))
261    {
262        memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) );
263        /* add protocol list, including RFCOMM scn */
264        protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
265        protoList[0].num_params = 0;
266        protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
267        protoList[1].num_params = 1;
268        protoList[1].params[0] = scn;
269        protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
270        protoList[2].num_params = 0;
271
272        if (SDP_AddProtocolList(sdp_handle, 3, protoList))
273        {
274            status = TRUE;  /* All mandatory fields were successful */
275
276            /* optional:  if name is not "", add a name entry */
277            SDP_AddAttribute(sdp_handle,
278                             (UINT16)ATTR_ID_SERVICE_NAME,
279                             (UINT8)TEXT_STR_DESC_TYPE,
280                             (UINT32)(strlen(p_bta_maps_cfg->service_name) + 1),
281                             (UINT8 *)p_bta_maps_cfg->service_name);
282
283            /* Add in the Bluetooth Profile Descriptor List */
284            SDP_AddProfileDescriptorList(sdp_handle,
285                                             UUID_SERVCLASS_MAP_PROFILE,
286                                             BTA_MAPS_DEFAULT_VERSION);
287
288        } /* end of setting mandatory protocol list */
289    } /* end of setting mandatory service class */
290
291    /* add supported feature and repositories */
292    if (status)
293    {
294        SDP_AddAttribute(sdp_handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE,
295                  (UINT32)1, (UINT8*)&p_bta_maps_cfg->mas_id);
296        SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE,
297                  (UINT32)1, (UINT8*)&p_bta_maps_cfg->supported_message_types);
298
299        /* Make the service browseable */
300        SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
301    }
302
303    if (!status)
304    {
305        SDP_DeleteRecord(sdp_handle);
306        sdp_handle = 0;
307        APPL_TRACE_ERROR0("bta_mass_sdp_register FAILED");
308    }
309    else
310    {
311        bta_sys_add_uuid(service);  /* UUID_SERVCLASS_MESSAGE_ACCESS */
312        APPL_TRACE_DEBUG1("MAPSS:  SDP Registered (handle 0x%08x)", sdp_handle);
313    }
314
315    return sdp_handle;
316}
317
318
319/* object format lookup table */
320static const tBTA_OP_FMT bta_ops_obj_fmt[] =
321{
322    BTA_OP_VCARD21_FMT,
323    BTA_OP_VCARD30_FMT,
324    BTA_OP_VCAL_FMT,
325    BTA_OP_ICAL_FMT,
326    BTA_OP_VNOTE_FMT,
327    BTA_OP_VMSG_FMT,
328    BTA_OP_OTHER_FMT
329};
330
331#define BTA_OPS_NUM_FMTS        7
332#define BTA_OPS_PROTOCOL_COUNT  3
333
334#ifndef BTUI_OPS_FORMATS
335#define BTUI_OPS_FORMATS            (BTA_OP_VCARD21_MASK | BTA_OP_VCARD30_MASK | \
336                                         BTA_OP_VCAL_MASK | BTA_OP_ICAL_MASK | \
337                                         BTA_OP_VNOTE_MASK | BTA_OP_VMSG_MASK | \
338                                         BTA_OP_ANY_MASK )
339#endif
340
341static int add_ops_sdp(const char *p_service_name,int scn)
342{
343
344
345    tSDP_PROTOCOL_ELEM  protoList [BTA_OPS_PROTOCOL_COUNT];
346    UINT16      servclass = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
347    int         i, j;
348    tBTA_UTL_COD cod;
349    UINT8       desc_type[BTA_OPS_NUM_FMTS];
350    UINT8       type_len[BTA_OPS_NUM_FMTS];
351    UINT8       *type_value[BTA_OPS_NUM_FMTS];
352    UINT16      browse;
353    UINT32 sdp_handle;
354    tBTA_OP_FMT_MASK    formats = BTUI_OPS_FORMATS;
355
356    APPL_TRACE_DEBUG2("scn %d, service name %s", scn, p_service_name);
357
358    sdp_handle = SDP_CreateRecord();
359
360    /* add service class */
361    if (SDP_AddServiceClassIdList(sdp_handle, 1, &servclass))
362    {
363        /* add protocol list, including RFCOMM scn */
364        protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
365        protoList[0].num_params = 0;
366        protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
367        protoList[1].num_params = 1;
368        protoList[1].params[0] = scn;
369        protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
370        protoList[2].num_params = 0;
371
372        if (SDP_AddProtocolList(sdp_handle, BTA_OPS_PROTOCOL_COUNT, protoList))
373        {
374            SDP_AddAttribute(sdp_handle,
375               (UINT16)ATTR_ID_SERVICE_NAME,
376                (UINT8)TEXT_STR_DESC_TYPE,
377                (UINT32)(strlen(p_service_name) + 1),
378                (UINT8 *)p_service_name);
379
380            SDP_AddProfileDescriptorList(sdp_handle,
381                UUID_SERVCLASS_OBEX_OBJECT_PUSH,
382                0x0100);
383        }
384    }
385
386    /* Make the service browseable */
387    browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
388    SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
389
390    /* add sequence for supported types */
391    for (i = 0, j = 0; i < BTA_OPS_NUM_FMTS; i++)
392    {
393        if ((formats >> i) & 1)
394        {
395            type_value[j] = (UINT8 *) &bta_ops_obj_fmt[i];
396            desc_type[j] = UINT_DESC_TYPE;
397            type_len[j++] = 1;
398        }
399    }
400
401    SDP_AddSequence(sdp_handle, (UINT16) ATTR_ID_SUPPORTED_FORMATS_LIST,
402        (UINT8) j, desc_type, type_len, type_value);
403
404    /* set class of device */
405    cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
406    utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
407
408    bta_sys_add_uuid(servclass); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */
409
410    return sdp_handle;
411}
412#define SPP_NUM_PROTO_ELEMS 2
413static int add_spp_sdp(const char *service_name, int scn)
414{
415    UINT16 serviceclassid = UUID_SERVCLASS_SERIAL_PORT;
416    tSDP_PROTOCOL_ELEM  proto_elem_list[SPP_NUM_PROTO_ELEMS];
417    int              sdp_handle;
418
419    APPL_TRACE_DEBUG2("scn %d, service name %s", scn, service_name);
420
421    /* register the service */
422    if ((sdp_handle = SDP_CreateRecord()) != FALSE)
423    {
424        /*** Fill out the protocol element sequence for SDP ***/
425        proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
426        proto_elem_list[0].num_params = 0;
427        proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
428        proto_elem_list[1].num_params = 1;
429
430        proto_elem_list[1].params[0] = scn;
431
432        if (SDP_AddProtocolList(sdp_handle, SPP_NUM_PROTO_ELEMS, proto_elem_list))
433        {
434            if (SDP_AddServiceClassIdList(sdp_handle, 1, &serviceclassid))
435            {
436                if ((SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME,
437                                TEXT_STR_DESC_TYPE, (UINT32)(strlen(service_name)+1),
438                                (UINT8 *)service_name)))
439                {
440                    UINT16  list[1];
441                    /* Make the service browseable */
442                    list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
443                    SDP_AddUuidSequence (sdp_handle,  ATTR_ID_BROWSE_GROUP_LIST,
444                                    1, list);
445                }
446            }
447        }
448    }
449    return sdp_handle;
450}
451
452
453
454static int add_rfc_sdp_by_uuid(const char* name, const uint8_t* uuid, int scn)
455{
456    int handle = 0;
457
458    APPL_TRACE_DEBUG2("name:%s, scn:%d", name, scn);
459
460    /*
461        Bluetooth Socket API relies on having preregistered bluez sdp records for HSAG, HFAG, OPP & PBAP
462        that are mapped to rc chan 10, 11,12 & 19. Today HSAG and HFAG is routed to BRCM AG and are not
463        using BT socket API so for now we will need to support OPP and PBAP to enable 3rd party developer
464        apps running on BRCM Android.
465
466        To do this we will check the UUID for the requested service and mimic the SDP records of bluez
467        upon reception.  See functions add_opush() and add_pbap() in sdptool.c for actual records
468    */
469
470    /* special handling for preregistered bluez services (OPP, PBAP) that we need to mimic */
471
472    int final_scn = get_reserved_rfc_channel(uuid);
473    if (final_scn == -1)
474    {
475        final_scn=scn;
476    }
477    if (IS_UUID(UUID_OBEX_OBJECT_PUSH,uuid))
478    {
479        handle = add_ops_sdp(name,final_scn);
480    }
481    else if (IS_UUID(UUID_PBAP_PSE,uuid))
482    {
483        handle = add_pbap_sdp(name, final_scn); //PBAP Server is always 19
484    }
485    else if (IS_UUID(UUID_MAPS_MAS,uuid))
486    {
487        handle = add_maps_sdp(name, final_scn); //PBAP Server is always 19
488    }
489    else if (IS_UUID(UUID_SPP, uuid))
490    {
491        handle = add_spp_sdp(name, final_scn);
492    }
493    else
494    {
495        handle = add_sdp_by_uuid(name, uuid, final_scn);
496    }
497    return handle;
498}
499
500BOOLEAN is_reserved_rfc_channel(int scn)
501{
502    switch(scn)
503    {
504        case RESERVED_SCN_PBS:
505        case RESERVED_SCN_OPS:
506            return TRUE;
507    }
508    return FALSE;
509}
510
511
512int get_reserved_rfc_channel (const uint8_t* uuid)
513{
514    if (IS_UUID(UUID_PBAP_PSE,uuid))
515    {
516      return RESERVED_SCN_PBS;
517    }
518    else if (IS_UUID(UUID_OBEX_OBJECT_PUSH,uuid))
519    {
520      return RESERVED_SCN_OPS;
521    }
522    return -1;
523}
524
525int add_rfc_sdp_rec(const char* name, const uint8_t* uuid, int scn)
526{
527    int sdp_handle = 0;
528    if(is_uuid_empty(uuid))
529    {
530        switch(scn)
531        {
532            case RESERVED_SCN_PBS: // PBAP Reserved port
533                uuid = UUID_PBAP_PSE;
534                break;
535             case RESERVED_SCN_OPS:
536                uuid = UUID_OBEX_OBJECT_PUSH;
537                break;
538            default:
539                uuid = UUID_SPP;
540                break;
541        }
542    }
543    sdp_handle = add_rfc_sdp_by_uuid(name, uuid, scn);
544    return sdp_handle;
545}
546
547void del_rfc_sdp_rec(int handle)
548{
549    APPL_TRACE_DEBUG1("del_rfc_sdp_rec: handle:0x%x", handle);
550    if(handle != -1 && handle != 0)
551        BTA_JvDeleteRecord( handle );
552}
553
554