1 /* ****************************************************************
3 * Copyright 2015 Intel Corporation All Rights Reserved.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************/
20 #include "gatt_dbus.h"
24 #include "cagattservice.h"
31 static char const TAG[] = "BLE_SERVICE";
33 static GVariant * CAGattServiceGetProperties(GattService1 * service)
36 Create a variant containing the @c GattService1 properties, of
37 the form @c a{sa{sv}}.
41 * Populate the property table, and create the variant to be
42 * embedded in the results of the
43 * @c org.freedesktop.Dbus.ObjectManager.GetManagedObjects()
46 * The @c "Device" property is only available on the client side
47 * so we don't bother returning it here.
49 * @todo Do we care about the @c "Includes" property?
50 * @c "Includes" isn't implemented by BlueZ as of version
51 * 5.30, so we can leave it out.
53 CADBusSkeletonProperty const properties[] = {
55 g_variant_new_string(gatt_service1_get_uuid(service)) },
57 g_variant_new_boolean(gatt_service1_get_primary(service)) },
60 gatt_service1_get_characteristics(service),
65 CAMakePropertyDictionary(
66 BLUEZ_GATT_SERVICE_INTERFACE,
68 sizeof(properties) / sizeof(properties[0]));
72 * Implementation of the
73 * @c org.freedesktop.DBus.ObjectManager.GetManagedObjects() method
74 * for the @c org.bluez.GattService1 interface.
76 static gboolean CAGattServiceHandleGetManagedObjects(
77 ObjectManager * object,
78 GDBusMethodInvocation * invocation,
82 * @note Ideally we shouldn't need this implementation, and should
83 * be able to simply rely GDBusObjectManagerServer instead.
84 * Unfortunately, BlueZ expects the @c
85 * org.bluez.GattService1 object to implement the @c
86 * ObjectManager interface, and both interfaces must rooted
87 * at the same object path, as well. That requirement
88 * prevents us from using @c GDBusObjectManagerServer since
89 * it won't allow us to export more than interface on a
94 Build the object array containing the IoTivity
95 org.bluez.GattService1 hierarchy.
99 CAGattService * const service = user_data;
101 GVariantBuilder builder;
102 g_variant_builder_init(&builder, G_VARIANT_TYPE("a{oa{sa{sv}}}"));
104 // Start out with the service itself.
105 g_variant_builder_add(&builder,
107 service->object_path,
108 CAGattServiceGetProperties(service->service));
111 Add the request characteristic and user description
114 CAGattCharacteristic * const request_chrc =
115 &service->request_characteristic;
117 g_variant_builder_add(&builder,
119 request_chrc->object_path,
120 CAGattCharacteristicGetProperties(
121 request_chrc->characteristic));
123 CAGattDescriptor * const request_desc = &request_chrc->descriptor;
125 g_variant_builder_add(&builder,
127 request_desc->object_path,
128 CAGattDescriptorGetProperties(
129 request_desc->descriptor));
132 Add the response characteristic and user description
135 CAGattCharacteristic * const response_chrc =
136 &service->response_characteristic;
138 g_variant_builder_add(&builder,
140 response_chrc->object_path,
141 CAGattCharacteristicGetProperties(
142 response_chrc->characteristic));
144 CAGattDescriptor * const response_desc = &response_chrc->descriptor;
146 g_variant_builder_add(&builder,
148 response_desc->object_path,
149 CAGattDescriptorGetProperties(
150 response_desc->descriptor));
152 GVariant * const objects = g_variant_builder_end(&builder);
154 object_manager_complete_get_managed_objects(object,
161 bool CAGattServiceInitialize(CAGattService * s,
162 CALEContext * context,
163 char const * hci_name)
166 assert(context != NULL);
167 assert(hci_name != NULL);
169 // Path of the form /org/iotivity/gatt/hci0/service0.
171 g_strdup_printf("%s/%s/%s",
172 CA_GATT_SERVICE_ROOT_PATH,
174 CA_GATT_SERVICE_PATH);
176 assert(g_variant_is_object_path(s->object_path));
178 s->object_manager = object_manager_skeleton_new();
179 s->service = gatt_service1_skeleton_new();
181 gatt_service1_set_uuid(s->service, CA_GATT_SERVICE_UUID);
182 gatt_service1_set_primary(s->service, TRUE);
184 if (!CAGattRequestCharacteristicInitialize(s, context)
185 || !CAGattResponseCharacteristicInitialize(s, context))
187 CAGattServiceDestroy(s);
192 The characteristic object paths are not fixed at compile-time.
193 Retrieve the object paths that were set at run-time.
195 char const * characteristic_paths[] = {
196 s->request_characteristic.object_path,
197 s->response_characteristic.object_path,
201 gatt_service1_set_characteristics(s->service, characteristic_paths);
204 Set the org.freedesktop.DBus.ObjectManager.GetManagedObjects()
205 handler for our BlueZ GATT service.
209 "handle-get-managed-objects",
210 G_CALLBACK(CAGattServiceHandleGetManagedObjects),
214 BlueZ expects both the org.freedesktop.DBus.ObjectManager and
215 org.bluez.GattService1 interfaces to be rooted at the same
216 object path. Export the service and object manager interface
217 skeletons with the same object path.
219 GError * error = NULL;
220 if (!g_dbus_interface_skeleton_export(
221 G_DBUS_INTERFACE_SKELETON(s->object_manager),
225 || !g_dbus_interface_skeleton_export(
226 G_DBUS_INTERFACE_SKELETON(s->service),
233 "Unable to export GATT service interfaces: %s",
242 void CAGattServiceDestroy(CAGattService * s)
245 * @todo If necessary, emit the
246 * @c org.freedesktop.DBus.ObjectManager.InterfacesRemoved
247 * signal via @c object_manager_emit_interfaces_removed() if
248 * the CA GATT service objects were removed from the
252 assert(s != NULL); // As designed, s is always non-NULL.
254 g_clear_object(&s->gatt_manager);
256 CAGattCharacteristicDestroy(&s->response_characteristic);
257 CAGattCharacteristicDestroy(&s->request_characteristic);
259 g_clear_object(&s->service);
260 g_clear_object(&s->object_manager);
262 g_free(s->object_path);
263 s->object_path = NULL;