]> git.gir.st - sendHID.git/blob - main.c
restructuring and more unicode
[sendHID.git] / main.c
1 /*
2 description: sends a sequence of keystrokes to the hid device.
3 parameters:
4 device file (e.g. /dev/hidg0)
5 keyboard layout (1=en_us, 2=de_at, 3=de_at-nodeadkeys)
6 unicode method: 1=gtk_holddown, 2=gtk_spaceend, 3=windows
7 the string to send (as whitespace is important, the `echo` way of concatenating all parameters is not supported. if your string has white space in it and you are in an interactive session, quote your string.)
8 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include "scancodes.h"
13
14 enum params = {//argv-indices:
15 P_EXE, //executable name
16 P_DEV, //device file
17 P_LAY, //layout
18 P_UNI, //unicode method
19 P_STR, //string to type
20 NUM_P //number of parameters
21 };
22 enum kbdl = { //keyboard layouts:
23 na_NA, //reserved
24 en_US,
25 de_AT,
26 de_ND //de_AT-nodeadkeys
27 };
28 enum uni_m = {//unicode methods:
29 SKIP, //ignore any keys not on the layout
30 GTK_HOLD, //hold ctrl and shift while entering hex values
31 GTK_SPACE, //end hex sequence with spacebar
32 WINDOWS //use alt+numpad
33 };
34 enum errors = {
35 ERR_SUCCESS, //no error
36 ERR_ARGCOUNT, //wrong number of arguments
37 ERR_SYMBOL, //symbol not in look up table
38 ERR_LAYOUT, //parameter P_LAY does not contain a correct keyboard layout
39 ERR_LAZY //i haven't done this
40 };
41
42 void send_key (FILE* hid_dev, unsigned short key, unsigned short mod);
43 struct layout* tolay (struct keysym* s, enum kbdl layout);
44 enum errors send_unicode (FILE* hid_dev, unsigned int unicode, enum uni_m method, enum kbdl layout);
45
46 int main (int argc, char** argv) {
47 if (argc != NUM_P) {
48 fprintf (stderr, "Usage: %s <device file> <layout> <unicode> \"<string>\"\n", argv[P_EXE]);
49 return ERR_ARGCOUNT;
50 }
51 FILE* hid_dev = fopen ("/dev/hidg0", "w");
52 for (int i = 0; i < strlen (argv[P_STR]); i++) {
53
54 char tmp[UTF8_MAX_LENGTH] = {argv[P_STR][i], argv[P_STR][i+1], argv[P_STR][i+2], '\0'};
55 //TODO: replace by something less stupid
56 if (argv[P_STR][i] < 128) { // not multi byte
57 tmp[1] = '\0';
58 } else { // is multi byte
59 if (argv[P_STR][i] < 0xe0) {
60 i++; //skip next thing
61 tmp[2] = 0;
62 } else {
63 i+=2; //WARN: fails on utf8 > 3 byte
64 }
65 }
66
67 struct keysym* s = toscan (tmp);
68 if (s == NULL) {
69 fprintf (stderr, "Key Symbol not found.\n");
70 return ERR_SYMBOL;
71 }
72 struct layout* l = tolay (s, atoi (argv[P_LAY]));
73 if (l == NULL) {
74 fprintf (stderr, "Unrecognised keyboard layout.\n");
75 return ERR_LAYOUT;
76 }
77 if (l->key != 0x00) {
78 send_key(hid_dev, l->key, l->mod);
79 send_key(hid_dev, '\0', '\0'); //release all keys
80 if (l->is_dead && !ignore_deadkey) {
81 //dead keys need to be pressed twice to show up
82 send_key(hid_dev, l->key, l->mod);
83 send_key(hid_dev, '\0', '\0'); //release all keys
84 }
85 } else {
86 //key does not exist in this layout, use unicode method
87 fprintf (stderr, "Warning: Key not in this layout!\n");
88 send_unicode (s-> unicode, atoi (argv[P_UNI]);
89 }
90 }
91 fclose (hid_dev);
92
93 return ERR_SUCCESS;
94 }
95
96 struct layout* get_layout (struct keysym* s, enum kbdl layout) {
97 switch (layout) {
98 case na_NA:
99 fprintf (stderr, "This keyboard layout is reserved.\n");
100 return NULL;
101 case en_US:
102 return &(s->en_us);
103 case de_AT:
104 return &(s->de_at);
105 case de_ND:
106 return &(s->de_at);
107 default:
108 fprintf (stderr, "Unrecognised keyboard layout.\n");
109 return NULL;
110 }
111
112 void send_key (FILE* hid_dev, unsigned short key, unsigned short mod) {
113 fprintf (hid_dev, "%c%c%c%c%c%c%c%c", mod, '\0', key, '\0', '\0', '\0', '\0', '\0');
114 }
115
116 struct layout* tolay (struct keysym* s, enum kbdl layout) {
117 switch (layout) {
118 case en_US: return &(s->en_us);
119 case de_AT: return &(s->de_at);
120 case de_ND: return &(s->de_nd);
121 default: return NULL;
122 }
123 }
124
125 enum errors send_unicode (FILE* hid_dev, unsigned int unicode, enum uni_m method, enum kbdl layout) {
126 char buf[10];
127 struct keysym* s;
128 struct layout* l;
129
130 if (unicode == 0x00) {
131 printf ("Symbol not in lookup table!\n");
132 return ERR_SYMBOL;
133 }
134
135 switch (method) {
136 case SKIP:
137 break;
138 case GTK_HOLD:
139 fprintf ("Hold-down X11 not implemented!\n");
140 return ERR_LAZY;
141 case GTK_SPACE:
142 sprintf (string, "%x", unicode);
143 s = toscan ("u");
144 l = tolay (s, layout);
145 send_key (hid_dev, l->key, MOD_LCTRL | MOD_LSHIFT);
146 for (int i = 0; i < strlen (string); i++) {
147 s = toscan (string);
148 l = tolay (s, layout);
149 send_key (hid_dev, l->key, MOD_LCTRL | MOD_LSHIFT);
150 }
151 send_key (hid_dev, '\0', '\0');
152 break;
153 case WINDOWS:
154 fprintf ("windows method not implemented!\n");
155 return ERR_LAZY;
156 default:
157 fprintf ("unknown unicode method!\n");
158 return ERR_LAYOUT; //TODO: better error code
159 }
160 }
Imprint / Impressum