1# Copyright 2021-2022 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""" 15Drivers that can be used to customize the interaction between a host and a controller, 16like loading firmware after a cold start. 17""" 18 19# ----------------------------------------------------------------------------- 20# Imports 21# ----------------------------------------------------------------------------- 22from __future__ import annotations 23import logging 24import pathlib 25import platform 26from typing import Dict, Iterable, Optional, Type, TYPE_CHECKING 27 28from . import rtk, intel 29from .common import Driver 30 31if TYPE_CHECKING: 32 from bumble.host import Host 33 34# ----------------------------------------------------------------------------- 35# Logging 36# ----------------------------------------------------------------------------- 37logger = logging.getLogger(__name__) 38 39 40# ----------------------------------------------------------------------------- 41# Functions 42# ----------------------------------------------------------------------------- 43async def get_driver_for_host(host: Host) -> Optional[Driver]: 44 """Probe diver classes until one returns a valid instance for a host, or none is 45 found. 46 If a "driver" HCI metadata entry is present, only that driver class will be probed. 47 """ 48 driver_classes: Dict[str, Type[Driver]] = {"rtk": rtk.Driver, "intel": intel.Driver} 49 probe_list: Iterable[str] 50 if driver_name := host.hci_metadata.get("driver"): 51 # Only probe a single driver 52 probe_list = [driver_name] 53 else: 54 # Probe all drivers 55 probe_list = driver_classes.keys() 56 57 for driver_name in probe_list: 58 if driver_class := driver_classes.get(driver_name): 59 logger.debug(f"Probing driver class: {driver_name}") 60 if driver := await driver_class.for_host(host): 61 logger.debug(f"Instantiated {driver_name} driver") 62 return driver 63 else: 64 logger.debug(f"Skipping unknown driver class: {driver_name}") 65 66 return None 67 68 69def project_data_dir() -> pathlib.Path: 70 """ 71 Returns: 72 A path to an OS-specific directory for bumble data. The directory is created if 73 it doesn't exist. 74 """ 75 import platformdirs 76 77 if platform.system() == 'Darwin': 78 # platformdirs doesn't handle macOS right: it doesn't assemble a bundle id 79 # out of author & project 80 return platformdirs.user_data_path( 81 appname='com.google.bumble', ensure_exists=True 82 ) 83 else: 84 # windows and linux don't use the com qualifier 85 return platformdirs.user_data_path( 86 appname='bumble', appauthor='google', ensure_exists=True 87 ) 88