mirror of
https://github.com/polhenarejos/pico-keys-sdk
synced 2026-05-08 22:16:10 +02:00
Adding a secondary HID interface that emulates a keyboard.
With it, an app can send a password directly to the host, like it is typed by user. Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
@@ -143,6 +143,8 @@ typedef struct {
|
|||||||
#define CTAP1_ERR_INVALID_CHANNEL 0x0b // CID not valid
|
#define CTAP1_ERR_INVALID_CHANNEL 0x0b // CID not valid
|
||||||
#define CTAP1_ERR_OTHER 0x7f // Other unspecified error
|
#define CTAP1_ERR_OTHER 0x7f // Other unspecified error
|
||||||
|
|
||||||
|
extern void add_keyboard_buffer(const uint8_t *, size_t);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -93,9 +93,72 @@ uint32_t hid_write(uint16_t size) {
|
|||||||
uint16_t send_buffer_size = 0;
|
uint16_t send_buffer_size = 0;
|
||||||
bool last_write_result = false;
|
bool last_write_result = false;
|
||||||
|
|
||||||
|
static uint8_t keyboard_buffer[256];
|
||||||
|
static uint8_t keyboard_buffer_len = 0;
|
||||||
|
static const uint8_t conv_table[128][2] = { HID_ASCII_TO_KEYCODE };
|
||||||
|
static uint8_t keyboard_w = 0;
|
||||||
|
static bool sent_key = false;
|
||||||
|
|
||||||
|
void add_keyboard_buffer(const uint8_t *data, size_t data_len) {
|
||||||
|
keyboard_buffer_len = MIN(sizeof(keyboard_buffer), data_len);
|
||||||
|
memcpy(keyboard_buffer, data, keyboard_buffer_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_hid_report(uint8_t report_id) {
|
||||||
|
if (!tud_hid_ready())
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch(report_id) {
|
||||||
|
case REPORT_ID_KEYBOARD: {
|
||||||
|
if (keyboard_w < keyboard_buffer_len) {
|
||||||
|
if (sent_key == false) {
|
||||||
|
uint8_t keycode[6] = { 0 };
|
||||||
|
uint8_t modifier = 0;
|
||||||
|
uint8_t chr = keyboard_buffer[keyboard_w];
|
||||||
|
if (conv_table[chr][0])
|
||||||
|
modifier = KEYBOARD_MODIFIER_LEFTSHIFT;
|
||||||
|
keycode[0] = conv_table[chr][1];
|
||||||
|
if (tud_hid_n_keyboard_report(ITF_KEYBOARD, REPORT_ID_KEYBOARD, modifier, keycode) == true)
|
||||||
|
sent_key = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (tud_hid_n_keyboard_report(ITF_KEYBOARD, REPORT_ID_KEYBOARD, 0, NULL) == true) {
|
||||||
|
keyboard_w++;
|
||||||
|
sent_key = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (keyboard_w == keyboard_buffer_len && keyboard_buffer_len > 0) {
|
||||||
|
keyboard_w = keyboard_buffer_len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hid_task(void) {
|
||||||
|
// Poll every 10ms
|
||||||
|
const uint32_t interval_ms = 10;
|
||||||
|
static uint32_t start_ms = 0;
|
||||||
|
|
||||||
|
if (board_millis() - start_ms < interval_ms)
|
||||||
|
return;
|
||||||
|
start_ms += interval_ms;
|
||||||
|
|
||||||
|
// Remote wakeup
|
||||||
|
if ( tud_suspended() && keyboard_buffer_len > 0) {
|
||||||
|
tud_remote_wakeup();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
send_hid_report(REPORT_ID_KEYBOARD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, /*uint16_t*/ uint8_t len) {
|
void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, /*uint16_t*/ uint8_t len) {
|
||||||
uint8_t seq = report[4] & TYPE_MASK ? 0 : report[4] + 1;
|
if (send_buffer_size > 0 && instance == ITF_HID) {
|
||||||
if (send_buffer_size > 0) {
|
uint8_t seq = report[4] & TYPE_MASK ? 0 : report[4] + 1;
|
||||||
if (last_write_result == true) {
|
if (last_write_result == true) {
|
||||||
ctap_resp->cid = ctap_req->cid;
|
ctap_resp->cid = ctap_req->cid;
|
||||||
ctap_resp->cont.seq = seq;
|
ctap_resp->cont.seq = seq;
|
||||||
@@ -108,7 +171,7 @@ void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, /*uint1
|
|||||||
}
|
}
|
||||||
|
|
||||||
int driver_write_hid(const uint8_t *buffer, size_t buffer_size) {
|
int driver_write_hid(const uint8_t *buffer, size_t buffer_size) {
|
||||||
last_write_result = tud_hid_report(0, buffer, buffer_size);
|
last_write_result = tud_hid_n_report(ITF_HID, 0, buffer, buffer_size);
|
||||||
printf("result %d\n", last_write_result);
|
printf("result %d\n", last_write_result);
|
||||||
if (last_write_result == false)
|
if (last_write_result == false)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -127,7 +190,7 @@ void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t rep
|
|||||||
(void) report_id;
|
(void) report_id;
|
||||||
(void) report_type;
|
(void) report_type;
|
||||||
|
|
||||||
usb_rx(ITF_HID, buffer, bufsize);
|
usb_rx(itf, buffer, bufsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t last_cmd_time = 0, last_packet_time = 0;
|
uint32_t last_cmd_time = 0, last_packet_time = 0;
|
||||||
|
|||||||
@@ -106,7 +106,7 @@
|
|||||||
#define CFG_TUD_CDC 0
|
#define CFG_TUD_CDC 0
|
||||||
#define CFG_TUD_MSC 0
|
#define CFG_TUD_MSC 0
|
||||||
#ifdef USB_ITF_HID
|
#ifdef USB_ITF_HID
|
||||||
#define CFG_TUD_HID 1
|
#define CFG_TUD_HID 2
|
||||||
#else
|
#else
|
||||||
#define CFG_TUD_HID 0
|
#define CFG_TUD_HID 0
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ void card_exit() {
|
|||||||
led_set_blink(BLINK_SUSPENDED);
|
led_set_blink(BLINK_SUSPENDED);
|
||||||
card_locked_itf = ITF_TOTAL;
|
card_locked_itf = ITF_TOTAL;
|
||||||
}
|
}
|
||||||
|
extern void hid_task();
|
||||||
void usb_task() {
|
void usb_task() {
|
||||||
bool mounted = false;
|
bool mounted = false;
|
||||||
for (uint8_t itf = 0; itf < ITF_TOTAL; itf++) {
|
for (uint8_t itf = 0; itf < ITF_TOTAL; itf++) {
|
||||||
@@ -265,6 +265,7 @@ void usb_task() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hid_task();
|
||||||
}
|
}
|
||||||
|
|
||||||
void timeout_stop() {
|
void timeout_stop() {
|
||||||
|
|||||||
@@ -39,7 +39,8 @@
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
#ifdef USB_ITF_HID
|
#ifdef USB_ITF_HID
|
||||||
ITF_HID,
|
ITF_HID = 0,
|
||||||
|
ITF_KEYBOARD,
|
||||||
#endif
|
#endif
|
||||||
#ifdef USB_ITF_CCID
|
#ifdef USB_ITF_CCID
|
||||||
ITF_CCID,
|
ITF_CCID,
|
||||||
@@ -47,6 +48,11 @@ enum {
|
|||||||
ITF_TOTAL
|
ITF_TOTAL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
REPORT_ID_KEYBOARD = 1,
|
||||||
|
REPORT_ID_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
extern void usb_task();
|
extern void usb_task();
|
||||||
extern queue_t usb_to_card_q;
|
extern queue_t usb_to_card_q;
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ tusb_desc_configuration_t const desc_config =
|
|||||||
+ sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + 2*sizeof(tusb_desc_endpoint_t)
|
+ sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + 2*sizeof(tusb_desc_endpoint_t)
|
||||||
#endif
|
#endif
|
||||||
#ifdef USB_ITF_HID
|
#ifdef USB_ITF_HID
|
||||||
+ TUD_HID_INOUT_DESC_LEN
|
+ TUD_HID_INOUT_DESC_LEN + TUD_HID_DESC_LEN
|
||||||
#endif
|
#endif
|
||||||
),
|
),
|
||||||
.bNumInterfaces = ITF_TOTAL,
|
.bNumInterfaces = ITF_TOTAL,
|
||||||
@@ -156,12 +156,13 @@ static uint8_t desc_config_extended[sizeof(tusb_desc_configuration_t)
|
|||||||
+ sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + 2*sizeof(tusb_desc_endpoint_t)
|
+ sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + 2*sizeof(tusb_desc_endpoint_t)
|
||||||
#endif
|
#endif
|
||||||
#ifdef USB_ITF_HID
|
#ifdef USB_ITF_HID
|
||||||
+ TUD_HID_INOUT_DESC_LEN
|
+ TUD_HID_INOUT_DESC_LEN + TUD_HID_DESC_LEN
|
||||||
#endif
|
#endif
|
||||||
];
|
];
|
||||||
|
|
||||||
#ifdef USB_ITF_HID
|
#ifdef USB_ITF_HID
|
||||||
#define HID_USAGE_PAGE_FIDO 0xF1D0
|
#define HID_USAGE_PAGE_FIDO 0xF1D0
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
HID_USAGE_FIDO_U2FHID = 0x01, // U2FHID usage for top-level collection
|
HID_USAGE_FIDO_U2FHID = 0x01, // U2FHID usage for top-level collection
|
||||||
@@ -195,17 +196,28 @@ uint8_t const desc_hid_report[] =
|
|||||||
{
|
{
|
||||||
TUD_HID_REPORT_DESC_FIDO_U2F(CFG_TUD_HID_EP_BUFSIZE)
|
TUD_HID_REPORT_DESC_FIDO_U2F(CFG_TUD_HID_EP_BUFSIZE)
|
||||||
};
|
};
|
||||||
|
uint8_t const desc_hid_report_kb[] =
|
||||||
|
{
|
||||||
|
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID_KEYBOARD))
|
||||||
|
};
|
||||||
#define EPNUM_HID 0x03
|
#define EPNUM_HID 0x03
|
||||||
|
|
||||||
static uint8_t desc_hid[] = {
|
static uint8_t desc_hid[] = {
|
||||||
// Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval
|
TUD_HID_INOUT_DESCRIPTOR(ITF_HID, ITF_HID+5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10)
|
||||||
TUD_HID_INOUT_DESCRIPTOR(ITF_HID, ITF_HID+5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10)
|
};
|
||||||
|
|
||||||
|
static uint8_t desc_hid_kb[] = {
|
||||||
|
TUD_HID_DESCRIPTOR(ITF_KEYBOARD, ITF_KEYBOARD+5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report_kb), 0x80 | (EPNUM_HID+1), 16, 5)
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf)
|
uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf)
|
||||||
{
|
{
|
||||||
printf("report_cb %d\n", itf);
|
printf("report_cb %d\n", itf);
|
||||||
return desc_hid_report;
|
if (itf == ITF_HID)
|
||||||
|
return desc_hid_report;
|
||||||
|
else if (itf == ITF_KEYBOARD)
|
||||||
|
return desc_hid_report_kb;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -220,6 +232,7 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
|
|||||||
memcpy(p, &desc_config, sizeof(tusb_desc_configuration_t)); p += sizeof(tusb_desc_configuration_t);
|
memcpy(p, &desc_config, sizeof(tusb_desc_configuration_t)); p += sizeof(tusb_desc_configuration_t);
|
||||||
#ifdef USB_ITF_HID
|
#ifdef USB_ITF_HID
|
||||||
memcpy(p, &desc_hid, sizeof(desc_hid)); p += sizeof(desc_hid);
|
memcpy(p, &desc_hid, sizeof(desc_hid)); p += sizeof(desc_hid);
|
||||||
|
memcpy(p, &desc_hid_kb, sizeof(desc_hid_kb)); p += sizeof(desc_hid_kb);
|
||||||
#endif
|
#endif
|
||||||
#ifdef USB_ITF_CCID
|
#ifdef USB_ITF_CCID
|
||||||
memcpy(p, &desc_interface, sizeof(tusb_desc_interface_t)); p += sizeof(tusb_desc_interface_t);
|
memcpy(p, &desc_interface, sizeof(tusb_desc_interface_t)); p += sizeof(tusb_desc_interface_t);
|
||||||
@@ -261,6 +274,7 @@ char const* string_desc_arr [] =
|
|||||||
"Pico Key Config" // 4: Vendor Interface
|
"Pico Key Config" // 4: Vendor Interface
|
||||||
#ifdef USB_ITF_HID
|
#ifdef USB_ITF_HID
|
||||||
,"Pico Key HID Interface"
|
,"Pico Key HID Interface"
|
||||||
|
,"Pico Key HID Keyboard Interface"
|
||||||
#endif
|
#endif
|
||||||
#ifdef USB_ITF_CCID
|
#ifdef USB_ITF_CCID
|
||||||
,"Pico Key CCID Interface"
|
,"Pico Key CCID Interface"
|
||||||
|
|||||||
Reference in New Issue
Block a user