blob: 1efa7eb20545b34ff4179e0451c689c21cb57c27 [file] [log] [blame]
Todd Broche2dfb362011-02-23 20:48:54 -08001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Todd Broche2dfb362011-02-23 20:48:54 -08004#include <arpa/inet.h>
5#include <assert.h>
6#include <errno.h>
7#include <ftdi.h>
8#include <inttypes.h>
9#include <netinet/in.h>
10#include <pthread.h>
11#include <stdio.h>
12#include <stdint.h>
13#include <string.h>
14#include <sys/types.h>
15#include <sys/socket.h>
16#include <unistd.h>
17
18#include "ftdi_common.h"
19#include "ftdigpio.h"
20#include "ftdiuart.h"
21#include "ftdii2c.h"
22
23#define MAX_BUF 512
24#define GPIO_FIELDS 3
25
26void usage(char *progname) {
27 printf("%s [common ftdi args]\n\n", progname);
28 exit(-1);
29}
30
31// parse_ul_element - parse element return non-zero for error else properly
32// converted value returned in value and buf set to character beyond delimeter
33char *parse_ul_element(unsigned long *value, char *buf, char delim) {
34 char *eptr;
35 *value = strtoul(buf, &eptr, 0);
36 if (!delim) {
37 return eptr;
38 } else if (eptr[0] != delim) {
39 return NULL;
40 }
41 return eptr + 1;
42}
43
44// parse_buffer_gpio - parse gpio command from client
45// <interface>,<direction>,<value>[,<mask>]
46// ex) 1,0xff,0xff -- set all gpios to output '1' on interface 1
47int parse_buffer_gpio(char *buf, struct gpio_s *gpio,
48 unsigned int *interface) {
49
50 char *bptr = buf;
51 unsigned long tmp_ul;
52
53 if (((bptr = parse_ul_element(&tmp_ul, bptr, ',')) == NULL) ||
54 (!tmp_ul || (tmp_ul > 4))) {
55 prn_error("Malformed interface argument\n");
56 return 1;
57 }
58 *interface = (unsigned int)tmp_ul;
59
60 if (((bptr = parse_ul_element(&tmp_ul, bptr, ',')) == NULL) ||
61 (tmp_ul > 0xff)) {
62 prn_error("Malformed direction argument\n");
63 return 1;
64 }
65 gpio->direction = (uint8_t)tmp_ul;
66 if (((bptr = parse_ul_element(&tmp_ul, bptr, 0)) == NULL) ||
67 (tmp_ul > 0xff)) {
68 prn_error("Malformed value argument\n");
69 return 1;
70 }
71 gpio->value = (uint8_t)tmp_ul;
72 if (bptr[0] == ',') {
73 bptr++;
74 // there's a mask
75 if (((bptr = parse_ul_element(&tmp_ul, bptr, 0)) == NULL) ||
76 (tmp_ul > 0xff)) {
77 prn_error("Malformed mask argument\n");
78 return 1;
79 }
80 gpio->mask = (uint8_t)tmp_ul;
81 } else {
82 gpio->mask = 0xff;
83 }
84 prn_dbg("Done parsing gpio buffer i:%d d:0x%02x v:0x%02x m:0x%02x\n",
85 *interface, gpio->direction, gpio->value, gpio->mask);
86 return 0;
87}
88// parse_buffer_i2c - parse i2c command from client
89// ex) 0x40,1,0x0,2 -- for i2c slave 0x40 write 1byte 0, read 2bytes
90int parse_buffer_i2c(char *buf, int *argc, uint8_t *argv) {
91 int argcnt = 0;
92 char *field;
93 field = strtok(buf, ",");
94 while (field) {
95 argv[argcnt++] = strtoul(field, NULL, 0);
96 field = strtok(NULL, ",");
97 }
98 // do some checking
99 if ((argcnt > 2) && (argcnt < argv[1] + 2)) {
100 prn_error("looks like i2c write w/o enough data\n");
101 return -1;
102 } else if (argcnt < 2) {
103 prn_error("Must have at least 2 arguments to i2c cmd=%s\n", buf);
104 return -1;
105 }
106 *argc = argcnt;
107 return 0;
108}
109
110// process_client - interact w/ client connection
111//
112// response to client looks like:
113// I:<read value>
114// A:
115//
116// or in case of error
117// E:<msg>
118//
119// where:
120// read value == value read for that bank of 8 gpios
121// msg == detailed message of error condition
122int process_client(struct ftdi_itype *interfaces, int int_cnt, int client) {
123
124 char buf[MAX_BUF];
125 char *rsp = buf;
126 int blen, bcnt, err;
127 struct gpio_s new_gpio;
128 uint8_t rd_val;
129
130 struct ftdi_itype *interface;
131
132 memset(rsp, 0, MAX_BUF);
133 if ((blen = read(client,buf,MAX_BUF-1)) <= 0) {
134 if (blen == 0) {
135 prn_info("client connection (fd=%d) hung up\n", client);
136 return 1;
137 } else {
138 perror("reading from client ... guess he disappeared");
139 return 1;
140 }
141 }
142
143 prn_dbg("client cmd: %s",buf);
144 if ((buf[0] == 'g') && (buf[1] == ',')) {
145 unsigned int interface_num;
146 if (parse_buffer_gpio(&buf[2], &new_gpio, &interface_num)) {
147 snprintf(buf, MAX_BUF,
148 "E:parsing client request. Should be\n\t%s\n",
149 "<interface>,<dir>,<val>[,<mask>]");
150 goto CLIENT_RSP;
151 }
152
153 interface = fcom_lookup_interface(interfaces, int_cnt, interface_num, ANY);
154 if (interface == NULL) {
155 snprintf(rsp, MAX_BUF, "E:No gpio at interface %d\n", interface_num);
156 goto CLIENT_RSP;
157 }
158
159 struct fgpio_context *fgc = NULL;
160 fgc = (struct fgpio_context *)interface->context;
161 assert(fgc);
162 if ((err = fgpio_wr_rd(fgc, &new_gpio, &rd_val, interface->type))) {
163 if (err == FGPIO_ERR_MASK) {
164 snprintf(rsp, MAX_BUF, "E:Illegal gpio mask. Bits avail are 0x%02x\n",
165 fgc->gpio.mask);
166 } else {
167 snprintf(rsp, MAX_BUF, "E:writing/reading gpio\n");
168 }
169 goto CLIENT_RSP;
170 }
171 snprintf(rsp, MAX_BUF, "I:0x%02x\nA:\n", rd_val);
172 } else if ((buf[0] == 'i') && (buf[1] == ',')) {
173 int argcnt = 0;
174
175 uint8_t args[128];
176 uint8_t rbuf[128];
177 if (parse_buffer_i2c(&buf[2], &argcnt, args)) {
178 snprintf(rsp, MAX_BUF, "E:parsing client request. Should be\n\t%s\n",
179 "<slv>,[<bytes to Wr>,<Wr0>,<Wr1>,<WrN>],[<bytes to Rd>]");
180 goto CLIENT_RSP;
181 }
182
183 interface = fcom_lookup_interface(interfaces, int_cnt, 2, I2C);
184 if (interface == NULL) {
185 snprintf(rsp, MAX_BUF, "E:No i2c at interface 2\n");
186 goto CLIENT_RSP;
187 }
188 struct fi2c_context *fic = NULL;
189 fic = (struct fi2c_context *)interface->context;
190 assert(fic);
191
192 // defaults if read-only
193 uint8_t *wbuf = NULL;
194 int wcnt = 0;
195 int rcnt = args[argcnt-1];
196 fic->slv = args[0];
197 if (argcnt > 2) {
198 wbuf = &args[2];
199 wcnt = args[1];
200 if (argcnt != wcnt + 3) {
201 // its just a write
202 rcnt = 0;
203 }
204 }
205 if (fi2c_wr_rd(fic, wbuf, wcnt, rbuf, rcnt)) {
206 snprintf(rsp, MAX_BUF, "E:writing/reading i2c\n");
207 goto CLIENT_RSP;
208 }
209 int bytes_remaining = MAX_BUF;
210 if (rcnt) {
211 snprintf(rsp, bytes_remaining, "I:0x");
212 rsp = rsp + 4;
213 bytes_remaining-=4;
214 int i;
215 for (i = 0; i < rcnt; i++) {
216 if (i && !(i % 4)) {
217 snprintf(rsp, bytes_remaining, "\nI:0x");
218 rsp+=5;
219 bytes_remaining-=5;
220 }
221 snprintf(rsp, bytes_remaining, "%02x", rbuf[i]);
222 rsp+=2;
223 bytes_remaining-=2;
224 if (bytes_remaining < 5) {
225 snprintf(buf, MAX_BUF, "E: i2c request too large. See developer\n");
226 goto CLIENT_RSP;
227 }
228 }
229 }
230 snprintf(rsp, bytes_remaining, "\nA:\n");
231 } else {
232 snprintf(rsp, MAX_BUF,
233 "E:parsing client request. Should be\n\t%s\n\t%s\n",
234 "g,<interface>,<dir>,<val>",
235 "i,<slv>,<bytes to write(4max)>,<write word>,<bytes to read>");
236 }
237
238CLIENT_RSP:
239 blen = strlen(buf);
240 bcnt = write(client, buf, blen);
241 if (bcnt != blen)
242 perror("writing to client");
243 return 0;
244}
245
246int init_socket(int port) {
247 struct sockaddr_in server_addr;
248
249 prn_dbg("Initializing server\n");
250 int sock = socket(AF_INET, SOCK_STREAM, 0);
251 if (sock < 0)
252 perror("opening socket");
253
254 memset(&server_addr, 0, sizeof(server_addr));
255
256 server_addr.sin_family = AF_INET;
257 server_addr.sin_addr.s_addr = INADDR_ANY;
258 server_addr.sin_port = htons(port);
259
260 int tr = 1;
261 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &tr, sizeof(int)) == -1) {
262 perror("setting sockopt");
263 exit(-1);
264 }
265 if (bind(sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
266 perror("binding socket");
267 exit(-1);
268 }
269
270 return sock;
271}
272
273int init_server(int port) {
274 int sock = init_socket(port);
275
276 assert(listen(sock, 5) == 0);
277 prn_dbg("Server initialized\n");
278 return sock;
279}
280
281void *run_uart(void *ptr) {
282 struct fuart_context *fcc = (struct fuart_context *)ptr;
283
284 while (1) {
285 if (fuart_wr_rd(fcc, 10000)) {
286 prn_error("fuart_wr_rd");
287 break;
288 }
289 }
290 // should never reach
291 return NULL;
292}
293
294void run_server(struct ftdi_itype *interfaces, int int_cnt, int server_fd) {
295 struct sockaddr_in client_addr;
296 fd_set read_fds, master_fds;
297 unsigned int client_len = sizeof(client_addr);
298
299 FD_ZERO(&read_fds);
300 FD_ZERO(&master_fds);
301 int max_fd = server_fd;
302 FD_SET(server_fd, &master_fds);
303
304 prn_dbg("Running server fd=%d\n", server_fd);
305 while (1) {
306 read_fds = master_fds;
307
308 if(select(max_fd+1, &read_fds, NULL, NULL, NULL) == -1) {
309 perror("Select test failed");
310 exit(1);
311 }
312 prn_dbg("select ok\n");
313
314 int i;
315 for (i = 0; i <= max_fd; i++) {
316 if (FD_ISSET(i, &read_fds)) {
317 if (i == server_fd) {
318 // add new clients
319 int new_client = accept(server_fd, (struct sockaddr *)&client_addr,
320 &client_len);
321 if (new_client < 0) {
322 perror("accepting connection");
323 exit(1);
324 } else {
325 prn_info("Client connected %s fd:%d\n",
326 inet_ntoa(client_addr.sin_addr), new_client);
327 FD_SET(new_client, &master_fds);
328 if (new_client > max_fd) {
329 max_fd = new_client;
330 prn_dbg("max_fd increased to %d\n", max_fd);
331 }
332 }
333 } else {
334 // process connected clients
335 if (process_client(interfaces, int_cnt, i)) {
336 close(i);
337 FD_CLR(i, &master_fds);
338 }
339 }
340 }
341 }
342 }
343}
344
345#define NUM_GPIOS 2
346#define NUM_INTERFACES 4
347
348int main(int argc, char **argv) {
349 int sock;
350
351 struct ftdi_common_args fargs = {
352 .interface = 0,
353 //.vendor_id = 0x18d1,
354 //.product_id = 0x5001,
355 .vendor_id = 0x0403,
356 .product_id = 0x6011,
357 .speed = 115200,
358 .bits = BITS_8,
359 .parity = NONE,
360 .sbits = STOP_BIT_1
361 };
362
363 int args_consumed;
364 if ((args_consumed = fcom_args(&fargs, argc, argv)) < 0) {
365 usage(argv[0]);
366 }
367
368 int i;
369 struct ftdi_context fc[NUM_INTERFACES];
370 struct fgpio_context fgs[NUM_GPIOS];
371
372 for (i = 0; i < NUM_INTERFACES; i++) {
373 if (ftdi_init(&fc[i]) < 0) {
374 ERROR_FTDI("Initializing ftdi context", &fc[i]);
375 return 1;
376 }
377 }
378
379 struct ftdi_itype interfaces[NUM_INTERFACES];
380
381 for (i = 0; i < NUM_GPIOS; i++) {
382 if (fgpio_init(&fgs[i], &fc[i])) {
383 prn_error("fgpio_init\n");
384 return FCOM_ERR;
385 }
386 }
387
388 // should be JTAG/SPI ... but GPIOs for now or use flashrom/openocd separately
389 fargs.interface = 1;
390 if (fgpio_open(&fgs[0], &fargs)) {
391 prn_error("fgpio_open\n");
392 return FCOM_ERR;
393 }
394 interfaces[fargs.interface - 1].context = (void *)&fgs[0];
395 interfaces[fargs.interface - 1].type = GPIO;
396
397 // i2c master
398 struct fi2c_context fic;
399 fargs.interface = 2;
400 if (fi2c_init(&fic, &fc[3])) {
401 prn_error("fi2c_init\n");
402 return FCOM_ERR;
403 }
404 if (fi2c_open(&fic, &fargs)) {
405 prn_error("fi2c_open\n");
406 return FCOM_ERR;
407 }
408 // 100khz
409 if (fi2c_setclock(&fic, 100000)) {
410 prn_error("fi2c_setclock\n");
411 return FCOM_ERR;
412 }
413 interfaces[fargs.interface - 1].context = (void *)&fic;
414 interfaces[fargs.interface - 1].type = I2C;
415
416 // DUT console uart
417 fargs.interface = 3;
418 struct fuart_context fcc;
419 if (fuart_init(&fcc, &fc[2])) {
420 prn_error("fuart_init\n");
421 return FCOM_ERR;
422 }
423 if (fuart_open(&fcc, &fargs)) {
424 prn_error("fuart_open\n");
425 return FCOM_ERR;
426 }
427 printf("ftdi uart connected to pty at %s\n", fcc.name);
428 pthread_t fcc_thread;
429 if (pthread_create(&fcc_thread, NULL, run_uart, (void *)&fcc)) {
430 perror("threading fuart");
431 return errno;
432 }
433 interfaces[fargs.interface - 1].context = (void *)&fcc;
434 interfaces[fargs.interface - 1].type = UART;
435
436 // legit gpios
437 fargs.interface = 4;
438 if (fgpio_open(&fgs[1], &fargs)) {
439 prn_error("fgpio_open\n");
440 return FCOM_ERR;
441 }
442 interfaces[fargs.interface - 1].context = (void *)&fgs[1];
443 interfaces[fargs.interface - 1].type = GPIO;
444
445 sock = init_server(9999);
446 prn_info("%s running accepting connections at port %d\n", argv[0], 9999);
447 run_server(interfaces, NUM_INTERFACES, sock);
448 return 0;
449}