Home | History | Annotate | Download | only in leds
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdlib.h>
     18 #include <string.h>
     19 
     20 #include <eventnums.h>
     21 #include <gpio.h>
     22 #include <hostIntf.h>
     23 #include <leds_gpio.h>
     24 #include <nanohubPacket.h>
     25 #include <sensors.h>
     26 #include <seos.h>
     27 #include <timer.h>
     28 #include <plat/gpio.h>
     29 #include <plat/exti.h>
     30 #include <plat/syscfg.h>
     31 #include <variant/variant.h>
     32 
     33 #define LEDS_GPIO_APP_ID        APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 20)
     34 #define LEDS_GPIO_APP_VERSION   1
     35 
     36 #ifndef LEDS_DBG_ENABLE
     37 #define LEDS_DBG_ENABLE         0
     38 #endif
     39 
     40 enum sensorLedsEvents
     41 {
     42     EVT_SENSOR_LEDS_TIMER = EVT_APP_START + 1,
     43     EVT_TEST,
     44 };
     45 
     46 struct LedsVal {
     47     struct Gpio *ledid;
     48     uint8_t val;
     49 };
     50 
     51 static struct LedsTask
     52 {
     53     struct LedsVal leds[LEDS_GPIO_MAX];
     54     uint32_t num;
     55 
     56     uint32_t id;
     57     uint32_t sHandle;
     58     uint32_t ledsTimerHandle;
     59     bool     ledsOn;
     60 } mTask;
     61 
     62 static void sensorLedsTimerCallback(uint32_t timerId, void *data)
     63 {
     64     osEnqueuePrivateEvt(EVT_SENSOR_LEDS_TIMER, data, NULL, mTask.id);
     65 }
     66 
     67 static uint32_t ledsRates[] = {
     68     SENSOR_HZ(0.1),
     69     SENSOR_HZ(0.5),
     70     SENSOR_HZ(1.0f),
     71     SENSOR_HZ(2.0f),
     72     0
     73 };
     74 
     75 // should match "supported rates in length"
     76 static const uint64_t ledsRatesRateVals[] =
     77 {
     78     10 * 1000000000ULL,
     79     2 * 1000000000ULL,
     80     1 * 1000000000ULL,
     81     1000000000ULL / 2,
     82 };
     83 
     84 /* Sensor Operations */
     85 static bool sensorLedsPower(bool on, void *cookie)
     86 {
     87     if (mTask.ledsTimerHandle) {
     88         timTimerCancel(mTask.ledsTimerHandle);
     89         mTask.ledsTimerHandle = 0;
     90     }
     91 
     92     return sensorSignalInternalEvt(mTask.sHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, on, 0);
     93 }
     94 
     95 static bool sensorLedsFwUpload(void *cookie)
     96 {
     97     return sensorSignalInternalEvt(mTask.sHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
     98 }
     99 
    100 static bool sensorLedsSetRate(uint32_t rate, uint64_t latency, void *cookie)
    101 {
    102     if (mTask.ledsTimerHandle)
    103         timTimerCancel(mTask.ledsTimerHandle);
    104 
    105     mTask.ledsTimerHandle = timTimerSet(sensorTimerLookupCommon(ledsRates,
    106                 ledsRatesRateVals, rate), 0, 50, sensorLedsTimerCallback, NULL, false);
    107 
    108     return sensorSignalInternalEvt(mTask.sHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
    109 }
    110 
    111 static bool sensorConfigLedsGpio(void *cfgData, void *buf)
    112 {
    113     struct LedsCfg *lcfg = (struct LedsCfg *)cfgData;
    114 
    115     if (lcfg->led_num >= mTask.num) {
    116         osLog(LOG_INFO, "Wrong led number %"PRIu32"\n", lcfg->led_num);
    117         return false;
    118     }
    119     mTask.leds[lcfg->led_num].val = lcfg->value ? 1 : 0;
    120     gpioSet(mTask.leds[lcfg->led_num].ledid, mTask.leds[lcfg->led_num].val);
    121 
    122     osLog(LOG_INFO, "Set led[%"PRIu32"]=%"PRIu32"\n", lcfg->led_num, lcfg->value);
    123     return true;
    124 }
    125 
    126 static void sensorLedsOnOff(bool flag)
    127 {
    128     uint32_t i;
    129 
    130     for (i=0; i < mTask.num; i++)
    131         gpioSet(mTask.leds[i].ledid, flag ? mTask.leds[i].val : 0);
    132 }
    133 
    134 static const struct SensorInfo sensorInfoLedsGpio = {
    135     .sensorName = "Leds-Gpio",
    136     .sensorType = SENS_TYPE_LEDS,
    137     .supportedRates = ledsRates,
    138 };
    139 
    140 static const struct SensorOps sensorOpsLedsGpio = {
    141     .sensorPower    = sensorLedsPower,
    142     .sensorFirmwareUpload = sensorLedsFwUpload,
    143     .sensorSetRate  = sensorLedsSetRate,
    144     .sensorCfgData  = sensorConfigLedsGpio,
    145 };
    146 
    147 static void handleEvent(uint32_t evtType, const void *evtData)
    148 {
    149     switch (evtType) {
    150     case EVT_APP_START:
    151         osEventUnsubscribe(mTask.id, EVT_APP_START);
    152         /* Test leds */
    153         if (LEDS_DBG_ENABLE) {
    154             mTask.leds[0].val = 1;
    155             osEnqueuePrivateEvt(EVT_TEST, NULL, NULL, mTask.id);
    156         }
    157         osLog(LOG_INFO, "[Leds-Gpio] detected\n");
    158         break;
    159     case EVT_SENSOR_LEDS_TIMER:
    160         mTask.ledsOn = !mTask.ledsOn;
    161         sensorLedsOnOff(mTask.ledsOn);
    162         break;
    163     case EVT_TEST:
    164         sensorLedsSetRate(SENSOR_HZ(1), 0, NULL);
    165         break;
    166     default:
    167         break;
    168     }
    169 }
    170 
    171 static bool startTask(uint32_t taskId)
    172 {
    173     const struct LedsGpio *leds;
    174     struct Gpio *led;
    175     uint32_t i;
    176 
    177     mTask.id = taskId;
    178     mTask.num = 0;
    179     mTask.ledsOn = false;
    180 
    181     leds = ledsGpioBoardCfg();
    182     for (i=0; i < leds->num && i < LEDS_GPIO_MAX; i++) {
    183         led = gpioRequest(leds->leds_array[i]);
    184         if (!led)
    185             continue;
    186         mTask.leds[mTask.num].val = 0;
    187         mTask.leds[mTask.num++].ledid = led;
    188         gpioConfigOutput(led, GPIO_SPEED_LOW, GPIO_PULL_NONE, GPIO_OUT_PUSH_PULL, 0);
    189     }
    190     if (mTask.num == 0)
    191         return false;
    192     mTask.sHandle = sensorRegister(&sensorInfoLedsGpio, &sensorOpsLedsGpio, NULL, true);
    193     osEventSubscribe(taskId, EVT_APP_START);
    194     return true;
    195 }
    196 
    197 static void endTask(void)
    198 {
    199     uint32_t i;
    200 
    201     sensorUnregister(mTask.sHandle);
    202     for (i=0; i < mTask.num; i++) {
    203         gpioSet(mTask.leds[i].ledid, 0);
    204         gpioRelease(mTask.leds[i].ledid);
    205     }
    206 }
    207 
    208 INTERNAL_APP_INIT(LEDS_GPIO_APP_ID, LEDS_GPIO_APP_VERSION, startTask, endTask, handleEvent);
    209