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