From 5bfd94f638b96035913ca20c1c52217839aa9a78 Mon Sep 17 00:00:00 2001 From: Fan DANG Date: Sun, 5 May 2024 22:54:34 +0800 Subject: [PATCH 1/2] add the consumer usage report to send eject --- interfaces/USB/class/kbdhid/kbdhid.c | 10 +++ interfaces/USB/class/kbdhid/kbdhid.h | 1 + interfaces/USB/class/kbdhid/usbd_kbdhid.c | 76 +++++++++++++---------- interfaces/USB/class/kbdhid/usbd_kbdhid.h | 5 +- src/apdu.c | 8 +++ 5 files changed, 66 insertions(+), 34 deletions(-) diff --git a/interfaces/USB/class/kbdhid/kbdhid.c b/interfaces/USB/class/kbdhid/kbdhid.c index 2ab41ca9..a8251e3e 100644 --- a/interfaces/USB/class/kbdhid/kbdhid.c +++ b/interfaces/USB/class/kbdhid/kbdhid.c @@ -90,6 +90,7 @@ static void KBDHID_TypeKeySeq(void) { report.modifier = 0; // No modifier key } report.keycode[0] = keycode; + report.id = 1; // Emulate the key press USBD_KBDHID_SendReport(&usb_device, (uint8_t *)&report, sizeof(report)); state = KBDHID_KeyDown; @@ -99,6 +100,7 @@ static void KBDHID_TypeKeySeq(void) { case KBDHID_KeyDown: if (USBD_KBDHID_IsIdle()) { memset(&report, 0, sizeof(report)); // Clear the report + report.id = 1; // Emulate the key release USBD_KBDHID_SendReport(&usb_device, (uint8_t *)&report, sizeof(report)); key_seq_position++; @@ -108,6 +110,14 @@ static void KBDHID_TypeKeySeq(void) { } } +void KBDHID_Eject() { + report.id = 2; + report.modifier = 0xB8; + USBD_KBDHID_SendReport(&usb_device, (uint8_t *)&report, 2); + report.modifier = 0x00; + USBD_KBDHID_SendReport(&usb_device, (uint8_t *)&report, 2); +} + uint8_t KBDHID_Init() { memset(&report, 0, sizeof(report)); state = KBDHID_Idle; diff --git a/interfaces/USB/class/kbdhid/kbdhid.h b/interfaces/USB/class/kbdhid/kbdhid.h index f1be65b3..05a8156a 100644 --- a/interfaces/USB/class/kbdhid/kbdhid.h +++ b/interfaces/USB/class/kbdhid/kbdhid.h @@ -6,5 +6,6 @@ uint8_t KBDHID_Init(void); uint8_t KBDHID_Loop(void); +void KBDHID_Eject(void); #endif // __KBDHID_H_INCLUDED__ diff --git a/interfaces/USB/class/kbdhid/usbd_kbdhid.c b/interfaces/USB/class/kbdhid/usbd_kbdhid.c index 59a1ecf4..08eac432 100644 --- a/interfaces/USB/class/kbdhid/usbd_kbdhid.c +++ b/interfaces/USB/class/kbdhid/usbd_kbdhid.c @@ -9,38 +9,50 @@ static USBD_KBDHID_HandleTypeDef hid_handle; // clang-format off static const uint8_t report_desc[KBDHID_REPORT_DESC_SIZE] = { - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x06, // USAGE (Keyboard) - 0xa1, 0x01, // COLLECTION (Application) - 0x05, 0x07, // USAGE_PAGE (Keyboard) - 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) - 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x75, 0x01, // REPORT_SIZE (1) - 0x95, 0x08, // REPORT_COUNT (8) - 0x81, 0x02, // INPUT (Data,Var,Abs) // 8x1b modifier keys - 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x08, // REPORT_SIZE (8) - 0x81, 0x03, // INPUT (Cnst,Var,Abs) // 1x8b constants - 0x95, 0x05, // REPORT_COUNT (5) - 0x75, 0x01, // REPORT_SIZE (1) - 0x05, 0x08, // USAGE_PAGE (LEDs) - 0x19, 0x01, // USAGE_MINIMUM (Num Lock) - 0x29, 0x05, // USAGE_MAXIMUM (Kana) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x03, // REPORT_SIZE (3) - 0x91, 0x03, // OUTPUT (Cnst,Var,Abs) - 0x95, 0x06, // REPORT_COUNT (6) - 0x75, 0x08, // REPORT_SIZE (8) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x65, // LOGICAL_MAXIMUM (101) - 0x05, 0x07, // USAGE_PAGE (Keyboard) - 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) - 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) - 0x81, 0x00, // INPUT (Data,Ary,Abs) // 6x8b key codes - 0xc0 // END_COLLECTION + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x06, // Usage (Keyboard) + 0xA1, 0x01, // Collection (Application) + 0x85, 0x01, // Report ID (1) + 0x05, 0x07, // Usage Page (Kbrd/Keypad) + 0x19, 0xE0, // Usage Minimum (0xE0) + 0x29, 0xE7, // Usage Maximum (0xE7) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x08, // Report Count (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x95, 0x05, // Report Count (5) + 0x75, 0x01, // Report Size (1) + 0x05, 0x08, // Usage Page (LEDs) + 0x19, 0x01, // Usage Minimum (Num Lock) + 0x29, 0x05, // Usage Maximum (Kana) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + 0x95, 0x01, // Report Count (1) + 0x75, 0x03, // Report Size (3) + 0x91, 0x03, // Output (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + 0x95, 0x05, // Report Count (5) + 0x75, 0x08, // Report Size (8) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x65, // Logical Maximum (101) + 0x05, 0x07, // Usage Page (Kbrd/Keypad) + 0x19, 0x00, // Usage Minimum (0x00) + 0x29, 0x65, // Usage Maximum (0x65) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0xC0, // End Collection + 0x05, 0x0C, // Usage Page (Consumer) + 0x09, 0x01, // Usage (Consumer Control) + 0xA1, 0x01, // Collection (Application) + 0x85, 0x02, // Report ID (2) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x08, // Report Size (1) + 0x95, 0x01, // Report Count (1) + 0x0A, 0xAE, 0x01, // Usage (AL Keyboard Layout) + 0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) + 0xC0, // End Collection }; static const uint8_t USBD_KBDHID_Desc[] = { diff --git a/interfaces/USB/class/kbdhid/usbd_kbdhid.h b/interfaces/USB/class/kbdhid/usbd_kbdhid.h index 2a8c0d22..24e5f4c5 100644 --- a/interfaces/USB/class/kbdhid/usbd_kbdhid.h +++ b/interfaces/USB/class/kbdhid/usbd_kbdhid.h @@ -8,7 +8,7 @@ #define KBDHID_REPORT_DESC 0x22 #define KBDHID_REQ_SET_IDLE 0x0A #define USBD_KBDHID_REPORT_BUF_SIZE 8 -#define KBDHID_REPORT_DESC_SIZE 63 +#define KBDHID_REPORT_DESC_SIZE 87 typedef enum { KBDHID_IDLE = 0, KBDHID_BUSY } KBDHID_StateTypeDef; @@ -19,9 +19,10 @@ typedef struct { } USBD_KBDHID_HandleTypeDef; typedef struct { + uint8_t id; uint8_t modifier; uint8_t reserved; - uint8_t keycode[6]; + uint8_t keycode[5]; } keyboard_report_t; uint8_t USBD_KBDHID_Init(USBD_HandleTypeDef *pdev); diff --git a/src/apdu.c b/src/apdu.c index cdfa536b..249cff25 100644 --- a/src/apdu.c +++ b/src/apdu.c @@ -10,6 +10,7 @@ #include #include #include +#include enum APPLET { APPLET_NULL, @@ -151,6 +152,13 @@ int apdu_output(RAPDU_CHAINING *ex, RAPDU *sh) { } void process_apdu(CAPDU *capdu, RAPDU *rapdu) { + if (CLA == 0xFF && INS == 0xEE && P1 == 0xFF && P2 == 0xEE) { + // A special APDU to trigger Eject + KBDHID_Eject(); + LL = 0; + SW = SW_NO_ERROR; + return; + } static enum PIV_STATE piv_state; if (current_applet == APPLET_PIV) { // Offload some APDU chaining commands of PIV applet, From 7ce1860b948c89cbcf9c5e31f6b11ff84d644a31 Mon Sep 17 00:00:00 2001 From: Fan DANG Date: Sun, 12 May 2024 12:54:04 +0800 Subject: [PATCH 2/2] Use KBDHID_TypeKeySeq to send EJECT --- interfaces/USB/class/kbdhid/kbdhid.c | 48 ++++++++++++++++++---------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/interfaces/USB/class/kbdhid/kbdhid.c b/interfaces/USB/class/kbdhid/kbdhid.c index a8251e3e..967a752f 100644 --- a/interfaces/USB/class/kbdhid/kbdhid.c +++ b/interfaces/USB/class/kbdhid/kbdhid.c @@ -7,6 +7,8 @@ #include #include +#define EJECT_KEY 0x03 + static enum { KBDHID_Idle, KBDHID_Typing, @@ -82,17 +84,24 @@ static void KBDHID_TypeKeySeq(void) { DBG_MSG("Key typing ended\n"); state = KBDHID_Idle; } else if (USBD_KBDHID_IsIdle()) { - uint8_t keycode = ascii2keycode(key_sequence[key_seq_position]); - if (keycode & 0x80) { // Check for shift flag - report.modifier = 0x02; // Shift key - keycode &= 0x7F; // Clear shift flag + if (key_sequence[key_seq_position] == EJECT_KEY) { + report.id = 2; + report.modifier = 0xB8; + // Emulate the key press + USBD_KBDHID_SendReport(&usb_device, (uint8_t *)&report, 2); } else { - report.modifier = 0; // No modifier key + uint8_t keycode = ascii2keycode(key_sequence[key_seq_position]); + if (keycode & 0x80) { // Check for shift flag + report.modifier = 0x02; // Shift key + keycode &= 0x7F; // Clear shift flag + } else { + report.modifier = 0; // No modifier key + } + report.keycode[0] = keycode; + report.id = 1; + // Emulate the key press + USBD_KBDHID_SendReport(&usb_device, (uint8_t *) &report, sizeof(report)); } - report.keycode[0] = keycode; - report.id = 1; - // Emulate the key press - USBD_KBDHID_SendReport(&usb_device, (uint8_t *)&report, sizeof(report)); state = KBDHID_KeyDown; } break; @@ -100,9 +109,15 @@ static void KBDHID_TypeKeySeq(void) { case KBDHID_KeyDown: if (USBD_KBDHID_IsIdle()) { memset(&report, 0, sizeof(report)); // Clear the report - report.id = 1; - // Emulate the key release - USBD_KBDHID_SendReport(&usb_device, (uint8_t *)&report, sizeof(report)); + if (key_sequence[key_seq_position] == EJECT_KEY) { + report.id = 2; + // Emulate the key release + USBD_KBDHID_SendReport(&usb_device, (uint8_t *)&report, 2); + } else { + report.id = 1; + // Emulate the key release + USBD_KBDHID_SendReport(&usb_device, (uint8_t *) &report, sizeof(report)); + } key_seq_position++; state = KBDHID_KeyUp; break; @@ -111,11 +126,10 @@ static void KBDHID_TypeKeySeq(void) { } void KBDHID_Eject() { - report.id = 2; - report.modifier = 0xB8; - USBD_KBDHID_SendReport(&usb_device, (uint8_t *)&report, 2); - report.modifier = 0x00; - USBD_KBDHID_SendReport(&usb_device, (uint8_t *)&report, 2); + key_sequence[0] = EJECT_KEY; + key_sequence[1] = 0; + key_seq_position = 0; + state = KBDHID_Typing; } uint8_t KBDHID_Init() {