Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 1 of 1

Thread: Added Modifier key support to KeyboardController in USBHost_t36

Hybrid View

  1. #1
    Junior Member
    Join Date
    Jun 2019
    Location
    Huntsville
    Posts
    5

    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 by supersquirel500; 07-09-2019 at 10:06 PM. Reason: fixed typos and incorrect release keycode

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •