]> git.gir.st - sendHID.git/blob - main.c
max length of stdin #defined instead of magic number
[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 #define TEXT_LEN 256 //max length of piped text
15 enum params {//argv-indices:
16 P_EXE, //executable name
17 P_DEV, //device file
18 P_LAY, //layout
19 P_UNI, //unicode method
20 NUM_P //number of parameters
21 };
22 enum uni_m {//unicode methods:
23 SKIP, //ignore any keys not on the layout
24 GTK_HOLD, //hold ctrl and shift while entering hex values
25 GTK_SPACE, //end hex sequence with spacebar
26 WINDOWS //use alt+numpad
27 };
28 enum errors {
29 ERR_SUCCESS, //no error
30 ERR_ARGCOUNT, //wrong number of arguments
31 ERR_SYMBOL, //symbol not in look up table
32 ERR_LAYOUT, //parameter P_LAY does not contain a correct keyboard layout
33 ERR_LAZY //i haven't done this
34 };
35
36 void send_key (FILE* hid_dev, unsigned short key, unsigned short mod);
37 enum errors send_unicode (FILE* hid_dev, unsigned int unicode, enum uni_m method, enum kbdl layout);
38
39 int main (int argc, char** argv) {
40 if (argc != NUM_P) {
41 fprintf (stderr, "Usage: %s <device file> <layout> <unicode>\n", argv[P_EXE]);
42 fprintf (stderr, "Takes string to type from stdin\n");
43 return ERR_ARGCOUNT;
44 }
45 FILE* hid_dev = fopen ("/dev/hidg0", "w");
46 char in_string[TEXT_LEN];
47 fgets(in_string, TEXT_LEN, stdin);
48 for (int i = 0; i < strlen (in_string); i++) {
49
50 char tmp[UTF8_MAX_LENGTH] = {in_string[i], in_string[i+1], in_string[i+2], '\0'};
51 //TODO: replace by something less stupid
52 if (in_string[i] < 128) { // not multi byte
53 tmp[1] = '\0';
54 } else { // is multi byte
55 if (in_string[i] < 0xe0) {
56 i++; //skip next thing
57 tmp[2] = 0;
58 } else {
59 i+=2; //WARN: fails on utf8 > 3 byte
60 }
61 }
62
63 struct keysym* s = toscan (tmp);
64 if (s == NULL) {
65 fprintf (stderr, "Key Symbol not found.\n");
66 fclose (hid_dev);
67 return ERR_SYMBOL;
68 }
69 struct layout* l = tolay (s, atoi (argv[P_LAY]));
70 if (l == NULL) {
71 fprintf (stderr, "Unrecognised keyboard layout.\n");
72 fclose (hid_dev);
73 return ERR_LAYOUT;
74 }
75 if (l->key != 0x00) {
76 send_key(hid_dev, l->key, l->mod);
77 send_key(hid_dev, '\0', '\0'); //release all keys
78 if (l->is_dead) {
79 //dead keys need to be pressed twice to show up
80 send_key(hid_dev, l->key, l->mod);
81 send_key(hid_dev, '\0', '\0'); //release all keys
82 }
83 } else {
84 //key does not exist in this layout, use unicode method
85 //fprintf (stderr, "Warning: Key '%s'(0x%x) not in this layout!\n", s->sym, s->unicode);
86 send_unicode (hid_dev, s->unicode, atoi (argv[P_UNI]), atoi(argv[P_LAY]));
87 }
88 }
89 fclose (hid_dev);
90
91 return ERR_SUCCESS;
92 }
93
94 void send_key (FILE* hid_dev, unsigned short key, unsigned short mod) {
95 fprintf (hid_dev, "%c%c%c%c%c%c%c%c", mod, '\0', key, '\0', '\0', '\0', '\0', '\0');
96 }
97
98 enum errors send_unicode (FILE* hid_dev, unsigned int unicode, enum uni_m method, enum kbdl layout) {
99 char buf[10];
100 struct keysym* s;
101 struct layout* l;
102
103 if (unicode == 0x00) {
104 fprintf (stderr, "Symbol not in lookup table!\n");
105 return ERR_SYMBOL;
106 }
107
108 switch (method) {
109 case SKIP:
110 break;
111 case GTK_HOLD:
112 sprintf (buf, "%x", unicode);
113 s = toscan ("u");
114 l = tolay (s, layout);
115 send_key (hid_dev, l->key, MOD_LCTRL | MOD_LSHIFT);
116 for (int i = 0; i < strlen (buf); i++) {
117 s = toscan ((char[2]){buf[i], '\0'});
118 l = tolay (s, layout);
119 send_key (hid_dev, l->key, MOD_LCTRL | MOD_LSHIFT);
120 }
121 send_key (hid_dev, '\0', '\0');
122 break;
123 case GTK_SPACE:
124 sprintf (buf, "%x ", unicode);
125 s = toscan ("u");
126 l = tolay (s, layout);
127 send_key (hid_dev, l->key, MOD_LCTRL | MOD_LSHIFT);
128 for (int i = 0; i < strlen (buf); i++) {
129 s = toscan ((char[2]){buf[i], '\0'});
130 l = tolay (s, layout);
131 send_key (hid_dev, l->key, MOD_NONE);
132 }
133 send_key (hid_dev, '\0', '\0');
134 break;
135 case WINDOWS:
136 fprintf (stderr, "windows method not implemented!\n");
137 return ERR_LAZY;
138 default:
139 fprintf (stderr, "unknown unicode method!\n");
140 return ERR_LAYOUT; //TODO: better error code
141 }
142 return ERR_SUCCESS;
143 }
Imprint / Impressum