# Lint as: python2, python3 # Copyright 2019 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Provides utilities to support bluetooth adapter tests""" from __future__ import absolute_import import logging import re import uuid import common from autotest_lib.client.bin.input.linux_input import EV_KEY from autotest_lib.server.cros.bluetooth.debug_linux_keymap import ( linux_input_keymap) from ast import literal_eval as make_tuple def reconstruct_string(events): """ Tries to reconstruct a string from linux input in a simple way @param events: list of event objects received over the BT channel @returns: reconstructed string """ recon = [] for ev in events: # If it's a key pressed event if ev.type == EV_KEY and ev.value == 1: recon.append(linux_input_keymap.get(ev.code, "_")) return "".join(recon) def parse_trace_file(filename): """ Reads contents of trace file @param filename: location of trace file on disk @returns: structure containing contents of filename """ contents = [] try: with open(filename, 'r') as mf: for line in mf: # Reconstruct tuple and add to trace contents.append(make_tuple(line)) except EnvironmentError: logging.error('Unable to open file %s', filename) return None return contents class Bluetooth_UUID(uuid.UUID): """A class to manipulate Bluetooth UUIDs.""" BLUETOOTH_BASE_UUID_FORMAT = '%s-0000-1000-8000-00805F9B34FB' def __init__(self, hex_str): super(Bluetooth_UUID, self).__init__(hex_str) @classmethod def create_valid_uuid(cls, hex_str): """Create valid long UUIDs based on Bluetooth short UUIDs. @param hex_str: the hex string that represents a short or long UUID. @returns: the UUID object if successful; or None otherwise. """ h = re.sub('^0x', '', hex_str).replace('-', '') # The Bluetooth spec only allowed short UUIDs in 16 bits or 32 bits. # The long UUID takes 128 bits. # Reference: # www.bluetooth.com/specifications/assigned-numbers/service-discovery hlen = len(h) if hlen not in (4, 8, 32): return None # Convert the short UUIDs to the full UUID. if hlen in (4, 8): h = cls.BLUETOOTH_BASE_UUID_FORMAT % h.zfill(8) return cls(h) class BluetoothPolicy(object): """A helper class to keep popular bluetooth service lists. Refer to https://www.bluetooth.com/specifications/assigned-numbers/service-discovery/ """ def to_allowlist(uuids): """Helper function to convert a group of uuids to allowlist format @param uuids: an iterable object of UUID string @returns: comma-separated UUID string """ return ','.join(list(uuids)) UUID_HID = '0x1124' UUID_HOG = '0x1812' UUID_DIS = '0x180a' UUID_BATT = '0x180f' UUID_A2DP = '0x110d' UUID_AUDIO_SOURCE = '0x110a' UUID_AUDIO_SINK = '0x110b' UUID_AVRCP = '0x110e' UUID_AVRCP_TARGET = '0x110c' UUID_AVRCP_CONTROLLER = '0x110f' UUID_GENERIC_AUDIO = '0x1203' UUID_HANDSFREE = '0x111e' UUID_HANDSFREE_AUDIO_GATEWAY = '0x111f' UUID_HEADSET = '0x1108' UUID_HEADSET_AUDIO_GATEWAY = '0x1112' UUIDSET_BLE_HID = {UUID_HOG, UUID_DIS, UUID_BATT} UUIDSET_AUDIO = {UUID_A2DP, UUID_AUDIO_SINK, UUID_AUDIO_SOURCE, UUID_AVRCP, UUID_AVRCP_TARGET, UUID_AVRCP_CONTROLLER, UUID_GENERIC_AUDIO, UUID_HANDSFREE, UUID_HANDSFREE_AUDIO_GATEWAY, UUID_HEADSET, UUID_HEADSET_AUDIO_GATEWAY} ALLOWLIST_CLASSIC_HID = UUID_HID ALLOWLIST_BLE_HID = to_allowlist(UUIDSET_BLE_HID) ALLOWLIST_AUDIO = to_allowlist(UUIDSET_AUDIO) ALLOWLIST_BLE_HID_AUDIO = to_allowlist(UUIDSET_BLE_HID.union(UUIDSET_AUDIO)) ALLOWLIST_CLASSIC_BLE_HID = to_allowlist(UUIDSET_BLE_HID.union({UUID_HID}))