/* * Copyright (C) 2015 Intel Corporation * * 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 <string.h> #include <cutils/log.h> #include <stdexcept> #include <errno.h> #include <sys/epoll.h> #include "SensorsHAL.hpp" Sensor * (*SensorContext::sensorFactoryFuncs[MAX_DEVICES])(int); struct sensor_t SensorContext::sensorDescs[MAX_DEVICES]; int SensorContext::sensorsNum = 0; android::Mutex SensorContext::mutex; SensorContext::SensorContext(const hw_module_t *module) { /* create the epoll fd used to register the incoming fds */ pollFd = epoll_create(MAX_DEVICES); if (pollFd == -1) { throw std::runtime_error("Failed to create poll file descriptor"); } memset(&device, 0, sizeof(device)); device.common.tag = HARDWARE_DEVICE_TAG; device.common.version = SENSORS_DEVICE_API_VERSION_1_0; device.common.module = const_cast<hw_module_t*>(module); device.common.close = CloseWrapper; device.activate = ActivateWrapper; device.setDelay = SetDelayWrapper; device.poll = PollEventsWrapper; device.batch = BatchWrapper; device.flush = FlushWrapper; memset(sensors, 0, sizeof(Sensor *) * MAX_DEVICES); } SensorContext::~SensorContext() { int rc; for (int i = 0; i < sensorsNum; i++) { if (sensors[i]) { delete sensors[i]; sensors[i] = nullptr; } } rc = close(pollFd); if (rc != 0) { ALOGE("Cannot close poll file descriptor"); } } int SensorContext::addSensorModule(struct sensor_t *sensorDesc, Sensor * (*sensorFactoryFunc)(int)) { android::Mutex::Autolock autolock(mutex); if ((sensorDesc == nullptr) || (sensorFactoryFunc == nullptr)) { ALOGE("%s: cannot add a null sensor", __func__); return -EINVAL; } if (sensorsNum >= MAX_DEVICES) { ALOGE("%s: Cannot add more than %d sensors.", __func__, MAX_DEVICES); return -E2BIG; } sensorDesc->handle = sensorsNum; sensorDescs[sensorsNum] = *sensorDesc; sensorFactoryFuncs[sensorsNum] = sensorFactoryFunc; sensorsNum++; return 0; } int SensorContext::OpenWrapper(const struct hw_module_t *module, const char* id, struct hw_device_t **device) { SensorContext *ctx; try { ctx = new SensorContext(module); } catch (const std::runtime_error& e) { ALOGE("%s: Failed to open sensors hal. Error message: %s", __func__, e.what()); return -1; } *device = &ctx->device.common; return 0; } int SensorContext::GetSensorsListWrapper(struct sensors_module_t *module, struct sensor_t const **list) { android::Mutex::Autolock autolock(mutex); if (!list || (sensorsNum == 0)) { return 0; } *list = sensorDescs; return sensorsNum; } int SensorContext::activate(int handle, int enabled) { int rc = 0; if (enabled != 0 && enabled != 1) { ALOGE("%s: Invalid parameter", __func__); return -EINVAL; } if (handle < 0 || handle >= sensorsNum) { return -EINVAL; } try { if (enabled) { if (sensors[handle] == nullptr) { sensors[handle] = sensorFactoryFuncs[handle](pollFd); if (sensors[handle] == nullptr) { return -1; } rc = sensors[handle]->activate(handle, enabled); if (rc != 0) { goto delete_sensor; } } else { return 0; } } else { if (sensors[handle] != nullptr) { rc = sensors[handle]->activate(handle, enabled); delete sensors[handle]; sensors[handle] = nullptr; } else { return 0; } } return rc; } catch (const std::exception& e) { /* The upper layer doesn't expect exceptions. Catch them all. */ ALOGE("%s: Failed to %s sensor %d. Error message: %s.", __func__, enabled ? "activate" : "deactivate", handle, e.what()); } delete_sensor: if (sensors[handle] != nullptr) { delete sensors[handle]; sensors[handle] = nullptr; } return -1; } int SensorContext::setDelay(int handle, int64_t ns) { if (handle < 0 || handle >= sensorsNum) { return -EINVAL; } if (sensors[handle] == nullptr) { ALOGE("%s: cannot set delay. sensor %d is not activated", __func__, handle); return -EINVAL; } return sensors[handle]->setDelay(handle, ns); } int SensorContext::pollEvents(sensors_event_t *data, int count) { int nfds, i; struct epoll_event ev[MAX_DEVICES]; int returnedEvents = 0, sensorIndex = -1; /* return only when at least one event is available */ while(true) { nfds = epoll_wait(pollFd, ev, MAX_DEVICES, -1); if (nfds < 0) { ALOGE("%s: epoll_wait returned an error: %d", __func__, errno); return nfds; } { // Autolock scope android::Mutex::Autolock autolock(mutex); for(i = 0; i < nfds && returnedEvents < count; i++) { if (ev[i].events == EPOLLIN) { sensorIndex = ev[i].data.u32; if ((sensorIndex < 0) || (sensorIndex > sensorsNum)) { ALOGE("%s: Invalid sensor index", __func__); return -1; } if (sensors[sensorIndex] == nullptr) { /* The sensor might have been deactivated by another thread */ continue; } /* * The read operation might fail if the data is read by another * pollEvents call executed by another thread. */ if (sensors[sensorIndex]->readOneEvent(data + returnedEvents)) { returnedEvents++; } } } } // Autolock scope if (returnedEvents > 0) { return returnedEvents; } } } int SensorContext::batch(int handle, int flags, int64_t period_ns, int64_t timeout) { if (handle < 0 || handle >= sensorsNum) { return -EINVAL; } if (sensors[handle] == nullptr) { ALOGE("%s: cannot set delay. sensor %d is not activated", __func__, handle); return -EINVAL; } return sensors[handle]->batch(handle, flags, period_ns, timeout); } int SensorContext::flush(int handle) { if (handle < 0 || handle >= sensorsNum) { return -EINVAL; } if (sensors[handle] == nullptr) { ALOGE("%s: cannot set delay. sensor %d is not activated", __func__, handle); return -EINVAL; } /* flush doesn't apply to one-shot sensors */ if (sensorDescs[handle].flags & SENSOR_FLAG_ONE_SHOT_MODE) return -EINVAL; return sensors[handle]->flush(handle); } int SensorContext::CloseWrapper(hw_device_t *dev) { SensorContext *sensorContext = reinterpret_cast<SensorContext *>(dev); android::Mutex::Autolock autolock(mutex); if (sensorContext != nullptr) { delete sensorContext; } return 0; } int SensorContext::ActivateWrapper(sensors_poll_device_t *dev, int handle, int enabled) { android::Mutex::Autolock autolock(mutex); return reinterpret_cast<SensorContext *>(dev)->activate(handle, enabled); } int SensorContext::SetDelayWrapper(sensors_poll_device_t *dev, int handle, int64_t ns) { android::Mutex::Autolock autolock(mutex); return reinterpret_cast<SensorContext *>(dev)->setDelay(handle, ns); } int SensorContext::PollEventsWrapper(sensors_poll_device_t *dev, sensors_event_t *data, int count) { return reinterpret_cast<SensorContext *>(dev)->pollEvents(data, count); } int SensorContext::BatchWrapper(sensors_poll_device_1_t *dev, int handle, int flags, int64_t period_ns, int64_t timeout) { android::Mutex::Autolock autolock(mutex); return reinterpret_cast<SensorContext *>(dev)->batch(handle, flags, period_ns, timeout); } int SensorContext::FlushWrapper(sensors_poll_device_1_t *dev, int handle) { android::Mutex::Autolock autolock(mutex); return reinterpret_cast<SensorContext *>(dev)->flush(handle); } static struct hw_module_methods_t sensors_module_methods = { .open = SensorContext::OpenWrapper, }; struct sensors_module_t HAL_MODULE_INFO_SYM = { .common = { .tag = HARDWARE_MODULE_TAG, .version_major = 1, .version_minor = 0, .id = SENSORS_HARDWARE_MODULE_ID, .name = "Edison Sensor HAL", .author = "Intel", .methods = &sensors_module_methods, .dso = nullptr, .reserved = {0}, }, .get_sensors_list = SensorContext::GetSensorsListWrapper, .set_operation_mode = nullptr };