stm32h743_usbhs_8k_mouse: create project

This commit is contained in:
wangyz1997 2024-09-28 16:37:08 +08:00
parent 36da2a1a65
commit 72e5fc5746
170 changed files with 2665 additions and 15974 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,369 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_audio.h"
struct audio_entity_param {
uint32_t wCur;
uint32_t wMin;
uint32_t wMax;
uint32_t wRes;
};
struct usbd_audio_priv {
struct audio_entity_info *table;
uint8_t num;
uint16_t uac_version;
} g_usbd_audio[CONFIG_USBDEV_MAX_BUS];
static int audio_class_endpoint_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
uint8_t control_selector;
uint32_t sampling_freq = 0;
uint8_t ep;
control_selector = HI_BYTE(setup->wValue);
ep = LO_BYTE(setup->wIndex);
switch (control_selector) {
case AUDIO_EP_CONTROL_SAMPLING_FEQ:
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
memcpy((uint8_t *)&sampling_freq, *data, *len);
USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
usbd_audio_set_sampling_freq(busid, ep, sampling_freq);
break;
case AUDIO_REQUEST_GET_CUR:
case AUDIO_REQUEST_GET_MIN:
case AUDIO_REQUEST_GET_MAX:
case AUDIO_REQUEST_GET_RES:
sampling_freq = usbd_audio_get_sampling_freq(busid, ep);
memcpy(*data, &sampling_freq, 3);
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
*len = 3;
break;
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
return -1;
}
return 0;
}
static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("Audio Class request: "
"bRequest 0x%02x\r\n",
setup->bRequest);
uint8_t entity_id;
uint8_t ep = 0;
uint8_t subtype = 0x01;
uint8_t control_selector;
uint8_t ch;
uint8_t mute;
uint16_t volume;
int volume_db = 0;
uint32_t sampling_freq = 0;
const char *mute_string[2] = { "off", "on" };
entity_id = HI_BYTE(setup->wIndex);
control_selector = HI_BYTE(setup->wValue);
ch = LO_BYTE(setup->wValue);
ARG_UNUSED(mute_string);
for (uint8_t i = 0; i < g_usbd_audio[busid].num; i++) {
if (g_usbd_audio[busid].table[i].bEntityId == entity_id) {
subtype = g_usbd_audio[busid].table[i].bDescriptorSubtype;
ep = g_usbd_audio[busid].table[i].ep;
break;
}
}
if (subtype == 0x01) {
USB_LOG_ERR("Do not find subtype for 0x%02x\r\n", entity_id);
return -1;
}
USB_LOG_DBG("Audio entity_id:%02x, subtype:%02x, cs:%02x\r\n", entity_id, subtype, control_selector);
switch (subtype) {
case AUDIO_CONTROL_FEATURE_UNIT:
switch (control_selector) {
case AUDIO_FU_CONTROL_MUTE:
if (g_usbd_audio[busid].uac_version < 0x0200) {
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
mute = (*data)[0];
usbd_audio_set_mute(busid, ep, ch, mute);
break;
case AUDIO_REQUEST_GET_CUR:
(*data)[0] = usbd_audio_get_mute(busid, ep, ch);
*len = 1;
break;
default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1;
}
} else {
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
(*data)[0] = usbd_audio_get_mute(busid, ep, ch);
*len = 1;
} else {
mute = (*data)[0];
usbd_audio_set_mute(busid, ep, ch, mute);
}
break;
default:
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1;
}
}
break;
case AUDIO_FU_CONTROL_VOLUME:
if (g_usbd_audio[busid].uac_version < 0x0200) {
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
memcpy(&volume, *data, *len);
if (volume < 0x8000) {
volume_db = volume / 256;
} else if (volume > 0x8000) {
volume_db = (0xffff - volume + 1) / -256;
}
volume_db += 128; /* 0 ~ 255 */
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%04x\r\n", ep, ch, volume);
usbd_audio_set_volume(busid, ep, ch, volume_db);
break;
case AUDIO_REQUEST_GET_CUR:
volume_db = usbd_audio_get_volume(busid, ep, ch);
volume_db -= 128;
if (volume_db >= 0) {
volume = volume_db * 256;
} else {
volume = volume_db * 256 + 0xffff + 1;
}
memcpy(*data, &volume, 2);
*len = 2;
break;
case AUDIO_REQUEST_GET_MIN:
(*data)[0] = 0x00; /* -2560/256 dB */
(*data)[1] = 0xdb;
*len = 2;
break;
case AUDIO_REQUEST_GET_MAX:
(*data)[0] = 0x00; /* 0 dB */
(*data)[1] = 0x00;
*len = 2;
break;
case AUDIO_REQUEST_GET_RES:
(*data)[0] = 0x00; /* -256/256 dB */
(*data)[1] = 0x01;
*len = 2;
break;
default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1;
}
} else {
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
volume_db = usbd_audio_get_volume(busid, ep, ch);
volume = volume_db;
memcpy(*data, &volume, 2);
*len = 2;
} else {
memcpy(&volume, *data, *len);
volume_db = volume;
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%02x\r\n", ep, ch, volume);
usbd_audio_set_volume(busid, ep, ch, volume_db);
}
break;
case AUDIO_REQUEST_RANGE:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
*((uint16_t *)(*data + 0)) = 1;
*((uint16_t *)(*data + 2)) = 0;
*((uint16_t *)(*data + 4)) = 100;
*((uint16_t *)(*data + 6)) = 1;
*len = 8;
} else {
}
break;
default:
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1;
}
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class cs 0x%02x \r\n", control_selector);
return -1;
}
break;
case AUDIO_CONTROL_CLOCK_SOURCE:
switch (control_selector) {
case AUDIO_CS_CONTROL_SAM_FREQ:
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
sampling_freq = usbd_audio_get_sampling_freq(busid, ep);
memcpy(*data, &sampling_freq, 4);
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
*len = 4;
} else {
memcpy(&sampling_freq, *data, setup->wLength);
USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
usbd_audio_set_sampling_freq(busid, ep, sampling_freq);
}
break;
case AUDIO_REQUEST_RANGE:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
uint8_t *sampling_freq_table = NULL;
uint16_t num;
usbd_audio_get_sampling_freq_table(busid, ep, &sampling_freq_table);
num = (uint16_t)((uint16_t)(sampling_freq_table[1] << 8) | ((uint16_t)sampling_freq_table[0]));
memcpy(*data, sampling_freq_table, (12 * num + 2));
*len = (12 * num + 2);
} else {
}
break;
default:
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1;
}
break;
case AUDIO_CS_CONTROL_CLOCK_VALID:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
(*data)[0] = 1;
*len = 1;
} else {
return -1;
}
break;
default:
//USB_LOG_WRN("Unhandled Audio Class cs 0x%02x \r\n", control_selector);
return -1;
}
break;
default:
break;
}
return 0;
}
static void audio_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
break;
case USBD_EVENT_SET_INTERFACE: {
struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg;
if (intf->bAlternateSetting) {
usbd_audio_open(busid, intf->bInterfaceNumber);
} else {
usbd_audio_close(busid, intf->bInterfaceNumber);
}
}
break;
default:
break;
}
}
struct usbd_interface *usbd_audio_init_intf(uint8_t busid,
struct usbd_interface *intf,
uint16_t uac_version,
struct audio_entity_info *table,
uint8_t num)
{
if (uac_version < 0x0200) {
intf->class_interface_handler = audio_class_interface_request_handler;
intf->class_endpoint_handler = audio_class_endpoint_request_handler;
intf->vendor_handler = NULL;
intf->notify_handler = audio_notify_handler;
} else {
intf->class_interface_handler = audio_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = audio_notify_handler;
}
g_usbd_audio[busid].uac_version = uac_version;
g_usbd_audio[busid].table = table;
g_usbd_audio[busid].num = num;
return intf;
}
__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume)
{
(void)busid;
(void)ep;
(void)ch;
(void)volume;
}
__WEAK int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch)
{
(void)busid;
(void)ep;
(void)ch;
return 0;
}
__WEAK void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute)
{
(void)busid;
(void)ep;
(void)ch;
(void)mute;
}
__WEAK bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch)
{
(void)busid;
(void)ep;
(void)ch;
return 0;
}
__WEAK void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
{
(void)busid;
(void)ep;
(void)sampling_freq;
}
__WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep)
{
(void)busid;
(void)ep;
return 0;
}
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
{
(void)busid;
(void)ep;
(void)sampling_freq_table;
}

View File

@ -1,43 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_AUDIO_H
#define USBD_AUDIO_H
#include "usb_audio.h"
#ifdef __cplusplus
extern "C" {
#endif
struct audio_entity_info {
uint8_t bDescriptorSubtype;
uint8_t bEntityId;
uint8_t ep;
};
/* Init audio interface driver */
struct usbd_interface *usbd_audio_init_intf(uint8_t busid, struct usbd_interface *intf,
uint16_t uac_version,
struct audio_entity_info *table,
uint8_t num);
void usbd_audio_open(uint8_t busid, uint8_t intf);
void usbd_audio_close(uint8_t busid, uint8_t intf);
void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume);
int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch);
void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute);
bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch);
void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq);
uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep);
void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table);
#ifdef __cplusplus
}
#endif
#endif /* USBD_AUDIO_H */

View File

@ -1,509 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_audio.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_audio"
#include "usb_log.h"
#define DEV_FORMAT "/dev/audio%d"
/* general descriptor field offsets */
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
#define DESC_bDescriptorSubType 2 /** Descriptor subtype offset */
/* interface descriptor field offsets */
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
#ifndef CONFIG_USBHOST_MAX_AUDIO_CLASS
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 4
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_audio_buf[128];
static struct usbh_audio g_audio_class[CONFIG_USBHOST_MAX_AUDIO_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_audio *usbh_audio_class_alloc(void)
{
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_AUDIO_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_audio_class[devno], 0, sizeof(struct usbh_audio));
g_audio_class[devno].minor = devno;
return &g_audio_class[devno];
}
}
return NULL;
}
static void usbh_audio_class_free(struct usbh_audio *audio_class)
{
int devno = audio_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(audio_class, 0, sizeof(struct usbh_audio));
}
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq)
{
struct usb_setup_packet *setup;
struct usb_endpoint_descriptor *ep_desc;
uint8_t mult;
uint16_t mps;
int ret;
uint8_t intf = 0xff;
uint8_t altsetting = 1;
if (!audio_class || !audio_class->hport) {
return -USB_ERR_INVAL;
}
setup = audio_class->hport->setup;
if (audio_class->is_opened) {
return 0;
}
for (uint8_t i = 0; i < audio_class->module_num; i++) {
if (strcmp(name, audio_class->module[i].name) == 0) {
for (uint8_t j = 0; j < audio_class->num_of_intf_altsettings; j++) {
for (uint8_t k = 0; k < audio_class->module[i].altsetting[j].sampfreq_num; k++) {
if (audio_class->module[i].altsetting[j].sampfreq[k] == samp_freq) {
intf = audio_class->module[i].data_intf;
altsetting = j;
goto freq_found;
}
}
}
}
}
return -USB_ERR_NODEV;
freq_found:
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = USB_REQUEST_SET_INTERFACE;
setup->wValue = altsetting;
setup->wIndex = intf;
setup->wLength = 0;
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
if (ret < 0) {
return ret;
}
ep_desc = &audio_class->hport->config.intf[intf].altsetting[altsetting].ep[0].ep_desc;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_ENDPOINT;
setup->bRequest = AUDIO_REQUEST_SET_CUR;
setup->wValue = (AUDIO_EP_CONTROL_SAMPLING_FEQ << 8) | 0x00;
setup->wIndex = ep_desc->bEndpointAddress;
setup->wLength = 3;
memcpy(g_audio_buf, &samp_freq, 3);
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
if (ep_desc->bEndpointAddress & 0x80) {
audio_class->isoin_mps = mps * (mult + 1);
USBH_EP_INIT(audio_class->isoin, ep_desc);
} else {
audio_class->isoout_mps = mps * (mult + 1);
USBH_EP_INIT(audio_class->isoout, ep_desc);
}
USB_LOG_INFO("Open audio module :%s, altsetting: %u\r\n", name, altsetting);
audio_class->is_opened = true;
return ret;
}
int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
{
struct usb_setup_packet *setup;
struct usb_endpoint_descriptor *ep_desc;
int ret;
uint8_t intf = 0xff;
uint8_t altsetting = 1;
if (!audio_class || !audio_class->hport) {
return -USB_ERR_INVAL;
}
setup = audio_class->hport->setup;
for (size_t i = 0; i < audio_class->module_num; i++) {
if (strcmp(name, audio_class->module[i].name) == 0) {
intf = audio_class->module[i].data_intf;
}
}
if (intf == 0xff) {
return -USB_ERR_NODEV;
}
USB_LOG_INFO("Close audio module :%s\r\n", name);
audio_class->is_opened = false;
ep_desc = &audio_class->hport->config.intf[intf].altsetting[altsetting].ep[0].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
if (audio_class->isoin) {
audio_class->isoin = NULL;
}
} else {
if (audio_class->isoout) {
audio_class->isoout = NULL;
}
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = USB_REQUEST_SET_INTERFACE;
setup->wValue = 0;
setup->wIndex = intf;
setup->wLength = 0;
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
return ret;
}
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume)
{
struct usb_setup_packet *setup;
int ret;
uint8_t intf = 0xff;
uint8_t feature_id = 0xff;
uint16_t volume_hex;
if (!audio_class || !audio_class->hport) {
return -USB_ERR_INVAL;
}
setup = audio_class->hport->setup;
for (size_t i = 0; i < audio_class->module_num; i++) {
if (strcmp(name, audio_class->module[i].name) == 0) {
intf = audio_class->ctrl_intf;
feature_id = audio_class->module[i].feature_unit_id;
}
}
if (intf == 0xff) {
return -USB_ERR_NODEV;
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = AUDIO_REQUEST_SET_CUR;
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
setup->wIndex = (feature_id << 8) | intf;
setup->wLength = 2;
volume_hex = -0xDB00 / 100 * volume + 0xdb00;
memcpy(g_audio_buf, &volume_hex, 2);
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
return ret;
}
int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_t ch, bool mute)
{
struct usb_setup_packet *setup;
int ret;
uint8_t intf = 0xff;
uint8_t feature_id = 0xff;
if (!audio_class || !audio_class->hport) {
return -USB_ERR_INVAL;
}
setup = audio_class->hport->setup;
for (size_t i = 0; i < audio_class->module_num; i++) {
if (strcmp(name, audio_class->module[i].name) == 0) {
intf = audio_class->ctrl_intf;
feature_id = audio_class->module[i].feature_unit_id;
}
}
if (intf == 0xff) {
return -USB_ERR_NODEV;
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = AUDIO_REQUEST_SET_CUR;
setup->wValue = (AUDIO_FU_CONTROL_MUTE << 8) | ch;
setup->wIndex = (feature_id << 8) | intf;
setup->wLength = 1;
memcpy(g_audio_buf, &mute, 1);
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
return ret;
}
void usbh_audio_list_module(struct usbh_audio *audio_class)
{
USB_LOG_INFO("============= Audio module information ===================\r\n");
USB_LOG_RAW("bcdADC :%04x\r\n", audio_class->bcdADC);
USB_LOG_RAW("Num of modules :%u\r\n", audio_class->module_num);
USB_LOG_RAW("Num of altsettings:%u\r\n", audio_class->num_of_intf_altsettings);
for (uint8_t i = 0; i < audio_class->module_num; i++) {
USB_LOG_RAW(" module name :%s\r\n", audio_class->module[i].name);
USB_LOG_RAW(" module feature unit id :%d\r\n", audio_class->module[i].feature_unit_id);
for (uint8_t j = 0; j < audio_class->num_of_intf_altsettings; j++) {
if (j == 0) {
USB_LOG_RAW(" Ingore altsetting 0\r\n");
continue;
}
USB_LOG_RAW(" Altsetting %u\r\n", j);
USB_LOG_RAW(" module channels :%u\r\n", audio_class->module[i].altsetting[j].channels);
//USB_LOG_RAW(" module format_type :%u\r\n",audio_class->module[i].altsetting[j].format_type);
USB_LOG_RAW(" module bitresolution :%u\r\n", audio_class->module[i].altsetting[j].bitresolution);
USB_LOG_RAW(" module sampfreq num :%u\r\n", audio_class->module[i].altsetting[j].sampfreq_num);
for (uint8_t k = 0; k < audio_class->module[i].altsetting[j].sampfreq_num; k++) {
USB_LOG_RAW(" module sampfreq :%d hz\r\n", audio_class->module[i].altsetting[j].sampfreq[k]);
}
}
}
USB_LOG_INFO("============= Audio module information ===================\r\n");
}
static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
{
int ret;
uint8_t cur_iface = 0xff;
uint8_t cur_iface_count = 0xff;
uint8_t cur_alt_setting = 0xff;
uint8_t input_offset = 0;
uint8_t output_offset = 0;
uint8_t feature_unit_offset = 0;
uint8_t format_offset = 0;
uint8_t *p;
struct usbh_audio *audio_class = usbh_audio_class_alloc();
if (audio_class == NULL) {
USB_LOG_ERR("Fail to alloc audio_class\r\n");
return -USB_ERR_NOMEM;
}
audio_class->hport = hport;
audio_class->ctrl_intf = intf;
audio_class->num_of_intf_altsettings = hport->config.intf[intf + 1].altsetting_num;
hport->config.intf[intf].priv = audio_class;
p = hport->raw_config_desc;
while (p[DESC_bLength]) {
switch (p[DESC_bDescriptorType]) {
case USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION:
cur_iface_count = p[3];
break;
case USB_DESCRIPTOR_TYPE_INTERFACE:
cur_iface = p[INTF_DESC_bInterfaceNumber];
cur_alt_setting = p[INTF_DESC_bAlternateSetting];
break;
case USB_DESCRIPTOR_TYPE_ENDPOINT:
break;
case AUDIO_INTERFACE_DESCRIPTOR_TYPE:
if (cur_iface == audio_class->ctrl_intf) {
switch (p[DESC_bDescriptorSubType]) {
case AUDIO_CONTROL_HEADER: {
struct audio_cs_if_ac_header_descriptor *desc = (struct audio_cs_if_ac_header_descriptor *)p;
audio_class->bcdADC = desc->bcdADC;
audio_class->bInCollection = desc->bInCollection;
} break;
case AUDIO_CONTROL_INPUT_TERMINAL: {
struct audio_cs_if_ac_input_terminal_descriptor *desc = (struct audio_cs_if_ac_input_terminal_descriptor *)p;
audio_class->module[input_offset].input_terminal_id = desc->bTerminalID;
audio_class->module[input_offset].input_terminal_type = desc->wTerminalType;
audio_class->module[input_offset].input_channel_config = desc->wChannelConfig;
if (desc->wTerminalType == AUDIO_TERMINAL_STREAMING) {
audio_class->module[input_offset].terminal_link_id = desc->bTerminalID;
}
if (desc->wTerminalType == AUDIO_INTERM_MIC) {
audio_class->module[input_offset].name = "mic";
}
input_offset++;
} break;
break;
case AUDIO_CONTROL_OUTPUT_TERMINAL: {
struct audio_cs_if_ac_output_terminal_descriptor *desc = (struct audio_cs_if_ac_output_terminal_descriptor *)p;
audio_class->module[output_offset].output_terminal_id = desc->bTerminalID;
audio_class->module[output_offset].output_terminal_type = desc->wTerminalType;
if (desc->wTerminalType == AUDIO_TERMINAL_STREAMING) {
audio_class->module[output_offset].terminal_link_id = desc->bTerminalID;
}
if (desc->wTerminalType == AUDIO_OUTTERM_SPEAKER) {
audio_class->module[output_offset].name = "speaker";
}
output_offset++;
} break;
case AUDIO_CONTROL_FEATURE_UNIT: {
struct audio_cs_if_ac_feature_unit_descriptor *desc = (struct audio_cs_if_ac_feature_unit_descriptor *)p;
audio_class->module[feature_unit_offset].feature_unit_id = desc->bUnitID;
audio_class->module[feature_unit_offset].feature_unit_controlsize = desc->bControlSize;
for (uint8_t j = 0; j < desc->bControlSize; j++) {
audio_class->module[feature_unit_offset].feature_unit_controls[j] = p[6 + j];
}
feature_unit_offset++;
} break;
case AUDIO_CONTROL_PROCESSING_UNIT:
break;
default:
break;
}
} else if ((cur_iface < (audio_class->ctrl_intf + cur_iface_count)) && (cur_iface > audio_class->ctrl_intf)) {
switch (p[DESC_bDescriptorSubType]) {
case AUDIO_STREAMING_GENERAL:
break;
case AUDIO_STREAMING_FORMAT_TYPE: {
struct audio_cs_if_as_format_type_descriptor *desc = (struct audio_cs_if_as_format_type_descriptor *)p;
audio_class->module[format_offset].data_intf = cur_iface;
audio_class->module[format_offset].altsetting[cur_alt_setting].channels = desc->bNrChannels;
audio_class->module[format_offset].altsetting[cur_alt_setting].format_type = desc->bFormatType;
audio_class->module[format_offset].altsetting[cur_alt_setting].bitresolution = desc->bBitResolution;
audio_class->module[format_offset].altsetting[cur_alt_setting].sampfreq_num = desc->bSamFreqType;
for (uint8_t j = 0; j < desc->bSamFreqType; j++) {
audio_class->module[format_offset].altsetting[cur_alt_setting].sampfreq[j] = (uint32_t)(p[10 + j * 3] << 16) |
(uint32_t)(p[9 + j * 3] << 8) |
(uint32_t)(p[8 + j * 3] << 0);
}
if (cur_alt_setting == (hport->config.intf[intf + 1].altsetting_num - 1)) {
format_offset++;
}
} break;
default:
break;
}
}
break;
default:
break;
}
/* skip to next descriptor */
p += p[DESC_bLength];
}
if ((input_offset != output_offset) && (input_offset != feature_unit_offset) && (input_offset != format_offset)) {
return -USB_ERR_INVAL;
}
audio_class->module_num = input_offset;
for (size_t i = 0; i < audio_class->module_num; i++) {
ret = usbh_audio_close(audio_class, audio_class->module[i].name);
if (ret < 0) {
USB_LOG_ERR("Fail to close audio module :%s\r\n", audio_class->module[i].name);
return ret;
}
}
usbh_audio_list_module(audio_class);
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, audio_class->minor);
USB_LOG_INFO("Register Audio Class:%s\r\n", hport->config.intf[intf].devname);
usbh_audio_run(audio_class);
return 0;
}
static int usbh_audio_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_audio *audio_class = (struct usbh_audio *)hport->config.intf[intf].priv;
if (audio_class) {
if (audio_class->isoin) {
}
if (audio_class->isoout) {
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister Audio Class:%s\r\n", hport->config.intf[intf].devname);
usbh_audio_stop(audio_class);
}
usbh_audio_class_free(audio_class);
}
return ret;
}
static int usbh_audio_data_connect(struct usbh_hubport *hport, uint8_t intf)
{
(void)hport;
(void)intf;
return 0;
}
static int usbh_audio_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
(void)hport;
(void)intf;
return 0;
}
__WEAK void usbh_audio_run(struct usbh_audio *audio_class)
{
(void)audio_class;
}
__WEAK void usbh_audio_stop(struct usbh_audio *audio_class)
{
(void)audio_class;
}
const struct usbh_class_driver audio_ctrl_class_driver = {
.driver_name = "audio_ctrl",
.connect = usbh_audio_ctrl_connect,
.disconnect = usbh_audio_ctrl_disconnect
};
const struct usbh_class_driver audio_streaming_class_driver = {
.driver_name = "audio_streaming",
.connect = usbh_audio_data_connect,
.disconnect = usbh_audio_data_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info audio_ctrl_intf_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
.class = USB_DEVICE_CLASS_AUDIO,
.subclass = AUDIO_SUBCLASS_AUDIOCONTROL,
.protocol = 0x00,
.id_table = NULL,
.class_driver = &audio_ctrl_class_driver
};
CLASS_INFO_DEFINE const struct usbh_class_info audio_streaming_intf_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
.class = USB_DEVICE_CLASS_AUDIO,
.subclass = AUDIO_SUBCLASS_AUDIOSTREAMING,
.protocol = 0x00,
.id_table = NULL,
.class_driver = &audio_streaming_class_driver
};

View File

@ -1,76 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_AUDIO_H
#define USBH_AUDIO_H
#include "usb_audio.h"
struct usbh_audio_format_type {
uint8_t channels;
uint8_t format_type;
uint8_t bitresolution;
uint8_t sampfreq_num;
uint32_t sampfreq[3];
};
/**
* bSourceID in feature_unit = input_terminal_id
* bSourceID in output_terminal = feature_unit_id
* terminal_link_id = input_terminal_id or output_terminal_id (if input_terminal_type or output_terminal_type is 0x0101)
*
*
*/
struct usbh_audio_module {
const char *name;
uint8_t data_intf;
uint8_t input_terminal_id;
uint16_t input_terminal_type;
uint16_t input_channel_config;
uint8_t output_terminal_id;
uint16_t output_terminal_type;
uint8_t feature_unit_id;
uint8_t feature_unit_controlsize;
uint8_t feature_unit_controls[8];
uint8_t terminal_link_id;
struct usbh_audio_format_type altsetting[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS];
};
struct usbh_audio {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *isoin; /* ISO IN endpoint */
struct usb_endpoint_descriptor *isoout; /* ISO OUT endpoint */
uint8_t ctrl_intf; /* interface number */
uint8_t minor;
uint16_t isoin_mps;
uint16_t isoout_mps;
bool is_opened;
uint16_t bcdADC;
uint8_t bInCollection;
uint8_t num_of_intf_altsettings;
struct usbh_audio_module module[2];
uint8_t module_num;
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq);
int usbh_audio_close(struct usbh_audio *audio_class, const char *name);
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume);
int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_t ch, bool mute);
void usbh_audio_run(struct usbh_audio *audio_class);
void usbh_audio_stop(struct usbh_audio *audio_class);
#ifdef __cplusplus
}
#endif
#endif /* USBH_AUDIO_H */

View File

@ -1,698 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USB_CDC_H
#define USB_CDC_H
/*------------------------------------------------------------------------------
* Definitions based on usbcdc11.pdf (www.usb.org)
*----------------------------------------------------------------------------*/
/* Communication device class specification version 1.10 */
#define CDC_V1_10 0x0110U
// Communication device class specification version 1.2
#define CDC_V1_2_0 0x0120U
/* Communication interface class code */
/* (usbcdc11.pdf, 4.2, Table 15) */
#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02U
/* Communication interface class subclass codes */
/* (usbcdc11.pdf, 4.3, Table 16) */
#define CDC_SUBCLASS_NONE 0x00 /* Reserved */
#define CDC_SUBCLASS_DLC 0x01 /* Direct Line Control Model */
#define CDC_SUBCLASS_ACM 0x02 /* Abstract Control Model */
#define CDC_SUBCLASS_TCM 0x03 /* Telephone Control Model */
#define CDC_SUBCLASS_MCM 0x04 /* Multi-Channel Control Model */
#define CDC_SUBCLASS_CAPI 0x05 /* CAPI Control Model */
#define CDC_SUBCLASS_ECM 0x06 /* Ethernet Networking Control Model */
#define CDC_SUBCLASS_ATM 0x07 /* ATM Networking Control Model */
/* 0x08-0x0d Reserved (future use) */
#define CDC_SUBCLASS_MBIM 0x0e /* MBIM Control Model */
/* 0x0f-0x7f Reserved (future use) */
/* 0x80-0xfe Reserved (vendor specific) */
#define CDC_DIRECT_LINE_CONTROL_MODEL 0x01U
#define CDC_ABSTRACT_CONTROL_MODEL 0x02U
#define CDC_TELEPHONE_CONTROL_MODEL 0x03U
#define CDC_MULTI_CHANNEL_CONTROL_MODEL 0x04U
#define CDC_CAPI_CONTROL_MODEL 0x05U
#define CDC_ETHERNET_NETWORKING_CONTROL_MODEL 0x06U
#define CDC_ATM_NETWORKING_CONTROL_MODEL 0x07U
#define CDC_WIRELESS_HANDSET_CONTROL_MODEL 0x08U
#define CDC_DEVICE_MANAGEMENT 0x09U
#define CDC_MOBILE_DIRECT_LINE_MODEL 0x0AU
#define CDC_OBEX 0x0BU
#define CDC_ETHERNET_EMULATION_MODEL 0x0CU
#define CDC_NETWORK_CONTROL_MODEL 0x0DU
/* Communication interface class control protocol codes */
/* (usbcdc11.pdf, 4.4, Table 17) */
#define CDC_COMMON_PROTOCOL_NONE 0x00U
#define CDC_COMMON_PROTOCOL_AT_COMMANDS 0x01U
#define CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101 0x02U
#define CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO 0x03U
#define CDC_COMMON_PROTOCOL_AT_COMMANDS_GSM_707 0x04U
#define CDC_COMMON_PROTOCOL_AT_COMMANDS_3GPP_27007 0x05U
#define CDC_COMMON_PROTOCOL_AT_COMMANDS_CDMA 0x06U
#define CDC_COMMON_PROTOCOL_ETHERNET_EMULATION_MODEL 0x07U
// NCM Communication Interface Protocol Codes
// (usbncm10.pdf, 4.2, Table 4-2)
#define CDC_NCM_PROTOCOL_NONE 0x00U
#define CDC_NCM_PROTOCOL_OEM 0xFEU
/* Data interface class code */
/* (usbcdc11.pdf, 4.5, Table 18) */
#define CDC_DATA_INTERFACE_CLASS 0x0A
/* Data Interface Sub-Class Codes ********************************************/
#define CDC_DATA_SUBCLASS_NONE 0x00
/* Data interface class protocol codes */
/* (usbcdc11.pdf, 4.7, Table 19) */
#define CDC_DATA_PROTOCOL_ISDN_BRI 0x30
#define CDC_DATA_PROTOCOL_HDLC 0x31
#define CDC_DATA_PROTOCOL_TRANSPARENT 0x32
#define CDC_DATA_PROTOCOL_Q921_MANAGEMENT 0x50
#define CDC_DATA_PROTOCOL_Q921_DATA_LINK 0x51
#define CDC_DATA_PROTOCOL_Q921_MULTIPLEXOR 0x52
#define CDC_DATA_PROTOCOL_V42 0x90
#define CDC_DATA_PROTOCOL_EURO_ISDN 0x91
#define CDC_DATA_PROTOCOL_V24_RATE_ADAPTATION 0x92
#define CDC_DATA_PROTOCOL_CAPI 0x93
#define CDC_DATA_PROTOCOL_HOST_BASED_DRIVER 0xFD
#define CDC_DATA_PROTOCOL_DESCRIBED_IN_PUFD 0xFE
/* Type values for bDescriptorType field of functional descriptors */
/* (usbcdc11.pdf, 5.2.3, Table 24) */
#define CDC_CS_INTERFACE 0x24
#define CDC_CS_ENDPOINT 0x25
/* Type values for bDescriptorSubtype field of functional descriptors */
/* (usbcdc11.pdf, 5.2.3, Table 25) */
#define CDC_FUNC_DESC_HEADER 0x00
#define CDC_FUNC_DESC_CALL_MANAGEMENT 0x01
#define CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT 0x02
#define CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT 0x03
#define CDC_FUNC_DESC_TELEPHONE_RINGER 0x04
#define CDC_FUNC_DESC_REPORTING_CAPABILITIES 0x05
#define CDC_FUNC_DESC_UNION 0x06
#define CDC_FUNC_DESC_COUNTRY_SELECTION 0x07
#define CDC_FUNC_DESC_TELEPHONE_OPERATIONAL_MODES 0x08
#define CDC_FUNC_DESC_USB_TERMINAL 0x09
#define CDC_FUNC_DESC_NETWORK_CHANNEL 0x0A
#define CDC_FUNC_DESC_PROTOCOL_UNIT 0x0B
#define CDC_FUNC_DESC_EXTENSION_UNIT 0x0C
#define CDC_FUNC_DESC_MULTI_CHANNEL_MANAGEMENT 0x0D
#define CDC_FUNC_DESC_CAPI_CONTROL_MANAGEMENT 0x0E
#define CDC_FUNC_DESC_ETHERNET_NETWORKING 0x0F
#define CDC_FUNC_DESC_ATM_NETWORKING 0x10
#define CDC_FUNC_DESC_WIRELESS_HANDSET_CONTROL_MODEL 0x11
#define CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL 0x12
#define CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL_DETAIL 0x13
#define CDC_FUNC_DESC_DEVICE_MANAGEMENT_MODEL 0x14
#define CDC_FUNC_DESC_OBEX 0x15
#define CDC_FUNC_DESC_COMMAND_SET 0x16
#define CDC_FUNC_DESC_COMMAND_SET_DETAIL 0x17
#define CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL 0x18
#define CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER 0x19
#define CDC_FUNC_DESC_NCM 0x1A
/* CDC class-specific request codes */
/* (usbcdc11.pdf, 6.2, Table 46) */
/* see Table 45 for info about the specific requests. */
#define CDC_REQUEST_SEND_ENCAPSULATED_COMMAND 0x00
#define CDC_REQUEST_GET_ENCAPSULATED_RESPONSE 0x01
#define CDC_REQUEST_SET_COMM_FEATURE 0x02
#define CDC_REQUEST_GET_COMM_FEATURE 0x03
#define CDC_REQUEST_CLEAR_COMM_FEATURE 0x04
#define CDC_REQUEST_SET_AUX_LINE_STATE 0x10
#define CDC_REQUEST_SET_HOOK_STATE 0x11
#define CDC_REQUEST_PULSE_SETUP 0x12
#define CDC_REQUEST_SEND_PULSE 0x13
#define CDC_REQUEST_SET_PULSE_TIME 0x14
#define CDC_REQUEST_RING_AUX_JACK 0x15
#define CDC_REQUEST_SET_LINE_CODING 0x20
#define CDC_REQUEST_GET_LINE_CODING 0x21
#define CDC_REQUEST_SET_CONTROL_LINE_STATE 0x22
#define CDC_REQUEST_SEND_BREAK 0x23
#define CDC_REQUEST_SET_RINGER_PARMS 0x30
#define CDC_REQUEST_GET_RINGER_PARMS 0x31
#define CDC_REQUEST_SET_OPERATION_PARMS 0x32
#define CDC_REQUEST_GET_OPERATION_PARMS 0x33
#define CDC_REQUEST_SET_LINE_PARMS 0x34
#define CDC_REQUEST_GET_LINE_PARMS 0x35
#define CDC_REQUEST_DIAL_DIGITS 0x36
#define CDC_REQUEST_SET_UNIT_PARAMETER 0x37
#define CDC_REQUEST_GET_UNIT_PARAMETER 0x38
#define CDC_REQUEST_CLEAR_UNIT_PARAMETER 0x39
#define CDC_REQUEST_GET_PROFILE 0x3A
#define CDC_REQUEST_SET_ETHERNET_MULTICAST_FILTERS 0x40
#define CDC_REQUEST_SET_ETHERNET_PMP_FILTER 0x41
#define CDC_REQUEST_GET_ETHERNET_PMP_FILTER 0x42
#define CDC_REQUEST_SET_ETHERNET_PACKET_FILTER 0x43
#define CDC_REQUEST_GET_ETHERNET_STATISTIC 0x44
#define CDC_REQUEST_SET_ATM_DATA_FORMAT 0x50
#define CDC_REQUEST_GET_ATM_DEVICE_STATISTICS 0x51
#define CDC_REQUEST_SET_ATM_DEFAULT_VC 0x52
#define CDC_REQUEST_GET_ATM_VC_STATISTICS 0x53
#define CDC_REQUEST_GET_NTB_PARAMETERS 0x80
#define CDC_REQUEST_GET_NET_ADDRESS 0x81
#define CDC_REQUEST_SET_NET_ADDRESS 0x82
#define CDC_REQUEST_GET_NTB_FORMAT 0x83
#define CDC_REQUEST_SET_NTB_FORMAT 0x84
#define CDC_REQUEST_GET_NTB_INPUT_SIZE 0x85
#define CDC_REQUEST_SET_NTB_INPUT_SIZE 0x86
#define CDC_REQUEST_GET_MAX_DATAGRAM_SIZE 0x87
#define CDC_REQUEST_SET_MAX_DATAGRAM_SIZE 0x88
#define CDC_REQUEST_GET_CRC_MODE 0x89
#define CDC_REQUEST_SET_CRC_MODE 0x90
/* Communication feature selector codes */
/* (usbcdc11.pdf, 6.2.2..6.2.4, Table 47) */
#define CDC_ABSTRACT_STATE 0x01
#define CDC_COUNTRY_SETTING 0x02
/** Control Signal Bitmap Values for SetControlLineState */
#define SET_CONTROL_LINE_STATE_RTS 0x02
#define SET_CONTROL_LINE_STATE_DTR 0x01
/* Feature Status returned for ABSTRACT_STATE Selector */
/* (usbcdc11.pdf, 6.2.3, Table 48) */
#define CDC_IDLE_SETTING (1 << 0)
#define CDC_DATA_MULTPLEXED_STATE (1 << 1)
/* Control signal bitmap values for the SetControlLineState request */
/* (usbcdc11.pdf, 6.2.14, Table 51) */
#define CDC_DTE_PRESENT (1 << 0)
#define CDC_ACTIVATE_CARRIER (1 << 1)
/* CDC class-specific notification codes */
/* (usbcdc11.pdf, 6.3, Table 68) */
/* see Table 67 for Info about class-specific notifications */
#define CDC_NOTIFICATION_NETWORK_CONNECTION 0x00
#define CDC_RESPONSE_AVAILABLE 0x01
#define CDC_AUX_JACK_HOOK_STATE 0x08
#define CDC_RING_DETECT 0x09
#define CDC_NOTIFICATION_SERIAL_STATE 0x20
#define CDC_CALL_STATE_CHANGE 0x28
#define CDC_LINE_STATE_CHANGE 0x29
#define CDC_CONNECTION_SPEED_CHANGE 0x2A
/* UART state bitmap values (Serial state notification). */
/* (usbcdc11.pdf, 6.3.5, Table 69) */
#define CDC_SERIAL_STATE_OVERRUN (1 << 6) /* receive data overrun error has occurred */
#define CDC_SERIAL_STATE_OVERRUN_Pos (6)
#define CDC_SERIAL_STATE_OVERRUN_Msk (1 << CDC_SERIAL_STATE_OVERRUN_Pos)
#define CDC_SERIAL_STATE_PARITY (1 << 5) /* parity error has occurred */
#define CDC_SERIAL_STATE_PARITY_Pos (5)
#define CDC_SERIAL_STATE_PARITY_Msk (1 << CDC_SERIAL_STATE_PARITY_Pos)
#define CDC_SERIAL_STATE_FRAMING (1 << 4) /* framing error has occurred */
#define CDC_SERIAL_STATE_FRAMING_Pos (4)
#define CDC_SERIAL_STATE_FRAMING_Msk (1 << CDC_SERIAL_STATE_FRAMING_Pos)
#define CDC_SERIAL_STATE_RING (1 << 3) /* state of ring signal detection */
#define CDC_SERIAL_STATE_RING_Pos (3)
#define CDC_SERIAL_STATE_RING_Msk (1 << CDC_SERIAL_STATE_RING_Pos)
#define CDC_SERIAL_STATE_BREAK (1 << 2) /* state of break detection */
#define CDC_SERIAL_STATE_BREAK_Pos (2)
#define CDC_SERIAL_STATE_BREAK_Msk (1 << CDC_SERIAL_STATE_BREAK_Pos)
#define CDC_SERIAL_STATE_TX_CARRIER (1 << 1) /* state of transmission carrier */
#define CDC_SERIAL_STATE_TX_CARRIER_Pos (1)
#define CDC_SERIAL_STATE_TX_CARRIER_Msk (1 << CDC_SERIAL_STATE_TX_CARRIER_Pos)
#define CDC_SERIAL_STATE_RX_CARRIER (1 << 0) /* state of receiver carrier */
#define CDC_SERIAL_STATE_RX_CARRIER_Pos (0)
#define CDC_SERIAL_STATE_RX_CARRIER_Msk (1 << CDC_SERIAL_STATE_RX_CARRIER_Pos)
#define CDC_ECM_XMIT_OK (1 << 0)
#define CDC_ECM_RVC_OK (1 << 1)
#define CDC_ECM_XMIT_ERROR (1 << 2)
#define CDC_ECM_RCV_ERROR (1 << 3)
#define CDC_ECM_RCV_NO_BUFFER (1 << 4)
#define CDC_ECM_DIRECTED_BYTES_XMIT (1 << 5)
#define CDC_ECM_DIRECTED_FRAMES_XMIT (1 << 6)
#define CDC_ECM_MULTICAST_BYTES_XMIT (1 << 7)
#define CDC_ECM_MULTICAST_FRAMES_XMIT (1 << 8)
#define CDC_ECM_BROADCAST_BYTES_XMIT (1 << 9)
#define CDC_ECM_BROADCAST_FRAMES_XMIT (1 << 10)
#define CDC_ECM_DIRECTED_BYTES_RCV (1 << 11)
#define CDC_ECM_DIRECTED_FRAMES_RCV (1 << 12)
#define CDC_ECM_MULTICAST_BYTES_RCV (1 << 13)
#define CDC_ECM_MULTICAST_FRAMES_RCV (1 << 14)
#define CDC_ECM_BROADCAST_BYTES_RCV (1 << 15)
#define CDC_ECM_BROADCAST_FRAMES_RCV (1 << 16)
#define CDC_ECM_RCV_CRC_ERROR (1 << 17)
#define CDC_ECM_TRANSMIT_QUEUE_LENGTH (1 << 18)
#define CDC_ECM_RCV_ERROR_ALIGNMENT (1 << 19)
#define CDC_ECM_XMIT_ONE_COLLISION (1 << 20)
#define CDC_ECM_XMIT_MORE_COLLISIONS (1 << 21)
#define CDC_ECM_XMIT_DEFERRED (1 << 22)
#define CDC_ECM_XMIT_MAX_COLLISIONS (1 << 23)
#define CDC_ECM_RCV_OVERRUN (1 << 24)
#define CDC_ECM_XMIT_UNDERRUN (1 << 25)
#define CDC_ECM_XMIT_HEARTBEAT_FAILURE (1 << 26)
#define CDC_ECM_XMIT_TIMES_CRS_LOST (1 << 27)
#define CDC_ECM_XMIT_LATE_COLLISIONS (1 << 28)
#define CDC_ECM_MAC_STR_DESC (uint8_t *)"010202030000"
#define CDC_ECM_MAC_ADDR0 0x00U /* 01 */
#define CDC_ECM_MAC_ADDR1 0x02U /* 02 */
#define CDC_ECM_MAC_ADDR2 0x02U /* 03 */
#define CDC_ECM_MAC_ADDR3 0x03U /* 00 */
#define CDC_ECM_MAC_ADDR4 0x00U /* 00 */
#define CDC_ECM_MAC_ADDR5 0x00U /* 00 */
#define CDC_ECM_NET_DISCONNECTED 0x00U
#define CDC_ECM_NET_CONNECTED 0x01U
#define CDC_ECM_ETH_STATS_RESERVED 0xE0U
#define CDC_ECM_BMREQUEST_TYPE_ECM 0xA1U
#define CDC_ECM_CONNECT_SPEED_UPSTREAM 0x004C4B40U /* 5Mbps */
#define CDC_ECM_CONNECT_SPEED_DOWNSTREAM 0x004C4B40U /* 5Mbps */
#define CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION 0x00
#define CDC_ECM_NOTIFY_CODE_RESPONSE_AVAILABLE 0x01
#define CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE 0x2A
#define CDC_NCM_NTH16_SIGNATURE 0x484D434E
#define CDC_NCM_NDP16_SIGNATURE_NCM0 0x304D434E
#define CDC_NCM_NDP16_SIGNATURE_NCM1 0x314D434E
/*------------------------------------------------------------------------------
* Structures based on usbcdc11.pdf (www.usb.org)
*----------------------------------------------------------------------------*/
/* Header functional descriptor */
/* (usbcdc11.pdf, 5.2.3.1) */
/* This header must precede any list of class-specific descriptors. */
struct cdc_header_descriptor {
uint8_t bFunctionLength; /* size of this descriptor in bytes */
uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */
uint8_t bDescriptorSubtype; /* Header functional descriptor subtype */
uint16_t bcdCDC; /* USB CDC specification release version */
} __PACKED;
/* Call management functional descriptor */
/* (usbcdc11.pdf, 5.2.3.2) */
/* Describes the processing of calls for the communication class interface. */
struct cdc_call_management_descriptor {
uint8_t bFunctionLength; /* size of this descriptor in bytes */
uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */
uint8_t bDescriptorSubtype; /* call management functional descriptor subtype */
uint8_t bmCapabilities; /* capabilities that this configuration supports */
uint8_t bDataInterface; /* interface number of the data class interface used for call management (optional) */
} __PACKED;
/* Abstract control management functional descriptor */
/* (usbcdc11.pdf, 5.2.3.3) */
/* Describes the command supported by the communication interface class with the Abstract Control Model subclass code. */
struct cdc_abstract_control_management_descriptor {
uint8_t bFunctionLength; /* size of this descriptor in bytes */
uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */
uint8_t bDescriptorSubtype; /* abstract control management functional descriptor subtype */
uint8_t bmCapabilities; /* capabilities supported by this configuration */
} __PACKED;
/* Union functional descriptors */
/* (usbcdc11.pdf, 5.2.3.8) */
/* Describes the relationship between a group of interfaces that can be considered to form a functional unit. */
struct cdc_union_descriptor {
uint8_t bFunctionLength; /* size of this descriptor in bytes */
uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */
uint8_t bDescriptorSubtype; /* union functional descriptor subtype */
uint8_t bMasterInterface; /* interface number designated as master */
} __PACKED;
/* Union functional descriptors with one slave interface */
/* (usbcdc11.pdf, 5.2.3.8) */
struct cdc_union_1slave_descriptor {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bControlInterface;
uint8_t bSubordinateInterface0;
} __PACKED;
/* Line coding structure for GET_LINE_CODING / SET_LINE_CODING class requests*/
/* Format of the data returned when a GetLineCoding request is received */
/* (usbcdc11.pdf, 6.2.13) */
struct cdc_line_coding {
uint32_t dwDTERate; /* Data terminal rate in bits per second */
uint8_t bCharFormat; /* Number of stop bits */
uint8_t bParityType; /* Parity bit type */
uint8_t bDataBits; /* Number of data bits */
} __PACKED;
/** Data structure for the notification about SerialState */
struct cdc_acm_notification {
uint8_t bmRequestType;
uint8_t bNotificationType;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
uint16_t data;
} __PACKED;
/** Ethernet Networking Functional Descriptor */
struct cdc_eth_descriptor {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t iMACAddress;
uint32_t bmEthernetStatistics;
uint16_t wMaxSegmentSize;
uint16_t wNumberMCFilters;
uint8_t bNumberPowerFilters;
} __PACKED;
struct cdc_eth_notification {
uint8_t bmRequestType;
uint8_t bNotificationType;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
uint8_t data[8];
} __PACKED;
struct cdc_ncm_ntb_parameters {
uint16_t wLength;
uint16_t bmNtbFormatsSupported;
uint32_t dwNtbInMaxSize;
uint16_t wNdbInDivisor;
uint16_t wNdbInPayloadRemainder;
uint16_t wNdbInAlignment;
uint16_t wReserved;
uint32_t dwNtbOutMaxSize;
uint16_t wNdbOutDivisor;
uint16_t wNdbOutPayloadRemainder;
uint16_t wNdbOutAlignment;
uint16_t wNtbOutMaxDatagrams;
};
struct cdc_ncm_nth16 {
uint32_t dwSignature;
uint16_t wHeaderLength;
uint16_t wSequence;
uint16_t wBlockLength;
uint16_t wNdpIndex;
};
struct cdc_ncm_ndp16_datagram {
uint16_t wDatagramIndex;
uint16_t wDatagramLength;
};
struct cdc_ncm_ndp16 {
uint32_t dwSignature;
uint16_t wLength;
uint16_t wNextNdpIndex;
struct cdc_ncm_ndp16_datagram datagram[];
};
/*Length of template descriptor: 66 bytes*/
#define CDC_ACM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
// clang-format off
#define CDC_ACM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, str_idx) \
/* Interface Associate */ \
0x08, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
bFirstInterface, /* bFirstInterface */ \
0x02, /* bInterfaceCount */ \
USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \
CDC_ABSTRACT_CONTROL_MODEL, /* bFunctionSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bFunctionProtocol */ \
0x00, /* iFunction */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bFirstInterface, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
CDC_ABSTRACT_CONTROL_MODEL, /* bInterfaceSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bInterfaceProtocol */ \
str_idx, /* iInterface */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
WBVAL(CDC_V1_10), /* bcdCDC */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_CALL_MANAGEMENT, /* bDescriptorSubtype */ \
0x00, /* bmCapabilities */ \
(uint8_t)(bFirstInterface + 1), /* bDataInterface */ \
0x04, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \
0x02, /* bmCapabilities */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
bFirstInterface, /* bMasterInterface */ \
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
int_ep, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x08, 0x00, /* wMaxPacketSize */ \
0x0a, /* bInterval */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
(uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x02, /* bNumEndpoints */ \
CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
0x00, /* bInterfaceSubClass */ \
0x00, /* bInterfaceProtocol */ \
0x00, /* iInterface */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
out_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00 /* bInterval */
// clang-format on
/*Length of template descriptor: 66 bytes*/
#define CDC_RNDIS_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
// clang-format off
#define CDC_RNDIS_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, str_idx) \
/* Interface Associate */ \
0x08, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
bFirstInterface, /* bFirstInterface */ \
0x02, /* bInterfaceCount */ \
USB_DEVICE_CLASS_WIRELESS, /* bFunctionClass */ \
CDC_DIRECT_LINE_CONTROL_MODEL, /* bFunctionSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bFunctionProtocol */ \
0x00, /* iFunction */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bFirstInterface, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_WIRELESS, /* bInterfaceClass */ \
CDC_DIRECT_LINE_CONTROL_MODEL, /* bInterfaceSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bInterfaceProtocol */ \
str_idx, /* iInterface */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
WBVAL(CDC_V1_10), /* bcdCDC */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_CALL_MANAGEMENT, /* bDescriptorSubtype */ \
0x00, /* bmCapabilities */ \
(uint8_t)(bFirstInterface + 1), /* bDataInterface */ \
0x04, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \
0x00, /* bmCapabilities */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
bFirstInterface, /* bMasterInterface */ \
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
int_ep, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x08, 0x00, /* wMaxPacketSize */ \
0x10, /* bInterval */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
(uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x02, /* bNumEndpoints */ \
CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
0x00, /* bInterfaceSubClass */ \
0x00, /* bInterfaceProtocol */ \
0x00, /* iInterface */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
out_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00 /* bInterval */
// clang-format on
#define DBVAL_BE(x) ((x >> 24) & 0xFF), ((x >> 16) & 0xFF), ((x >> 8) & 0xFF), (x & 0xFF)
/*Length of template descriptor: 71 bytes*/
#define CDC_ECM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 13 + 7 + 9 + 7 + 7)
// clang-format off
#define CDC_ECM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, \
eth_statistics, wMaxSegmentSize, wNumberMCFilters, bNumberPowerFilters, str_idx) \
/* Interface Associate */ \
0x08, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
bFirstInterface, /* bFirstInterface */ \
0x02, /* bInterfaceCount */ \
USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \
CDC_ETHERNET_NETWORKING_CONTROL_MODEL, /* bFunctionSubClass */ \
CDC_COMMON_PROTOCOL_NONE, /* bFunctionProtocol */ \
0x00, /* iFunction */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bFirstInterface, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
CDC_ETHERNET_NETWORKING_CONTROL_MODEL, /* bInterfaceSubClass */ \
CDC_COMMON_PROTOCOL_NONE, /* bInterfaceProtocol */ \
str_idx, /* iInterface */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
WBVAL(CDC_V1_10), /* bcdCDC */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
bFirstInterface, /* bMasterInterface */ \
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
/* CDC_ECM Functional Descriptor */ \
0x0D, /* bFunctionLength */\
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */\
CDC_FUNC_DESC_ETHERNET_NETWORKING, /* Ethernet Networking functional descriptor subtype */\
str_idx, /* Device's MAC string index */\
DBVAL_BE(eth_statistics), /* Ethernet statistics (bitmap) */\
WBVAL(wMaxSegmentSize),/* wMaxSegmentSize: Ethernet Maximum Segment size, typically 1514 bytes */\
WBVAL(wNumberMCFilters), /* wNumberMCFilters: the number of multicast filters */\
bNumberPowerFilters, /* bNumberPowerFilters: the number of wakeup power filters */\
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
int_ep, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x10, 0x00, /* wMaxPacketSize */ \
0x10, /* bInterval */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
(uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x02, /* bNumEndpoints */ \
CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
0x00, /* bInterfaceSubClass */ \
0x00, /* bInterfaceProtocol */ \
0x00, /* iInterface */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
out_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00 /* bInterval */
// clang-format on
/*Length of template descriptor: 77 bytes*/
#define CDC_NCM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 13 + 6 + 7 + 9 + 7 + 7)
// clang-format off
#define CDC_NCM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, \
eth_statistics, wMaxSegmentSize, wNumberMCFilters, bNumberPowerFilters, str_idx) \
/* Interface Associate */ \
0x08, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
bFirstInterface, /* bFirstInterface */ \
0x02, /* bInterfaceCount */ \
USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \
CDC_NETWORK_CONTROL_MODEL, /* bFunctionSubClass */ \
CDC_COMMON_PROTOCOL_NONE, /* bFunctionProtocol */ \
0x00, /* iFunction */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bFirstInterface, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
CDC_NETWORK_CONTROL_MODEL, /* bInterfaceSubClass */ \
CDC_COMMON_PROTOCOL_NONE, /* bInterfaceProtocol */ \
str_idx, /* iInterface */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
WBVAL(CDC_V1_10), /* bcdCDC */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
bFirstInterface, /* bMasterInterface */ \
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
/* CDC ETH Functional Descriptor */ \
0x0D, /* bFunctionLength */\
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */\
CDC_FUNC_DESC_ETHERNET_NETWORKING, /* Ethernet Networking functional descriptor subtype */\
str_idx, /* Device's MAC string index */\
DBVAL_BE(eth_statistics), /* Ethernet statistics (bitmap) */\
WBVAL(wMaxPacketSize),/* wMaxSegmentSize: Ethernet Maximum Segment size, typically 1514 bytes */\
WBVAL(wNumberMCFilters), /* wNumberMCFilters: the number of multicast filters */\
bNumberPowerFilters, /* bNumberPowerFilters: the number of wakeup power filters */\
0x06, \
CDC_CS_INTERFACE, \
CDC_FUNC_DESC_NCM, \
0x00, 0x01, \
0x23, \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
int_ep, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x10, 0x00, /* wMaxPacketSize */ \
0x10, /* bInterval */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
(uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x02, /* bNumEndpoints */ \
CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
0x00, /* bInterfaceSubClass */ \
0x00, /* bInterfaceProtocol */ \
0x00, /* iInterface */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
out_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00 /* bInterval */
// clang-format on
#endif /* USB_CDC_H */

View File

@ -1,13 +0,0 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_CDC_H
#define USBD_CDC_H
// legacy for old version
#include "usbd_cdc_acm.h"
#endif

View File

@ -1,134 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_cdc_acm.h"
const char *stop_name[] = { "1", "1.5", "2" };
const char *parity_name[] = { "N", "O", "E", "M", "S" };
static int cdc_acm_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("CDC Class request: "
"bRequest 0x%02x\r\n",
setup->bRequest);
struct cdc_line_coding line_coding;
bool dtr, rts;
uint8_t intf_num = LO_BYTE(setup->wIndex);
switch (setup->bRequest) {
case CDC_REQUEST_SET_LINE_CODING:
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
memcpy(&line_coding, *data, setup->wLength);
USB_LOG_DBG("Set intf:%d linecoding <%d %d %s %s>\r\n",
intf_num,
line_coding.dwDTERate,
line_coding.bDataBits,
parity_name[line_coding.bParityType],
stop_name[line_coding.bCharFormat]);
usbd_cdc_acm_set_line_coding(busid, intf_num, &line_coding);
break;
case CDC_REQUEST_SET_CONTROL_LINE_STATE:
dtr = (setup->wValue & 0x0001);
rts = (setup->wValue & 0x0002);
USB_LOG_DBG("Set intf:%d DTR 0x%x,RTS 0x%x\r\n",
intf_num,
dtr,
rts);
usbd_cdc_acm_set_dtr(busid, intf_num, dtr);
usbd_cdc_acm_set_rts(busid, intf_num, rts);
break;
case CDC_REQUEST_GET_LINE_CODING:
usbd_cdc_acm_get_line_coding(busid, intf_num, &line_coding);
memcpy(*data, &line_coding, 7);
*len = 7;
USB_LOG_DBG("Get intf:%d linecoding %d %d %d %d\r\n",
intf_num,
line_coding.dwDTERate,
line_coding.bCharFormat,
line_coding.bParityType,
line_coding.bDataBits);
break;
case CDC_REQUEST_SEND_BREAK:
usbd_cdc_acm_send_break(busid, intf_num);
break;
default:
USB_LOG_WRN("Unhandled CDC Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
return 0;
}
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf)
{
(void)busid;
intf->class_interface_handler = cdc_acm_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = NULL;
return intf;
}
__WEAK void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
{
(void)busid;
(void)intf;
(void)line_coding;
}
__WEAK void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
{
(void)busid;
(void)intf;
line_coding->dwDTERate = 2000000;
line_coding->bDataBits = 8;
line_coding->bParityType = 0;
line_coding->bCharFormat = 0;
}
__WEAK void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
{
(void)busid;
(void)intf;
(void)dtr;
}
__WEAK void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts)
{
(void)busid;
(void)intf;
(void)rts;
}
__WEAK void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf)
{
(void)busid;
(void)intf;
}

View File

@ -1,29 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_CDC_ACM_H
#define USBD_CDC_ACM_H
#include "usb_cdc.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Init cdc acm interface driver */
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf);
/* Setup request command callback api */
void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr);
void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts);
void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf);
#ifdef __cplusplus
}
#endif
#endif /* USBD_CDC_ACM_H */

View File

@ -1,262 +0,0 @@
/*
* Copyright (c) 2023, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_cdc_ecm.h"
#define CDC_ECM_OUT_EP_IDX 0
#define CDC_ECM_IN_EP_IDX 1
#define CDC_ECM_INT_EP_IDX 2
/* Describe EndPoints configuration */
static struct usbd_endpoint cdc_ecm_ep_data[3];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_notify_buf[16];
volatile uint8_t *g_cdc_ecm_rx_data_buffer = NULL;
volatile uint32_t g_cdc_ecm_rx_data_length = 0;
volatile uint32_t g_cdc_ecm_tx_data_length = 0;
static volatile uint8_t g_current_net_status = 0;
static volatile uint8_t g_cmd_intf = 0;
static uint32_t g_connect_speed_table[2] = { CDC_ECM_CONNECT_SPEED_UPSTREAM,
CDC_ECM_CONNECT_SPEED_DOWNSTREAM };
void usbd_cdc_ecm_send_notify(uint8_t notifycode, uint8_t value, uint32_t *speed)
{
struct cdc_eth_notification *notify = (struct cdc_eth_notification *)g_cdc_ecm_notify_buf;
uint8_t bytes2send = 0;
notify->bmRequestType = CDC_ECM_BMREQUEST_TYPE_ECM;
notify->bNotificationType = notifycode;
switch (notifycode) {
case CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION:
notify->wValue = value;
notify->wIndex = g_cmd_intf;
notify->wLength = 0U;
for (uint8_t i = 0U; i < 8U; i++) {
notify->data[i] = 0U;
}
bytes2send = 8U;
break;
case CDC_ECM_NOTIFY_CODE_RESPONSE_AVAILABLE:
notify->wValue = 0U;
notify->wIndex = g_cmd_intf;
notify->wLength = 0U;
for (uint8_t i = 0U; i < 8U; i++) {
notify->data[i] = 0U;
}
bytes2send = 8U;
break;
case CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE:
notify->wValue = 0U;
notify->wIndex = g_cmd_intf;
notify->wLength = 0x0008U;
bytes2send = 16U;
memcpy(notify->data, speed, 8);
break;
default:
break;
}
if (bytes2send) {
usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send);
}
}
static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("CDC ECM Class request: "
"bRequest 0x%02x\r\n",
setup->bRequest);
(void)busid;
(void)data;
(void)len;
g_cmd_intf = LO_BYTE(setup->wIndex);
switch (setup->bRequest) {
case CDC_REQUEST_SET_ETHERNET_PACKET_FILTER:
/* bit0 Promiscuous
* bit1 ALL Multicast
* bit2 Directed
* bit3 Broadcast
* bit4 Multicast
*/
if (g_current_net_status == 0) {
g_current_net_status = 1;
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, NULL);
}
break;
default:
USB_LOG_WRN("Unhandled CDC ECM Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
return 0;
}
void cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
(void)busid;
(void)arg;
switch (event) {
case USBD_EVENT_RESET:
g_current_net_status = 0;
g_cdc_ecm_rx_data_length = 0;
g_cdc_ecm_tx_data_length = 0;
g_cdc_ecm_rx_data_buffer = NULL;
break;
case USBD_EVENT_CONFIGURED:
usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(busid, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr));
break;
default:
break;
}
}
void cdc_ecm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)busid;
g_cdc_ecm_rx_data_length += nbytes;
if (nbytes < usbd_get_ep_mps(0, ep)) {
g_cdc_ecm_rx_data_buffer = g_cdc_ecm_rx_buffer;
usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
} else {
usbd_ep_start_read(0, ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(0, ep));
}
}
void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)busid;
if ((nbytes % usbd_get_ep_mps(0, ep)) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(0, ep, NULL, 0);
} else {
g_cdc_ecm_tx_data_length = 0;
}
}
void cdc_ecm_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)busid;
(void)ep;
(void)nbytes;
if (g_current_net_status == 1) {
g_current_net_status = 2;
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, g_connect_speed_table);
}
}
int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len)
{
if (g_cdc_ecm_tx_data_length > 0) {
return -USB_ERR_BUSY;
}
g_cdc_ecm_tx_data_length = len;
USB_LOG_DBG("txlen:%d\r\n", g_cdc_ecm_tx_data_length);
return usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, buf, g_cdc_ecm_tx_data_length);
}
void usbd_cdc_ecm_start_read_next(void)
{
g_cdc_ecm_rx_data_length = 0;
g_cdc_ecm_rx_data_buffer = NULL;
usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, g_cdc_ecm_rx_buffer, usbd_get_ep_mps(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr));
}
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
struct pbuf *usbd_cdc_ecm_eth_rx(void)
{
struct pbuf *p;
if (g_cdc_ecm_rx_data_buffer == NULL) {
return NULL;
}
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_data_length, PBUF_POOL);
if (p == NULL) {
usbd_cdc_ecm_start_read_next();
return NULL;
}
usb_memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
p->len = g_cdc_ecm_rx_data_length;
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_data_length);
usbd_cdc_ecm_start_read_next();
return p;
}
int usbd_cdc_ecm_eth_tx(struct pbuf *p)
{
struct pbuf *q;
uint8_t *buffer;
if (g_cdc_ecm_tx_data_length > 0) {
return -USB_ERR_BUSY;
}
if (p->tot_len > sizeof(g_cdc_ecm_tx_buffer)) {
p->tot_len = sizeof(g_cdc_ecm_tx_buffer);
}
buffer = g_cdc_ecm_tx_buffer;
for (q = p; q != NULL; q = q->next) {
usb_memcpy(buffer, q->payload, q->len);
buffer += q->len;
}
return usbd_cdc_ecm_start_write(g_cdc_ecm_tx_buffer, p->tot_len);
}
#endif
struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep)
{
intf->class_interface_handler = cdc_ecm_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = cdc_ecm_notify_handler;
cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr = out_ep;
cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_cb = cdc_ecm_bulk_out;
cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr = in_ep;
cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_cb = cdc_ecm_bulk_in;
cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr = int_ep;
cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_cb = cdc_ecm_int_in;
usbd_add_endpoint(0, &cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX]);
usbd_add_endpoint(0, &cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX]);
usbd_add_endpoint(0, &cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX]);
return intf;
}
void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2])
{
memcpy(g_connect_speed_table, speed, 8);
}
__WEAK void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len)
{
(void)buf;
(void)len;
}

View File

@ -1,42 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_CDC_ECM_H
#define USBD_CDC_ECM_H
#include "usb_cdc.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Ethernet Maximum Segment size, typically 1514 bytes */
#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1514U
/* Init cdc ecm interface driver */
struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep);
/* Setup request command callback api */
void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2]);
/* Api for eth only without any net stack */
uint8_t *usbd_cdc_ecm_get_tx_buffer(void);
void usbd_cdc_ecm_send_done(void);
int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len);
void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len);
void usbd_cdc_ecm_start_read_next(void);
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
#include "lwip/netif.h"
#include "lwip/pbuf.h"
struct pbuf *usbd_cdc_ecm_eth_rx(void);
int usbd_cdc_ecm_eth_tx(struct pbuf *p);
#endif
#ifdef __cplusplus
}
#endif
#endif /* USBD_CDC_ECM_H */

View File

@ -1,284 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_cdc_acm.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_cdc_acm"
#include "usb_log.h"
#define DEV_FORMAT "/dev/ttyACM%d"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_acm_buf[CONFIG_USBHOST_MAX_CDC_ACM_CLASS][USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
static struct usbh_cdc_acm g_cdc_acm_class[CONFIG_USBHOST_MAX_CDC_ACM_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_cdc_acm *usbh_cdc_acm_class_alloc(void)
{
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_CDC_ACM_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_cdc_acm_class[devno], 0, sizeof(struct usbh_cdc_acm));
g_cdc_acm_class[devno].minor = devno;
return &g_cdc_acm_class[devno];
}
}
return NULL;
}
static void usbh_cdc_acm_class_free(struct usbh_cdc_acm *cdc_acm_class)
{
int devno = cdc_acm_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm));
}
int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
{
struct usb_setup_packet *setup;
if (!cdc_acm_class || !cdc_acm_class->hport) {
return -USB_ERR_INVAL;
}
setup = cdc_acm_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_SET_LINE_CODING;
setup->wValue = 0;
setup->wIndex = cdc_acm_class->intf;
setup->wLength = 7;
memcpy(g_cdc_acm_buf[cdc_acm_class->minor], line_coding, sizeof(struct cdc_line_coding));
return usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf[cdc_acm_class->minor]);
}
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
{
struct usb_setup_packet *setup;
int ret;
if (!cdc_acm_class || !cdc_acm_class->hport) {
return -USB_ERR_INVAL;
}
setup = cdc_acm_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_GET_LINE_CODING;
setup->wValue = 0;
setup->wIndex = cdc_acm_class->intf;
setup->wLength = 7;
ret = usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf[cdc_acm_class->minor]);
if (ret < 0) {
return ret;
}
memcpy(line_coding, g_cdc_acm_buf[cdc_acm_class->minor], sizeof(struct cdc_line_coding));
return ret;
}
int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bool rts)
{
struct usb_setup_packet *setup;
if (!cdc_acm_class || !cdc_acm_class->hport) {
return -USB_ERR_INVAL;
}
setup = cdc_acm_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE;
setup->wValue = (dtr << 0) | (rts << 1);
setup->wIndex = cdc_acm_class->intf;
setup->wLength = 0;
return usbh_control_transfer(cdc_acm_class->hport, setup, NULL);
}
static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret = 0;
struct usbh_cdc_acm *cdc_acm_class = usbh_cdc_acm_class_alloc();
if (cdc_acm_class == NULL) {
USB_LOG_ERR("Fail to alloc cdc_acm_class\r\n");
return -USB_ERR_NOMEM;
}
cdc_acm_class->hport = hport;
cdc_acm_class->intf = intf;
hport->config.intf[intf].priv = cdc_acm_class;
hport->config.intf[intf + 1].priv = NULL;
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
USBH_EP_INIT(cdc_acm_class->intin, ep_desc);
#endif
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(cdc_acm_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(cdc_acm_class->bulkout, ep_desc);
}
}
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, cdc_acm_class->minor);
USB_LOG_INFO("Register CDC ACM Class:%s\r\n", hport->config.intf[intf].devname);
#if 0
USB_LOG_INFO("Test cdc acm rx and tx and rx for 5 times, baudrate is 115200\r\n");
struct cdc_line_coding linecoding;
uint8_t count = 5;
linecoding.dwDTERate = 115200;
linecoding.bDataBits = 8;
linecoding.bParityType = 0;
linecoding.bCharFormat = 0;
usbh_cdc_acm_set_line_coding(cdc_acm_class, &linecoding);
usbh_cdc_acm_set_line_state(cdc_acm_class, true, false);
memset(g_cdc_acm_buf, 'a', sizeof(g_cdc_acm_buf));
ret = usbh_cdc_acm_bulk_out_transfer(cdc_acm_class, g_cdc_acm_buf, sizeof(g_cdc_acm_buf), 0xfffffff);
USB_LOG_RAW("out ret:%d\r\n", ret);
while (count--) {
ret = usbh_cdc_acm_bulk_in_transfer(cdc_acm_class, g_cdc_acm_buf, sizeof(g_cdc_acm_buf), 0xfffffff);
USB_LOG_RAW("in ret:%d\r\n", ret);
if (ret > 0) {
for (uint32_t i = 0; i < ret; i++) {
USB_LOG_RAW("%02x ", g_cdc_acm_buf[i]);
}
}
USB_LOG_RAW("\r\n");
}
#endif
usbh_cdc_acm_run(cdc_acm_class);
return ret;
}
static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)hport->config.intf[intf].priv;
if (cdc_acm_class) {
if (cdc_acm_class->bulkin) {
usbh_kill_urb(&cdc_acm_class->bulkin_urb);
}
if (cdc_acm_class->bulkout) {
usbh_kill_urb(&cdc_acm_class->bulkout_urb);
}
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
if (cdc_acm_class->intin) {
usbh_kill_urb(&cdc_acm_class->intin_urb);
}
#endif
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister CDC ACM Class:%s\r\n", hport->config.intf[intf].devname);
usbh_cdc_acm_stop(cdc_acm_class);
}
usbh_cdc_acm_class_free(cdc_acm_class);
}
return ret;
}
int usbh_cdc_acm_bulk_in_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &cdc_acm_class->bulkin_urb;
usbh_bulk_urb_fill(urb, cdc_acm_class->hport, cdc_acm_class->bulkin, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
int usbh_cdc_acm_bulk_out_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &cdc_acm_class->bulkout_urb;
usbh_bulk_urb_fill(urb, cdc_acm_class->hport, cdc_acm_class->bulkout, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
static int usbh_cdc_data_connect(struct usbh_hubport *hport, uint8_t intf)
{
(void)hport;
(void)intf;
return 0;
}
static int usbh_cdc_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
(void)hport;
(void)intf;
return 0;
}
__WEAK void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
{
(void)cdc_acm_class;
}
__WEAK void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
{
(void)cdc_acm_class;
}
const struct usbh_class_driver cdc_acm_class_driver = {
.driver_name = "cdc_acm",
.connect = usbh_cdc_acm_connect,
.disconnect = usbh_cdc_acm_disconnect
};
const struct usbh_class_driver cdc_data_class_driver = {
.driver_name = "cdc_data",
.connect = usbh_cdc_data_connect,
.disconnect = usbh_cdc_data_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_CDC,
.subclass = CDC_ABSTRACT_CONTROL_MODEL,
.protocol = CDC_COMMON_PROTOCOL_AT_COMMANDS,
.id_table = NULL,
.class_driver = &cdc_acm_class_driver
};
CLASS_INFO_DEFINE const struct usbh_class_info cdc_data_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS,
.class = USB_DEVICE_CLASS_CDC_DATA,
.subclass = 0x00,
.protocol = 0x00,
.id_table = NULL,
.class_driver = &cdc_data_class_driver
};

View File

@ -1,50 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_CDC_ACM_H
#define USBH_CDC_ACM_H
#include "usb_cdc.h"
struct usbh_cdc_acm {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint (optional) */
#endif
struct usbh_urb bulkout_urb;
struct usbh_urb bulkin_urb;
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
struct usbh_urb intin_urb;
#endif
struct cdc_line_coding linecoding;
uint8_t intf;
uint8_t minor;
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding);
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding);
int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bool rts);
int usbh_cdc_acm_bulk_in_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
int usbh_cdc_acm_bulk_out_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class);
void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class);
#ifdef __cplusplus
}
#endif
#endif /* USBH_CDC_ACM_H */

View File

@ -1,331 +0,0 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_cdc_ecm.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_cdc_ecm"
#include "usb_log.h"
#define DEV_FORMAT "/dev/cdc_ether"
/* general descriptor field offsets */
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
#define DESC_bDescriptorSubType 2 /** Descriptor subtype offset */
/* interface descriptor field offsets */
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
#define CONFIG_USBHOST_CDC_ECM_PKT_FILTER 0x000C
#define CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE 1514U
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_inttx_buffer[16];
static struct usbh_cdc_ecm g_cdc_ecm_class;
static int usbh_cdc_ecm_set_eth_packet_filter(struct usbh_cdc_ecm *cdc_ecm_class, uint16_t filter_value)
{
struct usb_setup_packet *setup;
if (!cdc_ecm_class || !cdc_ecm_class->hport) {
return -USB_ERR_INVAL;
}
setup = cdc_ecm_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_SET_ETHERNET_PACKET_FILTER;
setup->wValue = filter_value;
setup->wIndex = cdc_ecm_class->ctrl_intf;
setup->wLength = 0;
return usbh_control_transfer(cdc_ecm_class->hport, setup, NULL);
}
int usbh_cdc_ecm_get_connect_status(struct usbh_cdc_ecm *cdc_ecm_class)
{
int ret;
usbh_int_urb_fill(&cdc_ecm_class->intin_urb, cdc_ecm_class->hport, cdc_ecm_class->intin, g_cdc_ecm_inttx_buffer, 16, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&cdc_ecm_class->intin_urb);
if (ret < 0) {
return ret;
}
if (g_cdc_ecm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION) {
if (g_cdc_ecm_inttx_buffer[2] == CDC_ECM_NET_CONNECTED) {
cdc_ecm_class->connect_status = true;
} else {
cdc_ecm_class->connect_status = false;
}
} else if (g_cdc_ecm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE) {
memcpy(cdc_ecm_class->speed, &g_cdc_ecm_inttx_buffer[8], 8);
}
return 0;
}
static int usbh_cdc_ecm_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret;
uint8_t altsetting = 0;
char mac_buffer[12];
uint8_t *p;
uint8_t cur_iface = 0xff;
uint8_t mac_str_idx = 0xff;
struct usbh_cdc_ecm *cdc_ecm_class = &g_cdc_ecm_class;
memset(cdc_ecm_class, 0, sizeof(struct usbh_cdc_ecm));
cdc_ecm_class->hport = hport;
cdc_ecm_class->ctrl_intf = intf;
cdc_ecm_class->data_intf = intf + 1;
hport->config.intf[intf].priv = cdc_ecm_class;
hport->config.intf[intf + 1].priv = NULL;
p = hport->raw_config_desc;
while (p[DESC_bLength]) {
switch (p[DESC_bDescriptorType]) {
case USB_DESCRIPTOR_TYPE_INTERFACE:
cur_iface = p[INTF_DESC_bInterfaceNumber];
//cur_alt_setting = p[INTF_DESC_bAlternateSetting];
break;
case CDC_CS_INTERFACE:
if ((cur_iface == cdc_ecm_class->ctrl_intf) && p[DESC_bDescriptorSubType] == CDC_FUNC_DESC_ETHERNET_NETWORKING) {
struct cdc_eth_descriptor *desc = (struct cdc_eth_descriptor *)p;
mac_str_idx = desc->iMACAddress;
cdc_ecm_class->max_segment_size = desc->wMaxSegmentSize;
goto get_mac;
}
break;
default:
break;
}
/* skip to next descriptor */
p += p[DESC_bLength];
}
get_mac:
if (mac_str_idx == 0xff) {
USB_LOG_ERR("Do not find cdc ecm mac string\r\n");
return -1;
}
memset(mac_buffer, 0, 12);
ret = usbh_get_string_desc(cdc_ecm_class->hport, mac_str_idx, (uint8_t *)mac_buffer);
if (ret < 0) {
return ret;
}
for (int i = 0, j = 0; i < 12; i += 2, j++) {
char byte_str[3];
byte_str[0] = mac_buffer[i];
byte_str[1] = mac_buffer[i + 1];
byte_str[2] = '\0';
uint32_t byte = strtoul(byte_str, NULL, 16);
cdc_ecm_class->mac[j] = (unsigned char)byte;
}
USB_LOG_INFO("CDC ECM MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
cdc_ecm_class->mac[0],
cdc_ecm_class->mac[1],
cdc_ecm_class->mac[2],
cdc_ecm_class->mac[3],
cdc_ecm_class->mac[4],
cdc_ecm_class->mac[5]);
if (cdc_ecm_class->max_segment_size > CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE) {
USB_LOG_ERR("CDC ECM Max Segment Size is overflow, default is %u, but now %u\r\n", CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE, cdc_ecm_class->max_segment_size);
} else {
USB_LOG_INFO("CDC ECM Max Segment Size:%u\r\n", cdc_ecm_class->max_segment_size);
}
/* enable int ep */
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
USBH_EP_INIT(cdc_ecm_class->intin, ep_desc);
if (hport->config.intf[intf + 1].altsetting_num > 1) {
altsetting = hport->config.intf[intf + 1].altsetting_num - 1;
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[altsetting].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf + 1].altsetting[altsetting].ep[i].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(cdc_ecm_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(cdc_ecm_class->bulkout, ep_desc);
}
}
USB_LOG_INFO("Select cdc ecm altsetting: %d\r\n", altsetting);
usbh_set_interface(cdc_ecm_class->hport, cdc_ecm_class->data_intf, altsetting);
} else {
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(cdc_ecm_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(cdc_ecm_class->bulkout, ep_desc);
}
}
}
/* bit0 Promiscuous
* bit1 ALL Multicast
* bit2 Directed
* bit3 Broadcast
* bit4 Multicast
*/
ret = usbh_cdc_ecm_set_eth_packet_filter(cdc_ecm_class, CONFIG_USBHOST_CDC_ECM_PKT_FILTER);
if (ret < 0) {
return ret;
}
USB_LOG_INFO("Set CDC ECM packet filter:%04x\r\n", CONFIG_USBHOST_CDC_ECM_PKT_FILTER);
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
USB_LOG_INFO("Register CDC ECM Class:%s\r\n", hport->config.intf[intf].devname);
usbh_cdc_ecm_run(cdc_ecm_class);
return ret;
}
static int usbh_cdc_ecm_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_cdc_ecm *cdc_ecm_class = (struct usbh_cdc_ecm *)hport->config.intf[intf].priv;
if (cdc_ecm_class) {
if (cdc_ecm_class->bulkin) {
usbh_kill_urb(&cdc_ecm_class->bulkin_urb);
}
if (cdc_ecm_class->bulkout) {
usbh_kill_urb(&cdc_ecm_class->bulkout_urb);
}
if (cdc_ecm_class->intin) {
usbh_kill_urb(&cdc_ecm_class->intin_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister CDC ECM Class:%s\r\n", hport->config.intf[intf].devname);
usbh_cdc_ecm_stop(cdc_ecm_class);
}
memset(cdc_ecm_class, 0, sizeof(struct usbh_cdc_ecm));
}
return ret;
}
void usbh_cdc_ecm_rx_thread(void *argument)
{
uint32_t g_cdc_ecm_rx_length;
int ret;
(void)argument;
USB_LOG_INFO("Create cdc ecm rx thread\r\n");
// clang-format off
find_class:
// clang-format on
g_cdc_ecm_class.connect_status = false;
if (usbh_find_class_instance("/dev/cdc_ether") == NULL) {
goto delete;
}
while (g_cdc_ecm_class.connect_status == false) {
ret = usbh_cdc_ecm_get_connect_status(&g_cdc_ecm_class);
if (ret < 0) {
usb_osal_msleep(100);
goto find_class;
}
usb_osal_msleep(128);
}
g_cdc_ecm_rx_length = 0;
while (1) {
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkin_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkin, g_cdc_ecm_rx_buffer, CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_cdc_ecm_class.bulkin_urb);
if (ret < 0) {
goto find_class;
}
g_cdc_ecm_rx_length = g_cdc_ecm_class.bulkin_urb.actual_length;
/* A transfer is complete because last packet is a short packet.
* Short packet is not zero, match g_cdc_ecm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize).
* Short packet is zero, check if g_cdc_ecm_class.bulkin_urb.actual_length < transfer_size, for example transfer is complete with size is 512 < 1514.
* This case is always true
*/
if (g_cdc_ecm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize) ||
(g_cdc_ecm_class.bulkin_urb.actual_length < CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE)) {
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_length);
usbh_cdc_ecm_eth_input(g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_length);
g_cdc_ecm_rx_length = 0;
} else {
/* There's no way to run here. */
}
}
// clang-format off
delete:
USB_LOG_INFO("Delete cdc ecm rx thread\r\n");
usb_osal_thread_delete(NULL);
// clang-format on
}
uint8_t *usbh_cdc_ecm_get_eth_txbuf(void)
{
return g_cdc_ecm_tx_buffer;
}
int usbh_cdc_ecm_eth_output(uint32_t buflen)
{
if (g_cdc_ecm_class.connect_status == false) {
return -USB_ERR_NOTCONN;
}
USB_LOG_DBG("txlen:%d\r\n", buflen);
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkout_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkout, g_cdc_ecm_tx_buffer, buflen, USB_OSAL_WAITING_FOREVER, NULL, NULL);
return usbh_submit_urb(&g_cdc_ecm_class.bulkout_urb);
}
__WEAK void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
{
(void)cdc_ecm_class;
}
__WEAK void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
{
(void)cdc_ecm_class;
}
const struct usbh_class_driver cdc_ecm_class_driver = {
.driver_name = "cdc_ecm",
.connect = usbh_cdc_ecm_connect,
.disconnect = usbh_cdc_ecm_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info cdc_ecm_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_CDC,
.subclass = CDC_ETHERNET_NETWORKING_CONTROL_MODEL,
.protocol = CDC_COMMON_PROTOCOL_NONE,
.id_table = NULL,
.class_driver = &cdc_ecm_class_driver
};

View File

@ -1,50 +0,0 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_CDC_ECM_H
#define USBH_CDC_ECM_H
#include "usb_cdc.h"
struct usbh_cdc_ecm {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
struct usb_endpoint_descriptor *intin; /* Interrupt IN endpoint */
struct usbh_urb bulkout_urb; /* Bulk out endpoint */
struct usbh_urb bulkin_urb; /* Bulk IN endpoint */
struct usbh_urb intin_urb; /* Interrupt IN endpoint */
uint8_t ctrl_intf; /* Control interface number */
uint8_t data_intf; /* Data interface number */
uint8_t minor;
uint8_t mac[6];
bool connect_status;
uint16_t max_segment_size;
uint32_t speed[2];
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
int usbh_cdc_ecm_get_connect_status(struct usbh_cdc_ecm *cdc_ecm_class);
void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class);
void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class);
uint8_t *usbh_cdc_ecm_get_eth_txbuf(void);
int usbh_cdc_ecm_eth_output(uint32_t buflen);
void usbh_cdc_ecm_eth_input(uint8_t *buf, uint32_t buflen);
void usbh_cdc_ecm_rx_thread(void *argument);
#ifdef __cplusplus
}
#endif
#endif /* USBH_CDC_ECM_H */

View File

@ -1,411 +0,0 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_cdc_ncm.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_cdc_ncm"
#include "usb_log.h"
#define DEV_FORMAT "/dev/cdc_ncm"
/* general descriptor field offsets */
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
#define DESC_bDescriptorSubType 2 /** Descriptor subtype offset */
/* interface descriptor field offsets */
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_SEGSZE 1514U
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ncm_rx_buffer[CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ncm_tx_buffer[CONFIG_USBHOST_CDC_NCM_ETH_MAX_TX_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ncm_inttx_buffer[16];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ncm_buf[32];
static struct usbh_cdc_ncm g_cdc_ncm_class;
static int usbh_cdc_ncm_get_ntb_parameters(struct usbh_cdc_ncm *cdc_ncm_class, struct cdc_ncm_ntb_parameters *param)
{
struct usb_setup_packet *setup;
int ret;
if (!cdc_ncm_class || !cdc_ncm_class->hport) {
return -USB_ERR_INVAL;
}
setup = cdc_ncm_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_GET_NTB_PARAMETERS;
setup->wValue = 0;
setup->wIndex = cdc_ncm_class->ctrl_intf;
setup->wLength = 28;
ret = usbh_control_transfer(cdc_ncm_class->hport, setup, g_cdc_ncm_buf);
if (ret < 0) {
return ret;
}
memcpy((uint8_t *)param, g_cdc_ncm_buf, ret - 8);
return 0;
}
static void print_ntb_parameters(struct cdc_ncm_ntb_parameters *param)
{
USB_LOG_RAW("CDC NCM ntb parameters:\r\n");
USB_LOG_RAW("wLength: 0x%02x \r\n", param->wLength);
USB_LOG_RAW("bmNtbFormatsSupported: %s \r\n", param->bmNtbFormatsSupported ? "NTB16" : "NTB32");
USB_LOG_RAW("dwNtbInMaxSize: 0x%04x \r\n", param->dwNtbInMaxSize);
USB_LOG_RAW("wNdbInDivisor: 0x%02x \r\n", param->wNdbInDivisor);
USB_LOG_RAW("wNdbInPayloadRemainder: 0x%02x \r\n", param->wNdbInPayloadRemainder);
USB_LOG_RAW("wNdbInAlignment: 0x%02x \r\n", param->wNdbInAlignment);
USB_LOG_RAW("dwNtbOutMaxSize: 0x%04x \r\n", param->dwNtbOutMaxSize);
USB_LOG_RAW("wNdbOutDivisor: 0x%02x \r\n", param->wNdbOutDivisor);
USB_LOG_RAW("wNdbOutPayloadRemainder: 0x%02x \r\n", param->wNdbOutPayloadRemainder);
USB_LOG_RAW("wNdbOutAlignment: 0x%02x \r\n", param->wNdbOutAlignment);
USB_LOG_RAW("wNtbOutMaxDatagrams: 0x%02x \r\n", param->wNtbOutMaxDatagrams);
}
int usbh_cdc_ncm_get_connect_status(struct usbh_cdc_ncm *cdc_ncm_class)
{
int ret;
usbh_int_urb_fill(&cdc_ncm_class->intin_urb, cdc_ncm_class->hport, cdc_ncm_class->intin, g_cdc_ncm_inttx_buffer, 16, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&cdc_ncm_class->intin_urb);
if (ret < 0) {
return ret;
}
if (g_cdc_ncm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION) {
if (g_cdc_ncm_inttx_buffer[2] == CDC_ECM_NET_CONNECTED) {
cdc_ncm_class->connect_status = true;
} else {
cdc_ncm_class->connect_status = false;
}
} else if (g_cdc_ncm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE) {
memcpy(cdc_ncm_class->speed, &g_cdc_ncm_inttx_buffer[8], 8);
}
return 0;
}
static int usbh_cdc_ncm_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret;
uint8_t altsetting = 0;
char mac_buffer[12];
uint8_t *p;
uint8_t cur_iface = 0xff;
uint8_t mac_str_idx = 0xff;
struct usbh_cdc_ncm *cdc_ncm_class = &g_cdc_ncm_class;
memset(cdc_ncm_class, 0, sizeof(struct usbh_cdc_ncm));
cdc_ncm_class->hport = hport;
cdc_ncm_class->ctrl_intf = intf;
cdc_ncm_class->data_intf = intf + 1;
hport->config.intf[intf].priv = cdc_ncm_class;
hport->config.intf[intf + 1].priv = NULL;
p = hport->raw_config_desc;
while (p[DESC_bLength]) {
switch (p[DESC_bDescriptorType]) {
case USB_DESCRIPTOR_TYPE_INTERFACE:
cur_iface = p[INTF_DESC_bInterfaceNumber];
//cur_alt_setting = p[INTF_DESC_bAlternateSetting];
break;
case CDC_CS_INTERFACE:
if ((cur_iface == cdc_ncm_class->ctrl_intf) && p[DESC_bDescriptorSubType] == CDC_FUNC_DESC_ETHERNET_NETWORKING) {
struct cdc_eth_descriptor *desc = (struct cdc_eth_descriptor *)p;
mac_str_idx = desc->iMACAddress;
cdc_ncm_class->max_segment_size = desc->wMaxSegmentSize;
goto get_mac;
}
break;
default:
break;
}
/* skip to next descriptor */
p += p[DESC_bLength];
}
get_mac:
if (mac_str_idx == 0xff) {
USB_LOG_ERR("Do not find cdc ncm mac string\r\n");
return -1;
}
memset(mac_buffer, 0, 12);
ret = usbh_get_string_desc(cdc_ncm_class->hport, mac_str_idx, (uint8_t *)mac_buffer);
if (ret < 0) {
return ret;
}
for (int i = 0, j = 0; i < 12; i += 2, j++) {
char byte_str[3];
byte_str[0] = mac_buffer[i];
byte_str[1] = mac_buffer[i + 1];
byte_str[2] = '\0';
uint32_t byte = strtoul(byte_str, NULL, 16);
cdc_ncm_class->mac[j] = (unsigned char)byte;
}
USB_LOG_INFO("CDC NCM MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
cdc_ncm_class->mac[0],
cdc_ncm_class->mac[1],
cdc_ncm_class->mac[2],
cdc_ncm_class->mac[3],
cdc_ncm_class->mac[4],
cdc_ncm_class->mac[5]);
if (cdc_ncm_class->max_segment_size > CONFIG_USBHOST_CDC_NCM_ETH_MAX_SEGSZE) {
USB_LOG_ERR("CDC NCM Max Segment Size is overflow, default is %u, but now %u\r\n", CONFIG_USBHOST_CDC_NCM_ETH_MAX_SEGSZE, cdc_ncm_class->max_segment_size);
} else {
USB_LOG_INFO("CDC NCM Max Segment Size:%u\r\n", cdc_ncm_class->max_segment_size);
}
usbh_cdc_ncm_get_ntb_parameters(cdc_ncm_class, &cdc_ncm_class->ntb_param);
print_ntb_parameters(&cdc_ncm_class->ntb_param);
/* enable int ep */
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
USBH_EP_INIT(cdc_ncm_class->intin, ep_desc);
if (hport->config.intf[intf + 1].altsetting_num > 1) {
altsetting = hport->config.intf[intf + 1].altsetting_num - 1;
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[altsetting].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf + 1].altsetting[altsetting].ep[i].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(cdc_ncm_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(cdc_ncm_class->bulkout, ep_desc);
}
}
USB_LOG_INFO("Select cdc ncm altsetting: %d\r\n", altsetting);
usbh_set_interface(cdc_ncm_class->hport, cdc_ncm_class->data_intf, altsetting);
} else {
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(cdc_ncm_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(cdc_ncm_class->bulkout, ep_desc);
}
}
}
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
USB_LOG_INFO("Register CDC NCM Class:%s\r\n", hport->config.intf[intf].devname);
usbh_cdc_ncm_run(cdc_ncm_class);
return ret;
}
static int usbh_cdc_ncm_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_cdc_ncm *cdc_ncm_class = (struct usbh_cdc_ncm *)hport->config.intf[intf].priv;
if (cdc_ncm_class) {
if (cdc_ncm_class->bulkin) {
usbh_kill_urb(&cdc_ncm_class->bulkin_urb);
}
if (cdc_ncm_class->bulkout) {
usbh_kill_urb(&cdc_ncm_class->bulkout_urb);
}
if (cdc_ncm_class->intin) {
usbh_kill_urb(&cdc_ncm_class->intin_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister CDC NCM Class:%s\r\n", hport->config.intf[intf].devname);
usbh_cdc_ncm_stop(cdc_ncm_class);
}
memset(cdc_ncm_class, 0, sizeof(struct usbh_cdc_ncm));
}
return ret;
}
void usbh_cdc_ncm_rx_thread(void *argument)
{
uint32_t g_cdc_ncm_rx_length;
int ret;
#if CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE <= (16 * 1024)
uint32_t transfer_size = CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE;
#else
uint32_t transfer_size = (16 * 1024);
#endif
(void)argument;
USB_LOG_INFO("Create cdc ncm rx thread\r\n");
// clang-format off
find_class:
// clang-format on
g_cdc_ncm_class.connect_status = false;
if (usbh_find_class_instance("/dev/cdc_ncm") == NULL) {
goto delete;
}
while (g_cdc_ncm_class.connect_status == false) {
ret = usbh_cdc_ncm_get_connect_status(&g_cdc_ncm_class);
if (ret < 0) {
usb_osal_msleep(100);
goto find_class;
}
}
g_cdc_ncm_rx_length = 0;
while (1) {
usbh_bulk_urb_fill(&g_cdc_ncm_class.bulkin_urb, g_cdc_ncm_class.hport, g_cdc_ncm_class.bulkin, &g_cdc_ncm_rx_buffer[g_cdc_ncm_rx_length], transfer_size, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_cdc_ncm_class.bulkin_urb);
if (ret < 0) {
goto find_class;
}
g_cdc_ncm_rx_length += g_cdc_ncm_class.bulkin_urb.actual_length;
/* A transfer is complete because last packet is a short packet.
* Short packet is not zero, match g_cdc_ncm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ncm_class.bulkin->wMaxPacketSize).
* Short packet is zero, check if g_cdc_ncm_class.bulkin_urb.actual_length < transfer_size, for example transfer is complete with size is 1024 < 2048.
*/
if ((g_cdc_ncm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ncm_class.bulkin->wMaxPacketSize)) ||
(g_cdc_ncm_class.bulkin_urb.actual_length < transfer_size)) {
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ncm_rx_length);
struct cdc_ncm_nth16 *nth16 = (struct cdc_ncm_nth16 *)&g_cdc_ncm_rx_buffer[0];
if ((nth16->dwSignature != CDC_NCM_NTH16_SIGNATURE) ||
(nth16->wHeaderLength != 12) ||
(nth16->wBlockLength != g_cdc_ncm_rx_length)) {
USB_LOG_ERR("invalid rx nth16\r\n");
g_cdc_ncm_rx_length = 0;
continue;
}
struct cdc_ncm_ndp16 *ndp16 = (struct cdc_ncm_ndp16 *)&g_cdc_ncm_rx_buffer[nth16->wNdpIndex];
if ((ndp16->dwSignature != CDC_NCM_NDP16_SIGNATURE_NCM0) && (ndp16->dwSignature != CDC_NCM_NDP16_SIGNATURE_NCM1)) {
USB_LOG_ERR("invalid rx ndp16\r\n");
g_cdc_ncm_rx_length = 0;
continue;
}
uint16_t datagram_num = (ndp16->wLength - 8) / 4;
USB_LOG_DBG("datagram num:%02x\r\n", datagram_num);
for (uint16_t i = 0; i < datagram_num; i++) {
struct cdc_ncm_ndp16_datagram *ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_rx_buffer[nth16->wNdpIndex + 8 + 4 * i];
if (ndp16_datagram->wDatagramIndex && ndp16_datagram->wDatagramLength) {
USB_LOG_DBG("ndp16_datagram index:%02x, length:%02x\r\n", ndp16_datagram->wDatagramIndex, ndp16_datagram->wDatagramLength);
uint8_t *buf = (uint8_t *)&g_cdc_ncm_rx_buffer[ndp16_datagram->wDatagramIndex];
usbh_cdc_ncm_eth_input(buf, ndp16_datagram->wDatagramLength);
}
}
g_cdc_ncm_rx_length = 0;
} else {
#if CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE <= (16 * 1024)
if (g_cdc_ncm_rx_length == CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE) {
#else
if ((g_cdc_ncm_rx_length + (16 * 1024)) > CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE) {
#endif
USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE\r\n");
while (1) {
}
}
}
}
// clang-format off
delete:
USB_LOG_INFO("Delete cdc ncm rx thread\r\n");
usb_osal_thread_delete(NULL);
// clang-format on
}
uint8_t *usbh_cdc_ncm_get_eth_txbuf(void)
{
return &g_cdc_ncm_tx_buffer[16];
}
int usbh_cdc_ncm_eth_output(uint32_t buflen)
{
struct cdc_ncm_ndp16_datagram *ndp16_datagram;
if (g_cdc_ncm_class.connect_status == false) {
return -USB_ERR_NOTCONN;
}
struct cdc_ncm_nth16 *nth16 = (struct cdc_ncm_nth16 *)&g_cdc_ncm_tx_buffer[0];
nth16->dwSignature = CDC_NCM_NTH16_SIGNATURE;
nth16->wHeaderLength = 12;
nth16->wSequence = g_cdc_ncm_class.bulkout_sequence++;
nth16->wBlockLength = 16 + 16 + USB_ALIGN_UP(buflen, 4);
nth16->wNdpIndex = 16 + USB_ALIGN_UP(buflen, 4);
struct cdc_ncm_ndp16 *ndp16 = (struct cdc_ncm_ndp16 *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex];
ndp16->dwSignature = CDC_NCM_NDP16_SIGNATURE_NCM0;
ndp16->wLength = 16;
ndp16->wNextNdpIndex = 0;
ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex + 8 + 4 * 0];
ndp16_datagram->wDatagramIndex = 16;
ndp16_datagram->wDatagramLength = buflen;
ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex + 8 + 4 * 1];
ndp16_datagram->wDatagramIndex = 0;
ndp16_datagram->wDatagramLength = 0;
USB_LOG_DBG("txlen:%d\r\n", nth16->wBlockLength);
usbh_bulk_urb_fill(&g_cdc_ncm_class.bulkout_urb, g_cdc_ncm_class.hport, g_cdc_ncm_class.bulkout, g_cdc_ncm_tx_buffer, nth16->wBlockLength, USB_OSAL_WAITING_FOREVER, NULL, NULL);
return usbh_submit_urb(&g_cdc_ncm_class.bulkout_urb);
}
__WEAK void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class)
{
(void)cdc_ncm_class;
}
__WEAK void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class)
{
(void)cdc_ncm_class;
}
const struct usbh_class_driver cdc_ncm_class_driver = {
.driver_name = "cdc_ncm",
.connect = usbh_cdc_ncm_connect,
.disconnect = usbh_cdc_ncm_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info cdc_ncm_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_CDC,
.subclass = CDC_NETWORK_CONTROL_MODEL,
.protocol = CDC_COMMON_PROTOCOL_NONE,
.id_table = NULL,
.class_driver = &cdc_ncm_class_driver
};

View File

@ -1,54 +0,0 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_CDC_NCM_H
#define USBH_CDC_NCM_H
#include "usb_cdc.h"
struct usbh_cdc_ncm {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
struct usb_endpoint_descriptor *intin; /* Interrupt IN endpoint */
struct usbh_urb bulkout_urb; /* Bulk out endpoint */
struct usbh_urb bulkin_urb; /* Bulk IN endpoint */
struct usbh_urb intin_urb; /* Interrupt IN endpoint */
uint8_t ctrl_intf; /* Control interface number */
uint8_t data_intf; /* Data interface number */
uint8_t minor;
struct cdc_ncm_ntb_parameters ntb_param;
uint16_t bulkin_sequence;
uint16_t bulkout_sequence;
uint8_t mac[6];
bool connect_status;
uint16_t max_segment_size;
uint32_t speed[2];
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
int usbh_cdc_ncm_get_connect_status(struct usbh_cdc_ncm *cdc_ncm_class);
void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class);
void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class);
uint8_t *usbh_cdc_ncm_get_eth_txbuf(void);
int usbh_cdc_ncm_eth_output(uint32_t buflen);
void usbh_cdc_ncm_eth_input(uint8_t *buf, uint32_t buflen);
void usbh_cdc_ncm_rx_thread(void *argument);
#ifdef __cplusplus
}
#endif
#endif /* USBH_CDC_NCM_H */

View File

@ -1,137 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USB_DFU_H
#define USB_DFU_H
/**\addtogroup USB_MODULE_DFU USB DFU class
* \brief This module contains USB Device Firmware Upgrade class definitions.
* \details This module based on
* + [USB Device Firmware Upgrade Specification, Revision 1.1]
* (https://www.usb.org/sites/default/files/DFU_1.1.pdf)
* @{ */
/** DFU Specification release */
#define DFU_VERSION 0x0110
/** DFU Class Subclass */
#define DFU_SUBCLASS_DFU 0x01
/** DFU Class runtime Protocol */
#define DFU_PROTOCOL_RUNTIME 0x01
/** DFU Class DFU mode Protocol */
#define DFU_PROTOCOL_MODE 0x02
/**
* @brief DFU Class Specific Requests
*/
#define DFU_REQUEST_DETACH 0x00
#define DFU_REQUEST_DNLOAD 0x01
#define DFU_REQUEST_UPLOAD 0x02
#define DFU_REQUEST_GETSTATUS 0x03
#define DFU_REQUEST_CLRSTATUS 0x04
#define DFU_REQUEST_GETSTATE 0x05
#define DFU_REQUEST_ABORT 0x06
/** DFU FUNCTIONAL descriptor type */
#define DFU_FUNC_DESC 0x21
/** DFU attributes DFU Functional Descriptor */
#define DFU_ATTR_WILL_DETACH 0x08
#define DFU_ATTR_MANIFESTATION_TOLERANT 0x04
#define DFU_ATTR_CAN_UPLOAD 0x02
#define DFU_ATTR_CAN_DNLOAD 0x01
/** bStatus values for the DFU_GETSTATUS response */
#define DFU_STATUS_OK 0x00U
#define DFU_STATUS_ERR_TARGET 0x01U
#define DFU_STATUS_ERR_FILE 0x02U
#define DFU_STATUS_ERR_WRITE 0x03U
#define DFU_STATUS_ERR_ERASE 0x04U
#define DFU_STATUS_ERR_CHECK_ERASED 0x05U
#define DFU_STATUS_ERR_PROG 0x06U
#define DFU_STATUS_ERR_VERIFY 0x07U
#define DFU_STATUS_ERR_ADDRESS 0x08U
#define DFU_STATUS_ERR_NOTDONE 0x09U
#define DFU_STATUS_ERR_FIRMWARE 0x0AU
#define DFU_STATUS_ERR_VENDOR 0x0BU
#define DFU_STATUS_ERR_USB 0x0CU
#define DFU_STATUS_ERR_POR 0x0DU
#define DFU_STATUS_ERR_UNKNOWN 0x0EU
#define DFU_STATUS_ERR_STALLEDPKT 0x0FU
/** bState values for the DFU_GETSTATUS response */
#define DFU_STATE_APP_IDLE 0U
#define DFU_STATE_APP_DETACH 1U
#define DFU_STATE_DFU_IDLE 2U
#define DFU_STATE_DFU_DNLOAD_SYNC 3U
#define DFU_STATE_DFU_DNLOAD_BUSY 4U
#define DFU_STATE_DFU_DNLOAD_IDLE 5U
#define DFU_STATE_DFU_MANIFEST_SYNC 6U
#define DFU_STATE_DFU_MANIFEST 7U
#define DFU_STATE_DFU_MANIFEST_WAIT_RESET 8U
#define DFU_STATE_DFU_UPLOAD_IDLE 9U
#define DFU_STATE_DFU_ERROR 10U
/** DFU Manifestation State */
#define DFU_MANIFEST_COMPLETE 0U
#define DFU_MANIFEST_IN_PROGRESS 1U
/** Special Commands with Download Request */
#define DFU_CMD_GETCOMMANDS 0U
#define DFU_CMD_SETADDRESSPOINTER 0x21U
#define DFU_CMD_ERASE 0x41U
#define DFU_MEDIA_ERASE 0x00U
#define DFU_MEDIA_PROGRAM 0x01U
/** Other defines */
/* Bit Detach capable = bit 3 in bmAttributes field */
#define DFU_DETACH_MASK (1U << 3)
#define DFU_MANIFEST_MASK (1U << 2)
/** Run-Time Functional Descriptor */
struct dfu_runtime_descriptor {
uint8_t bLength; /**<\brief Descriptor length in bytes.*/
uint8_t bDescriptorType; /**<\brief DFU functional descriptor type.*/
uint8_t bmAttributes; /**<\brief USB DFU capabilities \ref USB_DFU_CAPAB*/
uint16_t wDetachTimeout; /**<\brief USB DFU detach timeout in ms.*/
uint16_t wTransferSize; /**<\brief USB DFU maximum transfer block size in bytes.*/
uint16_t bcdDFUVersion; /**<\brief USB DFU version \ref VERSION_BCD utility macro.*/
} __PACKED;
/**\brief Payload packet to response in DFU_GETSTATUS request */
struct dfu_info {
uint8_t bStatus; /**<\brief An indication of the status resulting from the
* execution of the most recent request.*/
uint8_t bPollTimeout; /**<\brief Minimum time (LSB) in ms, that the host should wait
* before sending a subsequent DFU_GETSTATUS request.*/
uint16_t wPollTimeout; /**<\brief Minimum time (MSB) in ms, that the host should wait
* before sending a subsequent DFU_GETSTATUS request.*/
uint8_t bState; /**<\brief An indication of the state that the device is going
* to enter immediately following transmission of this response.*/
uint8_t iString; /**<\brief Index of the status string descriptor.*/
};
// clang-format off
#define DFU_DESCRIPTOR_INIT() \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
0x00, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x00, /* bNumEndpoints Default Control Pipe only */ \
USB_DEVICE_CLASS_APP_SPECIFIC, /* bInterfaceClass */ \
0x01, /* bInterfaceSubClass Device Firmware Upgrade */ \
0x02, /* bInterfaceProtocol DFU mode */ \
0x04, /* iInterface */ /*!< Device Firmware Update Functional Descriptor */ \
0x09, /* bLength */ \
0x21, /* DFU Functional Descriptor */ \
0x0B, /* bmAttributes */ \
WBVAL(0x00ff), /* wDetachTimeOut */ \
WBVAL(USBD_DFU_XFER_SIZE), /* wTransferSize */ \
WBVAL(0x011a) /* bcdDFUVersion */
// clang-format on
#endif /* USB_DFU_H */

View File

@ -1,505 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_dfu.h"
/** Modify the following three parameters according to different platforms */
#ifndef USBD_DFU_XFER_SIZE
#define USBD_DFU_XFER_SIZE 1024
#endif
#ifndef USBD_DFU_APP_DEFAULT_ADD
#define USBD_DFU_APP_DEFAULT_ADD 0x8004000
#endif
#ifndef FLASH_PROGRAM_TIME
#define FLASH_PROGRAM_TIME 50
#endif
#ifndef FLASH_ERASE_TIME
#define FLASH_ERASE_TIME 50
#endif
struct usbd_dfu_priv {
struct dfu_info info;
union {
uint32_t d32[USBD_DFU_XFER_SIZE / 4U];
uint8_t d8[USBD_DFU_XFER_SIZE];
} buffer;
uint32_t wblock_num;
uint32_t wlength;
uint32_t data_ptr;
uint32_t alt_setting;
uint8_t dev_status[6];
uint8_t ReservedForAlign[2];
uint8_t dev_state;
uint8_t manif_state;
uint8_t firmwar_flag;
} g_usbd_dfu;
static void dfu_reset(void)
{
memset(&g_usbd_dfu, 0, sizeof(g_usbd_dfu));
g_usbd_dfu.alt_setting = 0U;
g_usbd_dfu.data_ptr = USBD_DFU_APP_DEFAULT_ADD;
g_usbd_dfu.wblock_num = 0U;
g_usbd_dfu.wlength = 0U;
g_usbd_dfu.manif_state = DFU_MANIFEST_COMPLETE;
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[5] = 0U;
}
static uint16_t dfu_getstatus(uint32_t add, uint8_t cmd, uint8_t *buffer)
{
switch (cmd) {
case DFU_MEDIA_PROGRAM:
buffer[1] = (uint8_t)FLASH_PROGRAM_TIME;
buffer[2] = (uint8_t)(FLASH_PROGRAM_TIME << 8);
buffer[3] = 0;
break;
case DFU_MEDIA_ERASE:
buffer[1] = (uint8_t)FLASH_ERASE_TIME;
buffer[2] = (uint8_t)(FLASH_ERASE_TIME << 8);
buffer[3] = 0;
default:
break;
}
return (0);
}
static void dfu_request_detach(void)
{
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
/* Update the state machine */
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U; /*bwPollTimeout=0ms*/
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
g_usbd_dfu.dev_status[5] = 0U; /*iString*/
g_usbd_dfu.wblock_num = 0U;
g_usbd_dfu.wlength = 0U;
}
}
static void dfu_request_upload(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
struct usb_setup_packet *req = setup;
uint32_t addr;
uint8_t *phaddr;
/* Data setup request */
if (req->wLength > 0U) {
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
/* Update the global length and block number */
g_usbd_dfu.wblock_num = req->wValue;
g_usbd_dfu.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
/* DFU Get Command */
if (g_usbd_dfu.wblock_num == 0U) {
/* Update the state machine */
g_usbd_dfu.dev_state = (g_usbd_dfu.wlength > 3U) ? DFU_STATE_DFU_IDLE : DFU_STATE_DFU_UPLOAD_IDLE;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
/* Store the values of all supported commands */
g_usbd_dfu.buffer.d8[0] = DFU_CMD_GETCOMMANDS;
g_usbd_dfu.buffer.d8[1] = DFU_CMD_SETADDRESSPOINTER;
g_usbd_dfu.buffer.d8[2] = DFU_CMD_ERASE;
/* Send the status data over EP0 */
memcpy(*data, g_usbd_dfu.buffer.d8, 3);
*len = 3;
} else if (g_usbd_dfu.wblock_num > 1U) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_UPLOAD_IDLE;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
addr = ((g_usbd_dfu.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + g_usbd_dfu.data_ptr;
/* Return the physical address where data are stored */
phaddr = dfu_read_flash((uint8_t *)addr, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
/* Send the status data over EP0 */
memcpy(*data, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
*len = g_usbd_dfu.wlength;
} else /* unsupported g_usbd_dfu.wblock_num */
{
g_usbd_dfu.dev_state = DFU_STATUS_ERR_STALLEDPKT;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
/* Call the error management function (command will be NAKed */
USB_LOG_ERR("Dfu_request_upload unsupported g_usbd_dfu.wblock_num\r\n");
}
}
/* Unsupported state */
else {
g_usbd_dfu.wlength = 0U;
g_usbd_dfu.wblock_num = 0U;
/* Call the error management function (command will be NAKed */
USB_LOG_ERR("Dfu_request_upload unsupported state\r\n");
}
}
/* No Data setup request */
else {
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
}
}
static void dfu_request_dnload(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
/* Data setup request */
struct usb_setup_packet *req = setup;
if (req->wLength > 0U) {
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE)) {
/* Update the global length and block number */
g_usbd_dfu.wblock_num = req->wValue;
g_usbd_dfu.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
/* Update the state machine */
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
/*!< Data has received complete */
memcpy((uint8_t *)g_usbd_dfu.buffer.d8, (uint8_t *)*data, g_usbd_dfu.wlength);
/*!< Set flag = 1 Write the firmware to the flash in the next dfu_request_getstatus */
g_usbd_dfu.firmwar_flag = 1;
}
/* Unsupported state */
else {
USB_LOG_ERR("Dfu_request_dnload unsupported state\r\n");
}
}
/* 0 Data DNLOAD request */
else {
/* End of DNLOAD operation*/
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE)) {
g_usbd_dfu.manif_state = DFU_MANIFEST_IN_PROGRESS;
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
} else {
/* Call the error management function (command will be NAKed */
USB_LOG_ERR("Dfu_request_dnload End of DNLOAD operation but dev_state %02x \r\n", g_usbd_dfu.dev_state);
}
}
}
static int8_t dfu_getstatus_special_handler(void)
{
uint32_t addr;
if (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_BUSY) {
/* Decode the Special Command */
if (g_usbd_dfu.wblock_num == 0U) {
if (g_usbd_dfu.wlength == 1U) {
if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_GETCOMMANDS) {
/* Nothing to do */
}
} else if (g_usbd_dfu.wlength == 5U) {
if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_SETADDRESSPOINTER) {
g_usbd_dfu.data_ptr = g_usbd_dfu.buffer.d8[1];
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[2] << 8;
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[3] << 16;
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[4] << 24;
} else if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_ERASE) {
g_usbd_dfu.data_ptr = g_usbd_dfu.buffer.d8[1];
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[2] << 8;
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[3] << 16;
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[4] << 24;
USB_LOG_DBG("Erase start add %08x \r\n", g_usbd_dfu.data_ptr);
/*!< Erase */
dfu_erase_flash(g_usbd_dfu.data_ptr);
} else {
return -1;
}
} else {
/* Reset the global length and block number */
g_usbd_dfu.wlength = 0U;
g_usbd_dfu.wblock_num = 0U;
/* Call the error management function (command will be NAKed) */
USB_LOG_ERR("Reset the global length and block number\r\n");
}
}
/* Regular Download Command */
else {
if (g_usbd_dfu.wblock_num > 1U) {
/* Decode the required address */
addr = ((g_usbd_dfu.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + g_usbd_dfu.data_ptr;
/* Perform the write operation */
/* Write flash */
USB_LOG_DBG("Write start add %08x length %d\r\n", addr, g_usbd_dfu.wlength);
dfu_write_flash(g_usbd_dfu.buffer.d8, (uint8_t *)addr, g_usbd_dfu.wlength);
}
}
/* Reset the global length and block number */
g_usbd_dfu.wlength = 0U;
g_usbd_dfu.wblock_num = 0U;
/* Update the state machine */
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
}
return 0;
}
static void dfu_request_getstatus(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
/*!< Determine whether to leave DFU mode */
if (g_usbd_dfu.manif_state == DFU_MANIFEST_IN_PROGRESS &&
g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC &&
g_usbd_dfu.dev_status[1] == 0U &&
g_usbd_dfu.dev_status[2] == 0U &&
g_usbd_dfu.dev_status[3] == 0U &&
g_usbd_dfu.dev_status[4] == g_usbd_dfu.dev_state) {
g_usbd_dfu.manif_state = DFU_MANIFEST_COMPLETE;
if ((0x0B & DFU_MANIFEST_MASK) != 0U) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
return;
} else {
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_WAIT_RESET;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
/* Generate system reset to allow jumping to the user code */
dfu_leave();
}
}
switch (g_usbd_dfu.dev_state) {
case DFU_STATE_DFU_DNLOAD_SYNC:
if (g_usbd_dfu.wlength != 0U) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_BUSY;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
if ((g_usbd_dfu.wblock_num == 0U) && (g_usbd_dfu.buffer.d8[0] == DFU_CMD_ERASE)) {
dfu_getstatus(g_usbd_dfu.data_ptr, DFU_MEDIA_ERASE, g_usbd_dfu.dev_status);
} else {
dfu_getstatus(g_usbd_dfu.data_ptr, DFU_MEDIA_PROGRAM, g_usbd_dfu.dev_status);
}
} else /* (g_usbd_dfu.wlength==0)*/
{
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_IDLE;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
}
break;
case DFU_STATE_DFU_MANIFEST_SYNC:
if (g_usbd_dfu.manif_state == DFU_MANIFEST_IN_PROGRESS) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST;
g_usbd_dfu.dev_status[1] = 1U; /*bwPollTimeout = 1ms*/
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
} else {
if ((g_usbd_dfu.manif_state == DFU_MANIFEST_COMPLETE) &&
((0x0B & DFU_MANIFEST_MASK) != 0U)) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
}
}
break;
default:
break;
}
/* Send the status data over EP0 */
memcpy(*data, g_usbd_dfu.dev_status, 6);
*len = 6;
if (g_usbd_dfu.firmwar_flag == 1) {
if (dfu_getstatus_special_handler() != 0) {
USB_LOG_ERR("dfu_getstatus_special_handler error \r\n");
}
g_usbd_dfu.firmwar_flag = 0;
}
}
static void dfu_request_clrstatus(void)
{
if (g_usbd_dfu.dev_state == DFU_STATE_DFU_ERROR) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK; /* bStatus */
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state; /* bState */
g_usbd_dfu.dev_status[5] = 0U; /* iString */
} else {
/* State Error */
g_usbd_dfu.dev_state = DFU_STATE_DFU_ERROR;
g_usbd_dfu.dev_status[0] = DFU_STATUS_ERR_UNKNOWN; /* bStatus */
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state; /* bState */
g_usbd_dfu.dev_status[5] = 0U; /* iString */
}
}
static void dfu_request_getstate(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
/* Return the current state of the DFU interface */
(*data)[0] = g_usbd_dfu.dev_state;
*len = 1;
}
void dfu_request_abort(void)
{
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
g_usbd_dfu.dev_status[5] = 0U; /* iString */
g_usbd_dfu.wblock_num = 0U;
g_usbd_dfu.wlength = 0U;
}
}
static int dfu_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("DFU Class request: "
"bRequest 0x%02x\r\n",
setup->bRequest);
switch (setup->bRequest) {
case DFU_REQUEST_DETACH:
dfu_request_detach();
break;
case DFU_REQUEST_DNLOAD:
dfu_request_dnload(setup, data, len);
break;
case DFU_REQUEST_UPLOAD:
dfu_request_upload(setup, data, len);
break;
case DFU_REQUEST_GETSTATUS:
dfu_request_getstatus(setup, data, len);
break;
case DFU_REQUEST_CLRSTATUS:
dfu_request_clrstatus();
break;
case DFU_REQUEST_GETSTATE:
dfu_request_getstate(setup, data, len);
break;
case DFU_REQUEST_ABORT:
dfu_request_abort();
break;
default:
USB_LOG_WRN("Unhandled DFU Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
return 0;
}
static void dfu_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
dfu_reset();
break;
default:
break;
}
}
struct usbd_interface *usbd_dfu_init_intf(struct usbd_interface *intf)
{
intf->class_interface_handler = dfu_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = dfu_notify_handler;
return intf;
}
__WEAK uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len)
{
return dest;
}
__WEAK uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len)
{
return 0;
}
__WEAK uint16_t dfu_erase_flash(uint32_t add)
{
return 0;
}
__WEAK void dfu_leave(void)
{
}

View File

@ -1,27 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_DFU_H
#define USBD_DFU_H
#include "usb_dfu.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Init dfu interface driver */
struct usbd_interface *usbd_dfu_init_intf(struct usbd_interface *intf);
/* Interface functions that need to be implemented by the user */
uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len);
uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len);
uint16_t dfu_erase_flash(uint32_t add);
void dfu_leave(void);
#ifdef __cplusplus
}
#endif
#endif /* USBD_DFU_H */

View File

@ -1,321 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_hid.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_hid"
#include "usb_log.h"
#define DEV_FORMAT "/dev/input%d"
/* general descriptor field offsets */
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
/* interface descriptor field offsets */
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[CONFIG_USBHOST_MAX_HID_CLASS][USB_ALIGN_UP(256, CONFIG_USB_ALIGN_SIZE)];
static struct usbh_hid g_hid_class[CONFIG_USBHOST_MAX_HID_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_hid *usbh_hid_class_alloc(void)
{
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_HID_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_hid_class[devno], 0, sizeof(struct usbh_hid));
g_hid_class[devno].minor = devno;
return &g_hid_class[devno];
}
}
return NULL;
}
static void usbh_hid_class_free(struct usbh_hid *hid_class)
{
int devno = hid_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(hid_class, 0, sizeof(struct usbh_hid));
}
static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer)
{
struct usb_setup_packet *setup;
int ret;
if (!hid_class || !hid_class->hport) {
return -USB_ERR_INVAL;
}
setup = hid_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = HID_DESCRIPTOR_TYPE_HID_REPORT << 8;
setup->wIndex = hid_class->intf;
setup->wLength = hid_class->report_size;
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
if (ret < 0) {
return ret;
}
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
return ret;
}
int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t duration)
{
struct usb_setup_packet *setup;
if (!hid_class || !hid_class->hport) {
return -USB_ERR_INVAL;
}
setup = hid_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = HID_REQUEST_SET_IDLE;
setup->wValue = (duration << 8) | report_id;
setup->wIndex = hid_class->intf;
setup->wLength = 0;
return usbh_control_transfer(hid_class->hport, setup, NULL);
}
int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer)
{
struct usb_setup_packet *setup;
int ret;
if (!hid_class || !hid_class->hport) {
return -USB_ERR_INVAL;
}
setup = hid_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = HID_REQUEST_GET_IDLE;
setup->wValue = 0;
setup->wIndex = hid_class->intf;
setup->wLength = 1;
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
if (ret < 0) {
return ret;
}
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
return ret;
}
int usbh_hid_set_protocol(struct usbh_hid *hid_class, uint8_t protocol)
{
struct usb_setup_packet *setup;
if (!hid_class || !hid_class->hport) {
return -USB_ERR_INVAL;
}
setup = hid_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = HID_REQUEST_SET_PROTOCOL;
setup->wValue = protocol;
setup->wIndex = 0;
setup->wLength = 0;
return usbh_control_transfer(hid_class->hport, setup, NULL);
}
int usbh_hid_set_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen)
{
struct usb_setup_packet *setup;
if (!hid_class || !hid_class->hport) {
return -USB_ERR_INVAL;
}
setup = hid_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = HID_REQUEST_SET_REPORT;
setup->wValue = (uint16_t)(((uint32_t)report_type << 8U) | (uint32_t)report_id);
setup->wIndex = 0;
setup->wLength = buflen;
return usbh_control_transfer(hid_class->hport, setup, buffer);
}
int usbh_hid_get_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen)
{
struct usb_setup_packet *setup;
int ret;
if (!hid_class || !hid_class->hport) {
return -USB_ERR_INVAL;
}
setup = hid_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = HID_REQUEST_GET_REPORT;
setup->wValue = (uint16_t)(((uint32_t)report_type << 8U) | (uint32_t)report_id);
setup->wIndex = 0;
setup->wLength = buflen;
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
if (ret < 0) {
return ret;
}
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
return ret;
}
int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret;
uint8_t cur_iface = 0xff;
uint8_t *p;
bool found = false;
struct usbh_hid *hid_class = usbh_hid_class_alloc();
if (hid_class == NULL) {
USB_LOG_ERR("Fail to alloc hid_class\r\n");
return -USB_ERR_NOMEM;
}
hid_class->hport = hport;
hid_class->intf = intf;
hport->config.intf[intf].priv = hid_class;
p = hport->raw_config_desc;
while (p[DESC_bLength]) {
switch (p[DESC_bDescriptorType]) {
case USB_DESCRIPTOR_TYPE_INTERFACE:
cur_iface = p[INTF_DESC_bInterfaceNumber];
if (cur_iface == intf) {
hid_class->protocol = p[7];
struct usb_hid_descriptor *desc = (struct usb_hid_descriptor *)(p + 9);
if (desc->bDescriptorType != HID_DESCRIPTOR_TYPE_HID) {
USB_LOG_ERR("HID descriptor not found\r\n");
return -USB_ERR_INVAL;
}
if (desc->subdesc[0].bDescriptorType != HID_DESCRIPTOR_TYPE_HID_REPORT) {
USB_LOG_ERR("HID report descriptor not found\r\n");
return -USB_ERR_INVAL;
}
hid_class->report_size = desc->subdesc[0].wDescriptorLength;
if (hid_class->report_size > sizeof(g_hid_buf[hid_class->minor])) {
USB_LOG_ERR("HID report descriptor too large\r\n");
return -USB_ERR_INVAL;
}
found = true;
goto found;
}
break;
default:
break;
}
/* skip to next descriptor */
p += p[DESC_bLength];
}
if (found == false) {
USB_LOG_ERR("HID interface not found\r\n");
return -USB_ERR_INVAL;
}
found:
// /* 0x0 = boot protocol, 0x1 = report protocol */
// ret = usbh_hid_set_protocol(hid_class, 0x1);
// if (ret < 0) {
// return ret;
// }
ret = usbh_hid_set_idle(hid_class, 0, 0);
if (ret < 0) {
USB_LOG_WRN("Do not support set idle\r\n");
}
ret = usbh_hid_get_report_descriptor(hid_class, hid_class->report_desc);
if (ret < 0) {
return ret;
}
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(hid_class->intin, ep_desc);
} else {
USBH_EP_INIT(hid_class->intout, ep_desc);
}
}
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hid_class->minor);
USB_LOG_INFO("Register HID Class:%s\r\n", hport->config.intf[intf].devname);
usbh_hid_run(hid_class);
return ret;
}
int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_hid *hid_class = (struct usbh_hid *)hport->config.intf[intf].priv;
if (hid_class) {
if (hid_class->intin) {
usbh_kill_urb(&hid_class->intin_urb);
}
if (hid_class->intout) {
usbh_kill_urb(&hid_class->intout_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister HID Class:%s\r\n", hport->config.intf[intf].devname);
usbh_hid_stop(hid_class);
}
usbh_hid_class_free(hid_class);
}
return ret;
}
__WEAK void usbh_hid_run(struct usbh_hid *hid_class)
{
(void)hid_class;
}
__WEAK void usbh_hid_stop(struct usbh_hid *hid_class)
{
(void)hid_class;
}
const struct usbh_class_driver hid_class_driver = {
.driver_name = "hid",
.connect = usbh_hid_connect,
.disconnect = usbh_hid_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info hid_custom_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS,
.class = USB_DEVICE_CLASS_HID,
.subclass = 0x00,
.protocol = 0x00,
.id_table = NULL,
.class_driver = &hid_class_driver
};

View File

@ -1,44 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_HID_H
#define USBH_HID_H
#include "usb_hid.h"
struct usbh_hid {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint */
struct usb_endpoint_descriptor *intout; /* INTR OUT endpoint */
struct usbh_urb intin_urb; /* INTR IN urb */
struct usbh_urb intout_urb; /* INTR OUT urb */
uint8_t report_desc[256];
uint16_t report_size;
uint8_t protocol;
uint8_t intf; /* interface number */
uint8_t minor;
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t duration);
int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer);
int usbh_hid_set_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen);
int usbh_hid_get_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen);
void usbh_hid_run(struct usbh_hid *hid_class);
void usbh_hid_stop(struct usbh_hid *hid_class);
#ifdef __cplusplus
}
#endif
#endif /* USBH_HID_H */

View File

@ -1,89 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USB_MSC_H
#define USB_MSC_H
/* MSC Subclass Codes */
#define MSC_SUBCLASS_RBC 0x01 /* Reduced block commands (e.g., flash devices) */
#define MSC_SUBCLASS_SFF8020I_MMC2 0x02 /* SFF-8020i/MMC-2 (ATAPI) (e.g., C/DVD) */
#define MSC_SUBCLASS_QIC157 0x03 /* QIC-157 (e.g., tape device) */
#define MSC_SUBCLASS_UFI 0x04 /* e.g. floppy device */
#define MSC_SUBCLASS_SFF8070I 0x05 /* SFF-8070i (e.g. floppy disk) */
#define MSC_SUBCLASS_SCSI 0x06 /* SCSI transparent */
/* MSC Protocol Codes */
#define MSC_PROTOCOL_CBI_INT 0x00 /* CBI transport with command completion interrupt */
#define MSC_PROTOCOL_CBI_NOINT 0x01 /* CBI transport without command completion interrupt */
#define MSC_PROTOCOL_BULK_ONLY 0x50 /* Bulk only transport */
/* MSC Request Codes */
#define MSC_REQUEST_RESET 0xFF
#define MSC_REQUEST_GET_MAX_LUN 0xFE
/** MSC Command Block Wrapper (CBW) Signature */
#define MSC_CBW_Signature 0x43425355
/** Bulk-only Command Status Wrapper (CSW) Signature */
#define MSC_CSW_Signature 0x53425355
/** MSC Command Block Status Values */
#define CSW_STATUS_CMD_PASSED 0x00
#define CSW_STATUS_CMD_FAILED 0x01
#define CSW_STATUS_PHASE_ERROR 0x02
#define MSC_MAX_CDB_LEN (16) /* Max length of SCSI Command Data Block */
/** MSC Bulk-Only Command Block Wrapper (CBW) */
struct CBW {
uint32_t dSignature; /* 'USBC' = 0x43425355 */
uint32_t dTag; /* Depends on command id */
uint32_t dDataLength; /* Number of bytes that host expects to transfer */
uint8_t bmFlags; /* Bit 7: Direction=IN (other obsolete or reserved) */
uint8_t bLUN; /* LUN (normally 0) */
uint8_t bCBLength; /* len of cdb[] */
uint8_t CB[MSC_MAX_CDB_LEN]; /* Command Data Block */
} __PACKED;
#define USB_SIZEOF_MSC_CBW 31
/** MSC Bulk-Only Command Status Wrapper (CSW) */
struct CSW {
uint32_t dSignature; /* 'USBS' = 0x53425355 */
uint32_t dTag; /* Same tag as original command */
uint32_t dDataResidue; /* Amount not transferred */
uint8_t bStatus; /* Status of transfer */
} __PACKED;
#define USB_SIZEOF_MSC_CSW 13
/*Length of template descriptor: 23 bytes*/
#define MSC_DESCRIPTOR_LEN (9 + 7 + 7)
// clang-format off
#define MSC_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, wMaxPacketSize, str_idx) \
/* Interface */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bFirstInterface, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x02, /* bNumEndpoints */ \
USB_DEVICE_CLASS_MASS_STORAGE, /* bInterfaceClass */ \
MSC_SUBCLASS_SCSI, /* bInterfaceSubClass */ \
MSC_PROTOCOL_BULK_ONLY, /* bInterfaceProtocol */ \
str_idx, /* iInterface */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
out_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00 /* bInterval */
// clang-format on
#endif /* USB_MSC_H */

View File

@ -1,972 +0,0 @@
/*
* Apache NuttX
* Copyright 2020 The Apache Software Foundation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __INCLUDE_NUTTX_SCSI_H
#define __INCLUDE_NUTTX_SCSI_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* SCSI commands ************************************************************/
#define SCSI_CMD_TESTUNITREADY 0x00
#define SCSI_CMD_REZEROUNIT 0x01
#define SCSI_CMD_REQUESTSENSE 0x03
#define SCSI_CMD_FORMAT_UNIT 0x04
#define SCSI_CMD_REASSIGNBLOCKS 0x07
#define SCSI_CMD_READ6 0x08
#define SCSI_CMD_WRITE6 0x0a
#define SCSI_CMD_SEEK6 0x0b
#define SCSI_CMD_SPACE6 0x11
#define SCSI_CMD_INQUIRY 0x12
#define SCSI_CMD_MODESELECT6 0x15
#define SCSI_CMD_RESERVE6 0x16
#define SCSI_CMD_RELEASE6 0x17
#define SCSI_CMD_COPY 0x18
#define SCSI_CMD_MODESENSE6 0x1a
#define SCSI_CMD_STARTSTOPUNIT 0x1b
#define SCSI_CMD_RECEIVEDIAGNOSTICRESULTS 0x1c
#define SCSI_CMD_SENDDIAGNOSTIC 0x1d
#define SCSI_CMD_PREVENTMEDIAREMOVAL 0x1e
#define SCSI_CMD_READFORMATCAPACITIES 0x23
#define SCSI_CMD_READCAPACITY10 0x25
#define SCSI_CMD_READ10 0x28
#define SCSI_CMD_WRITE10 0x2a
#define SCSI_CMD_SEEK10 0x2b
#define SCSI_CMD_WRITEANDVERIFY 0x2e
#define SCSI_CMD_VERIFY10 0x2f
#define SCSI_CMD_SEARCHDATAHIGH 0x30
#define SCSI_CMD_SEARCHDATAEQUAL 0x31
#define SCSI_CMD_SEARCHDATALOW 0x32
#define SCSI_CMD_SETLIMITS10 0x33
#define SCSI_CMD_PREFETCH10 0x34
#define SCSI_CMD_SYNCHCACHE10 0x35
#define SCSI_CMD_LOCKCACHE 0x36
#define SCSI_CMD_READDEFECTDATA10 0x37
#define SCSI_CMD_COMPARE 0x39
#define SCSI_CMD_COPYANDVERIFY 0x3a
#define SCSI_CMD_WRITEBUFFER 0x3b
#define SCSI_CMD_READBUFFER 0x3c
#define SCSI_CMD_READLONG10 0x3e
#define SCSI_CMD_WRITELONG10 0x3f
#define SCSI_CMD_CHANGEDEFINITION 0x40
#define SCSI_CMD_WRITESAME10 0x41
#define SCSI_CMD_LOGSELECT 0x4c
#define SCSI_CMD_LOGSENSE 0x4d
#define SCSI_CMD_XDWRITE10 0x50
#define SCSI_CMD_XPWRITE10 0x51
#define SCSI_CMD_XDREAD10 0x52
#define SCSI_CMD_MODESELECT10 0x55
#define SCSI_CMD_RESERVE10 0x56
#define SCSI_CMD_RELEASE10 0x57
#define SCSI_CMD_MODESENSE10 0x5a
#define SCSI_CMD_PERSISTENTRESERVEIN 0x5e
#define SCSI_CMD_PERSISTENTRESERVEOUT 0x5f
#define SCSI_CMD_32 0x7f
#define SCSI_CMD_XDWRITEEXTENDED 0x80
#define SCSI_CMD_REBUILD 0x82
#define SCSI_CMD_REGENERATE 0x82
#define SCSI_CMD_EXTENDEDCOPY 0x83
#define SCSI_CMD_COPYRESULTS 0x84
#define SCSI_CMD_ACCESSCONTROLIN 0x86
#define SCSI_CMD_ACCESSCONTROLOUT 0x87
#define SCSI_CMD_READ16 0x88
#define SCSI_CMD_WRITE16 0x8a
#define SCSI_CMD_READATTRIBUTE 0x8c
#define SCSI_CMD_WRITEATTRIBUTE 0x8d
#define SCSI_CMD_WRITEANDVERIFY16 0x8e
#define SCSI_CMD_PREFETCH16 0x90
#define SCSI_CMD_SYNCHCACHE16 0x91
#define SCSI_CMD_LOCKUNLOCKACACHE 0x92
#define SCSI_CMD_WRITESAME16 0x93
#define SCSI_CMD_READCAPACITY16 0x9e
#define SCSI_CMD_READLONG16 0x9e
#define SCSI_CMD_WRITELONG106 0x9f
#define SCSI_CMD_REPORTLUNS 0xa0
#define SCSI_CMD_MAINTENANCEIN 0xa3
#define SCSI_CMD_MAINTENANCEOUT 0xa4
#define SCSI_CMD_MOVEMEDIUM 0xa5
#define SCSI_CMD_MOVEMEDIUMATTACHED 0xa7
#define SCSI_CMD_READ12 0xa8
#define SCSI_CMD_WRITE12 0xaa
#define SCSI_CMD_READMEDIASERIALNUMBER 0xab
#define SCSI_CMD_WRITEANDVERIFY12 0xae
#define SCSI_CMD_VERIFY12 0xaf
#define SCSI_CMD_SETLIMITS12 0xb3
#define SCSI_CMD_READELEMENTSTATUS 0xb4
#define SCSI_CMD_READDEFECTDATA12 0xb7
#define SCSI_CMD_REDUNDANCYGROUPIN 0xba
#define SCSI_CMD_REDUNDANCYGROUPOUT 0xbb
#define SCSI_CMD_SPAREIN 0xbc
#define SCSI_CMD_SPAREOUT 0xbd
#define SCSI_CMD_VOLUMESETIN 0xbe
#define SCSI_CMD_VOLUMESETOUT 0xbf
/* Common SCSI KCQ values (sense Key/additional sense Code/ASC Qualifier) ***
*
* 0xnn0386 Write Fault Data Corruption
* 0xnn0500 Illegal request
* 0xnn0600 Unit attention
* 0xnn0700 Data protect
* 0xnn0800 LUN communication failure
* 0xnn0801 LUN communication timeout
* 0xnn0802 LUN communication parity error
* 0xnn0803 LUN communication CRC error
* 0xnn0900 vendor specific sense key
* 0xnn0901 servo fault
* 0xnn0904 head select fault
* 0xnn0a00 error log overflow
* 0xnn0b00 aborted command
* 0xnn0c00 write error
* 0xnn0c02 write error - auto-realloc failed
* 0xnn0e00 data miscompare
* 0xnn1200 address mark not founf for ID field
* 0xnn1400 logical block not found
* 0xnn1500 random positioning error
* 0xnn1501 mechanical positioning error
* 0xnn1502 positioning error detected by read of medium
* 0xnn2700 write protected
* 0xnn2900 POR or bus reset occurred
* 0xnn3101 format failed
* 0xnn3191 format corrupted
* 0xnn3201 defect list update error
* 0xnn3202 no spares available
* 0xnn3501 unspecified enclosure services failure
* 0xnn3700 parameter rounded
* 0xnn3d00 invalid bits in identify message
* 0xnn3e00 LUN not self-configured yet
* 0xnn4001 DRAM parity error
* 0xnn4002 DRAM parity error
* 0xnn4200 power-on or self-test failure
* 0xnn4c00 LUN failed self-configuration
* 0xnn5c00 RPL status change
* 0xnn5c01 spindles synchronized
* 0xnn5c02 spindles not synchronized
* 0xnn6500 voltage fault
* 0xnn8000 general firmware error
*/
/* No sense KCQ values */
#define SCSI_KCQ_NOSENSE 0x000000 /* No error */
#define SCSI_KCQ_PFATHRESHOLDREACHED 0x005c00 /* No sense - PFA threshold reached */
/* Soft error KCQ values */
#define SCSI_KCQSE_RWENOINDEX 0x010100 /* Recovered Write error - no index */
#define SCSI_KCQSE_RECOVEREDNOSEEKCOMPLETION 0x010200 /* Recovered no seek completion */
#define SCSI_KCQSE_RWEWRITEFAULT 0x010300 /* Recovered Write error - write fault */
#define SCSI_KCQSE_TRACKFOLLOWINGERROR 0x010900 /* Track following error */
#define SCSI_KCQSE_TEMPERATUREWARNING 0x010b01 /* Temperature warning */
#define SCSI_KCQSE_RWEWARREALLOCATED 0x010c01 /* Recovered Write error with auto-realloc - reallocated */
#define SCSI_KCQSE_RWERECOMMENDREASSIGN 0x010c03 /* Recovered Write error - recommend reassign */
#define SCSI_KCQSE_RDWOEUSINGPREVLBI 0x011201 /* Recovered data without ECC using prev logical block ID */
#define SCSI_KCQSE_RDWEUSINGPREVLBI 0x011202 /* Recovered data with ECC using prev logical block ID */
#define SCSI_KCQSE_RECOVEREDRECORDNOTFOUND 0x011401 /* Recovered Record Not Found */
#define SCSI_KCQSE_RWEDSME 0x011600 /* Recovered Write error - Data Sync Mark Error */
#define SCSI_KCQSE_RWEDSEDATAREWRITTEN 0x011601 /* Recovered Write error - Data Sync Error - data rewritten */
#define SCSI_KCQSE_RWEDSERECOMMENDREWRITE 0x011602 /* Recovered Write error - Data Sync Error - recommend rewrite */
#define SCSI_KCQSE_RWEDSEDATAAUTOREALLOCATED 0x011603 /* Recovered Write error - Data Sync Error - data auto-reallocated */
#define SCSI_KCQSE_RWEDSERECOMMENDREASSIGNMENT 0x011604 /* Recovered Write error - Data Sync Error - recommend reassignment */
#define SCSI_KCQSE_RDWNECORRECTIONAPPLIED 0x011700 /* Recovered data with no error correction applied */
#define SCSI_KCQSE_RREWITHRETRIES 0x011701 /* Recovered Read error - with retries */
#define SCSI_KCQSE_RDUSINGPOSITIVEOFFSET 0x011702 /* Recovered data using positive offset */
#define SCSI_KCQSE_RDUSINGNEGATIVEOFFSET 0x011703 /* Recovered data using negative offset */
#define SCSI_KCQSE_RDUSINGPREVIOUSLBI 0x011705 /* Recovered data using previous logical block ID */
#define SCSI_KCQSE_RREWOEAUTOREALLOCATED 0x011706 /* Recovered Read error - without ECC, auto reallocated */
#define SCSI_KCQSE_RREWOERECOMMENDREASSIGN 0x011707 /* Recovered Read error - without ECC, recommend reassign */
#define SCSI_KCQSE_RREWOERECOMMENDREWRITE 0x011708 /* Recovered Read error - without ECC, recommend rewrite */
#define SCSI_KCQSE_RREWOEDATAREWRITTEN 0x011709 /* Recovered Read error - without ECC, data rewritten */
#define SCSI_KCQSE_RREWE 0x011800 /* Recovered Read error - with ECC */
#define SCSI_KCQSE_RDWEANDRETRIES 0x011801 /* Recovered data with ECC and retries */
#define SCSI_KCQSE_RREWEAUTOREALLOCATED 0x011802 /* Recovered Read error - with ECC, auto reallocated */
#define SCSI_KCQSE_RREWERECOMMENDREASSIGN 0x011805 /* Recovered Read error - with ECC, recommend reassign */
#define SCSI_KCQSE_RDUSINGECCANDOFFSETS 0x011806 /* Recovered data using ECC and offsets */
#define SCSI_KCQSE_RREWEDATAREWRITTEN 0x011807 /* Recovered Read error - with ECC, data rewritten */
#define SCSI_KCQSE_DLNOTFOUND 0x011c00 /* Defect List not found */
#define SCSI_KCQSE_PRIMARYDLNOTFOUND 0x011c01 /* Primary defect list not found */
#define SCSI_KCQSE_GROWNDLNOTFOUND 0x011c02 /* Grown defect list not found */
#define SCSI_KCQSE_PARTIALDLTRANSFERRED 0x011f00 /* Partial defect list transferred */
#define SCSI_KCQSE_INTERNALTARGETFAILURE 0x014400 /* Internal target failure */
#define SCSI_KCQSE_PFATHRESHOLDREACHED 0x015d00 /* PFA threshold reached */
#define SCSI_KCQSE_PFATESTWARNING 0x015dff /* PFA test warning */
#define SCSI_KCQSE_INTERNALLOGICFAILURE 0x018100 /* Internal logic failure */
/* Not Ready / Diagnostic Failure KCQ values */
#define SCSI_KCQNR_CAUSENOTREPORTABLE 0x020400 /* Not Ready - Cause not reportable. */
#define SCSI_KCQNR_BECOMINGREADY 0x020401 /* Not Ready - becoming ready */
#define SCSI_KCQNR_NEEDINITIALIZECOMMAND 0x020402 /* Not Ready - need initialize command (start unit) */
#define SCSI_KCQNR_MANUALINTERVENTIONREQUIRED 0x020403 /* Not Ready - manual intervention required */
#define SCSI_KCQNR_FORMATINPROGRESS 0x020404 /* Not Ready - format in progress */
#define SCSI_KCQNR_SELFTESTINPROGRESS 0x020409 /* Not Ready - self-test in progress */
#define SCSI_KCQNR_MEDIUMFORMATCORRUPTED 0x023100 /* Not Ready - medium format corrupted */
#define SCSI_KCQNR_FORMATCOMMANDFAILED 0x023101 /* Not Ready - format command failed */
#define SCSI_KCQNR_ESUNAVAILABLE 0x023502 /* Not Ready - enclosure services unavailable */
#define SCSI_KCQNR_MEDIANOTPRESENT 0x023a00 /* Not Ready - media not present */
#define SCSI_KCQDF_BRINGUPFAILORDEGRADEDMODE 0x024080 /* Diagnostic Failure - bring-up fail or degraded mode */
#define SCSI_KCQDF_HARDDISKCONTROLLER 0x024081 /* Diagnostic Failure - Hard Disk Controller */
#define SCSI_KCQDF_RAMMICROCODENOTLOADED 0x024085 /* Diagnostic Failure - RAM microcode not loaded */
#define SCSI_KCQDF_RROCALIBRATION 0x024090 /* Diagnostic Failure - RRO Calibration */
#define SCSI_KCQDF_CHANNELCALIBRATION 0x024091 /* Diagnostic Failure - Channel Calibration */
#define SCSI_KCQDF_HEADLOAD 0x024092 /* Diagnostic Failure - Head Load */
#define SCSI_KCQDF_WRITEAE 0x024093 /* Diagnostic Failure - Write AE */
#define SCSI_KCQDF_12VOVERCURRENT 0x024094 /* Diagnostic Failure - 12V over current */
#define SCSI_KCQDF_OTHERSPINDLEFAILURE 0x024095 /* Diagnostic Failure - Other spindle failure */
#define SCSI_KCQDF_SELFRESET 0x0240b0 /* Diagnostic Failure - self-reset */
#define SCSI_KCQDF_CONFIGNOTLOADED 0x024c00 /* Diagnostic Failure - config not loaded */
/* Medium error KCQ values */
#define SCSI_KCQME_WRITEFAULT 0x030300 /* Medium Error - write fault */
#define SCSI_KCQME_WRITEFAULTAUTOREALLOCFAILED 0x030c02 /* Medium Error - write error - auto-realloc failed */
#define SCSI_KCQME_WRITERTLIMITEXCEEDED 0x030cbb /* Medium Error - write recovery time limit exceeded */
#define SCSI_KCQME_IDCRCERROR 0x031000 /* Medium Error - ID CRC error */
#define SCSI_KCQME_UNRRE1 0x031100 /* Medium Error - unrecovered read error */
#define SCSI_KCQME_READRETRIESEXHAUSTED 0x031101 /* Medium Error - read retries exhausted */
#define SCSI_KCQME_ERRORTOOLONGTOCORRECT 0x031102 /* Medium Error - error too long to correct */
#define SCSI_KCQME_UREAUTOREALLOCFAILED 0x031104 /* Medium Error - unrecovered read error - auto re-alloc failed */
#define SCSI_KCQME_URERECOMMENDREASSIGN 0x03110b /* Medium Error - unrecovered read error - recommend reassign */
#define SCSI_KCQME_READRTLIMITEXCEEDED 0x0311ff /* Medium Error - read recovery time limit exceeded */
#define SCSI_KCQME_RECORDNOTFOUND 0x031401 /* Medium Error - record not found */
#define SCSI_KCQME_DSME 0x031600 /* Medium Error - Data Sync Mark error */
#define SCSI_KCQME_DSERECOMMENDREASSIGN 0x031604 /* Medium Error - Data Sync Error - recommend reassign */
#define SCSI_KCQME_DLE 0x031900 /* Medium Error - defect list error */
#define SCSI_KCQME_DLNOTAVAILABLE 0x031901 /* Medium Error - defect list not available */
#define SCSI_KCQME_DLEINPRIMARYLIST 0x031902 /* Medium Error - defect list error in primary list */
#define SCSI_KCQME_DLEINGROWNLIST 0x031903 /* Medium Error - defect list error in grown list */
#define SCSI_KCQME_FEWERTHAN50PCTDLCOPIES 0x03190e /* Medium Error - fewer than 50% defect list copies */
#define SCSI_KCQME_MEDIUMFORMATCORRUPTED 0x033100 /* Medium Error - medium format corrupted */
#define SCSI_KCQME_FORMATCOMMANDFAILED 0x033101 /* Medium Error - format command failed */
#define SCSI_KCQME_DATAAUTOREALLOCATED 0x038000 /* Medium Error - data auto-reallocated */
/* Hardware Error KCQ values */
#define SCSI_KCQHE_NOINDEXORSECTOR 0x040100 /* Hardware Error - no index or sector */
#define SCSI_KCQHE_NOSEEKCOMPLETE 0x040200 /* Hardware Error - no seek complete */
#define SCSI_KCQHE_WRITEFAULT 0x040300 /* Hardware Error - write fault */
#define SCSI_KCQHE_COMMUNICATIONFAILURE 0x040800 /* Hardware Error - communication failure */
#define SCSI_KCQHE_TRACKFOLLOWINGERROR 0x040900 /* Hardware Error - track following error */
#define SCSI_KCQHE_UREINRESERVEDAREA 0x041100 /* Hardware Error - unrecovered read error in reserved area */
#define SCSI_KCQHE_DSMEINRESERVEDAREA 0x041600 /* Hardware Error - Data Sync Mark error in reserved area */
#define SCSI_KCQHE_DLE 0x041900 /* Hardware Error - defect list error */
#define SCSI_KCQHE_DLEINPRIMARYLIST 0x041902 /* Hardware Error - defect list error in Primary List */
#define SCSI_KCQHE_DLEINGROWNLIST 0x041903 /* Hardware Error - defect list error in Grown List */
#define SCSI_KCQHE_REASSIGNFAILED 0x043100 /* Hardware Error - reassign failed */
#define SCSI_KCQHE_NODEFECTSPAREAVAILABLE 0x043200 /* Hardware Error - no defect spare available */
#define SCSI_KCQHE_UNSUPPORTEDENCLOSUREFUNCTION 0x043501 /* Hardware Error - unsupported enclosure function */
#define SCSI_KCQHE_ESUNAVAILABLE 0x043502 /* Hardware Error - enclosure services unavailable */
#define SCSI_KCQHE_ESTRANSFERFAILURE 0x043503 /* Hardware Error - enclosure services transfer failure */
#define SCSI_KCQHE_ESREFUSED 0x043504 /* Hardware Error - enclosure services refused */
#define SCSI_KCQHE_SELFTESTFAILED 0x043e03 /* Hardware Error - self-test failed */
#define SCSI_KCQHE_UNABLETOUPDATESELFTEST 0x043e04 /* Hardware Error - unable to update self-test */
#define SCSI_KCQHE_DMDIAGNOSTICFAIL 0x044080 /* Hardware Error - Degrade Mode. Diagnostic Fail */
#define SCSI_KCQHE_DMHWERROR 0x044081 /* Hardware Error - Degrade Mode. H/W Error */
#define SCSI_KCQHE_DMRAMMICROCODENOTLOADED 0x044085 /* Hardware Error - Degrade Mode. RAM microcode not loaded */
#define SCSI_KCQHE_SEEKTESTFAILURE 0x044090 /* Hardware Error - seek test failure */
#define SCSI_KCQHE_READWRITETESTFAILURE 0x0440a0 /* Hardware Error - read/write test failure */
#define SCSI_KCQHE_DEVICESELFRESET 0x0440b0 /* Hardware Error - device self-reset */
#define SCSI_KCQHE_COMPONENTMISMATCH 0x0440d0 /* Hardware Error - component mismatch */
#define SCSI_KCQHE_INTERNALTARGETFAILURE 0x044400 /* Hardware Error - internal target failure */
#define SCSI_KCQHE_INTERNALLOGICERROR 0x048100 /* Hardware Error - internal logic error */
#define SCSI_KCQHE_COMMANDTIMEOUT 0x048200 /* Hardware Error - command timeout */
/* Illegal Request KCQ values */
#define SCSI_KCQIR_PARMLISTLENGTHERROR 0x051a00 /* Illegal Request - parm list length error */
#define SCSI_KCQIR_INVALIDCOMMAND 0x052000 /* Illegal Request - invalid/unsupported command code */
#define SCSI_KCQIR_LBAOUTOFRANGE 0x052100 /* Illegal Request - LBA out of range */
#define SCSI_KCQIR_INVALIDFIELDINCBA 0x052400 /* Illegal Request - invalid field in CDB (Command Descriptor Block) */
#define SCSI_KCQIR_INVALIDLUN 0x052500 /* Illegal Request - invalid LUN */
#define SCSI_KCQIR_INVALIDFIELDSINPARMLIST 0x052600 /* Illegal Request - invalid fields in parm list */
#define SCSI_KCQIR_PARAMETERNOTSUPPORTED 0x052601 /* Illegal Request - parameter not supported */
#define SCSI_KCQIR_INVALIDPARMVALUE 0x052602 /* Illegal Request - invalid parm value */
#define SCSI_KCQIR_IFPTHRESHOLDPARAMETER 0x052603 /* Illegal Request - invalid field parameter - threshold parameter */
#define SCSI_KCQIR_INVALIDRELEASEOFPR 0x052604 /* Illegal Request - invalid release of persistent reservation */
#define SCSI_KCQIR_IFPTMSFIRMWARETAG 0x052697 /* Illegal Request - invalid field parameter - TMS firmware tag */
#define SCSI_KCQIR_IFPCHECKSUM 0x052698 /* Illegal Request - invalid field parameter - check sum */
#define SCSI_KCQIR_IFPFIRMWARETAG 0x052699 /* Illegal Request - invalid field parameter - firmware tag */
#define SCSI_KCQIR_COMMANDSEQUENCEERROR 0x052c00 /* Illegal Request - command sequence error */
#define SCSI_KCQIR_UNSUPPORTEDENCLOSUREFUNCTION 0x053501 /* Illegal Request - unsupported enclosure function */
#define SCSI_KCQIR_SAVINGPARMSNOTSUPPORTED 0x053900 /* Illegal Request - Saving parameters not supported */
#define SCSI_KCQIR_INVALIDMESSAGE 0x054900 /* Illegal Request - invalid message */
#define SCSI_KCQIR_MEDIALOADOREJECTFAILED 0x055300 /* Illegal Request - media load or eject failed */
#define SCSI_KCQIR_UNLOADTAPEFAILURE 0x055301 /* Illegal Request - unload tape failure */
#define SCSI_KCQIR_MEDIUMREMOVALPREVENTED 0x055302 /* Illegal Request - medium removal prevented */
#define SCSI_KCQIR_SYSTEMRESOURCEFAILURE 0x055500 /* Illegal Request - system resource failure */
#define SCSI_KCQIR_SYSTEMBUFFERFULL 0x055501 /* Illegal Request - system buffer full */
#define SCSI_KCQIR_INSUFFICIENTRR 0x055504 /* Illegal Request - Insufficient Registration Resources */
/* Unit Attention KCQ values */
#define SCSI_KCQUA_NOTREADYTOTRANSITION 0x062800 /* Unit Attention - not-ready to ready transition (format complete) */
#define SCSI_KCQUA_DEVICERESETOCCURRED 0x062900 /* Unit Attention - POR or device reset occurred */
#define SCSI_KCQUA_POROCCURRED 0x062901 /* Unit Attention - POR occurred */
#define SCSI_KCQUA_SCSIBUSRESETOCCURRED 0x062902 /* Unit Attention - SCSI bus reset occurred */
#define SCSI_KCQUA_TARGETRESETOCCURRED 0x062903 /* Unit Attention - TARGET RESET occurred */
#define SCSI_KCQUA_SELFINITIATEDRESETOCCURRED 0x062904 /* Unit Attention - self-initiated-reset occurred */
#define SCSI_KCQUA_TRANSCEIVERMODECHANGETOSE 0x062905 /* Unit Attention - transceiver mode change to SE */
#define SCSI_KCQUA_TRANSCEIVERMODECHANGETOLVD 0x062906 /* Unit Attention - transceiver mode change to LVD */
#define SCSI_KCQUA_PARAMETERSCHANGED 0x062a00 /* Unit Attention - parameters changed */
#define SCSI_KCQUA_MODEPARAMETERSCHANGED 0x062a01 /* Unit Attention - mode parameters changed */
#define SCSI_KCQUA_LOGSELECTPARMSCHANGED 0x062a02 /* Unit Attention - log select parms changed */
#define SCSI_KCQUA_RESERVATIONSPREEMPTED 0x062a03 /* Unit Attention - Reservations pre-empted */
#define SCSI_KCQUA_RESERVATIONSRELEASED 0x062a04 /* Unit Attention - Reservations released */
#define SCSI_KCQUA_REGISTRATIONSPREEMPTED 0x062a05 /* Unit Attention - Registrations pre-empted */
#define SCSI_KCQUA_COMMANDSCLEARED 0x062f00 /* Unit Attention - commands cleared by another initiator */
#define SCSI_KCQUA_OPERATINGCONDITIONSCHANGED 0x063f00 /* Unit Attention - target operating conditions have changed */
#define SCSI_KCQUA_MICROCODECHANGED 0x063f01 /* Unit Attention - microcode changed */
#define SCSI_KCQUA_CHANGEDOPERATINGDEFINITION 0x063f02 /* Unit Attention - changed operating definition */
#define SCSI_KCQUA_INQUIRYPARAMETERSCHANGED 0x063f03 /* Unit Attention - inquiry parameters changed */
#define SCSI_KCQUA_DEVICEIDENTIFIERCHANGED 0x063f05 /* Unit Attention - device identifier changed */
#define SCSI_KCQUA_INVALIDAPMPARAMETERS 0x063f90 /* Unit Attention - invalid APM parameters */
#define SCSI_KCQUA_WORLDWIDENAMEMISMATCH 0x063f91 /* Unit Attention - world-wide name mismatch */
#define SCSI_KCQUA_PFATHRESHOLDREACHED 0x065d00 /* Unit Attention - PFA threshold reached */
#define SCSI_KCQUA_PFATHRESHOLDEXCEEDED 0x065dff /* Unit Attention - PFA threshold exceeded */
/* Write Protect KCQ values */
#define SCSI_KCQWP_COMMANDNOTALLOWED 0x072700 /* Write Protect - command not allowed */
/* Aborted Command KCQ values */
#define SCSI_KCQAC_NOADDITIONALSENSECODE 0x0b0000 /* Aborted Command - no additional sense code */
#define SCSI_KCQAC_SYNCDATATRANSFERERROR 0x0b1b00 /* Aborted Command - sync data transfer error (extra ACK) */
#define SCSI_KCQAC_UNSUPPORTEDLUN 0x0b2500 /* Aborted Command - unsupported LUN */
#define SCSI_KCQAC_ECHOBUFFEROVERWRITTEN 0x0b3f0f /* Aborted Command - echo buffer overwritten */
#define SCSI_KCQAC_MESSAGEREJECTERROR 0x0b4300 /* Aborted Command - message reject error */
#define SCSI_KCQAC_INTERNALTARGETFAILURE 0x0b4400 /* Aborted Command - internal target failure */
#define SCSI_KCQAC_SELECTIONFAILURE 0x0b4500 /* Aborted Command - Selection/Reselection failure */
#define SCSI_KCQAC_SCSIPARITYERROR 0x0b4700 /* Aborted Command - SCSI parity error */
#define SCSI_KCQAC_INITIATORDETECTEDERRORECEIVED 0x0b4800 /* Aborted Command - initiator-detected error message received */
#define SCSI_KCQAC_ILLEGALMESSAGE 0x0b4900 /* Aborted Command - inappropriate/illegal message */
#define SCSI_KCQAC_DATAPHASEERROR 0x0b4b00 /* Aborted Command - data phase error */
#define SCSI_KCQAC_OVERLAPPEDCOMMANDSATTEMPTED 0x0b4e00 /* Aborted Command - overlapped commands attempted */
#define SCSI_KCQAC_LOOPINITIALIZATION 0x0b4f00 /* Aborted Command - due to loop initialization */
/* Other KCQ values: */
#define SCSO_KCQOTHER_MISCOMPARE 0x0e1d00 /* Miscompare - during verify byte check operation */
/* SSCSI Status Codes *******************************************************/
#define SCSI_STATUS_OK 0x00 /* OK */
#define SCSI_STATUS_CHECKCONDITION 0x02 /* Check condition */
#define SCSI_STATUS_CONDITIONMET 0x04 /* Condition met */
#define SCSI_STATUS_BUSY 0x08 /* Busy */
#define SCSI_STATUS_INTERMEDIATE 0x10 /* Intermediate */
#define SCSI_STATUS_DATAOVERUNDERRUN 0x12 /* Data Under/Over Run? */
#define SCSI_STATUS_INTERMEDIATECONDITIONMET 0x14 /* Intermediate - Condition met */
#define SCSI_STATUS_RESERVATIONCONFLICT 0x18 /* Reservation conflict */
#define SCSI_STATUS_COMMANDTERMINATED 0x22 /* Command terminated */
#define SCSI_STATUS_QUEUEFULL 0x28 /* Queue (task set) full */
#define SCSI_STATUS_ACAACTIVE 0x30 /* ACA active */
#define SCSI_STATUS_TASKABORTED 0x40 /* Task aborted */
/* Definitions for selected SCSI commands ***********************************/
/* Inquiry */
#define SCSICMD_INQUIRYFLAGS_EVPD 0x01 /* Bit 0: EVPD */
/* Bits 5-7: Peripheral Qualifier */
#define SCSIRESP_INQUIRYPQ_CONNECTED 0x00 /* 000: Device is connected */
#define SCSIRESP_INQUIRYPQ_NOTCONNECTED 0x20 /* 001: Device is NOT connected */
#define SCSIRESP_INQUIRYPQ_NOTCAPABLE 0x60 /* 011: LUN not supported */
/* Bits 0-4: Peripheral Device */
#define SCSIRESP_INQUIRYPD_DIRECTACCESS 0x00 /* Direct-access block device */
#define SCSIRESP_INQUIRYPD_SEQUENTIALACCESS 0x01 /* Sequential-access block device */
#define SCSIRESP_INQUIRYPD_PRINTER 0x02 /* Printer device */
#define SCSIRESP_INQUIRYPD_PROCESSOR 0x03 /* Processor device */
#define SCSIRESP_INQUIRYPD_WRONCE 0x04 /* Write once device */
#define SCSIRESP_INQUIRYPD_CDDVD 0x05 /* CD/DVD device */
#define SCSIRESP_INQUIRYPD_SCANNER 0x06 /* Scanner device (obsolete) */
#define SCSIRESP_INQUIRYPD_OPTICAL 0x07 /* Optical memory device */
#define SCSIRESP_INQUIRYPD_MEDIUMCHANGER 0x08 /* Medium changer device (Jukebox) */
#define SCSIRESP_INQUIRYPD_COMMUNICATIONS 0x09 /* Communications device (obsolete) */
#define SCSIRESP_INQUIRYPD_STORAGEARRAY 0x0c /* Storage array controller device */
#define SCSIRESP_INQUIRYPD_ENCLOSURESERVICES 0x0d /* Enclosure services device */
#define SCSIRESP_INQUIRYPD_RBC 0x0e /* Simplified direct-access device */
#define SCSIRESP_INQUIRYPD_OCRW 0x0f /* Optical reader/writer device */
#define SCSIRESP_INQUIRYPD_BCC 0x10 /* Bridge controller commands */
#define SCSIRESP_INQUIRYPD_OSD 0x11 /* Object-based storage device */
#define SCSIRESP_INQUIRYPD_ADC 0x12 /* Automation/drive interface */
#define SCSIRESP_INQUIRYPD_WKLU 0x1e /* Well-known logical unit */
#define SCSIRESP_INQUIRYPD_UNKNOWN 0x1f /* Direct-access block device */
#define SCSIRESP_INQUIRYFLAGS1_RMB 0x80 /* Bit 7: RMB */
#define SCSIRESP_INQUIRYFLAGS2_NORMACA 0x20 /* Bit 5: NormACA */
#define SCSIRESP_INQUIRYFLAGS2_HISUP 0x10 /* Bit 4: HiSup */
#define SCSIRESP_INQUIRYFLAGS2_FMTMASK 0x0f /* Bits 0-3: Response data format */
#define SCSIRESP_INQUIRYFLAGS3_SCCS 0x80 /* Bit 8: SCCS */
#define SCSIRESP_INQUIRYFLAGS3_ACC 0x40 /* Bit 7: ACC */
#define SCSIRESP_INQUIRYFLAGS3_TPGSMASK 0x30 /* Bits 4-5: TPGS */
#define SCSIRESP_INQUIRYFLAGS3_3PC 0x08 /* Bit 3: 3PC */
#define SCSIRESP_INQUIRYFLAGS3_PROTECT 0x01 /* Bit 0: Protect */
#define SCSIRESP_INQUIRYFLAGS4_BQUE 0x80 /* Bit 7: BQue */
#define SCSIRESP_INQUIRYFLAGS4_ENCSERV 0x40 /* Bit 6: EncServ */
#define SCSIRESP_INQUIRYFLAGS4_VS 0x20 /* Bit 5: VS */
#define SCSIRESP_INQUIRYFLAGS4_MULTIP 0x10 /* Bit 4: MultIP */
#define SCSIRESP_INQUIRYFLAGS4_MCHNGR 0x08 /* Bit 3: MChngr */
#define SCSIRESP_INQUIRYFLAGS4_ADDR16 0x01 /* Bit 0: Addr16 */
#define SCSIRESP_INQUIRYFLAGS5_WBUS16 0x20 /* Bit 5: WBus16 */
#define SCSIRESP_INQUIRYFLAGS5_SYNC 0x10 /* Bit 4: SYNC */
#define SCSIRESP_INQUIRYFLAGS5_LINKED 0x08 /* Bit 3: LINKED */
#define SCSIRESP_INQUIRYFLAGS5_CMDQUEUE 0x02 /* Bit 1: CmdQue */
#define SCSIRESP_INQUIRYFLAGS5_VS 0x01 /* Bit 0: VS */
#define SCSIRESP_INQUIRYFLAGS6_CLOCKINGMASK 0xc0 /* Bits 2-3: Clocking */
#define SCSIRESP_INQUIRYFLAGS6_QAS 0x02 /* Bit 1: QAS */
#define SCSIRESP_INQUIRYFLAGS6_IUS 0x01 /* Bit 0: IUS */
/* Sense data */
/* Sense data response codes */
#define SCSIRESP_SENSEDATA_CURRENTFIXED 0x70 /* Byte 1 is always the response code */
#define SCSIRESP_SENSEDATA_DEFERREDFIXED 0x71
#define SCSIRESP_SENSEDATA_CURRENTDESC 0x72
#define SCSIRESP_SENSEDATA_DEFERREDDESC 0x73
#define SCSIRESP_SENSEDATA_RESPVALID 0x80
/* Fixed sense data flags */
#define SCSIRESP_SENSEDATA_FILEMARK 0x80 /* Bit 7: FileMark */
#define SCSIRESP_SENSEDATA_EOM 0x40 /* Bit 6: EOM */
#define SCSIRESP_SENSEDATA_ILI 0x20 /* Bit 5: ILI */
#define SCSIRESP_SENSEDATA_SENSEKEYMASK 0x0f /* Bits 0-3: Sense key */
#define SCSIRESP_SENSEDATA_NOSENSE 0x00 /* Nothing to be reported */
#define SCSIRESP_SENSEDATA_RECOVEREDERROR 0x01 /* Successful after recovery action */
#define SCSIRESP_SENSEDATA_NOTREADY 0x02 /* Logical unit is not accessible */
#define SCSIRESP_SENSEDATA_MEDIUMERROR 0x03 /* Error possibly caused by flaw in medium */
#define SCSIRESP_SENSEDATA_HARDWAREERROR 0x04 /* Non-recoverable hardware error */
#define SCSIRESP_SENSEDATA_ILLEGALREQUEST 0x05 /* Error in received request */
#define SCSIRESP_SENSEDATA_UNITATTENTION 0x06 /* Unit attention condition */
#define SCSIRESP_SENSEDATA_DATAPROTECT 0x07 /* Action failed, medium protected */
#define SCSIRESP_SENSEDATA_BLANKCHECK 0x08 /* Encountered blank media */
#define SCSIRESP_SENSEDATA_VENDORSPECIFIC 0x09 /* Vendor specific condition */
#define SCSIRESP_SENSEDATA_ABORTEDCOMMAND 0x0b /* Command was aborted */
#define SCSIRESP_SENSEDATA_KEYVALID 0x80 /* Sense-specific data valid */
/* Mode Select 6 */
#define SCSICMD_MODESELECT6_PF 0x10 /* Bit 4: PF */
#define SCSICMD_MODESELECT6_SP 0x01 /* Bit 0: SP */
/* Mode Sense 6 */
#define SCSICMD_MODESENSE6_DBD 0x08 /* Bit 3: PF */
#define SCSICMD_MODESENSE_PCMASK 0xc0 /* Bits 6-7: Page control (PC) */
#define SCSICMD_MODESENSE_PCCURRENT 0x00 /* Current values */
#define SCSICMD_MODESENSE_PCCHANGEABLE 0x40 /* Changeable values */
#define SCSICMD_MODESENSE_PCDEFAULT 0x80 /* Default values */
#define SCSICMD_MODESENSE_PCSAVED 0xc0 /* Saved values */
#define SCSICMD_MODESENSE_PGCODEMASK 0x3f /* Bits 0-5: Page code */
#define SCSICMD_MODESENSE6_PCDEFAULT 0x80 /* Default values */
/* Direct-access device page codes */
#define SCSIRESP_MODESENSE_PGCCODE_VENDOR 0x00 /* Vendor-specific */
#define SCSIRESP_MODESENSE_PGCCODE_RWERROR 0x01 /* Read/Write error recovery mode page */
#define SCSIRESP_MODESENSE_PGCCODE_RECONNECT 0x02 /* Disconnect-reconnect mode page */
#define SCSIRESP_MODESENSE_PGCCODE_FORMATDEV 0x03 /* Format device mode page (obsolete) */
#define SCSIRESP_MODESENSE_PGCCODE_RIGID 0x04 /* Rigid disk geometry mode page (obsolete) */
#define SCSIRESP_MODESENSE_PGCCODE_FLEXIBLE 0x05 /* Flexible disk geometry mode page (obsolete) */
#define SCSIRESP_MODESENSE_PGCCODE_VERIFY 0x07 /* Verify error recovery mode page */
#define SCSIRESP_MODESENSE_PGCCODE_CACHING 0x08 /* Caching mode page */
#define SCSIRESP_MODESENSE_PGCCODE_CONTROL 0x0a /* Control mode page (0x0a/0x00) */
#define SCSIRESP_MODESENSE_PGCCODE_CONTROLEXT 0x0a /* Control extension mode page (0x0a/0x01) */
#define SCSIRESP_MODESENSE_PGCCODE_MEDIUMTYPES 0x0b /* Medum types supported mode page (obsolete) */
#define SCSIRESP_MODESENSE_PGCCODE_NP 0x0c /* Notch and partition mode page (obsolete) */
#define SCSIRESP_MODESENSE_PGCCODE_XOR 0x10 /* XOR control mode page */
#define SCSIRESP_MODESENSE_PGCCODE_ES 0x14 /* Enclosure services mode page */
#define SCSIRESP_MODESENSE_PGCCODE_PSLUN 0x18 /* Protocol-specific LUN mode page */
#define SCSIRESP_MODESENSE_PGCCODE_PSPORT 0x19 /* Protocol-specific port mode page */
#define SCSIRESP_MODESENSE_PGCCODE_POWER 0x1a /* Power condition mode page */
#define SCSIRESP_MODESENSE_PGCCODE_IE 0x1c /* Informational exceptions control mode page (0x1c/0x00) */
#define SCSIRESP_MODESENSE_PGCCODE_BC 0x1c /* Background control mode page (0x1c/0x01) */
#define SCSIRESP_MODESENSE_PGCCODE_RETURNALL 0x3f /* Return all mode pages */
/* Direct-access caching mode page */
#define SCSIRESP_CACHINGMODEPG_PS 0x80 /* Byte 0, Bit 7: PS */
#define SCSIRESP_CACHINGMODEPG_SPF 0x60 /* Byte 0, Bit 6: SPF */
#define SCSIRESP_CACHINGMODEPG_IC 0x80 /* Byte 2, Bit 7: IC */
#define SCSIRESP_CACHINGMODEPG_ABPF 0x40 /* Byte 2, Bit 6: ABPF */
#define SCSIRESP_CACHINGMODEPG_CAP 0x20 /* Byte 2, Bit 5: CAP */
#define SCSIRESP_CACHINGMODEPG_DISC 0x10 /* Byte 2, Bit 4: DISC */
#define SCSIRESP_CACHINGMODEPG_SIZE 0x08 /* Byte 2, Bit 3: SIZE */
#define SCSIRESP_CACHINGMODEPG_WCE 0x04 /* Byte 2, Bit 2: Write cache enable (WCE) */
#define SCSIRESP_CACHINGMODEPG_MF 0x02 /* Byte 2, Bit 1: MF */
#define SCSIRESP_CACHINGMODEPG_RCD 0x01 /* Byte 2, Bit 0: Read cache disable (RCD) */
#define SCSIRESP_MODEPARMHDR_DAPARM_WP 0x80 /* Bit 7: WP (Direct-access block devices only) */
#define SCSIRESP_MODEPARMHDR_DAPARM_DBPFUA 0x10 /* Bit 4: DBOFUA (Direct-access block devices only) */
#define SCSIRESP_PAGEFMT_PS 0x80 /* Bit 7: PS */
#define SCSIRESP_PAGEFMT_SPF 0x40 /* Bit 6: SPF */
#define SCSIRESP_PAGEFMT_PGCODEMASK 0x3f /* Bits 0-5: Page code */
/* Prevent / Allow Medium Removal */
#define SCSICMD_PREVENTMEDIUMREMOVAL_TRANSPORT 0x01 /* Removal prohibited from data transport */
#define SCSICMD_PREVENTMEDIUMREMOVAL_MCHANGER 0x02 /* Removal prohibited from medium changer */
/* Read format capacities */
#define SCIRESP_RDFMTCAPACITIES_UNFORMATED 0x01 /* Unformatted media */
#define SCIRESP_RDFMTCAPACITIES_FORMATED 0x02 /* Formatted media */
#define SCIRESP_RDFMTCAPACITIES_NOMEDIA 0x03 /* No media */
/* Read 6 */
#define SCSICMD_READ6_MSLBAMASK 0x1f
/* Write 6 */
#define SCSICMD_WRITE6_MSLBAMASK 0x1f
/* Mode Select 10 */
#define SCSICMD_MODESELECT10_PF 0x10 /* Bit 4: PF */
#define SCSICMD_MODESELECT10_SP 0x01 /* Bit 0: SP */
/* Mode Sense 10 */
#define SCSICMD_MODESENSE10_LLBAA 0x10 /* Bit 4: LLBAA */
#define SCSICMD_MODESENSE10_DBD 0x08 /* Bit 3: PF */
/* Read 10 */
#define SCSICMD_READ10FLAGS_RDPROTECTMASK 0xe0
#define SCSICMD_READ10FLAGS_DPO 0x10 /* Disable Page Out */
#define SCSICMD_READ10FLAGS_FUA 0x08
#define SCSICMD_READ10FLAGS_FUANV 0x02
/* Write 10 */
#define SCSICMD_WRITE10FLAGS_WRPROTECTMASK 0xe0
#define SCSICMD_WRITE10FLAGS_DPO 0x10 /* Disable Page Out */
#define SCSICMD_WRITE10FLAGS_FUA 0x08
#define SCSICMD_WRITE10FLAGS_FUANV 0x02
/* Verify 10 */
#define SCSICMD_VERIFY10_VRPROTECTMASK 0xe0 /* Byte 1: Bits 5-7: VRPROTECT */
#define SCSICMD_VERIFY10_DPO 0x10 /* Byte 1: Bit 4: Disable Page Out (DPO) */
#define SCSICMD_VERIFY10_BYTCHK 0x02 /* Byte 1: Bit 2: BytChk */
/* Read 12 */
#define SCSICMD_READ12FLAGS_RDPROTECTMASK 0xe0
#define SCSICMD_READ12FLAGS_DPO 0x10 /* Disable Page Out */
#define SCSICMD_READ12FLAGS_FUA 0x08
#define SCSICMD_READ12FLAGS_FUANV 0x02
/* Write 12 */
#define SCSICMD_WRITE12FLAGS_WRPROTECTMASK 0xe0
#define SCSICMD_WRITE12FLAGS_DPO 0x10 /* Disable Page Out */
#define SCSICMD_WRITE12FLAGS_FUA 0x08
#define SCSICMD_WRITE12FLAGS_FUANV 0x02
/* Verify 12 */
#define SCSICMD_VERIFY12_VRPROTECTMASK 0xe0 /* Byte 1: Bits 5-7: VRPROTECT */
#define SCSICMD_VERIFY12_DPO 0x10 /* Byte 1: Bit 4: Disable Page Out (DPO) */
#define SCSICMD_VERIFY12_BYTCHK 0x02 /* Byte 1: Bit 2: BytChk */
/****************************************************************************
* Public Types
****************************************************************************/
/* Format structures for selected SCSI primary commands */
#define SCSICMD_TESTUNITREADY_SIZEOF 6
struct scsicmd_requestsense_s
{
uint8_t opcode; /* 0: 0x03 */
uint8_t flags; /* 1: See SCSICMD_REQUESTSENSE_FLAGS_* */
uint8_t reserved[2]; /* 2-3: Reserved */
uint8_t alloclen; /* 4: Allocation length */
uint8_t control; /* 5: Control */
};
#define SCSICMD_REQUESTSENSE_SIZEOF 6
#define SCSICMD_REQUESTSENSE_MSSIZEOF 12 /* MS-Windows REQUEST SENSE with cbw->cdblen == 12 */
struct scsiresp_fixedsensedata_s
{
uint8_t code; /* 0: Response code See SCSIRESP_SENSEDATA_*FIXED defns */
uint8_t obsolete; /* 1: */
uint8_t flags; /* 2: See SCSIRESP_SENSEDATA_* definitions */
uint8_t info[4]; /* 3-6: Information */
uint8_t len; /* 7: Additional length */
uint8_t cmdinfo[4]; /* 8-11: Command-specific information */
uint8_t code2; /* 12: Additional sense code */
uint8_t qual2; /* 13: Additional sense code qualifier */
uint8_t fru; /* 14: Field replacement unit code */
uint8_t key[3]; /* 15-17: Sense key specific */
/* 18-: Additional bytes may follow */
};
#define SCSIRESP_FIXEDSENSEDATA_SIZEOF 18 /* Minimum size */
struct scscicmd_inquiry_s
{
uint8_t opcode; /* 0: 0x12 */
uint8_t flags; /* 1: See SCSICMD_INQUIRY_FLAGS_* */
uint8_t pagecode; /* 2: Page code */
uint8_t alloclen[2]; /* 3-4: Allocation length */
uint8_t control; /* 5: Control */
};
#define SCSICMD_INQUIRY_SIZEOF 6
struct scsiresp_inquiry_s
{
/* Mandatory */
uint8_t qualtype; /* 0: Bits 5-7: Peripheral qualifier; Bits 0-4: Peripheral device type */
uint8_t flags1; /* 1: See SCSIRESP_INQUIRY_FLAGS1_* */
uint8_t version; /* 2: Version */
uint8_t flags2; /* 3: See SCSIRESP_INQUIRY_FLAGS2_* */
uint8_t len; /* 4: Additional length */
uint8_t flags3; /* 5: See SCSIRESP_INQUIRY_FLAGS3_* */
uint8_t flags4; /* 6: See SCSIRESP_INQUIRY_FLAGS4_* */
uint8_t flags5; /* 7: See SCSIRESP_INQUIRY_FLAGS5_* */
uint8_t vendorid[8]; /* 8-15: T10 Vendor Identification */
uint8_t productid[16]; /* 16-31: Product Identification */
uint8_t revision[4]; /* 32-35: Product Revision Level */
/* Optional */
uint8_t vendor[20]; /* 36-55: Vendor specific */
uint8_t flags6; /* 56: See SCSIRESP_INQUIRY_FLAGS6_* */
uint8_t reserved1; /* 57: Reserved */
uint8_t version1[2]; /* 58-59: Version Descriptor 1 */
uint8_t version2[2]; /* 60-61: Version Descriptor 2 */
uint8_t version3[2]; /* 62-63: Version Descriptor 3 */
uint8_t version4[2]; /* 64-65: Version Descriptor 4 */
uint8_t version5[2]; /* 66-67: Version Descriptor 5 */
uint8_t version6[2]; /* 68-69: Version Descriptor 6 */
uint8_t version7[2]; /* 70-71: Version Descriptor 7 */
uint8_t version8[2]; /* 72-73: Version Descriptor 8 */
uint8_t reserved2[22]; /* 74-95: Reserved */
/* 96-: Vendor-specific parameters may follow */
};
#define SCSIRESP_INQUIRY_SIZEOF 36 /* Minimum size */
struct scsicmd_modeselect6_s
{
uint8_t opcode; /* 0x15 */
uint8_t flags; /* 1: See SCSICMD_MODESELECT6_FLAGS_* */
uint8_t reserved[2]; /* 2-3: Reserved */
uint8_t plen; /* 4: Parameter list length */
uint8_t control; /* 5: Control */
};
#define SCSICMD_MODESELECT6_SIZEOF 6
struct scsicmd_modesense6_s
{
uint8_t opcode; /* 0x1a */
uint8_t flags; /* 1: See SCSICMD_MODESENSE6_FLAGS_* */
uint8_t pcpgcode; /* 2: Bits 6-7: PC, bits 0-5: page code */
uint8_t subpgcode; /* 3: subpage code */
uint8_t alloclen; /* 4: Allocation length */
uint8_t control; /* 5: Control */
};
#define SCSICMD_MODESENSE6_SIZEOF 6
struct scsiresp_modeparameterhdr6_s
{
uint8_t mdlen; /* 0: Mode data length */
uint8_t type; /* 1: Medium type */
uint8_t param; /* 2: Device-specific parameter */
uint8_t bdlen; /* 3: Block descriptor length */
};
#define SCSIRESP_MODEPARAMETERHDR6_SIZEOF 4
struct scsiresp_blockdesc_s
{
uint8_t density; /* 0: density code */
uint8_t nblocks[3]; /* 1-3: Number of blocks */
uint8_t reserved; /* 4: reserved */
uint8_t blklen[3]; /* 5-7: Block len */
};
#define SCSIRESP_BLOCKDESC_SIZEOF 8
struct scsiresp_pageformat_s
{
uint8_t pgcode; /* 0: See SCSIRESP_PAGEFMT_* definitions */
uint8_t pglen; /* 1: Page length (n-1) */
uint8_t parms[1]; /* 2-n: Mode parameters */
};
struct scsiresp_subpageformat_s
{
uint8_t pgcode; /* 0: See SCSIRESP_PAGEFMT_* definitions */
uint8_t subpgcode; /* 1: sub-page code */
uint8_t pglen[2]; /* 2-3: Page length (n-3) */
uint8_t parms[1]; /* 4-n: Mode parameters */
};
struct scsiresp_cachingmodepage_s
{
uint8_t pgcode; /* 0: Bit 7: PS; Bit 6: SPF, Bits 0-5: page code == 8 */
uint8_t len; /* 1: Page length (18) */
uint8_t flags1; /* 2: See SCSIRESP_CACHINGMODEPG_* definitions */
uint8_t priority; /* 3: Bits 4-7: Demand read retention priority; Bits 0-3: Write retention priority */
uint8_t dpflen[2]; /* 4-5: Disable prefetch transfer length */
uint8_t minpf[2]; /* 6-7: Minimum pre-fetch */
uint8_t maxpf[2]; /* 8-9: Maximum pre-fetch */
uint8_t maxpfc[2]; /* 10-11: Maximum pref-fetch ceiling */
uint8_t flags2; /* 12: See SCSIRESP_CACHINGMODEPG_* definitions */
uint8_t nsegments; /* 13: Number of cache segments */
uint8_t segsize[2]; /* 14-15: Cache segment size */
uint8_t reserved; /* 16: Reserved */
uint8_t obsolete[3]; /* 17-19: Obsolete */
};
/* Format structures for selected SCSI block commands */
struct scsicmd_read6_s
{
uint8_t opcode; /* 0: 0x08 */
uint8_t mslba; /* 1: Bits 5-7: reserved; Bits 0-6: MS Logical Block Address (LBA) */
uint8_t lslba[2]; /* 2-3: LS Logical Block Address (LBA) */
uint8_t xfrlen; /* 4: Transfer length (in contiguous logical blocks) */
uint8_t control; /* 5: Control */
};
#define SCSICMD_READ6_SIZEOF 6
struct scsicmd_write6_s
{
uint8_t opcode; /* 0: 0x0a */
uint8_t mslba; /* 1: Bits 5-7: reserved; Bits 0-6: MS Logical Block Address (LBA) */
uint8_t lslba[2]; /* 2-3: LS Logical Block Address (LBA) */
uint8_t xfrlen; /* 4: Transfer length (in contiguous logical blocks) */
uint8_t control; /* 5: Control */
};
#define SCSICMD_WRITE6_SIZEOF 6
struct scsicmd_startstopunit_s
{
uint8_t opcode; /* 0: 0x1b */
uint8_t immed; /* 1: Bits 2-7: Reserved, Bit 0: Immed */
uint8_t reserved; /* 2: reserved */
uint8_t pcm; /* 3: Bits 4-7: Reserved, Bits 0-3: Power condition modifier */
uint8_t pc; /* 4: Bits 4-7: Power condition, Bit 2: NO_FLUSH, Bit 1: LOEJ, Bit 0: START */
uint8_t control; /* 5: Control */
};
#define SCSICMD_STARTSTOPUNIT_SIZEOF 6
struct scsicmd_preventmediumremoval_s
{
uint8_t opcode; /* 0: 0x1e */
uint8_t reserved[3]; /* 1-3: Reserved */
uint8_t prevent; /* 4: Bits 2-7: Reserved, Bits 0:1: prevent */
uint8_t control; /* 5: Control */
};
#define SCSICMD_PREVENTMEDIUMREMOVAL_SIZEOF 6
struct scsicmd_readformatcapcacities_s
{
uint8_t opcode; /* 0: 0x23 */
uint8_t reserved[6]; /* 1-6: Reserved */
uint8_t alloclen[2]; /* 7-8: Allocation length */
uint8_t control; /* 9: Control */
};
#define SCSICMD_READFORMATCAPACITIES_SIZEOF 10
struct scsiresp_readformatcapacities_s
{
/* Current capacity header */
uint8_t reserved[3]; /* 0-2: Reserved */
uint8_t listlen; /* 3: Capacity list length */
/* Current/Maximum Capacity Descriptor (actually a separate structure) */
uint8_t nblocks[4]; /* 4-7: Number of blocks */
uint8_t type; /* 8: Bits 2-7: Reserved, Bits 0-1: Descriptor type */
uint8_t blocklen[3]; /* 9-11: Block length */
};
#define SCSIRESP_READFORMATCAPACITIES_SIZEOF 12
#define SCSIRESP_CURRCAPACITYDESC_SIZEOF 8
struct scsiresp_formattedcapacitydesc_s
{
uint8_t nblocks[4]; /* 0-3: Number of blocks */
uint8_t type; /* 4: Bits 2-7: Type, bits 0-1, reserved */
uint8_t param[3]; /* 5-7: Type dependent parameter */
};
#define SCSIRESP_FORMATTEDCAPACITYDESC_SIZEOF 8
struct scsicmd_readcapacity10_s
{
uint8_t opcode; /* 0: 0x25 */
uint8_t reserved1; /* 1: Bits 1-7: Reserved, Bit 0: Obsolete */
uint8_t lba[4]; /* 2-5: Logical block address (LBA) */
uint8_t reserved2[2]; /* 6-7: Reserved */
uint8_t pmi; /* 8: Bits 1-7 Reserved; Bit 0: PMI */
uint8_t control; /* 9: Control */
};
#define SCSICMD_READCAPACITY10_SIZEOF 10
struct scsiresp_readcapacity10_s
{
uint8_t lba[4]; /* 0-3: Returned logical block address (LBA) */
uint8_t blklen[4]; /* 4-7: Logical block length (in bytes) */
};
#define SCSIRESP_READCAPACITY10_SIZEOF 8
struct scsicmd_read10_s
{
uint8_t opcode; /* 0: 0x28 */
uint8_t flags; /* 1: See SCSICMD_READ10FLAGS_* */
uint8_t lba[4]; /* 2-5: Logical Block Address (LBA) */
uint8_t groupno; /* 6: Bits 5-7: reserved; Bits 0-6: group number */
uint8_t xfrlen[2]; /* 7-8: Transfer length (in contiguous logical blocks) */
uint8_t control; /* 9: Control */
};
#define SCSICMD_READ10_SIZEOF 10
struct scsicmd_write10_s
{
uint8_t opcode; /* 0: 0x2a */
uint8_t flags; /* 1: See SCSICMD_WRITE10FLAGS_* */
uint8_t lba[4]; /* 2-5: Logical Block Address (LBA) */
uint8_t groupno; /* 6: Bits 5-7: reserved; Bits 0-6: group number */
uint8_t xfrlen[2]; /* 7-8: Transfer length (in contiguous logical blocks) */
uint8_t control; /* 9: Control */
};
#define SCSICMD_WRITE10_SIZEOF 10
struct scsicmd_verify10_s
{
uint8_t opcode; /* 0: 0x2f */
uint8_t flags; /* 1: See SCSICMD_VERIFY10_* definitions */
uint8_t lba[4]; /* 2-5: Logical block address (LBA) */
uint8_t groupno; /* 6: Bit 7: restricted; Bits 5-6: Reserved, Bits 0-4: Group number */
uint8_t len[2]; /* 7-8: Verification length (in blocks) */
uint8_t control; /* 9: Control */
};
#define SCSICMD_VERIFY10_SIZEOF 10
struct scsicmd_synchronizecache10_s
{
uint8_t opcode; /* 0: 0x35 */
uint8_t flags; /* 1: See SCSICMD_SYNCHRONIZECACHE10_* definitions */
uint8_t lba[4]; /* 2-5: Logical block address (LBA) */
uint8_t groupno; /* 6: Bit 7: restricted; Bits 5-6: Reserved, Bits 0-4: Group number */
uint8_t len[2]; /* 7-8: Number of logical blocks */
uint8_t control; /* 9: Control */
};
#define SCSICMD_SYNCHRONIZECACHE10_SIZEOF 10
struct scsicmd_modeselect10_s
{
uint8_t opcode; /* 0: 0x55 */
uint8_t flags; /* 1: See SCSICMD_MODESELECT10_FLAGS_* */
uint8_t reserved[5]; /* 2-6: Reserved */
uint8_t parmlen[2]; /* 7-8: Parameter list length */
uint8_t control; /* 9: Control */
};
#define SCSICMD_MODESELECT10_SIZEOF 10
struct scsiresp_modeparameterhdr10_s
{
uint8_t mdlen[2]; /* 0-1: Mode data length */
uint8_t type; /* 2: Medium type */
uint8_t param; /* 3: Device-specific parameter */
uint8_t reserved[2]; /* 4-5: reserved */
uint8_t bdlen[2]; /* 6-7: Block descriptor length */
};
#define SCSIRESP_MODEPARAMETERHDR10_SIZEOF 8
struct scsicmd_modesense10_s
{
uint8_t opcode; /* O: 0x5a */
uint8_t flags; /* 1: See SCSICMD_MODESENSE10_FLAGS_* */
uint8_t pcpgcode; /* 2: Bits 6-7: PC, bits 0-5: page code */
uint8_t subpgcode; /* 3: subpage code */
uint8_t reserved[3]; /* 4-6: reserved */
uint8_t alloclen[2]; /* 7-8: Allocation length */
uint8_t control; /* 9: Control */
};
#define SCSICMD_MODESENSE10_SIZEOF 10
struct scsicmd_readcapacity16_s
{
uint8_t opcode; /* 0: 0x9e */
uint8_t action; /* 1: Bits 5-7: Reserved, Bits 0-4: Service action */
uint8_t lba[8]; /* 2-9: Logical block address (LBA) */
uint8_t len[4]; /* 10-13: Allocation length */
uint8_t reserved; /* 14: Reserved */
uint8_t control; /* 15: Control */
};
#define SCSICMD_READCAPACITY16_SIZEOF 16
struct scsicmd_read12_s
{
uint8_t opcode; /* 0: 0xa8 */
uint8_t flags; /* 1: See SCSICMD_READ12FLAGS_* */
uint8_t lba[4]; /* 2-5: Logical Block Address (LBA) */
uint8_t xfrlen[4]; /* 6-9: Transfer length (in contiguous logical blocks) */
uint8_t groupno; /* 10: Bit 7: restricted; Bits 5-6: reserved; Bits 0-6: group number */
uint8_t control; /* 11: Control */
};
#define SCSICMD_READ12_SIZEOF 12
struct scsicmd_write12_s
{
uint8_t opcode; /* 0: 0xaa */
uint8_t flags; /* 1: See SCSICMD_WRITE12FLAGS_* */
uint8_t lba[4]; /* 2-5: Logical Block Address (LBA) */
uint8_t xfrlen[4]; /* 6-9: Transfer length (in contiguous logical blocks) */
uint8_t groupno; /* 10: Bit 7: restricted; Bits 5-6: reserved; Bits 0-6: group number */
uint8_t control; /* 11: Control */
};
#define SCSICMD_WRITE12_SIZEOF 12
struct scsicmd_verify12_s
{
uint8_t opcode; /* 0: 0xaf */
uint8_t flags; /* 1: See SCSICMD_VERIFY12_* definitions */
uint8_t lba[4]; /* 2-5: Logical block address (LBA) */
uint8_t len[4]; /* 6-9: Verification length */
uint8_t groupno; /* 10: Bit 7: restricted; Bits 5-6: Reserved, Bits 0-4: Group number */
uint8_t control; /* 11: Control */
};
#define SCSICMD_VERIFY12_SIZEOF 12
/****************************************************************************
* Public Functions Definitions
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __INCLUDE_NUTTX_SCSI_H */

View File

@ -1,997 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
* Copyright (c) 2024, zhihong chen
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_msc.h"
#include "usb_scsi.h"
#if defined(CONFIG_USBDEV_MSC_THREAD)
#include "usb_osal.h"
#elif defined(CONFIG_USBDEV_MSC_POLLING)
#include "chry_ringbuffer.h"
#endif
#define MSD_OUT_EP_IDX 0
#define MSD_IN_EP_IDX 1
/* Describe EndPoints configuration */
static struct usbd_endpoint mass_ep_data[CONFIG_USBDEV_MAX_BUS][2];
/* MSC Bulk-only Stage */
enum Stage {
MSC_READ_CBW = 0, /* Command Block Wrapper */
MSC_DATA_OUT = 1, /* Data Out Phase */
MSC_DATA_IN = 2, /* Data In Phase */
MSC_SEND_CSW = 3, /* Command Status Wrapper */
MSC_WAIT_CSW = 4, /* Command Status Wrapper */
};
/* Device data structure */
USB_NOCACHE_RAM_SECTION struct usbd_msc_priv {
/* state of the bulk-only state machine */
enum Stage stage;
USB_MEM_ALIGNX struct CBW cbw;
USB_MEM_ALIGNX struct CSW csw;
bool readonly;
bool popup;
uint8_t sKey; /* Sense key */
uint8_t ASC; /* Additional Sense Code */
uint8_t ASQ; /* Additional Sense Qualifier */
uint8_t max_lun;
uint32_t start_sector;
uint32_t nsectors;
uint32_t scsi_blk_size[CONFIG_USBDEV_MSC_MAX_LUN];
uint32_t scsi_blk_nbr[CONFIG_USBDEV_MSC_MAX_LUN];
USB_MEM_ALIGNX uint8_t block_buffer[CONFIG_USBDEV_MSC_MAX_BUFSIZE];
#if defined(CONFIG_USBDEV_MSC_THREAD)
usb_osal_mq_t usbd_msc_mq;
usb_osal_thread_t usbd_msc_thread;
uint32_t nbytes;
#elif defined(CONFIG_USBDEV_MSC_POLLING)
chry_ringbuffer_t msc_rb;
uint8_t msc_rb_pool[2];
uint32_t nbytes;
#endif
} g_usbd_msc[CONFIG_USBDEV_MAX_BUS];
#ifdef CONFIG_USBDEV_MSC_THREAD
static void usbdev_msc_thread(void *argument);
#endif
static void usdb_msc_set_max_lun(uint8_t busid)
{
g_usbd_msc[busid].max_lun = CONFIG_USBDEV_MSC_MAX_LUN - 1u;
}
static void usbd_msc_reset(uint8_t busid)
{
g_usbd_msc[busid].stage = MSC_READ_CBW;
g_usbd_msc[busid].readonly = false;
}
static int msc_storage_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("MSC Class request: "
"bRequest 0x%02x\r\n",
setup->bRequest);
switch (setup->bRequest) {
case MSC_REQUEST_RESET:
usbd_msc_reset(busid);
break;
case MSC_REQUEST_GET_MAX_LUN:
(*data)[0] = g_usbd_msc[busid].max_lun;
*len = 1;
break;
default:
USB_LOG_WRN("Unhandled MSC Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
return 0;
}
void msc_storage_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
(void)arg;
switch (event) {
case USBD_EVENT_INIT:
#if defined(CONFIG_USBDEV_MSC_THREAD)
g_usbd_msc[busid].usbd_msc_mq = usb_osal_mq_create(1);
if (g_usbd_msc[busid].usbd_msc_mq == NULL) {
USB_LOG_ERR("No memory to alloc for g_usbd_msc[busid].usbd_msc_mq\r\n");
}
g_usbd_msc[busid].usbd_msc_thread = usb_osal_thread_create("usbd_msc", CONFIG_USBDEV_MSC_STACKSIZE, CONFIG_USBDEV_MSC_PRIO, usbdev_msc_thread, (void *)busid);
if (g_usbd_msc[busid].usbd_msc_thread == NULL) {
USB_LOG_ERR("No memory to alloc for g_usbd_msc[busid].usbd_msc_thread\r\n");
}
#elif defined(CONFIG_USBDEV_MSC_POLLING)
chry_ringbuffer_init(&g_usbd_msc[busid].msc_rb, g_usbd_msc[busid].msc_rb_pool, sizeof(g_usbd_msc[busid].msc_rb_pool));
#endif
break;
case USBD_EVENT_DEINIT:
#if defined(CONFIG_USBDEV_MSC_THREAD)
if (g_usbd_msc[busid].usbd_msc_mq) {
usb_osal_mq_delete(g_usbd_msc[busid].usbd_msc_mq);
}
if (g_usbd_msc[busid].usbd_msc_thread) {
usb_osal_thread_delete(g_usbd_msc[busid].usbd_msc_thread);
}
#endif
break;
case USBD_EVENT_RESET:
usbd_msc_reset(busid);
break;
case USBD_EVENT_CONFIGURED:
USB_LOG_DBG("Start reading cbw\r\n");
usbd_ep_start_read(busid, mass_ep_data[busid][MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&g_usbd_msc[busid].cbw, USB_SIZEOF_MSC_CBW);
break;
default:
break;
}
}
static void usbd_msc_bot_abort(uint8_t busid)
{
if ((g_usbd_msc[busid].cbw.bmFlags == 0) && (g_usbd_msc[busid].cbw.dDataLength != 0)) {
usbd_ep_set_stall(busid, mass_ep_data[busid][MSD_OUT_EP_IDX].ep_addr);
}
usbd_ep_set_stall(busid, mass_ep_data[busid][MSD_IN_EP_IDX].ep_addr);
usbd_ep_start_read(busid, mass_ep_data[busid][0].ep_addr, (uint8_t *)&g_usbd_msc[busid].cbw, USB_SIZEOF_MSC_CBW);
}
static void usbd_msc_send_csw(uint8_t busid, uint8_t CSW_Status)
{
g_usbd_msc[busid].csw.dSignature = MSC_CSW_Signature;
g_usbd_msc[busid].csw.bStatus = CSW_Status;
/* updating the State Machine , so that we wait CSW when this
* transfer is complete, ie when we get a bulk in callback
*/
g_usbd_msc[busid].stage = MSC_WAIT_CSW;
USB_LOG_DBG("Send csw\r\n");
usbd_ep_start_write(busid, mass_ep_data[busid][MSD_IN_EP_IDX].ep_addr, (uint8_t *)&g_usbd_msc[busid].csw, sizeof(struct CSW));
}
static void usbd_msc_send_info(uint8_t busid, uint8_t *buffer, uint8_t size)
{
size = MIN(size, g_usbd_msc[busid].cbw.dDataLength);
/* updating the State Machine , so that we send CSW when this
* transfer is complete, ie when we get a bulk in callback
*/
g_usbd_msc[busid].stage = MSC_SEND_CSW;
usbd_ep_start_write(busid, mass_ep_data[busid][MSD_IN_EP_IDX].ep_addr, buffer, size);
g_usbd_msc[busid].csw.dDataResidue -= size;
g_usbd_msc[busid].csw.bStatus = CSW_STATUS_CMD_PASSED;
}
static bool SCSI_processWrite(uint8_t busid, uint32_t nbytes);
static bool SCSI_processRead(uint8_t busid);
/**
* @brief SCSI_SetSenseData
* Load the last error code in the error list
* @param sKey: Sense Key
* @param ASC: Additional Sense Code
* @retval none
*/
static void SCSI_SetSenseData(uint8_t busid, uint32_t KCQ)
{
g_usbd_msc[busid].sKey = (uint8_t)(KCQ >> 16);
g_usbd_msc[busid].ASC = (uint8_t)(KCQ >> 8);
g_usbd_msc[busid].ASQ = (uint8_t)(KCQ);
}
/**
* @brief SCSI Command list
*
*/
static bool SCSI_testUnitReady(uint8_t busid, uint8_t **data, uint32_t *len)
{
if (g_usbd_msc[busid].cbw.dDataLength != 0U) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
*data = NULL;
*len = 0;
return true;
}
static bool SCSI_requestSense(uint8_t busid, uint8_t **data, uint32_t *len)
{
uint8_t data_len = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
if (g_usbd_msc[busid].cbw.dDataLength == 0U) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
if (g_usbd_msc[busid].cbw.CB[4] < SCSIRESP_FIXEDSENSEDATA_SIZEOF) {
data_len = g_usbd_msc[busid].cbw.CB[4];
}
uint8_t request_sense[SCSIRESP_FIXEDSENSEDATA_SIZEOF] = {
0x70,
0x00,
0x00, /* Sense Key */
0x00,
0x00,
0x00,
0x00,
SCSIRESP_FIXEDSENSEDATA_SIZEOF - 8,
0x00,
0x00,
0x00,
0x00,
0x00, /* Additional Sense Code */
0x00, /* Additional Sense Request */
0x00,
0x00,
0x00,
0x00,
};
request_sense[2] = g_usbd_msc[busid].sKey;
request_sense[12] = g_usbd_msc[busid].ASC;
request_sense[13] = g_usbd_msc[busid].ASQ;
#if 0
request_sense[ 2] = 0x06; /* UNIT ATTENTION */
request_sense[12] = 0x28; /* Additional Sense Code: Not ready to ready transition */
request_sense[13] = 0x00; /* Additional Sense Code Qualifier */
#endif
#if 0
request_sense[ 2] = 0x02; /* NOT READY */
request_sense[12] = 0x3A; /* Additional Sense Code: Medium not present */
request_sense[13] = 0x00; /* Additional Sense Code Qualifier */
#endif
#if 0
request_sense[ 2] = 0x05; /* ILLEGAL REQUEST */
request_sense[12] = 0x20; /* Additional Sense Code: Invalid command */
request_sense[13] = 0x00; /* Additional Sense Code Qualifier */
#endif
#if 0
request_sense[ 2] = 0x00; /* NO SENSE */
request_sense[12] = 0x00; /* Additional Sense Code: No additional code */
request_sense[13] = 0x00; /* Additional Sense Code Qualifier */
#endif
memcpy(*data, (uint8_t *)request_sense, data_len);
*len = data_len;
return true;
}
static bool SCSI_inquiry(uint8_t busid, uint8_t **data, uint32_t *len)
{
uint8_t data_len = SCSIRESP_INQUIRY_SIZEOF;
uint8_t inquiry00[6] = {
0x00,
0x00,
0x00,
(0x06 - 4U),
0x00,
0x80
};
/* USB Mass storage VPD Page 0x80 Inquiry Data for Unit Serial Number */
uint8_t inquiry80[8] = {
0x00,
0x80,
0x00,
0x08,
0x20, /* Put Product Serial number */
0x20,
0x20,
0x20
};
uint8_t inquiry[SCSIRESP_INQUIRY_SIZEOF] = {
/* 36 */
/* LUN 0 */
0x00,
0x80,
0x02,
0x02,
(SCSIRESP_INQUIRY_SIZEOF - 5),
0x00,
0x00,
0x00,
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', /* Product : 16 Bytes */
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ' ', ' ', ' ' /* Version : 4 Bytes */
};
memcpy(&inquiry[8], CONFIG_USBDEV_MSC_MANUFACTURER_STRING, strlen(CONFIG_USBDEV_MSC_MANUFACTURER_STRING));
memcpy(&inquiry[16], CONFIG_USBDEV_MSC_PRODUCT_STRING, strlen(CONFIG_USBDEV_MSC_PRODUCT_STRING));
memcpy(&inquiry[32], CONFIG_USBDEV_MSC_VERSION_STRING, strlen(CONFIG_USBDEV_MSC_VERSION_STRING));
if (g_usbd_msc[busid].cbw.dDataLength == 0U) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
if ((g_usbd_msc[busid].cbw.CB[1] & 0x01U) != 0U) { /* Evpd is set */
if (g_usbd_msc[busid].cbw.CB[2] == 0U) { /* Request for Supported Vital Product Data Pages*/
data_len = 0x06;
memcpy(*data, (uint8_t *)inquiry00, data_len);
} else if (g_usbd_msc[busid].cbw.CB[2] == 0x80U) { /* Request for VPD page 0x80 Unit Serial Number */
data_len = 0x08;
memcpy(*data, (uint8_t *)inquiry80, data_len);
} else { /* Request Not supported */
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDFIELDINCBA);
return false;
}
} else {
if (g_usbd_msc[busid].cbw.CB[4] < SCSIRESP_INQUIRY_SIZEOF) {
data_len = g_usbd_msc[busid].cbw.CB[4];
}
memcpy(*data, (uint8_t *)inquiry, data_len);
}
*len = data_len;
return true;
}
static bool SCSI_startStopUnit(uint8_t busid, uint8_t **data, uint32_t *len)
{
if (g_usbd_msc[busid].cbw.dDataLength != 0U) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
if ((g_usbd_msc[busid].cbw.CB[4] & 0x3U) == 0x1U) /* START=1 */
{
//SCSI_MEDIUM_UNLOCKED;
} else if ((g_usbd_msc[busid].cbw.CB[4] & 0x3U) == 0x2U) /* START=0 and LOEJ Load Eject=1 */
{
//SCSI_MEDIUM_EJECTED;
g_usbd_msc[busid].popup = true;
} else if ((g_usbd_msc[busid].cbw.CB[4] & 0x3U) == 0x3U) /* START=1 and LOEJ Load Eject=1 */
{
//SCSI_MEDIUM_UNLOCKED;
} else {
}
*data = NULL;
*len = 0;
return true;
}
static bool SCSI_preventAllowMediaRemoval(uint8_t busid, uint8_t **data, uint32_t *len)
{
if (g_usbd_msc[busid].cbw.dDataLength != 0U) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
if (g_usbd_msc[busid].cbw.CB[4] == 0U) {
//SCSI_MEDIUM_UNLOCKED;
} else {
//SCSI_MEDIUM_LOCKED;
}
*data = NULL;
*len = 0;
return true;
}
static bool SCSI_modeSense6(uint8_t busid, uint8_t **data, uint32_t *len)
{
uint8_t data_len = 4;
if (g_usbd_msc[busid].cbw.dDataLength == 0U) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
if (g_usbd_msc[busid].cbw.CB[4] < SCSIRESP_MODEPARAMETERHDR6_SIZEOF) {
data_len = g_usbd_msc[busid].cbw.CB[4];
}
uint8_t sense6[SCSIRESP_MODEPARAMETERHDR6_SIZEOF] = { 0x03, 0x00, 0x00, 0x00 };
if (g_usbd_msc[busid].readonly) {
sense6[2] = 0x80;
}
memcpy(*data, (uint8_t *)sense6, data_len);
*len = data_len;
return true;
}
static bool SCSI_modeSense10(uint8_t busid, uint8_t **data, uint32_t *len)
{
uint8_t data_len = 27;
if (g_usbd_msc[busid].cbw.dDataLength == 0U) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
if (g_usbd_msc[busid].cbw.CB[8] < 27) {
data_len = g_usbd_msc[busid].cbw.CB[8];
}
uint8_t sense10[27] = {
0x00,
0x26,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x08,
0x12,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00
};
memcpy(*data, (uint8_t *)sense10, data_len);
*len = data_len;
return true;
}
static bool SCSI_readFormatCapacity(uint8_t busid, uint8_t **data, uint32_t *len)
{
if (g_usbd_msc[busid].cbw.dDataLength == 0U) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
uint8_t format_capacity[SCSIRESP_READFORMATCAPACITIES_SIZEOF] = {
0x00,
0x00,
0x00,
0x08, /* Capacity List Length */
(uint8_t)((g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN] >> 24) & 0xff),
(uint8_t)((g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN] >> 16) & 0xff),
(uint8_t)((g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN] >> 8) & 0xff),
(uint8_t)((g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN] >> 0) & 0xff),
0x02, /* Descriptor Code: Formatted Media */
0x00,
(uint8_t)((g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN] >> 8) & 0xff),
(uint8_t)((g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN] >> 0) & 0xff),
};
memcpy(*data, (uint8_t *)format_capacity, SCSIRESP_READFORMATCAPACITIES_SIZEOF);
*len = SCSIRESP_READFORMATCAPACITIES_SIZEOF;
return true;
}
static bool SCSI_readCapacity10(uint8_t busid, uint8_t **data, uint32_t *len)
{
if (g_usbd_msc[busid].cbw.dDataLength == 0U) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
uint8_t capacity10[SCSIRESP_READCAPACITY10_SIZEOF] = {
(uint8_t)(((g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN] - 1) >> 24) & 0xff),
(uint8_t)(((g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN] - 1) >> 16) & 0xff),
(uint8_t)(((g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN] - 1) >> 8) & 0xff),
(uint8_t)(((g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN] - 1) >> 0) & 0xff),
(uint8_t)((g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN] >> 24) & 0xff),
(uint8_t)((g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN] >> 16) & 0xff),
(uint8_t)((g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN] >> 8) & 0xff),
(uint8_t)((g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN] >> 0) & 0xff),
};
memcpy(*data, (uint8_t *)capacity10, SCSIRESP_READCAPACITY10_SIZEOF);
*len = SCSIRESP_READCAPACITY10_SIZEOF;
return true;
}
static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
{
(void)data;
(void)len;
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */
USB_LOG_DBG("lba: 0x%04x\r\n", g_usbd_msc[busid].start_sector);
g_usbd_msc[busid].nsectors = GET_BE16(&g_usbd_msc[busid].cbw.CB[7]); /* Number of Blocks to transfer */
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc[busid].nsectors);
if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) {
SCSI_SetSenseData(busid, SCSI_KCQIR_LBAOUTOFRANGE);
USB_LOG_ERR("LBA out of range\r\n");
return false;
}
if (g_usbd_msc[busid].cbw.dDataLength != (g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN])) {
USB_LOG_ERR("scsi_blk_len does not match with dDataLength\r\n");
return false;
}
g_usbd_msc[busid].stage = MSC_DATA_IN;
#if defined(CONFIG_USBDEV_MSC_THREAD)
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
return true;
#elif defined(CONFIG_USBDEV_MSC_POLLING)
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_IN);
return true;
#else
return SCSI_processRead(busid);
#endif
}
static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len)
{
(void)data;
(void)len;
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */
USB_LOG_DBG("lba: 0x%04x\r\n", g_usbd_msc[busid].start_sector);
g_usbd_msc[busid].nsectors = GET_BE32(&g_usbd_msc[busid].cbw.CB[6]); /* Number of Blocks to transfer */
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc[busid].nsectors);
if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) {
SCSI_SetSenseData(busid, SCSI_KCQIR_LBAOUTOFRANGE);
USB_LOG_ERR("LBA out of range\r\n");
return false;
}
if (g_usbd_msc[busid].cbw.dDataLength != (g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN])) {
USB_LOG_ERR("scsi_blk_len does not match with dDataLength\r\n");
return false;
}
g_usbd_msc[busid].stage = MSC_DATA_IN;
#if defined(CONFIG_USBDEV_MSC_THREAD)
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
return true;
#elif defined(CONFIG_USBDEV_MSC_POLLING)
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_IN);
return true;
#else
return SCSI_processRead(busid);
#endif
}
static bool SCSI_write10(uint8_t busid, uint8_t **data, uint32_t *len)
{
uint32_t data_len = 0;
(void)data;
(void)len;
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */
USB_LOG_DBG("lba: 0x%04x\r\n", g_usbd_msc[busid].start_sector);
g_usbd_msc[busid].nsectors = GET_BE16(&g_usbd_msc[busid].cbw.CB[7]); /* Number of Blocks to transfer */
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc[busid].nsectors);
data_len = g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN];
if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) {
USB_LOG_ERR("LBA out of range\r\n");
return false;
}
if (g_usbd_msc[busid].cbw.dDataLength != data_len) {
return false;
}
g_usbd_msc[busid].stage = MSC_DATA_OUT;
data_len = MIN(data_len, CONFIG_USBDEV_MSC_MAX_BUFSIZE);
usbd_ep_start_read(busid, mass_ep_data[busid][MSD_OUT_EP_IDX].ep_addr, g_usbd_msc[busid].block_buffer, data_len);
return true;
}
static bool SCSI_write12(uint8_t busid, uint8_t **data, uint32_t *len)
{
uint32_t data_len = 0;
(void)data;
(void)len;
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */
USB_LOG_DBG("lba: 0x%04x\r\n", g_usbd_msc[busid].start_sector);
g_usbd_msc[busid].nsectors = GET_BE32(&g_usbd_msc[busid].cbw.CB[6]); /* Number of Blocks to transfer */
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc[busid].nsectors);
data_len = g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN];
if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) {
USB_LOG_ERR("LBA out of range\r\n");
return false;
}
if (g_usbd_msc[busid].cbw.dDataLength != data_len) {
return false;
}
g_usbd_msc[busid].stage = MSC_DATA_OUT;
data_len = MIN(data_len, CONFIG_USBDEV_MSC_MAX_BUFSIZE);
usbd_ep_start_read(busid, mass_ep_data[busid][MSD_OUT_EP_IDX].ep_addr, g_usbd_msc[busid].block_buffer, data_len);
return true;
}
/* do not use verify to reduce code size */
#if 0
static bool SCSI_verify10(uint8_t busid, uint8_t **data, uint32_t *len)
{
/* Logical Block Address of First Block */
uint32_t lba = 0;
uint32_t blk_num = 0;
if ((g_usbd_msc[busid].cbw.CB[1] & 0x02U) == 0x00U) {
return true;
}
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
if ((g_usbd_msc[busid].cbw.CB[1] & 0x02U) == 0x02U) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDFIELDINCBA);
return false; /* Error, Verify Mode Not supported*/
}
lba = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]);
USB_LOG_DBG("lba: 0x%x\r\n", lba);
g_usbd_msc[busid].scsi_blk_addr = lba * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN];
/* Number of Blocks to transfer */
blk_num = GET_BE16(&g_usbd_msc[busid].cbw.CB[7]);
USB_LOG_DBG("num (block) : 0x%x\r\n", blk_num);
g_usbd_msc[busid].scsi_blk_len = blk_num * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN];
if ((lba + blk_num) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) {
USB_LOG_ERR("LBA out of range\r\n");
return false;
}
if (g_usbd_msc[busid].cbw.dDataLength != g_usbd_msc[busid].scsi_blk_len) {
return false;
}
g_usbd_msc[busid].stage = MSC_DATA_OUT;
return true;
}
#endif
static bool SCSI_processRead(uint8_t busid)
{
uint32_t transfer_len;
USB_LOG_DBG("read lba:%d\r\n", g_usbd_msc[busid].start_sector);
transfer_len = MIN(g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN], CONFIG_USBDEV_MSC_MAX_BUFSIZE);
if (usbd_msc_sector_read(busid, g_usbd_msc[busid].cbw.bLUN, g_usbd_msc[busid].start_sector, g_usbd_msc[busid].block_buffer, transfer_len) != 0) {
SCSI_SetSenseData(busid, SCSI_KCQHE_UREINRESERVEDAREA);
return false;
}
g_usbd_msc[busid].start_sector += (transfer_len / g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN]);
g_usbd_msc[busid].nsectors -= (transfer_len / g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN]);
g_usbd_msc[busid].csw.dDataResidue -= transfer_len;
if (g_usbd_msc[busid].nsectors == 0) {
g_usbd_msc[busid].stage = MSC_SEND_CSW;
}
usbd_ep_start_write(busid, mass_ep_data[busid][MSD_IN_EP_IDX].ep_addr, g_usbd_msc[busid].block_buffer, transfer_len);
return true;
}
static bool SCSI_processWrite(uint8_t busid, uint32_t nbytes)
{
uint32_t data_len = 0;
USB_LOG_DBG("write lba:%d\r\n", g_usbd_msc[busid].start_sector);
if (usbd_msc_sector_write(busid, g_usbd_msc[busid].cbw.bLUN, g_usbd_msc[busid].start_sector, g_usbd_msc[busid].block_buffer, nbytes) != 0) {
SCSI_SetSenseData(busid, SCSI_KCQHE_WRITEFAULT);
return false;
}
g_usbd_msc[busid].start_sector += (nbytes / g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN]);
g_usbd_msc[busid].nsectors -= (nbytes / g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN]);
g_usbd_msc[busid].csw.dDataResidue -= nbytes;
if (g_usbd_msc[busid].nsectors == 0) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_PASSED);
} else {
data_len = MIN(g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN], CONFIG_USBDEV_MSC_MAX_BUFSIZE);
usbd_ep_start_read(busid, mass_ep_data[busid][MSD_OUT_EP_IDX].ep_addr, g_usbd_msc[busid].block_buffer, data_len);
}
return true;
}
static bool SCSI_CBWDecode(uint8_t busid, uint32_t nbytes)
{
uint8_t *buf2send = g_usbd_msc[busid].block_buffer;
uint32_t len2send = 0;
bool ret = false;
if (nbytes != sizeof(struct CBW)) {
USB_LOG_ERR("size != sizeof(cbw)\r\n");
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
g_usbd_msc[busid].csw.dTag = g_usbd_msc[busid].cbw.dTag;
g_usbd_msc[busid].csw.dDataResidue = g_usbd_msc[busid].cbw.dDataLength;
if ((g_usbd_msc[busid].cbw.dSignature != MSC_CBW_Signature) || (g_usbd_msc[busid].cbw.bCBLength < 1) || (g_usbd_msc[busid].cbw.bCBLength > 16)) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
} else {
USB_LOG_DBG("Decode CB:0x%02x\r\n", g_usbd_msc[busid].cbw.CB[0]);
switch (g_usbd_msc[busid].cbw.CB[0]) {
case SCSI_CMD_TESTUNITREADY:
ret = SCSI_testUnitReady(busid, &buf2send, &len2send);
break;
case SCSI_CMD_REQUESTSENSE:
ret = SCSI_requestSense(busid, &buf2send, &len2send);
break;
case SCSI_CMD_INQUIRY:
ret = SCSI_inquiry(busid, &buf2send, &len2send);
break;
case SCSI_CMD_STARTSTOPUNIT:
ret = SCSI_startStopUnit(busid, &buf2send, &len2send);
break;
case SCSI_CMD_PREVENTMEDIAREMOVAL:
ret = SCSI_preventAllowMediaRemoval(busid, &buf2send, &len2send);
break;
case SCSI_CMD_MODESENSE6:
ret = SCSI_modeSense6(busid, &buf2send, &len2send);
break;
case SCSI_CMD_MODESENSE10:
ret = SCSI_modeSense10(busid, &buf2send, &len2send);
break;
case SCSI_CMD_READFORMATCAPACITIES:
ret = SCSI_readFormatCapacity(busid, &buf2send, &len2send);
break;
case SCSI_CMD_READCAPACITY10:
ret = SCSI_readCapacity10(busid, &buf2send, &len2send);
break;
case SCSI_CMD_READ10:
ret = SCSI_read10(busid, NULL, 0);
break;
case SCSI_CMD_READ12:
ret = SCSI_read12(busid, NULL, 0);
break;
case SCSI_CMD_WRITE10:
ret = SCSI_write10(busid, NULL, 0);
break;
case SCSI_CMD_WRITE12:
ret = SCSI_write12(busid, NULL, 0);
break;
case SCSI_CMD_VERIFY10:
//ret = SCSI_verify10(NULL, 0);
ret = false;
break;
default:
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
USB_LOG_WRN("unsupported cmd:0x%02x\r\n", g_usbd_msc[busid].cbw.CB[0]);
ret = false;
break;
}
}
if (ret) {
if (g_usbd_msc[busid].stage == MSC_READ_CBW) {
if (len2send) {
USB_LOG_DBG("Send info len:%d\r\n", len2send);
usbd_msc_send_info(busid, buf2send, len2send);
} else {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_PASSED);
}
}
}
return ret;
}
void mass_storage_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)ep;
switch (g_usbd_msc[busid].stage) {
case MSC_READ_CBW:
if (SCSI_CBWDecode(busid, nbytes) == false) {
USB_LOG_ERR("Command:0x%02x decode err\r\n", g_usbd_msc[busid].cbw.CB[0]);
usbd_msc_bot_abort(busid);
return;
}
break;
case MSC_DATA_OUT:
switch (g_usbd_msc[busid].cbw.CB[0]) {
case SCSI_CMD_WRITE10:
case SCSI_CMD_WRITE12:
#if defined(CONFIG_USBDEV_MSC_THREAD)
g_usbd_msc[busid].nbytes = nbytes;
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_OUT);
#elif defined(CONFIG_USBDEV_MSC_POLLING)
g_usbd_msc[busid].nbytes = nbytes;
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_OUT);
#else
if (SCSI_processWrite(busid, nbytes) == false) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
}
#endif
break;
default:
break;
}
break;
default:
break;
}
}
void mass_storage_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)ep;
(void)nbytes;
switch (g_usbd_msc[busid].stage) {
case MSC_DATA_IN:
switch (g_usbd_msc[busid].cbw.CB[0]) {
case SCSI_CMD_READ10:
case SCSI_CMD_READ12:
#if defined(CONFIG_USBDEV_MSC_THREAD)
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
#elif defined(CONFIG_USBDEV_MSC_POLLING)
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_IN);
#else
if (SCSI_processRead(busid) == false) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
return;
}
#endif
break;
default:
break;
}
break;
/*the device has to send a CSW*/
case MSC_SEND_CSW:
usbd_msc_send_csw(busid, CSW_STATUS_CMD_PASSED);
break;
/*the host has received the CSW*/
case MSC_WAIT_CSW:
g_usbd_msc[busid].stage = MSC_READ_CBW;
USB_LOG_DBG("Start reading cbw\r\n");
usbd_ep_start_read(busid, mass_ep_data[busid][MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&g_usbd_msc[busid].cbw, USB_SIZEOF_MSC_CBW);
break;
default:
break;
}
}
#if defined(CONFIG_USBDEV_MSC_THREAD)
static void usbdev_msc_thread(void *argument)
{
uintptr_t event;
int ret;
uint8_t busid = (uint8_t)argument;
while (1) {
ret = usb_osal_mq_recv(g_usbd_msc[busid].usbd_msc_mq, (uintptr_t *)&event, USB_OSAL_WAITING_FOREVER);
if (ret < 0) {
continue;
}
USB_LOG_DBG("event:%d\r\n", event);
if (event == MSC_DATA_OUT) {
if (SCSI_processWrite(busid, g_usbd_msc[busid].nbytes) == false) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
}
} else if (event == MSC_DATA_IN) {
if (SCSI_processRead(busid) == false) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
}
} else {
}
}
}
#elif defined(CONFIG_USBDEV_MSC_POLLING)
void usbd_msc_polling(uint8_t busid)
{
uint8_t event;
if (chry_ringbuffer_read_byte(&g_usbd_msc[busid].msc_rb, &event)) {
USB_LOG_DBG("event:%d\r\n", event);
if (event == MSC_DATA_OUT) {
if (SCSI_processWrite(busid, g_usbd_msc[busid].nbytes) == false) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
}
} else if (event == MSC_DATA_IN) {
if (SCSI_processRead(busid) == false) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
}
} else {
}
}
}
#endif
struct usbd_interface *usbd_msc_init_intf(uint8_t busid, struct usbd_interface *intf, const uint8_t out_ep, const uint8_t in_ep)
{
intf->class_interface_handler = msc_storage_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = msc_storage_notify_handler;
mass_ep_data[busid][MSD_OUT_EP_IDX].ep_addr = out_ep;
mass_ep_data[busid][MSD_OUT_EP_IDX].ep_cb = mass_storage_bulk_out;
mass_ep_data[busid][MSD_IN_EP_IDX].ep_addr = in_ep;
mass_ep_data[busid][MSD_IN_EP_IDX].ep_cb = mass_storage_bulk_in;
usbd_add_endpoint(busid, &mass_ep_data[busid][MSD_OUT_EP_IDX]);
usbd_add_endpoint(busid, &mass_ep_data[busid][MSD_IN_EP_IDX]);
memset((uint8_t *)&g_usbd_msc[busid], 0, sizeof(struct usbd_msc_priv));
usdb_msc_set_max_lun(busid);
for (uint8_t i = 0u; i <= g_usbd_msc[busid].max_lun; i++) {
usbd_msc_get_cap(busid, i, &g_usbd_msc[busid].scsi_blk_nbr[i], &g_usbd_msc[busid].scsi_blk_size[i]);
if (g_usbd_msc[busid].scsi_blk_size[i] > CONFIG_USBDEV_MSC_MAX_BUFSIZE) {
USB_LOG_ERR("msc block buffer overflow\r\n");
return NULL;
}
}
return intf;
}
void usbd_msc_set_readonly(uint8_t busid, bool readonly)
{
g_usbd_msc[busid].readonly = readonly;
}
bool usbd_msc_get_popup(uint8_t busid)
{
return g_usbd_msc[busid].popup;
}

View File

@ -1,34 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
* Copyright (c) 2024, zhihong chen
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_MSC_H
#define USBD_MSC_H
#include "usb_msc.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Init msc interface driver */
struct usbd_interface *usbd_msc_init_intf(uint8_t busid, struct usbd_interface *intf,
const uint8_t out_ep,
const uint8_t in_ep);
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size);
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length);
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length);
void usbd_msc_set_readonly(uint8_t busid, bool readonly);
bool usbd_msc_get_popup(uint8_t busid);
void usbd_msc_polling(uint8_t busid);
#ifdef __cplusplus
}
#endif
#endif /* USBD_MSC_H */

View File

@ -1,447 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_msc.h"
#include "usb_scsi.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_msc"
#include "usb_log.h"
#define DEV_FORMAT "/dev/sd%c"
#define MSC_INQUIRY_TIMEOUT 500
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[CONFIG_USBHOST_MAX_MSC_CLASS][USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
static struct usbh_msc g_msc_class[CONFIG_USBHOST_MAX_MSC_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_msc_modeswitch_config *g_msc_modeswitch_config = NULL;
static struct usbh_msc *usbh_msc_class_alloc(void)
{
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_MSC_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_msc_class[devno], 0, sizeof(struct usbh_msc));
g_msc_class[devno].sdchar = 'a' + devno;
return &g_msc_class[devno];
}
}
return NULL;
}
static void usbh_msc_class_free(struct usbh_msc *msc_class)
{
int devno = msc_class->sdchar - 'a';
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(msc_class, 0, sizeof(struct usbh_msc));
}
static int usbh_msc_get_maxlun(struct usbh_msc *msc_class, uint8_t *buffer)
{
struct usb_setup_packet *setup;
if (!msc_class || !msc_class->hport) {
return -USB_ERR_INVAL;
}
setup = msc_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = MSC_REQUEST_GET_MAX_LUN;
setup->wValue = 0;
setup->wIndex = msc_class->intf;
setup->wLength = 1;
return usbh_control_transfer(msc_class->hport, setup, buffer);
}
static void usbh_msc_cbw_dump(struct CBW *cbw)
{
int i;
USB_LOG_DBG("CBW:\r\n");
USB_LOG_DBG(" signature: 0x%08x\r\n", (unsigned int)cbw->dSignature);
USB_LOG_DBG(" tag: 0x%08x\r\n", (unsigned int)cbw->dTag);
USB_LOG_DBG(" datlen: 0x%08x\r\n", (unsigned int)cbw->dDataLength);
USB_LOG_DBG(" flags: 0x%02x\r\n", cbw->bmFlags);
USB_LOG_DBG(" lun: 0x%02x\r\n", cbw->bLUN);
USB_LOG_DBG(" cblen: 0x%02x\r\n", cbw->bCBLength);
USB_LOG_DBG("CB:\r\n");
for (i = 0; i < cbw->bCBLength; i += 8) {
USB_LOG_DBG(" 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\r\n",
cbw->CB[i], cbw->CB[i + 1], cbw->CB[i + 2],
cbw->CB[i + 3], cbw->CB[i + 4], cbw->CB[i + 5],
cbw->CB[i + 6], cbw->CB[i + 7]);
}
}
static void usbh_msc_csw_dump(struct CSW *csw)
{
(void)csw;
USB_LOG_DBG("CSW:\r\n");
USB_LOG_DBG(" signature: 0x%08x\r\n", (unsigned int)csw->dSignature);
USB_LOG_DBG(" tag: 0x%08x\r\n", (unsigned int)csw->dTag);
USB_LOG_DBG(" residue: 0x%08x\r\n", (unsigned int)csw->dDataResidue);
USB_LOG_DBG(" status: 0x%02x\r\n", csw->bStatus);
}
static inline int usbh_msc_bulk_in_transfer(struct usbh_msc *msc_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &msc_class->bulkin_urb;
usbh_bulk_urb_fill(urb, msc_class->hport, msc_class->bulkin, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
static inline int usbh_msc_bulk_out_transfer(struct usbh_msc *msc_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &msc_class->bulkout_urb;
usbh_bulk_urb_fill(urb, msc_class->hport, msc_class->bulkout, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, struct CSW *csw, uint8_t *buffer, uint32_t timeout)
{
int nbytes;
usbh_msc_cbw_dump(cbw);
/* Send the CBW */
nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, timeout);
if (nbytes < 0) {
USB_LOG_ERR("cbw transfer error\r\n");
goto __err_exit;
}
if (cbw->dDataLength != 0) {
if (cbw->CB[0] == SCSI_CMD_WRITE10) {
nbytes = usbh_msc_bulk_out_transfer(msc_class, buffer, cbw->dDataLength, timeout);
} else if (cbw->CB[0] == SCSI_CMD_READCAPACITY10) {
nbytes = usbh_msc_bulk_in_transfer(msc_class, buffer, cbw->dDataLength, timeout);
if (nbytes >= 0) {
/* Save the capacity information */
msc_class->blocknum = GET_BE32(&buffer[0]) + 1;
msc_class->blocksize = GET_BE32(&buffer[4]);
}
} else {
nbytes = usbh_msc_bulk_in_transfer(msc_class, buffer, cbw->dDataLength, timeout);
}
if (nbytes < 0) {
USB_LOG_ERR("msc data transfer error\r\n");
goto __err_exit;
}
}
/* Receive the CSW */
memset(csw, 0, USB_SIZEOF_MSC_CSW);
nbytes = usbh_msc_bulk_in_transfer(msc_class, (uint8_t *)csw, USB_SIZEOF_MSC_CSW, timeout);
if (nbytes < 0) {
USB_LOG_ERR("csw transfer error\r\n");
goto __err_exit;
}
usbh_msc_csw_dump(csw);
/* check csw status */
if (csw->dSignature != MSC_CSW_Signature) {
USB_LOG_ERR("csw signature error\r\n");
return -USB_ERR_INVAL;
}
if (csw->bStatus != 0) {
USB_LOG_ERR("csw bStatus %d\r\n", csw->bStatus);
return -USB_ERR_INVAL;
}
__err_exit:
return nbytes < 0 ? (int)nbytes : 0;
}
static inline int usbh_msc_scsi_testunitready(struct usbh_msc *msc_class)
{
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
cbw->bCBLength = SCSICMD_TESTUNITREADY_SIZEOF;
cbw->CB[0] = SCSI_CMD_TESTUNITREADY;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], NULL, MSC_INQUIRY_TIMEOUT);
}
static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
{
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
cbw->bmFlags = 0x80;
cbw->dDataLength = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
cbw->bCBLength = SCSICMD_REQUESTSENSE_SIZEOF;
cbw->CB[0] = SCSI_CMD_REQUESTSENSE;
cbw->CB[4] = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
}
static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
{
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
cbw->dDataLength = SCSIRESP_INQUIRY_SIZEOF;
cbw->bmFlags = 0x80;
cbw->bCBLength = SCSICMD_INQUIRY_SIZEOF;
cbw->CB[0] = SCSI_CMD_INQUIRY;
cbw->CB[4] = SCSIRESP_INQUIRY_SIZEOF;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
}
static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
{
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
cbw->dDataLength = SCSIRESP_READCAPACITY10_SIZEOF;
cbw->bmFlags = 0x80;
cbw->bCBLength = SCSICMD_READCAPACITY10_SIZEOF;
cbw->CB[0] = SCSI_CMD_READCAPACITY10;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
}
static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t *message)
{
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memcpy(g_msc_buf[msc_class->sdchar - 'a'], message, 31);
usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], NULL, MSC_INQUIRY_TIMEOUT);
}
static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret;
struct usbh_msc_modeswitch_config *config;
struct usbh_msc *msc_class = usbh_msc_class_alloc();
if (msc_class == NULL) {
USB_LOG_ERR("Fail to alloc msc_class\r\n");
return -USB_ERR_NOMEM;
}
msc_class->hport = hport;
msc_class->intf = intf;
hport->config.intf[intf].priv = msc_class;
ret = usbh_msc_get_maxlun(msc_class, g_msc_buf[msc_class->sdchar - 'a']);
if (ret < 0) {
return ret;
}
USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[msc_class->sdchar - 'a'][0] + 1);
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(msc_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(msc_class->bulkout, ep_desc);
}
}
if (g_msc_modeswitch_config) {
uint8_t num = 0;
while (1) {
config = &g_msc_modeswitch_config[num];
if (config && config->name) {
if ((hport->device_desc.idVendor == config->vid) &&
(hport->device_desc.idProduct == config->pid)) {
USB_LOG_INFO("%s usb_modeswitch enable\r\n", config->name);
usbh_msc_modeswitch(msc_class, config->message_content);
return 0;
}
num++;
} else {
break;
}
}
}
ret = usbh_msc_scsi_testunitready(msc_class);
if (ret < 0) {
ret = usbh_msc_scsi_requestsense(msc_class);
if (ret < 0) {
USB_LOG_ERR("Fail to scsi_testunitready\r\n");
return ret;
}
}
ret = usbh_msc_scsi_inquiry(msc_class);
if (ret < 0) {
USB_LOG_ERR("Fail to scsi_inquiry\r\n");
return ret;
}
ret = usbh_msc_scsi_readcapacity10(msc_class);
if (ret < 0) {
USB_LOG_ERR("Fail to scsi_readcapacity10\r\n");
return ret;
}
if (msc_class->blocksize > 0) {
USB_LOG_INFO("Capacity info:\r\n");
USB_LOG_INFO("Block num:%d,block size:%d\r\n", (unsigned int)msc_class->blocknum, (unsigned int)msc_class->blocksize);
} else {
USB_LOG_ERR("Invalid block size\r\n");
return -USB_ERR_RANGE;
}
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
USB_LOG_INFO("Register MSC Class:%s\r\n", hport->config.intf[intf].devname);
usbh_msc_run(msc_class);
return ret;
}
static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_msc *msc_class = (struct usbh_msc *)hport->config.intf[intf].priv;
if (msc_class) {
if (msc_class->bulkin) {
usbh_kill_urb(&msc_class->bulkin_urb);
}
if (msc_class->bulkout) {
usbh_kill_urb(&msc_class->bulkout_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister MSC Class:%s\r\n", hport->config.intf[intf].devname);
usbh_msc_stop(msc_class);
}
usbh_msc_class_free(msc_class);
}
return ret;
}
int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
{
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
cbw->dDataLength = (msc_class->blocksize * nsectors);
cbw->bCBLength = SCSICMD_WRITE10_SIZEOF;
cbw->CB[0] = SCSI_CMD_WRITE10;
SET_BE32(&cbw->CB[2], start_sector);
SET_BE16(&cbw->CB[7], nsectors);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
}
int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
{
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
cbw->dDataLength = (msc_class->blocksize * nsectors);
cbw->bmFlags = 0x80;
cbw->bCBLength = SCSICMD_READ10_SIZEOF;
cbw->CB[0] = SCSI_CMD_READ10;
SET_BE32(&cbw->CB[2], start_sector);
SET_BE16(&cbw->CB[7], nsectors);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
}
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)
{
if (config) {
g_msc_modeswitch_config = config;
} else {
g_msc_modeswitch_config = NULL;
}
}
__WEAK void usbh_msc_run(struct usbh_msc *msc_class)
{
(void)msc_class;
}
__WEAK void usbh_msc_stop(struct usbh_msc *msc_class)
{
(void)msc_class;
}
const struct usbh_class_driver msc_class_driver = {
.driver_name = "msc",
.connect = usbh_msc_connect,
.disconnect = usbh_msc_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info msc_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_MASS_STORAGE,
.subclass = MSC_SUBCLASS_SCSI,
.protocol = MSC_PROTOCOL_BULK_ONLY,
.id_table = NULL,
.class_driver = &msc_class_driver
};

View File

@ -1,49 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_MSC_H
#define USBH_MSC_H
#include "usb_msc.h"
#include "usb_scsi.h"
struct usbh_msc {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
struct usbh_urb bulkin_urb; /* Bulk IN urb */
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
uint8_t intf; /* Data interface number */
uint8_t sdchar;
uint32_t blocknum; /* Number of blocks on the USB mass storage device */
uint16_t blocksize; /* Block size of USB mass storage device */
void *user_data;
};
struct usbh_msc_modeswitch_config {
const char *name;
uint16_t vid; /* Vendor ID (for vendor/product specific devices) */
uint16_t pid; /* Product ID (for vendor/product specific devices) */
const uint8_t *message_content;
};
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config);
int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors);
int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors);
void usbh_msc_run(struct usbh_msc *msc_class);
void usbh_msc_stop(struct usbh_msc *msc_class);
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* USBH_MSC_H */

View File

@ -1,115 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USB_HC_H
#define USB_HC_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*usbh_complete_callback_t)(void *arg, int nbytes);
struct usbh_bus;
/**
* @brief USB Iso Configuration.
*
* Structure containing the USB Iso configuration.
*/
struct usbh_iso_frame_packet {
uint8_t *transfer_buffer;
uint32_t transfer_buffer_length;
uint32_t actual_length;
int errorcode;
};
/**
* @brief USB Urb Configuration.
*
* Structure containing the USB Urb configuration.
*/
struct usbh_urb {
usb_slist_t list;
void *hcpriv;
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *ep;
uint8_t data_toggle;
uint8_t interval;
struct usb_setup_packet *setup;
uint8_t *transfer_buffer;
uint32_t transfer_buffer_length;
int transfer_flags;
uint32_t actual_length;
uint32_t timeout;
int errorcode;
uint32_t num_of_iso_packets;
uint32_t start_frame;
usbh_complete_callback_t complete;
void *arg;
#if defined(__ICCARM__) || defined(__ICCRISCV__) || defined(__ICCRX__)
struct usbh_iso_frame_packet *iso_packet;
#else
struct usbh_iso_frame_packet iso_packet[0];
#endif
};
/**
* @brief usb host controller hardware init.
*
* @return On success will return 0, and others indicate fail.
*/
int usb_hc_init(struct usbh_bus *bus);
/**
* @brief usb host controller hardware deinit.
*
* @return On success will return 0, and others indicate fail.
*/
int usb_hc_deinit(struct usbh_bus *bus);
/**
* @brief Get frame number.
*
* @return frame number.
*/
uint16_t usbh_get_frame_number(struct usbh_bus *bus);
/**
* @brief control roothub.
*
* @param setup setup request buffer.
* @param buf buf for reading response or write data.
* @return On success will return 0, and others indicate fail.
*/
int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, uint8_t *buf);
/**
* @brief Submit a usb transfer request to an endpoint.
*
* If timeout is not zero, this function will be in poll transfer mode,
* otherwise will be in async transfer mode.
*
* @param urb Usb request block.
* @return On success will return 0, and others indicate fail.
*/
int usbh_submit_urb(struct usbh_urb *urb);
/**
* @brief Cancel a transfer request.
*
* This function will call When calls usbh_submit_urb and return -USB_ERR_TIMEOUT or -USB_ERR_SHUTDOWN.
*
* @param urb Usb request block.
* @return On success will return 0, and others indicate fail.
*/
int usbh_kill_urb(struct usbh_urb *urb);
#ifdef __cplusplus
}
#endif
#endif /* USB_HC_H */

View File

@ -1,64 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USB_OSAL_H
#define USB_OSAL_H
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#define USB_OSAL_WAITING_FOREVER (0xFFFFFFFFU)
typedef void *usb_osal_thread_t;
typedef void *usb_osal_sem_t;
typedef void *usb_osal_mutex_t;
typedef void *usb_osal_mq_t;
typedef void (*usb_thread_entry_t)(void *argument);
typedef void (*usb_timer_handler_t)(void *argument);
struct usb_osal_timer {
usb_timer_handler_t handler;
void *argument;
bool is_period;
uint32_t ticks;
void *timer;
};
/*
* Task with smaller priority value indicates higher task priority
*/
usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args);
void usb_osal_thread_delete(usb_osal_thread_t thread);
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count);
void usb_osal_sem_delete(usb_osal_sem_t sem);
int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout);
int usb_osal_sem_give(usb_osal_sem_t sem);
void usb_osal_sem_reset(usb_osal_sem_t sem);
usb_osal_mutex_t usb_osal_mutex_create(void);
void usb_osal_mutex_delete(usb_osal_mutex_t mutex);
int usb_osal_mutex_take(usb_osal_mutex_t mutex);
int usb_osal_mutex_give(usb_osal_mutex_t mutex);
usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs);
void usb_osal_mq_delete(usb_osal_mq_t mq);
int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr);
int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout);
struct usb_osal_timer *usb_osal_timer_create(const char *name, uint32_t timeout_ms, usb_timer_handler_t handler, void *argument, bool is_period);
void usb_osal_timer_delete(struct usb_osal_timer *timer);
void usb_osal_timer_start(struct usb_osal_timer *timer);
void usb_osal_timer_stop(struct usb_osal_timer *timer);
size_t usb_osal_enter_critical_section(void);
void usb_osal_leave_critical_section(size_t flag);
void usb_osal_msleep(uint32_t delay);
void *usb_osal_malloc(size_t size);
void usb_osal_free(void *ptr);
#endif /* USB_OSAL_H */

View File

@ -1,910 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_core"
#include "usb_log.h"
struct usbh_class_info *usbh_class_info_table_begin = NULL;
struct usbh_class_info *usbh_class_info_table_end = NULL;
usb_slist_t g_bus_head = USB_SLIST_OBJECT_INIT(g_bus_head);
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t ep0_request_buffer[CONFIG_USBHOST_MAX_BUS][USB_ALIGN_UP(CONFIG_USBHOST_REQUEST_BUFFER_LEN, CONFIG_USB_ALIGN_SIZE)];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct usb_setup_packet g_setup_buffer[CONFIG_USBHOST_MAX_BUS][CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USBHOST_MAX_EHPORTS];
struct usbh_bus g_usbhost_bus[CONFIG_USBHOST_MAX_BUS];
/* general descriptor field offsets */
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
#define USB_DEV_ADDR_MAX 0x7f
#define USB_DEV_ADDR_MARK_OFFSET 5
#define USB_DEV_ADDR_MARK_MASK 0x1f
static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen)
{
uint8_t startaddr = devgen->next;
uint8_t devaddr;
int index;
int bitno;
for (;;) {
devaddr = devgen->next;
if (devgen->next >= 0x7f) {
devgen->next = 2;
} else {
devgen->next++;
}
index = devaddr >> 5;
bitno = devaddr & 0x1f;
if ((devgen->alloctab[index] & (1 << bitno)) == 0) {
devgen->alloctab[index] |= (1 << bitno);
return (int)devaddr;
}
if (startaddr == devaddr) {
return -USB_ERR_NOMEM;
}
}
}
static int __usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr)
{
int index;
int bitno;
if ((devaddr > 0) && (devaddr < USB_DEV_ADDR_MAX)) {
index = devaddr >> USB_DEV_ADDR_MARK_OFFSET;
bitno = devaddr & USB_DEV_ADDR_MARK_MASK;
/* Free the address */
if ((devgen->alloctab[index] |= (1 << bitno)) != 0) {
devgen->alloctab[index] &= ~(1 << bitno);
} else {
return -1;
}
if (devaddr < devgen->next) {
devgen->next = devaddr;
}
}
return 0;
}
static int usbh_free_devaddr(struct usbh_hubport *hport)
{
if (hport->dev_addr > 0) {
__usbh_free_devaddr(&hport->bus->devgen, hport->dev_addr);
}
return 0;
}
static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uint8_t subclass, uint8_t protocol,
uint16_t vid, uint16_t pid)
{
struct usbh_class_info *index = NULL;
for (index = usbh_class_info_table_begin; index < usbh_class_info_table_end; index++) {
if ((index->match_flags & USB_CLASS_MATCH_INTF_CLASS) && !(index->class == class)) {
continue;
}
if ((index->match_flags & USB_CLASS_MATCH_INTF_SUBCLASS) && !(index->subclass == subclass)) {
continue;
}
if ((index->match_flags & USB_CLASS_MATCH_INTF_PROTOCOL) && !(index->protocol == protocol)) {
continue;
}
if (index->match_flags & USB_CLASS_MATCH_VID_PID && index->id_table) {
/* scan id table */
uint32_t i;
for (i = 0; index->id_table[i][0] && index->id_table[i][0] != vid && index->id_table[i][1] != pid; i++) {
}
/* do not match, continue next */
if (!index->id_table[i][0]) {
continue;
}
}
return index->class_driver;
}
return NULL;
}
static int parse_device_descriptor(struct usbh_hubport *hport, struct usb_device_descriptor *desc, uint16_t length)
{
if (desc->bLength != USB_SIZEOF_DEVICE_DESC) {
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
return -USB_ERR_INVAL;
} else if (desc->bDescriptorType != USB_DESCRIPTOR_TYPE_DEVICE) {
USB_LOG_ERR("unexpected device descriptor 0x%02x\r\n", desc->bDescriptorType);
return -USB_ERR_INVAL;
} else {
if (length <= 8) {
return 0;
}
#if 0
USB_LOG_DBG("Device Descriptor:\r\n");
USB_LOG_DBG("bLength: 0x%02x \r\n", desc->bLength);
USB_LOG_DBG("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType);
USB_LOG_DBG("bcdUSB: 0x%04x \r\n", desc->bcdUSB);
USB_LOG_DBG("bDeviceClass: 0x%02x \r\n", desc->bDeviceClass);
USB_LOG_DBG("bDeviceSubClass: 0x%02x \r\n", desc->bDeviceSubClass);
USB_LOG_DBG("bDeviceProtocol: 0x%02x \r\n", desc->bDeviceProtocol);
USB_LOG_DBG("bMaxPacketSize0: 0x%02x \r\n", desc->bMaxPacketSize0);
USB_LOG_DBG("idVendor: 0x%04x \r\n", desc->idVendor);
USB_LOG_DBG("idProduct: 0x%04x \r\n", desc->idProduct);
USB_LOG_DBG("bcdDevice: 0x%04x \r\n", desc->bcdDevice);
USB_LOG_DBG("iManufacturer: 0x%02x \r\n", desc->iManufacturer);
USB_LOG_DBG("iProduct: 0x%02x \r\n", desc->iProduct);
USB_LOG_DBG("iSerialNumber: 0x%02x \r\n", desc->iSerialNumber);
USB_LOG_DBG("bNumConfigurations: 0x%02x\r\n", desc->bNumConfigurations);
#endif
hport->device_desc.bLength = desc->bLength;
hport->device_desc.bDescriptorType = desc->bDescriptorType;
hport->device_desc.bcdUSB = desc->bcdUSB;
hport->device_desc.bDeviceClass = desc->bDeviceClass;
hport->device_desc.bDeviceSubClass = desc->bDeviceSubClass;
hport->device_desc.bDeviceProtocol = desc->bDeviceProtocol;
hport->device_desc.bMaxPacketSize0 = desc->bMaxPacketSize0;
hport->device_desc.idVendor = desc->idVendor;
hport->device_desc.idProduct = desc->idProduct;
hport->device_desc.bcdDevice = desc->bcdDevice;
hport->device_desc.iManufacturer = desc->iManufacturer;
hport->device_desc.iProduct = desc->iProduct;
hport->device_desc.iSerialNumber = desc->iSerialNumber;
hport->device_desc.bNumConfigurations = desc->bNumConfigurations;
}
return 0;
}
static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_configuration_descriptor *desc, uint16_t length)
{
struct usb_interface_descriptor *intf_desc;
struct usb_endpoint_descriptor *ep_desc;
uint8_t cur_alt_setting = 0xff;
uint8_t cur_iface = 0xff;
uint8_t cur_ep = 0xff;
uint8_t cur_ep_num = 0xff;
uint32_t desc_len = 0;
uint8_t *p;
if (desc->bLength != USB_SIZEOF_CONFIG_DESC) {
USB_LOG_ERR("invalid config bLength 0x%02x\r\n", desc->bLength);
return -USB_ERR_INVAL;
} else if (desc->bDescriptorType != USB_DESCRIPTOR_TYPE_CONFIGURATION) {
USB_LOG_ERR("unexpected config descriptor 0x%02x\r\n", desc->bDescriptorType);
return -USB_ERR_INVAL;
} else {
if (length <= USB_SIZEOF_CONFIG_DESC) {
return 0;
}
#if 0
USB_LOG_DBG("Config Descriptor:\r\n");
USB_LOG_DBG("bLength: 0x%02x \r\n", desc->bLength);
USB_LOG_DBG("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType);
USB_LOG_DBG("wTotalLength: 0x%04x \r\n", desc->wTotalLength);
USB_LOG_DBG("bNumInterfaces: 0x%02x \r\n", desc->bNumInterfaces);
USB_LOG_DBG("bConfigurationValue: 0x%02x \r\n", desc->bConfigurationValue);
USB_LOG_DBG("iConfiguration: 0x%02x \r\n", desc->iConfiguration);
USB_LOG_DBG("bmAttributes: 0x%02x \r\n", desc->bmAttributes);
USB_LOG_DBG("bMaxPower: 0x%02x \r\n", desc->bMaxPower);
#endif
hport->config.config_desc.bLength = desc->bLength;
hport->config.config_desc.bDescriptorType = desc->bDescriptorType;
hport->config.config_desc.wTotalLength = desc->wTotalLength;
hport->config.config_desc.bNumInterfaces = desc->bNumInterfaces;
hport->config.config_desc.bConfigurationValue = desc->bConfigurationValue;
hport->config.config_desc.iConfiguration = desc->iConfiguration;
hport->config.config_desc.iConfiguration = desc->iConfiguration;
hport->config.config_desc.bmAttributes = desc->bmAttributes;
hport->config.config_desc.bMaxPower = desc->bMaxPower;
p = (uint8_t *)desc;
p += USB_SIZEOF_CONFIG_DESC;
desc_len = USB_SIZEOF_CONFIG_DESC;
memset(hport->config.intf, 0, sizeof(struct usbh_interface) * CONFIG_USBHOST_MAX_INTERFACES);
while (p[DESC_bLength] && (desc_len <= length)) {
switch (p[DESC_bDescriptorType]) {
case USB_DESCRIPTOR_TYPE_INTERFACE:
intf_desc = (struct usb_interface_descriptor *)p;
cur_iface = intf_desc->bInterfaceNumber;
cur_alt_setting = intf_desc->bAlternateSetting;
cur_ep_num = intf_desc->bNumEndpoints;
cur_ep = 0;
if (cur_iface > (CONFIG_USBHOST_MAX_INTERFACES - 1)) {
USB_LOG_ERR("Interface num overflow\r\n");
while (1) {
}
}
if (cur_alt_setting > (CONFIG_USBHOST_MAX_INTF_ALTSETTINGS - 1)) {
USB_LOG_ERR("Interface altsetting num overflow\r\n");
while (1) {
}
}
if (cur_ep_num > CONFIG_USBHOST_MAX_ENDPOINTS) {
USB_LOG_ERR("Endpoint num overflow\r\n");
while (1) {
}
}
#if 0
USB_LOG_DBG("Interface Descriptor:\r\n");
USB_LOG_DBG("bLength: 0x%02x \r\n", intf_desc->bLength);
USB_LOG_DBG("bDescriptorType: 0x%02x \r\n", intf_desc->bDescriptorType);
USB_LOG_DBG("bInterfaceNumber: 0x%02x \r\n", intf_desc->bInterfaceNumber);
USB_LOG_DBG("bAlternateSetting: 0x%02x \r\n", intf_desc->bAlternateSetting);
USB_LOG_DBG("bNumEndpoints: 0x%02x \r\n", intf_desc->bNumEndpoints);
USB_LOG_DBG("bInterfaceClass: 0x%02x \r\n", intf_desc->bInterfaceClass);
USB_LOG_DBG("bInterfaceSubClass: 0x%02x \r\n", intf_desc->bInterfaceSubClass);
USB_LOG_DBG("bInterfaceProtocol: 0x%02x \r\n", intf_desc->bInterfaceProtocol);
USB_LOG_DBG("iInterface: 0x%02x \r\n", intf_desc->iInterface);
#endif
memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].intf_desc, intf_desc, 9);
hport->config.intf[cur_iface].altsetting_num = cur_alt_setting + 1;
break;
case USB_DESCRIPTOR_TYPE_ENDPOINT:
ep_desc = (struct usb_endpoint_descriptor *)p;
memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].ep[cur_ep].ep_desc, ep_desc, 7);
cur_ep++;
break;
default:
break;
}
/* skip to next descriptor */
p += p[DESC_bLength];
desc_len += p[DESC_bLength];
}
}
return 0;
}
static void usbh_print_hubport_info(struct usbh_hubport *hport)
{
USB_LOG_RAW("Device Descriptor:\r\n");
USB_LOG_RAW("bLength: 0x%02x \r\n", hport->device_desc.bLength);
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", hport->device_desc.bDescriptorType);
USB_LOG_RAW("bcdUSB: 0x%04x \r\n", hport->device_desc.bcdUSB);
USB_LOG_RAW("bDeviceClass: 0x%02x \r\n", hport->device_desc.bDeviceClass);
USB_LOG_RAW("bDeviceSubClass: 0x%02x \r\n", hport->device_desc.bDeviceSubClass);
USB_LOG_RAW("bDeviceProtocol: 0x%02x \r\n", hport->device_desc.bDeviceProtocol);
USB_LOG_RAW("bMaxPacketSize0: 0x%02x \r\n", hport->device_desc.bMaxPacketSize0);
USB_LOG_RAW("idVendor: 0x%04x \r\n", hport->device_desc.idVendor);
USB_LOG_RAW("idProduct: 0x%04x \r\n", hport->device_desc.idProduct);
USB_LOG_RAW("bcdDevice: 0x%04x \r\n", hport->device_desc.bcdDevice);
USB_LOG_RAW("iManufacturer: 0x%02x \r\n", hport->device_desc.iManufacturer);
USB_LOG_RAW("iProduct: 0x%02x \r\n", hport->device_desc.iProduct);
USB_LOG_RAW("iSerialNumber: 0x%02x \r\n", hport->device_desc.iSerialNumber);
USB_LOG_RAW("bNumConfigurations: 0x%02x\r\n", hport->device_desc.bNumConfigurations);
USB_LOG_RAW("Config Descriptor:\r\n");
USB_LOG_RAW("bLength: 0x%02x \r\n", hport->config.config_desc.bLength);
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", hport->config.config_desc.bDescriptorType);
USB_LOG_RAW("wTotalLength: 0x%04x \r\n", hport->config.config_desc.wTotalLength);
USB_LOG_RAW("bNumInterfaces: 0x%02x \r\n", hport->config.config_desc.bNumInterfaces);
USB_LOG_RAW("bConfigurationValue: 0x%02x \r\n", hport->config.config_desc.bConfigurationValue);
USB_LOG_RAW("iConfiguration: 0x%02x \r\n", hport->config.config_desc.iConfiguration);
USB_LOG_RAW("bmAttributes: 0x%02x \r\n", hport->config.config_desc.bmAttributes);
USB_LOG_RAW("bMaxPower: 0x%02x \r\n", hport->config.config_desc.bMaxPower);
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
for (uint8_t j = 0; j < hport->config.intf[i].altsetting_num; j++) {
USB_LOG_RAW("\tInterface Descriptor:\r\n");
USB_LOG_RAW("\tbLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bLength);
USB_LOG_RAW("\tbDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bDescriptorType);
USB_LOG_RAW("\tbInterfaceNumber: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceNumber);
USB_LOG_RAW("\tbAlternateSetting: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bAlternateSetting);
USB_LOG_RAW("\tbNumEndpoints: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints);
USB_LOG_RAW("\tbInterfaceClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceClass);
USB_LOG_RAW("\tbInterfaceSubClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceSubClass);
USB_LOG_RAW("\tbInterfaceProtocol: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceProtocol);
USB_LOG_RAW("\tiInterface: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.iInterface);
for (uint8_t k = 0; k < hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints; k++) {
USB_LOG_RAW("\t\tEndpoint Descriptor:\r\n");
USB_LOG_RAW("\t\tbLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bLength);
USB_LOG_RAW("\t\tbDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bDescriptorType);
USB_LOG_RAW("\t\tbEndpointAddress: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bEndpointAddress);
USB_LOG_RAW("\t\tbmAttributes: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bmAttributes);
USB_LOG_RAW("\t\twMaxPacketSize: 0x%04x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.wMaxPacketSize);
USB_LOG_RAW("\t\tbInterval: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bInterval);
}
}
}
}
static int usbh_get_default_mps(int speed)
{
switch (speed) {
case USB_SPEED_LOW: /* For low speed, we use 8 bytes */
return 8;
case USB_SPEED_FULL: /* For full or high speed, we use 64 bytes */
case USB_SPEED_HIGH:
return 64;
case USB_SPEED_SUPER: /* For super speed , we must use 512 bytes */
case USB_SPEED_SUPER_PLUS:
return 512;
default:
return 64;
}
}
int usbh_enumerate(struct usbh_hubport *hport)
{
struct usb_interface_descriptor *intf_desc;
struct usb_setup_packet *setup;
struct usb_device_descriptor *dev_desc;
struct usb_endpoint_descriptor *ep;
int dev_addr;
uint16_t ep_mps;
uint8_t config_value;
uint8_t config_index;
int ret;
hport->setup = &g_setup_buffer[hport->bus->busid][hport->parent->index - 1][hport->port - 1];
setup = hport->setup;
ep = &hport->ep0;
/* Config EP0 mps from speed */
ep->bEndpointAddress = 0x00;
ep->bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT;
ep->bmAttributes = USB_ENDPOINT_TYPE_CONTROL;
ep->wMaxPacketSize = usbh_get_default_mps(hport->speed);
ep->bInterval = 0;
ep->bLength = 7;
/* Configure EP0 with zero address */
hport->dev_addr = 0;
/* Read the first 8 bytes of the device descriptor */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_DEVICE << 8) | 0);
setup->wIndex = 0;
setup->wLength = 8;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
USB_LOG_ERR("Failed to get device descriptor,errorcode:%d\r\n", ret);
goto errout;
}
parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], 8);
/* Extract the correct max packetsize from the device descriptor */
dev_desc = (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid];
if (dev_desc->bcdUSB >= USB_3_0) {
ep_mps = 1 << dev_desc->bMaxPacketSize0;
} else {
ep_mps = dev_desc->bMaxPacketSize0;
}
USB_LOG_DBG("Device rev=%04x cls=%02x sub=%02x proto=%02x size=%d\r\n",
dev_desc->bcdUSB, dev_desc->bDeviceClass, dev_desc->bDeviceSubClass,
dev_desc->bDeviceProtocol, ep_mps);
/* Reconfigure EP0 with the correct maximum packet size */
ep->wMaxPacketSize = ep_mps;
/* Assign a function address to the device connected to this port */
dev_addr = usbh_allocate_devaddr(&hport->bus->devgen);
if (dev_addr < 0) {
USB_LOG_ERR("Failed to allocate devaddr,errorcode:%d\r\n", ret);
goto errout;
}
/* Set the USB device address */
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_SET_ADDRESS;
setup->wValue = dev_addr;
setup->wIndex = 0;
setup->wLength = 0;
ret = usbh_control_transfer(hport, setup, NULL);
if (ret < 0) {
USB_LOG_ERR("Failed to set devaddr,errorcode:%d\r\n", ret);
goto errout;
}
/* Wait device set address completely */
usb_osal_msleep(2);
/*Reconfigure EP0 with the correct address */
hport->dev_addr = dev_addr;
/* Read the full device descriptor */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_DEVICE << 8) | 0);
setup->wIndex = 0;
setup->wLength = USB_SIZEOF_DEVICE_DESC;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
USB_LOG_ERR("Failed to get full device descriptor,errorcode:%d\r\n", ret);
goto errout;
}
parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], USB_SIZEOF_DEVICE_DESC);
USB_LOG_INFO("New device found,idVendor:%04x,idProduct:%04x,bcdDevice:%04x\r\n",
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idVendor,
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idProduct,
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->bcdDevice);
USB_LOG_INFO("The device has %d bNumConfigurations\r\n", ((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->bNumConfigurations);
config_index = 0;
USB_LOG_DBG("The device selects config %d\r\n", config_index);
/* Read the first 9 bytes of the config descriptor */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_CONFIGURATION << 8) | config_index);
setup->wIndex = 0;
setup->wLength = USB_SIZEOF_CONFIG_DESC;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
USB_LOG_ERR("Failed to get config descriptor,errorcode:%d\r\n", ret);
goto errout;
}
parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid], USB_SIZEOF_CONFIG_DESC);
/* Read the full size of the configuration data */
uint16_t wTotalLength = ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->wTotalLength;
if (wTotalLength > CONFIG_USBHOST_REQUEST_BUFFER_LEN) {
ret = -USB_ERR_NOMEM;
USB_LOG_ERR("wTotalLength %d is overflow, default is %d\r\n", wTotalLength, CONFIG_USBHOST_REQUEST_BUFFER_LEN);
goto errout;
}
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_CONFIGURATION << 8) | config_index);
setup->wIndex = 0;
setup->wLength = wTotalLength;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
USB_LOG_ERR("Failed to get full config descriptor,errorcode:%d\r\n", ret);
goto errout;
}
ret = parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid], wTotalLength);
if (ret < 0) {
USB_LOG_ERR("Parse config fail\r\n");
goto errout;
}
USB_LOG_INFO("The device has %d interfaces\r\n", ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->bNumInterfaces);
hport->raw_config_desc = usb_osal_malloc(wTotalLength);
if (hport->raw_config_desc == NULL) {
ret = -USB_ERR_NOMEM;
USB_LOG_ERR("No memory to alloc for raw_config_desc\r\n");
goto errout;
}
config_value = ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->bConfigurationValue;
memcpy(hport->raw_config_desc, ep0_request_buffer[hport->bus->busid], wTotalLength);
#ifdef CONFIG_USBHOST_GET_STRING_DESC
uint8_t string_buffer[128];
/* Get Manufacturer string */
memset(string_buffer, 0, 128);
ret = usbh_get_string_desc(hport, USB_STRING_MFC_INDEX, string_buffer);
if (ret < 0) {
USB_LOG_ERR("Failed to get Manufacturer string,errorcode:%d\r\n", ret);
goto errout;
}
USB_LOG_INFO("Manufacturer: %s\r\n", string_buffer);
/* Get Product string */
memset(string_buffer, 0, 128);
ret = usbh_get_string_desc(hport, USB_STRING_PRODUCT_INDEX, string_buffer);
if (ret < 0) {
USB_LOG_ERR("Failed to get get Product string,errorcode:%d\r\n", ret);
goto errout;
}
USB_LOG_INFO("Product: %s\r\n", string_buffer);
/* Get SerialNumber string */
memset(string_buffer, 0, 128);
ret = usbh_get_string_desc(hport, USB_STRING_SERIAL_INDEX, string_buffer);
if (ret < 0) {
USB_LOG_ERR("Failed to get get SerialNumber string,errorcode:%d\r\n", ret);
goto errout;
}
USB_LOG_INFO("SerialNumber: %s\r\n", string_buffer);
#endif
/* Select device configuration 1 */
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_SET_CONFIGURATION;
setup->wValue = config_value;
setup->wIndex = 0;
setup->wLength = 0;
ret = usbh_control_transfer(hport, setup, NULL);
if (ret < 0) {
USB_LOG_ERR("Failed to set configuration,errorcode:%d\r\n", ret);
goto errout;
}
#ifdef CONFIG_USBHOST_MSOS_ENABLE
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = CONFIG_USBHOST_MSOS_VENDOR_CODE;
setup->wValue = 0;
setup->wIndex = 0x0004;
setup->wLength = 16;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0 && (ret != -USB_ERR_STALL)) {
USB_LOG_ERR("Failed to get msosv1 compat id,errorcode:%d\r\n", ret);
goto errout;
}
#endif
USB_LOG_INFO("Enumeration success, start loading class driver\r\n");
/*search supported class driver*/
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
intf_desc = &hport->config.intf[i].altsetting[0].intf_desc;
struct usbh_class_driver *class_driver = (struct usbh_class_driver *)usbh_find_class_driver(intf_desc->bInterfaceClass, intf_desc->bInterfaceSubClass, intf_desc->bInterfaceProtocol, hport->device_desc.idVendor, hport->device_desc.idProduct);
if (class_driver == NULL) {
USB_LOG_ERR("do not support Class:0x%02x,Subclass:0x%02x,Protocl:0x%02x\r\n",
intf_desc->bInterfaceClass,
intf_desc->bInterfaceSubClass,
intf_desc->bInterfaceProtocol);
continue;
}
hport->config.intf[i].class_driver = class_driver;
USB_LOG_INFO("Loading %s class driver\r\n", class_driver->driver_name);
ret = CLASS_CONNECT(hport, i);
}
errout:
if (hport->raw_config_desc) {
usb_osal_free(hport->raw_config_desc);
hport->raw_config_desc = NULL;
}
return ret;
}
void usbh_hubport_release(struct usbh_hubport *hport)
{
if (hport->connected) {
hport->connected = false;
usbh_free_devaddr(hport);
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
if (hport->config.intf[i].class_driver && hport->config.intf[i].class_driver->disconnect) {
CLASS_DISCONNECT(hport, i);
}
}
hport->config.config_desc.bNumInterfaces = 0;
usbh_kill_urb(&hport->ep0_urb);
if (hport->mutex) {
usb_osal_mutex_delete(hport->mutex);
}
}
}
static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uintptr_t reg_base)
{
memset(bus, 0, sizeof(struct usbh_bus));
bus->busid = busid;
bus->hcd.hcd_id = busid;
bus->hcd.reg_base = reg_base;
/* devaddr 1 is for roothub */
bus->devgen.next = 2;
usb_slist_add_tail(&g_bus_head, &bus->list);
}
int usbh_initialize(uint8_t busid, uintptr_t reg_base)
{
struct usbh_bus *bus;
if (busid >= CONFIG_USBHOST_MAX_BUS) {
USB_LOG_ERR("bus overflow\r\n");
while (1) {
}
}
bus = &g_usbhost_bus[busid];
usbh_bus_init(bus, busid, reg_base);
#ifdef __ARMCC_VERSION /* ARM C Compiler */
extern const int usbh_class_info$$Base;
extern const int usbh_class_info$$Limit;
usbh_class_info_table_begin = (struct usbh_class_info *)&usbh_class_info$$Base;
usbh_class_info_table_end = (struct usbh_class_info *)&usbh_class_info$$Limit;
#elif defined(__GNUC__)
extern uint32_t __usbh_class_info_start__;
extern uint32_t __usbh_class_info_end__;
usbh_class_info_table_begin = (struct usbh_class_info *)&__usbh_class_info_start__;
usbh_class_info_table_end = (struct usbh_class_info *)&__usbh_class_info_end__;
#elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
usbh_class_info_table_begin = (struct usbh_class_info *)__section_begin(".usbh_class_info");
usbh_class_info_table_end = (struct usbh_class_info *)__section_end(".usbh_class_info");
#endif
usbh_hub_initialize(bus);
return 0;
}
int usbh_deinitialize(uint8_t busid)
{
struct usbh_bus *bus;
bus = &g_usbhost_bus[busid];
usbh_hub_deinitialize(bus);
usb_slist_remove(&g_bus_head, &bus->list);
return 0;
}
int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer)
{
struct usbh_urb *urb;
int ret;
urb = &hport->ep0_urb;
usb_osal_mutex_take(hport->mutex);
usbh_control_urb_fill(urb, hport, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
usb_osal_mutex_give(hport->mutex);
return ret;
}
int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *output)
{
struct usb_setup_packet *setup = hport->setup;
int ret;
uint8_t *src;
uint8_t *dst;
uint16_t len;
uint16_t i = 2;
uint16_t j = 0;
/* Get Manufacturer string */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_STRING << 8) | index);
setup->wIndex = 0x0409;
setup->wLength = 255;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
return ret;
}
src = ep0_request_buffer[hport->bus->busid];
dst = output;
len = src[0];
while (i < len) {
dst[j] = src[i];
i += 2;
j++;
}
return 0;
}
int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsetting)
{
struct usb_setup_packet *setup = hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = USB_REQUEST_SET_INTERFACE;
setup->wValue = altsetting;
setup->wIndex = intf;
setup->wLength = 0;
return usbh_control_transfer(hport, setup, NULL);
}
static void *usbh_list_all_interface_name(struct usbh_hub *hub, const char *devname)
{
struct usbh_hubport *hport;
struct usbh_hub *hub_next;
void *priv;
for (uint8_t port = 0; port < hub->nports; port++) {
hport = &hub->child[port];
if (hport->connected) {
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv)
return hport->config.intf[itf].priv;
if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
hub_next = hport->config.intf[itf].priv;
if (hub_next && hub_next->connected) {
priv = usbh_list_all_interface_name(hub_next, devname);
if (priv) {
return priv;
}
}
}
}
}
}
}
return NULL;
}
static void usbh_list_all_interface_driver(struct usbh_hub *hub)
{
struct usbh_hubport *hport;
struct usbh_hub *hub_next;
const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed", "wireless-speed", "super-speed", "superplus-speed" };
for (uint8_t port = 0; port < hub->nports; port++) {
hport = &hub->child[port];
if (hport->connected) {
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
for (uint8_t j = 0; j < hub->index; j++) {
USB_LOG_RAW("\t");
}
USB_LOG_RAW("|__Port %u, dev addr:0x%02x, If %u, ClassDriver=%s, %s\r\n",
hport->port,
hport->dev_addr,
itf,
hport->config.intf[itf].class_driver->driver_name,
speed_table[hport->speed]);
if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
hub_next = hport->config.intf[itf].priv;
if (hub_next && hub_next->connected) {
usbh_list_all_interface_driver(hub_next);
}
}
}
}
}
}
}
static void usbh_list_all_interface_desc(struct usbh_bus *bus, struct usbh_hub *hub)
{
struct usbh_hubport *hport;
struct usbh_hub *hub_next;
for (uint8_t port = 0; port < hub->nports; port++) {
hport = &hub->child[port];
if (hport->connected) {
USB_LOG_RAW("\r\nBus %u, Hub %u, Port %u, dev addr:0x%02x, VID:PID 0x%04x:0x%04x\r\n",
bus->busid,
hub->index,
hport->port,
hport->dev_addr,
hport->device_desc.idVendor,
hport->device_desc.idProduct);
usbh_print_hubport_info(hport);
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
hub_next = hport->config.intf[itf].priv;
if (hub_next && hub_next->connected) {
usbh_list_all_interface_desc(bus, hub_next);
}
}
}
}
}
}
}
void *usbh_find_class_instance(const char *devname)
{
usb_slist_t *bus_list;
struct usbh_hub *hub;
struct usbh_bus *bus;
void *priv;
size_t flags;
flags = usb_osal_enter_critical_section();
usb_slist_for_each(bus_list, &g_bus_head)
{
bus = usb_slist_entry(bus_list, struct usbh_bus, list);
hub = &bus->hcd.roothub;
priv = usbh_list_all_interface_name(hub, devname);
if (priv) {
usb_osal_leave_critical_section(flags);
return priv;
}
}
usb_osal_leave_critical_section(flags);
return NULL;
}
int lsusb(int argc, char **argv)
{
usb_slist_t *bus_list;
struct usbh_hub *hub;
struct usbh_bus *bus;
size_t flags;
if (argc < 2) {
USB_LOG_RAW("Usage: lsusb [options]...\r\n");
USB_LOG_RAW("List USB devices\r\n");
USB_LOG_RAW(" -v, --verbose\r\n");
USB_LOG_RAW(" Increase verbosity (show descriptors)\r\n");
// USB_LOG_RAW(" -s [[bus]:[devnum]]\r\n");
// USB_LOG_RAW(" Show only devices with specified device and/or bus numbers (in decimal)\r\n");
// USB_LOG_RAW(" -d vendor:[product]\r\n");
// USB_LOG_RAW(" Show only devices with the specified vendor and product ID numbers (in hexadecimal)\r\n");
USB_LOG_RAW(" -t, --tree\r\n");
USB_LOG_RAW(" Dump the physical USB device hierachy as a tree\r\n");
USB_LOG_RAW(" -V, --version\r\n");
USB_LOG_RAW(" Show version of program\r\n");
USB_LOG_RAW(" -h, --help\r\n");
USB_LOG_RAW(" Show usage and help\r\n");
return 0;
}
if (argc > 3) {
return 0;
}
flags = usb_osal_enter_critical_section();
if (strcmp(argv[1], "-V") == 0) {
USB_LOG_RAW("CherryUSB Version %s\r\n", CHERRYUSB_VERSION_STR);
}
if (strcmp(argv[1], "-t") == 0) {
usb_slist_for_each(bus_list, &g_bus_head)
{
bus = usb_slist_entry(bus_list, struct usbh_bus, list);
hub = &bus->hcd.roothub;
USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, is roothub\r\n",
bus->busid,
hub->index,
hub->nports);
usbh_list_all_interface_driver(hub);
}
}
if (strcmp(argv[1], "-v") == 0) {
usb_slist_for_each(bus_list, &g_bus_head)
{
bus = usb_slist_entry(bus_list, struct usbh_bus, list);
hub = &bus->hcd.roothub;
usbh_list_all_interface_desc(bus, hub);
}
}
usb_osal_leave_critical_section(flags);
return 0;
}

View File

@ -1,285 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_CORE_H
#define USBH_CORE_H
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include "usb_config.h"
#include "usb_util.h"
#include "usb_errno.h"
#include "usb_def.h"
#include "usb_list.h"
#include "usb_log.h"
#include "usb_hc.h"
#include "usb_osal.h"
#include "usbh_hub.h"
#include "usb_memcpy.h"
#include "usb_version.h"
#ifdef __cplusplus
extern "C" {
#endif
#define USB_CLASS_MATCH_VENDOR 0x0001
#define USB_CLASS_MATCH_PRODUCT 0x0002
#define USB_CLASS_MATCH_INTF_CLASS 0x0004
#define USB_CLASS_MATCH_INTF_SUBCLASS 0x0008
#define USB_CLASS_MATCH_INTF_PROTOCOL 0x0010
#define USB_CLASS_MATCH_VID_PID (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT)
#define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i))
#define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i))
#ifdef __ARMCC_VERSION /* ARM C Compiler */
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
#elif defined(__GNUC__)
#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1)
#elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
#pragma section = ".usbh_class_info"
#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1)
#endif
#define USBH_GET_URB_INTERVAL(interval, speed) (speed < USB_SPEED_HIGH ? interval : (1 << (interval - 1)))
#define USBH_EP_INIT(ep, ep_desc) \
do { \
ep = ep_desc; \
USB_LOG_INFO("Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n", \
ep_desc->bEndpointAddress, \
ep_desc->bmAttributes, \
USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize), \
ep_desc->bInterval, \
USB_GET_MULT(ep_desc->wMaxPacketSize)); \
} while (0)
struct usbh_class_info {
uint8_t match_flags; /* Used for product specific matches; range is inclusive */
uint8_t class; /* Base device class code */
uint8_t subclass; /* Sub-class, depends on base class. Eg. */
uint8_t protocol; /* Protocol, depends on base class. Eg. */
const uint16_t (*id_table)[2]; /* List of Vendor/Product ID pairs */
const struct usbh_class_driver *class_driver;
};
struct usbh_hubport;
struct usbh_class_driver {
const char *driver_name;
int (*connect)(struct usbh_hubport *hport, uint8_t intf);
int (*disconnect)(struct usbh_hubport *hport, uint8_t intf);
};
struct usbh_endpoint {
struct usb_endpoint_descriptor ep_desc;
};
struct usbh_interface_altsetting {
struct usb_interface_descriptor intf_desc;
struct usbh_endpoint ep[CONFIG_USBHOST_MAX_ENDPOINTS];
};
struct usbh_interface {
char devname[CONFIG_USBHOST_DEV_NAMELEN];
struct usbh_class_driver *class_driver;
void *priv;
struct usbh_interface_altsetting altsetting[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS];
uint8_t altsetting_num;
};
struct usbh_configuration {
struct usb_configuration_descriptor config_desc;
struct usbh_interface intf[CONFIG_USBHOST_MAX_INTERFACES];
};
struct usbh_hubport {
bool connected; /* True: device connected; false: disconnected */
uint8_t port; /* Hub port index */
uint8_t dev_addr; /* device address */
uint8_t speed; /* device speed */
uint8_t depth; /* distance from root hub */
uint8_t route; /* route string */
uint8_t slot_id; /* slot id */
struct usb_device_descriptor device_desc;
struct usbh_configuration config;
const char *iManufacturer;
const char *iProduct;
const char *iSerialNumber;
uint8_t *raw_config_desc;
struct usb_setup_packet *setup;
struct usbh_hub *parent;
struct usbh_hub *self; /* if this hubport is a hub */
struct usbh_bus *bus;
struct usb_endpoint_descriptor ep0;
struct usbh_urb ep0_urb;
usb_osal_mutex_t mutex;
};
struct usbh_hub {
bool connected;
bool is_roothub;
uint8_t index;
uint8_t hub_addr;
uint8_t speed;
uint8_t nports;
uint8_t powerdelay;
uint8_t tt_think;
bool ismtt;
struct usb_hub_descriptor hub_desc; /* USB 2.0 only */
struct usb_hub_ss_descriptor hub_ss_desc; /* USB 3.0 only */
struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
struct usbh_hubport *parent;
struct usbh_bus *bus;
struct usb_endpoint_descriptor *intin;
struct usbh_urb intin_urb;
uint8_t *int_buffer;
struct usb_osal_timer *int_timer;
};
struct usbh_devaddr_map {
/**
* alloctab[0]:addr from 0~31
* alloctab[1]:addr from 32~63
* alloctab[2]:addr from 64~95
* alloctab[3]:addr from 96~127
*
*/
uint8_t next; /* Next device address */
uint32_t alloctab[4]; /* Bit allocation table */
};
struct usbh_hcd {
uintptr_t reg_base;
uint8_t hcd_id;
uint8_t roothub_intbuf[2]; /* at most 15 roothub ports */
struct usbh_hub roothub;
};
struct usbh_bus {
usb_slist_t list;
uint8_t busid;
struct usbh_hcd hcd;
struct usbh_devaddr_map devgen;
usb_osal_thread_t hub_thread;
usb_osal_mq_t hub_mq;
};
static inline void usbh_control_urb_fill(struct usbh_urb *urb,
struct usbh_hubport *hport,
struct usb_setup_packet *setup,
uint8_t *transfer_buffer,
uint32_t transfer_buffer_length,
uint32_t timeout,
usbh_complete_callback_t complete,
void *arg)
{
urb->hport = hport;
urb->ep = &hport->ep0;
urb->setup = setup;
urb->transfer_buffer = transfer_buffer;
urb->transfer_buffer_length = transfer_buffer_length;
urb->timeout = timeout;
urb->complete = complete;
urb->arg = arg;
}
static inline void usbh_bulk_urb_fill(struct usbh_urb *urb,
struct usbh_hubport *hport,
struct usb_endpoint_descriptor *ep,
uint8_t *transfer_buffer,
uint32_t transfer_buffer_length,
uint32_t timeout,
usbh_complete_callback_t complete,
void *arg)
{
urb->hport = hport;
urb->ep = ep;
urb->setup = NULL;
urb->transfer_buffer = transfer_buffer;
urb->transfer_buffer_length = transfer_buffer_length;
urb->timeout = timeout;
urb->complete = complete;
urb->arg = arg;
}
static inline void usbh_int_urb_fill(struct usbh_urb *urb,
struct usbh_hubport *hport,
struct usb_endpoint_descriptor *ep,
uint8_t *transfer_buffer,
uint32_t transfer_buffer_length,
uint32_t timeout,
usbh_complete_callback_t complete,
void *arg)
{
urb->hport = hport;
urb->ep = ep;
urb->setup = NULL;
urb->transfer_buffer = transfer_buffer;
urb->transfer_buffer_length = transfer_buffer_length;
urb->timeout = timeout;
urb->complete = complete;
urb->arg = arg;
urb->interval = USBH_GET_URB_INTERVAL(ep->bInterval, hport->speed);
}
extern struct usbh_bus g_usbhost_bus[];
#ifdef USBH_IRQHandler
#error USBH_IRQHandler is obsolete, please call USBH_IRQHandler(xxx) in your irq
#endif
/**
* @brief Submit an control transfer to an endpoint.
* This is a blocking method; this method will not return until the transfer has completed.
* Default timeout is 500ms.
*
* @param pipe The control endpoint to send/receive the control request.
* @param setup Setup packet to be sent.
* @param buffer buffer used for sending the request and for returning any responses.
* @return On success will return 0, and others indicate fail.
*/
int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer);
/**
* @brief Retrieves a USB string descriptor from a specific hub port.
*
* This function is responsible for retrieving the USB string descriptor
* with the specified index from the USB device connected to the given hub port.
* The retrieved descriptor is stored in the output buffer provided.
*
* @param hport Pointer to the USB hub port structure.
* @param index Index of the string descriptor to retrieve.
* @param output Pointer to the buffer where the retrieved descriptor will be stored.
* @return On success will return 0, and others indicate fail.
*/
int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *output);
/**
* @brief Sets the alternate setting for a USB interface on a specific hub port.
*
* This function is responsible for setting the alternate setting of the
* specified USB interface on the USB device connected to the given hub port.
* The interface and alternate setting are identified by the respective parameters.
*
* @param hport Pointer to the USB hub port structure.
* @param intf Interface number to set the alternate setting for.
* @param altsetting Alternate setting value to set for the interface.
* @return On success will return 0, and others indicate fail.
*/
int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsetting);
int usbh_initialize(uint8_t busid, uintptr_t reg_base);
int usbh_deinitialize(uint8_t busid);
void *usbh_find_class_instance(const char *devname);
int lsusb(int argc, char **argv);
#ifdef __cplusplus
}
#endif
#endif /* USBH_CORE_H */

View File

@ -1,41 +0,0 @@
# Note
If you are using more than one port, all ip parameters must be the same(like fifo num, endpoint num, dma support and so on), otherwise give up using multi ports.
## Support Chip List
## STM32
- STM32F105xc、STM32F107xc
- STM32F205xx、STM32F207xx、STM32F215xx、STM32F217xx
- STM32F401xc、STM32F401xe、STM32F405xx、STM32F407xx、STM32F411xe、STM32F412cx、STM32F412rx、STM32F412vx、STM32F412zx、STM32F413xx、STM32F415xx、STM32F417xx、STM32F423xx、STM32F423xx、STM32F429xx、STM32F437xx、STM32F439xx、STM32F446xx、STM32F469xx、STM32F479xx
- STM32F7xx
- STM32H7xx
- STM32L4xx
- STM32MPxx
## AT32
- AT32F402xx、AT32F405xx、AT32F415xx、AT32F423xx、AT32F425xx、AT32F435xx、AT32F437xx
## GD32
- GD32F30X_CL
- GD32F405、GD32F407
- GD32F450
## HC32
- HC32F4A0
## Espressif
- ESP32S2、ESP32S3
## Sophgo
- CV18xx
## Kendryte
- K230

View File

@ -1,57 +0,0 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usb_config.h"
#include "stdint.h"
#include "usb_dwc2_reg.h"
/* you can find this config in function: usb_global_init, file:at32fxxx_usb.c, for example:
*
* usbx->gccfg_bit.pwrdown = TRUE;
* usbx->gccfg_bit.avalidsesen = TRUE;
* usbx->gccfg_bit.bvalidsesen = TRUE;
*
*/
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
{
#ifdef CONFIG_USB_HS
return ((1 << 16) | (1 << 21));
#else
// AT32F415
#if defined(AT32F415RCT7) || defined(AT32F415RCT7_7) || defined(AT32F415CCT7) || \
defined(AT32F415CCU7) || defined(AT32F415KCU7_4) || defined(AT32F415RBT7) || \
defined(AT32F415RBT7_7) || defined(AT32F415CBT7) || defined(AT32F415CBU7) || \
defined(AT32F415KBU7_4) || defined(AT32F415R8T7) || defined(AT32F415R8T7_7) || \
defined(AT32F415C8T7) || defined(AT32F415K8U7_4)
return ((1 << 16) | (1 << 18) | (1 << 19) | (1 << 21));
#else
return ((1 << 16) | (1 << 21));
#endif
#endif
}
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
{
#ifdef CONFIG_USB_HS
return ((1 << 16) | (1 << 21));
#else
// AT32F415
#if defined(AT32F415RCT7) || defined(AT32F415RCT7_7) || defined(AT32F415CCT7) || \
defined(AT32F415CCU7) || defined(AT32F415KCU7_4) || defined(AT32F415RBT7) || \
defined(AT32F415RBT7_7) || defined(AT32F415CBT7) || defined(AT32F415CBU7) || \
defined(AT32F415KBU7_4) || defined(AT32F415R8T7) || defined(AT32F415R8T7_7) || \
defined(AT32F415C8T7) || defined(AT32F415K8U7_4)
return ((1 << 16) | (1 << 18) | (1 << 19) | (1 << 21));
#else
return ((1 << 16) | (1 << 21));
#endif
#endif
}
void usbd_dwc2_delay_ms(uint8_t ms)
{
/* implement later */
}

View File

@ -1,131 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "esp_idf_version.h"
#include "esp_intr_alloc.h"
#include "esp_private/usb_phy.h"
#include "soc/periph_defs.h"
#include "freertos/FreeRTOS.h"
#include "usbd_core.h"
#include "usbh_core.h"
#ifdef CONFIG_IDF_TARGET_ESP32S2
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_USB_INTR_SOURCE ETS_USB_INTR_SOURCE
#elif CONFIG_IDF_TARGET_ESP32S3
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_USB_INTR_SOURCE ETS_USB_INTR_SOURCE
#elif CONFIG_IDF_TARGET_ESP32P4
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_USB_INTR_SOURCE ETS_USB_OTG_INTR_SOURCE
#else
#define DEFAULT_CPU_FREQ_MHZ 160
#endif
uint32_t SystemCoreClock = (DEFAULT_CPU_FREQ_MHZ * 1000 * 1000);
static usb_phy_handle_t s_phy_handle = NULL;
static intr_handle_t s_interrupt_handle = NULL;
static void usb_dc_interrupt_cb(void *arg_pv)
{
extern void USBD_IRQHandler(uint8_t busid);
USBD_IRQHandler(0);
}
void usb_dc_low_level_init(uint8_t busid)
{
usb_phy_config_t phy_config = {
.controller = USB_PHY_CTRL_OTG,
.otg_mode = USB_OTG_MODE_DEVICE,
.target = USB_PHY_TARGET_INT,
};
esp_err_t ret = usb_new_phy(&phy_config, &s_phy_handle);
if (ret != ESP_OK) {
USB_LOG_ERR("USB Phy Init Failed!\r\n");
return;
}
// TODO: Check when to enable interrupt
ret = esp_intr_alloc(DEFAULT_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, usb_dc_interrupt_cb, 0, &s_interrupt_handle);
if (ret != ESP_OK) {
USB_LOG_ERR("USB Interrupt Init Failed!\r\n");
return;
}
USB_LOG_INFO("cherryusb, version: "CHERRYUSB_VERSION_STR"\r\n");
}
void usb_dc_low_level_deinit(uint8_t busid)
{
if (s_interrupt_handle) {
esp_intr_free(s_interrupt_handle);
s_interrupt_handle = NULL;
}
if (s_phy_handle) {
usb_del_phy(s_phy_handle);
s_phy_handle = NULL;
}
}
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
{
return 0;
}
static void usb_hc_interrupt_cb(void *arg_pv)
{
extern void USBH_IRQHandler(uint8_t busid);
USBH_IRQHandler(0);
}
void usb_hc_low_level_init(struct usbh_bus *bus)
{
// Host Library defaults to internal PHY
usb_phy_config_t phy_config = {
.controller = USB_PHY_CTRL_OTG,
.target = USB_PHY_TARGET_INT,
.otg_mode = USB_OTG_MODE_HOST,
.otg_speed = USB_PHY_SPEED_UNDEFINED, // In Host mode, the speed is determined by the connected device
.ext_io_conf = NULL,
.otg_io_conf = NULL,
};
esp_err_t ret = usb_new_phy(&phy_config, &s_phy_handle);
if (ret != ESP_OK) {
USB_LOG_ERR("USB Phy Init Failed!\r\n");
return;
}
// TODO: Check when to enable interrupt
ret = esp_intr_alloc(DEFAULT_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, usb_hc_interrupt_cb, 0, &s_interrupt_handle);
if (ret != ESP_OK) {
USB_LOG_ERR("USB Interrupt Init Failed!\r\n");
return;
}
USB_LOG_INFO("cherryusb, version: "CHERRYUSB_VERSION_STR"\r\n");
}
void usb_hc_low_level_deinit(struct usbh_bus *bus)
{
if (s_interrupt_handle) {
esp_intr_free(s_interrupt_handle);
s_interrupt_handle = NULL;
}
if (s_phy_handle) {
usb_del_phy(s_phy_handle);
s_phy_handle = NULL;
}
}
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
{
return 0;
}
void usbd_dwc2_delay_ms(uint8_t ms)
{
vTaskDelay(pdMS_TO_TICKS(ms));
}

View File

@ -1,37 +0,0 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usb_config.h"
#include "stdint.h"
#include "usb_dwc2_reg.h"
/* you can find this config in function:usb_core_init, file:drv_usb_core.c, for example:
*
* usb_regs->gr->GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN;
*
*/
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
{
#ifdef CONFIG_USB_HS
return 0;
#else
return ((1 << 16) | (1 << 18) | (1 << 19) | (1 << 21));
#endif
}
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
{
#ifdef CONFIG_USB_HS
return 0;
#else
return ((1 << 16) | (1 << 18) | (1 << 19) | (1 << 21));
#endif
}
void usbd_dwc2_delay_ms(uint8_t ms)
{
/* implement later */
}

View File

@ -1,31 +0,0 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usb_config.h"
#include "usb_dwc2_reg.h"
/* When using [GPIO_SetFunc(USBF_VBUS_PORT, USBF_VBUS_PIN, USBF_VBUS_FUNC);], there is no need to configure GOTGCTL */
#define USB_OTG_GLB ((DWC2_GlobalTypeDef *)(reg_base))
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
{
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
return 0;
}
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
{
USB_OTG_GLB->GOTGCTL &= ~USB_OTG_GOTGCTL_BVALOEN;
USB_OTG_GLB->GOTGCTL &= ~USB_OTG_GOTGCTL_BVALOVAL;
return 0;
}
void usbd_dwc2_delay_ms(uint8_t ms)
{
/* implement later */
}

View File

@ -1,157 +0,0 @@
/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtthread.h>
#include <rthw.h>
#include "usbd_core.h"
#include "usbh_core.h"
#define DEFAULT_USB_HCLK_FREQ_MHZ 200
uint32_t SystemCoreClock = (DEFAULT_USB_HCLK_FREQ_MHZ * 1000 * 1000);
uintptr_t g_usb_otg0_base = (uintptr_t)0x91500000UL;
uintptr_t g_usb_otg1_base = (uintptr_t)0x91540000UL;
static void sysctl_reset_hw_done(volatile uint32_t *reset_reg, uint8_t reset_bit, uint8_t done_bit)
{
*reset_reg |= (1 << done_bit); /* clear done bit */
rt_thread_mdelay(1);
*reset_reg |= (1 << reset_bit); /* set reset bit */
rt_thread_mdelay(1);
/* check done bit */
while (*reset_reg & (1 << done_bit) == 0)
;
}
#define USB_IDPULLUP0 (1 << 4)
#define USB_DMPULLDOWN0 (1 << 8)
#define USB_DPPULLDOWN0 (1 << 9)
#ifdef PKG_CHERRYUSB_HOST
static void usb_hc_interrupt_cb(int irq, void *arg_pv)
{
extern void USBH_IRQHandler(uint8_t busid);
USBH_IRQHandler((uint8_t)(uintptr_t)arg_pv);
}
void usb_hc_low_level_init(struct usbh_bus *bus)
{
uint32_t *hs_reg;
uint32_t usb_ctl3;
if (bus->hcd.hcd_id == 0) {
sysctl_reset_hw_done((volatile uint32_t *)0x9110103c, 0, 28);
hs_reg = (uint32_t *)rt_ioremap((void *)(0x91585000 + 0x7C), 0x1000);
usb_ctl3 = *hs_reg | USB_IDPULLUP0;
*hs_reg = usb_ctl3 | (USB_DMPULLDOWN0 | USB_DPPULLDOWN0);
rt_iounmap(hs_reg);
rt_hw_interrupt_install(173, usb_hc_interrupt_cb, NULL, "usbh0");
rt_hw_interrupt_umask(173);
} else {
sysctl_reset_hw_done((volatile uint32_t *)0x9110103c, 1, 29);
hs_reg = (uint32_t *)rt_ioremap((void *)(0x91585000 + 0x9C), 0x1000);
usb_ctl3 = *hs_reg | USB_IDPULLUP0;
*hs_reg = usb_ctl3 | (USB_DMPULLDOWN0 | USB_DPPULLDOWN0);
rt_iounmap(hs_reg);
rt_hw_interrupt_install(174, usb_hc_interrupt_cb, 1, "usbh1");
rt_hw_interrupt_umask(174);
}
}
void usb_hc_low_level_deinit(struct usbh_bus *bus)
{
if (bus->hcd.hcd_id == 0) {
rt_hw_interrupt_mask(173);
} else {
rt_hw_interrupt_mask(174);
}
}
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
{
return 0;
}
#endif
#ifdef PKG_CHERRYUSB_DEVICE
static void usb_dc_interrupt_cb(int irq, void *arg_pv)
{
extern void USBD_IRQHandler(uint8_t busid);
USBD_IRQHandler(0);
}
#ifdef CHERRYUSB_DEVICE_USING_USB0
void usb_dc_low_level_init(uint8_t busid)
{
sysctl_reset_hw_done((volatile uint32_t *)0x9110103c, 0, 28);
uint32_t *hs_reg = (uint32_t *)rt_ioremap((void *)(0x91585000 + 0x7C), 0x1000);
*hs_reg = 0x37;
rt_iounmap(hs_reg);
rt_hw_interrupt_install(173, usb_dc_interrupt_cb, NULL, "usbd");
rt_hw_interrupt_umask(173);
}
void usb_dc_low_level_deinit(uint8_t busid)
{
rt_hw_interrupt_mask(173);
}
#else
void usb_dc_low_level_init(uint8_t busid)
{
sysctl_reset_hw_done((volatile uint32_t *)0x9110103c, 1, 29);
uint32_t *hs_reg = (uint32_t *)rt_ioremap((void *)(0x91585000 + 0x9C), 0x1000);
*hs_reg = 0x37;
rt_iounmap(hs_reg);
rt_hw_interrupt_install(174, usb_dc_interrupt_cb, NULL, "usbd");
rt_hw_interrupt_umask(174);
}
void usb_dc_low_level_deinit(uint8_t busid)
{
rt_hw_interrupt_mask(174);
}
#endif
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
{
return 0;
}
void usbd_dwc2_delay_ms(uint8_t ms)
{
/* implement later */
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,33 +0,0 @@
# Note
## Support Chip List
## STM32
- STM32F042x6、STM32F048xx、STM32F070x6、STM32F070xb、STM32F072xb、STM32F078xx
- STM32F102x6、STM32F102xb、STM32F103x6、STM32F103xb、STM32F103xe、STM32F103xg
- STM32F302x8、STM32F302xc、STM32F302xe、STM32F373xc
- STM32g431xx、STM32g441xx、STM32g471xx、STM32g483xx、STM32g484xx、STM32gbk1cb
- STM32l052xx、STM32l053xx、STM32l062xx、STM32l063xx、STM32l072xx、STM32l073xx、STM32l082xx、STM32l083xx
- STM32l100xb、STM32l100xba、STM32l100xc、STM32l151xb、STM32l151xba、STM32l151xc、STM32l151xca、STM32l151xd、STM32l151xdx、STM32l151xe、STM32l152xb、STM32l152xba、STM32l152xc、STM32l152xa、STM32l152xd、STM32l152xdx、STM32l152xe、STM32l162xc、STM32l162xca、STM32l162xd、STM32l162xdx、STM32l162xe
- STM32l412xx、STM32l422xx、STM32l432xx、STM32l433xx、STM32l442xx、STM32l452xx、STM32l462xx
- STM32wb5mxx、STM32wb35xx、STM32wb55xx
## AT32
- AT32F403xx、AT32F407xx、AT32F413xx
## APM32
- APM32f10x
## GD32
- GD32F10X_MD、GD32F10X_HD、GD32F10X_XD
- GD32F30X_HD、GD32F30X_XD
- GD32F350
- GD32F407
## CH32
- CH32F10x、CH32V10x

View File

@ -1,557 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#ifndef CONFIG_USBDEV_FSDEV_PMA_ACCESS
#error "please define CONFIG_USBDEV_FSDEV_PMA_ACCESS in usb_config.h"
#endif
#define PMA_ACCESS CONFIG_USBDEV_FSDEV_PMA_ACCESS
#include "usb_fsdev_reg.h"
#ifndef CONFIG_USB_FSDEV_RAM_SIZE
#define CONFIG_USB_FSDEV_RAM_SIZE 512
#endif
#ifndef CONFIG_USBDEV_EP_NUM
#define CONFIG_USBDEV_EP_NUM 8
#endif
#define USB ((USB_TypeDef *)g_usbdev_bus[0].reg_base)
#define USB_BTABLE_SIZE (8 * CONFIG_USBDEV_EP_NUM)
static void fsdev_write_pma(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes);
static void fsdev_read_pma(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes);
/* Endpoint state */
struct fsdev_ep_state {
uint16_t ep_mps; /* Endpoint max packet size */
uint8_t ep_type; /* Endpoint type */
uint8_t ep_stalled; /* Endpoint stall flag */
uint8_t ep_enable; /* Endpoint enable */
uint16_t ep_pma_buf_len; /* Previously allocated buffer size */
uint16_t ep_pma_addr; /* ep pmd allocated addr */
uint8_t *xfer_buf;
uint32_t xfer_len;
uint32_t actual_xfer_len;
};
/* Driver state */
struct fsdev_udc {
struct usb_setup_packet setup;
volatile uint8_t dev_addr; /*!< USB Address */
volatile uint32_t pma_offset; /*!< pma offset */
struct fsdev_ep_state in_ep[CONFIG_USBDEV_EP_NUM]; /*!< IN endpoint parameters*/
struct fsdev_ep_state out_ep[CONFIG_USBDEV_EP_NUM]; /*!< OUT endpoint parameters */
} g_fsdev_udc;
__WEAK void usb_dc_low_level_init(void)
{
}
__WEAK void usb_dc_low_level_deinit(void)
{
}
int usb_dc_init(uint8_t busid)
{
usb_dc_low_level_init();
/* Init Device */
/* CNTR_FRES = 1 */
USB->CNTR = (uint16_t)USB_CNTR_FRES;
/* CNTR_FRES = 0 */
USB->CNTR = 0U;
/* Clear pending interrupts */
USB->ISTR = 0U;
/*Set Btable Address*/
USB->BTABLE = BTABLE_ADDRESS;
uint32_t winterruptmask;
/* Set winterruptmask variable */
winterruptmask = USB_CNTR_CTRM | USB_CNTR_WKUPM |
USB_CNTR_SUSPM | USB_CNTR_ERRM |
USB_CNTR_SOFM | USB_CNTR_ESOFM |
USB_CNTR_RESETM;
/* Set interrupt mask */
USB->CNTR = (uint16_t)winterruptmask;
/* Enabling DP Pull-UP bit to Connect internal PU resistor on USB DP line */
USB->BCDR |= (uint16_t)USB_BCDR_DPPU;
return 0;
}
int usb_dc_deinit(uint8_t busid)
{
/* disable all interrupts and force USB reset */
USB->CNTR = (uint16_t)USB_CNTR_FRES;
/* clear interrupt status register */
USB->ISTR = 0U;
/* switch-off device */
USB->CNTR = (uint16_t)(USB_CNTR_FRES | USB_CNTR_PDWN);
usb_dc_low_level_deinit();
return 0;
}
int usbd_set_address(uint8_t busid, const uint8_t addr)
{
if (addr == 0U) {
/* set device address and enable function */
USB->DADDR = (uint16_t)USB_DADDR_EF;
}
g_fsdev_udc.dev_addr = addr;
return 0;
}
int usbd_set_remote_wakeup(uint8_t busid)
{
return -1;
}
uint8_t usbd_get_port_speed(uint8_t busid)
{
return USB_SPEED_FULL;
}
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
if (ep_idx > (CONFIG_USBDEV_EP_NUM - 1)) {
USB_LOG_ERR("Ep addr %02x overflow\r\n", ep->bEndpointAddress);
return -1;
}
uint16_t wEpRegVal;
/* initialize Endpoint */
switch (USB_GET_ENDPOINT_TYPE(ep->bmAttributes)) {
case USB_ENDPOINT_TYPE_CONTROL:
wEpRegVal = USB_EP_CONTROL;
break;
case USB_ENDPOINT_TYPE_BULK:
wEpRegVal = USB_EP_BULK;
break;
case USB_ENDPOINT_TYPE_INTERRUPT:
wEpRegVal = USB_EP_INTERRUPT;
break;
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
wEpRegVal = USB_EP_ISOCHRONOUS;
break;
default:
break;
}
PCD_SET_EPTYPE(USB, ep_idx, wEpRegVal);
PCD_SET_EP_ADDRESS(USB, ep_idx, ep_idx);
if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
g_fsdev_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
g_fsdev_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
g_fsdev_udc.out_ep[ep_idx].ep_enable = true;
if (g_fsdev_udc.out_ep[ep_idx].ep_mps > g_fsdev_udc.out_ep[ep_idx].ep_pma_buf_len) {
if (g_fsdev_udc.pma_offset + g_fsdev_udc.out_ep[ep_idx].ep_mps > CONFIG_USB_FSDEV_RAM_SIZE) {
USB_LOG_ERR("Ep pma %02x overflow\r\n", ep->bEndpointAddress);
return -1;
}
g_fsdev_udc.out_ep[ep_idx].ep_pma_buf_len = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
g_fsdev_udc.out_ep[ep_idx].ep_pma_addr = g_fsdev_udc.pma_offset;
/*Set the endpoint Receive buffer address */
PCD_SET_EP_RX_ADDRESS(USB, ep_idx, g_fsdev_udc.pma_offset);
g_fsdev_udc.pma_offset += USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
}
/*Set the endpoint Receive buffer counter*/
PCD_SET_EP_RX_CNT(USB, ep_idx, USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize));
PCD_CLEAR_RX_DTOG(USB, ep_idx);
} else {
g_fsdev_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
g_fsdev_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
g_fsdev_udc.in_ep[ep_idx].ep_enable = true;
if (g_fsdev_udc.in_ep[ep_idx].ep_mps > g_fsdev_udc.in_ep[ep_idx].ep_pma_buf_len) {
if (g_fsdev_udc.pma_offset + g_fsdev_udc.in_ep[ep_idx].ep_mps > CONFIG_USB_FSDEV_RAM_SIZE) {
USB_LOG_ERR("Ep pma %02x overflow\r\n", ep->bEndpointAddress);
return -1;
}
g_fsdev_udc.in_ep[ep_idx].ep_pma_buf_len = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
g_fsdev_udc.in_ep[ep_idx].ep_pma_addr = g_fsdev_udc.pma_offset;
/*Set the endpoint Transmit buffer address */
PCD_SET_EP_TX_ADDRESS(USB, ep_idx, g_fsdev_udc.pma_offset);
g_fsdev_udc.pma_offset += USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
}
PCD_CLEAR_TX_DTOG(USB, ep_idx);
if (USB_GET_ENDPOINT_TYPE(ep->bmAttributes) != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
/* Configure NAK status for the Endpoint */
PCD_SET_EP_TX_STATUS(USB, ep_idx, USB_EP_TX_NAK);
} else {
/* Configure TX Endpoint to disabled state */
PCD_SET_EP_TX_STATUS(USB, ep_idx, USB_EP_TX_DIS);
}
}
return 0;
}
int usbd_ep_close(uint8_t busid, const uint8_t ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (USB_EP_DIR_IS_OUT(ep)) {
PCD_CLEAR_RX_DTOG(USB, ep_idx);
/* Configure DISABLE status for the Endpoint*/
PCD_SET_EP_RX_STATUS(USB, ep_idx, USB_EP_RX_DIS);
} else {
PCD_CLEAR_TX_DTOG(USB, ep_idx);
/* Configure DISABLE status for the Endpoint*/
PCD_SET_EP_TX_STATUS(USB, ep_idx, USB_EP_TX_DIS);
}
return 0;
}
int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (USB_EP_DIR_IS_OUT(ep)) {
PCD_SET_EP_RX_STATUS(USB, ep_idx, USB_EP_RX_STALL);
} else {
PCD_SET_EP_TX_STATUS(USB, ep_idx, USB_EP_TX_STALL);
}
return 0;
}
int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (USB_EP_DIR_IS_OUT(ep)) {
PCD_CLEAR_RX_DTOG(USB, ep_idx);
/* Configure VALID status for the Endpoint */
PCD_SET_EP_RX_STATUS(USB, ep_idx, USB_EP_RX_VALID);
} else {
PCD_CLEAR_TX_DTOG(USB, ep_idx);
if (g_fsdev_udc.in_ep[ep_idx].ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
/* Configure NAK status for the Endpoint */
PCD_SET_EP_TX_STATUS(USB, ep_idx, USB_EP_TX_NAK);
}
}
return 0;
}
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (USB_EP_DIR_IS_OUT(ep)) {
if (PCD_GET_EP_RX_STATUS(USB, ep_idx) & USB_EP_RX_STALL) {
*stalled = 1;
} else {
*stalled = 0;
}
} else {
if (PCD_GET_EP_TX_STATUS(USB, ep_idx) & USB_EP_TX_STALL) {
*stalled = 1;
} else {
*stalled = 0;
}
}
return 0;
}
int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (!data && data_len) {
return -1;
}
if (!g_fsdev_udc.in_ep[ep_idx].ep_enable) {
return -2;
}
g_fsdev_udc.in_ep[ep_idx].xfer_buf = (uint8_t *)data;
g_fsdev_udc.in_ep[ep_idx].xfer_len = data_len;
g_fsdev_udc.in_ep[ep_idx].actual_xfer_len = 0;
data_len = MIN(data_len, g_fsdev_udc.in_ep[ep_idx].ep_mps);
fsdev_write_pma(USB, (uint8_t *)data, g_fsdev_udc.in_ep[ep_idx].ep_pma_addr, (uint16_t)data_len);
PCD_SET_EP_TX_CNT(USB, ep_idx, (uint16_t)data_len);
PCD_SET_EP_TX_STATUS(USB, ep_idx, USB_EP_TX_VALID);
return 0;
}
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (!data && data_len) {
return -1;
}
if (!g_fsdev_udc.out_ep[ep_idx].ep_enable) {
return -2;
}
g_fsdev_udc.out_ep[ep_idx].xfer_buf = data;
g_fsdev_udc.out_ep[ep_idx].xfer_len = data_len;
g_fsdev_udc.out_ep[ep_idx].actual_xfer_len = 0;
PCD_SET_EP_RX_STATUS(USB, ep_idx, USB_EP_RX_VALID);
return 0;
}
void USBD_IRQHandler(uint8_t busid)
{
uint16_t wIstr, wEPVal;
uint8_t ep_idx;
uint8_t read_count;
uint16_t write_count;
uint16_t store_ep[8];
wIstr = USB->ISTR;
if (wIstr & USB_ISTR_CTR) {
while ((USB->ISTR & USB_ISTR_CTR) != 0U) {
wIstr = USB->ISTR;
/* extract highest priority endpoint number */
ep_idx = (uint8_t)(wIstr & USB_ISTR_EP_ID);
if (ep_idx == 0U) {
if ((wIstr & USB_ISTR_DIR) == 0U) {
PCD_CLEAR_TX_EP_CTR(USB, ep_idx);
write_count = PCD_GET_EP_TX_CNT(USB, ep_idx);
g_fsdev_udc.in_ep[ep_idx].xfer_buf += write_count;
g_fsdev_udc.in_ep[ep_idx].xfer_len -= write_count;
g_fsdev_udc.in_ep[ep_idx].actual_xfer_len += write_count;
usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_fsdev_udc.in_ep[ep_idx].actual_xfer_len);
if (g_fsdev_udc.setup.wLength == 0) {
/* In status, start reading setup */
usbd_ep_start_read(0, 0x00, NULL, 0);
} else if (g_fsdev_udc.setup.wLength && ((g_fsdev_udc.setup.bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) {
/* In status, start reading setup */
usbd_ep_start_read(0, 0x00, NULL, 0);
}
if ((g_fsdev_udc.dev_addr > 0U) && (write_count == 0U)) {
USB->DADDR = ((uint16_t)g_fsdev_udc.dev_addr | USB_DADDR_EF);
g_fsdev_udc.dev_addr = 0U;
}
} else {
wEPVal = PCD_GET_ENDPOINT(USB, ep_idx);
if ((wEPVal & USB_EP_SETUP) != 0U) {
PCD_CLEAR_RX_EP_CTR(USB, ep_idx);
read_count = PCD_GET_EP_RX_CNT(USB, ep_idx);
fsdev_read_pma(USB, (uint8_t *)&g_fsdev_udc.setup, g_fsdev_udc.out_ep[ep_idx].ep_pma_addr, (uint16_t)read_count);
usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_fsdev_udc.setup);
} else if ((wEPVal & USB_EP_CTR_RX) != 0U) {
PCD_CLEAR_RX_EP_CTR(USB, ep_idx);
read_count = PCD_GET_EP_RX_CNT(USB, ep_idx);
fsdev_read_pma(USB, g_fsdev_udc.out_ep[ep_idx].xfer_buf, g_fsdev_udc.out_ep[ep_idx].ep_pma_addr, (uint16_t)read_count);
g_fsdev_udc.out_ep[ep_idx].xfer_buf += read_count;
g_fsdev_udc.out_ep[ep_idx].xfer_len -= read_count;
g_fsdev_udc.out_ep[ep_idx].actual_xfer_len += read_count;
usbd_event_ep_out_complete_handler(0, ep_idx, g_fsdev_udc.out_ep[ep_idx].actual_xfer_len);
if (read_count == 0) {
/* Out status, start reading setup */
usbd_ep_start_read(0, 0x00, NULL, 0);
}
}
}
} else {
wEPVal = PCD_GET_ENDPOINT(USB, ep_idx);
if ((wEPVal & USB_EP_CTR_RX) != 0U) {
PCD_CLEAR_RX_EP_CTR(USB, ep_idx);
read_count = PCD_GET_EP_RX_CNT(USB, ep_idx);
fsdev_read_pma(USB, g_fsdev_udc.out_ep[ep_idx].xfer_buf, g_fsdev_udc.out_ep[ep_idx].ep_pma_addr, (uint16_t)read_count);
g_fsdev_udc.out_ep[ep_idx].xfer_buf += read_count;
g_fsdev_udc.out_ep[ep_idx].xfer_len -= read_count;
g_fsdev_udc.out_ep[ep_idx].actual_xfer_len += read_count;
if ((read_count < g_fsdev_udc.out_ep[ep_idx].ep_mps) ||
(g_fsdev_udc.out_ep[ep_idx].xfer_len == 0)) {
usbd_event_ep_out_complete_handler(0, ep_idx, g_fsdev_udc.out_ep[ep_idx].actual_xfer_len);
} else {
PCD_SET_EP_RX_STATUS(USB, ep_idx, USB_EP_RX_VALID);
}
}
if ((wEPVal & USB_EP_CTR_TX) != 0U) {
PCD_CLEAR_TX_EP_CTR(USB, ep_idx);
write_count = PCD_GET_EP_TX_CNT(USB, ep_idx);
g_fsdev_udc.in_ep[ep_idx].xfer_buf += write_count;
g_fsdev_udc.in_ep[ep_idx].xfer_len -= write_count;
g_fsdev_udc.in_ep[ep_idx].actual_xfer_len += write_count;
if (g_fsdev_udc.in_ep[ep_idx].xfer_len == 0) {
usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_fsdev_udc.in_ep[ep_idx].actual_xfer_len);
} else {
write_count = MIN(g_fsdev_udc.in_ep[ep_idx].xfer_len, g_fsdev_udc.in_ep[ep_idx].ep_mps);
fsdev_write_pma(USB, g_fsdev_udc.in_ep[ep_idx].xfer_buf, g_fsdev_udc.in_ep[ep_idx].ep_pma_addr, (uint16_t)write_count);
PCD_SET_EP_TX_CNT(USB, ep_idx, write_count);
PCD_SET_EP_TX_STATUS(USB, ep_idx, USB_EP_TX_VALID);
}
}
}
}
}
if (wIstr & USB_ISTR_RESET) {
memset(&g_fsdev_udc, 0, sizeof(struct fsdev_udc));
g_fsdev_udc.pma_offset = USB_BTABLE_SIZE;
usbd_event_reset_handler(0);
/* start reading setup packet */
PCD_SET_EP_RX_STATUS(USB, 0, USB_EP_RX_VALID);
USB->ISTR &= (uint16_t)(~USB_ISTR_RESET);
}
if (wIstr & USB_ISTR_PMAOVR) {
USB->ISTR &= (uint16_t)(~USB_ISTR_PMAOVR);
}
if (wIstr & USB_ISTR_ERR) {
USB->ISTR &= (uint16_t)(~USB_ISTR_ERR);
}
if (wIstr & USB_ISTR_WKUP) {
USB->CNTR &= (uint16_t) ~(USB_CNTR_LP_MODE);
USB->CNTR &= (uint16_t) ~(USB_CNTR_FSUSP);
USB->ISTR &= (uint16_t)(~USB_ISTR_WKUP);
}
if (wIstr & USB_ISTR_SUSP) {
/* WA: To Clear Wakeup flag if raised with suspend signal */
/* Store Endpoint register */
for (uint8_t i = 0U; i < 8U; i++) {
store_ep[i] = PCD_GET_ENDPOINT(USB, i);
}
/* FORCE RESET */
USB->CNTR |= (uint16_t)(USB_CNTR_FRES);
/* CLEAR RESET */
USB->CNTR &= (uint16_t)(~USB_CNTR_FRES);
/* wait for reset flag in ISTR */
while ((USB->ISTR & USB_ISTR_RESET) == 0U) {
}
/* Clear Reset Flag */
USB->ISTR &= (uint16_t)(~USB_ISTR_RESET);
/* Restore Registre */
for (uint8_t i = 0U; i < 8U; i++) {
PCD_SET_ENDPOINT(USB, i, store_ep[i]);
}
/* Force low-power mode in the macrocell */
USB->CNTR |= (uint16_t)USB_CNTR_FSUSP;
/* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
USB->ISTR &= (uint16_t)(~USB_ISTR_SUSP);
USB->CNTR |= (uint16_t)USB_CNTR_LP_MODE;
}
if (wIstr & USB_ISTR_SOF) {
USB->ISTR &= (uint16_t)(~USB_ISTR_SOF);
}
if (wIstr & USB_ISTR_ESOF) {
USB->ISTR &= (uint16_t)(~USB_ISTR_ESOF);
}
}
static void fsdev_write_pma(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
{
uint32_t n = ((uint32_t)wNBytes + 1U) >> 1;
uint32_t BaseAddr = (uint32_t)USBx;
uint32_t i, temp1, temp2;
__IO uint16_t *pdwVal;
uint8_t *pBuf = pbUsrBuf;
pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
for (i = n; i != 0U; i--) {
temp1 = *pBuf;
pBuf++;
temp2 = temp1 | ((uint16_t)((uint16_t)*pBuf << 8));
*pdwVal = (uint16_t)temp2;
pdwVal++;
#if PMA_ACCESS > 1U
pdwVal++;
#endif
pBuf++;
}
}
/**
* @brief Copy data from packet memory area (PMA) to user memory buffer
* @param USBx USB peripheral instance register address.
* @param pbUsrBuf pointer to user memory area.
* @param wPMABufAddr address into PMA.
* @param wNBytes no. of bytes to be copied.
* @retval None
*/
static void fsdev_read_pma(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
{
uint32_t n = (uint32_t)wNBytes >> 1;
uint32_t BaseAddr = (uint32_t)USBx;
uint32_t i, temp;
__IO uint16_t *pdwVal;
uint8_t *pBuf = pbUsrBuf;
pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
for (i = n; i != 0U; i--) {
temp = *(__IO uint16_t *)pdwVal;
pdwVal++;
*pBuf = (uint8_t)((temp >> 0) & 0xFFU);
pBuf++;
*pBuf = (uint8_t)((temp >> 8) & 0xFFU);
pBuf++;
#if PMA_ACCESS > 1U
pdwVal++;
#endif
}
if ((wNBytes % 2U) != 0U) {
temp = *pdwVal;
*pBuf = (uint8_t)((temp >> 0) & 0xFFU);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,110 +0,0 @@
#include "main.h"
void USBD_IRQHandler(uint8_t busid);
void usb_dc_low_level_init(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = { 0 };
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Enable HSI48 oscillator and select HSI48 for USBHS */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48;
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
/* Enable USB Voltage detector */
HAL_PWREx_EnableUSBVoltageDetector();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/* USB_OTG_HS GPIO Configuration
PC0 ------> USB_OTG_HS_ULPI_STP
PC2_C ------> USB_OTG_HS_ULPI_DIR
PC3_C ------> USB_OTG_HS_ULPI_NXT
PA3 ------> USB_OTG_HS_ULPI_D0
PA5 ------> USB_OTG_HS_ULPI_CK
PB0 ------> USB_OTG_HS_ULPI_D1
PB1 ------> USB_OTG_HS_ULPI_D2
PB10 ------> USB_OTG_HS_ULPI_D3
PB11 ------> USB_OTG_HS_ULPI_D4
PB12 ------> USB_OTG_HS_ULPI_D5
PB13 ------> USB_OTG_HS_ULPI_D6
PB5 ------> USB_OTG_HS_ULPI_D7
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF10_OTG2_HS;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF10_OTG2_HS;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF10_OTG2_HS;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_USB_OTG_HS_CLK_ENABLE();
__HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE();
/* USB_OTG_HS interrupt Init */
HAL_NVIC_SetPriority(OTG_HS_IRQn, 9, 0);
HAL_NVIC_EnableIRQ(OTG_HS_IRQn);
}
void usb_dc_low_level_deinit(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
HAL_NVIC_DisableIRQ(OTG_HS_IRQn);
/* Peripheral clock disable */
__HAL_RCC_USB_OTG_HS_CLK_DISABLE();
__HAL_RCC_USB_OTG_HS_ULPI_CLK_DISABLE();
/* HSI48 clock disable */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48;
RCC_OscInitStruct.HSI48State = RCC_HSI48_OFF;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
/* USB_OTG_HS GPIO Configuration
PC0 ------> USB_OTG_HS_ULPI_STP
PC2_C ------> USB_OTG_HS_ULPI_DIR
PC3_C ------> USB_OTG_HS_ULPI_NXT
PA3 ------> USB_OTG_HS_ULPI_D0
PA5 ------> USB_OTG_HS_ULPI_CK
PB0 ------> USB_OTG_HS_ULPI_D1
PB1 ------> USB_OTG_HS_ULPI_D2
PB10 ------> USB_OTG_HS_ULPI_D3
PB11 ------> USB_OTG_HS_ULPI_D4
PB12 ------> USB_OTG_HS_ULPI_D5
PB13 ------> USB_OTG_HS_ULPI_D6
PB5 ------> USB_OTG_HS_ULPI_D7
*/
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3);
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3|GPIO_PIN_5);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_5);
}
void OTG_HS_IRQHandler(void)
{
USBD_IRQHandler(0);
}

View File

@ -1,341 +0,0 @@
#include "usbd_core.h"
#include "usbd_hid.h"
#include <string.h>
#include "main.h"
/* USB设备配置 */
#define USBD_VID 0x0483
#define USBD_PID 0x5710
#define USBD_PVN 0x0100 //Product Version Number
#define USBD_MAX_POWER 500
#define USBD_LANGID_STRING 1033
/* HID IN&OUT端点配置 */
#define CUSTOM_HID_IN_EP 0x81
#define CUSTOM_HID_IN_EP_SIZE 16
#define CUSTOM_HID_IN_INTERVAL 10
#define CUSTOM_HID_OUT_EP 0x02
#define CUSTOM_HID_OUT_EP_SIZE 16
#define CUSTOM_HID_OUT_EP_INTERVAL 10
/* 描述符长度 */
#define HID_CONFIG_DESC_SIZE 41 //配置描述符长度
#define HID_CUSTOM_REPORT_DESC_SIZE 36 //HID报告描述符
/* 端点缓冲区 */
static USB_MEM_ALIGNX uint8_t read_buffer[CUSTOM_HID_OUT_EP_SIZE];
static USB_MEM_ALIGNX uint8_t send_buffer[CUSTOM_HID_IN_EP_SIZE];
volatile uint8_t hid_led_status = 0;
/* USB描述符 */
static uint8_t usb_descriptor[] = {
/* 设备(Device)描述符 所有设备有且只有一个 */
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, USBD_PVN, 0x01),
/* 配置(Configuration)描述符 所有设备至少有一个 */
USB_CONFIG_DESCRIPTOR_INIT(HID_CONFIG_DESC_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
/* 截至此处的配置描述符长度: 9 */
/* 接口(Interface)描述符 HID设备 */
0x09, /* bLength: Interface Descriptor size */
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints */
0x03, /* bInterfaceClass: HID */
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0, /* iInterface: Index of string descriptor */
/* 截至此处的配置描述符长度: 18 */
/* HID描述符 自定义HID设备 */
0x09, /* bLength: HID Descriptor size */
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
0x11, /* bcdHID: HID Class Spec release number */
0x01,
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
0x22, /* bDescriptorType */
HID_CUSTOM_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
0x00,
/* 截至此处的配置描述符长度: 27 */
/* 端点(Endpoint)描述符 HID IN */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
CUSTOM_HID_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
WBVAL(CUSTOM_HID_IN_EP_SIZE), /* wMaxPacketSize: 4 Byte max */
CUSTOM_HID_IN_INTERVAL, /* bInterval: Polling Interval */
/* 截至此处的配置描述符长度: 34 */
/* 端点(Endpoint)描述符 HID OUT */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
CUSTOM_HID_OUT_EP, /* bEndpointAddress: Endpoint Address (OUT) */
0x03, /* bmAttributes: Interrupt endpoint */
WBVAL(CUSTOM_HID_OUT_EP_SIZE), /* wMaxPacketSize: 4 Byte max */
CUSTOM_HID_OUT_EP_INTERVAL, /* bInterval: Polling Interval */
/* 截至此处的配置描述符长度: 41 配置描述符结束 */
/* 字符串(String)描述符 设备支持的语言描述符 */
USB_LANGID_INIT(USBD_LANGID_STRING),
/* 字符串(String)描述符 制造商字符串 */
0x0C, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'S', 0x00,
'T', 0x00,
'M', 0x00,
'3', 0x00,
'2', 0x00, /* 5字符 */
/* 字符串(String)描述符 产品字符串 */
0x2C, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'H', 0x00,
'I', 0x00,
'D', 0x00,
' ', 0x00,
'C', 0x00,
'o', 0x00,
'n', 0x00,
't', 0x00,
'r', 0x00,
'o', 0x00,
'l', 0x00,
' ', 0x00,
'I', 0x00,
'n', 0x00,
't', 0x00,
'e', 0x00,
'r', 0x00,
'f', 0x00,
'a', 0x00,
'c', 0x00,
'e', 0x00, /* 21字符 */
/* 字符串(String)描述符 序列号字符串 */
0x32, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00, /* 24字符 */
#ifdef CONFIG_USB_HS
/* 设备限定(Device Qualifier)描述符 同时支持全速与高速的设备必须有 */
0x0A,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02, 0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
#endif
/* 空描述符 */
0x00
};
/* 自定义HID报告描述符 */
static const uint8_t hid_custom_report_desc[HID_CUSTOM_REPORT_DESC_SIZE] = {
0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined Page 0) */
0x09, 0x01, /* USAGE (Vendor Usage 1) */
0xA1, 0x01, /* COLLECTION (Application) */
0x85, 0x01, /* REPORT ID (0x01) */
0x09, 0x01, /* USAGE (Vendor Usage 1) */
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
0x25, 0xFF, /* LOGICAL_MAXIMUM (255) */
0x75, 0x08, /* REPORT_SIZE (8) */
0x95, CUSTOM_HID_OUT_EP_SIZE-1, /* REPORT_COUNT (63) */
0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
0x85, 0x02, /* REPORT ID (0x02) */
0x09, 0x01, /* USAGE (Vendor Usage 1) */
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
0x25, 0xFF, /* LOGICAL_MAXIMUM (255) */
0x75, 0x08, /* REPORT_SIZE (8) */
0x95, CUSTOM_HID_IN_EP_SIZE-1, /* REPORT_COUNT (63) */
0x81, 0x02, /* INPUT (Data,Var,Abs) */
0xC0 /* END_COLLECTION */
};
#define HID_STATE_IDLE 0
#define HID_STATE_BUSY 1
volatile uint8_t usb_hid_status = HID_STATE_BUSY;
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONNECTED:
break;
case USBD_EVENT_DISCONNECTED:
break;
case USBD_EVENT_RESUME:
break;
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
/* setup first out ep read transfer */
usbd_ep_start_read(busid, CUSTOM_HID_OUT_EP, read_buffer, CUSTOM_HID_OUT_EP_SIZE);
usb_hid_status = HID_STATE_IDLE;
HAL_GPIO_WritePin(LED_Y1_GPIO_Port, LED_Y1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_Y2_GPIO_Port, LED_Y2_Pin, GPIO_PIN_SET);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
/**
* @brief
*
* @param buffer
* @param length
* @param width
*/
void print_buffer(const uint8_t *buffer, size_t length, uint8_t width)
{
size_t row = 0;
while(row * width < length) {
USB_LOG_RAW("%04X ", row * width);
for(size_t col = 0; col < width; col ++) { //打印16进制
if(col + row*width >= length) {
for(size_t cnt = col; cnt < width; cnt ++) {
USB_LOG_RAW(" "); //补齐剩余空格
}
break;
}
USB_LOG_RAW("%02X ", buffer[col + row*width]);
}
USB_LOG_RAW(" ");
for(size_t col = 0; col < width; col ++) { //打印字符
if(col + row*width >= length) {
USB_LOG_RAW("\r\n");
return;
}
char c = buffer[col + row*width];
if(c > '~' || c < ' ') {
c = '.';
}
USB_LOG_RAW("%c", c);
}
USB_LOG_RAW("\r\n");
row ++;
}
}
static void usbd_hid_custom_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
usb_hid_status = HID_STATE_IDLE;
USB_LOG_RAW("%d bytes of data sent, content:\r\n", nbytes);
print_buffer(send_buffer, nbytes, 8);
HAL_GPIO_TogglePin(LED_Y2_GPIO_Port, LED_Y2_Pin);
}
static void usbd_hid_custom_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
usbd_ep_start_read(busid, ep, read_buffer, CUSTOM_HID_IN_EP_SIZE);
USB_LOG_RAW("%d bytes of data received, content:\r\n", nbytes);
print_buffer(read_buffer, nbytes, 8);
HAL_GPIO_TogglePin(LED_Y1_GPIO_Port, LED_Y1_Pin);
hid_led_status = read_buffer[1];
}
static void fill_usb_descriptor_serial_number(void)
{
char uid_string[25];
sprintf(uid_string, "%08X%08X%08X", HAL_GetUIDw0(), HAL_GetUIDw1(), HAL_GetUIDw2());
uint16_t serial_number_offset = 0;
for (uint16_t i = 0; i < sizeof(usb_descriptor) - 3; i ++) { //查找USB描述符中序列号字符描述符的偏移
if (usb_descriptor[i + 0] == '0' && usb_descriptor[i + 1] == 0x00 &&
usb_descriptor[i + 2] == '0' && usb_descriptor[i + 3] == 0x00) {
serial_number_offset = i;
break;
}
}
if (serial_number_offset == 0) { //未找到
return;
}
for (uint8_t i = 0; i < 24; i ++) { //共24位
usb_descriptor[serial_number_offset + i * 2] = uid_string[i];
}
}
void hid_custom_init(uint8_t busid, uintptr_t reg_base)
{
static struct usbd_interface intf0;
static struct usbd_endpoint custom_in_ep = {
.ep_cb = usbd_hid_custom_in_callback,
.ep_addr = CUSTOM_HID_IN_EP
};
static struct usbd_endpoint custom_out_ep = {
.ep_cb = usbd_hid_custom_out_callback,
.ep_addr = CUSTOM_HID_OUT_EP
};
fill_usb_descriptor_serial_number();
usbd_desc_register(busid, usb_descriptor);
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE));
usbd_add_endpoint(busid, &custom_in_ep);
usbd_add_endpoint(busid, &custom_out_ep);
usbd_initialize(busid, reg_base, usbd_event_handler);
}
void hid_custom_send(const uint8_t *data, uint16_t length)
{
send_buffer[0] = 0x02; //OUT
if (length > CUSTOM_HID_IN_EP_SIZE - 1) {
length = CUSTOM_HID_IN_EP_SIZE - 1; //限制发送长度
} else {
memset(&send_buffer[1 + length], 0x00, CUSTOM_HID_IN_EP_SIZE - 1 - length); //缓冲区后部补0
}
memcpy(&send_buffer[1], data, length);
usbd_ep_start_write(0, CUSTOM_HID_IN_EP, send_buffer, CUSTOM_HID_IN_EP_SIZE);
usb_hid_status = HID_STATE_BUSY;
while (usb_hid_status == HID_STATE_BUSY) {
__WFI();
}
}

View File

@ -1,609 +0,0 @@
;********************************************************************************
;* File Name : startup_stm32h743xx.s
;* @author MCD Application Team
;* Description : STM32H7xx devices vector table for MDK-ARM toolchain.
;* This module performs:
;* - Set the initial SP
;* - Set the initial PC == Reset_Handler
;* - Set the vector table entries with the exceptions ISR address
;* - Branches to __main in the C library (which eventually
;* calls main()).
;* After Reset the Cortex-M processor is in Thread mode,
;* priority is Privileged, and the Stack is set to Main.
;* <<< Use Configuration Wizard in Context Menu >>>
;******************************************************************************
;* @attention
;*
;* Copyright (c) 2017 STMicroelectronics.
;* All rights reserved.
;*
;* This software is licensed under terms that can be found in the LICENSE file
;* in the root directory of this software component.
;* If no LICENSE file comes with this software, it is provided AS-IS.
;*
;*******************************************************************************
; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <h> Stack Configuration
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Stack_Size EQU 0x2000
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
; <h> Heap Configuration
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Heap_Size EQU 0x400
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
PRESERVE8
THUMB
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window WatchDog interrupt ( wwdg1_it)
DCD PVD_AVD_IRQHandler ; PVD/AVD through EXTI Line detection
DCD TAMP_STAMP_IRQHandler ; Tamper and TimeStamps through the EXTI line
DCD RTC_WKUP_IRQHandler ; RTC Wakeup through the EXTI line
DCD FLASH_IRQHandler ; FLASH
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line0
DCD EXTI1_IRQHandler ; EXTI Line1
DCD EXTI2_IRQHandler ; EXTI Line2
DCD EXTI3_IRQHandler ; EXTI Line3
DCD EXTI4_IRQHandler ; EXTI Line4
DCD DMA1_Stream0_IRQHandler ; DMA1 Stream 0
DCD DMA1_Stream1_IRQHandler ; DMA1 Stream 1
DCD DMA1_Stream2_IRQHandler ; DMA1 Stream 2
DCD DMA1_Stream3_IRQHandler ; DMA1 Stream 3
DCD DMA1_Stream4_IRQHandler ; DMA1 Stream 4
DCD DMA1_Stream5_IRQHandler ; DMA1 Stream 5
DCD DMA1_Stream6_IRQHandler ; DMA1 Stream 6
DCD ADC_IRQHandler ; ADC1, ADC2
DCD FDCAN1_IT0_IRQHandler ; FDCAN1 interrupt line 0
DCD FDCAN2_IT0_IRQHandler ; FDCAN2 interrupt line 0
DCD FDCAN1_IT1_IRQHandler ; FDCAN1 interrupt line 1
DCD FDCAN2_IT1_IRQHandler ; FDCAN2 interrupt line 1
DCD EXTI9_5_IRQHandler ; External Line[9:5]s
DCD TIM1_BRK_IRQHandler ; TIM1 Break interrupt
DCD TIM1_UP_IRQHandler ; TIM1 Update Interrupt
DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation Interrupt
DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
DCD TIM2_IRQHandler ; TIM2
DCD TIM3_IRQHandler ; TIM3
DCD TIM4_IRQHandler ; TIM4
DCD I2C1_EV_IRQHandler ; I2C1 Event
DCD I2C1_ER_IRQHandler ; I2C1 Error
DCD I2C2_EV_IRQHandler ; I2C2 Event
DCD I2C2_ER_IRQHandler ; I2C2 Error
DCD SPI1_IRQHandler ; SPI1
DCD SPI2_IRQHandler ; SPI2
DCD USART1_IRQHandler ; USART1
DCD USART2_IRQHandler ; USART2
DCD USART3_IRQHandler ; USART3
DCD EXTI15_10_IRQHandler ; External Line[15:10]
DCD RTC_Alarm_IRQHandler ; RTC Alarm (A and B) through EXTI Line
DCD 0 ; Reserved
DCD TIM8_BRK_TIM12_IRQHandler ; TIM8 Break Interrupt and TIM12 global interrupt
DCD TIM8_UP_TIM13_IRQHandler ; TIM8 Update Interrupt and TIM13 global interrupt
DCD TIM8_TRG_COM_TIM14_IRQHandler ; TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt
DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare Interrupt
DCD DMA1_Stream7_IRQHandler ; DMA1 Stream7
DCD FMC_IRQHandler ; FMC
DCD SDMMC1_IRQHandler ; SDMMC1
DCD TIM5_IRQHandler ; TIM5
DCD SPI3_IRQHandler ; SPI3
DCD UART4_IRQHandler ; UART4
DCD UART5_IRQHandler ; UART5
DCD TIM6_DAC_IRQHandler ; TIM6 and DAC1&2 underrun errors
DCD TIM7_IRQHandler ; TIM7
DCD DMA2_Stream0_IRQHandler ; DMA2 Stream 0
DCD DMA2_Stream1_IRQHandler ; DMA2 Stream 1
DCD DMA2_Stream2_IRQHandler ; DMA2 Stream 2
DCD DMA2_Stream3_IRQHandler ; DMA2 Stream 3
DCD DMA2_Stream4_IRQHandler ; DMA2 Stream 4
DCD ETH_IRQHandler ; Ethernet
DCD ETH_WKUP_IRQHandler ; Ethernet Wakeup through EXTI line
DCD FDCAN_CAL_IRQHandler ; FDCAN calibration unit interrupt
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD DMA2_Stream5_IRQHandler ; DMA2 Stream 5
DCD DMA2_Stream6_IRQHandler ; DMA2 Stream 6
DCD DMA2_Stream7_IRQHandler ; DMA2 Stream 7
DCD USART6_IRQHandler ; USART6
DCD I2C3_EV_IRQHandler ; I2C3 event
DCD I2C3_ER_IRQHandler ; I2C3 error
DCD OTG_HS_EP1_OUT_IRQHandler ; USB OTG HS End Point 1 Out
DCD OTG_HS_EP1_IN_IRQHandler ; USB OTG HS End Point 1 In
DCD OTG_HS_WKUP_IRQHandler ; USB OTG HS Wakeup through EXTI
DCD OTG_HS_IRQHandler ; USB OTG HS
DCD DCMI_IRQHandler ; DCMI
DCD 0 ; Reserved
DCD RNG_IRQHandler ; Rng
DCD FPU_IRQHandler ; FPU
DCD UART7_IRQHandler ; UART7
DCD UART8_IRQHandler ; UART8
DCD SPI4_IRQHandler ; SPI4
DCD SPI5_IRQHandler ; SPI5
DCD SPI6_IRQHandler ; SPI6
DCD SAI1_IRQHandler ; SAI1
DCD LTDC_IRQHandler ; LTDC
DCD LTDC_ER_IRQHandler ; LTDC error
DCD DMA2D_IRQHandler ; DMA2D
DCD SAI2_IRQHandler ; SAI2
DCD QUADSPI_IRQHandler ; QUADSPI
DCD LPTIM1_IRQHandler ; LPTIM1
DCD CEC_IRQHandler ; HDMI_CEC
DCD I2C4_EV_IRQHandler ; I2C4 Event
DCD I2C4_ER_IRQHandler ; I2C4 Error
DCD SPDIF_RX_IRQHandler ; SPDIF_RX
DCD OTG_FS_EP1_OUT_IRQHandler ; USB OTG FS End Point 1 Out
DCD OTG_FS_EP1_IN_IRQHandler ; USB OTG FS End Point 1 In
DCD OTG_FS_WKUP_IRQHandler ; USB OTG FS Wakeup through EXTI
DCD OTG_FS_IRQHandler ; USB OTG FS
DCD DMAMUX1_OVR_IRQHandler ; DMAMUX1 Overrun interrupt
DCD HRTIM1_Master_IRQHandler ; HRTIM Master Timer global Interrupts
DCD HRTIM1_TIMA_IRQHandler ; HRTIM Timer A global Interrupt
DCD HRTIM1_TIMB_IRQHandler ; HRTIM Timer B global Interrupt
DCD HRTIM1_TIMC_IRQHandler ; HRTIM Timer C global Interrupt
DCD HRTIM1_TIMD_IRQHandler ; HRTIM Timer D global Interrupt
DCD HRTIM1_TIME_IRQHandler ; HRTIM Timer E global Interrupt
DCD HRTIM1_FLT_IRQHandler ; HRTIM Fault global Interrupt
DCD DFSDM1_FLT0_IRQHandler ; DFSDM Filter0 Interrupt
DCD DFSDM1_FLT1_IRQHandler ; DFSDM Filter1 Interrupt
DCD DFSDM1_FLT2_IRQHandler ; DFSDM Filter2 Interrupt
DCD DFSDM1_FLT3_IRQHandler ; DFSDM Filter3 Interrupt
DCD SAI3_IRQHandler ; SAI3 global Interrupt
DCD SWPMI1_IRQHandler ; Serial Wire Interface 1 global interrupt
DCD TIM15_IRQHandler ; TIM15 global Interrupt
DCD TIM16_IRQHandler ; TIM16 global Interrupt
DCD TIM17_IRQHandler ; TIM17 global Interrupt
DCD MDIOS_WKUP_IRQHandler ; MDIOS Wakeup Interrupt
DCD MDIOS_IRQHandler ; MDIOS global Interrupt
DCD JPEG_IRQHandler ; JPEG global Interrupt
DCD MDMA_IRQHandler ; MDMA global Interrupt
DCD 0 ; Reserved
DCD SDMMC2_IRQHandler ; SDMMC2 global Interrupt
DCD HSEM1_IRQHandler ; HSEM1 global Interrupt
DCD 0 ; Reserved
DCD ADC3_IRQHandler ; ADC3 global Interrupt
DCD DMAMUX2_OVR_IRQHandler ; DMAMUX Overrun interrupt
DCD BDMA_Channel0_IRQHandler ; BDMA Channel 0 global Interrupt
DCD BDMA_Channel1_IRQHandler ; BDMA Channel 1 global Interrupt
DCD BDMA_Channel2_IRQHandler ; BDMA Channel 2 global Interrupt
DCD BDMA_Channel3_IRQHandler ; BDMA Channel 3 global Interrupt
DCD BDMA_Channel4_IRQHandler ; BDMA Channel 4 global Interrupt
DCD BDMA_Channel5_IRQHandler ; BDMA Channel 5 global Interrupt
DCD BDMA_Channel6_IRQHandler ; BDMA Channel 6 global Interrupt
DCD BDMA_Channel7_IRQHandler ; BDMA Channel 7 global Interrupt
DCD COMP1_IRQHandler ; COMP1 global Interrupt
DCD LPTIM2_IRQHandler ; LP TIM2 global interrupt
DCD LPTIM3_IRQHandler ; LP TIM3 global interrupt
DCD LPTIM4_IRQHandler ; LP TIM4 global interrupt
DCD LPTIM5_IRQHandler ; LP TIM5 global interrupt
DCD LPUART1_IRQHandler ; LP UART1 interrupt
DCD 0 ; Reserved
DCD CRS_IRQHandler ; Clock Recovery Global Interrupt
DCD ECC_IRQHandler ; ECC diagnostic Global Interrupt
DCD SAI4_IRQHandler ; SAI4 global interrupt
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD WAKEUP_PIN_IRQHandler ; Interrupt for all 6 wake-up pins
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
AREA |.text|, CODE, READONLY
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
; Dummy Exception Handlers (infinite loops which can be modified)
NMI_Handler PROC
EXPORT NMI_Handler [WEAK]
B .
ENDP
HardFault_Handler\
PROC
EXPORT HardFault_Handler [WEAK]
B .
ENDP
MemManage_Handler\
PROC
EXPORT MemManage_Handler [WEAK]
B .
ENDP
BusFault_Handler\
PROC
EXPORT BusFault_Handler [WEAK]
B .
ENDP
UsageFault_Handler\
PROC
EXPORT UsageFault_Handler [WEAK]
B .
ENDP
SVC_Handler PROC
EXPORT SVC_Handler [WEAK]
B .
ENDP
DebugMon_Handler\
PROC
EXPORT DebugMon_Handler [WEAK]
B .
ENDP
PendSV_Handler PROC
EXPORT PendSV_Handler [WEAK]
B .
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler [WEAK]
B .
ENDP
Default_Handler PROC
EXPORT WWDG_IRQHandler [WEAK]
EXPORT PVD_AVD_IRQHandler [WEAK]
EXPORT TAMP_STAMP_IRQHandler [WEAK]
EXPORT RTC_WKUP_IRQHandler [WEAK]
EXPORT FLASH_IRQHandler [WEAK]
EXPORT RCC_IRQHandler [WEAK]
EXPORT EXTI0_IRQHandler [WEAK]
EXPORT EXTI1_IRQHandler [WEAK]
EXPORT EXTI2_IRQHandler [WEAK]
EXPORT EXTI3_IRQHandler [WEAK]
EXPORT EXTI4_IRQHandler [WEAK]
EXPORT DMA1_Stream0_IRQHandler [WEAK]
EXPORT DMA1_Stream1_IRQHandler [WEAK]
EXPORT DMA1_Stream2_IRQHandler [WEAK]
EXPORT DMA1_Stream3_IRQHandler [WEAK]
EXPORT DMA1_Stream4_IRQHandler [WEAK]
EXPORT DMA1_Stream5_IRQHandler [WEAK]
EXPORT DMA1_Stream6_IRQHandler [WEAK]
EXPORT DMA1_Stream7_IRQHandler [WEAK]
EXPORT ADC_IRQHandler [WEAK]
EXPORT FDCAN1_IT0_IRQHandler [WEAK]
EXPORT FDCAN2_IT0_IRQHandler [WEAK]
EXPORT FDCAN1_IT1_IRQHandler [WEAK]
EXPORT FDCAN2_IT1_IRQHandler [WEAK]
EXPORT EXTI9_5_IRQHandler [WEAK]
EXPORT TIM1_BRK_IRQHandler [WEAK]
EXPORT TIM1_UP_IRQHandler [WEAK]
EXPORT TIM1_TRG_COM_IRQHandler [WEAK]
EXPORT TIM1_CC_IRQHandler [WEAK]
EXPORT TIM2_IRQHandler [WEAK]
EXPORT TIM3_IRQHandler [WEAK]
EXPORT TIM4_IRQHandler [WEAK]
EXPORT I2C1_EV_IRQHandler [WEAK]
EXPORT I2C1_ER_IRQHandler [WEAK]
EXPORT I2C2_EV_IRQHandler [WEAK]
EXPORT I2C2_ER_IRQHandler [WEAK]
EXPORT SPI1_IRQHandler [WEAK]
EXPORT SPI2_IRQHandler [WEAK]
EXPORT USART1_IRQHandler [WEAK]
EXPORT USART2_IRQHandler [WEAK]
EXPORT USART3_IRQHandler [WEAK]
EXPORT EXTI15_10_IRQHandler [WEAK]
EXPORT RTC_Alarm_IRQHandler [WEAK]
EXPORT TIM8_BRK_TIM12_IRQHandler [WEAK]
EXPORT TIM8_UP_TIM13_IRQHandler [WEAK]
EXPORT TIM8_TRG_COM_TIM14_IRQHandler [WEAK]
EXPORT TIM8_CC_IRQHandler [WEAK]
EXPORT DMA1_Stream7_IRQHandler [WEAK]
EXPORT FMC_IRQHandler [WEAK]
EXPORT SDMMC1_IRQHandler [WEAK]
EXPORT TIM5_IRQHandler [WEAK]
EXPORT SPI3_IRQHandler [WEAK]
EXPORT UART4_IRQHandler [WEAK]
EXPORT UART5_IRQHandler [WEAK]
EXPORT TIM6_DAC_IRQHandler [WEAK]
EXPORT TIM7_IRQHandler [WEAK]
EXPORT DMA2_Stream0_IRQHandler [WEAK]
EXPORT DMA2_Stream1_IRQHandler [WEAK]
EXPORT DMA2_Stream2_IRQHandler [WEAK]
EXPORT DMA2_Stream3_IRQHandler [WEAK]
EXPORT DMA2_Stream4_IRQHandler [WEAK]
EXPORT ETH_IRQHandler [WEAK]
EXPORT ETH_WKUP_IRQHandler [WEAK]
EXPORT FDCAN_CAL_IRQHandler [WEAK]
EXPORT DMA2_Stream5_IRQHandler [WEAK]
EXPORT DMA2_Stream6_IRQHandler [WEAK]
EXPORT DMA2_Stream7_IRQHandler [WEAK]
EXPORT USART6_IRQHandler [WEAK]
EXPORT I2C3_EV_IRQHandler [WEAK]
EXPORT I2C3_ER_IRQHandler [WEAK]
EXPORT OTG_HS_EP1_OUT_IRQHandler [WEAK]
EXPORT OTG_HS_EP1_IN_IRQHandler [WEAK]
EXPORT OTG_HS_WKUP_IRQHandler [WEAK]
EXPORT OTG_HS_IRQHandler [WEAK]
EXPORT DCMI_IRQHandler [WEAK]
EXPORT RNG_IRQHandler [WEAK]
EXPORT FPU_IRQHandler [WEAK]
EXPORT UART7_IRQHandler [WEAK]
EXPORT UART8_IRQHandler [WEAK]
EXPORT SPI4_IRQHandler [WEAK]
EXPORT SPI5_IRQHandler [WEAK]
EXPORT SPI6_IRQHandler [WEAK]
EXPORT SAI1_IRQHandler [WEAK]
EXPORT LTDC_IRQHandler [WEAK]
EXPORT LTDC_ER_IRQHandler [WEAK]
EXPORT DMA2D_IRQHandler [WEAK]
EXPORT SAI2_IRQHandler [WEAK]
EXPORT QUADSPI_IRQHandler [WEAK]
EXPORT LPTIM1_IRQHandler [WEAK]
EXPORT CEC_IRQHandler [WEAK]
EXPORT I2C4_EV_IRQHandler [WEAK]
EXPORT I2C4_ER_IRQHandler [WEAK]
EXPORT SPDIF_RX_IRQHandler [WEAK]
EXPORT OTG_FS_EP1_OUT_IRQHandler [WEAK]
EXPORT OTG_FS_EP1_IN_IRQHandler [WEAK]
EXPORT OTG_FS_WKUP_IRQHandler [WEAK]
EXPORT OTG_FS_IRQHandler [WEAK]
EXPORT DMAMUX1_OVR_IRQHandler [WEAK]
EXPORT HRTIM1_Master_IRQHandler [WEAK]
EXPORT HRTIM1_TIMA_IRQHandler [WEAK]
EXPORT HRTIM1_TIMB_IRQHandler [WEAK]
EXPORT HRTIM1_TIMC_IRQHandler [WEAK]
EXPORT HRTIM1_TIMD_IRQHandler [WEAK]
EXPORT HRTIM1_TIME_IRQHandler [WEAK]
EXPORT HRTIM1_FLT_IRQHandler [WEAK]
EXPORT DFSDM1_FLT0_IRQHandler [WEAK]
EXPORT DFSDM1_FLT1_IRQHandler [WEAK]
EXPORT DFSDM1_FLT2_IRQHandler [WEAK]
EXPORT DFSDM1_FLT3_IRQHandler [WEAK]
EXPORT SAI3_IRQHandler [WEAK]
EXPORT SWPMI1_IRQHandler [WEAK]
EXPORT TIM15_IRQHandler [WEAK]
EXPORT TIM16_IRQHandler [WEAK]
EXPORT TIM17_IRQHandler [WEAK]
EXPORT MDIOS_WKUP_IRQHandler [WEAK]
EXPORT MDIOS_IRQHandler [WEAK]
EXPORT JPEG_IRQHandler [WEAK]
EXPORT MDMA_IRQHandler [WEAK]
EXPORT SDMMC2_IRQHandler [WEAK]
EXPORT HSEM1_IRQHandler [WEAK]
EXPORT ADC3_IRQHandler [WEAK]
EXPORT DMAMUX2_OVR_IRQHandler [WEAK]
EXPORT BDMA_Channel0_IRQHandler [WEAK]
EXPORT BDMA_Channel1_IRQHandler [WEAK]
EXPORT BDMA_Channel2_IRQHandler [WEAK]
EXPORT BDMA_Channel3_IRQHandler [WEAK]
EXPORT BDMA_Channel4_IRQHandler [WEAK]
EXPORT BDMA_Channel5_IRQHandler [WEAK]
EXPORT BDMA_Channel6_IRQHandler [WEAK]
EXPORT BDMA_Channel7_IRQHandler [WEAK]
EXPORT COMP1_IRQHandler [WEAK]
EXPORT LPTIM2_IRQHandler [WEAK]
EXPORT LPTIM3_IRQHandler [WEAK]
EXPORT LPTIM4_IRQHandler [WEAK]
EXPORT LPTIM5_IRQHandler [WEAK]
EXPORT LPUART1_IRQHandler [WEAK]
EXPORT CRS_IRQHandler [WEAK]
EXPORT ECC_IRQHandler [WEAK]
EXPORT SAI4_IRQHandler [WEAK]
EXPORT WAKEUP_PIN_IRQHandler [WEAK]
WWDG_IRQHandler
PVD_AVD_IRQHandler
TAMP_STAMP_IRQHandler
RTC_WKUP_IRQHandler
FLASH_IRQHandler
RCC_IRQHandler
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
DMA1_Stream0_IRQHandler
DMA1_Stream1_IRQHandler
DMA1_Stream2_IRQHandler
DMA1_Stream3_IRQHandler
DMA1_Stream4_IRQHandler
DMA1_Stream5_IRQHandler
DMA1_Stream6_IRQHandler
ADC_IRQHandler
FDCAN1_IT0_IRQHandler
FDCAN2_IT0_IRQHandler
FDCAN1_IT1_IRQHandler
FDCAN2_IT1_IRQHandler
EXTI9_5_IRQHandler
TIM1_BRK_IRQHandler
TIM1_UP_IRQHandler
TIM1_TRG_COM_IRQHandler
TIM1_CC_IRQHandler
TIM2_IRQHandler
TIM3_IRQHandler
TIM4_IRQHandler
I2C1_EV_IRQHandler
I2C1_ER_IRQHandler
I2C2_EV_IRQHandler
I2C2_ER_IRQHandler
SPI1_IRQHandler
SPI2_IRQHandler
USART1_IRQHandler
USART2_IRQHandler
USART3_IRQHandler
EXTI15_10_IRQHandler
RTC_Alarm_IRQHandler
TIM8_BRK_TIM12_IRQHandler
TIM8_UP_TIM13_IRQHandler
TIM8_TRG_COM_TIM14_IRQHandler
TIM8_CC_IRQHandler
DMA1_Stream7_IRQHandler
FMC_IRQHandler
SDMMC1_IRQHandler
TIM5_IRQHandler
SPI3_IRQHandler
UART4_IRQHandler
UART5_IRQHandler
TIM6_DAC_IRQHandler
TIM7_IRQHandler
DMA2_Stream0_IRQHandler
DMA2_Stream1_IRQHandler
DMA2_Stream2_IRQHandler
DMA2_Stream3_IRQHandler
DMA2_Stream4_IRQHandler
ETH_IRQHandler
ETH_WKUP_IRQHandler
FDCAN_CAL_IRQHandler
DMA2_Stream5_IRQHandler
DMA2_Stream6_IRQHandler
DMA2_Stream7_IRQHandler
USART6_IRQHandler
I2C3_EV_IRQHandler
I2C3_ER_IRQHandler
OTG_HS_EP1_OUT_IRQHandler
OTG_HS_EP1_IN_IRQHandler
OTG_HS_WKUP_IRQHandler
OTG_HS_IRQHandler
DCMI_IRQHandler
RNG_IRQHandler
FPU_IRQHandler
UART7_IRQHandler
UART8_IRQHandler
SPI4_IRQHandler
SPI5_IRQHandler
SPI6_IRQHandler
SAI1_IRQHandler
LTDC_IRQHandler
LTDC_ER_IRQHandler
DMA2D_IRQHandler
SAI2_IRQHandler
QUADSPI_IRQHandler
LPTIM1_IRQHandler
CEC_IRQHandler
I2C4_EV_IRQHandler
I2C4_ER_IRQHandler
SPDIF_RX_IRQHandler
OTG_FS_EP1_OUT_IRQHandler
OTG_FS_EP1_IN_IRQHandler
OTG_FS_WKUP_IRQHandler
OTG_FS_IRQHandler
DMAMUX1_OVR_IRQHandler
HRTIM1_Master_IRQHandler
HRTIM1_TIMA_IRQHandler
HRTIM1_TIMB_IRQHandler
HRTIM1_TIMC_IRQHandler
HRTIM1_TIMD_IRQHandler
HRTIM1_TIME_IRQHandler
HRTIM1_FLT_IRQHandler
DFSDM1_FLT0_IRQHandler
DFSDM1_FLT1_IRQHandler
DFSDM1_FLT2_IRQHandler
DFSDM1_FLT3_IRQHandler
SAI3_IRQHandler
SWPMI1_IRQHandler
TIM15_IRQHandler
TIM16_IRQHandler
TIM17_IRQHandler
MDIOS_WKUP_IRQHandler
MDIOS_IRQHandler
JPEG_IRQHandler
MDMA_IRQHandler
SDMMC2_IRQHandler
HSEM1_IRQHandler
ADC3_IRQHandler
DMAMUX2_OVR_IRQHandler
BDMA_Channel0_IRQHandler
BDMA_Channel1_IRQHandler
BDMA_Channel2_IRQHandler
BDMA_Channel3_IRQHandler
BDMA_Channel4_IRQHandler
BDMA_Channel5_IRQHandler
BDMA_Channel6_IRQHandler
BDMA_Channel7_IRQHandler
COMP1_IRQHandler
LPTIM2_IRQHandler
LPTIM3_IRQHandler
LPTIM4_IRQHandler
LPTIM5_IRQHandler
LPUART1_IRQHandler
CRS_IRQHandler
ECC_IRQHandler
SAI4_IRQHandler
WAKEUP_PIN_IRQHandler
B .
ENDP
ALIGN
;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************
IF :DEF:__MICROLIB
EXPORT __initial_sp
EXPORT __heap_base
EXPORT __heap_limit
ELSE
IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap
LDR R0, = Heap_Mem
LDR R1, =(Stack_Mem + Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR
ALIGN
ENDIF
END

View File

@ -1,597 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_projx.xsd">
<SchemaVersion>2.1</SchemaVersion>
<Header>### uVision Project, (C) Keil Software</Header>
<Targets>
<Target>
<TargetName>stm32h743_cherryusb_hs</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<pCCUsed>6160000::V6.16::ARMCLANG</pCCUsed>
<uAC6>1</uAC6>
<TargetOption>
<TargetCommonOption>
<Device>STM32H743VGTx</Device>
<Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32H7xx_DFP.3.1.1</PackID>
<PackURL>https://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000-0x2001FFFF) IRAM2(0x24000000-0x2407FFFF) IROM(0x8000000-0x807FFFF) IROM2(0x8100000-0x817FFFF) CLOCK(12000000) FPU3(DFPU) CPUTYPE("Cortex-M7") ELITTLE TZ</Cpu>
<FlashUtilSpec></FlashUtilSpec>
<StartupFile></StartupFile>
<FlashDriverDll></FlashDriverDll>
<DeviceId>0</DeviceId>
<RegisterFile></RegisterFile>
<MemoryEnv></MemoryEnv>
<Cmp></Cmp>
<Asm></Asm>
<Linker></Linker>
<OHString></OHString>
<InfinionOptionDll></InfinionOptionDll>
<SLE66CMisc></SLE66CMisc>
<SLE66AMisc></SLE66AMisc>
<SLE66LinkerMisc></SLE66LinkerMisc>
<SFDFile>$$Device:STM32H743VGTx$CMSIS\SVD\STM32H743.svd</SFDFile>
<bCustSvd>0</bCustSvd>
<UseEnv>0</UseEnv>
<BinPath></BinPath>
<IncludePath></IncludePath>
<LibPath></LibPath>
<RegisterFilePath></RegisterFilePath>
<DBRegisterFilePath></DBRegisterFilePath>
<TargetStatus>
<Error>0</Error>
<ExitCodeStop>0</ExitCodeStop>
<ButtonStop>0</ButtonStop>
<NotGenerated>0</NotGenerated>
<InvalidFlash>1</InvalidFlash>
</TargetStatus>
<OutputDirectory>stm32h743_cherryusb_hs\</OutputDirectory>
<OutputName>stm32h743_cherryusb_hs</OutputName>
<CreateExecutable>1</CreateExecutable>
<CreateLib>0</CreateLib>
<CreateHexFile>1</CreateHexFile>
<DebugInformation>1</DebugInformation>
<BrowseInformation>1</BrowseInformation>
<ListingPath></ListingPath>
<HexFormatSelection>1</HexFormatSelection>
<Merge32K>0</Merge32K>
<CreateBatchFile>0</CreateBatchFile>
<BeforeCompile>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name></UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopU1X>0</nStopU1X>
<nStopU2X>0</nStopU2X>
</BeforeCompile>
<BeforeMake>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name></UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopB1X>0</nStopB1X>
<nStopB2X>0</nStopB2X>
</BeforeMake>
<AfterMake>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>1</RunUserProg2>
<UserProg1Name></UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopA1X>0</nStopA1X>
<nStopA2X>0</nStopA2X>
</AfterMake>
<SelectedForBatchBuild>1</SelectedForBatchBuild>
<SVCSIdString></SVCSIdString>
</TargetCommonOption>
<CommonProperty>
<UseCPPCompiler>0</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>0</AlwaysBuild>
<GenerateAssemblyFile>0</GenerateAssemblyFile>
<AssembleAssemblyFile>0</AssembleAssemblyFile>
<PublicsOnly>0</PublicsOnly>
<StopOnExitCode>3</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>0</ComprImg>
</CommonProperty>
<DllOption>
<SimDllName>SARMCM3.DLL</SimDllName>
<SimDllArguments>-REMAP -MPU</SimDllArguments>
<SimDlgDll>DCM.DLL</SimDlgDll>
<SimDlgDllArguments>-pCM7</SimDlgDllArguments>
<TargetDllName>SARMCM3.DLL</TargetDllName>
<TargetDllArguments>-MPU</TargetDllArguments>
<TargetDlgDll>TCM.DLL</TargetDlgDll>
<TargetDlgDllArguments>-pCM7</TargetDlgDllArguments>
</DllOption>
<DebugOption>
<OPTHX>
<HexSelection>1</HexSelection>
<HexRangeLowAddress>0</HexRangeLowAddress>
<HexRangeHighAddress>0</HexRangeHighAddress>
<HexOffset>0</HexOffset>
<Oh166RecLen>16</Oh166RecLen>
</OPTHX>
</DebugOption>
<Utilities>
<Flash1>
<UseTargetDll>1</UseTargetDll>
<UseExternalTool>0</UseExternalTool>
<RunIndependent>0</RunIndependent>
<UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
<Capability>1</Capability>
<DriverSelection>4101</DriverSelection>
</Flash1>
<bUseTDR>1</bUseTDR>
<Flash2>BIN\UL2CM3.DLL</Flash2>
<Flash3></Flash3>
<Flash4></Flash4>
<pFcarmOut></pFcarmOut>
<pFcarmGrp></pFcarmGrp>
<pFcArmRoot></pFcArmRoot>
<FcArmLst>0</FcArmLst>
</Utilities>
<TargetArmAds>
<ArmAdsMisc>
<GenerateListings>0</GenerateListings>
<asHll>1</asHll>
<asAsm>1</asAsm>
<asMacX>1</asMacX>
<asSyms>1</asSyms>
<asFals>1</asFals>
<asDbgD>1</asDbgD>
<asForm>1</asForm>
<ldLst>0</ldLst>
<ldmm>1</ldmm>
<ldXref>1</ldXref>
<BigEnd>0</BigEnd>
<AdsALst>1</AdsALst>
<AdsACrf>1</AdsACrf>
<AdsANop>0</AdsANop>
<AdsANot>0</AdsANot>
<AdsLLst>1</AdsLLst>
<AdsLmap>1</AdsLmap>
<AdsLcgr>1</AdsLcgr>
<AdsLsym>1</AdsLsym>
<AdsLszi>1</AdsLszi>
<AdsLtoi>1</AdsLtoi>
<AdsLsun>1</AdsLsun>
<AdsLven>1</AdsLven>
<AdsLsxf>1</AdsLsxf>
<RvctClst>0</RvctClst>
<GenPPlst>0</GenPPlst>
<AdsCpuType>"Cortex-M7"</AdsCpuType>
<RvctDeviceName></RvctDeviceName>
<mOS>0</mOS>
<uocRom>0</uocRom>
<uocRam>0</uocRam>
<hadIROM>1</hadIROM>
<hadIRAM>1</hadIRAM>
<hadXRAM>0</hadXRAM>
<uocXRam>0</uocXRam>
<RvdsVP>3</RvdsVP>
<RvdsMve>0</RvdsMve>
<RvdsCdeCp>0</RvdsCdeCp>
<hadIRAM2>1</hadIRAM2>
<hadIROM2>1</hadIROM2>
<StupSel>8</StupSel>
<useUlib>1</useUlib>
<EndSel>0</EndSel>
<uLtcg>0</uLtcg>
<nSecure>0</nSecure>
<RoSelD>3</RoSelD>
<RwSelD>4</RwSelD>
<CodeSel>0</CodeSel>
<OptFeed>0</OptFeed>
<NoZi1>0</NoZi1>
<NoZi2>0</NoZi2>
<NoZi3>0</NoZi3>
<NoZi4>0</NoZi4>
<NoZi5>0</NoZi5>
<Ro1Chk>0</Ro1Chk>
<Ro2Chk>0</Ro2Chk>
<Ro3Chk>0</Ro3Chk>
<Ir1Chk>1</Ir1Chk>
<Ir2Chk>0</Ir2Chk>
<Ra1Chk>0</Ra1Chk>
<Ra2Chk>0</Ra2Chk>
<Ra3Chk>0</Ra3Chk>
<Im1Chk>1</Im1Chk>
<Im2Chk>0</Im2Chk>
<OnChipMemories>
<Ocm1>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm1>
<Ocm2>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm2>
<Ocm3>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm3>
<Ocm4>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm4>
<Ocm5>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm5>
<Ocm6>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm6>
<IRAM>
<Type>0</Type>
<StartAddress>0x20000000</StartAddress>
<Size>0x20000</Size>
</IRAM>
<IROM>
<Type>1</Type>
<StartAddress>0x8000000</StartAddress>
<Size>0x80000</Size>
</IROM>
<XRAM>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</XRAM>
<OCR_RVCT1>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT1>
<OCR_RVCT2>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT2>
<OCR_RVCT3>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT3>
<OCR_RVCT4>
<Type>1</Type>
<StartAddress>0x8000000</StartAddress>
<Size>0x80000</Size>
</OCR_RVCT4>
<OCR_RVCT5>
<Type>1</Type>
<StartAddress>0x8100000</StartAddress>
<Size>0x80000</Size>
</OCR_RVCT5>
<OCR_RVCT6>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT6>
<OCR_RVCT7>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT7>
<OCR_RVCT8>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT8>
<OCR_RVCT9>
<Type>0</Type>
<StartAddress>0x24000000</StartAddress>
<Size>0x80000</Size>
</OCR_RVCT9>
<OCR_RVCT10>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT10>
</OnChipMemories>
<RvctStartVector></RvctStartVector>
</ArmAdsMisc>
<Cads>
<interw>1</interw>
<Optim>2</Optim>
<oTime>0</oTime>
<SplitLS>0</SplitLS>
<OneElfS>1</OneElfS>
<Strict>0</Strict>
<EnumInt>0</EnumInt>
<PlainCh>0</PlainCh>
<Ropi>0</Ropi>
<Rwpi>0</Rwpi>
<wLevel>3</wLevel>
<uThumb>0</uThumb>
<uSurpInc>0</uSurpInc>
<uC99>1</uC99>
<uGnu>1</uGnu>
<useXO>0</useXO>
<v6Lang>3</v6Lang>
<v6LangP>3</v6LangP>
<vShortEn>1</vShortEn>
<vShortWch>1</vShortWch>
<v6Lto>0</v6Lto>
<v6WtE>0</v6WtE>
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>USE_HAL_DRIVER,STM32H743xx</Define>
<Undefine></Undefine>
<IncludePath>../Core/Inc;../Drivers/STM32H7xx_HAL_Driver/Inc;../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32H7xx/Include;../Drivers/CMSIS/Include;../../3rdparty/CherryUSB-1.4.0/core;../../3rdparty/CherryUSB-1.4.0/common;../../3rdparty/CherryUSB-1.4.0/port/dwc2;../../3rdparty/CherryUSB-1.4.0/class/hid</IncludePath>
</VariousControls>
</Cads>
<Aads>
<interw>1</interw>
<Ropi>0</Ropi>
<Rwpi>0</Rwpi>
<thumb>0</thumb>
<SplitLS>0</SplitLS>
<SwStkChk>0</SwStkChk>
<NoWarn>0</NoWarn>
<uSurpInc>0</uSurpInc>
<useXO>0</useXO>
<ClangAsOpt>1</ClangAsOpt>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Aads>
<LDads>
<umfTarg>1</umfTarg>
<Ropi>0</Ropi>
<Rwpi>0</Rwpi>
<noStLib>0</noStLib>
<RepFail>1</RepFail>
<useFile>0</useFile>
<TextAddressRange></TextAddressRange>
<DataAddressRange></DataAddressRange>
<pXoBase></pXoBase>
<ScatterFile></ScatterFile>
<IncludeLibs></IncludeLibs>
<IncludeLibsPath></IncludeLibsPath>
<Misc></Misc>
<LinkerInputFile></LinkerInputFile>
<DisabledWarnings></DisabledWarnings>
</LDads>
</TargetArmAds>
</TargetOption>
<Groups>
<Group>
<GroupName>Application/MDK-ARM</GroupName>
<Files>
<File>
<FileName>startup_stm32h743xx.s</FileName>
<FileType>2</FileType>
<FilePath>startup_stm32h743xx.s</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>Application/User/Core</GroupName>
<Files>
<File>
<FileName>usb_dc_msp.c</FileName>
<FileType>1</FileType>
<FilePath>..\Core\Src\usb_dc_msp.c</FilePath>
</File>
<File>
<FileName>usb_device_custom_hid.c</FileName>
<FileType>1</FileType>
<FilePath>..\Core\Src\usb_device_custom_hid.c</FilePath>
</File>
<File>
<FileName>usb_config.h</FileName>
<FileType>5</FileType>
<FilePath>..\Core\Inc\usb_config.h</FilePath>
</File>
<File>
<FileName>main.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/main.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_it.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/stm32h7xx_it.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_msp.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/stm32h7xx_hal_msp.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>Drivers/STM32H7xx_HAL_Driver</GroupName>
<Files>
<File>
<FileName>stm32h7xx_hal_cortex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_cortex.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_rcc.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_rcc_ex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc_ex.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_flash.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_flash_ex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash_ex.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_gpio.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_gpio.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_hsem.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_hsem.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_dma.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_dma_ex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma_ex.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_mdma.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_mdma.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_pwr.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_pwr_ex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr_ex.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_i2c.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_i2c.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_i2c_ex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_i2c_ex.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_exti.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_exti.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_tim.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_tim_ex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim_ex.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_uart.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_uart.c</FilePath>
</File>
<File>
<FileName>stm32h7xx_hal_uart_ex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_uart_ex.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>Drivers/CMSIS</GroupName>
<Files>
<File>
<FileName>system_stm32h7xx.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/system_stm32h7xx.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>CherryUSB</GroupName>
<Files>
<File>
<FileName>usbd_core.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\3rdparty\CherryUSB-1.4.0\core\usbd_core.c</FilePath>
</File>
<File>
<FileName>usb_dc_dwc2.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\3rdparty\CherryUSB-1.4.0\port\dwc2\usb_dc_dwc2.c</FilePath>
</File>
<File>
<FileName>usb_glue_st.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\3rdparty\CherryUSB-1.4.0\port\dwc2\usb_glue_st.c</FilePath>
</File>
<File>
<FileName>usbd_hid.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\3rdparty\CherryUSB-1.4.0\class\hid\usbd_hid.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>::CMSIS</GroupName>
</Group>
</Groups>
</Target>
</Targets>
<RTE>
<apis/>
<components>
<component Cclass="CMSIS" Cgroup="CORE" Cvendor="ARM" Cversion="5.5.0" condition="ARMv6_7_8-M Device">
<package name="CMSIS" schemaVersion="1.3" url="http://www.keil.com/pack/" vendor="ARM" version="5.8.0"/>
<targetInfos>
<targetInfo name="stm32h743_cherryusb_hs"/>
</targetInfos>
</component>
</components>
<files/>
</RTE>
<LayerInfo>
<Layers>
<Layer>
<LayName>stm32h743_cherryusb_hs</LayName>
<LayPrjMark>1</LayPrjMark>
</Layer>
</Layers>
</LayerInfo>
</Project>

View File

@ -0,0 +1,212 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.debug.238545867">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.debug.238545867" moduleId="org.eclipse.cdt.core.settings" name="Debug">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactExtension="elf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.debug.238545867" name="Debug" parent="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.debug">
<folderInfo id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.debug.238545867." name="/" resourcePath="">
<toolChain id="com.st.stm32cube.ide.mcu.gnu.managedbuild.toolchain.exe.debug.349291389" name="MCU ARM GCC" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.toolchain.exe.debug">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_mcu.1182488091" name="MCU" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_mcu" useByScannerDiscovery="true" value="STM32H743VGTx" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_cpuid.1100277903" name="CPU" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_cpuid" useByScannerDiscovery="false" value="0" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_coreid.229541713" name="Core" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_coreid" useByScannerDiscovery="false" value="0" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu.1169103595" name="Floating-point unit" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu" useByScannerDiscovery="true" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu.value.fpv5-d16" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.847402065" name="Floating-point ABI" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi" useByScannerDiscovery="true" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.value.hard" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board.225159456" name="Board" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board" useByScannerDiscovery="false" value="genericBoard" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.77341362" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Debug || true || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32H743VGTx || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../Core/Inc | ../Drivers/STM32H7xx_HAL_Driver/Inc | ../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy | ../Drivers/CMSIS/Device/ST/STM32H7xx/Include | ../Drivers/CMSIS/Include || || || USE_HAL_DRIVER | STM32H743xx || || Drivers | Core/Startup | Core || || || ${workspace_loc:/${ProjName}/STM32H743VGTX_FLASH.ld} || true || NonSecure || || secure_nsclib.o || || None || || || " valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.debug.option.cpuclock.914293263" name="Cpu clock frequence" superClass="com.st.stm32cube.ide.mcu.debug.option.cpuclock" useByScannerDiscovery="false" value="200" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.converthex.919179987" name="Convert to Intel Hex file (-O ihex)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.converthex" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.convertbinary.605184946" name="Convert to binary file (-O binary)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.convertbinary" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.showsize.182151138" name="Show size information about built artifact" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.showsize" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.1617094204" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/>
<builder buildPath="${workspace_loc:/stm32h743_usbhs_8k_mouse}/Debug" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.1656771471" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.1887056056" name="MCU/MPU GCC Assembler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel.1248648846" name="Debug level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel.value.g3" valueType="enumerated"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.definedsymbols.1326005159" name="Define symbols (-D)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.definedsymbols" valueType="definedSymbols">
<listOptionValue builtIn="false" value="DEBUG"/>
</option>
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.input.665023280" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.input"/>
</tool>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.2054841574" name="MCU/MPU GCC Compiler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel.421147382" name="Debug level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel.value.g3" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level.1048045543" name="Optimization level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level" useByScannerDiscovery="false"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.definedsymbols.1966435148" name="Define symbols (-D)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.definedsymbols" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="DEBUG"/>
<listOptionValue builtIn="false" value="USE_HAL_DRIVER"/>
<listOptionValue builtIn="false" value="STM32H743xx"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.includepaths.1762960837" name="Include paths (-I)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.includepaths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="../Core/Inc"/>
<listOptionValue builtIn="false" value="../Drivers/STM32H7xx_HAL_Driver/Inc"/>
<listOptionValue builtIn="false" value="../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy"/>
<listOptionValue builtIn="false" value="../Drivers/CMSIS/Device/ST/STM32H7xx/Include"/>
<listOptionValue builtIn="false" value="../Drivers/CMSIS/Include"/>
<listOptionValue builtIn="false" value="../Third_Party/CherryUSB/class/hid"/>
<listOptionValue builtIn="false" value="../Third_Party/CherryUSB/common"/>
<listOptionValue builtIn="false" value="../Third_Party/CherryUSB/core"/>
<listOptionValue builtIn="false" value="../Third_Party/CherryUSB/port/dwc2"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.otherflags.751428081" name="Other flags" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.otherflags" useByScannerDiscovery="true" valueType="stringList">
<listOptionValue builtIn="false" value="-Wformat=0"/>
</option>
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c.314726074" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c"/>
</tool>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.1280164584" name="MCU/MPU G++ Compiler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.debuglevel.1049961626" name="Debug level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.debuglevel" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.debuglevel.value.g3" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.optimization.level.670536052" name="Optimization level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.optimization.level" useByScannerDiscovery="false"/>
</tool>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.957672311" name="MCU/MPU GCC Linker" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.script.699359276" name="Linker Script (-T)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.script" value="${workspace_loc:/${ProjName}/STM32H743VGTX_FLASH.ld}" valueType="string"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.otherflags.107832544" name="Other flags" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.otherflags" valueType="stringList">
<listOptionValue builtIn="false" value="-Wl,--print-memory-usage"/>
</option>
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.input.387733867" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.linker.1706216836" name="MCU/MPU G++ Linker" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.linker"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.archiver.1602905602" name="MCU/MPU GCC Archiver" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.archiver"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.size.1590072357" name="MCU Size" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.size"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objdump.listfile.1359203186" name="MCU Output Converter list file" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objdump.listfile"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.hex.605686935" name="MCU Output Converter Hex" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.hex"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.binary.1033325000" name="MCU Output Converter Binary" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.binary"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.verilog.835632053" name="MCU Output Converter Verilog" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.verilog"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.srec.917765756" name="MCU Output Converter Motorola S-rec" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.srec"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.symbolsrec.376575735" name="MCU Output Converter Motorola S-rec with symbols" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.symbolsrec"/>
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="Third_Party"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Core"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Drivers"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
<cconfiguration id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release.741658024">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release.741658024" moduleId="org.eclipse.cdt.core.settings" name="Release">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactExtension="elf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release.741658024" name="Release" parent="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release">
<folderInfo id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release.741658024." name="/" resourcePath="">
<toolChain id="com.st.stm32cube.ide.mcu.gnu.managedbuild.toolchain.exe.release.259302700" name="MCU ARM GCC" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.toolchain.exe.release">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_mcu.948350025" name="MCU" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_mcu" useByScannerDiscovery="true" value="STM32H743VGTx" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_cpuid.2143300840" name="CPU" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_cpuid" useByScannerDiscovery="false" value="0" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_coreid.1966654056" name="Core" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_coreid" useByScannerDiscovery="false" value="0" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu.908895095" name="Floating-point unit" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu" useByScannerDiscovery="true" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu.value.fpv5-d16" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.1507861964" name="Floating-point ABI" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi" useByScannerDiscovery="true" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.value.hard" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board.2044896575" name="Board" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board" useByScannerDiscovery="false" value="genericBoard" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.1658261950" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Release || false || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32H743VGTx || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../Core/Inc | ../Drivers/STM32H7xx_HAL_Driver/Inc | ../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy | ../Drivers/CMSIS/Device/ST/STM32H7xx/Include | ../Drivers/CMSIS/Include || || || USE_HAL_DRIVER | STM32H743xx || || Drivers | Core/Startup | Core || || || ${workspace_loc:/${ProjName}/STM32H743VGTX_FLASH.ld} || true || NonSecure || || secure_nsclib.o || || None || || || " valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.debug.option.cpuclock.570630537" name="Cpu clock frequence" superClass="com.st.stm32cube.ide.mcu.debug.option.cpuclock" useByScannerDiscovery="false" value="200" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.converthex.960449879" name="Convert to Intel Hex file (-O ihex)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.converthex" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.convertbinary.846745374" name="Convert to binary file (-O binary)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.convertbinary" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.showsize.2039488821" name="Show size information about built artifact" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.showsize" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.2066852322" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/>
<builder buildPath="${workspace_loc:/stm32h743_usbhs_8k_mouse}/Release" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.91117937" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.1426193676" name="MCU/MPU GCC Assembler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel.313717713" name="Debug level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel.value.g0" valueType="enumerated"/>
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.input.1038497889" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.input"/>
</tool>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.797539412" name="MCU/MPU GCC Compiler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel.1438233111" name="Debug level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel.value.g0" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level.2023942604" name="Optimization level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level.value.ofast" valueType="enumerated"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.definedsymbols.2019704288" name="Define symbols (-D)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.definedsymbols" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="USE_HAL_DRIVER"/>
<listOptionValue builtIn="false" value="STM32H743xx"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.includepaths.1609614570" name="Include paths (-I)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.includepaths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="../Core/Inc"/>
<listOptionValue builtIn="false" value="../Drivers/STM32H7xx_HAL_Driver/Inc"/>
<listOptionValue builtIn="false" value="../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy"/>
<listOptionValue builtIn="false" value="../Drivers/CMSIS/Device/ST/STM32H7xx/Include"/>
<listOptionValue builtIn="false" value="../Drivers/CMSIS/Include"/>
<listOptionValue builtIn="false" value="../Third_Party/CherryUSB/class/hid"/>
<listOptionValue builtIn="false" value="../Third_Party/CherryUSB/common"/>
<listOptionValue builtIn="false" value="../Third_Party/CherryUSB/core"/>
<listOptionValue builtIn="false" value="../Third_Party/CherryUSB/port/dwc2"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.otherflags.1521195300" name="Other flags" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.otherflags" useByScannerDiscovery="true" valueType="stringList">
<listOptionValue builtIn="false" value="-Wformat=0"/>
</option>
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c.436480412" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c"/>
</tool>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.1169108700" name="MCU/MPU G++ Compiler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.debuglevel.1325522584" name="Debug level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.debuglevel" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.debuglevel.value.g0" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.optimization.level.1100479008" name="Optimization level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.optimization.level.value.os" valueType="enumerated"/>
</tool>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.2109194419" name="MCU/MPU GCC Linker" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.script.1845909156" name="Linker Script (-T)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.script" value="${workspace_loc:/${ProjName}/STM32H743VGTX_FLASH.ld}" valueType="string"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.otherflags.2127923250" name="Other flags" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.otherflags" valueType="stringList">
<listOptionValue builtIn="false" value="-Wl,--print-memory-usage"/>
</option>
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.input.669757527" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.linker.1168687349" name="MCU/MPU G++ Linker" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.linker"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.archiver.1877928963" name="MCU/MPU GCC Archiver" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.archiver"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.size.1291159604" name="MCU Size" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.size"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objdump.listfile.757719397" name="MCU Output Converter list file" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objdump.listfile"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.hex.933899451" name="MCU Output Converter Hex" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.hex"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.binary.941977267" name="MCU Output Converter Binary" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.binary"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.verilog.843120275" name="MCU Output Converter Verilog" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.verilog"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.srec.1050779051" name="MCU Output Converter Motorola S-rec" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.srec"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.symbolsrec.194383418" name="MCU Output Converter Motorola S-rec with symbols" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.symbolsrec"/>
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="Third_Party"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Core"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Drivers"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.pathentry"/>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="stm32h743_usbhs_8k_mouse.null.1055489337" name="stm32h743_usbhs_8k_mouse"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.debug.238545867;com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.debug.238545867.;com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.2054841574;com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c.314726074">
<autodiscovery enabled="false" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release.741658024;com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release.741658024.;com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.797539412;com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c.436480412">
<autodiscovery enabled="false" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Debug">
<resource resourceType="PROJECT" workspacePath="/stm32h743_usbhs_8k_mouse"/>
</configuration>
<configuration configurationName="Release">
<resource resourceType="PROJECT" workspacePath="/stm32h743_usbhs_8k_mouse"/>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
</cproject>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>stm32h743_usbhs_8k_mouse</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.st.stm32cube.ide.mcu.MCUProjectNature</nature>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>com.st.stm32cube.ide.mcu.MCUCubeIdeServicesRevAev2ProjectNature</nature>
<nature>com.st.stm32cube.ide.mcu.MCUCubeProjectNature</nature>
<nature>com.st.stm32cube.ide.mcu.MCUAdvancedStructureProjectNature</nature>
<nature>com.st.stm32cube.ide.mcu.MCUSingleCpuProjectNature</nature>
<nature>com.st.stm32cube.ide.mcu.MCURootProjectNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>

View File

@ -41,7 +41,7 @@ extern "C" {
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
extern UART_HandleTypeDef huart1;
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
@ -57,6 +57,7 @@ void Error_Handler(void);
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
#define DBG_UART huart1
#define LED_Y2_Pin GPIO_PIN_2
#define LED_Y2_GPIO_Port GPIOE
#define LED_Y1_Pin GPIO_PIN_6

View File

@ -0,0 +1,18 @@
#ifndef __USB_DEVICE_MOUSE
#define __USB_DEVICE_MOUSE
#include <stdint.h>
#define USBD_VID 0x0483
#define USBD_PID 0x5750
#define USBD_MAX_POWER_MA 200
#define USBD_LANGID_STRING 1033
#define HID_MOUSE_INT_EP 0x81
#define HID_MOUSE_INT_EP_SIZE 4
#define HID_MOUSE_INT_EP_INTERVAL 1
void hid_mouse_init(uint8_t busid, uintptr_t reg_base);
void hid_mouse_send(uint8_t busid, uint8_t buttons, int8_t x, int8_t y, int8_t wheel);
#endif

View File

@ -21,7 +21,7 @@
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "usb_device_mouse.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
@ -31,13 +31,8 @@
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define LED_R_ON_STR "红色LED打开"
#define LED_R_OFF_STR "红色LED关闭"
#define LED_G_ON_STR "绿色LED打开"
#define LED_G_OFF_STR "绿色LED关闭"
#define KEY1_PRESSED_STR "按键1按下"
#define KEY2_PRESSED_STR "按键2按下"
#define KEY3_PRESSED_STR "按键3按下"
#define CURSOR_STEP 5U
#define CURSOR_WIDTH 20U
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
@ -50,7 +45,7 @@
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
extern volatile uint8_t hid_led_status;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
@ -59,17 +54,45 @@ static void MPU_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
void hid_custom_init(uint8_t busid, uintptr_t reg_base);
void hid_custom_send(const uint8_t *data, uint16_t length);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int fputc(int c, FILE *f)
void draw_circle(uint8_t *x_out, uint8_t *y_out)
{
uint8_t ch = c;
HAL_UART_Transmit(&huart1, &ch, 1, 10);
return c;
static int32_t move_cnt = 0;
static uint8_t step_x_y = 0;
static int8_t x = 0, y = 0;
move_cnt++;
if (move_cnt > CURSOR_WIDTH) {
step_x_y ++;
step_x_y = step_x_y % 4;
move_cnt = 0;
}
switch (step_x_y) {
case 0: {
y = 0;
x = CURSOR_STEP;
} break;
case 1: {
x = 0;
y = CURSOR_STEP;
} break;
case 2: {
y = 0;
x = (int8_t)(-CURSOR_STEP);
} break;
case 3: {
x = 0;
y = (int8_t)(-CURSOR_STEP);
} break;
}
*x_out = x;
*y_out = y;
}
/* USER CODE END 0 */
@ -93,69 +116,37 @@ int main(void)
HAL_Init();
/* USER CODE BEGIN Init */
HAL_DBGMCU_EnableDBGSleepMode(); //Enable debug port while CPU is sleeping
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
HAL_DBGMCU_EnableDBGSleepMode(); //Enable debug port while CPU is sleeping
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
hid_custom_init(0, USB1_OTG_HS_PERIPH_BASE);
hid_mouse_init(0, USB1_OTG_HS_PERIPH_BASE);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
uint8_t x, y;
while (1)
{
if (hid_led_status == 1) {
HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_RESET);
hid_custom_send((const uint8_t*)LED_R_OFF_STR, sizeof(LED_R_OFF_STR));
} else if (hid_led_status == 2) {
HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_SET);
hid_custom_send((const uint8_t*)LED_R_ON_STR, sizeof(LED_R_ON_STR));
} else if (hid_led_status == 3) {
HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_RESET);
hid_custom_send((const uint8_t*)LED_G_OFF_STR, sizeof(LED_G_OFF_STR));
} else if (hid_led_status == 4) {
HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_SET);
hid_custom_send((const uint8_t*)LED_G_ON_STR, sizeof(LED_G_ON_STR));
if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET) {
draw_circle(&x, &y);
hid_mouse_send(0, 0, x, y, 0);
} else {
__WFI();
}
hid_led_status = 0;
if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET) {
HAL_Delay(10);
hid_custom_send((const uint8_t*)KEY1_PRESSED_STR, sizeof(KEY1_PRESSED_STR));
while (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET);
HAL_Delay(10);
}
if (HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == GPIO_PIN_RESET) {
HAL_Delay(10);
hid_custom_send((const uint8_t*)KEY2_PRESSED_STR, sizeof(KEY2_PRESSED_STR));
HAL_GPIO_TogglePin(LED_R_GPIO_Port, LED_R_Pin);
while (HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == GPIO_PIN_RESET);
HAL_Delay(10);
}
if (HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin) == GPIO_PIN_RESET) {
HAL_Delay(10);
hid_custom_send((const uint8_t*)KEY3_PRESSED_STR, sizeof(KEY3_PRESSED_STR));
HAL_GPIO_TogglePin(LED_G_GPIO_Port, LED_G_Pin);
while (HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin) == GPIO_PIN_RESET);
HAL_Delay(10);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
__WFI();
}
/* USER CODE END 3 */
}
@ -182,10 +173,18 @@ void SystemClock_Config(void)
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 10;
RCC_OscInitStruct.PLL.PLLN = 160;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
@ -196,18 +195,22 @@ void SystemClock_Config(void)
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV4;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV4;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV4;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
/** Enables the Clock Security System
*/
HAL_RCC_EnableCSS();
}
/**
@ -271,15 +274,16 @@ static void MX_GPIO_Init(void)
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED_Y2_GPIO_Port, LED_Y2_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_Y2_GPIO_Port, LED_Y2_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED_Y1_GPIO_Port, LED_Y1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_Y1_GPIO_Port, LED_Y1_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOD, LED_R_Pin|LED_G_Pin, GPIO_PIN_RESET);
@ -363,10 +367,12 @@ void Error_Handler(void)
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_RESET);
while (1)
{
while (1) {
__WFI();
}
/* USER CODE END Error_Handler_Debug */
}

View File

@ -155,5 +155,105 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
}
/* USER CODE BEGIN 1 */
void usb_dc_low_level_init(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = { 0 };
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Enable HSI48 oscillator and select HSI48 for USBHS */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48;
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
/* Enable USB Voltage detector */
HAL_PWREx_EnableUSBVoltageDetector();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/* USB_OTG_HS GPIO Configuration
PC0 ------> USB_OTG_HS_ULPI_STP
PC2_C ------> USB_OTG_HS_ULPI_DIR
PC3_C ------> USB_OTG_HS_ULPI_NXT
PA3 ------> USB_OTG_HS_ULPI_D0
PA5 ------> USB_OTG_HS_ULPI_CK
PB0 ------> USB_OTG_HS_ULPI_D1
PB1 ------> USB_OTG_HS_ULPI_D2
PB10 ------> USB_OTG_HS_ULPI_D3
PB11 ------> USB_OTG_HS_ULPI_D4
PB12 ------> USB_OTG_HS_ULPI_D5
PB13 ------> USB_OTG_HS_ULPI_D6
PB5 ------> USB_OTG_HS_ULPI_D7
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF10_OTG2_HS;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF10_OTG2_HS;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF10_OTG2_HS;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_USB_OTG_HS_CLK_ENABLE();
__HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE();
/* USB_OTG_HS interrupt Init */
HAL_NVIC_SetPriority(OTG_HS_IRQn, 9, 0);
HAL_NVIC_EnableIRQ(OTG_HS_IRQn);
}
void usb_dc_low_level_deinit(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
HAL_NVIC_DisableIRQ(OTG_HS_IRQn);
/* Peripheral clock disable */
__HAL_RCC_USB_OTG_HS_CLK_DISABLE();
__HAL_RCC_USB_OTG_HS_ULPI_CLK_DISABLE();
/* HSI48 clock disable */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48;
RCC_OscInitStruct.HSI48State = RCC_HSI48_OFF;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
/* USB_OTG_HS GPIO Configuration
PC0 ------> USB_OTG_HS_ULPI_STP
PC2_C ------> USB_OTG_HS_ULPI_DIR
PC3_C ------> USB_OTG_HS_ULPI_NXT
PA3 ------> USB_OTG_HS_ULPI_D0
PA5 ------> USB_OTG_HS_ULPI_CK
PB0 ------> USB_OTG_HS_ULPI_D1
PB1 ------> USB_OTG_HS_ULPI_D2
PB10 ------> USB_OTG_HS_ULPI_D3
PB11 ------> USB_OTG_HS_ULPI_D4
PB12 ------> USB_OTG_HS_ULPI_D5
PB13 ------> USB_OTG_HS_ULPI_D6
PB5 ------> USB_OTG_HS_ULPI_D7
*/
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3);
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3|GPIO_PIN_5);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_5);
}
/* USER CODE END 1 */

View File

@ -46,7 +46,7 @@
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
void USBD_IRQHandler(uint8_t busid);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
@ -71,6 +71,7 @@ void NMI_Handler(void)
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
HAL_RCC_NMI_IRQHandler();
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
while (1)
{
@ -199,5 +200,8 @@ void SysTick_Handler(void)
/******************************************************************************/
/* USER CODE BEGIN 1 */
void OTG_HS_IRQHandler(void)
{
USBD_IRQHandler(0);
}
/* USER CODE END 1 */

View File

@ -0,0 +1,96 @@
/**
******************************************************************************
* @file syscalls.c
* @author Auto-generated by STM32CubeIDE
* @brief STM32CubeIDE Minimal System calls file
*
* For more information about which c-functions
* need which of these lowlevel functions
* please consult the Newlib libc-manual
******************************************************************************
* @attention
*
* Copyright (c) 2020-2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes */
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>
#include <unistd.h>
#include "main.h"
int _getpid(void)
{
return 1;
}
int _kill(int pid, int sig)
{
UNUSED(pid);
UNUSED(sig);
errno = EINVAL;
return -1;
}
int _read(int file, char *ptr, int len)
{
UNUSED(file);
*ptr = '\0'; //未实现
return 0;
}
int _write(int file, char *ptr, int len)
{
if (file == STDOUT_FILENO || file == STDERR_FILENO) {
HAL_UART_Transmit(&DBG_UART, (uint8_t*)ptr, len, 0xFFFF); //使用串口打印printf信息
}
return len;
}
int _close(int file)
{
UNUSED(file);
return -1;
}
int _fstat(int file, struct stat *st)
{
UNUSED(file);
st->st_mode = S_IFCHR;
return 0;
}
int _isatty(int file)
{
UNUSED(file);
return 1;
}
int _lseek(int file, int ptr, int dir)
{
UNUSED(file);
UNUSED(ptr);
UNUSED(ptr);
return 0;
}

View File

@ -0,0 +1,79 @@
/**
******************************************************************************
* @file sysmem.c
* @author Generated by STM32CubeIDE
* @brief STM32CubeIDE System Memory calls file
*
* For more information about which C functions
* need which of these lowlevel functions
* please consult the newlib libc manual
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes */
#include <errno.h>
#include <stdint.h>
/**
* Pointer to the current high watermark of the heap usage
*/
static uint8_t *__sbrk_heap_end = NULL;
/**
* @brief _sbrk() allocates memory to the newlib heap and is used by malloc
* and others from the C library
*
* @verbatim
* ############################################################################
* # .data # .bss # newlib heap # MSP stack #
* # # # # Reserved by _Min_Stack_Size #
* ############################################################################
* ^-- RAM start ^-- _end _estack, RAM end --^
* @endverbatim
*
* This implementation starts allocating at the '_end' linker symbol
* The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack
* The implementation considers '_estack' linker symbol to be RAM end
* NOTE: If the MSP stack, at any point during execution, grows larger than the
* reserved size, please increase the '_Min_Stack_Size'.
*
* @param incr Memory size
* @return Pointer to allocated memory
*/
void *_sbrk(ptrdiff_t incr)
{
extern uint8_t _end; /* Symbol defined in the linker script */
extern uint8_t _estack; /* Symbol defined in the linker script */
extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */
const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size;
const uint8_t *max_heap = (uint8_t *)stack_limit;
uint8_t *prev_heap_end;
/* Initialize heap end at first call */
if (NULL == __sbrk_heap_end)
{
__sbrk_heap_end = &_end;
}
/* Protect heap from growing into the reserved MSP stack */
if (__sbrk_heap_end + incr > max_heap)
{
errno = ENOMEM;
return (void *)-1;
}
prev_heap_end = __sbrk_heap_end;
__sbrk_heap_end += incr;
return (void *)prev_heap_end;
}

View File

@ -0,0 +1,261 @@
#include "usb_device_mouse.h"
#include <string.h>
#include "main.h"
#include "usbd_core.h"
#include "usbd_hid.h"
#define HID_MOUSE_CONFIG_DESCRIPTOR_SIZE 34
#define HID_MOUSE_REPORT_DESC_SIZE 52
static volatile uint8_t hid_mouse_busy = 0;
static uint8_t hid_mouse_descriptor[] = {
/* 设备(Device)描述符 所有设备有且只有一个 */
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
/* 配置(Configuration)描述符 所有设备至少有一个 */
USB_CONFIG_DESCRIPTOR_INIT(HID_MOUSE_CONFIG_DESCRIPTOR_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER_MA),
/* 截至此处的配置描述符长度: 9 */
/* 接口(Interface)描述符 HID鼠标 */
0x09, /* bLength: Descriptor size */
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: 1 */
0x03, /* bInterfaceClass: HID */
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x02, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0, /* iInterface: Index of string descriptor */
/* 截至此处的配置描述符长度: 18 */
/* HID描述符 鼠标 */
0x09, /* bLength: HID Descriptor size */
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
0x11, 0x01, /* bcdHID: HID Class Spec release number: HID1.11 */
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
0x22, /* bDescriptorType */
WBVAL(HID_MOUSE_REPORT_DESC_SIZE), /* wItemLength: Total length of Report descriptor */
/* 截至此处的配置描述符长度: 27 */
/* 端点(Endpoint)描述符 鼠标INT IN端点 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
HID_MOUSE_INT_EP, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
WBVAL(HID_MOUSE_INT_EP_SIZE), /* wMaxPacketSize: 9 Bytes maximum */
HID_MOUSE_INT_EP_INTERVAL, /* bInterval: Polling Interval */
/* 截至此处的配置描述符长度: 34 */
/* 字符串(String)描述符 设备支持的语言描述符 */
USB_LANGID_INIT(USBD_LANGID_STRING),
/* 字符串(String)描述符 制造商字符串 */
0x0C, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'S', 0x00,
'T', 0x00,
'M', 0x00,
'3', 0x00,
'2', 0x00, /* 共5字符 */
/* 字符串(String)描述符 产品字符串 */
0x28, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'E', 0x00,
'm', 0x00,
'u', 0x00,
'l', 0x00,
'a', 0x00,
't', 0x00,
'e', 0x00,
'd', 0x00,
' ', 0x00,
'8', 0x00,
'k', 0x00,
'H', 0x00,
'z', 0x00,
' ', 0x00,
'M', 0x00,
'o', 0x00,
'u', 0x00,
's', 0x00,
'e', 0x00, /* 共14字符 */
/* 字符串(String)描述符 序列号字符串 */
0x32, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00,
'0', 0x00, /* 共24字符 */
#ifdef CONFIG_USB_HS
/* 设备限定(Device Qualifier)描述符 同时支持全速与高速的设备必须有 */
0x0A,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
#endif
/* 空描述符 */
0x00
};
static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (0x01)
0x29, 0x03, // Usage Maximum (0x03)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x03, // Report Count (3)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x75, 0x05, // Report Size (5)
0x95, 0x01, // Report Count (1)
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x09, 0x38, // Usage (Wheel)
0x15, 0x81, // Logical Minimum (-127)
0x25, 0x7F, // Logical Maximum (127)
0x75, 0x08, // Report Size (8)
0x95, 0x03, // Report Count (3)
0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
0xC0, // End Collection
};
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONNECTED:
break;
case USBD_EVENT_DISCONNECTED:
break;
case USBD_EVENT_RESUME:
break;
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_SET);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
static void hid_mouse_in_ep_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
static uint16_t count = 0;
count ++;
if (count > 8000 / 2) { //8KHz回报率时LED以1Hz频率闪烁
HAL_GPIO_TogglePin(LED_R_GPIO_Port, LED_R_Pin);
count = 0;
}
hid_mouse_busy = 0;
}
static struct usbd_endpoint hid_mouse_in_ep = {
.ep_cb = hid_mouse_in_ep_callback,
.ep_addr = HID_MOUSE_INT_EP
};
static void fill_usb_descriptor_serial_number(void)
{
char uid_string[25];
sprintf(uid_string, "%08X%08X%08X", HAL_GetUIDw0(), HAL_GetUIDw1(), HAL_GetUIDw2());
uint16_t serial_number_offset = 0;
for (uint16_t i = 0; i < sizeof(hid_mouse_descriptor) - 3; i ++) { //查找USB描述符中序列号字符描述符的偏移
if (hid_mouse_descriptor[i + 0] == '0' && hid_mouse_descriptor[i + 1] == 0x00 &&
hid_mouse_descriptor[i + 2] == '0' && hid_mouse_descriptor[i + 3] == 0x00) {
serial_number_offset = i;
break;
}
}
if (serial_number_offset == 0) { //未找到
return;
}
for (uint8_t i = 0; i < 24; i ++) { //共24位
hid_mouse_descriptor[serial_number_offset + i * 2] = uid_string[i];
}
}
void hid_mouse_init(uint8_t busid, uintptr_t reg_base)
{
static struct usbd_interface intf0;
fill_usb_descriptor_serial_number();
usbd_desc_register(busid, hid_mouse_descriptor);
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
usbd_add_endpoint(busid, &hid_mouse_in_ep); //添加键盘鼠标INT IN端点
usbd_initialize(busid, reg_base, usbd_event_handler);
}
void hid_mouse_send(uint8_t busid, uint8_t buttons, int8_t x, int8_t y, int8_t wheel)
{
static USB_MEM_ALIGNX uint8_t report[HID_MOUSE_INT_EP_SIZE];
memset(report, 0, HID_MOUSE_INT_EP_SIZE);
report[0] = buttons; //鼠标按键
report[1] = (uint8_t)x; //Delta x
report[2] = (uint8_t)y; //Delta y
report[3] = (uint8_t)wheel; //滚轮
hid_mouse_busy = 1;
int ret = usbd_ep_start_write(busid, HID_MOUSE_INT_EP, report, HID_MOUSE_INT_EP_SIZE);
if (ret < 0) {
return;
}
while (hid_mouse_busy == 1) {
__WFI();
}
}

View File

@ -0,0 +1,750 @@
/**
******************************************************************************
* @file startup_stm32h743xx.s
* @author MCD Application Team
* @brief STM32H743xx Devices vector table for GCC based toolchain.
* This module performs:
* - Set the initial SP
* - Set the initial PC == Reset_Handler,
* - Set the vector table entries with the exceptions ISR address
* - Branches to main in the C library (which eventually
* calls main()).
* After Reset the Cortex-M processor is in Thread mode,
* priority is Privileged, and the Stack is set to Main.
******************************************************************************
* @attention
*
* Copyright (c) 2017 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
.syntax unified
.cpu cortex-m7
.fpu softvfp
.thumb
.global g_pfnVectors
.global Default_Handler
/* start address for the initialization values of the .data section.
defined in linker script */
.word _sidata
/* start address for the .data section. defined in linker script */
.word _sdata
/* end address for the .data section. defined in linker script */
.word _edata
/* start address for the .bss section. defined in linker script */
.word _sbss
/* end address for the .bss section. defined in linker script */
.word _ebss
/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
/**
* @brief This is the code that gets called when the processor first
* starts execution following a reset event. Only the absolutely
* necessary set is performed, after which the application
* supplied main() routine is called.
* @param None
* @retval : None
*/
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
ldr sp, =_estack /* set stack pointer */
/* Call the clock system initialization function.*/
bl SystemInit
/* Copy the data segment initializers from flash to SRAM */
ldr r0, =_sdata
ldr r1, =_edata
ldr r2, =_sidata
movs r3, #0
b LoopCopyDataInit
CopyDataInit:
ldr r4, [r2, r3]
str r4, [r0, r3]
adds r3, r3, #4
LoopCopyDataInit:
adds r4, r0, r3
cmp r4, r1
bcc CopyDataInit
/* Zero fill the bss segment. */
ldr r2, =_sbss
ldr r4, =_ebss
movs r3, #0
b LoopFillZerobss
FillZerobss:
str r3, [r2]
adds r2, r2, #4
LoopFillZerobss:
cmp r2, r4
bcc FillZerobss
/* Call static constructors */
bl __libc_init_array
/* Call the application's entry point.*/
bl main
bx lr
.size Reset_Handler, .-Reset_Handler
/**
* @brief This is the code that gets called when the processor receives an
* unexpected interrupt. This simply enters an infinite loop, preserving
* the system state for examination by a debugger.
* @param None
* @retval None
*/
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler
/******************************************************************************
*
* The minimal vector table for a Cortex M. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
*******************************************************************************/
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
/* External Interrupts */
.word WWDG_IRQHandler /* Window WatchDog */
.word PVD_AVD_IRQHandler /* PVD/AVD through EXTI Line detection */
.word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */
.word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */
.word FLASH_IRQHandler /* FLASH */
.word RCC_IRQHandler /* RCC */
.word EXTI0_IRQHandler /* EXTI Line0 */
.word EXTI1_IRQHandler /* EXTI Line1 */
.word EXTI2_IRQHandler /* EXTI Line2 */
.word EXTI3_IRQHandler /* EXTI Line3 */
.word EXTI4_IRQHandler /* EXTI Line4 */
.word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */
.word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */
.word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */
.word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */
.word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */
.word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */
.word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */
.word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */
.word FDCAN1_IT0_IRQHandler /* FDCAN1 interrupt line 0 */
.word FDCAN2_IT0_IRQHandler /* FDCAN2 interrupt line 0 */
.word FDCAN1_IT1_IRQHandler /* FDCAN1 interrupt line 1 */
.word FDCAN2_IT1_IRQHandler /* FDCAN2 interrupt line 1 */
.word EXTI9_5_IRQHandler /* External Line[9:5]s */
.word TIM1_BRK_IRQHandler /* TIM1 Break interrupt */
.word TIM1_UP_IRQHandler /* TIM1 Update interrupt */
.word TIM1_TRG_COM_IRQHandler /* TIM1 Trigger and Commutation interrupt */
.word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
.word TIM2_IRQHandler /* TIM2 */
.word TIM3_IRQHandler /* TIM3 */
.word TIM4_IRQHandler /* TIM4 */
.word I2C1_EV_IRQHandler /* I2C1 Event */
.word I2C1_ER_IRQHandler /* I2C1 Error */
.word I2C2_EV_IRQHandler /* I2C2 Event */
.word I2C2_ER_IRQHandler /* I2C2 Error */
.word SPI1_IRQHandler /* SPI1 */
.word SPI2_IRQHandler /* SPI2 */
.word USART1_IRQHandler /* USART1 */
.word USART2_IRQHandler /* USART2 */
.word USART3_IRQHandler /* USART3 */
.word EXTI15_10_IRQHandler /* External Line[15:10]s */
.word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */
.word 0 /* Reserved */
.word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */
.word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */
.word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */
.word TIM8_CC_IRQHandler /* TIM8 Capture Compare */
.word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */
.word FMC_IRQHandler /* FMC */
.word SDMMC1_IRQHandler /* SDMMC1 */
.word TIM5_IRQHandler /* TIM5 */
.word SPI3_IRQHandler /* SPI3 */
.word UART4_IRQHandler /* UART4 */
.word UART5_IRQHandler /* UART5 */
.word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */
.word TIM7_IRQHandler /* TIM7 */
.word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */
.word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */
.word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */
.word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */
.word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */
.word ETH_IRQHandler /* Ethernet */
.word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */
.word FDCAN_CAL_IRQHandler /* FDCAN calibration unit interrupt*/
.word 0 /* Reserved */
.word 0 /* Reserved */
.word 0 /* Reserved */
.word 0 /* Reserved */
.word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */
.word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */
.word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */
.word USART6_IRQHandler /* USART6 */
.word I2C3_EV_IRQHandler /* I2C3 event */
.word I2C3_ER_IRQHandler /* I2C3 error */
.word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */
.word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */
.word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */
.word OTG_HS_IRQHandler /* USB OTG HS */
.word DCMI_IRQHandler /* DCMI */
.word 0 /* Reserved */
.word RNG_IRQHandler /* Rng */
.word FPU_IRQHandler /* FPU */
.word UART7_IRQHandler /* UART7 */
.word UART8_IRQHandler /* UART8 */
.word SPI4_IRQHandler /* SPI4 */
.word SPI5_IRQHandler /* SPI5 */
.word SPI6_IRQHandler /* SPI6 */
.word SAI1_IRQHandler /* SAI1 */
.word LTDC_IRQHandler /* LTDC */
.word LTDC_ER_IRQHandler /* LTDC error */
.word DMA2D_IRQHandler /* DMA2D */
.word SAI2_IRQHandler /* SAI2 */
.word QUADSPI_IRQHandler /* QUADSPI */
.word LPTIM1_IRQHandler /* LPTIM1 */
.word CEC_IRQHandler /* HDMI_CEC */
.word I2C4_EV_IRQHandler /* I2C4 Event */
.word I2C4_ER_IRQHandler /* I2C4 Error */
.word SPDIF_RX_IRQHandler /* SPDIF_RX */
.word OTG_FS_EP1_OUT_IRQHandler /* USB OTG FS End Point 1 Out */
.word OTG_FS_EP1_IN_IRQHandler /* USB OTG FS End Point 1 In */
.word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI */
.word OTG_FS_IRQHandler /* USB OTG FS */
.word DMAMUX1_OVR_IRQHandler /* DMAMUX1 Overrun interrupt */
.word HRTIM1_Master_IRQHandler /* HRTIM Master Timer global Interrupt */
.word HRTIM1_TIMA_IRQHandler /* HRTIM Timer A global Interrupt */
.word HRTIM1_TIMB_IRQHandler /* HRTIM Timer B global Interrupt */
.word HRTIM1_TIMC_IRQHandler /* HRTIM Timer C global Interrupt */
.word HRTIM1_TIMD_IRQHandler /* HRTIM Timer D global Interrupt */
.word HRTIM1_TIME_IRQHandler /* HRTIM Timer E global Interrupt */
.word HRTIM1_FLT_IRQHandler /* HRTIM Fault global Interrupt */
.word DFSDM1_FLT0_IRQHandler /* DFSDM Filter0 Interrupt */
.word DFSDM1_FLT1_IRQHandler /* DFSDM Filter1 Interrupt */
.word DFSDM1_FLT2_IRQHandler /* DFSDM Filter2 Interrupt */
.word DFSDM1_FLT3_IRQHandler /* DFSDM Filter3 Interrupt */
.word SAI3_IRQHandler /* SAI3 global Interrupt */
.word SWPMI1_IRQHandler /* Serial Wire Interface 1 global interrupt */
.word TIM15_IRQHandler /* TIM15 global Interrupt */
.word TIM16_IRQHandler /* TIM16 global Interrupt */
.word TIM17_IRQHandler /* TIM17 global Interrupt */
.word MDIOS_WKUP_IRQHandler /* MDIOS Wakeup Interrupt */
.word MDIOS_IRQHandler /* MDIOS global Interrupt */
.word JPEG_IRQHandler /* JPEG global Interrupt */
.word MDMA_IRQHandler /* MDMA global Interrupt */
.word 0 /* Reserved */
.word SDMMC2_IRQHandler /* SDMMC2 global Interrupt */
.word HSEM1_IRQHandler /* HSEM1 global Interrupt */
.word 0 /* Reserved */
.word ADC3_IRQHandler /* ADC3 global Interrupt */
.word DMAMUX2_OVR_IRQHandler /* DMAMUX Overrun interrupt */
.word BDMA_Channel0_IRQHandler /* BDMA Channel 0 global Interrupt */
.word BDMA_Channel1_IRQHandler /* BDMA Channel 1 global Interrupt */
.word BDMA_Channel2_IRQHandler /* BDMA Channel 2 global Interrupt */
.word BDMA_Channel3_IRQHandler /* BDMA Channel 3 global Interrupt */
.word BDMA_Channel4_IRQHandler /* BDMA Channel 4 global Interrupt */
.word BDMA_Channel5_IRQHandler /* BDMA Channel 5 global Interrupt */
.word BDMA_Channel6_IRQHandler /* BDMA Channel 6 global Interrupt */
.word BDMA_Channel7_IRQHandler /* BDMA Channel 7 global Interrupt */
.word COMP1_IRQHandler /* COMP1 global Interrupt */
.word LPTIM2_IRQHandler /* LP TIM2 global interrupt */
.word LPTIM3_IRQHandler /* LP TIM3 global interrupt */
.word LPTIM4_IRQHandler /* LP TIM4 global interrupt */
.word LPTIM5_IRQHandler /* LP TIM5 global interrupt */
.word LPUART1_IRQHandler /* LP UART1 interrupt */
.word 0 /* Reserved */
.word CRS_IRQHandler /* Clock Recovery Global Interrupt */
.word ECC_IRQHandler /* ECC diagnostic Global Interrupt */
.word SAI4_IRQHandler /* SAI4 global interrupt */
.word 0 /* Reserved */
.word 0 /* Reserved */
.word WAKEUP_PIN_IRQHandler /* Interrupt for all 6 wake-up pins */
.size g_pfnVectors, .-g_pfnVectors
/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/
.weak NMI_Handler
.thumb_set NMI_Handler,Default_Handler
.weak HardFault_Handler
.thumb_set HardFault_Handler,Default_Handler
.weak MemManage_Handler
.thumb_set MemManage_Handler,Default_Handler
.weak BusFault_Handler
.thumb_set BusFault_Handler,Default_Handler
.weak UsageFault_Handler
.thumb_set UsageFault_Handler,Default_Handler
.weak SVC_Handler
.thumb_set SVC_Handler,Default_Handler
.weak DebugMon_Handler
.thumb_set DebugMon_Handler,Default_Handler
.weak PendSV_Handler
.thumb_set PendSV_Handler,Default_Handler
.weak SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler
.weak WWDG_IRQHandler
.thumb_set WWDG_IRQHandler,Default_Handler
.weak PVD_AVD_IRQHandler
.thumb_set PVD_AVD_IRQHandler,Default_Handler
.weak TAMP_STAMP_IRQHandler
.thumb_set TAMP_STAMP_IRQHandler,Default_Handler
.weak RTC_WKUP_IRQHandler
.thumb_set RTC_WKUP_IRQHandler,Default_Handler
.weak FLASH_IRQHandler
.thumb_set FLASH_IRQHandler,Default_Handler
.weak RCC_IRQHandler
.thumb_set RCC_IRQHandler,Default_Handler
.weak EXTI0_IRQHandler
.thumb_set EXTI0_IRQHandler,Default_Handler
.weak EXTI1_IRQHandler
.thumb_set EXTI1_IRQHandler,Default_Handler
.weak EXTI2_IRQHandler
.thumb_set EXTI2_IRQHandler,Default_Handler
.weak EXTI3_IRQHandler
.thumb_set EXTI3_IRQHandler,Default_Handler
.weak EXTI4_IRQHandler
.thumb_set EXTI4_IRQHandler,Default_Handler
.weak DMA1_Stream0_IRQHandler
.thumb_set DMA1_Stream0_IRQHandler,Default_Handler
.weak DMA1_Stream1_IRQHandler
.thumb_set DMA1_Stream1_IRQHandler,Default_Handler
.weak DMA1_Stream2_IRQHandler
.thumb_set DMA1_Stream2_IRQHandler,Default_Handler
.weak DMA1_Stream3_IRQHandler
.thumb_set DMA1_Stream3_IRQHandler,Default_Handler
.weak DMA1_Stream4_IRQHandler
.thumb_set DMA1_Stream4_IRQHandler,Default_Handler
.weak DMA1_Stream5_IRQHandler
.thumb_set DMA1_Stream5_IRQHandler,Default_Handler
.weak DMA1_Stream6_IRQHandler
.thumb_set DMA1_Stream6_IRQHandler,Default_Handler
.weak ADC_IRQHandler
.thumb_set ADC_IRQHandler,Default_Handler
.weak FDCAN1_IT0_IRQHandler
.thumb_set FDCAN1_IT0_IRQHandler,Default_Handler
.weak FDCAN2_IT0_IRQHandler
.thumb_set FDCAN2_IT0_IRQHandler,Default_Handler
.weak FDCAN1_IT1_IRQHandler
.thumb_set FDCAN1_IT1_IRQHandler,Default_Handler
.weak FDCAN2_IT1_IRQHandler
.thumb_set FDCAN2_IT1_IRQHandler,Default_Handler
.weak EXTI9_5_IRQHandler
.thumb_set EXTI9_5_IRQHandler,Default_Handler
.weak TIM1_BRK_IRQHandler
.thumb_set TIM1_BRK_IRQHandler,Default_Handler
.weak TIM1_UP_IRQHandler
.thumb_set TIM1_UP_IRQHandler,Default_Handler
.weak TIM1_TRG_COM_IRQHandler
.thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler
.weak TIM1_CC_IRQHandler
.thumb_set TIM1_CC_IRQHandler,Default_Handler
.weak TIM2_IRQHandler
.thumb_set TIM2_IRQHandler,Default_Handler
.weak TIM3_IRQHandler
.thumb_set TIM3_IRQHandler,Default_Handler
.weak TIM4_IRQHandler
.thumb_set TIM4_IRQHandler,Default_Handler
.weak I2C1_EV_IRQHandler
.thumb_set I2C1_EV_IRQHandler,Default_Handler
.weak I2C1_ER_IRQHandler
.thumb_set I2C1_ER_IRQHandler,Default_Handler
.weak I2C2_EV_IRQHandler
.thumb_set I2C2_EV_IRQHandler,Default_Handler
.weak I2C2_ER_IRQHandler
.thumb_set I2C2_ER_IRQHandler,Default_Handler
.weak SPI1_IRQHandler
.thumb_set SPI1_IRQHandler,Default_Handler
.weak SPI2_IRQHandler
.thumb_set SPI2_IRQHandler,Default_Handler
.weak USART1_IRQHandler
.thumb_set USART1_IRQHandler,Default_Handler
.weak USART2_IRQHandler
.thumb_set USART2_IRQHandler,Default_Handler
.weak USART3_IRQHandler
.thumb_set USART3_IRQHandler,Default_Handler
.weak EXTI15_10_IRQHandler
.thumb_set EXTI15_10_IRQHandler,Default_Handler
.weak RTC_Alarm_IRQHandler
.thumb_set RTC_Alarm_IRQHandler,Default_Handler
.weak TIM8_BRK_TIM12_IRQHandler
.thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler
.weak TIM8_UP_TIM13_IRQHandler
.thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler
.weak TIM8_TRG_COM_TIM14_IRQHandler
.thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler
.weak TIM8_CC_IRQHandler
.thumb_set TIM8_CC_IRQHandler,Default_Handler
.weak DMA1_Stream7_IRQHandler
.thumb_set DMA1_Stream7_IRQHandler,Default_Handler
.weak FMC_IRQHandler
.thumb_set FMC_IRQHandler,Default_Handler
.weak SDMMC1_IRQHandler
.thumb_set SDMMC1_IRQHandler,Default_Handler
.weak TIM5_IRQHandler
.thumb_set TIM5_IRQHandler,Default_Handler
.weak SPI3_IRQHandler
.thumb_set SPI3_IRQHandler,Default_Handler
.weak UART4_IRQHandler
.thumb_set UART4_IRQHandler,Default_Handler
.weak UART5_IRQHandler
.thumb_set UART5_IRQHandler,Default_Handler
.weak TIM6_DAC_IRQHandler
.thumb_set TIM6_DAC_IRQHandler,Default_Handler
.weak TIM7_IRQHandler
.thumb_set TIM7_IRQHandler,Default_Handler
.weak DMA2_Stream0_IRQHandler
.thumb_set DMA2_Stream0_IRQHandler,Default_Handler
.weak DMA2_Stream1_IRQHandler
.thumb_set DMA2_Stream1_IRQHandler,Default_Handler
.weak DMA2_Stream2_IRQHandler
.thumb_set DMA2_Stream2_IRQHandler,Default_Handler
.weak DMA2_Stream3_IRQHandler
.thumb_set DMA2_Stream3_IRQHandler,Default_Handler
.weak DMA2_Stream4_IRQHandler
.thumb_set DMA2_Stream4_IRQHandler,Default_Handler
.weak ETH_IRQHandler
.thumb_set ETH_IRQHandler,Default_Handler
.weak ETH_WKUP_IRQHandler
.thumb_set ETH_WKUP_IRQHandler,Default_Handler
.weak FDCAN_CAL_IRQHandler
.thumb_set FDCAN_CAL_IRQHandler,Default_Handler
.weak DMA2_Stream5_IRQHandler
.thumb_set DMA2_Stream5_IRQHandler,Default_Handler
.weak DMA2_Stream6_IRQHandler
.thumb_set DMA2_Stream6_IRQHandler,Default_Handler
.weak DMA2_Stream7_IRQHandler
.thumb_set DMA2_Stream7_IRQHandler,Default_Handler
.weak USART6_IRQHandler
.thumb_set USART6_IRQHandler,Default_Handler
.weak I2C3_EV_IRQHandler
.thumb_set I2C3_EV_IRQHandler,Default_Handler
.weak I2C3_ER_IRQHandler
.thumb_set I2C3_ER_IRQHandler,Default_Handler
.weak OTG_HS_EP1_OUT_IRQHandler
.thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler
.weak OTG_HS_EP1_IN_IRQHandler
.thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler
.weak OTG_HS_WKUP_IRQHandler
.thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler
.weak OTG_HS_IRQHandler
.thumb_set OTG_HS_IRQHandler,Default_Handler
.weak DCMI_IRQHandler
.thumb_set DCMI_IRQHandler,Default_Handler
.weak RNG_IRQHandler
.thumb_set RNG_IRQHandler,Default_Handler
.weak FPU_IRQHandler
.thumb_set FPU_IRQHandler,Default_Handler
.weak UART7_IRQHandler
.thumb_set UART7_IRQHandler,Default_Handler
.weak UART8_IRQHandler
.thumb_set UART8_IRQHandler,Default_Handler
.weak SPI4_IRQHandler
.thumb_set SPI4_IRQHandler,Default_Handler
.weak SPI5_IRQHandler
.thumb_set SPI5_IRQHandler,Default_Handler
.weak SPI6_IRQHandler
.thumb_set SPI6_IRQHandler,Default_Handler
.weak SAI1_IRQHandler
.thumb_set SAI1_IRQHandler,Default_Handler
.weak LTDC_IRQHandler
.thumb_set LTDC_IRQHandler,Default_Handler
.weak LTDC_ER_IRQHandler
.thumb_set LTDC_ER_IRQHandler,Default_Handler
.weak DMA2D_IRQHandler
.thumb_set DMA2D_IRQHandler,Default_Handler
.weak SAI2_IRQHandler
.thumb_set SAI2_IRQHandler,Default_Handler
.weak QUADSPI_IRQHandler
.thumb_set QUADSPI_IRQHandler,Default_Handler
.weak LPTIM1_IRQHandler
.thumb_set LPTIM1_IRQHandler,Default_Handler
.weak CEC_IRQHandler
.thumb_set CEC_IRQHandler,Default_Handler
.weak I2C4_EV_IRQHandler
.thumb_set I2C4_EV_IRQHandler,Default_Handler
.weak I2C4_ER_IRQHandler
.thumb_set I2C4_ER_IRQHandler,Default_Handler
.weak SPDIF_RX_IRQHandler
.thumb_set SPDIF_RX_IRQHandler,Default_Handler
.weak OTG_FS_EP1_OUT_IRQHandler
.thumb_set OTG_FS_EP1_OUT_IRQHandler,Default_Handler
.weak OTG_FS_EP1_IN_IRQHandler
.thumb_set OTG_FS_EP1_IN_IRQHandler,Default_Handler
.weak OTG_FS_WKUP_IRQHandler
.thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler
.weak OTG_FS_IRQHandler
.thumb_set OTG_FS_IRQHandler,Default_Handler
.weak DMAMUX1_OVR_IRQHandler
.thumb_set DMAMUX1_OVR_IRQHandler,Default_Handler
.weak HRTIM1_Master_IRQHandler
.thumb_set HRTIM1_Master_IRQHandler,Default_Handler
.weak HRTIM1_TIMA_IRQHandler
.thumb_set HRTIM1_TIMA_IRQHandler,Default_Handler
.weak HRTIM1_TIMB_IRQHandler
.thumb_set HRTIM1_TIMB_IRQHandler,Default_Handler
.weak HRTIM1_TIMC_IRQHandler
.thumb_set HRTIM1_TIMC_IRQHandler,Default_Handler
.weak HRTIM1_TIMD_IRQHandler
.thumb_set HRTIM1_TIMD_IRQHandler,Default_Handler
.weak HRTIM1_TIME_IRQHandler
.thumb_set HRTIM1_TIME_IRQHandler,Default_Handler
.weak HRTIM1_FLT_IRQHandler
.thumb_set HRTIM1_FLT_IRQHandler,Default_Handler
.weak DFSDM1_FLT0_IRQHandler
.thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler
.weak DFSDM1_FLT1_IRQHandler
.thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler
.weak DFSDM1_FLT2_IRQHandler
.thumb_set DFSDM1_FLT2_IRQHandler,Default_Handler
.weak DFSDM1_FLT3_IRQHandler
.thumb_set DFSDM1_FLT3_IRQHandler,Default_Handler
.weak SAI3_IRQHandler
.thumb_set SAI3_IRQHandler,Default_Handler
.weak SWPMI1_IRQHandler
.thumb_set SWPMI1_IRQHandler,Default_Handler
.weak TIM15_IRQHandler
.thumb_set TIM15_IRQHandler,Default_Handler
.weak TIM16_IRQHandler
.thumb_set TIM16_IRQHandler,Default_Handler
.weak TIM17_IRQHandler
.thumb_set TIM17_IRQHandler,Default_Handler
.weak MDIOS_WKUP_IRQHandler
.thumb_set MDIOS_WKUP_IRQHandler,Default_Handler
.weak MDIOS_IRQHandler
.thumb_set MDIOS_IRQHandler,Default_Handler
.weak JPEG_IRQHandler
.thumb_set JPEG_IRQHandler,Default_Handler
.weak MDMA_IRQHandler
.thumb_set MDMA_IRQHandler,Default_Handler
.weak SDMMC2_IRQHandler
.thumb_set SDMMC2_IRQHandler,Default_Handler
.weak HSEM1_IRQHandler
.thumb_set HSEM1_IRQHandler,Default_Handler
.weak ADC3_IRQHandler
.thumb_set ADC3_IRQHandler,Default_Handler
.weak DMAMUX2_OVR_IRQHandler
.thumb_set DMAMUX2_OVR_IRQHandler,Default_Handler
.weak BDMA_Channel0_IRQHandler
.thumb_set BDMA_Channel0_IRQHandler,Default_Handler
.weak BDMA_Channel1_IRQHandler
.thumb_set BDMA_Channel1_IRQHandler,Default_Handler
.weak BDMA_Channel2_IRQHandler
.thumb_set BDMA_Channel2_IRQHandler,Default_Handler
.weak BDMA_Channel3_IRQHandler
.thumb_set BDMA_Channel3_IRQHandler,Default_Handler
.weak BDMA_Channel4_IRQHandler
.thumb_set BDMA_Channel4_IRQHandler,Default_Handler
.weak BDMA_Channel5_IRQHandler
.thumb_set BDMA_Channel5_IRQHandler,Default_Handler
.weak BDMA_Channel6_IRQHandler
.thumb_set BDMA_Channel6_IRQHandler,Default_Handler
.weak BDMA_Channel7_IRQHandler
.thumb_set BDMA_Channel7_IRQHandler,Default_Handler
.weak COMP1_IRQHandler
.thumb_set COMP1_IRQHandler,Default_Handler
.weak LPTIM2_IRQHandler
.thumb_set LPTIM2_IRQHandler,Default_Handler
.weak LPTIM3_IRQHandler
.thumb_set LPTIM3_IRQHandler,Default_Handler
.weak LPTIM4_IRQHandler
.thumb_set LPTIM4_IRQHandler,Default_Handler
.weak LPTIM5_IRQHandler
.thumb_set LPTIM5_IRQHandler,Default_Handler
.weak LPUART1_IRQHandler
.thumb_set LPUART1_IRQHandler,Default_Handler
.weak CRS_IRQHandler
.thumb_set CRS_IRQHandler,Default_Handler
.weak ECC_IRQHandler
.thumb_set ECC_IRQHandler,Default_Handler
.weak SAI4_IRQHandler
.thumb_set SAI4_IRQHandler,Default_Handler
.weak WAKEUP_PIN_IRQHandler
.thumb_set WAKEUP_PIN_IRQHandler,Default_Handler

Some files were not shown because too many files have changed in this diff Show More