1717#include < linux/uhid.h>
1818#include < linux/input.h>
1919#include < jni.h>
20+ #include < android/log.h>
2021
2122static struct uinput_user_dev uinput_dev;
2223static int uinput_fd;
23- static struct input_event inputEventX, inputEventY, inputEventSYN, inputEventTL, inputEventTR, inputEventThumbL, inputEventHat0Y ;
24+ static struct input_event inputEventX, inputEventY, inputEventSYN, inputEventTL, inputEventTR, inputEventThumbL;
2425
2526extern " C"
2627JNIEXPORT void JNICALL
27- Java_com_tile_tuoluoyi_GamePadNative_nativeInputEvent (JNIEnv *env, jclass clazz, jint x_value,
28- jint y_value) {
28+ Java_com_tile_tuoluoyi_GamePadNative_nativeUInputEvent (JNIEnv *env, jclass clazz, jint x_value,
29+ jint y_value) {
2930
3031 inputEventX.value = x_value;
3132 write (uinput_fd, &inputEventX, sizeof (struct input_event ));
@@ -58,7 +59,7 @@ Java_com_tile_tuoluoyi_GamePadNative_nativeCreateUInput(JNIEnv *env, jclass claz
5859 uinput_dev.id .vendor = 0x1 ;
5960 uinput_dev.id .product = 0x1 ;
6061 // UInput机制中,轴事件的最小值是-32768,最大值是32767。但是我为了正负对称,就没有把最小值设为-32768。
61- // 设定好了最小值和最大值的作用是,后续我们发送轴事件时安卓系统会自动将轴事件归一化至-1到1之间。比如后续发一个-666,安卓系统就将这个数据归一化为-666/32767
62+ // 设定好了最小值和最大值的作用是,后续我们发送轴事件时安卓系统会自动将轴事件归一化至-1到1之间。比如后续发一个-666,安卓系统就将这个数据归一化为-666/65534
6263 uinput_dev.absmin [ABS_X] = -1 ;
6364 uinput_dev.absmax [ABS_X] = 1 ;
6465 uinput_dev.absmin [ABS_Y] = -1 ;
@@ -135,111 +136,67 @@ Java_com_tile_tuoluoyi_GamePadNative_nativeCreateUInput(JNIEnv *env, jclass claz
135136 memset (&inputEventThumbL, 0 , sizeof (struct input_event ));
136137 inputEventThumbL.type = EV_KEY;
137138 inputEventThumbL.code = BTN_THUMBL;
138- memset (&inputEventHat0Y, 0 , sizeof (struct input_event ));
139- inputEventHat0Y.type = EV_ABS;
140- inputEventHat0Y.code = ABS_HAT0Y;
141139
142140 return true ;
143141}
144142
145143extern " C"
146144JNIEXPORT void JNICALL
147- Java_com_tile_tuoluoyi_GamePadNative_nativePressTL (JNIEnv *env, jclass clazz, jboolean pressed) {
145+ Java_com_tile_tuoluoyi_GamePadNative_nativeUInputPressTL (JNIEnv *env, jclass clazz,
146+ jboolean pressed) {
148147 inputEventTL.value = pressed ? 1 : 0 ;
149148 write (uinput_fd, &inputEventTL, sizeof (struct input_event ));
150-
151149 write (uinput_fd, &inputEventSYN, sizeof (struct input_event ));
152150}
151+
153152extern " C"
154153JNIEXPORT void JNICALL
155- Java_com_tile_tuoluoyi_GamePadNative_nativePressTR (JNIEnv *env, jclass clazz, jboolean pressed) {
154+ Java_com_tile_tuoluoyi_GamePadNative_nativeUInputPressTR (JNIEnv *env, jclass clazz,
155+ jboolean pressed) {
156156 inputEventTR.value = pressed ? 1 : 0 ;
157157 write (uinput_fd, &inputEventTR, sizeof (struct input_event ));
158-
159158 write (uinput_fd, &inputEventSYN, sizeof (struct input_event ));
160159}
161160extern " C"
162161JNIEXPORT void JNICALL
163- Java_com_tile_tuoluoyi_GamePadNative_nativePressThumbL (JNIEnv *env, jclass clazz,
164- jboolean pressed) {
162+ Java_com_tile_tuoluoyi_GamePadNative_nativeUInputPressThumbL (JNIEnv *env, jclass clazz,
163+ jboolean pressed) {
165164 inputEventThumbL.value = pressed ? 1 : 0 ;
166165 write (uinput_fd, &inputEventThumbL, sizeof (struct input_event ));
167-
168166 write (uinput_fd, &inputEventSYN, sizeof (struct input_event ));
169167}
170- extern " C"
171- JNIEXPORT void JNICALL
172- Java_com_tile_tuoluoyi_GamePadNative_nativePressHat0Y (JNIEnv *env, jclass clazz, jboolean pressed) {
173- inputEventHat0Y.value = pressed ? -1 : 0 ;
174- write (uinput_fd, &inputEventHat0Y, sizeof (struct input_event ));
175168
176- write (uinput_fd, &inputEventSYN, sizeof (struct input_event ));
177- }
178169
170+ // 0x16, 0x01, 0x80, // Logical Minimum (-32767)
171+ // 0x26, 0xFF, 0x7F, // Logical Maximum (32767)
172+ static unsigned char descrpition[] = {
173+ 0x05 , 0x01 , // Usage Page (Generic Desktop Ctrls)
174+ 0x09 , 0x05 , // Usage (Game Pad)
175+ 0xA1 , 0x01 , // Collection (Application)
176+ 0x05 , 0x09 , // Usage Page (Button)
177+ 0x19 , 0x01 , // Usage Minimum (0x01)
178+ 0x29 , 0x10 , // Usage Maximum (0x10)
179+ 0x15 , 0x00 , // Logical Minimum (0)
180+ 0x25 , 0x01 , // Logical Maximum (1)
181+ 0x75 , 0x01 , // Report Size (1)
182+ 0x95 , 0x10 , // Report Count (16)
183+ 0x81 , 0x02 , // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
184+ 0x05 , 0x01 , // Usage Page (Generic Desktop Ctrls)
185+ 0x15 , 0x80 , // Logical Minimum (-128)
186+ 0x25 , 0x7F , // Logical Maximum (127)
187+ 0x36 , 0x00 , 0x80 , // Physical Minimum (-32768)
188+ 0x46 , 0xFF , 0x7F , // Physical Maximum (32767)
189+ 0x09 , 0x32 , // Usage (Z)
190+ 0x09 , 0x35 , // Usage (Rz)
191+ 0x75 , 0x10 , // Report Size (16)
192+ 0x95 , 0x02 , // Report Count (2)
193+ 0x81 , 0x42 , // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
194+ 0xC0 , // End Collection
195+
196+ // 45 bytes
179197
180- static unsigned char rdesc[] = {
181- 0x05 , 0x01 , /* USAGE_PAGE (Generic Desktop) */
182- 0x09 , 0x02 , /* USAGE (Mouse) */
183- 0xa1 , 0x01 , /* COLLECTION (Application) */
184- 0x09 , 0x01 , /* USAGE (Pointer) */
185- 0xa1 , 0x00 , /* COLLECTION (Physical) */
186- 0x85 , 0x01 , /* REPORT_ID (1) */
187- 0x05 , 0x09 , /* USAGE_PAGE (Button) */
188- 0x19 , 0x01 , /* USAGE_MINIMUM (Button 1) */
189- 0x29 , 0x03 , /* USAGE_MAXIMUM (Button 3) */
190- 0x15 , 0x00 , /* LOGICAL_MINIMUM (0) */
191- 0x25 , 0x01 , /* LOGICAL_MAXIMUM (1) */
192- 0x95 , 0x03 , /* REPORT_COUNT (3) */
193- 0x75 , 0x01 , /* REPORT_SIZE (1) */
194- 0x81 , 0x02 , /* INPUT (Data,Var,Abs) */
195- 0x95 , 0x01 , /* REPORT_COUNT (1) */
196- 0x75 , 0x05 , /* REPORT_SIZE (5) */
197- 0x81 , 0x01 , /* INPUT (Cnst,Var,Abs) */
198- 0x05 , 0x01 , /* USAGE_PAGE (Generic Desktop) */
199- 0x09 , 0x30 , /* USAGE (X) */
200- 0x09 , 0x31 , /* USAGE (Y) */
201- 0x09 , 0x38 , /* USAGE (WHEEL) */
202- 0x15 , 0x81 , /* LOGICAL_MINIMUM (-127) */
203- 0x25 , 0x7f , /* LOGICAL_MAXIMUM (127) */
204- 0x75 , 0x08 , /* REPORT_SIZE (8) */
205- 0x95 , 0x03 , /* REPORT_COUNT (3) */
206- 0x81 , 0x06 , /* INPUT (Data,Var,Rel) */
207- 0xc0 , /* END_COLLECTION */
208- 0xc0 , /* END_COLLECTION */
209- 0x05 , 0x01 , /* USAGE_PAGE (Generic Desktop) */
210- 0x09 , 0x06 , /* USAGE (Keyboard) */
211- 0xa1 , 0x01 , /* COLLECTION (Application) */
212- 0x85 , 0x02 , /* REPORT_ID (2) */
213- 0x05 , 0x08 , /* USAGE_PAGE (Led) */
214- 0x19 , 0x01 , /* USAGE_MINIMUM (1) */
215- 0x29 , 0x03 , /* USAGE_MAXIMUM (3) */
216- 0x15 , 0x00 , /* LOGICAL_MINIMUM (0) */
217- 0x25 , 0x01 , /* LOGICAL_MAXIMUM (1) */
218- 0x95 , 0x03 , /* REPORT_COUNT (3) */
219- 0x75 , 0x01 , /* REPORT_SIZE (1) */
220- 0x91 , 0x02 , /* Output (Data,Var,Abs) */
221- 0x95 , 0x01 , /* REPORT_COUNT (1) */
222- 0x75 , 0x05 , /* REPORT_SIZE (5) */
223- 0x91 , 0x01 , /* Output (Cnst,Var,Abs) */
224- 0xc0 , /* END_COLLECTION */
225- };
226-
227- static int uhid_write (int fd, const struct uhid_event *ev) {
228- ssize_t ret;
229-
230- ret = write (fd, ev, sizeof (*ev));
231- if (ret < 0 ) {
232- fprintf (stderr, " Cannot write to uhid: %m\n " );
233- return -errno;
234- } else if (ret != sizeof (*ev)) {
235- fprintf (stderr, " Wrong size written to uhid: %zd != %zu\n " ,
236- ret, sizeof (ev));
237- return -EFAULT;
238- } else {
239- return 0 ;
240- }
241- }
242198
199+ };
243200
244201static int uhid_fd;
245202static struct uhid_event uhidEventXY;
@@ -248,29 +205,26 @@ extern "C"
248205JNIEXPORT jboolean JNICALL
249206Java_com_tile_tuoluoyi_GamePadNative_nativeCreateUHid (JNIEnv *env, jclass clazz) {
250207
251- if ((uhid_fd = open (" /dev/uinput " , O_RDWR | O_NDELAY)) < 0 ) {
208+ if ((uhid_fd = open (" /dev/uhid " , O_RDWR | O_NDELAY)) < 0 ) {
252209 return false ;// error process.
253210 }
254- struct uhid_event ev;
255- memset (&ev, 0 , sizeof (uhid_event));
211+ struct uhid_event ev = {0 };
256212 ev.type = UHID_CREATE;
257213 strcpy ((char *) ev.u .create .name , " Xbox Wireless Controller" );
258- ev.u .create .rd_data = rdesc ;
259- ev.u .create .rd_size = sizeof (rdesc );
260- ev.u .create .bus = BUS_USB ;
261- ev.u .create .vendor = 0x15d9 ;
262- ev.u .create .product = 0x0a37 ;
263- ev.u .create .version = 0 ;
214+ ev.u .create .rd_data = descrpition ;
215+ ev.u .create .rd_size = sizeof (descrpition );
216+ ev.u .create .bus = BUS_VIRTUAL ;
217+ ev.u .create .vendor = 0x1 ;
218+ ev.u .create .product = 0x1 ;
219+ ev.u .create .version = 0x1 ;
264220 ev.u .create .country = 0 ;
265- ssize_t ret = write (uhid_fd, &ev, sizeof (ev));
266- if (ret != sizeof (ev)) {
221+ if (write (uhid_fd, &ev, sizeof (ev)) != sizeof (uhid_event)) {
267222 return false ;
268223 }
269224
270225 memset (&uhidEventXY, 0 , sizeof (uhid_event));
271226 uhidEventXY.type = UHID_INPUT;
272- uhidEventXY.u .input .size = 5 ;
273- uhidEventXY.u .input .data [0 ] = 0x1 ;
227+ uhidEventXY.u .input .size = 6 ;
274228
275229 return true ;
276230}
@@ -279,21 +233,51 @@ extern "C"
279233JNIEXPORT jboolean JNICALL
280234Java_com_tile_tuoluoyi_GamePadNative_nativeCloseUHid (JNIEnv *env, jclass clazz) {
281235
282- struct uhid_event ev;
283- memset (&ev, 0 , sizeof (ev));
236+ struct uhid_event ev = {0 };
284237 ev.type = UHID_DESTROY;
285238 return write (uhid_fd, &ev, sizeof (uhid_event)) > 0 ;
286239}
287240
288241
289242extern " C"
290243JNIEXPORT void JNICALL
291- Java_com_tile_tuoluoyi_GamePadNative_nativeUHidInputEvent (JNIEnv *env, jclass clazz, jint x_value,
292- jint y_value) {
293-
294- uhidEventXY.u .input .data [2 ] = x_value;
295- uhidEventXY.u .input .data [3 ] = y_value;
244+ Java_com_tile_tuoluoyi_GamePadNative_nativeUHidEvent (JNIEnv *env, jclass clazz, jint x_value,
245+ jint y_value) {
246+
247+
248+ if (y_value>32767 ) y_value = 32767 ;
249+ else if (y_value<-32767 ) y_value = -32767 ;
250+ if (x_value>32767 ) x_value = 32767 ;
251+ else if (x_value<-32767 ) x_value = -32767 ;
252+ uhidEventXY.u .input .data [2 ] = y_value & 0xFF ;
253+ uhidEventXY.u .input .data [3 ] = (y_value >> 8 ) & 0xFF ;
254+ uhidEventXY.u .input .data [4 ] = x_value & 0xFF ;
255+ uhidEventXY.u .input .data [5 ] = (x_value >> 8 ) & 0xFF ;
296256 write (uhid_fd, &uhidEventXY, sizeof (uhid_event));
297257
298258}
299259
260+
261+ extern " C"
262+ JNIEXPORT void JNICALL
263+ Java_com_tile_tuoluoyi_GamePadNative_nativeUHidPressTL (JNIEnv *env, jclass clazz,
264+ jboolean pressed) {
265+ pressed ? (uhidEventXY.u .input .data [0 ] |= 1 << 6 ) : (uhidEventXY.u .input .data [0 ] &= ~(1 << 6 ));
266+ write (uhid_fd, &uhidEventXY, sizeof (uhid_event));
267+ }
268+ extern " C"
269+ JNIEXPORT void JNICALL
270+ Java_com_tile_tuoluoyi_GamePadNative_nativeUHidPressTR (JNIEnv *env, jclass clazz,
271+ jboolean pressed) {
272+ pressed ? (uhidEventXY.u .input .data [0 ] |= 1 << 7 ) : (uhidEventXY.u .input .data [0 ] &= ~(1 << 7 ));
273+ write (uhid_fd, &uhidEventXY, sizeof (uhid_event));
274+ }
275+ extern " C"
276+ JNIEXPORT void JNICALL
277+ Java_com_tile_tuoluoyi_GamePadNative_nativeUHidPressThumbL (JNIEnv *env, jclass clazz,
278+ jboolean pressed) {
279+ pressed ? (uhidEventXY.u .input .data [1 ] |= 1 << 5 ) : (uhidEventXY.u .input .data [1 ] &= ~(1 << 5 ));
280+ write (uhid_fd, &uhidEventXY, sizeof (uhid_event));
281+ // __android_log_print(ANDROID_LOG_INFO, "MyTag", "This is a log message from JNI%d",
282+ // uhidEventXY.u.input.data[2]);
283+ }
0 commit comments