diff --git a/apps/controller_info.py b/apps/controller_info.py new file mode 100644 index 0000000..74d4550 --- /dev/null +++ b/apps/controller_info.py @@ -0,0 +1,105 @@ +# Copyright 2021-2022 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ----------------------------------------------------------------------------- +# Imports +# ----------------------------------------------------------------------------- +import asyncio +import os +import logging +import click +from colors import color +from bumble.company_ids import COMPANY_IDENTIFIERS + +from bumble.core import name_or_number +from bumble.hci import ( + map_null_terminated_utf8_string, + HCI_LE_SUPPORTED_FEATURES_NAMES, + HCI_SUCCESS, + HCI_VERSION_NAMES, + LMP_VERSION_NAMES, + HCI_Command, + HCI_Read_BD_ADDR_Command, + HCI_READ_BD_ADDR_COMMAND, + HCI_Read_Local_Name_Command, + HCI_READ_LOCAL_NAME_COMMAND +) +from bumble.host import Host +from bumble.transport import open_transport_or_link + + +# ----------------------------------------------------------------------------- +async def get_classic_info(host): + if host.supports_command(HCI_READ_BD_ADDR_COMMAND): + response = await host.send_command(HCI_Read_BD_ADDR_Command()) + if response.return_parameters.status == HCI_SUCCESS: + print() + print(color('Classic Address:', 'yellow'), response.return_parameters.bd_addr) + + if host.supports_command(HCI_READ_LOCAL_NAME_COMMAND): + response = await host.send_command(HCI_Read_Local_Name_Command()) + if response.return_parameters.status == HCI_SUCCESS: + print() + print(color('Local Name:', 'yellow'), map_null_terminated_utf8_string(response.return_parameters.local_name)) + + +# ----------------------------------------------------------------------------- +async def get_le_info(host): + print() + print(color('LE Features:', 'yellow')) + for feature in host.supported_le_features: + print(' ', name_or_number(HCI_LE_SUPPORTED_FEATURES_NAMES, feature)) + + +# ----------------------------------------------------------------------------- +async def async_main(transport): + print('<<< connecting to HCI...') + async with await open_transport_or_link(transport) as (hci_source, hci_sink): + print('<<< connected') + + host = Host(hci_source, hci_sink) + await host.reset() + + # Print version + print(color('Version:', 'yellow')) + print(color(' Manufacturer: ', 'green'), name_or_number(COMPANY_IDENTIFIERS, host.local_version.company_identifier)) + print(color(' HCI Version: ', 'green'), name_or_number(HCI_VERSION_NAMES, host.local_version.hci_version)) + print(color(' HCI Subversion:', 'green'), host.local_version.hci_subversion) + print(color(' LMP Version: ', 'green'), name_or_number(LMP_VERSION_NAMES, host.local_version.lmp_version)) + print(color(' LMP Subversion:', 'green'), host.local_version.lmp_subversion) + + # Get the Classic info + await get_classic_info(host) + + # Get the LE info + await get_le_info(host) + + # Print the list of commands supported by the controller + print() + print(color('Supported Commands:', 'yellow')) + for command in host.supported_commands: + print(' ', HCI_Command.command_name(command)) + + +# ----------------------------------------------------------------------------- +@click.command() +@click.argument('transport') +def main(transport): + logging.basicConfig(level = os.environ.get('BUMBLE_LOGLEVEL', 'WARNING').upper()) + asyncio.run(async_main(transport)) + + +# ----------------------------------------------------------------------------- +if __name__ == '__main__': + main()