1*a248dafdSChristopher Ferris /*
2*a248dafdSChristopher Ferris * Copyright (C) 2014 Andrew Duggan
3*a248dafdSChristopher Ferris * Copyright (C) 2014 Synaptics Inc
4*a248dafdSChristopher Ferris *
5*a248dafdSChristopher Ferris * Licensed under the Apache License, Version 2.0 (the "License");
6*a248dafdSChristopher Ferris * you may not use this file except in compliance with the License.
7*a248dafdSChristopher Ferris * You may obtain a copy of the License at
8*a248dafdSChristopher Ferris *
9*a248dafdSChristopher Ferris * http://www.apache.org/licenses/LICENSE-2.0
10*a248dafdSChristopher Ferris *
11*a248dafdSChristopher Ferris * Unless required by applicable law or agreed to in writing, software
12*a248dafdSChristopher Ferris * distributed under the License is distributed on an "AS IS" BASIS,
13*a248dafdSChristopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*a248dafdSChristopher Ferris * See the License for the specific language governing permissions and
15*a248dafdSChristopher Ferris * limitations under the License.
16*a248dafdSChristopher Ferris */
17*a248dafdSChristopher Ferris
18*a248dafdSChristopher Ferris #include <stdio.h>
19*a248dafdSChristopher Ferris #include <string.h>
20*a248dafdSChristopher Ferris #include <errno.h>
21*a248dafdSChristopher Ferris #include <getopt.h>
22*a248dafdSChristopher Ferris #include <sys/types.h>
23*a248dafdSChristopher Ferris #include <sys/stat.h>
24*a248dafdSChristopher Ferris #include <fcntl.h>
25*a248dafdSChristopher Ferris #include <dirent.h>
26*a248dafdSChristopher Ferris #include <unistd.h>
27*a248dafdSChristopher Ferris #include <time.h>
28*a248dafdSChristopher Ferris #include <string>
29*a248dafdSChristopher Ferris #include <sstream>
30*a248dafdSChristopher Ferris #include <time.h>
31*a248dafdSChristopher Ferris
32*a248dafdSChristopher Ferris #include "hiddevice.h"
33*a248dafdSChristopher Ferris #include "rmi4update.h"
34*a248dafdSChristopher Ferris
35*a248dafdSChristopher Ferris #define VERSION_MAJOR 1
36*a248dafdSChristopher Ferris #define VERSION_MINOR 3
37*a248dafdSChristopher Ferris #define VERSION_SUBMINOR 12
38*a248dafdSChristopher Ferris
39*a248dafdSChristopher Ferris #define RMI4UPDATE_GETOPTS "hfd:t:pclvm"
40*a248dafdSChristopher Ferris
41*a248dafdSChristopher Ferris bool needDebugMessage;
42*a248dafdSChristopher Ferris
printHelp(const char * prog_name)43*a248dafdSChristopher Ferris void printHelp(const char *prog_name)
44*a248dafdSChristopher Ferris {
45*a248dafdSChristopher Ferris fprintf(stdout, "Usage: %s [OPTIONS] FIRMWAREFILE\n", prog_name);
46*a248dafdSChristopher Ferris fprintf(stdout, "\t-h, --help\t\tPrint this message\n");
47*a248dafdSChristopher Ferris fprintf(stdout, "\t-f, --force\t\tForce updating firmware even it the image provided is older\n\t\t\t\tthen the current firmware on the device.\n");
48*a248dafdSChristopher Ferris fprintf(stdout, "\t-d, --device\t\thidraw device file associated with the device being updated.\n");
49*a248dafdSChristopher Ferris fprintf(stdout, "\t-p, --fw-props\t\tPrint the firmware properties.\n");
50*a248dafdSChristopher Ferris fprintf(stdout, "\t-c, --config-id\t\tPrint the config id.\n");
51*a248dafdSChristopher Ferris fprintf(stdout, "\t-l, --lockdown\t\tPerform lockdown.\n");
52*a248dafdSChristopher Ferris fprintf(stdout, "\t-v, --version\t\tPrint version number.\n");
53*a248dafdSChristopher Ferris fprintf(stdout, "\t-t, --device-type\tFilter by device type [touchpad or touchscreen].\n");
54*a248dafdSChristopher Ferris }
55*a248dafdSChristopher Ferris
printVersion()56*a248dafdSChristopher Ferris void printVersion()
57*a248dafdSChristopher Ferris {
58*a248dafdSChristopher Ferris fprintf(stdout, "rmi4update version %d.%d.%d\n",
59*a248dafdSChristopher Ferris VERSION_MAJOR, VERSION_MINOR, VERSION_SUBMINOR);
60*a248dafdSChristopher Ferris }
61*a248dafdSChristopher Ferris
GetFirmwareProps(const char * deviceFile,std::string & props,bool configid)62*a248dafdSChristopher Ferris int GetFirmwareProps(const char * deviceFile, std::string &props, bool configid)
63*a248dafdSChristopher Ferris {
64*a248dafdSChristopher Ferris HIDDevice rmidevice;
65*a248dafdSChristopher Ferris int rc = UPDATE_SUCCESS;
66*a248dafdSChristopher Ferris std::stringstream ss;
67*a248dafdSChristopher Ferris
68*a248dafdSChristopher Ferris rc = rmidevice.Open(deviceFile);
69*a248dafdSChristopher Ferris if (rc)
70*a248dafdSChristopher Ferris return rc;
71*a248dafdSChristopher Ferris
72*a248dafdSChristopher Ferris if (needDebugMessage)
73*a248dafdSChristopher Ferris rmidevice.m_hasDebug = true;
74*a248dafdSChristopher Ferris
75*a248dafdSChristopher Ferris // Clear all interrupts before parsing to avoid unexpected interrupts.
76*a248dafdSChristopher Ferris rmidevice.ToggleInterruptMask(false);
77*a248dafdSChristopher Ferris
78*a248dafdSChristopher Ferris rmidevice.ScanPDT(0x1);
79*a248dafdSChristopher Ferris rmidevice.QueryBasicProperties();
80*a248dafdSChristopher Ferris
81*a248dafdSChristopher Ferris // Restore the interrupts
82*a248dafdSChristopher Ferris rmidevice.ToggleInterruptMask(true);
83*a248dafdSChristopher Ferris
84*a248dafdSChristopher Ferris if (configid) {
85*a248dafdSChristopher Ferris ss << std::hex << rmidevice.GetConfigID();
86*a248dafdSChristopher Ferris } else {
87*a248dafdSChristopher Ferris ss << rmidevice.GetFirmwareVersionMajor() << "."
88*a248dafdSChristopher Ferris << rmidevice.GetFirmwareVersionMinor() << "."
89*a248dafdSChristopher Ferris << rmidevice.GetFirmwareID();
90*a248dafdSChristopher Ferris
91*a248dafdSChristopher Ferris if (rmidevice.InBootloader())
92*a248dafdSChristopher Ferris ss << " bootloader";
93*a248dafdSChristopher Ferris }
94*a248dafdSChristopher Ferris
95*a248dafdSChristopher Ferris props = ss.str();
96*a248dafdSChristopher Ferris
97*a248dafdSChristopher Ferris return rc;
98*a248dafdSChristopher Ferris }
99*a248dafdSChristopher Ferris
main(int argc,char ** argv)100*a248dafdSChristopher Ferris int main(int argc, char **argv)
101*a248dafdSChristopher Ferris {
102*a248dafdSChristopher Ferris int rc;
103*a248dafdSChristopher Ferris FirmwareImage image;
104*a248dafdSChristopher Ferris int opt;
105*a248dafdSChristopher Ferris int index;
106*a248dafdSChristopher Ferris char *deviceName = NULL;
107*a248dafdSChristopher Ferris const char *firmwareName = NULL;
108*a248dafdSChristopher Ferris bool force = false;
109*a248dafdSChristopher Ferris static struct option long_options[] = {
110*a248dafdSChristopher Ferris {"help", 0, NULL, 'h'},
111*a248dafdSChristopher Ferris {"force", 0, NULL, 'f'},
112*a248dafdSChristopher Ferris {"device", 1, NULL, 'd'},
113*a248dafdSChristopher Ferris {"fw-props", 0, NULL, 'p'},
114*a248dafdSChristopher Ferris {"config-id", 0, NULL, 'c'},
115*a248dafdSChristopher Ferris {"lockdown", 0, NULL, 'l'},
116*a248dafdSChristopher Ferris {"version", 0, NULL, 'v'},
117*a248dafdSChristopher Ferris {"device-type", 1, NULL, 't'},
118*a248dafdSChristopher Ferris {0, 0, 0, 0},
119*a248dafdSChristopher Ferris };
120*a248dafdSChristopher Ferris bool printFirmwareProps = false;
121*a248dafdSChristopher Ferris bool printConfigid = false;
122*a248dafdSChristopher Ferris bool performLockdown = false;
123*a248dafdSChristopher Ferris needDebugMessage = false;
124*a248dafdSChristopher Ferris HIDDevice device;
125*a248dafdSChristopher Ferris enum RMIDeviceType deviceType = RMI_DEVICE_TYPE_ANY;
126*a248dafdSChristopher Ferris
127*a248dafdSChristopher Ferris while ((opt = getopt_long(argc, argv, RMI4UPDATE_GETOPTS, long_options, &index)) != -1) {
128*a248dafdSChristopher Ferris switch (opt) {
129*a248dafdSChristopher Ferris case 'h':
130*a248dafdSChristopher Ferris printHelp(argv[0]);
131*a248dafdSChristopher Ferris return 0;
132*a248dafdSChristopher Ferris case 'f':
133*a248dafdSChristopher Ferris force = true;
134*a248dafdSChristopher Ferris break;
135*a248dafdSChristopher Ferris case 'd':
136*a248dafdSChristopher Ferris deviceName = optarg;
137*a248dafdSChristopher Ferris break;
138*a248dafdSChristopher Ferris case 'p':
139*a248dafdSChristopher Ferris printFirmwareProps = true;
140*a248dafdSChristopher Ferris break;
141*a248dafdSChristopher Ferris case 'c':
142*a248dafdSChristopher Ferris printFirmwareProps = true;
143*a248dafdSChristopher Ferris printConfigid = true;
144*a248dafdSChristopher Ferris break;
145*a248dafdSChristopher Ferris case 'l':
146*a248dafdSChristopher Ferris performLockdown = true;
147*a248dafdSChristopher Ferris break;
148*a248dafdSChristopher Ferris case 't':
149*a248dafdSChristopher Ferris if (!strcasecmp((const char *)optarg, "touchpad"))
150*a248dafdSChristopher Ferris deviceType = RMI_DEVICE_TYPE_TOUCHPAD;
151*a248dafdSChristopher Ferris else if (!strcasecmp((const char *)optarg, "touchscreen"))
152*a248dafdSChristopher Ferris deviceType = RMI_DEVICE_TYPE_TOUCHSCREEN;
153*a248dafdSChristopher Ferris break;
154*a248dafdSChristopher Ferris case 'v':
155*a248dafdSChristopher Ferris printVersion();
156*a248dafdSChristopher Ferris return 0;
157*a248dafdSChristopher Ferris case 'm':
158*a248dafdSChristopher Ferris needDebugMessage = true;
159*a248dafdSChristopher Ferris break;
160*a248dafdSChristopher Ferris default:
161*a248dafdSChristopher Ferris break;
162*a248dafdSChristopher Ferris
163*a248dafdSChristopher Ferris }
164*a248dafdSChristopher Ferris }
165*a248dafdSChristopher Ferris
166*a248dafdSChristopher Ferris if (printFirmwareProps) {
167*a248dafdSChristopher Ferris std::string props;
168*a248dafdSChristopher Ferris
169*a248dafdSChristopher Ferris if (!deviceName) {
170*a248dafdSChristopher Ferris fprintf(stderr, "Specifiy which device to query\n");
171*a248dafdSChristopher Ferris return 1;
172*a248dafdSChristopher Ferris }
173*a248dafdSChristopher Ferris rc = GetFirmwareProps(deviceName, props, printConfigid);
174*a248dafdSChristopher Ferris if (rc) {
175*a248dafdSChristopher Ferris fprintf(stderr, "Failed to read properties from device: %s\n", update_err_to_string(rc));
176*a248dafdSChristopher Ferris return 1;
177*a248dafdSChristopher Ferris }
178*a248dafdSChristopher Ferris fprintf(stdout, "%s\n", props.c_str());
179*a248dafdSChristopher Ferris return 0;
180*a248dafdSChristopher Ferris }
181*a248dafdSChristopher Ferris
182*a248dafdSChristopher Ferris if (optind < argc) {
183*a248dafdSChristopher Ferris firmwareName = argv[optind];
184*a248dafdSChristopher Ferris } else {
185*a248dafdSChristopher Ferris printHelp(argv[0]);
186*a248dafdSChristopher Ferris return -1;
187*a248dafdSChristopher Ferris }
188*a248dafdSChristopher Ferris
189*a248dafdSChristopher Ferris rc = image.Initialize(firmwareName);
190*a248dafdSChristopher Ferris if (rc != UPDATE_SUCCESS) {
191*a248dafdSChristopher Ferris fprintf(stderr, "Failed to initialize the firmware image: %s\n", update_err_to_string(rc));
192*a248dafdSChristopher Ferris return 1;
193*a248dafdSChristopher Ferris }
194*a248dafdSChristopher Ferris
195*a248dafdSChristopher Ferris if (deviceName) {
196*a248dafdSChristopher Ferris rc = device.Open(deviceName);
197*a248dafdSChristopher Ferris if (rc) {
198*a248dafdSChristopher Ferris fprintf(stderr, "%s: failed to initialize rmi device (%d): %s\n", argv[0], errno,
199*a248dafdSChristopher Ferris strerror(errno));
200*a248dafdSChristopher Ferris return 1;
201*a248dafdSChristopher Ferris }
202*a248dafdSChristopher Ferris } else {
203*a248dafdSChristopher Ferris if (!device.FindDevice(deviceType))
204*a248dafdSChristopher Ferris return 1;
205*a248dafdSChristopher Ferris }
206*a248dafdSChristopher Ferris
207*a248dafdSChristopher Ferris if (needDebugMessage) {
208*a248dafdSChristopher Ferris device.m_hasDebug = true;
209*a248dafdSChristopher Ferris }
210*a248dafdSChristopher Ferris
211*a248dafdSChristopher Ferris RMI4Update update(device, image);
212*a248dafdSChristopher Ferris rc = update.UpdateFirmware(force, performLockdown);
213*a248dafdSChristopher Ferris
214*a248dafdSChristopher Ferris if (rc != UPDATE_SUCCESS)
215*a248dafdSChristopher Ferris {
216*a248dafdSChristopher Ferris device.Reset();
217*a248dafdSChristopher Ferris return 1;
218*a248dafdSChristopher Ferris }
219*a248dafdSChristopher Ferris
220*a248dafdSChristopher Ferris return 0;
221*a248dafdSChristopher Ferris }
222