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 2 36#define VERSION_SUBMINOR 0 37 38#define RMI4UPDATE_GETOPTS "hfd:plv" 39 40void printHelp(const char *prog_name) 41{ 42 fprintf(stdout, "Usage: %s [OPTIONS] FIRMWAREFILE\n", prog_name); 43 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"); 45 fprintf(stdout, "\t-d, --device\thidraw device file associated with the device being updated.\n"); 46 fprintf(stdout, "\t-p, --fw-props\tPrint the firmware properties.\n"); 47 fprintf(stdout, "\t-l, --lockdown\tPerform lockdown.\n"); 48 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); 55} 56 57int UpdateDevice(FirmwareImage & image, bool force, bool performLockdown, const char * deviceFile) 58{ 59 HIDDevice rmidevice; 60 int rc; 61 62 rc = rmidevice.Open(deviceFile); 63 if (rc) 64 return rc; 65 66 RMI4Update update(rmidevice, image); 67 rc = update.UpdateFirmware(force, performLockdown); 68 if (rc != UPDATE_SUCCESS) 69 return rc; 70 71 return rc; 72} 73 74int 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 84 rmidevice.ScanPDT(0x1); 85 rmidevice.QueryBasicProperties(); 86 87 ss << rmidevice.GetFirmwareVersionMajor() << "." 88 << rmidevice.GetFirmwareVersionMinor() << "." 89 << std::hex << rmidevice.GetFirmwareID(); 90 91 if (rmidevice.InBootloader()) 92 ss << " bootloader"; 93 94 props = ss.str(); 95 96 return rc; 97} 98 99int main(int argc, char **argv) 100{ 101 int rc; 102 FirmwareImage image; 103 int opt; 104 int index; 105 char *deviceName = NULL; 106 const char *firmwareName = NULL; 107 bool force = false; 108 static struct option long_options[] = { 109 {"help", 0, NULL, 'h'}, 110 {"force", 0, NULL, 'f'}, 111 {"device", 1, NULL, 'd'}, 112 {"fw-props", 0, NULL, 'p'}, 113 {"lockdown", 0, NULL, 'l'}, 114 {"version", 0, NULL, 'v'}, 115 {0, 0, 0, 0}, 116 }; 117 struct dirent * devDirEntry; 118 DIR * devDir; 119 bool printFirmwareProps = false; 120 bool performLockdown = false; 121 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; 130 case 'd': 131 deviceName = optarg; 132 break; 133 case 'p': 134 printFirmwareProps = true; 135 break; 136 case 'l': 137 performLockdown = true; 138 break; 139 case 'v': 140 printVersion(); 141 return 0; 142 default: 143 break; 144 145 } 146 } 147 148 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 164 if (optind < argc) { 165 firmwareName = argv[optind]; 166 } else { 167 printHelp(argv[0]); 168 return -1; 169 } 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 177 if (deviceName) { 178 rc = UpdateDevice(image, force, performLockdown, deviceName); 179 180 return rc; 181 } else { 182 char deviceFile[PATH_MAX]; 183 bool found = false; 184 185 devDir = opendir("/dev"); 186 if (!devDir) 187 return -1; 188 189 while ((devDirEntry = readdir(devDir)) != NULL) { 190 if (strstr(devDirEntry->d_name, "hidraw")) { 191 char rawDevice[PATH_MAX]; 192 strncpy(rawDevice, devDirEntry->d_name, PATH_MAX); 193 snprintf(deviceFile, PATH_MAX, "/dev/%s", devDirEntry->d_name); 194 rc = UpdateDevice(image, force, performLockdown, deviceFile); 195 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; 207 } 208 209 return 0; 210} 211