blob: e64f7f2c3e575992ce0d2f490c76fcc153ab8b2e [file] [log] [blame]
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Sample app for WebUSB enabled custom class driver.
*
* Sample app for WebUSB enabled custom class driver. The received
* data is echoed back to the WebUSB based application running in
* the browser at host.
*/
#include <stdio.h>
#include <string.h>
#include <device.h>
#include <uart.h>
#include <zephyr.h>
#include "webusb_serial.h"
static volatile bool data_transmitted;
static volatile bool data_arrived;
static uint8_t data_buf[64];
/* WebUSB Platform Capability Descriptor */
static const uint8_t webusb_bos_descriptor[] = {
/* Binary Object Store descriptor */
0x05, 0x0F, 0x1D, 0x00, 0x01,
/* WebUSB Platform Capability Descriptor:
* https://wicg.github.io/webusb/#webusb-platform-capability-descriptor
*/
0x18, 0x10, 0x05, 0x00,
/* PlatformCapability UUID */
0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47,
0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65,
/* Version, VendorCode, Landing Page */
0x00, 0x01, 0x01, 0x01,
};
/* WebUSB Device Requests */
static const uint8_t webusb_allowed_origins[] = {
/* Allowed Origins Header:
* https://wicg.github.io/webusb/#get-allowed-origins
*/
0x05, 0x00, 0x0D, 0x00, 0x01,
/* Configuration Subset Header:
* https://wicg.github.io/webusb/#configuration-subset-header
*/
0x04, 0x01, 0x01, 0x01,
/* Function Subset Header:
* https://wicg.github.io/webusb/#function-subset-header
*/
0x04, 0x02, 0x02, 0x01
};
/* Number of allowed origins */
#define NUMBER_OF_ALLOWED_ORIGINS 1
/* URL Descriptor: https://wicg.github.io/webusb/#url-descriptor */
static const uint8_t webusb_origin_url[] = {
/* Length, DescriptorType, Scheme */
0x11, 0x03, 0x00,
'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't', ':', '8', '0', '0', '0'
};
/**
* @brief Custom handler for standard requests in
* order to catch the request and return the
* WebUSB Platform Capability Descriptor.
*
* @param pSetup Information about the request to execute.
* @param len Size of the buffer.
* @param data Buffer containing the request result.
*
* @return 0 on success, negative errno code on fail
*/
int custom_handle_req(struct usb_setup_packet *pSetup,
int32_t *len, uint8_t **data)
{
if (GET_DESC_TYPE(pSetup->wValue) == DESCRIPTOR_TYPE_BOS) {
*data = (uint8_t *)(&webusb_bos_descriptor);
*len = sizeof(webusb_bos_descriptor);
return 0;
}
return -ENOTSUP;
}
/**
* @brief Handler called for WebUSB vendor specific commands.
*
* @param pSetup Information about the request to execute.
* @param len Size of the buffer.
* @param data Buffer containing the request result.
*
* @return 0 on success, negative errno code on fail.
*/
int vendor_handle_req(struct usb_setup_packet *pSetup,
int32_t *len, uint8_t **data)
{
/* Get Allowed origins request */
if (pSetup->bRequest == 0x01 && pSetup->wIndex == 0x01) {
*data = (uint8_t *)(&webusb_allowed_origins);
*len = sizeof(webusb_allowed_origins);
return 0;
} else if (pSetup->bRequest == 0x01 && pSetup->wIndex == 0x02) {
/* Get URL request */
uint8_t index = GET_DESC_INDEX(pSetup->wValue);
if (index == 0 || index > NUMBER_OF_ALLOWED_ORIGINS)
return -ENOTSUP;
*data = (uint8_t *)(&webusb_origin_url);
*len = sizeof(webusb_origin_url);
return 0;
}
return -ENOTSUP;
}
static void interrupt_handler(struct device *dev)
{
uart_irq_update(dev);
if (uart_irq_tx_ready(dev)) {
data_transmitted = true;
}
if (uart_irq_rx_ready(dev)) {
data_arrived = true;
}
}
static void write_data(struct device *dev, const uint8_t *buf, int len)
{
uart_irq_tx_enable(dev);
data_transmitted = false;
uart_fifo_fill(dev, buf, len);
while (data_transmitted == false)
;
uart_irq_tx_disable(dev);
}
static void read_and_echo_data(struct device *dev, int *bytes_read)
{
while (data_arrived == false)
;
data_arrived = false;
/* Read all data and echo it back */
while ((*bytes_read = uart_fifo_read(dev,
data_buf, sizeof(data_buf)))) {
write_data(dev, data_buf, *bytes_read);
}
}
/* Custom and Vendor request handlers */
static struct webusb_req_handlers req_handlers = {
.custom_handler = custom_handle_req,
.vendor_handler = vendor_handle_req,
};
void main(void)
{
struct device *dev;
uint32_t baudrate, dtr = 0;
int ret, bytes_read;
dev = device_get_binding(WEBUSB_SERIAL_PORT_NAME);
if (!dev) {
printf("WebUSB device not found\n");
return;
}
/* Set the custom and vendor request handlers */
webusb_register_request_handlers(&req_handlers);
#ifdef CONFIG_UART_LINE_CTRL
printf("Wait for DTR\n");
while (1) {
uart_line_ctrl_get(dev, LINE_CTRL_DTR, &dtr);
if (dtr) {
break;
}
}
printf("DTR set, start test\n");
/* Wait 1 sec for the host to do all settings */
k_busy_wait(1000000);
ret = uart_line_ctrl_get(dev, LINE_CTRL_BAUD_RATE, &baudrate);
if (ret) {
printf("Failed to get baudrate, ret code %d\n", ret);
} else {
printf("Baudrate detected: %d\n", baudrate);
}
#endif
uart_irq_callback_set(dev, interrupt_handler);
/* Enable rx interrupts */
uart_irq_rx_enable(dev);
/* Echo the received data */
while (1) {
read_and_echo_data(dev, &bytes_read);
}
}