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