/*
* Copyright (c) 2002, 2003, 2004 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Julio M. Merino Vidal.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. The name authors may not be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 2002, 2003\
The NetBSD Foundation, Inc. All rights reserved.");
__RCSID("$NetBSD: wsmoused.c,v 1.29 2022/05/20 21:31:24 andvar Exp $");
#endif /* not lint */
/* Logs the given error message to syslog if running in daemon mode, or
* to the console if running in the foreground. */
void
log_err(int e, const char *fmt, ...)
{
va_list ap;
/* Logs the given error message to syslog if running in daemon mode, or
* to the console if running in the foreground. */
void
log_errx(int e, const char *fmt, ...)
{
va_list ap;
/* Logs the given info message to syslog if running in daemon mode, or
* to the console if running in the foreground. */
void
log_info(const char *fmt, ...)
{
va_list ap;
/* Logs the given warning message to syslog if running in daemon mode, or
* to the console if running in the foreground. */
void
log_warn(const char *fmt, ...)
{
va_list ap;
/* Logs the given warning message to syslog if running in daemon mode, or
* to the console if running in the foreground. */
void
log_warnx(const char *fmt, ...)
{
va_list ap;
/* Opens the mouse device (if not already opened). The argument `secs'
* specifies how much seconds the function will wait before trying to
* open the device; this is used when returning from the X console. */
static void
open_device(unsigned int secs)
{
int status;
if (Mouse.m_devfd != -1)
return;
sleep(secs);
/* Open mouse file descriptor */
Mouse.m_devfd = open(Mouse.m_devname, O_RDONLY | O_NONBLOCK, 0);
if (Mouse.m_devfd == -1)
log_err(EXIT_FAILURE, "cannot open %s", Mouse.m_devname);
const int version = WSMOUSE_EVENT_VERSION;
status = ioctl(Mouse.m_devfd, WSMOUSEIO_SETVERSION, &version);
if (status == -1)
log_err(EXIT_FAILURE, "cannot set version %s", Mouse.m_devname);
/*
* Get calibration data for touch panel. Not fatal if we can't.
*/
Mouse.m_doabs = 0;
unsigned int mouse_type = 0; /* defined WSMOUSE_TYPE_* start at 1 */
status = ioctl(Mouse.m_devfd, WSMOUSEIO_GTYPE, &mouse_type);
if (status == -1) {
log_warn("WSMOUSEIO_GTYPE");
return;
}
/* absolute position events make no sense for free-ranging mice */
if (mouse_type != WSMOUSE_TYPE_TPANEL)
return;
status = ioctl(Mouse.m_devfd, WSMOUSEIO_GCALIBCOORDS, &Mouse.m_calib);
if (status == -1) {
log_warn("WSMOUSEIO_GCALIBCOORDS");
return;
}
/* Main program event loop. This function polls the wscons status
* device and the mouse device; whenever an event is received, the
* appropriate callback is fired for all attached modes. If the polls
* times out (which only happens when the mouse is disabled), another
* callback is launched. */
static void
event_loop(void)
{
int i, res;
struct pollfd fds[2];
struct wscons_event event;
for (;;) {
fds[1].fd = Mouse.m_devfd;
fds[1].events = POLLIN;
if (Mouse.m_disabled)
res = poll(fds, 1, INFTIM);
else
res = poll(fds, 2, 300);
if (res < 0)
log_warn("failed to read from devices");
if (fds[0].revents & POLLIN) {
res = read(Mouse.m_statfd, &event, sizeof(event));
if (debug)
(void)fprintf(stderr, "event [type=%u,value=%d,"
"time=[%lld,%ld]\n", event.type,
event.value, (long long)event.time.tv_sec,
(long)event.time.tv_nsec);
if (res != sizeof(event))
log_warn("failed to read from mouse stat");
for (i = 0; i < MAX_MODES && Modes[i] != NULL; i++)
if (Modes[i]->mb_wscons_event != NULL)
Modes[i]->mb_wscons_event(event, 1);
generic_wscons_event(event);
for (i = 0; i < MAX_MODES && Modes[i] != NULL; i++)
if (Modes[i]->mb_wscons_event != NULL)
Modes[i]->mb_wscons_event(event, 0);
} else if (fds[1].revents & POLLIN) {
res = read(Mouse.m_devfd, &event, sizeof(event));
if (res != sizeof(event))
log_warn("failed to read from mouse");
if (debug)
(void)fprintf(stderr, "event [type=%u,value=%d,"
"time=[%lld,%ld]\n", event.type,
event.value, (long long)event.time.tv_sec,
(long)event.time.tv_nsec);
if (Mouse.m_fifofd >= 0) {
res = write(Mouse.m_fifofd, &event,
sizeof(event));
if (res != sizeof(event))
log_warn("failed to write to fifo");
}
for (i = 0; i < MAX_MODES && Modes[i] != NULL; i++)
if (Modes[i]->mb_wsmouse_event != NULL)
Modes[i]->mb_wsmouse_event(event);
} else {
for (i = 0; i < MAX_MODES && Modes[i] != NULL; i++)
if (Modes[i]->mb_poll_timeout != NULL)
Modes[i]->mb_poll_timeout();
}
}
}
/* This function parses generic wscons status events. Actually, it
* handles the screen switch event to enable or disable the mouse,
* depending if we are entering or leaving the X console. */
static void
generic_wscons_event(struct wscons_event evt)
{
/* Attaches a mode to the list of active modes, based on its name.
* Returns 1 on success or 0 if the mode fails to initialize or there is
* any other problem. */
static int
attach_mode(const char *name)
{
int i, pos;
struct mode_bootstrap *mb;
for (i = 0, pos = -1; i < MAX_MODES; i++)
if (Modes[i] == NULL) {
pos = i;
break;
}
if (pos == -1) {
log_warnx("modes table full; cannot register `%s'", name);
return 0;
}
for (i = 0; i < MAX_MODES; i++) {
mb = Avail_Modes[i];
if (mb != NULL && strcmp(name, mb->mb_name) == 0) {
int res;
res = mb->mb_startup(&Mouse);
if (res == 0) {
log_warnx("startup failed for `%s' mode",
mb->mb_name);
return 0;
} else {
Modes[pos] = mb;
return 1;
}
}
}
log_warnx("unknown mode `%s' (see the `modes' directive)", name);
return 0;
}
/* Attaches all modes given in the whitespace separated string `list'.
* A fatal error is produced if no active modes can be attached. */
static void
attach_modes(char *list)
{
char *last, *p;
int count;
/* Main program. Parses command line options, reads the configuration
* file, initializes the mouse and associated files and launches the main
* event loop. */
int
main(int argc, char **argv)
{
char *conffile, *modelist, *tstat;
int needconf, nodaemon, opt;
struct block *conf;