138 lines
4.0 KiB
Python
138 lines
4.0 KiB
Python
|
|
# 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}))
|