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 <list>
31 
32 #include "directchannel.h"
33 #include "eventnums.h"
34 #include "halIntf.h"
35 #include "hubdefs.h"
36 #include "ring.h"
37 
38 #include <unordered_map>
39 
40 #define WAKELOCK_NAME "sensorHal"
41 
42 #define ACCEL_BIAS_TAG     "accel"
43 #define ACCEL_SW_BIAS_TAG  "accel_sw"
44 #define GYRO_BIAS_TAG      "gyro"
45 #define GYRO_OTC_DATA_TAG  "gyro_otc"
46 #define GYRO_SW_BIAS_TAG   "gyro_sw"
47 #define MAG_BIAS_TAG       "mag"
48 
49 #define MAX_ALTERNATES     2
50 
51 namespace android {
52 
53 struct 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     void releaseWakeLockIfAppropriate();
79 
80     //TODO: factor out event ring buffer functionality into a separate class
81     ssize_t read(sensors_event_t *ev, size_t size);
82     ssize_t write(const sensors_event_t *ev, size_t n);
83 
84     void saveSensorSettings() const;
85 
setRawScaleHubConnection86     void setRawScale(float scaleAccel, float scaleMag) {
87         mScaleAccel = scaleAccel;
88         mScaleMag = scaleMag;
89     }
90 
91     void setLeftyMode(bool enable);
92 
93 protected:
94     HubConnection();
95     virtual ~HubConnection();
96 
97     virtual void onFirstRef();
98 
99 private:
100     typedef uint32_t rate_q10_t;  // q10 means lower 10 bits are for fractions
101 
102     bool mWakelockHeld;
103     int32_t mWakeEventCount;
104 
105     void protectIfWakeEventLocked(int32_t sensor);
106     ssize_t decrementIfWakeEventLocked(int32_t sensor);
107 
period_ns_to_frequency_q10HubConnection108     static inline uint64_t period_ns_to_frequency_q10(nsecs_t period_ns) {
109         return 1024000000000ULL / period_ns;
110     }
111 
frequency_q10_to_period_nsHubConnection112     static inline nsecs_t frequency_q10_to_period_ns(uint64_t frequency_q10) {
113         if (frequency_q10)
114             return 1024000000000LL / frequency_q10;
115         else
116             return (nsecs_t)0;
117     }
118 
frequency_to_frequency_q10HubConnection119     static inline uint64_t frequency_to_frequency_q10(float frequency) {
120         return period_ns_to_frequency_q10(static_cast<nsecs_t>(1e9f/frequency));
121     }
122 
123     enum
124     {
125         CONFIG_CMD_DISABLE      = 0,
126         CONFIG_CMD_ENABLE       = 1,
127         CONFIG_CMD_FLUSH        = 2,
128         CONFIG_CMD_CFG_DATA     = 3,
129         CONFIG_CMD_CALIBRATE    = 4,
130     };
131 
132     struct ConfigCmd
133     {
134         uint32_t evtType;
135         uint64_t latency;
136         rate_q10_t rate;
137         uint8_t sensorType;
138         uint8_t cmd;
139         uint16_t flags;
140         uint8_t data[];
141     } __attribute__((packed));
142 
143     struct MsgCmd
144     {
145         uint32_t evtType;
146         struct HostHubRawPacket msg;
147     } __attribute__((packed));
148 
149     struct LeftyState
150     {
151         bool accel; // Process wrist-aware accel samples as lefty mode
152         bool gyro; // Process wrist-aware gyro samples as lefty mode
153         bool hub; // Sensor hub is currently operating in lefty mode
154     };
155 
156     struct Flush
157     {
158         int handle;
159         uint8_t count;
160 
161         // Used to synchronize the transition in and out of
162         // lefty mode between nanohub and the AP.
163         bool internal;
164     };
165 
166     struct SensorState {
167         uint64_t latency;
168         uint64_t lastTimestamp;
169         uint64_t desiredTSample;
170         rate_q10_t rate;
171         uint8_t sensorType;
172         uint8_t primary;
173         uint8_t alt[MAX_ALTERNATES];
174         bool enable;
175     };
176 
177     struct FirstSample
178     {
179         uint8_t numSamples;
180         uint8_t numFlushes;
181         uint8_t highAccuracy : 1;
182         uint8_t biasPresent : 1;
183         uint8_t biasSample : 6;
184         uint8_t pad;
185     };
186 
187     struct RawThreeAxisSample
188     {
189         uint32_t deltaTime;
190         int16_t ix, iy, iz;
191     } __attribute__((packed));
192 
193     struct ThreeAxisSample
194     {
195         uint32_t deltaTime;
196         float x, y, z;
197     } __attribute__((packed));
198 
199     struct OneAxisSample
200     {
201         uint32_t deltaTime;
202         union
203         {
204             float fdata;
205             uint32_t idata;
206         };
207     } __attribute__((packed));
208 
209     // The following structure should match struct HostIntfDataBuffer found in
210     // firmware/inc/hostIntf.h
211     struct nAxisEvent
212     {
213         uint32_t evtType;
214         union
215         {
216             struct
217             {
218                 uint64_t referenceTime;
219                 union
220                 {
221                     struct FirstSample firstSample;
222                     struct OneAxisSample oneSamples[];
223                     struct RawThreeAxisSample rawThreeSamples[];
224                     struct ThreeAxisSample threeSamples[];
225                 };
226             };
227             uint8_t buffer[];
228         };
229     } __attribute__((packed));
230 
231     static Mutex sInstanceLock;
232     static HubConnection *sInstance;
233 
234     // This lock is used for synchronization between the write thread (from
235     // sensorservice) and the read thread polling from the nanohub driver.
236     Mutex mLock;
237 
238     RingBuffer mRing;
239     int32_t mWriteFailures;
240 
241     float mMagBias[3];
242     uint8_t mMagAccuracy;
243     uint8_t mMagAccuracyRestore;
244 
245     float mGyroBias[3], mAccelBias[3], mAccelEnabledBias[3];
246     bool mAccelEnabledBiasStored;
247     GyroOtcData mGyroOtcData;
248 
249     float mScaleAccel, mScaleMag;
250 
251     LeftyState mLefty;
252 
253     SensorState mSensorState[NUM_COMMS_SENSORS_PLUS_1];
254     std::list<struct Flush> mFlushesPending[NUM_COMMS_SENSORS_PLUS_1];
255 
256     uint64_t mStepCounterOffset;
257     uint64_t mLastStepCount;
258 
259     int mFd;
260     int mInotifyPollIndex;
261     struct pollfd mPollFds[4];
262     int mNumPollFds;
263 
264     sensors_event_t *initEv(sensors_event_t *ev, uint64_t timestamp, uint32_t type, uint32_t sensor);
265     uint8_t magAccuracyUpdate(sensors_vec_t *sv);
266     void processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct OneAxisSample *sample, bool highAccuracy);
267     void processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct RawThreeAxisSample *sample, bool highAccuracy);
268     void processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct ThreeAxisSample *sample, bool highAccuracy);
269     void postOsLog(uint8_t *buf, ssize_t len);
270     void processAppData(uint8_t *buf, ssize_t len);
271     ssize_t processBuf(uint8_t *buf, size_t len);
272 
isValidHandleHubConnection273     inline bool isValidHandle(int handle) {
274         return handle >= 0
275             && handle < NUM_COMMS_SENSORS_PLUS_1
276             && mSensorState[handle].sensorType;
277     }
278 
279     ssize_t sendCmd(const void *buf, size_t count);
280     void initConfigCmd(struct ConfigCmd *cmd, int handle);
281 
282     void queueFlushInternal(int handle, bool internal);
283 
284     void queueDataInternal(int handle, void *data, size_t length);
285 
286     void discardInotifyEvent();
287     void waitOnNanohubLock();
288 
289     void initNanohubLock();
290 
291     void restoreSensorState();
292     void sendCalibrationOffsets();
293 
294     // Enable SCHED_FIFO priority for main thread
295     void enableSchedFifoMode();
296 
297 #ifdef LID_STATE_REPORTING_ENABLED
298     int mUinputFd;
299 
300     status_t initializeUinputNode();
301     void sendFolioEvent(int32_t data);
302 #endif  // LID_STATE_REPORTING_ENABLED
303 
304 #ifdef USB_MAG_BIAS_REPORTING_ENABLED
305     int mMagBiasPollIndex;
306     float mUsbMagBias;
307 
308     void queueUsbMagBias();
309 #endif  // USB_MAG_BIAS_REPORTING_ENABLED
310 
311 #ifdef DOUBLE_TOUCH_ENABLED
312     int mDoubleTouchPollIndex;
313 #endif  // DOUBLE_TOUCH_ENABLED
314 
315     // Direct report functions
316 public:
317     int addDirectChannel(const struct sensors_direct_mem_t *mem);
318     int removeDirectChannel(int channel_handle);
319     int configDirectReport(int sensor_handle, int channel_handle, int rate_level);
320     bool isDirectReportSupported() const;
321 private:
322     void sendDirectReportEvent(const sensors_event_t *nev, size_t n);
323     void mergeDirectReportRequest(struct ConfigCmd *cmd, int handle);
324     bool isSampleIntervalSatisfied(int handle, uint64_t timestamp);
325     void updateSampleRate(int handle, int reason);
326 #ifdef DIRECT_REPORT_ENABLED
327     int stopAllDirectReportOnChannel(
328             int channel_handle, std::vector<int32_t> *unstoppedSensors);
329     uint64_t rateLevelToDeviceSamplingPeriodNs(int handle, int rateLevel) const;
intervalLargeEnoughHubConnection330     inline static bool intervalLargeEnough(uint64_t actual, uint64_t desired) {
331         return (actual + (actual >> 4)) >= desired; // >= 94.11% of desired
332     }
333 
334     struct DirectChannelTimingInfo{
335         uint64_t lastTimestamp;
336         int rateLevel;
337     };
338     Mutex mDirectChannelLock;
339     //sensor_handle=>(channel_handle => DirectChannelTimingInfo)
340     std::unordered_map<int32_t,
341             std::unordered_map<int32_t, DirectChannelTimingInfo> > mSensorToChannel;
342     //channel_handle=>ptr of Channel obj
343     std::unordered_map<int32_t, std::unique_ptr<DirectChannelBase>> mDirectChannel;
344     int32_t mDirectChannelHandle;
345 #endif
346 
347     DISALLOW_EVIL_CONSTRUCTORS(HubConnection);
348 };
349 
350 }  // namespace android
351 
352 #endif  // HUB_CONNECTION_H_
353