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