Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/ps2kbd.c
Context not available. | |||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/stat.h> | |||||
#include <machine/vmm_snapshot.h> | #include <machine/vmm_snapshot.h> | ||||
Context not available. | |||||
#include <strings.h> | #include <strings.h> | ||||
#include <pthread.h> | #include <pthread.h> | ||||
#include <pthread_np.h> | #include <pthread_np.h> | ||||
#include <unistd.h> | |||||
#include <fcntl.h> | |||||
#include "bhyverun.h" | |||||
#include "atkbdc.h" | #include "atkbdc.h" | ||||
#include "debug.h" | #include "debug.h" | ||||
#include "console.h" | #include "console.h" | ||||
Context not available. | |||||
#define PS2KBD_FIFOSZ 16 | #define PS2KBD_FIFOSZ 16 | ||||
#define PS2KBD_LAYOUT_BASEDIR "/usr/share/bhyve/kbdlayout/" | |||||
struct fifo { | struct fifo { | ||||
uint8_t buf[PS2KBD_FIFOSZ]; | uint8_t buf[PS2KBD_FIFOSZ]; | ||||
int rindex; /* index to read from */ | int rindex; /* index to read from */ | ||||
Context not available. | |||||
/* | /* | ||||
* FIXME: Pause/break and Print Screen/SysRq require special handling. | * FIXME: Pause/break and Print Screen/SysRq require special handling. | ||||
*/ | */ | ||||
static const struct extended_translation extended_translations[] = { | static struct extended_translation extended_translations[128] = { | ||||
{0xff08, 0x66}, /* Back space */ | {0xff08, 0x66}, /* Back space */ | ||||
{0xff09, 0x0d}, /* Tab */ | {0xff09, 0x0d}, /* Tab */ | ||||
{0xff0d, 0x5a}, /* Return */ | {0xff0d, 0x5a}, /* Return */ | ||||
Context not available. | |||||
}; | }; | ||||
/* ASCII to type 2 scancode lookup table */ | /* ASCII to type 2 scancode lookup table */ | ||||
static const uint8_t ascii_translations[128] = { | static uint8_t ascii_translations[128] = { | ||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
Context not available. | |||||
assert(pthread_mutex_isowned_np(&sc->mtx)); | assert(pthread_mutex_isowned_np(&sc->mtx)); | ||||
int e0_prefix, found; | int e0_prefix, found; | ||||
uint8_t code; | uint8_t code; | ||||
const struct extended_translation *trans; | struct extended_translation *trans; | ||||
if (keycode) { | if (keycode) { | ||||
code = keyset1to2_translations[(uint8_t)(keycode & 0x7f)]; | code = keyset1to2_translations[(uint8_t)(keycode & 0x7f)]; | ||||
Context not available. | |||||
atkbdc_event(sc->atkbdc_sc, 1); | atkbdc_event(sc->atkbdc_sc, 1); | ||||
} | } | ||||
static void | |||||
ps2kbd_update_extended_translation(uint32_t keycode, uint32_t scancode, uint32_t prefix) | |||||
{ | |||||
int i = 0; | |||||
do { | |||||
if (extended_translations[i].keysym == keycode) | |||||
break; | |||||
} while(extended_translations[++i].keysym); | |||||
if (i == (sizeof(extended_translations) / sizeof(struct extended_translation) - 1)) | |||||
return; | |||||
if (!extended_translations[i].keysym) { | |||||
extended_translations[i].keysym = keycode; | |||||
extended_translations[i+1].keysym = 0; | |||||
extended_translations[i+1].scancode = 0; | |||||
extended_translations[i+1].flags = 0; | |||||
} | |||||
extended_translations[i].scancode = (uint8_t)(scancode & 0xff); | |||||
extended_translations[i].flags = (prefix ? SCANCODE_E0_PREFIX : 0); | |||||
} | |||||
static void | |||||
ps2kbd_setkbdlayout(void) | |||||
{ | |||||
int err; | |||||
int fd; | |||||
char path[256]; | |||||
jhb: Use MAX_PATHNAME (or whatever the right constant is) | |||||
char *buf, *next, *line; | |||||
struct stat sb; | |||||
size_t sz; | |||||
uint8_t ascii; | |||||
uint32_t keycode, scancode, prefix; | |||||
strcpy(path, PS2KBD_LAYOUT_BASEDIR); | |||||
strncat(path, kbdlayout_name, (sizeof(path) - strlen(PS2KBD_LAYOUT_BASEDIR) - 1)); | |||||
jhbUnsubmitted Not Done Inline ActionsThis is probably simpler as a single call to snprintf(). strlcat would let you avoid the complicated length expression, but using snprintf() is even simpler. jhb: This is probably simpler as a single call to snprintf(). strlcat would let you avoid the… | |||||
err = stat(path, &sb); | |||||
if (err) | |||||
return; | |||||
buf = (char *)malloc(sizeof(char) * sb.st_size); | |||||
if (buf == NULL) | |||||
return; | |||||
fd = open(path, O_RDONLY); | |||||
if (fd == -1) | |||||
goto out; | |||||
sz = read(fd, buf, sb.st_size ); | |||||
close(fd); | |||||
if (sz != sb.st_size ) | |||||
goto out; | |||||
next = buf; | |||||
while ((line = strsep(&next, "\n")) != NULL) { | |||||
if (sscanf(line, "'%c',%x;", &ascii, &scancode) == 2) { | |||||
if (ascii < 0x80) | |||||
ascii_translations[ascii] = (uint8_t)(scancode & 0xff); | |||||
} else if (sscanf(line, "%x,%x,%x;", &keycode, &scancode, &prefix) == 3 ) { | |||||
ps2kbd_update_extended_translation(keycode, scancode, prefix); | |||||
} else if (sscanf(line, "%x,%x;", &keycode, &scancode) == 2) { | |||||
if (keycode < 0x80) | |||||
ascii_translations[(uint8_t)(keycode & 0xff)] = (uint8_t)(scancode & 0xff); | |||||
else | |||||
ps2kbd_update_extended_translation(keycode, scancode, 0); | |||||
} | |||||
} | |||||
out: | |||||
free(buf); | |||||
} | |||||
struct ps2kbd_softc * | struct ps2kbd_softc * | ||||
ps2kbd_init(struct atkbdc_softc *atkbdc_sc) | ps2kbd_init(struct atkbdc_softc *atkbdc_sc) | ||||
{ | { | ||||
struct ps2kbd_softc *sc; | struct ps2kbd_softc *sc; | ||||
if (kbdlayout_name != NULL) | |||||
ps2kbd_setkbdlayout(); | |||||
sc = calloc(1, sizeof (struct ps2kbd_softc)); | sc = calloc(1, sizeof (struct ps2kbd_softc)); | ||||
pthread_mutex_init(&sc->mtx, NULL); | pthread_mutex_init(&sc->mtx, NULL); | ||||
fifo_init(sc); | fifo_init(sc); | ||||
Context not available. |
Use MAX_PATHNAME (or whatever the right constant is)