blob: 5bcdf2419709733a8836cb8094dd3e5aabbdf7fd [file] [log] [blame]
# Copyright 2017 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Touch Component."""
import abc
import logging
import struct
import time
from cros.factory.device import device_types
class ITouch(device_types.DeviceComponent, abc.ABC):
"""Touch Component."""
def GetController(self, index):
"""Gets the touch controller with specified index.
Args:
index: index of the touch device.
Returns:
The corresponding touch controller.
"""
raise NotImplementedError
class ITouchController(device_types.DeviceComponent, abc.ABC):
"""Touch Controller."""
def CheckInterface(self):
"""Check whether the controller interface exists or not.
Returns:
True if the controller interface exists. Otherwise, False.
"""
raise NotImplementedError
def Calibrate(self):
"""Calibrate the controller.
Returns:
True if the calibration is successful. Otherwise, False.
"""
raise NotImplementedError
def GetMatrices(self, frame_idx_list):
"""Return matrices of values for touch uniformity test.
Args:
frame_idx_list: A list of frame indices.
Returns:
A list of matrices.
"""
raise NotImplementedError
class Atmel1664sTouchController(ITouchController):
"""Atmel 1664s touch controller."""
_I2C_DEVICES_PATH = '/sys/bus/i2c/devices'
_KERNEL_DEBUG_PATH = '/sys/kernel/debug/atmel_mxt_ts'
_FRAME_FILENAMES = ['refs', 'deltas']
def __init__(self, dut, i2c_bus_id=None):
super().__init__(dut)
if i2c_bus_id is None:
i2c_bus_id = self._ProbeI2CBusId()
i2c_device_path = dut.path.join(self._I2C_DEVICES_PATH, i2c_bus_id)
self._object_path = dut.path.join(i2c_device_path, 'object')
self._kerdbg_path = dut.path.join(self._KERNEL_DEBUG_PATH, i2c_bus_id)
self._rows = None
self._cols = None
if self.CheckInterface():
size = dut.ReadSpecialFile(dut.path.join(i2c_device_path, 'matrix_size'))
self._rows, self._cols = [int(s) for s in size.split()]
def _ProbeI2CBusId(self):
candidates = [
# yapf: disable
self._device.path.basename(path) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
for path in self._device.Glob(
# yapf: disable
self._device.path.join(self._KERNEL_DEBUG_PATH, '*'))] # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
assert len(candidates) == 1, (
f'Not having exactly one possible device: {candidates}')
return candidates[0]
def CheckInterface(self):
"""See ITouchController.CheckInterface."""
# yapf: disable
return self._device.path.exists(self._object_path) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
def Calibrate(self):
"""See ITouchController.Calibrate."""
logging.info('Calibrating...')
# Force calibration with T6 instance 0, byte 2 (calibrate), non-zero value.
self._device.WriteFile(self._object_path, '06000201')
# Empirical value to give the controller some time to finish calibration.
time.sleep(0.2)
return True # TODO(dparker): Figure out how to detect calibration errors.
def GetMatrices(self, frame_idx_list):
"""See ITouchController.GetMatrices.
Args:
frame_idx_list: Index 0 = References, Index 1 = Deltas.
"""
# yapf: disable
fmt = f'<{int(self._rows * self._cols)}h' # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
nbytes = struct.calcsize(fmt)
result = []
for frame_idx in frame_idx_list:
file_name = self._FRAME_FILENAMES[frame_idx]
# yapf: disable
file_path = self._device.path.join(self._kerdbg_path, file_name) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
buf = self._device.ReadSpecialFile(file_path, count=nbytes)
# yapf: disable
data = struct.unpack(fmt, buf) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
result.append([
# yapf: disable
list(data[i * self._cols:(i + 1) * self._cols]) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
# yapf: disable
for i in range(self._rows)]) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
return result