1// Copyright 2017 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 <acpica/acpi.h> 8#include <ddktl/device.h> 9#include <ddktl/protocol/hidbus.h> 10#include <chromiumos-platform-ec/ec_commands.h> 11#include <fbl/macros.h> 12#include <fbl/mutex.h> 13#include <fbl/ref_counted.h> 14#include <fbl/ref_ptr.h> 15#include <fbl/vector.h> 16#include <zircon/compiler.h> 17#include <zircon/types.h> 18 19class AcpiCrOsEc : public fbl::RefCounted<AcpiCrOsEc> { 20 public: 21 static zx_status_t Create(fbl::RefPtr<AcpiCrOsEc>* out); 22 zx_status_t IssueCommand(uint16_t command, uint8_t command_version, 23 const void* out, size_t outsize, 24 void* in, size_t insize, size_t* actual); 25 26 bool supports_motion_sense() const { 27 return features_.flags[0] & EC_FEATURE_MASK_0(EC_FEATURE_MOTION_SENSE); 28 } 29 30 bool supports_motion_sense_fifo() const { 31 return features_.flags[0] & EC_FEATURE_MASK_0(EC_FEATURE_MOTION_SENSE_FIFO); 32 } 33 34 ~AcpiCrOsEc(); 35 private: 36 AcpiCrOsEc(); 37 DISALLOW_COPY_ASSIGN_AND_MOVE(AcpiCrOsEc); 38 39 fbl::Mutex io_lock_; 40 struct ec_response_get_features features_; 41}; 42 43// TODO(teisenbe): Define motionsense interface 44 45class AcpiCrOsEcMotionDevice; 46using DeviceType = ddk::Device<AcpiCrOsEcMotionDevice>; 47 48// CrOS EC protocol to HID protocol translator for device motion sensors 49class AcpiCrOsEcMotionDevice : public DeviceType, 50 public ddk::HidBusProtocol<AcpiCrOsEcMotionDevice> { 51public: 52 static zx_status_t Create(fbl::RefPtr<AcpiCrOsEc> ec, 53 zx_device_t* parent, ACPI_HANDLE acpi_handle, 54 fbl::unique_ptr<AcpiCrOsEcMotionDevice>* out); 55 56 // hidbus protocol implementation 57 zx_status_t HidBusQuery(uint32_t options, hid_info_t* info); 58 zx_status_t HidBusStart(ddk::HidBusIfcProxy proxy); 59 void HidBusStop(); 60 zx_status_t HidBusGetDescriptor(uint8_t desc_type, void** data, size_t* len); 61 zx_status_t HidBusGetReport(uint8_t rpt_type, uint8_t rpt_id, void* data, size_t len, 62 size_t* out_len); 63 zx_status_t HidBusSetReport(uint8_t rpt_type, uint8_t rpt_id, void* data, size_t len); 64 zx_status_t HidBusGetIdle(uint8_t rpt_id, uint8_t* duration); 65 zx_status_t HidBusSetIdle(uint8_t rpt_id, uint8_t duration); 66 zx_status_t HidBusGetProtocol(uint8_t* protocol); 67 zx_status_t HidBusSetProtocol(uint8_t protocol); 68 69 void DdkRelease(); 70 ~AcpiCrOsEcMotionDevice(); 71private: 72 AcpiCrOsEcMotionDevice(fbl::RefPtr<AcpiCrOsEc> ec, zx_device_t* parent, 73 ACPI_HANDLE acpi_handle); 74 DISALLOW_COPY_ASSIGN_AND_MOVE(AcpiCrOsEcMotionDevice); 75 76 struct SensorInfo { 77 bool valid; 78 79 enum motionsensor_type type; 80 enum motionsensor_location loc; 81 uint32_t min_sampling_freq; 82 uint32_t max_sampling_freq; 83 uint32_t fifo_max_event_count; 84 85 // For MOTIONSENSE_TYPE_ACCEL, value is in Gs 86 // MOTIONSENSE_TYPE_GYRO, value is in deg/s 87 // MOTIONSENSE_TYPE_MAG, value is in multiples of 1/16 uT 88 // MOTIONSENSE_TYPE_LIGHT, value is in lux? 89 int32_t phys_min; 90 int32_t phys_max; 91 }; 92 93 static void NotifyHandler(ACPI_HANDLE handle, UINT32 value, void* ctx); 94 95 // Hardware commands 96 zx_status_t QueryNumSensors(uint8_t* count); 97 zx_status_t QuerySensorInfo(uint8_t sensor_num, SensorInfo* info); 98 zx_status_t SetEcSamplingRate(uint8_t sensor_num, uint32_t milliseconds); 99 zx_status_t SetSensorOutputDataRate(uint8_t sensor_num, uint32_t freq_millihertz); 100 zx_status_t GetSensorRange(uint8_t sensor_num, int32_t* range); 101 zx_status_t GetKbWakeAngle(int32_t* angle); 102 zx_status_t SetKbWakeAngle(int16_t angle); 103 zx_status_t FifoInterruptEnable(bool enable); 104 zx_status_t FifoRead(struct ec_response_motion_sensor_data* data); 105 106 // Guard against concurrent use of the HID interfaces 107 fbl::Mutex hid_lock_; 108 void QueueHidReportLocked(const uint8_t* data, size_t len); 109 zx_status_t ConsumeFifoLocked(); 110 111 // Chat with hardware to build up |sensors_| 112 zx_status_t ProbeSensors(); 113 114 // Populate |hid_descriptor_| based on the contents of |sensors_| 115 zx_status_t BuildHidDescriptor(); 116 117 fbl::RefPtr<AcpiCrOsEc> ec_; 118 119 const ACPI_HANDLE acpi_handle_; 120 121 // Interface the driver is currently bound to 122 ddk::HidBusIfcProxy proxy_; 123 124 fbl::Vector<SensorInfo> sensors_; 125 126 fbl::unique_ptr<uint8_t[]> hid_descriptor_ = nullptr; 127 size_t hid_descriptor_len_ = 0; 128}; 129