blob: 946fb02a2e37de8fd843b3ae4896f661857ca7fd [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVICES_LIGHT_SENSOR_DRIVERS_AMS_LIGHT_TCS3400_H_
#define SRC_DEVICES_LIGHT_SENSOR_DRIVERS_AMS_LIGHT_TCS3400_H_
#include <lib/device-protocol/i2c-channel.h>
#include <lib/zircon-internal/thread_annotations.h>
#include <lib/zx/interrupt.h>
#include <lib/zx/status.h>
#include <time.h>
#include <ddktl/device.h>
#include <ddktl/protocol/gpio.h>
#include <ddktl/protocol/hidbus.h>
#include <fbl/mutex.h>
#include <hid/ambient-light.h>
namespace tcs {
class Tcs3400Device;
using DeviceType = ddk::Device<Tcs3400Device, ddk::Unbindable>;
// Note: the TCS-3400 device is connected via i2c and is not a HID
// device. This driver reads a collection of data from the data and
// parses it into a message which will be sent up the stack. This message
// complies with a HID descriptor that was manually scripted (i.e. - not
// reported by the device iteself).
class Tcs3400Device : public DeviceType,
public ddk::HidbusProtocol<Tcs3400Device, ddk::base_protocol> {
public:
static zx_status_t Create(void* ctx, zx_device_t* parent);
Tcs3400Device(zx_device_t* device, ddk::I2cChannel i2c, ddk::GpioProtocolClient gpio,
zx::port port)
: DeviceType(device), i2c_(std::move(i2c)), gpio_(gpio), port_(std::move(port)) {}
virtual ~Tcs3400Device() = default;
zx_status_t Bind();
zx_status_t InitMetadata();
// Methods required by the ddk mixins
zx_status_t HidbusStart(const hidbus_ifc_protocol_t* ifc) TA_EXCL(client_input_lock_);
zx_status_t HidbusQuery(uint32_t options, hid_info_t* info);
void HidbusStop();
zx_status_t HidbusGetDescriptor(hid_description_type_t desc_type, void* out_data_buffer,
size_t data_size, size_t* out_data_actual);
zx_status_t HidbusGetReport(uint8_t rpt_type, uint8_t rpt_id, void* data, size_t len,
size_t* out_len) TA_EXCL(client_input_lock_, feature_lock_);
zx_status_t HidbusSetReport(uint8_t rpt_type, uint8_t rpt_id, const void* data, size_t len)
TA_EXCL(feature_lock_);
zx_status_t HidbusGetIdle(uint8_t rpt_id, uint8_t* duration);
zx_status_t HidbusSetIdle(uint8_t rpt_id, uint8_t duration);
zx_status_t HidbusGetProtocol(uint8_t* protocol);
zx_status_t HidbusSetProtocol(uint8_t protocol);
void DdkUnbind(ddk::UnbindTxn txn);
void DdkRelease();
protected:
virtual void ShutDown() TA_EXCL(client_input_lock_); // protected for unit test.
private:
ddk::I2cChannel i2c_ TA_GUARDED(i2c_lock_);
ddk::GpioProtocolClient gpio_ TA_GUARDED(i2c_lock_);
zx::interrupt irq_;
thrd_t thread_ = {};
zx::port port_;
fbl::Mutex client_input_lock_ TA_ACQ_BEFORE(i2c_lock_);
fbl::Mutex feature_lock_;
fbl::Mutex i2c_lock_;
ddk::HidbusIfcProtocolClient client_ TA_GUARDED(client_input_lock_);
ambient_light_input_rpt_t input_rpt_ TA_GUARDED(client_input_lock_);
ambient_light_feature_rpt_t feature_rpt_ TA_GUARDED(feature_lock_);
uint8_t atime_ = 1;
uint8_t again_ = 1;
bool isSaturated_ = false;
time_t lastSaturatedLog_ = 0;
zx_status_t FillInputRpt() TA_REQ(client_input_lock_);
zx_status_t InitGain(uint8_t gain);
int Thread();
};
} // namespace tcs
#endif // SRC_DEVICES_LIGHT_SENSOR_DRIVERS_AMS_LIGHT_TCS3400_H_