1 /*
2 OWFS -- One-Wire filesystem
3 ow_ftdi: low-level communication routines for FTDI-based adapters
4
5 Copyright 2014-2016 Johan Ström <johan@stromnet.se>
6 Released under GPLv2 for inclusion in the OWFS project.
7
8 This file implements a serial layer for use with FTDI-based USB serial
9 adapters. It should be usable as an in-place replacement for any ports
10 with type ct_serial, given that the actual device can be reached through
11 a FTDI chip (which is accessible).
12
13 The main benifit of using this rather than accessing through a regular
14 ttyUSB/cuaU device is that it will tweak the FTDI chip's latency timer.
15 Since 1W transactions often use single character reads, the default setting
16 inflicts a 16ms delay on every single read operation. With this layer
17 we bring that down to (max) 1ms.
18
19 This is (mostly) called from ow_com* routines, when the underlying
20 port_in type is ct_ftdi.
21
22 Please note that this is only a serial layer, for interacting with FTDI
23 serial adapter chips. Generally, there is no way to know WHAT is conneted
24 a given chip. Thus, ut is *not* possible to write a "scan for any FTDI
25 1wire device" feature, unless the device has a unique VID/PID.
26
27 The owftdi_open method assumes that the device arg is prefixed with "ftdi:".
28
29 The following args can be used to identify a specific port:
30
31 ftdi:d:<devicenode>
32 path of bus and device-node (e.g. "003/001") within usb device tree
33 (usually at /proc/bus/usb/)
34 ftdi:i:<vendor>:<product>
35 first device with given vendor and product id, ids can be decimal, octal
36 (preceded by "0") or hex (preceded by "0x")
37 ftdi:i:<vendor>:<product>:<index>
38 as above with index being the number of the device (starting with 0)
39 if there are more than one
40 ftdi:s:<vendor>:<product>:<serial>
41 first device with given vendor id, product id and serial string
42
43 The strings are passed to libftdi as a "descriptor".
44 An additional format is supported, for certain bus types.
45
46 ftdi:<serial>
47
48 This only works if there is a pre-defined VID/PID for the bus type used.
49 Currently, this is only valid for the VID/PID found on the LinkUSB (i.e. bus_link).
50 Note that those VID/PID's are the default for any FT232R device, and in no way exclusive
51 to LinkUSB.
52 */
53
54 #include <config.h>
55 #include "owfs_config.h"
56 #include "ow_connection.h"
57
58 #if OW_FTDI
59 //#define BENCH
60
61 #define FTDI_LINKUSB_VID 0x0403
62 #define FTDI_LINKUSB_PID 0x6001
63
64 #include <ftdi.h>
65 #include <assert.h>
66 #include <inttypes.h>
67
68 #include "ow_ftdi.h"
69
min(int a,int b)70 static inline int min(int a, int b) {
71 return (a > b) ? b : a;
72 }
73
max(int a,int b)74 static inline int max(int a, int b) {
75 return (a > b) ? a : b;
76 }
77
78 #define FTDIC(in) ((in)->master.link.ftdic)
79 static GOOD_OR_BAD owftdi_open_device(struct connection_in *in, const char *description) ;
80 static GOOD_OR_BAD owftdi_open_device_specific(struct connection_in *in, int vid, int pid, const char *serial) ;
81 static GOOD_OR_BAD owftdi_opened(struct connection_in *in) ;
82
83 #define owftdi_configure_baud(in) owftdi_configure_baud0(in, COM_BaudRate((in)->pown->baud))
84 static GOOD_OR_BAD owftdi_configure_baud0(struct connection_in *in, int baud) ;
85 static GOOD_OR_BAD owftdi_configure_bits(struct connection_in *in, enum ftdi_break_type break_) ;
86 static GOOD_OR_BAD owftdi_configure_dtrrts(struct connection_in *in, int value) ;
87
owftdi_open(struct connection_in * in)88 GOOD_OR_BAD owftdi_open( struct connection_in * in ) {
89 GOOD_OR_BAD gbResult;
90 const char* arg = in->pown->init_data;
91 const char* target = arg+5;
92 assert(arg);
93 assert(strstr(arg, "ftdi:") == arg);
94
95 if(strlen(target) < 2) {
96 LEVEL_DEFAULT("Invalid ftdi target string");
97 return gbBAD ;
98 }
99
100 char c0 = target[0];
101 char c1 = target[1];
102 const char* serial = NULL;
103 if(c0 != 'd' && c0 != 'i' && c0 != 's' && c1 != ':') {
104 // Assume plain serial; only works with known device-types
105 serial = target;
106 }
107
108 if(FTDIC(in)) {
109 LEVEL_DEFAULT("FTDI interface %s was NOT closed?",
110 DEVICENAME(in));
111 return gbBAD ;
112 }
113
114 if(!(FTDIC(in) = ftdi_new())) {
115 LEVEL_DEFAULT("Failed to get FTDI context");
116 return gbBAD ;
117 }
118
119 if(serial) {
120 switch(in->pown->busmode) {
121 case bus_link:
122 gbResult = owftdi_open_device_specific(in,
123 FTDI_LINKUSB_VID, FTDI_LINKUSB_PID,
124 serial);
125
126 if(GOOD(gbResult))
127 in->adapter_name = "LinkUSB";
128
129 break;
130 default:
131 LEVEL_DEFAULT(
132 "Cannot use ftdi:<serial> with this device (%d), please use full format",
133 in->pown->busmode);
134 gbResult = gbBAD;
135 break;
136 }
137 }else{
138 gbResult = owftdi_open_device(in, target);
139 }
140
141 if(GOOD(gbResult)) {
142 gbResult = owftdi_change(in);
143 }
144
145 if(BAD(gbResult)) {
146 ftdi_free(FTDIC(in));
147 FTDIC(in) = NULL;
148 }
149 else {
150 in->pown->state = cs_deflowered;
151 }
152
153
154
155 return gbResult;
156 }
157
owftdi_free(struct connection_in * in)158 void owftdi_free( struct connection_in *in ) {
159 if(!FTDIC(in)) {
160 assert(in->pown->file_descriptor == FILE_DESCRIPTOR_BAD);
161 return ;
162 }
163
164 // Best effort, port might not be open, only context
165 ftdi_usb_close(FTDIC(in));
166
167 ftdi_free(FTDIC(in));
168 FTDIC(in) = NULL;
169
170 in->pown->state = cs_virgin;
171 // TODO: Cleaner?
172 in->pown->file_descriptor = FILE_DESCRIPTOR_BAD;
173 }
174
owftdi_close(struct connection_in * in)175 void owftdi_close( struct connection_in * in ) {
176 owftdi_free(in);
177 }
178
owftdi_flush(const struct connection_in * in)179 void owftdi_flush( const struct connection_in *in ) {
180 if(!FTDIC(in)) {
181 LEVEL_DEFAULT("Cannot flush FTDI interface %s, not open", DEVICENAME(in));
182 return;
183 }
184
185 ftdi_usb_purge_tx_buffer(FTDIC(in));
186 ftdi_usb_purge_rx_buffer(FTDIC(in));
187 }
188
189
owftdi_break(struct connection_in * in)190 void owftdi_break ( struct connection_in *in ) {
191 assert (FTDIC(in));
192
193 // Wait a bit, ensuring any pending writes get through.
194 usleep(100000);
195
196 /* tcsendbreak manpage:
197 * linux: 0.25-0.5s
198 * freebsd: "four tenths of a second"
199 *
200 * break for 0.4s here as well
201 */
202 LEVEL_DEBUG("Sending FTDI break..");
203 owftdi_configure_bits(in, BREAK_ON);
204 usleep(400000);
205 owftdi_configure_bits(in, BREAK_OFF);
206 }
207
208
owftdi_open_device(struct connection_in * in,const char * description)209 static GOOD_OR_BAD owftdi_open_device(struct connection_in *in, const char *description) {
210 int ret = ftdi_usb_open_string(FTDIC(in), description);
211 if(ret != 0) {
212 ERROR_CONNECT("Failed to open FTDI device with description '%s': %d = %s",
213 description, ret, ftdi_get_error_string(FTDIC(in)));
214 return gbBAD;
215 }
216
217 return owftdi_opened(in);
218 }
219
owftdi_open_device_specific(struct connection_in * in,int vid,int pid,const char * serial)220 static GOOD_OR_BAD owftdi_open_device_specific(struct connection_in *in, int vid, int pid, const char *serial) {
221 int ret = ftdi_usb_open_desc(FTDIC(in), vid, pid, NULL, serial);
222 if(ret != 0) {
223 ERROR_CONNECT("Failed to open FTDI device with vid/pid 0x%x/0%x and serial '%s': %d = %s",
224 vid, pid, serial, ret, ftdi_get_error_string(FTDIC(in)));
225 return gbBAD;
226 }
227
228 return owftdi_opened(in);
229 }
230
owftdi_opened(struct connection_in * in)231 static GOOD_OR_BAD owftdi_opened(struct connection_in *in) {
232 int ret;
233
234 /* Set DTR and RTS high. This is normally done by the OS when using the
235 * generic serial interface. We must do it manually, or we will not be able to
236 * communicate with the LinkUSB after boot/re-plug.
237 *
238 * Unfortunately, this can not be used to power-cycle the LinkUSB, it seems..
239 */
240 RETURN_BAD_IF_BAD(owftdi_configure_dtrrts(in, 1));
241
242 // Set latency timer to 1ms; improves response speed alot
243 if((ret = ftdi_set_latency_timer(FTDIC(in), 1)) != 0) {
244 ERROR_CONNECT("Failed to set FTDI latency timer: %d = %s",
245 ret,
246 ftdi_get_error_string(FTDIC(in)));
247 return gbBAD;
248 }
249
250 // Fake a file_descriptor, so we can pass FILE_DESCRIPTOR_NOT_VALID check in
251 // COM_read, COM_test
252 // TODO: Cleaner?
253 in->pown->file_descriptor = 999;
254
255 return gbGOOD;
256 }
257
owftdi_configure_baud0(struct connection_in * in,int baud)258 static GOOD_OR_BAD owftdi_configure_baud0(struct connection_in *in, int baud) {
259 int ret;
260 if((ret = ftdi_set_baudrate(FTDIC(in), baud)) != 0) {
261 ERROR_CONNECT("Failed to set FTDI baud rate to %d: %d = %s",
262 baud,
263 ret,
264 ftdi_get_error_string(FTDIC(in)));
265 return gbBAD;
266 }
267
268 return gbGOOD;
269 }
270
owftdi_configure_bits(struct connection_in * in,enum ftdi_break_type break_)271 static GOOD_OR_BAD owftdi_configure_bits(struct connection_in *in, enum ftdi_break_type break_) {
272 struct port_in * pin = in->pown ;
273 enum ftdi_bits_type bits;
274 enum ftdi_stopbits_type stop;
275 enum ftdi_parity_type parity;
276 int ret;
277
278 switch (pin->bits) {
279 case 7:
280 bits = BITS_7;
281 break ;
282 case 8:
283 default:
284 bits = BITS_8;
285 break ;
286 }
287
288 switch (pin->parity) {
289 case parity_none:
290 default:
291 parity = NONE;
292 break ;
293 case parity_even:
294 parity = EVEN;
295 break ;
296 case parity_odd:
297 parity = ODD;
298 break ;
299 case parity_mark:
300 parity = MARK;
301 break ;
302 }
303
304 // stop bits
305 switch (pin->stop) {
306 case stop_1:
307 default:
308 stop = STOP_BIT_1;
309 break ;
310 case stop_15:
311 stop = STOP_BIT_15;
312 break;
313 case stop_2:
314 stop = STOP_BIT_2;
315 break ;
316 }
317
318 if((ret = ftdi_set_line_property2(FTDIC(in), bits, stop, parity, break_)) != 0) {
319 ERROR_CONNECT("Failed to set FTDI bit-configuration: %d = %s",
320 ret,
321 ftdi_get_error_string(FTDIC(in)));
322 return gbBAD;
323 }
324
325 return gbGOOD;
326 }
327
owftdi_configure_flow(struct connection_in * in)328 static GOOD_OR_BAD owftdi_configure_flow(struct connection_in *in) {
329 struct port_in * pin = in->pown ;
330 int flow;
331 int ret;
332
333 switch( pin->flow ) {
334 case flow_hard:
335 flow = SIO_RTS_CTS_HS;
336 break ;
337 case flow_none:
338 flow = SIO_DISABLE_FLOW_CTRL;
339 break ;
340 case flow_soft:
341 default:
342 LEVEL_DEBUG("Unsupported COM port flow control");
343 return gbBAD ;
344 }
345
346 if((ret = ftdi_setflowctrl(FTDIC(in), flow)) != 0) {
347 ERROR_CONNECT("Failed to set FTDI flow-control: %d = %s",
348 ret,
349 ftdi_get_error_string(FTDIC(in)));
350 return gbBAD;
351 }
352
353 return gbGOOD;
354 }
355
owftdi_configure_dtrrts(struct connection_in * in,int value)356 static GOOD_OR_BAD owftdi_configure_dtrrts(struct connection_in *in, int value) {
357 int ret = ftdi_setdtr_rts(FTDIC(in), value, value);
358 if(ret != 0) {
359 ERROR_CONNECT("Failed to set FTDI DTR/RTS high, %d: %s",
360 ret, ftdi_get_error_string(FTDIC(in)));
361 return gbBAD;
362 }
363 return gbGOOD;
364 }
365
owftdi_change(struct connection_in * in)366 GOOD_OR_BAD owftdi_change(struct connection_in *in) {
367 RETURN_BAD_IF_BAD(owftdi_configure_baud(in));
368 RETURN_BAD_IF_BAD(owftdi_configure_bits(in, BREAK_OFF));
369 RETURN_BAD_IF_BAD(owftdi_configure_flow(in));
370
371 return gbGOOD;
372 }
373
owftdi_read(BYTE * data,size_t requested_size,struct connection_in * in)374 SIZE_OR_ERROR owftdi_read(BYTE * data, size_t requested_size, struct connection_in *in) {
375 struct port_in * pin = in->pown ;
376 struct timeval tv_start;
377 size_t chars_read = 0,
378 to_be_read = requested_size;
379 int retries = 0;
380 time_t timeout;
381
382 #ifdef BENCH
383 struct timeval tv_end, tv_timing;
384 #endif
385
386 /* Configure USB *block transfer* timeout, this is not wait-for-any-data timeout
387 * which we must implement manually below. */
388 timeout = pin->timeout.tv_sec * 1000 + pin->timeout.tv_usec/1000;
389 FTDIC(in)->usb_read_timeout = timeout;
390
391
392 /* ftdi_read_data will loop internally and read until requested_size has been filled,
393 * or at least filled from whats available in the FTDI buffer.
394 * The FTDI buffer is however one step away from the LINK, a RX buffer is inbetween.
395 * A copy operation from the RX buffer to the FTDI buffer is done only when it's full,
396 * or when the "latency timer" kicks in. We thus have to keep reading from the FTDI
397 * buffer for a while.
398 *
399 * With our latency timer of 1ms, we will have a empty read after 1ms. However, in most
400 * cases we actuall DO get data in time!
401 */
402 LEVEL_DEBUG("attempt %zu bytes Time: "TVformat, requested_size, TVvar(&(pin->timeout)));
403 gettimeofday(&tv_start, NULL);
404 while(to_be_read> 0) {
405 int ret = ftdi_read_data(FTDIC(in), &data[chars_read], to_be_read);
406 if(ret < 0) {
407 LEVEL_DATA("FTDI read failed: %d = %s",
408 ret, ftdi_get_error_string(FTDIC(in)));
409 STAT_ADD1(NET_read_errors);
410 owftdi_close(in);
411 return -EINVAL;
412 }
413 if(ret == 0) {
414 // No data there yet... Sleep a bit and wait for more
415 struct timeval tv_cur;
416 time_t timeleft;
417 gettimeofday(&tv_cur, NULL);
418 timeleft = timeout*1000L -
419 ((tv_cur.tv_sec - tv_start.tv_sec)*1000000L +
420 (tv_cur.tv_usec - tv_start.tv_usec));
421
422 #if 0
423 LEVEL_DEBUG("No data available, delaying a bit (%"PRIu64"ms left, retrie %d)",
424 timeleft/1000L,
425 retries
426 );
427 #endif
428
429 if(timeleft < 0) {
430 LEVEL_CONNECT("TIMEOUT after %d bytes", requested_size - to_be_read);
431 // XXX: Stats here is not in tcp_read?
432 STAT_ADD1_BUS(e_bus_timeouts, in);
433 return -EAGAIN;
434 }
435
436 /* In <= 1ms, the latency timer will trigger a copy of the RX buffer
437 * to the USB bus. When that time has come, we can try to read again.
438 * Do it a bit quicker to get smaller latency.
439 * Testing shows that we usually get our data within one or two loops
440 * in normal situations, so this isn't really heavy busyloading.
441 */
442 usleep(min(timeleft, (retries < 10) ? 200 : 1000));
443 retries++;
444 continue;
445 }
446 TrafficIn("read", &data[chars_read], ret, in) ;
447 to_be_read -= ret;
448 chars_read += ret;
449 }
450 #ifdef BENCH
451 gettimeofday(&tv_end, NULL);
452 timersub(&tv_end, &tv_start, &tv_timing);
453 LEVEL_DEBUG("ftdi_read, read %d bytes. %d read-loops=%.6fus, actual= %d",
454 requested_size,
455 retries,
456 ((uint64_t)(tv_timing.tv_sec*1000000L) + (double)(tv_timing.tv_usec)),
457 chars_read
458 );
459 #endif
460
461 LEVEL_DEBUG("ftdi_read: %d - %d = %d (%d retries)",
462 (int)requested_size, (int) to_be_read, (int) (requested_size-to_be_read),
463 retries) ;
464 return chars_read;
465 }
466
owftdi_write_once(const BYTE * data,size_t length,struct connection_in * in)467 GOOD_OR_BAD owftdi_write_once( const BYTE * data, size_t length, struct connection_in *in) {
468 // Mimics COM_write_once
469 FTDIC(in)->usb_write_timeout = Globals.timeout_serial * 1000; // XXX why not pin->timeout?
470
471 TrafficOut("write", data, length, in);
472 int ret = ftdi_write_data(FTDIC(in), data, (int)length);
473 if(ret < 0) {
474 ERROR_CONNECT("FTDI write to %s failed: %d = %s",
475 SAFESTRING(DEVICENAME(in)),
476 ret,
477 ftdi_get_error_string(FTDIC(in)));
478
479 STAT_ADD1_BUS(e_bus_write_errors, in);
480 owftdi_close(in);
481 return gbBAD;
482 }
483
484 LEVEL_DEBUG("ftdi_write: %zu = actual %d", length, ret) ;
485
486 return gbGOOD;
487 }
488
489 /* slurp up any pending chars -- used at the start to clear the com buffer */
owftdi_slurp(struct connection_in * in,uint64_t usec)490 void owftdi_slurp(struct connection_in *in, uint64_t usec) {
491 int ret;
492 BYTE data[1];
493
494 /* This function is implemented similar to read; it must do repeated
495 * ftdi_read_data calls, or we might miss to slurp critical data,
496 * and the state machine will become confused.
497 *
498 * First purge any data in rx buffer, then do some subsequent reads.
499 */
500
501 ret = ftdi_usb_purge_rx_buffer(FTDIC(in));
502 if(ret != 0) {
503 ERROR_CONNECT("Failed to purge rx buffers on FTDI device, %d: %s",
504 ret, ftdi_get_error_string(FTDIC(in)));
505 }
506
507 // Allow for at least 2 rounds of latency timeouts.. or we seem to miss \n in 19200 sometimes..
508 usec = max(usec, 2*1000);
509
510 // USB block transfer timeout
511 int prev_timeout = FTDIC(in)->usb_read_timeout;
512 struct timeval tv_start;
513 FTDIC(in)->usb_read_timeout = usec/1000;
514
515 gettimeofday(&tv_start, NULL);
516 while(1) {
517 ret = ftdi_read_data(FTDIC(in), data, 1);
518 #if 0
519 LEVEL_DEBUG("ftdi_slurp read ret %d, %s ", ret, ftdi_get_error_string(FTDIC(in)));
520 #endif
521 if(ret < 1) {
522 // No data there yet... Sleep a bit and wait for more
523 struct timeval tv_cur;
524 time_t timeleft;
525 gettimeofday(&tv_cur, NULL);
526 timeleft = usec -
527 ((tv_cur.tv_sec - tv_start.tv_sec)*1000000L +
528 (tv_cur.tv_usec - tv_start.tv_usec));
529
530 if(timeleft < 0) {
531 #if 0
532 LEVEL_DEBUG("ftdi_slurp timeout, timeleft=%d ", timeleft);
533 #endif
534 break;
535 }
536
537 usleep(min(timeleft, 200));
538 continue;
539 }
540
541 TrafficIn("slurp", data, 1, in);
542 }
543
544 FTDIC(in)->usb_read_timeout = prev_timeout;
545 }
546
547 #endif /* OW_FTDI */
548