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