Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c0e43e44 authored by Yun-hao Chung's avatar Yun-hao Chung Committed by Gerrit Code Review
Browse files

Merge "Floss: Auto generate pin code for keyboard-like devices"

parents c07ac1c5 f2e8bfde
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -212,6 +212,15 @@ impl IBluetoothCallback for BtCallback {
        );
    }

    fn on_pin_display(&mut self, remote_device: BluetoothDevice, pincode: String) {
        print_info!(
            "Device [{}: {}] would like to pair, enter pin code {} on the remote",
            &remote_device.address,
            &remote_device.name,
            pincode
        );
    }

    fn on_bond_state_changed(&mut self, status: u32, address: String, state: u32) {
        print_info!("Bonding state changed: [{}] state: {}, Status = {}", address, state, status);

+3 −0
Original line number Diff line number Diff line
@@ -535,6 +535,9 @@ impl IBluetoothCallback for IBluetoothCallbackDBus {
    #[dbus_method("OnPinRequest")]
    fn on_pin_request(&mut self, remote_device: BluetoothDevice, cod: u32, min_16_digit: bool) {}

    #[dbus_method("OnPinDisplay")]
    fn on_pin_display(&mut self, remote_device: BluetoothDevice, pincode: String) {}

    #[dbus_method("OnBondStateChanged")]
    fn on_bond_state_changed(&mut self, status: u32, address: String, state: u32) {}

+4 −0
Original line number Diff line number Diff line
@@ -117,6 +117,10 @@ impl IBluetoothCallback for BluetoothCallbackDBus {
    fn on_pin_request(&mut self, remote_device: BluetoothDevice, cod: u32, min_16_digit: bool) {
        dbus_generated!()
    }
    #[dbus_method("OnPinDisplay")]
    fn on_pin_display(&mut self, remote_device: BluetoothDevice, pincode: String) {
        dbus_generated!()
    }
    #[dbus_method("OnBondStateChanged")]
    fn on_bond_state_changed(&mut self, status: u32, address: String, state: u32) {
        dbus_generated!()
+36 −9
Original line number Diff line number Diff line
@@ -20,11 +20,14 @@ use bt_topshim::{
};

use bt_utils::array_utils;
use bt_utils::cod::{is_cod_hid_combo, is_cod_hid_keyboard};
use btif_macros::{btif_callback, btif_callbacks_dispatcher};

use log::{debug, warn};
use num_traits::cast::ToPrimitive;
use num_traits::pow;
use std::collections::HashMap;
use std::convert::TryInto;
use std::fs::File;
use std::hash::Hash;
use std::io::Write;
@@ -402,6 +405,9 @@ pub trait IBluetoothCallback: RPCProxy {
    /// When there is a pin request to display the event to client.
    fn on_pin_request(&mut self, remote_device: BluetoothDevice, cod: u32, min_16_digit: bool);

    /// When there is a auto-gen pin to display the event to client.
    fn on_pin_display(&mut self, remote_device: BluetoothDevice, pincode: String);

    /// When a bonding attempt has completed.
    fn on_bond_state_changed(&mut self, status: u32, device_address: String, state: u32);

@@ -1368,15 +1374,36 @@ impl BtifBluetoothCallbacks for Bluetooth {
        cod: u32,
        min_16_digit: bool,
    ) {
        let device = BluetoothDevice::new(remote_addr.to_string(), remote_name.clone());

        let digits = match min_16_digit {
            true => 16,
            false => 6,
        };

        if is_cod_hid_keyboard(cod) || is_cod_hid_combo(cod) {
            debug!("auto gen pin for device {} (cod={:#x})", device.address, cod);
            // generate a random pin code to display.
            let pin = rand::random::<u64>() % pow(10, digits);
            let display_pin = format!("{:06}", pin);

            // Currently this supports many agent because we accept many callbacks.
            // TODO(b/274706838): We need a way to select the default agent.
            self.callbacks.for_all_callbacks(|callback| {
            callback.on_pin_request(
                BluetoothDevice::new(remote_addr.to_string(), remote_name.clone()),
                cod,
                min_16_digit,
            );
                callback.on_pin_display(device.clone(), display_pin.clone());
            });

            let pin_vec = display_pin.chars().map(|d| d.try_into().unwrap()).collect::<Vec<u8>>();

            self.set_pin(device, true, pin_vec);
        } else {
            debug!("sending pin request for device {} (cod={:#x}) to clients", device.address, cod);
            // Currently this supports many agent because we accept many callbacks.
            // TODO(b/274706838): We need a way to select the default agent.
            self.callbacks.for_all_callbacks(|callback| {
                callback.on_pin_request(device.clone(), cod, min_16_digit);
            });
        }
    }

    fn bond_state(
+41 −0
Original line number Diff line number Diff line
//! This library provides helper functions to parse cod.

struct Class {
    major: u32,
    minor: u32,
}

impl Class {
    fn new(cod: u32) -> Class {
        Class { major: (cod & 0x1f00) >> 8, minor: (cod & 0xff) }
    }
}

pub fn is_cod_hid_keyboard(cod: u32) -> bool {
    let c = Class::new(cod);
    c.major == 0x05 && ((c.minor >> 6) & 0x03) == 0x01
}

pub fn is_cod_hid_combo(cod: u32) -> bool {
    let c = Class::new(cod);
    c.major == 0x05 && ((c.minor >> 6) & 0x03) == 0x03
}

#[cfg(test)]
mod tests {
    use crate::cod::{is_cod_hid_combo, is_cod_hid_keyboard};

    #[test]
    fn test_cod() {
        let keyboard_gamepad_cod = 0x0548;
        let combo_joystick_cod = 0x05c4;
        let mouse_cod = 0x0580;

        assert_eq!(is_cod_hid_keyboard(keyboard_gamepad_cod), true);
        assert_eq!(is_cod_hid_combo(keyboard_gamepad_cod), false);
        assert_eq!(is_cod_hid_keyboard(combo_joystick_cod), false);
        assert_eq!(is_cod_hid_combo(combo_joystick_cod), true);
        assert_eq!(is_cod_hid_keyboard(mouse_cod), false);
        assert_eq!(is_cod_hid_combo(mouse_cod), false);
    }
}
Loading