1/* $NetBSD: wskbd.c,v 1.5 2021/01/31 22:45:47 rillig Exp $ */ 2 3/*- 4 * Copyright (c) 2003 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by David Laight. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__RCSID("$NetBSD: wskbd.c,v 1.5 2021/01/31 22:45:47 rillig Exp $"); 34 35#include <unistd.h> 36#include <stdlib.h> 37#include <fcntl.h> 38#include <sys/ioctl.h> 39#include <dev/wscons/wsconsio.h> 40#include <dev/wscons/wsksymdef.h> 41 42#include "defs.h" 43#include "menu_defs.h" 44#include "msg_defs.h" 45void save_kb_encoding(void); 46 47/* wscons setup for sysinst */ 48 49static const char *kbd_name = 0; 50static int kb_default = 0; 51 52struct kb_types { 53 kbd_t kb_encoding; 54 const char *kb_enc_txt; 55 const char *kb_name; 56}; 57 58/* Types and names of keyboards, maybe the names should be translated... */ 59static const struct kb_types kb_types[] = { 60#define KB_sysinst(tag, tagf, value, cc, ccf, country) \ 61 {tag | tagf, cc ccf, country}, 62KB_ENC_FUN(KB_sysinst) 63{KB_US | KB_COLEMAK, "us" ".colemak", "US-Colemak"}, 64{KB_US | KB_DVORAK, "us" ".dvorak", "US-Dvorak"} 65}; 66 67static int 68set_kb_encoding(menudesc *m, void *arg) 69{ 70 int fd = *(int *)arg; 71 const struct kb_types *kbt = kb_types + m->cursel; 72 73 if (kbt->kb_encoding != KB_USER) { 74 ioctl(fd, WSKBDIO_SETENCODING, &kbt->kb_encoding); 75 kbd_name = kbt->kb_enc_txt; 76 } 77 return 1; 78} 79 80static void 81set_kb_default(menudesc *m, void *arg) 82{ 83 m->cursel = kb_default; 84} 85 86void 87get_kb_encoding(void) 88{ 89 int fd; 90 unsigned int i; 91 int kb_menu; 92 kbd_t kbdencoding; 93 menu_ent opt[__arraycount(kb_types)]; 94 const char *dflt = msg_string(MSG_kb_default); 95 96 /* 97 * Check if we are running on a wscons keyboard at all, 98 * do not bother to try changing the layout if not. 99 */ 100 if (ioctl(0, WSKBDIO_GTYPE, &i) == -1) 101 return; 102 103 memset(opt, 0, sizeof(opt)); 104 fd = open("/dev/wskbd0", O_WRONLY); 105 if (fd < 0) 106 return; 107 if (ioctl(fd, WSKBDIO_GETENCODING, &kbdencoding) >= 0) { 108 memset(&opt, 0, sizeof opt); 109 for (i = 0; i < __arraycount(opt); i++) { 110 if (kb_types[i].kb_encoding == KB_USER) 111 opt[0].opt_name = MSG_unchanged; 112 else { 113 opt[i].opt_name = kb_types[i].kb_name; 114 if (strcmp(kb_types[i].kb_name, dflt) == 0) 115 kb_default = i; 116 } 117 opt[i].opt_action = set_kb_encoding; 118 } 119 kb_menu = new_menu(MSG_Keyboard_type, opt, __arraycount(opt), 120 -1, -8, 0, 0, 121 MC_SCROLL | MC_NOEXITOPT, 122 set_kb_default, NULL, NULL, NULL, NULL); 123 if (kb_menu != -1) { 124 msg_display(MSG_hello); 125 process_menu(kb_menu, &fd); 126 free_menu(kb_menu); 127 } 128 } 129 close(fd); 130} 131 132void 133save_kb_encoding(void) 134{ 135 const char *tp = target_prefix(); 136 137 if (kbd_name == NULL) 138 return; 139 /* 140 * Put the keyboard encoding into the wscons.conf file. Either: 141 * 1) replace an existing line 142 * 2) replace a commented out line 143 * or 144 * 3) add a line to the end of the file 145 */ 146 run_program(0, "sed -an -e 'H;$!d;g'" 147 " -e 's/\\nencoding [a-zA-Z0-9.]*\\n/\\\nencoding %s\\\n/; t done'" 148 " -e 's/\\n#encoding [a-zA-Z0-9.]*\\n/\\\nencoding %s\\\n/; t done'" 149 " -e 's/$/\\\nencoding %s/'" 150 " -e ':done'" 151 " -e 'w %s/etc/wscons.conf' %s/etc/wscons.conf", 152 kbd_name, kbd_name, kbd_name, tp, tp); 153} 154