OSDN Git Service

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