Home | History | Annotate | Download | only in rmi4update
      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 
     40 void 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 
     51 void printVersion()
     52 {
     53 	fprintf(stdout, "rmi4update version %d.%d.%d\n",
     54 		VERSION_MAJOR, VERSION_MINOR, VERSION_SUBMINOR);
     55 }
     56 
     57 int 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 
     74 int 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 
     99 int 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