Home | History | Annotate | Download | only in synaptics_s3708
      1 /*
      2  * Copyright (C) 2016 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 <errno.h>
     18 #include <float.h>
     19 #include <stdlib.h>
     20 #include <string.h>
     21 
     22 #include <eventnums.h>
     23 #include <gpio.h>
     24 #include <heap.h>
     25 #include <hostIntf.h>
     26 #include <isr.h>
     27 #include <i2c.h>
     28 #include <nanohubPacket.h>
     29 #include <sensors.h>
     30 #include <seos.h>
     31 #include <timer.h>
     32 #include <util.h>
     33 
     34 #include <cpu/inc/cpuMath.h>
     35 
     36 #include <plat/inc/exti.h>
     37 #include <plat/inc/gpio.h>
     38 #include <plat/inc/syscfg.h>
     39 
     40 #define S3708_APP_ID                APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, 13)
     41 #define S3708_APP_VERSION           2
     42 
     43 #define I2C_BUS_ID                  0
     44 #define I2C_SPEED                   400000
     45 #define I2C_ADDR                    0x20
     46 
     47 #define S3708_REG_PAGE_SELECT       0xFF
     48 
     49 #define S3708_REG_F01_DATA_BASE     0x06
     50 #define S3708_INT_STATUS_LPWG       0x04
     51 
     52 #define S3708_REG_DATA_BASE         0x08
     53 #define S3708_REG_DATA_4_OFFSET     0x02
     54 #define S3708_INT_STATUS_DOUBLE_TAP 0x03
     55 
     56 #define S3708_REG_F01_CTRL_BASE     0x14
     57 #define S3708_NORMAL_MODE           0x00
     58 #define S3708_SLEEP_MODE            0x01
     59 
     60 #define S3708_REG_CTRL_BASE         0x1b
     61 #define S3708_REG_CTRL_20_OFFSET    0x07
     62 #define S3708_REPORT_MODE_CONT      0x00
     63 #define S3708_REPORT_MODE_LPWG      0x02
     64 
     65 #define MAX_PENDING_I2C_REQUESTS    4
     66 #define MAX_I2C_TRANSFER_SIZE       8
     67 #define MAX_I2C_RETRY_DELAY         250000000ull // 250 milliseconds
     68 #define MAX_I2C_RETRY_COUNT         (15000000000ull / MAX_I2C_RETRY_DELAY) // 15 seconds
     69 #define HACK_RETRY_SKIP_COUNT       1
     70 
     71 #define DEFAULT_PROX_RATE_HZ        SENSOR_HZ(5.0f)
     72 #define DEFAULT_PROX_LATENCY        0.0
     73 #define PROXIMITY_THRESH_NEAR       5.0f    // distance in cm
     74 
     75 #define EVT_SENSOR_PROX  sensorGetMyEventType(SENS_TYPE_PROX)
     76 
     77 #define ENABLE_DEBUG 0
     78 
     79 #define INFO_PRINT(fmt, ...) osLog(LOG_INFO, "[DoubleTouch] " fmt, ##__VA_ARGS__)
     80 #define ERROR_PRINT(fmt, ...) osLog(LOG_ERROR, "[DoubleTouch] " fmt, ##__VA_ARGS__)
     81 #if ENABLE_DEBUG
     82 #define DEBUG_PRINT(fmt, ...) INFO_PRINT(fmt, ##__VA_ARGS__)
     83 #else
     84 #define DEBUG_PRINT(fmt, ...) ((void)0)
     85 #endif
     86 
     87 
     88 #ifndef TOUCH_PIN
     89 #error "TOUCH_PIN is not defined; please define in variant.h"
     90 #endif
     91 
     92 #ifndef TOUCH_IRQ
     93 #error "TOUCH_IRQ is not defined; please define in variant.h"
     94 #endif
     95 
     96 enum SensorEvents
     97 {
     98     EVT_SENSOR_I2C = EVT_APP_START + 1,
     99     EVT_SENSOR_TOUCH_INTERRUPT,
    100     EVT_SENSOR_RETRY_TIMER,
    101 };
    102 
    103 enum TaskState
    104 {
    105     STATE_ENABLE_0,
    106     STATE_ENABLE_1,
    107     STATE_DISABLE_0,
    108     STATE_INT_HANDLE_0,
    109     STATE_INT_HANDLE_1,
    110     STATE_IDLE,
    111     STATE_CANCELLED,
    112 };
    113 
    114 struct I2cTransfer
    115 {
    116     size_t tx;
    117     size_t rx;
    118     int err;
    119     uint8_t txrxBuf[MAX_I2C_TRANSFER_SIZE];
    120     uint8_t state;
    121     bool inUse;
    122 };
    123 
    124 struct TaskStatistics {
    125     uint64_t enabledTimestamp;
    126     uint64_t proxEnabledTimestamp;
    127     uint64_t lastProxFarTimestamp;
    128     uint64_t totalEnabledTime;
    129     uint64_t totalProxEnabledTime;
    130     uint64_t totalProxFarTime;
    131 };
    132 
    133 enum ProxState {
    134     PROX_STATE_UNKNOWN,
    135     PROX_STATE_NEAR,
    136     PROX_STATE_FAR
    137 };
    138 
    139 static struct TaskStruct
    140 {
    141     struct Gpio *pin;
    142     struct ChainedIsr isr;
    143     struct TaskStatistics stats;
    144     struct I2cTransfer transfers[MAX_PENDING_I2C_REQUESTS];
    145     uint32_t id;
    146     uint32_t handle;
    147     uint32_t retryTimerHandle;
    148     uint32_t retryCnt;
    149     uint32_t proxHandle;
    150     enum ProxState proxState;
    151     bool on;
    152     bool gestureEnabled;
    153     bool isrEnabled;
    154 } mTask;
    155 
    156 static inline void enableInterrupt(bool enable)
    157 {
    158     if (!mTask.isrEnabled && enable) {
    159         extiEnableIntGpio(mTask.pin, EXTI_TRIGGER_FALLING);
    160         extiChainIsr(TOUCH_IRQ, &mTask.isr);
    161     } else if (mTask.isrEnabled && !enable) {
    162         extiUnchainIsr(TOUCH_IRQ, &mTask.isr);
    163         extiDisableIntGpio(mTask.pin);
    164     }
    165     mTask.isrEnabled = enable;
    166 }
    167 
    168 static bool touchIsr(struct ChainedIsr *localIsr)
    169 {
    170     struct TaskStruct *data = container_of(localIsr, struct TaskStruct, isr);
    171 
    172     if (!extiIsPendingGpio(data->pin)) {
    173         return false;
    174     }
    175 
    176     osEnqueuePrivateEvt(EVT_SENSOR_TOUCH_INTERRUPT, NULL, NULL, data->id);
    177 
    178     extiClearPendingGpio(data->pin);
    179 
    180     return true;
    181 }
    182 
    183 static void i2cCallback(void *cookie, size_t tx, size_t rx, int err)
    184 {
    185     struct I2cTransfer *xfer = cookie;
    186 
    187     xfer->tx = tx;
    188     xfer->rx = rx;
    189     xfer->err = err;
    190 
    191     osEnqueuePrivateEvt(EVT_SENSOR_I2C, cookie, NULL, mTask.id);
    192     // Do not print error for ENXIO since we expect there to be times where we
    193     // cannot talk to the touch controller.
    194     if (err == -ENXIO) {
    195         DEBUG_PRINT("i2c error (tx: %d, rx: %d, err: %d)\n", tx, rx, err);
    196     } else if (err != 0) {
    197         ERROR_PRINT("i2c error (tx: %d, rx: %d, err: %d)\n", tx, rx, err);
    198     }
    199 }
    200 
    201 static void retryTimerCallback(uint32_t timerId, void *cookie)
    202 {
    203     osEnqueuePrivateEvt(EVT_SENSOR_RETRY_TIMER, cookie, NULL, mTask.id);
    204 }
    205 
    206 // Allocate a buffer and mark it as in use with the given state, or return NULL
    207 // if no buffers available. Must *not* be called from interrupt context.
    208 static struct I2cTransfer *allocXfer(uint8_t state)
    209 {
    210     size_t i;
    211 
    212     for (i = 0; i < ARRAY_SIZE(mTask.transfers); i++) {
    213         if (!mTask.transfers[i].inUse) {
    214             mTask.transfers[i].inUse = true;
    215             mTask.transfers[i].state = state;
    216             memset(mTask.transfers[i].txrxBuf, 0x00, sizeof(mTask.transfers[i].txrxBuf));
    217             return &mTask.transfers[i];
    218         }
    219     }
    220 
    221     ERROR_PRINT("Ran out of I2C buffers!");
    222     return NULL;
    223 }
    224 
    225 // Helper function to initiate the I2C transfer. Returns true is the transaction
    226 // was successfully register by I2C driver. Otherwise, returns false.
    227 static bool performXfer(struct I2cTransfer *xfer, size_t txBytes, size_t rxBytes)
    228 {
    229     int ret;
    230 
    231     if ((txBytes > MAX_I2C_TRANSFER_SIZE) || (rxBytes > MAX_I2C_TRANSFER_SIZE)) {
    232         ERROR_PRINT("txBytes and rxBytes must be less than %d", MAX_I2C_TRANSFER_SIZE);
    233         return false;
    234     }
    235 
    236     if (rxBytes) {
    237         ret = i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, xfer->txrxBuf, txBytes, xfer->txrxBuf, rxBytes, i2cCallback, xfer);
    238     } else {
    239         ret = i2cMasterTx(I2C_BUS_ID, I2C_ADDR, xfer->txrxBuf, txBytes, i2cCallback, xfer);
    240     }
    241 
    242     if (ret != 0) {
    243         ERROR_PRINT("I2C transfer was not successful (error %d)!", ret);
    244     }
    245 
    246     return (ret == 0);
    247 }
    248 
    249 // Helper function to write a one byte register. Returns true if we got a
    250 // successful return value from i2cMasterTx().
    251 static bool writeRegister(uint8_t reg, uint8_t value, uint8_t state)
    252 {
    253     struct I2cTransfer *xfer = allocXfer(state);
    254 
    255     if (xfer != NULL) {
    256         xfer->txrxBuf[0] = reg;
    257         xfer->txrxBuf[1] = value;
    258         return performXfer(xfer, 2, 0);
    259     }
    260 
    261     return false;
    262 }
    263 
    264 static bool setSleepEnable(bool enable, uint8_t state)
    265 {
    266     return writeRegister(S3708_REG_F01_CTRL_BASE, enable ? S3708_SLEEP_MODE : S3708_NORMAL_MODE, state);
    267 }
    268 
    269 static bool setReportingMode(uint8_t mode, uint8_t state)
    270 {
    271     struct I2cTransfer *xfer;
    272 
    273     xfer = allocXfer(state);
    274     if (xfer != NULL) {
    275         xfer->txrxBuf[0] = S3708_REG_CTRL_BASE + S3708_REG_CTRL_20_OFFSET;
    276         xfer->txrxBuf[1] = 0x00;
    277         xfer->txrxBuf[2] = 0x00;
    278         xfer->txrxBuf[3] = mode;
    279         return performXfer(xfer, 4, 0);
    280     }
    281 
    282     return false;
    283 }
    284 
    285 static void setRetryTimer()
    286 {
    287     mTask.retryCnt++;
    288     if (mTask.retryCnt < MAX_I2C_RETRY_COUNT) {
    289         mTask.retryTimerHandle = timTimerSet(MAX_I2C_RETRY_DELAY, 0, 50, retryTimerCallback, NULL, true);
    290         if (!mTask.retryTimerHandle) {
    291             ERROR_PRINT("failed to allocate timer");
    292         }
    293     } else {
    294         ERROR_PRINT("could not communicate with touch controller");
    295     }
    296 }
    297 
    298 static void setGesturePower(bool enable, bool skipI2c)
    299 {
    300     bool ret;
    301     size_t i;
    302 
    303     INFO_PRINT("gesture: %d", enable);
    304 
    305     // Cancel any pending I2C transactions by changing the callback state
    306     for (i = 0; i < ARRAY_SIZE(mTask.transfers); i++) {
    307         if (mTask.transfers[i].inUse) {
    308             mTask.transfers[i].state = STATE_CANCELLED;
    309         }
    310     }
    311 
    312     if (enable) {
    313         mTask.retryCnt = 0;
    314 
    315         // Set page number to 0x00
    316         ret = writeRegister(S3708_REG_PAGE_SELECT, 0x00, STATE_ENABLE_0);
    317     } else {
    318         // Cancel any pending retries
    319         if (mTask.retryTimerHandle) {
    320             timTimerCancel(mTask.retryTimerHandle);
    321             mTask.retryTimerHandle = 0;
    322         }
    323 
    324         if (skipI2c) {
    325             ret = true;
    326         } else {
    327             // Reset to continuous reporting mode
    328             ret = setReportingMode(S3708_REPORT_MODE_CONT, STATE_DISABLE_0);
    329         }
    330     }
    331 
    332     if (ret) {
    333         mTask.gestureEnabled = enable;
    334         enableInterrupt(enable);
    335     }
    336 }
    337 
    338 static void configProx(bool on) {
    339     if (on) {
    340         mTask.stats.proxEnabledTimestamp = sensorGetTime();
    341         sensorRequest(mTask.id, mTask.proxHandle, DEFAULT_PROX_RATE_HZ,
    342                       DEFAULT_PROX_LATENCY);
    343         osEventSubscribe(mTask.id, EVT_SENSOR_PROX);
    344     } else {
    345         sensorRelease(mTask.id, mTask.proxHandle);
    346         osEventUnsubscribe(mTask.id, EVT_SENSOR_PROX);
    347 
    348         mTask.stats.totalProxEnabledTime += sensorGetTime() - mTask.stats.proxEnabledTimestamp;
    349         if (mTask.proxState == PROX_STATE_FAR) {
    350             mTask.stats.totalProxFarTime += sensorGetTime() - mTask.stats.lastProxFarTimestamp;
    351         }
    352     }
    353     mTask.proxState = PROX_STATE_UNKNOWN;
    354 }
    355 
    356 static bool callbackPower(bool on, void *cookie)
    357 {
    358     uint32_t enabledSeconds, proxEnabledSeconds, proxFarSeconds;
    359 
    360     INFO_PRINT("power: %d", on);
    361 
    362     if (on) {
    363         mTask.stats.enabledTimestamp = sensorGetTime();
    364     } else {
    365         mTask.stats.totalEnabledTime += sensorGetTime() - mTask.stats.enabledTimestamp;
    366     }
    367 
    368     enabledSeconds = U64_DIV_BY_U64_CONSTANT(mTask.stats.totalEnabledTime, 1000000000);
    369     proxEnabledSeconds = U64_DIV_BY_U64_CONSTANT(mTask.stats.totalProxEnabledTime, 1000000000);
    370     proxFarSeconds = U64_DIV_BY_U64_CONSTANT(mTask.stats.totalProxFarTime, 1000000000);
    371     INFO_PRINT("STATS: enabled %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32
    372                ", prox enabled %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32
    373                ", prox far %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32,
    374         enabledSeconds / 3600, (enabledSeconds % 3600) / 60, enabledSeconds % 60,
    375         proxEnabledSeconds / 3600, (proxEnabledSeconds % 3600) / 60, proxEnabledSeconds % 60,
    376         proxFarSeconds / 3600, (proxFarSeconds % 3600) / 60, proxFarSeconds % 60);
    377 
    378     // If the task is disabled, that means the AP is on and has switched the I2C
    379     // mux. Therefore, no I2C transactions will succeed so skip them.
    380     if (mTask.gestureEnabled) {
    381         setGesturePower(false, true /* skipI2c */);
    382     }
    383 
    384     mTask.on = on;
    385     configProx(on);
    386 
    387     return sensorSignalInternalEvt(mTask.handle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, mTask.on, 0);
    388 }
    389 
    390 static bool callbackFirmwareUpload(void *cookie)
    391 {
    392     return sensorSignalInternalEvt(mTask.handle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
    393 }
    394 
    395 static bool callbackSetRate(uint32_t rate, uint64_t latency, void *cookie)
    396 {
    397     return sensorSignalInternalEvt(mTask.handle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
    398 }
    399 
    400 static bool callbackFlush(void *cookie)
    401 {
    402     return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_DOUBLE_TOUCH), SENSOR_DATA_EVENT_FLUSH, NULL);
    403 }
    404 
    405 static const struct SensorInfo mSensorInfo = {
    406     .sensorName = "Double Touch",
    407     .sensorType = SENS_TYPE_DOUBLE_TOUCH,
    408     .numAxis = NUM_AXIS_EMBEDDED,
    409     .interrupt = NANOHUB_INT_WAKEUP,
    410     .minSamples = 20
    411 };
    412 
    413 static const struct SensorOps mSensorOps =
    414 {
    415     .sensorPower = callbackPower,
    416     .sensorFirmwareUpload = callbackFirmwareUpload,
    417     .sensorSetRate = callbackSetRate,
    418     .sensorFlush = callbackFlush,
    419 };
    420 
    421 static void processI2cResponse(struct I2cTransfer *xfer)
    422 {
    423     struct I2cTransfer *nextXfer;
    424     union EmbeddedDataPoint sample;
    425 
    426     switch (xfer->state) {
    427         case STATE_ENABLE_0:
    428             setSleepEnable(false, STATE_ENABLE_1);
    429             break;
    430 
    431         case STATE_ENABLE_1:
    432             // HACK: DozeService reactivates pickup gesture before the screen
    433             // comes on, so we need to wait for some time after enabling before
    434             // trying to talk to touch controller. We may see the touch
    435             // controller on the first few samples and then have communication
    436             // switched off. So, wait HACK_RETRY_SKIP_COUNT samples before we
    437             // consider the transaction.
    438             if (mTask.retryCnt < HACK_RETRY_SKIP_COUNT) {
    439                 setRetryTimer();
    440             } else {
    441                 setReportingMode(S3708_REPORT_MODE_LPWG, STATE_IDLE);
    442             }
    443             break;
    444 
    445         case STATE_DISABLE_0:
    446             setSleepEnable(true, STATE_IDLE);
    447             break;
    448 
    449         case STATE_INT_HANDLE_0:
    450             // If the interrupt was from the LPWG function, read the function interrupt status register
    451             if (xfer->txrxBuf[1] & S3708_INT_STATUS_LPWG) {
    452                 nextXfer = allocXfer(STATE_INT_HANDLE_1);
    453                 if (nextXfer != NULL) {
    454                     nextXfer->txrxBuf[0] = S3708_REG_DATA_BASE + S3708_REG_DATA_4_OFFSET;
    455                     performXfer(nextXfer, 1, 5);
    456                 }
    457             }
    458             break;
    459 
    460         case STATE_INT_HANDLE_1:
    461             // Verify the LPWG interrupt status
    462             if (xfer->txrxBuf[0] & S3708_INT_STATUS_DOUBLE_TAP) {
    463                 DEBUG_PRINT("Sending event");
    464                 sample.idata = 1;
    465                 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_DOUBLE_TOUCH), sample.vptr, NULL);
    466             }
    467             break;
    468 
    469         default:
    470             break;
    471     }
    472 }
    473 
    474 static void handleI2cEvent(struct I2cTransfer *xfer)
    475 {
    476     if (xfer->err == 0) {
    477         processI2cResponse(xfer);
    478     } else if (xfer->state == STATE_ENABLE_0 || xfer->state == STATE_ENABLE_1) {
    479         setRetryTimer();
    480     }
    481 
    482     xfer->inUse = false;
    483 }
    484 
    485 static void handleEvent(uint32_t evtType, const void* evtData)
    486 {
    487     struct I2cTransfer *xfer;
    488     union EmbeddedDataPoint embeddedSample;
    489     enum ProxState lastProxState;
    490     int ret;
    491 
    492     switch (evtType) {
    493         case EVT_APP_START:
    494             osEventUnsubscribe(mTask.id, EVT_APP_START);
    495             ret = i2cMasterRequest(I2C_BUS_ID, I2C_SPEED);
    496             // Since the i2c bus can be shared with other drivers, it is
    497             // possible that one of the other drivers requested the bus first.
    498             // Therefore, either 0 or -EBUSY is an acceptable return.
    499             if ((ret < 0) && (ret != -EBUSY)) {
    500                 ERROR_PRINT("i2cMasterRequest() failed!");
    501             }
    502 
    503             sensorFind(SENS_TYPE_PROX, 0, &mTask.proxHandle);
    504 
    505             sensorRegisterInitComplete(mTask.handle);
    506             break;
    507 
    508         case EVT_SENSOR_I2C:
    509             handleI2cEvent((struct I2cTransfer *)evtData);
    510             break;
    511 
    512         case EVT_SENSOR_TOUCH_INTERRUPT:
    513             if (mTask.on) {
    514                 // Read the interrupt status register
    515                 xfer = allocXfer(STATE_INT_HANDLE_0);
    516                 if (xfer != NULL) {
    517                     xfer->txrxBuf[0] = S3708_REG_F01_DATA_BASE;
    518                     performXfer(xfer, 1, 2);
    519                 }
    520             }
    521             break;
    522 
    523         case EVT_SENSOR_PROX:
    524             if (mTask.on) {
    525                 // cast off the const, and cast to union
    526                 embeddedSample = (union EmbeddedDataPoint)((void*)evtData);
    527                 lastProxState = mTask.proxState;
    528                 mTask.proxState = (embeddedSample.fdata < PROXIMITY_THRESH_NEAR) ? PROX_STATE_NEAR : PROX_STATE_FAR;
    529 
    530                 if ((lastProxState != PROX_STATE_FAR) && (mTask.proxState == PROX_STATE_FAR)) {
    531                     mTask.stats.lastProxFarTimestamp = sensorGetTime();
    532                     setGesturePower(true, false);
    533                 } else if ((lastProxState == PROX_STATE_FAR) && (mTask.proxState == PROX_STATE_NEAR)) {
    534                     mTask.stats.totalProxFarTime += sensorGetTime() - mTask.stats.lastProxFarTimestamp;
    535                     setGesturePower(false, false);
    536                 }
    537             }
    538             break;
    539 
    540         case EVT_SENSOR_RETRY_TIMER:
    541             if (mTask.on) {
    542                 // Set page number to 0x00
    543                 writeRegister(S3708_REG_PAGE_SELECT, 0x00, STATE_ENABLE_0);
    544             }
    545             break;
    546     }
    547 }
    548 
    549 static bool startTask(uint32_t taskId)
    550 {
    551     mTask.id = taskId;
    552     mTask.handle = sensorRegister(&mSensorInfo, &mSensorOps, NULL, false);
    553 
    554     mTask.pin = gpioRequest(TOUCH_PIN);
    555     gpioConfigInput(mTask.pin, GPIO_SPEED_LOW, GPIO_PULL_NONE);
    556     syscfgSetExtiPort(mTask.pin);
    557     mTask.isr.func = touchIsr;
    558 
    559     osEventSubscribe(taskId, EVT_APP_START);
    560     return true;
    561 }
    562 
    563 static void endTask(void)
    564 {
    565     enableInterrupt(false);
    566     extiUnchainIsr(TOUCH_IRQ, &mTask.isr);
    567     extiClearPendingGpio(mTask.pin);
    568     gpioRelease(mTask.pin);
    569 
    570     i2cMasterRelease(I2C_BUS_ID);
    571 
    572     sensorUnregister(mTask.handle);
    573 }
    574 
    575 INTERNAL_APP_INIT(S3708_APP_ID, S3708_APP_VERSION, startTask, endTask, handleEvent);
    576