blob: 2d5dfeb6594012d43a3d9d79e874874bb23c04e4 [file] [log] [blame]
/*
* Copyright (c) 2016-2018 Intel Corporation.
* Copyright (c) 2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <init.h>
#include <usb/usb_device.h>
#include <usb/class/usb_hid.h>
#define LOG_LEVEL LOG_LEVEL_DBG
LOG_MODULE_REGISTER(main);
#define REPORT_ID_1 0x01
#define REPORT_ID_2 0x02
static struct k_delayed_work delayed_report_send;
static struct device *hdev;
#define REPORT_TIMEOUT K_SECONDS(2)
/* Some HID sample Report Descriptor */
static const u8_t hid_report_desc[] = {
/* 0x05, 0x01, USAGE_PAGE (Generic Desktop) */
HID_GI_USAGE_PAGE, USAGE_GEN_DESKTOP,
/* 0x09, 0x00, USAGE (Undefined) */
HID_LI_USAGE, USAGE_GEN_DESKTOP_UNDEFINED,
/* 0xa1, 0x01, COLLECTION (Application) */
HID_MI_COLLECTION, COLLECTION_APPLICATION,
/* 0x15, 0x00, LOGICAL_MINIMUM one-byte (0) */
HID_GI_LOGICAL_MIN(1), 0x00,
/* 0x26, 0xff, 0x00, LOGICAL_MAXIMUM two-bytes (255) */
HID_GI_LOGICAL_MAX(2), 0xFF, 0x00,
/* 0x85, 0x01, REPORT_ID (1) */
HID_GI_REPORT_ID, REPORT_ID_1,
/* 0x75, 0x08, REPORT_SIZE (8) in bits */
HID_GI_REPORT_SIZE, 0x08,
/* 0x95, 0x01, REPORT_COUNT (1) */
HID_GI_REPORT_COUNT, 0x01,
/* 0x09, 0x00, USAGE (Undefined) */
HID_LI_USAGE, USAGE_GEN_DESKTOP_UNDEFINED,
/* v0x81, 0x82, INPUT (Data,Var,Abs,Vol) */
HID_MI_INPUT, 0x82,
/* 0x85, 0x02, REPORT_ID (2) */
HID_GI_REPORT_ID, REPORT_ID_2,
/* 0x75, 0x08, REPORT_SIZE (8) in bits */
HID_GI_REPORT_SIZE, 0x08,
/* 0x95, 0x01, REPORT_COUNT (1) */
HID_GI_REPORT_COUNT, 0x01,
/* 0x09, 0x00, USAGE (Undefined) */
HID_LI_USAGE, USAGE_GEN_DESKTOP_UNDEFINED,
/* 0x91, 0x82, OUTPUT (Data,Var,Abs,Vol) */
HID_MI_OUTPUT, 0x82,
/* 0xc0 END_COLLECTION */
HID_MI_COLLECTION_END,
};
static void send_report(struct k_work *work)
{
static u8_t report_1[2] = { REPORT_ID_1, 0x00 };
int ret, wrote;
ret = hid_int_ep_write(hdev, report_1, sizeof(report_1), &wrote);
LOG_DBG("Wrote %d bytes with ret %d", wrote, ret);
/* Increment reported data */
report_1[1]++;
}
static void in_ready_cb(void)
{
k_delayed_work_submit(&delayed_report_send, REPORT_TIMEOUT);
}
static void status_cb(enum usb_dc_status_code status, const u8_t *param)
{
switch (status) {
case USB_DC_CONFIGURED:
in_ready_cb();
break;
case USB_DC_SOF:
break;
default:
LOG_DBG("status %u unhandled", status);
break;
}
}
static void idle_cb(u16_t report_id)
{
static u8_t report_1[2] = { 0x00, 0xEB };
int ret, wrote;
ret = hid_int_ep_write(hdev, report_1, sizeof(report_1), &wrote);
LOG_DBG("Idle callback: wrote %d bytes with ret %d", wrote, ret);
}
static void protocol_cb(u8_t protocol)
{
LOG_DBG("New protocol: %s", protocol == HID_PROTOCOL_BOOT ?
"boot" : "report");
}
static const struct hid_ops ops = {
.int_in_ready = in_ready_cb,
.status_cb = status_cb,
.on_idle = idle_cb,
.protocol_change = protocol_cb,
};
void main(void)
{
LOG_DBG("Starting application");
k_delayed_work_init(&delayed_report_send, send_report);
#ifndef CONFIG_USB_COMPOSITE_DEVICE
hdev = device_get_binding(CONFIG_USB_HID_DEVICE_NAME_0);
if (hdev == NULL) {
LOG_ERR("Cannot get USB HID Device");
return;
}
LOG_DBG("HID Device: dev %p", hdev);
usb_hid_register_device(hdev, hid_report_desc, sizeof(hid_report_desc),
&ops);
usb_hid_init(hdev);
#endif
}
#ifdef CONFIG_USB_COMPOSITE_DEVICE
static int composite_pre_init(struct device *dev)
{
hdev = device_get_binding(CONFIG_USB_HID_DEVICE_NAME_0);
if (hdev == NULL) {
LOG_ERR("Cannot get USB HID Device");
return -ENODEV;
}
LOG_DBG("HID Device: dev %p", hdev);
usb_hid_register_device(hdev, hid_report_desc, sizeof(hid_report_desc),
&ops);
return usb_hid_init(hdev);
}
SYS_INIT(composite_pre_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
#endif