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

Commit 33fc8239 authored by Charlie Boutier's avatar Charlie Boutier Committed by Automerger Merge Worker
Browse files

Merge "Revert "Revert "uwb(hal): Implement UCI over serial in the defau...""...

Merge "Revert "Revert "uwb(hal): Implement UCI over serial in the defau..."" am: 29567e79 am: 57cccf0c

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2530005



Change-Id: I305a268fad2824f1ddd7f958cc2101289b5fc626
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 6b32036b 57cccf0c
Loading
Loading
Loading
Loading
+14 −17
Original line number Diff line number Diff line
@@ -7,29 +7,26 @@ package {
    default_applicable_licenses: ["hardware_interfaces_license"],
}

cc_binary {
rust_binary {
    name: "android.hardware.uwb-service",
    crate_name: "uwb_default_hal",
    relative_install_path: "hw",
    init_rc: ["uwb-service.rc"],
    vintf_fragments: ["uwb-service.xml"],
    vendor: true,
    cflags: [
        "-Wall",
        "-Wextra",
        "-g",
    rustlibs: [
        "android.hardware.uwb-V1-rust",
        "liblogger",
        "liblog_rust",
        "libbinder_rs",
        "libbinder_tokio_rs",
        "libtokio",
        "libnix",
        "libanyhow",
    ],
    shared_libs: [
        "liblog",
        "libbinder_ndk",
    ],
    static_libs: [
        "libbase",
        "libutils",
        "android.hardware.uwb-V1-ndk",
    proc_macros: [
        "libasync_trait",
    ],
    srcs: [
        "service.cpp",
        "uwb.cpp",
        "uwb_chip.cpp",
        "src/service.rs",
    ],
}

uwb/aidl/default/service.cpp

deleted100644 → 0
+0 −42
Original line number Diff line number Diff line
/*
 * Copyright 2021, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <utils/StrongPointer.h>

#include "uwb.h"

using ::aidl::android::hardware::uwb::IUwb;
using ::android::sp;
using ::android::base::InitLogging;
using ::android::base::StderrLogger;
using ::android::hardware::uwb::impl::Uwb;

int main(int /*argc*/, char* argv[]) {
    InitLogging(argv, StderrLogger);
    LOG(INFO) << "UWB HAL starting up";

    ABinderProcess_setThreadPoolMaxThreadCount(0);
    std::shared_ptr<IUwb> uwb = ndk::SharedRefBase::make<Uwb>();
    const std::string instance = std::string() + IUwb::descriptor + "/default";
    binder_status_t status = AServiceManager_addService(uwb->asBinder().get(), instance.c_str());
    CHECK(status == STATUS_OK);

    ABinderProcess_joinThreadPool();
    return EXIT_FAILURE;  // should not reach
}
+47 −0
Original line number Diff line number Diff line
use android_hardware_uwb::aidl::android::hardware::uwb::IUwb::{self, IUwb as _};
use android_hardware_uwb::binder;

use tokio::runtime::Runtime;

use std::env;
use std::panic;

use log::Level;

mod uwb;
mod uwb_chip;

fn main() -> anyhow::Result<()> {
    logger::init(
        logger::Config::default()
            .with_min_level(Level::Debug)
            .with_tag_on_device("android.hardware.uwb"),
    );

    // Redirect panic messages to logcat.
    panic::set_hook(Box::new(|panic_info| {
        log::error!("{}", panic_info);
    }));

    log::info!("UWB HAL starting up");

    // Create the tokio runtime
    let rt = Runtime::new()?;

    let chips = env::args()
        .skip(1) // Skip binary name
        .enumerate()
        .map(|(i, arg)| uwb_chip::UwbChip::new(i.to_string(), arg));

    binder::add_service(
        &format!("{}/default", IUwb::BpUwb::get_descriptor()),
        IUwb::BnUwb::new_binder(
            uwb::Uwb::from_chips(chips, rt.handle().clone()),
            binder::BinderFeatures::default(),
        )
        .as_binder(),
    )?;

    binder::ProcessState::join_thread_pool();
    Ok(())
}
+53 −0
Original line number Diff line number Diff line
use android_hardware_uwb::aidl::android::hardware::uwb::{IUwb, IUwbChip};
use android_hardware_uwb::binder;
use binder::{Result, Strong};
use binder_tokio::TokioRuntime;
use tokio::runtime::Handle as TokioHandle;

use crate::uwb_chip;

pub struct Uwb {
    chips: Vec<Strong<dyn IUwbChip::IUwbChip>>,
}

impl Uwb {
    pub fn from_chips(
        chips: impl IntoIterator<Item = uwb_chip::UwbChip>,
        handle: TokioHandle,
    ) -> Self {
        Self {
            chips: chips
                .into_iter()
                .map(|chip| {
                    IUwbChip::BnUwbChip::new_async_binder(
                        chip,
                        TokioRuntime(handle.clone()),
                        binder::BinderFeatures::default(),
                    )
                })
                .collect(),
        }
    }
}

impl binder::Interface for Uwb {}

impl IUwb::IUwb for Uwb {
    fn getChips(&self) -> Result<Vec<String>> {
        log::debug!("getChips");
        self.chips.iter().map(|chip| chip.getName()).collect()
    }

    fn getChip(&self, name: &str) -> Result<Strong<dyn IUwbChip::IUwbChip>> {
        log::debug!("getChip {}", name);
        let chip = self
            .chips
            .iter()
            .find(|chip| chip.getName().as_deref() == Ok(name));
        if let Some(chip) = chip {
            Ok(chip.clone())
        } else {
            Err(binder::ExceptionCode::ILLEGAL_ARGUMENT.into())
        }
    }
}
+168 −0
Original line number Diff line number Diff line
use android_hardware_uwb::aidl::android::hardware::uwb::{
    IUwbChip::IUwbChipAsyncServer, IUwbClientCallback::IUwbClientCallback, UwbEvent::UwbEvent,
    UwbStatus::UwbStatus,
};
use android_hardware_uwb::binder;
use async_trait::async_trait;
use binder::{Result, Strong};

use tokio::fs::File;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::sync::Mutex;

use std::os::fd::AsRawFd;

use std::io;

use nix::sys::termios;

enum State {
    Closed,
    Opened {
        callbacks: Strong<dyn IUwbClientCallback>,
        #[allow(dead_code)]
        tasks: tokio::task::JoinSet<()>,
        write: File,
    },
}

pub struct UwbChip {
    name: String,
    path: String,
    state: Mutex<State>,
}

impl UwbChip {
    pub fn new(name: String, path: String) -> Self {
        Self {
            name,
            path,
            state: Mutex::new(State::Closed),
        }
    }
}

pub fn makeraw(file: File) -> io::Result<File> {
    let fd = file.as_raw_fd();

    let mut attrs = termios::tcgetattr(fd)?;

    termios::cfmakeraw(&mut attrs);

    termios::tcsetattr(fd, termios::SetArg::TCSANOW, &attrs)?;

    Ok(file)
}

impl binder::Interface for UwbChip {}

#[async_trait]
impl IUwbChipAsyncServer for UwbChip {
    async fn getName(&self) -> Result<String> {
        Ok(self.name.clone())
    }

    async fn open(&self, callbacks: &Strong<dyn IUwbClientCallback>) -> Result<()> {
        log::debug!("open: {:?}", &self.path);

        let serial = File::open(&self.path)
            .await
            .and_then(makeraw)
            .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;

        let mut read = serial
            .try_clone()
            .await
            .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
        let write = serial;

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

        if let State::Closed = *state {
            let client_callbacks = callbacks.clone();

            let mut tasks = tokio::task::JoinSet::new();

            tasks.spawn(async move {
                loop {
                    const UWB_HEADER_SIZE: usize = 4;

                    let mut buffer = vec![0; UWB_HEADER_SIZE];
                    read.read_exact(&mut buffer[0..UWB_HEADER_SIZE])
                        .await
                        .unwrap();

                    let length = buffer[3] as usize + UWB_HEADER_SIZE;

                    buffer.resize(length, 0);
                    read.read_exact(&mut buffer[UWB_HEADER_SIZE..length])
                        .await
                        .unwrap();

                    client_callbacks.onUciMessage(&buffer[..]).unwrap();
                }
            });

            callbacks.onHalEvent(UwbEvent::OPEN_CPLT, UwbStatus::OK)?;

            *state = State::Opened {
                callbacks: callbacks.clone(),
                tasks,
                write,
            };

            Ok(())
        } else {
            Err(binder::ExceptionCode::ILLEGAL_STATE.into())
        }
    }

    async fn close(&self) -> Result<()> {
        log::debug!("close");

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

        if let State::Opened { ref callbacks, .. } = *state {
            callbacks.onHalEvent(UwbEvent::CLOSE_CPLT, UwbStatus::OK)?;
            *state = State::Closed;
            Ok(())
        } else {
            Err(binder::ExceptionCode::ILLEGAL_STATE.into())
        }
    }

    async fn coreInit(&self) -> Result<()> {
        log::debug!("coreInit");

        if let State::Opened { ref callbacks, .. } = *self.state.lock().await {
            callbacks.onHalEvent(UwbEvent::POST_INIT_CPLT, UwbStatus::OK)?;
            Ok(())
        } else {
            Err(binder::ExceptionCode::ILLEGAL_STATE.into())
        }
    }

    async fn sessionInit(&self, _id: i32) -> Result<()> {
        log::debug!("sessionInit");

        Ok(())
    }

    async fn getSupportedAndroidUciVersion(&self) -> Result<i32> {
        Ok(1)
    }

    async fn sendUciMessage(&self, data: &[u8]) -> Result<i32> {
        log::debug!("sendUciMessage");

        if let State::Opened { write, .. } = &mut *self.state.lock().await {
            write
                .write(data)
                .await
                .map(|written| written as i32)
                .map_err(|_| binder::StatusCode::UNKNOWN_ERROR.into())
        } else {
            Err(binder::ExceptionCode::ILLEGAL_STATE.into())
        }
    }
}
Loading