├── README.md ├── bin ├── event2usbhid └── mkusbhid ├── misc ├── 99-bluetooth.rules ├── event2usbhid_keyboard.service ├── event2usbhid_mouse.service └── mkusbhid.service └── src ├── Makefile ├── keyboard.c ├── main.c └── mouse.c /README.md: -------------------------------------------------------------------------------- 1 | # event2usbhid 2 | Raspberry Pi Zero Wを、Bluetooth キーボード/マウス → USBキーボード/マウス変換機にしてみた 3 | 4 | 5 | http://moguno.hatenablog.jp/entry/2020/11/22/220450 6 | -------------------------------------------------------------------------------- /bin/event2usbhid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moguno/event2usbhid/43eed1e8859e613f624873912ba010d6af74624a/bin/event2usbhid -------------------------------------------------------------------------------- /bin/mkusbhid: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | usbg_init() { 4 | base=$1 5 | 6 | mkdir -p $base/usb_gadget 7 | 8 | echo $base/usb_gadget 9 | } 10 | 11 | usbg_create_gadget() { 12 | state=$1 13 | gadget=$2 14 | declare -n _g_attrs=$3 15 | declare -n _g_strs=$4 16 | 17 | mkdir -p $state/$gadget 18 | cd $state/$gadget 19 | 20 | for key in "${!_g_attrs[@]}"; do 21 | echo -ne ${_g_attrs[$key]} > $key 22 | done 23 | 24 | mkdir $state/$gadget/strings/0x409 25 | cd $state/$gadget/strings/0x409 26 | 27 | for key in "${!_g_strs[@]}"; do 28 | echo -ne ${_g_strs[$key]} > $key 29 | done 30 | 31 | echo $state/$gadget 32 | } 33 | 34 | usbg_create_function() { 35 | gadget=$1 36 | function=$2 37 | function_id=$3 38 | declare -n _f_attrs=$4 39 | 40 | mkdir -p $gadget/functions/$function.$function_id 41 | cd $gadget/functions/$function.$function_id 42 | 43 | for key in "${!_f_attrs[@]}"; do 44 | echo -ne ${_f_attrs[$key]} > $key 45 | done 46 | 47 | echo $gadget/functions/$function.$function_id 48 | } 49 | 50 | usbg_create_config() { 51 | gadget=$1 52 | config_id=$2 53 | config=$3 54 | declare -n _c_strs=$4 55 | 56 | mkdir -p $gadget/configs/$config.$config_id/strings/0x409 57 | cd $gadget/configs/$config.$config_id/strings/0x409 58 | 59 | for key in "${!_c_strs[@]}"; do 60 | echo -ne ${_c_strs[$key]} > $key 61 | done 62 | 63 | echo $gadget/configs/$config.$config_id 64 | } 65 | 66 | usbg_add_config_function() { 67 | config=$1 68 | name=$2 69 | function=$3 70 | 71 | ln -s $function $config/$name 72 | } 73 | 74 | usbg_enable_gadget() { 75 | gadget=$1 76 | 77 | cd $gadget 78 | 79 | ls /sys/class/udc > UDC 80 | } 81 | 82 | /sbin/modprobe dwc2 83 | /sbin/modprobe libcomposite 84 | 85 | state=`usbg_init "/sys/kernel/config/"` 86 | 87 | declare -A g_attrs 88 | g_attrs["bcdUSB"]="0x0200" 89 | g_attrs["bDeviceClass"]="0x00" 90 | g_attrs["bDeviceSubClass"]="0x00" 91 | g_attrs["bDeviceProtocol"]="0x00" 92 | g_attrs["bMaxPacketSize0"]="64" 93 | g_attrs["idVendor"]="0x1d6b" 94 | g_attrs["idProduct"]="0x0105" 95 | g_attrs["bcdDevice"]="0x0001" 96 | 97 | declare -A g_strs 98 | g_strs["serialnumber"]="0123456789" 99 | g_strs["manufacturer"]="moguno" 100 | g_strs["product"]="HID Converter" 101 | 102 | gadget=`usbg_create_gadget $state "g11" g_attrs g_strs` 103 | 104 | desc="" 105 | desc+="\x05""\x01" # USAGE_PAGE (Generic Desktop) 106 | desc+="\x09""\x06" # USAGE (Keyboard) 107 | desc+="\xA1""\x01" # COLLECTION (Application) 108 | 109 | desc+="\x85""\x01" # REPORT_ID (1) 110 | 111 | # Bitmapped Modifiers 112 | 113 | desc+="\x05""\x07" # USAGE_PAGE (Key Codes) 114 | desc+="\x19""\xE0" # USAGE_MINIMUM (224) 115 | desc+="\x29""\xE7" # USAGE_MAXIMUM (231) 116 | desc+="\x15""\x00" # LOGICAL_MINIMUM (0) 117 | desc+="\x25""\x01" # LOGICAL_MAXIMUM (1) 118 | desc+="\x75""\x01" # REPORT_SIZE (1) 119 | desc+="\x95""\x08" # REPORT_COUNT (8) 120 | desc+="\x81""\x02" # INPUT (Data Variable Absolute) 121 | 122 | # Reserved 123 | 124 | desc+="\x95""\x01" # REPORT_COUNT (1) 125 | desc+="\x75""\x08" # REPORT_SIZE (8) 126 | desc+="\x81""\x01" # INPUT (Constant) 127 | 128 | # LEDs 129 | 130 | desc+="\x05""\x08" # USAGE_PAGE (LED) 131 | desc+="\x19""\x01" # USAGE_MINIMUM (1) 132 | desc+="\x29""\x05" # USAGE_MAXIMUM (5) 133 | desc+="\x95""\x05" # REPORT_COUNT (5) 134 | desc+="\x75""\x01" # REPORT_SIZE (1) 135 | desc+="\x91""\x02" # OUTPUT (Data Variable Absolute) 136 | 137 | # Padding 138 | 139 | desc+="\x95""\x01" # REPORT_COUNT (1) 140 | desc+="\x75""\x03" # REPORT_SIZE (3) 141 | desc+="\x91""\x03" # OUTPUT (Constant) 142 | 143 | # Keyboard Keys 144 | 145 | desc+="\x15""\x00" # LOGICAL_MINIMUM (0) 146 | desc+="\x25""\xFF" # LOGICAL_MAXIMUM (255) 147 | desc+="\x05""\x07" # USAGE_PAGE (Key Codes) 148 | desc+="\x19""\x00" # USAGE_MINIMUM (0) 149 | desc+="\x29""\xFF" # USAGE_MAXIMUM (255) 150 | desc+="\x95""\x0D" # REPORT_COUNT (13) 151 | desc+="\x75""\x08" # REPORT_SIZE (8) 152 | desc+="\x81""\x00" # INPUT (Data Array Absolute) 153 | 154 | desc+="\xC0" # END_COLLECTION 155 | 156 | # Media Keys 157 | 158 | desc+="\x05""\x0C" # USAGE_PAGE (Conumer) 159 | desc+="\x09""\x01" # USAGE (Consumer Control) 160 | desc+="\xA1""\x01" # Collection (Application) 161 | 162 | desc+="\x85""\x02" # Report ID (2) 163 | 164 | desc+="\x05""\x0C" # Usage Page (Consumer) 165 | desc+="\x15""\x00" # Logical Minimum (0) 166 | desc+="\x25""\x01" # Logical Maximum (1) 167 | desc+="\x75""\x01" # Report Size (1) 168 | 169 | desc+="\x95""\x06" # Report Count (6) 170 | desc+="\x09""\xB5" # Usage (Scan Next Track) 171 | desc+="\x09""\xB6" # Usage (Scan Previous Track) 172 | desc+="\x09""\xB7" # Usage (Stop) 173 | desc+="\x09""\xB8" # Usage (Eject) 174 | desc+="\x09""\xCD" # Usage (Play/Pause) 175 | desc+="\x09""\xE2" # Usage (Mute) 176 | desc+="\x81""\x06" # Input (DataVarRel) 177 | 178 | desc+="\x95""\x02" # Report Count (2) 179 | desc+="\x09""\xE9" # Usage (Volume Increment) 180 | desc+="\x09""\xEA" # Usage (Volume Decrement) 181 | desc+="\x81""\x02" # Input (DataVarAbsNo WrapLinearPreferred StateNo Null Position) 182 | 183 | desc+="\xC0" # END_COLLECTION 184 | 185 | declare -A f_attrs_keyboard 186 | f_attrs_keyboard["protocol"]="1" 187 | f_attrs_keyboard["report_desc"]=$desc 188 | f_attrs_keyboard["report_length"]="16" 189 | f_attrs_keyboard["subclass"]="0" 190 | 191 | f_hid_keyboard=`usbg_create_function $gadget "hid" "usb0" f_attrs_keyboard` 192 | 193 | desc="" 194 | desc+="\x05""\x01" # USAGE_PAGE (Generic Desktop) 195 | desc+="\x09""\x02" # USAGE (Mouse) 196 | desc+="\xA1""\x01" # COLLECTION (Application) 197 | desc+="\x09""\x01" # USAGE (Pointer) 198 | desc+="\xA1""\x00" # COLLECTION (Physical) 199 | desc+="\x85""\x03" # Report ID (3) 200 | desc+="\x05""\x09" # USAGE_PAGE (Button) 201 | desc+="\x19""\x01" # USAGE_MINIMUM (Button 1) 202 | desc+="\x29""\x03" # USAGE_MAXIMUM (Button 3) 203 | desc+="\x15""\x00" # LOGICAL_MINIMUM (0) 204 | desc+="\x25""\x01" # LOGICAL_MAXIMUM (1) 205 | desc+="\x95""\x03" # REPORT_COUNT (3) 206 | desc+="\x75""\x01" # REPORT_SIZE (1) 207 | desc+="\x81""\x02" # INPUT (Data,Var,Abs) 208 | desc+="\x95""\x01" # REPORT_COUNT (1) 209 | desc+="\x75""\x05" # REPORT_SIZE (5) 210 | desc+="\x81""\x03" # INPUT (Cnst,Var,Abs) 211 | desc+="\x05""\x01" # USAGE_PAGE (Generic Desktop) 212 | desc+="\x09""\x30" # USAGE (X) 213 | desc+="\x09""\x31" # USAGE (Y) 214 | desc+="\x09""\x38" # USAGE (WHEEL) 215 | desc+="\x15""\x81" # LOGICAL_MINIMUM (-127) 216 | desc+="\x25""\x7F" # LOGICAL_MAXIMUM (127) 217 | desc+="\x75""\x08" # REPORT_SIZE (8) 218 | desc+="\x95""\x03" # REPORT_COUNT (3) 219 | desc+="\x81""\x06" # INPUT (Data,Var,Rel) 220 | desc+="\xC0" # END_COLLECTION 221 | desc+="\xC0" # END_COLLECTION 222 | 223 | declare -A f_attrs_mouse 224 | f_attrs_mouse["protocol"]="2" 225 | f_attrs_mouse["report_desc"]=$desc 226 | f_attrs_mouse["report_length"]="16" 227 | f_attrs_mouse["subclass"]="0" 228 | 229 | f_hid_mouse=`usbg_create_function $gadget "hid" "usb1" f_attrs_mouse` 230 | 231 | declare -A c_strs 232 | c_strs["configuration"]="2xHID" 233 | 234 | config=`usbg_create_config $gadget "1" "config" c_strs` 235 | 236 | usbg_add_config_function $config "keyboard" $f_hid_keyboard 237 | usbg_add_config_function $config "mouse" $f_hid_mouse 238 | 239 | usbg_enable_gadget $gadget 240 | 241 | exit 242 | -------------------------------------------------------------------------------- /misc/99-bluetooth.rules: -------------------------------------------------------------------------------- 1 | KERNEL=="event*", ATTRS{name}=="Microsoft Wedge Mobile Keyboard", TAG+="systemd", SYMLINK+="input/keyboard", ENV{SYSTEMD_ALIAS}="/sys/class/input/keyboard" 2 | 3 | KERNEL=="event*", ATTRS{name}=="Microsoft Sculpt Comfort Mouse", TAG+="systemd", SYMLINK+="input/mouse", ENV{SYSTEMD_ALIAS}="/sys/class/input/mouse" 4 | -------------------------------------------------------------------------------- /misc/event2usbhid_keyboard.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Keyboard Event Device to USB HID 3 | After=network.target 4 | BindsTo=sys-class-input-keyboard.device 5 | After=sys-class-input-keyboard.device 6 | Requires=mkusbhid.service 7 | 8 | [Service] 9 | ExecStart=/bin/sh -c "/opt/event2usbhid/bin/event2usbhid keyboard < /dev/input/keyboard > /dev/hidg0" 10 | Restart=always 11 | StandardOutput=journal 12 | StandardError=journal 13 | 14 | [Install] 15 | WantedBy=sys-class-input-keyboard.device 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /misc/event2usbhid_mouse.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Mouse Event Device to USB HID 3 | After=network.target 4 | BindsTo=sys-class-input-mouse.device 5 | After=sys-class-input-mouse.device 6 | Requires=mkusbhid.service 7 | 8 | [Service] 9 | ExecStart=/bin/sh -c "/opt/event2usbhid/bin/event2usbhid mouse < /dev/input/mouse > /dev/hidg1" 10 | Restart=always 11 | StandardOutput=journal 12 | StandardError=journal 13 | 14 | [Install] 15 | WantedBy=sys-class-input-mouse.device 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /misc/mkusbhid.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Event Device 2 USB HID Initializer 3 | After=network.target 4 | 5 | [Service] 6 | ExecStart=/opt/event2usbhid/bin/mkusbhid 7 | Type=oneshot 8 | StandardOutput=journal 9 | StandardError=journal 10 | 11 | [Install] 12 | WantedBy=multi-user.target 13 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | all: ../bin/event2usbhid 2 | 3 | ../bin/event2usbhid: main.c keyboard.c mouse.c 4 | $(CC) -o ../bin/event2usbhid main.c keyboard.c mouse.c 5 | -------------------------------------------------------------------------------- /src/keyboard.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | //! eventファイル→USB HIDのキーコード変換表 11 | unsigned short linux_to_usb[] = { 12 | 0x00, 0x29, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 13 | 0x26, 0x27, 0x2D, 0x2E, 0x2A, 0x2B, 0x14, 0x1A, 0x08, 0x15, 14 | 0x17, 0x1C, 0x18, 0x0C, 0x12, 0x13, 0x2F, 0x30, 0x28, 0xe0, 15 | 0x04, 0x16, 0x07, 0x09, 0x0A, 0x0B, 0x0D, 0x0E, 0x0F, 0x33, 16 | 0x34, 0x35, 0xE1, 0x32, 0x1D, 0x1B, 0x06, 0x19, 0x05, 0x11, 17 | 0x10, 0x36, 0x37, 0x38, 0xE5, 0x55, 0xE2, 0x2C, 0x39, 0x3A, 18 | 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x53, 19 | 0x47, 0x5F, 0x60, 0x61, 0x56, 0x5C, 0x5D, 0x5E, 0x57, 0x59, 20 | 0x5A, 0x5B, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44, 0x45, 0x87, 21 | 0x6A, 0x00, 0x8A, 0x88, 0x8B, 0x00, 0x58, 0xE4, 0x54, 0x46, 22 | 0xE6, 0x00, 0x4A, 0x52, 0x4B, 0x50, 0x4F, 0x4D, 0x51, 0x4E, 23 | 0x49, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 24 | 0x00, 0x00, 0x00, 0x00, 0x89, 0xE3, 0xE7, 0x65 25 | }; 26 | 27 | 28 | /** 29 | * @fn 30 | * @brief /dev/input/eventNからイベントを読み込む 31 | * 32 | * @param[out] event 読み込んだイベントを書き込むポインタ 33 | */ 34 | void getKeyboardEvent(struct input_event *event) { 35 | 36 | // 有効なイベントが取れるまでブロックする 37 | while(1) { 38 | read(0, event, sizeof(*event)); 39 | 40 | // キーイベント以外は無視する 41 | if (event->type != EV_KEY) { 42 | continue; 43 | } 44 | 45 | // キーリピートは無視する 46 | if (event->value == 2) { 47 | continue; 48 | } 49 | 50 | break; 51 | } 52 | } 53 | 54 | 55 | /** 56 | * @fn 57 | * @brief キーを離した時の処理 58 | * 59 | * @param[in] hid_code 離したUSB HIDのキーコード 60 | * @param[in,out] pressed_keys 押しているキーの配列 61 | * 62 | * @return 指定したキーが押されていた:1、押されていなかった:0 63 | */ 64 | int releaseKey(unsigned short hid_code, unsigned short *pressed_keys){ 65 | int x; 66 | 67 | for(x = 0; x < 14; x++){ 68 | if(pressed_keys[x] == hid_code){ 69 | pressed_keys[x] = 0; 70 | return 1; 71 | } 72 | } 73 | 74 | return 0; 75 | } 76 | 77 | 78 | /** 79 | * @fn 80 | * @brief キーを押したときの処理 81 | * 82 | * @param[in] hid_code 押したUSB HIDのキーコード 83 | * @param[in,out] pressed_keys 押しているキーの配列 84 | */ 85 | void pressKey(unsigned short hid_code, unsigned short *pressed_keys){ 86 | int x; 87 | 88 | for(x = 0; x < 14; x++){ 89 | if(pressed_keys[x] == 0){ 90 | pressed_keys[x] = hid_code; 91 | return; 92 | } 93 | } 94 | } 95 | 96 | 97 | /** 98 | * @fn 99 | * @brief libcompositeにキーボードイベントを書き込む 100 | * 101 | * @param[in] modifiers CTRLとかSHIFTとかの押され具合 102 | * @param[in] pressed_keys 押しているキーの配列 103 | */ 104 | void sendKeyboardHIDReport(char modifiers, unsigned short *pressed_keys){ 105 | int x; 106 | unsigned char buf[16]; 107 | 108 | memset(buf, 0, sizeof(buf)); 109 | 110 | buf[0] = 1; // report ID 111 | buf[1] = modifiers; 112 | buf[2] = 0; // padding 113 | 114 | for(x = 3; x < 16; x++){ 115 | buf[x] = pressed_keys[x - 3]; 116 | } 117 | 118 | write(1, buf, sizeof(buf)); 119 | } 120 | 121 | 122 | /** 123 | * @fn 124 | * @brief キーボード変換処理 125 | */ 126 | void keyboard() { 127 | unsigned short pressed_keys[14]; 128 | 129 | memset(pressed_keys, 0, sizeof(pressed_keys)); 130 | 131 | while(1) { 132 | struct input_event event; 133 | 134 | getKeyboardEvent(&event); 135 | 136 | unsigned short usb_keycode = linux_to_usb[event.code]; 137 | 138 | if (event.value == 1) { 139 | pressKey(usb_keycode, pressed_keys); 140 | } else { 141 | releaseKey(usb_keycode, pressed_keys); 142 | } 143 | 144 | sendKeyboardHIDReport(0, pressed_keys); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // プロトタイプ宣言 5 | void keyboard(); 6 | void mouse(); 7 | 8 | 9 | /** 10 | * @fn 11 | * @brief 使い方表示 12 | * 13 | * @param[in] exe_name 実行可能ファイルのファイル名 14 | */ 15 | void usage(char *exe_name) { 16 | fprintf(stderr, "Usage: %s [keyboard|mouse] < /dev/input/eventN > /dev/hidgN\n", exe_name); 17 | } 18 | 19 | 20 | /** 21 | * @fn 22 | * @brief メイン処理 23 | * 24 | * @param[in] コマンドライン引数の数 25 | * @param[in] コマンドライン引数 26 | * 27 | * @return 0:正常終了、1:エラー終了 28 | */ 29 | int main(int argc, char *argv[]) { 30 | if (argc != 2) { 31 | usage(argv[0]); 32 | return 1; 33 | } 34 | 35 | int keyboard_flag = strncmp(argv[1], "keyboard", strlen("keyboard")); 36 | int mouse_flag = strncmp(argv[1], "mouse", strlen("mouse")); 37 | 38 | if ((keyboard_flag != 0) && (mouse_flag != 0)) { 39 | usage(argv[0]); 40 | return 1; 41 | } 42 | 43 | if (keyboard_flag == 0) { 44 | keyboard(); 45 | } else { 46 | mouse(); 47 | } 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /src/mouse.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /** 10 | * @fn 11 | * @brief /dev/input/eventNからイベントを読み込む 12 | * 13 | * @param[out] event 読み込んだイベントを書き込むポインタ 14 | */ 15 | void getMouseEvent(struct input_event *event) { 16 | read(0, event, sizeof(*event)); 17 | } 18 | 19 | 20 | /** 21 | * @fn 22 | * @brief libcompositeにマウスイベントを書き込む 23 | * 24 | * @param[in] buttons マウスボタンの押され具合 25 | * @param[in] x X座標の移動量 26 | * @param[in] y Y座標の移動量 27 | * @param[in] wheel ホイールの移動量 28 | */ 29 | void sendMouseReport(int buttons, int x, int y, int wheel){ 30 | unsigned char buf[5]; 31 | buf[0] = 3; 32 | buf[1] = buttons; 33 | buf[2] = x; 34 | buf[3] = y; 35 | buf[4] = wheel; 36 | 37 | write(1, buf, sizeof(buf)); 38 | } 39 | 40 | 41 | /** 42 | * @fn 43 | * @brief マウス処理 44 | */ 45 | void mouse() { 46 | int x = 0; 47 | int y = 0; 48 | int wheel = 0; 49 | int buttons = 0; 50 | 51 | while(1) { 52 | struct input_event event; 53 | 54 | getMouseEvent(&event); 55 | 56 | // カーソル/ホイールイベント 57 | if (event.type == EV_REL) { 58 | // X座標の移動量をクリッピング 59 | if (event.code == REL_X) { 60 | int value; 61 | 62 | if (event.value > 127) { 63 | value = 127; 64 | } else { 65 | value = event.value; 66 | } 67 | 68 | if (event.value < -127) { 69 | value = -127; 70 | } else { 71 | value = event.value; 72 | } 73 | 74 | x = value; 75 | 76 | // Y座標の移動量をクリッピング 77 | } else if(event.code == REL_Y) { 78 | int value; 79 | 80 | if (event.value > 127) { 81 | value = 127; 82 | } else { 83 | value = event.value; 84 | } 85 | 86 | if (event.value < -127) { 87 | value = -127; 88 | } else { 89 | value = event.value; 90 | } 91 | 92 | y = value; 93 | 94 | // ホイールの移動量をクリッピング 95 | } else if(event.code == 11) { 96 | int value; 97 | 98 | if (event.value > 127) { 99 | value = 127; 100 | } else { 101 | value = event.value; 102 | } 103 | 104 | if (event.value < -127) { 105 | value = -127; 106 | } else { 107 | value = event.value; 108 | } 109 | 110 | // なぜか1カチ=120のため 111 | wheel = value / 120; 112 | 113 | } 114 | 115 | // マウスボタンイベント 116 | } else if(event.type == EV_KEY) { 117 | if(event.code == BTN_LEFT) { 118 | if(event.value == 1) { 119 | buttons |= 1; 120 | } else { 121 | buttons &= ~1; 122 | } 123 | } 124 | 125 | if(event.code == BTN_RIGHT) { 126 | if(event.value == 1) { 127 | buttons |= 2; 128 | } else { 129 | buttons &= ~2; 130 | } 131 | } 132 | 133 | if(event.code == BTN_MIDDLE) { 134 | if(event.value == 1) { 135 | buttons |= 4; 136 | } else { 137 | buttons &= ~4; 138 | } 139 | } 140 | 141 | // 現状を送信する 142 | sendMouseReport(buttons, x, y, wheel); 143 | 144 | x = 0; 145 | y = 0; 146 | wheel = 0; 147 | 148 | // 同期イベント? 149 | } else if((event.code == 0) && (event.type == 0) && (event.value == 0)) { 150 | 151 | // 現状を送信する 152 | sendMouseReport(buttons, x, y, wheel); 153 | x = 0; 154 | y = 0; 155 | wheel = 0; 156 | } 157 | } 158 | } 159 | --------------------------------------------------------------------------------