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 "eventnums.h"
31 #include "hubdefs.h"
32 #include "ring.h"
33 
34 namespace android {
35 
36 struct HubConnection : public Thread {
37     static HubConnection *getInstance();
38 
39     status_t initCheck() const;
40 
41     enum ProximitySensorType {
42         PROXIMITY_UNKNOWN,
43         PROXIMITY_ROHM,
44         PROXIMITY_AMS,
45     };
46 
47     // Blocks until it can return a status
48     status_t getAliveCheck();
49 
50     virtual bool threadLoop();
51 
52     void queueActivate(int handle, bool enable);
53     void queueSetDelay(int handle, nsecs_t delayNs);
54     void queueBatch(
55             int handle,
56             int flags,
57             nsecs_t sampling_period_ns,
58             nsecs_t max_report_latency_ns);
59     void queueFlush(int handle);
60     void queueData(int handle, void *data, size_t length);
61 
62     ssize_t read(sensors_event_t *ev, size_t size);
63 
64     typedef void (*ActivityFunc)(
65             void *, uint64_t time_us, bool is_flush, float x, float y, float z);
66 
67     void setActivityCallback(void *cookie, ActivityFunc cb);
68 
69     void saveSensorSettings() const;
70 
71 protected:
72     HubConnection();
73     virtual ~HubConnection();
74 
75     virtual void onFirstRef();
76 
77 private:
78     typedef uint32_t rate_q10_t;  // q10 means lower 10 bits are for fractions
79 
period_ns_to_frequency_q10HubConnection80     static inline uint64_t period_ns_to_frequency_q10(nsecs_t period_ns) {
81         return 1024000000000ULL / period_ns;
82     }
83 
frequency_q10_to_period_nsHubConnection84     static inline nsecs_t frequency_q10_to_period_ns(uint64_t frequency_q10) {
85         if (frequency_q10)
86             return 1024000000000LL / frequency_q10;
87         else
88             return (nsecs_t)0;
89     }
90 
91     enum
92     {
93         CONFIG_CMD_DISABLE      = 0,
94         CONFIG_CMD_ENABLE       = 1,
95         CONFIG_CMD_FLUSH        = 2,
96         CONFIG_CMD_CFG_DATA     = 3,
97         CONFIG_CMD_CALIBRATE    = 4,
98     };
99 
100     struct ConfigCmd
101     {
102         uint32_t evtType;
103         uint64_t latency;
104         rate_q10_t rate;
105         uint8_t sensorType;
106         uint8_t cmd;
107         uint16_t flags;
108         uint8_t data[];
109     } __attribute__((packed));
110 
111     struct MsgCmd
112     {
113         uint32_t evtType;
114         struct HostHubRawPacket msg;
115     } __attribute__((packed));
116 
117     struct SensorState {
118         uint64_t latency;
119         rate_q10_t rate;
120         uint8_t sensorType;
121         uint8_t alt;
122         uint8_t flushCnt;
123         bool enable;
124     };
125 
126     struct FirstSample
127     {
128         uint8_t numSamples;
129         uint8_t numFlushes;
130         uint8_t highAccuracy : 1;
131         uint8_t biasPresent : 1;
132         uint8_t biasSample : 6;
133         uint8_t pad;
134     };
135 
136     struct RawThreeAxisSample
137     {
138         uint32_t deltaTime;
139         int16_t ix, iy, iz;
140     } __attribute__((packed));
141 
142     struct ThreeAxisSample
143     {
144         uint32_t deltaTime;
145         float x, y, z;
146     } __attribute__((packed));
147 
148     struct OneAxisSample
149     {
150         uint32_t deltaTime;
151         union
152         {
153             float fdata;
154             uint32_t idata;
155         };
156     } __attribute__((packed));
157 
158     // The following structure should match struct HostIntfDataBuffer found in
159     // firmware/inc/hostIntf.h
160     struct nAxisEvent
161     {
162         uint32_t evtType;
163         union
164         {
165             struct
166             {
167                 uint64_t referenceTime;
168                 union
169                 {
170                     struct FirstSample firstSample;
171                     struct OneAxisSample oneSamples[];
172                     struct RawThreeAxisSample rawThreeSamples[];
173                     struct ThreeAxisSample threeSamples[];
174                 };
175             };
176             uint8_t buffer[];
177         };
178     } __attribute__((packed));
179 
180     static Mutex sInstanceLock;
181     static HubConnection *sInstance;
182 
183     // This lock is used for synchronization between the write thread (from
184     // sensorservice) and the read thread polling from the nanohub driver.
185     Mutex mLock;
186 
187     RingBuffer mRing;
188 
189     void *mActivityCbCookie;
190     ActivityFunc mActivityCb;
191 
192     float mMagBias[3];
193     uint8_t mMagAccuracy;
194     uint8_t mMagAccuracyRestore;
195 
196     float mGyroBias[3];
197 
198     SensorState mSensorState[NUM_COMMS_SENSORS_PLUS_1];
199 
200     uint64_t mStepCounterOffset;
201     uint64_t mLastStepCount;
202 
203     int mFd;
204     int mInotifyPollIndex;
205     struct pollfd mPollFds[3];
206     int mNumPollFds;
207 
208     sensors_event_t *initEv(sensors_event_t *ev, uint64_t timestamp, uint32_t type, uint32_t sensor);
209     void magAccuracyUpdate(float x, float y, float z);
210     void processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct OneAxisSample *sample, bool highAccuracy);
211     void processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct RawThreeAxisSample *sample, bool highAccuracy);
212     void processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct ThreeAxisSample *sample, bool highAccuracy);
213     void postOsLog(uint8_t *buf, ssize_t len);
214     ssize_t processBuf(uint8_t *buf, ssize_t len);
215 
216     void initConfigCmd(struct ConfigCmd *cmd, int handle);
217 
218     void queueDataInternal(int handle, void *data, size_t length);
219 
220     void discardInotifyEvent();
221     void waitOnNanohubLock();
222 
223     void initNanohubLock();
224 
225     void restoreSensorState();
226     void sendCalibrationOffsets();
227 
228 #ifdef LID_STATE_REPORTING_ENABLED
229     int mUinputFd;
230 
231     status_t initializeUinputNode();
232     void sendFolioEvent(int32_t data);
233 #endif  // LID_STATE_REPORTING_ENABLED
234 
235 #ifdef USB_MAG_BIAS_REPORTING_ENABLED
236     int mMagBiasPollIndex;
237     float mUsbMagBias;
238 
239     void queueUsbMagBias();
240 #endif  // USB_MAG_BIAS_REPORTING_ENABLED
241 
242     DISALLOW_EVIL_CONSTRUCTORS(HubConnection);
243 };
244 
245 }  // namespace android
246 
247 #endif  // HUB_CONNECTION_H_
248