mod acl_stream;
mod peripheral;
use libc;
use nom;
use bytes::{BytesMut, BufMut};
use std::{
self,
ffi::CStr,
collections::{HashSet, HashMap},
sync::{Arc, Mutex},
sync::atomic::{AtomicBool, Ordering},
thread,
};
use crate::Result;
use crate::api::{CentralEvent, BDAddr, Central, EventHandler};
use crate::bluez::{
util::handle_error,
protocol::hci,
adapter::peripheral::Peripheral,
constants::*,
ioctl,
};
#[derive(Copy, Debug)]
#[repr(C)]
pub struct HCIDevStats {
pub err_rx : u32,
pub err_tx : u32,
pub cmd_tx : u32,
pub evt_rx : u32,
pub acl_tx : u32,
pub acl_rx : u32,
pub sco_tx : u32,
pub sco_rx : u32,
pub byte_rx : u32,
pub byte_tx : u32,
}
impl Clone for HCIDevStats{
fn clone(&self) -> Self { *self }
}
impl HCIDevStats {
fn default() -> HCIDevStats {
HCIDevStats {
err_rx: 0u32,
err_tx: 0u32,
cmd_tx: 0u32,
evt_rx: 0u32,
acl_tx: 0u32,
acl_rx: 0u32,
sco_tx: 0u32,
sco_rx: 0u32,
byte_rx: 0u32,
byte_tx: 0u32
}
}
}
#[derive(Copy, Debug)]
#[repr(C)]
pub struct HCIDevInfo {
pub dev_id : u16,
pub name : [libc::c_char; 8],
pub bdaddr : BDAddr,
pub flags : u32,
pub type_ : u8,
pub features : [u8; 8],
pub pkt_type : u32,
pub link_policy : u32,
pub link_mode : u32,
pub acl_mtu : u16,
pub acl_pkts : u16,
pub sco_mtu : u16,
pub sco_pkts : u16,
pub stat : HCIDevStats,
}
impl Clone for HCIDevInfo {
fn clone(&self) -> Self { *self }
}
impl HCIDevInfo {
pub fn default() -> HCIDevInfo {
HCIDevInfo {
dev_id: 0,
name: [0 as libc::c_char; 8],
bdaddr: BDAddr { address: [0u8; 6] },
flags: 0u32,
type_: 0u8,
features: [0u8; 8],
pkt_type: 0u32,
link_policy: 0u32,
link_mode: 0u32,
acl_mtu: 0u16,
acl_pkts: 0u16,
sco_mtu: 0u16,
sco_pkts: 0u16,
stat: HCIDevStats::default()
}
}
}
#[derive(Copy, Debug)]
#[repr(C)]
struct SockaddrHCI {
hci_family: libc::sa_family_t,
hci_dev: u16,
hci_channel: u16,
}
impl Clone for SockaddrHCI {
fn clone(&self) -> Self { *self }
}
#[derive(Debug, Copy, Clone)]
pub enum AdapterType {
BrEdr,
Amp,
Unknown(u8)
}
impl AdapterType {
fn parse(typ: u8) -> AdapterType {
match typ {
0 => AdapterType::BrEdr,
1 => AdapterType::Amp,
x => AdapterType::Unknown(x),
}
}
fn num(&self) -> u8 {
match *self {
AdapterType::BrEdr => 0,
AdapterType::Amp => 1,
AdapterType::Unknown(x) => x,
}
}
}
#[derive(Hash, Eq, PartialEq, Debug, Copy, Clone)]
pub enum AdapterState {
Up, Init, Running, Raw, PScan, IScan, Inquiry, Auth, Encrypt
}
impl AdapterState {
fn parse(flags: u32) -> HashSet<AdapterState> {
use self::AdapterState::*;
let states = [Up, Init, Running, Raw, PScan, IScan, Inquiry, Auth, Encrypt];
let mut set = HashSet::new();
for (i, f) in states.iter().enumerate() {
if flags & (1 << (i & 31)) != 0 {
set.insert(f.clone());
}
}
set
}
}
#[derive(Clone)]
pub struct ConnectedAdapter {
pub adapter: Adapter,
adapter_fd: i32,
should_stop: Arc<AtomicBool>,
pub scan_enabled: Arc<AtomicBool>,
pub active: Arc<AtomicBool>,
pub filter_duplicates: Arc<AtomicBool>,
peripherals: Arc<Mutex<HashMap<BDAddr, Peripheral>>>,
handle_map: Arc<Mutex<HashMap<u16, BDAddr>>>,
event_handlers: Arc<Mutex<Vec<EventHandler>>>,
}
impl ConnectedAdapter {
pub fn new(adapter: &Adapter) -> Result<ConnectedAdapter> {
let adapter_fd = handle_error(unsafe {
libc::socket(libc::AF_BLUETOOTH, libc::SOCK_RAW | libc::SOCK_CLOEXEC, 1)
})?;
let addr = SockaddrHCI {
hci_family: libc::AF_BLUETOOTH as u16,
hci_dev: adapter.dev_id,
hci_channel: 0,
};
handle_error(unsafe {
libc::bind(adapter_fd, &addr as *const SockaddrHCI as *const libc::sockaddr,
std::mem::size_of::<SockaddrHCI>() as u32)
})?;
let should_stop = Arc::new(AtomicBool::new(false));
let connected = ConnectedAdapter {
adapter: adapter.clone(),
adapter_fd,
active: Arc::new(AtomicBool::new(false)),
filter_duplicates: Arc::new(AtomicBool::new(false)),
should_stop,
scan_enabled: Arc::new(AtomicBool::new(false)),
event_handlers: Arc::new(Mutex::new(vec![])),
peripherals: Arc::new(Mutex::new(HashMap::new())),
handle_map: Arc::new(Mutex::new(HashMap::new())),
};
connected.add_raw_socket_reader(adapter_fd);
connected.set_socket_filter()?;
Ok(connected)
}
fn set_socket_filter(&self) -> Result<()> {
let mut filter = BytesMut::with_capacity(14);
let type_mask = (1 << HCI_COMMAND_PKT) | (1 << HCI_EVENT_PKT) | (1 << HCI_ACLDATA_PKT);
let event_mask1 = (1 << EVT_DISCONN_COMPLETE) | (1 << EVT_ENCRYPT_CHANGE) |
(1 << EVT_CMD_COMPLETE) | (1 << EVT_CMD_STATUS);
let event_mask2 = 1 << (EVT_LE_META_EVENT - 32);
let opcode = 0;
filter.put_u32_le(type_mask);
filter.put_u32_le(event_mask1);
filter.put_u32_le(event_mask2);
filter.put_u16_le(opcode);
handle_error(unsafe {
libc::setsockopt(self.adapter_fd, SOL_HCI, HCI_FILTER,
filter.as_mut_ptr() as *mut _ as *mut libc::c_void,
filter.len() as u32)
})?;
Ok(())
}
fn add_raw_socket_reader(&self, fd: i32) {
let should_stop = self.should_stop.clone();
let connected = self.clone();
thread::spawn(move || {
let mut buf = [0u8; 2048];
let mut cur: Vec<u8> = vec![];
while !should_stop.load(Ordering::Relaxed) {
let len = handle_error(unsafe {
libc::read(fd, buf.as_mut_ptr() as *mut _ as *mut libc::c_void, buf.len()) as i32
}).unwrap_or(0) as usize;
if len == 0 {
continue;
}
cur.put_slice(&buf[0..len]);
let mut new_cur: Option<Vec<u8>> = Some(vec![]);
{
let result = {
hci::message(&cur)
};
match result {
Ok((left, result)) => {
ConnectedAdapter::handle(&connected, result);
if !left.is_empty() {
new_cur = Some(left.to_owned());
};
}
Err(nom::Err::Incomplete(_)) => {
new_cur = None;
},
Err(nom::Err::Error(err)) | Err(nom::Err::Failure(err)) => {
error!("parse error {:?}\nfrom: {:?}", err, cur);
}
}
};
cur = new_cur.unwrap_or(cur);
}
});
}
fn emit(&self, event: CentralEvent) {
debug!("emitted {:?}", event);
let handlers = self.event_handlers.clone();
let vec = handlers.lock().unwrap();
for handler in (*vec).iter() {
handler(event.clone());
}
}
fn handle(&self, message: hci::Message) {
debug!("got message {:?}", message);
match message {
hci::Message::LEAdvertisingReport(info) => {
let mut new = false;
let address = info.bdaddr.clone();
{
let mut peripherals = self.peripherals.lock().unwrap();
let peripheral = peripherals.entry(info.bdaddr)
.or_insert_with(|| {
new = true;
Peripheral::new(self.clone(), info.bdaddr)
});
peripheral.handle_device_message(&hci::Message::LEAdvertisingReport(info));
}
if new {
self.emit(CentralEvent::DeviceDiscovered(address.clone()))
} else {
self.emit(CentralEvent::DeviceUpdated(address.clone()))
}
}
hci::Message::LEConnComplete(info) => {
info!("connected to {:?}", info);
let address = info.bdaddr.clone();
let handle = info.handle.clone();
match self.peripheral(address) {
Some(peripheral) => {
peripheral.handle_device_message(&hci::Message::LEConnComplete(info))
}
None => warn!("Got connection for unknown device {}", info.bdaddr)
}
let mut handles = self.handle_map.lock().unwrap();
handles.insert(handle, address);
self.emit(CentralEvent::DeviceConnected(address));
}
hci::Message::ACLDataPacket(data) => {
let message = hci::Message::ACLDataPacket(data);
let peripherals = self.peripherals.lock().unwrap();
for peripheral in peripherals.values() {
peripheral.handle_device_message(&message);
}
},
hci::Message::DisconnectComplete { handle, .. } => {
let mut handles = self.handle_map.lock().unwrap();
match handles.remove(&handle) {
Some(addr) => {
match self.peripheral(addr) {
Some(peripheral) => peripheral.handle_device_message(&message),
None => warn!("got disconnect for unknown device {}", addr),
};
self.emit(CentralEvent::DeviceDisconnected(addr));
}
None => {
warn!("got disconnect for unknown handle {}", handle);
}
}
}
_ => {
}
}
}
fn write(&self, message: &mut [u8]) -> Result<()> {
debug!("writing({}) {:?}", self.adapter_fd, message);
let ptr = message.as_mut_ptr();
handle_error(unsafe {
libc::write(self.adapter_fd, ptr as *mut _ as *mut libc::c_void, message.len()) as i32
})?;
Ok(())
}
fn set_scan_params(&self) -> Result<()> {
let mut data = BytesMut::with_capacity(7);
data.put_u8(if self.active.load(Ordering::Relaxed) { 1 } else { 0 });
data.put_u16_le(0x0010);
data.put_u16_le(0x0010);
data.put_u8(0);
data.put_u8(0);
let mut buf = hci::hci_command(LE_SET_SCAN_PARAMETERS_CMD, &*data);
self.write(&mut *buf)
}
fn set_scan_enabled(&self, enabled: bool) -> Result<()> {
let mut data = BytesMut::with_capacity(2);
data.put_u8(if enabled { 1 } else { 0 });
data.put_u8(if self.filter_duplicates.load(Ordering::Relaxed) { 1 } else { 0 });
self.scan_enabled.clone().store(enabled, Ordering::Relaxed);
let mut buf = hci::hci_command(LE_SET_SCAN_ENABLE_CMD, &*data);
self.write(&mut *buf)
}
}
impl Central<Peripheral> for ConnectedAdapter {
fn on_event(&self, handler: EventHandler) {
let list = self.event_handlers.clone();
list.lock().unwrap().push(handler);
}
fn active(&self, enabled: bool) {
self.active.clone().store(enabled, Ordering::Relaxed);
}
fn filter_duplicates(&self, enabled: bool) {
self.filter_duplicates.clone().store(enabled, Ordering::Relaxed);
}
fn start_scan(&self) -> Result<()> {
self.set_scan_params()?;
self.set_scan_enabled(true)
}
fn stop_scan(&self) -> Result<()> {
self.set_scan_enabled(false)
}
fn peripherals(&self) -> Vec<Peripheral> {
let l = self.peripherals.lock().unwrap();
l.values().map(|p| p.clone()).collect()
}
fn peripheral(&self, address: BDAddr) -> Option<Peripheral> {
let l = self.peripherals.lock().unwrap();
l.get(&address).map(|p| p.clone())
}
}
#[derive(Debug, Clone)]
pub struct Adapter {
pub name: String,
pub dev_id: u16,
pub addr: BDAddr,
pub typ: AdapterType,
pub states: HashSet<AdapterState>,
pub info: HCIDevInfo,
}
impl Adapter {
pub fn from_device_info(di: &HCIDevInfo) -> Adapter {
info!("DevInfo: {:?}", di);
Adapter {
name: String::from(unsafe { CStr::from_ptr(di.name.as_ptr()).to_str().unwrap() }),
dev_id: 0,
addr: di.bdaddr,
typ: AdapterType::parse((di.type_ & 0x30) >> 4),
states: AdapterState::parse(di.flags),
info: di.clone(),
}
}
pub fn from_dev_id(ctl: i32, dev_id: u16) -> Result<Adapter> {
let mut di = HCIDevInfo::default();
di.dev_id = dev_id;
unsafe {
ioctl::hci_get_dev_info(ctl, &mut di)?;
}
Ok(Adapter::from_device_info(&di))
}
pub fn is_up(&self) -> bool {
self.states.contains(&AdapterState::Up)
}
pub fn connect(&self) -> Result<ConnectedAdapter> {
ConnectedAdapter::new(self)
}
}