blob: 6bfe2d6c5304315bee45d74562ea967a0e57a7aa [file] [log] [blame]
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <zephyr/device.h>
#include <zephyr/usb/usbd.h>
#include <zephyr/sys/iterable_sections.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(usbd_sample_config);
#define ZEPHYR_PROJECT_USB_VID 0x2fe3
USBD_DEVICE_DEFINE(sample_usbd,
DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)),
ZEPHYR_PROJECT_USB_VID, CONFIG_SAMPLE_USBD_PID);
USBD_DESC_LANG_DEFINE(sample_lang);
USBD_DESC_MANUFACTURER_DEFINE(sample_mfr, CONFIG_SAMPLE_USBD_MANUFACTURER);
USBD_DESC_PRODUCT_DEFINE(sample_product, CONFIG_SAMPLE_USBD_PRODUCT);
USBD_DESC_SERIAL_NUMBER_DEFINE(sample_sn, "0123456789ABCDEF");
static const uint8_t attributes = (IS_ENABLED(CONFIG_SAMPLE_USBD_SELF_POWERED) ?
USB_SCD_SELF_POWERED : 0) |
(IS_ENABLED(CONFIG_SAMPLE_USBD_REMOTE_WAKEUP) ?
USB_SCD_REMOTE_WAKEUP : 0);
USBD_CONFIGURATION_DEFINE(sample_config,
attributes,
CONFIG_SAMPLE_USBD_MAX_POWER);
struct usbd_contex *sample_usbd_init_device(usbd_msg_cb_t msg_cb)
{
int err;
err = usbd_add_descriptor(&sample_usbd, &sample_lang);
if (err) {
LOG_ERR("Failed to initialize language descriptor (%d)", err);
return NULL;
}
err = usbd_add_descriptor(&sample_usbd, &sample_mfr);
if (err) {
LOG_ERR("Failed to initialize manufacturer descriptor (%d)", err);
return NULL;
}
err = usbd_add_descriptor(&sample_usbd, &sample_product);
if (err) {
LOG_ERR("Failed to initialize product descriptor (%d)", err);
return NULL;
}
err = usbd_add_descriptor(&sample_usbd, &sample_sn);
if (err) {
LOG_ERR("Failed to initialize SN descriptor (%d)", err);
return NULL;
}
err = usbd_add_configuration(&sample_usbd, &sample_config);
if (err) {
LOG_ERR("Failed to add configuration (%d)", err);
return NULL;
}
STRUCT_SECTION_FOREACH(usbd_class_iter, iter) {
/* Pull everything that is enabled in our configuration. */
err = usbd_register_class(&sample_usbd, iter->c_nd->name, 1);
if (err) {
LOG_ERR("Failed to register %s (%d)",
iter->c_nd->name, err);
return NULL;
}
LOG_DBG("Register %s", iter->c_nd->name);
}
/* Always use class code information from Interface Descriptors */
if (IS_ENABLED(CONFIG_USBD_CDC_ACM_CLASS) ||
IS_ENABLED(CONFIG_USBD_CDC_ECM_CLASS) ||
IS_ENABLED(CONFIG_USBD_AUDIO2_CLASS)) {
/*
* Class with multiple interfaces have an Interface
* Association Descriptor available, use an appropriate triple
* to indicate it.
*/
usbd_device_set_code_triple(&sample_usbd,
USB_BCC_MISCELLANEOUS, 0x02, 0x01);
} else {
usbd_device_set_code_triple(&sample_usbd, 0, 0, 0);
}
if (msg_cb != NULL) {
err = usbd_msg_register_cb(&sample_usbd, msg_cb);
if (err) {
LOG_ERR("Failed to register message callback");
return NULL;
}
}
err = usbd_init(&sample_usbd);
if (err) {
LOG_ERR("Failed to initialize device support");
return NULL;
}
return &sample_usbd;
}