Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Apple Magic Keyboard A1843 CAPS LED #138

Open
peterburk opened this issue Oct 17, 2024 · 0 comments
Open

Support for Apple Magic Keyboard A1843 CAPS LED #138

peterburk opened this issue Oct 17, 2024 · 0 comments

Comments

@peterburk
Copy link

Thank you for your library! I just got a Teensy 4.0, and was able to use the MouseKeyboardForward.ino sketch with a Dell keyboard right out of the box.

My project is to build an HID remapper for my Apple Magic Keyboard A1843, so I can type Command-C and have the office PC receive Ctrl-C (among other features, such as media keys sending UART commands to my iPod).

For the Magic Keyboard, it didn't work when I first plugged it in. I investigated further, and made the following changes to support typing and modifier keys.

C:\Users\burkipe\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.59.0\libraries\USBHost_t36\keyboard.cpp

uint8_t key_modifiers = 0;
uint32_t thisKey = 0;


bool KeyboardController::hid_process_in_data(const Transfer_t *transfer)
{
	const uint8_t *buffer = (const uint8_t *)transfer->buffer;
	
	uint16_t len = transfer->length;
	const uint8_t *p = buffer;
	USBHDBGSerial.printf("HPID(%p, %u):", transfer->driver, len);
	  if (len > 32) len = 32;
	while (len--) USBHDBGSerial.printf(" %02X", *p++); 


	if (buffer[3] != thisKey)  { Keyboard.release(0XF000 | thisKey); thisKey = 0; }
	if (buffer[3] != 0x00) { thisKey = buffer[3]; Keyboard.press(0XF000 | thisKey);  }
	// if (buffer[3] == 0x00)  { Keyboard.release(0XF000 | thisKey); thisKey = 0; }

	if (buffer[3] == 0x39) 
	{ 
		// leds_.capsLock = true; updateLEDS(); 
		if (driver_[0] != nullptr) {
				USBHDBGSerial.printf("driver_[0]->sendControlPacket");
			// Only do it this way if we are a standard USB device
			leds_.capsLock = true;
	    driver_[0]->sendControlPacket(0x21, 9, 0x200, 1, sizeof(leds_.byte), (void*) &leds_.byte); 
			// sendControlPacket(uint32_t bmRequestType, uint32_t bRequest, uint32_t wValue, uint32_t wIndex, uint32_t wLength, void *buf)
			
			} else {
				USBHDBGSerial.printf("driver_[0] is nullptr");
			}
	}

	// Probably need to do some more checking of the data, but
	// first pass if length == 8 assume boot format:
	// Hoped driver would be something I could check but...
	if ((transfer->driver == driver_[0]) &&  (transfer->length == 8)) {
		/*USBHDBGSerial.printf(" (boot)\n"); */
		process_boot_keyboard_format(buffer, true);
		keyboard_uses_boot_format_  = true;
		return true;
	}
	USBHDBGSerial.printf("\n");

	return false;
}


void KeyboardController::hid_input_data(uint32_t usage, int32_t value)
{
	// Hack ignore 0xff00 high words as these are user values... 
	// USBHDBGSerial.printf("KeyboardController: topusage= %x usage=%X, value=%d\n", topusage_, usage, value);
	
	if ((usage & 0xffff0000) == 0xff000000) return; 

	if ((topusage_ == 0x10000 ) && (usage == 0x700E1) && (value == 1)) {		USBHDBGSerial.printf("Left shift down"); int mask = 1 << 1; key_modifiers |= mask; USBHDBGSerial.printf("key_modifiers %x", key_modifiers); Keyboard.set_modifier(key_modifiers);	}
	if ((topusage_ == 0x10000 ) && (usage == 0x700E1) && (value == 0)) {		USBHDBGSerial.printf("Left shift up"); int mask = 1 << 1; key_modifiers &= ~mask; USBHDBGSerial.printf("key_modifiers %x", key_modifiers); Keyboard.set_modifier(key_modifiers);	}
	if ((topusage_ == 0x10000 ) && (usage == 0x700E3) && (value == 1)) {		USBHDBGSerial.printf("Command down"); int mask = 1 << 3; key_modifiers |= mask; USBHDBGSerial.printf("key_modifiers %x", key_modifiers); Keyboard.set_modifier(key_modifiers);	}
	if ((topusage_ == 0x10000 ) && (usage == 0x700E3) && (value == 0)) {		USBHDBGSerial.printf("Command up"); int mask = 1 << 3; key_modifiers &= ~mask; USBHDBGSerial.printf("key_modifiers %x", key_modifiers); Keyboard.set_modifier(key_modifiers);	}
	if ((topusage_ == 0x10000 ) && (usage == 0x700E0) && (value == 1)) {		USBHDBGSerial.printf("Control down"); int mask = 1 << 0; key_modifiers |= mask; USBHDBGSerial.printf("key_modifiers %x", key_modifiers); Keyboard.set_modifier(key_modifiers);	}
	if ((topusage_ == 0x10000 ) && (usage == 0x700E0) && (value == 0)) {		USBHDBGSerial.printf("Control up"); int mask = 1 << 0; key_modifiers &= ~mask; USBHDBGSerial.printf("key_modifiers %x", key_modifiers); Keyboard.set_modifier(key_modifiers);	}
	if ((topusage_ == 0x10000 ) && (usage == 0x700E2) && (value == 1)) {		USBHDBGSerial.printf("Alt down"); int mask = 1 << 2; key_modifiers |= mask; USBHDBGSerial.printf("key_modifiers %x", key_modifiers); Keyboard.set_modifier(key_modifiers);	}
	if ((topusage_ == 0x10000 ) && (usage == 0x700E2) && (value == 0)) {		USBHDBGSerial.printf("Alt up"); int mask = 1 << 2; key_modifiers &= ~mask; USBHDBGSerial.printf("key_modifiers %x", key_modifiers); Keyboard.set_modifier(key_modifiers);	}

	// If this is the TOPUSAGE_KEYBOARD do in it's own function
	if (process_hid_keyboard_data(usage, value))
		return;

Now I'm trying to support the CAPS lock LED.

TinyUSB is able to switch on the LED correctly using a Raspberry Pi Pico, by sending the following commands:

image

On the Teensy,

driver_[0]->sendControlPacket(0x21, 9, 0x200, 1, sizeof(leds_.byte), (void*) &leds_.byte); 

is sending correctly, but the second IN transaction is STALLing.

image

How do I ACK the IN transaction from the keyboard?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant