mirror of https://github.com/nirenjan/libx52.git
Add client communication library
This change adds a library to connect to the X52 daemon and send commands and receive responses. The library is a thin wrapper around the POSIX sockets API. While a client could implement the functions themselves, the library makes it a little bit easier, as well as allowing for third-party clients to connect to and communicate with the daemon.reverse-scroll
parent
293ba0a99d
commit
18c0c72c74
|
@ -13,7 +13,7 @@ libx52test*
|
|||
libx52util/util_char_map.c
|
||||
udev/*.rules
|
||||
x52d*
|
||||
!daemon/x52d_*.*
|
||||
!daemon/x52d*.*
|
||||
test-*
|
||||
libx52-*.tar.gz
|
||||
|
||||
|
|
|
@ -861,6 +861,7 @@ FILE_PATTERNS = \
|
|||
libx52io.h \
|
||||
libx52util.h \
|
||||
x52_cli.c \
|
||||
x52dcomm.h \
|
||||
*.dox
|
||||
|
||||
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
||||
|
|
|
@ -46,6 +46,20 @@ x52d_LDFLAGS += @EVDEV_LIBS@
|
|||
x52d_LDADD += libx52io.la
|
||||
endif
|
||||
|
||||
lib_LTLIBRARIES += libx52dcomm.la
|
||||
|
||||
# Client library to communicate with X52 daemon
|
||||
libx52dcomm_la_SOURCES = \
|
||||
daemon/x52d_comm_client.c
|
||||
libx52dcomm_la_CFLAGS = \
|
||||
-I $(top_srcdir) \
|
||||
-DSYSCONFDIR=\"$(sysconfdir)\" \
|
||||
-DLOCALEDIR=\"$(localedir)\" \
|
||||
-DLOGDIR=\"$(localstatedir)/log\" \
|
||||
-DRUNDIR=\"$(localstatedir)/run\" \
|
||||
$(WARN_CFLAGS)
|
||||
libx52dcomm_la_LDFLAGS = $(WARN_LDFLAGS)
|
||||
|
||||
x52dconfdir = @sysconfdir@/x52d
|
||||
x52dconf_DATA = daemon/x52d.conf
|
||||
|
||||
|
@ -63,6 +77,7 @@ EXTRA_DIST += \
|
|||
daemon/x52d_device.h \
|
||||
daemon/x52d_io.h \
|
||||
daemon/x52d_mouse.h \
|
||||
daemon/x52dcomm.h \
|
||||
daemon/x52d.conf
|
||||
|
||||
if HAVE_SYSTEMD
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Saitek X52 Pro MFD & LED driver - Client communication library
|
||||
*
|
||||
* Copyright (C) 2021 Nirenjan Krishnan (nirenjan@nirenjan.org)
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "x52dcomm.h"
|
||||
#include "x52d_const.h"
|
||||
|
||||
int x52d_dial_command(const char *sock_path)
|
||||
{
|
||||
int sock;
|
||||
socklen_t len;
|
||||
struct sockaddr_un remote;
|
||||
int saved_errno;
|
||||
|
||||
if (sock_path == NULL) {
|
||||
sock_path = X52D_SOCK_COMMAND;
|
||||
}
|
||||
|
||||
len = strlen(sock_path);
|
||||
if (len >= sizeof(remote.sun_path)) {
|
||||
/* Socket path will not fit inside sun_path */
|
||||
errno = E2BIG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Create a socket */
|
||||
sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sock == -1) {
|
||||
/* Failure creating the socket, abort early */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Setup the sockaddr structure */
|
||||
memset(&remote, 0, sizeof(remote));
|
||||
remote.sun_family = AF_UNIX;
|
||||
/* We've already verified that sock_path will fit, so we don't need strncpy */
|
||||
strcpy(remote.sun_path, sock_path);
|
||||
len += sizeof(remote.sun_family);
|
||||
|
||||
/* Connect to the socket */
|
||||
if (connect(sock, (struct sockaddr *)&remote, len) == -1) {
|
||||
/* Failure connecting to the socket. Cleanup */
|
||||
saved_errno = errno;
|
||||
/* close may modify errno, so we save it prior to the call */
|
||||
close(sock);
|
||||
sock = -1;
|
||||
errno = saved_errno;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
int x52d_send_command(int sock_fd, char *buffer, size_t buflen)
|
||||
{
|
||||
int rc;
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
* Unix sockets should have sufficient capacity to send the full
|
||||
* datagram in a single message. Assume that is the case.
|
||||
*/
|
||||
rc = send(sock_fd, buffer, buflen, 0);
|
||||
if (rc < 0) {
|
||||
// Error
|
||||
if (errno == EINTR) {
|
||||
// System call interrupted due to signal. Try again
|
||||
continue;
|
||||
} else {
|
||||
// Failed. Return early
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Wait till we get a response */
|
||||
for (;;) {
|
||||
rc = recv(sock_fd, buffer, buflen, 0);
|
||||
if (rc < 0) {
|
||||
// Error
|
||||
if (errno == EINTR) {
|
||||
// System call interrupted due to signal. Try again
|
||||
continue;
|
||||
} else {
|
||||
// Failed. Return early
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
#define X52D_PID_FILE RUNDIR "/" X52D_APP_NAME ".pid"
|
||||
|
||||
#define X52D_SOCK_COMMAND RUNDIR "/" X52D_APP_NAME ".cmd"
|
||||
|
||||
#include "gettext.h"
|
||||
#define N_(x) gettext_noop(x)
|
||||
#define _(x) gettext(x)
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Saitek X52 Pro MFD & LED driver
|
||||
*
|
||||
* Copyright (C) 2021 Nirenjan Krishnan (nirenjan@nirenjan.org)
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file x52dcomm.h
|
||||
* @brief Functions, structures and enumerations for the Saitek X52 MFD & LED
|
||||
* daemon communication library.
|
||||
*
|
||||
* This file contains the type, enum and function prototypes for the Saitek X52
|
||||
* daemon communication library. These functions allow a client application to
|
||||
* communicate with a running X52 daemon, execute commands and retrieve data.
|
||||
*
|
||||
* @author Nirenjan Krishnan (nirenjan@nirenjan.org)
|
||||
*/
|
||||
#ifndef X52DCOMM_H
|
||||
#define X52DCOMM_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup x52dcomm Daemon communication
|
||||
*
|
||||
* These functions are used to communicate with the X52 daemon.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Open a connection to the daemon.
|
||||
*
|
||||
* This method opens a socket connection to the daemon command socket. This
|
||||
* socket allows the client to issue commands and retrieve data. The \p sock_path
|
||||
* parameter may be NULL, in which case, it will use the default socket path.
|
||||
*
|
||||
* The client will need to use the returned descriptor to communicate with the
|
||||
* daemon using \ref x52d_send_command. Once finished, the client may use the
|
||||
* \c close(2) method to close the file descriptor.
|
||||
*
|
||||
* @param[in] sock_path Path to the daemon command socket.
|
||||
*
|
||||
* @returns Non-negative socket file descriptor on success.
|
||||
* @returns -1 on failure, and set \c errno accordingly.
|
||||
*
|
||||
* @exception E2BIG returned if the passed socket path is too big
|
||||
*/
|
||||
int x52d_dial_command(const char *sock_path);
|
||||
|
||||
/**
|
||||
* @brief Send a command to the daemon and retrieve the response.
|
||||
*
|
||||
* The client sends the command and parameters as a single NULL terminated
|
||||
* string, and retrieves the response in the same manner. Depending on the
|
||||
* result, the return status is either a positive integer or -1, and \c errno
|
||||
* is set accordingly.
|
||||
*
|
||||
* \p buffer should contain sufficient space to accomodate the returned
|
||||
* response string.
|
||||
*
|
||||
* This is a blocking function and will not return until either a response is
|
||||
* received from the server, or an exception condition occurs.
|
||||
*
|
||||
* @param[in] sock_fd Socket descriptor returned from
|
||||
* \ref x52d_dial_command
|
||||
*
|
||||
* @param[inout] buffer Pointer to the string containing the command and
|
||||
* parameters. This is also used to save the returned
|
||||
* response.
|
||||
*
|
||||
* @param[in] buflen Length of the buffer to hold the returned response.
|
||||
*
|
||||
* @returns number of bytes returned from the server
|
||||
* @returns -1 on an error condition, and \c errno is set accordingly.
|
||||
*/
|
||||
int x52d_send_command(int sock_fd, char *buffer, size_t buflen);
|
||||
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // !defined X52DCOMM_H
|
||||
|
Loading…
Reference in New Issue