Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) ===========================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) Linux USB HID gadget driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) ===========================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) Introduction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) ============
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) The HID Gadget driver provides emulation of USB Human Interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) Devices (HID). The basic HID handling is done in the kernel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) and HID reports can be sent/received through I/O on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) /dev/hidgX character devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) For more details about HID, see the developer page on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) https://www.usb.org/developers/hidpage/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) Configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) =============
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) g_hid is a platform driver, so to use it you need to add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) struct platform_device(s) to your platform code defining the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) HID function descriptors you want to use - E.G. something
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) like::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)   #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)   #include <linux/usb/g_hid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)   /* hid descriptor for a keyboard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)   static struct hidg_func_descriptor my_hid_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	.subclass		= 0, /* No subclass */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	.protocol		= 1, /* Keyboard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	.report_length		= 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	.report_desc_length	= 63,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	.report_desc		= {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 		0x05, 0x01,	/* USAGE_PAGE (Generic Desktop)	          */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		0x09, 0x06,	/* USAGE (Keyboard)                       */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 		0xa1, 0x01,	/* COLLECTION (Application)               */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		0x05, 0x07,	/*   USAGE_PAGE (Keyboard)                */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 		0x19, 0xe0,	/*   USAGE_MINIMUM (Keyboard LeftControl) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		0x29, 0xe7,	/*   USAGE_MAXIMUM (Keyboard Right GUI)   */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		0x15, 0x00,	/*   LOGICAL_MINIMUM (0)                  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		0x25, 0x01,	/*   LOGICAL_MAXIMUM (1)                  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		0x75, 0x01,	/*   REPORT_SIZE (1)                      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		0x95, 0x08,	/*   REPORT_COUNT (8)                     */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		0x81, 0x02,	/*   INPUT (Data,Var,Abs)                 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		0x95, 0x01,	/*   REPORT_COUNT (1)                     */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		0x75, 0x08,	/*   REPORT_SIZE (8)                      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		0x81, 0x03,	/*   INPUT (Cnst,Var,Abs)                 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		0x95, 0x05,	/*   REPORT_COUNT (5)                     */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		0x75, 0x01,	/*   REPORT_SIZE (1)                      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		0x05, 0x08,	/*   USAGE_PAGE (LEDs)                    */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		0x19, 0x01,	/*   USAGE_MINIMUM (Num Lock)             */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 		0x29, 0x05,	/*   USAGE_MAXIMUM (Kana)                 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		0x91, 0x02,	/*   OUTPUT (Data,Var,Abs)                */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		0x95, 0x01,	/*   REPORT_COUNT (1)                     */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		0x75, 0x03,	/*   REPORT_SIZE (3)                      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		0x91, 0x03,	/*   OUTPUT (Cnst,Var,Abs)                */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		0x95, 0x06,	/*   REPORT_COUNT (6)                     */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		0x75, 0x08,	/*   REPORT_SIZE (8)                      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		0x15, 0x00,	/*   LOGICAL_MINIMUM (0)                  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		0x25, 0x65,	/*   LOGICAL_MAXIMUM (101)                */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 		0x05, 0x07,	/*   USAGE_PAGE (Keyboard)                */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 		0x19, 0x00,	/*   USAGE_MINIMUM (Reserved)             */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		0x29, 0x65,	/*   USAGE_MAXIMUM (Keyboard Application) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		0x81, 0x00,	/*   INPUT (Data,Ary,Abs)                 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		0xc0		/* END_COLLECTION                         */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)   };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)   static struct platform_device my_hid = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	.name			= "hidg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	.id			= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	.num_resources		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	.resource		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	.dev.platform_data	= &my_hid_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)   };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) You can add as many HID functions as you want, only limited by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) the amount of interrupt endpoints your gadget driver supports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) Configuration with configfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) ===========================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) Instead of adding fake platform devices and drivers in order to pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) some data to the kernel, if HID is a part of a gadget composed with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) configfs the hidg_func_descriptor.report_desc is passed to the kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) by writing the appropriate stream of bytes to a configfs attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) Send and receive HID reports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) ============================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) HID reports can be sent/received using read/write on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) /dev/hidgX character devices. See below for an example program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) to do this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) hid_gadget_test is a small interactive program to test the HID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) gadget driver. To use, point it at a hidg device and set the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) device type (keyboard / mouse / joystick) - E.G.::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	# hid_gadget_test /dev/hidg0 keyboard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) You are now in the prompt of hid_gadget_test. You can type any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) combination of options and values. Available options and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) values are listed at program start. In keyboard mode you can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) send up to six values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) For example type: g i s t r --left-shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) Hit return and the corresponding report will be sent by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) HID gadget.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) Another interesting example is the caps lock test. Type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) --caps-lock and hit return. A report is then sent by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) gadget and you should receive the host answer, corresponding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) to the caps lock LED status::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	--caps-lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	recv report:2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) With this command::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	# hid_gadget_test /dev/hidg1 mouse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) You can test the mouse emulation. Values are two signed numbers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) Sample code::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)     /* hid_gadget_test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)     #include <pthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)     #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)     #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)     #include <ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)     #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)     #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)     #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)     #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)     #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)     #define BUF_LEN 512
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)     struct options {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	const char    *opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)   };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)   static struct options kmod[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	{.opt = "--left-ctrl",		.val = 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	{.opt = "--right-ctrl",		.val = 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	{.opt = "--left-shift",		.val = 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	{.opt = "--right-shift",	.val = 0x20},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	{.opt = "--left-alt",		.val = 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	{.opt = "--right-alt",		.val = 0x40},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	{.opt = "--left-meta",		.val = 0x08},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	{.opt = "--right-meta",		.val = 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	{.opt = NULL}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)   };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)   static struct options kval[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	{.opt = "--return",	.val = 0x28},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	{.opt = "--esc",	.val = 0x29},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	{.opt = "--bckspc",	.val = 0x2a},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	{.opt = "--tab",	.val = 0x2b},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	{.opt = "--spacebar",	.val = 0x2c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	{.opt = "--caps-lock",	.val = 0x39},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	{.opt = "--f1",		.val = 0x3a},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	{.opt = "--f2",		.val = 0x3b},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	{.opt = "--f3",		.val = 0x3c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	{.opt = "--f4",		.val = 0x3d},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	{.opt = "--f5",		.val = 0x3e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	{.opt = "--f6",		.val = 0x3f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	{.opt = "--f7",		.val = 0x40},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	{.opt = "--f8",		.val = 0x41},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	{.opt = "--f9",		.val = 0x42},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	{.opt = "--f10",	.val = 0x43},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	{.opt = "--f11",	.val = 0x44},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	{.opt = "--f12",	.val = 0x45},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	{.opt = "--insert",	.val = 0x49},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	{.opt = "--home",	.val = 0x4a},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	{.opt = "--pageup",	.val = 0x4b},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	{.opt = "--del",	.val = 0x4c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	{.opt = "--end",	.val = 0x4d},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	{.opt = "--pagedown",	.val = 0x4e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	{.opt = "--right",	.val = 0x4f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	{.opt = "--left",	.val = 0x50},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	{.opt = "--down",	.val = 0x51},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	{.opt = "--kp-enter",	.val = 0x58},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	{.opt = "--up",		.val = 0x52},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	{.opt = "--num-lock",	.val = 0x53},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	{.opt = NULL}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)   };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)   int keyboard_fill_report(char report[8], char buf[BUF_LEN], int *hold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)   {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	char *tok = strtok(buf, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	int key = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	for (; tok != NULL; tok = strtok(NULL, " ")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		if (strcmp(tok, "--quit") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		if (strcmp(tok, "--hold") == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 			*hold = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		if (key < 6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 			for (i = 0; kval[i].opt != NULL; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 				if (strcmp(tok, kval[i].opt) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 					report[2 + key++] = kval[i].val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 			if (kval[i].opt != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		if (key < 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 			if (islower(tok[0])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 				report[2 + key++] = (tok[0] - ('a' - 0x04));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		for (i = 0; kmod[i].opt != NULL; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 			if (strcmp(tok, kmod[i].opt) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 				report[0] = report[0] | kmod[i].val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		if (kmod[i].opt != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		if (key < 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 			fprintf(stderr, "unknown option: %s\n", tok);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	return 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)   }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)   static struct options mmod[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	{.opt = "--b1", .val = 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	{.opt = "--b2", .val = 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	{.opt = "--b3", .val = 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	{.opt = NULL}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)   };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)   int mouse_fill_report(char report[8], char buf[BUF_LEN], int *hold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)   {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	char *tok = strtok(buf, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	int mvt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	for (; tok != NULL; tok = strtok(NULL, " ")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		if (strcmp(tok, "--quit") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		if (strcmp(tok, "--hold") == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 			*hold = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		for (i = 0; mmod[i].opt != NULL; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 			if (strcmp(tok, mmod[i].opt) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 				report[0] = report[0] | mmod[i].val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		if (mmod[i].opt != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		if (!(tok[0] == '-' && tok[1] == '-') && mvt < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 			errno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 			report[1 + mvt++] = (char)strtol(tok, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 			if (errno != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 				fprintf(stderr, "Bad value:'%s'\n", tok);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 				report[1 + mvt--] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		fprintf(stderr, "unknown option: %s\n", tok);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	return 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)   }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)   static struct options jmod[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	{.opt = "--b1",		.val = 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	{.opt = "--b2",		.val = 0x20},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	{.opt = "--b3",		.val = 0x40},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	{.opt = "--b4",		.val = 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	{.opt = "--hat1",	.val = 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	{.opt = "--hat2",	.val = 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	{.opt = "--hat3",	.val = 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	{.opt = "--hat4",	.val = 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	{.opt = "--hatneutral",	.val = 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	{.opt = NULL}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)   };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)   int joystick_fill_report(char report[8], char buf[BUF_LEN], int *hold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)   {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	char *tok = strtok(buf, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	int mvt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	*hold = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	/* set default hat position: neutral */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	report[3] = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	for (; tok != NULL; tok = strtok(NULL, " ")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		if (strcmp(tok, "--quit") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		for (i = 0; jmod[i].opt != NULL; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 			if (strcmp(tok, jmod[i].opt) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 				report[3] = (report[3] & 0xF0) | jmod[i].val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		if (jmod[i].opt != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		if (!(tok[0] == '-' && tok[1] == '-') && mvt < 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 			errno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 			report[mvt++] = (char)strtol(tok, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 			if (errno != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 				fprintf(stderr, "Bad value:'%s'\n", tok);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 				report[mvt--] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		fprintf(stderr, "unknown option: %s\n", tok);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	return 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)   }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)   void print_options(char c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)   {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	if (c == 'k') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		printf("	keyboard options:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		       "		--hold\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		for (i = 0; kmod[i].opt != NULL; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 			printf("\t\t%s\n", kmod[i].opt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		printf("\n	keyboard values:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		       "		[a-z] or\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		for (i = 0; kval[i].opt != NULL; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 			printf("\t\t%-8s%s", kval[i].opt, i % 2 ? "\n" : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	} else if (c == 'm') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		printf("	mouse options:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		       "		--hold\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		for (i = 0; mmod[i].opt != NULL; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 			printf("\t\t%s\n", mmod[i].opt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		printf("\n	mouse values:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		       "		Two signed numbers\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		       "--quit to close\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		printf("	joystick options:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		for (i = 0; jmod[i].opt != NULL; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 			printf("\t\t%s\n", jmod[i].opt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		printf("\n	joystick values:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		       "		three signed numbers\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		       "--quit to close\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)   }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)   int main(int argc, const char *argv[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)   {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	const char *filename = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	int fd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	char buf[BUF_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	int cmd_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	char report[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	int to_send = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	int hold = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	fd_set rfds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	int retval, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	if (argc < 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 		fprintf(stderr, "Usage: %s devname mouse|keyboard|joystick\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 			argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	if (argv[2][0] != 'k' && argv[2][0] != 'm' && argv[2][0] != 'j')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	  return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	filename = argv[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	if ((fd = open(filename, O_RDWR, 0666)) == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 		perror(filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 		return 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	print_options(argv[2][0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	while (42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 		FD_ZERO(&rfds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 		FD_SET(STDIN_FILENO, &rfds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		FD_SET(fd, &rfds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		retval = select(fd + 1, &rfds, NULL, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		if (retval == -1 && errno == EINTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		if (retval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 			perror("select()");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 			return 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		if (FD_ISSET(fd, &rfds)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 			cmd_len = read(fd, buf, BUF_LEN - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 			printf("recv report:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 			for (i = 0; i < cmd_len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 				printf(" %02x", buf[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 			printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		if (FD_ISSET(STDIN_FILENO, &rfds)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 			memset(report, 0x0, sizeof(report));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 			cmd_len = read(STDIN_FILENO, buf, BUF_LEN - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 			if (cmd_len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 			buf[cmd_len - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 			hold = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 			memset(report, 0x0, sizeof(report));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 			if (argv[2][0] == 'k')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 				to_send = keyboard_fill_report(report, buf, &hold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 			else if (argv[2][0] == 'm')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 				to_send = mouse_fill_report(report, buf, &hold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 				to_send = joystick_fill_report(report, buf, &hold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 			if (to_send == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 			if (write(fd, report, to_send) != to_send) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 				perror(filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 				return 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 			if (!hold) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 				memset(report, 0x0, sizeof(report));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 				if (write(fd, report, to_send) != to_send) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 					perror(filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 					return 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)   }