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

Commit 141967ee authored by Bob Wang's avatar Bob Wang Committed by Gerrit Code Review
Browse files

Merge "[uwb-chip] Send DeviceResetCmd and poll rsp and ntf before hal is closed." into main

parents 435d7f42 49aa335f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ rust_binary {
        "libtokio_util",
        "libnix",
        "libanyhow",
        "libpdl_runtime",
        "libuwb_uci_packets",
    ],
    proc_macros: [
        "libasync_trait",
+45 −2
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@ use std::fs::{File, OpenOptions};
use std::io::{self, Read, Write};
use std::os::unix::fs::OpenOptionsExt;

use pdl_runtime::Packet;
use uwb_uci_packets::{DeviceResetCmdBuilder, ResetConfig, UciControlPacket, UciControlPacketHal};

enum State {
    Closed,
    Opened {
@@ -46,11 +49,23 @@ impl UwbChip {
impl State {
    /// Terminate the reader task.
    async fn close(&mut self) -> Result<()> {
        if let State::Opened { ref mut token, ref callbacks, ref mut death_recipient, ref mut handle, .. } = *self {
        if let State::Opened {
            ref mut token,
            ref callbacks,
            ref mut death_recipient,
            ref mut handle,
            ref mut serial,
        } = *self
        {
            log::info!("waiting for task cancellation");
            callbacks.as_binder().unlink_to_death(death_recipient)?;
            token.cancel();
            handle.await.unwrap();
            consume_device_reset_rsp_and_ntf(
                &mut serial
                    .try_clone()
                    .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?,
            );
            log::info!("task successfully cancelled");
            callbacks.onHalEvent(UwbEvent::CLOSE_CPLT, UwbStatus::OK)?;
            *self = State::Closed;
@@ -59,6 +74,20 @@ impl State {
    }
}

fn consume_device_reset_rsp_and_ntf(reader: &mut File) {
    // Poll the DeviceResetRsp and DeviceStatusNtf before hal is closed to prevent
    // the host from getting response and notifications from a 'powered down' UWBS.
    // Do nothing when these packets are received.
    const DEVICE_RESET_RSP: [u8; 5] = [64, 0, 0, 1, 0];
    const DEVICE_STATUS_NTF: [u8; 5] = [96, 1, 0, 1, 1];
    let mut buffer = vec![0; DEVICE_RESET_RSP.len() + DEVICE_STATUS_NTF.len()];
    read_exact(reader, &mut buffer).unwrap();

    // Make sure received packets are the expected ones.
    assert_eq!(&buffer[0..DEVICE_RESET_RSP.len()], &DEVICE_RESET_RSP);
    assert_eq!(&buffer[DEVICE_RESET_RSP.len()..], &DEVICE_STATUS_NTF);
}

pub fn makeraw(file: File) -> io::Result<File> {
    // Configure the file descriptor as raw fd.
    use nix::sys::termios::*;
@@ -209,7 +238,21 @@ impl IUwbChipAsyncServer for UwbChip {

        let mut state = self.state.lock().await;

        if matches!(*state, State::Opened { .. }) {
        if let State::Opened { ref mut serial, .. } = *state {
            let packet: UciControlPacket = DeviceResetCmdBuilder {
                reset_config: ResetConfig::UwbsReset,
            }
            .build()
            .into();
            // DeviceResetCmd need to be send to reset the device to stop all running
            // activities on UWBS.
            let packet_vec: Vec<UciControlPacketHal> = packet.into();
            for hal_packet in packet_vec.into_iter() {
                serial
                    .write(&hal_packet.to_vec())
                    .map(|written| written as i32)
                    .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
            }
            state.close().await
        } else {
            Err(binder::ExceptionCode::ILLEGAL_STATE.into())