Skip to content
Permalink
Browse files

samples: intel_s1000: USB control for audio sample

Add USB transport driver to control the sample application
from a host connected to Intel® Sue Creek S1000 board
via an USB interface.

Signed-off-by: Sathish Kuttan <sathish.k.kuttan@intel.com>
  • Loading branch information...
sathishkuttan authored and nashif committed Jun 28, 2019
1 parent d19a5f9 commit 3adf7e034e6bbdc518b760d915ba8843f8d8dbfc
@@ -0,0 +1,202 @@
/*
* Copyright (c) 2019 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/

#define LOG_LEVEL LOG_LEVEL_INF
#include <logging/log.h>
LOG_MODULE_REGISTER(usb_transport);

#include <zephyr.h>

#include <usb/usb_device.h>
#include <usb/class/usb_hid.h>

#include "usb_transport.h"

/* callback function list */
static int usb_transport_get_report(struct usb_setup_packet *setup,
s32_t *len, u8_t **data);
static int usb_transport_get_idle(struct usb_setup_packet *setup,
s32_t *len, u8_t **data);
static int usb_transport_get_protocol(struct usb_setup_packet *setup,
s32_t *len, u8_t **data);
static int usb_transport_set_report(struct usb_setup_packet *setup,
s32_t *len, u8_t **data);
static int usb_transport_set_idle(struct usb_setup_packet *setup,
s32_t *len, u8_t **data);
static int usb_transport_set_protocol(struct usb_setup_packet *setup,
s32_t *len, u8_t **data);
static void usb_transport_host_ready(void);

static const struct hid_ops usb_transport_callbacks = {
.get_report = usb_transport_get_report,
.get_idle = usb_transport_get_idle,
.get_protocol = usb_transport_get_protocol,
.set_report = usb_transport_set_report,
.set_idle = usb_transport_set_idle,
.set_protocol = usb_transport_set_protocol,
.int_in_ready = usb_transport_host_ready,
};

/* create an HID report descriptor with input and output reports */
static const u8_t usb_transport_hid_report_desc[] = {
/* Usage page: vendor defined */
HID_GLOBAL_ITEM(ITEM_TAG_USAGE_PAGE, 2), 0x00, 0xFF,

/* Usage: vendor specific */
HID_LI_USAGE, 0x01,
/* Collection: Application Collection */
HID_MI_COLLECTION, COLLECTION_APPLICATION,
/* Logical Minimum: 0 */
HID_GI_LOGICAL_MIN(1), 0x00,
/* Logical Maximum: 255 */
HID_GI_LOGICAL_MAX(1), 0xFF,
/* Report Size: 8 bits */
HID_GI_REPORT_SIZE, 0x08,
/* Report Count (in bytes) */
HID_GI_REPORT_COUNT, (USB_TPORT_HID_REPORT_COUNT - 1),

/* Report ID: 1 */
HID_GI_REPORT_ID, USB_TPORT_HID_REPORT_ID,
/* Vendor Usage 2 */
HID_LI_USAGE, 0x02,
/* Input: Data, Variable, Absolute & Buffered bytes*/
HID_MI_INPUT, 0x86,

/* Report ID: 1 */
HID_GI_REPORT_ID, USB_TPORT_HID_REPORT_ID,
/* Vendor Usage 2 */
HID_LI_USAGE, 0x02,
/* Output: Data, Variable, Absolute & Buffered bytes*/
HID_MI_OUTPUT, 0x86,

/* End collection */
HID_MI_COLLECTION_END,
};

static usb_transport_receive_callback_t receive_data_cb;

static struct device *hid_device;

int usb_transport_init(usb_transport_receive_callback_t callback)
{
hid_device = device_get_binding("HID_0");

if (hid_device == NULL) {
LOG_ERR("USB HID Device not found");
return -ENODEV;
}

/* register a HID device and the callback functions */
usb_hid_register_device(hid_device, usb_transport_hid_report_desc,
sizeof(usb_transport_hid_report_desc),
&usb_transport_callbacks);

receive_data_cb = callback;

/* initialize USB interface and HID class */
return usb_hid_init(hid_device);
}

int usb_transport_send_reply(u8_t *data, u32_t len)
{
int ret = 0;
u32_t written = 0;
union usb_hid_report_hdr *header;

/* roll back buffer to point to header */
data = data - sizeof(union usb_hid_report_hdr);
header = (union usb_hid_report_hdr *)data;

/* send reply in one or more HID reports */
while (len) {
/* populate header */
header->byte.report_id = USB_TPORT_HID_REPORT_ID;
header->byte.unused[0] = header->byte.unused[1] = 0;
if (len < USB_TPORT_HID_REPORT_DATA_LEN) {
header->byte.byte_count = len;
len = 0;
} else {
header->byte.byte_count = USB_TPORT_HID_REPORT_DATA_LEN;
len -= USB_TPORT_HID_REPORT_DATA_LEN;
}

ret = hid_int_ep_write(hid_device, (u8_t *)header,
USB_TPORT_HID_REPORT_COUNT, &written);

if (ret) {
LOG_DBG("usb_write failed with error %d", ret);
break;
}

if (written != USB_TPORT_HID_REPORT_COUNT) {
/* usb_write is expected to send all data */
LOG_ERR("usb_write: requested %u sent %u",
USB_TPORT_HID_REPORT_COUNT, written);
ret = -EIO;
break;
}

/* move pointer to fill next header */
header = (union usb_hid_report_hdr *)((u8_t *)header +
USB_TPORT_HID_REPORT_DATA_LEN);
}

return ret;
}

static int usb_transport_get_report(struct usb_setup_packet *setup,
s32_t *len, u8_t **data)
{
LOG_DBG("usb_transport_get_report");
return 0;
}

static int usb_transport_get_idle(struct usb_setup_packet *setup,
s32_t *len, u8_t **data)
{
LOG_DBG("usb_transport_get_idle");
return 0;
}

static int usb_transport_get_protocol(struct usb_setup_packet *setup,
s32_t *len, u8_t **data)
{
LOG_DBG("usb_transport_get_protocol");
return 0;
}

static int usb_transport_set_report(struct usb_setup_packet *setup,
s32_t *len, u8_t **data)
{
u8_t *buffer;
s32_t size;

/* strip the HID header */
buffer = *data + sizeof(union usb_hid_report_hdr);
size = *len - sizeof(union usb_hid_report_hdr);

receive_data_cb(buffer, size);
return 0;
}

static int usb_transport_set_idle(struct usb_setup_packet *setup,
s32_t *len, u8_t **data)
{
LOG_DBG("usb_transport_set_idle");
return 0;
}

static int usb_transport_set_protocol(struct usb_setup_packet *setup,
s32_t *len, u8_t **data)
{
LOG_DBG("usb_transport_set_protocol");
return 0;
}

static void usb_transport_host_ready(void)
{
LOG_DBG("usb_transport_host_ready");
}
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2019 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef TUNING_USB_TRANSPORT_H
#define TUNING_USB_TRANSPORT_H

#define USB_TPORT_HID_REPORT_ID (1)
#define USB_TPORT_HID_REPORT_COUNT (56)
#define USB_TPORT_HID_REPORT_DATA_LEN \
(USB_TPORT_HID_REPORT_COUNT - sizeof(union usb_hid_report_hdr))

/* 4 byte header in every HID report */
union usb_hid_report_hdr {
struct {
u8_t report_id;
u8_t unused[2];
u8_t byte_count;
} __packed byte;
u32_t word;
};

typedef void (*usb_transport_receive_callback_t)(u8_t *data, u32_t len);

int usb_transport_init(usb_transport_receive_callback_t callback);
int usb_transport_send_reply(u8_t *data, u32_t len);

#endif /* TUNING_USB_TRANSPORT_H */

0 comments on commit 3adf7e0

Please sign in to comment.
You can’t perform that action at this time.