Ability to send HCI commands from Rust

* Autogenerate packet code in Rust from PDL (packet file copied from rootcanal)
* Implement parsing of packets that have a type header
* Expose Python APIs for sending HCI commands
* Expose Python APIs for instantiating a local controller
This commit is contained in:
Gabriel White-Vega
2023-09-14 14:28:22 -04:00
parent c12dee4e76
commit 7e331c2944
16 changed files with 7041 additions and 72 deletions

View File

@@ -12,9 +12,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use bumble::wrapper::{drivers::rtk::DriverInfo, transport::Transport};
use bumble::wrapper::{
controller::Controller,
device::Device,
drivers::rtk::DriverInfo,
hci::packets::{
AddressType, Error, ErrorCode, ReadLocalVersionInformationBuilder,
ReadLocalVersionInformationComplete,
},
hci::Address,
host::Host,
link::Link,
transport::Transport,
};
use nix::sys::stat::Mode;
use pyo3::PyResult;
use pyo3::{
exceptions::PyException,
{PyErr, PyResult},
};
#[pyo3_asyncio::tokio::test]
async fn fifo_transport_can_open() -> PyResult<()> {
@@ -35,3 +50,26 @@ async fn realtek_driver_info_all_drivers() -> PyResult<()> {
assert_eq!(12, DriverInfo::all_drivers()?.len());
Ok(())
}
#[pyo3_asyncio::tokio::test]
async fn hci_command_wrapper_has_correct_methods() -> PyResult<()> {
let address = Address::new("F0:F1:F2:F3:F4:F5", &AddressType::RandomDeviceAddress)?;
let link = Link::new_local_link()?;
let controller = Controller::new("C1", None, None, Some(link), Some(address.clone())).await?;
let host = Host::new(controller.clone().into(), controller.into())?;
let device = Device::new(None, Some(address), None, Some(host), None)?;
device.power_on().await?;
// Send some simple command. A successful response means [HciCommandWrapper] has the minimum
// required interface for the Python code to think its an [HCI_Command] object.
let command = ReadLocalVersionInformationBuilder {};
let event: ReadLocalVersionInformationComplete = device
.send_command(&command.into(), true)
.await?
.try_into()
.map_err(|e: Error| PyErr::new::<PyException, _>(e.to_string()))?;
assert_eq!(ErrorCode::Success, event.get_status());
Ok(())
}