1052556f215226db267e5e21d090c4555bba41704Andrew Duggan/* 2052556f215226db267e5e21d090c4555bba41704Andrew Duggan * Copyright (C) 2014 Andrew Duggan 3052556f215226db267e5e21d090c4555bba41704Andrew Duggan * Copyright (C) 2014 Synaptics Inc 4052556f215226db267e5e21d090c4555bba41704Andrew Duggan * 5052556f215226db267e5e21d090c4555bba41704Andrew Duggan * Licensed under the Apache License, Version 2.0 (the "License"); 6052556f215226db267e5e21d090c4555bba41704Andrew Duggan * you may not use this file except in compliance with the License. 7052556f215226db267e5e21d090c4555bba41704Andrew Duggan * You may obtain a copy of the License at 8052556f215226db267e5e21d090c4555bba41704Andrew Duggan * 9052556f215226db267e5e21d090c4555bba41704Andrew Duggan * http://www.apache.org/licenses/LICENSE-2.0 10052556f215226db267e5e21d090c4555bba41704Andrew Duggan * 11052556f215226db267e5e21d090c4555bba41704Andrew Duggan * Unless required by applicable law or agreed to in writing, software 12052556f215226db267e5e21d090c4555bba41704Andrew Duggan * distributed under the License is distributed on an "AS IS" BASIS, 13052556f215226db267e5e21d090c4555bba41704Andrew Duggan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14052556f215226db267e5e21d090c4555bba41704Andrew Duggan * See the License for the specific language governing permissions and 15052556f215226db267e5e21d090c4555bba41704Andrew Duggan * limitations under the License. 16052556f215226db267e5e21d090c4555bba41704Andrew Duggan */ 17052556f215226db267e5e21d090c4555bba41704Andrew Duggan 184e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#include <stdio.h> 194e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#include <time.h> 204e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#include <string.h> 214e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#include <errno.h> 22777d012aadce5220c1445b8923d86e95fcc60128Andrew Duggan#include <stdlib.h> 234e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 244e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#include "rmidevice.h" 254e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 264e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_PDT_ENTRY_SIZE 6 274e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_PAGE_SELECT_REGISTER 0xFF 284e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_MAX_PAGE 0xFF 294e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_PAGE_SIZE 0x100 304e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_PAGE_SCAN_START 0x00e9 314e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_PAGE_SCAN_END 0x0005 32fc17a65f3c9c3db99ab5c962bf55d109e485f9b5Andrew Duggan#define RMI_DEVICE_F01_BASIC_QUERY_LEN 11 334e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_F01_QRY5_YEAR_MASK 0x1f 344e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_F01_QRY6_MONTH_MASK 0x0f 354e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_F01_QRY7_DAY_MASK 0x1f 364e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 374e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_F01_QRY1_HAS_LTS (1 << 2) 384e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_F01_QRY1_HAS_SENSOR_ID (1 << 3) 394e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_F01_QRY1_HAS_CHARGER_INP (1 << 4) 404e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_F01_QRY1_HAS_ADJ_DOZE (1 << 5) 414e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_F01_QRY1_HAS_ADJ_DOZE_HOFF (1 << 6) 424e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_F01_QRY1_HAS_PROPS_2 (1 << 7) 434e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 444e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_F01_LTS_RESERVED_SIZE 19 454e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 464e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_F01_QRY42_DS4_QUERIES (1 << 0) 474e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_F01_QRY42_MULTI_PHYS (1 << 1) 484e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 494e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_F01_QRY43_01_PACKAGE_ID (1 << 0) 504e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_DEVICE_F01_QRY43_01_BUILD_ID (1 << 1) 514e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 524e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define PACKAGE_ID_BYTES 4 534e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define BUILD_ID_BYTES 3 544e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 554e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_F01_CMD_DEVICE_RESET 1 564e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan#define RMI_F01_DEFAULT_RESET_DELAY_MS 100 574e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 584e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Dugganint RMIDevice::SetRMIPage(unsigned char page) 594e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan{ 605d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan int rc; 615d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan 625d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan if (m_page == page) 635d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan return 0; 645d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan 655d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan m_page = page; 665d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan rc = Write(RMI_DEVICE_PAGE_SELECT_REGISTER, &page, 1); 67b2191d0467eaee992eff48646c40a01d1e405597Andrew de los Reyes if (rc < 0 || rc < 1) { 685d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan m_page = -1; 695d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan return rc; 705d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan } 715d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan return 0; 724e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan} 734e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 744e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Dugganint RMIDevice::QueryBasicProperties() 754e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan{ 764e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan int rc; 774e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan unsigned char basicQuery[RMI_DEVICE_F01_BASIC_QUERY_LEN]; 784e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan unsigned short queryAddr; 794e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan unsigned char infoBuf[4]; 804e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan unsigned short prodInfoAddr; 814e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan RMIFunction f01; 824e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 83d8f0896e72f336f81bf507e5344631177309ea3cAndrew Duggan SetRMIPage(0x00); 84d8f0896e72f336f81bf507e5344631177309ea3cAndrew Duggan 854e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan if (GetFunction(f01, 1)) { 864e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan queryAddr = f01.GetQueryBase(); 874e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 884e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan rc = Read(queryAddr, basicQuery, RMI_DEVICE_F01_BASIC_QUERY_LEN); 89b2191d0467eaee992eff48646c40a01d1e405597Andrew de los Reyes if (rc < 0 || rc < RMI_DEVICE_F01_BASIC_QUERY_LEN) { 904e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stderr, "Failed to read the basic query: %s\n", strerror(errno)); 914e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan return rc; 924e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 934e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_manufacturerID = basicQuery[0]; 944e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_hasLTS = basicQuery[1] & RMI_DEVICE_F01_QRY1_HAS_LTS; 954e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_hasSensorID = basicQuery[1] & RMI_DEVICE_F01_QRY1_HAS_SENSOR_ID; 964e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_hasAdjustableDoze = basicQuery[1] & RMI_DEVICE_F01_QRY1_HAS_ADJ_DOZE; 974e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_hasAdjustableDozeHoldoff = basicQuery[1] & RMI_DEVICE_F01_QRY1_HAS_ADJ_DOZE_HOFF; 984e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_hasQuery42 = basicQuery[1] & RMI_DEVICE_F01_QRY1_HAS_PROPS_2; 99777d012aadce5220c1445b8923d86e95fcc60128Andrew Duggan m_firmwareVersionMajor = basicQuery[2]; 100777d012aadce5220c1445b8923d86e95fcc60128Andrew Duggan m_firmwareVersionMinor = basicQuery[3]; 1014e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 1024e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan snprintf(m_dom, sizeof(m_dom), "20%02d/%02d/%02d", 1034e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan basicQuery[5] & RMI_DEVICE_F01_QRY5_YEAR_MASK, 1044e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan basicQuery[6] & RMI_DEVICE_F01_QRY6_MONTH_MASK, 1054e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan basicQuery[7] & RMI_DEVICE_F01_QRY7_DAY_MASK); 1064e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 107fc17a65f3c9c3db99ab5c962bf55d109e485f9b5Andrew Duggan queryAddr += 11; 108fc17a65f3c9c3db99ab5c962bf55d109e485f9b5Andrew Duggan rc = Read(queryAddr, m_productID, RMI_PRODUCT_ID_LENGTH); 109b2191d0467eaee992eff48646c40a01d1e405597Andrew de los Reyes if (rc < 0 || rc < RMI_PRODUCT_ID_LENGTH) { 110fc17a65f3c9c3db99ab5c962bf55d109e485f9b5Andrew Duggan fprintf(stderr, "Failed to read the product id: %s\n", strerror(errno)); 111fc17a65f3c9c3db99ab5c962bf55d109e485f9b5Andrew Duggan return rc; 112fc17a65f3c9c3db99ab5c962bf55d109e485f9b5Andrew Duggan } 1134e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_productID[RMI_PRODUCT_ID_LENGTH] = '\0'; 1144e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 1154e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan prodInfoAddr = queryAddr + 6; 1164e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan queryAddr += 10; 1174e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 1184e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan if (m_hasLTS) 1194e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan ++queryAddr; 1204e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 1214e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan if (m_hasSensorID) { 1224e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan rc = Read(queryAddr++, &m_sensorID, 1); 123b2191d0467eaee992eff48646c40a01d1e405597Andrew de los Reyes if (rc < 0 || rc < 1) { 1244e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stderr, "Failed to read sensor id: %s\n", strerror(errno)); 1254e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan return rc; 1264e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 1274e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 1284e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 1294e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan if (m_hasLTS) 1304e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan queryAddr += RMI_DEVICE_F01_LTS_RESERVED_SIZE; 1314e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 1324e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan if (m_hasQuery42) { 1334e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan rc = Read(queryAddr++, infoBuf, 1); 134b2191d0467eaee992eff48646c40a01d1e405597Andrew de los Reyes if (rc < 0 || rc < 1) { 1354e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stderr, "Failed to read query 42: %s\n", strerror(errno)); 1364e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan return rc; 1374e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 1384e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 1394e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_hasDS4Queries = infoBuf[0] & RMI_DEVICE_F01_QRY42_DS4_QUERIES; 1404e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_hasMultiPhysical = infoBuf[0] & RMI_DEVICE_F01_QRY42_MULTI_PHYS; 1414e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 1424e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 1434e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan if (m_hasDS4Queries) { 1444e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan rc = Read(queryAddr++, &m_ds4QueryLength, 1); 145b2191d0467eaee992eff48646c40a01d1e405597Andrew de los Reyes if (rc < 0 || rc < 1) { 1464e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stderr, "Failed to read DS4 query length: %s\n", strerror(errno)); 1474e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan return rc; 1484e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 1494e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 1504e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 1514e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan for (int i = 1; i <= m_ds4QueryLength; ++i) { 1524e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan unsigned char val; 1534e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan rc = Read(queryAddr++, &val, 1); 154b2191d0467eaee992eff48646c40a01d1e405597Andrew de los Reyes if (rc < 0 || rc < 1) { 1554e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stderr, "Failed to read F01 Query43.%02d: %s\n", i, strerror(errno)); 1564e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan continue; 1574e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 1584e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 1594e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan switch(i) { 1604e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan case 1: 1614e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_hasPackageIDQuery = val & RMI_DEVICE_F01_QRY43_01_PACKAGE_ID; 1624e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_hasBuildIDQuery = val & RMI_DEVICE_F01_QRY43_01_BUILD_ID; 1634e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan break; 1644e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan case 2: 1654e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan case 3: 1664e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan default: 1674e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan break; 1684e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 1694e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 1704e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 1714e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan if (m_hasPackageIDQuery) { 1724e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan rc = Read(prodInfoAddr++, infoBuf, PACKAGE_ID_BYTES); 173b2191d0467eaee992eff48646c40a01d1e405597Andrew de los Reyes if (rc >= PACKAGE_ID_BYTES) { 1744e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan unsigned short *val = (unsigned short *)infoBuf; 1754e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_packageID = *val; 1764e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan val = (unsigned short *)(infoBuf + 2); 1774e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_packageRev = *val; 1784e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 1794e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 1804e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 1814e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan if (m_hasBuildIDQuery) { 1824e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan rc = Read(prodInfoAddr, infoBuf, BUILD_ID_BYTES); 183b2191d0467eaee992eff48646c40a01d1e405597Andrew de los Reyes if (rc >= BUILD_ID_BYTES) { 1844e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan unsigned short *val = (unsigned short *)infoBuf; 1854e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_buildID = *val; 1864e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_buildID += infoBuf[2] * 65536; 1874e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 1884e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 1894e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 1904e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan return 0; 1914e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan} 1924e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 1934e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Dugganvoid RMIDevice::PrintProperties() 1944e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan{ 1954e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stdout, "manufacturerID:\t\t%d\n", m_manufacturerID); 1964e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stdout, "Has LTS?:\t\t%d\n", m_hasLTS); 1974e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stdout, "Has Sensor ID?:\t\t%d\n", m_hasSensorID); 1984e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stdout, "Has Adjustable Doze?:\t%d\n", m_hasAdjustableDoze); 1994e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stdout, "Has Query 42?:\t\t%d\n", m_hasQuery42); 2004e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stdout, "Date of Manufacturer:\t%s\n", m_dom); 2014e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stdout, "Product ID:\t\t%s\n", m_productID); 202777d012aadce5220c1445b8923d86e95fcc60128Andrew Duggan fprintf(stdout, "Firmware Version:\t%d.%d\n", m_firmwareVersionMajor, m_firmwareVersionMinor); 2034e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stdout, "Package ID:\t\t%d\n", m_packageID); 2044e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stdout, "Package Rev:\t\t%d\n", m_packageRev); 2054e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stdout, "Build ID:\t\t%ld\n", m_buildID); 2064e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stdout, "Sensor ID:\t\t%d\n", m_sensorID); 2074e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stdout, "Has DS4 Queries?:\t%d\n", m_hasDS4Queries); 2084e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stdout, "Has Multi Phys?:\t%d\n", m_hasMultiPhysical); 2094e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stdout, "\n"); 2104e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan} 2114e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 2124e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Dugganint RMIDevice::Reset() 2134e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan{ 2144e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan int rc; 2154e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan RMIFunction f01; 2164e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan const unsigned char deviceReset = RMI_F01_CMD_DEVICE_RESET; 2174e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 2184e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan if (!GetFunction(f01, 1)) 2194e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan return -1; 2204e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 2214e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stdout, "Resetting...\n"); 2224e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan rc = Write(f01.GetCommandBase(), &deviceReset, 1); 223b2191d0467eaee992eff48646c40a01d1e405597Andrew de los Reyes if (rc < 0 || rc < 1) 2244e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan return rc; 2254e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 2265d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan rc = Sleep(RMI_F01_DEFAULT_RESET_DELAY_MS); 2275d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan if (rc < 0) 2285d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan return -1; 2294e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stdout, "Reset completed.\n"); 2304e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan return 0; 2314e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan} 2324e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 2334e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Dugganbool RMIDevice::GetFunction(RMIFunction &func, int functionNumber) 2344e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan{ 2354e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan std::vector<RMIFunction>::iterator funcIter; 2364e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 2374e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan for (funcIter = m_functionList.begin(); funcIter != m_functionList.end(); ++funcIter) { 2384e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan if (funcIter->GetFunctionNumber() == functionNumber) { 2394e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan func = *funcIter; 2404e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan return true; 2414e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 2424e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 2434e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan return false; 2444e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan} 2454e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 246e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Dugganvoid RMIDevice::PrintFunctions() 247e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan{ 248e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan std::vector<RMIFunction>::iterator funcIter; 249e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan 250e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan for (funcIter = m_functionList.begin(); funcIter != m_functionList.end(); ++funcIter) 251bcdd7c6b1132937424c89f3ed897b6b7c9996225Andrew Duggan fprintf(stdout, "0x%02x (%d) (%d) (0x%x): 0x%02x 0x%02x 0x%02x 0x%02x\n", 252e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan funcIter->GetFunctionNumber(), funcIter->GetFunctionVersion(), 253bcdd7c6b1132937424c89f3ed897b6b7c9996225Andrew Duggan funcIter->GetInterruptSourceCount(), 254bcdd7c6b1132937424c89f3ed897b6b7c9996225Andrew Duggan funcIter->GetInterruptMask(), 255bcdd7c6b1132937424c89f3ed897b6b7c9996225Andrew Duggan funcIter->GetDataBase(), 256e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan funcIter->GetControlBase(), funcIter->GetCommandBase(), 257e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan funcIter->GetQueryBase()); 258e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan} 259e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan 260baf6bbac1ce5bb27f17b9c4fa9a4ab394af23542Satoshi Noguchiint RMIDevice::ScanPDT(int endFunc, int endPage) 2614e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan{ 2624e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan int rc; 2634e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan unsigned int page; 264baf6bbac1ce5bb27f17b9c4fa9a4ab394af23542Satoshi Noguchi unsigned int maxPage; 2654e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan unsigned int addr; 2664e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan unsigned char entry[RMI_DEVICE_PDT_ENTRY_SIZE]; 2673020cbb062d094612429051eec89f268133799acSatoshi Noguchi unsigned int interruptCount = 0; 2684e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 269baf6bbac1ce5bb27f17b9c4fa9a4ab394af23542Satoshi Noguchi maxPage = (unsigned int)((endPage < 0) ? RMI_DEVICE_MAX_PAGE : endPage); 270baf6bbac1ce5bb27f17b9c4fa9a4ab394af23542Satoshi Noguchi 2714e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_functionList.clear(); 2724e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 273baf6bbac1ce5bb27f17b9c4fa9a4ab394af23542Satoshi Noguchi for (page = 0; page < maxPage; ++page) { 2744e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan unsigned int page_start = RMI_DEVICE_PAGE_SIZE * page; 2754e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan unsigned int pdt_start = page_start + RMI_DEVICE_PAGE_SCAN_START; 2764e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan unsigned int pdt_end = page_start + RMI_DEVICE_PAGE_SCAN_END; 2774e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan bool found = false; 2784e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 2794e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan SetRMIPage(page); 2804e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 2814e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan for (addr = pdt_start; addr >= pdt_end; addr -= RMI_DEVICE_PDT_ENTRY_SIZE) { 2824e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan rc = Read(addr, entry, RMI_DEVICE_PDT_ENTRY_SIZE); 283b2191d0467eaee992eff48646c40a01d1e405597Andrew de los Reyes if (rc < 0 || rc < RMI_DEVICE_PDT_ENTRY_SIZE) { 2844e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan fprintf(stderr, "Failed to read PDT entry at address (0x%04x)\n", addr); 2854e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan return rc; 2864e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 2874e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 2883020cbb062d094612429051eec89f268133799acSatoshi Noguchi RMIFunction func(entry, page_start, interruptCount); 2894e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan if (func.GetFunctionNumber() == 0) 2904e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan break; 2914e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 2924e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan m_functionList.push_back(func); 2933020cbb062d094612429051eec89f268133799acSatoshi Noguchi interruptCount += func.GetInterruptSourceCount(); 2944e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan found = true; 295c14ec9ced73a2f5d243c010c9fc45cb5e4956a3aAndrew Duggan 296c14ec9ced73a2f5d243c010c9fc45cb5e4956a3aAndrew Duggan if (func.GetFunctionNumber() == endFunc) 297c14ec9ced73a2f5d243c010c9fc45cb5e4956a3aAndrew Duggan return 0; 2984e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 2994e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 300baf6bbac1ce5bb27f17b9c4fa9a4ab394af23542Satoshi Noguchi if (!found && (endPage < 0)) 3014e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan break; 3024e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan } 3034e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan 3043020cbb062d094612429051eec89f268133799acSatoshi Noguchi m_numInterruptRegs = (interruptCount + 7) / 8; 3053020cbb062d094612429051eec89f268133799acSatoshi Noguchi 3064e811258783e0f1e0cdaf70e3bdb2069ce4f046Andrew Duggan return 0; 30765e5553ace01906e5c0ac3a810afd552a2820acdAndrew Duggan} 30865e5553ace01906e5c0ac3a810afd552a2820acdAndrew Duggan 3092f5c0c0f9a3164923ff7edc58e848096ae98fc18Andrew Dugganbool RMIDevice::InBootloader() 3102f5c0c0f9a3164923ff7edc58e848096ae98fc18Andrew Duggan{ 3112f5c0c0f9a3164923ff7edc58e848096ae98fc18Andrew Duggan RMIFunction f01; 3122f5c0c0f9a3164923ff7edc58e848096ae98fc18Andrew Duggan if (GetFunction(f01, 0x01)) { 3132f5c0c0f9a3164923ff7edc58e848096ae98fc18Andrew Duggan int rc; 3142f5c0c0f9a3164923ff7edc58e848096ae98fc18Andrew Duggan unsigned char status; 3152f5c0c0f9a3164923ff7edc58e848096ae98fc18Andrew Duggan 3162f5c0c0f9a3164923ff7edc58e848096ae98fc18Andrew Duggan rc = Read(f01.GetDataBase(), &status, 1); 317b2191d0467eaee992eff48646c40a01d1e405597Andrew de los Reyes if (rc < 0 || rc < 1) 3182f5c0c0f9a3164923ff7edc58e848096ae98fc18Andrew Duggan return true; 3192f5c0c0f9a3164923ff7edc58e848096ae98fc18Andrew Duggan 3202f5c0c0f9a3164923ff7edc58e848096ae98fc18Andrew Duggan return !!(status & 0x40); 3212f5c0c0f9a3164923ff7edc58e848096ae98fc18Andrew Duggan } 3222f5c0c0f9a3164923ff7edc58e848096ae98fc18Andrew Duggan return true; 3232f5c0c0f9a3164923ff7edc58e848096ae98fc18Andrew Duggan} 3242f5c0c0f9a3164923ff7edc58e848096ae98fc18Andrew Duggan 32565e5553ace01906e5c0ac3a810afd552a2820acdAndrew Dugganlong long diff_time(struct timespec *start, struct timespec *end) 32665e5553ace01906e5c0ac3a810afd552a2820acdAndrew Duggan{ 32765e5553ace01906e5c0ac3a810afd552a2820acdAndrew Duggan long long diff; 32865e5553ace01906e5c0ac3a810afd552a2820acdAndrew Duggan diff = (end->tv_sec - start->tv_sec) * 1000 * 1000; 32965e5553ace01906e5c0ac3a810afd552a2820acdAndrew Duggan diff += (end->tv_nsec - start->tv_nsec) / 1000; 33065e5553ace01906e5c0ac3a810afd552a2820acdAndrew Duggan return diff; 3315d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan} 3325d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan 3335d47750894ddaf019a016505f790c439e2eae3acAndrew Dugganint Sleep(int ms) 3345d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan{ 3355d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan struct timespec ts; 3365d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan struct timespec rem; 3375d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan 3385d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan ts.tv_sec = ms / 1000; 3395d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan ts.tv_nsec = (ms % 1000) * 1000 * 1000; 3405d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan for (;;) { 3415d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan if (nanosleep(&ts, &rem) == 0) { 3425d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan break; 3435d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan } else { 3445d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan if (errno == EINTR) { 3455d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan ts = rem; 3465d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan continue; 3475d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan } 3485d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan return -1; 3495d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan } 3505d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan } 3515d47750894ddaf019a016505f790c439e2eae3acAndrew Duggan return 0; 352e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan} 353e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan 354e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Dugganvoid print_buffer(const unsigned char *buf, unsigned int len) 355e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan{ 356e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan for (unsigned int i = 0; i < len; ++i) { 357e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan fprintf(stdout, "0x%02X ", buf[i]); 358e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan if (i % 8 == 7) 359e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan fprintf(stdout, "\n"); 360e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan } 361e9a5cd0172ce96168a9431531d259b677f331aa6Andrew Duggan fprintf(stdout, "\n"); 362b2191d0467eaee992eff48646c40a01d1e405597Andrew de los Reyes} 363