1# Copyright 2023 Google LLC 2# 3# Licensed under the Apache License, Version 2.0 (the 'License'); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an 'AS IS' BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""Client Class to access the Floss GATT server interface.""" 15 16import collections 17import logging 18 19from floss.pandora.floss import bluetooth_gatt_service 20from floss.pandora.floss import floss_enums 21from floss.pandora.floss import observer_base 22from floss.pandora.floss import utils 23from gi.repository import GLib 24 25 26class GattServerCallbacks: 27 """Callbacks for the GATT server interface. 28 29 Implement this to observe these callbacks when exporting callbacks via register_server. 30 """ 31 32 def on_server_registered(self, status, server_id): 33 """Called when GATT server registered. 34 35 Args: 36 status: floss_enums.GattStatus. 37 server_id: Bluetooth GATT server id. 38 """ 39 pass 40 41 def on_server_connection_state(self, server_id, connected, addr): 42 """Called when GATT server connection state changed. 43 44 Args: 45 server_id: Bluetooth GATT server id. 46 connected: A boolean value that indicates whether the GATT server is connected. 47 addr: Remote device MAC address. 48 """ 49 pass 50 51 def on_service_added(self, status, service): 52 """Called when service added. 53 54 Args: 55 status: floss_enums.GattStatus. 56 service: BluetoothGattService. 57 """ 58 pass 59 60 def on_service_removed(self, status, handle): 61 """Called when service removed. 62 63 Args: 64 status: floss_enums.GattStatus. 65 handle: Service record handle. 66 """ 67 pass 68 69 def on_characteristic_read_request(self, addr, trans_id, offset, is_long, handle): 70 """Called when there is a request to read a characteristic. 71 72 Args: 73 addr: Remote device MAC address. 74 trans_id: Transaction id. 75 offset: Represents the offset from which the attribute value should be read. 76 is_long: A boolean value representing whether the characteristic size is longer than what we can put in the 77 ATT PDU. 78 handle: The characteristic handle. 79 """ 80 pass 81 82 def on_descriptor_read_request(self, addr, trans_id, offset, is_long, handle): 83 """Called when there is a request to read a descriptor. 84 85 Args: 86 addr: Remote device MAC address. 87 trans_id: Transaction id. 88 offset: Represents the offset from which the descriptor value should be read. 89 is_long: A boolean value representing whether the descriptor size is longer than what we can put in the 90 ATT PDU. 91 handle: The descriptor handle. 92 """ 93 pass 94 95 def on_characteristic_write_request(self, addr, trans_id, offset, length, is_prep, need_rsp, handle, value): 96 """Called when there is a request to write a characteristic. 97 98 Args: 99 addr: Remote device MAC address. 100 trans_id: Transaction id. 101 offset: Represents the offset at which the attribute value should be written. 102 length: The length of the attribute value that should be written. 103 is_prep: A boolean value representing whether it's a 'prepare write' command. 104 need_rsp: A boolean value representing whether it's a 'write no response' command. 105 handle: The characteristic handle. 106 value: The value that should be written to the attribute. 107 """ 108 pass 109 110 def on_descriptor_write_request(self, addr, trans_id, offset, length, is_prep, need_rsp, handle, value): 111 """Called when there is a request to write a descriptor. 112 113 Args: 114 addr: Remote device MAC address. 115 trans_id: Transaction id. 116 offset: The offset value at which the value should be written. 117 length: The length of the value that should be written. 118 is_prep: A boolean value representing whether it's a 'prepare write' command. 119 need_rsp: A boolean value representing whether it's a 'write no response' command. 120 handle: The descriptor handle. 121 value: The value that should be written to the descriptor. 122 """ 123 pass 124 125 def on_execute_write(self, addr, trans_id, exec_write): 126 """Called when execute write. 127 128 Args: 129 addr: Remote device MAC address. 130 trans_id: Transaction id. 131 exec_write: A boolean value that indicates whether the write operation should be executed or canceled. 132 """ 133 pass 134 135 def on_notification_sent(self, addr, status): 136 """Called when notification sent. 137 138 Args: 139 addr: Remote device MAC address. 140 status: floss_enums.GattStatus. 141 """ 142 pass 143 144 def on_mtu_changed(self, addr, mtu): 145 """Called when the MTU changed. 146 147 Args: 148 addr: Remote device MAC address. 149 mtu: Maximum transmission unit. 150 """ 151 pass 152 153 def on_phy_update(self, addr, tx_phy, rx_phy, status): 154 """Called when physical update. 155 156 Args: 157 addr: Remote device MAC address. 158 tx_phy: The new TX PHY for the connection. 159 rx_phy: The new RX PHY for the connection. 160 status: floss_enums.GattStatus. 161 """ 162 pass 163 164 def on_phy_read(self, addr, tx_phy, rx_phy, status): 165 """Called when physical read. 166 167 Args: 168 addr: Remote device MAC address. 169 tx_phy: The current transmit PHY for the connection. 170 rx_phy: The current receive PHY for the connection. 171 status: floss_enums.GattStatus. 172 """ 173 pass 174 175 def on_connection_updated(self, addr, interval, latency, timeout, status): 176 """Called when connection updated. 177 178 Args: 179 addr: Remote device MAC address. 180 interval: Connection interval value. 181 latency: The number of consecutive connection events during which the device doesn't have to be listening. 182 timeout: Supervision timeout for this connection in milliseconds. 183 status: floss_enums.GattStatus. 184 """ 185 pass 186 187 def on_subrate_change(self, addr, subrate_factor, latency, cont_num, timeout, status): 188 """Called when subrate changed. 189 190 Args: 191 addr: Remote device MAC address. 192 subrate_factor: Subrate factor value. 193 latency: The number of consecutive connection events during which the device doesn't have to be listening. 194 cont_num: Continuation number. 195 timeout: Supervision timeout for this connection in milliseconds. 196 status: floss_enums.GattStatus. 197 """ 198 pass 199 200 201def uuid16_to_uuid128(uuid): 202 """Converts 16-bit UUID to 128-bit UUID. 203 204 Args: 205 uuid: 16-bit UUID value. 206 207 Returns: 208 128-bit UUID. 209 """ 210 return utils.uuid16_to_uuid128(uuid).upper() 211 212 213class FlossGattServer(GattServerCallbacks): 214 """Handles method calls and callbacks from the GATT server interface.""" 215 216 ADAPTER_SERVICE = 'org.chromium.bluetooth' 217 GATT_SERVER_INTERFACE = 'org.chromium.bluetooth.BluetoothGatt' 218 GATT_OBJECT_PATTERN = '/org/chromium/bluetooth/hci{}/gatt' 219 GATT_CB_OBJ_NAME = 'test_gatt_server' 220 CB_EXPORTED_INTF = 'org.chromium.bluetooth.BluetoothGattServerCallback' 221 222 # Bluetooth GATT DataBase attribute type. 223 BTGATT_DB_PRIMARY_SERVICE = 0 224 BTGATT_DB_SECONDARY_SERVICE = 1 225 BTGATT_DB_INCLUDED_SERVICE = 2 226 BTGATT_DB_CHARACTERISTIC = 3 227 BTGATT_DB_DESCRIPTOR = 4 228 229 GATT_READ_AUTH_REQUIRED = floss_enums.GattPermission.PERM_READ_ENCRYPTED 230 GATT_READ_MITM_REQUIRED = floss_enums.GattPermission.PERM_READ_ENC_MITM 231 GATT_WRITE_AUTH_REQUIRED = (floss_enums.GattPermission.PERM_WRITE_ENCRYPTED | 232 floss_enums.GattPermission.PERM_WRITE_SIGNED) 233 GATT_WRITE_MITM_REQUIRED = (floss_enums.GattPermission.PERM_WRITE_ENC_MITM | 234 floss_enums.GattPermission.PERM_WRITE_SIGNED_MITM) 235 236 SERVICE_ATTR_UUID = uuid16_to_uuid128('7777') 237 SERVER_CHANGED_CHAR_UUID = uuid16_to_uuid128('2a05') 238 SERVER_SUP_FEAT_UUID = uuid16_to_uuid128('2b3a') 239 CLIENT_SUP_FEAT_UUID = uuid16_to_uuid128('2b29') 240 DATABASE_HASH_UUID = uuid16_to_uuid128('2b2a') 241 LONG_CHAR_UUID = uuid16_to_uuid128('b000') 242 DESCRIPTOR_UUID = uuid16_to_uuid128('b001') 243 KEY_SIZE_CHAR_UUID = uuid16_to_uuid128('b002') 244 UNAUTHORIZED_CHAR_UUID = uuid16_to_uuid128('b003') 245 AUTHENTICATION_CHAR_UUID = uuid16_to_uuid128('b004') 246 INVALID_FOR_LE_UUID = uuid16_to_uuid128('b005') 247 INVALID_FOR_BR_EDR_UUID = uuid16_to_uuid128('b006') 248 NO_READ_CHAR_UUID = uuid16_to_uuid128('b007') 249 NO_WRITE_CHAR_UUID = uuid16_to_uuid128('b008') 250 SHORT_CHAR_UUID = uuid16_to_uuid128('b009') 251 WRITE_NO_RESPONSE_CHAR_UUID = uuid16_to_uuid128('b00a') 252 NOTIFY_CHAR_UUID = uuid16_to_uuid128('b00b') 253 AUTHENTICATE_SHORT_CHAR_UUID = uuid16_to_uuid128('b00c') 254 CCC_DESCRIPTOR_UUID = uuid16_to_uuid128('2902') 255 LONG_CHAR_512_UUID = uuid16_to_uuid128('b00d') 256 MITM_SHORT_CHAR_UUID = uuid16_to_uuid128('b00e') 257 258 LONG_TEST_VALUE_512 = [bytes([7])] * 512 259 LONG_TEST_VALUE = [bytes([7])] * 48 260 SHORT_TEST_VALUE = [bytes([7])] * 2 261 NOTIFICATION_VALUE = [bytes([1]), bytes([0])] 262 INDICATION_VALUE = [bytes([2]), bytes([0])] 263 264 class ExportedGattServerCallbacks(observer_base.ObserverBase): 265 """ 266 <node> 267 <interface name="org.chromium.bluetooth.BluetoothGattServerCallback"> 268 <method name="OnServerRegistered"> 269 <arg type="u" name="status" direction="in" /> 270 <arg type="i" name="server_id" direction="in" /> 271 </method> 272 <method name="OnServerConnectionState"> 273 <arg type="i" name="server_id" direction="in" /> 274 <arg type="b" name="connected" direction="in" /> 275 <arg type="s" name="addr" direction="in" /> 276 </method> 277 <method name="OnServiceAdded"> 278 <arg type="u" name="status" direction="in" /> 279 <arg type="a{sv}" name="service" direction="in" /> 280 </method> 281 <method name="OnServiceRemoved"> 282 <arg type="u" name="status" direction="in" /> 283 <arg type="i" name="handle" direction="in" /> 284 </method> 285 <method name="OnCharacteristicReadRequest"> 286 <arg type="s" name="addr" direction="in" /> 287 <arg type="i" name="trans_id" direction="in" /> 288 <arg type="i" name="offset" direction="in" /> 289 <arg type="b" name="is_long" direction="in" /> 290 <arg type="i" name="handle" direction="in" /> 291 </method> 292 <method name="OnDescriptorReadRequest"> 293 <arg type="s" name="addr" direction="in" /> 294 <arg type="i" name="trans_id" direction="in" /> 295 <arg type="i" name="offset" direction="in" /> 296 <arg type="b" name="is_long" direction="in" /> 297 <arg type="i" name="handle" direction="in" /> 298 </method> 299 <method name="OnCharacteristicWriteRequest"> 300 <arg type="s" name="addr" direction="in" /> 301 <arg type="i" name="trans_id" direction="in" /> 302 <arg type="i" name="offset" direction="in" /> 303 <arg type="i" name="length" direction="in" /> 304 <arg type="b" name="is_prep" direction="in" /> 305 <arg type="b" name="need_rsp" direction="in" /> 306 <arg type="i" name="handle" direction="in" /> 307 <arg type="ay" name="value" direction="in" /> 308 </method> 309 <method name="OnDescriptorWriteRequest"> 310 <arg type="s" name="addr" direction="in" /> 311 <arg type="i" name="trans_id" direction="in" /> 312 <arg type="i" name="offset" direction="in" /> 313 <arg type="i" name="length" direction="in" /> 314 <arg type="b" name="is_prep" direction="in" /> 315 <arg type="b" name="need_rsp" direction="in" /> 316 <arg type="i" name="handle" direction="in" /> 317 <arg type="ay" name="value" direction="in" /> 318 </method> 319 <method name="OnExecuteWrite"> 320 <arg type="s" name="addr" direction="in" /> 321 <arg type="i" name="trans_id" direction="in" /> 322 <arg type="b" name="exec_write" direction="in" /> 323 </method> 324 <method name="OnNotificationSent"> 325 <arg type="s" name="addr" direction="in" /> 326 <arg type="u" name="status" direction="in" /> 327 </method> 328 <method name="OnMtuChanged"> 329 <arg type="s" name="addr" direction="in" /> 330 <arg type="i" name="mtu" direction="in" /> 331 </method> 332 <method name="OnPhyUpdate"> 333 <arg type="s" name="addr" direction="in" /> 334 <arg type="u" name="tx_phy" direction="in" /> 335 <arg type="u" name="rx_phy" direction="in" /> 336 <arg type="u" name="status" direction="in" /> 337 </method> 338 <method name="OnPhyRead"> 339 <arg type="s" name="addr" direction="in" /> 340 <arg type="u" name="tx_phy" direction="in" /> 341 <arg type="u" name="rx_phy" direction="in" /> 342 <arg type="u" name="status" direction="in" /> 343 </method> 344 <method name="OnConnectionUpdated"> 345 <arg type="s" name="addr" direction="in" /> 346 <arg type="i" name="interval" direction="in" /> 347 <arg type="i" name="latency" direction="in" /> 348 <arg type="i" name="timeout" direction="in" /> 349 <arg type="u" name="status" direction="in" /> 350 </method> 351 <method name="OnSubrateChange"> 352 <arg type="s" name="addr" direction="in" /> 353 <arg type="i" name="subrate_factor" direction="in" /> 354 <arg type="i" name="latency" direction="in" /> 355 <arg type="i" name="cont_num" direction="in" /> 356 <arg type="i" name="timeout" direction="in" /> 357 <arg type="u" name="status" direction="in" /> 358 </method> 359 </interface> 360 </node> 361 """ 362 363 def __init__(self): 364 """Constructs exported callbacks object.""" 365 observer_base.ObserverBase.__init__(self) 366 367 def OnServerRegistered(self, status, server_id): 368 """Handles server registration callback. 369 370 Args: 371 status: floss_enums.GattStatus. 372 server_id: Bluetooth GATT server id. 373 """ 374 for observer in self.observers.values(): 375 observer.on_server_registered(status, server_id) 376 377 def OnServerConnectionState(self, server_id, connected, addr): 378 """Handles server connection state callback. 379 380 Args: 381 server_id: Bluetooth GATT server id. 382 connected: A boolean value that indicates whether the GATT server is connected. 383 addr: Remote device MAC address. 384 """ 385 for observer in self.observers.values(): 386 observer.on_server_connection_state(server_id, connected, addr) 387 388 def OnServiceAdded(self, status, service): 389 """Handles service added callback. 390 391 Args: 392 status: floss_enums.GattStatus. 393 service: BluetoothGattService. 394 """ 395 for observer in self.observers.values(): 396 observer.on_service_added(status, service) 397 398 def OnServiceRemoved(self, status, handle): 399 """Handles service removed callback. 400 401 Args: 402 status: floss_enums.GattStatus. 403 handle: Service record handle. 404 """ 405 for observer in self.observers.values(): 406 observer.on_service_removed(status, handle) 407 408 def OnCharacteristicReadRequest(self, addr, trans_id, offset, is_long, handle): 409 """Handles characteristic read request callback. 410 411 Args: 412 addr: Remote device MAC address. 413 trans_id: Transaction id. 414 offset: Represents the offset from which the attribute value should be read. 415 is_long: A boolean value representing whether the characteristic size is longer than what we can put in 416 the ATT PDU. 417 handle: The characteristic handle. 418 """ 419 for observer in self.observers.values(): 420 observer.on_characteristic_read_request(addr, trans_id, offset, is_long, handle) 421 422 def OnCharacteristicWriteRequest(self, addr, trans_id, offset, length, is_prep, need_rsp, handle, value): 423 """Handles characteristic write request callback. 424 425 Args: 426 addr: Remote device MAC address. 427 trans_id: Transaction id. 428 offset: Represents the offset from which the attribute value should be read. 429 length: The length of the value that should be written. 430 is_prep: A boolean value representing whether it's a 'prepare write' command. 431 need_rsp: A boolean value representing whether it's a 'write no response' command. 432 handle: The descriptor handle. 433 value: The value that should be written to the descriptor. 434 """ 435 for observer in self.observers.values(): 436 observer.on_characteristic_write_request(addr, trans_id, offset, length, is_prep, need_rsp, handle, 437 value) 438 439 def OnDescriptorReadRequest(self, addr, trans_id, offset, is_long, handle): 440 """Handles descriptor read request callback. 441 442 Args: 443 addr: Remote device MAC address. 444 trans_id: Transaction id. 445 offset: Represents the offset from which the descriptor value should be read. 446 is_long: A boolean value representing whether the descriptor size is longer than what we can put in the 447 ATT PDU. 448 handle: The descriptor handle. 449 """ 450 for observer in self.observers.values(): 451 observer.on_descriptor_read_request(addr, trans_id, offset, is_long, handle) 452 453 def OnDescriptorWriteRequest(self, addr, trans_id, offset, length, is_prep, need_rsp, handle, value): 454 """Handles descriptor write request callback. 455 456 Args: 457 addr: Remote device MAC address. 458 trans_id: Transaction id. 459 offset: The offset value at which the value should be written. 460 length: The length of the value that should be written. 461 is_prep: A boolean value representing whether it's a 'prepare write' command. 462 need_rsp: A boolean value representing whether it's a 'write no response' command. 463 handle: The descriptor handle. 464 value: The value that should be written to the descriptor. 465 """ 466 for observer in self.observers.values(): 467 observer.on_descriptor_write_request(addr, trans_id, offset, length, is_prep, need_rsp, handle, value) 468 469 def OnExecuteWrite(self, addr, trans_id, exec_write): 470 """Handles execute write callback. 471 472 Args: 473 addr: Remote device MAC address. 474 trans_id: Transaction id. 475 exec_write: A boolean value that indicates whether the write operation should be executed or canceled. 476 """ 477 for observer in self.observers.values(): 478 observer.on_execute_write(addr, trans_id, exec_write) 479 480 def OnNotificationSent(self, addr, status): 481 """Handles notification sent callback. 482 483 Args: 484 addr: Remote device MAC address. 485 status: floss_enums.GattStatus. 486 """ 487 for observer in self.observers.values(): 488 observer.on_notification_sent(addr, status) 489 490 def OnMtuChanged(self, addr, mtu): 491 """Handles MTU changed callback. 492 493 Args: 494 addr: Remote device MAC address. 495 mtu: Maximum transmission unit. 496 """ 497 for observer in self.observers.values(): 498 observer.on_mtu_changed(addr, mtu) 499 500 def OnPhyUpdate(self, addr, tx_phy, rx_phy, status): 501 """Handles physical update callback. 502 503 Args: 504 addr: Remote device MAC address. 505 tx_phy: The new TX PHY for the connection. 506 rx_phy: The new RX PHY for the connection. 507 status: floss_enums.GattStatus. 508 """ 509 for observer in self.observers.values(): 510 observer.on_phy_update(addr, tx_phy, rx_phy, status) 511 512 def OnPhyRead(self, addr, tx_phy, rx_phy, status): 513 """Handles physical read callback. 514 515 Args: 516 addr: Remote device MAC address. 517 tx_phy: The current transmit PHY for the connection. 518 rx_phy: The current receive PHY for the connection. 519 status: floss_enums.GattStatus. 520 """ 521 for observer in self.observers.values(): 522 observer.on_phy_read(addr, tx_phy, rx_phy, status) 523 524 def OnConnectionUpdated(self, addr, interval, latency, timeout, status): 525 """Handles connection updated callback. 526 527 Args: 528 addr: Remote device MAC address. 529 interval: Connection interval value. 530 latency: The number of consecutive connection events during which the device doesn't have to be 531 listening. 532 timeout: Supervision timeout for this connection in milliseconds. 533 status: floss_enums.GattStatus. 534 """ 535 for observer in self.observers.values(): 536 observer.on_connection_updated(addr, interval, latency, timeout, status) 537 538 def on_subrate_change(self, addr, subrate_factor, latency, cont_num, timeout, status): 539 """Handles subrate changed callback. 540 541 Args: 542 addr: Remote device MAC address. 543 subrate_factor: Subrate factor value. 544 latency: The number of consecutive connection events during which the device doesn't have to be 545 listening. 546 cont_num: Continuation number. 547 timeout: Supervision timeout for this connection in milliseconds. 548 status: floss_enums.GattStatus. 549 """ 550 for observer in self.observers.values(): 551 observer.on_subrate_change(addr, subrate_factor, latency, cont_num, timeout, status) 552 553 def __init__(self, bus, hci): 554 """Constructs the client. 555 556 Args: 557 bus: D-Bus bus over which we'll establish connections. 558 hci: HCI adapter index. Get this value from 'get_default_adapter' on FlossManagerClient. 559 """ 560 self.bus = bus 561 self.hci = hci 562 self.objpath = self.GATT_OBJECT_PATTERN.format(hci) 563 self.cb_dbus_objpath = utils.generate_dbus_cb_objpath(self.GATT_CB_OBJ_NAME, self.hci) 564 565 # Create and publish callbacks. 566 self.callbacks = self.ExportedGattServerCallbacks() 567 self.callbacks.add_observer('gatt_testing_server', self) 568 self.bus.register_object(self.cb_dbus_objpath, self.callbacks, None) 569 self.server_id = None 570 self.mtu_value = -1 571 self.write_requests = collections.deque([]) 572 self.gatt_services = [] 573 # Indicate if PTS attribute values were set or not (set only one time). 574 self.pts_set_values = False 575 576 def __del__(self): 577 """Destructor.""" 578 del self.callbacks 579 580 def check_permissions(self, uuid): 581 """Checks request UUID permission. 582 583 Args: 584 uuid: 128-bit UUID value as string. 585 586 Returns: 587 GATT status. 588 """ 589 if uuid is None: 590 logging.debug('check_permissions uuid is None or value is None') 591 return floss_enums.GattStatus.NOT_FOUND 592 elif uuid == self.LONG_CHAR_UUID: 593 logging.debug('check_permissions: uuid == long_char, return GATT_SUCCESS') 594 elif uuid == self.DESCRIPTOR_UUID: 595 logging.debug('check_permissions: uuid == descriptor, return GATT_SUCCESS') 596 elif uuid == self.UNAUTHORIZED_CHAR_UUID: 597 logging.debug('check_permissions: uuid == unauthorize_char, return GATT_INSUF_AUTHORIZATION') 598 return floss_enums.GattStatus.INSUF_AUTHORIZATION 599 elif uuid == self.AUTHENTICATION_CHAR_UUID: 600 logging.debug('check_permissions: uuid == authenticate_char, return GATT_SUCCESS') 601 elif uuid == self.INVALID_FOR_LE_UUID: 602 logging.debug('check_permissions: uuid == invalid_for_le, return GATT_SUCCESS') 603 return floss_enums.GattStatus.INTERNAL_ERROR 604 elif uuid == self.INVALID_FOR_BR_EDR_UUID: 605 logging.debug('check_permissions: uuid == invalid_for_bredr, return GATT_SUCCESS') 606 return floss_enums.GattStatus.INTERNAL_ERROR 607 elif uuid == self.NO_READ_CHAR_UUID: 608 logging.debug('check_permissions: uuid == no_read_char, return GATT_READ_NOT_PERMIT') 609 return floss_enums.GattStatus.READ_NOT_PERMIT 610 elif uuid == self.NO_WRITE_CHAR_UUID: 611 logging.debug('check_permissions: uuid == no_write_char, return GATT_WRITE_NOT_PERMIT') 612 return floss_enums.GattStatus.WRITE_NOT_PERMIT 613 elif uuid == self.SHORT_CHAR_UUID: 614 logging.debug('check_permissions: uuid == short_char, return GATT_SUCCESS') 615 elif uuid == self.WRITE_NO_RESPONSE_CHAR_UUID: 616 logging.debug('check_permissions: uuid == write_no_rsp_char, return GATT_SUCCESS') 617 elif uuid == self.AUTHENTICATE_SHORT_CHAR_UUID: 618 logging.debug('check_permissions: uuid == authenticate_short_char, return GATT_SUCCESS') 619 elif uuid == self.CCC_DESCRIPTOR_UUID: 620 logging.debug('check_permissions: uuid == ccc_descriptor, return GATT_SUCCESS') 621 elif uuid == self.LONG_CHAR_512_UUID: 622 logging.debug('check_permissions: uuid == long_char512, return GATT_SUCCESS') 623 elif uuid == self.MITM_SHORT_CHAR_UUID: 624 logging.debug('check_permissions: uuid == mitm_short_char, return GATT_SUCCESS') 625 else: 626 logging.debug('check_permissions: uuid: %s unknown return GATT_NOT_FOUND', uuid) 627 return floss_enums.GattStatus.NOT_FOUND 628 return floss_enums.GattStatus.SUCCESS 629 630 def generic_write(self, offset, length, handle, value): 631 """Writes GATT attribute value. 632 633 Args: 634 offset: Represents the offset at which the attribute value should be written. 635 length: The length of the attribute value that should be written. 636 handle: The attribute handle. 637 value: The value that should be written to the attribute. 638 639 Returns: 640 (Bluetooth Gatt status, attribute value). 641 """ 642 attribute = self.get_attribute_from_handle(handle) 643 attr_value = attribute.value if attribute is not None else [] 644 645 if len(attr_value) < offset: 646 logging.info('len(char_value) < offset') 647 return floss_enums.GattStatus.INVALID_OFFSET, [] 648 649 if offset + length > len(attr_value): 650 logging.info('offset + len > len(char_value)') 651 return floss_enums.GattStatus.INVALID_ATTRLEN, [] 652 653 attr_value[offset:(offset + length)] = value 654 self.update_attribute_value(attribute.uuid, attr_value) 655 return floss_enums.GattStatus.SUCCESS, attr_value 656 657 def generic_read(self, offset, handle): 658 """Reads GATT attribute value. 659 660 Args: 661 offset: Represents the offset from which the attribute value should be read. 662 handle: The attribute handle. 663 664 Returns: 665 (Bluetooth Gatt status, attribute value). 666 """ 667 attr_value = self.get_attribute_value_from_handle(handle) 668 669 if offset < 0 or offset > len(attr_value): 670 logging.info('generic_read len(value) < offset') 671 return floss_enums.GattStatus.INVALID_OFFSET, [] 672 673 return floss_enums.GattStatus.SUCCESS, attr_value[offset:] 674 675 def get_uuid_from_handle(self, handle): 676 """Gets attribute UUID from handle. 677 678 Args: 679 handle: The attribute handle. 680 681 Returns: 682 Attribute UUID as string if found, empty string otherwise. 683 """ 684 attribute = self.get_attribute_from_handle(handle) 685 return '' if attribute is None else attribute.uuid 686 687 def get_attribute_value_from_handle(self, handle): 688 """Gets attribute value from handle. 689 690 Args: 691 handle: The attribute handle. 692 693 Returns: 694 Attribute value as list if found, empty list otherwise. 695 """ 696 attribute = self.get_attribute_from_handle(handle) 697 return [] if attribute is None else attribute.value 698 699 def get_attribute_from_handle(self, handle): 700 """Gets GATT attribute from handle. 701 702 Args: 703 handle: The attribute handle. 704 705 Returns: 706 GATT attribute if found, None otherwise. 707 """ 708 for service in self.gatt_services: 709 if int(service.instance_id) == int(handle): 710 return service 711 for char in service.characteristics: 712 if int(char.instance_id) == int(handle): 713 return char 714 for desc in char.descriptors: 715 if int(desc.instance_id) == int(handle): 716 return desc 717 718 return None 719 720 def update_attribute_value(self, uuid, value): 721 """Update GATT attribute value. 722 723 Args: 724 uuid: GATT attribute uuid as string. 725 value: Attribute value as list. 726 """ 727 for service in self.gatt_services: 728 if service.uuid == uuid: 729 service.value = value 730 return 731 for char in service.characteristics: 732 if char.uuid == uuid: 733 char.value = value 734 return 735 for desc in char.descriptors: 736 if desc.uuid == uuid: 737 desc.value = value 738 return 739 logging.error('No attribute found with uuid = %s!', uuid) 740 741 def on_attr_read(self, addr, trans_id, offset, is_long, handle): 742 """Handles the read request for GATT attribute. 743 744 Args: 745 addr: Remote device MAC address. 746 trans_id: Transaction id. 747 offset: Represents the offset from which the attribute value should be read. 748 is_long: A boolean value representing whether the attribute size is longer than what we can put in the ATT 749 PDU. 750 handle: The attribute handle. 751 """ 752 uuid = self.get_uuid_from_handle(handle) 753 status = self.check_permissions(uuid) 754 value = [] 755 if status == floss_enums.GattStatus.SUCCESS: 756 if not is_long: 757 offset = 0 758 status, value = self.generic_read(offset, handle) 759 760 self.proxy().SendResponse(self.server_id, addr, trans_id, status, offset, value) 761 762 def on_attr_write(self, addr, trans_id, offset, length, is_prep, need_rsp, handle, value): 763 """Handles the read request for GATT attribute. 764 765 Args: 766 addr: Remote device MAC address. 767 trans_id: Transaction id. 768 offset: Represents the offset at which the attribute value should be written. 769 length: The length of the attribute value that should be written. 770 is_prep: A boolean value representing whether it's a 'prepare write' command. 771 need_rsp: A boolean value representing whether it's a 'write no response' command. 772 handle: The attribute handle. 773 value: The value that should be written to the attribute. 774 """ 775 uuid = self.get_uuid_from_handle(handle) 776 status = self.check_permissions(uuid) 777 778 if status == floss_enums.GattStatus.SUCCESS: 779 if is_prep: 780 self.write_requests.append((addr, trans_id, offset, length, is_prep, need_rsp, handle, value)) 781 else: 782 # write request. 783 status, value = self.generic_write(offset, length, handle, value) 784 else: 785 value = [] 786 787 if need_rsp: 788 self.proxy().SendResponse(self.server_id, addr, trans_id, status, offset, value) 789 else: 790 logging.info('No need to send response.') 791 792 def __set_pts_attributes_value(self): 793 """Sets PTS attributes value.""" 794 if not self.pts_set_values: 795 self.update_attribute_value(self.SERVICE_ATTR_UUID, self.SHORT_TEST_VALUE) 796 self.update_attribute_value(self.SERVER_CHANGED_CHAR_UUID, self.SHORT_TEST_VALUE) 797 self.update_attribute_value(self.SERVER_SUP_FEAT_UUID, self.SHORT_TEST_VALUE) 798 self.update_attribute_value(self.CLIENT_SUP_FEAT_UUID, self.SHORT_TEST_VALUE) 799 self.update_attribute_value(self.DATABASE_HASH_UUID, self.SHORT_TEST_VALUE) 800 self.update_attribute_value(self.LONG_CHAR_UUID, self.LONG_TEST_VALUE) 801 self.update_attribute_value(self.DESCRIPTOR_UUID, self.LONG_TEST_VALUE) 802 self.update_attribute_value(self.KEY_SIZE_CHAR_UUID, self.LONG_TEST_VALUE) 803 self.update_attribute_value(self.UNAUTHORIZED_CHAR_UUID, self.LONG_TEST_VALUE) 804 self.update_attribute_value(self.AUTHENTICATION_CHAR_UUID, self.LONG_TEST_VALUE) 805 self.update_attribute_value(self.INVALID_FOR_LE_UUID, self.LONG_TEST_VALUE) 806 self.update_attribute_value(self.INVALID_FOR_BR_EDR_UUID, self.LONG_TEST_VALUE) 807 self.update_attribute_value(self.NO_READ_CHAR_UUID, self.LONG_TEST_VALUE) 808 self.update_attribute_value(self.NO_WRITE_CHAR_UUID, self.LONG_TEST_VALUE) 809 self.update_attribute_value(self.SHORT_CHAR_UUID, self.SHORT_TEST_VALUE) 810 self.update_attribute_value(self.WRITE_NO_RESPONSE_CHAR_UUID, self.LONG_TEST_VALUE) 811 self.update_attribute_value(self.NOTIFY_CHAR_UUID, self.SHORT_TEST_VALUE) 812 self.update_attribute_value(self.AUTHENTICATE_SHORT_CHAR_UUID, self.SHORT_TEST_VALUE) 813 self.update_attribute_value(self.CCC_DESCRIPTOR_UUID, self.INDICATION_VALUE) 814 self.update_attribute_value(self.LONG_CHAR_512_UUID, self.LONG_TEST_VALUE_512) 815 self.update_attribute_value(self.MITM_SHORT_CHAR_UUID, self.SHORT_TEST_VALUE) 816 self.pts_set_values = True 817 818 def __define_services(self): 819 """Defines GATT services for PTS testing.""" 820 821 service = bluetooth_gatt_service.Service() 822 characteristic = bluetooth_gatt_service.Characteristic() 823 descriptor = bluetooth_gatt_service.Descriptor() 824 service.included_services = [] 825 service.characteristics = [] 826 characteristic.descriptors = [] 827 828 service.uuid = self.SERVICE_ATTR_UUID 829 service.instance_id = 0 830 service.service_type = self.BTGATT_DB_PRIMARY_SERVICE 831 832 characteristic.uuid = self.SERVER_CHANGED_CHAR_UUID 833 characteristic.instance_id = 1 834 characteristic.properties = floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_INDICATE 835 characteristic.permissions = floss_enums.GattPermission.PERM_READ | floss_enums.GattPermission.PERM_WRITE 836 characteristic.key_size = 0 837 characteristic.write_type = floss_enums.GattWriteType.WRITE 838 839 descriptor.uuid = self.CCC_DESCRIPTOR_UUID 840 descriptor.instance_id = 2 841 descriptor.permissions = floss_enums.GattPermission.PERM_READ | floss_enums.GattPermission.PERM_WRITE 842 characteristic.descriptors.append(descriptor) 843 844 service.characteristics.append(characteristic) 845 846 # ---------------------------------------------------- 847 characteristic = bluetooth_gatt_service.Characteristic() 848 characteristic.uuid = self.SERVER_SUP_FEAT_UUID 849 characteristic.instance_id = 3 850 characteristic.properties = floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_READ 851 characteristic.permissions = floss_enums.GattPermission.PERM_READ 852 characteristic.key_size = 0 853 characteristic.write_type = floss_enums.GattWriteType.INVALID 854 characteristic.descriptors = [] 855 856 service.characteristics.append(characteristic) 857 858 # ---------------------------------------------------- 859 characteristic = bluetooth_gatt_service.Characteristic() 860 characteristic.uuid = self.CLIENT_SUP_FEAT_UUID 861 characteristic.instance_id = 4 862 characteristic.properties = (floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_READ | 863 floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_WRITE) 864 characteristic.permissions = floss_enums.GattPermission.PERM_READ | floss_enums.GattPermission.PERM_WRITE 865 characteristic.key_size = 0 866 characteristic.write_type = floss_enums.GattWriteType.INVALID 867 characteristic.descriptors = [] 868 869 service.characteristics.append(characteristic) 870 871 # ---------------------------------------------------- 872 characteristic = bluetooth_gatt_service.Characteristic() 873 characteristic.uuid = self.DATABASE_HASH_UUID 874 characteristic.instance_id = 5 875 characteristic.properties = floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_READ 876 characteristic.permissions = floss_enums.GattPermission.PERM_READ 877 characteristic.key_size = 0 878 characteristic.write_type = floss_enums.GattWriteType.INVALID 879 characteristic.descriptors = [] 880 881 service.characteristics.append(characteristic) 882 883 # ---------------------------------------------------- 884 characteristic = bluetooth_gatt_service.Characteristic() 885 characteristic.uuid = self.DATABASE_HASH_UUID 886 characteristic.instance_id = 5 887 characteristic.properties = floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_READ 888 characteristic.permissions = floss_enums.GattPermission.PERM_READ 889 characteristic.key_size = 0 890 characteristic.write_type = floss_enums.GattWriteType.INVALID 891 characteristic.descriptors = [] 892 893 service.characteristics.append(characteristic) 894 895 # ---------------------------------------------------- 896 characteristic = bluetooth_gatt_service.Characteristic() 897 descriptor = bluetooth_gatt_service.Descriptor() 898 characteristic.uuid = self.LONG_CHAR_UUID 899 characteristic.instance_id = 6 900 characteristic.properties = (floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_READ | 901 floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_WRITE) 902 characteristic.permissions = floss_enums.GattPermission.PERM_READ | floss_enums.GattPermission.PERM_WRITE 903 characteristic.key_size = 0 904 characteristic.write_type = floss_enums.GattWriteType.WRITE 905 characteristic.descriptors = [] 906 907 descriptor.uuid = self.DESCRIPTOR_UUID 908 descriptor.instance_id = 7 909 descriptor.permissions = floss_enums.GattPermission.PERM_READ | floss_enums.GattPermission.PERM_WRITE 910 characteristic.descriptors.append(descriptor) 911 service.characteristics.append(characteristic) 912 913 # ---------------------------------------------------- 914 characteristic = bluetooth_gatt_service.Characteristic() 915 characteristic.uuid = self.KEY_SIZE_CHAR_UUID 916 characteristic.instance_id = 8 917 characteristic.properties = (floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_READ | 918 floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_WRITE) 919 characteristic.permissions = ( 920 10 << 12) | floss_enums.GattPermission.PERM_READ_ENCRYPTED | floss_enums.GattPermission.PERM_WRITE_ENCRYPTED 921 characteristic.key_size = 10 922 characteristic.write_type = floss_enums.GattWriteType.WRITE 923 characteristic.descriptors = [] 924 925 service.characteristics.append(characteristic) 926 # ---------------------------------------------------- 927 characteristic = bluetooth_gatt_service.Characteristic() 928 characteristic.uuid = self.UNAUTHORIZED_CHAR_UUID 929 characteristic.instance_id = 9 930 characteristic.properties = (floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_READ | 931 floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_WRITE) 932 characteristic.permissions = floss_enums.GattPermission.PERM_READ | floss_enums.GattPermission.PERM_WRITE 933 characteristic.key_size = 0 934 characteristic.write_type = floss_enums.GattWriteType.WRITE 935 characteristic.descriptors = [] 936 937 service.characteristics.append(characteristic) 938 # ---------------------------------------------------- 939 characteristic = bluetooth_gatt_service.Characteristic() 940 characteristic.uuid = self.AUTHENTICATION_CHAR_UUID 941 characteristic.instance_id = 10 942 characteristic.properties = (floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_READ | 943 floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_WRITE | 944 floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_AUTH) 945 characteristic.permissions = self.GATT_READ_AUTH_REQUIRED | self.GATT_WRITE_AUTH_REQUIRED 946 characteristic.key_size = 0 947 characteristic.write_type = floss_enums.GattWriteType.WRITE 948 characteristic.descriptors = [] 949 950 service.characteristics.append(characteristic) 951 952 # ---------------------------------------------------- 953 characteristic = bluetooth_gatt_service.Characteristic() 954 characteristic.uuid = self.INVALID_FOR_LE_UUID 955 characteristic.instance_id = 11 956 characteristic.properties = (floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_READ | 957 floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_WRITE) 958 characteristic.permissions = floss_enums.GattPermission.PERM_READ | floss_enums.GattPermission.PERM_WRITE 959 characteristic.key_size = 0 960 characteristic.write_type = floss_enums.GattWriteType.WRITE 961 characteristic.descriptors = [] 962 963 service.characteristics.append(characteristic) 964 # ---------------------------------------------------- 965 characteristic = bluetooth_gatt_service.Characteristic() 966 characteristic.uuid = self.INVALID_FOR_BR_EDR_UUID 967 characteristic.instance_id = 12 968 characteristic.properties = (floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_READ | 969 floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_WRITE) 970 characteristic.permissions = floss_enums.GattPermission.PERM_READ | floss_enums.GattPermission.PERM_WRITE 971 characteristic.key_size = 0 972 characteristic.write_type = floss_enums.GattWriteType.WRITE 973 characteristic.descriptors = [] 974 975 service.characteristics.append(characteristic) 976 # ---------------------------------------------------- 977 characteristic = bluetooth_gatt_service.Characteristic() 978 characteristic.uuid = self.NO_READ_CHAR_UUID 979 characteristic.instance_id = 13 980 # Only write property. 981 characteristic.properties = floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_WRITE 982 # Only write permission. 983 characteristic.permissions = floss_enums.GattPermission.PERM_WRITE 984 characteristic.key_size = 0 985 characteristic.write_type = floss_enums.GattWriteType.WRITE 986 characteristic.descriptors = [] 987 988 service.characteristics.append(characteristic) 989 # ---------------------------------------------------- 990 characteristic = bluetooth_gatt_service.Characteristic() 991 characteristic.uuid = self.NO_WRITE_CHAR_UUID 992 characteristic.instance_id = 14 993 # Only read property. 994 characteristic.properties = floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_READ 995 # Only read permission. 996 characteristic.permissions = floss_enums.GattPermission.PERM_READ 997 characteristic.key_size = 0 998 characteristic.write_type = floss_enums.GattWriteType.INVALID 999 characteristic.descriptors = [] 1000 1001 service.characteristics.append(characteristic) 1002 # ---------------------------------------------------- 1003 characteristic = bluetooth_gatt_service.Characteristic() 1004 characteristic.uuid = self.SHORT_CHAR_UUID 1005 characteristic.instance_id = 15 1006 characteristic.properties = (floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_READ | 1007 floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_WRITE) 1008 characteristic.permissions = floss_enums.GattPermission.PERM_READ | floss_enums.GattPermission.PERM_WRITE 1009 characteristic.key_size = 0 1010 characteristic.write_type = floss_enums.GattWriteType.WRITE 1011 characteristic.descriptors = [] 1012 1013 service.characteristics.append(characteristic) 1014 # ---------------------------------------------------- 1015 characteristic = bluetooth_gatt_service.Characteristic() 1016 characteristic.uuid = self.WRITE_NO_RESPONSE_CHAR_UUID 1017 characteristic.instance_id = 16 1018 # Write without response property. 1019 characteristic.properties = (floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_READ | 1020 floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_WRITE_NR) 1021 characteristic.permissions = floss_enums.GattPermission.PERM_READ | floss_enums.GattPermission.PERM_WRITE 1022 characteristic.key_size = 0 1023 characteristic.write_type = floss_enums.GattWriteType.WRITE_NO_RSP 1024 characteristic.descriptors = [] 1025 1026 service.characteristics.append(characteristic) 1027 # ---------------------------------------------------- 1028 characteristic = bluetooth_gatt_service.Characteristic() 1029 descriptor = bluetooth_gatt_service.Descriptor() 1030 characteristic.uuid = self.NOTIFY_CHAR_UUID 1031 characteristic.instance_id = 17 1032 characteristic.properties = (floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_NOTIFY | 1033 floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_INDICATE) 1034 characteristic.permissions = floss_enums.GattPermission.PERM_READ | floss_enums.GattPermission.PERM_WRITE 1035 characteristic.key_size = 0 1036 characteristic.write_type = floss_enums.GattWriteType.WRITE 1037 characteristic.descriptors = [] 1038 1039 descriptor.uuid = self.CCC_DESCRIPTOR_UUID 1040 descriptor.instance_id = 18 1041 descriptor.permissions = floss_enums.GattPermission.PERM_READ | floss_enums.GattPermission.PERM_WRITE 1042 1043 characteristic.descriptors.append(descriptor) 1044 service.characteristics.append(characteristic) 1045 # ---------------------------------------------------- 1046 characteristic = bluetooth_gatt_service.Characteristic() 1047 characteristic.uuid = self.AUTHENTICATE_SHORT_CHAR_UUID 1048 characteristic.instance_id = 19 1049 characteristic.properties = (floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_READ | 1050 floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_WRITE | 1051 floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_AUTH) 1052 characteristic.permissions = self.GATT_READ_AUTH_REQUIRED | self.GATT_WRITE_AUTH_REQUIRED 1053 characteristic.key_size = 0 1054 characteristic.write_type = floss_enums.GattWriteType.WRITE 1055 characteristic.descriptors = [] 1056 1057 service.characteristics.append(characteristic) 1058 # ---------------------------------------------------- 1059 characteristic = bluetooth_gatt_service.Characteristic() 1060 characteristic.uuid = self.LONG_CHAR_512_UUID 1061 characteristic.instance_id = 20 1062 characteristic.properties = (floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_READ | 1063 floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_WRITE) 1064 characteristic.permissions = floss_enums.GattPermission.PERM_READ | floss_enums.GattPermission.PERM_WRITE 1065 characteristic.key_size = 0 1066 characteristic.write_type = floss_enums.GattWriteType.WRITE 1067 characteristic.descriptors = [] 1068 1069 service.characteristics.append(characteristic) 1070 # ---------------------------------------------------- 1071 characteristic = bluetooth_gatt_service.Characteristic() 1072 characteristic.uuid = self.MITM_SHORT_CHAR_UUID 1073 characteristic.instance_id = 21 1074 characteristic.properties = (floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_READ | 1075 floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_WRITE | 1076 floss_enums.GattCharacteristicProprieties.CHAR_PROP_BIT_AUTH) 1077 characteristic.permissions = self.GATT_READ_MITM_REQUIRED | self.GATT_WRITE_MITM_REQUIRED 1078 characteristic.key_size = 0 1079 characteristic.write_type = floss_enums.GattWriteType.WRITE 1080 characteristic.descriptors = [] 1081 service.characteristics.append(characteristic) 1082 # ---------------------------------------------------- 1083 service_dict = bluetooth_gatt_service.convert_object_to_dict(service) 1084 self.proxy().AddService(self.server_id, self.make_dbus_service(service_dict)) 1085 1086 @utils.glib_callback() 1087 def on_server_registered(self, status, server_id): 1088 """Handles server registration callback. 1089 1090 Args: 1091 status: floss_enums.GattStatus. 1092 server_id: Bluetooth GATT server id. 1093 """ 1094 logging.debug('on_server_registered: status: %s, server_id: %s', status, server_id) 1095 1096 if status != floss_enums.GattStatus.SUCCESS: 1097 logging.error('Failed to register server with id: %s, status = %s', server_id, status) 1098 return 1099 self.server_id = server_id 1100 self.__define_services() 1101 1102 @utils.glib_callback() 1103 def on_server_connection_state(self, server_id, connected, addr): 1104 """Handles GATT server connection state callback. 1105 1106 Args: 1107 server_id: Bluetooth GATT server id. 1108 connected: A boolean value that indicates whether the GATT server is connected. 1109 addr: Remote device MAC address. 1110 """ 1111 logging.debug('on_server_connection_state: server_id: %s, connection_state: %s, device address: %s', server_id, 1112 connected, addr) 1113 1114 @utils.glib_callback() 1115 def on_service_added(self, status, service): 1116 """Handles service added callback. 1117 1118 Args: 1119 status: floss_enums.GattStatus. 1120 service: BluetoothGattService. 1121 """ 1122 if status != floss_enums.GattStatus.SUCCESS: 1123 return 1124 self.gatt_services.append(bluetooth_gatt_service.create_gatt_service(service)) 1125 1126 logging.debug('on_service_added: status: %s, service: %s', status, service) 1127 1128 # This function will run once when the server is initiated. 1129 self.__set_pts_attributes_value() 1130 1131 @utils.glib_callback() 1132 def on_service_removed(self, status, handle): 1133 """Handles service removed callback. 1134 1135 Args: 1136 status: floss_enums.GattStatus. 1137 handle: Service record handle. 1138 """ 1139 logging.debug('on_service_removed: status: %s, handle: %s', status, handle) 1140 1141 @utils.glib_callback() 1142 def on_characteristic_read_request(self, addr, trans_id, offset, is_long, handle): 1143 """Handles the read request of the characteristic callback. 1144 1145 Args: 1146 addr: Remote device MAC address. 1147 trans_id: Transaction id. 1148 offset: Represents the offset from which the attribute value should be read. 1149 is_long: A boolean value representing whether the characteristic size is longer than what we can put in the 1150 ATT PDU. 1151 handle: The characteristic handle. 1152 """ 1153 logging.debug( 1154 'on_characteristic_read_request: device address: %s, trans_id: %s, offset: %s, is_long: %s, handle: %s', 1155 addr, trans_id, offset, is_long, handle) 1156 1157 self.on_attr_read(addr, trans_id, offset, is_long, handle) 1158 1159 @utils.glib_callback() 1160 def on_descriptor_read_request(self, addr, trans_id, offset, is_long, handle): 1161 """Handles the read request of the descriptor callback. 1162 1163 Args: 1164 addr: Remote device MAC address. 1165 trans_id: Transaction id. 1166 offset: Represents the offset from which the descriptor value should be read. 1167 is_long: A boolean value representing whether the descriptor size is longer than what we can put in the 1168 ATT PDU. 1169 handle: The descriptor handle. 1170 """ 1171 logging.debug( 1172 'on_descriptor_read_request: device address: %s, trans_id: %s, offset: %s, is_long: %s, handle: %s', addr, 1173 trans_id, offset, is_long, handle) 1174 self.on_attr_read(addr, trans_id, offset, is_long, handle) 1175 1176 @utils.glib_callback() 1177 def on_characteristic_write_request(self, addr, trans_id, offset, length, is_prep, need_rsp, handle, value): 1178 """Handles the write request of the characteristic callback. 1179 1180 Args: 1181 addr: Remote device MAC address. 1182 trans_id: Transaction id. 1183 offset: Represents the offset at which the attribute value should be written. 1184 length: The length of the attribute value that should be written. 1185 is_prep: A boolean value representing whether it's a 'prepare write' command. 1186 need_rsp: A boolean value representing whether it's a 'write no response' command. 1187 handle: The characteristic handle. 1188 value: The value that should be written to the attribute. 1189 """ 1190 logging.debug( 1191 'on_characteristic_write_request: device address: %s, trans_id: %s, offset: %s, length: %s, is_prep: %s, ' 1192 'need_rsp: %s, handle: %s, values: %s', addr, trans_id, offset, length, is_prep, need_rsp, handle, value) 1193 self.on_attr_write(addr, trans_id, offset, length, is_prep, need_rsp, handle, value) 1194 1195 @utils.glib_callback() 1196 def on_descriptor_write_request(self, addr, trans_id, offset, length, is_prep, need_rsp, handle, value): 1197 """Handles the write request of the descriptor callback. 1198 1199 Args: 1200 addr: Remote device MAC address. 1201 trans_id: Transaction id. 1202 offset: The offset value at which the value should be written. 1203 length: The length of the value that should be written. 1204 is_prep: A boolean value representing whether it's a 'prepare write' command. 1205 need_rsp: A boolean value representing whether it's a 'write no response' command. 1206 handle: The descriptor handle. 1207 value: The value that should be written to the descriptor. 1208 """ 1209 logging.debug( 1210 'on_descriptor_write_request: device address: %s, trans_id: %s, offset: %s, length: %s, is_prep: %s, ' 1211 'need_rsp: %s, handle: %s, values: %s', addr, trans_id, offset, length, is_prep, need_rsp, handle, value) 1212 self.on_attr_write(addr, trans_id, offset, length, is_prep, need_rsp, handle, value) 1213 1214 @utils.glib_callback() 1215 def on_execute_write(self, addr, trans_id, exec_write): 1216 """Handles execute write callback. 1217 1218 Args: 1219 addr: Remote device MAC address. 1220 trans_id: Transaction id. 1221 exec_write: A boolean value that indicates whether the write operation should be executed or canceled. 1222 """ 1223 logging.debug('on_execute_write: device address: %s, trans_id: %s, exec_write: %s', addr, trans_id, exec_write) 1224 1225 if not exec_write: 1226 self.write_requests.clear() 1227 status = floss_enums.GattStatus.SUCCESS 1228 else: 1229 write_requests, self.write_requests = self.write_requests, collections.deque([]) 1230 for request in write_requests: 1231 _, _, offset2, length, _, _, handle2, value2 = request 1232 status, _ = self.generic_write(offset2, length, handle2, value2) 1233 if status != floss_enums.GattStatus.SUCCESS: 1234 break 1235 1236 self.proxy().SendResponse(self.server_id, addr, trans_id, status, 0, []) 1237 1238 @utils.glib_callback() 1239 def on_notification_sent(self, addr, status): 1240 """Handles notification sent callback. 1241 1242 Args: 1243 addr: Remote device MAC address. 1244 status: floss_enums.GattStatus. 1245 """ 1246 logging.debug('on_notification_sent: device address: %s, status: %s', addr, status) 1247 1248 @utils.glib_callback() 1249 def on_mtu_changed(self, addr, mtu): 1250 """Handles MTU changed callback. 1251 1252 Args: 1253 addr: Remote device MAC address. 1254 mtu: Maximum transmission unit. 1255 """ 1256 logging.debug('on_mtu_changed: device address: %s, mtu : %s', addr, mtu) 1257 self.mtu_value = mtu 1258 1259 @utils.glib_callback() 1260 def on_phy_update(self, addr, tx_phy, rx_phy, status): 1261 """Handles physical update callback. 1262 1263 Args: 1264 addr: Remote device MAC address. 1265 tx_phy: The new TX PHY for the connection. 1266 rx_phy: The new RX PHY for the connection. 1267 status: floss_enums.GattStatus. 1268 """ 1269 logging.debug('on_phy_update: device address: %s, tx_phy: %s, rx_phy: %s, status: %s', addr, tx_phy, rx_phy, 1270 status) 1271 1272 @utils.glib_callback() 1273 def on_phy_read(self, addr, tx_phy, rx_phy, status): 1274 """Handles physical read callback. 1275 1276 Args: 1277 addr: Remote device MAC address. 1278 tx_phy: The current transmit PHY for the connection. 1279 rx_phy: The current receive PHY for the connection. 1280 status: floss_enums.GattStatus. 1281 """ 1282 logging.debug('on_phy_read: device address: %s, tx_phy: %s, rx_phy: %s, status: %s', addr, tx_phy, rx_phy, 1283 status) 1284 1285 @utils.glib_callback() 1286 def on_connection_updated(self, addr, interval, latency, timeout, status): 1287 """Handles connection updated callback. 1288 1289 Args: 1290 addr: Remote device MAC address. 1291 interval: Connection interval value. 1292 latency: The number of consecutive connection events during which the device doesn't have to be listening. 1293 timeout: Supervision timeout for this connection in milliseconds. 1294 status: floss_enums.GattStatus. 1295 """ 1296 logging.debug('on_connection_updated: device address: %s, interval: %s, latency: %s, timeout: %s, status: %s', 1297 addr, interval, latency, timeout, status) 1298 1299 @utils.glib_callback() 1300 def on_subrate_change(self, addr, subrate_factor, latency, cont_num, timeout, status): 1301 """Handles subrate changed callback. 1302 1303 Args: 1304 addr: Remote device MAC address. 1305 subrate_factor: Subrate factor value. 1306 latency: The number of consecutive connection events during which the device doesn't have to be listening. 1307 cont_num: Continuation number. 1308 timeout: Supervision timeout for this connection in milliseconds. 1309 status: floss_enums.GattStatus. 1310 """ 1311 logging.debug( 1312 'on_subrate_change: device address: %s, subrate_factor: %s, latency: %s, cont_num: %s, timeout: %s, ' 1313 'status: %s', addr, subrate_factor, latency, cont_num, timeout, status) 1314 1315 @utils.glib_call(False) 1316 def has_proxy(self): 1317 """Checks whether GATT server proxy can be acquired.""" 1318 return bool(self.proxy()) 1319 1320 def proxy(self): 1321 """Gets proxy object to GATT server interface for method calls.""" 1322 return self.bus.get(self.ADAPTER_SERVICE, self.objpath)[self.GATT_SERVER_INTERFACE] 1323 1324 @utils.glib_call(False) 1325 def register_server(self, app_uuid, eatt_support): 1326 """Registers GATT server with provided UUID. 1327 1328 Args: 1329 app_uuid: GATT application uuid. 1330 eatt_support: A boolean value that indicates whether EATT is supported. 1331 1332 Returns: 1333 True on success, False otherwise. 1334 """ 1335 self.proxy().RegisterServer(app_uuid, self.cb_dbus_objpath, eatt_support) 1336 return True 1337 1338 @utils.glib_call(False) 1339 def unregister_server(self): 1340 """Unregisters GATT server for this client. 1341 1342 Returns: 1343 True on success, False otherwise. 1344 """ 1345 self.proxy().UnregisterServer(self.server_id) 1346 return True 1347 1348 @utils.glib_call(None) 1349 def server_connect(self, addr, is_direct, transport): 1350 """Connects remote device to GATT server. 1351 1352 Args: 1353 addr: Remote device MAC address. 1354 is_direct: A boolean value that specifies whether the connection should be made using direct connection. 1355 transport: BtTransport type. 1356 1357 Returns: 1358 Server connect as boolean on success, None otherwise. 1359 """ 1360 return self.proxy().ServerConnect(self.server_id, addr, is_direct, transport) 1361 1362 @utils.glib_call(None) 1363 def server_disconnect(self, addr): 1364 """Disconnects remote device from the GATT server. 1365 1366 Args: 1367 addr: Remote device MAC address. 1368 1369 Returns: 1370 Server disconnect as boolean on success, None otherwise. 1371 """ 1372 return self.proxy().ServerDisconnect(self.server_id, addr) 1373 1374 @utils.glib_call(False) 1375 def add_service(self, service): 1376 """Adds GATT service. 1377 1378 Args: 1379 service: BluetoothGattService. 1380 1381 Returns: 1382 True on success, False otherwise. 1383 """ 1384 self.proxy().AddService(self.server_id, service) 1385 return True 1386 1387 @utils.glib_call(False) 1388 def remove_service(self, handle): 1389 """Removes GATT service. 1390 1391 Args: 1392 handle: Service record handle. 1393 1394 Returns: 1395 True on success, False otherwise. 1396 """ 1397 self.proxy().RemoveService(self.server_id, handle) 1398 return True 1399 1400 @utils.glib_call(False) 1401 def clear_services(self): 1402 """Clears GATT services. 1403 1404 Returns: 1405 True on success, False otherwise. 1406 """ 1407 self.proxy().ClearServices(self.server_id) 1408 return True 1409 1410 @utils.glib_call(None) 1411 def send_response(self, addr, request_id, status, offset, value): 1412 """Sends GATT response. 1413 1414 Args: 1415 addr: Remote device MAC address. 1416 request_id: Request id. 1417 status: floss_enums.GattStatus. 1418 offset: The offset value to be sent in the response. 1419 value: The attribute value to be sent in the response. 1420 1421 Returns: 1422 Response send as boolean on success, None otherwise. 1423 """ 1424 return self.proxy().SendResponse(self.server_id, addr, request_id, status, offset, value) 1425 1426 @utils.glib_call(None) 1427 def send_notification(self, addr, handle, confirm, value): 1428 """Sends GATT notification. 1429 1430 Args: 1431 addr: Remote device MAC address. 1432 handle: The attribute handle of the attribute to send the notification for. 1433 confirm: A boolean value indicating whether the client should send a confirmation in response to 1434 the notification. 1435 value: The notification data to send. 1436 1437 Returns: 1438 Notification send as boolean on success, None otherwise. 1439 """ 1440 return self.proxy().SendNotification(self.server_id, addr, handle, confirm, value) 1441 1442 @utils.glib_call(False) 1443 def server_set_preferred_phy(self, addr, tx_phy, rx_phy, phy_options): 1444 """Sets preferred phy for server. 1445 1446 Args: 1447 addr: Remote device MAC address. 1448 tx_phy: Preferred PHY for transmitting data. 1449 rx_phy: Preferred PHY for receiving data. 1450 phy_options: Preferred Phy options. 1451 1452 Returns: 1453 True on success, False otherwise. 1454 """ 1455 self.proxy().ServerSetPreferredPhy(self.server_id, addr, tx_phy, rx_phy, phy_options) 1456 return True 1457 1458 @utils.glib_call(False) 1459 def server_read_phy(self, addr): 1460 """Reads phy of server. 1461 1462 Args: 1463 addr: Remote device MAC address. 1464 1465 Returns: 1466 True on success, False otherwise. 1467 """ 1468 self.proxy().ServerReadPhy(self.server_id, addr) 1469 return True 1470 1471 def register_callback_observer(self, name, observer): 1472 """Add an observer for all callbacks. 1473 1474 Args: 1475 name: Name of the observer. 1476 observer: Observer that implements all callback classes. 1477 """ 1478 if isinstance(observer, GattServerCallbacks): 1479 self.callbacks.add_observer(name, observer) 1480 1481 def unregister_callback_observer(self, name, observer): 1482 """Remove an observer for all callbacks. 1483 1484 Args: 1485 name: Name of the observer. 1486 observer: Observer that implements all callback classes. 1487 """ 1488 if isinstance(observer, GattServerCallbacks): 1489 self.callbacks.remove_observer(name, observer) 1490 1491 def make_dbus_descriptor(self, uuid, instance_id, permissions): 1492 """Makes struct for descriptor D-Bus. 1493 1494 Args: 1495 uuid : Descriptor UUID as string. 1496 instance_id: Descriptor identifier. 1497 permissions: Descriptor permissions. 1498 1499 Returns: 1500 Dictionary of descriptor. 1501 """ 1502 desc_uuid = utils.get_uuid_as_list(uuid) 1503 return { 1504 'uuid': GLib.Variant('ay', desc_uuid), 1505 'instance_id': GLib.Variant('i', instance_id), 1506 'permissions': GLib.Variant('i', permissions) 1507 } 1508 1509 def make_dbus_characteristic(self, uuid, instance_id, properties, permissions, key_size, write_type, descriptors): 1510 """Makes struct for characteristic D-Bus. 1511 1512 Args: 1513 uuid : Characteristic UUID as string. 1514 instance_id: Characteristic handle id. 1515 properties: Characteristic properties. 1516 permissions: Characteristic permissions. 1517 key_size: Characteristic key size. 1518 write_type: Characteristic write type. 1519 descriptors: Characteristic descriptors. 1520 1521 Returns: 1522 Dictionary of characteristic. 1523 """ 1524 desc = [] 1525 for d in descriptors: 1526 desc.append(self.make_dbus_descriptor(d['uuid'], d['instance_id'], d['permissions'])) 1527 char_uuid = utils.get_uuid_as_list(uuid) 1528 return { 1529 'uuid': GLib.Variant('ay', char_uuid), 1530 'instance_id': GLib.Variant('i', instance_id), 1531 'properties': GLib.Variant('i', properties), 1532 'permissions': GLib.Variant('i', permissions), 1533 'key_size': GLib.Variant('i', key_size), 1534 'write_type': GLib.Variant('u', write_type), 1535 'descriptors': GLib.Variant('aa{sv}', desc) 1536 } 1537 1538 def make_dbus_service(self, service): 1539 """Makes struct for service D-Bus. 1540 1541 Args: 1542 service: The struct of BluetoothGattService. 1543 1544 Returns: 1545 Dictionary of service. 1546 """ 1547 characteristics = [] 1548 for c in service['characteristics']: 1549 characteristics.append( 1550 self.make_dbus_characteristic(c['uuid'], c['instance_id'], c['properties'], c['permissions'], 1551 c['key_size'], c['write_type'], c['descriptors'])) 1552 1553 included_services = [] 1554 for s in service['included_services']: 1555 included_services.append(self.make_dbus_service(s)) 1556 service_uuid = utils.get_uuid_as_list(service['uuid']) 1557 return { 1558 'uuid': GLib.Variant('ay', service_uuid), 1559 'instance_id': GLib.Variant('i', service['instance_id']), 1560 'service_type': GLib.Variant('i', service['service_type']), 1561 'characteristics': GLib.Variant('aa{sv}', characteristics), 1562 'included_services': GLib.Variant('aa{sv}', included_services) 1563 } 1564