lights.c revision 748d6cd3dec472369f0de2eab0fff7a1e80d77ab
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 { 34748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca NOTIFICATIONS_TYPE, 35748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca LIGHTS_TYPE_NUM 36748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca} light_type_t; 37748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 38748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* Light device data structure */ 39748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastruct light_device_ext_t { 40748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca /* Base device */ 41748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca struct light_device_t base_dev; 42748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca /* Physical pin */ 43748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca int pin; 44748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca /* Current state of the light device */ 45748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca struct light_state_t state; 46748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca /* Number of device references */ 47748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca int refs; 48748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca /* Synchronization attributes */ 49748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_t flash_thread; 50748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_cond_t flash_cond; 51748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_t flash_signal_mutex; 52748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_t write_mutex; 53748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca}; 54748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 55748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int64_t const ONE_MS_IN_NS = 1000000LL; 56748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int64_t const ONE_S_IN_NS = 1000000000LL; 57748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 58748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 59748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Raw pin number for identifying the TRI_STATE_ALL GPIO 60748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * used to determine if we're on an Arduino board 61748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 62748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int const TRI_STATE_ALL_GPIO_RAW_PIN = 214; 63748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 64748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 65748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Pin constants 66748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Please add a pin to ARDUINO_PINS & NON_ARDUINO_PINS 67748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * when you add a new light type 68748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 69748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int const ARDUINO_PINS[LIGHTS_TYPE_NUM] = {13}; 70748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int const NON_ARDUINO_PINS[LIGHTS_TYPE_NUM] = {31}; 71748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 72748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 73748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Array of light devices with write_mutex statically initialized 74748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * to be able to synchronize the open_lights & close_lights functions 75748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 76748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastruct light_device_ext_t light_devices[] = { 77748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca [ 0 ... (LIGHTS_TYPE_NUM - 1) ] = { .write_mutex = PTHREAD_MUTEX_INITIALIZER } 78748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca}; 79c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 80748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 81748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Set the GPIO value 82748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param pin physical pin of the GPIO 83748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param value what value to set 84748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @return 0 if success, error code otherwise 85748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 86748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int set_gpio_value(int pin, int value) 87748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca{ 88748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca mraa_gpio_context gpio = NULL; 89748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca int rc = 0; 90748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 91748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if ((value != 0) && (value != 1)) { 92748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return EINVAL; 93748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 94c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 95748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca gpio = mraa_gpio_init(pin); 96748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (gpio == NULL) { 97748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return EPERM; 98748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 99748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 100748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (mraa_gpio_dir(gpio, MRAA_GPIO_OUT) != MRAA_SUCCESS) { 101748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca rc = EPERM; 102748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca goto close_gpio; 103748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 104748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 105748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (mraa_gpio_write(gpio, value) != MRAA_SUCCESS) { 106748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca rc = EPERM; 107748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 108c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 109748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscaclose_gpio: 110748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (mraa_gpio_close(gpio) != MRAA_SUCCESS) { 111748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca rc = EPERM; 112748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 113748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 114748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return rc; 115748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca} 116748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 117748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 118748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Get current timestamp in nanoseconds 119748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @return time in nanoseconds 120748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 121748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscaint64_t get_timestamp_monotonic() 122c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare{ 123748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca struct timespec ts = {0}; 124748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 125748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (!clock_gettime(CLOCK_MONOTONIC, &ts)) { 126748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return ONE_S_IN_NS * ts.tv_sec + ts.tv_nsec; 127748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 128748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 129748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return -1; 130748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca} 131748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 132748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 133748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Populates a timespec data structure from a int64_t timestamp 134748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param out what timespec to populate 135748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param target_ns timestamp in nanoseconds 136748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 137748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscavoid set_timestamp(struct timespec *out, int64_t target_ns) 138748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca{ 139748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca out->tv_sec = target_ns / ONE_S_IN_NS; 140748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca out->tv_nsec = target_ns % ONE_S_IN_NS; 141748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca} 142748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 143748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 144748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * pthread routine which flashes an LED 145748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param flash_param light device pointer 146748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 147748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic void * flash_routine (void *flash_param) 148748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca{ 149748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca struct light_device_ext_t *dev = (struct light_device_ext_t *)flash_param; 150748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca struct light_state_t *flash_state; 151748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca int color = 0, rc = 0; 152748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca struct timespec target_time; 153748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca int64_t timestamp, period; 154748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 155748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (dev == NULL) { 156748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGE("%s: Cannot flash a NULL light device", __func__); 157748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return NULL; 158748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 159748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 160748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca flash_state = &dev->state; 161748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 162748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_lock(&dev->flash_signal_mutex); 163748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 164748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca color = flash_state->color; 165748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 166748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca /* Light flashing loop */ 167748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca while (flash_state->flashMode) { 168748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca rc = set_gpio_value(dev->pin, color); 169748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (rc != 0) { 170748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGE("%s: Cannot set light color", __func__); 171748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca goto mutex_unlock; 172748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 173748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 174748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca timestamp = get_timestamp_monotonic(); 175748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (timestamp < 0) { 176748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGE("%s: Cannot get time from monotonic clock", __func__); 177748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca goto mutex_unlock; 178748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 179748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 180748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (color) { 181748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca color = 0; 182748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca period = flash_state->flashOnMS * ONE_MS_IN_NS; 183748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } else { 184748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca color = 1; 185748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca period = flash_state->flashOffMS * ONE_MS_IN_NS; 186748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 187748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 188748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca /* check for overflow */ 189748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (timestamp > LLONG_MAX - period) { 190748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGE("%s: Timestamp overflow", __func__); 191748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca goto mutex_unlock; 192748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 193748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 194748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca timestamp += period; 195748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 196748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca /* sleep until target_time or the cond var is signaled */ 197748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca set_timestamp(&target_time, timestamp); 198748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca rc = pthread_cond_timedwait(&dev->flash_cond, &dev->flash_signal_mutex, &target_time); 199748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if ((rc != 0) && (rc != ETIMEDOUT)) { 200748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGE("%s: pthread_cond_timedwait returned an error", __func__); 201748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca goto mutex_unlock; 202c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare } 203c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare } 204748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 205748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscamutex_unlock: 206748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_unlock(&dev->flash_signal_mutex); 207748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 208748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return NULL; 209c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare} 210c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 211748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 212748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Check lights flash state 213748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param state pointer to the state to check 214748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @return 0 if success, error code otherwise 215748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 216748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int check_flash_state(struct light_state_t const *state) 217748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca{ 218748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca int64_t ns = 0; 219748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 220748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if ((state->flashOffMS < 0) || (state->flashOnMS < 0)) { 221748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return EINVAL; 222748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 223748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 224748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if ((state->flashOffMS == 0) && (state->flashOnMS) == 0) { 225748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return EINVAL; 226748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 227748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 228748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca /* check for overflow in ns */ 229748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ns = state->flashOffMS * ONE_MS_IN_NS; 230748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (ns / ONE_MS_IN_NS != state->flashOffMS) { 231748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return EINVAL; 232748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 233748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ns = state->flashOnMS * ONE_MS_IN_NS; 234748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (ns / ONE_MS_IN_NS != state->flashOnMS) { 235748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return EINVAL; 236748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 237748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 238748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return 0; 239748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca} 240c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 241748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 242748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Generic function for setting the state of the light 243748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param base_dev light device data structure 244748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param state what state to set 245748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @return 0 if success, error code otherwise 246748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 247748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int set_light_generic(struct light_device_t *base_dev, 248748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca struct light_state_t const *state) 249c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare{ 250748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca struct light_device_ext_t *dev = (struct light_device_ext_t *)base_dev; 251748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca struct light_state_t *current_state; 252748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca int rc = 0; 253748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 254748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (dev == NULL) { 255748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGE("%s: Cannot set state for NULL device", __func__); 256748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return EINVAL; 257748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 258748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 259748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca current_state = &dev->state; 260748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 261748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_lock(&dev->write_mutex); 262748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 263748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGV("%s: flashMode:%x, color:%x", __func__, state->flashMode, state->color); 264748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 265748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (current_state->flashMode) { 266748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca /* destroy flashing thread */ 267748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_lock(&dev->flash_signal_mutex); 268748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca current_state->flashMode = LIGHT_FLASH_NONE; 269748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_cond_signal(&dev->flash_cond); 270748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_unlock(&dev->flash_signal_mutex); 271748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_join(dev->flash_thread, NULL); 272748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 273748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 274748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca *current_state = *state; 275748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 276748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (state->flashMode) { 277748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca /* start flashing thread */ 278748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (check_flash_state(current_state) == 0) { 279748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca rc = pthread_create(&dev->flash_thread, NULL, 280748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca flash_routine, (void *)dev); 281748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (rc != 0) { 282748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGE("%s: Cannot create flashing thread", __func__); 283748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca current_state->flashMode = LIGHT_FLASH_NONE; 284748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 285748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } else { 286748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGE("%s: Flash state is invalid", __func__); 287748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca current_state->flashMode = LIGHT_FLASH_NONE; 288748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 289c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare } else { 290748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca rc = set_gpio_value(dev->pin, state->color); 291748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (rc != 0) { 292748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGE("%s: Cannot set light color.", __func__); 293748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 294748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 295748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 296748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_unlock(&dev->write_mutex); 297748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 298748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return rc; 299748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca} 300748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 301748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 302748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Initialize light synchronization resources 303748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param cond what condition variable to initialize 304748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param signal_mutex what mutex (associated with the condvar) to initialize 305748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @return 0 if success, error code otherwise 306748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 307748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int init_light_sync_resources(pthread_cond_t *cond, 308748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_t *signal_mutex) 309748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca{ 310748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca int rc = 0; 311748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_condattr_t condattr; 312748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 313748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca rc = pthread_condattr_init(&condattr); 314748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (rc != 0) { 315748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGE("%s: Cannot initialize the pthread condattr", __func__); 316748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return rc; 317748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 318748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 319748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca rc = pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC); 320748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (rc != 0) { 321748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGE("%s: Cannot set the clock of condattr to monotonic", __func__); 322748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca goto destroy_condattr; 323748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 324748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 325748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca rc = pthread_cond_init(cond, &condattr); 326748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (rc != 0) { 327748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGE("%s: Cannot intialize the pthread structure", __func__); 328748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca goto destroy_condattr; 329748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 330748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 331748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca rc = pthread_mutex_init(signal_mutex, NULL); 332748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (rc != 0) { 333748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGE("%s: Cannot initialize the mutex associated with the pthread cond", __func__); 334748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca goto destroy_cond; 335748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 336748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 337748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_condattr_destroy(&condattr); 338748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return rc; 339748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 340748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscadestroy_cond: 341748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_cond_destroy(cond); 342748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscadestroy_condattr: 343748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_condattr_destroy(&condattr); 344748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return rc; 345748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca} 346748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 347748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 348748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Free light synchronization resources 349748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param cond what condition variable to free 350748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param signal_mutex what mutex (associated with the condvar) to free 351748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 352748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic void free_light_sync_resources(pthread_cond_t *cond, 353748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_t *signal_mutex) 354748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca{ 355748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_destroy(signal_mutex); 356748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_cond_destroy(cond); 357748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca} 358748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 359748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 360748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Close the lights module 361748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param base_dev light device data structure 362748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @return 0 if success, error code otherwise 363748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 364748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int close_lights(struct light_device_t *base_dev) 365748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca{ 366748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca struct light_device_ext_t *dev = (struct light_device_ext_t *)base_dev; 367748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca int rc = 0; 368748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 369748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (dev == NULL) { 370748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGE("%s: Cannot deallocate a NULL light device", __func__); 371748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return EINVAL; 372c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare } 373c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 374748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_lock(&dev->write_mutex); 375748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 376748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (dev->refs == 0) { 377748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca /* the light device is not open */ 378748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca rc = EINVAL; 379748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca goto mutex_unlock; 380748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } else if (dev->refs > 1) { 381748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca goto dec_refs; 382748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 383748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 384748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (dev->state.flashMode) { 385748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca /* destroy flashing thread */ 386748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_lock(&dev->flash_signal_mutex); 387748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca dev->state.flashMode = LIGHT_FLASH_NONE; 388748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_cond_signal(&dev->flash_cond); 389748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_unlock(&dev->flash_signal_mutex); 390748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_join(dev->flash_thread, NULL); 391748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 392748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 393748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca free_light_sync_resources(&dev->flash_cond, 394748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca &dev->flash_signal_mutex); 395748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 396748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscadec_refs: 397748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca dev->refs--; 398748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 399748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscamutex_unlock: 400748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_unlock(&dev->write_mutex); 401748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 402748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return rc; 403c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare} 404c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 405748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 406748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Module initialization routine which detects the LEDs' GPIOs 407748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param type light device type 408748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @return 0 if success, error code otherwise 409748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 410748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscastatic int init_module(int type) 411c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare{ 412748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca mraa_gpio_context gpio; 413748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 414748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (type < 0 || type >= LIGHTS_TYPE_NUM) { 415748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return EINVAL; 416748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 417748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 418748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca gpio = mraa_gpio_init_raw(TRI_STATE_ALL_GPIO_RAW_PIN); 419748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (gpio != NULL) { 420748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca /* Arduino board detected */ 421748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca mraa_gpio_close(gpio); 422748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca light_devices[type].pin = ARDUINO_PINS[type]; 423748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } else { 424748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca light_devices[type].pin = NON_ARDUINO_PINS[type]; 425748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 426748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 427c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare return 0; 428c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare} 429c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 430748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca/* 431748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * Open a new lights device instance by name 432748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param module associated hw module data structure 433748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param name lights device name 434748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @param device where to store the pointer of the allocated device 435748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca * @return 0 if success, error code otherwise 436748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca */ 437c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Bearestatic int open_lights(const struct hw_module_t *module, char const *name, 438c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare struct hw_device_t **device) 439c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare{ 440748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca struct light_device_ext_t *dev; 441748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca int rc = 0, type = -1; 442c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 443748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGV("%s: Opening %s lights module", __func__, name); 444748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 445748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) { 446748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca type = NOTIFICATIONS_TYPE; 447748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } else { 448748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return EINVAL; 449c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare } 450c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 451748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca dev = (struct light_device_ext_t *)(light_devices + type); 452c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 453748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_lock(&dev->write_mutex); 454c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 455748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (dev->refs != 0) { 456748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca /* already opened; nothing to do */ 457748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca goto inc_refs; 458748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 459748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 460748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca rc = init_module(type); 461748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (rc != 0) { 462748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca ALOGE("%s: Failed to initialize lights module", __func__); 463748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca goto mutex_unlock; 464748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 465c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 466748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca rc = init_light_sync_resources(&dev->flash_cond, 467748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca &dev->flash_signal_mutex); 468748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca if (rc != 0) { 469748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca goto mutex_unlock; 470748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca } 471748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 472748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca dev->base_dev.common.tag = HARDWARE_DEVICE_TAG; 473748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca dev->base_dev.common.version = 0; 474748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca dev->base_dev.common.module = (struct hw_module_t *)module; 475748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca dev->base_dev.common.close = (int (*)(struct hw_device_t *))close_lights; 476748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca dev->base_dev.set_light = set_light_generic; 477748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca 478748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscainc_refs: 479748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca dev->refs++; 480c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare *device = (struct hw_device_t *)dev; 481c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 482748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Muscamutex_unlock: 483748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca pthread_mutex_unlock(&dev->write_mutex); 484748d6cd3dec472369f0de2eab0fff7a1e80d77abConstantin Musca return rc; 485c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare} 486c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 487c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Bearestatic struct hw_module_methods_t lights_methods = 488c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare{ 489c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare .open = open_lights, 490c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare}; 491c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare 492c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Bearestruct hw_module_t HAL_MODULE_INFO_SYM = 493c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare{ 494c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare .tag = HARDWARE_MODULE_TAG, 495c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare .version_major = 1, 496c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare .version_minor = 0, 497c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare .id = LIGHTS_HARDWARE_MODULE_ID, 498c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare .name = "Edison lights module", 499c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare .author = "Intel", 500c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare .methods = &lights_methods, 501c7c4ec1204c73d3844935d3da7d07ddebd4f6607Bruce Beare}; 502