Hi C, On 05/01/2015 10:42 AM, fenugrec@xxxxxxxxxxx wrote: > Hi, > I'm trying to determine the current situation & "best practices" for > setting custom baud rates. All the hardware I own, and all USB-serial > ICs I know of, support baud rates beyond the set of ~15 "standard" > rates defined over 20 years ago, but there still seems to be no > straightforward, portable method of setting custom baud rates ! The short answer is there is no portable method to setting non-standard baud rates. That said, cfsetispeed/cfsetospeed is the generic method; you could feature test for BXXXXXXXX macros on each platform at build time. At run time, the proper method is to check the resulting speed with cfgetispeed/cfgetospeed after the (successful) tcsetattr(), because that's the only way to know what the driver accepted (even for the standard baud rates, there's no requirement for the terminal driver to support all of the defined rates). Even on Linux, there's no guarantee the platform even defines the baud rate you want. For example, sparc only defines up to B921600 (or, B2000000 depending on what you ask). FWIW, I'm not sure Linux is the issue here though, because AFAIK Linux supports _every_ method of setting non-standard baud rates. > So far, I've found 3 methods that *may* be able to set custom > baud rates, in *some* cases : > > 1- B38400 + ASYNC_SPD_CUST: > (source: comments in drivers/usb/serial/ftdi_sio.c ): > **** > Set tty->termios->c_cflag speed to B38400 > Sall TIOCSSERIAL ioctl with (struct serial_struct) set as follows: > -flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST > -custom_divisor set to baud_base / your_new_baudrate > **** > Problem : some drivers don't implement TIOCSSERIAL, > like ftdi_sio a few years ago, and currently also CH34* > ( drivers/usb/serial/ch341.c ) Don't use this method. > Also, wasn't this the method that used to make the kernel print an > unhelpful "X sets a custom speed on Y, this is deprecated" ? > I remember not finding an alternate method, at the time. > > 2- BOTHER > in drivers/tty/tty_ioctl.c , > the implementation of tty_termios_baud_rate() has this: > **** > #ifdef BOTHER > /* Magic token for arbitrary speed via c_ispeed/c_ospeed */ > if (cbaud == BOTHER) > return termios->c_ospeed; > #endif > **** > Which looked promising, but according to some lore : > - BOTHER isn't always/ever defined in <termios.h> ? > - #include <asm/termios.h> may cause problems, > and looks like a non-portable hack ? > - There's a connection with "termios2" vs glibc which I'm unsure of. BOTHER is for setting a completely custom rate (ie., not one of the defined BXXXXXX rates). You may get varying results doing this because there is no guarantee the uart clock can get within a reasonable degree of error of the baud rate you want. > 3- POSIX cfsetispeed / cfsetospeed: > (calling those functions with the integer value of the desired > baud rate ) > Its success depends on how the "speed_t" argument is implemented, > so it probably won't work because of the way the Bxx flags are defined? This is the recommended generic method. > So, what can I do ? I've looked at the code for stty and setserial, and > neither will succeed in setting the speed on a CH341. > > This isn't a new problem of course, but I was hoping the situation would > be saner, or at least have a clean solution in 2015 ! I'm not clear on something: you want a portable method of setting baud rates, but how do you know you're communicating with a CH341? Regards, Peter Hurley -- To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html