OSDN Git Service

rusty-gd: implement custom types & read address in controller
authorZach Johnson <zachoverflow@google.com>
Mon, 21 Dec 2020 22:34:40 +0000 (14:34 -0800)
committerZach Johnson <zachoverflow@google.com>
Wed, 13 Jan 2021 00:29:52 +0000 (16:29 -0800)
Bug: 171749953
Tag: #gd-refactor
Test: gd/cert/run --rhost SimpleHalTest
Change-Id: Ic8ddcac8fa2738e1282ca853a27450a56f1b54c7

gd/Android.bp
gd/packet/parser/fields/custom_field_fixed_size.cc
gd/packet/parser/fields/custom_field_fixed_size.h
gd/packet/parser/gen_rust.cc
gd/rust/hci/Android.bp
gd/rust/hci/custom_types/lib.rs [new file with mode: 0644]
gd/rust/hci/src/controller.rs
gd/rust/hci/src/lib.rs
gd/rust/packets/lib.rs

index 9f5fa86..c073497 100644 (file)
@@ -507,6 +507,7 @@ rust_library {
         "libbytes",
         "libnum_traits",
         "libthiserror",
+        "libbt_hci_custom_types",
     ],
 }
 
index c296438..8dc27fa 100644 (file)
@@ -31,6 +31,10 @@ std::string CustomFieldFixedSize::GetDataType() const {
   return type_name_;
 }
 
+std::string CustomFieldFixedSize::GetRustDataType() const {
+  return type_name_;
+}
+
 int CustomFieldFixedSize::GenBounds(std::ostream& s, Size start_offset, Size end_offset, Size size) const {
   if (!start_offset.empty()) {
     // Default to start if available.
@@ -68,3 +72,36 @@ void CustomFieldFixedSize::GenStringRepresentation(std::ostream& s, std::string
   // We assume that custom fields will have a ToString() method
   s << accessor << ".ToString()";
 }
+
+std::string CustomFieldFixedSize::GetRustParseDataType() const {
+  return "[u8; " + std::to_string(GetSize().bytes()) + "]";
+}
+
+void CustomFieldFixedSize::GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const {
+  Size size = GetSize();
+  int num_leading_bits = GetRustBitOffset(s, start_offset, end_offset, GetSize());
+  if (num_leading_bits != 0) {
+    ERROR(this) << "must be byte aligned";
+  }
+  if (size.bits() % 8 != 0) {
+    ERROR(this) << "size must be in full bytes";
+  }
+
+  s << "let " << GetName() << " = bytes[" << start_offset.bytes() << "..";
+  s << start_offset.bytes() + size.bytes() << "].try_into().unwrap();";
+}
+
+void CustomFieldFixedSize::GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const {
+  Size size = GetSize();
+  int num_leading_bits = GetRustBitOffset(s, start_offset, end_offset, GetSize());
+  if (num_leading_bits != 0) {
+    ERROR(this) << "must be byte aligned";
+  }
+  if (size.bits() % 8 != 0) {
+    ERROR(this) << "size must be in full bytes";
+  }
+
+  s << "let " << GetName() << ": " << GetRustParseDataType() << " = self." << GetName() << ".into();";
+  s << "buffer[" << start_offset.bytes() << ".." << start_offset.bytes() + GetSize().bytes() << "].copy_from_slice(&"
+    << GetName() << ");";
+}
index c53f0b0..8423f80 100644 (file)
@@ -43,5 +43,13 @@ class CustomFieldFixedSize : public ScalarField {
 
   virtual void GenStringRepresentation(std::ostream& s, std::string accessor) const override;
 
+  void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+
+  void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
+
+  virtual std::string GetRustDataType() const override;
+
+  virtual std::string GetRustParseDataType() const override;
+
   std::string type_name_;
 };
index 8e7ce02..3780d14 100644 (file)
@@ -37,13 +37,6 @@ pub enum Error {
   InvalidPacketError
 }
 
-pub struct Address {
-  pub addr: [u8; 6],
-}
-
-pub struct ClassOfDevice {
-  pub cod: [u8; 3],
-}
 )";
 }
 
index f0865b1..2b6e4c9 100644 (file)
@@ -18,8 +18,17 @@ rust_library {
         "libgddi",
         "liblog_rust",
         "libbt_common",
+        "libbt_hci_custom_types",
     ],
     proc_macros: [
         "libnum_derive",
     ],
 }
+
+rust_library {
+    name: "libbt_hci_custom_types",
+    defaults: ["gd_rust_defaults"],
+    crate_name: "bt_hci_custom_types",
+    srcs: ["custom_types/lib.rs"],
+    edition: "2018",
+}
diff --git a/gd/rust/hci/custom_types/lib.rs b/gd/rust/hci/custom_types/lib.rs
new file mode 100644 (file)
index 0000000..749afdc
--- /dev/null
@@ -0,0 +1,108 @@
+//! custom types to be imported by hci packet pdl
+//! (since hci depends on the packet library, we need to split these out)
+
+use std::convert::TryFrom;
+use std::fmt;
+
+/// Signal for "empty" address
+pub const EMPTY_ADDRESS: Address = Address { bytes: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00] };
+/// Signal for "any" address
+pub const ANY_ADDRESS: Address = Address { bytes: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] };
+
+/// A Bluetooth address
+#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
+pub struct Address {
+    /// the actual bytes representing this address
+    pub bytes: [u8; 6],
+}
+
+impl Address {
+    /// whether this address is empty
+    pub fn is_empty(&self) -> bool {
+        *self == EMPTY_ADDRESS
+    }
+}
+
+impl fmt::Display for Address {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
+            self.bytes[5],
+            self.bytes[4],
+            self.bytes[3],
+            self.bytes[2],
+            self.bytes[1],
+            self.bytes[0]
+        )
+    }
+}
+
+/// When you parse an address and it's not valid
+#[derive(Debug, Clone)]
+pub struct InvalidAddressError;
+
+impl TryFrom<&[u8]> for Address {
+    type Error = InvalidAddressError;
+
+    fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
+        if slice.len() == 6 {
+            match <[u8; 6]>::try_from(slice) {
+                Ok(bytes) => Ok(Self { bytes }),
+                Err(_) => Err(InvalidAddressError),
+            }
+        } else {
+            Err(InvalidAddressError)
+        }
+    }
+}
+
+impl From<Address> for [u8; 6] {
+    fn from(addr: Address) -> [u8; 6] {
+        addr.bytes
+    }
+}
+
+/// A Bluetooth class of device
+#[derive(Clone, Eq, Copy, PartialEq, Hash, Ord, PartialOrd, Debug)]
+pub struct ClassOfDevice {
+    /// the actual bytes representing this class of device
+    pub bytes: [u8; 3],
+}
+
+impl fmt::Display for ClassOfDevice {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "{:03X}-{:01X}-{:02X}",
+            ((self.bytes[2] as u16) << 4) | ((self.bytes[1] as u16) >> 4),
+            self.bytes[1] & 0x0F,
+            self.bytes[0]
+        )
+    }
+}
+
+/// When you parse a class of device and it's not valid
+#[derive(Debug, Clone)]
+pub struct InvalidClassOfDeviceError;
+
+impl TryFrom<&[u8]> for ClassOfDevice {
+    type Error = InvalidClassOfDeviceError;
+
+    fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
+        if slice.len() == 3 {
+            match <[u8; 3]>::try_from(slice) {
+                Ok(bytes) => Ok(Self { bytes }),
+                Err(_) => Err(InvalidClassOfDeviceError),
+            }
+        } else {
+            Err(InvalidClassOfDeviceError)
+        }
+    }
+}
+
+impl From<ClassOfDevice> for [u8; 3] {
+    fn from(cod: ClassOfDevice) -> [u8; 3] {
+        cod.bytes
+    }
+}
index 346df8c..ddf8227 100644 (file)
@@ -1,6 +1,6 @@
 //! Loads info from the controller at startup
 
-use crate::HciExports;
+use crate::{Address, HciExports};
 use bt_packets::hci::{
     Enable, ErrorCode, LeMaximumDataLength, LeReadBufferSizeV1Builder, LeReadBufferSizeV2Builder,
     LeReadConnectListSizeBuilder, LeReadLocalSupportedFeaturesBuilder,
@@ -8,9 +8,9 @@ use bt_packets::hci::{
     LeReadNumberOfSupportedAdvertisingSetsBuilder, LeReadPeriodicAdvertiserListSizeBuilder,
     LeReadResolvingListSizeBuilder, LeReadSuggestedDefaultDataLengthBuilder,
     LeReadSupportedStatesBuilder, LeSetEventMaskBuilder, LocalVersionInformation, OpCode,
-    OpCodeIndex, ReadBufferSizeBuilder, ReadLocalExtendedFeaturesBuilder, ReadLocalNameBuilder,
-    ReadLocalSupportedCommandsBuilder, ReadLocalVersionInformationBuilder, SetEventMaskBuilder,
-    WriteLeHostSupportBuilder, WriteSimplePairingModeBuilder,
+    OpCodeIndex, ReadBdAddrBuilder, ReadBufferSizeBuilder, ReadLocalExtendedFeaturesBuilder,
+    ReadLocalNameBuilder, ReadLocalSupportedCommandsBuilder, ReadLocalVersionInformationBuilder,
+    SetEventMaskBuilder, WriteLeHostSupportBuilder, WriteSimplePairingModeBuilder,
 };
 use gddi::{module, provides, Stoppable};
 use num_traits::ToPrimitive;
@@ -34,18 +34,12 @@ macro_rules! assert_success {
 
 #[provides]
 async fn provide_controller(mut hci: HciExports) -> ControllerExports {
-    assert_success!(hci.send(LeSetEventMaskBuilder {
-        le_event_mask: 0x0000000000021e7f
-    }));
-    assert_success!(hci.send(SetEventMaskBuilder {
-        event_mask: 0x3dbfffffffffffff
-    }));
-    assert_success!(hci.send(WriteSimplePairingModeBuilder {
-        simple_pairing_mode: Enable::Enabled
-    }));
-    assert_success!(hci.send(WriteLeHostSupportBuilder {
-        le_supported_host: Enable::Enabled
-    }));
+    assert_success!(hci.send(LeSetEventMaskBuilder { le_event_mask: 0x0000000000021e7f }));
+    assert_success!(hci.send(SetEventMaskBuilder { event_mask: 0x3dbfffffffffffff }));
+    assert_success!(
+        hci.send(WriteSimplePairingModeBuilder { simple_pairing_mode: Enable::Enabled })
+    );
+    assert_success!(hci.send(WriteLeHostSupportBuilder { le_supported_host: Enable::Enabled }));
 
     let name = null_terminated_to_string(
         assert_success!(hci.send(ReadLocalNameBuilder {})).get_local_name(),
@@ -143,8 +137,11 @@ async fn provide_controller(mut hci: HciExports) -> ControllerExports {
             0
         };
 
+    let address = assert_success!(hci.send(ReadBdAddrBuilder {})).get_bd_addr();
+
     ControllerExports {
         name,
+        address,
         version_info,
         commands,
         lmp_features,
@@ -186,6 +183,7 @@ async fn read_lmp_features(hci: &mut HciExports) -> Vec<u64> {
 #[derive(Clone, Stoppable)]
 pub struct ControllerExports {
     name: String,
+    address: Address,
     version_info: LocalVersionInformation,
     commands: SupportedCommands,
     lmp_features: Vec<u64>,
index f443d98..57fad97 100644 (file)
@@ -7,6 +7,8 @@ pub mod error;
 /// HCI layer facade service
 pub mod facade;
 
+pub use bt_hci_custom_types::*;
+
 use bt_common::time::Alarm;
 use bt_hal::HalExports;
 use bt_packets::hci::EventChild::{
index f28fe1d..b702270 100644 (file)
@@ -5,5 +5,7 @@
 #![allow(missing_docs)]
 
 pub mod hci {
+    use bt_hci_custom_types::*;
+
     include!(concat!(env!("OUT_DIR"), "/hci_packets.rs"));
 }