[Mammoth/Voyageurs] Add shift modifiers for scancodes.
This commit is contained in:
		
							parent
							
								
									a9351b222d
								
							
						
					
					
						commit
						844f55c7d0
					
				|  | @ -55,71 +55,54 @@ Thread KeyboardListenerBase::Listen() { | ||||||
| 
 | 
 | ||||||
| void KeyboardListenerBase::ListenLoop() { | void KeyboardListenerBase::ListenLoop() { | ||||||
|   while (true) { |   while (true) { | ||||||
|     auto scancode_or = server_.RecvChar(); |     auto scancode_or = server_.RecvUint16(); | ||||||
|     if (!scancode_or.ok()) { |     if (!scancode_or.ok()) { | ||||||
|       check(scancode_or.error()); |       check(scancode_or.error()); | ||||||
|     } |     } | ||||||
|     uint8_t scancode = scancode_or.value(); |     uint16_t scancode = scancode_or.value(); | ||||||
| 
 | 
 | ||||||
|     if (scancode == 0xE0) { |     Keycode k = ScancodeToKeycode(scancode & 0xFF); | ||||||
|       extended_on_ = true; |     uint8_t modifiers = (scancode >> 8) & 0xFF; | ||||||
|       continue; |     HandleKeycode(k, modifiers); | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     Keycode k = ScancodeToKeycode(scancode); |  | ||||||
|     Action a = ScancodeToAction(scancode); |  | ||||||
|     HandleKeycode(k, a); |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void KeyboardListenerBase::HandleKeycode(Keycode code, Action action) { | void KeyboardListenerBase::HandleKeycode(Keycode code, uint8_t modifiers) { | ||||||
|   char c = '\0'; |   char c = '\0'; | ||||||
| 
 | 
 | ||||||
|   if (action == kPressed) { |   if (code >= kA && code <= kZ) { | ||||||
|     if (code >= kA && code <= kZ) { |     if (IsShift(modifiers)) { | ||||||
|       if (IsShift()) { |       const char* alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | ||||||
|         const char* alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |       c = alpha[code - kA]; | ||||||
|         c = alpha[code - kA]; |  | ||||||
| 
 | 
 | ||||||
|       } else { |     } else { | ||||||
|         const char* alpha = "abcdefghijklmnopqrstuvwxyz"; |       const char* alpha = "abcdefghijklmnopqrstuvwxyz"; | ||||||
|         c = alpha[code - kA]; |       c = alpha[code - kA]; | ||||||
|       } |  | ||||||
|     } else if (code >= k1 && code <= k0) { |  | ||||||
|       if (IsShift()) { |  | ||||||
|         const char* num = "!@#$%^&*()"; |  | ||||||
|         c = num[code - k1]; |  | ||||||
|       } else { |  | ||||||
|         const char* num = "1234567890"; |  | ||||||
|         c = num[code - k1]; |  | ||||||
|       } |  | ||||||
|     } else if (code >= kMinus && code <= kBacktick) { |  | ||||||
|       if (IsShift()) { |  | ||||||
|         const char* sym = "_+{}|?:\"<>~"; |  | ||||||
|         c = sym[code - kMinus]; |  | ||||||
|       } else { |  | ||||||
|         const char* sym = "-=[]\\/;',.`"; |  | ||||||
|         c = sym[code - kMinus]; |  | ||||||
|       } |  | ||||||
|     } else if (code == kEnter) { |  | ||||||
|       c = '\n'; |  | ||||||
|     } else if (code == kSpace) { |  | ||||||
|       c = ' '; |  | ||||||
|     } else if (code == kTab) { |  | ||||||
|       c = '\t'; |  | ||||||
|     } else if (code == kBackspace) { |  | ||||||
|       c = '\b'; |  | ||||||
|     } else if (code == kLShift) { |  | ||||||
|       lshift_ = true; |  | ||||||
|     } else if (code == kRShift) { |  | ||||||
|       rshift_ = true; |  | ||||||
|     } |     } | ||||||
|   } else if (action == kReleased) { |   } else if (code >= k1 && code <= k0) { | ||||||
|     if (code == kLShift) { |     if (IsShift(modifiers)) { | ||||||
|       lshift_ = false; |       const char* num = "!@#$%^&*()"; | ||||||
|     } else if (code == kRShift) { |       c = num[code - k1]; | ||||||
|       rshift_ = false; |     } else { | ||||||
|  |       const char* num = "1234567890"; | ||||||
|  |       c = num[code - k1]; | ||||||
|     } |     } | ||||||
|  |   } else if (code >= kMinus && code <= kBacktick) { | ||||||
|  |     if (IsShift(modifiers)) { | ||||||
|  |       const char* sym = "_+{}|?:\"<>~"; | ||||||
|  |       c = sym[code - kMinus]; | ||||||
|  |     } else { | ||||||
|  |       const char* sym = "-=[]\\/;',.`"; | ||||||
|  |       c = sym[code - kMinus]; | ||||||
|  |     } | ||||||
|  |   } else if (code == kEnter) { | ||||||
|  |     c = '\n'; | ||||||
|  |   } else if (code == kSpace) { | ||||||
|  |     c = ' '; | ||||||
|  |   } else if (code == kTab) { | ||||||
|  |     c = '\t'; | ||||||
|  |   } else if (code == kBackspace) { | ||||||
|  |     c = '\b'; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (c != '\0') { |   if (c != '\0') { | ||||||
|  | @ -127,35 +110,7 @@ void KeyboardListenerBase::HandleKeycode(Keycode code, Action action) { | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Keycode KeyboardListenerBase::ScancodeToKeycode(uint8_t scancode) { | Keycode KeyboardListenerBase::ScancodeToKeycode(uint16_t scancode) { | ||||||
|   // Cancel out the released bit.
 |  | ||||||
|   scancode &= 0x7F; |  | ||||||
|   if (extended_on_) { |  | ||||||
|     extended_on_ = false; |  | ||||||
| 
 |  | ||||||
|     switch (scancode) { |  | ||||||
|       case 0x1D: |  | ||||||
|         return kRCtrl; |  | ||||||
|       case 0x38: |  | ||||||
|         return kRAlt; |  | ||||||
|       case 0x48: |  | ||||||
|         return kUp; |  | ||||||
|       case 0x4B: |  | ||||||
|         return kLeft; |  | ||||||
|       case 0x4D: |  | ||||||
|         return kRight; |  | ||||||
|       case 0x50: |  | ||||||
|         return kDown; |  | ||||||
|       case 0x53: |  | ||||||
|         return kDelete; |  | ||||||
|       case 0x5B: |  | ||||||
|         return kSuper; |  | ||||||
|     } |  | ||||||
|     dbgln("Unknown extended scancode {x}", scancode); |  | ||||||
| 
 |  | ||||||
|     return kUnknownKeycode; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   switch (scancode) { |   switch (scancode) { | ||||||
|     case 0x04: |     case 0x04: | ||||||
|       return kA; |       return kA; | ||||||
|  | @ -257,8 +212,10 @@ Keycode KeyboardListenerBase::ScancodeToKeycode(uint8_t scancode) { | ||||||
|       return kBacktick; |       return kBacktick; | ||||||
|     case 0x36: |     case 0x36: | ||||||
|       return kComma; |       return kComma; | ||||||
|     case 0x38: |     case 0x37: | ||||||
|       return kPeriod; |       return kPeriod; | ||||||
|  |     case 0x38: | ||||||
|  |       return kFSlash; | ||||||
|     case 0x39: |     case 0x39: | ||||||
|       return kEsc;  // Capslock
 |       return kEsc;  // Capslock
 | ||||||
|   } |   } | ||||||
|  | @ -268,8 +225,4 @@ Keycode KeyboardListenerBase::ScancodeToKeycode(uint8_t scancode) { | ||||||
|   return kUnknownKeycode; |   return kUnknownKeycode; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Action KeyboardListenerBase::ScancodeToAction(uint8_t scancode) { |  | ||||||
|   return (scancode & 0x80) ? kReleased : kPressed; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| }  // namespace mmth
 | }  // namespace mmth
 | ||||||
|  |  | ||||||
|  | @ -78,12 +78,6 @@ enum Keycode { | ||||||
|   kRight = 0x5B, |   kRight = 0x5B, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| enum Action { |  | ||||||
|   kUnknownAction, |  | ||||||
|   kPressed, |  | ||||||
|   kReleased, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| class KeyboardListenerBase { | class KeyboardListenerBase { | ||||||
|  public: |  public: | ||||||
|   KeyboardListenerBase(); |   KeyboardListenerBase(); | ||||||
|  | @ -99,7 +93,7 @@ class KeyboardListenerBase { | ||||||
|   // Override this to recieve all raw keycodes. By default
 |   // Override this to recieve all raw keycodes. By default
 | ||||||
|   // this function will try to translate each keycode into
 |   // this function will try to translate each keycode into
 | ||||||
|   // a printable character and call HandleCharacter.
 |   // a printable character and call HandleCharacter.
 | ||||||
|   virtual void HandleKeycode(Keycode code, Action action); |   virtual void HandleKeycode(Keycode code, uint8_t modifiers); | ||||||
| 
 | 
 | ||||||
|   // This function is called by the default HandleKeycode
 |   // This function is called by the default HandleKeycode
 | ||||||
|   // implementation if you do not override it. If it recieves
 |   // implementation if you do not override it. If it recieves
 | ||||||
|  | @ -109,15 +103,11 @@ class KeyboardListenerBase { | ||||||
|  private: |  private: | ||||||
|   PortServer server_; |   PortServer server_; | ||||||
| 
 | 
 | ||||||
|   bool extended_on_ = false; |   Keycode ScancodeToKeycode(uint16_t scancode); | ||||||
| 
 | 
 | ||||||
|   bool lshift_ = false; |   bool IsShift(uint8_t modifiers) { | ||||||
|   bool rshift_ = false; |     return (modifiers & 0x2) || (modifiers & 0x20); | ||||||
| 
 |   } | ||||||
|   Keycode ScancodeToKeycode(uint8_t scancode); |  | ||||||
|   Action ScancodeToAction(uint8_t scancode); |  | ||||||
| 
 |  | ||||||
|   bool IsShift() { return lshift_ || rshift_; } |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| }  // namespace mmth
 | }  // namespace mmth
 | ||||||
|  |  | ||||||
|  | @ -20,6 +20,11 @@ glcr::ErrorCode PortClient::WriteByte(uint8_t byte) { | ||||||
|       ZPortSend(port_cap_, 1, &byte, 0, nullptr)); |       ZPortSend(port_cap_, 1, &byte, 0, nullptr)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | glcr::ErrorCode PortClient::Write(uint16_t data) { | ||||||
|  |   return static_cast<glcr::ErrorCode>( | ||||||
|  |       ZPortSend(port_cap_, 2, &data, 0, nullptr)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| glcr::ErrorCode PortClient::Write(uint64_t data) { | glcr::ErrorCode PortClient::Write(uint64_t data) { | ||||||
|   return static_cast<glcr::ErrorCode>( |   return static_cast<glcr::ErrorCode>( | ||||||
|       ZPortSend(port_cap_, 8, &data, 0, nullptr)); |       ZPortSend(port_cap_, 8, &data, 0, nullptr)); | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ class PortClient { | ||||||
|   glcr::ErrorCode WriteString(glcr::String str, z_cap_t cap); |   glcr::ErrorCode WriteString(glcr::String str, z_cap_t cap); | ||||||
| 
 | 
 | ||||||
|   glcr::ErrorCode WriteByte(uint8_t byte); |   glcr::ErrorCode WriteByte(uint8_t byte); | ||||||
|  |   glcr::ErrorCode Write(uint16_t data); | ||||||
|   glcr::ErrorCode Write(uint64_t data); |   glcr::ErrorCode Write(uint64_t data); | ||||||
| 
 | 
 | ||||||
|   z_cap_t cap() { return port_cap_; } |   z_cap_t cap() { return port_cap_; } | ||||||
|  |  | ||||||
|  | @ -55,4 +55,12 @@ glcr::ErrorOr<char> PortServer::RecvChar() { | ||||||
|   return byte; |   return byte; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | glcr::ErrorOr<uint16_t> PortServer::RecvUint16() { | ||||||
|  |   uint64_t bytes = 2; | ||||||
|  |   uint64_t caps = 0; | ||||||
|  |   uint16_t data; | ||||||
|  |   RET_ERR(ZPortRecv(port_cap_, &bytes, &data, &caps, nullptr)); | ||||||
|  |   return data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| }  // namespace mmth
 | }  // namespace mmth
 | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ class PortServer { | ||||||
|   glcr::ErrorCode PollForIntCap(uint64_t* msg, uint64_t* cap); |   glcr::ErrorCode PollForIntCap(uint64_t* msg, uint64_t* cap); | ||||||
| 
 | 
 | ||||||
|   glcr::ErrorOr<char> RecvChar(); |   glcr::ErrorOr<char> RecvChar(); | ||||||
|  |   glcr::ErrorOr<uint16_t> RecvUint16(); | ||||||
| 
 | 
 | ||||||
|   z_cap_t cap() { return port_cap_; } |   z_cap_t cap() { return port_cap_; } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -42,6 +42,7 @@ void KeyboardDriver::InterruptLoop() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void KeyboardDriver::ProcessInput(uint64_t input) { | void KeyboardDriver::ProcessInput(uint64_t input) { | ||||||
|  |   uint16_t modifiers = (input & 0xFF) << 8; | ||||||
|   uint64_t new_bitmap = 0; |   uint64_t new_bitmap = 0; | ||||||
|   for (uint8_t i = 2; i < 8; i++) { |   for (uint8_t i = 2; i < 8; i++) { | ||||||
|     uint8_t code = (input >> (8 * i)) & 0xFF; |     uint8_t code = (input >> (8 * i)) & 0xFF; | ||||||
|  | @ -54,15 +55,14 @@ void KeyboardDriver::ProcessInput(uint64_t input) { | ||||||
|     uint64_t bit = 1 << code; |     uint64_t bit = 1 << code; | ||||||
|     new_bitmap |= bit; |     new_bitmap |= bit; | ||||||
|     if ((bitmap_ & bit) != bit) { |     if ((bitmap_ & bit) != bit) { | ||||||
|       SendKeypress(code); |       SendKeypress(modifiers | code); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   bitmap_ = new_bitmap; |   bitmap_ = new_bitmap; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void KeyboardDriver::SendKeypress(uint8_t scancode) { | void KeyboardDriver::SendKeypress(uint16_t scancode) { | ||||||
|   dbgln("{x}", scancode); |  | ||||||
|   for (mmth::PortClient& client : listeners_) { |   for (mmth::PortClient& client : listeners_) { | ||||||
|     client.WriteByte(scancode); |     client.Write(scancode); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -25,5 +25,5 @@ class KeyboardDriver { | ||||||
|   uint64_t bitmap_ = 0; |   uint64_t bitmap_ = 0; | ||||||
| 
 | 
 | ||||||
|   void ProcessInput(uint64_t input); |   void ProcessInput(uint64_t input); | ||||||
|   void SendKeypress(uint8_t scancode); |   void SendKeypress(uint16_t scancode); | ||||||
| }; | }; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue