48455bcee0d7a838568b2b8f4818c8a96fa4864c
[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.2 2004/03/24 17:46:23 cpressey 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) && (s[i] <= 0xff)))
268                 {
269                         conv_buf[0] = s[i];
270                         conv_buf[1] = '\0';
271                 }
272                 else if((s[i] == 0x1b) && (pf == 0))
273                 {
274                         strcpy(conv_buf,"ESC ");
275                 }
276                 else if(of)
277                 {
278                         sprintf(conv_buf,"\\%03.3o ", s[i]);
279                 }
280                 else
281                 {
282                         sprintf(conv_buf,"0x%02.2X ", s[i]);
283                 }
284                 strcat(res_str, conv_buf);
285         }
286         return(res_str);
287 }
288
289 /*---------------------------------------------------------------------------*
290  *      list the current keyboard mapping
291  *---------------------------------------------------------------------------*/
292 void
293 listcurrent(int kbfd)
294 {
295         static char *keytypetab[] = {
296                 "NONE     ",
297                 "SHIFT    ",
298                 "ALT/META ",
299                 "NUMLOCK  ",
300                 "CONTROL  ",
301                 "CAPSLOCK ",
302                 "ASCII    ",
303                 "SCROLL   ",
304                 "FUNCTION ",
305                 "KEYPAD   ",
306                 "BREAK    ",
307                 "ALTGR    ",
308                 "SHIFTLOCK",
309                 "CURSOR   ",
310                 "RETURN   "
311         };
312
313         struct kbd_ovlkey keyboardmap[KBDMAXKEYS];
314         struct kbd_ovlkey *kbmapp;
315         int keytype;
316         int altgr_defined;
317         int i;
318
319         altgr_defined = 0;
320         kbmapp = keyboardmap;
321
322         for (i = 0; i < KBDMAXKEYS; i++)
323         {
324                 kbmapp->keynum = i;
325
326                 if(ioctl(kbfd, KBDGCKEY, kbmapp) < 0)
327                 {
328                         perror("kcon: ioctl KBDGCKEY failed");
329                         exit(1);
330                 }
331
332                 if((kbmapp->type & KBD_MASK) == KBD_ALTGR)
333                         altgr_defined = i;
334
335                 kbmapp++;
336         }
337
338         if(altgr_defined)
339         {
340                 printf("S Key KeyType   Normal          Shift           Control         Altgr          \n");
341                 printf("- --- --------- --------------- --------------- --------------- ---------------\n");
342         }
343         else
344         {
345                 printf("S Key KeyType   Normal          Shift           Control        \n");
346                 printf("- --- --------- --------------- --------------- ---------------\n");
347         }
348
349         kbmapp = &keyboardmap[1];
350
351         for(i = 1; i < KBDMAXKEYS; i++)
352         {
353                 keytype = kbmapp->type;
354
355                 if(keytype)
356                 {
357                         if(keytype & KBD_OVERLOAD)
358                                 printf("! %3.3d %9.9s ", i, keytypetab[keytype & KBD_MASK]);
359                         else
360                                 printf("- %3.3d %9.9s ", i, keytypetab[keytype & KBD_MASK]);
361
362                         switch(keytype & KBD_MASK)
363                         {
364
365                                 case KBD_NUM:
366                                 case KBD_ASCII:
367                                 case KBD_FUNC:
368                                 case KBD_KP:
369                                 case KBD_CURSOR:
370                                 case KBD_RETURN: /* ??? */
371
372                                         if(kbmapp->subu == KBD_SUBT_STR)
373                                                 printf("%-15s ",showcntrl(kbmapp->unshift));
374                                         else
375                                                 printf("Function()      ");
376
377                                         if(kbmapp->subs == KBD_SUBT_STR)
378                                                 printf("%-15s ",showcntrl(kbmapp->shift));
379                                         else
380                                                 printf("Function()      ");
381
382                                         if(kbmapp->subc == KBD_SUBT_STR)
383                                                 printf("%-15s ",showcntrl(kbmapp->ctrl));
384                                         else
385                                                 printf("Function()      ");
386
387                                         if(altgr_defined)
388                                         {
389                                                 if(kbmapp->suba == KBD_SUBT_STR)
390                                                         printf("%-15s ",showcntrl(kbmapp->altgr));
391                                                 else
392                                                         printf("Function()      ");
393                                         }
394                                         break;
395                         }
396                         putchar('\n');
397                 }
398                 kbmapp++;
399         }
400 }
401
402 /*---------------------------------------------------------------------------*
403  *      show delay and rate values for keyboard
404  *---------------------------------------------------------------------------*/
405 int
406 showtypeamatic(int kbfd)
407 {
408         static char *delaytab[] = {
409                 "250",
410                 "500",
411                 "750",
412                 "1000"
413         };
414
415         static char *ratetab[] = {
416                 "30.0",
417                 "26.7",
418                 "24.0",
419                 "21.8",
420                 "20.0",
421                 "18.5",
422                 "17.1",
423                 "16.0",
424                 "15.0",
425                 "13.3",
426                 "12.0",
427                 "10.9",
428                 "10.0",
429                 "9.2",
430                 "8.6",
431                 "8.0",
432                 "7.5",
433                 "6.7",
434                 "6.0",
435                 "5.5",
436                 "5.0",
437                 "4.6",
438                 "4.3",
439                 "4.0",
440                 "3.7",
441                 "3.3",
442                 "3.0",
443                 "2.7",
444                 "2.5",
445                 "2.3",
446                 "2.1",
447                 "2.0"
448         };
449
450         int cur_typemat_val;
451         int delay, rate;
452
453         if((ioctl(kbfd, KBDGTPMAT, &cur_typemat_val)) < 0)
454         {
455                 perror("kcon: ioctl KBDGTPMAT failed");
456                 exit(1);
457         }
458
459         delay = ((cur_typemat_val & 0x60) >> 5);
460         rate = cur_typemat_val & 0x1f;
461
462         printf("\nDisplaying the current keyboard typematic values:\n\n");
463         printf("The delay-until-repeat time is [ %s ] milliseconds\n",delaytab[delay]);
464         printf("The repeat-rate is [ %s ] characters per second\n\n",ratetab[rate]);
465 }
466
467 /*---------------------------------------------------------------------------*
468  *      set repeat feature on/off
469  *---------------------------------------------------------------------------*/
470 void
471 setrepeat(int kbfd, int tf)
472 {
473         int     srepsw_val;
474
475         if(tf == 1)
476                 srepsw_val = KBD_REPEATON;
477         else
478                 srepsw_val = KBD_REPEATOFF;
479
480         if(ioctl(kbfd, KBDSREPSW, &srepsw_val) < 0)
481         {
482                 perror("kcon: ioctl KBDREPSW failed");
483                 exit(1);
484         }
485 }
486
487 /*---------------------------------------------------------------------------*
488  *      set delay and rate values for keyboard
489  *---------------------------------------------------------------------------*/
490 void
491 settypeam(int kbfd, int delay, int rate)
492 {
493         int cur_typemat_val;
494         int new_typemat_val;
495
496         if((ioctl(kbfd, KBDGTPMAT, &cur_typemat_val)) < 0)
497         {
498                 perror("kcon: ioctl KBDGTPMAT failed");
499                 exit(1);
500         }
501
502         if(delay == -1)
503                 delay = (cur_typemat_val & 0x60);
504         else
505                 delay = ((delay << 5) & 0x60);
506
507         if(rate == -1)
508                 rate = (cur_typemat_val & 0x1f);
509         else
510                 rate &= 0x1f;
511
512         new_typemat_val = delay | rate;
513
514         if((ioctl(kbfd, KBDSTPMAT, &new_typemat_val)) < 0)
515         {
516                 perror("kcon: ioctl KBDSTPMAT failed");
517                 exit(1);
518         }
519 }
520
521 /*---------------------------------------------------------------------------*
522  *      remap keyboard from keycap entry
523  *---------------------------------------------------------------------------*/
524 void
525 remapkeys(int kbfd, char *map)
526 {
527         char cap_entry[1024];
528         int ret;
529         char keyflag[128];
530         int i;
531
532         /* try to find the entry */
533
534         ret = kgetent(cap_entry, map);
535
536         if(ret == -1)
537         {
538                 fprintf(stderr, "kcon: keycap database not found or not accessible!\n");
539                 exit(1);
540         }
541         else if(ret == 0)
542         {
543                 fprintf(stderr, "kcon: keycap entry [%s] not found in database!\n", map);
544                 exit(1);
545         }
546
547         /* set default mapping */
548
549         if((ioctl(kbfd, KBDDEFAULT)) < 0)
550         {
551                 perror("kcon: ioctl KBDDEFAULT failed");
552                 exit(1);
553         }
554
555         /* DE flag present? */
556
557         if(kgetflag("de"))
558                 return;
559
560         for(i = 0; i < KBDMAXKEYS; i++)
561                 keyflag[i] = 0;
562
563         set_lock(keyflag, kbfd);
564
565         set_shift(keyflag, kbfd);
566
567         set_char(keyflag, kbfd);
568 }
569
570 /*---------------------------------------------------------------------------*
571  *      care for lock keys
572  *---------------------------------------------------------------------------*/
573 void
574 set_lock(char keyflag[], int kbfd)
575 {
576         int i, j;
577         char cap[16];
578         struct kbd_ovlkey entry;
579
580         struct  {
581                 char    *ch;
582                 u_short typ;
583         } lock[] =
584         {
585                 "ca",   KBD_CAPS,
586                 "sh",   KBD_SHFTLOCK,
587                 "nl",   KBD_NUMLOCK,
588                 "sc",   KBD_SCROLL
589         };
590
591
592         for(i = 0; i < 4; i++)
593         {
594                 int n;
595
596                 sprintf(cap, "%s", lock[i].ch);
597
598                 n = kgetnum(cap);
599
600                 if(n > 0)
601                 {
602                         if (keyflag[n])
603                         {
604                                 fprintf(stderr,"kcon: duplicate key definition for key [%d]!\n",n);
605                                 exit(1);
606                         }
607                         keyflag[n] = 1;
608
609                         entry.keynum = n;
610                         entry.type = lock[i].typ;
611
612                         if((ioctl(kbfd, KBDSCKEY, &entry)) < 0)
613                         {
614                                 perror("kcon: ioctl KBDSCKEY failed");
615                                 exit(1);
616                         }
617                 }
618         }
619 }
620
621 /*---------------------------------------------------------------------------*
622  *      care for shifting keys
623  *---------------------------------------------------------------------------*/
624 void
625 set_shift(char keyflag[], int kbfd)
626 {
627         int i, j;
628         char cap[16];
629         struct kbd_ovlkey entry;
630
631         struct {
632                 char    ch;
633                 u_short typ;
634         } shift[] =
635         {
636                 'm',    KBD_META,
637                 'l',    KBD_ALTGR,
638                 'h',    KBD_SHIFT,
639                 't',    KBD_CTL
640         };
641
642         for(i = 0; i < 4; i++)
643         {
644                 for(j = 1; j < 10; j++)
645                 {
646                         int n;
647
648                         sprintf(cap, "%c%d", shift[i].ch,j);
649
650                         n = kgetnum(cap);
651
652                         if (n >= 0)
653                         {
654                                 if (keyflag[n])
655                                 {
656                                         fprintf(stderr,"kcon: duplicate key definition for key [%d]!\n",n);
657                                         exit(1);
658                                 }
659                                 keyflag[n] = 1;
660
661                                 entry.keynum = n;
662                                 entry.type = shift[i].typ;
663                                 if((ioctl(kbfd, KBDSCKEY, &entry)) < 0)
664                                 {
665                                         perror("kcon: ioctl KBDSCKEY failed");
666                                         exit(1);
667                                 }
668                         }
669                 }
670         }
671 }
672
673 /*---------------------------------------------------------------------------*
674  *      care for normal keys
675  *---------------------------------------------------------------------------*/
676 void
677 set_char(char keyflag[], int kbfd)
678 {
679         int i, j;
680         char cap[16];
681         int setflag;
682         char *addr_str;
683         char *new_str;
684         struct kbd_ovlkey entry;
685
686         struct {
687                 char    *addr;
688                 char    ch;
689         } standard[] = {
690                 0,                      'D',
691                 &entry.unshift[0],      'K',
692                 &entry.shift[0],        'S',
693                 &entry.ctrl[0],         'C',
694                 &entry.altgr[0],        'A'
695         };
696
697         for(i = 1; i < KBDMAXKEYS; i++)
698         {
699                 setflag = 0;
700
701                 entry.keynum = i;
702
703                 if((ioctl(kbfd, KBDGOKEY, &entry)) < 0)
704                 {
705                         perror("kcon: ioctl KBDGOKEY failed");
706                         exit(1);
707                 }
708
709                 entry.type = KBD_ASCII;
710
711                 for(j = 0; j < 5; j++)
712                 {
713                         sprintf(cap, "%c%d", standard[j].ch,i);
714
715                         if((j == 0) && (kgetflag(cap)))
716                         {
717                                 /* delete a key */
718
719                                 entry.type = KBD_NONE;
720                                 setflag = 1;
721                                 goto setit;
722
723                         }
724                         else
725                         {
726                                 addr_str = standard[j].addr;
727                                 if(new_str = kgetstr(cap, &addr_str))
728                                 {
729                                         if(strlen(new_str) > KBDMAXOVLKEYSIZE)
730                                         {
731                                                 fprintf(stderr, "kcon: database entry string [%s] longer than max [%d]!\n",new_str,KBDMAXOVLKEYSIZE);
732                                                 exit(1);
733                                         }
734                                         setflag = 1;
735                                 }
736                         }
737                 }
738
739 setit:          if (setflag)
740                 {
741                         if (keyflag[i])
742                         {
743                                 fprintf(stderr,"kcon: duplicate key definition for key [%d]!\n",i);
744                                 exit(1);
745                         }
746                         keyflag[i] = 1;
747
748                         if((ioctl(kbfd, KBDSCKEY, &entry)) < 0)
749                         {
750                                 perror("kcon: ioctl KBDSCKEY failed");
751                                 exit(1);
752                         }
753                 }
754         }
755 }
756
757 /*------------------- EOF ------------------------------------------------*/