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