Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / src / profile.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2012  Intel Corporation. All rights reserved.
6  *
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdbool.h>
29 #include <stdint.h>
30 #include <stdlib.h>
31 #include <errno.h>
32
33 #include <glib.h>
34 #include <dbus/dbus.h>
35
36 #ifdef __TIZEN_PATCH__
37 #include <sys/types.h>
38 #include <sys/xattr.h>
39 #include <linux/xattr.h>
40 #endif
41
42 #include "lib/bluetooth.h"
43 #include "lib/sdp.h"
44 #include "lib/sdp_lib.h"
45 #include "lib/uuid.h"
46
47 #include "gdbus/gdbus.h"
48
49 #include "btio/btio.h"
50 #include "sdpd.h"
51 #include "log.h"
52 #include "error.h"
53 #include "uuid-helper.h"
54 #include "dbus-common.h"
55 #include "sdp-client.h"
56 #include "sdp-xml.h"
57 #include "adapter.h"
58 #include "device.h"
59 #include "profile.h"
60 #include "service.h"
61
62 #define DUN_DEFAULT_CHANNEL     1
63 #define SPP_DEFAULT_CHANNEL     3
64 #define HFP_HF_DEFAULT_CHANNEL  7
65 #define OPP_DEFAULT_CHANNEL     9
66 #define FTP_DEFAULT_CHANNEL     10
67 #define BIP_DEFAULT_CHANNEL     11
68 #define HSP_AG_DEFAULT_CHANNEL  12
69 #define HFP_AG_DEFAULT_CHANNEL  13
70 #define SYNC_DEFAULT_CHANNEL    14
71 #define PBAP_DEFAULT_CHANNEL    15
72 #define MAS_DEFAULT_CHANNEL     16
73 #define MNS_DEFAULT_CHANNEL     17
74
75 #define BTD_PROFILE_PSM_AUTO    -1
76 #define BTD_PROFILE_CHAN_AUTO   -1
77
78 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
79 #define HID_DEVICE_INTR_PSM 17
80 #define HID_DEVICE_CTRL_PSM 19
81 #endif
82
83 #define HFP_HF_RECORD                                                   \
84         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
85         <record>                                                        \
86                 <attribute id=\"0x0001\">                               \
87                         <sequence>                                      \
88                                 <uuid value=\"0x111e\" />               \
89                                 <uuid value=\"0x1203\" />               \
90                         </sequence>                                     \
91                 </attribute>                                            \
92                 <attribute id=\"0x0004\">                               \
93                         <sequence>                                      \
94                                 <sequence>                              \
95                                         <uuid value=\"0x0100\" />       \
96                                 </sequence>                             \
97                                 <sequence>                              \
98                                         <uuid value=\"0x0003\" />       \
99                                         <uint8 value=\"0x%02x\" />      \
100                                 </sequence>                             \
101                         </sequence>                                     \
102                 </attribute>                                            \
103                 <attribute id=\"0x0005\">                               \
104                         <sequence>                                      \
105                                 <uuid value=\"0x1002\" />               \
106                         </sequence>                                     \
107                 </attribute>                                            \
108                 <attribute id=\"0x0009\">                               \
109                         <sequence>                                      \
110                                 <sequence>                              \
111                                         <uuid value=\"0x111e\" />       \
112                                         <uint16 value=\"0x%04x\" />     \
113                                 </sequence>                             \
114                         </sequence>                                     \
115                 </attribute>                                            \
116                 <attribute id=\"0x0100\">                               \
117                         <text value=\"%s\" />                           \
118                 </attribute>                                            \
119                 <attribute id=\"0x0311\">                               \
120                         <uint16 value=\"0x%04x\" />                     \
121                 </attribute>                                            \
122         </record>"
123
124 #define HFP_AG_RECORD                                                   \
125         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
126         <record>                                                        \
127                 <attribute id=\"0x0001\">                               \
128                         <sequence>                                      \
129                                 <uuid value=\"0x111f\" />               \
130                                 <uuid value=\"0x1203\" />               \
131                         </sequence>                                     \
132                 </attribute>                                            \
133                 <attribute id=\"0x0004\">                               \
134                         <sequence>                                      \
135                                 <sequence>                              \
136                                         <uuid value=\"0x0100\" />       \
137                                 </sequence>                             \
138                                 <sequence>                              \
139                                         <uuid value=\"0x0003\" />       \
140                                         <uint8 value=\"0x%02x\" />      \
141                                 </sequence>                             \
142                         </sequence>                                     \
143                 </attribute>                                            \
144                 <attribute id=\"0x0005\">                               \
145                         <sequence>                                      \
146                                 <uuid value=\"0x1002\" />               \
147                         </sequence>                                     \
148                 </attribute>                                            \
149                 <attribute id=\"0x0009\">                               \
150                         <sequence>                                      \
151                                 <sequence>                              \
152                                         <uuid value=\"0x111e\" />       \
153                                         <uint16 value=\"0x%04x\" />     \
154                                 </sequence>                             \
155                         </sequence>                                     \
156                 </attribute>                                            \
157                 <attribute id=\"0x0100\">                               \
158                         <text value=\"%s\" />                           \
159                 </attribute>                                            \
160                 <attribute id=\"0x0311\">                               \
161                         <uint16 value=\"0x%04x\" />                     \
162                 </attribute>                                            \
163                 <attribute id=\"0x0301\" >                              \
164                         <uint8 value=\"0x01\" />                        \
165                 </attribute>                                            \
166         </record>"
167
168 #define HSP_AG_RECORD                                                   \
169         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
170         <record>                                                        \
171                 <attribute id=\"0x0001\">                               \
172                         <sequence>                                      \
173                                 <uuid value=\"0x1112\" />               \
174                                 <uuid value=\"0x1203\" />               \
175                         </sequence>                                     \
176                 </attribute>                                            \
177                 <attribute id=\"0x0004\">                               \
178                         <sequence>                                      \
179                                 <sequence>                              \
180                                         <uuid value=\"0x0100\" />       \
181                                 </sequence>                             \
182                                 <sequence>                              \
183                                         <uuid value=\"0x0003\" />       \
184                                         <uint8 value=\"0x%02x\" />      \
185                                 </sequence>                             \
186                         </sequence>                                     \
187                 </attribute>                                            \
188                 <attribute id=\"0x0005\">                               \
189                         <sequence>                                      \
190                                 <uuid value=\"0x1002\" />               \
191                         </sequence>                                     \
192                 </attribute>                                            \
193                 <attribute id=\"0x0009\">                               \
194                         <sequence>                                      \
195                                 <sequence>                              \
196                                         <uuid value=\"0x1108\" />       \
197                                         <uint16 value=\"0x%04x\" />     \
198                                 </sequence>                             \
199                         </sequence>                                     \
200                 </attribute>                                            \
201                 <attribute id=\"0x0100\">                               \
202                         <text value=\"%s\" />                           \
203                 </attribute>                                            \
204         </record>"
205
206 #ifdef __TIZEN_PATCH__
207 #define SPP_RECORD                                                      \
208         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
209         <record>                                                        \
210                 <attribute id=\"0x0001\">                               \
211                         <sequence>                                      \
212                                 %s                                      \
213                         </sequence>                                     \
214                 </attribute>                                            \
215                 <attribute id=\"0x0004\">                               \
216                         <sequence>                                      \
217                                 <sequence>                              \
218                                         <uuid value=\"0x0100\" />       \
219                                 </sequence>                             \
220                                 <sequence>                              \
221                                         <uuid value=\"0x0003\" />       \
222                                         <uint8 value=\"0x%02x\" />      \
223                                 </sequence>                             \
224                         </sequence>                                     \
225                 </attribute>                                            \
226                 <attribute id=\"0x0005\">                               \
227                         <sequence>                                      \
228                                 <uuid value=\"0x1002\" />               \
229                         </sequence>                                     \
230                 </attribute>                                            \
231                 %s                                                              \
232                 <attribute id=\"0x0009\">                               \
233                         <sequence>                                      \
234                                 <sequence>                              \
235                                         <uuid value=\"0x1101\" />       \
236                                         <uint16 value=\"0x%04x\" />     \
237                                 </sequence>                             \
238                         </sequence>                                     \
239                 </attribute>                                            \
240                 <attribute id=\"0x0100\">                               \
241                         <text value=\"%s\" />                           \
242                 </attribute>                                            \
243         </record>"
244
245 #define LANG_SEQ                                                                \
246                         "<attribute id=\"0x0006\">                              \
247                                 <sequence>                                      \
248                                         <uint16 value=\"0x%04x\" />     \
249                                         <uint16 value=\"0x%04x\" />     \
250                                         <uint16 value=\"0x%04x\" />     \
251                                 </sequence>                             \
252                         </attribute>"
253 #else
254 #define SPP_RECORD                                                      \
255         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
256         <record>                                                        \
257                 <attribute id=\"0x0001\">                               \
258                         <sequence>                                      \
259                                 <uuid value=\"0x1101\" />               \
260                                 %s                                      \
261                         </sequence>                                     \
262                 </attribute>                                            \
263                 <attribute id=\"0x0004\">                               \
264                         <sequence>                                      \
265                                 <sequence>                              \
266                                         <uuid value=\"0x0100\" />       \
267                                 </sequence>                             \
268                                 <sequence>                              \
269                                         <uuid value=\"0x0003\" />       \
270                                         <uint8 value=\"0x%02x\" />      \
271                                 </sequence>                             \
272                         </sequence>                                     \
273                 </attribute>                                            \
274                 <attribute id=\"0x0005\">                               \
275                         <sequence>                                      \
276                                 <uuid value=\"0x1002\" />               \
277                         </sequence>                                     \
278                 </attribute>                                            \
279                 <attribute id=\"0x0009\">                               \
280                         <sequence>                                      \
281                                 <sequence>                              \
282                                         <uuid value=\"0x1101\" />       \
283                                         <uint16 value=\"0x%04x\" />     \
284                                 </sequence>                             \
285                         </sequence>                                     \
286                 </attribute>                                            \
287                 <attribute id=\"0x0100\">                               \
288                         <text value=\"%s\" />                           \
289                 </attribute>                                            \
290         </record>"
291 #endif
292
293 #define DUN_RECORD                                                      \
294         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
295         <record>                                                        \
296                 <attribute id=\"0x0001\">                               \
297                         <sequence>                                      \
298                                 <uuid value=\"0x1103\" />               \
299                                 <uuid value=\"0x1201\" />               \
300                         </sequence>                                     \
301                 </attribute>                                            \
302                 <attribute id=\"0x0004\">                               \
303                         <sequence>                                      \
304                                 <sequence>                              \
305                                         <uuid value=\"0x0100\" />       \
306                                 </sequence>                             \
307                                 <sequence>                              \
308                                         <uuid value=\"0x0003\" />       \
309                                         <uint8 value=\"0x%02x\" />      \
310                                 </sequence>                             \
311                         </sequence>                                     \
312                 </attribute>                                            \
313                 <attribute id=\"0x0005\">                               \
314                         <sequence>                                      \
315                                 <uuid value=\"0x1002\" />               \
316                         </sequence>                                     \
317                 </attribute>                                            \
318                 <attribute id=\"0x0009\">                               \
319                         <sequence>                                      \
320                                 <sequence>                              \
321                                         <uuid value=\"0x1103\" />       \
322                                         <uint16 value=\"0x%04x\" />     \
323                                 </sequence>                             \
324                         </sequence>                                     \
325                 </attribute>                                            \
326                 <attribute id=\"0x0100\">                               \
327                         <text value=\"%s\" />                           \
328                 </attribute>                                            \
329         </record>"
330
331 #ifdef __TIZEN_PATCH__
332 #define OPP_RECORD                                                      \
333         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
334         <record>                                                        \
335                 <attribute id=\"0x0001\">                               \
336                         <sequence>                                      \
337                                 <uuid value=\"0x1105\" />               \
338                         </sequence>                                     \
339                 </attribute>                                            \
340                 <attribute id=\"0x0004\">                               \
341                         <sequence>                                      \
342                                 <sequence>                              \
343                                         <uuid value=\"0x0100\" />       \
344                                 </sequence>                             \
345                                 <sequence>                              \
346                                         <uuid value=\"0x0003\" />       \
347                                         <uint8 value=\"0x%02x\" />      \
348                                 </sequence>                             \
349                                 <sequence>                              \
350                                         <uuid value=\"0x0008\"/>        \
351                                 </sequence>                             \
352                         </sequence>                                     \
353                 </attribute>                                            \
354                 <attribute id=\"0x0005\">                               \
355                         <sequence>                                      \
356                                 <uuid value=\"0x1002\" />               \
357                         </sequence>                                     \
358                 </attribute>                                            \
359                 <attribute id=\"0x0009\">                               \
360                         <sequence>                                      \
361                                 <sequence>                              \
362                                         <uuid value=\"0x1105\" />       \
363                                         <uint16 value=\"0x%04x\" />     \
364                                 </sequence>                             \
365                         </sequence>                                     \
366                 </attribute>                                            \
367                 <attribute id=\"0x0303\">                               \
368                         <sequence>                                      \
369                                 <uint8 value=\"0x01\"/>                 \
370                                 <uint8 value=\"0x02\"/>                 \
371                                 <uint8 value=\"0x03\"/>                 \
372                                 <uint8 value=\"0x04\"/>                 \
373                                 <uint8 value=\"0x05\"/>                 \
374                                 <uint8 value=\"0x06\"/>                 \
375                                 <uint8 value=\"0xff\"/>                 \
376                         </sequence>                                     \
377                 </attribute>                                            \
378                 <attribute id=\"0x0100\">                               \
379                         <text value=\"%s\" />                           \
380                 </attribute>                                            \
381         </record>"
382 #else
383 #define OPP_RECORD                                                      \
384         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
385         <record>                                                        \
386                 <attribute id=\"0x0001\">                               \
387                         <sequence>                                      \
388                                 <uuid value=\"0x1105\" />               \
389                         </sequence>                                     \
390                 </attribute>                                            \
391                 <attribute id=\"0x0004\">                               \
392                         <sequence>                                      \
393                                 <sequence>                              \
394                                         <uuid value=\"0x0100\" />       \
395                                 </sequence>                             \
396                                 <sequence>                              \
397                                         <uuid value=\"0x0003\" />       \
398                                         <uint8 value=\"0x%02x\" />      \
399                                 </sequence>                             \
400                                 <sequence>                              \
401                                         <uuid value=\"0x0008\"/>        \
402                                 </sequence>                             \
403                         </sequence>                                     \
404                 </attribute>                                            \
405                 <attribute id=\"0x0005\">                               \
406                         <sequence>                                      \
407                                 <uuid value=\"0x1002\" />               \
408                         </sequence>                                     \
409                 </attribute>                                            \
410                 <attribute id=\"0x0009\">                               \
411                         <sequence>                                      \
412                                 <sequence>                              \
413                                         <uuid value=\"0x1105\" />       \
414                                         <uint16 value=\"0x%04x\" />     \
415                                 </sequence>                             \
416                         </sequence>                                     \
417                 </attribute>                                            \
418                 <attribute id=\"0x0303\">                               \
419                         <sequence>                                      \
420                                 <uint8 value=\"0x01\"/>                 \
421                                 <uint8 value=\"0x02\"/>                 \
422                                 <uint8 value=\"0x03\"/>                 \
423                                 <uint8 value=\"0x04\"/>                 \
424                                 <uint8 value=\"0x05\"/>                 \
425                                 <uint8 value=\"0x06\"/>                 \
426                                 <uint8 value=\"0xff\"/>                 \
427                         </sequence>                                     \
428                 </attribute>                                            \
429                 <attribute id=\"0x0200\">                               \
430                         <uint16 value=\"%u\" name=\"psm\"/>             \
431                 </attribute>                                            \
432                 <attribute id=\"0x0100\">                               \
433                         <text value=\"%s\" />                           \
434                 </attribute>                                            \
435         </record>"
436 #endif
437
438 #define FTP_RECORD                                                      \
439         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
440         <record>                                                        \
441                 <attribute id=\"0x0001\">                               \
442                         <sequence>                                      \
443                                 <uuid value=\"0x1106\" />               \
444                         </sequence>                                     \
445                 </attribute>                                            \
446                 <attribute id=\"0x0004\">                               \
447                         <sequence>                                      \
448                                 <sequence>                              \
449                                         <uuid value=\"0x0100\" />       \
450                                 </sequence>                             \
451                                 <sequence>                              \
452                                         <uuid value=\"0x0003\" />       \
453                                         <uint8 value=\"0x%02x\" />      \
454                                 </sequence>                             \
455                                 <sequence>                              \
456                                         <uuid value=\"0x0008\"/>        \
457                                 </sequence>                             \
458                         </sequence>                                     \
459                 </attribute>                                            \
460                 <attribute id=\"0x0005\">                               \
461                         <sequence>                                      \
462                                 <uuid value=\"0x1002\" />               \
463                         </sequence>                                     \
464                 </attribute>                                            \
465                 <attribute id=\"0x0009\">                               \
466                         <sequence>                                      \
467                                 <sequence>                              \
468                                         <uuid value=\"0x1106\" />       \
469                                         <uint16 value=\"0x%04x\" />     \
470                                 </sequence>                             \
471                         </sequence>                                     \
472                 </attribute>                                            \
473                 <attribute id=\"0x0200\">                               \
474                         <uint16 value=\"%u\" name=\"psm\"/>             \
475                 </attribute>                                            \
476                 <attribute id=\"0x0100\">                               \
477                         <text value=\"%s\" />                           \
478                 </attribute>                                            \
479         </record>"
480
481 #define PCE_RECORD                                                      \
482         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
483         <record>                                                        \
484                 <attribute id=\"0x0001\">                               \
485                         <sequence>                                      \
486                                 <uuid value=\"0x112e\" />               \
487                         </sequence>                                     \
488                 </attribute>                                            \
489                 <attribute id=\"0x0005\">                               \
490                         <sequence>                                      \
491                                 <uuid value=\"0x1002\" />               \
492                         </sequence>                                     \
493                 </attribute>                                            \
494                 <attribute id=\"0x0009\">                               \
495                         <sequence>                                      \
496                                 <sequence>                              \
497                                         <uuid value=\"0x1130\" />       \
498                                         <uint16 value=\"0x%04x\" />     \
499                                 </sequence>                             \
500                         </sequence>                                     \
501                 </attribute>                                            \
502                 <attribute id=\"0x0100\">                               \
503                         <text value=\"%s\" />                           \
504                 </attribute>                                            \
505         </record>"
506
507 #ifdef PBAP_SIM_ENABLE
508 #define PBAP_ACCESS "0x03"      /* Phone and SIM access support*/
509 #else
510 #define PBAP_ACCESS "0x01"      /* Phone access support only*/
511 #endif
512
513
514 #ifdef __TIZEN_PATCH__
515 #define PSE_RECORD                                                      \
516         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
517         <record>                                                        \
518                 <attribute id=\"0x0001\">                               \
519                         <sequence>                                      \
520                                 <uuid value=\"0x112f\" />               \
521                         </sequence>                                     \
522                 </attribute>                                            \
523                 <attribute id=\"0x0004\">                               \
524                         <sequence>                                      \
525                                 <sequence>                              \
526                                         <uuid value=\"0x0100\" />       \
527                                 </sequence>                             \
528                                 <sequence>                              \
529                                         <uuid value=\"0x0003\" />       \
530                                         <uint8 value=\"0x%02x\" />      \
531                                 </sequence>                             \
532                                 <sequence>                              \
533                                         <uuid value=\"0x0008\"/>        \
534                                 </sequence>                             \
535                         </sequence>                                     \
536                 </attribute>                                            \
537                 <attribute id=\"0x0005\">                               \
538                         <sequence>                                      \
539                                 <uuid value=\"0x1002\" />               \
540                         </sequence>                                     \
541                 </attribute>                                            \
542                 <attribute id=\"0x0009\">                               \
543                         <sequence>                                      \
544                                 <sequence>                              \
545                                         <uuid value=\"0x1130\" />       \
546                                         <uint16 value=\"0x%04x\" />     \
547                                 </sequence>                             \
548                         </sequence>                                     \
549                 </attribute>                                            \
550                 <attribute id=\"0x0100\">                               \
551                         <text value=\"%s\" />                           \
552                 </attribute>                                            \
553                 <attribute id=\"0x0314\">                               \
554                         <uint8 value=\""PBAP_ACCESS"\"/>                                \
555                 </attribute>                                            \
556                 <attribute id=\"0x0200\">                               \
557                         <uint16 value=\"%u\" name=\"psm\"/>             \
558                 </attribute>                                            \
559         </record>"
560 #else
561 #define PSE_RECORD                                                      \
562         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
563         <record>                                                        \
564                 <attribute id=\"0x0001\">                               \
565                         <sequence>                                      \
566                                 <uuid value=\"0x112f\" />               \
567                         </sequence>                                     \
568                 </attribute>                                            \
569                 <attribute id=\"0x0004\">                               \
570                         <sequence>                                      \
571                                 <sequence>                              \
572                                         <uuid value=\"0x0100\" />       \
573                                 </sequence>                             \
574                                 <sequence>                              \
575                                         <uuid value=\"0x0003\" />       \
576                                         <uint8 value=\"0x%02x\" />      \
577                                 </sequence>                             \
578                                 <sequence>                              \
579                                         <uuid value=\"0x0008\"/>        \
580                                 </sequence>                             \
581                         </sequence>                                     \
582                 </attribute>                                            \
583                 <attribute id=\"0x0005\">                               \
584                         <sequence>                                      \
585                                 <uuid value=\"0x1002\" />               \
586                         </sequence>                                     \
587                 </attribute>                                            \
588                 <attribute id=\"0x0009\">                               \
589                         <sequence>                                      \
590                                 <sequence>                              \
591                                         <uuid value=\"0x1130\" />       \
592                                         <uint16 value=\"0x%04x\" />     \
593                                 </sequence>                             \
594                         </sequence>                                     \
595                 </attribute>                                            \
596                 <attribute id=\"0x0100\">                               \
597                         <text value=\"%s\" />                           \
598                 </attribute>                                            \
599                 <attribute id=\"0x0314\">                               \
600                         <uint8 value=\"0x01\"/>                         \
601                 </attribute>                                            \
602                 <attribute id=\"0x0317\">                               \
603                         <uint32 value=\"0x00000003\"/>                  \
604                 </attribute>                                            \
605                 <attribute id=\"0x0200\">                               \
606                         <uint16 value=\"%u\" name=\"psm\"/>             \
607                 </attribute>                                            \
608         </record>"
609 #endif
610
611 #define MAS_RECORD                                                      \
612         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
613         <record>                                                        \
614                 <attribute id=\"0x0001\">                               \
615                         <sequence>                                      \
616                                 <uuid value=\"0x1132\"/>                \
617                         </sequence>                                     \
618                 </attribute>                                            \
619                 <attribute id=\"0x0004\">                               \
620                         <sequence>                                      \
621                                 <sequence>                              \
622                                         <uuid value=\"0x0100\"/>        \
623                                 </sequence>                             \
624                                 <sequence>                              \
625                                         <uuid value=\"0x0003\"/>        \
626                                         <uint8 value=\"0x%02x\"/>       \
627                                 </sequence>                             \
628                                 <sequence>                              \
629                                         <uuid value=\"0x0008\"/>        \
630                                 </sequence>                             \
631                         </sequence>                                     \
632                 </attribute>                                            \
633                 <attribute id=\"0x0005\">                               \
634                         <sequence>                                      \
635                                 <uuid value=\"0x1002\" />               \
636                         </sequence>                                     \
637                 </attribute>                                            \
638                 <attribute id=\"0x0009\">                               \
639                         <sequence>                                      \
640                                 <sequence>                              \
641                                         <uuid value=\"0x1134\"/>        \
642                                         <uint16 value=\"0x%04x\" />     \
643                                 </sequence>                             \
644                         </sequence>                                     \
645                 </attribute>                                            \
646                 <attribute id=\"0x0100\">                               \
647                         <text value=\"%s\"/>                            \
648                 </attribute>                                            \
649                 <attribute id=\"0x0315\">                               \
650                         <uint8 value=\"0x00\"/>                         \
651                 </attribute>                                            \
652                 <attribute id=\"0x0316\">                               \
653                         <uint8 value=\"0x0F\"/>                         \
654                 </attribute>                                            \
655                 <attribute id=\"0x0317\">                               \
656                         <uint32 value=\"0x0000007f\"/>                  \
657                 </attribute>                                            \
658                 <attribute id=\"0x0200\">                               \
659                         <uint16 value=\"%u\" name=\"psm\"/>             \
660                 </attribute>                                            \
661         </record>"
662
663 #define MNS_RECORD                                                      \
664         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
665         <record>                                                        \
666                 <attribute id=\"0x0001\">                               \
667                         <sequence>                                      \
668                                 <uuid value=\"0x1133\"/>                \
669                         </sequence>                                     \
670                 </attribute>                                            \
671                 <attribute id=\"0x0004\">                               \
672                         <sequence>                                      \
673                                 <sequence>                              \
674                                         <uuid value=\"0x0100\"/>        \
675                                 </sequence>                             \
676                                 <sequence>                              \
677                                         <uuid value=\"0x0003\"/>        \
678                                         <uint8 value=\"0x%02x\"/>       \
679                                 </sequence>                             \
680                                 <sequence>                              \
681                                         <uuid value=\"0x0008\"/>        \
682                                 </sequence>                             \
683                         </sequence>                                     \
684                 </attribute>                                            \
685                 <attribute id=\"0x0005\">                               \
686                         <sequence>                                      \
687                                 <uuid value=\"0x1002\" />               \
688                         </sequence>                                     \
689                 </attribute>                                            \
690                 <attribute id=\"0x0009\">                               \
691                         <sequence>                                      \
692                                 <sequence>                              \
693                                         <uuid value=\"0x1134\"/>        \
694                                         <uint16 value=\"0x%04x\"/>      \
695                                 </sequence>                             \
696                         </sequence>                                     \
697                 </attribute>                                            \
698                 <attribute id=\"0x0100\">                               \
699                         <text value=\"%s\"/>                            \
700                 </attribute>                                            \
701                 <attribute id=\"0x0317\">                               \
702                         <uint32 value=\"0x0000007f\"/>                  \
703                 </attribute>                                            \
704                 <attribute id=\"0x0200\">                               \
705                         <uint16 value=\"%u\" name=\"psm\"/>             \
706                 </attribute>                                            \
707         </record>"
708
709 #define SYNC_RECORD                                                     \
710         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
711         <record>                                                        \
712                 <attribute id=\"0x0001\">                               \
713                         <sequence>                                      \
714                                 <uuid value=\"0x1104\"/>                \
715                         </sequence>                                     \
716                 </attribute>                                            \
717                 <attribute id=\"0x0004\">                               \
718                         <sequence>                                      \
719                                 <sequence>                              \
720                                         <uuid value=\"0x0100\"/>        \
721                                 </sequence>                             \
722                                 <sequence>                              \
723                                         <uuid value=\"0x0003\"/>        \
724                                         <uint8 value=\"0x%02x\"/>       \
725                                 </sequence>                             \
726                                 <sequence>                              \
727                                         <uuid value=\"0x0008\"/>        \
728                                 </sequence>                             \
729                         </sequence>                                     \
730                 </attribute>                                            \
731                 <attribute id=\"0x0005\">                               \
732                         <sequence>                                      \
733                                 <uuid value=\"0x1002\" />               \
734                         </sequence>                                     \
735                 </attribute>                                            \
736                 <attribute id=\"0x0009\">                               \
737                         <sequence>                                      \
738                                 <sequence>                              \
739                                         <uuid value=\"0x1104\"/>        \
740                                         <uint16 value=\"0x%04x\" />     \
741                                  </sequence>                            \
742                         </sequence>                                     \
743                 </attribute>                                            \
744                 <attribute id=\"0x0100\">                               \
745                         <text value=\"%s\"/>                            \
746                 </attribute>                                            \
747                 <attribute id=\"0x0301\">                               \
748                         <sequence>                                      \
749                                 <uint8 value=\"0x01\"/>                 \
750                         </sequence>                                     \
751                 </attribute>                                            \
752         </record>"
753
754 #define GENERIC_RECORD                                                  \
755         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
756         <record>                                                        \
757                 <attribute id=\"0x0001\">                               \
758                         <sequence>                                      \
759                                 <uuid value=\"%s\" />                   \
760                         </sequence>                                     \
761                 </attribute>                                            \
762                 <attribute id=\"0x0004\">                               \
763                         <sequence>                                      \
764                                 <sequence>                              \
765                                         <uuid value=\"0x0100\" />       \
766                                         %s                              \
767                                 </sequence>                             \
768                                 %s                                      \
769                         </sequence>                                     \
770                 </attribute>                                            \
771                 <attribute id=\"0x0005\">                               \
772                         <sequence>                                      \
773                                 <uuid value=\"0x1002\" />               \
774                         </sequence>                                     \
775                 </attribute>                                            \
776                 %s                                                      \
777                 <attribute id=\"0x0100\">                               \
778                         <text value=\"%s\" />                           \
779                 </attribute>                                            \
780         </record>"
781
782 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
783 #define HID_DEVICE_RECORD       \
784         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>    \
785         <record>        \
786         <attribute id=\"0x0001\">       \
787                 <sequence>      \
788                         <uuid value=\"0x1124\" />       \
789                 </sequence>     \
790         </attribute>    \
791         <attribute id=\"0x0004\">       \
792                 <sequence>      \
793                         <sequence>      \
794                                 <uuid value=\"0x0100\" />       \
795                                 <uint16 value=\"0x0011\" />     \
796                         </sequence>     \
797                         <sequence>      \
798                                 <uuid value=\"0x0011\" />       \
799                         </sequence>     \
800                 </sequence>     \
801         </attribute>    \
802         <attribute id=\"0x0005\">       \
803                 <sequence>      \
804                         <uuid value=\"0x1002\" />       \
805                 </sequence>     \
806         </attribute>    \
807         <attribute id=\"0x0006\">       \
808                 <sequence>      \
809                         <uint16 value=\"0x656e\" />     \
810                         <uint16 value=\"0x006a\" />     \
811                         <uint16 value=\"0x0100\" />     \
812                 </sequence>     \
813         </attribute>    \
814         <attribute id=\"0x0009\">       \
815                 <sequence>      \
816                         <sequence>      \
817                                 <uuid value=\"0x0011\" />       \
818                                 <uint16 value=\"0x0100\" />     \
819                         </sequence>     \
820                 </sequence>     \
821         </attribute>    \
822         <attribute id=\"0x000d\">       \
823                 <sequence>      \
824                         <sequence>      \
825                                 <sequence>      \
826                                         <uuid value=\"0x0100\" />       \
827                                         <uint16 value=\"0x0013\" />     \
828                                 </sequence>     \
829                                 <sequence>      \
830                                         <uuid value=\"0x0011\" />       \
831                                 </sequence>     \
832                         </sequence>     \
833                 </sequence>     \
834         </attribute>    \
835         <attribute id=\"0x0100\">       \
836                 <text value=\"Bluez Mouse\" />  \
837         </attribute>    \
838         <attribute id=\"0x0101\">       \
839                 <text value=\"Mouse\" />        \
840         </attribute>    \
841         <attribute id=\"0x0200\">       \
842                 <uint16 value=\"0x0100\" />     \
843         </attribute>    \
844         <attribute id=\"0x0201\">       \
845                 <uint16 value=\"0x0111\" />     \
846         </attribute>    \
847         <attribute id=\"0x0202\">       \
848                 <uint8 value=\"0x40\" />                \
849         </attribute>    \
850         <attribute id=\"0x0203\">       \
851                 <uint8 value=\"0x00\" />                \
852         </attribute>    \
853         <attribute id=\"0x0204\">       \
854                 <boolean value=\"true\" />      \
855         </attribute>    \
856         <attribute id=\"0x0205\">       \
857                 <boolean value=\"true\" />      \
858         </attribute>    \
859         <attribute id=\"0x0206\">       \
860                 <sequence>      \
861                         <sequence>      \
862                                 <uint8 value=\"0x22\" />                \
863                                 <text encoding=\"hex\" value=\"05010902a10185010901a1000509190129031500250175019503810275059501810105010930093109381581257f750895028106c0c005010906a1018502a100050719e029e71500250175019508810295087508150025650507190029658100c0c0\" />        \
864                         </sequence>     \
865                 </sequence>     \
866         </attribute>    \
867         <attribute id=\"0x0207\">       \
868                 <sequence>      \
869                         <sequence>      \
870                                 <uint16 value=\"0x0409\" />     \
871                                 <uint16 value=\"0x0100\" />     \
872                         </sequence>     \
873                 </sequence>     \
874         </attribute>    \
875         <attribute id=\"0x020b\">       \
876                 <uint16 value=\"0x0100\" />     \
877         </attribute>    \
878         <attribute id=\"0x020e\">       \
879                 <boolean value=\"true\" />      \
880         </attribute>    \
881         </record>"
882 #endif
883
884
885 struct ext_io;
886
887 struct ext_profile {
888         struct btd_profile p;
889
890         char *name;
891         char *owner;
892         char *path;
893         char *uuid;
894         char *service;
895         char *role;
896
897         char *record;
898         char *(*get_record)(struct ext_profile *ext, struct ext_io *l2cap,
899                                                         struct ext_io *rfcomm);
900
901         char *remote_uuid;
902
903         guint id;
904
905         BtIOMode mode;
906         BtIOSecLevel sec_level;
907         bool authorize;
908
909         bool enable_client;
910         bool enable_server;
911
912         int local_psm;
913         int local_chan;
914
915         uint16_t remote_psm;
916         uint8_t remote_chan;
917
918         uint16_t version;
919         uint16_t features;
920
921         GSList *records;
922         GSList *servers;
923         GSList *conns;
924
925         GSList *connects;
926 #ifdef __TIZEN_PATCH__
927         char *destination;
928         char *app_path;
929 #endif
930 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
931         bool local_connect;
932 #endif
933 };
934
935 struct ext_io {
936         struct ext_profile *ext;
937         int proto;
938         GIOChannel *io;
939         guint io_id;
940         struct btd_adapter *adapter;
941         struct btd_device *device;
942         struct btd_service *service;
943
944         bool resolving;
945         bool connected;
946
947         uint16_t version;
948         uint16_t features;
949
950         uint16_t psm;
951         uint8_t chan;
952
953         guint auth_id;
954         DBusPendingCall *pending;
955 };
956
957 struct ext_record {
958         struct btd_adapter *adapter;
959         uint32_t handle;
960 };
961
962 struct btd_profile_custom_property {
963         char *uuid;
964         char *type;
965         char *name;
966         btd_profile_prop_exists exists;
967         btd_profile_prop_get get;
968         void *user_data;
969 };
970
971 static GSList *custom_props = NULL;
972
973 static GSList *profiles = NULL;
974 static GSList *ext_profiles = NULL;
975
976 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
977 static int connect_io(struct ext_io *conn, const bdaddr_t *src,
978                                                         const bdaddr_t *dst);
979 #endif
980
981 void btd_profile_foreach(void (*func)(struct btd_profile *p, void *data),
982                                                                 void *data)
983 {
984         GSList *l, *next;
985
986         for (l = profiles; l != NULL; l = next) {
987                 struct btd_profile *profile = l->data;
988
989                 next = g_slist_next(l);
990
991                 func(profile, data);
992         }
993
994         for (l = ext_profiles; l != NULL; l = next) {
995                 struct ext_profile *profile = l->data;
996
997                 next = g_slist_next(l);
998
999                 func(&profile->p, data);
1000         }
1001 }
1002
1003 int btd_profile_register(struct btd_profile *profile)
1004 {
1005         profiles = g_slist_append(profiles, profile);
1006         return 0;
1007 }
1008
1009 void btd_profile_unregister(struct btd_profile *profile)
1010 {
1011         profiles = g_slist_remove(profiles, profile);
1012 }
1013
1014 static struct ext_profile *find_ext_profile(const char *owner,
1015                                                 const char *path)
1016 {
1017         GSList *l;
1018
1019         for (l = ext_profiles; l != NULL; l = g_slist_next(l)) {
1020                 struct ext_profile *ext = l->data;
1021
1022                 if (g_strcmp0(ext->owner, owner))
1023                         continue;
1024
1025                 if (!g_strcmp0(ext->path, path))
1026                         return ext;
1027         }
1028
1029         return NULL;
1030 }
1031
1032 static void ext_io_destroy(gpointer p)
1033 {
1034         struct ext_io *ext_io = p;
1035
1036         if (ext_io->io_id > 0)
1037                 g_source_remove(ext_io->io_id);
1038
1039         if (ext_io->io) {
1040                 g_io_channel_shutdown(ext_io->io, FALSE, NULL);
1041                 g_io_channel_unref(ext_io->io);
1042         }
1043
1044         if (ext_io->auth_id != 0)
1045                 btd_cancel_authorization(ext_io->auth_id);
1046
1047         if (ext_io->pending) {
1048                 dbus_pending_call_cancel(ext_io->pending);
1049                 dbus_pending_call_unref(ext_io->pending);
1050         }
1051
1052         if (ext_io->resolving)
1053                 bt_cancel_discovery(btd_adapter_get_address(ext_io->adapter),
1054                                         device_get_address(ext_io->device));
1055
1056         if (ext_io->adapter)
1057                 btd_adapter_unref(ext_io->adapter);
1058
1059         if (ext_io->device)
1060                 btd_device_unref(ext_io->device);
1061
1062         if (ext_io->service)
1063                 btd_service_unref(ext_io->service);
1064
1065         g_free(ext_io);
1066 }
1067
1068 static gboolean ext_io_disconnected(GIOChannel *io, GIOCondition cond,
1069                                                         gpointer user_data)
1070 {
1071         struct ext_io *conn = user_data;
1072         struct ext_profile *ext = conn->ext;
1073         GError *gerr = NULL;
1074         char addr[18];
1075
1076         if (cond & G_IO_NVAL)
1077                 return FALSE;
1078
1079         bt_io_get(io, &gerr, BT_IO_OPT_DEST, addr, BT_IO_OPT_INVALID);
1080         if (gerr != NULL) {
1081                 error("Unable to get io data for %s: %s",
1082                                                 ext->name, gerr->message);
1083                 g_error_free(gerr);
1084                 goto drop;
1085         }
1086
1087         DBG("%s disconnected from %s", ext->name, addr);
1088 drop:
1089         if (conn->service) {
1090                 if (btd_service_get_state(conn->service) ==
1091                                                 BTD_SERVICE_STATE_CONNECTING)
1092                         btd_service_connecting_complete(conn->service, -EIO);
1093                 else
1094                         btd_service_disconnecting_complete(conn->service, 0);
1095         }
1096
1097         ext->conns = g_slist_remove(ext->conns, conn);
1098         ext_io_destroy(conn);
1099         return FALSE;
1100 }
1101
1102 static void new_conn_reply(DBusPendingCall *call, void *user_data)
1103 {
1104         struct ext_io *conn = user_data;
1105         struct ext_profile *ext = conn->ext;
1106         DBusMessage *reply = dbus_pending_call_steal_reply(call);
1107         DBusError err;
1108
1109         dbus_error_init(&err);
1110         dbus_set_error_from_message(&err, reply);
1111
1112         dbus_message_unref(reply);
1113
1114         dbus_pending_call_unref(conn->pending);
1115         conn->pending = NULL;
1116
1117         if (!dbus_error_is_set(&err)) {
1118                 if (conn->service)
1119                         btd_service_connecting_complete(conn->service, 0);
1120
1121                 conn->connected = true;
1122                 return;
1123         }
1124
1125         error("%s replied with an error: %s, %s", ext->name,
1126                                                 err.name, err.message);
1127
1128         if (conn->service)
1129                 btd_service_connecting_complete(conn->service, -ECONNREFUSED);
1130
1131         dbus_error_free(&err);
1132
1133         ext->conns = g_slist_remove(ext->conns, conn);
1134         ext_io_destroy(conn);
1135 }
1136
1137 static void disconn_reply(DBusPendingCall *call, void *user_data)
1138 {
1139         struct ext_io *conn = user_data;
1140         struct ext_profile *ext = conn->ext;
1141         DBusMessage *reply = dbus_pending_call_steal_reply(call);
1142         DBusError err;
1143
1144         dbus_error_init(&err);
1145         dbus_set_error_from_message(&err, reply);
1146
1147         dbus_message_unref(reply);
1148
1149         dbus_pending_call_unref(conn->pending);
1150         conn->pending = NULL;
1151
1152         if (!dbus_error_is_set(&err)) {
1153                 if (conn->service)
1154                         btd_service_disconnecting_complete(conn->service, 0);
1155
1156                 goto disconnect;
1157         }
1158
1159         error("%s replied with an error: %s, %s", ext->name,
1160                                                 err.name, err.message);
1161
1162         if (conn->service)
1163                 btd_service_disconnecting_complete(conn->service,
1164                                                                 -ECONNREFUSED);
1165
1166         dbus_error_free(&err);
1167
1168 disconnect:
1169         ext->conns = g_slist_remove(ext->conns, conn);
1170         ext_io_destroy(conn);
1171 }
1172
1173 struct prop_append_data {
1174         DBusMessageIter *dict;
1175         struct ext_io *io;
1176 };
1177
1178 static void append_prop(gpointer a, gpointer b)
1179 {
1180         struct btd_profile_custom_property *p = a;
1181         struct prop_append_data *data = b;
1182         DBusMessageIter entry, value, *dict = data->dict;
1183         struct btd_device *dev = data->io->device;
1184         struct ext_profile *ext = data->io->ext;
1185         const char *uuid = ext->service ? ext->service : ext->uuid;
1186
1187         if (strcasecmp(p->uuid, uuid) != 0)
1188                 return;
1189
1190         if (p->exists && !p->exists(p->uuid, dev, p->user_data))
1191                 return;
1192
1193         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, NULL,
1194                                                                 &entry);
1195         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &p->name);
1196         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, p->type,
1197                                                                 &value);
1198
1199         p->get(p->uuid, dev, &value, p->user_data);
1200
1201         dbus_message_iter_close_container(&entry, &value);
1202         dbus_message_iter_close_container(dict, &entry);
1203 }
1204
1205 static uint16_t get_supported_features(const sdp_record_t *rec)
1206 {
1207         sdp_data_t *data;
1208
1209         data = sdp_data_get(rec, SDP_ATTR_SUPPORTED_FEATURES);
1210         if (!data || data->dtd != SDP_UINT16)
1211                 return 0;
1212
1213         return data->val.uint16;
1214 }
1215
1216 static uint16_t get_profile_version(const sdp_record_t *rec)
1217 {
1218         sdp_list_t *descs;
1219         uint16_t version;
1220
1221         if (sdp_get_profile_descs(rec, &descs) < 0)
1222                 return 0;
1223
1224         if (descs && descs->data) {
1225                 sdp_profile_desc_t *desc = descs->data;
1226                 version = desc->version;
1227         } else {
1228                 version = 0;
1229         }
1230
1231         sdp_list_free(descs, free);
1232
1233         return version;
1234 }
1235
1236 static bool send_new_connection(struct ext_profile *ext, struct ext_io *conn)
1237 {
1238         DBusMessage *msg;
1239         DBusMessageIter iter, dict;
1240         struct prop_append_data data = { &dict, conn };
1241         const char *remote_uuid = ext->remote_uuid;
1242         const sdp_record_t *rec;
1243         const char *path;
1244         int fd;
1245
1246         msg = dbus_message_new_method_call(ext->owner, ext->path,
1247                                                         "org.bluez.Profile1",
1248                                                         "NewConnection");
1249         if (!msg) {
1250                 error("Unable to create NewConnection call for %s", ext->name);
1251                 return false;
1252         }
1253
1254         if (remote_uuid) {
1255                 rec = btd_device_get_record(conn->device, remote_uuid);
1256                 if (rec) {
1257                         conn->features = get_supported_features(rec);
1258                         conn->version = get_profile_version(rec);
1259                 }
1260         }
1261
1262         dbus_message_iter_init_append(msg, &iter);
1263
1264         path = device_get_path(conn->device);
1265         dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
1266
1267         fd = g_io_channel_unix_get_fd(conn->io);
1268
1269 #ifdef __TIZEN_PATCH__
1270 {
1271         DBG("Set smack label!");
1272         int ret;
1273
1274         ret = fsetxattr(fd, XATTR_NAME_SMACKIPIN, "System", sizeof("System"), 0);
1275         if (ret != 0) {
1276                 DBG("Set attr error: %d", ret);
1277         }
1278
1279         ret = fsetxattr(fd, XATTR_NAME_SMACKIPOUT, "System", sizeof("System"), 0);
1280         if (ret != 0) {
1281                 DBG("Set attr error: %d", ret);
1282         }
1283 }
1284 #endif
1285
1286         dbus_message_iter_append_basic(&iter, DBUS_TYPE_UNIX_FD, &fd);
1287
1288         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
1289
1290         if (conn->version)
1291                 dict_append_entry(&dict, "Version", DBUS_TYPE_UINT16,
1292                                                         &conn->version);
1293
1294         if (conn->features)
1295                 dict_append_entry(&dict, "Features", DBUS_TYPE_UINT16,
1296                                                         &conn->features);
1297
1298         g_slist_foreach(custom_props, append_prop, &data);
1299
1300         dbus_message_iter_close_container(&iter, &dict);
1301
1302         if (!g_dbus_send_message_with_reply(btd_get_dbus_connection(),
1303                                                 msg, &conn->pending, -1)) {
1304                 error("%s: sending NewConnection failed", ext->name);
1305                 dbus_message_unref(msg);
1306                 return false;
1307         }
1308
1309         dbus_message_unref(msg);
1310
1311         dbus_pending_call_set_notify(conn->pending, new_conn_reply, conn, NULL);
1312
1313         return true;
1314 }
1315
1316 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
1317 static int check_connection_psm(gconstpointer a, gconstpointer b)
1318 {
1319         const struct ext_io *conn = a;
1320         const int *psm = b;
1321         DBG("conn->psm %d, psm %d", conn->psm, *psm);
1322         return (conn->psm == *psm ? 0 : -1);
1323 }
1324 #endif
1325
1326 static void ext_connect(GIOChannel *io, GError *err, gpointer user_data)
1327 {
1328         struct ext_io *conn = user_data;
1329         struct ext_profile *ext = conn->ext;
1330         GError *io_err = NULL;
1331         char addr[18];
1332
1333         if (!bt_io_get(io, &io_err,
1334                                 BT_IO_OPT_DEST, addr,
1335                                 BT_IO_OPT_INVALID)) {
1336                 error("Unable to get connect data for %s: %s", ext->name,
1337                                                         io_err->message);
1338                 if (err) {
1339                         g_error_free(io_err);
1340                         io_err = NULL;
1341                 } else {
1342                         err = io_err;
1343                 }
1344                 goto drop;
1345         }
1346
1347         if (err != NULL) {
1348                 error("%s failed to connect to %s: %s", ext->name, addr,
1349                                                                 err->message);
1350                 goto drop;
1351         }
1352
1353         DBG("%s connected to %s", ext->name, addr);
1354
1355         if (conn->io_id == 0) {
1356                 GIOCondition cond = G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1357                 conn->io_id = g_io_add_watch(io, cond, ext_io_disconnected,
1358                                                                         conn);
1359         }
1360
1361 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
1362         if (g_strcmp0(ext->uuid, HID_UUID) == 0 && ext->local_connect == TRUE) {
1363                 GSList *l = NULL;
1364                 int psm = HID_DEVICE_CTRL_PSM;
1365                 ext->local_connect = FALSE;
1366                 l = g_slist_find_custom(ext->conns, &psm, check_connection_psm);
1367                 if (l == NULL) {
1368                         struct ext_io *conn1 = g_new0(struct ext_io, 1);
1369                         int error = 0;
1370                         ext->remote_psm = psm;
1371                         conn1->ext = ext;
1372                         conn1->psm = ext->remote_psm;
1373                         conn1->chan = ext->remote_chan;
1374                         error = connect_io(conn1, btd_adapter_get_address(conn->adapter),
1375                                                         device_get_address(conn->device));
1376                         DBG("error from connect_io %d", error);
1377                         conn1->adapter = btd_adapter_ref(conn->adapter);
1378                         conn1->device = btd_device_ref(conn->device);
1379                         conn1->service = btd_service_ref(conn->service);
1380                         ext->conns = g_slist_append(ext->conns, conn1);
1381                 } else {
1382                         DBG("Connection Already there");
1383                 }
1384         }
1385 #endif
1386
1387         if (conn->service && service_accept(conn->service) == 0) {
1388                 if (send_new_connection(ext, conn))
1389                         return;
1390         }
1391
1392 drop:
1393         if (conn->service)
1394                 btd_service_connecting_complete(conn->service,
1395                                                 err ? -err->code : -EIO);
1396
1397         if (io_err)
1398                 g_error_free(io_err);
1399
1400         ext->conns = g_slist_remove(ext->conns, conn);
1401         ext_io_destroy(conn);
1402 }
1403
1404 static void ext_auth(DBusError *err, void *user_data)
1405 {
1406         struct ext_io *conn = user_data;
1407         struct ext_profile *ext = conn->ext;
1408         GError *gerr = NULL;
1409         char addr[18];
1410
1411         conn->auth_id = 0;
1412
1413         bt_io_get(conn->io, &gerr, BT_IO_OPT_DEST, addr, BT_IO_OPT_INVALID);
1414         if (gerr != NULL) {
1415                 error("Unable to get connect data for %s: %s",
1416                                                 ext->name, gerr->message);
1417                 g_error_free(gerr);
1418                 goto drop;
1419         }
1420
1421         if (err && dbus_error_is_set(err)) {
1422                 error("%s rejected %s: %s", ext->name, addr, err->message);
1423                 goto drop;
1424         }
1425
1426         if (!bt_io_accept(conn->io, ext_connect, conn, NULL, &gerr)) {
1427                 error("bt_io_accept: %s", gerr->message);
1428                 g_error_free(gerr);
1429                 goto drop;
1430         }
1431
1432         DBG("%s authorized to connect to %s", addr, ext->name);
1433
1434         return;
1435
1436 drop:
1437         ext->conns = g_slist_remove(ext->conns, conn);
1438         ext_io_destroy(conn);
1439 }
1440
1441 static struct ext_io *create_conn(struct ext_io *server, GIOChannel *io,
1442                                                 bdaddr_t *src, bdaddr_t *dst)
1443 {
1444         struct btd_device *device;
1445         struct btd_service *service;
1446         struct ext_io *conn;
1447         GIOCondition cond;
1448         char addr[18];
1449
1450         device = btd_adapter_find_device(server->adapter, dst, BDADDR_BREDR);
1451         if (device == NULL) {
1452                 ba2str(dst, addr);
1453                 error("%s device %s not found", server->ext->name, addr);
1454                 return NULL;
1455         }
1456
1457         /* Do not add UUID if client role is not enabled */
1458         if (!server->ext->enable_client) {
1459                 service = NULL;
1460                 goto done;
1461         }
1462
1463         btd_device_add_uuid(device, server->ext->remote_uuid);
1464         service = btd_device_get_service(device, server->ext->remote_uuid);
1465         if (service == NULL) {
1466                 ba2str(dst, addr);
1467                 error("%s service not found for device %s", server->ext->name,
1468                                                                         addr);
1469                 return NULL;
1470         }
1471
1472 done:
1473         conn = g_new0(struct ext_io, 1);
1474         conn->io = g_io_channel_ref(io);
1475         conn->proto = server->proto;
1476         conn->ext = server->ext;
1477         conn->adapter = btd_adapter_ref(server->adapter);
1478         conn->device = btd_device_ref(device);
1479
1480         if (service)
1481                 conn->service = btd_service_ref(service);
1482
1483         cond = G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1484         conn->io_id = g_io_add_watch(io, cond, ext_io_disconnected, conn);
1485
1486         return conn;
1487 }
1488
1489 static void ext_confirm(GIOChannel *io, gpointer user_data)
1490 {
1491         struct ext_io *server = user_data;
1492         struct ext_profile *ext = server->ext;
1493         const char *uuid = ext->service ? ext->service : ext->uuid;
1494         struct ext_io *conn;
1495         GError *gerr = NULL;
1496         bdaddr_t src, dst;
1497         char addr[18];
1498
1499         bt_io_get(io, &gerr,
1500                         BT_IO_OPT_SOURCE_BDADDR, &src,
1501                         BT_IO_OPT_DEST_BDADDR, &dst,
1502                         BT_IO_OPT_DEST, addr,
1503                         BT_IO_OPT_INVALID);
1504         if (gerr != NULL) {
1505                 error("%s failed to get connect data: %s", ext->name,
1506                                                                 gerr->message);
1507                 g_error_free(gerr);
1508                 return;
1509         }
1510
1511         DBG("incoming connect from %s", addr);
1512
1513         conn = create_conn(server, io, &src, &dst);
1514         if (conn == NULL)
1515                 return;
1516
1517         conn->auth_id = btd_request_authorization(&src, &dst, uuid, ext_auth,
1518                                                                         conn);
1519         if (conn->auth_id == 0) {
1520                 error("%s authorization failure", ext->name);
1521                 ext_io_destroy(conn);
1522                 return;
1523         }
1524
1525         ext->conns = g_slist_append(ext->conns, conn);
1526
1527         DBG("%s authorizing connection from %s", ext->name, addr);
1528 }
1529
1530 static void ext_direct_connect(GIOChannel *io, GError *err, gpointer user_data)
1531 {
1532         struct ext_io *server = user_data;
1533         struct ext_profile *ext = server->ext;
1534         GError *gerr = NULL;
1535         struct ext_io *conn;
1536         bdaddr_t src, dst;
1537
1538         bt_io_get(io, &gerr,
1539                         BT_IO_OPT_SOURCE_BDADDR, &src,
1540                         BT_IO_OPT_DEST_BDADDR, &dst,
1541                         BT_IO_OPT_INVALID);
1542         if (gerr != NULL) {
1543                 error("%s failed to get connect data: %s", ext->name,
1544                                                                 gerr->message);
1545                 g_error_free(gerr);
1546                 return;
1547         }
1548
1549         conn = create_conn(server, io, &src, &dst);
1550         if (conn == NULL)
1551                 return;
1552
1553         ext->conns = g_slist_append(ext->conns, conn);
1554
1555         ext_connect(io, err, conn);
1556 }
1557
1558 static uint32_t ext_register_record(struct ext_profile *ext,
1559                                                         struct ext_io *l2cap,
1560                                                         struct ext_io *rfcomm,
1561                                                         struct btd_adapter *a)
1562 {
1563         sdp_record_t *rec;
1564         char *dyn_record = NULL;
1565         const char *record = ext->record;
1566
1567         if (!record && ext->get_record) {
1568                 dyn_record = ext->get_record(ext, l2cap, rfcomm);
1569                 record = dyn_record;
1570         }
1571
1572         if (!record)
1573                 return 0;
1574
1575         rec = sdp_xml_parse_record(record, strlen(record));
1576
1577         g_free(dyn_record);
1578
1579         if (!rec) {
1580                 error("Unable to parse record for %s", ext->name);
1581                 return 0;
1582         }
1583
1584         if (adapter_service_add(a, rec) < 0) {
1585                 error("Failed to register service record");
1586                 sdp_record_free(rec);
1587                 return 0;
1588         }
1589
1590         return rec->handle;
1591 }
1592
1593 static uint32_t ext_start_servers(struct ext_profile *ext,
1594                                                 struct btd_adapter *adapter)
1595 {
1596         struct ext_io *l2cap = NULL;
1597 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
1598         struct ext_io *l2cap1 = NULL;
1599 #endif
1600         struct ext_io *rfcomm = NULL;
1601         BtIOConfirm confirm;
1602         BtIOConnect connect;
1603         GError *err = NULL;
1604         GIOChannel *io;
1605 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
1606         GIOChannel *io1;
1607 #endif
1608
1609         if (ext->authorize) {
1610                 confirm = ext_confirm;
1611                 connect = NULL;
1612         } else {
1613                 confirm = NULL;
1614                 connect = ext_direct_connect;
1615         }
1616
1617         if (ext->local_psm) {
1618                 uint16_t psm;
1619
1620                 if (ext->local_psm > 0)
1621                         psm = ext->local_psm;
1622                 else
1623                         psm = 0;
1624
1625                 l2cap = g_new0(struct ext_io, 1);
1626                 l2cap->ext = ext;
1627
1628                 io = bt_io_listen(connect, confirm, l2cap, NULL, &err,
1629                                         BT_IO_OPT_SOURCE_BDADDR,
1630                                         btd_adapter_get_address(adapter),
1631                                         BT_IO_OPT_MODE, ext->mode,
1632                                         BT_IO_OPT_PSM, psm,
1633                                         BT_IO_OPT_SEC_LEVEL, ext->sec_level,
1634                                         BT_IO_OPT_INVALID);
1635                 if (err != NULL) {
1636                         error("L2CAP server failed for %s: %s",
1637                                                 ext->name, err->message);
1638                         g_free(l2cap);
1639                         l2cap = NULL;
1640                         g_clear_error(&err);
1641                         goto failed;
1642                 } else {
1643                         if (psm == 0)
1644                                 bt_io_get(io, NULL, BT_IO_OPT_PSM, &psm,
1645                                                         BT_IO_OPT_INVALID);
1646                         l2cap->io = io;
1647                         l2cap->proto = BTPROTO_L2CAP;
1648                         l2cap->psm = psm;
1649                         l2cap->adapter = btd_adapter_ref(adapter);
1650                         ext->servers = g_slist_append(ext->servers, l2cap);
1651                         DBG("%s listening on PSM %u", ext->name, psm);
1652                 }
1653 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
1654                 if (g_strcmp0(ext->uuid , HID_UUID) == 0) {
1655                         psm = HID_DEVICE_CTRL_PSM;
1656                         l2cap1 = g_new0(struct ext_io, 1);
1657                         l2cap1->ext = ext;
1658                         io1 = bt_io_listen(connect, confirm, l2cap, NULL, &err,
1659                                                 BT_IO_OPT_SOURCE_BDADDR,
1660                                                 btd_adapter_get_address(adapter),
1661                                                 BT_IO_OPT_MODE, ext->mode,
1662                                                 BT_IO_OPT_PSM, psm,
1663                                                 BT_IO_OPT_SEC_LEVEL, ext->sec_level,
1664                                                 BT_IO_OPT_INVALID);
1665                         l2cap1->io = io1;
1666                         l2cap1->proto = BTPROTO_L2CAP;
1667                         l2cap1->psm = psm;
1668                         l2cap1->adapter = btd_adapter_ref(adapter);
1669                         ext->servers = g_slist_append(ext->servers, l2cap1);
1670                         DBG("%s listening on PSM %u", ext->name, psm);
1671                 }
1672 #endif
1673         }
1674
1675         if (ext->local_chan) {
1676                 uint8_t chan;
1677
1678                 if (ext->local_chan > 0)
1679                         chan = ext->local_chan;
1680                 else
1681                         chan = 0;
1682
1683                 rfcomm = g_new0(struct ext_io, 1);
1684                 rfcomm->ext = ext;
1685
1686                 io = bt_io_listen(connect, confirm, rfcomm, NULL, &err,
1687                                         BT_IO_OPT_SOURCE_BDADDR,
1688                                         btd_adapter_get_address(adapter),
1689                                         BT_IO_OPT_CHANNEL, chan,
1690                                         BT_IO_OPT_SEC_LEVEL, ext->sec_level,
1691                                         BT_IO_OPT_INVALID);
1692                 if (err != NULL) {
1693                         error("RFCOMM server failed for %s: %s",
1694                                                 ext->name, err->message);
1695                         g_free(rfcomm);
1696                         g_clear_error(&err);
1697                         goto failed;
1698                 } else {
1699                         if (chan == 0)
1700                                 bt_io_get(io, NULL, BT_IO_OPT_CHANNEL, &chan,
1701                                                         BT_IO_OPT_INVALID);
1702                         rfcomm->io = io;
1703                         rfcomm->proto = BTPROTO_RFCOMM;
1704                         rfcomm->chan = chan;
1705                         rfcomm->adapter = btd_adapter_ref(adapter);
1706                         ext->servers = g_slist_append(ext->servers, rfcomm);
1707                         DBG("%s listening on chan %u", ext->name, chan);
1708                 }
1709         }
1710
1711         return ext_register_record(ext, l2cap, rfcomm, adapter);
1712
1713 failed:
1714         if (l2cap) {
1715                 ext->servers = g_slist_remove(ext->servers, l2cap);
1716                 ext_io_destroy(l2cap);
1717         }
1718
1719         return 0;
1720 }
1721
1722 static struct ext_profile *find_ext(struct btd_profile *p)
1723 {
1724         GSList *l;
1725
1726         l = g_slist_find(ext_profiles, p);
1727         if (!l)
1728                 return NULL;
1729
1730         return l->data;
1731 }
1732
1733 #ifdef __TIZEN_PATCH__
1734 gboolean ext_profile_is_registered_as_client_role(struct btd_profile *p)
1735 {
1736         struct ext_profile *ext = find_ext(p);
1737         if (ext && ext->role) {
1738                 if(strcasecmp(ext->role, "client") == 0) {
1739                         return TRUE;
1740                 } else {
1741                         return FALSE;
1742                 }
1743         }
1744         return FALSE;
1745 }
1746 #endif
1747
1748 static int ext_adapter_probe(struct btd_profile *p,
1749                                                 struct btd_adapter *adapter)
1750 {
1751         struct ext_profile *ext;
1752         struct ext_record *rec;
1753         uint32_t handle;
1754
1755         ext = find_ext(p);
1756         if (!ext)
1757                 return -ENOENT;
1758
1759         DBG("\"%s\" probed", ext->name);
1760
1761         handle = ext_start_servers(ext, adapter);
1762         if (!handle)
1763                 return 0;
1764
1765         rec = g_new0(struct ext_record, 1);
1766         rec->adapter = btd_adapter_ref(adapter);
1767         rec->handle = handle;
1768
1769         ext->records = g_slist_append(ext->records, rec);
1770
1771         return 0;
1772 }
1773
1774 static void ext_remove_records(struct ext_profile *ext,
1775                                                 struct btd_adapter *adapter)
1776 {
1777         GSList *l, *next;
1778
1779         for (l = ext->records; l != NULL; l = next) {
1780                 struct ext_record *r = l->data;
1781
1782                 next = g_slist_next(l);
1783
1784                 if (adapter && r->adapter != adapter)
1785                         continue;
1786
1787                 ext->records = g_slist_remove(ext->records, r);
1788
1789                 adapter_service_remove(adapter, r->handle);
1790                 btd_adapter_unref(r->adapter);
1791                 g_free(r);
1792         }
1793 }
1794
1795 static void ext_adapter_remove(struct btd_profile *p,
1796                                                 struct btd_adapter *adapter)
1797 {
1798         struct ext_profile *ext;
1799         GSList *l, *next;
1800
1801         ext = find_ext(p);
1802         if (!ext)
1803                 return;
1804
1805         DBG("\"%s\" removed", ext->name);
1806
1807         ext_remove_records(ext, adapter);
1808
1809         for (l = ext->servers; l != NULL; l = next) {
1810                 struct ext_io *server = l->data;
1811
1812                 next = g_slist_next(l);
1813
1814                 if (server->adapter != adapter)
1815                         continue;
1816
1817                 ext->servers = g_slist_remove(ext->servers, server);
1818                 ext_io_destroy(server);
1819         }
1820 }
1821
1822 static int ext_device_probe(struct btd_service *service)
1823 {
1824         struct btd_profile *p = btd_service_get_profile(service);
1825         struct ext_profile *ext;
1826
1827         ext = find_ext(p);
1828         if (!ext)
1829                 return -ENOENT;
1830
1831         DBG("%s probed with UUID %s", ext->name, p->remote_uuid);
1832
1833         return 0;
1834 }
1835
1836 static struct ext_io *find_connection(struct ext_profile *ext,
1837                                                         struct btd_device *dev)
1838 {
1839         GSList *l;
1840
1841         for (l = ext->conns; l != NULL; l = g_slist_next(l)) {
1842                 struct ext_io *conn = l->data;
1843
1844                 if (conn->device == dev)
1845                         return conn;
1846         }
1847
1848         return NULL;
1849 }
1850
1851 static void ext_device_remove(struct btd_service *service)
1852 {
1853         struct btd_profile *p = btd_service_get_profile(service);
1854         struct btd_device *dev = btd_service_get_device(service);
1855         struct ext_profile *ext;
1856         struct ext_io *conn;
1857
1858         ext = find_ext(p);
1859         if (!ext)
1860                 return;
1861
1862         DBG("%s", ext->name);
1863
1864         conn = find_connection(ext, dev);
1865         if (conn) {
1866                 ext->conns = g_slist_remove(ext->conns, conn);
1867                 ext_io_destroy(conn);
1868         }
1869 }
1870
1871 static int connect_io(struct ext_io *conn, const bdaddr_t *src,
1872                                                         const bdaddr_t *dst)
1873 {
1874         struct ext_profile *ext = conn->ext;
1875         GError *gerr = NULL;
1876         GIOChannel *io;
1877
1878         if (conn->psm) {
1879                 conn->proto = BTPROTO_L2CAP;
1880                 io = bt_io_connect(ext_connect, conn, NULL, &gerr,
1881                                         BT_IO_OPT_SOURCE_BDADDR, src,
1882                                         BT_IO_OPT_DEST_BDADDR, dst,
1883                                         BT_IO_OPT_SEC_LEVEL, ext->sec_level,
1884                                         BT_IO_OPT_PSM, conn->psm,
1885                                         BT_IO_OPT_INVALID);
1886         } else {
1887                 conn->proto = BTPROTO_RFCOMM;
1888                 io = bt_io_connect(ext_connect, conn, NULL, &gerr,
1889                                         BT_IO_OPT_SOURCE_BDADDR, src,
1890                                         BT_IO_OPT_DEST_BDADDR, dst,
1891                                         BT_IO_OPT_SEC_LEVEL, ext->sec_level,
1892                                         BT_IO_OPT_CHANNEL, conn->chan,
1893                                         BT_IO_OPT_INVALID);
1894         }
1895
1896         if (gerr != NULL) {
1897                 error("Unable to connect %s: %s", ext->name, gerr->message);
1898                 g_error_free(gerr);
1899                 return -EIO;
1900         }
1901
1902         conn->io = io;
1903
1904         return 0;
1905 }
1906
1907 static uint16_t get_goep_l2cap_psm(sdp_record_t *rec)
1908 {
1909         sdp_data_t *data;
1910
1911         data = sdp_data_get(rec, SDP_ATTR_GOEP_L2CAP_PSM);
1912         if (!data)
1913                 return 0;
1914
1915         if (data->dtd != SDP_UINT16)
1916                 return 0;
1917
1918         /* PSM must be odd and lsb of upper byte must be 0 */
1919         if ((data->val.uint16 & 0x0101) != 0x0001)
1920                 return 0;
1921
1922         return data->val.uint16;
1923 }
1924
1925 static void record_cb(sdp_list_t *recs, int err, gpointer user_data)
1926 {
1927         struct ext_io *conn = user_data;
1928         struct ext_profile *ext = conn->ext;
1929         sdp_list_t *r;
1930
1931         conn->resolving = false;
1932
1933         if (err < 0) {
1934                 error("Unable to get %s SDP record: %s", ext->name,
1935                                                         strerror(-err));
1936                 goto failed;
1937         }
1938
1939         if (!recs || !recs->data) {
1940                 error("No SDP records found for %s", ext->name);
1941                 err = -ENOTSUP;
1942                 goto failed;
1943         }
1944
1945         for (r = recs; r != NULL; r = r->next) {
1946                 sdp_record_t *rec = r->data;
1947                 sdp_list_t *protos;
1948                 int port;
1949 #ifdef __TIZEN_PATCH__
1950                 char *profile_uuid;
1951                 sdp_list_t *svcclass = NULL;
1952
1953                 if (sdp_get_service_classes(rec, &svcclass) < 0)
1954                         continue;
1955
1956                 /* Check for empty service classes list */
1957                 if (svcclass == NULL) {
1958                         DBG("Skipping record with no service classes");
1959                         continue;
1960                 }
1961
1962                 /* Extract the first element and skip the remainning */
1963                 profile_uuid = bt_uuid2string(svcclass->data);
1964                 if (!profile_uuid) {
1965                         sdp_list_free(svcclass, free);
1966                         continue;
1967                 }
1968
1969                 sdp_list_free(svcclass, free);
1970
1971                 DBG("profile uuid %s port uuid %s", profile_uuid, ext->remote_uuid);
1972
1973                 if (g_ascii_strncasecmp(profile_uuid, ext->remote_uuid,
1974                                                 strlen(profile_uuid)) != 0) {
1975                         free(profile_uuid);
1976                         continue;
1977                 }
1978
1979                 free(profile_uuid);
1980 #endif
1981
1982                 if (sdp_get_access_protos(rec, &protos) < 0) {
1983                         error("Unable to get proto list from %s record",
1984                                                                 ext->name);
1985                         err = -ENOTSUP;
1986                         goto failed;
1987                 }
1988
1989                 port = sdp_get_proto_port(protos, L2CAP_UUID);
1990                 if (port > 0)
1991                         conn->psm = port;
1992
1993                 port = sdp_get_proto_port(protos, RFCOMM_UUID);
1994                 if (port > 0)
1995                         conn->chan = port;
1996
1997                 if (conn->psm == 0 && sdp_get_proto_desc(protos, OBEX_UUID))
1998                         conn->psm = get_goep_l2cap_psm(rec);
1999
2000                 conn->features = get_supported_features(rec);
2001                 conn->version = get_profile_version(rec);
2002
2003                 sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free,
2004                                                                         NULL);
2005                 sdp_list_free(protos, NULL);
2006
2007                 if (conn->chan || conn->psm)
2008                         break;
2009         }
2010
2011         if (!conn->chan && !conn->psm) {
2012                 error("Failed to find L2CAP PSM or RFCOMM channel for %s",
2013                                                                 ext->name);
2014                 err = -ENOTSUP;
2015                 goto failed;
2016         }
2017
2018         err = connect_io(conn, btd_adapter_get_address(conn->adapter),
2019                                         device_get_address(conn->device));
2020         if (err < 0) {
2021                 error("Connecting %s failed: %s", ext->name, strerror(-err));
2022                 goto failed;
2023         }
2024
2025         return;
2026
2027 failed:
2028         if (conn->service)
2029                 btd_service_connecting_complete(conn->service, err);
2030
2031         ext->conns = g_slist_remove(ext->conns, conn);
2032         ext_io_destroy(conn);
2033 }
2034
2035 static int resolve_service(struct ext_io *conn, const bdaddr_t *src,
2036                                                         const bdaddr_t *dst)
2037 {
2038         struct ext_profile *ext = conn->ext;
2039         uuid_t uuid;
2040         int err;
2041
2042         bt_string2uuid(&uuid, ext->remote_uuid);
2043         sdp_uuid128_to_uuid(&uuid);
2044
2045         err = bt_search_service(src, dst, &uuid, record_cb, conn, NULL, 0);
2046         if (err == 0)
2047                 conn->resolving = true;
2048
2049         return err;
2050 }
2051
2052 static int ext_connect_dev(struct btd_service *service)
2053 {
2054         struct btd_device *dev = btd_service_get_device(service);
2055         struct btd_profile *profile = btd_service_get_profile(service);
2056         struct btd_adapter *adapter;
2057         struct ext_io *conn;
2058         struct ext_profile *ext;
2059         int err;
2060
2061         ext = find_ext(profile);
2062         if (!ext)
2063                 return -ENOENT;
2064
2065         conn = find_connection(ext, dev);
2066         if (conn)
2067                 return -EALREADY;
2068
2069         adapter = device_get_adapter(dev);
2070
2071         conn = g_new0(struct ext_io, 1);
2072         conn->ext = ext;
2073 #ifndef TIZEN_BT_HID_DEVICE_ENABLE
2074         if (ext->remote_psm || ext->remote_chan) {
2075                 conn->psm = ext->remote_psm;
2076                 conn->chan = ext->remote_chan;
2077                 err = connect_io(conn, btd_adapter_get_address(adapter),
2078                                                 device_get_address(dev));
2079         } else {
2080                 err = resolve_service(conn, btd_adapter_get_address(adapter),
2081                                                 device_get_address(dev));
2082         }
2083
2084         if (err < 0)
2085                 goto failed;
2086 #else
2087         if (g_strcmp0(ext->uuid, HID_UUID) == 0) {
2088                 ext->local_connect = TRUE;
2089                 ext->remote_psm = HID_DEVICE_INTR_PSM;
2090                 conn->psm = ext->remote_psm;
2091                 conn->chan = ext->remote_chan;
2092                 err = connect_io(conn, btd_adapter_get_address(adapter),
2093                                                 device_get_address(dev));
2094         } else {
2095                 if (ext->remote_psm || ext->remote_chan) {
2096                         conn->psm = ext->remote_psm;
2097                         conn->chan = ext->remote_chan;
2098                         err = connect_io(conn, btd_adapter_get_address(adapter),
2099                                                         device_get_address(dev));
2100                 } else {
2101                         err = resolve_service(conn, btd_adapter_get_address(adapter),
2102                                                         device_get_address(dev));
2103                 }
2104         }
2105         if (err < 0)
2106                 goto failed;
2107 #endif
2108         conn->adapter = btd_adapter_ref(adapter);
2109         conn->device = btd_device_ref(dev);
2110         conn->service = btd_service_ref(service);
2111
2112         ext->conns = g_slist_append(ext->conns, conn);
2113
2114         return 0;
2115
2116 failed:
2117         g_free(conn);
2118         return err;
2119 }
2120
2121 static int send_disconn_req(struct ext_profile *ext, struct ext_io *conn)
2122 {
2123         DBusMessage *msg;
2124         const char *path;
2125
2126         msg = dbus_message_new_method_call(ext->owner, ext->path,
2127                                                 "org.bluez.Profile1",
2128                                                 "RequestDisconnection");
2129         if (!msg) {
2130                 error("Unable to create RequestDisconnection call for %s",
2131                                                                 ext->name);
2132                 return -ENOMEM;
2133         }
2134
2135         path = device_get_path(conn->device);
2136         dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &path,
2137                                                         DBUS_TYPE_INVALID);
2138
2139         if (!g_dbus_send_message_with_reply(btd_get_dbus_connection(),
2140                                                 msg, &conn->pending, -1)) {
2141                 error("%s: sending RequestDisconnection failed", ext->name);
2142                 dbus_message_unref(msg);
2143                 return -EIO;
2144         }
2145
2146         dbus_message_unref(msg);
2147
2148         dbus_pending_call_set_notify(conn->pending, disconn_reply, conn, NULL);
2149
2150         return 0;
2151 }
2152
2153 static int ext_disconnect_dev(struct btd_service *service)
2154 {
2155         struct btd_device *dev = btd_service_get_device(service);
2156         struct btd_profile *profile = btd_service_get_profile(service);
2157         struct ext_profile *ext;
2158         struct ext_io *conn;
2159         int err;
2160
2161         ext = find_ext(profile);
2162         if (!ext)
2163                 return -ENOENT;
2164
2165 #ifndef TIZEN_BT_HID_DEVICE_ENABLE
2166         conn = find_connection(ext, dev);
2167         if (!conn || !conn->connected)
2168                 return -ENOTCONN;
2169
2170         if (conn->pending)
2171                 return -EBUSY;
2172
2173         err = send_disconn_req(ext, conn);
2174         if (err < 0)
2175                 return err;
2176 #else
2177         if (g_strcmp0(ext->uuid, HID_UUID) != 0) {
2178                 conn = find_connection(ext, dev);
2179                 if (!conn || !conn->connected)
2180                         return -ENOTCONN;
2181
2182                 if (conn->pending)
2183                         return -EBUSY;
2184
2185                 err = send_disconn_req(ext, conn);
2186                 if (err < 0)
2187                         return err;
2188         } else {
2189                 GSList *l;
2190                 /* As HID will be using two psm we need to send disconnect
2191                   * request for both the psms */
2192                 for (l = ext->conns; l != NULL; l = g_slist_next(l)) {
2193                         struct ext_io *conn1 = l->data;
2194                         if (conn1->device == dev) {
2195                                 err = send_disconn_req(ext, conn1);
2196                         }
2197                 }
2198         }
2199 #endif
2200         return 0;
2201 }
2202
2203 static char *get_hfp_hf_record(struct ext_profile *ext, struct ext_io *l2cap,
2204                                                         struct ext_io *rfcomm)
2205 {
2206         return g_strdup_printf(HFP_HF_RECORD, rfcomm->chan, ext->version,
2207                                                 ext->name, ext->features);
2208 }
2209
2210 static char *get_hfp_ag_record(struct ext_profile *ext, struct ext_io *l2cap,
2211                                                         struct ext_io *rfcomm)
2212 {
2213         return g_strdup_printf(HFP_AG_RECORD, rfcomm->chan, ext->version,
2214                                                 ext->name, ext->features);
2215 }
2216
2217 static char *get_hsp_ag_record(struct ext_profile *ext, struct ext_io *l2cap,
2218                                                         struct ext_io *rfcomm)
2219 {
2220         return g_strdup_printf(HSP_AG_RECORD, rfcomm->chan, ext->version,
2221                                                 ext->name);
2222 }
2223
2224 static char *get_spp_record(struct ext_profile *ext, struct ext_io *l2cap,
2225                                                         struct ext_io *rfcomm)
2226 {
2227         char *svc, *rec;
2228 #ifdef __TIZEN_PATCH__
2229         char *lan_seq;
2230         uint16_t code_ISO639 = (0x65 << 8) | 0x6e;
2231         uint16_t encoding = 106;
2232         uint16_t base_offset = SDP_PRIMARY_LANG_BASE;
2233 #endif
2234
2235         if (ext->service)
2236                 svc = g_strdup_printf("<uuid value=\"%s\" />", ext->service);
2237         else
2238                 svc = g_strdup("");
2239
2240 #ifdef __TIZEN_PATCH__
2241         lan_seq = g_strdup_printf(LANG_SEQ, code_ISO639, encoding,
2242                                                         base_offset);
2243         rec = g_strdup_printf(SPP_RECORD, svc, rfcomm->chan, lan_seq, ext->version,
2244                                                                 ext->name);
2245         g_free(lan_seq);
2246 #else
2247         rec = g_strdup_printf(SPP_RECORD, svc, rfcomm->chan, ext->version,
2248                                                                 ext->name);
2249 #endif
2250         g_free(svc);
2251         return rec;
2252 }
2253
2254 static char *get_dun_record(struct ext_profile *ext, struct ext_io *l2cap,
2255                                                         struct ext_io *rfcomm)
2256 {
2257         return g_strdup_printf(DUN_RECORD, rfcomm->chan, ext->version,
2258                                                                 ext->name);
2259 }
2260
2261 static char *get_pce_record(struct ext_profile *ext, struct ext_io *l2cap,
2262                                                         struct ext_io *rfcomm)
2263 {
2264         return g_strdup_printf(PCE_RECORD, ext->version, ext->name);
2265 }
2266
2267 static char *get_pse_record(struct ext_profile *ext, struct ext_io *l2cap,
2268                                                         struct ext_io *rfcomm)
2269 {
2270         uint16_t psm = 0;
2271         uint8_t chan = 0;
2272
2273         if (l2cap)
2274                 psm = l2cap->psm;
2275         if (rfcomm)
2276                 chan = rfcomm->chan;
2277
2278         return g_strdup_printf(PSE_RECORD, chan, ext->version, ext->name, psm);
2279 }
2280
2281 static char *get_mas_record(struct ext_profile *ext, struct ext_io *l2cap,
2282                                                         struct ext_io *rfcomm)
2283 {
2284         uint16_t psm = 0;
2285         uint8_t chan = 0;
2286
2287         if (l2cap)
2288                 psm = l2cap->psm;
2289         if (rfcomm)
2290                 chan = rfcomm->chan;
2291
2292         return g_strdup_printf(MAS_RECORD, chan, ext->version, ext->name, psm);
2293 }
2294
2295 static char *get_mns_record(struct ext_profile *ext, struct ext_io *l2cap,
2296                                                         struct ext_io *rfcomm)
2297 {
2298         uint16_t psm = 0;
2299         uint8_t chan = 0;
2300
2301         if (l2cap)
2302                 psm = l2cap->psm;
2303         if (rfcomm)
2304                 chan = rfcomm->chan;
2305
2306         return g_strdup_printf(MNS_RECORD, chan, ext->version, ext->name, psm);
2307 }
2308
2309 static char *get_sync_record(struct ext_profile *ext, struct ext_io *l2cap,
2310                                                         struct ext_io *rfcomm)
2311 {
2312         return g_strdup_printf(SYNC_RECORD, rfcomm->chan, ext->version,
2313                                                                 ext->name);
2314 }
2315
2316 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
2317 static char *get_hid_device_record(struct ext_profile *ext, struct ext_io *l2cap,
2318                                                         struct ext_io *rfcomm)
2319 {
2320         return g_strdup(HID_DEVICE_RECORD);
2321 }
2322 #endif
2323
2324 static char *get_opp_record(struct ext_profile *ext, struct ext_io *l2cap,
2325                                                         struct ext_io *rfcomm)
2326 {
2327 #ifndef __TIZEN_PATCH__
2328         uint16_t psm = 0;
2329 #endif
2330         uint8_t chan = 0;
2331
2332 #ifndef __TIZEN_PATCH__
2333         if (l2cap)
2334                 psm = l2cap->psm;
2335 #endif
2336         if (rfcomm)
2337                 chan = rfcomm->chan;
2338
2339 #ifdef __TIZEN_PATCH__
2340         return g_strdup_printf(OPP_RECORD, chan, ext->version, ext->name);
2341 #else
2342         return g_strdup_printf(OPP_RECORD, chan, ext->version, psm, ext->name);
2343 #endif
2344 }
2345
2346 static char *get_ftp_record(struct ext_profile *ext, struct ext_io *l2cap,
2347                                                         struct ext_io *rfcomm)
2348 {
2349         uint16_t psm = 0;
2350         uint8_t chan = 0;
2351
2352         if (l2cap)
2353                 psm = l2cap->psm;
2354         if (rfcomm)
2355                 chan = rfcomm->chan;
2356
2357         return g_strdup_printf(FTP_RECORD, chan, ext->version, psm, ext->name);
2358 }
2359
2360 #define RFCOMM_SEQ      "<sequence>                             \
2361                                 <uuid value=\"0x0003\" />       \
2362                                 <uint8 value=\"0x%02x\" />      \
2363                         </sequence>"
2364
2365 #define VERSION_ATTR                                                    \
2366                 "<attribute id=\"0x0009\">                              \
2367                         <sequence>                                      \
2368                                 <sequence>                              \
2369                                         <uuid value=\"%s\" />           \
2370                                         <uint16 value=\"0x%04x\" />     \
2371                                 </sequence>                             \
2372                         </sequence>                                     \
2373                 </attribute>"
2374
2375 static char *get_generic_record(struct ext_profile *ext, struct ext_io *l2cap,
2376                                                         struct ext_io *rfcomm)
2377 {
2378         char uuid_str[MAX_LEN_UUID_STR], svc_str[MAX_LEN_UUID_STR], psm[30];
2379         char *rf_seq, *ver_attr, *rec;
2380         uuid_t uuid;
2381
2382         bt_string2uuid(&uuid, ext->uuid);
2383         sdp_uuid2strn(&uuid, uuid_str, sizeof(uuid_str));
2384
2385         if (ext->service) {
2386                 bt_string2uuid(&uuid, ext->service);
2387                 sdp_uuid2strn(&uuid, svc_str, sizeof(svc_str));
2388         } else {
2389                 strncpy(svc_str, uuid_str, sizeof(svc_str));
2390         }
2391
2392         if (l2cap)
2393                 snprintf(psm, sizeof(psm), "<uint16 value=\"0x%04x\" />",
2394                                                                 l2cap->psm);
2395         else
2396                 psm[0] = '\0';
2397
2398         if (rfcomm)
2399                 rf_seq = g_strdup_printf(RFCOMM_SEQ, rfcomm->chan);
2400         else
2401                 rf_seq = g_strdup("");
2402
2403         if (ext->version)
2404                 ver_attr = g_strdup_printf(VERSION_ATTR, uuid_str,
2405                                                                 ext->version);
2406         else
2407                 ver_attr = g_strdup("");
2408
2409         rec = g_strdup_printf(GENERIC_RECORD, svc_str, psm, rf_seq, ver_attr,
2410                                                                 ext->name);
2411
2412         g_free(rf_seq);
2413         g_free(ver_attr);
2414
2415         return rec;
2416 }
2417
2418 static struct default_settings {
2419         const char      *uuid;
2420         const char      *name;
2421         int             priority;
2422         const char      *remote_uuid;
2423         int             channel;
2424         int             psm;
2425         BtIOMode        mode;
2426         BtIOSecLevel    sec_level;
2427         bool            authorize;
2428         bool            auto_connect;
2429         char *          (*get_record)(struct ext_profile *ext,
2430                                         struct ext_io *l2cap,
2431                                         struct ext_io *rfcomm);
2432         uint16_t        version;
2433         uint16_t        features;
2434 } defaults[] = {
2435         {
2436                 .uuid           = SPP_UUID,
2437                 .name           = "Serial Port",
2438                 .channel        = SPP_DEFAULT_CHANNEL,
2439                 .authorize      = true,
2440                 .get_record     = get_spp_record,
2441                 .version        = 0x0102,
2442         }, {
2443                 .uuid           = DUN_GW_UUID,
2444                 .name           = "Dial-Up Networking",
2445                 .channel        = DUN_DEFAULT_CHANNEL,
2446                 .authorize      = true,
2447                 .get_record     = get_dun_record,
2448                 .version        = 0x0102,
2449         }, {
2450                 .uuid           = HFP_HS_UUID,
2451                 .name           = "Hands-Free unit",
2452                 .priority       = BTD_PROFILE_PRIORITY_HIGH,
2453                 .remote_uuid    = HFP_AG_UUID,
2454                 .channel        = HFP_HF_DEFAULT_CHANNEL,
2455                 .authorize      = true,
2456                 .auto_connect   = true,
2457                 .get_record     = get_hfp_hf_record,
2458                 .version        = 0x0105,
2459         }, {
2460                 .uuid           = HFP_AG_UUID,
2461                 .name           = "Hands-Free Voice gateway",
2462                 .priority       = BTD_PROFILE_PRIORITY_HIGH,
2463                 .remote_uuid    = HFP_HS_UUID,
2464                 .channel        = HFP_AG_DEFAULT_CHANNEL,
2465                 .authorize      = true,
2466                 .auto_connect   = true,
2467                 .get_record     = get_hfp_ag_record,
2468                 .version        = 0x0105,
2469         }, {
2470                 .uuid           = HSP_AG_UUID,
2471                 .name           = "Headset Voice gateway",
2472                 .priority       = BTD_PROFILE_PRIORITY_HIGH,
2473                 .remote_uuid    = HSP_HS_UUID,
2474                 .channel        = HSP_AG_DEFAULT_CHANNEL,
2475                 .authorize      = true,
2476                 .auto_connect   = true,
2477                 .get_record     = get_hsp_ag_record,
2478                 .version        = 0x0102,
2479         }, {
2480                 .uuid           = OBEX_OPP_UUID,
2481                 .name           = "Object Push",
2482                 .channel        = OPP_DEFAULT_CHANNEL,
2483                 .psm            = BTD_PROFILE_PSM_AUTO,
2484                 .mode           = BT_IO_MODE_ERTM,
2485                 .sec_level      = BT_IO_SEC_LOW,
2486 #ifdef __TIZEN_PATCH__
2487                 .authorize      = true,
2488 #else
2489                 .authorize      = false,
2490 #endif
2491                 .get_record     = get_opp_record,
2492 #ifdef __TIZEN_PATCH__
2493                 .version    = 0x0100,
2494 #else
2495                 .version    = 0x0102,
2496 #endif
2497         }, {
2498                 .uuid           = OBEX_FTP_UUID,
2499                 .name           = "File Transfer",
2500                 .channel        = FTP_DEFAULT_CHANNEL,
2501                 .psm            = BTD_PROFILE_PSM_AUTO,
2502                 .mode           = BT_IO_MODE_ERTM,
2503                 .authorize      = true,
2504                 .get_record     = get_ftp_record,
2505                 .version        = 0x0102,
2506         }, {
2507                 .uuid           = OBEX_SYNC_UUID,
2508                 .name           = "Synchronization",
2509                 .channel        = SYNC_DEFAULT_CHANNEL,
2510                 .authorize      = true,
2511                 .get_record     = get_sync_record,
2512                 .version        = 0x0100,
2513         }, {
2514                 .uuid           = OBEX_PSE_UUID,
2515                 .name           = "Phone Book Access",
2516                 .channel        = PBAP_DEFAULT_CHANNEL,
2517                 .psm            = BTD_PROFILE_PSM_AUTO,
2518                 .mode           = BT_IO_MODE_ERTM,
2519                 .authorize      = true,
2520                 .get_record     = get_pse_record,
2521                 .version        = 0x0101,
2522         }, {
2523                 .uuid           = OBEX_PCE_UUID,
2524                 .name           = "Phone Book Access Client",
2525                 .remote_uuid    = OBEX_PSE_UUID,
2526                 .authorize      = true,
2527                 .get_record     = get_pce_record,
2528                 .version        = 0x0102,
2529         }, {
2530                 .uuid           = OBEX_MAS_UUID,
2531                 .name           = "Message Access",
2532                 .channel        = MAS_DEFAULT_CHANNEL,
2533                 .psm            = BTD_PROFILE_PSM_AUTO,
2534                 .mode           = BT_IO_MODE_ERTM,
2535                 .authorize      = true,
2536                 .get_record     = get_mas_record,
2537                 .version        = 0x0100
2538         }, {
2539                 .uuid           = OBEX_MNS_UUID,
2540                 .name           = "Message Notification",
2541                 .channel        = MNS_DEFAULT_CHANNEL,
2542                 .psm            = BTD_PROFILE_PSM_AUTO,
2543                 .mode           = BT_IO_MODE_ERTM,
2544                 .authorize      = true,
2545                 .get_record     = get_mns_record,
2546                 .version        = 0x0102
2547 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
2548         }, {
2549                 .uuid           = HID_UUID,
2550                 .name           = "HID Device",
2551                 .psm            = HID_DEVICE_INTR_PSM,
2552                 .authorize      = TRUE,
2553                 .get_record     = get_hid_device_record,
2554                 .version                = 0x0100,
2555         },
2556 #else
2557         },
2558 #endif
2559 };
2560
2561 static void ext_set_defaults(struct ext_profile *ext)
2562 {
2563         unsigned int i;
2564
2565         ext->mode = BT_IO_MODE_BASIC;
2566         ext->sec_level = BT_IO_SEC_MEDIUM;
2567         ext->authorize = true;
2568         ext->enable_client = true;
2569         ext->enable_server = true;
2570         ext->remote_uuid = NULL;
2571
2572         for (i = 0; i < G_N_ELEMENTS(defaults); i++) {
2573                 struct default_settings *settings = &defaults[i];
2574                 const char *remote_uuid;
2575
2576                 if (strcasecmp(ext->uuid, settings->uuid) != 0)
2577                         continue;
2578
2579                 if (settings->remote_uuid)
2580                         remote_uuid = settings->remote_uuid;
2581                 else
2582                         remote_uuid = ext->uuid;
2583
2584                 ext->remote_uuid = g_strdup(remote_uuid);
2585
2586                 if (settings->channel)
2587                         ext->local_chan = settings->channel;
2588
2589                 if (settings->psm)
2590                         ext->local_psm = settings->psm;
2591
2592                 if (settings->sec_level)
2593                         ext->sec_level = settings->sec_level;
2594
2595                 if (settings->mode)
2596                         ext->mode = settings->mode;
2597
2598                 ext->authorize = settings->authorize;
2599
2600                 if (settings->auto_connect)
2601                         ext->p.auto_connect = true;
2602
2603                 if (settings->priority)
2604                         ext->p.priority = settings->priority;
2605
2606                 if (settings->get_record)
2607                         ext->get_record = settings->get_record;
2608
2609                 if (settings->version)
2610                         ext->version = settings->version;
2611
2612                 if (settings->features)
2613                         ext->features = settings->features;
2614
2615                 if (settings->name)
2616                         ext->name = g_strdup(settings->name);
2617         }
2618 }
2619
2620 static int parse_ext_opt(struct ext_profile *ext, const char *key,
2621                                                         DBusMessageIter *value)
2622 {
2623         int type = dbus_message_iter_get_arg_type(value);
2624         const char *str;
2625         uint16_t u16;
2626         dbus_bool_t b;
2627
2628         if (strcasecmp(key, "Name") == 0) {
2629                 if (type != DBUS_TYPE_STRING)
2630                         return -EINVAL;
2631                 dbus_message_iter_get_basic(value, &str);
2632                 g_free(ext->name);
2633                 ext->name = g_strdup(str);
2634         } else if (strcasecmp(key, "AutoConnect") == 0) {
2635                 if (type != DBUS_TYPE_BOOLEAN)
2636                         return -EINVAL;
2637                 dbus_message_iter_get_basic(value, &b);
2638                 ext->p.auto_connect = b;
2639         } else if (strcasecmp(key, "PSM") == 0) {
2640                 if (type != DBUS_TYPE_UINT16)
2641                         return -EINVAL;
2642                 dbus_message_iter_get_basic(value, &u16);
2643                 ext->local_psm = u16 ? u16 : BTD_PROFILE_PSM_AUTO;
2644         } else if (strcasecmp(key, "Channel") == 0) {
2645                 if (type != DBUS_TYPE_UINT16)
2646                         return -EINVAL;
2647
2648                 dbus_message_iter_get_basic(value, &u16);
2649                 if (u16 > 31)
2650                         return -EINVAL;
2651                 ext->local_chan = u16 ? u16 : BTD_PROFILE_CHAN_AUTO;
2652         } else if (strcasecmp(key, "RequireAuthentication") == 0) {
2653                 if (type != DBUS_TYPE_BOOLEAN)
2654                         return -EINVAL;
2655
2656                 dbus_message_iter_get_basic(value, &b);
2657 #ifndef __TIZEN_PATCH__
2658                 if (b)
2659                         ext->sec_level = BT_IO_SEC_MEDIUM;
2660                 else
2661                         ext->sec_level = BT_IO_SEC_LOW;
2662 #else
2663 #ifdef TIZEN_BT_IO_CAPA_NO_INPUT_OUTPUT
2664                 /*
2665                  * NoInputOut device should have another authentication method.
2666                  * So turn off force authentication setting for that device.
2667                  */
2668                 if (b)
2669                         ext->sec_level = BT_IO_SEC_MEDIUM;
2670                 else
2671                         ext->sec_level = BT_IO_SEC_LOW;
2672 #else
2673                 if (!strcasecmp(ext->uuid, WEARABLE_OLD_SAP_UUID) ||
2674                     !strcasecmp(ext->uuid, WEARABLE_NEW_SAP_UUID)) {
2675                         DBG("Set SAP UUID's sec_level to HIGH");
2676                         ext->sec_level = BT_IO_SEC_HIGH;
2677                 } else if (b)
2678                         ext->sec_level = BT_IO_SEC_MEDIUM;
2679                 else
2680                         ext->sec_level = BT_IO_SEC_LOW;
2681 #endif
2682 #endif
2683         } else if (strcasecmp(key, "RequireAuthorization") == 0) {
2684                 if (type != DBUS_TYPE_BOOLEAN)
2685                         return -EINVAL;
2686                 dbus_message_iter_get_basic(value, &b);
2687                 ext->authorize = b;
2688         } else if (strcasecmp(key, "Role") == 0) {
2689                 if (type != DBUS_TYPE_STRING)
2690                         return -EINVAL;
2691                 dbus_message_iter_get_basic(value, &str);
2692                 g_free(ext->role);
2693                 ext->role = g_strdup(str);
2694
2695                 if (g_str_equal(ext->role, "client")) {
2696                         ext->enable_server = false;
2697                         ext->enable_client = true;
2698                 } else if (g_str_equal(ext->role, "server")) {
2699                         ext->enable_server = true;
2700                         ext->enable_client = false;
2701                 }
2702         } else if (strcasecmp(key, "ServiceRecord") == 0) {
2703                 if (type != DBUS_TYPE_STRING)
2704                         return -EINVAL;
2705                 dbus_message_iter_get_basic(value, &str);
2706                 g_free(ext->record);
2707                 ext->record = g_strdup(str);
2708                 ext->enable_server = true;
2709         } else if (strcasecmp(key, "Version") == 0) {
2710                 uint16_t ver;
2711
2712                 if (type != DBUS_TYPE_UINT16)
2713                         return -EINVAL;
2714
2715                 dbus_message_iter_get_basic(value, &ver);
2716                 ext->version = ver;
2717         } else if (strcasecmp(key, "Features") == 0) {
2718                 uint16_t feat;
2719
2720                 if (type != DBUS_TYPE_UINT16)
2721                         return -EINVAL;
2722
2723                 dbus_message_iter_get_basic(value, &feat);
2724                 ext->features = feat;
2725         } else if (strcasecmp(key, "Service") == 0) {
2726                 if (type != DBUS_TYPE_STRING)
2727                         return -EINVAL;
2728                 dbus_message_iter_get_basic(value, &str);
2729                 free(ext->service);
2730                 ext->service = bt_name2string(str);
2731         }
2732
2733         return 0;
2734 }
2735
2736 static void set_service(struct ext_profile *ext)
2737 {
2738         if (strcasecmp(ext->uuid, HSP_HS_UUID) == 0) {
2739                 ext->service = strdup(ext->uuid);
2740         } else if (strcasecmp(ext->uuid, HSP_AG_UUID) == 0) {
2741                 ext->service = ext->uuid;
2742                 ext->uuid = strdup(HSP_HS_UUID);
2743         } else if (strcasecmp(ext->uuid, HFP_HS_UUID) == 0) {
2744                 ext->service = strdup(ext->uuid);
2745         } else if (strcasecmp(ext->uuid, HFP_AG_UUID) == 0) {
2746                 ext->service = ext->uuid;
2747                 ext->uuid = strdup(HFP_HS_UUID);
2748         } else if (strcasecmp(ext->uuid, OBEX_SYNC_UUID) == 0 ||
2749                         strcasecmp(ext->uuid, OBEX_OPP_UUID) == 0 ||
2750                         strcasecmp(ext->uuid, OBEX_FTP_UUID) == 0) {
2751                 ext->service = strdup(ext->uuid);
2752         } else if (strcasecmp(ext->uuid, OBEX_PSE_UUID) == 0 ||
2753                         strcasecmp(ext->uuid, OBEX_PCE_UUID) ==  0) {
2754                 ext->service = ext->uuid;
2755                 ext->uuid = strdup(OBEX_PBAP_UUID);
2756         } else if (strcasecmp(ext->uuid, OBEX_MAS_UUID) == 0 ||
2757                         strcasecmp(ext->uuid, OBEX_MNS_UUID) == 0) {
2758                 ext->service = ext->uuid;
2759                 ext->uuid = strdup(OBEX_MAP_UUID);
2760         }
2761 }
2762
2763 #ifdef __TIZEN_PATCH__
2764 static struct ext_profile *create_ext2(const char *owner, const char *path,
2765                                         const char *uuid, const char *destination, const char *app_path,
2766                                         DBusMessageIter *opts)
2767 {
2768         struct btd_profile *p;
2769         struct ext_profile *ext;
2770
2771         ext = g_new0(struct ext_profile, 1);
2772
2773         ext->uuid = bt_name2string(uuid);
2774         if (ext->uuid == NULL) {
2775                 g_free(ext);
2776                 return NULL;
2777         }
2778
2779         ext->owner = g_strdup(destination);
2780         ext->path = g_strdup(app_path);
2781         ext->destination = g_strdup(destination);
2782         ext->app_path = g_strdup(app_path);
2783         DBG("VALUES Dest %s, path2 %s", destination, app_path);
2784         ext_set_defaults(ext);
2785
2786         while (dbus_message_iter_get_arg_type(opts) == DBUS_TYPE_DICT_ENTRY) {
2787                 DBusMessageIter value, entry;
2788                 const char *key;
2789
2790                 dbus_message_iter_recurse(opts, &entry);
2791                 dbus_message_iter_get_basic(&entry, &key);
2792
2793                 dbus_message_iter_next(&entry);
2794                 dbus_message_iter_recurse(&entry, &value);
2795
2796                 if (parse_ext_opt(ext, key, &value) < 0)
2797                         error("Invalid value for profile option %s", key);
2798
2799                 dbus_message_iter_next(opts);
2800         }
2801
2802         if (!ext->service)
2803                 set_service(ext);
2804
2805         if (ext->enable_server && !(ext->record || ext->get_record))
2806                 ext->get_record = get_generic_record;
2807
2808         if (!ext->name)
2809                 ext->name = g_strdup_printf("%s%s/%s", owner, path, uuid);
2810
2811         if (!ext->remote_uuid) {
2812                 if (ext->service)
2813                         ext->remote_uuid = g_strdup(ext->service);
2814                 else
2815                         ext->remote_uuid = g_strdup(ext->uuid);
2816         }
2817
2818         p = &ext->p;
2819
2820         p->name = ext->name;
2821         p->local_uuid = ext->service ? ext->service : ext->uuid;
2822         p->remote_uuid = ext->remote_uuid;
2823
2824         if (ext->enable_server) {
2825                 p->adapter_probe = ext_adapter_probe;
2826                 p->adapter_remove = ext_adapter_remove;
2827         }
2828
2829         if (ext->enable_client) {
2830                 p->device_probe = ext_device_probe;
2831                 p->device_remove = ext_device_remove;
2832                 p->connect = ext_connect_dev;
2833                 p->disconnect = ext_disconnect_dev;
2834         }
2835
2836         DBG("Created \"%s\"", ext->name);
2837
2838         ext_profiles = g_slist_append(ext_profiles, ext);
2839
2840         adapter_foreach(adapter_add_profile, &ext->p);
2841
2842         return ext;
2843 }
2844 #endif
2845
2846 static struct ext_profile *create_ext(const char *owner, const char *path,
2847                                         const char *uuid,
2848                                         DBusMessageIter *opts)
2849 {
2850         struct btd_profile *p;
2851         struct ext_profile *ext;
2852
2853         ext = g_new0(struct ext_profile, 1);
2854
2855         ext->uuid = bt_name2string(uuid);
2856         if (ext->uuid == NULL) {
2857                 g_free(ext);
2858                 return NULL;
2859         }
2860
2861         ext->owner = g_strdup(owner);
2862         ext->path = g_strdup(path);
2863
2864         ext_set_defaults(ext);
2865
2866         while (dbus_message_iter_get_arg_type(opts) == DBUS_TYPE_DICT_ENTRY) {
2867                 DBusMessageIter value, entry;
2868                 const char *key;
2869
2870                 dbus_message_iter_recurse(opts, &entry);
2871                 dbus_message_iter_get_basic(&entry, &key);
2872
2873                 dbus_message_iter_next(&entry);
2874                 dbus_message_iter_recurse(&entry, &value);
2875
2876                 if (parse_ext_opt(ext, key, &value) < 0)
2877                         error("Invalid value for profile option %s", key);
2878
2879                 dbus_message_iter_next(opts);
2880         }
2881
2882         if (!ext->service)
2883                 set_service(ext);
2884
2885         if (ext->enable_server && !(ext->record || ext->get_record))
2886                 ext->get_record = get_generic_record;
2887
2888         if (!ext->name)
2889                 ext->name = g_strdup_printf("%s%s/%s", owner, path, uuid);
2890
2891         if (!ext->remote_uuid) {
2892                 if (ext->service)
2893                         ext->remote_uuid = g_strdup(ext->service);
2894                 else
2895                         ext->remote_uuid = g_strdup(ext->uuid);
2896         }
2897
2898         p = &ext->p;
2899
2900         p->name = ext->name;
2901         p->local_uuid = ext->service ? ext->service : ext->uuid;
2902         p->remote_uuid = ext->remote_uuid;
2903         p->external = true;
2904
2905         if (ext->enable_server) {
2906                 p->adapter_probe = ext_adapter_probe;
2907                 p->adapter_remove = ext_adapter_remove;
2908         }
2909
2910         if (ext->enable_client) {
2911                 p->device_probe = ext_device_probe;
2912                 p->device_remove = ext_device_remove;
2913                 p->connect = ext_connect_dev;
2914                 p->disconnect = ext_disconnect_dev;
2915         }
2916
2917         DBG("Created \"%s\"", ext->name);
2918
2919         ext_profiles = g_slist_append(ext_profiles, ext);
2920
2921         adapter_foreach(adapter_add_profile, &ext->p);
2922
2923         return ext;
2924 }
2925
2926 static void remove_ext(struct ext_profile *ext)
2927 {
2928         adapter_foreach(adapter_remove_profile, &ext->p);
2929
2930         ext_profiles = g_slist_remove(ext_profiles, ext);
2931
2932         DBG("Removed \"%s\"", ext->name);
2933
2934         ext_remove_records(ext, NULL);
2935
2936         g_slist_free_full(ext->servers, ext_io_destroy);
2937         g_slist_free_full(ext->conns, ext_io_destroy);
2938
2939         g_free(ext->remote_uuid);
2940         g_free(ext->name);
2941         g_free(ext->owner);
2942         free(ext->uuid);
2943         free(ext->service);
2944         g_free(ext->role);
2945         g_free(ext->path);
2946         g_free(ext->record);
2947
2948         g_free(ext);
2949 }
2950
2951 static void ext_exited(DBusConnection *conn, void *user_data)
2952 {
2953         struct ext_profile *ext = user_data;
2954
2955         DBG("\"%s\" exited", ext->name);
2956
2957         remove_ext(ext);
2958 }
2959
2960 static DBusMessage *register_profile(DBusConnection *conn,
2961                                         DBusMessage *msg, void *user_data)
2962 {
2963         const char *path, *sender, *uuid;
2964         DBusMessageIter args, opts;
2965         struct ext_profile *ext;
2966
2967         sender = dbus_message_get_sender(msg);
2968
2969         DBG("sender %s", sender);
2970
2971         dbus_message_iter_init(msg, &args);
2972
2973         dbus_message_iter_get_basic(&args, &path);
2974         dbus_message_iter_next(&args);
2975
2976         ext = find_ext_profile(sender, path);
2977         if (ext)
2978                 return btd_error_already_exists(msg);
2979
2980         dbus_message_iter_get_basic(&args, &uuid);
2981         dbus_message_iter_next(&args);
2982
2983         if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY)
2984                 return btd_error_invalid_args(msg);
2985
2986         dbus_message_iter_recurse(&args, &opts);
2987
2988         ext = create_ext(sender, path, uuid, &opts);
2989         if (!ext)
2990                 return btd_error_invalid_args(msg);
2991
2992         ext->id = g_dbus_add_disconnect_watch(conn, sender, ext_exited, ext,
2993                                                                         NULL);
2994
2995         return dbus_message_new_method_return(msg);
2996 }
2997
2998 static DBusMessage *unregister_profile(DBusConnection *conn,
2999                                         DBusMessage *msg, void *user_data)
3000 {
3001         const char *path, *sender;
3002         struct ext_profile *ext;
3003
3004         sender = dbus_message_get_sender(msg);
3005
3006         DBG("sender %s", sender);
3007
3008         if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
3009                                                         DBUS_TYPE_INVALID))
3010                 return btd_error_invalid_args(msg);
3011
3012         ext = find_ext_profile(sender, path);
3013         if (!ext)
3014                 return btd_error_does_not_exist(msg);
3015
3016         g_dbus_remove_watch(conn, ext->id);
3017         remove_ext(ext);
3018
3019         return dbus_message_new_method_return(msg);
3020 }
3021
3022 #ifdef __TIZEN_PATCH__
3023 static DBusMessage *register_profile2(DBusConnection *conn,
3024                                         DBusMessage *msg, void *user_data)
3025 {
3026         const char *path, *sender, *uuid;
3027         DBusMessageIter args, opts;
3028         struct ext_profile *ext;
3029         const char *destination, *app_path;
3030         sender = dbus_message_get_sender(msg);
3031
3032         DBG("sender %s", sender);
3033
3034         dbus_message_iter_init(msg, &args);
3035
3036         dbus_message_iter_get_basic(&args, &path);
3037         dbus_message_iter_next(&args);
3038         DBG("path %s", path);
3039
3040         DBG("path %s", path);
3041         dbus_message_iter_get_basic(&args, &uuid);
3042         dbus_message_iter_next(&args);
3043         DBG("uuid %s", uuid);
3044         dbus_message_iter_get_basic(&args, &destination);
3045         dbus_message_iter_next(&args);
3046         DBG("destination %s", destination);
3047         dbus_message_iter_get_basic(&args, &app_path);
3048         dbus_message_iter_next(&args);
3049         DBG("path2 %s", app_path);
3050         ext = find_ext_profile(destination, path);
3051         if (ext)
3052                 return btd_error_already_exists(msg);
3053         if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY)
3054                 return btd_error_invalid_args(msg);
3055         DBG("interator");
3056         dbus_message_iter_recurse(&args, &opts);
3057
3058         ext = create_ext2(sender, path, uuid, destination, app_path, &opts);
3059         if (!ext)
3060                 return btd_error_invalid_args(msg);
3061 #if 0
3062         ext->id = g_dbus_add_disconnect_watch(conn, sender, ext_exited, ext,
3063                                                                         NULL);
3064 #endif
3065
3066         return dbus_message_new_method_return(msg);
3067 }
3068 #endif
3069
3070 static const GDBusMethodTable methods[] = {
3071         { GDBUS_METHOD("RegisterProfile",
3072                         GDBUS_ARGS({ "profile", "o"}, { "UUID", "s" },
3073                                                 { "options", "a{sv}" }),
3074                         NULL, register_profile) },
3075 #ifdef __TIZEN_PATCH__
3076         /* For Dbus Smack devides dbus API, the functionality is same */
3077         { GDBUS_METHOD("RegisterProfile1",
3078                         GDBUS_ARGS({ "profile", "o"}, { "UUID", "s" },
3079                                                 { "options", "a{sv}" }),
3080                         NULL, register_profile) },
3081         { GDBUS_METHOD("RegisterProfile2",
3082                         GDBUS_ARGS({"profile", "o"}, { "UUID", "s" },
3083                                                 {"destination", "s"}, {"path", "s"},
3084                                                 { "options", "a{sv}"}),
3085                         NULL, register_profile2) },
3086 #endif
3087
3088         { GDBUS_METHOD("UnregisterProfile", GDBUS_ARGS({ "profile", "o" }),
3089                         NULL, unregister_profile) },
3090         { }
3091 };
3092
3093 static struct btd_profile_custom_property *find_custom_prop(const char *uuid,
3094                                                         const char *name)
3095 {
3096         GSList *l;
3097
3098         for (l = custom_props; l; l = l->next) {
3099                 struct btd_profile_custom_property *prop = l->data;
3100
3101                 if (strcasecmp(prop->uuid, uuid) != 0)
3102                         continue;
3103
3104                 if (g_strcmp0(prop->name, name) == 0)
3105                         return prop;
3106         }
3107
3108         return NULL;
3109 }
3110
3111 bool btd_profile_add_custom_prop(const char *uuid, const char *type,
3112                                         const char *name,
3113                                         btd_profile_prop_exists exists,
3114                                         btd_profile_prop_get get,
3115                                         void *user_data)
3116 {
3117         struct btd_profile_custom_property *prop;
3118
3119         prop = find_custom_prop(uuid, name);
3120         if (prop != NULL)
3121                 return false;
3122
3123         prop = g_new0(struct btd_profile_custom_property, 1);
3124
3125         prop->uuid = strdup(uuid);
3126         prop->type = g_strdup(type);
3127         prop->name = g_strdup(name);
3128         prop->exists = exists;
3129         prop->get = get;
3130         prop->user_data = user_data;
3131
3132         custom_props = g_slist_append(custom_props, prop);
3133
3134         return true;
3135 }
3136
3137 static void free_property(gpointer data)
3138 {
3139         struct btd_profile_custom_property *p = data;
3140
3141         g_free(p->uuid);
3142         g_free(p->type);
3143         g_free(p->name);
3144
3145         g_free(p);
3146 }
3147
3148 bool btd_profile_remove_custom_prop(const char *uuid, const char *name)
3149 {
3150         struct btd_profile_custom_property *prop;
3151
3152         prop = find_custom_prop(uuid, name);
3153         if (prop == NULL)
3154                 return false;
3155
3156         custom_props = g_slist_remove(custom_props, prop);
3157         free_property(prop);
3158
3159         return false;
3160 }
3161
3162 void btd_profile_init(void)
3163 {
3164         g_dbus_register_interface(btd_get_dbus_connection(),
3165                                 "/org/bluez", "org.bluez.ProfileManager1",
3166                                 methods, NULL, NULL, NULL, NULL);
3167 }
3168
3169 void btd_profile_cleanup(void)
3170 {
3171         while (ext_profiles) {
3172                 struct ext_profile *ext = ext_profiles->data;
3173                 DBusConnection *conn = btd_get_dbus_connection();
3174                 DBusMessage *msg;
3175
3176                 DBG("Releasing \"%s\"", ext->name);
3177
3178                 g_slist_free_full(ext->conns, ext_io_destroy);
3179                 ext->conns = NULL;
3180
3181 #ifdef __TIZEN_PATCH__
3182                 if (ext->destination == NULL) {
3183                         msg = dbus_message_new_method_call(ext->owner,
3184                                                         ext->path,
3185                                                         "org.bluez.Profile1",
3186                                                         "Release");
3187                         if (msg)
3188                                 g_dbus_send_message(conn, msg);
3189                 }
3190 #else
3191                 msg = dbus_message_new_method_call(ext->owner, ext->path,
3192                                                         "org.bluez.Profile1",
3193                                                         "Release");
3194                 if (msg)
3195                         g_dbus_send_message(conn, msg);
3196 #endif
3197
3198                 g_dbus_remove_watch(conn, ext->id);
3199                 remove_ext(ext);
3200
3201         }
3202
3203         g_slist_free_full(custom_props, free_property);
3204         custom_props = NULL;
3205
3206         g_dbus_unregister_interface(btd_get_dbus_connection(),
3207                                 "/org/bluez", "org.bluez.ProfileManager1");
3208 }