Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / profiles / deviceinfo / deviceinfo.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2012 Texas Instruments, Inc.
6  *  Copyright (C) 2015 Google Inc.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdbool.h>
29 #include <errno.h>
30
31 #include <glib.h>
32
33 #include "lib/bluetooth.h"
34 #include "lib/sdp.h"
35 #include "lib/uuid.h"
36
37 #include "src/plugin.h"
38 #include "src/adapter.h"
39 #include "src/device.h"
40 #include "src/profile.h"
41 #include "src/service.h"
42 #include "attrib/gattrib.h"
43 #include "src/shared/util.h"
44 #include "src/shared/queue.h"
45 #include "src/shared/gatt-db.h"
46 #include "src/shared/gatt-client.h"
47 #include "attrib/att.h"
48 #include "src/log.h"
49
50 #define PNP_ID_SIZE     7
51
52 static void read_pnpid_cb(bool success, uint8_t att_ecode, const uint8_t *value,
53                                         uint16_t length, void *user_data)
54 {
55         struct btd_device *device = user_data;
56
57         if (!success) {
58                 error("Error reading PNP_ID value: %s",
59                                                 att_ecode2str(att_ecode));
60                 return;
61         }
62
63         if (length < PNP_ID_SIZE) {
64                 error("Error reading PNP_ID: Invalid pdu length received");
65                 return;
66         }
67
68         btd_device_set_pnpid(device, value[0], get_le16(&value[1]),
69                                 get_le16(&value[3]), get_le16(&value[5]));
70 }
71
72 static void handle_pnpid(struct btd_device *device, uint16_t value_handle)
73 {
74         struct bt_gatt_client *client = btd_device_get_gatt_client(device);
75
76         if (!bt_gatt_client_read_value(client, value_handle,
77                                                 read_pnpid_cb, device, NULL))
78                 DBG("Failed to send request to read pnpid");
79 }
80
81 static void handle_characteristic(struct gatt_db_attribute *attr,
82                                                                 void *user_data)
83 {
84         struct btd_device *device = user_data;
85         uint16_t value_handle;
86         bt_uuid_t uuid, pnpid_uuid;
87
88         bt_string_to_uuid(&pnpid_uuid, PNPID_UUID);
89
90         if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle, NULL,
91                                                                 &uuid)) {
92                 error("Failed to obtain characteristic data");
93                 return;
94         }
95
96         if (bt_uuid_cmp(&pnpid_uuid, &uuid) == 0)
97                 handle_pnpid(device, value_handle);
98         else {
99                 char uuid_str[MAX_LEN_UUID_STR];
100
101                 bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
102                 DBG("Unsupported characteristic: %s", uuid_str);
103         }
104 }
105
106 static void foreach_deviceinfo_service(struct gatt_db_attribute *attr,
107                                                                 void *user_data)
108 {
109         struct btd_device *device = user_data;
110
111         gatt_db_service_foreach_char(attr, handle_characteristic, device);
112 }
113
114 static int deviceinfo_driver_probe(struct btd_service *service)
115 {
116         return 0;
117 }
118
119 static void deviceinfo_driver_remove(struct btd_service *service)
120 {
121 }
122
123
124 static int deviceinfo_driver_accept(struct btd_service *service)
125 {
126         struct btd_device *device = btd_service_get_device(service);
127         struct gatt_db *db = btd_device_get_gatt_db(device);
128         char addr[18];
129         bt_uuid_t deviceinfo_uuid;
130
131         ba2str(device_get_address(device), addr);
132         DBG("deviceinfo profile accept (%s)", addr);
133
134         /* Handle the device info service */
135         bt_string_to_uuid(&deviceinfo_uuid, DEVICE_INFORMATION_UUID);
136         gatt_db_foreach_service(db, &deviceinfo_uuid,
137                                         foreach_deviceinfo_service, device);
138
139         return 0;
140 }
141
142 static struct btd_profile deviceinfo_profile = {
143         .name           = "deviceinfo",
144         .remote_uuid    = DEVICE_INFORMATION_UUID,
145         .external       = true,
146         .device_probe   = deviceinfo_driver_probe,
147         .device_remove  = deviceinfo_driver_remove,
148         .accept         = deviceinfo_driver_accept,
149 };
150
151 static int deviceinfo_init(void)
152 {
153         return btd_profile_register(&deviceinfo_profile);
154 }
155
156 static void deviceinfo_exit(void)
157 {
158         btd_profile_unregister(&deviceinfo_profile);
159 }
160
161 BLUETOOTH_PLUGIN_DEFINE(deviceinfo, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
162                                         deviceinfo_init, deviceinfo_exit)