• Home
  • History
  • Annotate
  • 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 "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