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