1c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare/* 2c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare * Copyright (C) 2008 The Android Open Source Project 3c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare * 4c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare * Licensed under the Apache License, Version 2.0 (the "License"); 5c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare * you may not use this file except in compliance with the License. 6c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare * You may obtain a copy of the License at 7c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare * 8c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare * http://www.apache.org/licenses/LICENSE-2.0 9c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare * 10c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare * Unless required by applicable law or agreed to in writing, software 11c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare * distributed under the License is distributed on an "AS IS" BASIS, 12c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare * See the License for the specific language governing permissions and 14c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare * limitations under the License. 15c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare */ 16c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 17c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare/* 18c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare * Based on htc/flounder/lights/lights.h 19c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare */ 20c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 21c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare#define LOG_TAG "lights" 22c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 23c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare#include <malloc.h> 24c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare#include <string.h> 25c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare#include <unistd.h> 26c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare#include <errno.h> 27748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca#include <cutils/log.h> 28c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare#include <hardware/lights.h> 29c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare#include <hardware/hardware.h> 30748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca#include <gpio.h> 31748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 32748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* List of supported lights */ 33748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscatypedef enum { 343dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca NOTIFICATIONS_TYPE, 353dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca LIGHTS_TYPE_NUM 36748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca} light_type_t; 37748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 38748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* Light device data structure */ 39748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastruct light_device_ext_t { 403dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca /* Base device */ 413dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca struct light_device_t base_dev; 423dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca /* Physical pin */ 433dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca int pin; 443dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca /* Current state of the light device */ 453dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca struct light_state_t state; 463dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca /* Number of device references */ 473dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca int refs; 483dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca /* Synchronization attributes */ 493dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_t flash_thread; 503dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_cond_t flash_cond; 513dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_t flash_signal_mutex; 523dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_t write_mutex; 53f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca /* Transform function to apply on value */ 54f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca int (*transform)(int); 55748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca}; 56748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 57748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int64_t const ONE_MS_IN_NS = 1000000LL; 58748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int64_t const ONE_S_IN_NS = 1000000000LL; 59748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 60748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 61f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca * Platform version strings used to identify board versions 62748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 63f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Muscastatic char * const EDISON_ARDUINO_PLATFORM_VERSION = "arduino"; 64f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Muscastatic char * const MINNOWBOARD_TURBOT_PLATFORM_VERSION = "Turbot"; 65748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 66748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 67748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Pin constants 6839bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Musca * Please add a pin to EDISON_ARDUINO_PINS, EDISON_MINIBOARD_PINS & 6939bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Musca * MINNOWBOARD_MAX_PINS when you add a new light type 70748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 7139bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Muscastatic int const EDISON_ARDUINO_PINS[LIGHTS_TYPE_NUM] = {13}; 7239bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Muscastatic int const EDISON_MINIBOARD_PINS[LIGHTS_TYPE_NUM] = {31}; 7339bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Muscastatic int const MINNOWBOARD_MAX_PINS[LIGHTS_TYPE_NUM] = {21}; 74f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Muscastatic int const MINNOWBOARD_TURBOT_PINS[LIGHTS_TYPE_NUM] = {27}; 75748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 76748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 77748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Array of light devices with write_mutex statically initialized 78748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * to be able to synchronize the open_lights & close_lights functions 79748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 80748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastruct light_device_ext_t light_devices[] = { 813dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca [ 0 ... (LIGHTS_TYPE_NUM - 1) ] = { .write_mutex = PTHREAD_MUTEX_INITIALIZER } 82748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca}; 83c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 84748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 85748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Set the GPIO value 86748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param pin physical pin of the GPIO 87748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param value what value to set 88748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @return 0 if success, error code otherwise 89748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 90748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int set_gpio_value(int pin, int value) 91748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca{ 923dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca mraa_gpio_context gpio = NULL; 933dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca int rc = 0; 94748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 953dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if ((value != 0) && (value != 1)) { 963dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return EINVAL; 973dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 98c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 993dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca gpio = mraa_gpio_init(pin); 1003dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (gpio == NULL) { 1013dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return EPERM; 1023dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 103748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 1043dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (mraa_gpio_dir(gpio, MRAA_GPIO_OUT) != MRAA_SUCCESS) { 1053dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca rc = EPERM; 1063dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca goto close_gpio; 1073dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 108748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 1093dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (mraa_gpio_write(gpio, value) != MRAA_SUCCESS) { 1103dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca rc = EPERM; 1113dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 112c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 113748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscaclose_gpio: 1143dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (mraa_gpio_close(gpio) != MRAA_SUCCESS) { 1153dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca rc = EPERM; 1163dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 117748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 1183dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return rc; 119748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca} 120748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 121748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 122f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca * Invert value 123f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca * @param value what value to invert 124f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca * @return value inverted 125f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca */ 126f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Muscastatic int invert_value(int value) { 127f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca return value ? 0 : 1; 128f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca} 129f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca 130f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca/* 131748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Get current timestamp in nanoseconds 132748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @return time in nanoseconds 133748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 134748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscaint64_t get_timestamp_monotonic() 135c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare{ 1365b95432c01a78c364aa029b05eeddb570d1828f2Constantin Musca struct timespec ts = {0, 0}; 137748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 1383dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (!clock_gettime(CLOCK_MONOTONIC, &ts)) { 1393dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return ONE_S_IN_NS * ts.tv_sec + ts.tv_nsec; 1403dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 141748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 1423dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return -1; 143748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca} 144748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 145748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 146748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Populates a timespec data structure from a int64_t timestamp 147748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param out what timespec to populate 148748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param target_ns timestamp in nanoseconds 149748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 150748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscavoid set_timestamp(struct timespec *out, int64_t target_ns) 151748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca{ 1523dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca out->tv_sec = target_ns / ONE_S_IN_NS; 1533dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca out->tv_nsec = target_ns % ONE_S_IN_NS; 154748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca} 155748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 156748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 157748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * pthread routine which flashes an LED 158748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param flash_param light device pointer 159748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 160748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic void * flash_routine (void *flash_param) 161748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca{ 1623dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca struct light_device_ext_t *dev = (struct light_device_ext_t *)flash_param; 1633dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca struct light_state_t *flash_state; 1643dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca int color = 0, rc = 0; 1653dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca struct timespec target_time; 1663dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca int64_t timestamp, period; 1673dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 1683dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (dev == NULL) { 1693dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGE("%s: Cannot flash a NULL light device", __func__); 1703dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return NULL; 1713dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 1723dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 1733dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca flash_state = &dev->state; 1743dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 1753dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_lock(&dev->flash_signal_mutex); 1763dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 1773dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca color = flash_state->color; 1783dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 1793dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca /* Light flashing loop */ 1803dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca while (flash_state->flashMode) { 1813dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca rc = set_gpio_value(dev->pin, color); 1823dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (rc != 0) { 1833dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGE("%s: Cannot set light color", __func__); 1843dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca goto mutex_unlock; 1853dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 1863dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 1873dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca timestamp = get_timestamp_monotonic(); 1883dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (timestamp < 0) { 1893dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGE("%s: Cannot get time from monotonic clock", __func__); 1903dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca goto mutex_unlock; 1913dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 1923dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 1933dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (color) { 1943dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca color = 0; 1953dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca period = flash_state->flashOnMS * ONE_MS_IN_NS; 1963dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } else { 1973dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca color = 1; 1983dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca period = flash_state->flashOffMS * ONE_MS_IN_NS; 1993dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 2003dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 2013dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca /* check for overflow */ 2023dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (timestamp > LLONG_MAX - period) { 2033dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGE("%s: Timestamp overflow", __func__); 2043dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca goto mutex_unlock; 2053dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 2063dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 2073dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca timestamp += period; 2083dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 2093dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca /* sleep until target_time or the cond var is signaled */ 2103dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca set_timestamp(&target_time, timestamp); 2113dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca rc = pthread_cond_timedwait(&dev->flash_cond, &dev->flash_signal_mutex, &target_time); 2123dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if ((rc != 0) && (rc != ETIMEDOUT)) { 2133dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGE("%s: pthread_cond_timedwait returned an error", __func__); 2143dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca goto mutex_unlock; 2153dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 2163dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 217748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 218748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscamutex_unlock: 2193dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_unlock(&dev->flash_signal_mutex); 220748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 2213dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return NULL; 222c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare} 223c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 224748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 225748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Check lights flash state 226748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param state pointer to the state to check 227748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @return 0 if success, error code otherwise 228748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 229748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int check_flash_state(struct light_state_t const *state) 230748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca{ 2313dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca int64_t ns = 0; 2323dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 2333dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if ((state->flashOffMS < 0) || (state->flashOnMS < 0)) { 2343dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return EINVAL; 2353dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 2363dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 2373dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if ((state->flashOffMS == 0) && (state->flashOnMS) == 0) { 2383dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return EINVAL; 2393dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 2403dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 2413dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca /* check for overflow in ns */ 2423dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ns = state->flashOffMS * ONE_MS_IN_NS; 2433dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (ns / ONE_MS_IN_NS != state->flashOffMS) { 2443dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return EINVAL; 2453dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 2463dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ns = state->flashOnMS * ONE_MS_IN_NS; 2473dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (ns / ONE_MS_IN_NS != state->flashOnMS) { 2483dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return EINVAL; 2493dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 2503dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 2513dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return 0; 252748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca} 253c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 254748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 255748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Generic function for setting the state of the light 256748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param base_dev light device data structure 257748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param state what state to set 258748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @return 0 if success, error code otherwise 259748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 260748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int set_light_generic(struct light_device_t *base_dev, 2613dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca struct light_state_t const *state) 262c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare{ 2633dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca struct light_device_ext_t *dev = (struct light_device_ext_t *)base_dev; 2643dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca struct light_state_t *current_state; 2653dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca int rc = 0; 2663dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 2673dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (dev == NULL) { 2683dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGE("%s: Cannot set state for NULL device", __func__); 2693dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return EINVAL; 2703dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 2713dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 2723dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca current_state = &dev->state; 2733dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 2743dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_lock(&dev->write_mutex); 2753dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 2763dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (dev->refs == 0) { 2773dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGE("%s: The light device is not opened", __func__); 2783dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_unlock(&dev->write_mutex); 2793dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return EINVAL; 2803dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 2813dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 2823dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGV("%s: flashMode:%x, color:%x", __func__, state->flashMode, state->color); 2833dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 2843dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (current_state->flashMode) { 2853dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca /* destroy flashing thread */ 2863dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_lock(&dev->flash_signal_mutex); 2873dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca current_state->flashMode = LIGHT_FLASH_NONE; 2883dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_cond_signal(&dev->flash_cond); 2893dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_unlock(&dev->flash_signal_mutex); 2903dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_join(dev->flash_thread, NULL); 2913dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 2923dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 2933dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca *current_state = *state; 294f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca if (dev->transform != NULL) { 295f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca current_state->color = dev->transform(current_state->color); 296f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca } 2973dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 298f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca if (current_state->flashMode) { 2993dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca /* start flashing thread */ 3003dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (check_flash_state(current_state) == 0) { 3013dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca rc = pthread_create(&dev->flash_thread, NULL, 3023dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca flash_routine, (void *)dev); 3033dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (rc != 0) { 3043dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGE("%s: Cannot create flashing thread", __func__); 3053dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca current_state->flashMode = LIGHT_FLASH_NONE; 3063dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 3073dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } else { 3083dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGE("%s: Flash state is invalid", __func__); 3093dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca current_state->flashMode = LIGHT_FLASH_NONE; 3103dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 3113dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } else { 312f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca rc = set_gpio_value(dev->pin, current_state->color); 3133dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (rc != 0) { 3143dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGE("%s: Cannot set light color.", __func__); 3153dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 3163dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 3173dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 3183dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_unlock(&dev->write_mutex); 3193dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 3203dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return rc; 321748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca} 322748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 323748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 324748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Initialize light synchronization resources 325748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param cond what condition variable to initialize 326748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param signal_mutex what mutex (associated with the condvar) to initialize 327748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @return 0 if success, error code otherwise 328748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 329748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int init_light_sync_resources(pthread_cond_t *cond, 3303dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_t *signal_mutex) 331748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca{ 3323dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca int rc = 0; 3333dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_condattr_t condattr; 3343dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 3353dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca rc = pthread_condattr_init(&condattr); 3363dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (rc != 0) { 3373dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGE("%s: Cannot initialize the pthread condattr", __func__); 3383dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return rc; 3393dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 3403dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 3413dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca rc = pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC); 3423dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (rc != 0) { 3433dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGE("%s: Cannot set the clock of condattr to monotonic", __func__); 3443dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca goto destroy_condattr; 3453dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 3463dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 3473dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca rc = pthread_cond_init(cond, &condattr); 3483dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (rc != 0) { 3493dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGE("%s: Cannot intialize the pthread structure", __func__); 3503dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca goto destroy_condattr; 3513dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 3523dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 3533dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca rc = pthread_mutex_init(signal_mutex, NULL); 3543dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (rc != 0) { 3553dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGE("%s: Cannot initialize the mutex associated with the pthread cond", __func__); 3563dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca goto destroy_cond; 3573dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 3583dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 3593dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_condattr_destroy(&condattr); 3603dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return rc; 361748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 362748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscadestroy_cond: 3633dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_cond_destroy(cond); 364748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscadestroy_condattr: 3653dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_condattr_destroy(&condattr); 3663dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return rc; 367748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca} 368748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 369748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 370748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Free light synchronization resources 371748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param cond what condition variable to free 372748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param signal_mutex what mutex (associated with the condvar) to free 373748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 374748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic void free_light_sync_resources(pthread_cond_t *cond, 3753dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_t *signal_mutex) 376748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca{ 3773dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_destroy(signal_mutex); 3783dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_cond_destroy(cond); 379748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca} 380748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 381748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 382748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Close the lights module 383748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param base_dev light device data structure 384748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @return 0 if success, error code otherwise 385748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 386748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int close_lights(struct light_device_t *base_dev) 387748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca{ 3883dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca struct light_device_ext_t *dev = (struct light_device_ext_t *)base_dev; 3893dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca int rc = 0; 3903dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 3913dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (dev == NULL) { 3923dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGE("%s: Cannot deallocate a NULL light device", __func__); 3933dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return EINVAL; 3943dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 3953dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 3963dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_lock(&dev->write_mutex); 3973dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 3983dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (dev->refs == 0) { 3993dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca /* the light device is not open */ 4003dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca rc = EINVAL; 4013dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca goto mutex_unlock; 4023dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } else if (dev->refs > 1) { 4033dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca goto dec_refs; 4043dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 4053dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 4063dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (dev->state.flashMode) { 4073dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca /* destroy flashing thread */ 4083dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_lock(&dev->flash_signal_mutex); 4093dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca dev->state.flashMode = LIGHT_FLASH_NONE; 4103dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_cond_signal(&dev->flash_cond); 4113dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_unlock(&dev->flash_signal_mutex); 4123dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_join(dev->flash_thread, NULL); 4133dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 4143dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 4153dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca free_light_sync_resources(&dev->flash_cond, 4163dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca &dev->flash_signal_mutex); 417748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 418748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscadec_refs: 4193dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca dev->refs--; 420748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 421748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscamutex_unlock: 4223dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_unlock(&dev->write_mutex); 423748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 4243dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return rc; 425c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare} 426c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 427748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 428748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Module initialization routine which detects the LEDs' GPIOs 429748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param type light device type 430748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @return 0 if success, error code otherwise 431748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 432748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int init_module(int type) 433c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare{ 434f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca const char *platform_version = NULL; 4353dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 4363dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (type < 0 || type >= LIGHTS_TYPE_NUM) { 4373dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return EINVAL; 4383dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 4393dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 440f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca light_devices[type].transform = NULL; 441f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca 44239bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Musca switch(mraa_get_platform_type()) { 44339bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Musca case MRAA_INTEL_EDISON_FAB_C: 444f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca platform_version = mraa_get_platform_version(MRAA_MAIN_PLATFORM_OFFSET); 445f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca if ((platform_version != NULL) && (strncmp(platform_version, 446f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca EDISON_ARDUINO_PLATFORM_VERSION, 447f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca strlen(EDISON_ARDUINO_PLATFORM_VERSION)) == 0)) { 44839bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Musca light_devices[type].pin = EDISON_ARDUINO_PINS[type]; 44939bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Musca } else { 45039bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Musca light_devices[type].pin = EDISON_MINIBOARD_PINS[type]; 45139bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Musca } 45239bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Musca break; 45339bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Musca case MRAA_INTEL_MINNOWBOARD_MAX: 454f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca platform_version = mraa_get_platform_version(MRAA_MAIN_PLATFORM_OFFSET); 455f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca if ((platform_version != NULL) && (strncmp(platform_version, 456f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca MINNOWBOARD_TURBOT_PLATFORM_VERSION, 457f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca strlen(MINNOWBOARD_TURBOT_PLATFORM_VERSION)) == 0)) { 458f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca light_devices[type].pin = MINNOWBOARD_TURBOT_PINS[type]; 459f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca light_devices[type].transform = invert_value; 460f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca } else { 461f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca light_devices[type].pin = MINNOWBOARD_MAX_PINS[type]; 462f39cee21fe73ee76b8d5f5ef5bc9746ac1d992f3Constantin Musca } 46339bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Musca break; 46439bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Musca default: 46539bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Musca ALOGE("%s: Hardware platform not supported", __func__); 46639bbf3e39686a35fbc19b1b9b3d2f1e03a8f72c6Constantin Musca return EINVAL; 4673dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 4683dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca 4693dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return 0; 470c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare} 471c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 472748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 473748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Open a new lights device instance by name 474748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param module associated hw module data structure 475748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param name lights device name 476748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param device where to store the pointer of the allocated device 477748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @return 0 if success, error code otherwise 478748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 479c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Bearestatic int open_lights(const struct hw_module_t *module, char const *name, 4803dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca struct hw_device_t **device) 481c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare{ 4823dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca struct light_device_ext_t *dev; 4833dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca int rc = 0, type = -1; 484c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 4853dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGV("%s: Opening %s lights module", __func__, name); 486748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 4873dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) { 4883dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca type = NOTIFICATIONS_TYPE; 4893dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } else { 4903dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return EINVAL; 4913dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 492c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 4933dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca dev = (struct light_device_ext_t *)(light_devices + type); 494c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 4953dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_lock(&dev->write_mutex); 496c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 4973dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (dev->refs != 0) { 4983dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca /* already opened; nothing to do */ 4993dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca goto inc_refs; 5003dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 501748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 5023dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca rc = init_module(type); 5033dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (rc != 0) { 5043dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca ALOGE("%s: Failed to initialize lights module", __func__); 5053dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca goto mutex_unlock; 5063dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 507c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 5083dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca rc = init_light_sync_resources(&dev->flash_cond, 5093dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca &dev->flash_signal_mutex); 5103dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca if (rc != 0) { 5113dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca goto mutex_unlock; 5123dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca } 513748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 5143dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca dev->base_dev.common.tag = HARDWARE_DEVICE_TAG; 5153dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca dev->base_dev.common.version = 0; 5163dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca dev->base_dev.common.module = (struct hw_module_t *)module; 5173dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca dev->base_dev.common.close = (int (*)(struct hw_device_t *))close_lights; 5183dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca dev->base_dev.set_light = set_light_generic; 519748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 520748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscainc_refs: 5213dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca dev->refs++; 5223dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca *device = (struct hw_device_t *)dev; 523c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 524748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscamutex_unlock: 5253dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca pthread_mutex_unlock(&dev->write_mutex); 5263dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca return rc; 527c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare} 528c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 529c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Bearestatic struct hw_module_methods_t lights_methods = 530c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare{ 5313dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca .open = open_lights, 532c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare}; 533c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 534c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Bearestruct hw_module_t HAL_MODULE_INFO_SYM = 535c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare{ 5363dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca .tag = HARDWARE_MODULE_TAG, 5373dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca .version_major = 1, 5383dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca .version_minor = 0, 5393dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca .id = LIGHTS_HARDWARE_MODULE_ID, 5403dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca .name = "Edison lights module", 5413dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca .author = "Intel", 5423dc1f7b573db70eb1d2d37a59080117997ed60b4Constantin Musca .methods = &lights_methods, 543c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare}; 544