hciraw 1.0.1

The interface to HCI Raw Sockets
Documentation
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],
        }
    }
}