btif_sock_sdp.c revision 98139d9ecf9f42bffa26b6840659131b0b3258f0
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_FEATURES, UINT_DESC_TYPE,
191                  (UINT32)1, (UINT8*)&p_bta_pbs_cfg->supported_features);
192        SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE,
193                  (UINT32)1, (UINT8*)&p_bta_pbs_cfg->supported_repositories);
194
195        /* Make the service browseable */
196        SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
197    }
198
199    if (!status)
200    {
201        SDP_DeleteRecord(sdp_handle);
202        sdp_handle = 0;
203        APPL_TRACE_ERROR0("bta_pbs_sdp_register FAILED");
204    }
205    else
206    {
207        bta_sys_add_uuid(pbs_service);  /* UUID_SERVCLASS_PBAP_PSE */
208        APPL_TRACE_DEBUG1("PBS:  SDP Registered (handle 0x%08x)", sdp_handle);
209    }
210
211    return sdp_handle;
212}
213
214/* This is horrible design - to reserve channel ID's and use them to magically link
215 * a channel number to a hard coded SDP entry.
216 * TODO: expose a prober SDP API, to avoid hacks like this, and make it possible
217 *        to set useful names for the ServiceName */
218#define BTA_MAP_MSG_TYPE_EMAIL    0x01
219#define BTA_MAP_MSG_TYPE_SMS_GSM  0x02
220#define BTA_MAP_MSG_TYPE_SMS_CDMA 0x04
221#define BTA_MAP_MSG_TYPE_MMS      0x08
222
223#define BTA_MAPS_DEFAULT_VERSION 0x0101 /* MAP 1.1 */
224typedef struct
225{
226    UINT8       mas_id;                 /* the MAS instance id */
227    const char* service_name;          /* Description of the MAS instance */
228    UINT8       supported_message_types;/* Server supported message types - SMS/MMS/EMAIL */
229} tBTA_MAPS_CFG;
230const tBTA_MAPS_CFG bta_maps_cfg_sms_mms =
231{
232    0,                  /* Mas id 0 is for SMS/MMS */
233    "MAP SMS/MMS",
234    BTA_MAP_MSG_TYPE_SMS_GSM | BTA_MAP_MSG_TYPE_SMS_CDMA | BTA_MAP_MSG_TYPE_MMS
235};
236const tBTA_MAPS_CFG bta_maps_cfg_email =
237{
238    1,                  /* Mas id 1 is for EMAIL */
239    "MAP EMAIL",
240    BTA_MAP_MSG_TYPE_EMAIL
241};
242static int add_maps_sdp(const char* p_service_name, int scn)
243{
244
245    tSDP_PROTOCOL_ELEM  protoList [3];
246    UINT16              service = UUID_SERVCLASS_MESSAGE_ACCESS;
247    UINT16              browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
248    BOOLEAN             status = FALSE;
249    UINT32              sdp_handle = 0;
250    // TODO: To add support for EMAIL set below depending on the scn to either SMS or Email
251    const tBTA_MAPS_CFG *p_bta_maps_cfg = &bta_maps_cfg_sms_mms;
252
253    APPL_TRACE_DEBUG2("add_maps_sdd:scn %d, service name %s", scn, p_service_name);
254
255    if ((sdp_handle = SDP_CreateRecord()) == 0)
256    {
257        APPL_TRACE_ERROR0("MAPS SDP: Unable to register MAPS Service");
258        return sdp_handle;
259    }
260
261    /* add service class */
262    if (SDP_AddServiceClassIdList(sdp_handle, 1, &service))
263    {
264        memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) );
265        /* add protocol list, including RFCOMM scn */
266        protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
267        protoList[0].num_params = 0;
268        protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
269        protoList[1].num_params = 1;
270        protoList[1].params[0] = scn;
271        protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
272        protoList[2].num_params = 0;
273
274        if (SDP_AddProtocolList(sdp_handle, 3, protoList))
275        {
276            status = TRUE;  /* All mandatory fields were successful */
277
278            /* optional:  if name is not "", add a name entry */
279            SDP_AddAttribute(sdp_handle,
280                            (UINT16)ATTR_ID_SERVICE_NAME,
281                            (UINT8)TEXT_STR_DESC_TYPE,
282                            (UINT32)(strlen(p_bta_maps_cfg->service_name) + 1),
283                            (UINT8 *)p_bta_maps_cfg->service_name);
284
285            /* Add in the Bluetooth Profile Descriptor List */
286            SDP_AddProfileDescriptorList(sdp_handle,
287                                             UUID_SERVCLASS_MAP_PROFILE,
288                                             BTA_MAPS_DEFAULT_VERSION);
289
290        } /* end of setting mandatory protocol list */
291    } /* end of setting mandatory service class */
292
293    /* add supported feature and repositories */
294    if (status)
295    {
296        SDP_AddAttribute(sdp_handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE,
297                  (UINT32)1, (UINT8*)&p_bta_maps_cfg->mas_id);
298        SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE,
299                  (UINT32)1, (UINT8*)&p_bta_maps_cfg->supported_message_types);
300
301        /* Make the service browseable */
302        SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
303    }
304
305    if (!status)
306    {
307        SDP_DeleteRecord(sdp_handle);
308        sdp_handle = 0;
309        APPL_TRACE_ERROR0("bta_mass_sdp_register FAILED");
310    }
311    else
312    {
313        bta_sys_add_uuid(service);  /* UUID_SERVCLASS_MESSAGE_ACCESS */
314        APPL_TRACE_DEBUG1("MAPSS:  SDP Registered (handle 0x%08x)", sdp_handle);
315    }
316
317    return sdp_handle;
318}
319
320
321/* object format lookup table */
322static const tBTA_OP_FMT bta_ops_obj_fmt[] =
323{
324    BTA_OP_VCARD21_FMT,
325    BTA_OP_VCARD30_FMT,
326    BTA_OP_VCAL_FMT,
327    BTA_OP_ICAL_FMT,
328    BTA_OP_VNOTE_FMT,
329    BTA_OP_VMSG_FMT,
330    BTA_OP_OTHER_FMT
331};
332
333#define BTA_OPS_NUM_FMTS        7
334#define BTA_OPS_PROTOCOL_COUNT  3
335
336#ifndef BTUI_OPS_FORMATS
337#define BTUI_OPS_FORMATS            (BTA_OP_VCARD21_MASK | BTA_OP_VCARD30_MASK | \
338                                         BTA_OP_VCAL_MASK | BTA_OP_ICAL_MASK | \
339                                         BTA_OP_VNOTE_MASK | BTA_OP_VMSG_MASK | \
340                                         BTA_OP_ANY_MASK )
341#endif
342
343static int add_ops_sdp(const char *p_service_name,int scn)
344{
345
346
347    tSDP_PROTOCOL_ELEM  protoList [BTA_OPS_PROTOCOL_COUNT];
348    UINT16      servclass = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
349    int         i, j;
350    tBTA_UTL_COD cod;
351    UINT8       desc_type[BTA_OPS_NUM_FMTS];
352    UINT8       type_len[BTA_OPS_NUM_FMTS];
353    UINT8       *type_value[BTA_OPS_NUM_FMTS];
354    UINT16      browse;
355    UINT32 sdp_handle;
356    tBTA_OP_FMT_MASK    formats = BTUI_OPS_FORMATS;
357
358    APPL_TRACE_DEBUG2("scn %d, service name %s", scn, p_service_name);
359
360    sdp_handle = SDP_CreateRecord();
361
362    /* add service class */
363    if (SDP_AddServiceClassIdList(sdp_handle, 1, &servclass))
364    {
365        /* add protocol list, including RFCOMM scn */
366        protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
367        protoList[0].num_params = 0;
368        protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
369        protoList[1].num_params = 1;
370        protoList[1].params[0] = scn;
371        protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
372        protoList[2].num_params = 0;
373
374        if (SDP_AddProtocolList(sdp_handle, BTA_OPS_PROTOCOL_COUNT, protoList))
375        {
376            SDP_AddAttribute(sdp_handle,
377               (UINT16)ATTR_ID_SERVICE_NAME,
378                (UINT8)TEXT_STR_DESC_TYPE,
379                (UINT32)(strlen(p_service_name) + 1),
380                (UINT8 *)p_service_name);
381
382            SDP_AddProfileDescriptorList(sdp_handle,
383                UUID_SERVCLASS_OBEX_OBJECT_PUSH,
384                0x0100);
385        }
386    }
387
388    /* Make the service browseable */
389    browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
390    SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
391
392    /* add sequence for supported types */
393    for (i = 0, j = 0; i < BTA_OPS_NUM_FMTS; i++)
394    {
395        if ((formats >> i) & 1)
396        {
397            type_value[j] = (UINT8 *) &bta_ops_obj_fmt[i];
398            desc_type[j] = UINT_DESC_TYPE;
399            type_len[j++] = 1;
400        }
401    }
402
403    SDP_AddSequence(sdp_handle, (UINT16) ATTR_ID_SUPPORTED_FORMATS_LIST,
404        (UINT8) j, desc_type, type_len, type_value);
405
406    /* set class of device */
407    cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
408    utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
409
410    bta_sys_add_uuid(servclass); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */
411
412    return sdp_handle;
413}
414#define SPP_NUM_PROTO_ELEMS 2
415static int add_spp_sdp(const char *service_name, int scn)
416{
417    UINT16 serviceclassid = UUID_SERVCLASS_SERIAL_PORT;
418    tSDP_PROTOCOL_ELEM  proto_elem_list[SPP_NUM_PROTO_ELEMS];
419    int              sdp_handle;
420
421    APPL_TRACE_DEBUG2("scn %d, service name %s", scn, service_name);
422
423    /* register the service */
424    if ((sdp_handle = SDP_CreateRecord()) != FALSE)
425    {
426        /*** Fill out the protocol element sequence for SDP ***/
427        proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
428        proto_elem_list[0].num_params = 0;
429        proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
430        proto_elem_list[1].num_params = 1;
431
432        proto_elem_list[1].params[0] = scn;
433
434        if (SDP_AddProtocolList(sdp_handle, SPP_NUM_PROTO_ELEMS, proto_elem_list))
435        {
436            if (SDP_AddServiceClassIdList(sdp_handle, 1, &serviceclassid))
437            {
438                if ((SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME,
439                                TEXT_STR_DESC_TYPE, (UINT32)(strlen(service_name)+1),
440                                (UINT8 *)service_name)))
441                {
442                    UINT16  list[1];
443                    /* Make the service browseable */
444                    list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
445                    SDP_AddUuidSequence (sdp_handle,  ATTR_ID_BROWSE_GROUP_LIST,
446                                    1, list);
447                }
448            }
449        }
450    }
451    return sdp_handle;
452}
453
454
455
456static int add_rfc_sdp_by_uuid(const char* name, const uint8_t* uuid, int scn)
457{
458    int handle = 0;
459
460    APPL_TRACE_DEBUG2("name:%s, scn:%d", name, scn);
461
462    /*
463        Bluetooth Socket API relies on having preregistered bluez sdp records for HSAG, HFAG, OPP & PBAP
464        that are mapped to rc chan 10, 11,12 & 19. Today HSAG and HFAG is routed to BRCM AG and are not
465        using BT socket API so for now we will need to support OPP and PBAP to enable 3rd party developer
466        apps running on BRCM Android.
467
468        To do this we will check the UUID for the requested service and mimic the SDP records of bluez
469        upon reception.  See functions add_opush() and add_pbap() in sdptool.c for actual records
470    */
471
472    /* special handling for preregistered bluez services (OPP, PBAP) that we need to mimic */
473
474    int final_scn = get_reserved_rfc_channel(uuid);
475    if (final_scn == -1)
476    {
477        final_scn=scn;
478    }
479    if (IS_UUID(UUID_OBEX_OBJECT_PUSH,uuid))
480    {
481        handle = add_ops_sdp(name,final_scn);
482    }
483    else if (IS_UUID(UUID_PBAP_PSE,uuid))
484    {
485        handle = add_pbap_sdp(name, final_scn); //PBAP Server is always 19
486    }
487    else if (IS_UUID(UUID_MAPS_MAS,uuid))
488    {
489        handle = add_maps_sdp(name, final_scn); //MAP Server is always 19
490    }
491    else if (IS_UUID(UUID_SPP, uuid))
492    {
493        handle = add_spp_sdp(name, final_scn);
494    }
495    else
496    {
497        handle = add_sdp_by_uuid(name, uuid, final_scn);
498    }
499    return handle;
500}
501
502BOOLEAN is_reserved_rfc_channel(int scn)
503{
504    switch(scn)
505    {
506        case RESERVED_SCN_PBS:
507        case RESERVED_SCN_OPS:
508            return TRUE;
509    }
510    return FALSE;
511}
512
513
514int get_reserved_rfc_channel (const uint8_t* uuid)
515{
516    if (IS_UUID(UUID_PBAP_PSE,uuid))
517    {
518      return RESERVED_SCN_PBS;
519    }
520    else if (IS_UUID(UUID_OBEX_OBJECT_PUSH,uuid))
521    {
522      return RESERVED_SCN_OPS;
523    }
524    return -1;
525}
526
527int add_rfc_sdp_rec(const char* name, const uint8_t* uuid, int scn)
528{
529    int sdp_handle = 0;
530    if(is_uuid_empty(uuid))
531    {
532        switch(scn)
533        {
534            case RESERVED_SCN_PBS: // PBAP Reserved port
535                uuid = UUID_PBAP_PSE;
536                break;
537             case RESERVED_SCN_OPS:
538                uuid = UUID_OBEX_OBJECT_PUSH;
539                break;
540            default:
541                uuid = UUID_SPP;
542                break;
543        }
544    }
545    sdp_handle = add_rfc_sdp_by_uuid(name, uuid, scn);
546    return sdp_handle;
547}
548
549void del_rfc_sdp_rec(int handle)
550{
551    APPL_TRACE_DEBUG1("del_rfc_sdp_rec: handle:0x%x", handle);
552    if(handle != -1 && handle != 0)
553        BTA_JvDeleteRecord( handle );
554}
555
556