| # 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 |