xref: /openbsd/sys/dev/usb/makemap.awk (revision 097a140d)
1#! /usr/bin/awk -f
2#	$OpenBSD: makemap.awk,v 1.15 2020/11/02 19:45:18 tobhe Exp $
3#
4# Copyright (c) 2005, Miodrag Vallat
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18# DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25# POSSIBILITY OF SUCH DAMAGE.
26#
27#
28# This script attempts to convert, with minimal hacks and losses, the
29# regular PS/2 keyboard (pckbd) layout tables into USB keyboard (ukbd)
30# layout tables.
31#
32
33BEGIN {
34	rcsid = "$OpenBSD: makemap.awk,v 1.15 2020/11/02 19:45:18 tobhe Exp $"
35	ifdepth = 0
36	ignore = 0
37	declk = 0
38	haskeys = 0
39	kbfr = 0
40	nmaps = 0
41
42	# PS/2 id -> UKBD conversion table, or "sanity lossage 101"
43	for (i = 0; i < 256; i++)
44		conv[i] = -1
45
46	conv[1] = 41
47	conv[2] = 30
48	conv[3] = 31
49	conv[4] = 32
50	conv[5] = 33
51	conv[6] = 34
52	conv[7] = 35
53	conv[8] = 36
54	conv[9] = 37
55	conv[10] = 38
56	conv[11] = 39
57	conv[12] = 45
58	conv[13] = 46
59	conv[14] = 42
60	conv[15] = 43
61	conv[16] = 20
62	conv[17] = 26
63	conv[18] = 8
64	conv[19] = 21
65	conv[20] = 23
66	conv[21] = 28
67	conv[22] = 24
68	conv[23] = 12
69	conv[24] = 18
70	conv[25] = 19
71	conv[26] = 47
72	conv[27] = 48
73	conv[28] = 40
74	conv[29] = 224
75	conv[30] = 4
76	conv[31] = 22
77	conv[32] = 7
78	conv[33] = 9
79	conv[34] = 10
80	conv[35] = 11
81	conv[36] = 13
82	conv[37] = 14
83	conv[38] = 15
84	conv[39] = 51
85	conv[40] = 52
86	conv[41] = 53
87	conv[42] = 225
88	conv[43] = 50
89	conv[44] = 29
90	conv[45] = 27
91	conv[46] = 6
92	conv[47] = 25
93	conv[48] = 5
94	conv[49] = 17
95	conv[50] = 16
96	conv[51] = 54
97	conv[52] = 55
98	conv[53] = 56
99	conv[54] = 229
100	conv[55] = 85
101	conv[56] = 226
102	conv[57] = 44
103	conv[58] = 57
104	conv[59] = 58
105	conv[60] = 59
106	conv[61] = 60
107	conv[62] = 61
108	conv[63] = 62
109	conv[64] = 63
110	conv[65] = 64
111	conv[66] = 65
112	conv[67] = 66
113	conv[68] = 67
114	conv[69] = 83
115	conv[70] = 71
116	conv[71] = 95
117	conv[72] = 96
118	conv[73] = 97
119	conv[74] = 86
120	conv[75] = 92
121	conv[76] = 93
122	conv[77] = 94
123	conv[78] = 87
124	conv[79] = 89
125	conv[80] = 90
126	conv[81] = 91
127	conv[82] = 98
128	conv[83] = 99
129	conv[86] = 100
130	conv[87] = 68
131	conv[88] = 69
132	conv[91] = 104
133	conv[92] = 105
134	conv[93] = 106
135	conv[99] = 107
136	conv[100] = 108
137	conv[101] = 109
138	conv[102] = 110
139	conv[103] = 111
140	conv[104] = 112
141	conv[105] = 113
142	conv[106] = 114
143	conv[107] = 115
144	conv[112] = 136
145	conv[115] = 135
146	conv[121] = 138
147	conv[123] = 139
148	conv[125] = 137
149	conv[127] = 72
150	conv[156] = 88
151	conv[157] = 228
152	conv[160] = 127
153	conv[170] = 70
154	conv[174] = 129
155	conv[176] = 128
156	conv[181] = 84
157	conv[184] = 230
158	# 198 is #if 0 in the PS/2 map...
159	conv[199] = 74
160	conv[200] = 82
161	conv[201] = 75
162	conv[203] = 80
163	conv[205] = 79
164	conv[207] = 77
165	conv[208] = 81
166	conv[209] = 78
167	conv[210] = 73
168	conv[211] = 76
169	conv[219] = 227
170	conv[220] = 231
171	conv[221] = 101
172}
173NR == 1 {
174	VERSION = $0
175	gsub("\\$", "", VERSION)
176	gsub("\\$", "", rcsid)
177
178	printf("/*\t\$OpenBSD\$\t*/\n\n")
179	printf("/*\n")
180	printf(" * THIS FILE IS AUTOMAGICALLY GENERATED.  DO NOT EDIT.\n")
181	printf(" *\n")
182	printf(" * generated by:\n")
183	printf(" *\t%s\n", rcsid)
184	printf(" * generated from:\n")
185	printf(" */\n")
186	print VERSION
187
188	next
189}
190
191#
192# A very limited #if ... #endif parser. We only want to correctly detect
193# ``#if 0'' constructs, so as not to process their contents. This is necessary
194# since our output is out-of-order from our input.
195#
196# Note that this does NOT handle ``#ifdef notyet'' correctly - please only use
197# ``#if 0'' constructs in the input.
198#
199
200/^#if/ {
201	ignores[ifdepth] = ignore
202	if ($2 == "0")
203		ignore = 1
204	#else
205	#	ignore = 0
206	ifdepth++
207	if (ignore)
208		next
209}
210/^#endif/ {
211	oldignore = ignore
212	ifdepth--
213	ignore = ignores[ifdepth]
214	ignores[ifdepth] = 0
215	if (oldignore)
216		next
217}
218
219$1 == "#include" {
220	if (ignore)
221		next
222	if ($2 == "<dev/pckbc/wskbdmap_mfii.h>")
223		next
224	printf("#include %s\n", $2)
225	next
226}
227$1 == "#define" || $1 == "#undef" {
228	if (ignore)
229		next
230	print $0
231	next
232}
233
234# Don't bother converting the DEC LK layout.
235/declk\[/ {
236	declk = 1
237	next
238}
239/declk/ {
240	next
241}
242
243/pckbd/ {
244	gsub("pckbd", "ukbd", $0)
245	mapname = $4
246}
247
248/KC/ {
249	if (ignore)
250		next
251
252	if (declk)
253		next
254
255	haskeys = 1
256
257	sidx = substr($1, 4, length($1) - 5)
258	orig = int(sidx)
259	id = conv[orig]
260
261	# 183 is another Print Screen...
262	if (orig == 183)
263		next
264
265	if (id == -1) {
266		printf("/* initially KC(%d),", orig)
267		for (f = 2; f <= NF; f++) {
268			if ($f != "/*" && $f != "*/")
269				printf("\t%s", $f)
270		}
271		printf("\t*/\n")
272	} else {
273		lines[id] = sprintf("    KC(%d),\t", id)
274		#
275		# This makes sure that the non-comment part of the output
276		# ends up with a trailing comma. This is necessary since
277		# the last line of an input block might not have a trailing
278		# comma, but might not be the last line of an output block
279		# due to sorting.
280		#
281		comma = 0
282		for (f = 2; f <= NF; f++) {
283			l = length($f)
284			if ($f == "/*")
285				comma++
286			if (comma == 0 && substr($f, l) != ",") {
287				lines[id] = sprintf("%s%s,", lines[id], $f)
288				l++
289			} else {
290				lines[id] = sprintf("%s%s", lines[id], $f)
291			}
292			if (comma == 0 && f != NF) {
293				if (l < 2 * 8)
294					lines[id] = lines[id] "\t"
295				if (l < 8)
296					lines[id] = lines[id] "\t"
297			}
298			if ($f == "*/")
299				comma--
300		}
301	}
302
303	next
304}
305/};/ {
306	if (ignore)
307		next
308
309	if (declk) {
310		declk = 0
311		next
312	}
313
314	if (haskeys) {
315		# Duplicate 42 (backspace) as 76 and 50 (backslash bar) as 49
316		if (!lines[76]) {
317			lines[76] = lines[42]
318			sub("42", "76", lines[76])
319		}
320		if (!lines[49]) {
321			lines[49] = lines[50]
322			sub("50", "49", lines[49])
323		}
324
325		#
326		# Several USB keyboards have extra keys do not appear in
327		# the traditional PS/2 maps. We add them here, except for
328		# the Sun keyboard Compose key (101) which conflicts with
329		# the ``menu'' key.
330		#
331		if (nmaps++ == 0) {
332			# 102 Suspend
333			lines[116] = "    KC(116),\tKS_Open,"
334			lines[117] = "    KC(117),\tKS_Help,"
335			lines[118] = "    KC(118),\tKS_Props,"
336			lines[119] = "    KC(119),\tKS_Front,"
337			lines[120] = "    KC(120),\tKS_Cmd,"
338			lines[121] = "    KC(121),\tKS_Again,"
339			lines[122] = "    KC(122),\tKS_Undo,"
340			lines[123] = "    KC(123),\tKS_Cut,"
341			lines[124] = "    KC(124),\tKS_Copy,"
342			lines[125] = "    KC(125),\tKS_Paste,"
343			lines[126] = "    KC(126),\tKS_Find,"
344			lines[232] = "    KC(232),\tKS_Cmd_BrightnessUp,"
345			lines[233] = "    KC(233),\tKS_Cmd_BrightnessDown,"
346		}
347
348		for (i = 0; i < 256; i++)
349			if (lines[i]) {
350				print lines[i]
351				lines[i] = ""
352			}
353
354		haskeys = 0
355
356		#
357		# Apple black USB keyboards use a slightly different
358		# layout. We define them here.
359		#
360		if (mapname == "ukbd_keydesc_fr[]") {
361			print $0
362			print "\nstatic const keysym_t ukbd_keydesc_fr_apple[] = {"
363			print "    KC(5),\tKS_b,\t\tKS_B,\t\tKS_ssharp,"
364			print "    KC(8),\tKS_e,\t\tKS_E,\t\tKS_ecircumflex,\tKS_Ecircumflex,"
365			print "    KC(11),\tKS_h,\t\tKS_H,\t\tKS_Igrave,\tKS_Icircumflex,"
366			print "    KC(12),\tKS_i,\t\tKS_I,\t\tKS_icircumflex,\tKS_idiaeresis,"
367			print "    KC(13),\tKS_j,\t\tKS_J,\t\tKS_Idiaeresis,\tKS_Iacute,"
368			print "    KC(14),\tKS_k,\t\tKS_K,\t\tKS_Egrave,\tKS_Ediaeresis,"
369			print "    KC(15),\tKS_l,\t\tKS_L,\t\tKS_voidSymbol,\tKS_bar,"
370			print "    KC(16),\tKS_comma,\tKS_question,\tKS_voidSymbol,\tKS_questiondown,"
371			print "    KC(17),\tKS_n,\t\tKS_N,\t\tKS_asciitilde,"
372			print "    KC(20),\tKS_a,\t\tKS_A,\t\tKS_ae,\t\tKS_AE,"
373			print "    KC(21),\tKS_r,\t\tKS_R,\t\tKS_registered,\tKS_comma,"
374			print "    KC(22),\tKS_s,\t\tKS_S,\t\tKS_Ograve,"
375			print "    KC(26),\tKS_z,\t\tKS_Z,\t\tKS_Acircumflex,\tKS_Aring,"
376			print "    KC(28),\tKS_y,\t\tKS_Y,\t\tKS_Uacute,"
377			print "    KC(31),\tKS_eacute,\tKS_2,\t\tKS_ediaeresis,"
378			print "    KC(32),\tKS_quotedbl,\tKS_3,"
379			print "    KC(33),\tKS_apostrophe,\tKS_4,"
380			print "    KC(34),\tKS_parenleft,\tKS_5,\t\tKS_braceleft,\tKS_bracketleft,"
381			print "    KC(35),\tKS_section,\tKS_6,"
382			print "    KC(36),\tKS_egrave,\tKS_7,\t\tKS_guillemotleft,"
383			print "\t\t\t\t\t\tKS_guillemotright,"
384			print "    KC(37),\tKS_exclam,\tKS_8,"
385			print "    KC(38),\tKS_ccedilla,\tKS_9,\t\tKS_Ccedilla,\tKS_Aacute,"
386			print "    KC(37),\tKS_exclam,\tKS_8,\t\tKS_exclamdown,\tKS_Ucircumflex,"
387			print "    KC(39),\tKS_agrave,\tKS_0,\t\tKS_oslash,\tKS_Ooblique,"
388			print "    KC(45),\tKS_parenright,\tKS_degree,\tKS_braceright,\tKS_bracketright,"
389			print "    KC(46),\tKS_minus,\tKS_underscore,"
390			print "    KC(47),\tKS_dead_circumflex, KS_dead_diaeresis,"
391			print "\t\t\t\t\t\tKS_ocircumflex,\tKS_Ocircumflex,"
392			print "    KC(48),\tKS_dollar,\tKS_asterisk,\tKS_cent,\tKS_yen,"
393			print "    KC(50),\tKS_grave,\tKS_sterling,\tKS_at,\t\tKS_numbersign,"
394			print "    KC(51),\tKS_m,\t\tKS_M,\t\tKS_mu,\t\tKS_Oacute,"
395			print "    KC(52),\tKS_ugrave,\tKS_percent,\tKS_Ugrave,"
396			print "    KC(53),\tKS_at,\t\tKS_numbersign,"
397			print "    KC(55),\tKS_colon,\tKS_slash,\tKS_voidSymbol,\tKS_backslash,"
398			print "    KC(56),\tKS_equal,\tKS_plus,"
399			print "    KC(103),\tKS_KP_Equal,"
400			print "    KC(231),\tKS_Mode_switch,\tKS_Multi_key,"
401		} else
402		if (mapname == "ukbd_keydesc_pt[]") {
403			print $0
404			print "\nstatic const keysym_t ukbd_keydesc_pt_apple[] = {"
405			print "/*  pos\t\tnormal\t\tshifted */"
406			print "    KC(46),\tKS_plus,\tKS_asterisk,"
407			print "    KC(47),\tKS_masculine,\tKS_ordfeminine,"
408			print "    KC(50),\tKS_backslash,\tKS_bar,"
409			print "    KC(52),\tKS_dead_tilde,\tKS_dead_circumflex"
410		}
411	}
412}
413/KB_FR/ {
414	print $0
415	kbfr++
416	# Add .apple variants, but not to the fr.dvorak variants
417	if (kbfr == 1) {
418		print "\tKBD_MAP(KB_FR | KB_APPLE,\tKB_FR,\tukbd_keydesc_fr_apple),"
419	} else if (kbfr == 3) {
420		print "\tKBD_MAP(KB_FR | KB_APPLE | KB_SWAPCTRLCAPS,\tKB_FR | KB_APPLE,"
421		print "\t\tukbd_keydesc_swapctrlcaps),"
422	}
423	next
424}
425/KB_PT/ {
426	print $0
427	print "\tKBD_MAP(KB_PT | KB_APPLE,\tKB_PT,\tukbd_keydesc_pt_apple),"
428	next
429}
430{
431	if (ignore)
432		next
433	if (declk)
434		next
435	print $0
436}
437