X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=control.c;h=7d942fdfab48557a412089f649544edb0816f30e;hb=b24d6584ce3c44cdb5ba9ebe6aa525ff7ecd477c;hp=6e961a2cd3bcb49347235e6a542d93f89fbf8ee5;hpb=f9635becefaca6e9e062be9a58e0ef2fdd3cf993;p=android-x86%2Fhardware-intel-libsensors.git diff --git a/control.c b/control.c index 6e961a2..7d942fd 100644 --- a/control.c +++ b/control.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -15,6 +16,7 @@ #include "utils.h" #include "transform.h" #include "calibration.h" +#include "description.h" /* Currently active sensors count, per device */ static int poll_sensors_per_dev[MAX_DEVICES]; /* poll-mode sensors */ @@ -39,25 +41,58 @@ static pthread_mutex_t thread_release_mutex [MAX_SENSORS]; * */ #define THREAD_REPORT_TAG_BASE 0x00010000 +/* When polling try to compensate for the iio overhead in + * order to try to get a frequency closer to the advertised one + */ +#define OVERHEAD_THRESHOLD 0.97 +#define ENABLE_BUFFER_RETRIES 10 +#define ENABLE_BUFFER_RETRY_DELAY_MS 10 static int enable_buffer(int dev_num, int enabled) { char sysfs_path[PATH_MAX]; + int ret, retries, millisec; + struct timespec req = {0}; + + retries = ENABLE_BUFFER_RETRIES; + millisec = ENABLE_BUFFER_RETRY_DELAY_MS; + req.tv_sec = 0; + req.tv_nsec = millisec * 1000000L; sprintf(sysfs_path, ENABLE_PATH, dev_num); - /* Low level, non-multiplexed, enable/disable routine */ - return sysfs_write_int(sysfs_path, enabled); + while (retries--) { + /* Low level, non-multiplexed, enable/disable routine */ + ret = sysfs_write_int(sysfs_path, enabled); + if (ret > 0) + break; + + ALOGE("Failed enabling buffer, retrying"); + nanosleep(&req, (struct timespec *)NULL); + } + + if (ret < 0) { + ALOGE("Could not enable buffer\n"); + return -EIO; + } + + return 0; } -static int setup_trigger(int dev_num, const char* trigger_val) +static void setup_trigger (int s, const char* trigger_val) { char sysfs_path[PATH_MAX]; - sprintf(sysfs_path, TRIGGER_PATH, dev_num); + sprintf(sysfs_path, TRIGGER_PATH, sensor_info[s].dev_num); + + if (trigger_val[0] != '\n') + ALOGI("Setting S%d (%s) trigger to %s\n", s, + sensor_info[s].friendly_name, trigger_val); - return sysfs_write_str(sysfs_path, trigger_val); + sysfs_write_str(sysfs_path, trigger_val); + + sensor_info[s].selected_trigger = trigger_val; } @@ -156,7 +191,7 @@ void build_sensor_report_maps(int dev_num) /* Stop sampling - if we are recovering from hal restart */ enable_buffer(dev_num, 0); - setup_trigger(dev_num, "\n"); + setup_trigger(s, "\n"); /* Turn on channels we're aware of */ for (c=0;c= sensor_count) { ALOGE("Invalid sensor handle!\n"); @@ -390,8 +433,8 @@ static void* acquisition_routine (void* param) goto exit; - period = 1000000000LL / sensor_info[s].sampling_rate; - + period = (int64_t) (1000000000.0/ sensor_info[s].sampling_rate); + period = period * OVERHEAD_THRESHOLD; time_add(&target_time, &entry_time, period); /* @@ -443,7 +486,7 @@ static void start_acquisition_thread (int s) ret = pthread_create( &sensor_info[s].acquisition_thread, NULL, acquisition_routine, - (void*) s); + (void*) (size_t) s); } @@ -481,34 +524,52 @@ static void stop_acquisition_thread (int s) int sensor_activate(int s, int enabled) { char device_name[PATH_MAX]; - char trigger_name[MAX_NAME_SIZE + 16]; - int c; struct epoll_event ev = {0}; int dev_fd; int ret; int dev_num = sensor_info[s].dev_num; - int i = sensor_info[s].catalog_index; int is_poll_sensor = !sensor_info[s].num_channels; + /* Prepare the report timestamp field for the first event, see set_report_ts method */ + sensor_info[s].report_ts = 0; + + /* If we want to activate gyro calibrated and gyro uncalibrated is activated + * Deactivate gyro uncalibrated - Uncalibrated releases handler + * Activate gyro calibrated - Calibrated has handler + * Reactivate gyro uncalibrated - Uncalibrated gets data from calibrated */ + + /* If we want to deactivate gyro calibrated and gyro uncalibrated is active + * Deactivate gyro uncalibrated - Uncalibrated no longer gets data from handler + * Deactivate gyro calibrated - Calibrated releases handler + * Reactivate gyro uncalibrated - Uncalibrated has handler */ + + if (sensor_catalog[sensor_info[s].catalog_index].type == SENSOR_TYPE_GYROSCOPE && + sensor_info[s].pair_idx && sensor_info[sensor_info[s].pair_idx].enable_count != 0) { + + sensor_activate(sensor_info[s].pair_idx, 0); + ret = sensor_activate(s, enabled); + sensor_activate(sensor_info[s].pair_idx, 1); + return ret; + } + ret = adjust_counters(s, enabled); /* If the operation was neutral in terms of state, we're done */ if (ret <= 0) return ret; + if (!is_poll_sensor) { /* Stop sampling */ enable_buffer(dev_num, 0); - setup_trigger(dev_num, "\n"); + setup_trigger(s, "\n"); /* If there's at least one sensor enabled on this iio device */ if (trig_sensors_per_dev[dev_num]) { - sprintf(trigger_name, "%s-dev%d", - sensor_info[s].internal_name, dev_num); /* Start sampling */ - setup_trigger(dev_num, trigger_name); + setup_trigger(s, sensor_info[s].init_trigger_name); enable_buffer(dev_num, 1); } } @@ -536,6 +597,18 @@ int sensor_activate(int s, int enabled) close(dev_fd); device_fd[dev_num] = -1; } + + /* If we recorded a trail of samples for filtering, delete it */ + if (sensor_info[s].history) { + free(sensor_info[s].history); + sensor_info[s].history = NULL; + sensor_info[s].history_size = 0; + if (sensor_info[s].history_sum) { + free(sensor_info[s].history_sum); + sensor_info[s].history_sum = NULL; + } + } + return 0; } @@ -583,6 +656,113 @@ int sensor_activate(int s, int enabled) } +static int is_fast_accelerometer (int s) +{ + /* + * Some games don't react well to accelerometers using any-motion + * triggers. Even very low thresholds seem to trip them, and they tend + * to request fairly high event rates. Favor continuous triggers if the + * sensor is an accelerometer and uses a sampling rate of at least 25. + */ + int catalog_index = sensor_info[s].catalog_index; + + if (sensor_catalog[catalog_index].type != SENSOR_TYPE_ACCELEROMETER) + return 0; + + if (sensor_info[s].sampling_rate < 25) + return 0; + + return 1; +} + + +static void enable_motion_trigger (int dev_num) +{ + /* + * In the ideal case, we enumerate two triggers per iio device ; the + * default (periodically firing) trigger, and another one (the motion + * trigger) that only fires up when motion is detected. This second one + * allows for lesser energy consumption, but requires periodic sample + * duplication at the HAL level for sensors that Android defines as + * continuous. This "duplicate last sample" logic can only be engaged + * once we got a first sample for the driver, so we start with the + * default trigger when an iio device is first opened, then adjust the + * trigger when we got events for all active sensors. Unfortunately in + * the general case several sensors can be associated to a given iio + * device, they can independently be controlled, and we have to adjust + * the trigger in use at the iio device level depending on whether or + * not appropriate conditions are met at the sensor level. + */ + + int s; + int i; + int active_sensors = trig_sensors_per_dev[dev_num]; + int candidate[MAX_SENSORS]; + int candidate_count = 0; + + if (!active_sensors) + return; + + /* Check that all active sensors are ready to switch */ + + for (s=0; sversion = sizeof(sensors_event_t); @@ -701,6 +893,58 @@ static int propagate_sensor_report(int s, struct sensors_event_t *data) } +static void synthetize_duplicate_samples (void) +{ + /* + * Some sensor types (ex: gyroscope) are defined as continuously firing + * by Android, despite the fact that we can be dealing with iio drivers + * that only report events for new samples. For these we generate + * reports periodically, duplicating the last data we got from the + * driver. This is not necessary for polling sensors. + */ + + int s; + int64_t current_ts; + int64_t target_ts; + int64_t period; + + for (s=0; sbias_x; + data[uncal_start + i].data[1] = data[returned_events + i].data[1] + gyro_data->bias_y; + data[uncal_start + i].data[2] = data[returned_events + i].data[2] + gyro_data->bias_z; + + data[uncal_start + i].uncalibrated_gyro.bias[0] = gyro_data->bias_x; + data[uncal_start + i].uncalibrated_gyro.bias[1] = gyro_data->bias_y; + data[uncal_start + i].uncalibrated_gyro.bias[2] = gyro_data->bias_z; + } + event_count <<= 1; + } + sensor_info[sensor_info[s].pair_idx].report_pending = 0; + returned_events += event_count; /* * If the sample was deemed invalid or unreportable, * e.g. had the same value as the previously reported @@ -760,10 +1077,10 @@ await_event: ALOGV("Awaiting sensor data\n"); - nfds = epoll_wait(poll_fd, ev, MAX_DEVICES, -1); + nfds = epoll_wait(poll_fd, ev, MAX_DEVICES, get_poll_wait_timeout()); if (nfds == -1) { - ALOGI("epoll_wait returned -1 (%s)\n", strerror(errno)); + ALOGE("epoll_wait returned -1 (%s)\n", strerror(errno)); goto await_event; } @@ -808,7 +1125,11 @@ int sensor_set_delay(int s, int64_t ns) float cur_sampling_rate; /* Currently used sampling rate */ int per_sensor_sampling_rate; int per_device_sampling_rate; - float max_supported_rate = 0; + int32_t min_delay_us = sensor_desc[s].minDelay; + max_delay_t max_delay_us = sensor_desc[s].maxDelay; + float min_supported_rate = max_delay_us ? (1000000.0f / max_delay_us) : 1; + float max_supported_rate = + (min_delay_us && min_delay_us != -1) ? (1000000.0f / min_delay_us) : 0; char freqs_buf[100]; char* cursor; int n; @@ -825,8 +1146,13 @@ int sensor_set_delay(int s, int64_t ns) * Artificially limit ourselves to 1 Hz or higher. This is mostly to * avoid setting up the stage for divisions by zero. */ - if (new_sampling_rate < 1) - new_sampling_rate = 1; + if (new_sampling_rate < min_supported_rate) + new_sampling_rate = min_supported_rate; + + if (max_supported_rate && + new_sampling_rate > max_supported_rate) { + new_sampling_rate = max_supported_rate; + } sensor_info[s].sampling_rate = new_sampling_rate; @@ -882,9 +1208,6 @@ int sensor_set_delay(int s, int64_t ns) /* Decode a single value */ sr = strtod(cursor, NULL); - if (sr > max_supported_rate) - max_supported_rate = sr; - /* If this matches the selected rate, we're happy */ if (new_sampling_rate == sr) break; @@ -929,6 +1252,11 @@ int sensor_set_delay(int s, int64_t ns) sysfs_write_float(sysfs_path, new_sampling_rate); + /* Switch back to continuous sampling for accelerometer based games */ + if (is_fast_accelerometer(s) && sensor_info[s].selected_trigger != + sensor_info[s].init_trigger_name) + setup_trigger(s, sensor_info[s].init_trigger_name); + if (trig_sensors_per_dev[dev_num]) enable_buffer(dev_num, 1); @@ -939,7 +1267,6 @@ int sensor_set_delay(int s, int64_t ns) int allocate_control_data (void) { int i; - struct epoll_event ev = {0}; for (i=0; i