1#!/usr/bin/env python3

2#

3# This file is part of Checkbox.

4#

5# Copyright 2018-2023 Canonical Ltd.

6#

7# Authors:

8# Jonathan Cave <jonathan.cave@canonical.com>

9# Pierre Equoy <pierre.equoy@canonical.com>

10#

11# Checkbox is free software: you can redistribute it and/or modify

12# it under the terms of the GNU General Public License version 3,

13# as published by the Free Software Foundation.

14#

15# Checkbox is distributed in the hope that it will be useful,

16# but WITHOUT ANY WARRANTY; without even the implied warranty of

17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

18# GNU General Public License for more details.

19#

20# You should have received a copy of the GNU General Public License

21# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.

22

23 import sys

24 from collections import namedtuple

25 from pathlib import Path

26

27

28 BTDevice = namedtuple("BTDevice", ["sysfs_name", "device_name"])

29

30

31 def get_node_content(path: Path):

32 """Retrieve the content from a sysfs path.

33

34 :param path: path to the sysfs node

35 :type path: str or Path

36 :return: content of the sysfs node

37 :rtype: str

38 """

39 with path.open("r") as f:

40 content = f.read().strip()

41 return content

42

43

44 def is_bluetooth_adapter(path):

45 """Check if a given sysfs node is a bluetooth adapter.

46

47 :param path: Path to the sysfs node

48 :type path: Path

49 :return: `True` if it is a bluetooth adapter, `False` otherwise

50 :rtype: bool

51 """

52 type = get_node_content(path / "type")

53 if type == "bluetooth":

54 return True

55 return False

56

57

58 def get_bluetooth_devices(paths_list):

59 """Retrieve information about bluetooth devices from a list of sysfs paths.

60

61 :param paths_list: List of sysfs paths to check

62 :type paths_list: list

63 :return: List of named tuples containing the sysfs basename and the device

64 name, for example:

65 [BTDevice(sysfs_name='rfkill3', device_name='dell-bluetooth'),]

66 :rtype: list

67 """

68 rf_devices = []

69 for rfdev in paths_list:

70 if is_bluetooth_adapter(rfdev): 70 ↛ 69 line 70 didn't jump to line 69 because the condition on line 70 was always true

71 device_name = get_node_content(rfdev / "name")

72 btdev = BTDevice(rfdev.name, device_name)

73 rf_devices.append(btdev)

74 return rf_devices

75

76

77 def main():

78 try:

79 rf_devices_paths = list(Path("/sys/class/rfkill").iterdir())

80 except FileNotFoundError:

81 rf_devices_paths = []

82 rf_devices = get_bluetooth_devices(rf_devices_paths)

83 if rf_devices:

84 for rf_device in rf_devices:

85 print(" ".join(rf_device))

86 else:

87 raise SystemExit("No bluetooth adapters registered with rfkill")

88

89

90 if __name__ == "__main__":

91 sys.exit(main())