diff --git a/blueman/gui/manager/ManagerDeviceList.py b/blueman/gui/manager/ManagerDeviceList.py index d1b4120aa..5ad3426eb 100644 --- a/blueman/gui/manager/ManagerDeviceList.py +++ b/blueman/gui/manager/ManagerDeviceList.py @@ -1,5 +1,5 @@ from gettext import gettext as _ -from typing import Optional, TYPE_CHECKING, List, Any, cast, Callable, Set, Dict +from typing import Optional, TYPE_CHECKING, List, Any, cast, Callable, Dict import html import logging import cairo @@ -16,12 +16,10 @@ from blueman.Functions import launch from blueman.Sdp import ServiceUUID, OBEX_OBJPUSH_SVCLASS_ID from blueman.gui.GtkAnimation import TreeRowFade, CellFade, AnimBase -from _blueman import ConnInfoReadError, conn_info import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk -from gi.repository import GLib from gi.repository import Gio from gi.repository import Gdk from gi.repository import GdkPixbuf @@ -71,8 +69,6 @@ def __init__(self, inst: "Blueman", adapter: Optional[str] = None) -> None: self.props.has_tooltip = True self.Blueman = inst - self._monitored_devices: Set[str] = set() - self.manager.connect_signal("battery-created", self.on_battery_created) self.manager.connect_signal("battery-removed", self.on_battery_removed) self._batteries: Dict[str, Battery] = {} @@ -368,48 +364,6 @@ def row_setup_event(self, tree_iter: Gtk.TreeIter, device: Device) -> None: except Exception as e: logging.exception(e) - if device["Connected"]: - self._monitor_power_levels(tree_iter, device) - - def _monitor_power_levels(self, tree_iter: Gtk.TreeIter, device: Device) -> None: - if device["Address"] in self._monitored_devices: - return - - assert self.Adapter is not None - cinfo = conn_info(device["Address"], os.path.basename(self.Adapter.get_object_path())) - try: - cinfo.init() - except ConnInfoReadError: - logging.warning("Failed to get power levels, probably a LE device.") - - model = self.liststore - assert isinstance(model, Gtk.TreeModel) - r = Gtk.TreeRowReference.new(model, model.get_path(tree_iter)) - self._update_power_levels(tree_iter, device, cinfo) - GLib.timeout_add(1000, self._check_power_levels, r, cinfo, device["Address"]) - self._monitored_devices.add(device["Address"]) - - def _check_power_levels(self, row_ref: Gtk.TreeRowReference, cinfo: conn_info, address: str) -> bool: - if not row_ref.valid(): - logging.warning("stopping monitor (row does not exist)") - cinfo.deinit() - self._monitored_devices.remove(address) - return False - - tree_iter = self.get_iter(row_ref.get_path()) - assert tree_iter is not None - - device = self.get(tree_iter, "device")["device"] - - if device["Connected"]: - self._update_power_levels(tree_iter, device, cinfo) - return True - else: - cinfo.deinit() - self._disable_power_levels(tree_iter) - self._monitored_devices.remove(address) - return False - def row_update_event(self, tree_iter: Gtk.TreeIter, key: str, value: Any) -> None: logging.info(f"{key} {value}") @@ -438,9 +392,7 @@ def row_update_event(self, tree_iter: Gtk.TreeIter, key: str, value: Any) -> Non elif key == "Connected": self.set(tree_iter, connected=value) - if value: - self._monitor_power_levels(tree_iter, self.get(tree_iter, "device")["device"]) - else: + if not value: self._disable_power_levels(tree_iter) elif key == "Name": self.set(tree_iter, no_name=False) @@ -449,28 +401,15 @@ def row_update_event(self, tree_iter: Gtk.TreeIter, key: str, value: Any) -> Non elif key == "Blocked": self.set(tree_iter, blocked=value) - def _update_power_levels(self, tree_iter: Gtk.TreeIter, device: Device, cinfo: conn_info) -> None: - row = self.get(tree_iter, "cell_fader", "battery", "rssi", "lq", "tpl") - - bars = {} + elif key == "RSSI": + self._update_bar(tree_iter, "rssi", 50 if value is None else max(50 + float(value) / 127 * 50, 10)) - obj_path = device.get_object_path() - if obj_path in self._batteries: - bars["battery"] = self._batteries[obj_path]["Percentage"] + elif key == "TxPower": + self._update_bar(tree_iter, "tpl", 0 if value is None else max(float(value) / 127 * 100, 10)) - # cinfo init may fail for bluetooth devices version 4 and up - # FIXME Workaround is horrible and we should show something better - if cinfo.failed: - bars.update({"rssi": 100.0, "tpl": 100.0}) - else: - try: - bars["rssi"] = max(50 + float(cinfo.get_rssi()) / 127 * 50, 10) - except ConnInfoReadError: - bars["rssi"] = 50 - try: - bars["tpl"] = max(50 + float(cinfo.get_tpl()) / 127 * 50, 10) - except ConnInfoReadError: - bars["tpl"] = 50 + def _update_bar(self, tree_iter: Gtk.TreeIter, name: str, perc: float) -> None: + row = self.get(tree_iter, "cell_fader", "battery", "rssi", "tpl") + row[name] = perc if row["battery"] == row["rssi"] == row["tpl"] == 0: self._prepare_fader(row["cell_fader"]).animate(start=0.0, end=1.0, duration=400) @@ -478,11 +417,10 @@ def _update_power_levels(self, tree_iter: Gtk.TreeIter, device: Device, cinfo: c w = 14 * self.get_scale_factor() h = 48 * self.get_scale_factor() - for (name, perc) in bars.items(): - if round(row[name], -1) != round(perc, -1): - icon_name = f"blueman-{name}-{int(round(perc, -1))}.png" - icon = GdkPixbuf.Pixbuf.new_from_file_at_scale(os.path.join(PIXMAP_PATH, icon_name), w, h, True) - self.set(tree_iter, **{name: perc, f"{name}_pb": icon}) + if round(row[name], -1) != round(perc, -1): + icon_name = f"blueman-{name}-{int(round(perc, -1))}.png" + icon = GdkPixbuf.Pixbuf.new_from_file_at_scale(os.path.join(PIXMAP_PATH, icon_name), w, h, True) + self.set(tree_iter, **{name: perc, f"{name}_pb": icon}) def _disable_power_levels(self, tree_iter: Gtk.TreeIter) -> None: row = self.get(tree_iter, "cell_fader", "battery", "rssi", "tpl") diff --git a/module/_blueman.pyx b/module/_blueman.pyx index 2b53d6dea..30f124da3 100644 --- a/module/_blueman.pyx +++ b/module/_blueman.pyx @@ -72,15 +72,6 @@ cdef extern from "bluetooth/rfcomm.h": cdef extern from "libblueman.h": - cdef struct conn_info_handles: - unsigned int handle - int dd - - - cdef int connection_init(int dev_id, char *addr, conn_info_handles *ci) - cdef int connection_get_rssi(conn_info_handles *ci, signed char *ret_rssi) - cdef int connection_get_tpl(conn_info_handles *ci, signed char *ret_tpl, unsigned char type) - cdef int connection_close(conn_info_handles *ci) cdef int c_get_rfcomm_channel "get_rfcomm_channel" (unsigned short service_class, char* btd_addr) cdef int get_rfcomm_list(rfcomm_dev_list_req **ret) cdef int c_create_rfcomm_device "create_rfcomm_device" (char *local_address, char *remote_address, int channel) @@ -94,11 +85,6 @@ class RFCOMMError(Exception): ERR = { -1:"Can't allocate memory", - -2:"HCI device open failed", - -3:"Not connected", - -4:"Get connection info failed", - -5:"Read RSSI failed", - -6:"Read transmit power level request failed", -8:"Getting rfcomm list failed", -9:"ERR_SOCKET_FAILED", -12: "Can't bind RFCOMM socket", @@ -205,55 +191,6 @@ def destroy_bridge(py_name="pan1"): if err < 0: raise BridgeException(-err) - -class ConnInfoReadError(Exception): - pass - -cdef class conn_info: - cdef conn_info_handles ci - cdef int hci - cdef char* addr - cdef public bint failed - - def __init__(self, py_addr, py_hci_name="hci0"): - self.failed = False - py_bytes_addr = py_addr.encode("UTF-8") - cdef char* addr = py_bytes_addr - - py_bytes_hci_name = py_hci_name.encode("UTF-8") - cdef char* hci_name = py_bytes_hci_name - - - self.hci = int(hci_name[3:]) - self.addr = addr - - def init(self): - res = connection_init(self.hci, self.addr, & self.ci) - if res < 0: - self.failed = True - raise ConnInfoReadError(ERR[res]) - - def deinit(self): - if self.failed: - return - connection_close(&self.ci) - - def get_rssi(self): - cdef signed char rssi - res = connection_get_rssi(&self.ci, &rssi) - if res < 0: - raise ConnInfoReadError(ERR[res]) - - return rssi - - def get_tpl(self, tp=0): - cdef signed char tpl - res = connection_get_tpl(&self.ci, &tpl, tp) - if res < 0: - raise ConnInfoReadError(ERR[res]) - - return tpl - def device_info(py_hci_name="hci0"): py_bytes_hci_name = py_hci_name.encode("UTF-8") cdef char* hci_name = py_bytes_hci_name diff --git a/module/libblueman.c b/module/libblueman.c index 03c94f74a..ddd5c09ba 100644 --- a/module/libblueman.c +++ b/module/libblueman.c @@ -35,8 +35,6 @@ #include #include -#include -#include #include #include #include @@ -132,109 +130,6 @@ int _destroy_bridge(const char* name) { return 0; } -static int find_conn(int s, int dev_id, long arg) -{ - struct hci_conn_list_req *cl; - struct hci_conn_info *ci; - int i; - int ret = 0; - - if (!(cl = malloc(10 * sizeof(*ci) + sizeof(*cl)))) - goto out; - - cl->dev_id = dev_id; - cl->conn_num = 10; - ci = cl->conn_info; - - if (ioctl(s, HCIGETCONNLIST, (void *) cl)) - goto out; - - for (i = 0; i < cl->conn_num; i++, ci++) - if (!bacmp((bdaddr_t *) arg, &ci->bdaddr)) { - ret = 1; - goto out; - } - -out: - free(cl); - return ret; -} - - - -int connection_init(int dev_id, char *addr, struct conn_info_handles *ci) -{ - struct hci_conn_info_req *cr = NULL; - bdaddr_t bdaddr; - - int dd; - int ret = 1; - - str2ba(addr, &bdaddr); - - if (dev_id < 0) { - dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); - if (dev_id < 0) { - ret = ERR_NOT_CONNECTED; - goto out; - } - } - - dd = hci_open_dev(dev_id); - if (dd < 0) { - ret = ERR_HCI_DEV_OPEN_FAILED; - goto out; - } - - cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); - if (!cr) { - ret = ERR_CANNOT_ALLOCATE; - goto out; - } - - bacpy(&cr->bdaddr, &bdaddr); - cr->type = ACL_LINK; - if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { - ret = ERR_GET_CONN_INFO_FAILED; - goto out; - } - - ci->dd = dd; - ci->handle = cr->conn_info->handle; - -out: - if (cr) - free(cr); - - return ret; -} - -int connection_get_rssi(struct conn_info_handles *ci, int8_t *ret_rssi) -{ - int8_t rssi; - if (hci_read_rssi(ci->dd, htobs(ci->handle), &rssi, 1000) < 0) { - return ERR_READ_RSSI_FAILED; - } - *ret_rssi = rssi; - return 1; - -} - -int connection_get_tpl(struct conn_info_handles *ci, int8_t *ret_tpl, uint8_t type) -{ - int8_t level; - if (hci_read_transmit_power_level(ci->dd, htobs(ci->handle), type, &level, 1000) < 0) { - return ERR_READ_TPL_FAILED; - } - *ret_tpl = level; - return 1; -} - -int connection_close(struct conn_info_handles *ci) -{ - hci_close_dev(ci->dd); - return 1; -} int get_rfcomm_channel(uint16_t service_class, char* btd_addr) { diff --git a/module/libblueman.h b/module/libblueman.h index 3f1b56a21..9ad6bfb7f 100644 --- a/module/libblueman.h +++ b/module/libblueman.h @@ -1,10 +1,5 @@ #pragma once #define ERR_CANNOT_ALLOCATE -1 -#define ERR_HCI_DEV_OPEN_FAILED -2 -#define ERR_NOT_CONNECTED -3 -#define ERR_GET_CONN_INFO_FAILED -4 -#define ERR_READ_RSSI_FAILED -5 -#define ERR_READ_TPL_FAILED -6 #define ERR_GET_RFCOMM_LIST_FAILED -8 #define ERR_SOCKET_FAILED -9 #define ERR_BIND_FAILED -12 @@ -12,15 +7,6 @@ #define ERR_CREATE_DEV_FAILED -14 #define ERR_RELEASE_DEV_FAILED -15 -struct conn_info_handles { - unsigned int handle; - int dd; -}; - -int connection_init(int dev_id, char *addr, struct conn_info_handles *ci); -int connection_get_rssi(struct conn_info_handles *ci, int8_t *ret_rssi); -int connection_get_tpl(struct conn_info_handles *ci, int8_t *ret_tpl, uint8_t type); -int connection_close(struct conn_info_handles *ci); int get_rfcomm_channel(uint16_t uuid, char* btd_addr); int get_rfcomm_list(struct rfcomm_dev_list_req **result); int create_rfcomm_device(char *local_address, char *remote_address, int channel); diff --git a/stubs/_blueman.pyi b/stubs/_blueman.pyi index 59d93181d..8bf0b645f 100644 --- a/stubs/_blueman.pyi +++ b/stubs/_blueman.pyi @@ -35,18 +35,8 @@ class BridgeException(Exception): errno: int def __init__(self, errno: int) -> None: ... -class ConnInfoReadError(Exception): ... - class RFCOMMError(Exception): ... -class conn_info: - failed: bool - def __init__(self, addr: str, hci_name: str) -> None: ... - def deinit(self) -> None: ... - def get_rssi(self) -> int: ... - def get_tpl(self) -> int: ... - def init(self) -> None: ... - def create_bridge(name: str = "pan1") -> None: ... def create_rfcomm_device(local_address: str, remote_address: str, channel: int) -> int: ... def destroy_bridge(name: str = "pan1") -> None: ...