forked from auracaster/bumble_mirror
- Added Rust wrappers where relevant - Edited a couple logs in python l2cap_bridge to be more symmetrical - Created cli subcommand for running the rustified l2cap bridge
146 lines
4.2 KiB
Rust
146 lines
4.2 KiB
Rust
// Copyright 2023 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
|
|
//
|
|
// http://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.
|
|
|
|
//! HCI
|
|
|
|
use itertools::Itertools as _;
|
|
use pyo3::{
|
|
exceptions::PyException, intern, types::PyModule, FromPyObject, PyAny, PyErr, PyObject,
|
|
PyResult, Python, ToPyObject,
|
|
};
|
|
|
|
/// HCI error code.
|
|
pub struct HciErrorCode(u8);
|
|
|
|
impl<'source> FromPyObject<'source> for HciErrorCode {
|
|
fn extract(ob: &'source PyAny) -> PyResult<Self> {
|
|
Ok(HciErrorCode(ob.extract()?))
|
|
}
|
|
}
|
|
|
|
impl ToPyObject for HciErrorCode {
|
|
fn to_object(&self, py: Python<'_>) -> PyObject {
|
|
self.0.to_object(py)
|
|
}
|
|
}
|
|
|
|
/// Provides helpers for interacting with HCI
|
|
pub struct HciConstant;
|
|
|
|
impl HciConstant {
|
|
/// Human-readable error name
|
|
pub fn error_name(status: HciErrorCode) -> PyResult<String> {
|
|
Python::with_gil(|py| {
|
|
PyModule::import(py, intern!(py, "bumble.hci"))?
|
|
.getattr(intern!(py, "HCI_Constant"))?
|
|
.call_method1(intern!(py, "error_name"), (status.0,))?
|
|
.extract()
|
|
})
|
|
}
|
|
}
|
|
|
|
/// A Bluetooth address
|
|
pub struct Address(pub(crate) PyObject);
|
|
|
|
impl Address {
|
|
/// The type of address
|
|
pub fn address_type(&self) -> PyResult<AddressType> {
|
|
Python::with_gil(|py| {
|
|
let addr_type = self
|
|
.0
|
|
.getattr(py, intern!(py, "address_type"))?
|
|
.extract::<u32>(py)?;
|
|
|
|
let module = PyModule::import(py, intern!(py, "bumble.hci"))?;
|
|
let klass = module.getattr(intern!(py, "Address"))?;
|
|
|
|
if addr_type
|
|
== klass
|
|
.getattr(intern!(py, "PUBLIC_DEVICE_ADDRESS"))?
|
|
.extract::<u32>()?
|
|
{
|
|
Ok(AddressType::PublicDevice)
|
|
} else if addr_type
|
|
== klass
|
|
.getattr(intern!(py, "RANDOM_DEVICE_ADDRESS"))?
|
|
.extract::<u32>()?
|
|
{
|
|
Ok(AddressType::RandomDevice)
|
|
} else if addr_type
|
|
== klass
|
|
.getattr(intern!(py, "PUBLIC_IDENTITY_ADDRESS"))?
|
|
.extract::<u32>()?
|
|
{
|
|
Ok(AddressType::PublicIdentity)
|
|
} else if addr_type
|
|
== klass
|
|
.getattr(intern!(py, "RANDOM_IDENTITY_ADDRESS"))?
|
|
.extract::<u32>()?
|
|
{
|
|
Ok(AddressType::RandomIdentity)
|
|
} else {
|
|
Err(PyErr::new::<PyException, _>("Invalid address type"))
|
|
}
|
|
})
|
|
}
|
|
|
|
/// True if the address is static
|
|
pub fn is_static(&self) -> PyResult<bool> {
|
|
Python::with_gil(|py| {
|
|
self.0
|
|
.getattr(py, intern!(py, "is_static"))?
|
|
.extract::<bool>(py)
|
|
})
|
|
}
|
|
|
|
/// True if the address is resolvable
|
|
pub fn is_resolvable(&self) -> PyResult<bool> {
|
|
Python::with_gil(|py| {
|
|
self.0
|
|
.getattr(py, intern!(py, "is_resolvable"))?
|
|
.extract::<bool>(py)
|
|
})
|
|
}
|
|
|
|
/// Address bytes in _little-endian_ format
|
|
pub fn as_le_bytes(&self) -> PyResult<Vec<u8>> {
|
|
Python::with_gil(|py| {
|
|
self.0
|
|
.call_method0(py, intern!(py, "to_bytes"))?
|
|
.extract::<Vec<u8>>(py)
|
|
})
|
|
}
|
|
|
|
/// Address bytes as big-endian colon-separated hex
|
|
pub fn as_hex(&self) -> PyResult<String> {
|
|
self.as_le_bytes().map(|bytes| {
|
|
bytes
|
|
.into_iter()
|
|
.rev()
|
|
.map(|byte| hex::encode_upper([byte]))
|
|
.join(":")
|
|
})
|
|
}
|
|
}
|
|
|
|
/// BT address types
|
|
#[allow(missing_docs)]
|
|
#[derive(PartialEq, Eq, Debug)]
|
|
pub enum AddressType {
|
|
PublicDevice,
|
|
RandomDevice,
|
|
PublicIdentity,
|
|
RandomIdentity,
|
|
}
|