Sharvil Nanavati | 3cf59ef | 2014-04-09 22:20:40 -0700 | [diff] [blame] | 1 | /****************************************************************************** |
| 2 | * |
Jakub Pawlowski | 5b790fe | 2017-09-18 09:00:20 -0700 | [diff] [blame] | 3 | * Copyright 2014 Google, Inc. |
Sharvil Nanavati | 3cf59ef | 2014-04-09 22:20:40 -0700 | [diff] [blame] | 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 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 19 | #include "btcore/include/property.h" |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 20 | #include <base/logging.h> |
Etan Cohen | 3e59b5b | 2015-03-31 17:15:53 -0700 | [diff] [blame] | 21 | #include <string.h> |
Chris Manton | 97c5444 | 2015-01-07 13:34:18 -0800 | [diff] [blame] | 22 | #include "btcore/include/device_class.h" |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 23 | #include "osi/include/allocator.h" |
Pavlin Radoslavov | c5c668a | 2017-09-07 16:22:53 -0700 | [diff] [blame] | 24 | #include "osi/include/compat.h" |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 25 | |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 26 | using bluetooth::Uuid; |
| 27 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 28 | static bt_property_t* property_new_(void* val, size_t len, |
| 29 | bt_property_type_t type); |
Sharvil Nanavati | 3cf59ef | 2014-04-09 22:20:40 -0700 | [diff] [blame] | 30 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 31 | bt_property_t* property_copy_array(const bt_property_t* properties, |
| 32 | size_t count) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 33 | CHECK(properties != NULL); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 34 | bt_property_t* clone = |
| 35 | static_cast<bt_property_t*>(osi_calloc(sizeof(bt_property_t) * count)); |
Sharvil Nanavati | 3cf59ef | 2014-04-09 22:20:40 -0700 | [diff] [blame] | 36 | |
| 37 | memcpy(&clone[0], &properties[0], sizeof(bt_property_t) * count); |
| 38 | for (size_t i = 0; i < count; ++i) { |
Chris Manton | 5c26224 | 2014-10-14 22:00:32 -0700 | [diff] [blame] | 39 | clone[i].val = osi_calloc(clone[i].len); |
Sharvil Nanavati | 3cf59ef | 2014-04-09 22:20:40 -0700 | [diff] [blame] | 40 | memcpy(clone[i].val, properties[i].val, clone[i].len); |
| 41 | } |
| 42 | |
| 43 | return clone; |
| 44 | } |
| 45 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 46 | bt_property_t* property_copy(bt_property_t* dest, const bt_property_t* src) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 47 | CHECK(dest != NULL); |
| 48 | CHECK(src != NULL); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 49 | return (bt_property_t*)memcpy(dest, src, sizeof(bt_property_t)); |
Chris Manton | 97c5444 | 2015-01-07 13:34:18 -0800 | [diff] [blame] | 50 | } |
| 51 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 52 | bool property_equals(const bt_property_t* p1, const bt_property_t* p2) { |
Sharvil Nanavati | 3cf59ef | 2014-04-09 22:20:40 -0700 | [diff] [blame] | 53 | // Two null properties are not the same. May need to revisit that |
| 54 | // decision when we have a test case that exercises that condition. |
| 55 | if (!p1 || !p2 || p1->type != p2->type) { |
| 56 | return false; |
| 57 | } |
| 58 | |
| 59 | // Although the Bluetooth name is a 249-byte array, the implementation |
| 60 | // treats it like a variable-length array with its size specified in the |
| 61 | // property's `len` field. We special-case the equivalence of BDNAME |
| 62 | // types here by truncating the larger, zero-padded name to its string |
| 63 | // length and comparing against the shorter name. |
| 64 | // |
| 65 | // Note: it may be the case that both strings are zero-padded but that |
| 66 | // hasn't come up yet so this implementation doesn't handle it. |
| 67 | if (p1->type == BT_PROPERTY_BDNAME && p1->len != p2->len) { |
| 68 | const bt_property_t *shorter = p1, *longer = p2; |
| 69 | if (p1->len > p2->len) { |
| 70 | shorter = p2; |
| 71 | longer = p1; |
| 72 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 73 | return strlen((const char*)longer->val) == (size_t)shorter->len && |
| 74 | !memcmp(longer->val, shorter->val, shorter->len); |
Sharvil Nanavati | 3cf59ef | 2014-04-09 22:20:40 -0700 | [diff] [blame] | 75 | } |
| 76 | |
| 77 | return p1->len == p2->len && !memcmp(p1->val, p2->val, p1->len); |
| 78 | } |
| 79 | |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 80 | bt_property_t* property_new_addr(const RawAddress* addr) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 81 | CHECK(addr != NULL); |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 82 | return property_new_((void*)addr, sizeof(RawAddress), BT_PROPERTY_BDADDR); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 83 | } |
| 84 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 85 | bt_property_t* property_new_device_class(const bt_device_class_t* dc) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 86 | CHECK(dc != NULL); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 87 | return property_new_((void*)dc, sizeof(bt_device_class_t), |
| 88 | BT_PROPERTY_CLASS_OF_DEVICE); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 89 | } |
| 90 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 91 | bt_property_t* property_new_device_type(bt_device_type_t type) { |
| 92 | return property_new_((void*)&type, sizeof(bt_device_type_t), |
| 93 | BT_PROPERTY_TYPE_OF_DEVICE); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 94 | } |
| 95 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 96 | bt_property_t* property_new_discovery_timeout(const uint32_t timeout) { |
| 97 | return property_new_((void*)&timeout, sizeof(uint32_t), |
| 98 | BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 99 | } |
| 100 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 101 | bt_property_t* property_new_name(const char* name) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 102 | CHECK(name != NULL); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 103 | return property_new_((void*)name, sizeof(bt_bdname_t), BT_PROPERTY_BDNAME); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 104 | } |
| 105 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 106 | bt_property_t* property_new_rssi(int8_t rssi) { |
| 107 | return property_new_((void*)&rssi, sizeof(int8_t), BT_PROPERTY_REMOTE_RSSI); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 108 | } |
| 109 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 110 | bt_property_t* property_new_scan_mode(bt_scan_mode_t scan_mode) { |
| 111 | return property_new_((void*)&scan_mode, sizeof(bt_scan_mode_t), |
| 112 | BT_PROPERTY_ADAPTER_SCAN_MODE); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 113 | } |
| 114 | |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 115 | bt_property_t* property_new_uuids(const Uuid* uuid, size_t count) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 116 | CHECK(uuid != NULL); |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 117 | return property_new_((void*)uuid, sizeof(Uuid) * count, BT_PROPERTY_UUIDS); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 118 | } |
| 119 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 120 | void property_free(bt_property_t* property) { |
Sharvil Nanavati | 3cf59ef | 2014-04-09 22:20:40 -0700 | [diff] [blame] | 121 | property_free_array(property, 1); |
| 122 | } |
| 123 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 124 | void property_free_array(bt_property_t* properties, size_t count) { |
| 125 | if (properties == NULL) return; |
Chris Manton | 97c5444 | 2015-01-07 13:34:18 -0800 | [diff] [blame] | 126 | |
Sharvil Nanavati | 3cf59ef | 2014-04-09 22:20:40 -0700 | [diff] [blame] | 127 | for (size_t i = 0; i < count; ++i) { |
Chris Manton | 5c26224 | 2014-10-14 22:00:32 -0700 | [diff] [blame] | 128 | osi_free(properties[i].val); |
Sharvil Nanavati | 3cf59ef | 2014-04-09 22:20:40 -0700 | [diff] [blame] | 129 | } |
| 130 | |
Chris Manton | 5c26224 | 2014-10-14 22:00:32 -0700 | [diff] [blame] | 131 | osi_free(properties); |
Sharvil Nanavati | 3cf59ef | 2014-04-09 22:20:40 -0700 | [diff] [blame] | 132 | } |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 133 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 134 | bool property_is_addr(const bt_property_t* property) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 135 | CHECK(property != NULL); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 136 | return property->type == BT_PROPERTY_BDADDR; |
| 137 | } |
| 138 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 139 | bool property_is_device_class(const bt_property_t* property) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 140 | CHECK(property != NULL); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 141 | return property->type == BT_PROPERTY_CLASS_OF_DEVICE; |
| 142 | } |
| 143 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 144 | bool property_is_device_type(const bt_property_t* property) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 145 | CHECK(property != NULL); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 146 | return property->type == BT_PROPERTY_TYPE_OF_DEVICE; |
| 147 | } |
| 148 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 149 | bool property_is_discovery_timeout(const bt_property_t* property) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 150 | CHECK(property != NULL); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 151 | return property->type == BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT; |
| 152 | } |
| 153 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 154 | bool property_is_name(const bt_property_t* property) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 155 | CHECK(property != NULL); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 156 | return property->type == BT_PROPERTY_BDNAME; |
| 157 | } |
| 158 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 159 | bool property_is_rssi(const bt_property_t* property) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 160 | CHECK(property != NULL); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 161 | return property->type == BT_PROPERTY_REMOTE_RSSI; |
| 162 | } |
| 163 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 164 | bool property_is_scan_mode(const bt_property_t* property) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 165 | CHECK(property != NULL); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 166 | return property->type == BT_PROPERTY_ADAPTER_SCAN_MODE; |
| 167 | } |
| 168 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 169 | bool property_is_uuids(const bt_property_t* property) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 170 | CHECK(property != NULL); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 171 | return property->type == BT_PROPERTY_UUIDS; |
| 172 | } |
| 173 | |
| 174 | // Convenience conversion methods to property values |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 175 | const RawAddress* property_as_addr(const bt_property_t* property) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 176 | CHECK(property_is_addr(property)); |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 177 | return (const RawAddress*)property->val; |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 178 | } |
| 179 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 180 | const bt_device_class_t* property_as_device_class( |
| 181 | const bt_property_t* property) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 182 | CHECK(property_is_device_class(property)); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 183 | return (const bt_device_class_t*)property->val; |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 184 | } |
| 185 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 186 | bt_device_type_t property_as_device_type(const bt_property_t* property) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 187 | CHECK(property_is_device_type(property)); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 188 | return *(const bt_device_type_t*)property->val; |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 189 | } |
| 190 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 191 | uint32_t property_as_discovery_timeout(const bt_property_t* property) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 192 | CHECK(property_is_discovery_timeout(property)); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 193 | return *(const uint32_t*)property->val; |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 194 | } |
| 195 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 196 | const bt_bdname_t* property_as_name(const bt_property_t* property) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 197 | CHECK(property_is_name(property)); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 198 | return (const bt_bdname_t*)property->val; |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 199 | } |
| 200 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 201 | int8_t property_as_rssi(const bt_property_t* property) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 202 | CHECK(property_is_rssi(property)); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 203 | return *(const int8_t*)property->val; |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 204 | } |
| 205 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 206 | bt_scan_mode_t property_as_scan_mode(const bt_property_t* property) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 207 | CHECK(property_is_scan_mode(property)); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 208 | return *(const bt_scan_mode_t*)property->val; |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 209 | } |
| 210 | |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 211 | const Uuid* property_as_uuids(const bt_property_t* property, size_t* count) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 212 | CHECK(property_is_uuids(property)); |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 213 | *count = sizeof(Uuid) / property->len; |
| 214 | return (const Uuid*)property->val; |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 215 | } |
| 216 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 217 | static bt_property_t* property_new_(void* val, size_t len, |
| 218 | bt_property_type_t type) { |
| 219 | bt_property_t* property = |
| 220 | static_cast<bt_property_t*>(osi_calloc(sizeof(bt_property_t))); |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 221 | |
Pavlin Radoslavov | c5c668a | 2017-09-07 16:22:53 -0700 | [diff] [blame] | 222 | property->val = osi_calloc(len + 1); |
Pavlin Radoslavov | 2a87466 | 2017-03-18 19:35:06 -0700 | [diff] [blame] | 223 | if (type == BT_PROPERTY_BDNAME) { |
Pavlin Radoslavov | c5c668a | 2017-09-07 16:22:53 -0700 | [diff] [blame] | 224 | strlcpy((char*)property->val, (const char*)val, len); |
Pavlin Radoslavov | 2a87466 | 2017-03-18 19:35:06 -0700 | [diff] [blame] | 225 | } else { |
| 226 | memcpy(property->val, val, len); |
| 227 | } |
Chris Manton | 3252cf0 | 2015-01-08 10:47:59 -0800 | [diff] [blame] | 228 | |
| 229 | property->type = type; |
| 230 | property->len = len; |
| 231 | |
| 232 | return property; |
| 233 | } |