sensors_mpl.cpp revision 6a4d9a48ffde124c498496f6dae1e77c2cae6864
1/*
2* Copyright (C) 2012 Invensense, Inc.
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8*      http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
16
17#define FUNC_LOG LOGV("%s", __PRETTY_FUNCTION__)
18
19#include <hardware/sensors.h>
20#include <fcntl.h>
21#include <errno.h>
22#include <dirent.h>
23#include <math.h>
24#include <poll.h>
25#include <pthread.h>
26#include <stdlib.h>
27
28#include <linux/input.h>
29
30#include <utils/Atomic.h>
31#include <utils/Log.h>
32
33#include "sensors.h"
34#include "MPLSensor.h"
35
36/*****************************************************************************/
37/* The SENSORS Module */
38
39#ifdef ENABLE_DMP_SCREEN_AUTO_ROTATION
40#define LOCAL_SENSORS (MPLSensor::NUMSENSORS + 1)
41#else
42#define LOCAL_SENSORS MPLSensor::NUMSENSORS
43#endif
44
45/* Vendor-defined Accel Load Calibration File Method
46* @param[out] Accel bias, length 3.  In HW units scaled by 2^16 in body frame
47* @return '0' for a successful load, '1' otherwise
48* example: int AccelLoadConfig(long* offset);
49* End of Vendor-defined Accel Load Cal Method
50*/
51
52static struct sensor_t sSensorList[LOCAL_SENSORS];
53static int sensors = (sizeof(sSensorList) / sizeof(sensor_t));
54
55static int open_sensors(const struct hw_module_t* module, const char* id,
56                        struct hw_device_t** device);
57
58static int sensors__get_sensors_list(struct sensors_module_t* module,
59                                     struct sensor_t const** list)
60{
61    *list = sSensorList;
62    return sensors;
63}
64
65static struct hw_module_methods_t sensors_module_methods = {
66        open: open_sensors
67};
68
69struct sensors_module_t HAL_MODULE_INFO_SYM = {
70        common: {
71                tag: HARDWARE_MODULE_TAG,
72                version_major: 1,
73                version_minor: 0,
74                id: SENSORS_HARDWARE_MODULE_ID,
75                name: "Invensense module",
76                author: "Invensense Inc.",
77                methods: &sensors_module_methods,
78        },
79        get_sensors_list: sensors__get_sensors_list,
80};
81
82struct sensors_poll_context_t {
83    struct sensors_poll_device_t device; // must be first
84
85    sensors_poll_context_t();
86    ~sensors_poll_context_t();
87    int activate(int handle, int enabled);
88    int setDelay(int handle, int64_t ns);
89    int pollEvents(sensors_event_t* data, int count);
90
91private:
92    enum {
93        mpl = 0,
94        compass,
95        dmpOrient,
96        numSensorDrivers,   // wake pipe goes here
97        numFds,
98    };
99
100    struct pollfd mPollFds[numSensorDrivers];
101    SensorBase *mSensor;
102    CompassSensor *mCompassSensor;
103};
104
105/******************************************************************************/
106
107sensors_poll_context_t::sensors_poll_context_t() {
108    VFUNC_LOG;
109
110    mCompassSensor = new CompassSensor();
111    MPLSensor *mplSensor = new MPLSensor(mCompassSensor);
112
113   /* For Vendor-defined Accel Calibration File Load
114    * Use the Following Constructor and Pass Your Load Cal File Function
115    *
116	* MPLSensor *mplSensor = new MPLSensor(mCompassSensor, AccelLoadConfig);
117	*/
118
119    // setup the callback object for handing mpl callbacks
120    setCallbackObject(mplSensor);
121
122    // populate the sensor list
123    sensors =
124            mplSensor->populateSensorList(sSensorList, sizeof(sSensorList));
125
126    mSensor = mplSensor;
127    mPollFds[mpl].fd = mSensor->getFd();
128    mPollFds[mpl].events = POLLIN;
129    mPollFds[mpl].revents = 0;
130
131    mPollFds[compass].fd = mCompassSensor->getFd();
132    mPollFds[compass].events = POLLIN;
133    mPollFds[compass].revents = 0;
134
135    mPollFds[dmpOrient].fd = ((MPLSensor*) mSensor)->getDmpOrientFd();
136    mPollFds[dmpOrient].events = POLLPRI;
137    mPollFds[dmpOrient].revents = 0;
138}
139
140sensors_poll_context_t::~sensors_poll_context_t() {
141    FUNC_LOG;
142    delete mSensor;
143    delete mCompassSensor;
144}
145
146int sensors_poll_context_t::activate(int handle, int enabled) {
147    FUNC_LOG;
148    return mSensor->enable(handle, enabled);
149}
150
151int sensors_poll_context_t::setDelay(int handle, int64_t ns)
152{
153    FUNC_LOG;
154    return mSensor->setDelay(handle, ns);
155}
156
157int sensors_poll_context_t::pollEvents(sensors_event_t *data, int count)
158{
159    VHANDLER_LOG;
160
161    int nbEvents = 0;
162    int nb, polltime = -1;
163
164    // look for new events
165    nb = poll(mPollFds, numSensorDrivers, polltime);
166
167    if (nb > 0) {
168        for (int i = 0; count && i < numSensorDrivers; i++) {
169            if (mPollFds[i].revents & (POLLIN | POLLPRI)) {
170                nb = 0;
171                if (i == mpl) {
172                    nb = mSensor->readEvents(NULL, 0);
173                    mPollFds[i].revents = 0;
174                }
175                else if (i == compass) {
176                    nb = ((MPLSensor*) mSensor)->readCompassEvents(NULL, 0);
177                    mPollFds[i].revents = 0;
178                }
179            }
180        }
181        nb = ((MPLSensor*) mSensor)->executeOnData(data, count);
182        if (nb > 0) {
183            count -= nb;
184            nbEvents += nb;
185            data += nb;
186        }
187
188        if (mPollFds[dmpOrient].revents & (POLLIN | POLLPRI)) {
189            nb = ((MPLSensor*) mSensor)->readDmpOrientEvents(data, count);
190            mPollFds[dmpOrient].revents= 0;
191            if (isDmpScreenAutoRotationEnabled() && nb > 0) {
192                count -= nb;
193                nbEvents += nb;
194                data += nb;
195            }
196        }
197    }
198
199    return nbEvents;
200}
201
202/******************************************************************************/
203
204static int poll__close(struct hw_device_t *dev)
205{
206    FUNC_LOG;
207    sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
208    if (ctx) {
209        delete ctx;
210    }
211    return 0;
212}
213
214static int poll__activate(struct sensors_poll_device_t *dev,
215                          int handle, int enabled)
216{
217    sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
218    return ctx->activate(handle, enabled);
219}
220
221static int poll__setDelay(struct sensors_poll_device_t *dev,
222                          int handle, int64_t ns)
223{
224    sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
225    int s= ctx->setDelay(handle, ns);
226    return s;
227}
228
229static int poll__poll(struct sensors_poll_device_t *dev,
230                      sensors_event_t* data, int count)
231{
232    sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
233    return ctx->pollEvents(data, count);
234}
235
236/******************************************************************************/
237
238/** Open a new instance of a sensor device using name */
239static int open_sensors(const struct hw_module_t* module, const char* id,
240                        struct hw_device_t** device)
241{
242    FUNC_LOG;
243    int status = -EINVAL;
244    sensors_poll_context_t *dev = new sensors_poll_context_t();
245
246    memset(&dev->device, 0, sizeof(sensors_poll_device_t));
247
248    dev->device.common.tag = HARDWARE_DEVICE_TAG;
249    dev->device.common.version  = 0;
250    dev->device.common.module   = const_cast<hw_module_t*>(module);
251    dev->device.common.close    = poll__close;
252    dev->device.activate        = poll__activate;
253    dev->device.setDelay        = poll__setDelay;
254    dev->device.poll            = poll__poll;
255
256    *device = &dev->device.common;
257    status = 0;
258
259    return status;
260}
261