Giter VIP home page Giter VIP logo

bluez-rs's Introduction

bluez-rs

A library for controlling Bluetooth on Linux.

crates.io crates.io

Documentation Examples

Some of the examples require elevated permissions. For example, to run the discover example, clone this repository, cargo build --example discover, then sudo setcap cap_net_admin+ep target/debug/examples/discover, then target/debug/examples/discover. Many of the functions of this crate are not possible without the CAP_NET_ADMIN capability.

License

This project is licensed under the MIT license.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in bluez by you, shall be licensed as MIT, without any additional terms or conditions.

bluez-rs's People

Contributors

dependabot[bot] avatar jacobrosenthal avatar laptou avatar oxc avatar pluehne avatar timvisee avatar tpoliaw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

bluez-rs's Issues

Panic on `set_local_name`

I'm attempting to set the publicly visible name for my bluetooth controller using set_local_name. This function panics though. Calling other functions such as set_discoverable works fine.

For example, this panics:

block_on(client.set_local_name(controller, "PokoeBox", None));

Here's a trace:

thread 'main' panicked at 'assertion failed: self.remaining() >= dst.len()', /home/timvisee/.cargo/registry/src/github.com-1ecc6299db9ec823/bytes-0.5.4/src/buf/buf_impl.rs:245:9
stack backtrace:
   0: backtrace::backtrace::libunwind::trace
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88
   1: backtrace::backtrace::trace_unsynchronized
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66
   2: std::sys_common::backtrace::_print_fmt
             at src/libstd/sys_common/backtrace.rs:77
   3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
             at src/libstd/sys_common/backtrace.rs:61
   4: core::fmt::write
             at src/libcore/fmt/mod.rs:1028
   5: std::io::Write::write_fmt
             at src/libstd/io/mod.rs:1412
   6: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:65
   7: std::sys_common::backtrace::print
             at src/libstd/sys_common/backtrace.rs:50
   8: std::panicking::default_hook::{{closure}}
             at src/libstd/panicking.rs:188
   9: std::panicking::default_hook
             at src/libstd/panicking.rs:205
  10: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:464
  11: std::panicking::continue_panic_fmt
             at src/libstd/panicking.rs:373
  12: rust_begin_unwind
             at src/libstd/panicking.rs:302
  13: core::panicking::panic_fmt
             at src/libcore/panicking.rs:139
  14: core::panicking::panic
             at src/libcore/panicking.rs:70
  15: bytes::buf::buf_impl::Buf::copy_to_slice
             at ./<::core::macros::panic macros>:5
  16: bluez::client::settings::<impl bluez::client::BlueZClient>::set_local_name::{{closure}}
             at /home/timvisee/.cargo/registry/src/github.com-1ecc6299db9ec823/bluez-0.1.1/src/client/settings.rs:57
  17: <std::future::GenFuture<T> as core::future::future::Future>::poll::{{closure}}
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:43
  18: std::future::set_task_context
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:79
  19: <std::future::GenFuture<T> as core::future::future::Future>::poll
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:43
  20: std::future::poll_with_tls_context::{{closure}}
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:121
  21: std::future::get_task_context
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:111
  22: std::future::poll_with_tls_context
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:121
  23: async_std::task::block_on::block_on::{{closure}}
             at /home/timvisee/.cargo/registry/src/github.com-1ecc6299db9ec823/async-std-1.5.0/src/task/block_on.rs:68
  24: <std::future::GenFuture<T> as core::future::future::Future>::poll::{{closure}}
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:43
  25: std::future::set_task_context
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:79
  26: <std::future::GenFuture<T> as core::future::future::Future>::poll
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:43
  27: async_std::task::block_on::run::{{closure}}
             at /home/timvisee/.cargo/registry/src/github.com-1ecc6299db9ec823/async-std-1.5.0/src/task/block_on.rs:128
  28: std::thread::local::LocalKey<T>::try_with
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/thread/local.rs:262
  29: std::thread::local::LocalKey<T>::with
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/thread/local.rs:239
  30: async_std::task::block_on::run
             at /home/timvisee/.cargo/registry/src/github.com-1ecc6299db9ec823/async-std-1.5.0/src/task/block_on.rs:118
  31: async_std::task::block_on::block_on::{{closure}}
             at /home/timvisee/.cargo/registry/src/github.com-1ecc6299db9ec823/async-std-1.5.0/src/task/block_on.rs:72
  32: async_std::task::task::Task::set_current::{{closure}}
             at /home/timvisee/.cargo/registry/src/github.com-1ecc6299db9ec823/async-std-1.5.0/src/task/task.rs:129
  33: std::thread::local::LocalKey<T>::try_with
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/thread/local.rs:262
  34: std::thread::local::LocalKey<T>::with
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/thread/local.rs:239
  35: async_std::task::task::Task::set_current
             at /home/timvisee/.cargo/registry/src/github.com-1ecc6299db9ec823/async-std-1.5.0/src/task/task.rs:124
  36: async_std::task::block_on::block_on
             at /home/timvisee/.cargo/registry/src/github.com-1ecc6299db9ec823/async-std-1.5.0/src/task/block_on.rs:72
  37: pokoebox_bluetooth::main::main::{{closure}}
             at src/main.rs:38
  38: <std::future::GenFuture<T> as core::future::future::Future>::poll::{{closure}}
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:43
  39: std::future::set_task_context
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:79
  40: <std::future::GenFuture<T> as core::future::future::Future>::poll
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:43
  41: std::future::poll_with_tls_context::{{closure}}
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:121
  42: std::future::get_task_context
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:111
  43: std::future::poll_with_tls_context
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:121
  44: pokoebox_bluetooth::main::{{closure}}
             at src/main.rs:10
  45: <std::future::GenFuture<T> as core::future::future::Future>::poll::{{closure}}
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:43
  46: std::future::set_task_context
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:79
  47: <std::future::GenFuture<T> as core::future::future::Future>::poll
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:43
  48: std::future::poll_with_tls_context::{{closure}}
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:121
  49: std::future::get_task_context
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:111
  50: std::future::poll_with_tls_context
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:121
  51: async_std::task::block_on::block_on::{{closure}}
             at /home/timvisee/.cargo/registry/src/github.com-1ecc6299db9ec823/async-std-1.5.0/src/task/block_on.rs:68
  52: <std::future::GenFuture<T> as core::future::future::Future>::poll::{{closure}}
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:43
  53: std::future::set_task_context
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:79
  54: <std::future::GenFuture<T> as core::future::future::Future>::poll
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/future.rs:43
  55: async_std::task::block_on::run::{{closure}}
             at /home/timvisee/.cargo/registry/src/github.com-1ecc6299db9ec823/async-std-1.5.0/src/task/block_on.rs:128
  56: std::thread::local::LocalKey<T>::try_with
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/thread/local.rs:262
  57: std::thread::local::LocalKey<T>::with
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/thread/local.rs:239
  58: async_std::task::block_on::run
             at /home/timvisee/.cargo/registry/src/github.com-1ecc6299db9ec823/async-std-1.5.0/src/task/block_on.rs:118
  59: async_std::task::block_on::block_on::{{closure}}
             at /home/timvisee/.cargo/registry/src/github.com-1ecc6299db9ec823/async-std-1.5.0/src/task/block_on.rs:72
  60: async_std::task::task::Task::set_current::{{closure}}
             at /home/timvisee/.cargo/registry/src/github.com-1ecc6299db9ec823/async-std-1.5.0/src/task/task.rs:129
  61: std::thread::local::LocalKey<T>::try_with
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/thread/local.rs:262
  62: std::thread::local::LocalKey<T>::with
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/thread/local.rs:239
  63: async_std::task::task::Task::set_current
             at /home/timvisee/.cargo/registry/src/github.com-1ecc6299db9ec823/async-std-1.5.0/src/task/task.rs:124
  64: async_std::task::block_on::block_on
             at /home/timvisee/.cargo/registry/src/github.com-1ecc6299db9ec823/async-std-1.5.0/src/task/block_on.rs:72
  65: pokoebox_bluetooth::main
             at src/main.rs:10
  66: std::rt::lang_start::{{closure}}
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/rt.rs:61
  67: std::rt::lang_start_internal::{{closure}}
             at src/libstd/rt.rs:48
  68: std::panicking::try::do_call
             at src/libstd/panicking.rs:287
  69: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:78
  70: std::panicking::try
             at src/libstd/panicking.rs:265
  71: std::panic::catch_unwind
             at src/libstd/panic.rs:396
  72: std::rt::lang_start_internal
             at src/libstd/rt.rs:47
  73: std::rt::lang_start
             at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/rt.rs:61
  74: main
  75: __libc_start_main
  76: _start
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

Cannot set device class

Thank you for this nice crate. When trying to set up my rpi as a bluetooth keyboard I run into the following error, specifically while setting the device class:

Error: Xfer { source: Bluez { source: CommandError { opcode: SetDeviceClass, status: InvalidParams } } }

Where Xfer is my own Error enum.

This is roughly my program:

pub async fn run() -> Result<(), Error> {
    let mut client = BlueZClient::new().unwrap();

    let version = client.get_mgmt_version().await?;
    trace!(
        "management version: {}.{}",
        version.version,
        version.revision
    );

    let controllers = client.get_ext_controller_list().await?;
    let (controller, type_is, bus) = controllers.first().with_context(|| NoControllers)?;
    trace!(
        "got controller:\n{:?} ({:?}, {:?})",
        controller,
        type_is,
        bus
    );
    trace!(
        "info:\n{:#?}",
        client.get_controller_info(*controller).await?
    );

    let ctrl_settings = client
        .set_powered(
            *controller,
            true
        )
        .await?;
    trace!("controller settings after power on: {:?}", ctrl_settings);

    let ctrl_settings = client
        .set_connectable(
            *controller,
            true
        )
        .await?;
    trace!("controller settings after connectable: {:?}", ctrl_settings);

    let ctrl_settings = client
        .set_discoverable(
            *controller,
            DiscoverableMode::Limited,
            Some(60)
        )
        .await?;
    trace!("controller settings after discoverable: {:?}", ctrl_settings);

    let return_classes = client
        .set_device_class(
            *controller,
            DeviceClass::Peripheral {
                keyboard: true,
                pointer: false,
                class: PeripheralDeviceClass::Uncategorized,
            },
        )
        .await?;

    trace!("set device class, got: {:?}", return_classes);
    Ok(())
}

It's notable however, that using the command line to set the device class is working:

sudo hciconfig hci0 class 0x002540

After running the cli above, the settings have properly updated:

ControllerInfo {
    address: Address {
        bytes: [
            248,
            250,
            50,
            235,
            39,
            184,
        ],
    },
    bluetooth_version: 7,
    manufacturer: 15,
    supported_settings: BitFlags<ControllerSetting> {
        bits: 0b11011111111111111,
        flags: Powered | Connectable | FastConnectable | Discoverable | Pairable | LinkLevelSecurity | SecureSimplePairing | BREDR | HighSpeed | LE | Advertising | SecureConnection | DebugKeys | Privacy | StaticAddress | PhyConfiguration,
    },
    current_settings: BitFlags<ControllerSetting> {
        bits: 0b101011010011,
        flags: Powered | Connectable | Pairable | SecureSimplePairing | BREDR | LE | SecureConnection,
    },
    class_of_device: (
        Peripheral {
            keyboard: true,
            pointer: false,
            class: Uncategorized,
        },
        BitFlags<ServiceClass> {
            bits: 0b0,
        },
    ),
    name: "raspberrypi",
    short_name: "",
}

I'm new to working with bluetooth so I'm not sure what the problem is, but I thought it might be that the DeviceClass wasn't being converted into the correct u16 - indeed my device class seems to convert to 0x540, but making exec_command public and calling it with an explicit class of 0x2540 encounters the same error.

Allow duplicate entries to be discovered

I'm looking for a way to continually discover beacons that use simple advertising packets to emit telemetry data (among others). Is there a way to run discovery in a way that would allow me to capture and process all these packets, even if multiple packets are sent from the same device?

Why does discover need `sudo`?

I notice that blueman-manager can discover devices with bluez without being root. Why does bluez-rs need sudo permissions for discovering?

I cannot compile bluez

I'm new to rust, but want to try it with bluez. From
cargo new test-bluez
I added:
bluez = "0.3.0"
to Cargo.toml, but when I try to compile, it fails with:

...
error: aborting due to 43 previous errors

Some errors have detailed explanations: E0034, E0308.
For more information about an error, try `rustc --explain E0034`.
error: could not compile `bitvec`

To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: build failed

I know that this is not a bluez problem, but I am hoping that there is something I can change with the way I import bluez into my project in order to make this compile.

Panic after device connect

After confirming a connection request, I'm getting a panic happening at the following line:

key_type: FromPrimitive::from_u8(buf.get_u8()).unwrap(),

This apparently comes up when processing the NewLongTermKey event.

buf.get_u8() gives a 3. The FromPrimitive helper can't parse this into a LongTermKeyType which is why it panics.

Any idea what is going on?

New release?

I see that RFCOMM support was added back in August, but no version with it in has been released yet.

Need examples of peripheral mode

Is there an example of peripheral mode, I am looking for a way to start a BLE server that offers data of CPU/memory usage, runs small shell scripts, etc.

Thanks!

How to get simple name from device advertisment

I'm really interested in the repository for a project I'm working on. Is it possible to filter a device "simple name" in the discovery process? I know that's available in the advertisement data. Does anyone have an example how to to pair a device?

Why sleep 50ms in the main loop?

sleep(Duration::from_millis(50)).await;

As far as I can tell, this library is async... meaning that execution will pause at the right time when needing to wait for data from file descriptors or socket, but returning right away if there is enough.

If you were polling the bluez API for changes, it would make sense to sleep to avoid polling too hard. But when doing async, the process pauses when it needs more data from an input...

I think it should be safe to drop the sleeping here. I can try to measure timings to confirm the above.

Question about sending commands

Sorry for bothering again, but I'm a bit confused on how this crate sends HCI commands. The bytes generated here:

impl Into<Bytes> for Request {
fn into(self) -> Bytes {
let mut buf = BytesMut::with_capacity(6 + self.param.len());
buf.put_u16_le(self.opcode as u16);
buf.put_u16_le(self.controller.into());
buf.put_u16_le(self.param.len() as u16);
buf.put(self.param);
buf.freeze()
}
}

don't seem to line up with the C library here. Would you mind explaining where I can find documentation about the type of data that can be sent to the HCI socket/stream?

How to connect to bluetooth devices without pairing

I know, I know, I'm an idiot, but for the life of me, I cannot figure out how to connect to bluetooth devices using this library. I'm not looking for pairing, and I'm not using BLE devices, I just need the equivalent of bluetoothctl connect <dev>.

IoCapability values are incorrect

The IoCapability values seem to be incorrect. I believe their values should start from 0, not 1.

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[repr(u8)]
pub enum IoCapability {
DisplayOnly = 1,
DisplayYesNo,
KeyboardOnly,
NoInputNoOutput,
KeyboardDisplay,
}

I couldn't really find proper documentation on this. But here's some source that specifies these:

https://github.com/redboltz/bluez/blob/bca184dd8fc86718984b204f121dc35196ecece2/tools/parser/smp.c#L49-L54

Could not find matching version of bitvec

I have created a new rust project (cargo init with cargo version 1.42.0) and added bluez = "0.1.2" as a dependency as written on the crates.io page. With no other changes to the helloWorld example, I get a build error saying

    Updating crates.io index
error: failed to select a version for the requirement `bitvec = "^0.16"`
  candidate versions found which didn't match: 0.17.4
  location searched: crates.io index
required by package `bluez v0.1.2`
    ... which is depended on by `tests v0.1.0 (/tmp/tests)`

Cloning this repo and running the examples worked fine.

It looks like all bitvec v0.16 crates have been yanked.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.