diff --git a/core/hostevents_sdl.cpp b/core/hostevents_sdl.cpp
index 1f245d0..2c049af 100644
--- a/core/hostevents_sdl.cpp
+++ b/core/hostevents_sdl.cpp
@@ -22,10 +22,14 @@ along with this program. If not, see .
#include
#include
#include
+#include
+#include
#include
EventManager* EventManager::event_manager;
+static int get_sdl_event_key_code(const SDL_KeyboardEvent &event);
+
void EventManager::poll_events()
{
SDL_Event event;
@@ -47,11 +51,28 @@ void EventManager::poll_events()
break;
case SDL_KEYDOWN:
- key_downs++;
- break;
-
- case SDL_KEYUP:
- key_ups++;
+ case SDL_KEYUP: {
+ int key_code = get_sdl_event_key_code(event.key);
+ if (key_code != -1) {
+ KeyboardEvent ke;
+ ke.key = key_code;
+ if (event.type == SDL_KEYDOWN) {
+ ke.flags = KEYBOARD_EVENT_DOWN;
+ key_downs++;
+ } else {
+ ke.flags = KEYBOARD_EVENT_UP;
+ key_ups++;
+ }
+ // Caps Lock is a special case, since it's a toggle key
+ if (ke.key == AdbKey_CapsLock) {
+ ke.flags = SDL_GetModState() & KMOD_CAPS ?
+ KEYBOARD_EVENT_DOWN : KEYBOARD_EVENT_UP;
+ }
+ this->_keyboard_signal.emit(ke);
+ } else {
+ LOG_F(WARNING, "Unknow key %x pressed", event.key.keysym.sym);
+ }
+ }
break;
case SDL_MOUSEMOTION: {
@@ -87,3 +108,138 @@ void EventManager::poll_events()
// perform post-processing
this->_post_signal.emit();
}
+
+
+static int get_sdl_event_key_code(const SDL_KeyboardEvent &event)
+{
+ switch (event.keysym.sym) {
+ case SDLK_a: return AdbKey_A;
+ case SDLK_b: return AdbKey_B;
+ case SDLK_c: return AdbKey_C;
+ case SDLK_d: return AdbKey_D;
+ case SDLK_e: return AdbKey_E;
+ case SDLK_f: return AdbKey_F;
+ case SDLK_g: return AdbKey_G;
+ case SDLK_h: return AdbKey_H;
+ case SDLK_i: return AdbKey_I;
+ case SDLK_j: return AdbKey_J;
+ case SDLK_k: return AdbKey_K;
+ case SDLK_l: return AdbKey_L;
+ case SDLK_m: return AdbKey_M;
+ case SDLK_n: return AdbKey_N;
+ case SDLK_o: return AdbKey_O;
+ case SDLK_p: return AdbKey_P;
+ case SDLK_q: return AdbKey_Q;
+ case SDLK_r: return AdbKey_R;
+ case SDLK_s: return AdbKey_S;
+ case SDLK_t: return AdbKey_T;
+ case SDLK_u: return AdbKey_U;
+ case SDLK_v: return AdbKey_V;
+ case SDLK_w: return AdbKey_W;
+ case SDLK_x: return AdbKey_X;
+ case SDLK_y: return AdbKey_Y;
+ case SDLK_z: return AdbKey_Z;
+
+ case SDLK_1: return AdbKey_1;
+ case SDLK_2: return AdbKey_2;
+ case SDLK_3: return AdbKey_3;
+ case SDLK_4: return AdbKey_4;
+ case SDLK_5: return AdbKey_5;
+ case SDLK_6: return AdbKey_6;
+ case SDLK_7: return AdbKey_7;
+ case SDLK_8: return AdbKey_8;
+ case SDLK_9: return AdbKey_9;
+ case SDLK_0: return AdbKey_0;
+
+ case SDLK_ESCAPE: return AdbKey_Escape;
+ case SDLK_BACKQUOTE: return AdbKey_Grave;
+ case SDLK_MINUS: return AdbKey_Minus;
+ case SDLK_EQUALS: return AdbKey_Equal;
+ case SDLK_LEFTBRACKET: return AdbKey_LeftBracket;
+ case SDLK_RIGHTBRACKET: return AdbKey_RightBracket;
+ case SDLK_BACKSLASH: return AdbKey_Backslash;
+ case SDLK_SEMICOLON: return AdbKey_Semicolon;
+ case SDLK_QUOTE: return AdbKey_Quote;
+ case SDLK_COMMA: return AdbKey_Comma;
+ case SDLK_PERIOD: return AdbKey_Period;
+ case SDLK_SLASH: return AdbKey_Slash;
+
+ // Convert shifted variants to unshifted
+ case SDLK_EXCLAIM: return AdbKey_1;
+ case SDLK_AT: return AdbKey_2;
+ case SDLK_HASH: return AdbKey_3;
+ case SDLK_DOLLAR: return AdbKey_4;
+ case SDLK_UNDERSCORE: return AdbKey_Minus;
+ case SDLK_PLUS: return AdbKey_Equal;
+ case SDLK_COLON: return AdbKey_Semicolon;
+ case SDLK_QUOTEDBL: return AdbKey_Quote;
+ case SDLK_LESS: return AdbKey_Comma;
+ case SDLK_GREATER: return AdbKey_Period;
+ case SDLK_QUESTION: return AdbKey_Slash;
+
+ case SDLK_TAB: return AdbKey_Tab;
+ case SDLK_RETURN: return AdbKey_Return;
+ case SDLK_SPACE: return AdbKey_Space;
+ case SDLK_BACKSPACE: return AdbKey_Delete;
+
+ case SDLK_DELETE: return AdbKey_ForwardDelete;
+ case SDLK_INSERT: return AdbKey_Help;
+ case SDLK_HOME: return AdbKey_Home;
+ case SDLK_HELP: return AdbKey_Home;
+ case SDLK_END: return AdbKey_End;
+ case SDLK_PAGEUP: return AdbKey_PageUp;
+ case SDLK_PAGEDOWN: return AdbKey_PageDown;
+
+ case SDLK_LCTRL: return AdbKey_Control;
+ case SDLK_RCTRL: return AdbKey_Control;
+ case SDLK_LSHIFT: return AdbKey_Shift;
+ case SDLK_RSHIFT: return AdbKey_Shift;
+ case SDLK_LALT: return AdbKey_Option;
+ case SDLK_RALT: return AdbKey_Option;
+ case SDLK_LGUI: return AdbKey_Command;
+ case SDLK_RGUI: return AdbKey_Command;
+ case SDLK_MENU: return AdbKey_Grave;
+ case SDLK_CAPSLOCK: return AdbKey_CapsLock;
+
+ case SDLK_UP: return AdbKey_ArrowUp;
+ case SDLK_DOWN: return AdbKey_ArrowDown;
+ case SDLK_LEFT: return AdbKey_ArrowLeft;
+ case SDLK_RIGHT: return AdbKey_ArrowRight;
+;
+ case SDLK_KP_0: return AdbKey_Keypad0;
+ case SDLK_KP_1: return AdbKey_Keypad1;
+ case SDLK_KP_2: return AdbKey_Keypad2;
+ case SDLK_KP_3: return AdbKey_Keypad3;
+ case SDLK_KP_4: return AdbKey_Keypad4;
+ case SDLK_KP_5: return AdbKey_Keypad5;
+ case SDLK_KP_6: return AdbKey_Keypad6;
+ case SDLK_KP_7: return AdbKey_Keypad7;
+ case SDLK_KP_9: return AdbKey_Keypad9;
+ case SDLK_KP_8: return AdbKey_Keypad8;
+ case SDLK_KP_PERIOD: return AdbKey_KeypadDecimal;
+ case SDLK_KP_PLUS: return AdbKey_KeypadPlus;
+ case SDLK_KP_MINUS: return AdbKey_KeypadMinus;
+ case SDLK_KP_MULTIPLY: return AdbKey_KeypadMultiply;
+ case SDLK_KP_DIVIDE: return AdbKey_KeypadDivide;
+ case SDLK_KP_ENTER: return AdbKey_KeypadEnter;
+ case SDLK_KP_EQUALS: return AdbKey_KeypadEquals;
+ case SDLK_NUMLOCKCLEAR: return AdbKey_KeypadClear;
+;
+ case SDLK_F1: return AdbKey_F1;
+ case SDLK_F2: return AdbKey_F2;
+ case SDLK_F3: return AdbKey_F3;
+ case SDLK_F4: return AdbKey_F4;
+ case SDLK_F5: return AdbKey_F5;
+ case SDLK_F6: return AdbKey_F6;
+ case SDLK_F7: return AdbKey_F7;
+ case SDLK_F8: return AdbKey_F8;
+ case SDLK_F9: return AdbKey_F9;
+ case SDLK_F10: return AdbKey_F10;
+ case SDLK_F11: return AdbKey_F11;
+ case SDLK_F12: return AdbKey_F12;
+ case SDLK_PRINTSCREEN: return AdbKey_F13;
+ case SDLK_SCROLLLOCK: return AdbKey_F14;
+ case SDLK_PAUSE: return AdbKey_F15;
+ }
+ return -1;
+}
diff --git a/devices/common/adb/adbbus.cpp b/devices/common/adb/adbbus.cpp
index c67a379..be94dfa 100644
--- a/devices/common/adb/adbbus.cpp
+++ b/devices/common/adb/adbbus.cpp
@@ -36,6 +36,16 @@ void AdbBus::register_device(AdbDevice* dev_obj) {
this->devices.push_back(dev_obj);
}
+uint8_t AdbBus::poll() {
+ for (auto dev : this->devices) {
+ uint8_t dev_poll = dev->poll();
+ if (dev_poll) {
+ return dev_poll;
+ }
+ }
+ return 0;
+}
+
uint8_t AdbBus::process_command(const uint8_t* in_data, int data_size) {
uint8_t dev_addr, dev_reg;
@@ -76,8 +86,12 @@ uint8_t AdbBus::process_command(const uint8_t* in_data, int data_size) {
this->got_answer = false;
- for (auto dev : this->devices)
+ for (auto dev : this->devices) {
this->got_answer = dev->talk(dev_addr, dev_reg);
+ if (this->got_answer) {
+ break;
+ }
+ }
if (!this->got_answer)
return ADB_STAT_TIMEOUT;
diff --git a/devices/common/adb/adbbus.h b/devices/common/adb/adbbus.h
index baa91eb..6af3757 100644
--- a/devices/common/adb/adbbus.h
+++ b/devices/common/adb/adbbus.h
@@ -55,6 +55,11 @@ public:
uint8_t process_command(const uint8_t* in_data, int data_size);
uint8_t get_output_count() { return this->output_count; };
+ // Polls devices that have a service request flag set. Returns the talk
+ // command corresponding to the first device that responded with data, or
+ // 0 if no device responded.
+ uint8_t poll();
+
// callbacks meant to be called by devices
const uint8_t* get_input_buf() { return this->input_buf; };
uint8_t* get_output_buf() { return this->output_buf; };
diff --git a/devices/common/adb/adbdevice.cpp b/devices/common/adb/adbdevice.cpp
index 281322a..da8cdf8 100644
--- a/devices/common/adb/adbdevice.cpp
+++ b/devices/common/adb/adbdevice.cpp
@@ -39,6 +39,21 @@ int AdbDevice::device_postinit() {
return 0;
};
+uint8_t AdbDevice::poll() {
+ if (!this->srq_flag) {
+ return 0;
+ }
+ bool has_data = this->get_register_0();
+ if (!has_data) {
+ return 0;
+ }
+
+ // Register 0 in bits 0-1 (both 0)
+ // Talk command in bits 2-3 (both 1)
+ // Device address in bits 4-7
+ return 0xC | (this->my_addr << 4);
+}
+
bool AdbDevice::talk(const uint8_t dev_addr, const uint8_t reg_num) {
if (dev_addr == this->my_addr && !this->got_collision) {
// see if another device already responded to this command
diff --git a/devices/common/adb/adbdevice.h b/devices/common/adb/adbdevice.h
index e015266..d7a506b 100644
--- a/devices/common/adb/adbdevice.h
+++ b/devices/common/adb/adbdevice.h
@@ -49,6 +49,10 @@ public:
virtual void listen(const uint8_t dev_addr, const uint8_t reg_num);
virtual uint8_t get_address() { return this->my_addr; };
+ // Attempts to oolls the device. Returns the talk command corresponding to
+ // the device if it has data, 0 otherwise.
+ uint8_t poll();
+
protected:
uint8_t gen_random_address();
diff --git a/devices/common/adb/adbkeyboard.cpp b/devices/common/adb/adbkeyboard.cpp
index 53e008e..f401ed7 100644
--- a/devices/common/adb/adbkeyboard.cpp
+++ b/devices/common/adb/adbkeyboard.cpp
@@ -34,20 +34,45 @@ AdbKeyboard::AdbKeyboard(std::string name) : AdbDevice(name) {
}
void AdbKeyboard::event_handler(const KeyboardEvent& event) {
+ this->key = event.key;
if (event.flags & KEYBOARD_EVENT_DOWN) {
+ this->key_state = 0;
}
else if (event.flags & KEYBOARD_EVENT_UP) {
+ this->key_state = 1;
}
+ this->changed = true;
}
void AdbKeyboard::reset() {
this->my_addr = ADB_ADDR_KBD;
this->dev_handler_id = 2; // Extended ADB keyboard
- this->exc_event_flag = 2;
+ this->exc_event_flag = 1;
this->srq_flag = 1; // enable service requests
+ this->key = 0;
+ this->key_state = 0;
+ this->changed = false;
}
bool AdbKeyboard::get_register_0() {
+ if (this->changed) {
+ uint8_t* out_buf = this->host_obj->get_output_buf();
+
+ out_buf[0] = (this->key_state << 7) | (this->key & 0x7F);
+ // It's possible that we get two events before the host polls us, but
+ // in practice it has not come up. We need to set the key status bit to
+ // 1 (released), otherwise if we leave it empty, the host will think
+ // that the a key (code 0) is pressed.
+ out_buf[1] = 1 << 7;
+
+ this->key = 0;
+ this->key_state = 0;
+ this->changed = false;
+
+ this->host_obj->set_output_count(2);
+ return true;
+ }
+
return false;
}
diff --git a/devices/common/adb/adbkeyboard.h b/devices/common/adb/adbkeyboard.h
index c68201f..f0f5c8a 100644
--- a/devices/common/adb/adbkeyboard.h
+++ b/devices/common/adb/adbkeyboard.h
@@ -50,10 +50,122 @@ public:
private:
- int32_t x_rel = 0;
- int32_t y_rel = 0;
- uint8_t buttons_state = 0;
+ uint32_t key = 0;
+ uint8_t key_state = 0;
bool changed = false;
};
+// ADB Extended Keyboard raw key codes (most of which eventually became virtual
+// key codes, see HIToolbox/Events.h).
+enum AdbKey {
+ AdbKey_A = 0x00,
+ AdbKey_B = 0x0b,
+ AdbKey_C = 0x08,
+ AdbKey_D = 0x02,
+ AdbKey_E = 0x0e,
+ AdbKey_F = 0x03,
+ AdbKey_G = 0x05,
+ AdbKey_H = 0x04,
+ AdbKey_I = 0x22,
+ AdbKey_J = 0x26,
+ AdbKey_K = 0x28,
+ AdbKey_L = 0x25,
+ AdbKey_M = 0x2e,
+ AdbKey_N = 0x2d,
+ AdbKey_O = 0x1f,
+ AdbKey_P = 0x23,
+ AdbKey_Q = 0x0c,
+ AdbKey_R = 0x0f,
+ AdbKey_S = 0x01,
+ AdbKey_T = 0x11,
+ AdbKey_U = 0x20,
+ AdbKey_V = 0x09,
+ AdbKey_W = 0x0d,
+ AdbKey_X = 0x07,
+ AdbKey_Y = 0x10,
+ AdbKey_Z = 0x06,
+
+ AdbKey_1 = 0x12,
+ AdbKey_2 = 0x13,
+ AdbKey_3 = 0x14,
+ AdbKey_4 = 0x15,
+ AdbKey_5 = 0x17,
+ AdbKey_6 = 0x16,
+ AdbKey_7 = 0x1a,
+ AdbKey_8 = 0x1c,
+ AdbKey_9 = 0x19,
+ AdbKey_0 = 0x1d,
+
+ AdbKey_Minus = 0x1b,
+ AdbKey_Equal = 0x18,
+ AdbKey_LeftBracket = 0x21,
+ AdbKey_RightBracket = 0x1e,
+ AdbKey_Backslash = 0x2a,
+ AdbKey_Semicolon = 0x29,
+ AdbKey_Quote = 0x27,
+ AdbKey_Comma = 0x2b,
+ AdbKey_Period = 0x2f,
+ AdbKey_Slash = 0x2c,
+
+ AdbKey_Tab = 0x30,
+ AdbKey_Return = 0x24,
+ AdbKey_Space = 0x31,
+ AdbKey_Delete = 0x33,
+
+ AdbKey_ForwardDelete = 0x75,
+ AdbKey_Help = 0x72,
+ AdbKey_Home = 0x73,
+ AdbKey_End = 0x77,
+ AdbKey_PageUp = 0x74,
+ AdbKey_PageDown = 0x79,
+
+ AdbKey_Grave = 0x32,
+ AdbKey_Escape = 0x35,
+ AdbKey_Control = 0x36,
+ AdbKey_Shift = 0x38,
+ AdbKey_Option = 0x3a,
+ AdbKey_Command = 0x37,
+ AdbKey_CapsLock = 0x39,
+
+ AdbKey_ArrowUp = 0x3e,
+ AdbKey_ArrowDown = 0x3d,
+ AdbKey_ArrowLeft = 0x3b,
+ AdbKey_ArrowRight = 0x3c,
+
+ AdbKey_Keypad0 = 0x52,
+ AdbKey_Keypad1 = 0x53,
+ AdbKey_Keypad2 = 0x54,
+ AdbKey_Keypad3 = 0x55,
+ AdbKey_Keypad4 = 0x56,
+ AdbKey_Keypad5 = 0x57,
+ AdbKey_Keypad6 = 0x58,
+ AdbKey_Keypad7 = 0x59,
+ AdbKey_Keypad9 = 0x5c,
+ AdbKey_Keypad8 = 0x5b,
+ AdbKey_KeypadDecimal = 0x41,
+ AdbKey_KeypadPlus = 0x45,
+ AdbKey_KeypadMinus = 0x4e,
+ AdbKey_KeypadMultiply = 0x43,
+ AdbKey_KeypadDivide = 0x4b,
+ AdbKey_KeypadEnter = 0x4c,
+ AdbKey_KeypadEquals = 0x51,
+ AdbKey_KeypadClear = 0x47,
+
+ AdbKey_F1 = 0x7a,
+ AdbKey_F2 = 0x78,
+ AdbKey_F3 = 0x63,
+ AdbKey_F4 = 0x76,
+ AdbKey_F5 = 0x60,
+ AdbKey_F6 = 0x61,
+ AdbKey_F7 = 0x62,
+ AdbKey_F8 = 0x64,
+ AdbKey_F9 = 0x65,
+ AdbKey_F10 = 0x6d,
+ AdbKey_F11 = 0x67,
+ AdbKey_F12 = 0x6f,
+ AdbKey_F13 = 0x69,
+ AdbKey_F14 = 0x6b,
+ AdbKey_F15 = 0x71,
+};
+
#endif // ADB_KEYBOARD_H
diff --git a/devices/common/viacuda.cpp b/devices/common/viacuda.cpp
index da91f32..ff2f681 100644
--- a/devices/common/viacuda.cpp
+++ b/devices/common/viacuda.cpp
@@ -473,25 +473,20 @@ void ViaCuda::process_adb_command() {
}
void ViaCuda::autopoll_handler() {
- uint8_t adb_status, output_size;
-
if (!this->autopoll_enabled)
return;
- // send TALK R0 command to address 3 (mouse)
- uint8_t in_data[2] = { 0x3C, 0};
+ uint8_t poll_command = this->adb_bus_obj->poll();
- adb_status = this->adb_bus_obj->process_command(in_data, 1);
-
- if (adb_status == ADB_STAT_OK) {
+ if (poll_command) {
if (!this->old_tip || !this->treq) {
LOG_F(WARNING, "Cuda transaction probably in progress");
}
// prepare autopoll packet
- response_header(CUDA_PKT_ADB, adb_status | ADB_STAT_AUTOPOLL);
- this->out_buf[2] = 0x3C; // put the proper ADB command
- output_size = this->adb_bus_obj->get_output_count();
+ response_header(CUDA_PKT_ADB, ADB_STAT_OK | ADB_STAT_AUTOPOLL);
+ this->out_buf[2] = poll_command; // put the proper ADB command
+ uint8_t output_size = this->adb_bus_obj->get_output_count();
if (output_size) {
std::memcpy(&this->out_buf[3], this->adb_bus_obj->get_output_buf(), output_size);
this->out_count += output_size;