1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! # Getting Started
//! The most important type in this crate is the [`BlueZClient`](crate::client::BlueZClient), which
//! is used to issue commands to and listen for events from the Bluetooth controller(s). It's
//! fully decked out in `async`/`.await` bling, too.
//!
//! ```no_run
//! # use std::error::Error;
//! # use bluez::client::BlueZClient;
//! # #[async_std::main]
//! # pub async fn main() -> Result<(), Box<dyn Error>> {
//! let mut client = BlueZClient::new().unwrap();
//!
//! let version = client.get_mgmt_version().await?;
//! println!(
//!     "management version: {}.{}",
//!     version.version, version.revision
//! );
//!
//! let controllers = client.get_controller_list().await?;
//!
//! for controller in controllers {
//!     let info = client.get_controller_info(controller).await?;
//!     println!("{:?}", info)
//! }
//!
//! #   Ok(())
//! # }
//! ```
//!
//!
//! Aside from directly issuing commands to the Bluetooth controller and recieving a response,
//! you may want to listen for events or perform processes that span multiple commands. For
//! this to work, you need to supply a callback to your client and call [`process()`][process]. The callback
//! will be called any time that the client processes an event (excluding events that indicate that
//! a command has completed), while [`process()`][process] will cause the client to check the underlying
//! socket for new input.
//!
//! ```no_run
//! # use std::error::Error;
//! # use std::time::Duration;
//! # use bluez::client::*;
//! # use bluez::interface::event::Event;
//! # #[async_std::main]
//! # pub async fn main() -> Result<(), Box<dyn Error>> {
//! #    let mut client = BlueZClient::new().unwrap();
//!
//! let controllers = client.get_controller_list().await?;
//! let controller = controllers.first().expect("no bluetooth controllers available");
//!
//! client.set_handler(|controller, event| match event {
//!     Event::DeviceFound {
//!         address,
//!         address_type,
//!         flags,
//!         rssi,
//!         ..
//!     } => {
//!         println!(
//!             "[{:?}] found device {} ({:?})",
//!             controller, address, address_type
//!         );
//!         println!("\tflags: {:?}", flags);
//!         println!("\trssi: {:?}", rssi);
//!     }
//!     _ => (),
//! });
//!
//! client
//!     .start_discovery(
//!         *controller,
//!         AddressTypeFlag::BREDR | AddressTypeFlag::LEPublic | AddressTypeFlag::LERandom,
//!     )
//!     .await?;
//!
//! for _ in 0usize..5000usize {
//!     client.process().await?;
//!     std::thread::sleep(Duration::from_millis(50));
//! }
//! #  Ok(())
//! # }
//! ```
//!
//! # The `process()` loop
//! Since [`process()`][process] returns the latest response to be processed, you may be wondering
//! why you would use a callback at all; isn't it easier to just take the return values inside
//! the loop?
//!
//! In the case demonstrated here, it would be. In fact, this is how it is implemented
//! in the [version of the sample on GitHub][sample], but the reason for the callback is that events
//! can arrive while a command is being executed. Since the client is mutably borrowed
//! for the span of each command (i.e., between the instruction being sent to the kernel
//! and the kernel sending a Command Status event), but another event may arrive before
//! the Command Status event, a way is needed to capture such an event. Internally, each command
//! just calls [`process()`][process] repeatedly until a relevant Command Status event appears, and
//! [`process()`][process] will call your handler.
//!
//! # Permissions
//! Commands that just query information, such as
//! [`BlueZClient::get_controller_info`](crate::client::BlueZClient::get_controller_info),
//! will usually work. However, commands that try to change any settings, such as
//! [`BlueZClient::set_powered`](crate::client::BlueZClient::set_powered) will fail with
//! 'permission denied' errors if your process does not have the `CAP_NET_RAW` capability.
//!
//! [process]: crate::client::BlueZClient::process
//! [sample]: https://github.com/laptou/bluez-rs/tree/master/src/example/discover.rs

#[macro_use]
extern crate num_derive;
#[macro_use]
extern crate thiserror;

pub use address::Address;
pub use result::{Error, Result};

pub mod client;
pub mod interface;
pub mod result;

mod address;
mod socket;
mod util;