diff options
author | Devaev Maxim <[email protected]> | 2020-11-15 23:16:46 +0300 |
---|---|---|
committer | Devaev Maxim <[email protected]> | 2020-11-15 23:16:46 +0300 |
commit | f5250bb0e90b005128bd5025604cc41d3c3f7392 (patch) | |
tree | 75fc6b4d1e89c0dcb0727fa7e16d961d0f8c2fd8 | |
parent | d99771b2cd0110c9a5fcf9279184451c51a2d120 (diff) |
display endpoints state
-rw-r--r-- | hid/src/main.cpp | 33 | ||||
-rw-r--r-- | hid/src/proto.h | 12 | ||||
-rw-r--r-- | hid/src/ps2/hid.h | 4 | ||||
-rw-r--r-- | hid/src/usb/hid.h | 28 | ||||
-rw-r--r-- | kvmd/plugins/hid/_mcu/__init__.py | 50 |
5 files changed, 82 insertions, 45 deletions
diff --git a/hid/src/main.cpp b/hid/src/main.cpp index 1bcd2162..f87c719f 100644 --- a/hid/src/main.cpp +++ b/hid/src/main.cpp @@ -59,19 +59,30 @@ // ----------------------------------------------------------------------------- -uint8_t cmdResetHid(const uint8_t *buffer) { // 0 bytes +uint8_t cmdPong(const uint8_t *_=NULL) { // 0 bytes + return ( + ((uint8_t)PROTO_RESP_PONG_PREFIX) + | hid_kbd.getLedsAs(PROTO_RESP_PONG_CAPS, PROTO_RESP_PONG_SCROLL, PROTO_RESP_PONG_NUM) + | (hid_kbd.isOnline() ? 0 : PROTO_RESP_PONG_KEYBOARD_OFFLINE) +# ifdef HID_USB_MOUSE + | (hid_mouse.isOnline() ? 0 : PROTO_RESP_PONG_MOUSE_OFFLINE) +# endif + ); +} + +uint8_t cmdResetHid(const uint8_t *_) { // 0 bytes # ifdef HID_USB_KBD hid_kbd.reset(); # endif # ifdef HID_USB_MOUSE hid_mouse.reset(); # endif - return PROTO_RESP_OK; + return cmdPong(); } uint8_t cmdKeyEvent(const uint8_t *buffer) { // 2 bytes hid_kbd.sendKey(buffer[0], buffer[1]); - return PROTO_RESP_OK; + return cmdPong(); } uint8_t cmdMouseButtonEvent(const uint8_t *buffer) { // 2 bytes @@ -91,7 +102,7 @@ uint8_t cmdMouseButtonEvent(const uint8_t *buffer) { // 2 bytes ); # undef MOUSE_PAIR # endif - return PROTO_RESP_OK; + return cmdPong(); } uint8_t cmdMouseMoveEvent(const uint8_t *buffer) { // 4 bytes @@ -106,22 +117,14 @@ uint8_t cmdMouseMoveEvent(const uint8_t *buffer) { // 4 bytes hid_mouse.sendMove(x, y); # endif - return PROTO_RESP_OK; + return cmdPong(); } uint8_t cmdMouseWheelEvent(const uint8_t *buffer) { // 2 bytes # ifdef HID_USB_MOUSE hid_mouse.sendWheel(buffer[1]); // Y only, X is not supported # endif - return PROTO_RESP_OK; -} - -uint8_t cmdPongLeds(const uint8_t *buffer) { // 0 bytes - return ((uint8_t) PROTO_RESP_PONG_PREFIX) | hid_kbd.getLedsAs( - PROTO_RESP_PONG_CAPS, - PROTO_RESP_PONG_SCROLL, - PROTO_RESP_PONG_NUM - ); + return cmdPong(); } uint8_t handleCmdBuffer(const uint8_t *buffer) { // 8 bytes @@ -136,7 +139,7 @@ uint8_t handleCmdBuffer(const uint8_t *buffer) { // 8 bytes case PROTO_CMD_MOUSE_BUTTON_EVENT: HANDLE(cmdMouseButtonEvent); case PROTO_CMD_MOUSE_MOVE_EVENT: HANDLE(cmdMouseMoveEvent); case PROTO_CMD_MOUSE_WHEEL_EVENT: HANDLE(cmdMouseWheelEvent); - case PROTO_CMD_PING: HANDLE(cmdPongLeds); + case PROTO_CMD_PING: HANDLE(cmdPong); case PROTO_CMD_REPEAT: return 0; default: return PROTO_RESP_INVALID_ERROR; } diff --git a/hid/src/proto.h b/hid/src/proto.h index 36502d4f..617711dd 100644 --- a/hid/src/proto.h +++ b/hid/src/proto.h @@ -26,16 +26,18 @@ #define PROTO_MAGIC 0x33 #define PROTO_CRC_POLINOM 0xA001 -#define PROTO_RESP_OK 0x20 +// #define PROTO_RESP_OK 0x20 // Legacy #define PROTO_RESP_NONE 0x24 #define PROTO_RESP_CRC_ERROR 0x40 #define PROTO_RESP_INVALID_ERROR 0x45 #define PROTO_RESP_TIMEOUT_ERROR 0x48 -#define PROTO_RESP_PONG_PREFIX 0x80 -#define PROTO_RESP_PONG_CAPS 0b00000001 -#define PROTO_RESP_PONG_SCROLL 0b00000010 -#define PROTO_RESP_PONG_NUM 0b00000100 +#define PROTO_RESP_PONG_PREFIX 0x80 +#define PROTO_RESP_PONG_CAPS 0b00000001 +#define PROTO_RESP_PONG_SCROLL 0b00000010 +#define PROTO_RESP_PONG_NUM 0b00000100 +#define PROTO_RESP_PONG_KEYBOARD_OFFLINE 0b00001000 +#define PROTO_RESP_PONG_MOUSE_OFFLINE 0b00010000 #define PROTO_CMD_PING 0x01 #define PROTO_CMD_REPEAT 0x02 diff --git a/hid/src/ps2/hid.h b/hid/src/ps2/hid.h index eca2bf4b..3f226090 100644 --- a/hid/src/ps2/hid.h +++ b/hid/src/ps2/hid.h @@ -41,6 +41,10 @@ class Ps2HidKeyboard { _dev.keyboard_init(); } + bool isOnline() { + return true; + } + void periodic() { _dev.keyboard_handle(&_leds); } diff --git a/hid/src/usb/hid.h b/hid/src/usb/hid.h index f0016931..d48d0fc2 100644 --- a/hid/src/usb/hid.h +++ b/hid/src/usb/hid.h @@ -40,9 +40,9 @@ static bool _checkEndpoint(uint8_t ep) { SREG = intr_state; return rw_allowed; } -# define CHECK_HID_EP(_hid) { if (!_checkEndpoint(_hid.getPluggedEndpoint())) return; } +# define CHECK_HID_EP { if (!isOnline()) return; } #else -# define CHECK_HID_EP(_hid) +# define CHECK_HID_EP #endif class UsbHidKeyboard { @@ -53,12 +53,20 @@ class UsbHidKeyboard { BootKeyboard.begin(); } + bool isOnline() { +# ifdef CHECK_ENDPOINT + return _checkEndpoint(BootKeyboard.getPluggedEndpoint()); +# else + return true; +# endif + } + void reset() { BootKeyboard.releaseAll(); } void sendKey(uint8_t code, bool state) { - CHECK_HID_EP(BootKeyboard); + CHECK_HID_EP; KeyboardKeycode usb_code = keymapUsb(code); if (usb_code != KEY_ERROR_UNDEFINED) { if (state) BootKeyboard.press(usb_code); @@ -85,6 +93,14 @@ class UsbHidMouse { SingleAbsoluteMouse.begin(); } + bool isOnline() { +# ifdef CHECK_ENDPOINT + return _checkEndpoint(SingleAbsoluteMouse.getPluggedEndpoint()); +# else + return true; +# endif + } + void reset() { SingleAbsoluteMouse.releaseAll(); } @@ -104,19 +120,19 @@ class UsbHidMouse { } void sendMove(int x, int y) { - CHECK_HID_EP(SingleAbsoluteMouse); + CHECK_HID_EP; SingleAbsoluteMouse.moveTo(x, y); } void sendWheel(int delta_y) { - CHECK_HID_EP(SingleAbsoluteMouse); + CHECK_HID_EP; // delta_x is not supported by hid-project now SingleAbsoluteMouse.move(0, 0, delta_y); } private: void _sendButton(uint8_t button, bool state) { - CHECK_HID_EP(SingleAbsoluteMouse); + CHECK_HID_EP; if (state) SingleAbsoluteMouse.press(button); else SingleAbsoluteMouse.release(button); } diff --git a/kvmd/plugins/hid/_mcu/__init__.py b/kvmd/plugins/hid/_mcu/__init__.py index 48ba8fde..b46c876d 100644 --- a/kvmd/plugins/hid/_mcu/__init__.py +++ b/kvmd/plugins/hid/_mcu/__init__.py @@ -59,10 +59,9 @@ from .gpio import Gpio # ===== class _RequestError(Exception): - def __init__(self, msg: str, online: bool=False) -> None: + def __init__(self, msg: str) -> None: super().__init__(msg) self.msg = msg - self.online = online class _PermRequestError(_RequestError): @@ -197,7 +196,8 @@ class BaseMcuHid(BaseHid, multiprocessing.Process): # pylint: disable=too-many- self.__notifier = aiomulti.AioProcessNotifier() self.__state_flags = aiomulti.AioSharedFlags({ - "online": True, + "keyboard_online": True, + "mouse_online": True, "caps": False, "scroll": False, "num": False, @@ -227,9 +227,9 @@ class BaseMcuHid(BaseHid, multiprocessing.Process): # pylint: disable=too-many- async def get_state(self) -> Dict: state = await self.__state_flags.get() return { - "online": state["online"], + "online": (state["keyboard_online"] and state["mouse_online"]), "keyboard": { - "online": state["online"], + "online": state["keyboard_online"], "leds": { "caps": state["caps"], "scroll": state["scroll"], @@ -237,7 +237,7 @@ class BaseMcuHid(BaseHid, multiprocessing.Process): # pylint: disable=too-many- }, }, "mouse": { - "online": state["online"], + "online": state["mouse_online"], "absolute": True, }, } @@ -361,26 +361,19 @@ class BaseMcuHid(BaseHid, multiprocessing.Process): # pylint: disable=too-many- elif code == 0x40: # CRC Error raise _TempRequestError(f"Got CRC error of request from HID: request={request!r}") elif code == 0x45: # Unknown command - raise _PermRequestError(f"HID did not recognize the request={request!r}", online=True) + raise _PermRequestError(f"HID did not recognize the request={request!r}") elif code == 0x24: # Rebooted? - raise _PermRequestError("No previous command state inside HID, seems it was rebooted", online=True) - elif code == 0x20: # Done - self.__state_flags.update(online=True) + raise _PermRequestError("No previous command state inside HID, seems it was rebooted") + elif code == 0x20: # Legacy done + self.__set_state_online(True) return True - elif code & 0x80: # Pong with leds - self.__state_flags.update( - online=True, - caps=bool(code & 0b00000001), - scroll=bool(code & 0x00000010), - num=bool(code & 0x00000100), - ) + elif code & 0x80: # Pong/Done with state + self.__set_state_code(code) return True raise _TempRequestError(f"Invalid response from HID: request={request!r}; code=0x{code:02X}") except _RequestError as err: common_retries -= 1 - self.__state_flags.update(online=err.online) - error_retval = err.online if live_log_errors: logger.error(err.msg) @@ -393,7 +386,11 @@ class BaseMcuHid(BaseHid, multiprocessing.Process): # pylint: disable=too-many- live_log_errors = True if isinstance(err, _PermRequestError): + error_retval = True break + + self.__set_state_online(False) + if common_retries and read_retries: time.sleep(self.__retries_delay) @@ -403,6 +400,21 @@ class BaseMcuHid(BaseHid, multiprocessing.Process): # pylint: disable=too-many- logger.error("Can't process HID request due many errors: %r", request) return error_retval + def __set_state_online(self, online: bool) -> None: + self.__state_flags.update( + keyboard_online=online, + mouse_online=online, + ) + + def __set_state_code(self, code: int) -> None: + self.__state_flags.update( + keyboard_online=(not (code & 0b00001000)), + mouse_online=(not (code & 0b00010000)), + caps=bool(code & 0b00000001), + scroll=bool(code & 0b00000010), + num=bool(code & 0b00000100), + ) + def __send_request(self, conn: BasePhyConnection, request: bytes) -> bytes: if not self.__noop: response = conn.send(request) |