Added Modifier key support to KeyboardController in USBHost_t36

Previously no detection was provided for the modifier keys (Shift, Ctrl, GUI, Alt) I just added them partially, you'll now receive the correct HID code in key_press and key_release but since there is no unicode conversion for these characters a 0 is still sent to the user's attachPress and attachRelease functions.

I feel that's acceptable though because many keys must act the same way since they also have no unicode conversion. Examples are:
PrintScreen
Scroll Lock
PauseBreak
NumLock
CapsLock
and Keypad5 without Numlock enabled

If the user wishes to report these keys back to the user's attachPress and attachRelease functions they can do so with further modifications inside the key_press and key_release functions. I'm going to continue this thread when I do figure out how I'd like to implement that but for now, here's the changes I made so far:

you can ignore this
**disclaimer: I feel the need to stress I made this in my own free time because I felt the need to fix was I perceived was an issue that I found and am not publishing any code that was written under my other project**


Code changes:
in USBHost_t36.h / KeyboardController
...add this function declaration
Code:
private:
	void update();
	uint16_t convert_to_unicode(uint32_t mod, uint32_t key);
	   uint8_t mod_to_hid(uint8_t mod); //I added this
	void key_press(uint32_t mod, uint32_t key);
	void key_release(uint32_t mod, uint32_t key);
	void (*keyPressedFunction)(int unicode);
	void (*keyReleasedFunction)(int unicode);

Then in keyboad.cpp (should be in the same folder as the USBHost_t36.h)
...add this method
Code:
uint8_t KeyboardController::mod_to_hid(uint8_t mod){
	//return HID keycode according to:
	//https://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/translate.pdf
	// or https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
	
	switch(mod){
		//left keys
		case 0b00000001: return 0xE0;
		case 0b00000010: return 0xE1;
		case 0b00000100: return 0xE2;
		case 0b00001000: return 0xE3;
		//right keys
		case 0b00010000: return 0xE4;
		case 0b00100000: return 0xE5;
		case 0b01000000: return 0xE6;
		case 0b10000000: return 0xE7;

		//only way to get here is if there is more than one bit
		//or if there were no bits. Either way our input was
		//wrong somewhow
		default: return 0;
	}
}

...then update your new_data method to look like this:
Code:
void KeyboardController::new_data(const Transfer_t *transfer)
{
	println("KeyboardController Callback (member)");
	print("  KB Data: ");
	print_hexbytes(transfer->buffer, 8);
	
	//detect modifier key flags
	//cycle through each bit. Wait for overflow to reset to 0
	for(uint8_t i=1; i > 0; i = i<<1){
		
		//if new has and prev doesn't -> newly pressed key
		if( (report[0] & i) && !(prev_report[0] & i) ){
			uint8_t keycode = mod_to_hid(report[0] & i);
			println("  press, modkey=", keycode);
			key_press(report[0], keycode); //should first argument even be listed?
		}

		//if new doesn't have but previous did -> released key
		else if( !(report[0] & i) && (prev_report[0] & i) ){
			uint8_t keycode = mod_to_hid(prev_report[0] & i);
			println("  release, modkey=", keycode);
			key_release(prev_report[0], keycode); //should first argument even be listed?
		}

	}
	for (int i=2; i < 8; i++) {
		uint32_t key = prev_report[i];
		if (key >= 4 && !contains(key, report)) {
			key_release(prev_report[0], key);
		}
	}
	for (int i=2; i < 8; i++) {
		uint32_t key = report[i];
		if (key >= 4 && !contains(key, prev_report)) {
			key_press(report[0], key);
		}
	}
	memcpy(prev_report, report, 8);
	queue_Data_Transfer(datapipe, report, 8, this);
}

that should be it. Hope this helps somebody else.
 
Last edited:
Back
Top