From patchwork Mon Oct 14 13:18:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harvey Yang X-Patchwork-Id: 21619 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 1DEEDC326C for ; Mon, 14 Oct 2024 14:00:54 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A4B8A65386; Mon, 14 Oct 2024 16:00:53 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="BgsNWVpy"; dkim-atps=neutral Received: from mail-pj1-x102d.google.com (mail-pj1-x102d.google.com [IPv6:2607:f8b0:4864:20::102d]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2AA6565381 for ; Mon, 14 Oct 2024 16:00:48 +0200 (CEST) Received: by mail-pj1-x102d.google.com with SMTP id 98e67ed59e1d1-2e2e6a1042dso3063167a91.2 for ; Mon, 14 Oct 2024 07:00:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1728914447; x=1729519247; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=eo2CEJPMEc98nxYdjEguIyVbah24nk+wH3oHihuMsMk=; b=BgsNWVpyaU4cC1yUNTpB+OW/3tT1HlclehjnXpE+s4d9hVQ9Vqs5eVEHhdwuMOHW8K ijO3IaLRlOqv44FIo8j9BvOjDdPDGpxmOII3graTW5rI/KWAnBJxKPWD4MqEReSVhXEh n7Ll89f6puWje4BxdhsI4WU65ak8IkryCqeiw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728914447; x=1729519247; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=eo2CEJPMEc98nxYdjEguIyVbah24nk+wH3oHihuMsMk=; b=vFaXkRVfBRPi0YwFTJTqhCe2Lude2eCv+2NliN6Z5tbg9fvIunjWTJvisEIgqvGSXj 4QdxlOs3zT5jw+RVTFmmlS3h2cJiRAPw8hC8bFQD0eIegsXTc8pJDOUDiTUViqqGHmSj jwfa0As6hGW7OWJyNU4X9hWl59/JbD3JZ1wFRvjJ9LyaHWniaXfgWdz2HF3AicJDOt6Q GknsvqaY9cpwXd39f6Earzcg21SCcyNvHNDT1CiWp4NdgszD5KfofpqIzuYaEXsjIc+v kl9oWZHzorgR1yb5vgfZZWbptoPJ9AZ7Ur9kMHPtb+38tOEj3uV4KYvQAJCuy3aRdOtc tJQA== X-Gm-Message-State: AOJu0Yx9xOX0gCHRkMkMynOHmiINUHXl2g610aD2vlWPF/3iWSwkoWSq nx8T5G/ZzOpGiAsmGTLIfqXQOP4Nf2gJHFu8zkHw/a4MQOrYy3t0WSvndW+7HxUC5A5xcRxqda4 = X-Google-Smtp-Source: AGHT+IEN/MGhn9v/5X5DZj+QYaEh8CSDTDFV/0vTulQmFzo31UNIXrO7gjD1r3fAx+aih1QjnK5BCA== X-Received: by 2002:a17:90a:4e0d:b0:2e2:b41b:854e with SMTP id 98e67ed59e1d1-2e3152e4dd9mr11448939a91.20.1728914446605; Mon, 14 Oct 2024 07:00:46 -0700 (PDT) Received: from chenghaoyang-low.c.googlers.com.com (199.211.81.34.bc.googleusercontent.com. [34.81.211.199]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2e2bb093837sm10459215a91.4.2024.10.14.07.00.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Oct 2024 07:00:45 -0700 (PDT) From: Harvey Yang To: libcamera-devel@lists.libcamera.org Cc: Harvey Yang , Han-Lin Chen Subject: [PATCH 2/2] libcamera: Add GyroSensor as a base class Date: Mon, 14 Oct 2024 13:18:57 +0000 Message-ID: <20241014140038.1133270-3-chenghaoyang@chromium.org> X-Mailer: git-send-email 2.47.0.rc1.288.g06298d1525-goog In-Reply-To: <20241014140038.1133270-1-chenghaoyang@chromium.org> References: <20241014140038.1133270-1-chenghaoyang@chromium.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" An android-cros implementation is also added, with defined SensorHalClient interface connecting to CrOS daemon iioservice. Signed-off-by: Harvey Yang Co-developed-by: Han-Lin Chen Signed-off-by: Han-Lin Chen --- include/libcamera/internal/gyro_sensor.h | 65 ++++++++ src/libcamera/cros_gyro_sensor.cpp | 179 +++++++++++++++++++++++ src/libcamera/gyro_sensor.cpp | 82 +++++++++++ src/libcamera/meson.build | 8 + 4 files changed, 334 insertions(+) create mode 100644 include/libcamera/internal/gyro_sensor.h create mode 100644 src/libcamera/cros_gyro_sensor.cpp create mode 100644 src/libcamera/gyro_sensor.cpp diff --git a/include/libcamera/internal/gyro_sensor.h b/include/libcamera/internal/gyro_sensor.h new file mode 100644 index 000000000..3a2d5ecee --- /dev/null +++ b/include/libcamera/internal/gyro_sensor.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Google Inc. + * + * gyro_sensor.h - A gyroscope sensor + */ + +#pragma once + +#include + +namespace libcamera { + +class GyroSensor final : public libcamera::Extensible +{ + LIBCAMERA_DECLARE_PRIVATE() + +public: + enum class Location { + kNone = 0, // The device doesn't have the location attribute. + kBase = 1, + kLid = 2, + kCamera = 3, + }; + + struct SensorSample { + double x_value; + double y_value; + double z_value; + int64_t timestamp; + }; + + GyroSensor(); + + int init(Location location); + + bool startReading(double frequency); + void stopReading(); + + SensorSample getLatestSample(); +}; + +#define PUBLIC_GYRO_SENSOR_IMPLEMENTATION \ + GyroSensor::GyroSensor() \ + : Extensible(std::make_unique()) \ + { \ + } \ + int GyroSensor::init(Location location) \ + { \ + return _d()->init(location); \ + } \ + bool GyroSensor::startReading(double frequency) \ + { \ + return _d()->startReading(frequency); \ + } \ + void GyroSensor::stopReading() \ + { \ + _d()->stopReading(); \ + } \ + GyroSensor::SensorSample GyroSensor::getLatestSample() \ + { \ + return _d()->getLatestSample(); \ + } + +} /* namespace libcamera */ diff --git a/src/libcamera/cros_gyro_sensor.cpp b/src/libcamera/cros_gyro_sensor.cpp new file mode 100644 index 000000000..062f0013d --- /dev/null +++ b/src/libcamera/cros_gyro_sensor.cpp @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Google Inc. + * + * cros_gyro_sensor.cpp - Chromium OS gyroscope sensor using mojo + */ + +#include +#include +#include + +#include "libcamera/internal/gyro_sensor.h" + +#include + +#include "../android/cros_mojo_token.h" + +namespace libcamera { + +namespace { + +std::string convertErrorTypeToString(cros::SamplesObserver::ErrorType error) +{ + switch (error) { + case cros::SamplesObserver::ErrorType::MOJO_DISCONNECTED: + return "MOJO_DISCONNECTED"; + + case cros::SamplesObserver::ErrorType::READ_FAILED: + return "READ_FAILED"; + + case cros::SamplesObserver::ErrorType::INVALID_ARGUMENT: + return "INVALID_ARGUMENT"; + + case cros::SamplesObserver::ErrorType::DEVICE_REMOVED: + return "DEVICE_REMOVED"; + } +} + +} /* namespace */ + +LOG_DEFINE_CATEGORY(CrosGyroSensor) + +class GyroSensor::Private : public Extensible::Private, + public cros::SamplesObserver +{ + LIBCAMERA_DECLARE_PUBLIC(GyroSensor) + +public: + Private(); + + int init(Location location); + + bool startReading(double frequency); + void stopReading(); + + SensorSample getLatestSample(); + + void OnSampleUpdated(cros::SamplesObserver::Sample sample) override; + void OnErrorOccurred(cros::SamplesObserver::ErrorType error) override; + +private: + cros::SensorHalClient *sensorHalClient_; + cros::SensorHalClient::Location location_; + + libcamera::Mutex gyroSampleMutex_; + SensorSample gyroSample_ LIBCAMERA_TSA_GUARDED_BY(gyroSampleMutex_); +}; + +/** + * \class libcamera::GyroSensor::Private + * \brief CrOS implementation of GyroSensor + */ +GyroSensor::Private::Private() +{ +} + +/** + * \brief Initialize with \a location inquiried + * \param[in] location The gyroscope with \a location needed + * \return 0 on success or a negative error code otherwise + */ +int GyroSensor::Private::init(Location location) +{ + sensorHalClient_ = cros::SensorHalClient::GetInstance(gCrosMojoToken); + location_ = static_cast(location); + if (sensorHalClient_ && + sensorHalClient_->HasDevice( + cros::SensorHalClient::DeviceType::kAnglVel, location_)) { + return 0; + } + + return -ENXIO; +} + +/** + * \brief Start reading gyroscope samples with \a frequency + * \param[in] frequency The frequency of samples required + * + * This should be called after init(). + * + * \sa init() + * + * \return True if succeed + */ +bool GyroSensor::Private::startReading(double frequency) +{ + return sensorHalClient_->RegisterSamplesObserver( + cros::SensorHalClient::DeviceType::kAnglVel, + location_, frequency, this); +} + +/** + * \brief Stop reading gyroscope samples + * + * \sa startReading() + */ +void GyroSensor::Private::stopReading() +{ + sensorHalClient_->UnregisterSamplesObserver(this); +} + +/** + * \brief This should be called after startReading() + * + * \sa startReading() + * + * \return The latest received sample + */ +GyroSensor::SensorSample GyroSensor::Private::getLatestSample() +{ + MutexLocker lock(gyroSampleMutex_); + + return gyroSample_; +} + +/** + * \brief A sample is updated and pushed to GyroSensor::Private + * \param[in] sample The sample being updated + */ +void GyroSensor::Private::OnSampleUpdated(cros::SamplesObserver::Sample sample) +{ + MutexLocker lock(gyroSampleMutex_); + + gyroSample_.x_value = sample.x_value; + gyroSample_.y_value = sample.y_value; + gyroSample_.z_value = sample.z_value; + gyroSample_.timestamp = sample.timestamp; +} + +/** + * \brief An error is occurred and pushed to GyroSensor::Private + * \param[in] error The error occurred + */ +void GyroSensor::Private::OnErrorOccurred(cros::SamplesObserver::ErrorType error) +{ + switch (error) { + case cros::SamplesObserver::ErrorType::READ_FAILED: + LOG(CrosGyroSensor, Error) << "SensorHalClient error: " + << convertErrorTypeToString(error); + break; + + case cros::SamplesObserver::ErrorType::MOJO_DISCONNECTED: + case cros::SamplesObserver::ErrorType::INVALID_ARGUMENT: + case cros::SamplesObserver::ErrorType::DEVICE_REMOVED: + LOG(CrosGyroSensor, Error) << "SensorHalClient error: " + << convertErrorTypeToString(error) + << ", aborting all usages"; + auto *sensorHalClient = + cros::SensorHalClient::GetInstance(gCrosMojoToken); + if (sensorHalClient) + sensorHalClient->UnregisterSamplesObserver(this); + + break; + } +} + +PUBLIC_GYRO_SENSOR_IMPLEMENTATION + +} /* namespace libcamera */ diff --git a/src/libcamera/gyro_sensor.cpp b/src/libcamera/gyro_sensor.cpp new file mode 100644 index 000000000..0ea4f0c71 --- /dev/null +++ b/src/libcamera/gyro_sensor.cpp @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Google Inc. + * + * gyro_sensor.cpp - A gyroscope sensor + */ + +/** + * \class libcamera::GyroSensor + * \brief Gyroscope Sensor + * + * The GyroSensor class models a gyroscope sensor capable of reporting + * gyroscope samples, with x, y, z, and timestamp channels. There might be + * multiple gyroscope sensors on a system, while should be distinguishable via + * GyroSensor::Location. + */ + +/** + * \enum libcamera::GyroSensor::Location + * \brief Gyroscope sensor's location type + * \var GyroSensor::kNone + * \brief No location attribute available + * \var GyroSensor::kBase + * \brief Gyroscope sensor is on the base + * \var GyroSensor::kLid + * \brief Gyroscope sensor is on the lid + * \var GyroSensor::kCamera + * \brief Gyroscope sensor is on the camera + */ + +/** + * \struct libcamera::GyroSensor::SensorSample + * \brief SensorSample contains all available channels within a sample + * + * \var SensorSample::x_value + * \brief Sensor reading on the x axis + * + * \var SensorSample::y_value + * \brief Sensor reading on the y axis + * + * \var SensorSample::z_value + * \brief Sensor reading on the z axis + * + * \var SensorSample::timestamp + * \brief The timestamp of the sample + */ + +/** + * \fn int GyroSensor::init(Location location) + * \brief Initialize with \a location inquiried + * \param[in] location The gyroscope with \a location needed + * \return 0 on success or a negative error code otherwise + */ + +/** + * \fn bool GyroSensor::startReading(double frequency) + * \brief Start reading gyroscope samples with \a frequency + * \param[in] frequency The frequency of samples required + * + * This should be called after init(). + * + * \sa init() + * + * \return True if succeed + */ + +/** + * \fn void GyroSensor::stopReading() + * \brief Stop reading gyroscope samples + * + * \sa startReading() + */ + +/** + * \fn SensorSample GyroSensor::getLatestSample() + * + * This should be called after startReading() + * + * \sa startReading() + * + * \return The latest received sample + */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index aa9ab0291..9cd393920 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -60,6 +60,14 @@ includes = [ libcamera_deps = [] +if get_option('android').enabled() and get_option('android_platform') == 'cros' + libcamera_public_sources += files([ + 'cros_gyro_sensor.cpp', + 'gyro_sensor.cpp', + ]) + libcamera_deps += [dependency('libcros_camera')] +endif + libatomic = cc.find_library('atomic', required : false) libthreads = dependency('threads')