Home | History | Annotate | Download | only in mraa
      1 /*
      2  * Copyright (C) 2015 Intel Corporation
      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 <cutils/log.h>
     18 #include <sys/epoll.h>
     19 #include <string.h>
     20 #include <errno.h>
     21 #include <hardware/sensors.h>
     22 #include "AcquisitionThread.hpp"
     23 #include "Utils.hpp"
     24 
     25 void* AcquisitionThread::acquisitionRoutine(void *param) {
     26   AcquisitionThread *acquisitionThread = reinterpret_cast<AcquisitionThread *>(param);
     27   Sensor *sensor = nullptr;
     28   int64_t timestamp = 0;
     29   struct timespec target_time;
     30   int rc = 0;
     31   sensors_event_t data;
     32 
     33   if (acquisitionThread == nullptr) {
     34     ALOGE("%s: The acquisition thread was not initialized", __func__);
     35     return nullptr;
     36   }
     37 
     38   sensor = acquisitionThread->sensor;
     39   if (sensor == nullptr) {
     40     ALOGE("%s: The acquisition thread doesn't have an associated sensor", __func__);
     41     return nullptr;
     42   }
     43 
     44   /* initialize sensor data structure */
     45   memset(&data, 0, sizeof(sensors_event_t));
     46   data.version = sizeof(sensors_event_t);
     47   data.sensor = sensor->getHandle();
     48   data.type = sensor->getType();
     49 
     50   pthread_mutex_lock(&acquisitionThread->pthreadMutex);
     51 
     52   /* get current timestamp */
     53   timestamp = get_timestamp_monotonic();
     54 
     55   /* loop until the thread is canceled */
     56   while(acquisitionThread->getWritePipeFd() != -1) {
     57     /* get one event from the sensor */
     58     if (sensor->pollEvents(&data, 1) != 1) {
     59       ALOGE("%s: Sensor %d: Cannot read data", __func__, data.sensor);
     60       goto exit;
     61     }
     62 
     63     /* send the data over the pipe to the main thread */
     64     rc = write(acquisitionThread->getWritePipeFd(), &data, sizeof(sensors_event_t));
     65     if (rc != sizeof(sensors_event_t)) {
     66       ALOGE("%s: Sensor %d: Cannot write data to pipe", __func__, data.sensor);
     67       goto exit;
     68     }
     69 
     70     if (acquisitionThread->getWritePipeFd() == -1) {
     71       ALOGE("%s: Sensor %d: The write pipe file descriptor is invalid", __func__, data.sensor);
     72       goto exit;
     73     }
     74 
     75     timestamp += sensor->getDelay();
     76     set_timestamp(&target_time, timestamp);
     77     pthread_cond_timedwait(&acquisitionThread->pthreadCond, &acquisitionThread->pthreadMutex, &target_time);
     78   }
     79 
     80 exit:
     81   pthread_mutex_unlock(&acquisitionThread->pthreadMutex);
     82   return nullptr;
     83 }
     84 
     85 AcquisitionThread::AcquisitionThread(int pollFd, Sensor *sensor)
     86     : pollFd(pollFd), sensor(sensor), initialized(false) {
     87   pipeFds[0] = pipeFds[1] = -1;
     88 }
     89 
     90 bool AcquisitionThread::init() {
     91   struct epoll_event ev;
     92   int rc;
     93 
     94   memset(&ev, 0, sizeof(ev));
     95 
     96   if (initialized) {
     97     ALOGE("%s: acquisition thread already initialized", __func__);
     98     return false;
     99   }
    100 
    101   /* create condition variable & mutex for quick thread release */
    102   rc = pthread_condattr_init(&pthreadCondAttr);
    103   if (rc != 0) {
    104     ALOGE("%s: Cannot initialize the pthread condattr", __func__);
    105     return false;
    106   }
    107   rc = pthread_condattr_setclock(&pthreadCondAttr, CLOCK_MONOTONIC);
    108   if (rc != 0) {
    109     ALOGE("%s: Cannot set the clock of condattr to monotonic", __func__);
    110     return false;
    111   }
    112   rc = pthread_cond_init(&pthreadCond, &pthreadCondAttr);
    113   if (rc != 0) {
    114     ALOGE("%s: Cannot intialize the pthread structure", __func__);
    115     return false;
    116   }
    117   rc = pthread_mutex_init(&pthreadMutex, nullptr);
    118   if (rc != 0) {
    119     ALOGE("%s: Cannot initialize the mutex associated with the pthread cond", __func__);
    120     goto mutex_err;
    121   }
    122 
    123   /* create pipe to signal events to the main thread */
    124   rc = pipe2(pipeFds, O_NONBLOCK);
    125   if (rc != 0) {
    126     ALOGE("%s: Cannot initialize pipe", __func__);
    127     goto pipe_err;
    128   }
    129 
    130   ev.events = EPOLLIN;
    131   ev.data.u32 = sensor->getHandle();
    132 
    133   /* add read pipe fd to pollFd */
    134   rc = epoll_ctl(pollFd, EPOLL_CTL_ADD, pipeFds[0] , &ev);
    135   if (rc != 0) {
    136     ALOGE("%s: Cannot add the read file descriptor to poll set", __func__);
    137     goto epoll_err;
    138   }
    139 
    140   /* launch the thread */
    141   rc = pthread_create(&pthread, nullptr, acquisitionRoutine, (void *)this);
    142   if (rc != 0) {
    143     ALOGE("%s: Cannot create acquisition pthread", __func__);
    144     goto thread_create_err;
    145   }
    146 
    147   initialized = true;
    148   return true;
    149 
    150 thread_create_err:
    151   epoll_ctl(pollFd, EPOLL_CTL_DEL, pipeFds[0], nullptr);
    152 epoll_err:
    153   close(pipeFds[0]);
    154   close(pipeFds[1]);
    155   pipeFds[0] = pipeFds[1] = -1;
    156 pipe_err:
    157   pthread_mutex_destroy(&pthreadMutex);
    158 mutex_err:
    159   pthread_cond_destroy(&pthreadCond);
    160   return false;
    161 }
    162 
    163 bool AcquisitionThread::generateFlushCompleteEvent() {
    164   sensors_event_t data;
    165   int rc;
    166 
    167   if (!initialized) {
    168     return false;
    169   }
    170 
    171   /* batching is not supported; return one META_DATA_FLUSH_COMPLETE event */
    172   memset(&data, 0, sizeof(sensors_event_t));
    173   data.version = META_DATA_VERSION;
    174   data.type = SENSOR_TYPE_META_DATA;
    175   data.meta_data.sensor = sensor->getHandle();
    176   data.meta_data.what = META_DATA_FLUSH_COMPLETE;
    177 
    178   /*
    179    * Send the event via the associated pipe. It doesn't need to be in a loop
    180    * as O_NONBLOCK is enabled and the number of bytes is <= PIPE_BUF.
    181    * If there is room to write n bytes to the pipe, then write succeeds
    182    * immediately, writing all n bytes; otherwise write fails.
    183    */
    184   rc = write(getWritePipeFd(), &data, sizeof(sensors_event_t));
    185   if (rc != sizeof(sensors_event_t)) {
    186     ALOGE("%s: not all data has been sent over the pipe", __func__);
    187     return false;
    188   }
    189 
    190   return true;
    191 }
    192 
    193 int AcquisitionThread::wakeup() {
    194   if (initialized) {
    195     return pthread_cond_signal(&pthreadCond);
    196   }
    197 
    198   return -EINVAL;
    199 }
    200 
    201 AcquisitionThread::~AcquisitionThread() {
    202   int readPipeEnd, writePipeEnd;
    203 
    204   if (initialized) {
    205     readPipeEnd = pipeFds[0];
    206     writePipeEnd = pipeFds[1];
    207     epoll_ctl(pollFd, EPOLL_CTL_DEL, readPipeEnd, nullptr);
    208 
    209     /* take the mutex to correctly signal the thread */
    210     pthread_mutex_lock(&pthreadMutex);
    211     pipeFds[0] = pipeFds[1] = -1;
    212     close(readPipeEnd);
    213     close(writePipeEnd);
    214 
    215     /* wakeup and wait for the thread */
    216     pthread_cond_signal(&pthreadCond);
    217     pthread_mutex_unlock(&pthreadMutex);
    218     pthread_join(pthread, nullptr);
    219 
    220     pthread_cond_destroy(&pthreadCond);
    221     pthread_mutex_destroy(&pthreadMutex);
    222   }
    223 }
    224