/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef HUB_CONNECTION_H_ #define HUB_CONNECTION_H_ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <poll.h> #include <utils/Errors.h> #include <utils/Mutex.h> #include <utils/Thread.h> #include "activityeventhandler.h" #include "eventnums.h" #include "hubdefs.h" #include "ring.h" namespace android { struct HubConnection : public Thread { static HubConnection *getInstance(); status_t initCheck() const; enum ProximitySensorType { PROXIMITY_UNKNOWN, PROXIMITY_ROHM, PROXIMITY_AMS, }; // Blocks until it can return a status status_t getAliveCheck(); virtual bool threadLoop(); void queueActivate(int handle, bool enable); void queueSetDelay(int handle, nsecs_t delayNs); void queueBatch(int handle, nsecs_t sampling_period_ns, nsecs_t max_report_latency_ns); void queueFlush(int handle); void queueData(int handle, void *data, size_t length); ssize_t read(sensors_event_t *ev, size_t size); void setActivityCallback(ActivityEventHandler *eventHandler); void saveSensorSettings() const; protected: HubConnection(); virtual ~HubConnection(); virtual void onFirstRef(); private: typedef uint32_t rate_q10_t; // q10 means lower 10 bits are for fractions static inline uint64_t period_ns_to_frequency_q10(nsecs_t period_ns) { return 1024000000000ULL / period_ns; } static inline nsecs_t frequency_q10_to_period_ns(uint64_t frequency_q10) { if (frequency_q10) return 1024000000000LL / frequency_q10; else return (nsecs_t)0; } enum { CONFIG_CMD_DISABLE = 0, CONFIG_CMD_ENABLE = 1, CONFIG_CMD_FLUSH = 2, CONFIG_CMD_CFG_DATA = 3, CONFIG_CMD_CALIBRATE = 4, }; struct ConfigCmd { uint32_t evtType; uint64_t latency; rate_q10_t rate; uint8_t sensorType; uint8_t cmd; uint16_t flags; uint8_t data[]; } __attribute__((packed)); struct MsgCmd { uint32_t evtType; struct HostHubRawPacket msg; } __attribute__((packed)); struct SensorState { uint64_t latency; rate_q10_t rate; uint8_t sensorType; uint8_t alt; uint8_t flushCnt; bool enable; }; struct FirstSample { uint8_t numSamples; uint8_t numFlushes; uint8_t highAccuracy : 1; uint8_t biasPresent : 1; uint8_t biasSample : 6; uint8_t pad; }; struct RawThreeAxisSample { uint32_t deltaTime; int16_t ix, iy, iz; } __attribute__((packed)); struct ThreeAxisSample { uint32_t deltaTime; float x, y, z; } __attribute__((packed)); struct OneAxisSample { uint32_t deltaTime; union { float fdata; uint32_t idata; }; } __attribute__((packed)); // The following structure should match struct HostIntfDataBuffer found in // firmware/inc/hostIntf.h struct nAxisEvent { uint32_t evtType; union { struct { uint64_t referenceTime; union { struct FirstSample firstSample; struct OneAxisSample oneSamples[]; struct RawThreeAxisSample rawThreeSamples[]; struct ThreeAxisSample threeSamples[]; }; }; uint8_t buffer[]; }; } __attribute__((packed)); static Mutex sInstanceLock; static HubConnection *sInstance; // This lock is used for synchronization between the write thread (from // sensorservice) and the read thread polling from the nanohub driver. Mutex mLock; RingBuffer mRing; ActivityEventHandler *mActivityEventHandler; float mMagBias[3]; uint8_t mMagAccuracy; uint8_t mMagAccuracyRestore; float mGyroBias[3], mAccelBias[3]; SensorState mSensorState[NUM_COMMS_SENSORS_PLUS_1]; uint64_t mStepCounterOffset; uint64_t mLastStepCount; int mFd; int mInotifyPollIndex; struct pollfd mPollFds[4]; int mNumPollFds; sensors_event_t *initEv(sensors_event_t *ev, uint64_t timestamp, uint32_t type, uint32_t sensor); void magAccuracyUpdate(float x, float y, float z); void processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct OneAxisSample *sample, bool highAccuracy); void processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct RawThreeAxisSample *sample, bool highAccuracy); void processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct ThreeAxisSample *sample, bool highAccuracy); void postOsLog(uint8_t *buf, ssize_t len); ssize_t processBuf(uint8_t *buf, ssize_t len); void initConfigCmd(struct ConfigCmd *cmd, int handle); void queueDataInternal(int handle, void *data, size_t length); void discardInotifyEvent(); void waitOnNanohubLock(); void initNanohubLock(); void restoreSensorState(); void sendCalibrationOffsets(); // Enable SCHED_FIFO priority for main thread void enableSchedFifoMode(); #ifdef LID_STATE_REPORTING_ENABLED int mUinputFd; status_t initializeUinputNode(); void sendFolioEvent(int32_t data); #endif // LID_STATE_REPORTING_ENABLED #ifdef USB_MAG_BIAS_REPORTING_ENABLED int mMagBiasPollIndex; float mUsbMagBias; void queueUsbMagBias(); #endif // USB_MAG_BIAS_REPORTING_ENABLED #ifdef DOUBLE_TOUCH_ENABLED int mDoubleTouchPollIndex; #endif // DOUBLE_TOUCH_ENABLED DISALLOW_EVIL_CONSTRUCTORS(HubConnection); }; } // namespace android #endif // HUB_CONNECTION_H_