xref: /openbsd/sys/dev/usb/makemap.awk (revision 404b540a)
1#! /usr/bin/awk -f
2#	$OpenBSD: makemap.awk,v 1.10 2009/01/11 16:54:53 miod 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.10 2009/01/11 16:54:53 miod 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] = 90M
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[112] = 135
133	conv[115] = 136
134	conv[121] = 137
135	conv[123] = 138
136	conv[125] = 139
137	conv[127] = 72
138	conv[156] = 88
139	conv[157] = 228
140	conv[160] = 127
141	conv[170] = 70
142	conv[174] = 129
143	conv[176] = 128
144	conv[181] = 84
145	conv[184] = 230
146	# 198 is #if 0 in the PS/2 map...
147	conv[199] = 74
148	conv[200] = 82
149	conv[201] = 75
150	conv[203] = 80
151	conv[205] = 79
152	conv[207] = 77
153	conv[208] = 81
154	conv[209] = 78
155	conv[210] = 73
156	conv[211] = 99
157	conv[219] = 227
158	conv[220] = 231
159	conv[221] = 101
160}
161NR == 1 {
162	VERSION = $0
163	gsub("\\$", "", VERSION)
164	gsub("\\$", "", rcsid)
165
166	printf("/*\t\$OpenBSD\$\t*/\n\n")
167	printf("/*\n")
168	printf(" * THIS FILE IS AUTOMAGICALLY GENERATED.  DO NOT EDIT.\n")
169	printf(" *\n")
170	printf(" * generated by:\n")
171	printf(" *\t%s\n", rcsid)
172	printf(" * generated from:\n")
173	printf(" */\n")
174	print VERSION
175
176	next
177}
178
179#
180# A very limited #if ... #endif parser. We only want to correctly detect
181# ``#if 0'' constructs, so as not to process their contents. This is necessary
182# since our output is out-of-order from our input.
183#
184# Note that this does NOT handle ``#ifdef notyet'' correctly - please only use
185# ``#if 0'' constructs in the input.
186#
187
188/^#if/ {
189	ignores[ifdepth] = ignore
190	if ($2 == "0")
191		ignore = 1
192	else
193		ignore = 0
194	ifdepth++
195	if (ignore)
196		next
197}
198/^#endif/ {
199	oldignore = ignore
200	ifdepth--
201	ignore = ignores[ifdepth]
202	ignores[ifdepth] = 0
203	if (oldignore)
204		next
205}
206
207$1 == "#include" {
208	if (ignore)
209		next
210	if ($2 == "<dev/pckbc/wskbdmap_mfii.h>")
211		next
212	printf("#include %s\n", $2)
213	next
214}
215$1 == "#define" || $1 == "#undef" {
216	if (ignore)
217		next
218	print $0
219	next
220}
221
222# Don't bother converting the DEC LK layout.
223/declk\[/ {
224	declk = 1
225	next
226}
227/declk/ {
228	next
229}
230
231/pckbd/ {
232	gsub("pckbd", "ukbd", $0)
233	mapname = $4
234}
235
236/KC/ {
237	if (ignore)
238		next
239
240	if (declk)
241		next
242
243	haskeys = 1
244
245	sidx = substr($1, 4, length($1) - 5)
246	orig = int(sidx)
247	id = conv[orig]
248
249	# 183 is another Print Screen...
250	if (orig == 183)
251		next
252
253	if (id == -1) {
254		printf("/* initially KC(%d),", orig)
255		for (f = 2; f <= NF; f++) {
256			if ($f != "/*" && $f != "*/")
257				printf("\t%s", $f)
258		}
259		printf("\t*/\n")
260	} else {
261		lines[id] = sprintf("    KC(%d),\t", id)
262		#
263		# This makes sure that the non-comment part of the output
264		# ends up with a trailing comma. This is necessary since
265		# the last line of an input block might not have a trailing
266		# comma, but might not be the last line of an output block
267		# due to sorting.
268		#
269		comma = 0
270		for (f = 2; f <= NF; f++) {
271			l = length($f)
272			if ($f == "/*")
273				comma++
274			if (comma == 0 && substr($f, l) != ",") {
275				lines[id] = sprintf("%s%s,", lines[id], $f)
276				l++
277			} else {
278				lines[id] = sprintf("%s%s", lines[id], $f)
279			}
280			if (comma == 0 && f != NF) {
281				if (l < 2 * 8)
282					lines[id] = lines[id] "\t"
283				if (l < 8)
284					lines[id] = lines[id] "\t"
285			}
286			if ($f == "*/")
287				comma--
288		}
289	}
290
291	next
292}
293/};/ {
294	if (ignore)
295		next
296
297	if (declk) {
298		declk = 0
299		next
300	}
301
302	if (haskeys) {
303		# Duplicate 42 (backspace) as 76 and 50 (backslash bar) as 49
304		if (!lines[76]) {
305			lines[76] = lines[42]
306			sub("42", "76", lines[76])
307		}
308		if (!lines[49]) {
309			lines[49] = lines[50]
310			sub("50", "49", lines[49])
311		}
312
313		#
314		# Sun USB keyboards extra keys do not appear in the PS/2
315		# maps. We add them here, except for the Compose key (101)
316		# which conflicts with the ``menu'' key.
317		#
318		if (nmaps++ == 0) {
319			# 102 Suspend
320			lines[116] = "    KC(116),\tKS_Open,"
321			lines[117] = "    KC(117),\tKS_Help,"
322			lines[118] = "    KC(118),\tKS_Props,"
323			lines[119] = "    KC(119),\tKS_Front,"
324			lines[120] = "    KC(120),\tKS_Cmd,"
325			lines[121] = "    KC(121),\tKS_Again,"
326			lines[122] = "    KC(122),\tKS_Undo,"
327			lines[123] = "    KC(123),\tKS_Cut,"
328			lines[124] = "    KC(124),\tKS_Copy,"
329			lines[125] = "    KC(125),\tKS_Paste,"
330			lines[126] = "    KC(126),\tKS_Find,"
331		}
332
333		for (i = 0; i < 256; i++)
334			if (lines[i]) {
335				print lines[i]
336				lines[i] = ""
337			}
338
339		haskeys = 0
340
341		#
342		# Apple black USB keyboards use a slightly different
343		# layout. We define them here.
344		#
345		if (mapname == "ukbd_keydesc_fr[]") {
346			print $0
347			print "\nstatic const keysym_t ukbd_keydesc_fr_apple[] = {"
348			print "    KC(5),\tKS_b,\t\tKS_B,\t\tKS_ssharp,"
349			print "    KC(8),\tKS_e,\t\tKS_E,\t\tKS_ecircumflex,\tKS_Ecircumflex,"
350			print "    KC(11),\tKS_h,\t\tKS_H,\t\tKS_Igrave,\tKS_Icircumflex,"
351			print "    KC(12),\tKS_i,\t\tKS_I,\t\tKS_icircumflex,\tKS_idiaeresis,"
352			print "    KC(13),\tKS_j,\t\tKS_J,\t\tKS_Idiaeresis,\tKS_Iacute,"
353			print "    KC(14),\tKS_k,\t\tKS_K,\t\tKS_Egrave,\tKS_Ediaeresis,"
354			print "    KC(15),\tKS_l,\t\tKS_L,\t\tKS_voidSymbol,\tKS_bar,"
355			print "    KC(16),\tKS_comma,\tKS_question,\tKS_voidSymbol,\tKS_questiondown,"
356			print "    KC(17),\tKS_n,\t\tKS_N,\t\tKS_asciitilde,"
357			print "    KC(20),\tKS_a,\t\tKS_A,\t\tKS_ae,\t\tKS_AE,"
358			print "    KC(21),\tKS_r,\t\tKS_R,\t\tKS_registered,\tKS_comma,"
359			print "    KC(22),\tKS_s,\t\tKS_S,\t\tKS_Ograve,"
360			print "    KC(26),\tKS_z,\t\tKS_Z,\t\tKS_Acircumflex,\tKS_Aring,"
361			print "    KC(28),\tKS_y,\t\tKS_Y,\t\tKS_Uacute,"
362			print "    KC(31),\tKS_eacute,\tKS_2,\t\tKS_ediaeresis,"
363			print "    KC(32),\tKS_quotedbl,\tKS_3,"
364			print "    KC(33),\tKS_apostrophe,\tKS_4,"
365			print "    KC(34),\tKS_parenleft,\tKS_5,\t\tKS_braceleft,\tKS_bracketleft,"
366			print "    KC(35),\tKS_section,\tKS_6,"
367			print "    KC(36),\tKS_egrave,\tKS_7,\t\tKS_guillemotleft,"
368			print "\t\t\t\t\t\tKS_guillemotright,"
369			print "    KC(37),\tKS_exclam,\tKS_8,"
370			print "    KC(38),\tKS_ccedilla,\tKS_9,\t\tKS_Ccedilla,\tKS_Aacute,"
371			print "    KC(37),\tKS_exclam,\tKS_8,\t\tKS_exclamdown,\tKS_Ucircumflex,"
372			print "    KC(39),\tKS_agrave,\tKS_0,\t\tKS_oslash,\tKS_Ooblique,"
373			print "    KC(45),\tKS_parenright,\tKS_degree,\tKS_braceright,\tKS_bracketright,"
374			print "    KC(46),\tKS_minus,\tKS_underscore,"
375			print "    KC(47),\tKS_dead_circumflex, KS_dead_diaeresis,"
376			print "\t\t\t\t\t\tKS_ocircumflex,\tKS_Ocircumflex,"
377			print "    KC(48),\tKS_dollar,\tKS_asterisk,\tKS_cent,\tKS_yen,"
378			print "    KC(50),\tKS_grave,\tKS_sterling,\tKS_at,\t\tKS_numbersign,"
379			print "    KC(51),\tKS_m,\t\tKS_M,\t\tKS_mu,\t\tKS_Oacute,"
380			print "    KC(52),\tKS_ugrave,\tKS_percent,\tKS_Ugrave,"
381			print "    KC(53),\tKS_at,\t\tKS_numbersign,"
382			print "    KC(55),\tKS_colon,\tKS_slash,\tKS_voidSymbol,\tKS_backslash,"
383			print "    KC(56),\tKS_equal,\tKS_plus,"
384			print "    KC(103),\tKS_KP_Equal,"
385			print "    KC(231),\tKS_Mode_switch,\tKS_Multi_key,"
386		} else
387		if (mapname == "ukbd_keydesc_pt[]") {
388			print $0
389			print "\nstatic const keysym_t ukbd_keydesc_pt_apple[] = {"
390			print "/*  pos\t\tnormal\t\tshifted */"
391			print "    KC(46),\tKS_plus,\tKS_asterisk,"
392			print "    KC(47),\tKS_masculine,\tKS_ordfeminine,"
393			print "    KC(50),\tKS_backslash,\tKS_bar,"
394			print "    KC(52),\tKS_dead_tilde,\tKS_dead_circumflex"
395		}
396	}
397}
398/KB_FR/ {
399	print $0
400	kbfr++
401	# Add .apple variants, but not to the fr.dvorak variants
402	if (kbfr == 1) {
403		print "\tKBD_MAP(KB_FR | KB_APPLE,\tKB_FR,\tukbd_keydesc_fr_apple),"
404	} else if (kbfr == 3) {
405		print "\tKBD_MAP(KB_FR | KB_APPLE | KB_SWAPCTRLCAPS,\tKB_FR | KB_APPLE,"
406		print "\t\tukbd_keydesc_swapctrlcaps),"
407	}
408	next
409}
410/KB_PT/ {
411	print $0
412	print "\tKBD_MAP(KB_PT | KB_APPLE,\tKB_PT,\tukbd_keydesc_pt_apple),"
413	next
414}
415{
416	if (ignore)
417		next
418	if (declk)
419		next
420	print $0
421}
422