Skip to content

Commit 1ced2a3

Browse files
MarekPietanordicjm
authored andcommitted
applications: nrf_desktop: Make set/get report more generic in USB state
Change makes set_report and get_report functions more generic to allow code reuse. Jira: NCSDK-27014 Signed-off-by: Marek Pieta <[email protected]>
1 parent e6bb2c0 commit 1ced2a3

File tree

1 file changed

+123
-84
lines changed

1 file changed

+123
-84
lines changed

applications/nrf_desktop/src/modules/usb_state.c

Lines changed: 123 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -82,44 +82,21 @@ static struct usb_hid_device *dev_to_hid(const struct device *dev)
8282
return usb_hid;
8383
}
8484

85-
static int get_report(const struct device *dev,
86-
struct usb_setup_packet *setup,
87-
int32_t *len_to_set, uint8_t **data)
85+
static int get_report(const struct device *dev, uint8_t report_type, uint8_t report_id,
86+
uint8_t *buf, size_t size)
8887
{
89-
uint8_t request_value[2];
90-
91-
sys_put_le16(setup->wValue, request_value);
88+
int err = -ENOTSUP;
9289

93-
switch (request_value[1]) {
90+
switch (report_type) {
9491
case REPORT_TYPE_FEATURE:
9592
if (IS_ENABLED(CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE) &&
96-
(request_value[0] == REPORT_ID_USER_CONFIG) &&
97-
(setup->wLength == (REPORT_SIZE_USER_CONFIG + sizeof(uint8_t)))) {
98-
size_t length = setup->wLength;
99-
uint8_t *buffer = *data;
100-
101-
/* HID Feature report ID is specific to USB.
102-
* Config channel does not use it.
103-
*/
104-
buffer[0] = REPORT_ID_USER_CONFIG;
105-
106-
int err = 0;
107-
93+
(report_id == REPORT_ID_USER_CONFIG) &&
94+
(size == REPORT_SIZE_USER_CONFIG)) {
10895
if (dev == usb_hid_device[0].dev) {
109-
err = config_channel_transport_get(&cfg_chan_transport,
110-
&buffer[1],
111-
length - 1);
96+
err = config_channel_transport_get(&cfg_chan_transport, buf, size);
11297
} else {
113-
err = config_channel_transport_get_disabled(&buffer[1], length - 1);
114-
}
115-
116-
if (err) {
117-
LOG_WRN("Failed to process report get (err: %d)", err);
98+
err = config_channel_transport_get_disabled(buf, size);
11899
}
119-
120-
*len_to_set = length;
121-
122-
return err;
123100
}
124101
break;
125102

@@ -132,46 +109,26 @@ static int get_report(const struct device *dev,
132109
break;
133110
}
134111

135-
LOG_WRN("Unsupported get report");
136-
LOG_WRN("bmRequestType: %02X bRequest: %02X wValue: %04X wIndex: %04X"
137-
" wLength: %04X", setup->bmRequestType, setup->bRequest,
138-
setup->wValue, setup->wIndex, setup->wLength);
139-
140-
return -ENOTSUP;
112+
return err;
141113
}
142114

143-
static int set_report(const struct device *dev,
144-
struct usb_setup_packet *setup,
145-
int32_t *len, uint8_t **data)
115+
static int set_report(const struct device *dev, uint8_t report_type, uint8_t report_id,
116+
const uint8_t *buf, size_t size)
146117
{
147-
uint8_t request_value[2];
118+
int err = -ENOTSUP;
148119

149-
sys_put_le16(setup->wValue, request_value);
150-
151-
switch (request_value[1]) {
120+
switch (report_type) {
152121
case REPORT_TYPE_FEATURE:
153122
if (IS_ENABLED(CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE) &&
154-
(request_value[0] == REPORT_ID_USER_CONFIG) &&
155-
(setup->wLength == (REPORT_SIZE_USER_CONFIG + sizeof(uint8_t)))) {
123+
(report_id == REPORT_ID_USER_CONFIG) &&
124+
(size == REPORT_SIZE_USER_CONFIG)) {
156125
if (dev == usb_hid_device[0].dev) {
157-
size_t length = setup->wLength;
158-
uint8_t *buffer = *data;
159-
160-
/* HID Feature report ID is specific to USB.
161-
* Config channel does not use it.
162-
*/
163-
int err = config_channel_transport_set(&cfg_chan_transport,
164-
&buffer[1],
165-
length - 1);
166-
167-
if (err) {
168-
LOG_WRN("Failed to process report set");
169-
}
170-
171-
return err;
126+
err = config_channel_transport_set(&cfg_chan_transport, buf, size);
172127
} else {
173-
/* Configuration channel does not use this USB HID instance. */
174-
return 0;
128+
/* Ignore the request. Configuration channel does not use this USB
129+
* HID instance.
130+
*/
131+
err = 0;
175132
}
176133
}
177134
break;
@@ -180,38 +137,37 @@ static int set_report(const struct device *dev,
180137
if (IS_ENABLED(CONFIG_DESKTOP_HID_REPORT_KEYBOARD_SUPPORT)) {
181138
struct usb_hid_device *usb_hid = dev_to_hid(dev);
182139

183-
if ((request_value[0] == REPORT_ID_KEYBOARD_LEDS) &&
140+
if ((report_id == REPORT_ID_KEYBOARD_LEDS) &&
184141
(usb_hid->hid_protocol == HID_PROTOCOL_REPORT) &&
185-
(setup->wLength == (REPORT_SIZE_KEYBOARD_LEDS + sizeof(uint8_t)))) {
142+
(size == REPORT_SIZE_KEYBOARD_LEDS)) {
186143
/* Handle HID keyboard LEDs report. */
187144
} else if (IS_ENABLED(CONFIG_DESKTOP_HID_BOOT_INTERFACE_KEYBOARD) &&
188-
(request_value[0] == REPORT_ID_RESERVED) &&
145+
(report_id == REPORT_ID_RESERVED) &&
189146
(usb_hid->hid_protocol == HID_PROTOCOL_BOOT) &&
190-
(setup->wLength == REPORT_SIZE_KEYBOARD_LEDS)) {
147+
(size == REPORT_SIZE_KEYBOARD_LEDS)) {
191148
/* Handle HID boot keyboard LEDs report. */
192149
} else {
193150
/* Ignore invalid report. */
194151
break;
195152
}
196153

197-
size_t dyndata_len = REPORT_SIZE_KEYBOARD_LEDS + sizeof(uint8_t);
154+
size_t dyndata_len = sizeof(uint8_t) + REPORT_SIZE_KEYBOARD_LEDS;
198155
struct hid_report_event *event = new_hid_report_event(dyndata_len);
199156

200157
event->source = usb_hid;
201158
/* Subscriber is not specified for HID output report. */
202159
event->subscriber = NULL;
203160

204-
uint8_t *buf = event->dyndata.data;
205-
206-
if (setup->wLength == REPORT_SIZE_KEYBOARD_LEDS) {
207-
*buf = REPORT_ID_KEYBOARD_LEDS;
208-
buf++;
209-
}
161+
uint8_t *evt_buf = event->dyndata.data;
210162

211-
memcpy(buf, *data, setup->wLength);
163+
/* Explicitly add report ID. */
164+
evt_buf[0] = REPORT_ID_KEYBOARD_LEDS;
165+
evt_buf++;
212166

167+
memcpy(evt_buf, buf, size);
213168
APP_EVENT_SUBMIT(event);
214-
return 0;
169+
170+
err = 0;
215171
}
216172
break;
217173

@@ -221,12 +177,7 @@ static int set_report(const struct device *dev,
221177
break;
222178
}
223179

224-
LOG_WRN("Unsupported set report");
225-
LOG_WRN("bmRequestType: %02X bRequest: %02X wValue: %04X wIndex: %04X"
226-
" wLength: %04X", setup->bmRequestType, setup->bRequest,
227-
setup->wValue, setup->wIndex, setup->wLength);
228-
229-
return -ENOTSUP;
180+
return err;
230181
}
231182

232183
static void report_sent(const struct device *dev, bool error)
@@ -630,11 +581,99 @@ static void verify_report_bm(void)
630581
#endif
631582
}
632583

584+
static void report_legacy_wValue_parse(uint16_t wValue, uint8_t *report_type, uint8_t *report_id)
585+
{
586+
uint8_t request_value[2];
587+
588+
sys_put_le16(wValue, request_value);
589+
*report_type = request_value[1];
590+
*report_id = request_value[0];
591+
}
592+
593+
static int get_report_legacy(const struct device *dev, struct usb_setup_packet *setup,
594+
int32_t *len_to_set, uint8_t **data)
595+
{
596+
__ASSERT_NO_MSG(dev);
597+
__ASSERT_NO_MSG(setup);
598+
__ASSERT_NO_MSG(len_to_set);
599+
__ASSERT_NO_MSG(data);
600+
601+
uint8_t report_type;
602+
uint8_t report_id;
603+
uint8_t *buf = *data;
604+
size_t size = setup->wLength;
605+
606+
report_legacy_wValue_parse(setup->wValue, &report_type, &report_id);
607+
608+
if (report_id != REPORT_ID_RESERVED) {
609+
buf[0] = report_id;
610+
buf++;
611+
size--;
612+
}
613+
614+
int err = get_report(dev, report_type, report_id, buf, size);
615+
616+
if (err) {
617+
LOG_WRN("get_report_legacy failed (err: %d)", err);
618+
LOG_WRN("bmRequestType: %02X bRequest: %02X wValue: %04X wIndex: %04X"
619+
" wLength: %04X", setup->bmRequestType, setup->bRequest,
620+
setup->wValue, setup->wIndex, setup->wLength);
621+
LOG_HEXDUMP_WRN(buf, size, "Get report");
622+
} else {
623+
*len_to_set = setup->wLength;
624+
}
625+
626+
return err;
627+
}
628+
629+
static int set_report_legacy(const struct device *dev, struct usb_setup_packet *setup,
630+
int32_t *len, uint8_t **data)
631+
{
632+
__ASSERT_NO_MSG(dev);
633+
__ASSERT_NO_MSG(setup);
634+
__ASSERT_NO_MSG(len);
635+
__ASSERT_NO_MSG(data);
636+
637+
uint8_t report_type;
638+
uint8_t report_id;
639+
uint8_t *buf = *data;
640+
size_t size = setup->wLength;
641+
642+
report_legacy_wValue_parse(setup->wValue, &report_type, &report_id);
643+
644+
int err = 0;
645+
646+
if (report_id != REPORT_ID_RESERVED) {
647+
/* The first byte of buf is report ID. Validate it and omit. */
648+
if (report_id == buf[0]) {
649+
buf++;
650+
size--;
651+
} else {
652+
LOG_WRN("HID report ID mismatch");
653+
err = -EINVAL;
654+
}
655+
}
656+
657+
if (!err) {
658+
err = set_report(dev, report_type, report_id, buf, size);
659+
}
660+
661+
if (err) {
662+
LOG_WRN("set_report_legacy failed (err: %d)", err);
663+
LOG_WRN("bmRequestType: %02X bRequest: %02X wValue: %04X wIndex: %04X"
664+
" wLength: %04X", setup->bmRequestType, setup->bRequest,
665+
setup->wValue, setup->wIndex, setup->wLength);
666+
LOG_HEXDUMP_WRN(buf, size, "Set report");
667+
}
668+
669+
return err;
670+
}
671+
633672
static int usb_init(void)
634673
{
635674
static const struct hid_ops hid_ops = {
636-
.get_report = get_report,
637-
.set_report = set_report,
675+
.get_report = get_report_legacy,
676+
.set_report = set_report_legacy,
638677
.int_in_ready = report_sent_cb,
639678
.protocol_change = protocol_change,
640679
};

0 commit comments

Comments
 (0)