1// Copyright 2018 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#pragma once 6 7#include <threads.h> 8 9#include <ddk/device.h> 10#include <ddk/protocol/gpio.h> 11#include <ddk/protocol/i2c.h> 12#include <ddk/protocol/test.h> 13#include <ddktl/device.h> 14#include <ddktl/protocol/hidbus.h> 15#include <ddktl/protocol/test.h> 16#include <fbl/mutex.h> 17#include <fbl/unique_ptr.h> 18#include <hid/ft3x27.h> 19 20#include <lib/zx/interrupt.h> 21#include <zircon/compiler.h> 22#include <zircon/types.h> 23 24enum { 25 FT_INT_PIN, 26 FT_RESET_PIN, 27 FT_PIN_COUNT, 28}; 29 30// clang-format off 31#define FTS_REG_CURPOINT 0x02 32#define FTS_REG_FINGER_START 0x03 33#define FTS_REG_INT_CNT 0x8F 34#define FTS_REG_FLOW_WORK_CNT 0x91 35#define FTS_REG_WORKMODE 0x00 36#define FTS_REG_WORKMODE_FACTORY_VALUE 0x40 37#define FTS_REG_WORKMODE_WORK_VALUE 0x00 38#define FTS_REG_ESDCHECK_DISABLE 0x8D 39#define FTS_REG_CHIP_ID 0xA3 40#define FTS_REG_CHIP_ID2 0x9F 41#define FTS_REG_POWER_MODE 0xA5 42#define FTS_REG_POWER_MODE_SLEEP_VALUE 0x03 43#define FTS_REG_FW_VER 0xA6 44#define FTS_REG_VENDOR_ID 0xA8 45#define FTS_REG_LCD_BUSY_NUM 0xAB 46#define FTS_REG_FACE_DEC_MODE_EN 0xB0 47#define FTS_REG_FACE_DEC_MODE_STATUS 0x01 48#define FTS_REG_IDE_PARA_VER_ID 0xB5 49#define FTS_REG_IDE_PARA_STATUS 0xB6 50#define FTS_REG_GLOVE_MODE_EN 0xC0 51#define FTS_REG_COVER_MODE_EN 0xC1 52#define FTS_REG_CHARGER_MODE_EN 0x8B 53#define FTS_REG_GESTURE_EN 0xD0 54#define FTS_REG_GESTURE_OUTPUT_ADDRESS 0xD3 55#define FTS_REG_MODULE_ID 0xE3 56#define FTS_REG_LIC_VER 0xE4 57#define FTS_REG_ESD_SATURATE 0xED 58// clang-format on 59 60namespace ft { 61class Ft3x27Device : public ddk::Device<Ft3x27Device, ddk::Unbindable>, 62 public ddk::HidBusProtocol<Ft3x27Device> { 63public: 64 Ft3x27Device(zx_device_t* device); 65 66 static zx_status_t Create(zx_device_t* device); 67 68 void DdkRelease(); 69 void DdkUnbind() __TA_EXCLUDES(proxy_lock_); 70 71 // HidBus required methods 72 void HidBusStop(); 73 zx_status_t HidBusGetDescriptor(uint8_t desc_type, void** data, size_t* len); 74 zx_status_t HidBusGetReport(uint8_t rpt_type, uint8_t rpt_id, void* data, 75 size_t len, size_t* out_len); 76 zx_status_t HidBusSetReport(uint8_t rpt_type, uint8_t rpt_id, void* data, 77 size_t len); 78 zx_status_t HidBusGetIdle(uint8_t rpt_id, uint8_t* duration); 79 zx_status_t HidBusSetIdle(uint8_t rpt_id, uint8_t duration); 80 zx_status_t HidBusGetProtocol(uint8_t* protocol); 81 zx_status_t HidBusSetProtocol(uint8_t protocol); 82 zx_status_t HidBusStart(ddk::HidBusIfcProxy proxy) __TA_EXCLUDES(proxy_lock_); 83 zx_status_t HidBusQuery(uint32_t options, hid_info_t* info) __TA_EXCLUDES(proxy_lock_); 84 85private: 86 /* Note: the ft3x27 device is connected via i2c and is NOT a HID 87 device. This driver reads a collection of data from the data and 88 parses it into a message which will be sent up the stack. This message 89 complies with a HID descriptor that manually scripted (i.e. - not 90 reported by the device iteself). 91 */ 92 // Number of touch points this device can report simultaneously 93 static constexpr uint32_t kMaxPoints = 5; 94 // Size of each individual touch record (note: there are kMaxPoints of 95 // them) on the i2c bus. This is not the HID report size. 96 static constexpr uint32_t kFingerRptSize = 6; 97 98 zx_status_t InitPdev(); 99 zx_status_t ShutDown() __TA_EXCLUDES(proxy_lock_); 100 101 uint8_t Read(uint8_t addr); 102 zx_status_t Read(uint8_t addr, uint8_t* buf, uint8_t len); 103 104 int Thread(); 105 106 ft3x27_touch_t ft_rpt_ __TA_GUARDED(proxy_lock_); 107 void ParseReport(ft3x27_finger_t* rpt, uint8_t* buf); 108 109 gpio_protocol_t gpios_[FT_PIN_COUNT]; 110 zx::interrupt irq_; 111 i2c_protocol_t i2c_; 112 113 thrd_t thread_; 114 fbl::atomic<bool> running_; 115 116 fbl::Mutex proxy_lock_; 117 ddk::HidBusIfcProxy proxy_ __TA_GUARDED(proxy_lock_); 118}; 119} 120