blob: eeeae1c5fc011ef19cb22992ce78163a434ef470 [file] [log] [blame]
Andrew Duggan052556f2014-04-16 11:32:30 -07001/*
2 * Copyright (C) 2013 - 2014 Andrew Duggan
3 * Copyright (C) 2013 - 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 <sys/types.h>
20#include <sys/stat.h>
21#include <fcntl.h>
22#include <errno.h>
23#include <string.h>
24#include <unistd.h>
25#include <sys/ioctl.h>
26#include <sys/select.h>
Andrew Duggan63078d52014-04-08 11:20:15 -070027#include <getopt.h>
Andrew Duggan4e811252014-04-03 15:17:57 -070028
29#include <linux/types.h>
30#include <linux/input.h>
31#include <linux/hidraw.h>
32#include <signal.h>
33#include <stdlib.h>
34
35#include "hiddevice.h"
36
Andrew Duggan63078d52014-04-08 11:20:15 -070037#define RMI4UPDATE_GETOPTS "hp:"
38
Andrew Duggan4e811252014-04-03 15:17:57 -070039static int report_attn = 0;
Andrew Duggan63078d52014-04-08 11:20:15 -070040static RMIDevice * g_device = NULL;
41
42void printArgsHelp(const char *prog_name)
43{
44 fprintf(stdout, "Usage: %s [OPTIONS] DEVICEFILE FIRMWAREFILE\n", prog_name);
45 fprintf(stdout, "\t-h, --help\tPrint this message\n");
46 fprintf(stdout, "\t-p, --protocol [protocol]\tSet which transport prototocl to use.\n");
47}
Andrew Duggan4e811252014-04-03 15:17:57 -070048
49void print_help()
50{
51 fprintf(stdout, "Commands:\n");
52 fprintf(stdout, "s [0,1,2]: Set RMIMode\n");
53 fprintf(stdout, "r address size: read size bytes from address\n");
54 fprintf(stdout, "w address { values }: write bytes to address\n");
55 fprintf(stdout, "a: Wait for attention\n");
56 fprintf(stdout, "q: quit\n");
57}
58
59int find_token(char * input, char * result, char ** endpp)
60{
61 int i = 0;
62 char * start = input;
63 char * end;
64
65 while (input[i] == ' ') {
66 ++start;
67 ++i;
68 }
69
70 while (input[i] != '\0') {
71 ++i;
72 if (input[i] == ' ') {
73 break;
74 }
75 }
76 end = &input[i];
77
78 if (start == end) {
79 return 0;
80 }
81
82 *endpp = end;
83 strncpy(result, start, end - start);
84 result[end - start + 1] = '\0';
85
86 return 1;
87}
88
Andrew Duggan63078d52014-04-08 11:20:15 -070089int process(RMIDevice * device, char * input)
Andrew Duggan4e811252014-04-03 15:17:57 -070090{
91 unsigned char report[256];
92 char token[256];
93 char * start;
94 char * end;
95 int rc;
96
97 memset(token, 0, 256);
98
99 if (input[0] == 's') {
100 start = input + 2;
101 find_token(start, token, &end);
102 int mode = strtol(token, NULL, 0);
103 if (mode >= 0 && mode <= 2) {
104 if (device->SetMode(mode)) {
105 fprintf(stderr, "Set RMI Mode to: %d\n", mode);
106 } else {
107 fprintf(stderr, "Set RMI Mode FAILED!\n");
108 return -1;
109 }
110 }
111 } else if (input[0] == 'r') {
112 start = input + 2;
113 find_token(start, token, &end);
114 start = end + 1;
115 int addr = strtol(token, NULL, 0);
116 find_token(start, token, &end);
117 start = end + 1;
118 int len = strtol(token, NULL, 0);
119 fprintf(stdout, "Address = 0x%02x Length = %d\n", addr, len);
120
121 memset(report, 0, sizeof(report));
122 rc = device->Read(addr, report, len);
123 if (rc < 0)
124 fprintf(stderr, "Failed to read report: %d\n", rc);
125
126 fprintf(stdout, "Data:\n");
127 for (int i = 0; i < len; ++i) {
128 fprintf(stdout, "0x%02X ", report[i]);
129 if (i % 8 == 7) {
130 fprintf(stdout, "\n");
131 }
132 }
133 fprintf(stdout, "\n");
134 } else if (input[0] == 'w') {
135 int index = 0;
136 start = input + 2;
137 find_token(start, token, &end);
138 start = end + 1;
139 int addr = strtol(token, NULL, 0);
140 int len = 0;
141
142 while (find_token(start, token, &end)) {
143 start = end + 1;
144 report[index++] = (unsigned char)strtol(token, NULL, 0);
145 ++len;
146 }
147
148 memset(report, 0, sizeof(report));
149
150 if (device->Write(addr, report, len) < 0) {
151 fprintf(stderr, "Failed to Write Report\n");
152 return -1;
153 }
154 } else if (input[0] == 'a') {
155 report_attn = 1;
156 while(report_attn) {
157 int bytes = 256;
158 device->GetAttentionReport(NULL, NULL, report, &bytes);
159 fprintf(stdout, "Data:\n");
160 for (int i = 0; i < bytes; ++i) {
161 fprintf(stdout, "0x%02X ", report[i]);
162 if (i % 8 == 7) {
163 fprintf(stdout, "\n");
164 }
165 }
166 fprintf(stdout, "\n\n");
167 }
168 } else if (input[0] == 'q') {
169 return 1;
170 } else {
171 print_help();
172 }
173 return 0;
174}
175
176static void cleanup(int status)
177{
178 if (report_attn) {
179 report_attn = 0;
180 if (g_device)
181 g_device->Cancel();
182 } else {
183 exit(0);
184 }
185}
186
187int main(int argc, char ** argv)
188{
189 int rc;
190 struct sigaction sig_cleanup_action;
Andrew Duggan63078d52014-04-08 11:20:15 -0700191 int opt;
192 int index;
193 RMIDevice *device;
194 const char *protocol = "HID";
195 static struct option long_options[] = {
196 {"help", 0, NULL, 'h'},
197 {"protocol", 1, NULL, 'p'},
198 {0, 0, 0, 0},
199 };
Andrew Duggan4e811252014-04-03 15:17:57 -0700200
201 memset(&sig_cleanup_action, 0, sizeof(struct sigaction));
202 sig_cleanup_action.sa_handler = cleanup;
203 sig_cleanup_action.sa_flags = SA_RESTART;
204 sigaction(SIGINT, &sig_cleanup_action, NULL);
205
Andrew Duggan63078d52014-04-08 11:20:15 -0700206 while ((opt = getopt_long(argc, argv, RMI4UPDATE_GETOPTS, long_options, &index)) != -1) {
207 switch (opt) {
208 case 'h':
209 printArgsHelp(argv[0]);
210 return 0;
211 case 'p':
212 protocol = optarg;
213 break;
214 default:
215 break;
216
217 }
218 }
219
220 if (!strncasecmp("hid", protocol, 3)) {
221 device = new HIDDevice();
222 } else {
223 fprintf(stderr, "Invalid Protocol: %s\n", protocol);
224 return -1;
225 }
226
227 rc = device->Open(argv[optind++]);
Andrew Duggan4e811252014-04-03 15:17:57 -0700228 if (rc) {
Andrew Duggan63078d52014-04-08 11:20:15 -0700229 fprintf(stderr, "%s: failed to initialize rmi device (%d): %s\n", argv[0], errno,
230 strerror(errno));
Andrew Duggan4e811252014-04-03 15:17:57 -0700231 return 1;
232 }
233
Andrew Duggan63078d52014-04-08 11:20:15 -0700234 device->ScanPDT();
235 device->QueryBasicProperties();
236 device->PrintProperties();
Andrew Duggan4e811252014-04-03 15:17:57 -0700237
Andrew Duggan63078d52014-04-08 11:20:15 -0700238 g_device = device;
Andrew Duggan4e811252014-04-03 15:17:57 -0700239
240 fprintf(stdout, "\n");
241 for (;;) {
242 fprintf(stdout, "\n");
243 print_help();
244 char buf[256];
245
246 if (fgets(buf, 256, stdin)) {
Andrew Duggan63078d52014-04-08 11:20:15 -0700247 if (process(device, buf) == 1)
Andrew Duggan4e811252014-04-03 15:17:57 -0700248 break;
249 }
250 }
251
Andrew Duggan63078d52014-04-08 11:20:15 -0700252 device->Close();
Andrew Duggan4e811252014-04-03 15:17:57 -0700253
254 return 0;
255}