267 lines
10 KiB
C++
267 lines
10 KiB
C++
/*
|
|
* Copyright (C) 2020 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.
|
|
*/
|
|
#define LOG_TAG "GoogleIIOSensorSubHal"
|
|
|
|
#include "SensorsSubHal.h"
|
|
#include <android/hardware/sensors/2.0/types.h>
|
|
#include <log/log.h>
|
|
|
|
ISensorsSubHal* sensorsHalGetSubHal(uint32_t* version) {
|
|
static ::android::hardware::sensors::V2_0::subhal::implementation::SensorsSubHal subHal;
|
|
*version = SUB_HAL_2_0_VERSION;
|
|
return &subHal;
|
|
}
|
|
|
|
namespace android {
|
|
namespace hardware {
|
|
namespace sensors {
|
|
namespace V2_0 {
|
|
namespace subhal {
|
|
namespace implementation {
|
|
|
|
using ::android::hardware::Void;
|
|
using ::android::hardware::sensors::V1_0::Event;
|
|
using ::android::hardware::sensors::V1_0::RateLevel;
|
|
using ::android::hardware::sensors::V1_0::SharedMemInfo;
|
|
using ::android::hardware::sensors::V2_0::SensorTimeout;
|
|
using ::android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
|
|
using ::android::hardware::sensors::V2_0::implementation::ScopedWakelock;
|
|
using ::sensor::hal::configuration::V1_0::Sensor;
|
|
using ::sensor::hal::configuration::V1_0::SensorHalConfiguration;
|
|
|
|
#define SENSOR_XML_CONFIG_FILE_NAME "sensor_hal_configuration.xml"
|
|
static const char* gSensorConfigLocationList[] = {"/odm/etc/sensors/", "/vendor/etc/sensors/"};
|
|
static const int gSensorConfigLocationListSize =
|
|
(sizeof(gSensorConfigLocationList) / sizeof(gSensorConfigLocationList[0]));
|
|
|
|
#define MODULE_NAME "android.hardware.sensors@2.0-Google-IIO-Subhal"
|
|
|
|
static std::optional<std::vector<Sensor>> readSensorsConfigFromXml() {
|
|
for (int i = 0; i < gSensorConfigLocationListSize; i++) {
|
|
const auto sensor_config_file =
|
|
std::string(gSensorConfigLocationList[i]) + SENSOR_XML_CONFIG_FILE_NAME;
|
|
auto sensorConfig = ::sensor::hal::configuration::V1_0::read(sensor_config_file.c_str());
|
|
if (sensorConfig) {
|
|
auto modulesList = sensorConfig->getFirstModules()->get_module();
|
|
for (auto module : modulesList) {
|
|
if (module.getHalName().compare(MODULE_NAME) == 0) {
|
|
return module.getFirstSensors()->getSensor();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ALOGI("Could not find the sensors configuration for module %s", MODULE_NAME);
|
|
return std::nullopt;
|
|
}
|
|
|
|
static std::optional<std::vector<Configuration>> getSensorConfiguration(
|
|
const std::vector<Sensor>& sensor_list, const std::string& name, SensorType type) {
|
|
for (auto sensor : sensor_list) {
|
|
if ((name.compare(sensor.getName()) == 0) && (type == (SensorType)sensor.getType())) {
|
|
return sensor.getConfiguration();
|
|
}
|
|
}
|
|
ALOGI("Could not find the sensor configuration for %s ", name.c_str());
|
|
return std::nullopt;
|
|
}
|
|
|
|
static bool isSensorSupported(iio_device_data* sensor) {
|
|
#define SENSOR_SUPPORTED(SENSOR_NAME, SENSOR_TYPE) \
|
|
{ .name = SENSOR_NAME, .type = SENSOR_TYPE, }
|
|
static const std::vector<sensors_supported_hal> supported_sensors = {
|
|
SENSOR_SUPPORTED("scmi.iio.accel", SensorType::ACCELEROMETER),
|
|
SENSOR_SUPPORTED("scmi.iio.gyro", SensorType::GYROSCOPE),
|
|
};
|
|
#undef SENSOR_SUPPORTED
|
|
|
|
if (!sensor) return false;
|
|
|
|
auto iter = std::find_if(
|
|
supported_sensors.begin(), supported_sensors.end(),
|
|
[&sensor](const auto& candidate) -> bool { return candidate.name == sensor->name; });
|
|
if (iter == supported_sensors.end()) return false;
|
|
|
|
sensor->type = iter->type;
|
|
return true;
|
|
}
|
|
|
|
SensorsSubHal::SensorsSubHal() : mCallback(nullptr), mNextHandle(1) {
|
|
int err;
|
|
std::vector<iio_device_data> iio_devices;
|
|
const auto sensors_config_list = readSensorsConfigFromXml();
|
|
err = load_iio_devices(DEFAULT_IIO_DIR, &iio_devices, isSensorSupported);
|
|
if (err == 0) {
|
|
for (auto& iio_device : iio_devices) {
|
|
err = scan_elements(iio_device.sysfspath, &iio_device);
|
|
if (err == 0) {
|
|
err = enable_sensor(iio_device.sysfspath, false);
|
|
if (err == 0) {
|
|
std::optional<std::vector<Configuration>> sensor_configuration = std::nullopt;
|
|
if (sensors_config_list)
|
|
sensor_configuration = getSensorConfiguration(
|
|
*sensors_config_list, iio_device.name, iio_device.type);
|
|
|
|
if (iio_device.channelInfo.size() == NUM_OF_CHANNEL_SUPPORTED) {
|
|
AddSensor(iio_device, sensor_configuration);
|
|
} else {
|
|
ALOGE("SensorsSubHal(): Unexpected number of channels for sensor %s",
|
|
iio_device.sysfspath.c_str());
|
|
}
|
|
} else {
|
|
ALOGE("SensorsSubHal(): Error in enabling_sensor %s to %d error code %d",
|
|
iio_device.sysfspath.c_str(), false, err);
|
|
}
|
|
} else {
|
|
ALOGE("SensorsSubHal(): Error in scanning channels for IIO device %s error code %d",
|
|
iio_device.sysfspath.c_str(), err);
|
|
}
|
|
}
|
|
} else {
|
|
ALOGE("SensorsSubHal: load_iio_devices returned error %d", err);
|
|
}
|
|
}
|
|
|
|
// Methods from ::android::hardware::sensors::V2_0::ISensors follow.
|
|
Return<void> SensorsSubHal::getSensorsList(getSensorsList_cb _hidl_cb) {
|
|
std::vector<SensorInfo> sensors;
|
|
for (const auto& sensor : mSensors) {
|
|
SensorInfo sensorInfo = sensor.second->getSensorInfo();
|
|
sensorInfo.flags &= ~static_cast<uint32_t>(V1_0::SensorFlagBits::MASK_DIRECT_CHANNEL);
|
|
sensorInfo.flags &= ~static_cast<uint32_t>(V1_0::SensorFlagBits::MASK_DIRECT_REPORT);
|
|
sensors.push_back(sensorInfo);
|
|
}
|
|
|
|
_hidl_cb(sensors);
|
|
return Void();
|
|
}
|
|
|
|
Return<Result> SensorsSubHal::setOperationMode(OperationMode mode) {
|
|
for (auto& sensor : mSensors) {
|
|
sensor.second->setOperationMode(mode);
|
|
}
|
|
mCurrentOperationMode = mode;
|
|
return Result::OK;
|
|
}
|
|
|
|
Return<Result> SensorsSubHal::activate(int32_t sensorHandle, bool enabled) {
|
|
auto sensor = mSensors.find(sensorHandle);
|
|
if (sensor != mSensors.end()) {
|
|
sensor->second->activate(enabled);
|
|
return Result::OK;
|
|
}
|
|
return Result::BAD_VALUE;
|
|
}
|
|
|
|
Return<Result> SensorsSubHal::batch(int32_t sensorHandle, int64_t samplingPeriodNs,
|
|
int64_t /* maxReportLatencyNs */) {
|
|
auto sensor = mSensors.find(sensorHandle);
|
|
if (sensor != mSensors.end()) {
|
|
sensor->second->batch(samplingPeriodNs);
|
|
return Result::OK;
|
|
}
|
|
return Result::BAD_VALUE;
|
|
}
|
|
|
|
Return<Result> SensorsSubHal::flush(int32_t sensorHandle) {
|
|
auto sensor = mSensors.find(sensorHandle);
|
|
if (sensor != mSensors.end()) {
|
|
return sensor->second->flush();
|
|
}
|
|
return Result::BAD_VALUE;
|
|
}
|
|
|
|
Return<Result> SensorsSubHal::injectSensorData(const Event& /* event */) {
|
|
return Result::INVALID_OPERATION;
|
|
}
|
|
|
|
Return<void> SensorsSubHal::registerDirectChannel(const SharedMemInfo& /* mem */,
|
|
registerDirectChannel_cb _hidl_cb) {
|
|
_hidl_cb(Result::INVALID_OPERATION, -1 /* channelHandle */);
|
|
return Return<void>();
|
|
}
|
|
|
|
Return<Result> SensorsSubHal::unregisterDirectChannel(int32_t /* channelHandle */) {
|
|
return Result::INVALID_OPERATION;
|
|
}
|
|
|
|
Return<void> SensorsSubHal::configDirectReport(int32_t /* sensorHandle */,
|
|
int32_t /* channelHandle */, RateLevel /* rate */,
|
|
configDirectReport_cb _hidl_cb) {
|
|
_hidl_cb(Result::INVALID_OPERATION, 0 /* reportToken */);
|
|
return Return<void>();
|
|
}
|
|
|
|
Return<void> SensorsSubHal::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) {
|
|
if (fd.getNativeHandle() == nullptr || fd->numFds < 1) {
|
|
ALOGE("%s: missing fd for writing", __FUNCTION__);
|
|
return Void();
|
|
}
|
|
FILE* out = fdopen(dup(fd->data[0]), "w");
|
|
|
|
if (args.size() != 0) {
|
|
fprintf(out,
|
|
"Note: sub-HAL %s currently does not support args. Input arguments are "
|
|
"ignored.\n",
|
|
getName().c_str());
|
|
}
|
|
|
|
std::ostringstream stream;
|
|
stream << "Available sensors:" << std::endl;
|
|
for (auto& sensor : mSensors) {
|
|
SensorInfo info = sensor.second->getSensorInfo();
|
|
HWSensorBase* hwSensor = static_cast<HWSensorBase*>(sensor.second.get());
|
|
stream << "Name: " << info.name << std::endl;
|
|
stream << "handle: " << info.sensorHandle << std::endl;
|
|
stream << "resolution: " << info.resolution << " minDelay: " << info.minDelay
|
|
<< " maxDelay:" << info.maxDelay << std::endl;
|
|
stream << "iio path" << hwSensor->mIioData.sysfspath << std::endl;
|
|
}
|
|
|
|
stream << std::endl;
|
|
|
|
fprintf(out, "%s", stream.str().c_str());
|
|
|
|
fclose(out);
|
|
return Return<void>();
|
|
}
|
|
|
|
Return<Result> SensorsSubHal::initialize(const sp<IHalProxyCallback>& halProxyCallback) {
|
|
mCallback = halProxyCallback;
|
|
setOperationMode(OperationMode::NORMAL);
|
|
return Result::OK;
|
|
}
|
|
|
|
void SensorsSubHal::postEvents(const std::vector<Event>& events, bool wakeup) {
|
|
ScopedWakelock wakelock = mCallback->createScopedWakelock(wakeup);
|
|
mCallback->postEvents(events, std::move(wakelock));
|
|
}
|
|
void SensorsSubHal::AddSensor(const struct iio_device_data& iio_data,
|
|
const std::optional<std::vector<Configuration>>& config) {
|
|
HWSensorBase* sensor = HWSensorBase::buildSensor(mNextHandle++ /* sensorHandle */,
|
|
this /* callback */, iio_data, config);
|
|
if (sensor != nullptr)
|
|
mSensors[sensor->getSensorInfo().sensorHandle] = std::unique_ptr<SensorBase>(sensor);
|
|
else
|
|
ALOGE("Unable to add sensor %s as buildSensor returned null", iio_data.name.c_str());
|
|
}
|
|
|
|
} // namespace implementation
|
|
} // namespace subhal
|
|
} // namespace V2_0
|
|
} // namespace sensors
|
|
} // namespace hardware
|
|
} // namespace android
|