OSDN Git Service

9259b14fbe0f919fa31780a9bf3279f6cab56f10
[android-x86/hardware-intel-libsensors.git] / common / libsensors / SensorIIODev.cpp
1 /*
2  * Copyright (C) 2010-2012 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 #include <dirent.h>
17 #include <fcntl.h>
18 #include <cutils/log.h>
19 #include "SensorIIODev.h"
20 #include "Helpers.h"
21
22 static const std::string IIO_DIR = "/sys/bus/iio/devices";
23 static const int DEF_BUFFER_LEN = 2;
24 static const int DEF_HYST_VALUE = 0;
25
26 SensorIIODev::SensorIIODev(const std::string& dev_name, const std::string& units,
27                            const std::string& exponent,
28                            const std::string& channel_prefix, int retry_cnt)
29              : SensorBase(""),
30                initialized(false),
31                unit_expo_str(exponent),
32                unit_str(units),
33                device_name(dev_name),
34                channel_prefix_str(channel_prefix),
35                unit_expo_value(0),
36                units_value(0),
37                retry_count(retry_cnt),
38                raw_buffer(NULL),
39                sample_delay_min_ms(0)
40 {
41     ALOGV("%s", __func__);
42 }
43
44 SensorIIODev::SensorIIODev(const std::string& dev_name, const std::string& units,
45                            const std::string& exponent,
46                            const std::string& channel_prefix)
47              : SensorBase(""),
48                initialized(false),
49                unit_expo_str(exponent),
50                unit_str(units),
51                device_name(dev_name),
52                channel_prefix_str(channel_prefix),
53                unit_expo_value(0),
54                units_value(0),
55                retry_count(1),
56                raw_buffer(NULL)
57 {
58
59     ALOGV("%s", __func__);
60 }
61
62 int SensorIIODev::discover()
63 {
64     int cnt;
65     int status;
66     int ret;
67
68     ALOGD(">>%s discover", __func__);
69     for (cnt = 0; cnt < retry_count; cnt++) {
70         status = ParseIIODirectory(device_name);
71         if (status >= 0){
72             std::stringstream filename;
73             initialized = true;
74             filename << "/dev/iio:device" << device_number;
75             mDevPath = filename.str();
76             ALOGV("mDevPath %s", mDevPath.c_str());
77             ret = 0;
78             break;
79         }
80         else{
81             ALOGE("Sensor IIO Init failed, retry left:%d\n", retry_count-cnt);
82             mDevPath = "";
83             ret = -1;
84         }
85         // Device not enumerated yet, wait and retry
86         sleep(1);
87     }
88     return ret;
89 }
90
91 int SensorIIODev::AllocateRxBuffer()
92 {
93     ALOGV(">>%s Allocate:%d", __func__, datum_size * buffer_len);
94     raw_buffer = new unsigned char[datum_size * buffer_len];
95     if (!raw_buffer) {
96         ALOGE("AllocateRxBuffer: Failed\n");
97         return -ENOMEM;
98     }
99     return 0;
100 }
101
102 int SensorIIODev::FreeRxBuffer()
103 {
104     ALOGV(">>%s", __func__);
105     delete []raw_buffer;
106     raw_buffer = NULL;
107     return 0;
108 }
109
110 int SensorIIODev::enable(int enabled)
111 {
112     int ret =0;
113
114     ALOGD(">>%s enabled:%d", __func__, enabled);
115
116     if (mEnabled == enabled) {
117         return 0;
118     }
119     if (enabled){
120         // QUIRK: some sensor hubs need to be turned on and off and on
121         // before sending any information. So we turn it on and off first
122         // before enabling again later in this function.
123         EnableBuffer(1);
124         EnableBuffer(0);
125
126         if (ReadHIDExponentValue(&unit_expo_value) < 0)
127             goto err_ret;
128         if (ReadHIDMeasurmentUnit(&units_value) < 0)
129             goto err_ret;
130         if (SetDataReadyTrigger(GetDeviceNumber(), true) < 0)
131             goto err_ret;
132         if (EnableBuffer(1) < 0)
133             goto err_ret;
134         if (DeviceActivate(GetDeviceNumber(), 1) < 0)
135             goto err_ret;
136         if (DeviceSetSensitivity(GetDeviceNumber(), DEF_HYST_VALUE) < 0)
137             goto err_ret;
138         if (AllocateRxBuffer() < 0)
139             goto err_ret;
140         mEnabled = enabled;
141     }
142     else{
143         mEnabled = enabled;
144         if (SetDataReadyTrigger(GetDeviceNumber(), false) < 0)
145             goto err_ret;
146         if (EnableBuffer(0) < 0)
147             goto err_ret;
148         if (DeviceActivate(GetDeviceNumber(), 0) < 0)
149             goto err_ret;
150         if (DeviceSetSensitivity(GetDeviceNumber(), 0))
151             goto err_ret;
152         if (FreeRxBuffer() < 0)
153             goto err_ret;
154         mDevPath = "";
155     }
156     return 0;
157
158 err_ret:
159     ALOGE("SesnorIIO: Enable failed\n");
160     return -1;
161 }
162
163 int SensorIIODev::setDelay(int64_t delay_ns){
164     int ms = nsToMs(delay_ns);
165     int r;
166
167     ALOGV(">>%s %ld", __func__, delay_ns);
168     if (IsDeviceInitialized() == false){
169         ALOGE("Device was not initialized \n");
170         return  -EFAULT;
171     }
172     if (ms){
173         if ((r = SetSampleDelay(GetDeviceNumber(), ms)) < 0)
174             return r;
175     }
176     ALOGV("<<%s", __func__);
177     return 0;
178 }
179
180 int SensorIIODev::setInitialState(){
181     mHasPendingEvent = false;
182     return 0;
183 }
184
185 long SensorIIODev::GetUnitValue()
186 {
187     return units_value;
188 }
189
190 long SensorIIODev::GetExponentValue()
191 {
192     return unit_expo_value;
193 }
194
195 bool SensorIIODev::IsDeviceInitialized(){
196     return initialized;
197 }
198
199 int SensorIIODev::GetDeviceNumber(){
200     return device_number;
201 }
202
203 int SensorIIODev::GetDir(const std::string& dir, std::vector < std::string >& files){
204     DIR *dp;
205     struct dirent *dirp;
206
207     if ((dp = opendir(dir.c_str())) == NULL){
208         ALOGE("Error opening directory %s\n", (char*)dir.c_str());
209         return errno;
210     }
211     while ((dirp = readdir(dp)) != NULL){
212         files.push_back(std::string(dirp->d_name));
213     }
214     closedir(dp);
215     return 0;
216 }
217
218 void SensorIIODev::ListFiles(const std::string& dir){
219     std::vector < std::string > files = std::vector < std::string > ();
220
221     GetDir(dir, files);
222
223     for (unsigned int i = 0; i < files.size(); i++){
224         ALOGV("File List.. %s\n", (char*)files[i].c_str());
225     }
226 }
227
228 // This function returns a device number for IIO device
229 // For example if the device is "iio:device1", this will return 1
230 int SensorIIODev::FindDeviceNumberFromName(const std::string& name, const std::string&
231     prefix){
232     int dev_number;
233     std::vector < std::string > files = std::vector < std::string > ();
234     std::string device_name;
235
236     GetDir(std::string(IIO_DIR), files);
237
238     for (unsigned int i = 0; i < files.size(); i++){
239         std::stringstream ss;
240         if ((files[i] == ".") || (files[i] == "..") || files[i].length() <=
241             prefix.length())
242             continue;
243
244         if (files[i].compare(0, prefix.length(), prefix) == 0){
245             sscanf(files[i].c_str() + prefix.length(), "%d", &dev_number);
246         }
247         ss << IIO_DIR << "/" << prefix << dev_number;
248         std::ifstream ifs(ss.str().c_str(), std::ifstream::in);
249         if (!ifs.good()){
250             dev_number =  -1;
251             ifs.close();
252             continue;
253         }
254         ifs.close();
255
256         std::ifstream ifn((ss.str() + "/" + "name").c_str(), std::ifstream::in);
257
258         if (!ifn.good()){
259             dev_number =  -1;
260             ifn.close();
261             continue;
262         }
263         std::getline(ifn, device_name);
264         if (name.compare(device_name) == 0){
265             ALOGV("matched %s\n", device_name.c_str());
266             ifn.close();
267             return dev_number;
268         }
269         ifn.close();
270
271     }
272     return  -EFAULT;
273 }
274
275 // Setup Trigger
276 int SensorIIODev::SetUpTrigger(int dev_num){
277     std::stringstream trigger_name;
278     int trigger_num;
279
280     trigger_name << device_name << "-dev" << dev_num;
281     if (trigger_name.str().length()){
282         ALOGV("trigger_name %s\n", (char*)trigger_name.str().c_str());
283         trigger_num = FindDeviceNumberFromName(trigger_name.str(), "trigger");
284         if (trigger_num < 0){
285             ALOGE("Failed to find trigger\n");
286             return  -EFAULT;
287         }
288     }
289     else{
290         ALOGE("trigger_name not found \n");
291         return  -EFAULT;
292     }
293     return 0;
294 }
295
296 // Setup buffer length in terms of datum size
297 int SensorIIODev::SetUpBufferLen(int len){
298     std::stringstream filename;
299     std::stringstream len_str;
300
301     ALOGV("%s: len:%d", __func__, len);
302
303     filename << buffer_dir_name.str() << "/" << "length";
304
305     PathOps path_ops;
306     len_str << len;
307     int ret = path_ops.write(filename.str(), len_str.str());
308     if (ret < 0) {
309         ALOGE("Write Error %s", filename.str().c_str());
310         return ret;
311     }
312     buffer_len = len;
313     return 0;
314 }
315
316 // Enable buffer
317 int SensorIIODev::EnableBuffer(int status){
318     std::stringstream filename;
319     std::stringstream status_str;
320
321     ALOGV("%s: len:%d", __func__, status);
322
323     filename << buffer_dir_name.str() << "/" << "enable";
324     PathOps path_ops;
325     status_str << status;
326     int ret = path_ops.write(filename.str(), status_str.str());
327     if (ret < 0) {
328         ALOGE("Write Error %s", filename.str().c_str());
329         return ret;
330     }
331     enable_buffer = status;
332     return 0;
333 }
334
335 int SensorIIODev::EnableChannels(){
336     int ret = 0;
337     int count;
338     int counter = 0;
339     std::string dir = std::string(IIO_DIR);
340     std::vector < std::string > files = std::vector < std::string > ();
341     const std::string FORMAT_SCAN_ELEMENTS_DIR = "/scan_elements";
342     unsigned char signchar, bits_used, total_bits, shift, unused;
343     SensorIIOChannel iio_channel;
344
345     ALOGV(">>%s", __func__);
346     scan_el_dir.str(std::string());
347     scan_el_dir << dev_device_name.str() << FORMAT_SCAN_ELEMENTS_DIR;
348     GetDir(scan_el_dir.str(), files);
349
350     for (unsigned int i = 0; i < files.size(); i++){
351         int len = files[i].length();
352         if (len > 3 && files[i].compare(len - 3, 3, "_en") == 0){
353             std::stringstream filename, file_type;
354             PathOps path_ops;
355
356             filename << scan_el_dir.str() << "/" << files[i];
357             ret = path_ops.write(filename.str(), "1");
358             if (ret < 0)
359               ALOGE("Channel Enable Error %s:%d", filename.str().c_str(), ret);
360         }
361     }
362     return ret;
363 }
364
365 int SensorIIODev::BuildChannelList(){
366     int ret;
367     int count;
368     int counter = 0;
369     std::string dir = std::string(IIO_DIR);
370     std::vector < std::string > files = std::vector < std::string > ();
371     const std::string FORMAT_SCAN_ELEMENTS_DIR = "/scan_elements";
372     unsigned char signchar, bits_used, total_bits, shift, unused;
373     SensorIIOChannel iio_channel;
374     std::string type_name;
375
376     ALOGV(">>%s", __func__);
377     scan_el_dir.str(std::string());
378     scan_el_dir << dev_device_name.str() << FORMAT_SCAN_ELEMENTS_DIR;
379     GetDir(scan_el_dir.str(), files);
380
381     // File ending with _en will specify a channel
382     // it contains the count. If we add all these count
383     // those many channels present
384     info_array.clear();
385     for (unsigned int i = 0; i < files.size(); i++){
386         int len = files[i].length();
387         // At the least the length should be more than 3 for "_en"
388         if (len > 3 && files[i].compare(len - 3, 3, "_en") == 0){
389             std::stringstream filename, file_type;
390             filename << scan_el_dir.str() << "/" << files[i];
391             std::ifstream ifs(filename.str().c_str(), std::ifstream::in);
392
393             if (!ifs.good()){
394                 ifs.close();
395                 continue;
396             }
397             count = ifs.get() - '0';
398             if (count == 1)
399                 counter++;
400             ifs.close();
401
402             iio_channel.enabled = 1;
403             iio_channel.scale = 1.0;
404             iio_channel.offset = 0;
405
406             iio_channel.name = files[i].substr(0, files[i].length() - 3);
407
408             ALOGV("IIO channel name:%s\n", (char*)iio_channel.name.c_str());
409             file_type << scan_el_dir.str() << "/" << iio_channel.name <<
410                 "_type";
411
412             std::ifstream its(file_type.str().c_str(), std::ifstream::in);
413             if (!its.good()){
414                 its.close();
415                 continue;
416             }
417             std::getline(its, type_name);
418             sscanf(type_name.c_str(), "%c%c%c%c%u/%u>>%u", (unsigned char*) &unused,
419                 (unsigned char*) &unused, (unsigned char*) &unused, (unsigned
420                 char*) &signchar, (unsigned int*) &bits_used, (unsigned int*)
421                 &total_bits, (unsigned int*) &shift);
422
423             its.close();
424             // Buggy sscanf on some platforms
425             if (total_bits == 0 || bits_used == 0){
426                 if (!strcmp(type_name.c_str(), "le:s16/32")){
427                     total_bits = 32;
428                     bits_used = 16;
429                 }
430                 else if (!strcmp(type_name.c_str(), "le:s16/16")){
431                     total_bits = 16;
432                     bits_used = 16;
433                 }
434                 else{
435                     total_bits = 32;
436                     bits_used = 16;
437                 }
438             }
439
440             iio_channel.bytes = total_bits / 8;
441             iio_channel.real_bytes = bits_used / 8;
442             iio_channel.shift = shift;
443             iio_channel.is_signed = signchar;
444
445             // Add to list
446             info_array.push_back(iio_channel);
447         }
448     }
449     ALOGV("<<%s", __func__);
450     return counter;
451 }
452
453 int SensorIIODev::GetSizeFromChannels(){
454     int size = 0;
455     for (unsigned int i = 0; i < info_array.size(); i++){
456         SensorIIOChannel channel = info_array[i];
457         size += channel.bytes;
458     }
459     ALOGD("%s:%d:%d", __func__, info_array.size(), size);
460     return size;
461 }
462
463 int SensorIIODev::GetChannelBytesUsedSize(unsigned int channel_no){
464     if (channel_no < info_array.size()){
465         SensorIIOChannel channel = info_array[channel_no];
466         return channel.real_bytes;
467     }
468     else
469         return 0;
470 }
471
472 int SensorIIODev::ParseIIODirectory(const std::string& name){
473     int dev_num;
474     int ret;
475     int size;
476
477     ALOGV(">>%s", __func__);
478
479     dev_device_name.str(std::string());
480     buffer_dir_name.str(std::string());
481
482     device_number = dev_num = FindDeviceNumberFromName(name, "iio:device");
483     if (dev_num < 0){
484         ALOGE("Failed to  find device %s\n", (char*)name.c_str());
485         return  -EFAULT;
486     }
487
488     // Construct device directory Eg. /sys/devices/iio:device0
489     dev_device_name << IIO_DIR << "/" << "iio:device" << dev_num;
490
491     // Construct device directory Eg. /sys/devices/iio:device0:buffer0
492     buffer_dir_name << dev_device_name.str() << "/" << "buffer";
493
494     // Setup Trigger
495     ret = SetUpTrigger(dev_num);
496     if (ret < 0){
497         ALOGE("ParseIIODirectory Failed due to Trigger\n");
498         return  -EFAULT;
499     }
500
501     // Setup buffer len. This is in the datum units, not an absolute number
502     SetUpBufferLen(DEF_BUFFER_LEN);
503
504     // Set up channel masks
505     ret = EnableChannels();
506     if (ret < 0){
507         ALOGE("ParseIIODirectory Failed due Enable Channels failed\n");
508         if (ret == -EACCES) {
509             // EACCES means the nodes do not have current owner.
510             // Need to retry, or else sensors won't power on.
511             // Other errors can be ignored, as these nodes are
512             // set once, and will return error when set again.
513             return ret;
514         }
515     }
516
517     // Parse the channels and build a list
518     ret = BuildChannelList();
519     if (ret < 0){
520         ALOGE("ParseIIODirectory Failed due BuildChannelList\n");
521         return  -EFAULT;
522     }
523
524     datum_size = GetSizeFromChannels();
525     ALOGV("Datum Size %d", datum_size);
526     ALOGV("<<%s", __func__);
527     return 0;
528 }
529
530 // Set Data Ready
531 int SensorIIODev::SetDataReadyTrigger(int dev_num, bool status){
532     std::stringstream filename;
533     std::stringstream trigger_name;
534     int trigger_num;
535
536     ALOGV("%s: status:%d", __func__, status);
537
538     filename << dev_device_name.str() << "/trigger/current_trigger";
539     trigger_name << device_name << "-dev" << dev_num;
540
541     PathOps path_ops;
542     int ret;
543     if (status)
544         ret = path_ops.write(filename.str(), trigger_name.str());
545     else
546         ret = path_ops.write(filename.str(), " ");
547     if (ret < 0) {
548         ALOGE("Write Error %s:%d", filename.str().c_str(), ret);
549         // Ignore error, as this may be due to
550         // Trigger was active during resume
551     }
552     return 0;
553 }
554
555 // Activate device
556 int SensorIIODev::DeviceActivate(int dev_num, int state){
557     std::stringstream filename;
558     std::stringstream activate_str;
559
560     ALOGV("%s: Device Activate:%d", __func__, rate);
561     return 0;
562 }
563
564 // Set sensitivity in absolute terms
565 int SensorIIODev::DeviceSetSensitivity(int dev_num, int value){
566     std::stringstream filename;
567     std::stringstream sensitivity_str;
568
569     ALOGV("%s: Sensitivity :%d", __func__, value);
570
571     filename << IIO_DIR << "/" << "iio:device" << dev_num << "/" << channel_prefix_str << "hysteresis";
572
573     PathOps path_ops;
574     sensitivity_str << value;
575     int ret = path_ops.write(filename.str(), sensitivity_str.str());
576     if (ret < 0) {
577         ALOGE("Write Error %s", filename.str().c_str());
578         // Don't bail out as this  field may be absent
579     }
580     return 0;
581 }
582
583 // Set the sample period delay: units ms
584 int SensorIIODev::SetSampleDelay(int dev_num, int period){
585     std::stringstream filename;
586     std::stringstream sample_rate_str;
587
588     ALOGV("%s: sample_rate:%d", __func__, rate);
589
590     if (sample_delay_min_ms && period < sample_delay_min_ms)
591         period = sample_delay_min_ms;
592
593     filename << IIO_DIR << "/" << "iio:device" << dev_num << "/" << channel_prefix_str << "sampling_frequency";
594     if (period <= 0) {
595         ALOGE("%s: Invalid_rate:%d", __func__, period);
596     }
597     PathOps path_ops;
598     sample_rate_str << 1000/period;
599     int ret = path_ops.write(filename.str(), sample_rate_str.str());
600     if (ret < 0) {
601         ALOGE("Write Error %s", filename.str().c_str());
602         // Don't bail out as this  field may be absent
603     }
604     return 0;
605 }
606
607 int SensorIIODev::readEvents(sensors_event_t *data, int count){
608     ssize_t read_size;
609     int numEventReceived;
610
611     if (count < 1)
612         return  - EINVAL;
613
614     if (mFd < 0)
615         return  - EBADF;
616
617     if (!raw_buffer)
618         return - EAGAIN;
619
620     if (mHasPendingEvent){
621         mHasPendingEvent = false;
622         mPendingEvent.timestamp = getTimestamp();
623         *data = mPendingEvent;
624         return 1;
625     }
626     read_size = read(mFd, raw_buffer, datum_size * buffer_len);
627     numEventReceived = 0;
628     if (processEvent(raw_buffer, datum_size) >= 0){
629         mPendingEvent.timestamp = getTimestamp();
630         mPendingEvent.timestamp = getTimestamp();
631         *data = mPendingEvent;
632         numEventReceived++;
633     }
634     return numEventReceived;
635 }
636
637 int SensorIIODev::ReadHIDMeasurmentUnit(long *unit){
638     std::stringstream filename;
639     int size;
640     std::string long_str;
641
642     filename << IIO_DIR << "/" << "iio:device" << device_number << "/" << unit_str;
643
644     std::ifstream its(filename.str().c_str(), std::ifstream::in);
645     if (!its.good()){
646         ALOGE("%s: Can't Open :%s",
647                 __func__, filename.str().c_str());
648         its.close();
649         return -EINVAL;
650     }
651     std::getline(its, long_str);
652     its.close();
653
654     if (long_str.length() > 0){
655         *unit = atol(long_str.c_str());
656         return 0;
657     }
658     ALOGE("ReadHIDMeasurmentUnit failed");
659     return  -EINVAL;
660 }
661
662 int SensorIIODev::ReadHIDExponentValue(long *exponent){
663     std::stringstream filename;
664     int size;
665     std::string long_str;
666
667     filename << IIO_DIR << "/" << "iio:device" << device_number << "/" << unit_expo_str;
668
669     std::ifstream its(filename.str().c_str(), std::ifstream::in);
670     if (!its.good()){
671         ALOGE("%s: Can't Open :%s",
672                __func__, filename.str().c_str());
673         its.close();
674         return -EINVAL;
675     }
676     std::getline(its, long_str);
677     its.close();
678
679     if (long_str.length() > 0){
680         *exponent = atol(long_str.c_str());
681         return 0;
682     }
683     ALOGE("ReadHIDExponentValue failed");
684     return  -EINVAL;
685 }