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