Skip to content

Commit d8c9f8d

Browse files
committed
applications: nrf_desktop: Add USB HID next APIs
Change adds USB HID next APIs to the application. Jira: NCSDK-27014 Signed-off-by: Marek Pieta <Marek.Pieta@nordicsemi.no>
1 parent 31ccd03 commit d8c9f8d

File tree

2 files changed

+165
-17
lines changed

2 files changed

+165
-17
lines changed

applications/nrf_desktop/src/modules/Kconfig.usb_state

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,7 @@ config DESKTOP_USB_STACK_NEXT
5656
select EXPERIMENTAL
5757
select USB_DEVICE_STACK_NEXT
5858
help
59-
Use experimental integration of USB next stack. The USB next API is
60-
not yet integrated by the module's implementation. The option only
61-
disables the legacy USB stack and builds with the USB next stack.
59+
Use experimental integration of USB next stack.
6260

6361
config DESKTOP_USB_STACK_LEGACY
6462
bool "USB legacy stack"
@@ -143,6 +141,12 @@ endif # DESKTOP_USB_STACK_LEGACY
143141

144142
if DESKTOP_USB_STACK_NEXT
145143

144+
config USBD_HID_IN_BUF_COUNT
145+
default 1
146+
help
147+
nRF Desktop queues HID reports at the source. There is no need to use
148+
multiple buffers in the IN pool per HID instance.
149+
146150
choice USBD_LOG_LEVEL_CHOICE
147151
default USBD_LOG_LEVEL_WRN
148152
help

applications/nrf_desktop/src/modules/usb_state.c

Lines changed: 158 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <zephyr/usb/usb_device.h>
1919
#include <zephyr/usb/usb_ch9.h>
2020
#include <zephyr/usb/class/usb_hid.h>
21+
#include <zephyr/usb/class/usbd_hid.h>
2122

2223
#define MODULE usb_state
2324
#include <caf/events/module_state_event.h>
@@ -58,6 +59,7 @@ struct usb_hid_device {
5859
uint32_t report_bm;
5960
uint8_t hid_protocol;
6061
uint8_t sent_report_id;
62+
uint32_t idle_duration[REPORT_ID_COUNT];
6163
bool report_enabled[REPORT_ID_COUNT];
6264
bool enabled;
6365
};
@@ -70,7 +72,16 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_DESKTOP_USB_STACK_NEXT) ||
7072
"Unsupported USB stack");
7173

7274
#if CONFIG_DESKTOP_USB_STACK_NEXT
73-
static struct usb_hid_device usb_hid_device[0];
75+
#define USB_NEXT_USB_HID_DEVICE_INIT(node_id) \
76+
{ \
77+
.dev = DEVICE_DT_GET(node_id), \
78+
.hid_protocol = HID_PROTOCOL_REPORT, \
79+
.sent_report_id = REPORT_ID_COUNT, \
80+
},
81+
82+
static struct usb_hid_device usb_hid_device[] = {
83+
DT_FOREACH_STATUS_OKAY(zephyr_hid_device, USB_NEXT_USB_HID_DEVICE_INIT)
84+
};
7485
#else
7586
static struct usb_hid_device usb_hid_device[CONFIG_USB_HID_DEVICE_COUNT];
7687
#endif
@@ -220,11 +231,6 @@ static void report_sent(const struct device *dev, bool error)
220231
usb_hid->sent_report_id = REPORT_ID_COUNT;
221232
}
222233

223-
static void report_sent_cb(const struct device *dev)
224-
{
225-
report_sent(dev, false);
226-
}
227-
228234
static void send_hid_report(const struct hid_report_event *event)
229235
{
230236
struct usb_hid_device *usb_hid = NULL;
@@ -288,7 +294,15 @@ static void send_hid_report(const struct hid_report_event *event)
288294
int err = 0;
289295

290296
if (IS_ENABLED(CONFIG_DESKTOP_USB_STACK_NEXT)) {
291-
LOG_WRN("send_hid_report not integrated for USB next");
297+
/* USB next stack expects buffer alignment. */
298+
if (IS_ALIGNED(report_buffer, sizeof(void *))) {
299+
err = hid_device_submit_report(usb_hid->dev, report_size, report_buffer);
300+
} else {
301+
uint8_t temp[report_size] __aligned(sizeof(void *));
302+
303+
memcpy(temp, report_buffer, report_size);
304+
err = hid_device_submit_report(usb_hid->dev, report_size, temp);
305+
}
292306
} else {
293307
__ASSERT_NO_MSG(IS_ENABLED(CONFIG_DESKTOP_USB_STACK_LEGACY));
294308
err = hid_int_ep_write(usb_hid->dev, report_buffer, report_size, NULL);
@@ -300,11 +314,11 @@ static void send_hid_report(const struct hid_report_event *event)
300314
}
301315
}
302316

303-
static void broadcast_usb_state(void)
317+
static void broadcast_usb_state(enum usb_state broadcast_state)
304318
{
305319
struct usb_state_event *event = new_usb_state_event();
306320

307-
event->state = state;
321+
event->state = broadcast_state;
308322

309323
APP_EVENT_SUBMIT(event);
310324
}
@@ -633,14 +647,19 @@ static int set_report_legacy(const struct device *dev, struct usb_setup_packet *
633647
return err;
634648
}
635649

650+
static void report_sent_cb_legacy(const struct device *dev)
651+
{
652+
report_sent(dev, false);
653+
}
654+
636655
static int usb_init_legacy_hid_device_init(struct usb_hid_device *usb_hid_dev,
637656
const struct device *dev,
638657
uint32_t report_bm)
639658
{
640659
static const struct hid_ops hid_ops = {
641660
.get_report = get_report_legacy,
642661
.set_report = set_report_legacy,
643-
.int_in_ready = report_sent_cb,
662+
.int_in_ready = report_sent_cb_legacy,
644663
.protocol_change = protocol_change,
645664
};
646665

@@ -754,7 +773,7 @@ static void usb_init_legacy_status_cb(enum usb_dc_status_code cb_status, const u
754773

755774
/* Update state. */
756775
state = new_state;
757-
broadcast_usb_state();
776+
broadcast_usb_state(state);
758777

759778
/* HID subscribe when entering active state. */
760779
if (state == USB_STATE_ACTIVE) {
@@ -811,6 +830,121 @@ static int usb_init_legacy(void)
811830
return 0;
812831
}
813832

833+
static bool is_usb_active_next(void)
834+
{
835+
bool usb_active = false;
836+
837+
for (size_t i = 0; i < ARRAY_SIZE(usb_hid_device); i++) {
838+
if (usb_hid_device[i].enabled) {
839+
usb_active = true;
840+
break;
841+
}
842+
}
843+
844+
return usb_active;
845+
}
846+
847+
static void iface_ready_next(const struct device *dev, const bool ready)
848+
{
849+
struct usb_hid_device *usb_hid = dev_to_hid(dev);
850+
bool was_usb_active = is_usb_active_next();
851+
852+
update_usb_hid(usb_hid, ready);
853+
854+
bool is_usb_active = is_usb_active_next();
855+
856+
if (state == USB_STATE_SUSPENDED) {
857+
/* USB state update is delayed if USB is suspended. */
858+
return;
859+
}
860+
861+
if (!was_usb_active && is_usb_active) {
862+
broadcast_usb_state(USB_STATE_ACTIVE);
863+
} else if (was_usb_active && !is_usb_active) {
864+
broadcast_usb_state(state);
865+
}
866+
}
867+
868+
static int get_report_next(const struct device *dev, const uint8_t type, const uint8_t id,
869+
const uint16_t len, uint8_t *const buf)
870+
{
871+
/* Omit the first byte - HID report ID. */
872+
return get_report(dev, type, id, buf + 1, len - 1);
873+
}
874+
875+
static int set_report_next(const struct device *dev, const uint8_t type, const uint8_t id,
876+
const uint16_t len, const uint8_t *const buf)
877+
{
878+
/* Omit the first byte - HID report ID. */
879+
return set_report(dev, type, id, buf + 1, len - 1);
880+
}
881+
882+
static void set_idle_next(const struct device *dev, const uint8_t id, const uint32_t duration)
883+
{
884+
struct usb_hid_device *usb_hid = dev_to_hid(dev);
885+
886+
usb_hid->idle_duration[id] = duration;
887+
}
888+
889+
static uint32_t get_idle_next(const struct device *dev, const uint8_t id)
890+
{
891+
struct usb_hid_device *usb_hid = dev_to_hid(dev);
892+
893+
return usb_hid->idle_duration[id];
894+
}
895+
896+
static void report_sent_cb_next(const struct device *dev)
897+
{
898+
struct usb_hid_device *usb_hid = dev_to_hid(dev);
899+
900+
/* USB next stack does not explicitly indicate failed transfers. */
901+
if (usb_hid->enabled) {
902+
report_sent(dev, false);
903+
} else {
904+
report_sent(dev, true);
905+
}
906+
}
907+
908+
static int usb_init_next_hid_device_init(struct usb_hid_device *usb_hid_dev, uint32_t report_bm)
909+
{
910+
static const struct hid_device_ops hid_ops = {
911+
.iface_ready = iface_ready_next,
912+
.get_report = get_report_next,
913+
.set_report = set_report_next,
914+
.set_idle = set_idle_next,
915+
.get_idle = get_idle_next,
916+
.set_protocol = protocol_change,
917+
.input_report_done = report_sent_cb_next,
918+
};
919+
920+
usb_hid_dev->report_bm = report_bm;
921+
922+
int err = hid_device_register(usb_hid_dev->dev, hid_report_desc, hid_report_desc_size,
923+
&hid_ops);
924+
925+
if (err) {
926+
LOG_ERR("hid_device_register failed for %p (err: %d)",
927+
(void *)usb_hid_dev->dev, err);
928+
}
929+
930+
return err;
931+
}
932+
933+
static int usb_init_next_hids_init(void)
934+
{
935+
int err = 0;
936+
937+
for (size_t i = 0; i < ARRAY_SIZE(usb_hid_device); i++) {
938+
err = usb_init_next_hid_device_init(&usb_hid_device[i], get_report_bm(i));
939+
if (err) {
940+
LOG_ERR("usb_init_next_hid_device_init failed (err: %d)", err);
941+
break;
942+
}
943+
}
944+
945+
return err;
946+
}
947+
814948
static void usb_init_next_status_cb(struct usbd_contex *const contex,
815949
const struct usbd_msg *const msg)
816950
{
@@ -871,7 +1005,11 @@ static void usb_init_next_status_cb(struct usbd_contex *const contex,
8711005
}
8721006

8731007
if (new_state != state) {
874-
broadcast_usb_state(new_state);
1008+
if ((state == USB_STATE_SUSPENDED) && is_usb_active_next()) {
1009+
broadcast_usb_state(USB_STATE_ACTIVE);
1010+
} else {
1011+
broadcast_usb_state(new_state);
1012+
}
8751013
state = new_state;
8761014
}
8771015
}
@@ -1016,15 +1154,21 @@ static struct usbd_contex *usb_init_next_usbd_init(void)
10161154

10171155
static int usb_init_next(void)
10181156
{
1157+
int err = usb_init_next_hids_init();
1158+
1159+
if (err) {
1160+
LOG_ERR("usb_init_next_hids_init failed (err: %d)", err);
1161+
return err;
1162+
}
1163+
10191164
struct usbd_contex *usbd = usb_init_next_usbd_init();
10201165

10211166
if (!usbd) {
10221167
LOG_ERR("usb_init_next_usbd_init failed");
10231168
return -ENXIO;
10241169
}
10251170

1026-
int err = usbd_msg_register_cb(usbd, usb_init_next_status_cb);
1027-
1171+
err = usbd_msg_register_cb(usbd, usb_init_next_status_cb);
10281172
if (err) {
10291173
LOG_ERR("usbd_msg_register_cb failed (err: %d)", err);
10301174
return err;

0 commit comments

Comments
 (0)