2 * Copyright (C) 2010-2012 Intel Corporation
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <cutils/log.h>
19 #include "SensorIIODev.h"
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;
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)
31 unit_expo_str(exponent),
33 device_name(dev_name),
34 channel_prefix_str(channel_prefix),
37 retry_count(retry_cnt),
41 ALOGV("%s", __func__);
44 SensorIIODev::SensorIIODev(const std::string& dev_name, const std::string& units,
45 const std::string& exponent,
46 const std::string& channel_prefix)
49 unit_expo_str(exponent),
51 device_name(dev_name),
52 channel_prefix_str(channel_prefix),
59 ALOGV("%s", __func__);
62 int SensorIIODev::discover()
68 ALOGD(">>%s discover", __func__);
69 for (cnt = 0; cnt < retry_count; cnt++) {
70 status = ParseIIODirectory(device_name);
72 std::stringstream filename;
74 filename << "/dev/iio:device" << device_number;
75 mDevPath = filename.str();
76 ALOGV("mDevPath %s", mDevPath.c_str());
81 ALOGE("Sensor IIO Init failed, retry left:%d\n", retry_count-cnt);
85 // Device not enumerated yet, wait and retry
91 int SensorIIODev::AllocateRxBuffer()
93 ALOGV(">>%s Allocate:%d", __func__, datum_size * buffer_len);
94 raw_buffer = new unsigned char[datum_size * buffer_len];
96 ALOGE("AllocateRxBuffer: Failed\n");
102 int SensorIIODev::FreeRxBuffer()
104 ALOGV(">>%s", __func__);
110 int SensorIIODev::enable(int enabled)
114 ALOGD(">>%s enabled:%d", __func__, enabled);
116 if (mEnabled == enabled) {
120 if (ReadHIDExponentValue(&unit_expo_value) < 0)
122 if (ReadHIDMeasurmentUnit(&units_value) < 0)
124 if (SetDataReadyTrigger(GetDeviceNumber(), true) < 0)
126 if (EnableBuffer(1) < 0)
128 if (DeviceActivate(GetDeviceNumber(), 1) < 0)
130 if (DeviceSetSensitivity(GetDeviceNumber(), DEF_HYST_VALUE) < 0)
132 if (AllocateRxBuffer() < 0)
138 if (SetDataReadyTrigger(GetDeviceNumber(), false) < 0)
140 if (EnableBuffer(0) < 0)
142 if (DeviceActivate(GetDeviceNumber(), 0) < 0)
144 if (DeviceSetSensitivity(GetDeviceNumber(), 0))
146 if (FreeRxBuffer() < 0)
153 ALOGE("SesnorIIO: Enable failed\n");
157 int SensorIIODev::setDelay(int64_t delay_ns){
158 int ms = nsToMs(delay_ns);
161 ALOGV(">>%s %ld", __func__, delay_ns);
162 if (IsDeviceInitialized() == false){
163 ALOGE("Device was not initialized \n");
167 if ((r = SetSampleDelay(GetDeviceNumber(), ms)) < 0)
170 ALOGV("<<%s", __func__);
174 int SensorIIODev::setInitialState(){
175 mHasPendingEvent = false;
179 long SensorIIODev::GetUnitValue()
184 long SensorIIODev::GetExponentValue()
186 return unit_expo_value;
189 bool SensorIIODev::IsDeviceInitialized(){
193 int SensorIIODev::GetDeviceNumber(){
194 return device_number;
197 int SensorIIODev::GetDir(const std::string& dir, std::vector < std::string >& files){
201 if ((dp = opendir(dir.c_str())) == NULL){
202 ALOGE("Error opening directory %s\n", (char*)dir.c_str());
205 while ((dirp = readdir(dp)) != NULL){
206 files.push_back(std::string(dirp->d_name));
212 void SensorIIODev::ListFiles(const std::string& dir){
213 std::vector < std::string > files = std::vector < std::string > ();
217 for (unsigned int i = 0; i < files.size(); i++){
218 ALOGV("File List.. %s\n", (char*)files[i].c_str());
222 // This function returns a device number for IIO device
223 // For example if the device is "iio:device1", this will return 1
224 int SensorIIODev::FindDeviceNumberFromName(const std::string& name, const std::string&
227 std::vector < std::string > files = std::vector < std::string > ();
228 std::string device_name;
230 GetDir(std::string(IIO_DIR), files);
232 for (unsigned int i = 0; i < files.size(); i++){
233 std::stringstream ss;
234 if ((files[i] == ".") || (files[i] == "..") || files[i].length() <=
238 if (files[i].compare(0, prefix.length(), prefix) == 0){
239 sscanf(files[i].c_str() + prefix.length(), "%d", &dev_number);
241 ss << IIO_DIR << "/" << prefix << dev_number;
242 std::ifstream ifs(ss.str().c_str(), std::ifstream::in);
250 std::ifstream ifn((ss.str() + "/" + "name").c_str(), std::ifstream::in);
257 std::getline(ifn, device_name);
258 if (name.compare(device_name) == 0){
259 ALOGV("matched %s\n", device_name.c_str());
270 int SensorIIODev::SetUpTrigger(int dev_num){
271 std::stringstream trigger_name;
274 trigger_name << device_name << "-dev" << dev_num;
275 if (trigger_name.str().length()){
276 ALOGV("trigger_name %s\n", (char*)trigger_name.str().c_str());
277 trigger_num = FindDeviceNumberFromName(trigger_name.str(), "trigger");
278 if (trigger_num < 0){
279 ALOGE("Failed to find trigger\n");
284 ALOGE("trigger_name not found \n");
290 // Setup buffer length in terms of datum size
291 int SensorIIODev::SetUpBufferLen(int len){
292 std::stringstream filename;
293 std::stringstream len_str;
295 ALOGV("%s: len:%d", __func__, len);
297 filename << buffer_dir_name.str() << "/" << "length";
301 int ret = path_ops.write(filename.str(), len_str.str());
303 ALOGE("Write Error %s", filename.str().c_str());
311 int SensorIIODev::EnableBuffer(int status){
312 std::stringstream filename;
313 std::stringstream status_str;
315 ALOGV("%s: len:%d", __func__, status);
317 filename << buffer_dir_name.str() << "/" << "enable";
319 status_str << status;
320 int ret = path_ops.write(filename.str(), status_str.str());
322 ALOGE("Write Error %s", filename.str().c_str());
325 enable_buffer = status;
329 int SensorIIODev::EnableChannels(){
333 std::string dir = std::string(IIO_DIR);
334 std::vector < std::string > files = std::vector < std::string > ();
335 const std::string FORMAT_SCAN_ELEMENTS_DIR = "/scan_elements";
336 unsigned char signchar, bits_used, total_bits, shift, unused;
337 SensorIIOChannel iio_channel;
339 ALOGV(">>%s", __func__);
340 scan_el_dir.str(std::string());
341 scan_el_dir << dev_device_name.str() << FORMAT_SCAN_ELEMENTS_DIR;
342 GetDir(scan_el_dir.str(), files);
344 for (unsigned int i = 0; i < files.size(); i++){
345 int len = files[i].length();
346 if (len > 3 && files[i].compare(len - 3, 3, "_en") == 0){
347 std::stringstream filename, file_type;
350 filename << scan_el_dir.str() << "/" << files[i];
351 ret = path_ops.write(filename.str(), "1");
353 ALOGE("Channel Enable Error %s:%d", filename.str().c_str(), ret);
359 int SensorIIODev::BuildChannelList(){
363 std::string dir = std::string(IIO_DIR);
364 std::vector < std::string > files = std::vector < std::string > ();
365 const std::string FORMAT_SCAN_ELEMENTS_DIR = "/scan_elements";
366 unsigned char signchar, bits_used, total_bits, shift, unused;
367 SensorIIOChannel iio_channel;
368 std::string type_name;
370 ALOGV(">>%s", __func__);
371 scan_el_dir.str(std::string());
372 scan_el_dir << dev_device_name.str() << FORMAT_SCAN_ELEMENTS_DIR;
373 GetDir(scan_el_dir.str(), files);
375 // File ending with _en will specify a channel
376 // it contains the count. If we add all these count
377 // those many channels present
378 for (unsigned int i = 0; i < files.size(); i++){
379 int len = files[i].length();
380 // At the least the length should be more than 3 for "_en"
381 if (len > 3 && files[i].compare(len - 3, 3, "_en") == 0){
382 std::stringstream filename, file_type;
383 filename << scan_el_dir.str() << "/" << files[i];
384 std::ifstream ifs(filename.str().c_str(), std::ifstream::in);
390 count = ifs.get() - '0';
395 iio_channel.enabled = 1;
396 iio_channel.scale = 1.0;
397 iio_channel.offset = 0;
399 iio_channel.name = files[i].substr(0, files[i].length() - 3);
401 ALOGV("IIO channel name:%s\n", (char*)iio_channel.name.c_str());
402 file_type << scan_el_dir.str() << "/" << iio_channel.name <<
405 std::ifstream its(file_type.str().c_str(), std::ifstream::in);
410 std::getline(its, type_name);
411 sscanf(type_name.c_str(), "%c%c%c%c%u/%u>>%u", (unsigned char*) &unused,
412 (unsigned char*) &unused, (unsigned char*) &unused, (unsigned
413 char*) &signchar, (unsigned int*) &bits_used, (unsigned int*)
414 &total_bits, (unsigned int*) &shift);
417 // Buggy sscanf on some platforms
418 if (total_bits == 0 || bits_used == 0){
419 if (!strcmp(type_name.c_str(), "le:s16/32")){
423 else if (!strcmp(type_name.c_str(), "le:s16/16")){
433 iio_channel.bytes = total_bits / 8;
434 iio_channel.real_bytes = bits_used / 8;
435 iio_channel.shift = shift;
436 iio_channel.is_signed = signchar;
439 info_array.push_back(iio_channel);
442 ALOGV("<<%s", __func__);
446 int SensorIIODev::GetSizeFromChannels(){
448 for (unsigned int i = 0; i < info_array.size(); i++){
449 SensorIIOChannel channel = info_array[i];
450 size += channel.bytes;
452 ALOGD("%s:%d:%d", __func__, info_array.size(), size);
456 int SensorIIODev::GetChannelBytesUsedSize(unsigned int channel_no){
457 if (channel_no < info_array.size()){
458 SensorIIOChannel channel = info_array[channel_no];
459 return channel.real_bytes;
465 int SensorIIODev::ParseIIODirectory(const std::string& name){
470 ALOGV(">>%s", __func__);
472 dev_device_name.str(std::string());
473 buffer_dir_name.str(std::string());
475 device_number = dev_num = FindDeviceNumberFromName(name, "iio:device");
477 ALOGE("Failed to find device %s\n", (char*)name.c_str());
481 // Construct device directory Eg. /sys/devices/iio:device0
482 dev_device_name << IIO_DIR << "/" << "iio:device" << dev_num;
484 // Construct device directory Eg. /sys/devices/iio:device0:buffer0
485 buffer_dir_name << dev_device_name.str() << "/" << "buffer";
488 ret = SetUpTrigger(dev_num);
490 ALOGE("ParseIIODirectory Failed due to Trigger\n");
494 // Setup buffer len. This is in the datum units, not an absolute number
495 SetUpBufferLen(DEF_BUFFER_LEN);
497 // Set up channel masks
498 ret = EnableChannels();
500 ALOGE("ParseIIODirectory Failed due Enable Channels failed\n");
503 // Parse the channels and build a list
504 ret = BuildChannelList();
506 ALOGE("ParseIIODirectory Failed due BuildChannelList\n");
510 datum_size = GetSizeFromChannels();
511 ALOGV("Datum Size %d", datum_size);
512 ALOGV("<<%s", __func__);
517 int SensorIIODev::SetDataReadyTrigger(int dev_num, bool status){
518 std::stringstream filename;
519 std::stringstream trigger_name;
522 ALOGV("%s: status:%d", __func__, status);
524 filename << dev_device_name.str() << "/trigger/current_trigger";
525 trigger_name << device_name << "-dev" << dev_num;
530 ret = path_ops.write(filename.str(), trigger_name.str());
532 ret = path_ops.write(filename.str(), " ");
534 ALOGE("Write Error %s:%d", filename.str().c_str(), ret);
535 // Ignore error, as this may be due to
536 // Trigger was active during resume
542 int SensorIIODev::DeviceActivate(int dev_num, int state){
543 std::stringstream filename;
544 std::stringstream activate_str;
546 ALOGV("%s: Device Activate:%d", __func__, rate);
550 // Set sensitivity in absolute terms
551 int SensorIIODev::DeviceSetSensitivity(int dev_num, int value){
552 std::stringstream filename;
553 std::stringstream sensitivity_str;
555 ALOGV("%s: Sensitivity :%d", __func__, value);
557 filename << IIO_DIR << "/" << "iio:device" << dev_num << "/" << channel_prefix_str << "hysteresis";
560 sensitivity_str << value;
561 int ret = path_ops.write(filename.str(), sensitivity_str.str());
563 ALOGE("Write Error %s", filename.str().c_str());
564 // Don't bail out as this field may be absent
569 // Set the sample period delay: units ms
570 int SensorIIODev::SetSampleDelay(int dev_num, int period){
571 std::stringstream filename;
572 std::stringstream sample_rate_str;
574 ALOGV("%s: sample_rate:%d", __func__, rate);
576 filename << IIO_DIR << "/" << "iio:device" << dev_num << "/" << channel_prefix_str << "sampling_frequency";
578 ALOGE("%s: Invalid_rate:%d", __func__, period);
581 sample_rate_str << 1000/period;
582 int ret = path_ops.write(filename.str(), sample_rate_str.str());
584 ALOGE("Write Error %s", filename.str().c_str());
585 // Don't bail out as this field may be absent
590 int SensorIIODev::readEvents(sensors_event_t *data, int count){
592 int numEventReceived;
603 if (mHasPendingEvent){
604 mHasPendingEvent = false;
605 mPendingEvent.timestamp = getTimestamp();
606 *data = mPendingEvent;
609 read_size = read(mFd, raw_buffer, datum_size * buffer_len);
610 numEventReceived = 0;
611 if (processEvent(raw_buffer, datum_size) >= 0){
612 mPendingEvent.timestamp = getTimestamp();
613 mPendingEvent.timestamp = getTimestamp();
614 *data = mPendingEvent;
617 return numEventReceived;
620 int SensorIIODev::ReadHIDMeasurmentUnit(long *unit){
621 std::stringstream filename;
623 std::string long_str;
625 filename << IIO_DIR << "/" << "iio:device" << device_number << "/" << unit_str;
627 std::ifstream its(filename.str().c_str(), std::ifstream::in);
629 ALOGE("%s: Can't Open :%s",
630 __func__, filename.str().c_str());
634 std::getline(its, long_str);
637 if (long_str.length() > 0){
638 *unit = atol(long_str.c_str());
641 ALOGE("ReadHIDMeasurmentUnit failed");
645 int SensorIIODev::ReadHIDExponentValue(long *exponent){
646 std::stringstream filename;
648 std::string long_str;
650 filename << IIO_DIR << "/" << "iio:device" << device_number << "/" << unit_expo_str;
652 std::ifstream its(filename.str().c_str(), std::ifstream::in);
654 ALOGE("%s: Can't Open :%s",
655 __func__, filename.str().c_str());
659 std::getline(its, long_str);
662 if (long_str.length() > 0){
663 *exponent = atol(long_str.c_str());
666 ALOGE("ReadHIDExponentValue failed");