Home | History | Annotate | Download | only in chameleon
      1 # Copyright 2015 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 """This module provides the utilities for bluetooth audio using chameleon."""
      6 
      7 import logging
      8 import time
      9 
     10 from autotest_lib.client.bin import utils
     11 
     12 
     13 _PIN = '0000'
     14 _SEARCH_TIMEOUT = 30.0
     15 _PAIRING_TIMEOUT = 5.0
     16 _CONNECT_TIMEOUT = 15.0
     17 
     18 
     19 class ChameleonBluetoothAudioError(Exception):
     20     """Error in this module."""
     21     pass
     22 
     23 
     24 def connect_bluetooth_module_full_flow(bt_adapter, target_mac_address,
     25                              timeout=_SEARCH_TIMEOUT):
     26     """Controls Cros device to connect to bluetooth module on audio board.
     27 
     28     @param bt_adapter: A BluetoothDevice object to control bluetooth adapter
     29                        on Cros device.
     30     @param target_mac_address: The MAC address of bluetooth module to be
     31                                connected.
     32     @param timeout: Timeout in seconds to search for bluetooth module.
     33 
     34     @raises: ChameleonBluetoothAudioError if Cros device fails to connect to
     35              bluetooth module on audio board.
     36 
     37     """
     38     # Resets bluetooth adapter on Cros device.
     39     if not bt_adapter.reset_on():
     40         raise ChameleonBluetoothAudioError(
     41                 'Failed to reset bluetooth adapter on Cros host.'
     42                 ' You should check if controller is available on Cros host'
     43                 ' using bluetoothctl.')
     44 
     45     # Starts discovery mode of bluetooth adapter.
     46     if not bt_adapter.start_discovery():
     47         raise ChameleonBluetoothAudioError(
     48                 'Failed to start discovery on bluetooth adapter on Cros host')
     49 
     50     def _find_device():
     51         """Controls bluetooth adapter to search for bluetooth module.
     52 
     53         @returns: True if there is a bluetooth device with MAC address
     54                   matches target_mac_address. False otherwise.
     55 
     56         """
     57         return bt_adapter.has_device(target_mac_address)
     58 
     59     # Searches for bluetooth module with given MAC address.
     60     found_device = utils.wait_for_value(_find_device, True, timeout_sec=timeout)
     61 
     62     if not found_device:
     63         raise ChameleonBluetoothAudioError(
     64                 'Can not find bluetooth module with MAC address %s' %
     65                 target_mac_address)
     66 
     67     pair_legacy_bluetooth_module(bt_adapter, target_mac_address)
     68 
     69     # Disconnects from bluetooth module to clean up the state.
     70     if not bt_adapter.disconnect_device(target_mac_address):
     71         raise ChameleonBluetoothAudioError(
     72                 'Failed to let Cros device disconnect from bluetooth module %s' %
     73                 target_mac_address)
     74 
     75     # Connects to bluetooth module.
     76     connect_bluetooth_module(bt_adapter, target_mac_address)
     77 
     78     logging.info('Bluetooth module at %s is connected', target_mac_address)
     79 
     80 
     81 def connect_bluetooth_module(bt_adapter, target_mac_address,
     82                              timeout=_CONNECT_TIMEOUT):
     83     """Controls Cros device to connect to bluetooth module on audio board.
     84 
     85     @param bt_adapter: A BluetoothDevice object to control bluetooth adapter
     86                        on Cros device.
     87     @param target_mac_address: The MAC address of bluetooth module to be
     88                                connected.
     89     @param timeout: Timeout in seconds to connect bluetooth module.
     90 
     91     @raises: ChameleonBluetoothAudioError if Cros device fails to connect to
     92              bluetooth module on audio board.
     93 
     94     """
     95     def _connect_device():
     96         success = bt_adapter.connect_device(target_mac_address)
     97         if not success:
     98             logging.debug('Can not connect device, retry in 1 second.')
     99             time.sleep(1)
    100             return False
    101         logging.debug('Connection established.')
    102         return True
    103 
    104     # Connects bluetooth module with given MAC address.
    105     connected = utils.wait_for_value(_connect_device, True, timeout_sec=timeout)
    106     if not connected:
    107         raise ChameleonBluetoothAudioError(
    108                 'Failed to let Cros device connect to bluetooth module %s' %
    109                 target_mac_address)
    110 
    111 
    112 def pair_legacy_bluetooth_module(bt_adapter, target_mac_address, pin=_PIN,
    113                                  pairing_timeout=_PAIRING_TIMEOUT, retries=3):
    114     """Pairs Cros device bluetooth adapter with legacy bluetooth module.
    115 
    116     @param bt_adapter: A BluetoothDevice object to control bluetooth adapter
    117                        on Cros device.
    118     @param target_mac_address: The MAC address of bluetooth module to be
    119                                paired.
    120     @param pin: The pin for legacy pairing.
    121     @param timeout: Timeout in seconds to pair bluetooth module in a trial.
    122     @param retries: Number of retries if pairing fails.
    123 
    124     @raises: ChameleonBluetoothAudioError if Cros device fails to pair
    125              bluetooth module on audio board after all the retries.
    126 
    127     """
    128     # Pairs the bluetooth adapter with bluetooth module.
    129     for trial in xrange(retries):
    130         if bt_adapter.pair_legacy_device(
    131             target_mac_address, pin, pairing_timeout):
    132                 logging.debug('Pairing to %s succeeded', target_mac_address)
    133                 return
    134         elif trial == retries - 1:
    135             raise ChameleonBluetoothAudioError(
    136                     'Failed to pair Cros device and bluetooth module %s' %
    137                     target_mac_address)
    138 
    139         logging.debug('Retry for pairing...')
    140