3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2012 Marcel Holtmann <marcel@holtmann.org>
6 * Copyright (C) 2012 Nordic Semiconductor Inc.
7 * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include <sys/types.h>
40 #include "lib/bluetooth.h"
45 #include "src/adapter.h"
46 #include "src/device.h"
47 #include "src/profile.h"
48 #include "src/service.h"
49 #include "src/shared/util.h"
50 #include "src/shared/uhid.h"
51 #include "src/shared/queue.h"
52 #include "src/plugin.h"
55 #include "attrib/att.h"
56 #include "attrib/gattrib.h"
57 #include "src/attio.h"
58 #include "attrib/gatt.h"
61 #define HOG_UUID "00001812-0000-1000-8000-00805f9b34fb"
65 struct btd_device *device;
69 static gboolean suspend_supported = FALSE;
70 static struct queue *devices = NULL;
72 static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
74 struct hog_device *dev = user_data;
78 bt_hog_attach(dev->hog, attrib);
81 static void attio_disconnected_cb(gpointer user_data)
83 struct hog_device *dev = user_data;
85 DBG("HoG disconnected");
87 bt_hog_detach(dev->hog);
90 static struct hog_device *hog_device_new(struct btd_device *device,
91 struct gatt_primary *prim)
93 struct hog_device *dev;
95 uint16_t vendor, product, version;
97 if (device_name_known(device))
98 device_get_name(device, name, sizeof(name));
100 strcpy(name, "bluez-hog-device");
102 vendor = btd_device_get_vendor(device);
103 product = btd_device_get_product(device);
104 version = btd_device_get_version(device);
106 DBG("name=%s vendor=0x%X, product=0x%X, version=0x%X", name, vendor,
109 dev = new0(struct hog_device, 1);
110 dev->device = btd_device_ref(device);
111 dev->hog = bt_hog_new_default(name, vendor, product, version, prim);
114 * TODO: Remove attio callback and use .accept once using
117 dev->attioid = btd_device_add_attio_callback(device,
119 attio_disconnected_cb,
123 devices = queue_new();
125 queue_push_tail(devices, dev);
130 static void hog_device_free(void *data)
132 struct hog_device *dev = data;
134 queue_remove(devices, dev);
135 if (queue_isempty(devices)) {
136 queue_destroy(devices, NULL);
140 btd_device_remove_attio_callback(dev->device, dev->attioid);
141 btd_device_unref(dev->device);
142 bt_hog_unref(dev->hog);
146 static void set_suspend(gpointer data, gpointer user_data)
148 struct hog_device *dev = data;
149 gboolean suspend = GPOINTER_TO_INT(user_data);
151 bt_hog_set_control_point(dev->hog, suspend);
154 static void suspend_callback(void)
156 gboolean suspend = TRUE;
158 DBG("Suspending ...");
160 queue_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
163 static void resume_callback(void)
165 gboolean suspend = FALSE;
169 queue_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
172 static int hog_probe(struct btd_service *service)
174 struct btd_device *device = btd_service_get_device(service);
175 const char *path = device_get_path(device);
176 GSList *primaries, *l;
178 DBG("path %s", path);
180 primaries = btd_device_get_primaries(device);
181 if (primaries == NULL)
184 for (l = primaries; l; l = g_slist_next(l)) {
185 struct gatt_primary *prim = l->data;
186 struct hog_device *dev;
188 if (strcmp(prim->uuid, HOG_UUID) != 0)
191 dev = hog_device_new(device, prim);
192 btd_service_set_user_data(service, dev);
199 static void hog_remove(struct btd_service *service)
201 struct hog_device *dev = btd_service_get_user_data(service);
202 struct btd_device *device = btd_service_get_device(service);
203 const char *path = device_get_path(device);
205 DBG("path %s", path);
207 hog_device_free(dev);
210 static struct btd_profile hog_profile = {
212 .remote_uuid = HOG_UUID,
213 .device_probe = hog_probe,
214 .device_remove = hog_remove,
217 static int hog_init(void)
221 err = suspend_init(suspend_callback, resume_callback);
223 error("Loading suspend plugin failed: %s (%d)", strerror(-err),
226 suspend_supported = TRUE;
228 return btd_profile_register(&hog_profile);
231 static void hog_exit(void)
233 if (suspend_supported)
236 btd_profile_unregister(&hog_profile);
239 BLUETOOTH_PLUGIN_DEFINE(hog, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,