/* * Copyright (C) 2010 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 "SensorDevice.h" #include "SensorService.h" #ifdef SYSFS_LIGHT_SENSOR #include #endif namespace android { // --------------------------------------------------------------------------- ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice) #ifdef SYSFS_LIGHT_SENSOR #define DUMMY_ALS_HANDLE 0xdeadbeef static ssize_t addDummyLightSensor(sensor_t const **list, ssize_t count) { struct sensor_t dummy_light = { name : "CyanogenMod dummy light sensor", vendor : "CyanogenMod", version : 1, handle : DUMMY_ALS_HANDLE, type : SENSOR_TYPE_LIGHT, maxRange : 20, resolution : 0.1, power : 20, }; void * new_list = malloc((count+1)*sizeof(sensor_t)); new_list = memcpy(new_list, *list, count*sizeof(sensor_t)); ((sensor_t *)new_list)[count] = dummy_light; *list = (sensor_t const *)new_list; count++; return count; } #endif SensorDevice::SensorDevice() : mSensorDevice(0), mSensorModule(0) { status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, (hw_module_t const**)&mSensorModule); ALOGE_IF(err, "couldn't load %s module (%s)", SENSORS_HARDWARE_MODULE_ID, strerror(-err)); if (mSensorModule) { err = sensors_open(&mSensorModule->common, &mSensorDevice); ALOGE_IF(err, "couldn't open device for module %s (%s)", SENSORS_HARDWARE_MODULE_ID, strerror(-err)); if (mSensorDevice) { sensor_t const* list; ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list); #ifdef SYSFS_LIGHT_SENSOR count = addDummyLightSensor(&list, count); #endif mActivationCount.setCapacity(count); Info model; for (size_t i=0 ; iactivate(mSensorDevice, list[i].handle, 0); } } } } void SensorDevice::dump(String8& result, char* buffer, size_t SIZE) { if (!mSensorModule) return; sensor_t const* list; ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list); snprintf(buffer, SIZE, "%d h/w sensors:\n", int(count)); result.append(buffer); Mutex::Autolock _l(mLock); for (size_t i=0 ; iget_sensors_list(mSensorModule, list); #ifdef SYSFS_LIGHT_SENSOR return addDummyLightSensor(list, count); #else return count; #endif } status_t SensorDevice::initCheck() const { return mSensorDevice && mSensorModule ? NO_ERROR : NO_INIT; } ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) { if (!mSensorDevice) return NO_INIT; ssize_t c; do { c = mSensorDevice->poll(mSensorDevice, buffer, count); } while (c == -EINTR); return c; } status_t SensorDevice::activate(void* ident, int handle, int enabled) { if (!mSensorDevice) return NO_INIT; status_t err(NO_ERROR); bool actuateHardware = false; #ifdef SYSFS_LIGHT_SENSOR if (handle == DUMMY_ALS_HANDLE) { int nwr, ret, fd; char value[2]; fd = open(SYSFS_LIGHT_SENSOR, O_RDWR); if(fd < 0) return -ENODEV; nwr = snprintf(value, 2, "%d\n", enabled ? 1 : 0); write(fd, value, nwr); close(fd); return 0; } #endif Info& info( mActivationCount.editValueFor(handle) ); ALOGD_IF(DEBUG_CONNECTIONS, "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%d", ident, handle, enabled, info.rates.size()); if (enabled) { Mutex::Autolock _l(mLock); ALOGD_IF(DEBUG_CONNECTIONS, "... index=%ld", info.rates.indexOfKey(ident)); if (info.rates.indexOfKey(ident) < 0) { info.rates.add(ident, DEFAULT_EVENTS_PERIOD); if (info.rates.size() == 1) { actuateHardware = true; } } else { // sensor was already activated for this ident } } else { Mutex::Autolock _l(mLock); ALOGD_IF(DEBUG_CONNECTIONS, "... index=%ld", info.rates.indexOfKey(ident)); ssize_t idx = info.rates.removeItem(ident); if (idx >= 0) { if (info.rates.size() == 0) { actuateHardware = true; } } else { // sensor wasn't enabled for this ident } } if (actuateHardware) { ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w"); err = mSensorDevice->activate(mSensorDevice, handle, enabled); ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle, strerror(-err)); } { // scope for the lock Mutex::Autolock _l(mLock); nsecs_t ns = info.selectDelay(); mSensorDevice->setDelay(mSensorDevice, handle, ns); } return err; } status_t SensorDevice::setDelay(void* ident, int handle, int64_t ns) { if (!mSensorDevice) return NO_INIT; Mutex::Autolock _l(mLock); Info& info( mActivationCount.editValueFor(handle) ); status_t err = info.setDelayForIdent(ident, ns); if (err < 0) return err; ns = info.selectDelay(); return mSensorDevice->setDelay(mSensorDevice, handle, ns); } // --------------------------------------------------------------------------- status_t SensorDevice::Info::setDelayForIdent(void* ident, int64_t ns) { ssize_t index = rates.indexOfKey(ident); if (index < 0) { ALOGE("Info::setDelayForIdent(ident=%p, ns=%lld) failed (%s)", ident, ns, strerror(-index)); return BAD_INDEX; } rates.editValueAt(index) = ns; return NO_ERROR; } nsecs_t SensorDevice::Info::selectDelay() { nsecs_t ns = rates.valueAt(0); for (size_t i=1 ; i