Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/vt/vt_accessibility.c
- This file was added.
/*- | |||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD | |||||
* | |||||
* Copyright (c) 2022 Hans Petter Selasky | |||||
* | |||||
* 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. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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/param.h> | |||||
#include <sys/systm.h> | |||||
#include <sys/kernel.h> | |||||
#include <sys/lock.h> | |||||
#include <sys/sx.h> | |||||
#include <sys/malloc.h> | |||||
#include <sys/mutex.h> | |||||
#include <sys/reboot.h> | |||||
#include <sys/devctl.h> | |||||
#include <dev/vt/vt.h> | |||||
static SYSCTL_NODE(_kern_vt, OID_AUTO, accessibility, | |||||
CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "Accessibility parameters"); | |||||
static int vt_access_enable(SYSCTL_HANDLER_ARGS); | |||||
static unsigned int vt_access_enabled; /* default is disabled */ | |||||
static struct sx vt_access_sx; | |||||
static struct callout vt_access_callout; | |||||
SX_SYSINIT(vt_access_sx, &vt_access_sx, "VT accessibility"); | |||||
#define VT_ACCESS_LOCK() sx_xlock(&vt_access_sx) | |||||
#define VT_ACCESS_UNLOCK() sx_xunlock(&vt_access_sx) | |||||
static unsigned vt_lines_per_interval = 1; /* default value */ | |||||
SYSCTL_UINT(_kern_vt_accessibility, OID_AUTO, lines_per_interval, CTLFLAG_RWTUN, | |||||
&vt_lines_per_interval, 0, "Number of lines the VT accessibility module will feed per interval, between 1 and 1000"); | |||||
static unsigned vt_interval_ms = 1000; /* default value */ | |||||
SYSCTL_UINT(_kern_vt_accessibility, OID_AUTO, interval_ms, CTLFLAG_RWTUN, | |||||
&vt_interval_ms, 0, "Interval between accessibility requests in milliseconds, between 10ms and 60000ms"); | |||||
SYSCTL_PROC(_kern_vt_accessibility, OID_AUTO, enable, | |||||
CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, &vt_access_enabled, | |||||
0, vt_access_enable, "IU", "Set if VT accessibility is enabled"); | |||||
static void | |||||
vt_access_worker_callout(void *arg) | |||||
{ | |||||
char buffer[512]; /* XXX the devctl buffer is not so big */ | |||||
unsigned max_ln; | |||||
unsigned max_iv; | |||||
size_t len; | |||||
max_ln = vt_lines_per_interval; | |||||
if (max_ln < 1) | |||||
max_ln = 1; | |||||
else if (max_ln > 1000) | |||||
max_ln = 1000; | |||||
max_iv = vt_interval_ms; | |||||
if (max_iv < 10) | |||||
max_iv = 10; | |||||
else if (max_iv > 60000) | |||||
max_iv = 60000; | |||||
if (devctl_queue_empty()) { | |||||
snprintf(buffer, sizeof(buffer) - 2, "text=\""); | |||||
imp: please construct the messages using sbuf. | |||||
hselaskyAuthorUnsubmitted Done Inline ActionsSure, but devd has its limits on the message size including headers (1Kbyte I think) hselasky: Sure, but devd has its limits on the message size including headers (1Kbyte I think) | |||||
len = strlen(buffer); | |||||
vtbuf_extract_accessibility(buffer + len, max_ln, sizeof(buffer) - 2 - len); | |||||
len = strlen(buffer); | |||||
/* Check if the buffer was filled */ | |||||
if (buffer[len - 1] != '"') { | |||||
buffer[len++] = '"'; | |||||
buffer[len++] = 0; | |||||
MPASS(len <= sizeof(buffer)); | |||||
devctl_notify("VT", "ACCESSIBILITY", "SPEAK", buffer); | |||||
} | |||||
} | |||||
/* Restart timer. */ | |||||
if (vt_access_enabled != 0) | |||||
callout_reset(&vt_access_callout, (max_iv * hz) / 1000, &vt_access_worker_callout, arg); | |||||
} | |||||
static void | |||||
vt_access_start(void) | |||||
{ | |||||
callout_init(&vt_access_callout, 1); | |||||
/* kick the callout */ | |||||
vt_access_worker_callout(NULL); | |||||
} | |||||
static void | |||||
vt_access_stop(void) | |||||
{ | |||||
callout_drain(&vt_access_callout); | |||||
} | |||||
static int | |||||
vt_access_enable(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
unsigned val; | |||||
int error; | |||||
VT_ACCESS_LOCK(); | |||||
/* Copy current value as required */ | |||||
val = *(unsigned *)arg1; | |||||
error = SYSCTL_OUT(req, &val, sizeof(unsigned)); | |||||
if (error || !req->newptr) | |||||
goto done; | |||||
error = SYSCTL_IN(req, &val, sizeof(unsigned)); | |||||
if (error) | |||||
goto done; | |||||
/* Range check input value */ | |||||
val = (val != 0) ? 1 : 0; | |||||
if (*(unsigned *)arg1 != val) { | |||||
*(unsigned *)arg1 = val; | |||||
if (val) | |||||
vt_access_start(); | |||||
else | |||||
vt_access_stop(); | |||||
} | |||||
done: | |||||
VT_ACCESS_UNLOCK(); | |||||
return (error); | |||||
} |
please construct the messages using sbuf.