Hi Mike, I think some more explanation is going to be required for the non FreeBSD users among us to understand the issues here, before we can decide what the right way forward is.
Firstly though a bit of background from my side. I designed the libserialport API and wrote much of the initial code. Uffe Jakobsen later contributed the FreeBSD support. libserialport is *not* specific to sigrok. It is a completely generic cross-platform serial port access library that is already in use by other unrelated projects. It should not make any assumptions about what is connected to a port. It would be perfectly normal and sensible to use libserialport for a program that did talk to modems rather than multimeters and oscilloscopes, or indeed anything else. When I designed the libserialport API, I implicitly made assumptions: - that a port would have a name of some form by which it could be identified (typically a "/dev/foo" path on Unixish systems). - that it is possible to generate a list of available ports, in which each actual port appears once (even if they can be accessed via symlinks or other aliases too). - that you could open a port using a name from that list, and then change the port settings freely through the resulting port handle. FreeBSD seems to break that assumption. Rather than having a single device node for the port, there are apparently two different device nodes for the same port, with the choice between them implicitly applying certain settings, in particular the DCD behaviour. So it seems you need to know in advance which settings you want before opening the port. Frankly, this doesn't fit the libserialport model. That could be seen as a failure on my part to come up with a sufficiently cross-platform API. But we are where we are. The API is out there and in use, and we need to figure out the best way of fitting FreeBSD into that. So I have some questions: - Having chosen which device node to open, are the settings that differ between the nodes locked down? Or is it possible to change them? I.e. can you open /dev/ttyuX and turn off the DCD behaviour, or to open /dev/cuaX and turn it on? - Exactly which behaviours (in terms of termios/stty settings) are preset for which device nodes? - Are these presets guaranteed, or are they just conventions? Is it possible to find a system in which the nodes have been given different settings? - Is there a convention within the FreeBSD user community over which name to use when identifying a physical port? Another factor we need to consider is the level of service provided by libserialport and what this means for the desired port configuration. The aim of libserialport is to provide an API that is usable in the same way across all platforms; this means that it can only support the lowest common denominator of functionality. When libserialport opens a port on a Unixish system, almost every "feature" in termios is immediately turned off; libserialport provides only a raw binary channel with no special processing. CTS, DSR, DCD and RI can be polled, RTS and DTR can be set and cleared. The only other functionality that can be enabled is the use of three specific flow control schemes: software XON/XOFF with standard control characters, and hardware flow control with either RTS/CTS or DTR/DSR as the control lines (if supported on that port). This is really all that can reliably be promised across the different platforms. As such, the expectation after opening a port with libserialport is that it will *not* wait for DCD to be asserted before being able to transmit and received data; that is not a capability libserialport offers, and so it should be turned off. It seems to me that this would argue for the library continuing to use /dev/cuauX on FreeBSD, unless /dev/ttyuX can be opened and the DCD behaviour then turned off. But I am happy to hear other arguments. I do not use FreeBSD and my understanding is only baѕed on the documentation, comments made in the libserialport code and the discussion on this list. Regards, Martin On Mon, Jul 11, 2016 at 07:47:14PM +0000, Mike Meyer wrote: > > Sigh. I'm having trouble getting this sent properly. Sorry 'bout the extra > mail. Here's the text. > It looks like the libserialport tty name checks for FreeBSD were written > by someone who's never used a Unix(TM) system like FreeBSD, so relied on > the documentation to figure out what the names were. > Forcing users to use /dev/cua devices for serial ports is simply wrong. > The call-out ports are usually used for modems because they are used for > "calling out" to another phone number, which requires that you be able to > dial the phone. This dates from the days when things that could dial the > phones (aka "call units") were actually different boxes from the ones that > did the serial line modulation/demodulation for the phone line, and hence > on different serial ports. Possibly only AT&T (you know, the folks that > wrote Unix) actually cared, but the distinction carried over into all > systems based on their code. > Since a logic analyzer/oscilloscope/dmm/etc can't dial the phone, there's > no point in using a /dev/cua device. The proper serial device to use is > the /dev/tty one. sigrok failing because you used /dev/ttyU0 is a > violation of POLA. > The attached patch changes the device check to /dev/tty, removes the > irrelevant comment, and changes the variable names to reflect the new > usage. > Note that I expect to apply this patch to 0.4.0 when I get around to > submitting new freebsd ports (which is waiting on the issue of pulseview > not building I sent mail about earlier). > Mike > diff --git a/freebsd.c b/freebsd.c > index 387b2f8..4148bec 100644 > --- a/freebsd.c > +++ b/freebsd.c > @@ -18,61 +18,18 @@ > */ > > /* > - * FreeBSD platform specific serial port information: > - * > - * FreeBSD has two device nodes for each serial port: > - * > - * 1) a call-in port > - * 2) a call-out port > - * > - * Quoting FreeBSD Handbook section 26.2.1 > - * (https://www.freebsd.org/doc/handbook/serial.html) > - * > - * In FreeBSD, each serial port is accessed through an entry in /dev. > - * There are two different kinds of entries: > - * > - * 1) Call-in ports are named /dev/ttyuN where N is the port number, > - * starting from zero. If a terminal is connected to the first serial port > - * (COM1), use /dev/ttyu0 to refer to the terminal. If the terminal is on > - * the second serial port (COM2), use /dev/ttyu1, and so forth. > - * Generally, the call-in port is used for terminals. Call-in ports > require > - * that the serial line assert the "Data Carrier Detect" signal to work > - * correctly. > - * > - * 2) Call-out ports are named /dev/cuauN on FreeBSD versions 10.x and higher > - * and /dev/cuadN on FreeBSD versions 9.x and lower. Call-out ports are > - * usually not used for terminals, but are used for modems. The call-out > - * port can be used if the serial cable or the terminal does not support > - * the "Data Carrier Detect" signal. > - * > - * FreeBSD also provides initialization devices (/dev/ttyuN.init and > - * /dev/cuauN.init or /dev/cuadN.init) and locking devices (/dev/ttyuN.lock > - * and /dev/cuauN.lock or /dev/cuadN.lock). The initialization devices are > - * used to initialize communications port parameters each time a port is > - * opened, such as crtscts for modems which use RTS/CTS signaling for flow > - * control. The locking devices are used to lock flags on ports to prevent > - * users or programs changing certain parameters. > - * > - * In line with the above device naming USB-serial devices have > - * the following naming: > - * > - * 1) call-in ports: /dev/ttyUN where N is the port number > - * 2) call-out ports: /dev/cuaUN where N is the port number > - * > - * See also: ucom(4), https://www.freebsd.org/cgi/man.cgi?query=ucom > - * > * Getting USB serial port device description: > * > * In order to query USB serial ports for device description - the mapping > * between the kernel device driver instances must be correlated with the > * above mentioned device nodes. > * > - * 1) For each USB-serial port (/dev/cuaUN) use libusb to lookup the device > + * 1) For each USB-serial port (/dev/ttyUN) use libusb to lookup the device > * description and the name of the kernel device driver instance. > * 2) Query sysctl for the kernel device driver instance info. > * 3) Derive the ttyname and (serial) port count for the kernel device > * driver instance. > - * 4) If sysctl ttyname and port matches /dev/cuaUN apply the libusb > + * 4) If sysctl ttyname and port matches /dev/tty apply the libusb > * device description. > */ > > @@ -91,7 +48,7 @@ > #include "libserialport.h" > #include "libserialport_internal.h" > > -#define DEV_CUA_PATH "/dev/cua" > +#define DEV_TTY_PATH "/dev/tty" > > //#define DBG(...) printf(__VA_ARGS__) > #define DBG(...) > @@ -240,24 +197,25 @@ SP_PRIV enum sp_return get_port_details(struct sp_port > *port) > struct libusb20_backend *be; > struct libusb20_device *dev, *dev_last; > char tbuf[FILENAME_MAX]; > - char *cua_sfx; > - int cua_dev_found; > + char *tty_sfx; > + int tty_dev_found; > uint8_t idx; > int sub_inst; > > DBG("Portname: '%s'\n", port->name); > > - if (!strncmp(port->name, DEV_CUA_PATH, strlen(DEV_CUA_PATH))) { > - cua_sfx = port->name + strlen(DEV_CUA_PATH); > - DBG("'%s': '%s'\n", DEV_CUA_PATH, cua_sfx); > - } else { > + if (!strncmp(port->name, DEV_TTY_PATH, strlen(DEV_TTY_PATH))) { > + tty_sfx = port->name + strlen(DEV_TTY_PATH); > + DBG("'%s': '%s'\n", DEV_TTY_PATH, tty_sfx); > + > + } else { > RETURN_ERROR(SP_ERR_ARG, "Device name not recognized"); > } > > /* Native UART enumeration. */ > - if ((cua_sfx[0] == 'u') || (cua_sfx[0] == 'd')) { > + if ((tty_sfx[0] == 'u') || (tty_sfx[0] == 'd')) { > port->transport = SP_TRANSPORT_NATIVE; > - snprintf(tbuf, sizeof(tbuf), "cua%s", cua_sfx); > + snprintf(tbuf, sizeof(tbuf), "tty%s", tty_sfx); > port->description = strdup(tbuf); > RETURN_OK(); > } > @@ -265,8 +223,8 @@ SP_PRIV enum sp_return get_port_details(struct sp_port > *port) > /* USB device enumeration. */ > dev = dev_last = NULL; > be = libusb20_be_alloc_default(); > - cua_dev_found = 0; > - while (cua_dev_found == 0) { > + tty_dev_found = 0; > + while (tty_dev_found == 0) { > dev = libusb20_be_device_foreach(be, dev_last); > if (!dev) > break; > @@ -291,9 +249,9 @@ SP_PRIV enum sp_return get_port_details(struct sp_port > *port) > snprintf(tbuf, > sizeof(tbuf), "%s", ttyname); > else > snprintf(tbuf, > sizeof(tbuf), "%s.%d", ttyname, sub_inst); > - if (!strcmp(cua_sfx, tbuf)) { > - DBG("MATCH: '%s' == > '%s'\n", cua_sfx, tbuf); > - cua_dev_found = 1; > + if (!strcmp(tty_sfx, tbuf)) { > + DBG("MATCH: '%s' == > '%s'\n", tty_sfx, tbuf); > + tty_dev_found = 1; > > populate_port_struct_from_libusb_desc(port, dev); > break; /* Break out of > sub instance loop. */ > } > @@ -308,7 +266,7 @@ SP_PRIV enum sp_return get_port_details(struct sp_port > *port) > free(drv_name_str); > if (drv_inst_str) > free(drv_inst_str); > - if (cua_dev_found) > + if (tty_dev_found) > break; /* Break out of USB device port idx > loop. */ > } > libusb20_dev_close(dev); > @@ -316,8 +274,8 @@ SP_PRIV enum sp_return get_port_details(struct sp_port > *port) > } > libusb20_be_free(be); > > - if (cua_dev_found == 0) > - DBG("WARN: Found no match '%s' %s'\n", port->name, cua_sfx); > + if (tty_dev_found == 0) > + DBG("WARN: Found no match '%s' %s'\n", port->name, tty_sfx); > > RETURN_OK(); > } > @@ -340,9 +298,9 @@ SP_PRIV enum sp_return list_ports(struct sp_port ***list) > ret = SP_OK; > if (entry.d_type != DT_CHR) > continue; > - if (strncmp(entry.d_name, "cuaU", 4) != 0) > - if (strncmp(entry.d_name, "cuau", 4) != 0) > - if (strncmp(entry.d_name, "cuad", 4) != 0) > + if (strncmp(entry.d_name, "ttyU", 4) != 0) > + if (strncmp(entry.d_name, "ttyu", 4) != 0) > + if (strncmp(entry.d_name, "ttyd", 4) != 0) > continue; > if (strend(entry.d_name, ".init")) > continue; > @@ -352,7 +310,7 @@ SP_PRIV enum sp_return list_ports(struct sp_port ***list) > snprintf(name, sizeof(name), "/dev/%s", entry.d_name); > DEBUG_FMT("Found device %s", name); > > - /* Check that we can open tty/cua device in rw mode - we need > that. */ > + /* Check that we can open tty device in rw mode - we need that. > */ > if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY | > O_TTY_INIT | O_CLOEXEC)) < 0) { > DEBUG("Open failed, skipping"); > continue; > ------------------------------------------------------------------------------ > Attend Shape: An AT&T Tech Expo July 15-16. Meet us at AT&T Park in San > Francisco, CA to explore cutting-edge tech and listen to tech luminaries > present their vision of the future. This family event has something for > everyone, including kids. Get more information and register today. > http://sdm.link/attshape > _______________________________________________ > sigrok-devel mailing list > [email protected] > https://lists.sourceforge.net/lists/listinfo/sigrok-devel ------------------------------------------------------------------------------ What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic patterns at an interface-level. Reveals which users, apps, and protocols are consuming the most bandwidth. Provides multi-vendor support for NetFlow, J-Flow, sFlow and other flows. Make informed decisions using capacity planning reports.http://sdm.link/zohodev2dev _______________________________________________ sigrok-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/sigrok-devel

