Imported Upstream version 1.2.0
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / linux / descriptor.c
1 /* ****************************************************************
2  *
3  * Copyright 2015 Intel Corporation All Rights Reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  ******************************************************************/
18
19 #include "descriptor.h"
20 #include "service.h"
21 #include "gatt_dbus.h"
22 #include "utils.h"
23 #include "bluez.h"
24
25 #include "logger.h"
26 #include "cagattservice.h"
27
28 #include <assert.h>
29
30
31 // Logging tag.
32 static char const TAG[] = "BLE_DESCRIPTOR";
33
34 /**
35  * Implementation of the @c org.bluez.GattDescriptor1.ReadValue()
36  * method.
37  *
38  * This function is implemented as a GDBus signal handler that returns
39  * a byte array containing the @c Value property of the GATT
40  * descriptor.
41  *
42  * @param[in] object     @c org.bluez.GattDescriptoror1 skeleton
43  *                       object associated with this method call.
44  * @param[in] invocation D-Bus method invocation related object used
45  *                       when sending results/errors asynchronously.
46  * @param[in] user_data  Unused.
47  *
48  * @return @c TRUE to indicate that
49  *         @c org.bluez.Descriptor.ReadValue()
50  *         method is implemented.
51  */
52 static gboolean CAGattDescriptorReadValue(
53     GattDescriptor1 * object,
54     GDBusMethodInvocation * invocation,
55     gpointer user_data)
56 {
57     (void)user_data;
58     /**
59      * @todo The @c GattDescriptor1 object still owns the returned
60      *       variant when using the below call.  Should be we use
61      *       @c gatt_descriptor1_dup_value() instead?
62      */
63     GVariant * const value = gatt_descriptor1_get_value(object);
64
65     gatt_descriptor1_complete_read_value(object, invocation, value);
66
67     return TRUE;
68 }
69
70 /**
71  * Initialize GATT descriptor fields.
72  *
73  * This function initializes the @c CAGattDescriptor object fields.
74  *
75  * @param[out] c               Information about GATT characteristic
76  *                             to which the descriptor belongs.
77  * @param[in]  connection      D-Bus connection to the bus on which
78  *                             the descriptor will be exported.
79  * @param[in]  s               Information about GATT service
80  *                             information to which the descriptor
81  *                             belongs.
82  * @param[in]  descriptor_path @c GattDescriptor1 object path for the
83  *                             user description descriptor.
84  * @param[in]  value           User description descriptor value,
85  *                             e.g. @c "OCF Node Request" or
86  *                             @c "OCF Node Response".
87  *
88  * @note This function does not allocate the @a descriptor object
89  *       itself.  The caller is responsible for allocating that
90  *       memory.
91  *
92  * @todo Too many parameters.  Perhaps pass in a pointer to a struct
93  *       instead.
94  */
95 static bool CAGattDescriptorInitialize(CAGattCharacteristic * c,
96                                        GDBusConnection * connection,
97                                        CAGattService * s,
98                                        char const * descriptor_path,
99                                        char const * value)
100 {
101     (void)s;
102     CAGattDescriptor * const d = &c->descriptor;
103
104     // Path of the form /org/iotivity/gatt/hci0/service0/char0/desc0.
105     d->object_path =
106         g_strdup_printf("%s/%s", c->object_path, descriptor_path);
107     assert(g_variant_is_object_path(d->object_path));
108
109     d->descriptor = gatt_descriptor1_skeleton_new();
110
111     gatt_descriptor1_set_uuid(
112         d->descriptor,
113         CA_GATT_CHRC_USER_DESCRIPTION_DESC_UUID);
114
115     gatt_descriptor1_set_characteristic(d->descriptor,
116                                         c->object_path);
117
118     gatt_descriptor1_set_value (d->descriptor,
119                                 g_variant_new_bytestring(value));
120
121     // Readable, no encryption, no authorization.
122     static char const * const flags[] = { "read", NULL };
123     gatt_descriptor1_set_flags(d->descriptor, flags);
124
125     /*
126       Connect the signal handler that implements the
127       orb.bluez.GattDescriptor1.ReadValue() method.
128     */
129     g_signal_connect(d->descriptor,
130                      "handle-read-value",
131                      G_CALLBACK(CAGattDescriptorReadValue),
132                      NULL);
133
134     // Export the descriptor interface on the bus.
135     GError * error = NULL;
136     if (!g_dbus_interface_skeleton_export(
137             G_DBUS_INTERFACE_SKELETON(d->descriptor),
138             connection,
139             d->object_path,
140             &error))
141     {
142         CAGattDescriptorDestroy(d);
143
144         OIC_LOG_V(ERROR,
145                   TAG,
146                   "Unable to export D-Bus GATT descriptor "
147                   "interface: %s",
148                   error->message);
149
150         g_error_free(error);
151
152         return false;
153     }
154
155     return true;
156 }
157
158 bool CAGattRequestDescriptorInitialize(struct CAGattService * s,
159                                        GDBusConnection * connection)
160 {
161     CAGattCharacteristic * const c = &s->request_characteristic;
162
163     return CAGattDescriptorInitialize(c,
164                                       connection,
165                                       s,
166                                       CA_GATT_REQUEST_USER_DESC_PATH,
167                                       CA_GATT_REQUEST_USER_DESCRIPTION);
168 }
169
170 bool CAGattResponseDescriptorInitialize(struct CAGattService * s,
171                                         GDBusConnection * connection)
172 {
173     CAGattCharacteristic * const c = &s->response_characteristic;
174
175     return CAGattDescriptorInitialize(c,
176                                       connection,
177                                       s,
178                                       CA_GATT_RESPONSE_USER_DESC_PATH,
179                                       CA_GATT_RESPONSE_USER_DESCRIPTION);
180 }
181
182 void CAGattDescriptorDestroy(CAGattDescriptor * d)
183 {
184     assert(d != NULL);  // As designed, d is always non-NULL.
185
186     g_clear_object(&d->descriptor);
187
188     g_free(d->object_path);
189     d->object_path = NULL;
190 }
191
192 GVariant * CAGattDescriptorGetProperties(GattDescriptor1 * descriptor)
193 {
194     /**
195      * Create a variant containing the @c GattDescriptor1 properties,
196      * of the form @c a{sa{sv}}.
197      *
198      * @note We don't care about the "Value" property here since it is
199      *       automatically made available by BlueZ on the client
200      *       side.
201      */
202
203     /*
204       Populate the property table, and create the variant to be
205       embedded in the results of the
206       org.freedesktop.Dbus.ObjectManager.GetManagedObjects() method
207       call.
208     */
209     CADBusSkeletonProperty const properties[] = {
210         { "UUID",
211           g_variant_new_string(
212               gatt_descriptor1_get_uuid(descriptor)) },
213         { "Characteristic",
214           g_variant_new_object_path(
215               gatt_descriptor1_get_characteristic(descriptor)) },
216         { "Flags",
217           g_variant_new_strv(
218               gatt_descriptor1_get_flags(descriptor),
219               -1) }
220     };
221
222     return
223         CAMakePropertyDictionary(
224             BLUEZ_GATT_DESCRIPTOR_INTERFACE,
225             properties,
226             sizeof(properties) / sizeof(properties[0]));
227 }