blob: 11146e1e286abefd9aef8f0fd1c3380a5eee64fd [file] [log] [blame]
Andrew Duggan052556f2014-04-16 11:32:30 -07001/*
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
Andrew Duggan4e811252014-04-03 15:17:57 -070018#include <stdio.h>
19#include <string.h>
20#include <errno.h>
21#include <getopt.h>
Andrew Dugganfa10fc82014-07-07 17:36:33 -070022#include <sys/types.h>
Andrew Duggan64f3a0c2014-07-31 11:22:01 -070023#include <sys/stat.h>
24#include <fcntl.h>
Andrew Dugganfa10fc82014-07-07 17:36:33 -070025#include <dirent.h>
Andrew Duggan64f3a0c2014-07-31 11:22:01 -070026#include <unistd.h>
27#include <time.h>
Andrew Duggana5f70ba2014-08-05 14:13:45 -070028#include <string>
29#include <sstream>
Andrew Duggan4e811252014-04-03 15:17:57 -070030
31#include "hiddevice.h"
32#include "rmi4update.h"
33
Andrew Duggand2e1d572014-11-12 11:37:42 -080034#define VERSION_MAJOR 1
Andrew Duggan3d6ee022015-09-23 15:03:19 -070035#define VERSION_MINOR 2
36#define VERSION_SUBMINOR 0
Andrew Duggand2e1d572014-11-12 11:37:42 -080037
38#define RMI4UPDATE_GETOPTS "hfd:plv"
Andrew Duggan4e811252014-04-03 15:17:57 -070039
40void printHelp(const char *prog_name)
41{
Andrew Dugganfa10fc82014-07-07 17:36:33 -070042 fprintf(stdout, "Usage: %s [OPTIONS] FIRMWAREFILE\n", prog_name);
Andrew Duggan4e811252014-04-03 15:17:57 -070043 fprintf(stdout, "\t-h, --help\tPrint this message\n");
44 fprintf(stdout, "\t-f, --force\tForce updating firmware even it the image provided is older\n\t\t\tthen the current firmware on the device.\n");
Andrew Dugganfa10fc82014-07-07 17:36:33 -070045 fprintf(stdout, "\t-d, --device\thidraw device file associated with the device being updated.\n");
Andrew Duggana5f70ba2014-08-05 14:13:45 -070046 fprintf(stdout, "\t-p, --fw-props\tPrint the firmware properties.\n");
Satoshi Noguchia0b675a2014-09-29 02:38:14 -070047 fprintf(stdout, "\t-l, --lockdown\tPerform lockdown.\n");
Andrew Duggand2e1d572014-11-12 11:37:42 -080048 fprintf(stdout, "\t-v, --version\tPrint version number.\n");
49}
50
51void printVersion()
52{
53 fprintf(stdout, "rmi4update version %d.%d.%d\n",
54 VERSION_MAJOR, VERSION_MINOR, VERSION_SUBMINOR);
Andrew Dugganfa10fc82014-07-07 17:36:33 -070055}
56
Satoshi Noguchia0b675a2014-09-29 02:38:14 -070057int UpdateDevice(FirmwareImage & image, bool force, bool performLockdown, const char * deviceFile)
Andrew Dugganeda95782014-07-25 12:31:13 -070058{
Andrew Dugganfa10fc82014-07-07 17:36:33 -070059 HIDDevice rmidevice;
60 int rc;
61
62 rc = rmidevice.Open(deviceFile);
63 if (rc)
64 return rc;
65
66 RMI4Update update(rmidevice, image);
Satoshi Noguchia0b675a2014-09-29 02:38:14 -070067 rc = update.UpdateFirmware(force, performLockdown);
Andrew Dugganfa10fc82014-07-07 17:36:33 -070068 if (rc != UPDATE_SUCCESS)
69 return rc;
70
71 return rc;
Andrew Duggan4e811252014-04-03 15:17:57 -070072}
73
Andrew Duggana5f70ba2014-08-05 14:13:45 -070074int GetFirmwareProps(const char * deviceFile, std::string &props)
75{
76 HIDDevice rmidevice;
77 int rc = UPDATE_SUCCESS;
78 std::stringstream ss;
79
80 rc = rmidevice.Open(deviceFile);
81 if (rc)
82 return rc;
83
Andrew Dugganc14ec9c2014-08-13 14:42:37 -070084 rmidevice.ScanPDT(0x1);
Andrew Duggana5f70ba2014-08-05 14:13:45 -070085 rmidevice.QueryBasicProperties();
86
87 ss << rmidevice.GetFirmwareVersionMajor() << "."
88 << rmidevice.GetFirmwareVersionMinor() << "."
89 << std::hex << rmidevice.GetFirmwareID();
90
Andrew Duggan2f5c0c02014-08-08 13:30:49 -070091 if (rmidevice.InBootloader())
92 ss << " bootloader";
93
Andrew Duggana5f70ba2014-08-05 14:13:45 -070094 props = ss.str();
95
96 return rc;
97}
98
Andrew Duggan4e811252014-04-03 15:17:57 -070099int main(int argc, char **argv)
100{
101 int rc;
Andrew Duggan4e811252014-04-03 15:17:57 -0700102 FirmwareImage image;
103 int opt;
104 int index;
Andrew Duggan9b590b72014-08-08 13:38:01 -0700105 char *deviceName = NULL;
Andrew Duggan72163582014-04-03 16:25:12 -0700106 const char *firmwareName = NULL;
Andrew Duggan4e811252014-04-03 15:17:57 -0700107 bool force = false;
108 static struct option long_options[] = {
109 {"help", 0, NULL, 'h'},
110 {"force", 0, NULL, 'f'},
Andrew Dugganfa10fc82014-07-07 17:36:33 -0700111 {"device", 1, NULL, 'd'},
Andrew Duggana5f70ba2014-08-05 14:13:45 -0700112 {"fw-props", 0, NULL, 'p'},
Satoshi Noguchia0b675a2014-09-29 02:38:14 -0700113 {"lockdown", 0, NULL, 'l'},
Andrew Duggand2e1d572014-11-12 11:37:42 -0800114 {"version", 0, NULL, 'v'},
Andrew Duggan4e811252014-04-03 15:17:57 -0700115 {0, 0, 0, 0},
116 };
Andrew Dugganfa10fc82014-07-07 17:36:33 -0700117 struct dirent * devDirEntry;
118 DIR * devDir;
Andrew Duggana5f70ba2014-08-05 14:13:45 -0700119 bool printFirmwareProps = false;
Satoshi Noguchia0b675a2014-09-29 02:38:14 -0700120 bool performLockdown = false;
Andrew Duggan4e811252014-04-03 15:17:57 -0700121
122 while ((opt = getopt_long(argc, argv, RMI4UPDATE_GETOPTS, long_options, &index)) != -1) {
123 switch (opt) {
124 case 'h':
125 printHelp(argv[0]);
126 return 0;
127 case 'f':
128 force = true;
129 break;
Andrew Dugganfa10fc82014-07-07 17:36:33 -0700130 case 'd':
131 deviceName = optarg;
132 break;
Andrew Duggana5f70ba2014-08-05 14:13:45 -0700133 case 'p':
134 printFirmwareProps = true;
135 break;
Satoshi Noguchia0b675a2014-09-29 02:38:14 -0700136 case 'l':
137 performLockdown = true;
138 break;
Andrew Duggand2e1d572014-11-12 11:37:42 -0800139 case 'v':
140 printVersion();
141 return 0;
Andrew Duggan4e811252014-04-03 15:17:57 -0700142 default:
143 break;
144
145 }
146 }
147
Andrew Duggana5f70ba2014-08-05 14:13:45 -0700148 if (printFirmwareProps) {
149 std::string props;
150
151 if (!deviceName) {
152 fprintf(stderr, "Specifiy which device to query\n");
153 return 1;
154 }
155 rc = GetFirmwareProps(deviceName, props);
156 if (rc) {
157 fprintf(stderr, "Failed to read properties from device: %s\n", update_err_to_string(rc));
158 return 1;
159 }
160 fprintf(stdout, "%s\n", props.c_str());
161 return 0;
162 }
163
Andrew Dugganfa10fc82014-07-07 17:36:33 -0700164 if (optind < argc) {
Andrew Duggan4e811252014-04-03 15:17:57 -0700165 firmwareName = argv[optind];
Andrew Dugganfa10fc82014-07-07 17:36:33 -0700166 } else {
167 printHelp(argv[0]);
Andrew Duggan99b3e572014-04-07 12:01:56 -0700168 return -1;
Andrew Duggan4e811252014-04-03 15:17:57 -0700169 }
170
171 rc = image.Initialize(firmwareName);
172 if (rc != UPDATE_SUCCESS) {
173 fprintf(stderr, "Failed to initialize the firmware image: %s\n", update_err_to_string(rc));
174 return 1;
175 }
176
Andrew Dugganfa10fc82014-07-07 17:36:33 -0700177 if (deviceName) {
Satoshi Noguchia0b675a2014-09-29 02:38:14 -0700178 rc = UpdateDevice(image, force, performLockdown, deviceName);
Andrew Duggan9b590b72014-08-08 13:38:01 -0700179
Andrew Duggan9b590b72014-08-08 13:38:01 -0700180 return rc;
Andrew Dugganfa10fc82014-07-07 17:36:33 -0700181 } else {
Andrew Duggan64f3a0c2014-07-31 11:22:01 -0700182 char deviceFile[PATH_MAX];
Andrew Dugganfa10fc82014-07-07 17:36:33 -0700183 bool found = false;
Andrew Duggan4e811252014-04-03 15:17:57 -0700184
Andrew Dugganfa10fc82014-07-07 17:36:33 -0700185 devDir = opendir("/dev");
186 if (!devDir)
187 return -1;
Andrew Duggan4e811252014-04-03 15:17:57 -0700188
Andrew Dugganfa10fc82014-07-07 17:36:33 -0700189 while ((devDirEntry = readdir(devDir)) != NULL) {
190 if (strstr(devDirEntry->d_name, "hidraw")) {
Andrew Dugganbef9c2d2015-05-06 17:45:48 -0700191 char rawDevice[PATH_MAX];
Andrew Duggan64f3a0c2014-07-31 11:22:01 -0700192 strncpy(rawDevice, devDirEntry->d_name, PATH_MAX);
193 snprintf(deviceFile, PATH_MAX, "/dev/%s", devDirEntry->d_name);
Satoshi Noguchia0b675a2014-09-29 02:38:14 -0700194 rc = UpdateDevice(image, force, performLockdown, deviceFile);
Andrew Dugganfa10fc82014-07-07 17:36:33 -0700195 if (rc != 0) {
196 continue;
197 } else {
198 found = true;
199 break;
200 }
201 }
202 }
203 closedir(devDir);
204
205 if (!found)
206 return rc;
Andrew Duggan4e811252014-04-03 15:17:57 -0700207 }
208
209 return 0;
210}