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 #include "hubconnection.h"
18 #include "eventnums.h"
19 #include "sensType.h"
20
21 #define LOG_TAG "nanohub"
22 #include <utils/Log.h>
23 #include <utils/SystemClock.h>
24
25 #include "file.h"
26 #include "JSONObject.h"
27
28 #include <errno.h>
29 #include <unistd.h>
30 #include <math.h>
31 #include <inttypes.h>
32
33 #include <cutils/properties.h>
34 #include <linux/input.h>
35 #include <linux/uinput.h>
36 #include <media/stagefright/foundation/ADebug.h>
37 #include <sys/inotify.h>
38
39 #define APP_ID_GET_VENDOR(appid) ((appid) >> 24)
40 #define APP_ID_MAKE(vendor, app) ((((uint64_t)(vendor)) << 24) | ((app) & 0x00FFFFFF))
41 #define APP_ID_VENDOR_GOOGLE 0x476f6f676cULL // "Googl"
42 #define APP_ID_APP_BMI160 2
43
44 #define SENS_TYPE_TO_EVENT(_sensorType) (EVT_NO_FIRST_SENSOR_EVENT + (_sensorType))
45
46 #define NANOHUB_FILE_PATH "/dev/nanohub"
47 #define NANOHUB_LOCK_DIR "/data/system/nanohub_lock"
48 #define NANOHUB_LOCK_FILE NANOHUB_LOCK_DIR "/lock"
49 #define MAG_BIAS_FILE_PATH "/sys/class/power_supply/battery/compass_compensation"
50
51 #define NANOHUB_LOCK_DIR_PERMS (S_IRUSR | S_IWUSR | S_IXUSR)
52
53 #define SENSOR_RATE_ONCHANGE 0xFFFFFF01UL
54 #define SENSOR_RATE_ONESHOT 0xFFFFFF02UL
55
56 #define MIN_MAG_SQ (10.0f * 10.0f)
57 #define MAX_MAG_SQ (80.0f * 80.0f)
58
59 #define ACCEL_RAW_KSCALE (8.0f * 9.81f / 32768.0f)
60
61 #define OS_LOG_EVENT 0x474F4C41 // ascii: ALOG
62
63 #ifdef LID_STATE_REPORTING_ENABLED
64 const char LID_STATE_PROPERTY[] = "sensors.contexthub.lid_state";
65 const char LID_STATE_UNKNOWN[] = "unknown";
66 const char LID_STATE_OPEN[] = "open";
67 const char LID_STATE_CLOSED[] = "closed";
68 #endif // LID_STATE_REPORTING_ENABLED
69
70 static const uint32_t delta_time_encoded = 1;
71 static const uint32_t delta_time_shift_table[2] = {9, 0};
72
73 namespace android {
74
75 // static
76 Mutex HubConnection::sInstanceLock;
77
78 // static
79 HubConnection *HubConnection::sInstance = NULL;
80
getInstance()81 HubConnection *HubConnection::getInstance()
82 {
83 Mutex::Autolock autoLock(sInstanceLock);
84 if (sInstance == NULL) {
85 sInstance = new HubConnection;
86 }
87 return sInstance;
88 }
89
HubConnection()90 HubConnection::HubConnection()
91 : Thread(false /* canCallJava */),
92 mRing(10 *1024),
93 mActivityCbCookie(NULL),
94 mActivityCb(NULL),
95 mStepCounterOffset(0ull),
96 mLastStepCount(0ull)
97 {
98 mMagBias[0] = mMagBias[1] = mMagBias[2] = 0.0f;
99 mMagAccuracy = SENSOR_STATUS_UNRELIABLE;
100 mMagAccuracyRestore = SENSOR_STATUS_UNRELIABLE;
101 mGyroBias[0] = mGyroBias[1] = mGyroBias[2] = 0.0f;
102
103 memset(&mSensorState, 0x00, sizeof(mSensorState));
104 mFd = open(NANOHUB_FILE_PATH, O_RDWR);
105 mPollFds[0].fd = mFd;
106 mPollFds[0].events = POLLIN;
107 mPollFds[0].revents = 0;
108 mNumPollFds = 1;
109
110 initNanohubLock();
111
112 #ifdef USB_MAG_BIAS_REPORTING_ENABLED
113 mUsbMagBias = 0;
114 mMagBiasPollIndex = -1;
115 int magBiasFd = open(MAG_BIAS_FILE_PATH, O_RDONLY);
116 if (magBiasFd < 0) {
117 ALOGW("Mag bias file open failed: %s", strerror(errno));
118 } else {
119 mPollFds[mNumPollFds].fd = magBiasFd;
120 mPollFds[mNumPollFds].events = 0;
121 mPollFds[mNumPollFds].revents = 0;
122 mMagBiasPollIndex = mNumPollFds;
123 mNumPollFds++;
124 }
125 #endif // USB_MAG_BIAS_REPORTING_ENABLED
126
127 mSensorState[COMMS_SENSOR_ACCEL].sensorType = SENS_TYPE_ACCEL;
128 mSensorState[COMMS_SENSOR_GYRO].sensorType = SENS_TYPE_GYRO;
129 mSensorState[COMMS_SENSOR_GYRO].alt = COMMS_SENSOR_GYRO_UNCALIBRATED;
130 mSensorState[COMMS_SENSOR_GYRO_UNCALIBRATED].sensorType = SENS_TYPE_GYRO;
131 mSensorState[COMMS_SENSOR_GYRO_UNCALIBRATED].alt = COMMS_SENSOR_GYRO;
132 mSensorState[COMMS_SENSOR_MAG].sensorType = SENS_TYPE_MAG;
133 mSensorState[COMMS_SENSOR_MAG].alt = COMMS_SENSOR_MAG_UNCALIBRATED;
134 mSensorState[COMMS_SENSOR_MAG_UNCALIBRATED].sensorType = SENS_TYPE_MAG;
135 mSensorState[COMMS_SENSOR_MAG_UNCALIBRATED].alt = COMMS_SENSOR_MAG;
136 mSensorState[COMMS_SENSOR_LIGHT].sensorType = SENS_TYPE_ALS;
137 mSensorState[COMMS_SENSOR_PROXIMITY].sensorType = SENS_TYPE_PROX;
138 mSensorState[COMMS_SENSOR_PRESSURE].sensorType = SENS_TYPE_BARO;
139 mSensorState[COMMS_SENSOR_TEMPERATURE].sensorType = SENS_TYPE_TEMP;
140 mSensorState[COMMS_SENSOR_ORIENTATION].sensorType = SENS_TYPE_ORIENTATION;
141 mSensorState[COMMS_SENSOR_WINDOW_ORIENTATION].sensorType = SENS_TYPE_WIN_ORIENTATION;
142 mSensorState[COMMS_SENSOR_WINDOW_ORIENTATION].rate = SENSOR_RATE_ONCHANGE;
143 mSensorState[COMMS_SENSOR_STEP_DETECTOR].sensorType = SENS_TYPE_STEP_DETECT;
144 mSensorState[COMMS_SENSOR_STEP_DETECTOR].rate = SENSOR_RATE_ONCHANGE;
145 mSensorState[COMMS_SENSOR_STEP_COUNTER].sensorType = SENS_TYPE_STEP_COUNT;
146 mSensorState[COMMS_SENSOR_SIGNIFICANT_MOTION].sensorType = SENS_TYPE_SIG_MOTION;
147 mSensorState[COMMS_SENSOR_SIGNIFICANT_MOTION].rate = SENSOR_RATE_ONESHOT;
148 mSensorState[COMMS_SENSOR_GRAVITY].sensorType = SENS_TYPE_GRAVITY;
149 mSensorState[COMMS_SENSOR_LINEAR_ACCEL].sensorType = SENS_TYPE_LINEAR_ACCEL;
150 mSensorState[COMMS_SENSOR_ROTATION_VECTOR].sensorType = SENS_TYPE_ROTATION_VECTOR;
151 mSensorState[COMMS_SENSOR_GEO_MAG].sensorType = SENS_TYPE_GEO_MAG_ROT_VEC;
152 mSensorState[COMMS_SENSOR_GAME_ROTATION_VECTOR].sensorType = SENS_TYPE_GAME_ROT_VECTOR;
153 mSensorState[COMMS_SENSOR_HALL].sensorType = SENS_TYPE_HALL;
154 mSensorState[COMMS_SENSOR_HALL].rate = SENSOR_RATE_ONCHANGE;
155 mSensorState[COMMS_SENSOR_SYNC].sensorType = SENS_TYPE_VSYNC;
156 mSensorState[COMMS_SENSOR_SYNC].rate = SENSOR_RATE_ONCHANGE;
157 mSensorState[COMMS_SENSOR_ACTIVITY].sensorType = SENS_TYPE_ACTIVITY;
158 mSensorState[COMMS_SENSOR_ACTIVITY].rate = SENSOR_RATE_ONCHANGE;
159 mSensorState[COMMS_SENSOR_TILT].sensorType = SENS_TYPE_TILT;
160 mSensorState[COMMS_SENSOR_TILT].rate = SENSOR_RATE_ONCHANGE;
161 mSensorState[COMMS_SENSOR_GESTURE].sensorType = SENS_TYPE_GESTURE;
162 mSensorState[COMMS_SENSOR_GESTURE].rate = SENSOR_RATE_ONESHOT;
163 mSensorState[COMMS_SENSOR_DOUBLE_TWIST].sensorType = SENS_TYPE_DOUBLE_TWIST;
164 mSensorState[COMMS_SENSOR_DOUBLE_TWIST].rate = SENSOR_RATE_ONCHANGE;
165 mSensorState[COMMS_SENSOR_DOUBLE_TAP].sensorType = SENS_TYPE_DOUBLE_TAP;
166 mSensorState[COMMS_SENSOR_DOUBLE_TAP].rate = SENSOR_RATE_ONCHANGE;
167
168 #ifdef LID_STATE_REPORTING_ENABLED
169 initializeUinputNode();
170
171 // set initial lid state
172 if (property_set(LID_STATE_PROPERTY, LID_STATE_UNKNOWN) < 0) {
173 ALOGE("could not set lid_state property");
174 }
175
176 // enable hall sensor for folio
177 if (mFd >= 0) {
178 queueActivate(COMMS_SENSOR_HALL, true /* enable */);
179 }
180 #endif // LID_STATE_REPORTING_ENABLED
181 }
182
~HubConnection()183 HubConnection::~HubConnection()
184 {
185 close(mFd);
186 }
187
onFirstRef()188 void HubConnection::onFirstRef()
189 {
190 run("HubConnection", PRIORITY_URGENT_DISPLAY);
191 }
192
initCheck() const193 status_t HubConnection::initCheck() const
194 {
195 return mFd < 0 ? UNKNOWN_ERROR : OK;
196 }
197
getAliveCheck()198 status_t HubConnection::getAliveCheck()
199 {
200 return OK;
201 }
202
readSettings(File * file)203 static sp<JSONObject> readSettings(File *file) {
204 off64_t size = file->seekTo(0, SEEK_END);
205 file->seekTo(0, SEEK_SET);
206
207 sp<JSONObject> root;
208
209 if (size > 0) {
210 char *buf = (char *)malloc(size);
211 CHECK_EQ(file->read(buf, size), (ssize_t)size);
212 file->seekTo(0, SEEK_SET);
213
214 sp<JSONCompound> in = JSONCompound::Parse(buf, size);
215 free(buf);
216 buf = NULL;
217
218 if (in != NULL && in->isObject()) {
219 root = (JSONObject *)in.get();
220 }
221 }
222
223 if (root == NULL) {
224 root = new JSONObject;
225 }
226
227 return root;
228 }
229
getCalibrationInt32(const sp<JSONObject> & settings,const char * key,int32_t * out,size_t numArgs)230 static bool getCalibrationInt32(
231 const sp<JSONObject> &settings, const char *key, int32_t *out,
232 size_t numArgs) {
233 sp<JSONArray> array;
234 if (!settings->getArray(key, &array)) {
235 return false;
236 } else {
237 for (size_t i = 0; i < numArgs; i++) {
238 if (!array->getInt32(i, &out[i])) {
239 return false;
240 }
241 }
242 }
243 return true;
244 }
245
getCalibrationFloat(const sp<JSONObject> & settings,const char * key,float out[3])246 static bool getCalibrationFloat(
247 const sp<JSONObject> &settings, const char *key, float out[3]) {
248 sp<JSONArray> array;
249 if (!settings->getArray(key, &array)) {
250 return false;
251 } else {
252 for (size_t i = 0; i < 3; i++) {
253 if (!array->getFloat(i, &out[i])) {
254 return false;
255 }
256 }
257 }
258 return true;
259 }
260
loadSensorSettings(sp<JSONObject> * settings,sp<JSONObject> * saved_settings)261 static void loadSensorSettings(sp<JSONObject>* settings,
262 sp<JSONObject>* saved_settings) {
263 File settings_file(CONTEXTHUB_SETTINGS_PATH, "r");
264 File saved_settings_file(CONTEXTHUB_SAVED_SETTINGS_PATH, "r");
265
266 status_t err;
267 if ((err = settings_file.initCheck()) != OK) {
268 ALOGE("settings file open failed: %d (%s)",
269 err,
270 strerror(-err));
271
272 *settings = new JSONObject;
273 } else {
274 *settings = readSettings(&settings_file);
275 }
276
277 if ((err = saved_settings_file.initCheck()) != OK) {
278 ALOGE("saved settings file open failed: %d (%s)",
279 err,
280 strerror(-err));
281 *saved_settings = new JSONObject;
282 } else {
283 *saved_settings = readSettings(&saved_settings_file);
284 }
285 }
286
saveSensorSettings() const287 void HubConnection::saveSensorSettings() const {
288 File saved_settings_file(CONTEXTHUB_SAVED_SETTINGS_PATH, "w");
289
290 status_t err;
291 if ((err = saved_settings_file.initCheck()) != OK) {
292 ALOGE("saved settings file open failed %d (%s)",
293 err,
294 strerror(-err));
295 return;
296 }
297
298 // Build a settings object.
299 sp<JSONArray> magArray = new JSONArray;
300 #ifdef USB_MAG_BIAS_REPORTING_ENABLED
301 magArray->addFloat(mMagBias[0] + mUsbMagBias);
302 #else
303 magArray->addFloat(mMagBias[0]);
304 #endif // USB_MAG_BIAS_REPORTING_ENABLED
305 magArray->addFloat(mMagBias[1]);
306 magArray->addFloat(mMagBias[2]);
307
308 sp<JSONObject> settingsObject = new JSONObject;
309 settingsObject->setArray("mag", magArray);
310
311 // Write the JSON string to disk.
312 AString serializedSettings = settingsObject->toString();
313 size_t size = serializedSettings.size();
314 if ((err = saved_settings_file.write(serializedSettings.c_str(), size)) != (ssize_t)size) {
315 ALOGE("saved settings file write failed %d (%s)",
316 err,
317 strerror(-err));
318 }
319 }
320
initEv(sensors_event_t * ev,uint64_t timestamp,uint32_t type,uint32_t sensor)321 sensors_event_t *HubConnection::initEv(sensors_event_t *ev, uint64_t timestamp, uint32_t type, uint32_t sensor)
322 {
323 memset(ev, 0x00, sizeof(sensors_event_t));
324 ev->version = sizeof(sensors_event_t);
325 ev->timestamp = timestamp;
326 ev->type = type;
327 ev->sensor = sensor;
328
329 return ev;
330 }
331
processSample(uint64_t timestamp,uint32_t type,uint32_t sensor,struct OneAxisSample * sample,bool highAccuracy)332 void HubConnection::processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct OneAxisSample *sample, __attribute__((unused)) bool highAccuracy)
333 {
334 sensors_event_t nev[1];
335 int cnt = 0;
336
337 switch (sensor) {
338 case COMMS_SENSOR_ACTIVITY:
339 if (mActivityCb != NULL) {
340 (*mActivityCb)(mActivityCbCookie, timestamp / 1000ull,
341 false, /* is_flush */
342 (float)(sample->idata & 0x7), 0.0, 0.0);
343 }
344 break;
345 case COMMS_SENSOR_PRESSURE:
346 initEv(&nev[cnt++], timestamp, type, sensor)->pressure = sample->fdata;
347 break;
348 case COMMS_SENSOR_TEMPERATURE:
349 initEv(&nev[cnt++], timestamp, type, sensor)->temperature = sample->fdata;
350 break;
351 case COMMS_SENSOR_PROXIMITY:
352 initEv(&nev[cnt++], timestamp, type, sensor)->distance = sample->fdata;
353 break;
354 case COMMS_SENSOR_LIGHT:
355 initEv(&nev[cnt++], timestamp, type, sensor)->light = sample->fdata;
356 break;
357 case COMMS_SENSOR_STEP_COUNTER:
358 // We'll stash away the last step count in case we need to reset
359 // the hub. This last step count would then become the new offset.
360 mLastStepCount = mStepCounterOffset + sample->idata;
361 initEv(&nev[cnt++], timestamp, type, sensor)->u64.step_counter = mLastStepCount;
362 break;
363 case COMMS_SENSOR_STEP_DETECTOR:
364 case COMMS_SENSOR_SIGNIFICANT_MOTION:
365 case COMMS_SENSOR_TILT:
366 case COMMS_SENSOR_DOUBLE_TWIST:
367 initEv(&nev[cnt++], timestamp, type, sensor)->data[0] = 1.0f;
368 break;
369 case COMMS_SENSOR_GESTURE:
370 case COMMS_SENSOR_SYNC:
371 initEv(&nev[cnt++], timestamp, type, sensor)->data[0] = sample->idata;
372 break;
373 case COMMS_SENSOR_HALL:
374 #ifdef LID_STATE_REPORTING_ENABLED
375 sendFolioEvent(sample->idata);
376 #endif // LID_STATE_REPORTING_ENABLED
377 break;
378 case COMMS_SENSOR_WINDOW_ORIENTATION:
379 initEv(&nev[cnt++], timestamp, type, sensor)->data[0] = sample->idata;
380 break;
381 default:
382 break;
383 }
384
385 if (cnt > 0)
386 mRing.write(nev, cnt);
387 }
388
magAccuracyUpdate(float x,float y,float z)389 void HubConnection::magAccuracyUpdate(float x, float y, float z)
390 {
391 float magSq = x * x + y * y + z * z;
392
393 if (magSq < MIN_MAG_SQ || magSq > MAX_MAG_SQ) {
394 // save last good accuracy (either MEDIUM or HIGH)
395 if (mMagAccuracy != SENSOR_STATUS_UNRELIABLE)
396 mMagAccuracyRestore = mMagAccuracy;
397 mMagAccuracy = SENSOR_STATUS_UNRELIABLE;
398 } else if (mMagAccuracy == SENSOR_STATUS_UNRELIABLE) {
399 // restore
400 mMagAccuracy = mMagAccuracyRestore;
401 }
402 }
403
processSample(uint64_t timestamp,uint32_t type,uint32_t sensor,struct RawThreeAxisSample * sample,bool highAccuracy)404 void HubConnection::processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct RawThreeAxisSample *sample, __attribute__((unused)) bool highAccuracy)
405 {
406 sensors_vec_t *sv;
407 sensors_event_t nev[2];
408 int cnt = 0;
409
410 switch (sensor) {
411 case COMMS_SENSOR_ACCEL:
412 sv = &initEv(&nev[cnt++], timestamp, type, sensor)->acceleration;
413 sv->x = sample->ix * ACCEL_RAW_KSCALE;
414 sv->y = sample->iy * ACCEL_RAW_KSCALE;
415 sv->z = sample->iz * ACCEL_RAW_KSCALE;
416 sv->status = SENSOR_STATUS_ACCURACY_HIGH;
417 break;
418 default:
419 break;
420 }
421
422 if (cnt > 0)
423 mRing.write(nev, cnt);
424 }
425
processSample(uint64_t timestamp,uint32_t type,uint32_t sensor,struct ThreeAxisSample * sample,bool highAccuracy)426 void HubConnection::processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct ThreeAxisSample *sample, bool highAccuracy)
427 {
428 sensors_vec_t *sv;
429 uncalibrated_event_t *ue;
430 sensors_event_t *ev;
431 sensors_event_t nev[2];
432 static const float heading_accuracy = M_PI / 6.0f;
433 float w;
434 int cnt = 0;
435
436 switch (sensor) {
437 case COMMS_SENSOR_ACCEL:
438 sv = &initEv(&nev[cnt++], timestamp, type, sensor)->acceleration;
439 sv->x = sample->x;
440 sv->y = sample->y;
441 sv->z = sample->z;
442 sv->status = SENSOR_STATUS_ACCURACY_HIGH;
443 break;
444 case COMMS_SENSOR_GYRO:
445 if (mSensorState[sensor].enable) {
446 sv = &initEv(&nev[cnt++], timestamp, type, sensor)->gyro;
447 sv->x = sample->x;
448 sv->y = sample->y;
449 sv->z = sample->z;
450 sv->status = SENSOR_STATUS_ACCURACY_HIGH;
451 }
452
453 if (mSensorState[COMMS_SENSOR_GYRO_UNCALIBRATED].enable) {
454 ue = &initEv(&nev[cnt++], timestamp,
455 SENSOR_TYPE_GYROSCOPE_UNCALIBRATED,
456 COMMS_SENSOR_GYRO_UNCALIBRATED)->uncalibrated_gyro;
457 ue->x_uncalib = sample->x + mGyroBias[0];
458 ue->y_uncalib = sample->y + mGyroBias[1];
459 ue->z_uncalib = sample->z + mGyroBias[2];
460 ue->x_bias = mGyroBias[0];
461 ue->y_bias = mGyroBias[1];
462 ue->z_bias = mGyroBias[2];
463 }
464 break;
465 case COMMS_SENSOR_GYRO_BIAS:
466 mGyroBias[0] = sample->x;
467 mGyroBias[1] = sample->y;
468 mGyroBias[2] = sample->z;
469 break;
470 case COMMS_SENSOR_MAG:
471 magAccuracyUpdate(sample->x, sample->y, sample->z);
472
473 if (mSensorState[sensor].enable) {
474 sv = &initEv(&nev[cnt++], timestamp, type, sensor)->magnetic;
475 sv->x = sample->x;
476 sv->y = sample->y;
477 sv->z = sample->z;
478 sv->status = mMagAccuracy;
479 }
480
481 if (mSensorState[COMMS_SENSOR_MAG_UNCALIBRATED].enable) {
482 ue = &initEv(&nev[cnt++], timestamp,
483 SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED,
484 COMMS_SENSOR_MAG_UNCALIBRATED)->uncalibrated_magnetic;
485 ue->x_uncalib = sample->x + mMagBias[0];
486 ue->y_uncalib = sample->y + mMagBias[1];
487 ue->z_uncalib = sample->z + mMagBias[2];
488 ue->x_bias = mMagBias[0];
489 ue->y_bias = mMagBias[1];
490 ue->z_bias = mMagBias[2];
491 }
492 break;
493 case COMMS_SENSOR_MAG_BIAS:
494 mMagAccuracy = highAccuracy ? SENSOR_STATUS_ACCURACY_HIGH : SENSOR_STATUS_ACCURACY_MEDIUM;
495 mMagBias[0] = sample->x;
496 mMagBias[1] = sample->y;
497 mMagBias[2] = sample->z;
498
499 saveSensorSettings();
500 break;
501 case COMMS_SENSOR_ORIENTATION:
502 case COMMS_SENSOR_LINEAR_ACCEL:
503 case COMMS_SENSOR_GRAVITY:
504 sv = &initEv(&nev[cnt++], timestamp, type, sensor)->orientation;
505 sv->x = sample->x;
506 sv->y = sample->y;
507 sv->z = sample->z;
508 sv->status = mMagAccuracy;
509 break;
510 case COMMS_SENSOR_DOUBLE_TAP:
511 ev = initEv(&nev[cnt++], timestamp, type, sensor);
512 ev->data[0] = sample->x;
513 ev->data[1] = sample->y;
514 ev->data[2] = sample->z;
515 break;
516 case COMMS_SENSOR_ROTATION_VECTOR:
517 ev = initEv(&nev[cnt++], timestamp, type, sensor);
518 w = sample->x * sample->x + sample->y * sample->y + sample->z * sample->z;
519 if (w < 1.0f)
520 w = sqrt(1.0f - w);
521 else
522 w = 0.0f;
523 ev->data[0] = sample->x;
524 ev->data[1] = sample->y;
525 ev->data[2] = sample->z;
526 ev->data[3] = w;
527 ev->data[4] = (4 - mMagAccuracy) * heading_accuracy;
528 break;
529 case COMMS_SENSOR_GEO_MAG:
530 case COMMS_SENSOR_GAME_ROTATION_VECTOR:
531 ev = initEv(&nev[cnt++], timestamp, type, sensor);
532 w = sample->x * sample->x + sample->y * sample->y + sample->z * sample->z;
533 if (w < 1.0f)
534 w = sqrt(1.0f - w);
535 else
536 w = 0.0f;
537 ev->data[0] = sample->x;
538 ev->data[1] = sample->y;
539 ev->data[2] = sample->z;
540 ev->data[3] = w;
541 break;
542 default:
543 break;
544 }
545
546 if (cnt > 0)
547 mRing.write(nev, cnt);
548 }
549
discardInotifyEvent()550 void HubConnection::discardInotifyEvent() {
551 // Read & discard an inotify event. We only use the presence of an event as
552 // a trigger to perform the file existence check (for simplicity)
553 if (mInotifyPollIndex >= 0) {
554 char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
555 int ret = ::read(mPollFds[mInotifyPollIndex].fd, buf, sizeof(buf));
556 ALOGD("Discarded %d bytes of inotify data", ret);
557 }
558 }
559
waitOnNanohubLock()560 void HubConnection::waitOnNanohubLock() {
561 if (mInotifyPollIndex < 0) {
562 return;
563 }
564 struct pollfd *pfd = &mPollFds[mInotifyPollIndex];
565
566 // While the lock file exists, poll on the inotify fd (with timeout)
567 while (access(NANOHUB_LOCK_FILE, F_OK) == 0) {
568 ALOGW("Nanohub is locked; blocking read thread");
569 int ret = poll(pfd, 1, 5000);
570 if ((ret > 0) && (pfd->revents & POLLIN)) {
571 discardInotifyEvent();
572 }
573 }
574 }
575
restoreSensorState()576 void HubConnection::restoreSensorState()
577 {
578 Mutex::Autolock autoLock(mLock);
579
580 sendCalibrationOffsets();
581
582 for (int i = 0; i < NUM_COMMS_SENSORS_PLUS_1; i++) {
583 if (mSensorState[i].sensorType && mSensorState[i].enable) {
584 struct ConfigCmd cmd;
585
586 initConfigCmd(&cmd, i);
587
588 ALOGI("restoring: sensor=%d, handle=%d, enable=%d, period=%" PRId64 ", latency=%" PRId64,
589 cmd.sensorType, i, mSensorState[i].enable, frequency_q10_to_period_ns(mSensorState[i].rate),
590 mSensorState[i].latency);
591
592 int ret = TEMP_FAILURE_RETRY(write(mFd, &cmd, sizeof(cmd)));
593 if (ret != sizeof(cmd)) {
594 ALOGE("failed to send config command to restore sensor %d\n", cmd.sensorType);
595 }
596
597 cmd.cmd = CONFIG_CMD_FLUSH;
598
599 for (int j = 0; j < mSensorState[i].flushCnt; j++) {
600 int ret = TEMP_FAILURE_RETRY(write(mFd, &cmd, sizeof(cmd)));
601 if (ret != sizeof(cmd)) {
602 ALOGE("failed to send flush command to sensor %d\n", cmd.sensorType);
603 }
604 }
605 }
606 }
607
608 mStepCounterOffset = mLastStepCount;
609 }
610
postOsLog(uint8_t * buf,ssize_t len)611 void HubConnection::postOsLog(uint8_t *buf, ssize_t len)
612 {
613 // if len is less than 6, it's either an invalid or an empty log message.
614 if (len < 6)
615 return;
616
617 buf[len] = 0x00;
618 switch (buf[4]) {
619 case 'E':
620 ALOGE("osLog: %s", &buf[5]);
621 break;
622 case 'W':
623 ALOGW("osLog: %s", &buf[5]);
624 break;
625 case 'I':
626 ALOGI("osLog: %s", &buf[5]);
627 break;
628 case 'D':
629 ALOGD("osLog: %s", &buf[5]);
630 break;
631 default:
632 break;
633 }
634 }
635
processBuf(uint8_t * buf,ssize_t len)636 ssize_t HubConnection::processBuf(uint8_t *buf, ssize_t len)
637 {
638 struct nAxisEvent *data = (struct nAxisEvent *)buf;
639 uint32_t type, sensor, bias, currSensor;
640 int i, numSamples;
641 bool one, rawThree, three;
642 sensors_event_t ev;
643 uint64_t timestamp;
644 ssize_t ret = 0;
645
646 if (len >= 4) {
647 ret = sizeof(data->evtType);
648 one = three = rawThree = false;
649 bias = 0;
650 switch (data->evtType) {
651 case OS_LOG_EVENT:
652 postOsLog(buf, len);
653 return 0;
654 case SENS_TYPE_TO_EVENT(SENS_TYPE_ACCEL):
655 type = SENSOR_TYPE_ACCELEROMETER;
656 sensor = COMMS_SENSOR_ACCEL;
657 three = true;
658 break;
659 case SENS_TYPE_TO_EVENT(SENS_TYPE_ACCEL_RAW):
660 type = SENSOR_TYPE_ACCELEROMETER;
661 sensor = COMMS_SENSOR_ACCEL;
662 rawThree = true;
663 break;
664 case SENS_TYPE_TO_EVENT(SENS_TYPE_GYRO):
665 type = SENSOR_TYPE_GYROSCOPE;
666 sensor = COMMS_SENSOR_GYRO;
667 bias = COMMS_SENSOR_GYRO_BIAS;
668 three = true;
669 break;
670 case SENS_TYPE_TO_EVENT(SENS_TYPE_MAG):
671 type = SENSOR_TYPE_MAGNETIC_FIELD;
672 sensor = COMMS_SENSOR_MAG;
673 bias = COMMS_SENSOR_MAG_BIAS;
674 three = true;
675 break;
676 case SENS_TYPE_TO_EVENT(SENS_TYPE_ALS):
677 type = SENSOR_TYPE_LIGHT;
678 sensor = COMMS_SENSOR_LIGHT;
679 one = true;
680 break;
681 case SENS_TYPE_TO_EVENT(SENS_TYPE_PROX):
682 type = SENSOR_TYPE_PROXIMITY;
683 sensor = COMMS_SENSOR_PROXIMITY;
684 one = true;
685 break;
686 case SENS_TYPE_TO_EVENT(SENS_TYPE_BARO):
687 type = SENSOR_TYPE_PRESSURE;
688 sensor = COMMS_SENSOR_PRESSURE;
689 one = true;
690 break;
691 case SENS_TYPE_TO_EVENT(SENS_TYPE_TEMP):
692 type = SENSOR_TYPE_AMBIENT_TEMPERATURE;
693 sensor = COMMS_SENSOR_TEMPERATURE;
694 one = true;
695 break;
696 case SENS_TYPE_TO_EVENT(SENS_TYPE_ORIENTATION):
697 type = SENSOR_TYPE_ORIENTATION;
698 sensor = COMMS_SENSOR_ORIENTATION;
699 three = true;
700 break;
701 case SENS_TYPE_TO_EVENT(SENS_TYPE_WIN_ORIENTATION):
702 type = SENSOR_TYPE_DEVICE_ORIENTATION;
703 sensor = COMMS_SENSOR_WINDOW_ORIENTATION;
704 one = true;
705 break;
706 case SENS_TYPE_TO_EVENT(SENS_TYPE_STEP_DETECT):
707 type = SENSOR_TYPE_STEP_DETECTOR;
708 sensor = COMMS_SENSOR_STEP_DETECTOR;
709 one = true;
710 break;
711 case SENS_TYPE_TO_EVENT(SENS_TYPE_STEP_COUNT):
712 type = SENSOR_TYPE_STEP_COUNTER;
713 sensor = COMMS_SENSOR_STEP_COUNTER;
714 one = true;
715 break;
716 case SENS_TYPE_TO_EVENT(SENS_TYPE_SIG_MOTION):
717 type = SENSOR_TYPE_SIGNIFICANT_MOTION;
718 sensor = COMMS_SENSOR_SIGNIFICANT_MOTION;
719 one = true;
720 break;
721 case SENS_TYPE_TO_EVENT(SENS_TYPE_GRAVITY):
722 type = SENSOR_TYPE_GRAVITY;
723 sensor = COMMS_SENSOR_GRAVITY;
724 three = true;
725 break;
726 case SENS_TYPE_TO_EVENT(SENS_TYPE_LINEAR_ACCEL):
727 type = SENSOR_TYPE_LINEAR_ACCELERATION;
728 sensor = COMMS_SENSOR_LINEAR_ACCEL;
729 three = true;
730 break;
731 case SENS_TYPE_TO_EVENT(SENS_TYPE_ROTATION_VECTOR):
732 type = SENSOR_TYPE_ROTATION_VECTOR;
733 sensor = COMMS_SENSOR_ROTATION_VECTOR;
734 three = true;
735 break;
736 case SENS_TYPE_TO_EVENT(SENS_TYPE_GEO_MAG_ROT_VEC):
737 type = SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR;
738 sensor = COMMS_SENSOR_GEO_MAG;
739 three = true;
740 break;
741 case SENS_TYPE_TO_EVENT(SENS_TYPE_GAME_ROT_VECTOR):
742 type = SENSOR_TYPE_GAME_ROTATION_VECTOR;
743 sensor = COMMS_SENSOR_GAME_ROTATION_VECTOR;
744 three = true;
745 break;
746 case SENS_TYPE_TO_EVENT(SENS_TYPE_HALL):
747 type = 0;
748 sensor = COMMS_SENSOR_HALL;
749 one = true;
750 break;
751 case SENS_TYPE_TO_EVENT(SENS_TYPE_VSYNC):
752 type = SENSOR_TYPE_SYNC;
753 sensor = COMMS_SENSOR_SYNC;
754 one = true;
755 break;
756 case SENS_TYPE_TO_EVENT(SENS_TYPE_ACTIVITY):
757 type = 0;
758 sensor = COMMS_SENSOR_ACTIVITY;
759 one = true;
760 break;
761 case SENS_TYPE_TO_EVENT(SENS_TYPE_TILT):
762 type = SENSOR_TYPE_TILT_DETECTOR;
763 sensor = COMMS_SENSOR_TILT;
764 one = true;
765 break;
766 case SENS_TYPE_TO_EVENT(SENS_TYPE_GESTURE):
767 type = SENSOR_TYPE_PICK_UP_GESTURE;
768 sensor = COMMS_SENSOR_GESTURE;
769 one = true;
770 break;
771 case SENS_TYPE_TO_EVENT(SENS_TYPE_DOUBLE_TWIST):
772 type = SENSOR_TYPE_DOUBLE_TWIST;
773 sensor = COMMS_SENSOR_DOUBLE_TWIST;
774 one = true;
775 break;
776 case SENS_TYPE_TO_EVENT(SENS_TYPE_DOUBLE_TAP):
777 type = SENSOR_TYPE_DOUBLE_TAP;
778 sensor = COMMS_SENSOR_DOUBLE_TAP;
779 three = true;
780 break;
781 case EVT_RESET_REASON:
782 uint32_t resetReason;
783 memcpy(&resetReason, data->buffer, sizeof(resetReason));
784 ALOGI("Observed hub reset: 0x%08" PRIx32, resetReason);
785 restoreSensorState();
786 return 0;
787 default:
788 return 0;
789 }
790 }
791
792 if (len >= 16) {
793 ret += sizeof(data->referenceTime);
794 timestamp = data->referenceTime;
795 numSamples = data->firstSample.numSamples;
796 for (i=0; i<numSamples; i++) {
797 if (data->firstSample.biasPresent && data->firstSample.biasSample == i)
798 currSensor = bias;
799 else
800 currSensor = sensor;
801
802 if (one) {
803 if (i > 0)
804 timestamp += ((uint64_t)data->oneSamples[i].deltaTime) << delta_time_shift_table[data->oneSamples[i].deltaTime & delta_time_encoded];
805 processSample(timestamp, type, currSensor, &data->oneSamples[i], data->firstSample.highAccuracy);
806 ret += sizeof(data->oneSamples[i]);
807 } else if (rawThree) {
808 if (i > 0)
809 timestamp += ((uint64_t)data->rawThreeSamples[i].deltaTime) << delta_time_shift_table[data->rawThreeSamples[i].deltaTime & delta_time_encoded];
810 processSample(timestamp, type, currSensor, &data->rawThreeSamples[i], data->firstSample.highAccuracy);
811 ret += sizeof(data->rawThreeSamples[i]);
812 } else if (three) {
813 if (i > 0)
814 timestamp += ((uint64_t)data->threeSamples[i].deltaTime) << delta_time_shift_table[data->threeSamples[i].deltaTime & delta_time_encoded];
815 processSample(timestamp, type, currSensor, &data->threeSamples[i], data->firstSample.highAccuracy);
816 ret += sizeof(data->threeSamples[i]);
817 }
818 }
819
820 if (!numSamples)
821 ret += sizeof(data->firstSample);
822
823 for (i=0; i<data->firstSample.numFlushes; i++) {
824 if (sensor == COMMS_SENSOR_ACTIVITY) {
825 if (mActivityCb != NULL) {
826 (*mActivityCb)(mActivityCbCookie, 0ull, /* when_us */
827 true, /* is_flush */
828 0.0f, 0.0f, 0.0f);
829 }
830 } else {
831 memset(&ev, 0x00, sizeof(sensors_event_t));
832 ev.version = META_DATA_VERSION;
833 ev.timestamp = 0;
834 ev.type = SENSOR_TYPE_META_DATA;
835 ev.sensor = 0;
836 ev.meta_data.what = META_DATA_FLUSH_COMPLETE;
837 if (mSensorState[sensor].alt && mSensorState[mSensorState[sensor].alt].flushCnt > 0) {
838 mSensorState[mSensorState[sensor].alt].flushCnt --;
839 ev.meta_data.sensor = mSensorState[sensor].alt;
840 } else {
841 mSensorState[sensor].flushCnt --;
842 ev.meta_data.sensor = sensor;
843 }
844
845 mRing.write(&ev, 1);
846 ALOGI("flushing %d", ev.meta_data.sensor);
847 }
848 }
849 }
850
851 return ret;
852 }
853
sendCalibrationOffsets()854 void HubConnection::sendCalibrationOffsets()
855 {
856 sp<JSONObject> settings;
857 sp<JSONObject> saved_settings;
858 int32_t accel[3], gyro[3], proximity, proximity_array[4];
859 float barometer, mag[3], light;
860
861 loadSensorSettings(&settings, &saved_settings);
862
863 if (getCalibrationInt32(settings, "accel", accel, 3))
864 queueDataInternal(COMMS_SENSOR_ACCEL, accel, sizeof(accel));
865
866 if (getCalibrationInt32(settings, "gyro", gyro, 3))
867 queueDataInternal(COMMS_SENSOR_GYRO, gyro, sizeof(gyro));
868
869 if (settings->getFloat("barometer", &barometer))
870 queueDataInternal(COMMS_SENSOR_PRESSURE, &barometer, sizeof(barometer));
871
872 if (settings->getInt32("proximity", &proximity))
873 queueDataInternal(COMMS_SENSOR_PROXIMITY, &proximity, sizeof(proximity));
874
875 if (getCalibrationInt32(settings, "proximity", proximity_array, 4))
876 queueDataInternal(COMMS_SENSOR_PROXIMITY, proximity_array, sizeof(proximity_array));
877
878 if (settings->getFloat("light", &light))
879 queueDataInternal(COMMS_SENSOR_LIGHT, &light, sizeof(light));
880
881 if (getCalibrationFloat(saved_settings, "mag", mag))
882 queueDataInternal(COMMS_SENSOR_MAG, mag, sizeof(mag));
883 }
884
threadLoop()885 bool HubConnection::threadLoop() {
886 ALOGI("threadLoop: starting");
887
888 if (mFd < 0) {
889 ALOGE("threadLoop: exiting prematurely: nanohub is unavailable");
890 return false;
891 }
892 waitOnNanohubLock();
893
894 sendCalibrationOffsets();
895
896 while (!Thread::exitPending()) {
897 ssize_t ret;
898
899 do {
900 ret = poll(mPollFds, mNumPollFds, -1);
901 } while (ret < 0 && errno == EINTR);
902
903 if (mInotifyPollIndex >= 0 && mPollFds[mInotifyPollIndex].revents & POLLIN) {
904 discardInotifyEvent();
905 waitOnNanohubLock();
906 }
907
908 #ifdef USB_MAG_BIAS_REPORTING_ENABLED
909 if (mMagBiasPollIndex >= 0 && mPollFds[mMagBiasPollIndex].revents & POLLERR) {
910 // Read from mag bias file
911 char buf[16];
912 lseek(mPollFds[mMagBiasPollIndex].fd, 0, SEEK_SET);
913 ::read(mPollFds[mMagBiasPollIndex].fd, buf, 16);
914 float bias = atof(buf);
915 mUsbMagBias = bias;
916 queueUsbMagBias();
917 }
918 #endif // USB_MAG_BIAS_REPORTING_ENABLED
919
920 if (mPollFds[0].revents & POLLIN) {
921 uint8_t recv[256];
922 ssize_t len = ::read(mFd, recv, sizeof(recv));
923
924 for (ssize_t offset = 0; offset < len;) {
925 ret = processBuf(recv + offset, len - offset);
926
927 if (ret > 0)
928 offset += ret;
929 else
930 break;
931 }
932 }
933 }
934
935 return false;
936 }
937
read(sensors_event_t * ev,size_t size)938 ssize_t HubConnection::read(sensors_event_t *ev, size_t size) {
939 return mRing.read(ev, size);
940 }
941
setActivityCallback(void * cookie,void (* cb)(void *,uint64_t time_ms,bool,float x,float y,float z))942 void HubConnection::setActivityCallback(
943 void *cookie,
944 void (*cb)(void *, uint64_t time_ms, bool, float x, float y, float z))
945 {
946 Mutex::Autolock autoLock(mLock);
947 mActivityCbCookie = cookie;
948 mActivityCb = cb;
949 }
950
initConfigCmd(struct ConfigCmd * cmd,int handle)951 void HubConnection::initConfigCmd(struct ConfigCmd *cmd, int handle)
952 {
953 uint8_t alt = mSensorState[handle].alt;
954
955 memset(cmd, 0x00, sizeof(*cmd));
956
957 cmd->evtType = EVT_NO_SENSOR_CONFIG_EVENT;
958 cmd->sensorType = mSensorState[handle].sensorType;
959
960 if (alt && mSensorState[alt].enable && mSensorState[handle].enable) {
961 cmd->cmd = CONFIG_CMD_ENABLE;
962 if (mSensorState[alt].rate > mSensorState[handle].rate)
963 cmd->rate = mSensorState[alt].rate;
964 else
965 cmd->rate = mSensorState[handle].rate;
966 if (mSensorState[alt].latency < mSensorState[handle].latency)
967 cmd->latency = mSensorState[alt].latency;
968 else
969 cmd->latency = mSensorState[handle].latency;
970 } else if (alt && mSensorState[alt].enable) {
971 cmd->cmd = mSensorState[alt].enable ? CONFIG_CMD_ENABLE : CONFIG_CMD_DISABLE;
972 cmd->rate = mSensorState[alt].rate;
973 cmd->latency = mSensorState[alt].latency;
974 } else { /* !alt || !mSensorState[alt].enable */
975 cmd->cmd = mSensorState[handle].enable ? CONFIG_CMD_ENABLE : CONFIG_CMD_DISABLE;
976 cmd->rate = mSensorState[handle].rate;
977 cmd->latency = mSensorState[handle].latency;
978 }
979 }
980
queueActivate(int handle,bool enable)981 void HubConnection::queueActivate(int handle, bool enable)
982 {
983 struct ConfigCmd cmd;
984 int ret;
985
986 Mutex::Autolock autoLock(mLock);
987
988 if (mSensorState[handle].sensorType) {
989 mSensorState[handle].enable = enable;
990
991 initConfigCmd(&cmd, handle);
992
993 ret = TEMP_FAILURE_RETRY(write(mFd, &cmd, sizeof(cmd)));
994 if (ret == sizeof(cmd))
995 ALOGI("queueActivate: sensor=%d, handle=%d, enable=%d",
996 cmd.sensorType, handle, enable);
997 else
998 ALOGE("queueActivate: failed to send command: sensor=%d, handle=%d, enable=%d",
999 cmd.sensorType, handle, enable);
1000 } else {
1001 ALOGI("queueActivate: unhandled handle=%d, enable=%d", handle, enable);
1002 }
1003 }
1004
queueSetDelay(int handle,nsecs_t sampling_period_ns)1005 void HubConnection::queueSetDelay(int handle, nsecs_t sampling_period_ns)
1006 {
1007 struct ConfigCmd cmd;
1008 int ret;
1009
1010 Mutex::Autolock autoLock(mLock);
1011
1012 if (mSensorState[handle].sensorType) {
1013 if (sampling_period_ns > 0 &&
1014 mSensorState[handle].rate != SENSOR_RATE_ONCHANGE &&
1015 mSensorState[handle].rate != SENSOR_RATE_ONESHOT) {
1016 mSensorState[handle].rate = period_ns_to_frequency_q10(sampling_period_ns);
1017 }
1018
1019 initConfigCmd(&cmd, handle);
1020
1021 ret = TEMP_FAILURE_RETRY(write(mFd, &cmd, sizeof(cmd)));
1022 if (ret == sizeof(cmd))
1023 ALOGI("queueSetDelay: sensor=%d, handle=%d, period=%" PRId64,
1024 cmd.sensorType, handle, sampling_period_ns);
1025 else
1026 ALOGE("queueSetDelay: failed to send command: sensor=%d, handle=%d, period=%" PRId64,
1027 cmd.sensorType, handle, sampling_period_ns);
1028 } else {
1029 ALOGI("queueSetDelay: unhandled handle=%d, period=%" PRId64, handle, sampling_period_ns);
1030 }
1031 }
1032
queueBatch(int handle,int flags,nsecs_t sampling_period_ns,nsecs_t max_report_latency_ns)1033 void HubConnection::queueBatch(
1034 int handle,
1035 __attribute__((unused)) int flags,
1036 nsecs_t sampling_period_ns,
1037 nsecs_t max_report_latency_ns)
1038 {
1039 struct ConfigCmd cmd;
1040 int ret;
1041
1042 Mutex::Autolock autoLock(mLock);
1043
1044 if (mSensorState[handle].sensorType) {
1045 if (sampling_period_ns > 0 &&
1046 mSensorState[handle].rate != SENSOR_RATE_ONCHANGE &&
1047 mSensorState[handle].rate != SENSOR_RATE_ONESHOT) {
1048 mSensorState[handle].rate = period_ns_to_frequency_q10(sampling_period_ns);
1049 }
1050 mSensorState[handle].latency = max_report_latency_ns;
1051
1052 initConfigCmd(&cmd, handle);
1053
1054 ret = TEMP_FAILURE_RETRY(write(mFd, &cmd, sizeof(cmd)));
1055 if (ret == sizeof(cmd))
1056 ALOGI("queueBatch: sensor=%d, handle=%d, period=%" PRId64 ", latency=%" PRId64,
1057 cmd.sensorType, handle, sampling_period_ns, max_report_latency_ns);
1058 else
1059 ALOGE("queueBatch: failed to send command: sensor=%d, handle=%d, period=%" PRId64 ", latency=%" PRId64,
1060 cmd.sensorType, handle, sampling_period_ns, max_report_latency_ns);
1061 } else {
1062 ALOGI("queueBatch: unhandled handle=%d, period=%" PRId64 ", latency=%" PRId64,
1063 handle, sampling_period_ns, max_report_latency_ns);
1064 }
1065 }
1066
queueFlush(int handle)1067 void HubConnection::queueFlush(int handle)
1068 {
1069 struct ConfigCmd cmd;
1070 int ret;
1071
1072 Mutex::Autolock autoLock(mLock);
1073
1074 if (mSensorState[handle].sensorType) {
1075 mSensorState[handle].flushCnt++;
1076
1077 initConfigCmd(&cmd, handle);
1078 cmd.cmd = CONFIG_CMD_FLUSH;
1079
1080 ret = TEMP_FAILURE_RETRY(write(mFd, &cmd, sizeof(cmd)));
1081 if (ret == sizeof(cmd))
1082 ALOGI("queueFlush: sensor=%d, handle=%d",
1083 cmd.sensorType, handle);
1084 else
1085 ALOGE("queueFlush: failed to send command: sensor=%d, handle=%d",
1086 cmd.sensorType, handle);
1087 } else {
1088 ALOGI("queueFlush: unhandled handle=%d", handle);
1089 }
1090 }
1091
queueDataInternal(int handle,void * data,size_t length)1092 void HubConnection::queueDataInternal(int handle, void *data, size_t length)
1093 {
1094 struct ConfigCmd *cmd = (struct ConfigCmd *)malloc(sizeof(struct ConfigCmd) + length);
1095 size_t ret;
1096
1097 if (cmd && mSensorState[handle].sensorType) {
1098 initConfigCmd(cmd, handle);
1099 memcpy(cmd->data, data, length);
1100 cmd->cmd = CONFIG_CMD_CFG_DATA;
1101
1102 ret = TEMP_FAILURE_RETRY(write(mFd, cmd, sizeof(*cmd) + length));
1103 if (ret == sizeof(*cmd) + length)
1104 ALOGI("queueData: sensor=%d, length=%zu",
1105 cmd->sensorType, length);
1106 else
1107 ALOGE("queueData: failed to send command: sensor=%d, length=%zu",
1108 cmd->sensorType, length);
1109 free(cmd);
1110 } else {
1111 ALOGI("queueData: unhandled handle=%d", handle);
1112 }
1113 }
1114
queueData(int handle,void * data,size_t length)1115 void HubConnection::queueData(int handle, void *data, size_t length)
1116 {
1117 Mutex::Autolock autoLock(mLock);
1118 queueDataInternal(handle, data, length);
1119 }
1120
initNanohubLock()1121 void HubConnection::initNanohubLock() {
1122 // Create the lock directory (if it doesn't already exist)
1123 if (mkdir(NANOHUB_LOCK_DIR, NANOHUB_LOCK_DIR_PERMS) < 0 && errno != EEXIST) {
1124 ALOGE("Couldn't create Nanohub lock directory: %s", strerror(errno));
1125 return;
1126 }
1127
1128 mInotifyPollIndex = -1;
1129 int inotifyFd = inotify_init1(IN_NONBLOCK);
1130 if (inotifyFd < 0) {
1131 ALOGE("Couldn't initialize inotify: %s", strerror(errno));
1132 } else if (inotify_add_watch(inotifyFd, NANOHUB_LOCK_DIR, IN_CREATE | IN_DELETE) < 0) {
1133 ALOGE("Couldn't add inotify watch: %s", strerror(errno));
1134 close(inotifyFd);
1135 } else {
1136 mPollFds[mNumPollFds].fd = inotifyFd;
1137 mPollFds[mNumPollFds].events = POLLIN;
1138 mPollFds[mNumPollFds].revents = 0;
1139 mInotifyPollIndex = mNumPollFds;
1140 mNumPollFds++;
1141 }
1142 }
1143
1144 #ifdef USB_MAG_BIAS_REPORTING_ENABLED
queueUsbMagBias()1145 void HubConnection::queueUsbMagBias()
1146 {
1147 struct MsgCmd *cmd = (struct MsgCmd *)malloc(sizeof(struct MsgCmd) + sizeof(float));
1148 size_t ret;
1149
1150 if (cmd) {
1151 cmd->evtType = EVT_APP_FROM_HOST;
1152 cmd->msg.appId = APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, APP_ID_APP_BMI160);
1153 cmd->msg.dataLen = sizeof(float);
1154 memcpy((float *)(cmd+1), &mUsbMagBias, sizeof(float));
1155
1156 ret = TEMP_FAILURE_RETRY(write(mFd, cmd, sizeof(*cmd) + sizeof(float)));
1157 if (ret == sizeof(*cmd) + sizeof(float))
1158 ALOGI("queueUsbMagBias: bias=%f\n", mUsbMagBias);
1159 else
1160 ALOGE("queueUsbMagBias: failed to send command: bias=%f\n", mUsbMagBias);
1161 free(cmd);
1162 }
1163 }
1164 #endif // USB_MAG_BIAS_REPORTING_ENABLED
1165
1166 #ifdef LID_STATE_REPORTING_ENABLED
initializeUinputNode()1167 status_t HubConnection::initializeUinputNode()
1168 {
1169 int ret = 0;
1170
1171 // Open uinput dev node
1172 mUinputFd = TEMP_FAILURE_RETRY(open("/dev/uinput", O_WRONLY | O_NONBLOCK));
1173 if (mUinputFd < 0) {
1174 ALOGE("could not open uinput node: %s", strerror(errno));
1175 return UNKNOWN_ERROR;
1176 }
1177
1178 // Enable SW_LID events
1179 ret = TEMP_FAILURE_RETRY(ioctl(mUinputFd, UI_SET_EVBIT, EV_SW));
1180 ret |= TEMP_FAILURE_RETRY(ioctl(mUinputFd, UI_SET_EVBIT, EV_SYN));
1181 ret |= TEMP_FAILURE_RETRY(ioctl(mUinputFd, UI_SET_SWBIT, SW_LID));
1182 if (ret < 0) {
1183 ALOGE("could not send ioctl to uinput node: %s", strerror(errno));
1184 return UNKNOWN_ERROR;
1185 }
1186
1187 // Create uinput node for SW_LID
1188 struct uinput_user_dev uidev;
1189 memset(&uidev, 0, sizeof(uidev));
1190 snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-folio");
1191 uidev.id.bustype = BUS_SPI;
1192 uidev.id.vendor = 0;
1193 uidev.id.product = 0;
1194 uidev.id.version = 0;
1195
1196 ret = TEMP_FAILURE_RETRY(write(mUinputFd, &uidev, sizeof(uidev)));
1197 if (ret < 0) {
1198 ALOGE("write to uinput node failed: %s", strerror(errno));
1199 return UNKNOWN_ERROR;
1200 }
1201
1202 ret = TEMP_FAILURE_RETRY(ioctl(mUinputFd, UI_DEV_CREATE));
1203 if (ret < 0) {
1204 ALOGE("could not send ioctl to uinput node: %s", strerror(errno));
1205 return UNKNOWN_ERROR;
1206 }
1207
1208 return OK;
1209 }
1210
sendFolioEvent(int32_t data)1211 void HubConnection::sendFolioEvent(int32_t data) {
1212 ssize_t ret = 0;
1213 struct input_event ev;
1214
1215 memset(&ev, 0, sizeof(ev));
1216
1217 ev.type = EV_SW;
1218 ev.code = SW_LID;
1219 ev.value = data;
1220 ret = TEMP_FAILURE_RETRY(write(mUinputFd, &ev, sizeof(ev)));
1221 if (ret < 0) {
1222 ALOGE("write to uinput node failed: %s", strerror(errno));
1223 return;
1224 }
1225
1226 // Force flush with EV_SYN event
1227 ev.type = EV_SYN;
1228 ev.code = SYN_REPORT;
1229 ev.value = 0;
1230 ret = TEMP_FAILURE_RETRY(write(mUinputFd, &ev, sizeof(ev)));
1231 if (ret < 0) {
1232 ALOGE("write to uinput node failed: %s", strerror(errno));
1233 return;
1234 }
1235
1236 // Set lid state property
1237 if (property_set(LID_STATE_PROPERTY,
1238 (data ? LID_STATE_CLOSED : LID_STATE_OPEN)) < 0) {
1239 ALOGE("could not set lid_state property");
1240 }
1241 }
1242 #endif // LID_STATE_REPORTING_ENABLED
1243
1244 } // namespace android
1245