OSDN Git Service

Fix build issues in bluedroid on master
[android-x86/system-bt.git] / btif / src / btif_sock_sdp.c
1 /******************************************************************************
2  *
3  *  Copyright (C) 2014 Google, Inc.
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 #define LOG_TAG "bt_btif_sock_sdp"
20
21 #include <stdint.h>
22 #include <stdbool.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <errno.h>
27
28 #include <hardware/bluetooth.h>
29 #include <hardware/bt_sock.h>
30
31 #include "btif_common.h"
32 #include "btif_util.h"
33 #include "bta_api.h"
34 #include "bt_target.h"
35 #include "gki.h"
36 #include "hcimsgs.h"
37 #include "sdp_api.h"
38 #include "btu.h"
39 #include "btm_api.h"
40 #include "btm_int.h"
41 #include "btif_sock_sdp.h"
42 #include "utl.h"
43 #include "../bta/pb/bta_pbs_int.h"
44 #include "../include/bta_op_api.h"
45 #include "bta_jv_api.h"
46
47 // This module provides an abstraction on top of the lower-level SDP database
48 // code for registration and discovery of various bluetooth sockets.
49 //
50 // This code also provides for on-demand registration of "pre-registered"
51 // services as a backwards compatibility function to third-party applications
52 // expecting a bluez stack.
53
54 // Realm Character Set -- 0 is ASCII
55 #define BTA_PBS_REALM_CHARSET 0
56
57 // Specifies whether or not client's user id is required during obex
58 // authentication
59 #define BTA_PBS_USERID_REQ FALSE
60
61 static const tBTA_PBS_CFG bta_pbs_cfg = {
62   BTA_PBS_REALM_CHARSET,                          // realm_charset: Server only
63   BTA_PBS_USERID_REQ,                             // userid_req: Server only
64   (BTA_PBS_SUPF_DOWNLOAD | BTA_PBS_SURF_BROWSE),  // supported_features
65   BTA_PBS_REPOSIT_LOCAL,                          // supported_repositories
66 };
67
68 // object format lookup table
69 #define OBEX_PUSH_NUM_FORMATS 7
70
71 static const tBTA_OP_FMT bta_ops_obj_fmt[OBEX_PUSH_NUM_FORMATS] = {
72   BTA_OP_VCARD21_FMT,
73   BTA_OP_VCARD30_FMT,
74   BTA_OP_VCAL_FMT,
75   BTA_OP_ICAL_FMT,
76   BTA_OP_VNOTE_FMT,
77   BTA_OP_VMSG_FMT,
78   BTA_OP_OTHER_FMT
79 };
80
81 // TODO(jtgans): Figure out if we actually need this define. This is ifndef
82 // defined in bt_target.h, but nowhere else, so right now, unless something
83 // overrides this before bt_target.h sets it, it will always be bt_target.h's
84 // version.
85 #ifndef BTUI_OPS_FORMATS
86 #define BTUI_OPS_FORMATS (BTA_OP_VCARD21_MASK   \
87                           | BTA_OP_VCARD30_MASK \
88                           | BTA_OP_VCAL_MASK    \
89                           | BTA_OP_ICAL_MASK    \
90                           | BTA_OP_VNOTE_MASK   \
91                           | BTA_OP_VMSG_MASK    \
92                           | BTA_OP_ANY_MASK)
93 #endif
94
95 /*
96  * This is horrible design - to reserve channel ID's and use them to magically
97  * link a channel number to a hard coded SDP entry.
98  *
99  * TODO: expose a prober SDP API, to avoid hacks like this, and make it possible
100  * to set useful names for the ServiceName
101  */
102 #define BTA_MAP_MSG_TYPE_EMAIL    0x01
103 #define BTA_MAP_MSG_TYPE_SMS_GSM  0x02
104 #define BTA_MAP_MSG_TYPE_SMS_CDMA 0x04
105 #define BTA_MAP_MSG_TYPE_MMS      0x08
106
107 #define BTA_MAP_MAS_ID_SMSMMS 0
108 #define BTA_MAP_MAS_ID_EMAIL 1
109
110 // MAP 1.1
111 #define BTA_MAP_DEFAULT_VERSION 0x0101
112
113 typedef struct {
114   uint8_t mas_id;                  // the MAS instance id
115   const char *service_name;      // Description of the MAS instance
116   uint8_t supported_message_types; // Server supported message types - SMS/MMS/EMAIL
117 } tBTA_MAP_CFG;
118
119 const tBTA_MAP_CFG bta_map_cfg_sms = {
120   BTA_MAP_MAS_ID_SMSMMS,
121   "MAP SMS",
122   BTA_MAP_MSG_TYPE_SMS_GSM | BTA_MAP_MSG_TYPE_SMS_CDMA
123 };
124
125 #define RESERVED_SCN_PBS 19
126 #define RESERVED_SCN_OPS 12
127
128 #define UUID_MAX_LENGTH 16
129 #define UUID_MATCHES(u1, u2) !memcmp(u1, u2, UUID_MAX_LENGTH)
130
131 // Adds a protocol list and service name (if provided) to an SDP record given by
132 // |sdp_handle|, and marks it as browseable. This is a shortcut for defining a
133 // set of protocols that includes L2CAP, RFCOMM, and optionally OBEX. If
134 // |with_obex| is |TRUE|, then an additional OBEX protocol UUID will be included
135 // at the end of the protocol list.
136 //
137 // Returns TRUE if successful, otherwise FALSE.
138 static bool create_base_record(const uint32_t sdp_handle, const char *name,
139                                const uint16_t channel, const bool with_obex) {
140   APPL_TRACE_DEBUG("create_base_record: scn: %d, name: %s, with_obex: %d",
141                    channel, name, with_obex);
142
143   // Setup the protocol list and add it.
144   tSDP_PROTOCOL_ELEM proto_list[SDP_MAX_LIST_ELEMS];
145   int num_proto_elements = with_obex ? 3 : 2;
146
147   memset(proto_list, 0, num_proto_elements * sizeof(tSDP_PROTOCOL_ELEM));
148
149   proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
150   proto_list[0].num_params = 0;
151   proto_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
152   proto_list[1].num_params = 1;
153   proto_list[1].params[0] = channel;
154
155   if (with_obex == TRUE) {
156     proto_list[2].protocol_uuid = UUID_PROTOCOL_OBEX;
157     proto_list[2].num_params = 0;
158   }
159
160   char *stage = "protocol_list";
161   if (!SDP_AddProtocolList(sdp_handle, num_proto_elements, proto_list))
162     goto error;
163
164   // Add the name to the SDP record.
165   if (name[0] != '\0') {
166     stage = "service_name";
167     if (!SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME,
168                           TEXT_STR_DESC_TYPE, (uint32_t)(strlen(name) + 1),
169                           (uint8_t *)name))
170       goto error;
171   }
172
173   // Mark the service as browseable.
174   uint16_t list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
175   stage = "browseable";
176   if (!SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &list))
177     goto error;
178
179   APPL_TRACE_DEBUG("create_base_record: successfully created base service "
180                    "record, handle: 0x%08x, scn: %d, name: %s, with_obex: %d",
181                    sdp_handle, channel, name, with_obex);
182   return TRUE;
183
184 error:
185   APPL_TRACE_ERROR("create_base_record: failed to create base service "
186                    "record, stage: %s, scn: %d, name: %s, with_obex: %d",
187                    stage, channel, name, with_obex);
188   return FALSE;
189 }
190
191 // Registers a service with the given |name|, |uuid|, and |channel| in the SDP
192 // database as a generic L2CAP RFCOMM protocol, storing its |uuid| as a service
193 // class sequence.
194 static int add_sdp_by_uuid(const char *name,  const uint8_t *uuid,
195                            const uint16_t channel) {
196   APPL_TRACE_DEBUG("add_sdp_by_uuid: scn: %d, service_name: %s", channel, name);
197
198   uint32_t handle = SDP_CreateRecord();
199   if (handle == 0) {
200     APPL_TRACE_ERROR("add_sdp_by_uuid: failed to create sdp record, "
201                      "scn: %d, service_name: %s", channel, name);
202     return 0;
203   }
204
205   // Create the base SDP record.
206   char *stage = "create_base_record";
207   if (!create_base_record(handle, name, channel, FALSE /* with_obex */))
208     goto error;
209
210   // Convert the |uuid| into a big-endian representation and add it as a
211   // sequence.
212   uint8_t type = UUID_DESC_TYPE;
213   uint8_t type_len = UUID_MAX_LENGTH;
214   uint8_t type_buf[48];
215   // Store the address of type buf in a pointer on the stack, so we can pass
216   // a double pointer to SDP_AddSequence
217   uint8_t *type_buf_ptr = type_buf;
218
219   // Do the conversion to big-endian -- tmp is only used to iterate through the
220   // UUID array in the macro and serves no other purpose as the conversion
221   // macros are not hygenic.
222   {
223     uint8_t *tmp = type_buf;
224     ARRAY_TO_BE_STREAM(tmp, uuid, UUID_MAX_LENGTH);
225   }
226
227   stage = "service_class_sequence";
228   if (!SDP_AddSequence(handle, (uint16_t)ATTR_ID_SERVICE_CLASS_ID_LIST,
229                        1, &type, &type_len, &type_buf_ptr))
230     goto error;
231
232
233   APPL_TRACE_DEBUG("add_sdp_by_uuid: service registered successfully, "
234                    "service_name: %s, handle: 0x%08x", name, handle);
235   return handle;
236
237 error:
238   SDP_DeleteRecord(handle);
239   APPL_TRACE_ERROR("add_sdp_by_uuid: failed to register service "
240                    "stage: %s, service_name: %s", stage, name);
241   return 0;
242 }
243
244 // Registers a service with the given |name| and |channel| in the SDP
245 // database as a PBAP protocol.
246 static int add_pbap_sdp(const char *name, const int channel) {
247   APPL_TRACE_DEBUG("add_pbap_sdp: scn %d, service_name %s", channel, name);
248
249   uint32_t handle = SDP_CreateRecord();
250   if (handle == 0) {
251     APPL_TRACE_ERROR("add_pbap_sdp: failed to create sdp record, "
252                      "service_name: %s", name);
253     return 0;
254   }
255
256   // Create the base SDP record.
257   char *stage = "create_base_record";
258   if (!create_base_record(handle, name, channel, TRUE /* with_obex */))
259     goto error;
260
261   // Add service class
262   uint16_t service = UUID_SERVCLASS_PBAP_PSE;
263   stage = "service_class";
264   if (!SDP_AddServiceClassIdList(handle, 1, &service))
265     goto error;
266
267   // Add in the phone access descriptor
268   stage = "profile_descriptor_list";
269   if (!SDP_AddProfileDescriptorList(handle,
270                                     UUID_SERVCLASS_PHONE_ACCESS,
271                                     BTA_PBS_DEFAULT_VERSION))
272     goto error;
273
274   // Set up our supported repositories
275   stage = "supported_repositories";
276   if (!SDP_AddAttribute(handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE,
277                         1, (uint8_t*)&bta_pbs_cfg.supported_repositories))
278     goto error;
279
280   // Notify the system that we've got a new service class UUID.
281   bta_sys_add_uuid(UUID_SERVCLASS_PBAP_PSE);
282   APPL_TRACE_DEBUG("add_pbap_sdp: service registered successfully, "
283                    "service_name: %s, handle: 0x%08x", name, handle);
284
285   return handle;
286
287 error:
288   SDP_DeleteRecord(handle);
289   APPL_TRACE_ERROR("add_pbap_sdp: failed to register PBAP service, stage: %s, "
290                    "service_name: %s", stage, name);
291   return 0;
292 }
293
294 // Registers a service with the given |name| and |channel| in the SDP database
295 // as a MAP protocol.
296 static int add_maps_sdp(const char *name, const int channel) {
297   APPL_TRACE_DEBUG("add_maps_sdp: scn %d, service_name %s", channel,
298                    name);
299
300   uint32_t handle = SDP_CreateRecord();
301   if (handle == 0) {
302     APPL_TRACE_ERROR("add_maps_sdp: failed to create sdp record, "
303                      "service_name: %s", name);
304     return 0;
305   }
306
307   // Create the base SDP record.
308   char *stage = "create_base_record";
309   if (!create_base_record(handle, name, channel, TRUE /* with_obex */))
310     goto error;
311
312   // add service class
313   uint16_t service = UUID_SERVCLASS_MESSAGE_ACCESS;
314   stage = "service_class";
315   if (!SDP_AddServiceClassIdList(handle, 1, &service))
316     goto error;
317
318   // TODO: To add support for EMAIL set below depending on the scn to either
319   // SMS or Email
320   const tBTA_MAP_CFG *bta_map_cfg = &bta_map_cfg_sms;
321
322   // Add in the Bluetooth Profile Descriptor List
323   stage = "profile_descriptor_list";
324   if (!SDP_AddProfileDescriptorList(handle,
325                                     UUID_SERVCLASS_MAP_PROFILE,
326                                     BTA_MAP_DEFAULT_VERSION))
327     goto error;
328
329   stage = "mas_instance_id";
330   if (!SDP_AddAttribute(handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE,
331                         (uint32_t)1, (uint8_t*)(&bta_map_cfg->mas_id)))
332     goto error;
333
334   stage = "support_message_types";
335   if (!SDP_AddAttribute(handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE,
336                         (uint32_t)1,
337                         (uint8_t*)(&bta_map_cfg->supported_message_types)))
338     goto error;
339
340   // Notify the system that we've got a new service class UUID.
341   bta_sys_add_uuid(service);  // UUID_SERVCLASS_MESSAGE_ACCESS
342   APPL_TRACE_DEBUG("ad_maps_sdp: service registered successfully, "
343                    "service_name: %s, handle 0x%08x)", name, handle);
344
345   return handle;
346
347 error:
348   SDP_DeleteRecord(handle);
349   APPL_TRACE_ERROR("add_maps_sdp: failed to register MAP service, stage: %s, "
350                    "service_name: %s", stage, name);
351   return 0;
352 }
353
354 // Registers a service with the given |name| and |channel| as an OBEX Push
355 // protocol.
356 static int add_ops_sdp(const char *name, const int channel) {
357   APPL_TRACE_DEBUG("add_ops_sdp: scn %d, service_name %s", channel, name);
358
359   uint32_t handle = SDP_CreateRecord();
360   if (handle == 0) {
361     APPL_TRACE_ERROR("add_ops_sdp: failed to create sdp record, "
362                      "service_name: %s", name);
363     return 0;
364   }
365
366   // Create the base SDP record.
367   char *stage = "create_base_record";
368   if (!create_base_record(handle, name, channel, TRUE /* with_obex */))
369     goto error;
370
371   // Add service class.
372   stage = "service_class";
373   uint16_t service = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
374   if (!SDP_AddServiceClassIdList(handle, 1, &service))
375     goto error;
376
377   // Add the OBEX push profile descriptor.
378   stage = "profile_descriptor_list";
379   if (!SDP_AddProfileDescriptorList(handle, UUID_SERVCLASS_OBEX_OBJECT_PUSH,
380                                     0x0100))
381     goto error;
382
383   // Add sequence for supported types.
384   uint8_t desc_type[OBEX_PUSH_NUM_FORMATS];
385   uint8_t type_len[OBEX_PUSH_NUM_FORMATS];
386   uint8_t *type_value[OBEX_PUSH_NUM_FORMATS];
387   uint8_t j = 0;
388
389   for (int i = 0; i < OBEX_PUSH_NUM_FORMATS; i++) {
390     if ((BTUI_OPS_FORMATS >> i) & 1) {
391       type_value[j] = (uint8_t*)(&bta_ops_obj_fmt[i]);
392       desc_type[j] = UINT_DESC_TYPE;
393       type_len[j++] = 1;
394     }
395   }
396
397   stage = "supported_types";
398   if (!SDP_AddSequence(handle, (uint16_t)ATTR_ID_SUPPORTED_FORMATS_LIST,
399                        j, desc_type, type_len, type_value))
400     goto error;
401
402   // Set class of device.
403   tBTA_UTL_COD cod;
404   cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
405   stage = "class_of_device";
406   if (!utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS))
407     goto error;
408
409   // Notify the system that we've got a new service class UUID.
410   bta_sys_add_uuid(UUID_SERVCLASS_OBEX_OBJECT_PUSH);
411   APPL_TRACE_DEBUG("ad_maps_sdp: service registered successfully, "
412                    "service_name: %s, handle 0x%08x)", name, handle);
413
414   return handle;
415
416 error:
417   SDP_DeleteRecord(handle);
418   APPL_TRACE_ERROR("add_ops_sdp: failed to register OPS service, "
419                    "stage: %s, service_name: %s", stage, name);
420   return 0;
421 }
422
423 // Registers a service with the given |name| and |channel| as a serial port
424 // profile protocol.
425 static int add_spp_sdp(const char *name, const int channel) {
426   APPL_TRACE_DEBUG("add_spp_sdp: scn %d, service_name %s", channel, name);
427
428   int handle = SDP_CreateRecord();
429   if (handle == 0) {
430     APPL_TRACE_ERROR("add_spp_sdp: failed to create sdp record, "
431                      "service_name: %s", name);
432     return 0;
433   }
434
435   // Create the base SDP record.
436   char *stage = "create_base_record";
437   if (!create_base_record(handle, name, channel, FALSE /* with_obex */))
438     goto error;
439
440   uint16_t service = UUID_SERVCLASS_SERIAL_PORT;
441   stage = "service_class";
442   if (!SDP_AddServiceClassIdList(handle, 1, &service))
443     goto error;
444
445   APPL_TRACE_DEBUG("add_spp_sdp: service registered successfully, "
446                    "service_name: %s, handle 0x%08x)", name, handle);
447
448   return handle;
449
450 error:
451   SDP_DeleteRecord(handle);
452   APPL_TRACE_ERROR("add_spp_sdp: failed to register SPP service, "
453                    "stage: %s, service_name: %s", stage, name);
454   return 0;
455 }
456
457 // Adds an RFCOMM SDP record for a service with the given |name|, |uuid|, and
458 // |channel|. This function attempts to identify the type of the service based
459 // upon its |uuid|, and will override the |channel| with a reserved channel
460 // number if the |uuid| matches one of the preregistered bluez SDP records.
461 static int add_rfc_sdp_by_uuid(const char *name, const uint8_t *uuid,
462                                const int channel) {
463   APPL_TRACE_DEBUG("add_rfc_sdp_by_uuid: service_name: %s, channel: %d", name,
464                    channel);
465
466   /*
467    * Bluetooth Socket API relies on having preregistered bluez sdp records for
468    * HSAG, HFAG, OPP & PBAP that are mapped to rc chan 10, 11,12 & 19. Today
469    * HSAG and HFAG is routed to BRCM AG and are not using BT socket API so for
470    * now we will need to support OPP and PBAP to enable 3rd party developer apps
471    * running on BRCM Android.
472    *
473    * To do this we will check the UUID for the requested service and mimic the
474    * SDP records of bluez upon reception.  See functions add_opush() and
475    * add_pbap() in sdptool.c for actual records.
476    */
477
478   int final_channel = get_reserved_rfc_channel(uuid);
479
480   if (final_channel == -1) {
481     final_channel = channel;
482   }
483
484   int handle = 0;
485
486   if (UUID_MATCHES(UUID_OBEX_OBJECT_PUSH, uuid)) {
487     handle = add_ops_sdp(name, final_channel);
488   } else if (UUID_MATCHES(UUID_PBAP_PSE,uuid)) {
489     // PBAP Server is always channel 19
490     handle = add_pbap_sdp(name, final_channel);
491   } else if (UUID_MATCHES(UUID_SPP, uuid)) {
492     handle = add_spp_sdp(name, final_channel);
493   } else if (UUID_MATCHES(UUID_MAPS_MAS,uuid)) {
494     // MAP Server is always channel 19
495     handle = add_maps_sdp(name, final_channel);
496   } else {
497     handle = add_sdp_by_uuid(name, uuid, final_channel);
498   }
499
500   return handle;
501 }
502
503 bool is_reserved_rfc_channel(const int channel) {
504   switch(channel) {
505     case RESERVED_SCN_PBS:
506     case RESERVED_SCN_OPS:
507       return TRUE;
508   }
509
510   return FALSE;
511 }
512
513 int get_reserved_rfc_channel(const uint8_t *uuid) {
514   if (UUID_MATCHES(UUID_PBAP_PSE, uuid)) {
515     return RESERVED_SCN_PBS;
516   } else if (UUID_MATCHES(UUID_OBEX_OBJECT_PUSH, uuid)) {
517     return RESERVED_SCN_OPS;
518   }
519
520   return -1;
521 }
522
523 // Adds an SDP record to the SDP database using the given |name|, |uuid|, and
524 // |channel|. Note that if the |uuid| is empty, the |uuid| will be set based
525 // upon the |channel| passed in.
526 int add_rfc_sdp_rec(const char *name, const uint8_t *uuid, const int channel) {
527   if (is_uuid_empty(uuid)) {
528     switch(channel) {
529       case RESERVED_SCN_PBS: // PBAP Reserved port
530         uuid = UUID_PBAP_PSE;
531         break;
532
533       case RESERVED_SCN_OPS:
534         uuid = UUID_OBEX_OBJECT_PUSH;
535         break;
536
537       default:
538         uuid = UUID_SPP;
539         break;
540     }
541   }
542
543   return add_rfc_sdp_by_uuid(name, uuid, channel);
544 }
545
546 // Deletes an SDP record with the given |handle|.
547 void del_rfc_sdp_rec(int handle) {
548   APPL_TRACE_DEBUG("del_rfc_sdp_rec: handle:0x%x", handle);
549
550   if ((handle != -1) && (handle != 0))
551     BTA_JvDeleteRecord(handle);
552 }