I have a Lenovo m90q which has a smart power on USB port. You can plug a keyboard that supports this in this port and when you press Alt+P on the keyboard, the computer will power on. I have checked that this works with a regular keyboard, and it did. After that, I wanted to make this happen with a Raspberry Pi Pico. So, I adapted a TinyUSB composite HID example to only include a keyboard and press Alt+P when a GPIO pin was pulled down. The code is quite long, so the full code can be found at GitHub. I am using the Pico C/C++ SDK to build this.
The code that sends the keyboard report (part of main.c) is the following:
static void send_hid_keyboard_report(bool btn)
{
// skip if hid is not ready yet
if (!tud_hid_ready() && !tud_suspended())
return;
// use to avoid send multiple consecutive zero report for keyboard
static bool has_keyboard_key = false;
static bool sent_alt = false;
if (btn)
{
if (!sent_alt)
{
uint8_t keycode[6] = {HID_KEY_ALT_LEFT};
// keycode[0] = HID_KEY_P;
tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode);
has_keyboard_key = true;
sent_alt = true;
}
else
{
uint8_t modifier = 4; // Left alt, see /questions/66671427/multiple-modifiers-2-in-keyboard-input-report-for-custom-hid-keyboard
uint8_t keycode[6] = {HID_KEY_ALT_LEFT, HID_KEY_P};
tud_hid_keyboard_report(REPORT_ID_KEYBOARD, modifier, keycode);
has_keyboard_key = true;
sent_alt = false;
}
}
else
{
uint8_t keycode[6] = {HID_KEY_NONE};
// send empty key report if previously has key pressed
if (has_keyboard_key)
tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode);
has_keyboard_key = false;
sent_alt = false;
}
}
The configuration for TinyUSB (tusb_config.h) is the following:
#ifndef BOARD_DEVICE_RHPORT_NUM
#define BOARD_DEVICE_RHPORT_NUM 0
#endif
#ifndef BOARD_DEVICE_RHPORT_SPEED
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
#endif
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
#ifndef CFG_TUSB_MEM_SECTION
#define CFG_TUSB_MEM_SECTION
#endif
#ifndef CFG_TUSB_MEM_ALIGN
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
// DEVICE CONFIGURATION
//--------------------------------------------------------------------
#ifndef CFG_TUD_ENDPOINT0_SIZE
#define CFG_TUD_ENDPOINT0_SIZE 64
#endif
//------------- CLASS -------------//
#define CFG_TUD_HID 1
#define CFG_TUD_CDC 0
#define CFG_TUD_MSC 0
#define CFG_TUD_MIDI 0
#define CFG_TUD_VENDOR 0
// HID buffer size Should be sufficient to hold ID (if any) + Data
#define CFG_TUD_HID_EP_BUFSIZE 64
This are the main files I think are most important. However, the problem could also be in the other files (main.c, usb_descriptors.c or usb_descriptors.h)
The above code did not work to start the PC up. So after that, I created a shortcut in the OS (Ubuntu 22), so that when I press Alt+P, the computer will shut down. This worked. I also compared the KeyPress event of the keyboard and the RPi Pico with a basic Python keylogger, but they seemed the same. After that, I also compared the deviceinfo by running lsusb. However, the only (in my eyes significant) differences were that the keyboard used USB 1.1 and the RPi Pico USB 2.0. Another difference was that the keyboard had two interfaces: the keyboard interface and another interface. The RPi Pico with my code only has one. However, I do not know what function that other interface has, so I cannot emulate it with the RPi Pico. What am I missing here and what do I need to get this working? By using the LEDs, I know that when I plug in the RPi Pico in the correct port when the computer is shutdown, it gets power and it is mounted and not suspended.
user26432072 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.