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