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
|
// SPDX-License-Identifier: GPL-2.0-or-later
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012 Texas Instruments, Inc.
* Copyright (C) 2015 Google Inc.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdbool.h>
#include <errno.h>
#include <glib.h>
#include "lib/bluetooth.h"
#include "lib/sdp.h"
#include "lib/uuid.h"
#include "src/plugin.h"
#include "src/adapter.h"
#include "src/device.h"
#include "src/profile.h"
#include "src/service.h"
#include "attrib/gattrib.h"
#include "src/shared/util.h"
#include "src/shared/queue.h"
#include "src/shared/gatt-db.h"
#include "src/shared/gatt-client.h"
#include "attrib/att.h"
#include "src/log.h"
#define PNP_ID_SIZE 7
static void read_pnpid_cb(bool success, uint8_t att_ecode, const uint8_t *value,
uint16_t length, void *user_data)
{
struct btd_device *device = user_data;
if (!success) {
error("Error reading PNP_ID value: %s",
att_ecode2str(att_ecode));
return;
}
if (length < PNP_ID_SIZE) {
error("Error reading PNP_ID: Invalid pdu length received");
return;
}
btd_device_set_pnpid(device, value[0], get_le16(&value[1]),
get_le16(&value[3]), get_le16(&value[5]));
}
static void handle_pnpid(struct btd_device *device, uint16_t value_handle)
{
struct bt_gatt_client *client = btd_device_get_gatt_client(device);
if (!bt_gatt_client_read_value(client, value_handle,
read_pnpid_cb, device, NULL))
DBG("Failed to send request to read pnpid");
}
static void handle_characteristic(struct gatt_db_attribute *attr,
void *user_data)
{
struct btd_device *device = user_data;
uint16_t value_handle;
bt_uuid_t uuid, pnpid_uuid;
bt_string_to_uuid(&pnpid_uuid, PNPID_UUID);
if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle, NULL,
NULL, &uuid)) {
error("Failed to obtain characteristic data");
return;
}
if (bt_uuid_cmp(&pnpid_uuid, &uuid) == 0)
handle_pnpid(device, value_handle);
else {
char uuid_str[MAX_LEN_UUID_STR];
bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
DBG("Unsupported characteristic: %s", uuid_str);
}
}
static void foreach_deviceinfo_service(struct gatt_db_attribute *attr,
void *user_data)
{
struct btd_device *device = user_data;
gatt_db_service_foreach_char(attr, handle_characteristic, device);
}
static int deviceinfo_probe(struct btd_service *service)
{
return 0;
}
static void deviceinfo_remove(struct btd_service *service)
{
}
static int deviceinfo_accept(struct btd_service *service)
{
struct btd_device *device = btd_service_get_device(service);
struct gatt_db *db = btd_device_get_gatt_db(device);
char addr[18];
bt_uuid_t deviceinfo_uuid;
ba2str(device_get_address(device), addr);
DBG("deviceinfo profile accept (%s)", addr);
/* Handle the device info service */
bt_string_to_uuid(&deviceinfo_uuid, DEVICE_INFORMATION_UUID);
gatt_db_foreach_service(db, &deviceinfo_uuid,
foreach_deviceinfo_service, device);
btd_service_connecting_complete(service, 0);
return 0;
}
static int deviceinfo_disconnect(struct btd_service *service)
{
btd_service_disconnecting_complete(service, 0);
return 0;
}
static struct btd_profile deviceinfo_profile = {
.name = "deviceinfo",
.remote_uuid = DEVICE_INFORMATION_UUID,
.device_probe = deviceinfo_probe,
.device_remove = deviceinfo_remove,
.accept = deviceinfo_accept,
.disconnect = deviceinfo_disconnect,
};
static int deviceinfo_init(void)
{
return btd_profile_register(&deviceinfo_profile);
}
static void deviceinfo_exit(void)
{
btd_profile_unregister(&deviceinfo_profile);
}
BLUETOOTH_PLUGIN_DEFINE(deviceinfo, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
deviceinfo_init, deviceinfo_exit)
|