use crate::{HciChannel, HciDevice};
/// A trait for objects that can be converted to HciSocketAddr.
///
/// This trait is used when constructing HCI raw sockets. By default it is
/// implemented for the following types:
///
/// * [`SockeAddr`]: [`to_socket_addr`] is the identity function.
pub trait ToHciSocketAddr {
/// Converts this object to a resolved HciSocketAddr.
fn to_socket_addr(&self) -> HciSocketAddr;
}
#[allow(missing_docs)]
#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
pub struct sockaddr_hci {
hci_family: libc::sa_family_t,
hci_dev: u16,
hci_channel: u16,
}
/// A HCI socket address.
#[derive(Copy, Clone)]
pub struct HciSocketAddr {
inner: sockaddr_hci,
}
#[allow(clippy::len_without_is_empty)]
impl HciSocketAddr {
/// Create HCI socket address.
///
/// The HCI socket address is characterized by a device and a channel. The
/// following rules apply:
/// * Device must be set to None for channels: Monitor, Control, Logging
/// * Device must be set to a valid Bluetooth controller ID for channels:
/// Raw, User
///
/// # Example
///
/// Create HCI socket address associated with no device and control channel
///
/// ```
/// use hciraw::{HciSocketAddr, HciChannel};
///
/// let addr = HciSocketAddr::new(None, HciChannel::Control);
/// ```
///
/// Create HCI socket address associated with Bluetooth controller 0 and the
/// raw channel
///
/// ```
/// use hciraw::{HciSocketAddr, HciChannel};
///
/// let addr = HciSocketAddr::new(Some(0), HciChannel::Raw);
/// ```
pub fn new(dev: HciDevice, chan: HciChannel) -> HciSocketAddr {
HciSocketAddr {
inner: sockaddr_hci {
hci_family: libc::AF_BLUETOOTH as libc::sa_family_t,
hci_dev: match dev {
None => 0xffff,
Some(d) => d,
},
hci_channel: chan as u16,
},
}
}
/// Get the length of the data in bytes. It is always 0x5 for HciSocketAddr.
pub fn len(self) -> libc::socklen_t {
0x5 as libc::socklen_t
}
}
impl ToHciSocketAddr for HciSocketAddr {
fn to_socket_addr(&self) -> HciSocketAddr {
*self
}
}
impl From<HciSocketAddr> for libc::sockaddr {
fn from(hsa: HciSocketAddr) -> libc::sockaddr {
let b1 = ((hsa.inner.hci_dev) & 0x00ff) as libc::c_char;
let b2 = ((hsa.inner.hci_dev >> 8) & 0x00ff) as libc::c_char;
let c1 = ((hsa.inner.hci_channel) & 0x00ff) as libc::c_char;
let c2 = ((hsa.inner.hci_channel >> 8) & 0x00ff) as libc::c_char;
libc::sockaddr {
sa_family: hsa.inner.hci_family,
sa_data: [b1, b2, c1, c2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
}
}
}