/* * Copyright (C) 2008 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 #include #include #include #include #include #include #include #include #include #include #include "nusensors.h" #include "LightSensor.h" #include "ProximitySensor.h" #include "MmaSensor.h" #include "AkmSensor.h" #include "GyroSensor.h" #include "PressureSensor.h" #include "TemperatureSensor.h" /*****************************************************************************/ struct sensors_poll_context_t { sensors_poll_device_1_t device; // must be first sensors_poll_context_t(); ~sensors_poll_context_t(); int activate(int handle, int enabled); int setDelay(int handle, int64_t ns); int pollEvents(sensors_event_t* data, int count); int batch(int handle, int flags, int64_t period_ns, int64_t timeout); int flush(int handle); bool getInitialized() { return mInitialized; }; private: bool mInitialized; enum { light = 0, proximity = 1, mma = 2, akm = 3, gyro = 4, pressure = 5, temperature = 6, numSensorDrivers, numFds, }; static const size_t flushPipe = numFds - 1; struct pollfd mPollFds[numFds]; int mFlushWritePipeFd; SensorBase* mSensors[numSensorDrivers]; int handleToDriver(int handle) const { switch (handle) { case ID_A: return mma; case ID_M: return akm; case ID_P: return proximity; case ID_L: return light; case ID_GY: return gyro; case ID_PR: return pressure; case ID_TMP: return temperature; } return -EINVAL; } }; /*****************************************************************************/ sensors_poll_context_t::sensors_poll_context_t() { mInitialized = false; /* Must clean this up early or else the destructor will make a mess */ memset(mSensors, 0, sizeof(mSensors)); mSensors[light] = new LightSensor(); mPollFds[light].fd = mSensors[light]->getFd(); mPollFds[light].events = POLLIN; mPollFds[light].revents = 0; mSensors[proximity] = new ProximitySensor(); mPollFds[proximity].fd = mSensors[proximity]->getFd(); mPollFds[proximity].events = POLLIN; mPollFds[proximity].revents = 0; mSensors[mma] = new MmaSensor(); mPollFds[mma].fd = mSensors[mma]->getFd(); mPollFds[mma].events = POLLIN; mPollFds[mma].revents = 0; mSensors[akm] = new AkmSensor(); mPollFds[akm].fd = mSensors[akm]->getFd(); mPollFds[akm].events = POLLIN; mPollFds[akm].revents = 0; mSensors[gyro] = new GyroSensor(); mPollFds[gyro].fd = mSensors[gyro]->getFd(); mPollFds[gyro].events = POLLIN; mPollFds[gyro].revents = 0; mSensors[pressure] = new PressureSensor(); mPollFds[pressure].fd = mSensors[pressure]->getFd(); mPollFds[pressure].events = POLLIN; mPollFds[pressure].revents = 0; mSensors[temperature] = new TemperatureSensor(); mPollFds[temperature].fd = mSensors[temperature]->getFd(); mPollFds[temperature].events = POLLIN; mPollFds[temperature].revents = 0; int flushFds[2]; int result = pipe(flushFds); LOGE_IF(result<0, "error creating flush pipe (%s)", strerror(errno)); result = fcntl(flushFds[0], F_SETFL, O_NONBLOCK); LOGE_IF(result<0, "error setting flushFds[0] access mode (%s)", strerror(errno)); result = fcntl(flushFds[1], F_SETFL, O_NONBLOCK); LOGE_IF(result<0, "error setting flushFds[1] access mode (%s)", strerror(errno)); mFlushWritePipeFd = flushFds[1]; mPollFds[flushPipe].fd = flushFds[0]; mPollFds[flushPipe].events = POLLIN; mPollFds[flushPipe].revents = 0; mInitialized = true; } sensors_poll_context_t::~sensors_poll_context_t() { for (int i=0 ; ienable(handle, enabled); } int sensors_poll_context_t::setDelay(int handle, int64_t ns) { int index = handleToDriver(handle); if (index < 0) return index; return mSensors[index]->setDelay(handle, ns); } int sensors_poll_context_t::flush(int handle) { int result; sensors_event_t flush_event_data; int index = handleToDriver(handle); if (index < 0) return index; result = mSensors[index]->isActivated(handle); if (!result) return -EINVAL; flush_event_data.sensor = 0; flush_event_data.timestamp = 0; flush_event_data.meta_data.sensor = handle; flush_event_data.meta_data.what = META_DATA_FLUSH_COMPLETE; flush_event_data.type = SENSOR_TYPE_META_DATA; flush_event_data.version = META_DATA_VERSION; result = write(mFlushWritePipeFd, &flush_event_data, sizeof(sensors_event_t)); ALOGE_IF(result<0, "error sending flush event data (%s)", strerror(errno)); return (result >= 0 ? 0 : result); } static int64_t tm_min=0; static int64_t tm_max=0; static int64_t tm_sum=0; static int64_t tm_last_print=0; static int64_t tm_count=0; static int debug_time = 0; static int debug_lvl = 0; #define NSEC_PER_SEC 1000000000 #include static inline int64_t timespec_to_ns(const struct timespec *ts) { return ((int64_t) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec; } static int64_t get_time_ns(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return timespec_to_ns(&ts); } int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count) { int nbEvents = 0; int nb, polltime = -1; // look for new events nb = poll(mPollFds, numFds, polltime); /* flush event data */ if ((count > 0) && (nb > 0)) { if (mPollFds[flushPipe].revents & POLLIN) { int n = read(mPollFds[flushPipe].fd, data, count * sizeof(sensors_event_t)); if (n < 0) { LOGE("error reading from flush pipe (%s)", strerror(errno)); return 0; } nb = n / sizeof(sensors_event_t); mPollFds[flushPipe].revents = 0; count -= nb; nbEvents += nb; data += nb; LOGI("report %d flush event\n", nbEvents); return nbEvents; } } if (nb > 0) { for (int i=0 ; count && i < numSensorDrivers ; i++) { SensorBase* const sensor(mSensors[i]); if (mPollFds[i].revents & POLLIN) { nb = 0; nb = sensor->readEvents(data, count); mPollFds[i].revents = 0; //LOGI("count = %d, nbEvents = %d, nb = %d\n", count, nbEvents, nb); if (nb > 0) { if (debug_time) { int64_t tm_cur = get_time_ns(); int64_t tm_delta = tm_cur - data->timestamp; if (tm_min==0 && tm_max==0) tm_min = tm_max = tm_delta; else if (tm_delta < tm_min) tm_min = tm_delta; else if (tm_delta > tm_max) tm_max = tm_delta; tm_sum += tm_delta; tm_count++; //LOGI("tm_count = %d\n", tm_count); if ((tm_cur-tm_last_print) > 1000000000) { LOGD("ST HAL report rate[%4lld]: %8lld, %8lld, %8lld\n", (long long)tm_count, (long long)tm_min, (long long)(tm_sum/tm_count), (long long)tm_max); tm_last_print = tm_cur; tm_min = tm_max = tm_count = tm_sum = 0; } } if (debug_lvl > 0) { for (int j=0; jactivate(handle, enabled); } static int poll__setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns) { sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev; LOGI("set delay: handle = %d, delay = %dns\n", handle, (int)ns); return ctx->setDelay(handle, ns); } static int poll__poll(struct sensors_poll_device_t *dev, sensors_event_t* data, int count) { sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev; return ctx->pollEvents(data, count); } static int poll__batch(struct sensors_poll_device_1 *dev, int handle, int flags, int64_t period_ns, int64_t timeout) { LOGI("set batch: handle = %d, period_ns = %dns, timeout = %dns\n", handle, (int)period_ns, (int)timeout); sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev; return ctx->setDelay(handle, period_ns); } static int poll__flush(struct sensors_poll_device_1 *dev, int handle) { LOGI("set flush: handle = %d\n", handle); sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev; return ctx->flush(handle); } /*****************************************************************************/ int init_nusensors(hw_module_t const* module, hw_device_t** device) { LOGD("%s\n",SENSOR_VERSION_AND_TIME); int status = -EINVAL; sensors_poll_context_t *dev = new sensors_poll_context_t(); if (!dev->getInitialized()) { LOGE("Failed to open the sensors"); return status; } memset(&dev->device, 0, sizeof(sensors_poll_device_1)); dev->device.common.tag = HARDWARE_DEVICE_TAG; dev->device.common.version = SENSORS_DEVICE_API_VERSION_1_3; dev->device.common.module = const_cast(module); dev->device.common.close = poll__close; dev->device.activate = poll__activate; dev->device.setDelay = poll__setDelay; dev->device.poll = poll__poll; /* Batch processing */ dev->device.batch = poll__batch; dev->device.flush = poll__flush; *device = &dev->device.common; status = 0; return status; }