summaryrefslogtreecommitdiff
path: root/src/dbus/server/bluez-manager.h
blob: 99cf4a33e60c1bfe7a4b076e96a9e4fb5c8fd098 (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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/*
 * Copyright (C) 2011 Intel Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) version 3.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#ifndef BLUEZ_MANAGER_H
#define BLUEZ_MANAGER_H

#include <string>

#include "gdbus-cxx-bridge.h"

#include <boost/utility.hpp>

#include <syncevo/declarations.h>

SE_BEGIN_CXX

class Server;
class GLibNotify;

/**
 * Query bluetooth devices from org.bluez
 * The basic workflow is:
 * 1) get default adapter from bluez by calling 'DefaultAdapter' method of org.bluez.Manager
 * 2) get all devices of the adapter by calling 'ListDevices' method of org.bluez.Adapter
 * 3) iterate all devices and get properties for each one by calling 'GetProperties' method of org.bluez.Device.
 *    Then check its UUIDs whether it contains sync services and put it in the sync device list if it is. If this
 *    is a sync device we then call DiscoverServices to check for the PnPInformation service record.
 *
 * To track changes of devices dynamically, here also listen signals from bluez:
 * org.bluez.Manager - DefaultAdapterChanged: default adapter is changed and thus have to get its devices
 *                                            and update sync device list
 * org.bluez.Adapter - DeviceCreated, DeviceRemoved: device is created or removed and device list is updated
 * org.bluez.Device - PropertyChanged: property is changed and device information is changed and tracked
 *
 * This class is to manage querying bluetooth devices from org.bluez. Also
 * it acts a proxy to org.bluez.Manager.
 */
class BluezManager : public GDBusCXX::DBusRemoteObject {
public:
    BluezManager(Server &server);
    bool isDone() { return m_done; }

private:
    class BluezDevice;

    /**
     * This class acts a proxy to org.bluez.Adapter.
     * Call methods of org.bluez.Adapter and listen signals from it
     * to get devices list and track its changes
     */
    class BluezAdapter: public GDBusCXX::DBusRemoteObject
    {
     public:
        BluezAdapter (BluezManager &manager, const std::string &path);

        void checkDone(bool forceDone = false)
        {
            if(forceDone || m_devReplies >= m_devNo) {
                m_devReplies = m_devNo = 0;
                m_manager.setDone(true);
            } else {
                m_manager.setDone(false);
            }
        }

        std::vector<boost::shared_ptr<BluezDevice> >& getDevices() { return m_devices; }

     private:
        /** callback of 'ListDevices' signal. Used to get all available devices of the adapter */
        void listDevicesCb(const std::vector<GDBusCXX::DBusObject_t> &devices, const std::string &error);

        /** callback of 'DeviceRemoved' signal. Used to track a device is removed */
        void deviceRemoved(const GDBusCXX::DBusObject_t &object);

        /** callback of 'DeviceCreated' signal. Used to track a new device is created */
        void deviceCreated(const GDBusCXX::DBusObject_t &object);

        BluezManager &m_manager;
        /** the number of device for the default adapter */
        int m_devNo;
        /** the number of devices having reply */
        int m_devReplies;

        /** all available devices */
        std::vector<boost::shared_ptr<BluezDevice> > m_devices;

        /** represents 'DeviceRemoved' signal of org.bluez.Adapter*/
        GDBusCXX::SignalWatch1<GDBusCXX::DBusObject_t> m_deviceRemoved;
        /** represents 'DeviceAdded' signal of org.bluez.Adapter*/
        GDBusCXX::SignalWatch1<GDBusCXX::DBusObject_t> m_deviceAdded;

        friend class BluezDevice;
    };

    /**
     * This class acts a proxy to org.bluez.Device.
     * Call methods of org.bluez.Device and listen signals from it
     * to get properties of device and track its changes
     */
    class BluezDevice: public GDBusCXX::DBusRemoteObject
    {
     public:
        typedef std::map<std::string, boost::variant<std::vector<std::string>, std::string > > PropDict;
        typedef std::map<uint32_t, std::string> ServiceDict;

        BluezDevice (BluezAdapter &adapter, const std::string &path);

        std::string getMac() { return m_mac; }

        /**
         * check whether the current device has sync service if yes,
         * put it in the adapter's sync devices list
         */
        void checkSyncService(const std::vector<std::string> &uuids);

     private:
        /** callback of 'GetProperties' method. The properties of the device is gotten */
        void getPropertiesCb(const PropDict &props, const std::string &error);

        /** callback of 'DiscoverServices' method. The service records are retrieved */
        void discoverServicesCb(const ServiceDict &serviceDict, const std::string &error);

        /** callback of 'PropertyChanged' signal. Changed property is tracked */
        void propertyChanged(const std::string &name, const boost::variant<std::vector<std::string>, std::string> &prop);

        BluezAdapter &m_adapter;
        /** name of the device */
        std::string m_name;
        /** mac address of the device */
        std::string m_mac;
        /** whether the calling of 'GetProperties' is returned */
        bool m_reply;

        typedef GDBusCXX::SignalWatch2<std::string, boost::variant<std::vector<std::string>, std::string> > PropertySignal;
        /** represents 'PropertyChanged' signal of org.bluez.Device */
        PropertySignal m_propertyChanged;

        friend class BluezAdapter;
    };

    /*
     * check whether the data is generated. If errors, force initilization done
     */
    void setDone(bool done) { m_done = done; }

    /** callback of 'DefaultAdapter' method to get the default bluetooth adapter  */
    void defaultAdapterCb(const GDBusCXX::DBusObject_t &adapter, const std::string &error);

    /** callback of 'DefaultAdapterChanged' signal to track changes of the default adapter */
    void defaultAdapterChanged(const GDBusCXX::DBusObject_t &adapter);

    Server &m_server;
    GDBusCXX::DBusConnectionPtr m_bluezConn;
    boost::shared_ptr<BluezAdapter> m_adapter;

    // Holds the bluetooth lookup table and whether it was successfully loaded.
    class lookupTable : private boost::noncopyable {
    public:
        lookupTable() : bt_key_file(NULL), isLoaded(false) {}
        ~lookupTable() { if (bt_key_file) g_key_file_free(bt_key_file); }

        GKeyFile *bt_key_file;
        bool isLoaded;
    } m_lookupTable;

    boost::shared_ptr<GLibNotify> m_watchedFile;
    void loadBluetoothDeviceLookupTable();
    bool getPnpInfoNamesFromValues(const std::string &vendorValue,  std::string &vendorName,
                                   const std::string &productValue, std::string &productName);

    /** represents 'DefaultAdapterChanged' signal of org.bluez.Adapter*/
    GDBusCXX::SignalWatch1<GDBusCXX::DBusObject_t> m_adapterChanged;

    /** flag to indicate whether the calls are all returned */
    bool m_done;
};

SE_END_CXX

#endif // BLUEZ_MANAGER_H