summaryrefslogtreecommitdiffstats
path: root/binding-bluetooth/bluetooth-api.c
blob: 39acb9add4df4d856ade18e2149bab863d4cea82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
@media only all and (prefers-color-scheme: dark) {
.highlight .hll { background-color: #49483e }
.highlight .c { color: #75715e } /* Comment */
.highlight .err { color: #960050; background-color: #1e0010 } /* Error */
.highlight .k { color: #66d9ef } /* Keyword */
.highlight .l { color: #ae81ff } /* Literal */
.highlight .n { color: #f8f8f2 } /* Name */
.highlight .o { color: #f92672 } /* Operator */
.highlight .p { color: #f8f8f2 } /* Punctuation */
.highlight .ch { color: #75715e } /* Comment.Hashbang */
.highlight .cm { color: #75715e } /* Comment.Multiline */
.highlight .cp { color: #75715e } /* Comment.Preproc */
.highlight .cpf { color: #75715e } /* Comment.PreprocFile */
.highlight .c1 { color: #75715e } /* Comment.Single */
.highlight .cs { color: #75715e } /* Comment.Special */
.highlight .gd { color: #f92672 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gi { color: #a6e22e } /* Generic.Inserted */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #75715e } /* Generic.Subheading */
.highlight .kc { color: #66d9ef } /* Keyword.Constant */
.highlight .kd { color: #66d9ef } /* Keyword.Declaration */
.highlight .kn { color: #f92672 } /* Keyword.Namespace */
.highlight .kp { color: #66d9ef } /* Keyword.Pseudo */
.highlight .kr { color: #66d9ef } /* Keyword.Reserved */
.highlight .kt { color: #66d9ef } /* Keyword.Type */
.highlight .ld { color: #e6db74 } /* Literal.Date */
.highlight .m { color: #ae81ff } /* Literal.Number */
.highlight .s { color: #e6db74 } /* Literal.String */
.highlight .na { color: #a6e22e } /* Name.Attribute */
.highlight .nb { color: #f8f8f2 } /* Name.Builtin */
.highlight .nc { color: #a6e22e } /* Name.Class */
.highlight .no { color: #66d9ef } /* Name.Constant */
.highlight .nd { color: #a6e22e } /* Name.Decorator */
.highlight .ni { color: #f8f8f2 } /* Name.Entity */
.highlight .ne { color: #a6e22e } /* Name.Exception */
.highlight .nf { color: #a6e22e } /* Name.Function */
.highlight .nl { color: #f8f8f2 } /* Name.Label */
.highlight .nn { color: #f8f8f2 } /* Name.Namespace */
.highlight .nx { color: #a6e22e } /* Name.Other */
.highlight .py { color: #f8f8f2 } /* Name.Property */
.highlight .nt { color: #f92672 } /* Name.Tag */
.highlight .nv { color: #f8f8f2 } /* Name.Variable */
.highlight .ow { color: #f92672 } /* Operator.Word */
.highlight .w { color: #f8f8f2 } /* Text.Whitespace */
.highlight .mb { color: #ae81ff } /* Literal.Number.Bin */
.highlight .mf { color: #ae81ff } /* Literal.Number.Float */
.highlight .mh { color: #ae81ff } /* Literal.Number.Hex */
.highlight .mi { color: #ae81ff } /* Literal.Number.Integer */
.highlight .mo { color: #ae81ff } /* Literal.Number.Oct */
.highlight .sa { color: #e6db74 } /* Literal.String.Affix */
.highlight .sb { color: #e6db74 } /* Literal.String.Backtick */
.highlight .sc { color: #e6db74 } /* Literal.String.Char */
.highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */
.highlight .sd { color: #e6db74 } /* Literal.String.Doc */
.highlight .s2 { color: #e6db74 } /* Literal.String.Double */
.highlight .se { color: #ae81ff } /* Literal.String.Escape */
.highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */
.highlight .si { color: #e6db74 } /* Literal.String.Interpol */
.highlight .sx { color: #e6db74 } /* Literal.String.Other */
.highlight .sr { color: #e6db74 } /* Literal.String.Regex */
.highlight .s1 { color: #e6db74 } /* Literal.String.Single */
.highlight .ss { color: #e6db74 } /* Literal.String.Symbol */
.highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #a6e22e } /* Name.Function.Magic */
.highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */
.highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */
.highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */
.highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */
.highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */
}
@media (prefers-color-scheme: light) {
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
}
<?xml version="1.0" encoding="UTF-8"?>
<manifest>

  <!-- remote servers to query -->
  <remote name="agl"
         fetch="https://gerrit.automotivelinux.org/gerrit/"
         review="https://gerrit.automotivelinux.org/gerrit/"
         pushurl="ssh://gerrit.automotivelinux.org:29418"
  />
  <remote name="yocto" fetch="https://git.yoctoproject.org/git/" />
  <remote name="github" fetch="https://github.com/" />
  <remote name="openembedded" fetch="https://git.openembedded.org/" />

  <!-- defaults -->
  <default remote="agl" sync-j="4" revision="refs/tags/pike/16.0.3"/>


  <!-- CORE -->
  <!-- use agl revisions/branches here -->

  <!-- AGL things. -->
  <project name="AGL/meta-agl" path="meta-agl" />
  <project name="AGL/meta-agl-demo" path="meta-agl-demo" />
  <project name="AGL/meta-agl-devel" path="meta-agl-devel" />


  <!-- ALL EXTERNAL REPOS BELOW USE A FIXED REVISION ! -->

  <!-- YOCTO & OE -->

  <!-- Yocto/OpenEmbedded things. -->
  <project name="poky" path="external/poky" remote="yocto" revision="d8d6d921fad14b82167d9f031d4fca06b5e01883" upstream="kirkstone" />
  <project name="openembedded/meta-openembedded" path="external/meta-openembedded" remote="github" revision="8a75c61cce2aa1d6e5a3597ab8fc5a7e6aeae1e4" upstream="kirkstone" />
  <project name="meta-lts-mixins" path="external/meta-lts-mixins_rust-1.68" remote="yocto" revision="6b3a208f7e14138728a6e581ac75e8973ab48ef3" upstream="kirkstone/rust-1.68" />


  <!-- UPSTREAM COMPONENTS -->

  <!-- meta-virtualization -->
  <project name="meta-virtualization" path="external/meta-virtualization" remote="yocto" revision="67b0ef4256a484851f3556d281ca4caa88374388" upstream="kirkstone"/>

  <!-- Qt things -->
  <project name="meta-qt5/meta-qt5" path="external/meta-qt5" remote="github" revision="ae8a97f79364bed1abc297636f7933d0e35f22be" upstream="kirkstone"/>

  <!-- Security layer -->
  <project name="meta-security" path="external/meta-security" remote="yocto" revision="1a3e42cedbd94ca73be45800d0e902fec35d0f0f" upstream="kirkstone"/>

  <!-- SELinux layer -->
  <project name="meta-selinux" path="external/meta-selinux" remote="yocto" revision="a401f4b2816a0b41ce8d9351542658c721935bcd" upstream="kirkstone"/>

  <!-- meta-codescanner - support for using CodeScanner during the build -->
  <project name="dl9pf/meta-codechecker" path="external/meta-codechecker" remote="github" revision="f27a46feb2291d333744850a82d5c8af303e3bd5" upstream="master"/>

  <!-- meta-spdxscanner - support for fossology -->
  <project name="meta-spdxscanner" path="external/meta-spdxscanner" remote="yocto" revision="25373bc58ece8b6f07680a103b4a1bbbc99e0db1" upstream="master"/>

  <!-- clang support -->
  <project name="kraj/meta-clang" path="external/meta-clang" remote="github" revision="79169d9be565b7a87310ca280d3a21aaf608ce33" upstream="kirkstone"/>

  <!-- meta-python2 as stop-gap to allow chromium to build until upstream fixes the dependencies -->
  <project name="meta-python2" path="external/meta-python2" remote="openembedded" revision="f02882e2aa9279ca7becca8d0cedbffe88b5a253" upstream="kirkstone" />

  <!-- meta-flutter -->
  <project name="meta-flutter/meta-flutter" path="external/meta-flutter" remote="github" revision="bd02a07748a44726a43c9fa1842064dbb7084d73" upstream="kirkstone"/>
  <project name="meta-flutter/workspace-automation" path="external/workspace-automation" remote="github" revision="1548ef193f55cf476af6189449ee876ba7a7fdaf" upstream="main"/>

  <!-- BSPs -->

  <!-- Renesas Gen3 specific things -->
  <project name="renesas-rcar/meta-renesas" path="bsp/meta-renesas" remote="github" revision="3a5cd5971edb07f0a17486e48062a1cb2f8a230f" upstream="kirkstone-dev"/>
  <project name="CogentEmbedded/meta-rcar" path="bsp/meta-rcar" remote="github" revision="511808a3e794ad0e35386f83d3d159c9ba48b4be" upstream="kirkstone-Yocto-v5.9.0"/>
  <project name="AGL/meta-agl-refhw" path="bsp/meta-agl-refhw" />

  <!-- consolidate on meta-freescale from git.yoctoproject.org -->
  <project name="meta-freescale" path="bsp/meta-freescale" remote="yocto" revision="dfd01d7bdf87b6bda254780a35659975d2b2c66e" upstream="kirkstone"/>
  <project name="Freescale/meta-freescale-3rdparty" path="bsp/meta-freescale-3rdparty" remote="github" revision="1a6ea560015ecda5fff8eccaf5b1327f1bb6c57f" upstream="kirkstone"/>

  <!-- TI Vayu / Jacinto 6 / DRA7 -->
  <project name="meta-arm" path="bsp/meta-arm" remote="yocto" revision="b187fb9232ca0a6b5f8f90b4715958546fc41d73" upstream="kirkstone"/>
  <project name="meta-ti" path="bsp/meta-ti" remote="yocto" revision="e4d60ab2c8565eaabbad1d51972296e412744190" upstream="kirkstone"/>

  <!-- Raspberry Pi 4 -->
  <project name="meta-raspberrypi" path="bsp/meta-raspberrypi" remote="yocto" revision="59a6a1b5dd1e21189adec49c61eae04ed3e70338" upstream="kirkstone"/>

  <!-- Sancloud BSP layers -->
  <project name="SanCloudLtd/meta-sancloud" path="bsp/meta-sancloud" remote="github" revision="e1a23019ce2ff3879986fa63071f1a2caa23697c" upstream="kirkstone"/>
  <project name="EmbeddedAndroid/meta-rtlwifi" path="bsp/meta-rtlwifi" remote="github" revision="032a394e7569d1254cd17a0358475b986e64a5a4" upstream="master"/>

</manifest>
href='#n802'>802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961
/*  Copyright 2016 ALPS ELECTRIC CO., LTD.
*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*   limitations under the License.
*/

#define _GNU_SOURCE

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <json-c/json.h>
#include <afb/afb-binding.h>
#include <afb/afb-service-itf.h>

#include "bluetooth-manager.h"
#include "bluetooth-agent.h"
#include "bluetooth-api.h"

/*
 * the interface to afb-daemon
 */
const struct afb_binding_interface *afbitf;

struct event
{
	struct event *next;
	struct afb_event event;
	char tag[1];
};

static struct event *events = 0;

/* searchs the event of tag */
static struct event *event_get(const char *tag)
{
	struct event *e = events;
	while(e && strcmp(e->tag, tag))
		e = e->next;
	return e;
}

/* deletes the event of tag */
static int event_del(const char *tag)
{
	struct event *e, **p;

	/* check exists */
	e = event_get(tag);
	if (!e) return -1;

	/* unlink */
	p = &events;
	while(*p != e) p = &(*p)->next;
	*p = e->next;

	/* destroys */
	afb_event_drop(e->event);
	free(e);
	return 0;
}

/* creates the event of tag */
static int event_add(const char *tag, const char *name)
{
	struct event *e;

	/* check valid tag */
	e = event_get(tag);
	if (e) return -1;

	/* creation */
	e = malloc(strlen(tag) + sizeof *e);
	if (!e) return -1;
	strcpy(e->tag, tag);

	/* make the event */
	e->event = afb_daemon_make_event(afbitf->daemon, name);
	if (!e->event.closure) { free(e); return -1; }

	/* link */
	e->next = events;
	events = e;
	return 0;
}

static int event_subscribe(struct afb_req request, const char *tag)
{
	struct event *e;
	e = event_get(tag);
	return e ? afb_req_subscribe(request, e->event) : -1;
}

static int event_unsubscribe(struct afb_req request, const char *tag)
{
	struct event *e;
	e = event_get(tag);
	return e ? afb_req_unsubscribe(request, e->event) : -1;
}

static int event_push(struct json_object *args, const char *tag)
{
	struct event *e;
	e = event_get(tag);
	return e ? afb_event_push(e->event, json_object_get(args)) : -1;
}

static json_object *new_json_object_parse_avrcp(struct btd_device *BDdevice, unsigned int filter)
{
    json_object *jresp = json_object_new_object();
    json_object *jstring = NULL;

    if (BD_AVRCP_TITLE & filter)
    {
        if (BDdevice->avrcp_title)
        {
            jstring = json_object_new_string(BDdevice->avrcp_title);
        }
        else
        {
            jstring = json_object_new_string("");
        }
        json_object_object_add(jresp, "Title", jstring);
    }

    if (BD_AVRCP_ARTIST & filter)
    {
        if (BDdevice->avrcp_artist)
        {
            jstring = json_object_new_string(BDdevice->avrcp_artist);
        }
        else
        {
            jstring = json_object_new_string("");
        }
        json_object_object_add(jresp, "Artist", jstring);
    }

    if (BD_AVRCP_STATUS & filter)
    {
        if (BDdevice->avrcp_status)
        {
            jstring = json_object_new_string(BDdevice->avrcp_status);
        }
        else
        {
            jstring = json_object_new_string("");
        }
        json_object_object_add(jresp, "Status", jstring);
    }

    if (BD_AVRCP_DURATION & filter)
    {
        json_object_object_add(jresp, "Duration",
                               json_object_new_int(BDdevice->avrcp_duration));
    }

    if (BD_AVRCP_POSITION & filter)
    {
        json_object_object_add(jresp, "Position",
                               json_object_new_int(BDdevice->avrcp_position));
    }

    return jresp;
}

/* create device json object*/
static json_object *new_json_object_from_device(struct btd_device *BDdevice, unsigned int filter)
{
    json_object *jresp = json_object_new_object();
    json_object *jstring = NULL;

    if (BD_PATH & filter)
    {
        if (BDdevice->path)
        {
            jstring = json_object_new_string(BDdevice->path);
        }
        else
        {
            jstring = json_object_new_string("");
        }
        json_object_object_add(jresp, "Path", jstring);
    }

    if (BD_ADDER & filter)
    {
        if (BDdevice->bdaddr)
        {
            jstring = json_object_new_string(BDdevice->bdaddr);
        }
        else
        {
            jstring = json_object_new_string("");
        }
        json_object_object_add(jresp, "Address", jstring);
    }

    if (BD_NAME & filter)
    {
        if (BDdevice->name)
        {
            jstring = json_object_new_string(BDdevice->name);
        }
        else
        {
            jstring = json_object_new_string("");
        }
        json_object_object_add(jresp, "Name", jstring);
    }

    if (BD_PAIRED & filter)
    {
        jstring = (TRUE == BDdevice->paired) ?
            json_object_new_string("True"):json_object_new_string("False");
        json_object_object_add(jresp, "Paired", jstring);
    }

    if (BD_TRUSTED & filter)
    {
        jstring = (TRUE == BDdevice->trusted) ?
            json_object_new_string("True"):json_object_new_string("False");
        json_object_object_add(jresp, "Trusted", jstring);
    }

    if (BD_ACLCONNECTED & filter)
    {
        jstring = (TRUE == BDdevice->connected) ?
            json_object_new_string("True"):json_object_new_string("False");
        json_object_object_add(jresp, "Connected", jstring);
    }

    if (BD_AVCONNECTED & filter)
    {
        jstring = (TRUE == BDdevice->avconnected) ?
            json_object_new_string("True"):json_object_new_string("False");
        json_object_object_add(jresp, "AVPConnected", jstring);

        if (BDdevice->avconnected)
        {
            jstring = new_json_object_parse_avrcp(BDdevice, filter);
            json_object_object_add(jresp, "Metadata", jstring);
        }
    }

    if (BD_TRANSPORT_STATE & filter)
    {
        jstring = BDdevice->transport_state ?
                  json_object_new_string(BDdevice->transport_state) :
                  json_object_new_string("none");
        json_object_object_add(jresp, "TransportState", jstring);
    }

    if (BD_TRANSPORT_VOLUME & filter)
    {
        json_object_object_add(jresp, "TransportVolume",
                               json_object_new_int(BDdevice->transport_volume));
    }

    if (BD_HFPCONNECTED & filter)
    {
        jstring = (TRUE == BDdevice->hfpconnected) ?
            json_object_new_string("True"):json_object_new_string("False");
        json_object_object_add(jresp, "HFPConnected", jstring);
    }

    if (BD_UUID_PROFILES & filter)
    {
        GList *list = BDdevice->uuids;

        if (list)
        {
            json_object *jarray = json_object_new_array();

            for (;list;list=list->next)
            {
                jstring = json_object_new_string(list->data);
                json_object_array_add(jarray, jstring);
            }
            json_object_object_add(jresp, "UUIDs", jarray);
        }
    }

    return jresp;
}

/**/
static void bt_power (struct afb_req request)
{
    LOGD("\n");

    const char *value = afb_req_value (request, "value");
    json_object *jresp = NULL;
    int ret = 0;

    jresp = json_object_new_object();

    /* no "?value=" parameter : return current state */
    if (!value) {
        gboolean power_value;
        ret = adapter_get_powered(&power_value);

        if (0==ret)
        {

            setHMIStatus(ACTIVE);
            (TRUE==power_value)?json_object_object_add (jresp, "power", json_object_new_string ("on"))
                                : json_object_object_add (jresp, "power", json_object_new_string ("off"));
        }
        else
        {
            afb_req_fail (request, "failed", "Unable to get power status");
            return;
        }

    }

    /* "?value=" parameter is "1" or "true" */
    else if ( atoi(value) == 1 || !strcasecmp(value, "true") )
    {
        if (adapter_set_powered (TRUE))
        {
            afb_req_fail (request,"failed","no more radio devices available");
            return;
        }
        json_object_object_add (jresp, "power", json_object_new_string ("on"));
        setHMIStatus(ACTIVE);
    }

    /* "?value=" parameter is "0" or "false" */
    else if ( atoi(value) == 0 || !strcasecmp(value, "false") )
    {
        if (adapter_set_powered (FALSE))
        {
            afb_req_fail (request, "failed", "Unable to release radio device");
            return;
        }

        json_object_object_add (jresp, "power", json_object_new_string("off"));
        setHMIStatus(INACTIVE);
    }
    else
    {
        afb_req_fail (request, "failed", "Invalid value");
        return;
    }

    afb_req_success (request, jresp, "Radio - Power set");
}

/**/
static void bt_start_discovery (struct afb_req request)
{
    LOGD("\n");
    int ret = 0;

    ret = adapter_start_discovery();

    if (ret)
    {
        afb_req_fail (request, "failed", "Unable to start discovery");
        return;
    }

    afb_req_success (request, NULL, NULL);
}

/**/
static void bt_stop_discovery (struct afb_req request)
{
    LOGD("\n");
    int ret = 0;

    ret = adapter_stop_discovery();

    if (ret)
    {
        afb_req_fail (request, "failed", "Unable to stop discovery");
        return;
    }

    afb_req_success (request, NULL, NULL);
}


/**/
static void bt_discovery_result (struct afb_req request)
{
    LOGD("\n");
    GSList *list = NULL;
    GSList *tmp = NULL;
    //adapter_update_devices();
    list = adapter_get_devices_list();
    if (NULL == list)
    {
        afb_req_fail (request, "failed", "No find devices");
        return;
    }

    json_object *my_array = json_object_new_array();

    tmp = list;
    for(;tmp;tmp=tmp->next)
    {
        struct btd_device *BDdevice = tmp->data;
        //LOGD("\n%s\t%s\n",BDdevice->bdaddr,BDdevice->name);

        unsigned int filter = BD_ADDER|BD_NAME|BD_PAIRED|BD_ACLCONNECTED|BD_AVCONNECTED|BD_HFPCONNECTED|BD_UUID_PROFILES;

        json_object *jresp = new_json_object_from_device(BDdevice, filter);

        json_object_array_add(my_array, jresp);
    }

    adapter_devices_list_free(list);

    afb_req_success(request, my_array, "BT - Scan Result is Displayed");
}

/**/
static void bt_pair (struct afb_req request)
{
    LOGD("\n");

    const char *value = afb_req_value (request, "value");
    int ret = 0;

    if (NULL == value)
    {
        afb_req_fail (request, "failed", "Please Input the Device Address");
        return;
    }

    ret = device_pair(value);
    if (0 == ret)
    {
        afb_req_success (request, NULL, NULL);
    }
    else
    {
        afb_req_fail (request, "failed", "Device pairing failed");
    }

}

/**/
static void bt_cancel_pairing (struct afb_req request)
{
    LOGD("\n");

    const char *value = afb_req_value (request, "value");
    int ret = 0;

    if (NULL == value)
    {
        afb_req_fail (request, "failed", "Please Input the Device Address");
        return;
    }

    ret = device_cancelPairing(value);
    if (0 == ret)
    {
        afb_req_success (request, NULL, NULL);
    }
    else
    {
        afb_req_fail (request, "failed", "Device cancel pairing failed");
    }

}

/**/
static void bt_connect (struct afb_req request)
{
    LOGD("\n");

    const char *value = afb_req_value (request, "value");
    const char *uuid = afb_req_value (request, "uuid");
    int ret = 0;

    if (NULL == value)
    {
        afb_req_fail (request, "failed", "Please Input the Device Address");
        return;
    }

    ret = device_connect(value, uuid);

    if (0 == ret)
    {
        json_object *jresp = json_object_new_object();
        json_object *jstring;

        jstring = json_object_new_string("connected");
        json_object_object_add(jresp, "Status", jstring);

        jstring = json_object_new_string(value);
        json_object_object_add(jresp, "Address", jstring);

        if (uuid) {
            jstring = json_object_new_string(uuid);
            json_object_object_add(jresp, "UUID", jstring);
        }

        event_push(jresp, "connection");
        afb_req_success (request, NULL, NULL);
    }
    else
    {
        afb_req_fail (request, "failed", "Device connect failed");
    }

}

/**/
static void bt_disconnect (struct afb_req request)
{
    LOGD("\n");

    const char *value = afb_req_value (request, "value");
    const char *uuid = afb_req_value (request, "uuid");
    int ret = 0;

    if (NULL == value)
    {
        afb_req_fail (request, "failed", "Please Input the Device Address");
        return;
    }

    ret = device_disconnect(value, uuid);
    if (0 == ret)
    {
        json_object *jresp = json_object_new_object();
        json_object *jstring;

        jstring = json_object_new_string("disconnected");
        json_object_object_add(jresp, "Status", jstring);

        jstring = json_object_new_string(value);
        json_object_object_add(jresp, "Address", jstring);

        if (uuid) {
            jstring = json_object_new_string(uuid);
            json_object_object_add(jresp, "UUID", jstring);
        }

        event_push(jresp, "connection");
        afb_req_success (request, NULL, NULL);
    }
    else
    {
        afb_req_fail (request, "failed", "Device disconnect failed");
    }

}

/**/
static void bt_remove_device (struct afb_req request)
{
    LOGD("\n");

    const char *value = afb_req_value (request, "value");
    int ret = 0;

    if (NULL == value)
    {
        afb_req_fail (request, "failed", "Please Input the Device Address");
        return;
    }

    ret = adapter_remove_device(value);
    if (0 == ret)
    {
                afb_req_success (request, NULL, NULL);
    }
    else
    {
        afb_req_fail (request, "failed", "Remove Device failed");
    }

}


/**/
static void bt_set_device_property (struct afb_req request)
{
    LOGD("\n");

    const char *address = afb_req_value (request, "Address");
    const char *property = afb_req_value (request, "Property");
    const char *value = afb_req_value (request, "value");
    int ret = 0;
    GSList *list = NULL;

    if (NULL == address || NULL==property || NULL==value)
    {
        afb_req_fail (request, "failed", "Please Check Input Parameter");
        return;
    }

    ret = device_set_property(address, property, value);
    if (0 == ret)
    {
        afb_req_success (request, NULL, NULL);
    }
    else
    {
        afb_req_fail (request, "failed", "Device set property failed");
    }

}

/**/
static void bt_set_property (struct afb_req request)
{
    LOGD("\n");

    const char *property = afb_req_value (request, "Property");
    const char *value = afb_req_value (request, "value");
    int ret = 0;
    gboolean setvalue;


    if (NULL==property || NULL==value)
    {
        afb_req_fail (request, "failed", "Please Check Input Parameter");
        return;
    }


    if ( atoi(value) == 1 || !strcasecmp(value, "true") )
    {
        ret = adapter_set_property (property, TRUE);

    }

    /* "?value=" parameter is "0" or "false" */
    else if ( atoi(value) == 0 || !strcasecmp(value, "false") )
    {
        ret = adapter_set_property (property, FALSE);
    }
    else
    {
        afb_req_fail (request, "failed", "Invalid value");
        return;
    }

    if (0 == ret)
    {
        afb_req_success (request, NULL, NULL);
    }
    else
    {
        afb_req_fail (request, "failed", "Bluetooth set property failed");
    }

}

/**/
static void bt_set_avrcp_controls (struct afb_req request)
{
    LOGD("\n");

    const char *address = afb_req_value (request, "Address");
    const char *value = afb_req_value (request, "value");
    int ret = 0;
    GSList *list = NULL;

    if (NULL==value)
    {
        afb_req_fail (request, "failed", "Please Check Input Parameter");
        return;
    }

    if (NULL == address)
    {
        list = adapter_get_devices_list();
        if (NULL == list)
        {
            afb_req_fail (request, "failed", "No find devices");
            return;
        }

        for (;list;list=list->next)
        {
            struct btd_device *BDdevice = list->data;
            //LOGD("\n%s\t%s\n",BDdevice->bdaddr,BDdevice->name);
            if (BDdevice->avconnected)
            {
                address = BDdevice->bdaddr;
                break;
            }
        }
    }

    ret = device_call_avrcp_method(address, value);
    if (0 == ret)
    {
        afb_req_success (request, NULL, NULL);
    }
    else
    {
        afb_req_fail (request, "failed", "Bluetooth set avrcp control failed");
    }
}

static void eventadd (struct afb_req request)
{
	const char *tag = afb_req_value(request, "tag");
	const char *name = afb_req_value(request, "name");

	if (tag == NULL || name == NULL)
		afb_req_fail(request, "failed", "bad arguments");
	else if (0 != event_add(tag, name))
		afb_req_fail(request, "failed", "creation error");
	else
		afb_req_success(request, NULL, NULL);
}

static void eventdel (struct afb_req request)
{
	const char *tag = afb_req_value(request, "tag");

	if (tag == NULL)
		afb_req_fail(request, "failed", "bad arguments");
	else if (0 != event_del(tag))
		afb_req_fail(request, "failed", "deletion error");
	else
		afb_req_success(request, NULL, NULL);
}

static void eventsub (struct afb_req request)
{
	const char *tag = afb_req_value(request, "tag");

	if (tag == NULL)
		afb_req_fail(request, "failed", "bad arguments");
	else if (0 != event_subscribe(request, tag))
		afb_req_fail(request, "failed", "subscription error");
	else
		afb_req_success(request, NULL, NULL);
}

static void eventunsub (struct afb_req request)
{
	const char *tag = afb_req_value(request, "tag");

	if (tag == NULL)
		afb_req_fail(request, "failed", "bad arguments");
	else if (0 != event_unsubscribe(request, tag))
		afb_req_fail(request, "failed", "unsubscription error");
	else
		afb_req_success(request, NULL, NULL);
}

static void eventpush (struct afb_req request)
{
	const char *tag = afb_req_value(request, "tag");
	const char *data = afb_req_value(request, "data");
	json_object *object = data ? json_tokener_parse(data) : NULL;

	if (tag == NULL)
		afb_req_fail(request, "failed", "bad arguments");
	else if (0 > event_push(object, tag))
		afb_req_fail(request, "failed", "push error");
	else
		afb_req_success(request, NULL, NULL);
}

/*
 * broadcast new device
 */
void bt_broadcast_device_added(struct btd_device *BDdevice)
{
    unsigned int filter = BD_ADDER|BD_NAME|BD_PAIRED|BD_ACLCONNECTED|BD_AVCONNECTED|BD_HFPCONNECTED|BD_UUID_PROFILES;
    int ret;
    json_object *jresp = new_json_object_from_device(BDdevice, filter);

    LOGD("\n");
    ret = event_push(jresp,"device_added");
    //ret = afb_daemon_broadcast_event(afbitf->daemon, "device_added", jresp);
    LOGD("%d\n",ret);
}

/*
 * broadcast device removed
 */
void bt_broadcast_device_removed(struct btd_device *BDdevice)
{
    unsigned int filter = BD_ADDER;
    int ret;
    json_object *jresp = new_json_object_from_device(BDdevice, filter);

    LOGD("\n");
    ret = event_push(jresp,"device_removed");
    //ret = afb_daemon_broadcast_event(afbitf->daemon, "device_removed", jresp);
    LOGD("%d\n",ret);
}


/*
 * broadcast device updated
 */
void bt_broadcast_device_properties_change(struct btd_device *BDdevice)
{

    unsigned int filter = BD_ADDER|BD_NAME|BD_PAIRED|BD_ACLCONNECTED|BD_AVCONNECTED|BD_HFPCONNECTED|BD_AVRCP_TITLE|BD_AVRCP_ARTIST|BD_AVRCP_STATUS|BD_AVRCP_DURATION|BD_AVRCP_POSITION|BD_TRANSPORT_STATE|BD_TRANSPORT_VOLUME|BD_UUID_PROFILES;

    int ret;
    json_object *jresp = new_json_object_from_device(BDdevice, filter);

    LOGD("\n");
    ret = event_push(jresp,"device_updated");
    //ret = afb_daemon_broadcast_event(afbitf->daemon, "device_updated", jresp);
    LOGD("%d\n",ret);
}

/*
 * broadcast request confirmation
 */
gboolean bt_request_confirmation(const gchar *device, guint passkey)
{
    json_object *jresp = json_object_new_object();
    json_object *jstring = NULL;
    int ret;

    jstring = json_object_new_string(device);
    json_object_object_add(jresp, "Address", jstring);
    jstring = json_object_new_int(passkey);
    json_object_object_add(jresp, "Passkey", jstring);

    ret = event_push(jresp,"request_confirmation");
    //ret = afb_daemon_broadcast_event(afbitf->daemon, "device_updated", jresp);

    LOGD("%d\n",ret);

    if (ret >0) {
        return TRUE;
    }else {
        return FALSE;
    }

}

static void bt_send_confirmation(struct afb_req request)
{
    const char *value = afb_req_value(request, "value");
    int ret;
    gboolean confirmation;

    if (!value) {
            afb_req_fail (request, "failed", "Unable to get value status");
            return;
    }

    /* "?value=" parameter is "1" or "yes" */
    else if ( atoi(value) == 1 || !strcasecmp(value, "yes") )
    {
        ret = agent_send_confirmation (TRUE);
    }

    /* "?value=" parameter is "0" or "no" */
    else if ( atoi(value) == 0 || !strcasecmp(value, "no") )
    {
        ret = agent_send_confirmation (TRUE);
    }
    else
    {
        afb_req_fail (request, "failed", "Invalid value");
        return;
    }

    if ( 0==ret) {
        afb_req_success(request, NULL, NULL);
    }else {
        afb_req_success(request, "failed", "fail");
    }

}

/*
 * array of the verbs exported to afb-daemon
 */
static const struct afb_verb_desc_v1 binding_verbs[]= {
/* VERB'S NAME                    SESSION MANAGEMENT                FUNCTION TO CALL                    SHORT DESCRIPTION */
{ .name = "power",               .session = AFB_SESSION_NONE,      .callback = bt_power,               .info = "Set Bluetooth Power ON or OFF" },
{ .name = "start_discovery",     .session = AFB_SESSION_NONE,      .callback = bt_start_discovery,     .info = "Start discovery" },
{ .name = "stop_discovery",      .session = AFB_SESSION_NONE,      .callback = bt_stop_discovery,      .info = "Stop discovery" },
{ .name = "discovery_result",    .session = AFB_SESSION_NONE,      .callback = bt_discovery_result,    .info = "Get discovery result" },
{ .name = "remove_device",       .session = AFB_SESSION_NONE,      .callback = bt_remove_device,       .info = "Remove the special device" },
{ .name = "pair",                .session = AFB_SESSION_NONE,      .callback = bt_pair,                .info = "Pair to special device" },
{ .name = "cancel_pair",         .session = AFB_SESSION_NONE,      .callback = bt_cancel_pairing,      .info = "Cancel the pairing process" },
{ .name = "connect",             .session = AFB_SESSION_NONE,      .callback = bt_connect,             .info = "Connect to special device" },
{ .name = "disconnect",          .session = AFB_SESSION_NONE,      .callback = bt_disconnect,          .info = "Disconnect special device" },
{ .name = "set_device_property", .session = AFB_SESSION_NONE,      .callback = bt_set_device_property, .info = "Set special device property" },
{ .name = "set_property",        .session = AFB_SESSION_NONE,      .callback = bt_set_property,        .info = "Set Bluetooth property" },
{ .name = "set_avrcp_controls",  .session = AFB_SESSION_NONE,      .callback = bt_set_avrcp_controls,  .info = "Set Bluetooth AVRCP controls" },
{ .name = "send_confirmation",   .session = AFB_SESSION_NONE,      .callback = bt_send_confirmation,   .info = "Send Confirmation" },
{ .name = "eventadd",            .session = AFB_SESSION_NONE,      .callback = eventadd,               .info = "adds the event of 'name' for the 'tag'"},
{ .name = "eventdel",            .session = AFB_SESSION_NONE,      .callback = eventdel,               .info = "deletes the event of 'tag'"},
{ .name = "eventsub",            .session = AFB_SESSION_NONE,      .callback = eventsub,               .info = "subscribes to the event of 'tag'"},
{ .name = "eventunsub",          .session = AFB_SESSION_NONE,      .callback = eventunsub,             .info = "unsubscribes to the event of 'tag'"},
{ .name = "eventpush",           .session = AFB_SESSION_NONE,      .callback = eventpush,              .info = "pushs the event of 'tag' with the 'data'"},

{ .name = NULL } /* marker for end of the array */
};

/*
 * description of the binding for afb-daemon
 */
static const struct afb_binding binding_description =
{
    .type   = AFB_BINDING_VERSION_1,
    .v1 = {
        .info   = "Application Framework Binder - Bluetooth Manager plugin",
        .prefix = "Bluetooth-Manager",
        .verbs   = binding_verbs
    }
};

/*
 * activation function for registering the binding called by afb-daemon
 */
const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf)
{
    afbitf = itf;         // records the interface for accessing afb-daemon

#if 1
//temp solution to fix configure Bluetooth USB Dongle
    system("rfkill unblock bluetooth");
    system("hciconfig hci0 up");
#endif

    Binding_RegisterCallback_t API_Callback;
    API_Callback.binding_device_added = bt_broadcast_device_added;
    API_Callback.binding_device_removed = bt_broadcast_device_removed;
    API_Callback.binding_device_properties_changed = bt_broadcast_device_properties_change;
    API_Callback.binding_request_confirmation = bt_request_confirmation;
    BindingAPIRegister(&API_Callback);

    return &binding_description;
}

int afbBindingV1ServiceInit(struct afb_service service)
{
    return BluetoothManagerInit();
}


/***************************** The End Of File ******************************/