Hello, I modified the instance in usbd_hid_generic to simulate it as keyboard. I checked the code of NRF52840 on github about the keyboard. It USES the function app_usbd_hid_generic_in_report_set() to send the key value, but I can't port it to generic, please help me
#include <stdint.h>
#include "nrf5_usb.h"
#include "ble_service.h"
#include "outputselect.h"
#ifdef NKRO_ENABLE
# include "keycode_config.h"
extern keymap_config_t keymap_config;
#endif
static uint8_t keyboard_led_stats = 0;
static bool m_report_pending;
static const app_usbd_hid_subclass_desc_t *keyboard_hid_report_desc[] = {&kbd_desc};
APP_USBD_HID_GENERIC_GLOBAL_DEF(m_app_hid_kbd, HID_KBD_INTERFACE, hid_kbd_user_ev_handler, (NRF_DRV_USBD_EPIN6), keyboard_hid_report_desc, 1, 1, APP_USBD_HID_SUBCLASS_BOOT, APP_USBD_HID_PROTO_KEYBOARD);
#ifdef NKRO_ENABLE
static const app_usbd_hid_subclass_desc_t *keyboard2_hid_report_desc[] = {&kbd2_desc};
APP_USBD_HID_GENERIC_GLOBAL_DEF(m_app_hid_kbd2, HID_KBD2_INTERFACE, hid_kbd_user_ev_handler, (NRF_DRV_USBD_EPIN2), keyboard2_hid_report_desc, 1, 1, APP_USBD_HID_SUBCLASS_NONE, APP_USBD_HID_PROTO_GENERIC);
#endif
#ifdef MOUSE_ENABLE
static const app_usbd_hid_subclass_desc_t *mouse_hid_report_desc[] = {&mouse_desc};
APP_USBD_HID_GENERIC_GLOBAL_DEF(m_app_hid_mouse, HID_MOUSE_INTERFACE, hid_user_ev_handler, (NRF_DRV_USBD_EPIN3), mouse_hid_report_desc, 1, 0, APP_USBD_HID_SUBCLASS_NONE, APP_USBD_HID_PROTO_GENERIC);
#endif
#ifdef EXTRAKEY_ENABLE
static const app_usbd_hid_subclass_desc_t *extra_hid_report_desc[] = {&extrakey_desc};
APP_USBD_HID_GENERIC_GLOBAL_DEF(m_app_hid_extra, HID_EXTRA_INTERFACE, hid_user_ev_handler, (NRF_DRV_USBD_EPIN4), extra_hid_report_desc, 1, 0, APP_USBD_HID_SUBCLASS_NONE, APP_USBD_HID_PROTO_GENERIC);
#endif
#define REPORT_QUEUE_LEN 32
static uint8_t kbd_report_queue[REPORT_QUEUE_LEN][KEYBOARD_REPORT_SIZE];
#ifdef NKRO_ENABLE
static uint8_t kbd2_report_queue[REPORT_QUEUE_LEN][NKRO_EPSIZE];
#endif
static volatile uint8_t widx = 0;
static void hid_kbd_process_state(report_keyboard_t *report) {
if (m_report_pending) return;
ret_code_t ret;
#ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) {
memcpy(kbd2_report_queue[widx], &report->nkro.mods, NKRO_EPSIZE);
ret = app_usbd_hid_generic_in_report_set(&m_app_hid_kbd2, kbd2_report_queue[widx++], NKRO_EPSIZE);
widx %= REPORT_QUEUE_LEN;
} else
#endif
{
memcpy(kbd_report_queue[widx], report, KEYBOARD_REPORT_SIZE);
// uint8_t asdf[8] = {};
// memcpy(&asdf[0], &report->mods, 8);
// NRF_LOG_INFO("%d %d %d %d", asdf[widx], asdf[widx], asdf[2], asdf[3]);
// NRF_LOG_INFO("%d %d %d %d", asdf[4], asdf[5], asdf[6], asdf[7]);
// ret = app_usbd_hid_generic_in_report_set(&m_app_hid_kbd, &report->mods, 8);
ret = app_usbd_hid_generic_in_report_set(&m_app_hid_kbd, kbd_report_queue[widx++], KEYBOARD_REPORT_SIZE);
widx %= REPORT_QUEUE_LEN;
}
APP_ERROR_CHECK(ret);
}
#ifdef MOUSE_ENABLE
static void hid_mouse_process_state(report_mouse_t *report) {
if (m_report_pending) return;
ret_code_t ret;
ret = app_usbd_hid_generic_in_report_set(&m_app_hid_mouse, &report->buttons, 5);
APP_ERROR_CHECK(ret);
}
#endif
#ifdef EXTRAKEY_ENABLE
static void hid_extra_process_state(uint8_t report_id, uint16_t data) {
if (m_report_pending) return;
ret_code_t ret;
uint8_t report[3];
report[0] = report_id;
report[1] = data & 0xFF;
report[2] = (data >> 8) & 0xFF;
ret = app_usbd_hid_generic_in_report_set(&m_app_hid_extra, &report, 3);
APP_ERROR_CHECK(ret);
}
#endif
static void kbd_status(void) {
size_t led_stats_size = 0;
const uint8_t *p_buff;
#ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) {
p_buff = app_usbd_hid_generic_out_report_get(&m_app_hid_kbd2, &led_stats_size);
} else
#endif
{
p_buff = app_usbd_hid_generic_out_report_get(&m_app_hid_kbd, &led_stats_size);
}
keyboard_led_stats = *(p_buff + 1);
}
/**
* @brief Class specific event handler.
*
* @param p_inst Class instance.
* @param event Class specific event.
* */
void hid_kbd_user_ev_handler(app_usbd_class_inst_t const *p_inst, app_usbd_hid_user_event_t event) {
switch (event) {
case APP_USBD_HID_USER_EVT_OUT_REPORT_READY: {
m_report_pending = false;
kbd_status();
break;
}
case APP_USBD_HID_USER_EVT_IN_REPORT_DONE: {
m_report_pending = false;
// hid_generic_mouse_process_state();
// bsp_board_led_invert(LED_HID_REP_IN);
break;
}
case APP_USBD_HID_USER_EVT_SET_BOOT_PROTO: {
UNUSED_RETURN_VALUE(hid_generic_clear_buffer(p_inst));
NRF_LOG_INFO("SET_BOOT_PROTO");
break;
}
case APP_USBD_HID_USER_EVT_SET_REPORT_PROTO: {
UNUSED_RETURN_VALUE(hid_generic_clear_buffer(p_inst));
NRF_LOG_INFO("SET_REPORT_PROTO");
break;
}
default:
break;
}
}
void hid_user_ev_handler(app_usbd_class_inst_t const *p_inst, app_usbd_hid_user_event_t event) {
switch (event) {
case APP_USBD_HID_USER_EVT_OUT_REPORT_READY: {
m_report_pending = false;
/* No output report defined for this example.*/
ASSERT(0);
break;
}
case APP_USBD_HID_USER_EVT_IN_REPORT_DONE: {
m_report_pending = false;
// hid_generic_mouse_process_state();
// bsp_board_led_invert(LED_HID_REP_IN);
break;
}
case APP_USBD_HID_USER_EVT_SET_BOOT_PROTO: {
UNUSED_RETURN_VALUE(hid_generic_clear_buffer(p_inst));
NRF_LOG_INFO("SET_BOOT_PROTO");
break;
}
case APP_USBD_HID_USER_EVT_SET_REPORT_PROTO: {
UNUSED_RETURN_VALUE(hid_generic_clear_buffer(p_inst));
NRF_LOG_INFO("SET_REPORT_PROTO");
break;
}
default:
break;
}
}
/**
* @brief USBD library specific event handler.
*
* @param event USBD library event.
* */
static void usbd_user_ev_handler(app_usbd_event_type_t event) {
switch (event) {
case APP_USBD_EVT_DRV_SOF:
break;
case APP_USBD_EVT_DRV_RESET:
m_report_pending = false;
break;
case APP_USBD_EVT_DRV_SUSPEND: // 3
m_report_pending = false;
app_usbd_suspend_req(); // Allow the library to put the peripheral into sleep mode
// bsp_board_leds_off();
break;
case APP_USBD_EVT_DRV_RESUME: // 4
m_report_pending = false;
// bsp_board_led_on(LED_USB_START);
kbd_status(); /* Restore LED state - during SUSPEND all LEDS are turned off */
break;
case APP_USBD_EVT_STARTED: // 2
m_report_pending = false;
// bsp_board_led_on(LED_USB_START);
break;
case APP_USBD_EVT_STOPPED:
app_usbd_disable();
// bsp_board_leds_off();
break;
case APP_USBD_EVT_POWER_DETECTED: // 0
NRF_LOG_INFO("USB power detected");
if (!nrf_drv_usbd_is_enabled()) {
app_usbd_enable();
}
ble_disconnect();
set_output(OUTPUT_USB);
break;
case APP_USBD_EVT_POWER_REMOVED:
NRF_LOG_INFO("USB power removed");
app_usbd_stop();
advertising_start(false);
break;
case APP_USBD_EVT_POWER_READY: // 1
NRF_LOG_INFO("USB ready");
app_usbd_start();
break;
default:
break;
}
}
#ifdef MOUSE_ENABLE
static ret_code_t idle_handle(app_usbd_class_inst_t const *p_inst, uint8_t report_id) {
switch (report_id) {
case 0: {
uint8_t report[] = {0xBE, 0xEF};
return app_usbd_hid_generic_idle_report_set(&m_app_hid_mouse, report, sizeof(report));
}
default:
return NRF_ERROR_NOT_SUPPORTED;
}
}
#endif
static uint8_t keyboard_leds(void);
static void send_keyboard(report_keyboard_t *report);
static void send_mouse(report_mouse_t *report);
static void send_system(uint16_t data);
static void send_consumer(uint16_t data);
static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};
host_driver_t *nrf5_usb_driver(void) { return &driver; }
static uint8_t keyboard_leds(void) { return keyboard_led_stats; }
static void send_keyboard(report_keyboard_t *report) {
if (NRF_USBD->ENABLE) {
hid_kbd_process_state(report);
}
}
static void send_mouse(report_mouse_t *report) {
#ifdef MOUSE_ENABLE
if (NRF_USBD->ENABLE) {
hid_mouse_process_state(report);
}
#endif
}
static void send_system(uint16_t data) {
#ifdef EXTRAKEY_ENABLE
if (NRF_USBD->ENABLE) {
hid_extra_process_state(REPORT_ID_SYSTEM, data);
}
#endif
}
static void send_consumer(uint16_t data) {
#ifdef EXTRAKEY_ENABLE
if (NRF_USBD->ENABLE) {
hid_extra_process_state(REPORT_ID_CONSUMER, data);
}
#endif
}
#ifdef MIDI_ENABLE
void send_midi_packet(MIDI_EventPacket_t *event) {
// NRF_LOG_INFO("asdfjkl %d", sizeof(MIDI_EventPacket_t));
// NRF_LOG_INFO("asdfjkl %d %d", event->Event, event->Data1);
// app_usbd_audio_class_tx_start(&m_app_audio_microphone.base, (uint8_t *)event, sizeof(MIDI_EventPacket_t));
// NRF_LOG_INFO("EPINEN: %d", NRF_USBD->EPINEN);
// chnWrite(&drivers.midi_driver.driver, (uint8_t *)event, sizeof(MIDI_EventPacket_t));
}
bool recv_midi_packet(MIDI_EventPacket_t *const event) {
// size_t size = chnReadTimeout(&drivers.midi_driver.driver, (uint8_t *)event, sizeof(MIDI_EventPacket_t), TIME_IMMEDIATE);
// return size == sizeof(MIDI_EventPacket_t);
return 0;
}
#endif
#include "nrf_delay.h"
void usb_keyboard_init(void) {
ret_code_t ret;
static const app_usbd_config_t usbd_config = {.ev_state_proc = usbd_user_ev_handler,
// chie4 add
.enable_sof = true};
ret = app_usbd_init(&usbd_config);
APP_ERROR_CHECK(ret);
app_usbd_class_inst_t const *class_inst_kbd;
class_inst_kbd = app_usbd_hid_generic_class_inst_get(&m_app_hid_kbd);
ret = app_usbd_class_append(class_inst_kbd);
APP_ERROR_CHECK(ret);
#ifdef NKRO_ENABLE
app_usbd_class_inst_t const *class_inst_kbd2;
class_inst_kbd2 = app_usbd_hid_generic_class_inst_get(&m_app_hid_kbd2);
ret = app_usbd_class_append(class_inst_kbd2);
APP_ERROR_CHECK(ret);
#endif
#ifdef MOUSE_ENABLE
app_usbd_class_inst_t const *class_inst_mouse;
class_inst_mouse = app_usbd_hid_generic_class_inst_get(&m_app_hid_mouse);
ret = hid_generic_idle_handler_set(class_inst_mouse, idle_handle);
ret = app_usbd_class_append(class_inst_mouse);
APP_ERROR_CHECK(ret);
#endif
#ifdef EXTRAKEY_ENABLE
app_usbd_class_inst_t const *class_inst_extra;
class_inst_extra = app_usbd_hid_generic_class_inst_get(&m_app_hid_extra);
ret = app_usbd_class_append(class_inst_extra);
APP_ERROR_CHECK(ret);
#endif
NRF_LOG_INFO("USBD HID composite example started.");
nrf_delay_ms(50);
ret = app_usbd_power_events_enable();
APP_ERROR_CHECK(ret);
}