22 #define LIRC_LOCKDIR "/var/lock/lockdev"
39 #include <sys/types.h>
41 #include <sys/ioctl.h>
44 #include <linux/serial.h>
48 #include "lirc/lirc_log.h"
49 #include "lirc/curl_poll.h"
56 struct termios options;
58 if (tcgetattr(fd, &options) == -1) {
59 log_trace(
"tty_reset(): tcgetattr() failed");
64 if (tcsetattr(fd, TCSAFLUSH, &options) == -1) {
65 log_trace(
"tty_reset(): tcsetattr() failed");
74 struct termios options;
76 if (tcgetattr(fd, &options) == -1) {
77 log_trace(
"%s: tcgetattr() failed", __func__);
82 options.c_cflag |= CRTSCTS;
84 options.c_cflag &= ~CRTSCTS;
85 if (tcsetattr(fd, TCSAFLUSH, &options) == -1) {
86 log_trace(
"%s: tcsetattr() failed", __func__);
97 if (ioctl(fd, TIOCMGET, &sts) < 0) {
98 log_trace(
"%s: ioctl(TIOCMGET) failed", __func__);
102 if (((sts & TIOCM_DTR) == 0) && enable) {
104 }
else if ((!enable) && (sts & TIOCM_DTR)) {
112 if (ioctl(fd, cmd, &sts) < 0) {
113 log_trace(
"%s: ioctl(TIOCMBI(S|C)) failed", __func__);
122 struct termios options;
125 #if defined __linux__
126 int use_custom_divisor = 0;
127 struct serial_struct serinfo;
224 #if defined __linux__
226 use_custom_divisor = 1;
229 log_trace(
"tty_setbaud(): bad baud rate %d", baud);
233 if (tcgetattr(fd, &options) == -1) {
234 log_trace(
"tty_setbaud(): tcgetattr() failed");
238 (void)cfsetispeed(&options, speed);
239 (void)cfsetospeed(&options, speed);
240 if (tcsetattr(fd, TCSAFLUSH, &options) == -1) {
241 log_trace(
"tty_setbaud(): tcsetattr() failed");
245 #if defined __linux__
246 if (use_custom_divisor) {
247 if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) {
248 log_trace(
"tty_setbaud(): TIOCGSERIAL failed");
252 serinfo.flags &= ~ASYNC_SPD_MASK;
253 serinfo.flags |= ASYNC_SPD_CUST;
254 serinfo.custom_divisor = serinfo.baud_base / baud;
255 if (ioctl(fd, TIOCSSERIAL, &serinfo) < 0) {
256 log_trace(
"tty_setbaud(): TIOCSSERIAL failed");
267 struct termios options;
284 log_trace(
"tty_setcsize(): bad csize rate %d", csize);
287 if (tcgetattr(fd, &options) == -1) {
288 log_trace(
"tty_setcsize(): tcgetattr() failed");
292 options.c_cflag &= ~CSIZE;
293 options.c_cflag |= size;
294 if (tcsetattr(fd, TCSAFLUSH, &options) == -1) {
295 log_trace(
"tty_setcsize(): tcsetattr() failed");
304 char filename[FILENAME_MAX + 1];
305 char symlink[FILENAME_MAX + 1];
306 char cwd[FILENAME_MAX + 1];
313 strcpy(filename, LIRC_LOCKDIR
"/LCK..");
315 last = strrchr(name,
'/');
321 if (strlen(filename) + strlen(s) > FILENAME_MAX) {
322 log_error(
"invalid filename \"%s%s\"", filename, s);
327 tty_create_lock_retry:
328 len = snprintf(
id, 10 + 1 + 1,
"%10d\n", getpid());
330 log_error(
"invalid pid \"%d\"", getpid());
333 lock = open(filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
336 lock = open(filename, O_RDONLY);
341 if (read(lock,
id, 10 + 1) == 10 + 1 && read(lock,
id, 1) == 0
342 && sscanf(
id,
"%d\n", &otherpid) > 0) {
343 if (kill(otherpid, 0) == -1 && errno == ESRCH) {
344 log_warn(
"detected stale lockfile %s", filename);
346 if (unlink(filename) != -1) {
348 goto tty_create_lock_retry;
351 "could not remove stale lockfile");
355 log_error(
"%s is locked by PID %d", name, otherpid);
357 log_error(
"invalid lockfile %s encountered", filename);
363 if (write(lock,
id, len) != len) {
366 if (unlink(filename) == -1)
371 if (close(lock) == -1) {
373 if (unlink(filename) == -1)
379 len = readlink(name, symlink, FILENAME_MAX);
381 if (errno != EINVAL) {
383 if (unlink(filename) == -1) {
394 char dirname[FILENAME_MAX + 1];
396 if (getcwd(cwd, FILENAME_MAX) == NULL) {
398 if (unlink(filename) == -1) {
400 "could not delete file \"%s\"",
407 strcpy(dirname, name);
408 dirname[strlen(name) - strlen(last)] = 0;
409 if (chdir(dirname) == -1) {
411 "chdir() to \"%s\" failed", dirname);
412 if (unlink(filename) == -1) {
414 "could not delete file \"%s\"",
422 if (unlink(filename) == -1) {
424 "could not delete file \"%s\"", filename);
430 if (chdir(cwd) == -1) {
432 if (unlink(filename) == -1) {
434 "could not delete file \"%s\"",
451 char id[20] = {
'\0' };
452 char filename[FILENAME_MAX + 1];
456 dp = opendir(LIRC_LOCKDIR);
458 while ((ep = readdir(dp))) {
459 if (strcmp(ep->d_name,
".") == 0 || strcmp(ep->d_name,
"..") == 0) {
463 strcpy(filename, LIRC_LOCKDIR
"/");
464 if (strlen(filename) + strlen(ep->d_name) > FILENAME_MAX) {
468 strcat(filename, ep->d_name);
469 if (strstr(filename,
"LCK..") == NULL) {
470 log_debug(
"Ignoring non-LCK.. logfile %s",
475 lock = open(filename, O_RDONLY);
480 len = read(lock,
id,
sizeof(
id) - 1);
486 pid = strtol(
id, NULL, 10);
487 if (pid == LONG_MIN || pid == LONG_MAX || pid == 0) {
488 log_debug(
"Can't parse lockfile %s (ignored)",
493 if (pid == getpid()) {
494 if (unlink(filename) == -1) {
496 "could not delete file \"%s\"",
505 log_error(
"could not open directory \"" LIRC_LOCKDIR
"\"");
515 mask = rts ? TIOCM_RTS : 0;
516 mask |= dtr ? TIOCM_DTR : 0;
517 if (ioctl(fd, TIOCMBIS, &mask) == -1) {
529 mask = rts ? TIOCM_RTS : 0;
530 mask |= dtr ? TIOCM_DTR : 0;
531 if (ioctl(fd, TIOCMBIC, &mask) == -1) {
533 log_trace(
"tty_clear(): ioctl() failed");
541 if (write(fd, &byte, 1) != 1) {
542 log_trace(
"tty_write(): write() failed");
559 struct pollfd pfd = {.fd = fd, .events = POLLIN, .revents = 0};
562 ret = curl_poll(&pfd, 1, 1000);
566 }
else if (ret != 1) {
570 if (read(fd, byte, 1) != 1) {
585 log_trace(
"sent: A%u D%01x reply: A%u D%01x", (((
unsigned int)(
unsigned char)byte) & 0xf0) >> 4,
586 ((
unsigned int)(
unsigned char)byte) & 0x0f, (((
unsigned int)(
unsigned char)reply) & 0xf0) >> 4,
587 ((
unsigned int)(
unsigned char)reply) & 0x0f);
int tty_setrtscts(int fd, int enable)
Set/clear CTS control line.
#define log_debug(fmt,...)
Log a debug message.
#define log_perror_debug(fmt,...)
perror wrapper logging with level LIRC_DEBUG.
int tty_setdtr(int fd, int enable)
Set/clear DTR control line.
int tty_delete_lock(void)
Delete any legacy lock(s) owned by this process.
#define log_warn(fmt,...)
Log a warning message.
logchannel_t
Log channels used to filter messages.
int tty_reset(int fd)
Set the cfmakeraw termio options.
int tty_create_lock(const char *name)
Creates a lock file of the type /var/local/LCK.
#define log_error(fmt,...)
Log an error message.
int tty_write(int fd, char byte)
Write a single byte to serial device.
int tty_clear(int fd, int rts, int dtr)
Clear RTS and DTR control lines.
int tty_setcsize(int fd, int csize)
Set the character size.
#define log_trace(fmt,...)
Log a trace message.
#define log_perror_err(fmt,...)
perror wrapper logging with level LIRC_ERROR.
int tty_write_echo(int fd, char byte)
Write a single byte and check the echo from remote party.
int tty_read(int fd, char *byte)
Read a single byte from serial device.
int tty_setbaud(int fd, int baud)
Set the speed a.
#define log_perror_warn(fmt,...)
perror wrapper logging with level LIRC_WARNING.
int tty_set(int fd, int rts, int dtr)
Set RTS and DTR control lines.