usb: hid: All hid_ops callbacks get device pointer.

This commit extends USB hid API callbacks by adding
'const struct device *dev' parameter. If the application
configured more than one HID device then it must specify
separate hid_ops for each device as its unable to determine
for which device the callback was called.

This patch makes it possible to have only one hid_ops within
the application and the application is aware for which device
the callback was called because of explicit device pointer.

Signed-off-by: Emil Obalski <emil.obalski@nordicsemi.no>
This commit is contained in:
Emil Obalski 2020-08-17 15:17:14 +02:00 committed by Carles Cufí
commit 0d8bd579a5
5 changed files with 43 additions and 30 deletions

View file

@ -103,6 +103,10 @@ Removed APIs in this release
Stable API changes in this release Stable API changes in this release
================================== ==================================
* USB
* HID class callbacks now takes a parameter ``const struct device*`` which
is the HID device for which callback was called.
Kernel Kernel
****** ******

View file

@ -57,11 +57,12 @@ struct usb_hid_descriptor {
/* Public headers */ /* Public headers */
typedef int (*hid_cb_t)(struct usb_setup_packet *setup, int32_t *len, typedef int (*hid_cb_t)(const struct device *dev,
struct usb_setup_packet *setup, int32_t *len,
uint8_t **data); uint8_t **data);
typedef void (*hid_int_ready_callback)(void); typedef void (*hid_int_ready_callback)(const struct device *dev);
typedef void (*hid_protocol_cb_t)(uint8_t protocol); typedef void (*hid_protocol_cb_t)(const struct device *dev, uint8_t protocol);
typedef void (*hid_idle_cb_t)(uint16_t report_id); typedef void (*hid_idle_cb_t)(const struct device *dev, uint16_t report_id);
struct hid_ops { struct hid_ops {
hid_cb_t get_report; hid_cb_t get_report;

View file

@ -192,8 +192,10 @@ static const char *evt_fail = "Unknown event detected!\r\n";
static const char *set_str = "String set to: "; static const char *set_str = "String set to: ";
static const char *endl = "\r\n"; static const char *endl = "\r\n";
static void in_ready_cb(void) static void in_ready_cb(const struct device *dev)
{ {
ARG_UNUSED(dev);
k_sem_give(&usb_sem); k_sem_give(&usb_sem);
} }

View file

@ -72,8 +72,10 @@ static void send_report(struct k_work *work)
report_1[1]++; report_1[1]++;
} }
static void in_ready_cb(void) static void in_ready_cb(const struct device *dev)
{ {
ARG_UNUSED(dev);
k_delayed_work_submit(&delayed_report_send, REPORT_TIMEOUT); k_delayed_work_submit(&delayed_report_send, REPORT_TIMEOUT);
} }
@ -81,7 +83,7 @@ static void status_cb(enum usb_dc_status_code status, const uint8_t *param)
{ {
switch (status) { switch (status) {
case USB_DC_CONFIGURED: case USB_DC_CONFIGURED:
in_ready_cb(); in_ready_cb(hdev);
break; break;
case USB_DC_SOF: case USB_DC_SOF:
break; break;
@ -91,17 +93,17 @@ static void status_cb(enum usb_dc_status_code status, const uint8_t *param)
} }
} }
static void idle_cb(uint16_t report_id) static void idle_cb(const struct device *dev, uint16_t report_id)
{ {
static uint8_t report_1[2] = { 0x00, 0xEB }; static uint8_t report_1[2] = { 0x00, 0xEB };
int ret, wrote; int ret, wrote;
ret = hid_int_ep_write(hdev, report_1, sizeof(report_1), &wrote); ret = hid_int_ep_write(dev, report_1, sizeof(report_1), &wrote);
LOG_DBG("Idle callback: wrote %d bytes with ret %d", wrote, ret); LOG_DBG("Idle callback: wrote %d bytes with ret %d", wrote, ret);
} }
static void protocol_cb(uint8_t protocol) static void protocol_cb(const struct device *dev, uint8_t protocol)
{ {
LOG_DBG("New protocol: %s", protocol == HID_PROTOCOL_BOOT ? LOG_DBG("New protocol: %s", protocol == HID_PROTOCOL_BOOT ?
"boot" : "report"); "boot" : "report");

View file

@ -255,12 +255,12 @@ static int hid_on_set_report(struct hid_device_info *dev_data,
return -ENOTSUP; return -ENOTSUP;
} }
static int hid_on_set_protocol(struct hid_device_info *dev_data, static int hid_on_set_protocol(const struct device *dev,
struct usb_setup_packet *setup, int32_t *len, struct hid_device_info *dev_data,
uint8_t **data) struct usb_setup_packet *setup)
{ {
#ifdef CONFIG_USB_HID_BOOT_PROTOCOL #ifdef CONFIG_USB_HID_BOOT_PROTOCOL
uint16_t protocol = (uint8_t)setup->wValue; uint16_t protocol = setup->wValue;
if (protocol > HID_PROTOCOL_REPORT) { if (protocol > HID_PROTOCOL_REPORT) {
LOG_ERR("Unsupported protocol: %u", protocol); LOG_ERR("Unsupported protocol: %u", protocol);
@ -273,7 +273,7 @@ static int hid_on_set_protocol(struct hid_device_info *dev_data,
dev_data->protocol = protocol; dev_data->protocol = protocol;
if (dev_data->ops && dev_data->ops->protocol_change) { if (dev_data->ops && dev_data->ops->protocol_change) {
dev_data->ops->protocol_change(protocol); dev_data->ops->protocol_change(dev, protocol);
} }
} }
@ -308,6 +308,8 @@ void hid_clear_idle_ctx(struct hid_device_info *dev_data)
void hid_sof_handler(struct hid_device_info *dev_data) void hid_sof_handler(struct hid_device_info *dev_data)
{ {
const struct device *dev = dev_data->common.dev;
for (uint16_t i = 0; i <= CONFIG_USB_HID_REPORTS; i++) { for (uint16_t i = 0; i <= CONFIG_USB_HID_REPORTS; i++) {
if (dev_data->idle_rate[i]) { if (dev_data->idle_rate[i]) {
dev_data->sof_cnt[i]++; dev_data->sof_cnt[i]++;
@ -319,7 +321,7 @@ void hid_sof_handler(struct hid_device_info *dev_data)
if (diff < (2 + (dev_data->idle_rate[i] / 10U))) { if (diff < (2 + (dev_data->idle_rate[i] / 10U))) {
dev_data->sof_cnt[i] = 0U; dev_data->sof_cnt[i] = 0U;
if (dev_data->ops && dev_data->ops->on_idle) { if (dev_data->ops && dev_data->ops->on_idle) {
dev_data->ops->on_idle(i); dev_data->ops->on_idle(dev, i);
} }
} }
@ -417,6 +419,7 @@ static int hid_class_handle_req(struct usb_setup_packet *setup,
{ {
struct hid_device_info *dev_data; struct hid_device_info *dev_data;
struct usb_dev_data *common; struct usb_dev_data *common;
const struct device *dev;
LOG_DBG("Class request:" LOG_DBG("Class request:"
"bRequest 0x%02x, bmRequestType 0x%02x len %d", "bRequest 0x%02x, bmRequestType 0x%02x len %d",
@ -431,12 +434,13 @@ static int hid_class_handle_req(struct usb_setup_packet *setup,
} }
dev_data = CONTAINER_OF(common, struct hid_device_info, common); dev_data = CONTAINER_OF(common, struct hid_device_info, common);
dev = common->dev;
if (REQTYPE_GET_DIR(setup->bmRequestType) == REQTYPE_DIR_TO_HOST) { if (REQTYPE_GET_DIR(setup->bmRequestType) == REQTYPE_DIR_TO_HOST) {
switch (setup->bRequest) { switch (setup->bRequest) {
case HID_GET_IDLE: case HID_GET_IDLE:
if (dev_data->ops && dev_data->ops->get_idle) { if (dev_data->ops && dev_data->ops->get_idle) {
return dev_data->ops->get_idle(setup, len, return dev_data->ops->get_idle(dev, setup, len,
data); data);
} else { } else {
return hid_on_get_idle(dev_data, setup, len, return hid_on_get_idle(dev_data, setup, len,
@ -445,8 +449,8 @@ static int hid_class_handle_req(struct usb_setup_packet *setup,
break; break;
case HID_GET_REPORT: case HID_GET_REPORT:
if (dev_data->ops && dev_data->ops->get_report) { if (dev_data->ops && dev_data->ops->get_report) {
return dev_data->ops->get_report(setup, len, return dev_data->ops->get_report(dev, setup,
data); len, data);
} else { } else {
return hid_on_get_report(dev_data, setup, len, return hid_on_get_report(dev_data, setup, len,
data); data);
@ -454,8 +458,8 @@ static int hid_class_handle_req(struct usb_setup_packet *setup,
break; break;
case HID_GET_PROTOCOL: case HID_GET_PROTOCOL:
if (dev_data->ops && dev_data->ops->get_protocol) { if (dev_data->ops && dev_data->ops->get_protocol) {
return dev_data->ops->get_protocol(setup, len, return dev_data->ops->get_protocol(dev, setup,
data); len, data);
} else { } else {
return hid_on_get_protocol(dev_data, setup, len, return hid_on_get_protocol(dev_data, setup, len,
data); data);
@ -469,7 +473,7 @@ static int hid_class_handle_req(struct usb_setup_packet *setup,
switch (setup->bRequest) { switch (setup->bRequest) {
case HID_SET_IDLE: case HID_SET_IDLE:
if (dev_data->ops && dev_data->ops->set_idle) { if (dev_data->ops && dev_data->ops->set_idle) {
return dev_data->ops->set_idle(setup, len, return dev_data->ops->set_idle(dev, setup, len,
data); data);
} else { } else {
return hid_on_set_idle(dev_data, setup, len, return hid_on_set_idle(dev_data, setup, len,
@ -478,8 +482,8 @@ static int hid_class_handle_req(struct usb_setup_packet *setup,
break; break;
case HID_SET_REPORT: case HID_SET_REPORT:
if (dev_data->ops && dev_data->ops->set_report) { if (dev_data->ops && dev_data->ops->set_report) {
return dev_data->ops->set_report(setup, len, return dev_data->ops->set_report(dev, setup,
data); len, data);
} else { } else {
return hid_on_set_report(dev_data, setup, len, return hid_on_set_report(dev_data, setup, len,
data); data);
@ -487,11 +491,11 @@ static int hid_class_handle_req(struct usb_setup_packet *setup,
break; break;
case HID_SET_PROTOCOL: case HID_SET_PROTOCOL:
if (dev_data->ops && dev_data->ops->set_protocol) { if (dev_data->ops && dev_data->ops->set_protocol) {
return dev_data->ops->set_protocol(setup, len, return dev_data->ops->set_protocol(dev, setup,
data); len, data);
} else { } else {
return hid_on_set_protocol(dev_data, setup, len, return hid_on_set_protocol(dev, dev_data,
data); setup);
} }
break; break;
default: default:
@ -582,7 +586,7 @@ static void hid_int_in(uint8_t ep, enum usb_dc_ep_cb_status_code ep_status)
return; return;
} }
dev_data->ops->int_in_ready(); dev_data->ops->int_in_ready(common->dev);
} }
#ifdef CONFIG_ENABLE_HID_INT_OUT_EP #ifdef CONFIG_ENABLE_HID_INT_OUT_EP
@ -604,7 +608,7 @@ static void hid_int_out(uint8_t ep, enum usb_dc_ep_cb_status_code ep_status)
return; return;
} }
dev_data->ops->int_out_ready(); dev_data->ops->int_out_ready(common->dev);
} }
#endif #endif