hciraw 1.0.1

The interface to HCI Raw Sockets
Documentation
use crate::BTPROTO_HCI;
use crate::{HciSocketAddr, ToHciSocketAddr};

use fd::FileDesc;
use libc::{c_int, AF_BLUETOOTH, SOCK_CLOEXEC, SOCK_NONBLOCK, SOCK_RAW};
use std::io;
use std::os::unix::io::{AsRawFd, RawFd};

pub struct HciSocket(FileDesc);

impl HciSocket {
    pub fn bind(addr: HciSocketAddr) -> io::Result<HciSocket> {
        unsafe {
            let fd: c_int = libc::socket(
                AF_BLUETOOTH,
                SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
                BTPROTO_HCI,
            );

            if fd == -1 {
                return Err(io::Error::last_os_error());
            }

            let a = addr.to_socket_addr();

            match libc::bind(fd, &libc::sockaddr::from(a), 0x5) {
                -1 => Err(io::Error::last_os_error()),
                _ => Ok(HciSocket(FileDesc::new(fd, true))),
            }
        }
    }

    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
        match unsafe {
            libc::write(
                self.as_raw_fd(),
                buf.as_ptr() as *const libc::c_void,
                buf.len(),
            )
        } {
            -1 => Err(io::Error::last_os_error()),
            r => Ok(r as usize),
        }
    }

    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
        match unsafe {
            libc::read(
                self.as_raw_fd(),
                buf.as_mut_ptr() as *mut libc::c_void,
                buf.len(),
            )
        } {
            -1 => Err(io::Error::last_os_error()),
            r => Ok(r as usize),
        }
    }
}

impl AsRawFd for HciSocket {
    fn as_raw_fd(&self) -> RawFd {
        self.0.as_raw_fd()
    }
}