1/*
2 * Copyright (C) 2015 The Android Open Source Project
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#ifndef HUB_CONNECTION_H_
18
19#define HUB_CONNECTION_H_
20
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <poll.h>
25
26#include <utils/Errors.h>
27#include <utils/Mutex.h>
28#include <utils/Thread.h>
29
30#include "activityeventhandler.h"
31#include "directchannel.h"
32#include "eventnums.h"
33#include "halIntf.h"
34#include "hubdefs.h"
35#include "ring.h"
36
37#ifdef USE_SENSORSERVICE_TO_GET_FIFO
38#include <thread>
39#endif
40#include <unordered_map>
41
42#define WAKELOCK_NAME "sensorHal"
43
44#define ACCEL_BIAS_TAG     "accel"
45#define ACCEL_SW_BIAS_TAG  "accel_sw"
46#define GYRO_BIAS_TAG      "gyro"
47#define GYRO_OTC_DATA_TAG  "gyro_otc"
48#define GYRO_SW_BIAS_TAG   "gyro_sw"
49#define MAG_BIAS_TAG       "mag"
50
51namespace android {
52
53struct HubConnection : public Thread {
54    static HubConnection *getInstance();
55
56    status_t initCheck() const;
57
58    enum ProximitySensorType {
59        PROXIMITY_UNKNOWN,
60        PROXIMITY_ROHM,
61        PROXIMITY_AMS,
62    };
63
64    // Blocks until it can return a status
65    status_t getAliveCheck();
66
67    virtual bool threadLoop();
68
69    void queueActivate(int handle, bool enable);
70    void queueSetDelay(int handle, nsecs_t delayNs);
71    void queueBatch(int handle, nsecs_t sampling_period_ns,
72            nsecs_t max_report_latency_ns);
73    void queueFlush(int handle);
74    void queueData(int handle, void *data, size_t length);
75
76    void setOperationParameter(const additional_info_event_t &info);
77
78    bool isWakeEvent(int32_t sensor);
79    void releaseWakeLockIfAppropriate();
80    ssize_t getWakeEventCount();
81    ssize_t decrementWakeEventCount();
82
83    //TODO: factor out event ring buffer functionality into a separate class
84    ssize_t read(sensors_event_t *ev, size_t size);
85    ssize_t write(const sensors_event_t *ev, size_t n);
86
87    void setActivityCallback(ActivityEventHandler *eventHandler);
88
89    void saveSensorSettings() const;
90
91    void setRawScale(float scaleAccel, float scaleMag) {
92        mScaleAccel = scaleAccel;
93        mScaleMag = scaleMag;
94    }
95
96protected:
97    HubConnection();
98    virtual ~HubConnection();
99
100    virtual void onFirstRef();
101
102private:
103    typedef uint32_t rate_q10_t;  // q10 means lower 10 bits are for fractions
104
105    bool mWakelockHeld;
106    int32_t mWakeEventCount;
107
108    void protectIfWakeEvent(int32_t sensor);
109
110    static inline uint64_t period_ns_to_frequency_q10(nsecs_t period_ns) {
111        return 1024000000000ULL / period_ns;
112    }
113
114    static inline nsecs_t frequency_q10_to_period_ns(uint64_t frequency_q10) {
115        if (frequency_q10)
116            return 1024000000000LL / frequency_q10;
117        else
118            return (nsecs_t)0;
119    }
120
121    static inline uint64_t frequency_to_frequency_q10(float frequency) {
122        return period_ns_to_frequency_q10(static_cast<nsecs_t>(1e9f/frequency));
123    }
124
125    enum
126    {
127        CONFIG_CMD_DISABLE      = 0,
128        CONFIG_CMD_ENABLE       = 1,
129        CONFIG_CMD_FLUSH        = 2,
130        CONFIG_CMD_CFG_DATA     = 3,
131        CONFIG_CMD_CALIBRATE    = 4,
132    };
133
134    struct ConfigCmd
135    {
136        uint32_t evtType;
137        uint64_t latency;
138        rate_q10_t rate;
139        uint8_t sensorType;
140        uint8_t cmd;
141        uint16_t flags;
142        uint8_t data[];
143    } __attribute__((packed));
144
145    struct MsgCmd
146    {
147        uint32_t evtType;
148        struct HostHubRawPacket msg;
149    } __attribute__((packed));
150
151    struct SensorState {
152        uint64_t latency;
153        rate_q10_t rate;
154        uint8_t sensorType;
155        uint8_t alt;
156        uint8_t flushCnt;
157        bool enable;
158    };
159
160    struct FirstSample
161    {
162        uint8_t numSamples;
163        uint8_t numFlushes;
164        uint8_t highAccuracy : 1;
165        uint8_t biasPresent : 1;
166        uint8_t biasSample : 6;
167        uint8_t pad;
168    };
169
170    struct RawThreeAxisSample
171    {
172        uint32_t deltaTime;
173        int16_t ix, iy, iz;
174    } __attribute__((packed));
175
176    struct ThreeAxisSample
177    {
178        uint32_t deltaTime;
179        float x, y, z;
180    } __attribute__((packed));
181
182    struct OneAxisSample
183    {
184        uint32_t deltaTime;
185        union
186        {
187            float fdata;
188            uint32_t idata;
189        };
190    } __attribute__((packed));
191
192    // The following structure should match struct HostIntfDataBuffer found in
193    // firmware/inc/hostIntf.h
194    struct nAxisEvent
195    {
196        uint32_t evtType;
197        union
198        {
199            struct
200            {
201                uint64_t referenceTime;
202                union
203                {
204                    struct FirstSample firstSample;
205                    struct OneAxisSample oneSamples[];
206                    struct RawThreeAxisSample rawThreeSamples[];
207                    struct ThreeAxisSample threeSamples[];
208                };
209            };
210            uint8_t buffer[];
211        };
212    } __attribute__((packed));
213
214    static Mutex sInstanceLock;
215    static HubConnection *sInstance;
216
217    // This lock is used for synchronization between the write thread (from
218    // sensorservice) and the read thread polling from the nanohub driver.
219    Mutex mLock;
220
221    RingBuffer mRing;
222
223    ActivityEventHandler *mActivityEventHandler;
224
225    float mMagBias[3];
226    uint8_t mMagAccuracy;
227    uint8_t mMagAccuracyRestore;
228
229    float mGyroBias[3], mAccelBias[3];
230    GyroOtcData mGyroOtcData;
231
232    float mScaleAccel, mScaleMag;
233
234    SensorState mSensorState[NUM_COMMS_SENSORS_PLUS_1];
235
236    uint64_t mStepCounterOffset;
237    uint64_t mLastStepCount;
238
239    int mFd;
240    int mInotifyPollIndex;
241    struct pollfd mPollFds[4];
242    int mNumPollFds;
243
244    sensors_event_t *initEv(sensors_event_t *ev, uint64_t timestamp, uint32_t type, uint32_t sensor);
245    uint8_t magAccuracyUpdate(sensors_vec_t *sv);
246    void processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct OneAxisSample *sample, bool highAccuracy);
247    void processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct RawThreeAxisSample *sample, bool highAccuracy);
248    void processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct ThreeAxisSample *sample, bool highAccuracy);
249    void postOsLog(uint8_t *buf, ssize_t len);
250    void processAppData(uint8_t *buf, ssize_t len);
251    ssize_t processBuf(uint8_t *buf, size_t len);
252
253    inline bool isValidHandle(int handle) {
254        return handle >= 0
255            && handle < NUM_COMMS_SENSORS_PLUS_1
256            && mSensorState[handle].sensorType;
257    }
258
259    void initConfigCmd(struct ConfigCmd *cmd, int handle);
260
261    void queueDataInternal(int handle, void *data, size_t length);
262
263    void discardInotifyEvent();
264    void waitOnNanohubLock();
265
266    void initNanohubLock();
267
268    void restoreSensorState();
269    void sendCalibrationOffsets();
270
271#ifdef USE_SENSORSERVICE_TO_GET_FIFO
272    // Enable SCHED_FIFO priority for main thread
273    std::thread mEnableSchedFifoThread;
274#endif
275    static void enableSchedFifoMode(sp<HubConnection> hub);
276
277#ifdef LID_STATE_REPORTING_ENABLED
278    int mUinputFd;
279
280    status_t initializeUinputNode();
281    void sendFolioEvent(int32_t data);
282#endif  // LID_STATE_REPORTING_ENABLED
283
284#ifdef USB_MAG_BIAS_REPORTING_ENABLED
285    int mMagBiasPollIndex;
286    float mUsbMagBias;
287
288    void queueUsbMagBias();
289#endif  // USB_MAG_BIAS_REPORTING_ENABLED
290
291#ifdef DOUBLE_TOUCH_ENABLED
292    int mDoubleTouchPollIndex;
293#endif  // DOUBLE_TOUCH_ENABLED
294
295    // Direct report functions
296public:
297    int addDirectChannel(const struct sensors_direct_mem_t *mem);
298    int removeDirectChannel(int channel_handle);
299    int configDirectReport(int sensor_handle, int channel_handle, int rate_level);
300    bool isDirectReportSupported() const;
301private:
302    void sendDirectReportEvent(const sensors_event_t *nev, size_t n);
303    void mergeDirectReportRequest(struct ConfigCmd *cmd, int handle);
304#ifdef DIRECT_REPORT_ENABLED
305    int stopAllDirectReportOnChannel(
306            int channel_handle, std::vector<int32_t> *unstoppedSensors);
307    Mutex mDirectChannelLock;
308    //sensor_handle=>(channel_handle, rate_level)
309    std::unordered_map<int32_t, std::unordered_map<int32_t, int32_t> > mSensorToChannel;
310    //channel_handle=>ptr of Channel obj
311    std::unordered_map<int32_t, std::unique_ptr<DirectChannelBase>> mDirectChannel;
312    int32_t mDirectChannelHandle;
313#endif
314
315    DISALLOW_EVIL_CONSTRUCTORS(HubConnection);
316};
317
318}  // namespace android
319
320#endif  // HUB_CONNECTION_H_
321