sensord: merge tizen 2.3 sensord into tizen branch
[platform/core/system/sensord.git] / src / accel / accel_sensor_hal.cpp
index 6a78105..aebe9fd 100755 (executable)
@@ -44,13 +44,6 @@ using std::ifstream;
 #define INPUT_NAME     "accelerometer_sensor"
 #define ACCEL_SENSORHUB_POLL_NODE_NAME "accel_poll_delay"
 
-#define SCAN_EL_DIR                            "scan_elements/"
-#define SCALE_AVAILABLE_NODE   "in_accel_scale_available"
-#define ACCEL_RINGBUF_LEN      32
-#define SEC_MSEC                       1000
-#define MSEC_TO_FREQ(VAL)      ((SEC_MSEC) / (VAL))
-#define NSEC_TO_MUSEC(VAL)     ((VAL) / 1000)
-
 accel_sensor_hal::accel_sensor_hal()
 : m_x(-1)
 , m_y(-1)
@@ -62,37 +55,31 @@ accel_sensor_hal::accel_sensor_hal()
        const string sensorhub_interval_node_name = "accel_poll_delay";
        csensor_config &config = csensor_config::get_instance();
 
-       node_path_info_query query;
-       node_path_info info;
-       int input_method = IIO_METHOD;
+       node_info_query query;
+       node_info info;
 
-       if (!get_model_properties(SENSOR_TYPE_ACCEL, m_model_id, input_method)) {
-               ERR("Failed to find model_properties");
+       if (!find_model_id(SENSOR_TYPE_ACCEL, m_model_id)) {
+               ERR("Failed to find model id");
                throw ENXIO;
        }
 
-       query.input_method = input_method;
        query.sensorhub_controlled = m_sensorhub_controlled = is_sensorhub_controlled(sensorhub_interval_node_name);
        query.sensor_type = SENSOR_TYPE_ACCEL;
-       query.input_event_key = "accelerometer_sensor";
+       query.key = "accelerometer_sensor";
        query.iio_enable_node_name = "accel_enable";
        query.sensorhub_interval_node_name = sensorhub_interval_node_name;
 
-       if (!get_node_path_info(query, info)) {
+       if (!get_node_info(query, info)) {
                ERR("Failed to get node info");
                throw ENXIO;
        }
 
-       show_node_path_info(info);
+       show_node_info(info);
 
+       m_method = info.method;
        m_data_node = info.data_node_path;
+       m_enable_node = info.enable_node_path;
        m_interval_node = info.interval_node_path;
-       m_accel_dir = info.base_dir;
-       m_trigger_path = info.trigger_node_path;
-       m_buffer_enable_node_path = info.buffer_enable_node_path;
-       m_buffer_length_node_path = info.buffer_length_node_path;
-       m_available_freq_node_path = info.available_freq_node_path;
-       m_available_scale_node_path = m_accel_dir + string(SCALE_AVAILABLE_NODE);
 
        if (!config.get(SENSOR_TYPE_ACCEL, m_model_id, ELEMENT_VENDOR, m_vendor)) {
                ERR("[VENDOR] is empty\n");
@@ -108,25 +95,6 @@ accel_sensor_hal::accel_sensor_hal()
 
        INFO("m_chip_name = %s\n",m_chip_name.c_str());
 
-       if (input_method == IIO_METHOD) {
-               m_trigger_name = m_model_id + "-trigger";
-               if (!verify_iio_trigger(m_trigger_name)) {
-                       ERR("Failed verify trigger");
-                       throw ENXIO;
-               }
-               string scan_dir = m_accel_dir + "scan_elements/";
-               if (!get_generic_channel_names(scan_dir, string("_type"), m_generic_channel_names))
-                       ERR ("Failed to find any input channels");
-               else
-               {
-                       INFO ("generic channel names:");
-                       for (vector <string>::iterator it = m_generic_channel_names.begin();
-                                       it != m_generic_channel_names.end(); ++it) {
-                               INFO ("%s", it->c_str());
-                       }
-               }
-       }
-
        long resolution;
 
        if (!config.get(SENSOR_TYPE_ACCEL, m_model_id, ELEMENT_RESOLUTION, resolution)) {
@@ -146,36 +114,38 @@ accel_sensor_hal::accel_sensor_hal()
        }
 
        m_raw_data_unit = (float)(raw_data_unit);
+       INFO("m_raw_data_unit = %f\n", m_raw_data_unit);
 
-       m_node_handle = open(m_data_node.c_str(), O_RDONLY | O_NONBLOCK);
-       if (m_node_handle < 0) {
+       if ((m_node_handle = open(m_data_node.c_str(), O_RDWR)) < 0) {
                ERR("accel handle open fail for accel processor, error:%s\n", strerror(errno));
                throw ENXIO;
        }
 
-       if (setup_channels() == true)
-               INFO("IIO channel setup successful");
-       else {
-               ERR("IIO channel setup failed");
-               throw ENXIO;
-       }
+       if (m_method == INPUT_EVENT_METHOD) {
+               int clockId = CLOCK_MONOTONIC;
+               if (ioctl(m_node_handle, EVIOCSCLOCKID, &clockId) != 0)
+                       ERR("Fail to set monotonic timestamp for %s", m_data_node.c_str());
 
-//     int clockId = CLOCK_MONOTONIC;
-//     if (ioctl(m_node_handle, EVIOCSCLOCKID, &clockId) != 0) {
-//             ERR("Fail to set monotonic timestamp for %s", m_data_node.c_str());
-//             throw ENXIO;
-//     }
+               update_value = [=](bool wait) {
+                       return this->update_value_input_event(wait);
+               };
+       } else {
+               if (!info.buffer_length_node_path.empty())
+                       set_node_value(info.buffer_length_node_path, 480);
+
+               if (!info.buffer_enable_node_path.empty())
+                       set_node_value(info.buffer_enable_node_path, 1);
+
+               update_value = [=](bool wait) {
+                       return this->update_value_iio(wait);
+               };
+       }
 
-       INFO("m_raw_data_unit = %f\n", m_raw_data_unit);
        INFO("accel_sensor is created!\n");
 }
 
 accel_sensor_hal::~accel_sensor_hal()
 {
-       enable_resource(false);
-       if (m_data != NULL)
-               delete []m_data;
-
        close(m_node_handle);
        m_node_handle = -1;
 
@@ -192,227 +162,170 @@ sensor_type_t accel_sensor_hal::get_type(void)
        return ACCELEROMETER_SENSOR;
 }
 
-bool accel_sensor_hal::add_accel_channels_to_array(void)
+bool accel_sensor_hal::enable(void)
 {
-       int i = 0;
-       m_channels = (struct channel_parameters*) malloc(sizeof(struct channel_parameters) * m_generic_channel_names.size());
-       for (vector <string>::iterator it = m_generic_channel_names.begin();
-                       it != m_generic_channel_names.end(); ++it) {
-               if (add_channel_to_array(m_accel_dir.c_str(), it->c_str() , &m_channels[i++]) < 0) {
-                       ERR("Failed to add channel %s to channel array", it->c_str());
-                       return false;
-               }
-       }
+       AUTOLOCK(m_mutex);
+
+       set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_ACCELEROMETER_ENABLE_BIT);
+       set_interval(m_polling_interval);
+
+       m_fired_time = 0;
+       INFO("Accel sensor real starting");
        return true;
 }
 
-bool accel_sensor_hal::setup_channels(void)
+bool accel_sensor_hal::disable(void)
 {
-       int freq, i;
-       double sf;
+       AUTOLOCK(m_mutex);
 
-       enable_resource(true);
+       set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_ACCELEROMETER_ENABLE_BIT);
 
-       if (!add_accel_channels_to_array()) {
-               ERR("Failed to add channels to array!");
-               return false;
-       }
+       INFO("Accel sensor real stopping");
+       return true;
+}
 
-       INFO("Sorting channels by index");
-       sort_channels_by_index(m_channels, m_generic_channel_names.size());
-       INFO("Sorting channels by index completed");
+bool accel_sensor_hal::set_interval(unsigned long val)
+{
+       unsigned long long polling_interval_ns;
 
-       m_scan_size = get_channel_array_size(m_channels, m_generic_channel_names.size());
-       if (m_scan_size == 0) {
-               ERR("Channel array size is zero");
-               return false;
-       }
+       AUTOLOCK(m_mutex);
 
-       m_data = new (std::nothrow) char[m_scan_size * ACCEL_RINGBUF_LEN];
-       if (m_data == NULL) {
-               ERR("Couldn't create data buffer\n");
-               return false;
-       }
+       polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);
 
-       FILE *fp = NULL;
-       fp = fopen(m_available_freq_node_path.c_str(), "r");
-       if (!fp) {
-               ERR("Fail to open available frequencies file:%s\n", m_available_freq_node_path.c_str());
+       if (!set_node_value(m_interval_node, polling_interval_ns)) {
+               ERR("Failed to set polling resource: %s\n", m_interval_node.c_str());
                return false;
        }
 
-       for (i = 0; i < MAX_FREQ_COUNT; i++)
-               m_sample_freq[i] = 0;
+       INFO("Interval is changed from %dms to %dms]", m_polling_interval, val);
+       m_polling_interval = val;
+       return true;
+}
 
-       i = 0;
 
-       while (fscanf(fp, "%d", &freq) > 0)
-               m_sample_freq[i++] = freq;
+bool accel_sensor_hal::update_value_input_event(bool wait)
+{
+       int accel_raw[3] = {0,};
+       bool x,y,z;
+       int read_input_cnt = 0;
+       const int INPUT_MAX_BEFORE_SYN = 10;
+       unsigned long long fired_time = 0;
+       bool syn = false;
+
+       x = y = z = false;
+
+       struct input_event accel_input;
+       DBG("accel event detection!");
+
+       while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
+               int len = read(m_node_handle, &accel_input, sizeof(accel_input));
+               if (len != sizeof(accel_input)) {
+                       ERR("accel_file read fail, read_len = %d\n",len);
+                       return false;
+               }
 
-       m_sample_freq_count = i;
+               ++read_input_cnt;
+
+               if (accel_input.type == EV_REL) {
+                       switch (accel_input.code) {
+                       case REL_X:
+                               accel_raw[0] = (int)accel_input.value;
+                               x = true;
+                               break;
+                       case REL_Y:
+                               accel_raw[1] = (int)accel_input.value;
+                               y = true;
+                               break;
+                       case REL_Z:
+                               accel_raw[2] = (int)accel_input.value;
+                               z = true;
+                               break;
+                       default:
+                               ERR("accel_input event[type = %d, code = %d] is unknown.", accel_input.type, accel_input.code);
+                               return false;
+                               break;
+                       }
+               } else if (accel_input.type == EV_SYN) {
+                       syn = true;
+                       fired_time = sensor_hal::get_timestamp(&accel_input.time);
+               } else {
+                       ERR("accel_input event[type = %d, code = %d] is unknown.", accel_input.type, accel_input.code);
+                       return false;
+               }
+       }
 
-       fp = fopen(m_available_scale_node_path.c_str(), "r");
-       if (!fp) {
-               ERR("Fail to open available scale factors file:%s\n", m_available_scale_node_path.c_str());
+       if (syn == false) {
+               ERR("EV_SYN didn't come until %d inputs had come", read_input_cnt);
                return false;
        }
 
-       for (i = 0; i < MAX_SCALING_COUNT; i++)
-               m_scale_factor[i] = 0;
+       AUTOLOCK(m_value_mutex);
 
-       i = 0;
+       if (x)
+               m_x =  accel_raw[0];
+       if (y)
+               m_y =  accel_raw[1];
+       if (z)
+               m_z =  accel_raw[2];
 
-       while (fscanf(fp, "%lf", &sf) > 0)
-               m_scale_factor[i++] = sf;
+       m_fired_time = fired_time;
 
-       m_scale_factor_count = i;
+       DBG("m_x = %d, m_y = %d, m_z = %d, time = %lluus", m_x, m_y, m_z, m_fired_time);
 
        return true;
 }
 
-void accel_sensor_hal::decode_data(void)
+
+bool accel_sensor_hal::update_value_iio(bool wait)
 {
-       AUTOLOCK(m_value_mutex);
+       const int READ_LEN = 14;
+       char data[READ_LEN] = {0,};
 
-       m_x = convert_bytes_to_int(*(unsigned short int *)(m_data + m_channels[0].buf_index), &m_channels[0]);
-       m_y = convert_bytes_to_int(*(unsigned short int *)(m_data + m_channels[1].buf_index), &m_channels[1]);
-       m_z = convert_bytes_to_int(*(unsigned short int *)(m_data + m_channels[2].buf_index), &m_channels[2]);
+       struct pollfd pfd;
 
-       long long int val = *(long long int *)(m_data + m_channels[3].buf_index);
-       if ((val >> m_channels[3].valid_bits) & 1)
-               val = (val & m_channels[3].mask) | ~m_channels[3].mask;
+       pfd.fd = m_node_handle;
+       pfd.events = POLLIN | POLLERR;
+       pfd.revents = 0;
 
-       m_fired_time = (unsigned long long int)(NSEC_TO_MUSEC(val));
-       DBG("m_x = %d, m_y = %d, m_z = %d, time = %lluus", m_x, m_y, m_z, m_fired_time);
-}
-bool accel_sensor_hal::setup_trigger(const char* trig_name, bool verify)
-{
-       int ret = 0;
+       int ret = poll(&pfd, 1, -1);
 
-       ret = update_sysfs_string(m_trigger_path.c_str(), trig_name);
-       if (ret < 0) {
-               ERR("failed to write to current_trigger,%s,%s\n", m_trigger_path.c_str(), trig_name);
+       if (ret == -1) {
+               ERR("poll error:%s m_node_handle:d", strerror(errno), m_node_handle);
+               return false;
+       } else if (!ret) {
+               ERR("poll timeout m_node_handle:%d", m_node_handle);
                return false;
        }
-       INFO("current_trigger setup successfully\n");
-       return true;
-}
 
-bool accel_sensor_hal::setup_buffer(int enable)
-{
-       int ret;
-       ret = update_sysfs_num(m_buffer_length_node_path.c_str(), ACCEL_RINGBUF_LEN, true);
-       if (ret < 0) {
-               ERR("failed to write to buffer/length\n");
+       if (pfd.revents & POLLERR) {
+               ERR("poll exception occurred! m_node_handle:%d", m_node_handle);
                return false;
        }
-       INFO("buffer/length setup successfully\n");
 
-       ret = update_sysfs_num(m_buffer_enable_node_path.c_str(), enable, true);
-       if (ret < 0) {
-               ERR("failed to write to buffer/enable\n");
+       if (!(pfd.revents & POLLIN)) {
+               ERR("poll nothing to read! m_node_handle:%d, pfd.revents = %d", m_node_handle, pfd.revents);
                return false;
        }
 
-       if (enable)
-               INFO("buffer enabled\n");
-       else
-               INFO("buffer disabled\n");
-       return true;
-}
+       int len = read(m_node_handle, data, sizeof(data));
 
-bool accel_sensor_hal::enable_resource(bool enable)
-{
-       string temp;
-       if(enable)
-               setup_trigger(m_trigger_name.c_str(), enable);
-       else
-               setup_trigger("NULL", enable);
-
-       for (vector <string>::iterator it = m_generic_channel_names.begin();
-                       it != m_generic_channel_names.end(); ++it) {
-               temp = m_accel_dir + string(SCAN_EL_DIR) + *it + string("_en");
-               if (update_sysfs_num(temp.c_str(), enable) < 0)
-                       return false;
+       if (len != sizeof(data)) {
+               ERR("Failed to read data, m_node_handle:%d read_len:%d", m_node_handle, len);
+               return false;
        }
-       setup_buffer(enable);
-       return true;
-}
 
-bool accel_sensor_hal::enable(void)
-{
-       AUTOLOCK(m_mutex);
+       AUTOLOCK(m_value_mutex);
 
-       if (!enable_resource(true))
-                       return false;
+       m_x = *((short *)(data));
+       m_y = *((short *)(data + 2));
+       m_z = *((short *)(data + 4));
 
-       set_interval(m_polling_interval);
+       m_fired_time = *((long long*)(data + 6));
 
-       m_fired_time = 0;
-       INFO("Accel sensor real starting");
-       return true;
-}
+       INFO("m_x = %d, m_y = %d, m_z = %d, time = %lluus", m_x, m_y, m_z, m_fired_time);
 
-bool accel_sensor_hal::disable(void)
-{
-       AUTOLOCK(m_mutex);
-
-       if (!enable_resource(false))
-               return false;
-
-       INFO("Accel sensor real stopping");
        return true;
-}
-
-bool accel_sensor_hal::set_interval(unsigned long ms_interval)
-{
-       int freq, i;
-
-       freq = (int)(MSEC_TO_FREQ(ms_interval));
-
-       for (i=0; i < m_sample_freq_count; i++) {
-               if (freq == m_sample_freq[i]) {
-                       if (update_sysfs_num(m_interval_node.c_str(), freq, true) == 0) {
-                               INFO("Interval is changed from %lums to %lums]", m_polling_interval, ms_interval);
-                               m_polling_interval = ms_interval;
-                               return true;
-                       }
-                       else {
-                               ERR("Failed to set data %lu\n", ms_interval);
-                               return false;
-                       }
-               }
-       }
 
-       DBG("The interval not supported: %lu\n", ms_interval);
-       ERR("Failed to set data %lu\n", ms_interval);
-       return false;
-}
-
-bool accel_sensor_hal::update_value(bool wait)
-{
-       int i;
-       struct pollfd pfd;
-       ssize_t read_size;
-       const int TIMEOUT = 1000;
-
-       pfd.fd = m_node_handle;
-       pfd.events = POLLIN;
-       if (wait)
-               poll(&pfd, 1, TIMEOUT);
-       else
-               poll(&pfd, 1, 0);
-
-       read_size = read(m_node_handle, m_data, ACCEL_RINGBUF_LEN * m_scan_size);
-       if (read_size <= 0) {
-               ERR("Accel:No data available\n");
-               return false;
-       }
-       else {
-               for (i = 0; i < (read_size / m_scan_size); i++)
-                       decode_data();
-       }
-       return true;
 }
 
 bool accel_sensor_hal::is_data_ready(bool wait)
@@ -449,21 +362,20 @@ bool accel_sensor_hal::get_properties(sensor_properties_s &properties)
        return true;
 }
 
-extern "C" void *create(void)
+extern "C" sensor_module* create(void)
 {
-       accel_sensor_hal *inst;
+       accel_sensor_hal *sensor;
 
        try {
-               inst = new accel_sensor_hal();
+               sensor = new(std::nothrow) accel_sensor_hal;
        } catch (int err) {
-               ERR("accel_sensor class create fail , errno : %d , errstr : %s\n", err, strerror(err));
+               ERR("Failed to create module, err: %d, cause: %s", err, strerror(err));
                return NULL;
        }
 
-       return (void*)inst;
-}
+       sensor_module *module = new(std::nothrow) sensor_module;
+       retvm_if(!module || !sensor, NULL, "Failed to allocate memory");
 
-extern "C" void destroy(void *inst)
-{
-       delete (accel_sensor_hal*)inst;
+       module->sensors.push_back(sensor);
+       return module;
 }