/*! * @section LICENSE * * (C) Copyright 2011~2014 Bosch Sensortec GmbH All Rights Reserved * * 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. * *------------------------------------------------------------------------------ * Disclaimer * * Common: Bosch Sensortec products are developed for the consumer goods * industry. They may only be used within the parameters of the respective valid * product data sheet. Bosch Sensortec products are provided with the express * understanding that there is no warranty of fitness for a particular purpose. * They are not fit for use in life-sustaining, safety or security sensitive * systems or any system or device that may lead to bodily harm or property * damage if the system or device malfunctions. In addition, Bosch Sensortec * products are not fit for use in products which interact with motor vehicle * systems. The resale and/or use of products are at the purchaser's own risk * and his own responsibility. The examination of fitness for the intended use * is the sole responsibility of the Purchaser. * * The purchaser shall indemnify Bosch Sensortec from all third party claims, * including any claims for incidental, or consequential damages, arising from * any product use not covered by the parameters of the respective valid product * data sheet or not approved by Bosch Sensortec and reimburse Bosch Sensortec * for all costs in connection with such claims. * * The purchaser must monitor the market for the purchased products, * particularly with regard to product safety and inform Bosch Sensortec without * delay of all security relevant incidents. * * Engineering Samples are marked with an asterisk (*) or (e). Samples may vary * from the valid technical specifications of the product series. They are * therefore not intended or fit for resale to third parties or for use in end * products. Their sole purpose is internal client testing. The testing of an * engineering sample may in no way replace the testing of a product series. * Bosch Sensortec assumes no liability for the use of engineering samples. By * accepting the engineering samples, the Purchaser agrees to indemnify Bosch * Sensortec from all claims arising from the use of engineering samples. * * Special: This software module (hereinafter called "Software") and any * information on application-sheets (hereinafter called "Information") is * provided free of charge for the sole purpose to support your application * work. The Software and Information is subject to the following terms and * conditions: * * The Software is specifically designed for the exclusive use for Bosch * Sensortec products by personnel who have special experience and training. Do * not use this Software if you do not have the proper experience or training. * * This Software package is provided `` as is `` and without any expressed or * implied warranties, including without limitation, the implied warranties of * merchantability and fitness for a particular purpose. * * Bosch Sensortec and their representatives and agents deny any liability for * the functional impairment of this Software in terms of fitness, performance * and safety. Bosch Sensortec and their representatives and agents shall not be * liable for any direct or indirect damages or injury, except as otherwise * stipulated in mandatory applicable law. * * The Information provided is believed to be accurate and reliable. Bosch * Sensortec assumes no responsibility for the consequences of use of such * Information nor for any infringement of patents or other rights of third * parties which may result from its use. * * @file BstSensor.cpp * @date "Wed Jul 10 16:42:40 2013 +0800" * @commit "0bdd1f5" * * @brief * * @detail * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "BstSensor.h" #include "BstSensorInfo.h" #include "sensors.h" #include "TargetPlatform.h" #define GET_HANDLES_TRY_NUM 20 const int BstSensor::s_tab_id2handle[BST_SENSOR_NUM_MAX] = { BST_SENSOR_HANDLE_ACCELERATION, /* 0 */ #ifdef __USECASE_TYPE_ACCEL_ONLY__ -1, -1, -1, -1, -1, -1, -1, BST_SENSOR_HANDLE_GEST_FLIP, #else BST_SENSOR_HANDLE_MAGNETIC_FIELD, /* 1 */ BST_SENSOR_HANDLE_GYROSCOPE, /* 2 */ BST_SENSOR_HANDLE_ORIENTATION, /* 3 */ BST_SENSOR_HANDLE_GRAVITY, /* 4 */ BST_SENSOR_HANDLE_LINEAR_ACCELERATION, /* 5 */ BST_SENSOR_HANDLE_ROTATION_VECTOR, /* 6 */ BST_SENSOR_HANDLE_PRESSURE, /* 7 */ BST_SENSOR_HANDLE_GEST_FLIP, /* 8 */ #ifdef __UNSTANDARD_SENSOR_SUPPORT__ BST_SENSOR_HANDLE_SW_SIGNIFICANT_MOTION, #else -1, #endif #ifdef __UNCALIBRATED_VIRTUAL_SENSOR_SUPPORT__ BST_SENSOR_HANDLE_GAME_ROTATION_VECTOR, BST_SENSOR_HANDLE_GYROSCOPE_UNCALIBRATED, BST_SENSOR_HANDLE_MAGNETIC_FIELD_UNCALIBRATED, #endif #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_1__ BST_SENSOR_HANDLE_GEOMAGNETIC_ROTATION_VECTOR, #endif #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_0__ #ifdef __UNSTANDARD_SENSOR_SUPPORT__ BST_SENSOR_HANDLE_STEP_COUNTER, BST_SENSOR_HANDLE_STEP_DETECTOR, #else -1, -1, #endif #endif #endif -1, /* 11 */ -1 /* 12 */ }; const int BstSensor::s_tab_handle2id[BST_SENSOR_NUM_MAX] = { ID_A, /* 1 */ ID_M, /* 2 */ ID_O, /* 3 */ ID_GY, /* 4 */ -1, /* 5 */ ID_PR, /* 6 */ -1, /* 7 */ -1, /* 8 */ ID_GR, /* 9 */ ID_LA, /* 10 */ ID_RV, /* 11 */ -1, /* 12 */ ID_GEST_FLIP, /* 13 */ ID_SGM, #ifdef __UNCALIBRATED_VIRTUAL_SENSOR_SUPPORT__ ID_GRV, /* 9: game rotation vector */ ID_GYU, /* 10: gyro uncalibrated */ ID_MU, /* 11: magnetic uncalibrated */ #endif #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_1__ ID_GEOM_RV, #endif #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_0__ ID_STC, ID_STD, #endif }; int8_t handles[BST_SENSOR_NUM_MAX]; int numOfHandles = 0; int BstSensor::initStorage() { char *path = NULL; int err = 0; struct stat st; int retry = 0; path = (char *)PATH_DIR_SENSOR_STORAGE; err = access(path, F_OK); if (!err) { st.st_mode = ~S_IFDIR; err = stat(path, &st); if (!S_ISDIR(st.st_mode)) { LOGE("" "a file of the same name exists"); /* mark error explicitly for creating the dir */ err = -ENOTDIR; } } while (0 !=err && retry < 4) { LOGE("" "create path of storage, err: %d, retry count %d", err, retry); unlink(path); err = mkdir(path, 0775); if (err) { LOGE("" "error creating storage dir"); } retry++; usleep(1000); } return err; } int BstSensor::initIPC() { int err = 0; char *filename; err = initStorage(); if (err) { LOGE("initStorage return %d", err); return err; } filename = (char *)FIFO_CMD; err = access(filename, F_OK | R_OK | W_OK); if (err) { LOGE(" " "can not access %s", filename); return err; } mCmdFd = open(filename, O_RDWR); if (mCmdFd < 0) { LOGE(" " "error openning file: %s", filename); mCmdFd = -abs(errno); err = mCmdFd; return err; } filename = (char *)FIFO_DAT; err = access(filename, F_OK | R_OK | W_OK); if (err) { LOGE(" " "can not access %s", filename); return err; } data_fd = open(filename, O_RDWR); if (data_fd < 0) { LOGE(" " "error openning file: %s", filename); err = data_fd; return err; } data_name = filename; return err; } BstSensor::BstSensor() : SensorBase(NULL, NULL), mEnabled(0) { struct exchange cmd; int i = 0; int ret = 0; int fData = -1; do { if (i ++ > GET_HANDLES_TRY_NUM) { LOGE("initIPC failed:%d", ret); return; } ret = initIPC(); if (!ret) { break; } sleep(1); } while(ret); /* if handles already initialized */ if (numOfHandles > 0) { return; } fData = open(FIFO_DAT, O_RDONLY|O_NONBLOCK); if (fData == -1) { LOGE("open fifo data failed:%d", fData); return; } memset(&cmd, 0, sizeof(cmd)); cmd.magic = CHANNEL_PKT_MAGIC_LIST; while (numOfHandles == 0) { int ret = 0; ret = write(mCmdFd, &cmd, sizeof(cmd)); sleep(1); numOfHandles = read(fData, handles, BST_SENSOR_NUM_MAX); LOGD("BstSensor write ret %d read num = %d", ret, numOfHandles); if (i ++ > GET_HANDLES_TRY_NUM) { LOGE("reading num of handles time out\n"); break; } } close(fData); } BstSensor::~BstSensor() { /* mCmdFd is added by BstSensor, while * data_fd is added by SensorBase * so here, only close mCmdFd */ if (mCmdFd >= 0) { close(mCmdFd); } } int BstSensor::id2handle(int32_t id) { if ( (id <= ID_SENSOR_BASE_BST) || (id >= ID_SENSOR_END_BST) ) { return -1; } else { return BstSensor::s_tab_id2handle[id - 1 - ID_SENSOR_BASE_BST]; } } int BstSensor::handle2id(int32_t handle) { if ( (handle - 1 < 0) || (handle - 1 >= BST_SENSOR_NUM_MAX) ) { LOGE(" " "Invalid handle %d", handle); return -1; } else { return BstSensor::s_tab_handle2id[handle - 1]; } } int BstSensor::enable(int32_t id, int enable) { int err = 0; int handle; struct exchange cmd; int pos = (int)id; const struct sensor_t *s; handle = BstSensor::id2handle(id); if (-1 == handle) { return -EINVAL; } if (mCmdFd < 0) { LOGE(" " "cannot tx cmd: %s", (char *)strerror(-mCmdFd)); return mCmdFd; } enable = !!enable; s = BstSensorInfo::getSensor(id); LOGI(" " "%s sensor <%s>", enable ? "enable" : "disable", (s != NULL) ? s->name : "unknown"); cmd.magic = CHANNEL_PKT_MAGIC_CMD; cmd.command.cmd = SET_SENSOR_ACTIVE; cmd.command.code = handle; cmd.command.value = enable; cmd.ts = 0; err = write(mCmdFd, &cmd, sizeof(cmd)); err = err < (int)sizeof(cmd) ? -1 : 0; if (!err) { if (enable) { mEnabled |= (1 << pos); } else { mEnabled &= ~(1 << pos); } } return err; } int BstSensor::setDelay(int32_t id, int64_t ns) { int err = 0; int handle; struct exchange cmd; const struct sensor_t *s; handle = BstSensor::id2handle(id); if (-1 == handle) { return -EINVAL; } if (mCmdFd < 0) { LOGE(" " "cannot tx cmd: %s", (char *)strerror(-mCmdFd)); return mCmdFd; } cmd.magic = CHANNEL_PKT_MAGIC_CMD; cmd.command.cmd = SET_SENSOR_DELAY; cmd.command.code = handle; cmd.command.value = ns / SCALE_TIME_MS2NS; cmd.ts = 0; s = BstSensorInfo::getSensor(id); LOGI(" " "set delay of <%s> to %jdms", (s != NULL) ? s->name : "unknown", ns / SCALE_TIME_MS2NS); err = write(mCmdFd, &cmd, sizeof(cmd)); err = err < (int)sizeof(cmd) ? -1 : 0; if (!err) { mDelays[id - ID_SENSOR_BASE_BST] = ns / SCALE_TIME_MS2NS; } return err; } int BstSensor::readEvents(sensors_event_t *pdata, int count) { int rslt; int err; struct exchange sensor_data; int sensor; sensors_event_t *pdata_cur; #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_1__ sensors_meta_data_event_t *p_flush_finish_event; #endif if (count > 1) { count = 1; } rslt = 0; pdata_cur = pdata; while (rslt < count) { #if 0 fds.revents = 0; err = poll(&fds, 1, BST_DATA_POLL_TIMEOUT); if (err <= 0) { return rslt; } #endif err = read(data_fd, &sensor_data, sizeof(sensor_data)); if (err < (int)sizeof(sensor_data)) { LOGE(" " "bad condition, stream needs sync"); return rslt; } if (CHANNEL_PKT_MAGIC_DAT != sensor_data.magic) { LOGE(" " "discard invalid data packet from stream"); return rslt; } #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_1__ if(SENSOR_TYPE_META_DATA == sensor_data.data.type) { sensor = sensor_data.data.sensor; p_flush_finish_event = pdata_cur; p_flush_finish_event->version = META_DATA_VERSION; p_flush_finish_event->type = SENSOR_TYPE_META_DATA; p_flush_finish_event->meta_data.what = META_DATA_FLUSH_COMPLETE; p_flush_finish_event->meta_data.sensor = BstSensor::handle2id(sensor); PINFO(" " "report flush finish event for sensor id: %d", p_flush_finish_event->meta_data.sensor); goto FLUSH_FINISH_EVENT_HANDLED; } #endif sensor = sensor_data.data.sensor; pdata_cur->version = sizeof(*pdata_cur); pdata_cur->sensor = BstSensor::handle2id(sensor); pdata_cur->timestamp = sensor_data.ts; switch (pdata_cur->sensor) { case SENSORS_ACCELERATION_HANDLE: pdata_cur->acceleration.x = sensor_data.data.acceleration.x; pdata_cur->acceleration.y = sensor_data.data.acceleration.y; pdata_cur->acceleration.z = sensor_data.data.acceleration.z; pdata_cur->acceleration.status = sensor_data.data.status; pdata_cur->type = SENSOR_TYPE_ACCELEROMETER; break; case SENSORS_GYROSCOPE_HANDLE: pdata_cur->gyro.x = sensor_data.data.gyro.x; pdata_cur->gyro.y = sensor_data.data.gyro.y; pdata_cur->gyro.z = sensor_data.data.gyro.z; pdata_cur->gyro.status = sensor_data.data.status; pdata_cur->type = SENSOR_TYPE_GYROSCOPE; break; case SENSORS_MAGNETIC_FIELD_HANDLE: pdata_cur->magnetic.x = sensor_data.data.magnetic.x; pdata_cur->magnetic.y = sensor_data.data.magnetic.y; pdata_cur->magnetic.z = sensor_data.data.magnetic.z; pdata_cur->magnetic.status = sensor_data.data.status; pdata_cur->type = SENSOR_TYPE_MAGNETIC_FIELD; break; case SENSORS_ORIENTATION_HANDLE: pdata_cur->orientation.azimuth = sensor_data.data.orientation.azimuth; pdata_cur->orientation.pitch = sensor_data.data.orientation.pitch; pdata_cur->orientation.roll = sensor_data.data.orientation.roll; pdata_cur->orientation.status = sensor_data.data.status; pdata_cur->type = SENSOR_TYPE_ORIENTATION; break; case SENSORS_PRESSURE_HANDLE: pdata_cur->pressure = sensor_data.data.pressure; pdata_cur->type = SENSOR_TYPE_PRESSURE; break; case SENSORS_GRAVITY_HANDLE: pdata_cur->data[0] = sensor_data.data.data[0]; pdata_cur->data[1] = sensor_data.data.data[1]; pdata_cur->data[2] = sensor_data.data.data[2]; pdata_cur->type = SENSOR_TYPE_GRAVITY; break; case SENSORS_LINEAR_ACCEL_HANDLE: pdata_cur->data[0] = sensor_data.data.data[0]; pdata_cur->data[1] = sensor_data.data.data[1]; pdata_cur->data[2] = sensor_data.data.data[2]; pdata_cur->type = SENSOR_TYPE_LINEAR_ACCELERATION; break; case SENSORS_ROTATION_VECTOR_HANDLE: pdata_cur->data[0] = sensor_data.data.data[0]; pdata_cur->data[1] = sensor_data.data.data[1]; pdata_cur->data[2] = sensor_data.data.data[2]; #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_0__ pdata_cur->data[3] = sensor_data.data.data[3]; pdata_cur->data[4] = sensor_data.data.data[4]; #endif pdata_cur->type = SENSOR_TYPE_ROTATION_VECTOR; break; case SENSORS_GEST_FLIP_HANDLE: pdata_cur->data[0] = sensor_data.data.data[0]; pdata_cur->data[1] = sensor_data.data.data[1]; pdata_cur->data[2] = sensor_data.data.data[2]; pdata_cur->type = BST_SENSOR_TYPE_GEST_FLIP; break; #ifdef __UNCALIBRATED_VIRTUAL_SENSOR_SUPPORT__ case SENSORS_GAME_ROTATION_VECTOR_HANDLE: pdata_cur->data[0] = sensor_data.data.data[0]; pdata_cur->data[1] = sensor_data.data.data[1]; pdata_cur->data[2] = sensor_data.data.data[2]; pdata_cur->data[3] = sensor_data.data.data[3]; pdata_cur->data[4] = sensor_data.data.data[4]; pdata_cur->type = SENSOR_TYPE_GAME_ROTATION_VECTOR; break; case SENSORS_GYROSCOPE_UNCALIBRATED_HANDLE: pdata_cur->uncalibrated_gyro.x_uncalib = sensor_data.data.uncalibrated_gyro.x_uncalib; pdata_cur->uncalibrated_gyro.y_uncalib = sensor_data.data.uncalibrated_gyro.y_uncalib; pdata_cur->uncalibrated_gyro.z_uncalib = sensor_data.data.uncalibrated_gyro.z_uncalib; pdata_cur->uncalibrated_gyro.x_bias = sensor_data.data.uncalibrated_gyro.x_bias; pdata_cur->uncalibrated_gyro.y_bias = sensor_data.data.uncalibrated_gyro.y_bias; pdata_cur->uncalibrated_gyro.z_bias = sensor_data.data.uncalibrated_gyro.z_bias; pdata_cur->type = SENSOR_TYPE_GYROSCOPE_UNCALIBRATED; break; case SENSORS_MAGNETIC_UNCALIBRATED_HANDLE: pdata_cur->uncalibrated_magnetic.x_uncalib = sensor_data.data.uncalibrated_magnetic.x_uncalib; pdata_cur->uncalibrated_magnetic.y_uncalib = sensor_data.data.uncalibrated_magnetic.y_uncalib; pdata_cur->uncalibrated_magnetic.z_uncalib = sensor_data.data.uncalibrated_magnetic.z_uncalib; pdata_cur->uncalibrated_magnetic.x_bias = sensor_data.data.uncalibrated_magnetic.x_bias; pdata_cur->uncalibrated_magnetic.y_bias = sensor_data.data.uncalibrated_magnetic.y_bias; pdata_cur->uncalibrated_magnetic.z_bias = sensor_data.data.uncalibrated_magnetic.z_bias; pdata_cur->type = SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED; break; #endif #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_1__ case SENSORS_GEOMAGNETIC_ROTATION_VECTOR_HANDLE: pdata_cur->data[0] = sensor_data.data.data[0]; pdata_cur->data[1] = sensor_data.data.data[1]; pdata_cur->data[2] = sensor_data.data.data[2]; pdata_cur->data[3] = sensor_data.data.data[3]; pdata_cur->data[4] = sensor_data.data.data[4]; pdata_cur->type = SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR; break; #endif #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_0__ case SENSORS_STEP_COUNTER_HANDLE: #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_1__ pdata_cur->u64.step_counter = sensor_data.data.step_counter; pdata_cur->u64.data[0] = sensor_data.data.step_counter; pdata_cur->u64.data[1] = 0; pdata_cur->u64.data[2] = 0; #else pdata_cur->step_counter = sensor_data.data.step_counter; pdata_cur->data[0] = sensor_data.data.step_counter; pdata_cur->data[1] = 0; pdata_cur->data[2] = 0; #endif pdata_cur->type = SENSOR_TYPE_STEP_COUNTER; break; case SENSORS_STEP_DETECTOR_HANDLE: pdata_cur->data[0] = sensor_data.data.data[0]; pdata_cur->data[1] = 0; pdata_cur->data[2] = 0; pdata_cur->type = SENSOR_TYPE_STEP_DETECTOR; break; #endif case SENSORS_SW_SIGNIFICANT_MOTION_HANDLE: pdata_cur->data[0] = sensor_data.data.data[0]; pdata_cur->data[1] = sensor_data.data.data[1]; pdata_cur->data[2] = sensor_data.data.data[2]; pdata_cur->type = BSTEXT_SENSOR_TYPE_SW_SGM; break; default: LOGE(" " "Invalid data pkt"); return rslt; } #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_1__ FLUSH_FINISH_EVENT_HANDLED: #endif rslt++; pdata_cur++; } return rslt; } int BstSensor::getSensorList(struct sensor_t *list, int len) { int num = 0; int i, j; int handlerID = 0; UNUSED_PARAM(len); for (i = 0; i < numOfHandles; i++) { for (j = 0; j < NUM_SENSORS; j++) { handlerID = id2handle(BstSensorInfo::g_bst_sensor_list[j].handle); if (handles[i] == handlerID) { memcpy(list++, &BstSensorInfo::g_bst_sensor_list[j], sizeof(struct sensor_t)); num++; } } } LOGI(" " "BST HAL version: %s", get_hal_version()); LOGI("build date : %s", get_build_date()); return num; } #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_1__ int BstSensor::flush(int id) { int err = 0; int ret = 0; struct exchange cmd; const struct sensor_t *s; int handle; if (mCmdFd < 0) { PERR(" " "cannot tx cmd: %s", (char *)strerror(-mCmdFd)); return mCmdFd; } handle = BstSensor::id2handle(id); if (-1 == handle) { PERR(" " "flush: cannot get handle for id %d", id); return 0; } cmd.magic = CHANNEL_PKT_MAGIC_CMD; cmd.command.cmd = SET_SENSOR_FLUSH; cmd.command.code = handle; s = BstSensorInfo::getSensor(id); PINFO(" " "flush <%s>, id: %d", (s != NULL) ? s->name : "unknown", id); err = write(mCmdFd, &cmd, sizeof(cmd)); ret = err < (int)sizeof(cmd) ? -1 : 0; return ret; } int BstSensor::batch(int id, int flags, int64_t period_ns, int64_t timeout) { int ret = 0; UNUSED_PARAM(flags); UNUSED_PARAM(timeout); ret = BstSensor::setDelay(id, period_ns); return ret; } #endif