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 
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     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 
setRawScaleHubConnection91     void setRawScale(float scaleAccel, float scaleMag) {
92         mScaleAccel = scaleAccel;
93         mScaleMag = scaleMag;
94     }
95 
96 protected:
97     HubConnection();
98     virtual ~HubConnection();
99 
100     virtual void onFirstRef();
101 
102 private:
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 
period_ns_to_frequency_q10HubConnection110     static inline uint64_t period_ns_to_frequency_q10(nsecs_t period_ns) {
111         return 1024000000000ULL / period_ns;
112     }
113 
frequency_q10_to_period_nsHubConnection114     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 
frequency_to_frequency_q10HubConnection121     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 
isValidHandleHubConnection253     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
296 public:
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;
301 private:
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