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