| /* |
| * 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 |
| }; |