Remove some unnecessary braces and fix a gcc 3.4 warning.
[dragonfly.git] / usr.sbin / pcvt / kcon / kcon.c
1 /*
2  * Copyright (c) 1992,1993,1994 Hellmuth Michaelis
3  *
4  * Copyright (c) 1992,1993 Holger Veit.
5  *
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to 386BSD by
9  * Holger Veit
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *      This product includes software developed by
22  *      Hellmuth Michaelis and Holger Veit
23  * 4. The name authors may not be used to endorse or promote products
24  *    derived from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
27  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *
37  * $DragonFly: src/usr.sbin/pcvt/kcon/Attic/kcon.c,v 1.3 2005/02/28 17:31:22 swildner Exp $
38  */
39
40 static char *id =
41         "@(#)kcon.c, 3.20, Last Edit-Date: [Wed Jan 25 16:33:08 1995]";
42
43 /*---------------------------------------------------------------------------*
44  *
45  *      kcon.c          Keyboard control and remapping
46  *      ----------------------------------------------
47  *
48  *      based on "keymap" which was written by
49  *      Holger Veit (veit@du9ds3.uni-duisburg.de)
50  *
51  *      -hm     a first rewrite
52  *      -hm     rewrite for pcvt 2.0 distribution
53  *      -hm     adding show current typematic values
54  *      -hm     hex/octal/esc output choices
55  *      -hm     remapping debugging
56  *      -hm     garbage output for remapped keys bugfix
57  *      -hm     patch from Lon Willet, adding -R
58  *
59  *---------------------------------------------------------------------------*/
60
61 #include <sys/types.h>
62 #include <sys/ioctl.h>
63 #include <machine/pcvt_ioctl.h>
64
65 #include <stdio.h>
66 #include <string.h>
67
68 #include "keycap.h"
69
70 static void usage(void);
71 static void listcurrent(int);
72 static void setrepeat(int, int);
73 static void settypeam(int, int, int);
74 static void remapkeys(int, char *);
75 static void set_lock(char[], int);
76 static void set_shift(char[], int);
77 static void set_char(char[], int);
78
79 int Rf = 0;
80 int df = 0;
81 int lf = 0;
82 int mf = 0;
83 int of = 0;
84 int pf = 0;
85 int rf = 0;
86 int tf = 0;
87 int xf = 0;
88 int sf = 0;
89
90 /*---------------------------------------------------------------------------*
91  *      main entry
92  *---------------------------------------------------------------------------*/
93 int
94 main(int argc, char **argv)
95 {
96         extern char *optarg;
97         extern int optind;
98
99         int c = 0;
100
101         int errf = 0;
102
103         int rate = -1;
104         int delay = -1;
105         char *map;
106         int kbfd;
107
108         while((c = getopt(argc, argv, "Rd:lm:opr:st:x")) != -1)
109         {
110                 switch(c)
111                 {
112                         case 'R':
113                                 Rf = 1;
114                                 break;
115
116                         case 'd':
117                                 df = 1;
118                                 delay = atoi(optarg);
119                                 break;
120
121                         case 'l':
122                                 lf = 1;
123                                 break;
124
125                         case 'm':
126                                 mf = 1;
127                                 map = optarg;
128                                 break;
129
130                         case 'o':
131                                 if(xf)
132                                         errf = 1;
133                                 else
134                                         of = 1;
135                                 break;
136
137                         case 'p':
138                                 pf = 1;
139                                 break;
140
141                         case 'r':
142                                 rf = 1;
143                                 rate = atoi(optarg);
144                                 break;
145
146                         case 's':
147                                 sf = 1;
148                                 break;
149
150                         case 't':
151                                 if(*optarg == '+')
152                                         tf = 1;
153                                 else if(*optarg == '-')
154                                         tf = -1;
155                                 else
156                                         errf = 1;
157                                 break;
158
159                         case 'x':
160                                 if(of)
161                                         errf = 1;
162                                 else
163                                         xf = 1;
164                                 break;
165
166                         default:
167                                 usage();
168                 }
169         }
170
171         if((Rf == 0 && df == 0 && lf == 0 && tf == 0 && sf == 0 &&
172             rf == 0 && mf == 0 ) || errf)
173         {
174                 usage();
175         }
176
177         if((kbfd = open(KEYB_DEVICE, 0)) < 0)
178         {
179                 perror("kcon: keyboard open failiure");
180                 exit(1);
181         }
182
183         if(sf)
184         {
185                 showtypeamatic(kbfd);
186                 exit(0);
187         }
188
189         if(lf)
190         {
191                 listcurrent(kbfd);
192                 exit(0);
193         }
194
195         if (Rf)
196         {
197                 if (ioctl(kbfd, KBDRESET, 0) < 0) {
198                         perror ("kcon: ioctl KBDRESET failed");
199                         exit (1);
200                 }
201         }
202
203         if(tf)
204         {
205                 setrepeat(kbfd, tf);
206         }
207
208         if(df || rf)
209         {
210                 if(delay > 3)
211                 {
212                         fprintf(stderr,"Delay value (%d) out of range, possible values are 0..3!\n",delay);
213                         exit(1);
214                 }
215                 if(rate > 31)
216                 {
217                         fprintf(stderr,"Rate value (%d) out of range, possible values are 0..31!\n",rate);
218                         exit(1);
219                 }
220                 settypeam(kbfd, delay, rate);
221         }
222
223         if(mf)
224         {
225                 remapkeys(kbfd, map);
226         }
227
228         close(kbfd);
229         exit(0);
230 }
231
232 /*---------------------------------------------------------------------------*
233  *      display usage info & exit
234  *---------------------------------------------------------------------------*/
235 void
236 usage(void)
237 {
238         fprintf(stderr, "\nkcon: keyboard control and remapping utility for pcvt video driver\n");
239         fprintf(stderr, "usage: [-R] [-d delay] [-l] [-m map] [-o] [-p] [-r rate] [-t +/-] [-x]\n");
240         fprintf(stderr, "       -R   full reset of keyboard\n");
241         fprintf(stderr, "       -d   delay until a key is repeated (range: 0...3 => 250...1000ms)\n");
242         fprintf(stderr, "       -l   produce listing of current keyboard mapping\n");
243         fprintf(stderr, "       -m   set keyboard remapping from a keycap entry\n");
244         fprintf(stderr, "       -o   set octal output for listing\n");
245         fprintf(stderr, "       -p   pure, don't display escape as 'ESC' for listing\n");
246         fprintf(stderr, "       -r   chars/second repeat value (range: 0...31 => 30...2 chars/sec)\n");
247         fprintf(stderr, "       -s   show, display the current keyboard typematic values\n");
248         fprintf(stderr, "       -t   switch repeat on(+) or off(-)\n");
249         fprintf(stderr, "       -x   set hexadecimal output for listing\n\n");
250         exit(1);
251 }
252
253 /*---------------------------------------------------------------------------*
254  *      convert control char in string to printable values
255  *---------------------------------------------------------------------------*/
256 char *
257 showcntrl(u_char *s)
258 {
259         static char res_str[80];
260         static char conv_buf[80];
261         int i;
262
263         res_str[0] = '\0';
264
265         for(i = 0; s[i]; i++)
266         {
267                 if(((s[i] > 0x20) && (s[i] <= 0x7e)) || (s[i] >= 0xa0))
268                 {
269                         conv_buf[0] = s[i];
270                         conv_buf[1] = '\0';
271                 }
272                 else if((s[i] == 0x1b) && (pf == 0))
273                         strcpy(conv_buf,"ESC ");
274                 else if(of)
275                         sprintf(conv_buf,"\\%03.3o ", s[i]);
276                 else
277                         sprintf(conv_buf,"0x%02.2X ", s[i]);
278                 strcat(res_str, conv_buf);
279         }
280         return(res_str);
281 }
282
283 /*---------------------------------------------------------------------------*
284  *      list the current keyboard mapping
285  *---------------------------------------------------------------------------*/
286 void
287 listcurrent(int kbfd)
288 {
289         static char *keytypetab[] = {
290                 "NONE     ",
291                 "SHIFT    ",
292                 "ALT/META ",
293                 "NUMLOCK  ",
294                 "CONTROL  ",
295                 "CAPSLOCK ",
296                 "ASCII    ",
297                 "SCROLL   ",
298                 "FUNCTION ",
299                 "KEYPAD   ",
300                 "BREAK    ",
301                 "ALTGR    ",
302                 "SHIFTLOCK",
303                 "CURSOR   ",
304                 "RETURN   "
305         };
306
307         struct kbd_ovlkey keyboardmap[KBDMAXKEYS];
308         struct kbd_ovlkey *kbmapp;
309         int keytype;
310         int altgr_defined;
311         int i;
312
313         altgr_defined = 0;
314         kbmapp = keyboardmap;
315
316         for (i = 0; i < KBDMAXKEYS; i++)
317         {
318                 kbmapp->keynum = i;
319
320                 if(ioctl(kbfd, KBDGCKEY, kbmapp) < 0)
321                 {
322                         perror("kcon: ioctl KBDGCKEY failed");
323                         exit(1);
324                 }
325
326                 if((kbmapp->type & KBD_MASK) == KBD_ALTGR)
327                         altgr_defined = i;
328
329                 kbmapp++;
330         }
331
332         if(altgr_defined)
333         {
334                 printf("S Key KeyType   Normal          Shift           Control         Altgr          \n");
335                 printf("- --- --------- --------------- --------------- --------------- ---------------\n");
336         }
337         else
338         {
339                 printf("S Key KeyType   Normal          Shift           Control        \n");
340                 printf("- --- --------- --------------- --------------- ---------------\n");
341         }
342
343         kbmapp = &keyboardmap[1];
344
345         for(i = 1; i < KBDMAXKEYS; i++)
346         {
347                 keytype = kbmapp->type;
348
349                 if(keytype)
350                 {
351                         if(keytype & KBD_OVERLOAD)
352                                 printf("! %3.3d %9.9s ", i, keytypetab[keytype & KBD_MASK]);
353                         else
354                                 printf("- %3.3d %9.9s ", i, keytypetab[keytype & KBD_MASK]);
355
356                         switch(keytype & KBD_MASK)
357                         {
358
359                                 case KBD_NUM:
360                                 case KBD_ASCII:
361                                 case KBD_FUNC:
362                                 case KBD_KP:
363                                 case KBD_CURSOR:
364                                 case KBD_RETURN: /* ??? */
365
366                                         if(kbmapp->subu == KBD_SUBT_STR)
367                                                 printf("%-15s ",showcntrl(kbmapp->unshift));
368                                         else
369                                                 printf("Function()      ");
370
371                                         if(kbmapp->subs == KBD_SUBT_STR)
372                                                 printf("%-15s ",showcntrl(kbmapp->shift));
373                                         else
374                                                 printf("Function()      ");
375
376                                         if(kbmapp->subc == KBD_SUBT_STR)
377                                                 printf("%-15s ",showcntrl(kbmapp->ctrl));
378                                         else
379                                                 printf("Function()      ");
380
381                                         if(altgr_defined)
382                                         {
383                                                 if(kbmapp->suba == KBD_SUBT_STR)
384                                                         printf("%-15s ",showcntrl(kbmapp->altgr));
385                                                 else
386                                                         printf("Function()      ");
387                                         }
388                                         break;
389                         }
390                         putchar('\n');
391                 }
392                 kbmapp++;
393         }
394 }
395
396 /*---------------------------------------------------------------------------*
397  *      show delay and rate values for keyboard
398  *---------------------------------------------------------------------------*/
399 int
400 showtypeamatic(int kbfd)
401 {
402         static char *delaytab[] = {
403                 "250",
404                 "500",
405                 "750",
406                 "1000"
407         };
408
409         static char *ratetab[] = {
410                 "30.0",
411                 "26.7",
412                 "24.0",
413                 "21.8",
414                 "20.0",
415                 "18.5",
416                 "17.1",
417                 "16.0",
418                 "15.0",
419                 "13.3",
420                 "12.0",
421                 "10.9",
422                 "10.0",
423                 "9.2",
424                 "8.6",
425                 "8.0",
426                 "7.5",
427                 "6.7",
428                 "6.0",
429                 "5.5",
430                 "5.0",
431                 "4.6",
432                 "4.3",
433                 "4.0",
434                 "3.7",
435                 "3.3",
436                 "3.0",
437                 "2.7",
438                 "2.5",
439                 "2.3",
440                 "2.1",
441                 "2.0"
442         };
443
444         int cur_typemat_val;
445         int delay, rate;
446
447         if((ioctl(kbfd, KBDGTPMAT, &cur_typemat_val)) < 0)
448         {
449                 perror("kcon: ioctl KBDGTPMAT failed");
450                 exit(1);
451         }
452
453         delay = ((cur_typemat_val & 0x60) >> 5);
454         rate = cur_typemat_val & 0x1f;
455
456         printf("\nDisplaying the current keyboard typematic values:\n\n");
457         printf("The delay-until-repeat time is [ %s ] milliseconds\n",delaytab[delay]);
458         printf("The repeat-rate is [ %s ] characters per second\n\n",ratetab[rate]);
459 }
460
461 /*---------------------------------------------------------------------------*
462  *      set repeat feature on/off
463  *---------------------------------------------------------------------------*/
464 void
465 setrepeat(int kbfd, int tf)
466 {
467         int     srepsw_val;
468
469         if(tf == 1)
470                 srepsw_val = KBD_REPEATON;
471         else
472                 srepsw_val = KBD_REPEATOFF;
473
474         if(ioctl(kbfd, KBDSREPSW, &srepsw_val) < 0)
475         {
476                 perror("kcon: ioctl KBDREPSW failed");
477                 exit(1);
478         }
479 }
480
481 /*---------------------------------------------------------------------------*
482  *      set delay and rate values for keyboard
483  *---------------------------------------------------------------------------*/
484 void
485 settypeam(int kbfd, int delay, int rate)
486 {
487         int cur_typemat_val;
488         int new_typemat_val;
489
490         if((ioctl(kbfd, KBDGTPMAT, &cur_typemat_val)) < 0)
491         {
492                 perror("kcon: ioctl KBDGTPMAT failed");
493                 exit(1);
494         }
495
496         if(delay == -1)
497                 delay = (cur_typemat_val & 0x60);
498         else
499                 delay = ((delay << 5) & 0x60);
500
501         if(rate == -1)
502                 rate = (cur_typemat_val & 0x1f);
503         else
504                 rate &= 0x1f;
505
506         new_typemat_val = delay | rate;
507
508         if((ioctl(kbfd, KBDSTPMAT, &new_typemat_val)) < 0)
509         {
510                 perror("kcon: ioctl KBDSTPMAT failed");
511                 exit(1);
512         }
513 }
514
515 /*---------------------------------------------------------------------------*
516  *      remap keyboard from keycap entry
517  *---------------------------------------------------------------------------*/
518 void
519 remapkeys(int kbfd, char *map)
520 {
521         char cap_entry[1024];
522         int ret;
523         char keyflag[128];
524         int i;
525
526         /* try to find the entry */
527
528         ret = kgetent(cap_entry, map);
529
530         if(ret == -1)
531         {
532                 fprintf(stderr, "kcon: keycap database not found or not accessible!\n");
533                 exit(1);
534         }
535         else if(ret == 0)
536         {
537                 fprintf(stderr, "kcon: keycap entry [%s] not found in database!\n", map);
538                 exit(1);
539         }
540
541         /* set default mapping */
542
543         if((ioctl(kbfd, KBDDEFAULT)) < 0)
544         {
545                 perror("kcon: ioctl KBDDEFAULT failed");
546                 exit(1);
547         }
548
549         /* DE flag present? */
550
551         if(kgetflag("de"))
552                 return;
553
554         for(i = 0; i < KBDMAXKEYS; i++)
555                 keyflag[i] = 0;
556
557         set_lock(keyflag, kbfd);
558
559         set_shift(keyflag, kbfd);
560
561         set_char(keyflag, kbfd);
562 }
563
564 /*---------------------------------------------------------------------------*
565  *      care for lock keys
566  *---------------------------------------------------------------------------*/
567 void
568 set_lock(char keyflag[], int kbfd)
569 {
570         int i, j;
571         char cap[16];
572         struct kbd_ovlkey entry;
573
574         struct  {
575                 char    *ch;
576                 u_short typ;
577         } lock[] =
578         {
579                 "ca",   KBD_CAPS,
580                 "sh",   KBD_SHFTLOCK,
581                 "nl",   KBD_NUMLOCK,
582                 "sc",   KBD_SCROLL
583         };
584
585
586         for(i = 0; i < 4; i++)
587         {
588                 int n;
589
590                 sprintf(cap, "%s", lock[i].ch);
591
592                 n = kgetnum(cap);
593
594                 if(n > 0)
595                 {
596                         if (keyflag[n])
597                         {
598                                 fprintf(stderr,"kcon: duplicate key definition for key [%d]!\n",n);
599                                 exit(1);
600                         }
601                         keyflag[n] = 1;
602
603                         entry.keynum = n;
604                         entry.type = lock[i].typ;
605
606                         if((ioctl(kbfd, KBDSCKEY, &entry)) < 0)
607                         {
608                                 perror("kcon: ioctl KBDSCKEY failed");
609                                 exit(1);
610                         }
611                 }
612         }
613 }
614
615 /*---------------------------------------------------------------------------*
616  *      care for shifting keys
617  *---------------------------------------------------------------------------*/
618 void
619 set_shift(char keyflag[], int kbfd)
620 {
621         int i, j;
622         char cap[16];
623         struct kbd_ovlkey entry;
624
625         struct {
626                 char    ch;
627                 u_short typ;
628         } shift[] =
629         {
630                 'm',    KBD_META,
631                 'l',    KBD_ALTGR,
632                 'h',    KBD_SHIFT,
633                 't',    KBD_CTL
634         };
635
636         for(i = 0; i < 4; i++)
637         {
638                 for(j = 1; j < 10; j++)
639                 {
640                         int n;
641
642                         sprintf(cap, "%c%d", shift[i].ch,j);
643
644                         n = kgetnum(cap);
645
646                         if (n >= 0)
647                         {
648                                 if (keyflag[n])
649                                 {
650                                         fprintf(stderr,"kcon: duplicate key definition for key [%d]!\n",n);
651                                         exit(1);
652                                 }
653                                 keyflag[n] = 1;
654
655                                 entry.keynum = n;
656                                 entry.type = shift[i].typ;
657                                 if((ioctl(kbfd, KBDSCKEY, &entry)) < 0)
658                                 {
659                                         perror("kcon: ioctl KBDSCKEY failed");
660                                         exit(1);
661                                 }
662                         }
663                 }
664         }
665 }
666
667 /*---------------------------------------------------------------------------*
668  *      care for normal keys
669  *---------------------------------------------------------------------------*/
670 void
671 set_char(char keyflag[], int kbfd)
672 {
673         int i, j;
674         char cap[16];
675         int setflag;
676         char *addr_str;
677         char *new_str;
678         struct kbd_ovlkey entry;
679
680         struct {
681                 char    *addr;
682                 char    ch;
683         } standard[] = {
684                 0,                      'D',
685                 &entry.unshift[0],      'K',
686                 &entry.shift[0],        'S',
687                 &entry.ctrl[0],         'C',
688                 &entry.altgr[0],        'A'
689         };
690
691         for(i = 1; i < KBDMAXKEYS; i++)
692         {
693                 setflag = 0;
694
695                 entry.keynum = i;
696
697                 if((ioctl(kbfd, KBDGOKEY, &entry)) < 0)
698                 {
699                         perror("kcon: ioctl KBDGOKEY failed");
700                         exit(1);
701                 }
702
703                 entry.type = KBD_ASCII;
704
705                 for(j = 0; j < 5; j++)
706                 {
707                         sprintf(cap, "%c%d", standard[j].ch,i);
708
709                         if((j == 0) && (kgetflag(cap)))
710                         {
711                                 /* delete a key */
712
713                                 entry.type = KBD_NONE;
714                                 setflag = 1;
715                                 goto setit;
716
717                         }
718                         else
719                         {
720                                 addr_str = standard[j].addr;
721                                 if(new_str = kgetstr(cap, &addr_str))
722                                 {
723                                         if(strlen(new_str) > KBDMAXOVLKEYSIZE)
724                                         {
725                                                 fprintf(stderr, "kcon: database entry string [%s] longer than max [%d]!\n",new_str,KBDMAXOVLKEYSIZE);
726                                                 exit(1);
727                                         }
728                                         setflag = 1;
729                                 }
730                         }
731                 }
732
733 setit:          if (setflag)
734                 {
735                         if (keyflag[i])
736                         {
737                                 fprintf(stderr,"kcon: duplicate key definition for key [%d]!\n",i);
738                                 exit(1);
739                         }
740                         keyflag[i] = 1;
741
742                         if((ioctl(kbfd, KBDSCKEY, &entry)) < 0)
743                         {
744                                 perror("kcon: ioctl KBDSCKEY failed");
745                                 exit(1);
746                         }
747                 }
748         }
749 }
750
751 /*------------------- EOF ------------------------------------------------*/