rtt更新
This commit is contained in:
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "event_groups.h"
|
||||
#include "csh.h"
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_adb.h"
|
||||
#include "chry_ringbuffer.h"
|
||||
|
||||
static chry_ringbuffer_t shell_rb;
|
||||
static uint8_t mempool[1024];
|
||||
|
||||
#ifndef task_repl_PRIORITY
|
||||
#define task_repl_PRIORITY (configMAX_PRIORITIES - 4U)
|
||||
#endif
|
||||
|
||||
#ifndef task_exec_PRIORITY
|
||||
#define task_exec_PRIORITY (configMAX_PRIORITIES - 5U)
|
||||
#endif
|
||||
|
||||
static chry_shell_t csh;
|
||||
static volatile bool login = false;
|
||||
|
||||
static StaticTask_t task_buffer_repl;
|
||||
static StaticTask_t task_buffer_exec;
|
||||
|
||||
static StackType_t task_stack_repl[1024];
|
||||
static StackType_t task_stack_exec[1024];
|
||||
|
||||
static TaskHandle_t task_hdl_repl = NULL;
|
||||
static TaskHandle_t task_hdl_exec = NULL;
|
||||
|
||||
static EventGroupHandle_t event_hdl;
|
||||
static StaticEventGroup_t event_grp;
|
||||
|
||||
void usbd_adb_notify_shell_read(uint8_t *data, uint32_t len)
|
||||
{
|
||||
chry_ringbuffer_write(&shell_rb, data, len);
|
||||
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xEventGroupSetBitsFromISR(event_hdl, 0x10, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
void usbd_adb_notify_write_done(void)
|
||||
{
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xEventGroupSetBitsFromISR(event_hdl, 0x20, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
static uint16_t csh_sput_cb(chry_readline_t *rl, const void *data, uint16_t size)
|
||||
{
|
||||
(void)rl;
|
||||
|
||||
if (!usb_device_is_configured(0)) {
|
||||
return size;
|
||||
}
|
||||
|
||||
if (usbd_adb_can_write() && size) {
|
||||
usbd_abd_write(ADB_SHELL_LOALID, data, size);
|
||||
xEventGroupWaitBits(event_hdl, 0x20, pdTRUE, pdFALSE, portMAX_DELAY);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static uint16_t csh_sget_cb(chry_readline_t *rl, void *data, uint16_t size)
|
||||
{
|
||||
(void)rl;
|
||||
|
||||
return chry_ringbuffer_read(&shell_rb, data, size);
|
||||
}
|
||||
|
||||
static void wait_char(void)
|
||||
{
|
||||
EventBits_t event;
|
||||
wait:
|
||||
/* In order to lock the log from being disrupted , wait for REPL task execution to complete */
|
||||
event = xEventGroupWaitBits(event_hdl, (0x10 | 0x01 | 0x04), pdTRUE, pdFALSE, portMAX_DELAY);
|
||||
if ((event & 0x10) == 0) {
|
||||
if (event & 0x01) {
|
||||
chry_readline_erase_line(&csh.rl);
|
||||
xEventGroupSetBits(event_hdl, 0x02);
|
||||
}
|
||||
if (event & 0x04) {
|
||||
chry_readline_edit_refresh(&csh.rl);
|
||||
xEventGroupSetBits(event_hdl, 0x08);
|
||||
}
|
||||
|
||||
goto wait;
|
||||
}
|
||||
}
|
||||
|
||||
static void task_repl(void *param)
|
||||
{
|
||||
(void)param;
|
||||
int ret;
|
||||
volatile uint8_t *pexec = (void *)&csh.exec;
|
||||
|
||||
for (;;) {
|
||||
restart:
|
||||
if (login) {
|
||||
goto repl;
|
||||
} else {
|
||||
}
|
||||
|
||||
ret = csh_login(&csh);
|
||||
if (ret == 0) {
|
||||
login = true;
|
||||
} else if (ret == 1) {
|
||||
/*!< no enough char */
|
||||
wait_char();
|
||||
continue;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
repl:
|
||||
ret = chry_shell_task_repl(&csh);
|
||||
|
||||
if (ret == -1) {
|
||||
/*!< error */
|
||||
goto restart;
|
||||
} else if (ret == 1) {
|
||||
/*!< no enough char */
|
||||
wait_char();
|
||||
} else {
|
||||
/*!< restart */
|
||||
}
|
||||
|
||||
/*!< check flag */
|
||||
if (*pexec == CSH_STATUS_EXEC_DONE) {
|
||||
*pexec = CSH_STATUS_EXEC_IDLE;
|
||||
chry_readline_auto_refresh(&csh.rl, true);
|
||||
chry_readline_ignore(&csh.rl, false);
|
||||
chry_readline_edit_refresh(&csh.rl);
|
||||
}
|
||||
|
||||
if (login == false) {
|
||||
chry_readline_erase_line(&csh.rl);
|
||||
csh.rl.noblock = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void task_exec(void *param)
|
||||
{
|
||||
(void)param;
|
||||
|
||||
/*!< execute shell command */
|
||||
chry_shell_task_exec(&csh);
|
||||
|
||||
/*!< notify REPL task execute done */
|
||||
xEventGroupSetBits(event_hdl, 0x10);
|
||||
|
||||
/*!< wait for REPL task delete */
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
|
||||
int chry_shell_port_create_context(chry_shell_t *csh, int argc, const char **argv)
|
||||
{
|
||||
volatile TaskHandle_t *p_task_hdl_exec = (void *)&task_hdl_exec;
|
||||
(void)csh;
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
if (*p_task_hdl_exec != NULL) {
|
||||
vTaskDelete(*p_task_hdl_exec);
|
||||
}
|
||||
|
||||
*p_task_hdl_exec = xTaskCreateStatic(task_exec, "task_exec", 1024U, NULL, task_exec_PRIORITY, task_stack_exec, &task_buffer_exec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void chry_shell_port_default_handler(chry_shell_t *csh, int sig)
|
||||
{
|
||||
volatile uint8_t *pexec = (void *)&csh->exec;
|
||||
volatile TaskHandle_t *p_task_hdl_exec = (void *)&task_hdl_exec;
|
||||
|
||||
switch (sig) {
|
||||
case CSH_SIGINT:
|
||||
case CSH_SIGQUIT:
|
||||
case CSH_SIGKILL:
|
||||
case CSH_SIGTERM:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/*!< force delete task */
|
||||
if (*p_task_hdl_exec != NULL) {
|
||||
vTaskDelete(task_hdl_exec);
|
||||
*p_task_hdl_exec = NULL;
|
||||
}
|
||||
|
||||
switch (sig) {
|
||||
case CSH_SIGINT:
|
||||
csh->rl.sput(&csh->rl, "^SIGINT" CONFIG_CSH_NEWLINE, sizeof("^SIGINT" CONFIG_CSH_NEWLINE) - 1);
|
||||
break;
|
||||
case CSH_SIGQUIT:
|
||||
csh->rl.sput(&csh->rl, "^SIGQUIT" CONFIG_CSH_NEWLINE, sizeof("^SIGQUIT" CONFIG_CSH_NEWLINE) - 1);
|
||||
break;
|
||||
case CSH_SIGKILL:
|
||||
csh->rl.sput(&csh->rl, "^SIGKILL" CONFIG_CSH_NEWLINE, sizeof("^SIGKILL" CONFIG_CSH_NEWLINE) - 1);
|
||||
break;
|
||||
case CSH_SIGTERM:
|
||||
csh->rl.sput(&csh->rl, "^SIGTERM" CONFIG_CSH_NEWLINE, sizeof("^SIGTERM" CONFIG_CSH_NEWLINE) - 1);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
*pexec = CSH_STATUS_EXEC_IDLE;
|
||||
chry_readline_auto_refresh(&csh->rl, true);
|
||||
chry_readline_ignore(&csh->rl, false);
|
||||
chry_readline_edit_refresh(&csh->rl);
|
||||
}
|
||||
|
||||
int shell_init(bool need_login)
|
||||
{
|
||||
chry_shell_init_t csh_init;
|
||||
|
||||
if (chry_ringbuffer_init(&shell_rb, mempool, sizeof(mempool))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (need_login) {
|
||||
login = false;
|
||||
} else {
|
||||
login = true;
|
||||
}
|
||||
|
||||
/*!< I/O callback */
|
||||
csh_init.sput = csh_sput_cb;
|
||||
csh_init.sget = csh_sget_cb;
|
||||
|
||||
#if defined(CONFIG_CSH_SYMTAB) && CONFIG_CSH_SYMTAB
|
||||
extern const int __fsymtab_start;
|
||||
extern const int __fsymtab_end;
|
||||
extern const int __vsymtab_start;
|
||||
extern const int __vsymtab_end;
|
||||
|
||||
/*!< get table from ld symbol */
|
||||
csh_init.command_table_beg = &__fsymtab_start;
|
||||
csh_init.command_table_end = &__fsymtab_end;
|
||||
csh_init.variable_table_beg = &__vsymtab_start;
|
||||
csh_init.variable_table_end = &__vsymtab_end;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CSH_PROMPTEDIT) && CONFIG_CSH_PROMPTEDIT
|
||||
static char csh_prompt_buffer[128];
|
||||
|
||||
/*!< set prompt buffer */
|
||||
csh_init.prompt_buffer = csh_prompt_buffer;
|
||||
csh_init.prompt_buffer_size = sizeof(csh_prompt_buffer);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CSH_HISTORY) && CONFIG_CSH_HISTORY
|
||||
static char csh_history_buffer[128];
|
||||
|
||||
/*!< set history buffer */
|
||||
csh_init.history_buffer = csh_history_buffer;
|
||||
csh_init.history_buffer_size = sizeof(csh_history_buffer);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CSH_LNBUFF_STATIC) && CONFIG_CSH_LNBUFF_STATIC
|
||||
static char csh_line_buffer[128];
|
||||
|
||||
/*!< set linebuffer */
|
||||
csh_init.line_buffer = csh_line_buffer;
|
||||
csh_init.line_buffer_size = sizeof(csh_line_buffer);
|
||||
#endif
|
||||
|
||||
csh_init.uid = 0;
|
||||
csh_init.user[0] = "cherry";
|
||||
|
||||
/*!< The port hash function is required,
|
||||
and the strcmp attribute is used weakly by default,
|
||||
int chry_shell_port_hash_strcmp(const char *hash, const char *str); */
|
||||
csh_init.hash[0] = "12345678"; /*!< If there is no password, set to NULL */
|
||||
csh_init.host = "cherryadb";
|
||||
csh_init.user_data = NULL;
|
||||
|
||||
int ret = chry_shell_init(&csh, &csh_init);
|
||||
if (ret) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
task_hdl_exec = NULL;
|
||||
event_hdl = xEventGroupCreateStatic(&event_grp);
|
||||
task_hdl_repl = xTaskCreateStatic(task_repl, "task_repl", 1024U, NULL, task_repl_PRIORITY, task_stack_repl, &task_buffer_repl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void shell_lock(void)
|
||||
{
|
||||
xEventGroupSetBits(event_hdl, 0x01);
|
||||
xEventGroupWaitBits(event_hdl, 0x02, pdTRUE, pdTRUE, portMAX_DELAY);
|
||||
}
|
||||
|
||||
void shell_unlock(void)
|
||||
{
|
||||
xEventGroupSetBits(event_hdl, 0x04);
|
||||
xEventGroupWaitBits(event_hdl, 0x08, pdTRUE, pdTRUE, portMAX_DELAY);
|
||||
}
|
||||
|
||||
static int csh_exit(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
usbd_adb_close(ADB_SHELL_LOALID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
CSH_SCMD_EXPORT_ALIAS(csh_exit, exit, );
|
||||
|
||||
#define __ENV_PATH "/sbin:/bin"
|
||||
const char ENV_PATH[] = __ENV_PATH;
|
||||
CSH_RVAR_EXPORT(ENV_PATH, PATH, sizeof(__ENV_PATH));
|
||||
|
||||
#define __ENV_ZERO ""
|
||||
const char ENV_ZERO[] = __ENV_ZERO;
|
||||
CSH_RVAR_EXPORT(ENV_ZERO, ZERO, sizeof(__ENV_ZERO));
|
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_adb.h"
|
||||
|
||||
/*!< endpoint address */
|
||||
#define WINUSB_IN_EP 0x81
|
||||
#define WINUSB_OUT_EP 0x02
|
||||
|
||||
#define USBD_VID 0xFFFF
|
||||
#define USBD_PID 0xFFFF
|
||||
#define USBD_MAX_POWER 100
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
/*!< config descriptor size */
|
||||
#define USB_CONFIG_SIZE (9 + 9 + 7 + 7)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define WINUSB_MAX_MPS 512
|
||||
#else
|
||||
#define WINUSB_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
#define WCID_VENDOR_CODE 0x17
|
||||
#define ADB_INTF_NUM 0
|
||||
|
||||
__ALIGN_BEGIN const uint8_t WCID_StringDescriptor_MSOS[18] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// MS OS string descriptor
|
||||
///////////////////////////////////////
|
||||
0x12, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
/* MSFT100 */
|
||||
'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, /* wcChar_7 */
|
||||
'1', 0x00, '0', 0x00, '0', 0x00, /* wcChar_7 */
|
||||
WCID_VENDOR_CODE, /* bVendorCode */
|
||||
0x00, /* bReserved */
|
||||
};
|
||||
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[40] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// WCID descriptor
|
||||
///////////////////////////////////////
|
||||
0x28, 0x00, 0x00, 0x00, /* dwLength */
|
||||
0x00, 0x01, /* bcdVersion */
|
||||
0x04, 0x00, /* wIndex */
|
||||
0x01, /* bCount */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_7 */
|
||||
|
||||
///////////////////////////////////////
|
||||
/// WCID function descriptor
|
||||
///////////////////////////////////////
|
||||
ADB_INTF_NUM, /* bFirstInterfaceNumber */
|
||||
0x01, /* bReserved */
|
||||
/* Compatible ID */
|
||||
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, /* cCID_8: WINUSB */
|
||||
/* */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
|
||||
};
|
||||
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_IF0_WCIDProperties[142] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// WCID property descriptor
|
||||
///////////////////////////////////////
|
||||
0x8e, 0x00, 0x00, 0x00, /* dwLength */
|
||||
0x00, 0x01, /* bcdVersion */
|
||||
0x05, 0x00, /* wIndex */
|
||||
0x01, 0x00, /* wCount */
|
||||
|
||||
///////////////////////////////////////
|
||||
/// registry propter descriptor
|
||||
///////////////////////////////////////
|
||||
0x84, 0x00, 0x00, 0x00, /* dwSize */
|
||||
0x01, 0x00, 0x00, 0x00, /* dwPropertyDataType */
|
||||
0x28, 0x00, /* wPropertyNameLength */
|
||||
/* DeviceInterfaceGUID */
|
||||
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, /* wcName_20 */
|
||||
'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, /* wcName_20 */
|
||||
't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, /* wcName_20 */
|
||||
'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, /* wcName_20 */
|
||||
'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, /* wcName_20 */
|
||||
0x4e, 0x00, 0x00, 0x00, /* dwPropertyDataLength */
|
||||
/* {1D4B2365-4749-48EA-B38A-7C6FDDDD7E26} */
|
||||
'{', 0x00, '1', 0x00, 'D', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'B', 0x00, '2', 0x00, '3', 0x00, '6', 0x00, /* wcData_39 */
|
||||
'5', 0x00, '-', 0x00, '4', 0x00, '7', 0x00, /* wcData_39 */
|
||||
'4', 0x00, '9', 0x00, '-', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'8', 0x00, 'E', 0x00, 'A', 0x00, '-', 0x00, /* wcData_39 */
|
||||
'B', 0x00, '3', 0x00, '8', 0x00, 'A', 0x00, /* wcData_39 */
|
||||
'-', 0x00, '7', 0x00, 'C', 0x00, '6', 0x00, /* wcData_39 */
|
||||
'F', 0x00, 'D', 0x00, 'D', 0x00, 'D', 0x00, /* wcData_39 */
|
||||
'D', 0x00, '7', 0x00, 'E', 0x00, '2', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '}', 0x00, 0x00, 0x00, /* wcData_39 */
|
||||
};
|
||||
|
||||
const uint8_t *WINUSB_IFx_WCIDProperties[] = {
|
||||
WINUSB_IF0_WCIDProperties,
|
||||
};
|
||||
|
||||
struct usb_msosv1_descriptor msosv1_desc = {
|
||||
.string = WCID_StringDescriptor_MSOS,
|
||||
.vendor_code = WCID_VENDOR_CODE,
|
||||
.compat_id = WINUSB_WCIDDescriptor,
|
||||
.comp_id_property = WINUSB_IFx_WCIDProperties,
|
||||
};
|
||||
|
||||
/*!< global descriptor */
|
||||
static const uint8_t adb_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
ADB_DESCRIPTOR_INIT(ADB_INTF_NUM, WINUSB_IN_EP, WINUSB_OUT_EP, WINUSB_MAX_MPS),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
///////////////////////////////////////
|
||||
/// string1 descriptor
|
||||
///////////////////////////////////////
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string2 descriptor
|
||||
///////////////////////////////////////
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'A', 0x00, /* wcChar6 */
|
||||
'D', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string3 descriptor
|
||||
///////////////////////////////////////
|
||||
0x1C, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'A', 0x00, /* wcChar6 */
|
||||
'D', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
'2', 0x00, /* wcChar9 */
|
||||
'0', 0x00, /* wcChar10 */
|
||||
'2', 0x00, /* wcChar11 */
|
||||
'4', 0x00, /* wcChar12 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x02,
|
||||
0x02,
|
||||
0x01,
|
||||
0x40,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
};
|
||||
|
||||
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:
|
||||
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct usbd_interface intf0;
|
||||
|
||||
extern int shell_init(bool need_login);
|
||||
void cherryadb_init(uint8_t busid, uint32_t reg_base)
|
||||
{
|
||||
/* default password is : 12345678 */
|
||||
/* shell_init() must be called in-task */
|
||||
if (0 != shell_init(false)) {
|
||||
/* shell failed to be initialized */
|
||||
printf("Failed to initialize shell\r\n");
|
||||
for (;;) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
usbd_desc_register(busid, adb_descriptor);
|
||||
usbd_add_interface(busid, usbd_adb_init_intf(busid, &intf0, WINUSB_IN_EP, WINUSB_OUT_EP));
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
}
|
@@ -144,7 +144,7 @@ const uint8_t audio_v1_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -212,7 +212,7 @@ struct audio_entity_info audio_entity_table[] = {
|
||||
.ep = AUDIO_IN_EP },
|
||||
};
|
||||
|
||||
void audio_v1_init(uint8_t busid, uint32_t reg_base)
|
||||
void audio_v1_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, audio_v1_descriptor);
|
||||
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 1));
|
||||
|
@@ -139,7 +139,7 @@ const uint8_t audio_v1_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -238,7 +238,7 @@ struct audio_entity_info audio_entity_table[] = {
|
||||
.ep = AUDIO_OUT_EP },
|
||||
};
|
||||
|
||||
void audio_v1_init(uint8_t busid, uint32_t reg_base)
|
||||
void audio_v1_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, audio_v1_descriptor);
|
||||
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 2));
|
||||
|
@@ -149,7 +149,7 @@ const uint8_t audio_v2_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -229,7 +229,7 @@ struct audio_entity_info audio_entity_table[] = {
|
||||
.ep = AUDIO_IN_EP },
|
||||
};
|
||||
|
||||
void audio_v2_init(uint8_t busid, uint32_t reg_base)
|
||||
void audio_v2_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, audio_v2_descriptor);
|
||||
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
|
||||
|
@@ -196,7 +196,7 @@ uint8_t audio_v2_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -346,7 +346,7 @@ struct audio_entity_info audio_entity_table[] = {
|
||||
.ep = AUDIO_IN_EP },
|
||||
};
|
||||
|
||||
void audio_v2_init(uint8_t busid, uint32_t reg_base)
|
||||
void audio_v2_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, audio_v2_descriptor);
|
||||
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 4));
|
||||
|
@@ -149,7 +149,7 @@ const uint8_t audio_v2_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -247,7 +247,7 @@ struct audio_entity_info audio_entity_table[] = {
|
||||
.ep = AUDIO_OUT_EP },
|
||||
};
|
||||
|
||||
void audio_v2_init(uint8_t busid, uint32_t reg_base)
|
||||
void audio_v2_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, audio_v2_descriptor);
|
||||
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
|
||||
|
@@ -0,0 +1,463 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
* Copyright (c) 2024, Egahp
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "bootuf2.h"
|
||||
#include "usbd_core.h"
|
||||
|
||||
char file_INFO[] = {
|
||||
"CherryUSB UF2 BOOT\r\n"
|
||||
"Model: " CONFIG_PRODUCT "\r\n"
|
||||
"Board-ID: " CONFIG_BOARD "\r\n"
|
||||
};
|
||||
|
||||
const char file_IDEX[] = {
|
||||
"<!doctype html>\n"
|
||||
"<html>"
|
||||
"<body>"
|
||||
"<script>\n"
|
||||
"location.replace(\"" CONFIG_BOOTUF2_INDEX_URL "\");\n"
|
||||
"</script>"
|
||||
"</body>"
|
||||
"</html>\n"
|
||||
};
|
||||
|
||||
const char file_JOIN[] = {
|
||||
"<!doctype html>\n"
|
||||
"<html>"
|
||||
"<body>"
|
||||
"<script>\n"
|
||||
"location.replace(\"" CONFIG_BOOTUF2_JOIN_URL "\");\n"
|
||||
"</script>"
|
||||
"</body>"
|
||||
"</html>\n"
|
||||
};
|
||||
|
||||
const char file_ID__[12] = BOOTUF2_FAMILYID_ARRAY;
|
||||
|
||||
static struct bootuf2_FILE files[] = {
|
||||
[0] = { .Name = file_ID__, .Content = NULL, .FileSize = 0 },
|
||||
[1] = { .Name = "INFO_UF2TXT", .Content = file_INFO, .FileSize = sizeof(file_INFO) - 1 },
|
||||
[2] = { .Name = "INDEX HTM", .Content = file_IDEX, .FileSize = sizeof(file_IDEX) - 1 },
|
||||
[3] = { .Name = "JOIN HTM", .Content = file_JOIN, .FileSize = sizeof(file_JOIN) - 1 },
|
||||
};
|
||||
|
||||
struct bootuf2_data {
|
||||
const struct bootuf2_DBR *const DBR;
|
||||
struct bootuf2_STATE *const STATE;
|
||||
uint8_t *const fbuff;
|
||||
uint8_t *const erase;
|
||||
size_t page_count;
|
||||
uint8_t *const cache;
|
||||
const size_t cache_size;
|
||||
uint32_t cached_address;
|
||||
size_t cached_bytes;
|
||||
};
|
||||
|
||||
/*!< define DBRs */
|
||||
static const struct bootuf2_DBR bootuf2_DBR = {
|
||||
.JMPInstruction = { 0xEB, 0x3C, 0x90 },
|
||||
.OEM = "UF2 UF2 ",
|
||||
.BPB = {
|
||||
.BytesPerSector = CONFIG_BOOTUF2_SECTOR_SIZE,
|
||||
.SectorsPerCluster = CONFIG_BOOTUF2_SECTOR_PER_CLUSTER,
|
||||
.ReservedSectors = CONFIG_BOOTUF2_SECTOR_RESERVED,
|
||||
.NumberOfFAT = CONFIG_BOOTUF2_NUM_OF_FAT,
|
||||
.RootEntries = CONFIG_BOOTUF2_ROOT_ENTRIES,
|
||||
.Sectors = (BOOTUF2_SECTORS(0) > 0xFFFF) ? 0 : BOOTUF2_SECTORS(0),
|
||||
.MediaDescriptor = 0xF8,
|
||||
.SectorsPerFAT = BOOTUF2_SECTORS_PER_FAT(0),
|
||||
.SectorsPerTrack = 1,
|
||||
.Heads = 1,
|
||||
.HiddenSectors = 0,
|
||||
.SectorsOver32MB = (BOOTUF2_SECTORS(0) > 0xFFFF) ? BOOTUF2_SECTORS(0) : 0,
|
||||
.BIOSDrive = 0x80,
|
||||
.Reserved = 0,
|
||||
.ExtendBootSignature = 0x29,
|
||||
.VolumeSerialNumber = 0x00420042,
|
||||
.VolumeLabel = "CHERRYUF2",
|
||||
.FileSystem = "FAT16 ",
|
||||
},
|
||||
};
|
||||
|
||||
/*!< define mask */
|
||||
static uint8_t __attribute__((aligned(4))) bootuf2_mask[BOOTUF2_BLOCKSMAX / 8 + 1] = { 0 };
|
||||
|
||||
/*!< define state */
|
||||
static struct bootuf2_STATE bootuf2_STATE = {
|
||||
.NumberOfBlock = 0,
|
||||
.NumberOfWritten = 0,
|
||||
.Mask = bootuf2_mask,
|
||||
.Enable = 1,
|
||||
};
|
||||
|
||||
/*!< define flash cache */
|
||||
static uint8_t __attribute__((aligned(4))) bootuf2_disk_cache[CONFIG_BOOTUF2_CACHE_SIZE];
|
||||
|
||||
/*!< define flash buff */
|
||||
static uint8_t __attribute__((aligned(4))) bootuf2_disk_fbuff[256];
|
||||
|
||||
/*!< define erase flag buff */
|
||||
static uint8_t __attribute__((aligned(4))) bootuf2_disk_erase[BOOTUF2_DIVCEIL(CONFIG_BOOTUF2_PAGE_COUNTMAX, 8)];
|
||||
|
||||
/*!< define disk */
|
||||
static struct bootuf2_data bootuf2_disk = {
|
||||
.DBR = &bootuf2_DBR,
|
||||
.STATE = &bootuf2_STATE,
|
||||
.fbuff = bootuf2_disk_fbuff,
|
||||
.erase = bootuf2_disk_erase,
|
||||
.cache = bootuf2_disk_cache,
|
||||
.cache_size = sizeof(bootuf2_disk_cache),
|
||||
};
|
||||
|
||||
static void fname_copy(char *dst, char const *src, uint16_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
if (*src)
|
||||
*dst++ = *src++;
|
||||
else
|
||||
*dst++ = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
static void fcalculate_cluster(struct bootuf2_data *ctx)
|
||||
{
|
||||
/*!< init files cluster */
|
||||
uint16_t cluster_beg = 2;
|
||||
for (int i = 0; i < ARRAY_SIZE(files); i++) {
|
||||
files[i].ClusterBeg = cluster_beg;
|
||||
files[i].ClusterEnd = -1 + cluster_beg +
|
||||
BOOTUF2_DIVCEIL(files[i].FileSize,
|
||||
ctx->DBR->BPB.BytesPerSector *
|
||||
ctx->DBR->BPB.SectorsPerCluster);
|
||||
cluster_beg = files[i].ClusterEnd + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int ffind_by_cluster(uint32_t cluster)
|
||||
{
|
||||
if (cluster >= 0xFFF0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(files); i++) {
|
||||
if ((files[i].ClusterBeg <= cluster) &&
|
||||
(cluster <= files[i].ClusterEnd)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool bootuf2block_check_writable(struct bootuf2_STATE *STATE,
|
||||
struct bootuf2_BLOCK *uf2, uint32_t block_max)
|
||||
{
|
||||
if (uf2->NumberOfBlock) {
|
||||
if (uf2->BlockIndex < block_max) {
|
||||
uint8_t mask = 1 << (uf2->BlockIndex % 8);
|
||||
uint32_t pos = uf2->BlockIndex / 8;
|
||||
|
||||
if ((STATE->Mask[pos] & mask) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void bootuf2block_state_update(struct bootuf2_STATE *STATE,
|
||||
struct bootuf2_BLOCK *uf2, uint32_t block_max)
|
||||
{
|
||||
if (uf2->NumberOfBlock) {
|
||||
if (STATE->NumberOfBlock != uf2->NumberOfBlock) {
|
||||
if ((uf2->NumberOfBlock >= BOOTUF2_BLOCKSMAX) ||
|
||||
STATE->NumberOfBlock) {
|
||||
/*!< uf2 block only can be update once */
|
||||
/*!< this will cause never auto reboot */
|
||||
STATE->NumberOfBlock = 0xffffffff;
|
||||
} else {
|
||||
STATE->NumberOfBlock = uf2->NumberOfBlock;
|
||||
}
|
||||
}
|
||||
|
||||
if (uf2->BlockIndex < block_max) {
|
||||
uint8_t mask = 1 << (uf2->BlockIndex % 8);
|
||||
uint32_t pos = uf2->BlockIndex / 8;
|
||||
|
||||
if ((STATE->Mask[pos] & mask) == 0) {
|
||||
STATE->Mask[pos] |= mask;
|
||||
STATE->NumberOfWritten++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
USB_LOG_DBG("UF2 block total %d written %d index %d\r\n",
|
||||
uf2->NumberOfBlock, STATE->NumberOfWritten, uf2->BlockIndex);
|
||||
}
|
||||
|
||||
static bool bootuf2block_state_check(struct bootuf2_STATE *STATE)
|
||||
{
|
||||
return (STATE->NumberOfWritten >= STATE->NumberOfBlock) &&
|
||||
STATE->NumberOfBlock;
|
||||
}
|
||||
|
||||
static int bootuf2_flash_flush(struct bootuf2_data *ctx)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (ctx->cached_bytes == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = bootuf2_flash_write(ctx->cached_address, ctx->cache, ctx->cached_bytes);
|
||||
|
||||
if (err) {
|
||||
USB_LOG_ERR("UF2 slot flash write error %d at offset %08lx len %d\r\n",
|
||||
err, ctx->cached_address, ctx->cached_bytes);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->cached_bytes = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bootuf2_flash_write_internal(struct bootuf2_data *ctx, struct bootuf2_BLOCK *uf2)
|
||||
{
|
||||
/*!< 1.cache not empty and address not continue */
|
||||
/*!< 2.cache full */
|
||||
if ((ctx->cached_bytes && ((ctx->cached_address + ctx->cached_bytes) != uf2->TargetAddress)) ||
|
||||
(ctx->cached_bytes == ctx->cache_size)) {
|
||||
int err = bootuf2_flash_flush(ctx);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
/*!< write len always is 256, cache_size always is a multiple of 256 */
|
||||
memcpy(ctx->cache + ctx->cached_bytes, uf2->Data, uf2->PayloadSize);
|
||||
|
||||
ctx->cached_address = uf2->TargetAddress - ctx->cached_bytes;
|
||||
ctx->cached_bytes += uf2->PayloadSize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bootuf2_init(void)
|
||||
{
|
||||
struct bootuf2_data *ctx;
|
||||
|
||||
ctx = &bootuf2_disk;
|
||||
|
||||
fcalculate_cluster(ctx);
|
||||
|
||||
ctx->cached_bytes = 0;
|
||||
ctx->cached_address = 0;
|
||||
}
|
||||
|
||||
int boot2uf2_read_sector(uint32_t start_sector, uint8_t *buff, uint32_t sector_count)
|
||||
{
|
||||
struct bootuf2_data *ctx;
|
||||
|
||||
ctx = &bootuf2_disk;
|
||||
|
||||
while (sector_count) {
|
||||
memset(buff, 0, ctx->DBR->BPB.BytesPerSector);
|
||||
|
||||
uint32_t sector_relative = start_sector;
|
||||
|
||||
/*!< DBR sector */
|
||||
if (start_sector == BOOTUF2_SECTOR_DBR_END) {
|
||||
memcpy(buff, ctx->DBR, sizeof(struct bootuf2_DBR));
|
||||
buff[510] = 0x55;
|
||||
buff[511] = 0xaa;
|
||||
}
|
||||
/*!< FAT sector */
|
||||
else if (start_sector < BOOTUF2_SECTOR_FAT_END(ctx->DBR)) {
|
||||
uint16_t *buff16 = (uint16_t *)buff;
|
||||
|
||||
sector_relative -= BOOTUF2_SECTOR_RSVD_END(ctx->DBR);
|
||||
|
||||
/*!< Perform the same operation on all FAT tables */
|
||||
while (sector_relative >= ctx->DBR->BPB.SectorsPerFAT) {
|
||||
sector_relative -= ctx->DBR->BPB.SectorsPerFAT;
|
||||
}
|
||||
|
||||
uint16_t cluster_unused = files[ARRAY_SIZE(files) - 1].ClusterEnd + 1;
|
||||
uint16_t cluster_absolute_first = sector_relative *
|
||||
BOOTUF2_FAT16_PER_SECTOR(ctx->DBR);
|
||||
|
||||
/*!< cluster used link to chain, or unsed */
|
||||
for (uint16_t i = 0, cluster_absolute = cluster_absolute_first;
|
||||
i < BOOTUF2_FAT16_PER_SECTOR(ctx->DBR);
|
||||
i++, cluster_absolute++) {
|
||||
if (cluster_absolute >= cluster_unused)
|
||||
buff16[i] = 0;
|
||||
else
|
||||
buff16[i] = cluster_absolute + 1;
|
||||
}
|
||||
|
||||
/*!< cluster 0 and 1 */
|
||||
if (sector_relative == 0) {
|
||||
buff[0] = ctx->DBR->BPB.MediaDescriptor;
|
||||
buff[1] = 0xff;
|
||||
buff16[1] = 0xffff;
|
||||
}
|
||||
|
||||
/*!< cluster end of file */
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(files); i++) {
|
||||
uint16_t cluster_file_last = files[i].ClusterEnd;
|
||||
|
||||
if (cluster_file_last >= cluster_absolute_first) {
|
||||
uint16_t idx = cluster_file_last - cluster_absolute_first;
|
||||
if (idx < BOOTUF2_FAT16_PER_SECTOR(ctx->DBR)) {
|
||||
buff16[idx] = 0xffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*!< root entries */
|
||||
else if (start_sector < BOOTUF2_SECTOR_ROOT_END(ctx->DBR)) {
|
||||
sector_relative -= BOOTUF2_SECTOR_FAT_END(ctx->DBR);
|
||||
|
||||
struct bootuf2_ENTRY *ent = (void *)buff;
|
||||
int remain_entries = BOOTUF2_ENTRY_PER_SECTOR(ctx->DBR);
|
||||
|
||||
uint32_t file_index_first;
|
||||
|
||||
/*!< volume label entry */
|
||||
if (sector_relative == 0) {
|
||||
fname_copy(ent->Name, (char const *)ctx->DBR->BPB.VolumeLabel, 11);
|
||||
ent->Attribute = 0x28;
|
||||
ent++;
|
||||
remain_entries--;
|
||||
file_index_first = 0;
|
||||
} else {
|
||||
/*!< -1 to account for volume label in first sector */
|
||||
file_index_first = sector_relative * BOOTUF2_ENTRY_PER_SECTOR(ctx->DBR) - 1;
|
||||
}
|
||||
|
||||
for (uint32_t idx = file_index_first;
|
||||
(remain_entries > 0) && (idx < ARRAY_SIZE(files));
|
||||
idx++, ent++) {
|
||||
const uint32_t cluster_beg = files[idx].ClusterBeg;
|
||||
|
||||
const struct bootuf2_FILE *f = &files[idx];
|
||||
|
||||
if ((0 == f->FileSize) &&
|
||||
(0 != idx)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fname_copy(ent->Name, f->Name, 11);
|
||||
ent->Attribute = 0x05;
|
||||
ent->CreateTimeTeenth = BOOTUF2_SECONDS_INT % 2 * 100;
|
||||
ent->CreateTime = BOOTUF2_DOS_TIME;
|
||||
ent->CreateDate = BOOTUF2_DOS_DATE;
|
||||
ent->LastAccessDate = BOOTUF2_DOS_DATE;
|
||||
ent->FirstClustH16 = cluster_beg >> 16;
|
||||
ent->UpdateTime = BOOTUF2_DOS_TIME;
|
||||
ent->UpdateDate = BOOTUF2_DOS_DATE;
|
||||
ent->FirstClustL16 = cluster_beg & 0xffff;
|
||||
ent->FileSize = f->FileSize;
|
||||
}
|
||||
}
|
||||
/*!< data */
|
||||
else if (start_sector < BOOTUF2_SECTOR_DATA_END(ctx->DBR)) {
|
||||
sector_relative -= BOOTUF2_SECTOR_ROOT_END(ctx->DBR);
|
||||
|
||||
int fid = ffind_by_cluster(2 + sector_relative / ctx->DBR->BPB.SectorsPerCluster);
|
||||
|
||||
if (fid >= 0) {
|
||||
const struct bootuf2_FILE *f = &files[fid];
|
||||
|
||||
uint32_t sector_relative_file =
|
||||
sector_relative -
|
||||
(files[fid].ClusterBeg - 2) * ctx->DBR->BPB.SectorsPerCluster;
|
||||
|
||||
size_t fcontent_offset = sector_relative_file * ctx->DBR->BPB.BytesPerSector;
|
||||
size_t fcontent_length = f->FileSize;
|
||||
|
||||
if (fcontent_length > fcontent_offset) {
|
||||
const void *src = (void *)((uint8_t *)(f->Content) + fcontent_offset);
|
||||
size_t copy_size = fcontent_length - fcontent_offset;
|
||||
|
||||
if (copy_size > ctx->DBR->BPB.BytesPerSector) {
|
||||
copy_size = ctx->DBR->BPB.BytesPerSector;
|
||||
}
|
||||
|
||||
memcpy(buff, src, copy_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*!< unknown sector, ignore */
|
||||
|
||||
start_sector++;
|
||||
sector_count--;
|
||||
buff += ctx->DBR->BPB.BytesPerSector;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bootuf2_write_sector(uint32_t start_sector, const uint8_t *buff, uint32_t sector_count)
|
||||
{
|
||||
struct bootuf2_data *ctx;
|
||||
|
||||
ctx = &bootuf2_disk;
|
||||
|
||||
while (sector_count) {
|
||||
struct bootuf2_BLOCK *uf2 = (void *)buff;
|
||||
|
||||
if (!((uf2->MagicStart0 == BOOTUF2_MAGIC_START0) &&
|
||||
(uf2->MagicStart1 == BOOTUF2_MAGIC_START1) &&
|
||||
(uf2->MagicEnd == BOOTUF2_MAGIC_END) &&
|
||||
(uf2->Flags & BOOTUF2_FLAG_FAMILID_PRESENT) &&
|
||||
!(uf2->Flags & BOOTUF2_FLAG_NOT_MAIN_FLASH))) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uf2->FamilyID == CONFIG_BOOTUF2_FAMILYID) {
|
||||
if (bootuf2block_check_writable(ctx->STATE, uf2, CONFIG_BOOTUF2_FLASHMAX)) {
|
||||
bootuf2_flash_write_internal(ctx, uf2);
|
||||
bootuf2block_state_update(ctx->STATE, uf2, CONFIG_BOOTUF2_FLASHMAX);
|
||||
} else {
|
||||
USB_LOG_DBG("UF2 block %d already written\r\n",
|
||||
uf2->BlockIndex);
|
||||
}
|
||||
} else {
|
||||
USB_LOG_DBG("UF2 block illegal id %08x\r\n", uf2->FamilyID);
|
||||
}
|
||||
|
||||
next:
|
||||
start_sector++;
|
||||
sector_count--;
|
||||
buff += ctx->DBR->BPB.BytesPerSector;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t bootuf2_get_sector_size(void)
|
||||
{
|
||||
return bootuf2_disk.DBR->BPB.BytesPerSector;
|
||||
}
|
||||
|
||||
uint32_t bootuf2_get_sector_count(void)
|
||||
{
|
||||
return bootuf2_disk.DBR->BPB.SectorsOver32MB + bootuf2_disk.DBR->BPB.Sectors;
|
||||
}
|
||||
|
||||
bool bootuf2_is_write_done(void)
|
||||
{
|
||||
if (bootuf2block_state_check(bootuf2_disk.STATE)) {
|
||||
bootuf2_flash_flush(&bootuf2_disk);
|
||||
USB_LOG_DBG("UF2 update ok\r\n");
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
* Copyright (c) 2024, Egahp
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef BOOTUF2_H
|
||||
#define BOOTUF2_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <bootuf2_config.h>
|
||||
|
||||
#ifndef __PACKED
|
||||
#define __PACKED __attribute__((packed))
|
||||
#endif
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(array) \
|
||||
((int)((sizeof(array) / sizeof((array)[0]))))
|
||||
#endif
|
||||
|
||||
struct bootuf2_BLOCK
|
||||
{
|
||||
// 32 byte header
|
||||
uint32_t MagicStart0;
|
||||
uint32_t MagicStart1;
|
||||
uint32_t Flags;
|
||||
uint32_t TargetAddress;
|
||||
uint32_t PayloadSize;
|
||||
uint32_t BlockIndex;
|
||||
uint32_t NumberOfBlock;
|
||||
uint32_t FamilyID; // or file_size
|
||||
uint8_t Data[476];
|
||||
uint32_t MagicEnd;
|
||||
} __PACKED;
|
||||
//BUILD_ASSERT(sizeof(struct bootuf2_BLOCK) == 512, "bootuf2_BLOCK not sector sized");
|
||||
|
||||
struct bootuf2_STATE
|
||||
{
|
||||
uint32_t NumberOfBlock;
|
||||
uint32_t NumberOfWritten;
|
||||
uint8_t *const Mask;
|
||||
uint8_t Enable;
|
||||
};
|
||||
|
||||
struct bootuf2_DBR
|
||||
{
|
||||
/*!< offset 0 */
|
||||
uint8_t JMPInstruction[3];
|
||||
/*!< offset 3 */
|
||||
uint8_t OEM[8];
|
||||
/*!< offset 11 */
|
||||
struct
|
||||
{
|
||||
uint16_t BytesPerSector;
|
||||
uint8_t SectorsPerCluster;
|
||||
uint16_t ReservedSectors;
|
||||
uint8_t NumberOfFAT;
|
||||
uint16_t RootEntries;
|
||||
uint16_t Sectors;
|
||||
uint8_t MediaDescriptor;
|
||||
uint16_t SectorsPerFAT;
|
||||
uint16_t SectorsPerTrack;
|
||||
uint16_t Heads;
|
||||
uint32_t HiddenSectors;
|
||||
uint32_t SectorsOver32MB;
|
||||
uint8_t BIOSDrive;
|
||||
uint8_t Reserved;
|
||||
uint8_t ExtendBootSignature;
|
||||
uint32_t VolumeSerialNumber;
|
||||
uint8_t VolumeLabel[11];
|
||||
uint8_t FileSystem[8];
|
||||
} __PACKED BPB;
|
||||
/*!< offset 62 */
|
||||
/*!< BootLoader */
|
||||
/*!< offset 511 */
|
||||
/*!< 0x55 0xAA */
|
||||
} __PACKED;
|
||||
//BUILD_ASSERT(sizeof(struct bootuf2_DBR) == 62, "bootuf2_DBR size must be 62 byte");
|
||||
|
||||
struct bootuf2_ENTRY
|
||||
{
|
||||
char Name[11];
|
||||
uint8_t Attribute;
|
||||
uint8_t NTReserved;
|
||||
uint8_t CreateTimeTeenth;
|
||||
uint16_t CreateTime;
|
||||
uint16_t CreateDate;
|
||||
uint16_t LastAccessDate;
|
||||
uint16_t FirstClustH16;
|
||||
uint16_t UpdateTime;
|
||||
uint16_t UpdateDate;
|
||||
uint16_t FirstClustL16;
|
||||
uint32_t FileSize;
|
||||
} __PACKED;
|
||||
//BUILD_ASSERT(sizeof(struct bootuf2_ENTRY) == 32, "bootuf2_ENTRY size must be 32 byte");
|
||||
|
||||
struct bootuf2_FILE
|
||||
{
|
||||
const char *const Name;
|
||||
const void *const Content;
|
||||
uint32_t FileSize;
|
||||
uint16_t ClusterBeg;
|
||||
uint16_t ClusterEnd;
|
||||
};
|
||||
|
||||
#define BOOTUF2_DIVCEIL(_v, _d) (((_v) / (_d)) + ((_v) % (_d) ? 1 : 0))
|
||||
|
||||
#define BOOTUF2_MAGIC_START0 0x0A324655u
|
||||
#define BOOTUF2_MAGIC_START1 0x9E5D5157u
|
||||
#define BOOTUF2_MAGIC_SERIAL 0x251B18BDu
|
||||
#define BOOTUF2_MAGIC_END 0x0AB16F30u
|
||||
|
||||
#define BOOTUF2_FLAG_NOT_MAIN_FLASH 0x00000001u
|
||||
#define BOOTUF2_FLAG_FILE_CONTAINER 0x00001000u
|
||||
#define BOOTUF2_FLAG_FAMILID_PRESENT 0x00002000u
|
||||
#define BOOTUF2_FLAG_MD5_PRESENT 0x00004000u
|
||||
|
||||
#define BOOTUF2_CMD_READ 0
|
||||
#define BOOTUF2_CMD_SYNC 1
|
||||
|
||||
#define BOOTUF2_BLOCKSMAX (((CONFIG_BOOTUF2_FLASHMAX) / 256) + (((CONFIG_BOOTUF2_FLASHMAX) % 256) ? 1 : 0))
|
||||
|
||||
#define BOOTUF2_FAMILYID_POSNUM(n) (((CONFIG_BOOTUF2_FAMILYID) / (0x10000000 >> ((n) * 4))) % 0x10)
|
||||
#define BOOTUF2_FAMILYID_ARRAY \
|
||||
{ \
|
||||
((BOOTUF2_FAMILYID_POSNUM(0) >= 10) ? BOOTUF2_FAMILYID_POSNUM(0) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(0) + '0'), \
|
||||
((BOOTUF2_FAMILYID_POSNUM(1) >= 10) ? BOOTUF2_FAMILYID_POSNUM(1) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(1) + '0'), \
|
||||
((BOOTUF2_FAMILYID_POSNUM(2) >= 10) ? BOOTUF2_FAMILYID_POSNUM(2) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(2) + '0'), \
|
||||
((BOOTUF2_FAMILYID_POSNUM(3) >= 10) ? BOOTUF2_FAMILYID_POSNUM(3) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(3) + '0'), \
|
||||
((BOOTUF2_FAMILYID_POSNUM(4) >= 10) ? BOOTUF2_FAMILYID_POSNUM(4) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(4) + '0'), \
|
||||
((BOOTUF2_FAMILYID_POSNUM(5) >= 10) ? BOOTUF2_FAMILYID_POSNUM(5) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(5) + '0'), \
|
||||
((BOOTUF2_FAMILYID_POSNUM(6) >= 10) ? BOOTUF2_FAMILYID_POSNUM(6) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(6) + '0'), \
|
||||
((BOOTUF2_FAMILYID_POSNUM(7) >= 10) ? BOOTUF2_FAMILYID_POSNUM(7) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(7) + '0'), \
|
||||
('I'), \
|
||||
('D'), \
|
||||
(' '), \
|
||||
('\0'), \
|
||||
};
|
||||
|
||||
#define BOOTUF2_FAT16_PER_SECTOR(pDBR) (pDBR->BPB.BytesPerSector / 2)
|
||||
#define BOOTUF2_ENTRY_PER_SECTOR(pDBR) (pDBR->BPB.BytesPerSector / sizeof(struct bootuf2_ENTRY))
|
||||
#define BOOTUF2_CLUSTERSMAX (0xFFF0 - 2)
|
||||
#define BOOTUF2_SECTOR_DBR_END (0)
|
||||
#define BOOTUF2_SECTOR_RSVD_END(pDBR) BOOTUF2_SECTOR_DBR_END + (pDBR->BPB.ReservedSectors)
|
||||
#define BOOTUF2_SECTOR_FAT_END(pDBR) BOOTUF2_SECTOR_RSVD_END(pDBR) + (pDBR->BPB.SectorsPerFAT * pDBR->BPB.NumberOfFAT)
|
||||
#define BOOTUF2_SECTOR_ROOT_END(pDBR) BOOTUF2_SECTOR_FAT_END(pDBR) + (pDBR->BPB.RootEntries / (pDBR->BPB.BytesPerSector / sizeof(struct bootuf2_ENTRY)))
|
||||
#define BOOTUF2_SECTOR_DATA_END(pDBR) (pDBR->BPB.Sectors + pDBR->BPB.SectorsOver32MB)
|
||||
|
||||
#define BOOTUF2_SECTORS_PER_FAT(n) \
|
||||
BOOTUF2_DIVCEIL(BOOTUF2_CLUSTERSMAX, (CONFIG_BOOTUF2_SECTOR_SIZE / 2))
|
||||
#define BOOTUF2_SECTORS_FOR_ENTRIES(n) \
|
||||
(CONFIG_BOOTUF2_ROOT_ENTRIES / (CONFIG_BOOTUF2_SECTOR_SIZE / sizeof(struct bootuf2_ENTRY)))
|
||||
#define BOOTUF2_SECTORS(n) \
|
||||
(CONFIG_BOOTUF2_SECTOR_RESERVED + \
|
||||
CONFIG_BOOTUF2_NUM_OF_FAT * BOOTUF2_SECTORS_PER_FAT(n) + \
|
||||
BOOTUF2_SECTORS_FOR_ENTRIES(n) + \
|
||||
BOOTUF2_CLUSTERSMAX * CONFIG_BOOTUF2_SECTOR_PER_CLUSTER)
|
||||
|
||||
#define BOOTUF2_YEAR_INT ( \
|
||||
(__DATE__[7u] - '0') * 1000u + \
|
||||
(__DATE__[8u] - '0') * 100u + \
|
||||
(__DATE__[9u] - '0') * 10u + \
|
||||
(__DATE__[10u] - '0') * 1u)
|
||||
|
||||
#define BOOTUF2_MONTH_INT ( \
|
||||
(__DATE__[2u] == 'n' && __DATE__[1u] == 'a') ? 1u /*Jan*/ \
|
||||
: (__DATE__[2u] == 'b') ? 2u /*Feb*/ \
|
||||
: (__DATE__[2u] == 'r' && __DATE__[1u] == 'a') ? 3u /*Mar*/ \
|
||||
: (__DATE__[2u] == 'r') ? 4u /*Apr*/ \
|
||||
: (__DATE__[2u] == 'y') ? 5u /*May*/ \
|
||||
: (__DATE__[2u] == 'n') ? 6u /*Jun*/ \
|
||||
: (__DATE__[2u] == 'l') ? 7u /*Jul*/ \
|
||||
: (__DATE__[2u] == 'g') ? 8u /*Aug*/ \
|
||||
: (__DATE__[2u] == 'p') ? 9u /*Sep*/ \
|
||||
: (__DATE__[2u] == 't') ? 10u /*Oct*/ \
|
||||
: (__DATE__[2u] == 'v') ? 11u /*Nov*/ \
|
||||
: 12u /*Dec*/)
|
||||
|
||||
#define BOOTUF2_DAY_INT ( \
|
||||
(__DATE__[4u] == ' ' ? 0 : __DATE__[4u] - '0') * 10u + \
|
||||
(__DATE__[5u] - '0'))
|
||||
|
||||
#define BOOTUF2_HOUR_INT ( \
|
||||
(__TIME__[0u] == '?' ? 0 : __TIME__[0u] - '0') * 10u + (__TIME__[1u] == '?' ? 0 : __TIME__[1u] - '0'))
|
||||
|
||||
#define BOOTUF2_MINUTE_INT ( \
|
||||
(__TIME__[3u] == '?' ? 0 : __TIME__[3u] - '0') * 10u + (__TIME__[4u] == '?' ? 0 : __TIME__[4u] - '0'))
|
||||
|
||||
#define BOOTUF2_SECONDS_INT ( \
|
||||
(__TIME__[6u] == '?' ? 0 : __TIME__[6u] - '0') * 10u + (__TIME__[7u] == '?' ? 0 : __TIME__[7u] - '0'))
|
||||
|
||||
#define BOOTUF2_DOS_DATE ( \
|
||||
((BOOTUF2_YEAR_INT - 1980u) << 9u) | \
|
||||
(BOOTUF2_MONTH_INT << 5u) | \
|
||||
(BOOTUF2_DAY_INT << 0u))
|
||||
|
||||
#define BOOTUF2_DOS_TIME ( \
|
||||
(BOOTUF2_HOUR_INT << 11u) | \
|
||||
(BOOTUF2_MINUTE_INT << 5u) | \
|
||||
(BOOTUF2_SECONDS_INT << 0u))
|
||||
|
||||
void bootuf2_init(void);
|
||||
int boot2uf2_read_sector(uint32_t start_sector, uint8_t *buff, uint32_t sector_count);
|
||||
int bootuf2_write_sector(uint32_t start_sector, const uint8_t *buff, uint32_t sector_count);
|
||||
uint16_t bootuf2_get_sector_size(void);
|
||||
uint32_t bootuf2_get_sector_count(void);
|
||||
|
||||
bool bootuf2_is_write_done(void);
|
||||
|
||||
void boot2uf2_flash_init(void);
|
||||
int bootuf2_flash_write(uint32_t address, const uint8_t *data, size_t size);
|
||||
|
||||
#endif /* BOOTUF2_H */
|
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef BOOTUF2_CONFIG_H
|
||||
#define BOOTUF2_CONFIG_H
|
||||
|
||||
#define CONFIG_PRODUCT "CherryUSB"
|
||||
#define CONFIG_BOARD "CherryUSB BOARD"
|
||||
#define CONFIG_BOOTUF2_INDEX_URL "https://github.com/cherry-embedded"
|
||||
#define CONFIG_BOOTUF2_JOIN_URL "http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=GyH2M5XfWTHQzmZis4ClpgvfdObPrvtk&authKey=LmcLhfno%2BiW51wmgVC%2F8WoYwUXqiclzWDHMU1Jy1d6S8cECJ4Q7bfJ%2FTe67RLakI&noverify=0&group_code=642693751"
|
||||
|
||||
#define CONFIG_BOOTUF2_CACHE_SIZE 4096
|
||||
#define CONFIG_BOOTUF2_SECTOR_SIZE 512
|
||||
#define CONFIG_BOOTUF2_SECTOR_PER_CLUSTER 2
|
||||
#define CONFIG_BOOTUF2_SECTOR_RESERVED 1
|
||||
#define CONFIG_BOOTUF2_NUM_OF_FAT 2
|
||||
#define CONFIG_BOOTUF2_ROOT_ENTRIES 64
|
||||
|
||||
#define CONFIG_BOOTUF2_FAMILYID 0xFFFFFFFF
|
||||
#define CONFIG_BOOTUF2_FLASHMAX 0x800000
|
||||
#define CONFIG_BOOTUF2_PAGE_COUNTMAX 1024
|
||||
|
||||
#endif
|
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_msc.h"
|
||||
#include "bootuf2.h"
|
||||
|
||||
#define MSC_IN_EP 0x81
|
||||
#define MSC_OUT_EP 0x02
|
||||
|
||||
#define USBD_VID 0xFFFF
|
||||
#define USBD_PID 0xFFFF
|
||||
#define USBD_MAX_POWER 100
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
#define USB_CONFIG_SIZE (9 + MSC_DESCRIPTOR_LEN)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define MSC_MAX_MPS 512
|
||||
#else
|
||||
#define MSC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
const uint8_t msc_bootuf2_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
///////////////////////////////////////
|
||||
/// string1 descriptor
|
||||
///////////////////////////////////////
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string2 descriptor
|
||||
///////////////////////////////////////
|
||||
0x26, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
' ', 0x00, /* wcChar9 */
|
||||
'U', 0x00, /* wcChar10 */
|
||||
'F', 0x00, /* wcChar11 */
|
||||
'2', 0x00, /* wcChar12 */
|
||||
' ', 0x00, /* wcChar13 */
|
||||
'D', 0x00, /* wcChar14 */
|
||||
'E', 0x00, /* wcChar15 */
|
||||
'M', 0x00, /* wcChar16 */
|
||||
'O', 0x00, /* wcChar17 */
|
||||
///////////////////////////////////////
|
||||
/// string3 descriptor
|
||||
///////////////////////////////////////
|
||||
0x16, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'2', 0x00, /* wcChar0 */
|
||||
'0', 0x00, /* wcChar1 */
|
||||
'2', 0x00, /* wcChar2 */
|
||||
'2', 0x00, /* wcChar3 */
|
||||
'1', 0x00, /* wcChar4 */
|
||||
'2', 0x00, /* wcChar5 */
|
||||
'3', 0x00, /* wcChar6 */
|
||||
'4', 0x00, /* wcChar7 */
|
||||
'5', 0x00, /* wcChar8 */
|
||||
'6', 0x00, /* wcChar9 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
};
|
||||
|
||||
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:
|
||||
bootuf2_init();
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
|
||||
{
|
||||
*block_num = bootuf2_get_sector_count();
|
||||
*block_size = bootuf2_get_sector_size();
|
||||
|
||||
USB_LOG_INFO("sector count:%d, sector size:%d\n", *block_num, *block_size);
|
||||
}
|
||||
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
boot2uf2_read_sector(sector, buffer, length / bootuf2_get_sector_size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
bootuf2_write_sector(sector, buffer, length / bootuf2_get_sector_size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct usbd_interface intf0;
|
||||
|
||||
void msc_bootuf2_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
boot2uf2_flash_init();
|
||||
usbd_desc_register(busid, msc_bootuf2_descriptor);
|
||||
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
|
||||
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
}
|
||||
|
||||
void boot2uf2_flash_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
int bootuf2_flash_write(uint32_t address, const uint8_t *data, size_t size)
|
||||
{
|
||||
USB_LOG_INFO("address:%08x, size:%d\n", address, size);
|
||||
return 0;
|
||||
}
|
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_msc.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_cdc_acm.h"
|
||||
#include "usbd_hid.h"
|
||||
|
||||
/*!< endpoint address */
|
||||
@@ -147,7 +147,7 @@ const uint8_t cdc_acm_hid_msc_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -301,7 +301,7 @@ struct usbd_interface intf1;
|
||||
struct usbd_interface intf2;
|
||||
struct usbd_interface intf3;
|
||||
|
||||
void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uint32_t reg_base)
|
||||
void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, cdc_acm_hid_msc_descriptor);
|
||||
|
||||
@@ -332,14 +332,15 @@ void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uint32_t reg_base)
|
||||
*/
|
||||
void hid_mouse_test(uint8_t busid)
|
||||
{
|
||||
if(usb_device_is_configured(busid) == false) {
|
||||
return;
|
||||
}
|
||||
/*!< move mouse pointer */
|
||||
mouse_cfg.x += 10;
|
||||
mouse_cfg.y = 0;
|
||||
int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
hid_state = HID_STATE_BUSY;
|
||||
usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
|
||||
while (hid_state == HID_STATE_BUSY) {
|
||||
}
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_cdc_acm.h"
|
||||
#include "usbd_msc.h"
|
||||
|
||||
/*!< endpoint address */
|
||||
@@ -58,7 +58,7 @@ static const uint8_t device_quality_descriptor[] = {
|
||||
0x02,
|
||||
0x01,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
};
|
||||
|
||||
@@ -173,7 +173,7 @@ static const uint8_t cdc_msc_descriptor[] = {
|
||||
0x02,
|
||||
0x01,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -247,7 +247,7 @@ struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
struct usbd_interface intf2;
|
||||
|
||||
void cdc_acm_msc_init(uint8_t busid, uint32_t reg_base)
|
||||
void cdc_acm_msc_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
usbd_desc_register(busid, &cdc_msc_descriptor);
|
||||
|
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_cdc_acm.h"
|
||||
|
||||
/*!< endpoint address */
|
||||
#define CDC_IN_EP 0x81
|
||||
@@ -113,7 +113,7 @@ static const uint8_t cdc_descriptor[] = {
|
||||
0x02,
|
||||
0x01,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -223,7 +223,7 @@ struct usbd_interface intf5;
|
||||
struct usbd_interface intf6;
|
||||
struct usbd_interface intf7;
|
||||
|
||||
void cdc_acm_multi_init(uint8_t busid, uint32_t reg_base)
|
||||
void cdc_acm_multi_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, cdc_descriptor);
|
||||
|
||||
|
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_cdc_acm.h"
|
||||
|
||||
/*!< endpoint address */
|
||||
#define CDC_IN_EP 0x81
|
||||
@@ -98,7 +98,7 @@ static const uint8_t cdc_descriptor[] = {
|
||||
0x02,
|
||||
0x01,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -174,7 +174,7 @@ struct usbd_endpoint cdc_in_ep = {
|
||||
static struct usbd_interface intf0;
|
||||
static struct usbd_interface intf1;
|
||||
|
||||
void cdc_acm_init(uint8_t busid, uint32_t reg_base)
|
||||
void cdc_acm_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
const uint8_t data[10] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
|
||||
|
||||
|
@@ -6,6 +6,10 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc_ecm.h"
|
||||
|
||||
#ifndef CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
||||
#error "Please enable CONFIG_USBDEV_CDC_ECM_USING_LWIP for this demo"
|
||||
#endif
|
||||
|
||||
/*!< endpoint address */
|
||||
#define CDC_IN_EP 0x81
|
||||
#define CDC_OUT_EP 0x02
|
||||
@@ -124,7 +128,7 @@ static const uint8_t cdc_ecm_descriptor[] = {
|
||||
0x02,
|
||||
0x01,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -222,12 +226,12 @@ void cdc_ecm_lwip_init(void)
|
||||
while (!netif_is_up(netif)) {
|
||||
}
|
||||
|
||||
// while (dhserv_init(&dhcp_config)) {}
|
||||
while (dhserv_init(&dhcp_config)) {}
|
||||
|
||||
// while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
|
||||
while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
|
||||
}
|
||||
|
||||
void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len)
|
||||
void usbd_cdc_ecm_data_recv_done(uint32_t len)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -269,7 +273,7 @@ struct usbd_interface intf1;
|
||||
* sudo ifconfig enxaabbccddeeff up
|
||||
* sudo dhcpclient enxaabbccddeeff
|
||||
*/
|
||||
void cdc_ecm_init(uint8_t busid, uint32_t reg_base)
|
||||
void cdc_ecm_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
cdc_ecm_lwip_init();
|
||||
|
||||
|
@@ -6,6 +6,10 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_rndis.h"
|
||||
|
||||
#ifndef CONFIG_USBDEV_RNDIS_USING_LWIP
|
||||
#error "Please enable CONFIG_USBDEV_RNDIS_USING_LWIP for this demo"
|
||||
#endif
|
||||
|
||||
/*!< endpoint address */
|
||||
#define CDC_IN_EP 0x81
|
||||
#define CDC_OUT_EP 0x02
|
||||
@@ -100,7 +104,7 @@ static const uint8_t cdc_descriptor[] = {
|
||||
0x02,
|
||||
0x01,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -170,7 +174,7 @@ rt_err_t rt_usbd_rndis_eth_tx(rt_device_t dev, struct pbuf *p)
|
||||
return usbd_rndis_eth_tx(p);
|
||||
}
|
||||
|
||||
void usbd_rndis_data_recv_done(void)
|
||||
void usbd_rndis_data_recv_done(uint32_t len)
|
||||
{
|
||||
eth_device_ready(&rndis_dev);
|
||||
}
|
||||
@@ -258,12 +262,12 @@ void rndis_lwip_init(void)
|
||||
while (!netif_is_up(netif)) {
|
||||
}
|
||||
|
||||
// while (dhserv_init(&dhcp_config)) {}
|
||||
while (dhserv_init(&dhcp_config)) {}
|
||||
|
||||
// while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
|
||||
while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
|
||||
}
|
||||
|
||||
void usbd_rndis_data_recv_done(void)
|
||||
void usbd_rndis_data_recv_done(uint32_t len)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -304,7 +308,7 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
|
||||
void cdc_rndis_init(uint8_t busid, uint32_t reg_base)
|
||||
void cdc_rndis_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
#ifdef RT_USING_LWIP
|
||||
rt_usbd_rndis_init();
|
||||
|
@@ -136,7 +136,7 @@ const uint8_t dfu_flash_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -169,7 +169,7 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||
|
||||
struct usbd_interface intf0;
|
||||
|
||||
void dfu_flash_init(uint8_t busid, uint32_t reg_base)
|
||||
void dfu_flash_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, dfu_flash_descriptor);
|
||||
usbd_add_interface(busid, usbd_dfu_init_intf(&intf0));
|
||||
|
@@ -146,7 +146,7 @@ static const uint8_t hid_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -272,7 +272,7 @@ static struct usbd_endpoint custom_out_ep = {
|
||||
*/
|
||||
struct usbd_interface intf0;
|
||||
|
||||
void hid_custom_init(uint8_t busid, uint32_t reg_base)
|
||||
void hid_custom_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, hid_descriptor);
|
||||
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE));
|
||||
|
@@ -122,7 +122,7 @@ static const uint8_t hid_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -221,7 +221,7 @@ static struct usbd_endpoint hid_in_ep = {
|
||||
|
||||
struct usbd_interface intf0;
|
||||
|
||||
void hid_keyboard_init(uint8_t busid, uint32_t reg_base)
|
||||
void hid_keyboard_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, hid_descriptor);
|
||||
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE));
|
||||
@@ -236,12 +236,13 @@ void hid_keyboard_test(uint8_t busid)
|
||||
{
|
||||
const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
memcpy(write_buffer, sendbuffer, 8);
|
||||
int ret = usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8);
|
||||
if (ret < 0) {
|
||||
if(usb_device_is_configured(busid) == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(write_buffer, sendbuffer, 8);
|
||||
hid_state = HID_STATE_BUSY;
|
||||
usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8);
|
||||
while (hid_state == HID_STATE_BUSY) {
|
||||
}
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@
|
||||
/*!< endpoint address */
|
||||
#define HID_INT_EP 0x81
|
||||
#define HID_INT_EP_SIZE 4
|
||||
#define HID_INT_EP_INTERVAL 10
|
||||
#define HID_INT_EP_INTERVAL 1
|
||||
|
||||
#define USBD_VID 0xffff
|
||||
#define USBD_PID 0xffff
|
||||
@@ -126,7 +126,7 @@ const uint8_t hid_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -239,7 +239,7 @@ static struct usbd_endpoint hid_in_ep = {
|
||||
|
||||
struct usbd_interface intf0;
|
||||
|
||||
void hid_mouse_init(uint8_t busid, uint32_t reg_base)
|
||||
void hid_mouse_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, hid_descriptor);
|
||||
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
|
||||
@@ -254,25 +254,65 @@ void hid_mouse_init(uint8_t busid, uint32_t reg_base)
|
||||
mouse_cfg.y = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief hid mouse test
|
||||
* @pre none
|
||||
* @param[in] none
|
||||
* @retval none
|
||||
*/
|
||||
#define CURSOR_STEP 2U
|
||||
#define CURSOR_WIDTH 20U
|
||||
|
||||
void draw_circle(uint8_t *buf)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
buf[0] = 0;
|
||||
buf[1] = x;
|
||||
buf[2] = y;
|
||||
buf[3] = 0;
|
||||
}
|
||||
|
||||
/* https://cps-check.com/cn/polling-rate-check */
|
||||
void hid_mouse_test(uint8_t busid)
|
||||
{
|
||||
if(usb_device_is_configured(busid) == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
int counter = 0;
|
||||
while (counter < 1000) {
|
||||
/*!< move mouse pointer */
|
||||
mouse_cfg.x += 40;
|
||||
mouse_cfg.y += 0;
|
||||
|
||||
int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
draw_circle((uint8_t *)&mouse_cfg);
|
||||
hid_state = HID_STATE_BUSY;
|
||||
usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
|
||||
while (hid_state == HID_STATE_BUSY) {
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_hid.h"
|
||||
|
||||
/*!< endpoint address */
|
||||
#define HID_INT_EP 0x81
|
||||
#define HID_INT_EP_SIZE 4
|
||||
#define HID_INT_EP_INTERVAL 1
|
||||
|
||||
#define USBD_VID 0xffff
|
||||
#define USBD_PID 0xffff
|
||||
#define USBD_MAX_POWER 100
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
/*!< config descriptor size */
|
||||
#define USB_HID_CONFIG_DESC_SIZ 34
|
||||
/*!< report descriptor size */
|
||||
#define HID_MOUSE_REPORT_DESC_SIZE 74
|
||||
|
||||
/*!< global descriptor */
|
||||
const uint8_t hid_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x01, 0x01, USB_CONFIG_REMOTE_WAKEUP | USB_CONFIG_SELF_POWERED, USBD_MAX_POWER),
|
||||
|
||||
/************** Descriptor of Joystick Mouse interface ****************/
|
||||
/* 09 */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
|
||||
0x00, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints */
|
||||
0x03, /* bInterfaceClass: HID */
|
||||
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
|
||||
0x02, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
|
||||
0, /* iInterface: Index of string descriptor */
|
||||
/******************** Descriptor of Joystick Mouse HID ********************/
|
||||
/* 18 */
|
||||
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_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
|
||||
0x00,
|
||||
/******************** Descriptor of Mouse endpoint ********************/
|
||||
/* 27 */
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||
HID_INT_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||
0x03, /* bmAttributes: Interrupt endpoint */
|
||||
HID_INT_EP_SIZE, /* wMaxPacketSize: 4 Byte max */
|
||||
0x00,
|
||||
HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
|
||||
/* 34 */
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
///////////////////////////////////////
|
||||
/// string1 descriptor
|
||||
///////////////////////////////////////
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string2 descriptor
|
||||
///////////////////////////////////////
|
||||
0x26, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
' ', 0x00, /* wcChar9 */
|
||||
'H', 0x00, /* wcChar10 */
|
||||
'I', 0x00, /* wcChar11 */
|
||||
'D', 0x00, /* wcChar12 */
|
||||
' ', 0x00, /* wcChar13 */
|
||||
'D', 0x00, /* wcChar14 */
|
||||
'E', 0x00, /* wcChar15 */
|
||||
'M', 0x00, /* wcChar16 */
|
||||
'O', 0x00, /* wcChar17 */
|
||||
///////////////////////////////////////
|
||||
/// string3 descriptor
|
||||
///////////////////////////////////////
|
||||
0x16, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'2', 0x00, /* wcChar0 */
|
||||
'0', 0x00, /* wcChar1 */
|
||||
'2', 0x00, /* wcChar2 */
|
||||
'2', 0x00, /* wcChar3 */
|
||||
'1', 0x00, /* wcChar4 */
|
||||
'2', 0x00, /* wcChar5 */
|
||||
'3', 0x00, /* wcChar6 */
|
||||
'4', 0x00, /* wcChar7 */
|
||||
'5', 0x00, /* wcChar8 */
|
||||
'6', 0x00, /* wcChar9 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
};
|
||||
|
||||
/*!< hid mouse report descriptor */
|
||||
static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
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 (Button 1)
|
||||
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
|
||||
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||
0x95, 0x03, // REPORT_COUNT (3)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x75, 0x05, // REPORT_SIZE (5)
|
||||
0x81, 0x01, // INPUT (Cnst,Var,Abs)
|
||||
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x30, // USAGE (X)
|
||||
0x09, 0x31, // USAGE (Y)
|
||||
0x09, 0x38,
|
||||
|
||||
0x15, 0x81, // LOGICAL_MINIMUM (-127)
|
||||
0x25, 0x7F, // LOGICAL_MAXIMUM (127)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x95, 0x03, // REPORT_COUNT (2)
|
||||
|
||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||
0xC0, 0x09,
|
||||
0x3c, 0x05,
|
||||
0xff, 0x09,
|
||||
|
||||
0x01, 0x15,
|
||||
0x00, 0x25,
|
||||
0x01, 0x75,
|
||||
0x01, 0x95,
|
||||
|
||||
0x02, 0xb1,
|
||||
0x22, 0x75,
|
||||
0x06, 0x95,
|
||||
0x01, 0xb1,
|
||||
|
||||
0x01, 0xc0 // END_COLLECTION
|
||||
};
|
||||
|
||||
/*!< mouse report struct */
|
||||
struct hid_mouse {
|
||||
uint8_t buttons;
|
||||
int8_t x;
|
||||
int8_t y;
|
||||
int8_t wheel;
|
||||
};
|
||||
|
||||
/*!< mouse report */
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct hid_mouse mouse_cfg;
|
||||
|
||||
#define HID_STATE_IDLE 0
|
||||
#define HID_STATE_BUSY 1
|
||||
|
||||
/*!< hid state ! Data can be sent only when state is idle */
|
||||
static volatile uint8_t hid_state = HID_STATE_IDLE;
|
||||
|
||||
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:
|
||||
hid_state = HID_STATE_IDLE;
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* function ------------------------------------------------------------------*/
|
||||
static void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
hid_state = HID_STATE_IDLE;
|
||||
}
|
||||
|
||||
/*!< endpoint call back */
|
||||
static struct usbd_endpoint hid_in_ep = {
|
||||
.ep_cb = usbd_hid_int_callback,
|
||||
.ep_addr = HID_INT_EP
|
||||
};
|
||||
|
||||
static struct usbd_interface intf0;
|
||||
|
||||
void hid_mouse_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, hid_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_in_ep);
|
||||
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
|
||||
/*!< init mouse report data */
|
||||
mouse_cfg.buttons = 0;
|
||||
mouse_cfg.wheel = 0;
|
||||
mouse_cfg.x = 0;
|
||||
mouse_cfg.y = 0;
|
||||
}
|
||||
|
||||
#define CURSOR_STEP 2U
|
||||
#define CURSOR_WIDTH 20U
|
||||
|
||||
void draw_circle(uint8_t *buf)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
buf[0] = 0;
|
||||
buf[1] = x;
|
||||
buf[2] = y;
|
||||
buf[3] = 0;
|
||||
}
|
||||
|
||||
/* https://cps-check.com/cn/polling-rate-check */
|
||||
void hid_mouse_test(uint8_t busid)
|
||||
{
|
||||
static uint32_t count = 1000;
|
||||
int ret;
|
||||
|
||||
if(usb_device_is_configured(busid) == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if (gpio_read_pin(GPIO_PIN) == 1) {
|
||||
// ret = usbd_send_remote_wakeup(busid);
|
||||
// if (ret < 0) {
|
||||
// return;
|
||||
// }
|
||||
// count = 5000;
|
||||
// }
|
||||
|
||||
while (count) {
|
||||
draw_circle((uint8_t *)&mouse_cfg);
|
||||
hid_state = HID_STATE_BUSY;
|
||||
usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
|
||||
while (hid_state == HID_STATE_BUSY) {
|
||||
}
|
||||
|
||||
count--;
|
||||
}
|
||||
}
|
@@ -145,7 +145,7 @@ const uint8_t midi_descriptor[] = {
|
||||
0x02,
|
||||
0x01,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -202,7 +202,7 @@ struct usbd_endpoint midi_in_ep = {
|
||||
.ep_cb = usbd_midi_bulk_in
|
||||
};
|
||||
|
||||
void midi_init(uint8_t busid, uint32_t reg_base)
|
||||
void midi_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, midi_descriptor);
|
||||
usbd_add_interface(busid, &intf0);
|
||||
|
@@ -94,7 +94,7 @@ const uint8_t msc_ram_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -154,12 +154,19 @@ int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct usbd_interface intf0;
|
||||
static struct usbd_interface intf0;
|
||||
|
||||
void msc_ram_init(uint8_t busid, uint32_t reg_base)
|
||||
void msc_ram_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, msc_ram_descriptor);
|
||||
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
|
||||
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
void msc_ram_polling(uint8_t busid)
|
||||
{
|
||||
usbd_msc_polling(busid);
|
||||
}
|
||||
#endif
|
@@ -97,7 +97,7 @@ const uint8_t msc_storage_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -154,7 +154,7 @@ int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *
|
||||
return 0;
|
||||
}
|
||||
|
||||
void msc_storage_init(uint8_t busid, uint32_t reg_base)
|
||||
void msc_storage_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
rt_err_t res;
|
||||
|
||||
|
@@ -120,7 +120,7 @@ void usbh_hid_callback(void *arg, int nbytes)
|
||||
struct usbh_hid *hid_class = (struct usbh_hid *)arg;
|
||||
|
||||
if (nbytes > 0) {
|
||||
for (size_t i = 0; i < nbytes; i++) {
|
||||
for (int i = 0; i < nbytes; i++) {
|
||||
USB_LOG_RAW("0x%02x ", hid_buffer[i]);
|
||||
}
|
||||
USB_LOG_RAW("nbytes:%d\r\n", nbytes);
|
||||
@@ -254,38 +254,38 @@ delete:
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_CDC_ACM
|
||||
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
|
||||
{
|
||||
#if TEST_USBH_CDC_ACM
|
||||
usb_osal_thread_create("usbh_cdc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_acm_thread, cdc_acm_class);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_HID
|
||||
void usbh_hid_run(struct usbh_hid *hid_class)
|
||||
{
|
||||
#if TEST_USBH_HID
|
||||
usb_osal_thread_create("usbh_hid", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hid_thread, hid_class);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_hid_stop(struct usbh_hid *hid_class)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_MSC
|
||||
void usbh_msc_run(struct usbh_msc *msc_class)
|
||||
{
|
||||
#if TEST_USBH_MSC
|
||||
usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, msc_class);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_msc_stop(struct usbh_msc *msc_class)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_AUDIO
|
||||
#error "commercial charge"
|
||||
@@ -294,3 +294,26 @@ void usbh_msc_stop(struct usbh_msc *msc_class)
|
||||
#if TEST_USBH_VIDEO
|
||||
#error "commercial charge"
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#include "usbh_aoa.h"
|
||||
|
||||
static struct aoa_string_info deviceinfo = {
|
||||
.acc_manufacturer = "CherryUSB",
|
||||
.acc_model = "CherryUSB",
|
||||
.acc_description = "Android Open Accessory CherryUSB",
|
||||
.acc_version = "1.0",
|
||||
.acc_uri = "http://developer.android.com/tools/adk/index.html",
|
||||
.acc_serial = "CherryUSB"
|
||||
};
|
||||
|
||||
int aoa_switch(int argc, char **argv)
|
||||
{
|
||||
struct usbh_hubport *hport = usbh_find_hubport(0, 1, 1);
|
||||
|
||||
usbh_aoa_switch(hport, &deviceinfo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SHELL_CMD_EXPORT_ALIAS(aoa_switch, aoa_switch, aoa_switch);
|
||||
#endif
|
@@ -9,6 +9,8 @@
|
||||
#include "usbd_hid.h"
|
||||
#include "cherryusb_mjpeg.h"
|
||||
|
||||
#define MAX_PACKETS_IN_ONE_TRANSFER 1
|
||||
|
||||
#define VIDEO_IN_EP 0x81
|
||||
#define VIDEO_INT_EP 0x86
|
||||
|
||||
@@ -224,7 +226,7 @@ const uint8_t video_audio_hid_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -267,7 +269,7 @@ static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = {
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t audio_read_buffer[AUDIO_OUT_PACKET];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t audio_write_buffer[AUDIO_IN_PACKET];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t video_packet_buffer[40 * 1024];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t video_packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE];
|
||||
|
||||
volatile bool video_tx_flag = 0;
|
||||
volatile bool audio_tx_flag = 0;
|
||||
@@ -331,8 +333,10 @@ void usbd_video_close(uint8_t busid, uint8_t intf)
|
||||
|
||||
void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
//USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||
video_iso_tx_busy = false;
|
||||
if (usbd_video_stream_split_transfer(busid, ep)) {
|
||||
/* one frame has done */
|
||||
video_iso_tx_busy = false;
|
||||
}
|
||||
}
|
||||
|
||||
static struct usbd_endpoint video_in_ep = {
|
||||
@@ -416,7 +420,7 @@ struct audio_entity_info audio_entity_table[] = {
|
||||
.ep = AUDIO_OUT_EP },
|
||||
};
|
||||
|
||||
void composite_init(uint8_t busid, uint32_t reg_base)
|
||||
void composite_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, video_audio_hid_descriptor);
|
||||
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
||||
@@ -458,56 +462,30 @@ void hid_keyboard_test(uint8_t busid)
|
||||
{
|
||||
const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
memcpy(hid_write_buffer, sendbuffer, 8);
|
||||
int ret = usbd_ep_start_write(busid, HID_INT_EP, hid_write_buffer, 8);
|
||||
if (ret < 0) {
|
||||
if(usb_device_is_configured(busid) == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(hid_write_buffer, sendbuffer, 8);
|
||||
hid_state = HID_STATE_BUSY;
|
||||
usbd_ep_start_write(busid, HID_INT_EP, hid_write_buffer, 8);
|
||||
while (hid_state == HID_STATE_BUSY) {
|
||||
}
|
||||
}
|
||||
|
||||
void video_test(uint8_t busid)
|
||||
{
|
||||
uint32_t out_len;
|
||||
uint32_t packets;
|
||||
memset(video_packet_buffer, 0, sizeof(video_packet_buffer));
|
||||
|
||||
(void)packets;
|
||||
memset(video_packet_buffer, 0, 40 * 1024);
|
||||
while (1) {
|
||||
if (video_tx_flag) {
|
||||
packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg), video_packet_buffer, &out_len);
|
||||
#if 1
|
||||
video_iso_tx_busy = true;
|
||||
usbd_ep_start_write(busid, VIDEO_IN_EP, video_packet_buffer, out_len);
|
||||
usbd_video_stream_start_write(busid, VIDEO_IN_EP, &video_packet_buffer[0][0], &video_packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg));
|
||||
while (video_iso_tx_busy) {
|
||||
if (video_tx_flag == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* dwc2 must use this method */
|
||||
for (uint32_t i = 0; i < packets; i++) {
|
||||
if (i == (packets - 1)) {
|
||||
video_iso_tx_busy = true;
|
||||
usbd_ep_start_write(busid, VIDEO_IN_EP, &video_packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE);
|
||||
while (video_iso_tx_busy) {
|
||||
if (video_tx_flag == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
video_iso_tx_busy = true;
|
||||
usbd_ep_start_write(busid, VIDEO_IN_EP, &video_packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE);
|
||||
while (video_iso_tx_busy) {
|
||||
if (video_tx_flag == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
@@ -7,6 +7,8 @@
|
||||
#include "usbd_video.h"
|
||||
#include "cherryusb_h264.h"
|
||||
|
||||
#define MAX_PACKETS_IN_ONE_TRANSFER 1
|
||||
|
||||
#define VIDEO_IN_EP 0x81
|
||||
#define VIDEO_INT_EP 0x83
|
||||
|
||||
@@ -129,7 +131,7 @@ const uint8_t video_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -180,8 +182,10 @@ void usbd_video_close(uint8_t busid, uint8_t intf)
|
||||
|
||||
void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
//USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||
iso_tx_busy = false;
|
||||
if (usbd_video_stream_split_transfer(busid, ep)) {
|
||||
/* one frame has done */
|
||||
iso_tx_busy = false;
|
||||
}
|
||||
}
|
||||
|
||||
static struct usbd_endpoint video_in_ep = {
|
||||
@@ -192,7 +196,7 @@ static struct usbd_endpoint video_in_ep = {
|
||||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
|
||||
void video_init(uint8_t busid, uint32_t reg_base)
|
||||
void video_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, video_descriptor);
|
||||
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
||||
@@ -202,7 +206,7 @@ void video_init(uint8_t busid, uint32_t reg_base)
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
}
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[40 * 1024];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][40 * 1024];
|
||||
|
||||
void video_test(uint8_t busid)
|
||||
{
|
||||
@@ -210,40 +214,16 @@ void video_test(uint8_t busid)
|
||||
uint32_t packets;
|
||||
|
||||
(void)packets;
|
||||
memset(packet_buffer, 0, 40 * 1024);
|
||||
memset(packet_buffer, 0, sizeof(packet_buffer));
|
||||
while (1) {
|
||||
if (tx_flag) {
|
||||
packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_h264, sizeof(cherryusb_h264), packet_buffer, &out_len);
|
||||
#if 1
|
||||
iso_tx_busy = true;
|
||||
usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len);
|
||||
usbd_video_stream_start_write(busid, VIDEO_IN_EP, &packet_buffer[0][0], &packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_h264, sizeof(cherryusb_h264));
|
||||
while (iso_tx_busy) {
|
||||
if (tx_flag == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* dwc2 must use this method */
|
||||
for (uint32_t i = 0; i < packets; i++) {
|
||||
if (i == (packets - 1)) {
|
||||
iso_tx_busy = true;
|
||||
usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE);
|
||||
while (iso_tx_busy) {
|
||||
if (tx_flag == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
iso_tx_busy = true;
|
||||
usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE);
|
||||
while (iso_tx_busy) {
|
||||
if (tx_flag == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
@@ -7,6 +7,8 @@
|
||||
#include "usbd_video.h"
|
||||
#include "cherryusb_mjpeg.h"
|
||||
|
||||
#define MAX_PACKETS_IN_ONE_TRANSFER 1
|
||||
|
||||
#define VIDEO_IN_EP 0x81
|
||||
#define VIDEO_INT_EP 0x83
|
||||
|
||||
@@ -34,7 +36,7 @@
|
||||
#define MAX_BIT_RATE (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS)
|
||||
#define MAX_FRAME_SIZE (unsigned long)(WIDTH * HEIGHT * 2)
|
||||
|
||||
#define VS_HEADER_SIZ (unsigned int)(VIDEO_SIZEOF_VS_INPUT_HEADER_DESC(1,1) + VIDEO_SIZEOF_VS_FORMAT_MJPEG_DESC + VIDEO_SIZEOF_VS_FRAME_MJPEG_DESC(1))
|
||||
#define VS_HEADER_SIZ (unsigned int)(VIDEO_SIZEOF_VS_INPUT_HEADER_DESC(1, 1) + VIDEO_SIZEOF_VS_FORMAT_MJPEG_DESC + VIDEO_SIZEOF_VS_FRAME_MJPEG_DESC(1))
|
||||
|
||||
#define USB_VIDEO_DESC_SIZ (unsigned long)(9 + \
|
||||
VIDEO_VC_NOEP_DESCRIPTOR_LEN + \
|
||||
@@ -129,7 +131,7 @@ const uint8_t video_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -180,8 +182,10 @@ void usbd_video_close(uint8_t busid, uint8_t intf)
|
||||
|
||||
void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
//USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||
iso_tx_busy = false;
|
||||
if (usbd_video_stream_split_transfer(busid, ep)) {
|
||||
/* one frame has done */
|
||||
iso_tx_busy = false;
|
||||
}
|
||||
}
|
||||
|
||||
static struct usbd_endpoint video_in_ep = {
|
||||
@@ -192,7 +196,7 @@ static struct usbd_endpoint video_in_ep = {
|
||||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
|
||||
void video_init(uint8_t busid, uint32_t reg_base)
|
||||
void video_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, video_descriptor);
|
||||
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
||||
@@ -202,48 +206,21 @@ void video_init(uint8_t busid, uint32_t reg_base)
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
}
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[40 * 1024];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE];
|
||||
|
||||
void video_test(uint8_t busid)
|
||||
{
|
||||
uint32_t out_len;
|
||||
uint32_t packets;
|
||||
memset(packet_buffer, 0, sizeof(packet_buffer));
|
||||
|
||||
(void)packets;
|
||||
memset(packet_buffer, 0, 40 * 1024);
|
||||
while (1) {
|
||||
if (tx_flag) {
|
||||
packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg), packet_buffer, &out_len);
|
||||
#if 1
|
||||
iso_tx_busy = true;
|
||||
usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len);
|
||||
usbd_video_stream_start_write(busid, VIDEO_IN_EP, &packet_buffer[0][0], &packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg));
|
||||
while (iso_tx_busy) {
|
||||
if (tx_flag == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* dwc2 must use this method */
|
||||
for (uint32_t i = 0; i < packets; i++) {
|
||||
if (i == (packets - 1)) {
|
||||
iso_tx_busy = true;
|
||||
usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE);
|
||||
while (iso_tx_busy) {
|
||||
if (tx_flag == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
iso_tx_busy = true;
|
||||
usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE);
|
||||
while (iso_tx_busy) {
|
||||
if (tx_flag == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
@@ -7,6 +7,8 @@
|
||||
#include "usbd_video.h"
|
||||
#include "cherryusb_yuyv.h"
|
||||
|
||||
#define MAX_PACKETS_IN_ONE_TRANSFER 1
|
||||
|
||||
#define VIDEO_IN_EP 0x81
|
||||
#define VIDEO_INT_EP 0x83
|
||||
|
||||
@@ -131,7 +133,7 @@ const uint8_t video_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -182,8 +184,10 @@ void usbd_video_close(uint8_t busid, uint8_t intf)
|
||||
|
||||
void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
//USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||
iso_tx_busy = false;
|
||||
if (usbd_video_stream_split_transfer(busid, ep)) {
|
||||
/* one frame has done */
|
||||
iso_tx_busy = false;
|
||||
}
|
||||
}
|
||||
|
||||
static struct usbd_endpoint video_in_ep = {
|
||||
@@ -194,7 +198,7 @@ static struct usbd_endpoint video_in_ep = {
|
||||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
|
||||
void video_init(uint8_t busid, uint32_t reg_base)
|
||||
void video_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, video_descriptor);
|
||||
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
||||
@@ -204,48 +208,21 @@ void video_init(uint8_t busid, uint32_t reg_base)
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
}
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[40 * 1024];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE];
|
||||
|
||||
void video_test(uint8_t busid)
|
||||
{
|
||||
uint32_t out_len;
|
||||
uint32_t packets;
|
||||
memset(packet_buffer, 0, sizeof(packet_buffer));
|
||||
|
||||
(void)packets;
|
||||
memset(packet_buffer, 0, 40 * 1024);
|
||||
while (1) {
|
||||
if (tx_flag) {
|
||||
packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_yuyv, sizeof(cherryusb_yuyv), packet_buffer, &out_len);
|
||||
#if 1
|
||||
iso_tx_busy = true;
|
||||
usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len);
|
||||
usbd_video_stream_start_write(busid, VIDEO_IN_EP, &packet_buffer[0][0], &packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_yuyv, sizeof(cherryusb_yuyv));
|
||||
while (iso_tx_busy) {
|
||||
if (tx_flag == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* dwc2 must use this method */
|
||||
for (uint32_t i = 0; i < packets; i++) {
|
||||
if (i == (packets - 1)) {
|
||||
iso_tx_busy = true;
|
||||
usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE);
|
||||
while (iso_tx_busy) {
|
||||
if (tx_flag == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
iso_tx_busy = true;
|
||||
usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE);
|
||||
while (iso_tx_busy) {
|
||||
if (tx_flag == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,383 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_hid.h"
|
||||
|
||||
#define USBD_VID 0xffff
|
||||
#define USBD_PID 0xffff
|
||||
#define USBD_MAX_POWER 100
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
#define HID_INT_EP 0x81
|
||||
#define HID_INT_EP_SIZE 8
|
||||
#define HID_INT_EP_INTERVAL 10
|
||||
|
||||
#define USB_HID_CONFIG_DESC_SIZ (34 + 9)
|
||||
#define HID_KEYBOARD_REPORT_DESC_SIZE 63
|
||||
|
||||
#define USBD_WEBUSB_VENDOR_CODE (0x22)
|
||||
#define USBD_WINUSB_VENDOR_CODE (0x21)
|
||||
|
||||
#define USBD_WINUSB_DESC_SET_LEN (0xB2)
|
||||
#define URL_DESCRIPTOR_LENGTH (3 + 36)
|
||||
|
||||
#define USBD_WEBUSB_INTF_NUM 0x01
|
||||
|
||||
#define WEBUSB_URL_STRINGS \
|
||||
'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', \
|
||||
'c', 'h', 'e', 'r', 'r', 'y', '-', 'e', 'm', 'b', 'e', 'd', 'd', 'e', 'd', '/', 'C', 'h', 'e', 'r', 'r', 'y', 'U', 'S', 'B',
|
||||
|
||||
const uint8_t USBD_WinUSBDescriptorSetDescriptor[USBD_WINUSB_DESC_SET_LEN] = {
|
||||
// Microsoft OS 2.0 描述符集标头
|
||||
0x0A, 0x00, // Descriptor size (10 bytes)
|
||||
0x00, 0x00, // MS OS 2.0 descriptor set header
|
||||
0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000)
|
||||
USBD_WINUSB_DESC_SET_LEN, 0x00, // Size, MS OS 2.0 descriptor set
|
||||
|
||||
// Microsoft OS 2.0 配置子集标头
|
||||
0x08, 0x00, // wLength
|
||||
0x01, 0x00, // wDescriptorType
|
||||
0x00, // 适用于配置 1
|
||||
0x00, // bReserved
|
||||
0XA8, 0X00, // Size, MS OS 2.0 configuration subset
|
||||
|
||||
// Microsoft OS 2.0 功能子集头
|
||||
0x08, 0x00, // Descriptor size (8 bytes)
|
||||
0x02, 0x00, // MS OS 2.0 function subset header
|
||||
USBD_WEBUSB_INTF_NUM, // bFirstInterface
|
||||
0x00, // 必须设置为 0
|
||||
0xA0, 0x00,
|
||||
|
||||
// Microsoft OS 2.0 兼容 ID 描述符
|
||||
// 兼容 ID 描述符告诉 Windows 此设备与 WinUSB 驱动程序兼容
|
||||
0x14, 0x00, // wLength 20
|
||||
0x03, 0x00, // MS_OS_20_FEATURE_COMPATIBLE_ID
|
||||
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
// Microsoft OS 2.0 注册表属性描述符
|
||||
// 注册表属性分配设备接口 GUID
|
||||
0x84, 0x00, //wLength: 132
|
||||
0x04, 0x00, // wDescriptorType: MS_OS_20_FEATURE_REG_PROPERTY: 0x04 (Table 9)
|
||||
0x07, 0x00, //wPropertyDataType: REG_MULTI_SZ (Table 15)
|
||||
0x2a, 0x00, //wPropertyNameLength:
|
||||
//bPropertyName: “DeviceInterfaceGUID”
|
||||
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00,
|
||||
'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00,
|
||||
0x00, 0x00,
|
||||
0x50, 0x00, // wPropertyDataLength
|
||||
//bPropertyData: “{975F44D9-0D08-43FD-8B3E-127CA8AFFF9D}”.
|
||||
'{', 0x00, '9', 0x00, 'd', 0x00, '7', 0x00, 'd', 0x00, 'e', 0x00, 'b', 0x00, 'b', 0x00, 'c', 0x00, '-', 0x00,
|
||||
'c', 0x00, '8', 0x00, '5', 0x00, 'd', 0x00, '-', 0x00, '1', 0x00, '1', 0x00, 'd', 0x00, '1', 0x00, '-', 0x00,
|
||||
'9', 0x00, 'e', 0x00, 'b', 0x00, '4', 0x00, '-', 0x00, '0', 0x00, '0', 0x00, '6', 0x00, '0', 0x00, '0', 0x00,
|
||||
'8', 0x00, 'c', 0x00, '3', 0x00, 'a', 0x00, '1', 0x00, '9', 0x00, 'a', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const uint8_t USBD_WebUSBURLDescriptor[URL_DESCRIPTOR_LENGTH] = {
|
||||
URL_DESCRIPTOR_LENGTH,
|
||||
WEBUSB_URL_TYPE,
|
||||
WEBUSB_URL_SCHEME_HTTPS,
|
||||
WEBUSB_URL_STRINGS
|
||||
};
|
||||
|
||||
#define USBD_BOS_WTOTALLENGTH 0x39
|
||||
|
||||
#define LANDING_PAGE 0x01
|
||||
uint8_t USBD_BinaryObjectStoreDescriptor[USBD_BOS_WTOTALLENGTH] = {
|
||||
// BOS描述符
|
||||
0x05, // bLength 固长为5
|
||||
0x0F, // bDescriptorType 固定为15
|
||||
USBD_BOS_WTOTALLENGTH, 0x00, // wTotalLength BOS描述符的总大小
|
||||
0x02, // bNumDeviceCaps BOS描述符中独立设备功能特性描述符的数量
|
||||
|
||||
// WebUSB 平台功能描述符
|
||||
0x18, // Descriptor size (24 bytes)
|
||||
0x10, // Descriptor type (Device Capability) 设备功能描述符
|
||||
0x05, // Capability type (Platform) 平台描述符
|
||||
0x00, // Reserved
|
||||
|
||||
// WebUSB Platform Capability ID (3408b638-09a9-47a0-8bfd-a0768815b665)
|
||||
// 平台功能 UUID 将此标识为WebUSB 平台功能描述符,它提供有关设备的基本信息
|
||||
0x38, 0xB6, 0x08, 0x34,
|
||||
0xA9, 0x09,
|
||||
0xA0, 0x47,
|
||||
0x8B, 0xFD,
|
||||
0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65,
|
||||
|
||||
0x00, 0x01, // WebUSB version 1.0
|
||||
USBD_WEBUSB_VENDOR_CODE, // Vendor-assigned WebUSB request code
|
||||
LANDING_PAGE, // Landing page
|
||||
|
||||
// Microsoft 平台功能描述符
|
||||
// 标头
|
||||
0x1C, // Descriptor size (28 bytes)
|
||||
0x10, // Descriptor type (Device Capability)
|
||||
0x05, // Capability type (Platform)
|
||||
0x00, // Reserved
|
||||
|
||||
0xDF, 0x60, 0xDD, 0xD8, /* PlatformCapabilityUUID */
|
||||
0x89, 0x45, 0xC7, 0x4C,
|
||||
0x9C, 0xD2, 0x65, 0x9D,
|
||||
0x9E, 0x64, 0x8A, 0x9F,
|
||||
|
||||
// 描述符集信息结构
|
||||
0x00, 0x00, 0x03, 0x06, /* >= Win 8.1 * dwWindowsVersion 最低兼容 Windows 版本 */
|
||||
|
||||
USBD_WINUSB_DESC_SET_LEN, 0X00, /* wDescriptorSetTotalLength */
|
||||
|
||||
USBD_WINUSB_VENDOR_CODE, /* bVendorCode */
|
||||
0X00 /* bAltEnumCode */
|
||||
};
|
||||
|
||||
struct usb_webusb_descriptor webusb_url_desc = {
|
||||
.vendor_code = USBD_WEBUSB_VENDOR_CODE,
|
||||
.string = USBD_WebUSBURLDescriptor,
|
||||
.string_len = USBD_WINUSB_DESC_SET_LEN
|
||||
};
|
||||
|
||||
struct usb_msosv2_descriptor msosv2_desc = {
|
||||
.vendor_code = USBD_WINUSB_VENDOR_CODE,
|
||||
.compat_id = USBD_WinUSBDescriptorSetDescriptor,
|
||||
.compat_id_len = USBD_WINUSB_DESC_SET_LEN,
|
||||
};
|
||||
|
||||
struct usb_bos_descriptor bos_desc = {
|
||||
.string = USBD_BinaryObjectStoreDescriptor,
|
||||
.string_len = USBD_BOS_WTOTALLENGTH
|
||||
};
|
||||
|
||||
static const uint8_t webusb_hid_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
|
||||
/************** Descriptor of Joystick Mouse interface ****************/
|
||||
/* 09 */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
|
||||
0x00, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints */
|
||||
0x03, /* bInterfaceClass: HID */
|
||||
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
|
||||
0x01, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
|
||||
0, /* iInterface: Index of string descriptor */
|
||||
/******************** Descriptor of Joystick Mouse HID ********************/
|
||||
/* 18 */
|
||||
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_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
|
||||
0x00,
|
||||
/******************** Descriptor of Mouse endpoint ********************/
|
||||
/* 27 */
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||
HID_INT_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||
0x03, /* bmAttributes: Interrupt endpoint */
|
||||
HID_INT_EP_SIZE, /* wMaxPacketSize: 4 Byte max */
|
||||
0x00,
|
||||
HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
|
||||
/* 34 */
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(USBD_WEBUSB_INTF_NUM, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
///////////////////////////////////////
|
||||
/// string1 descriptor
|
||||
///////////////////////////////////////
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string2 descriptor
|
||||
///////////////////////////////////////
|
||||
0x26, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
' ', 0x00, /* wcChar9 */
|
||||
'H', 0x00, /* wcChar10 */
|
||||
'I', 0x00, /* wcChar11 */
|
||||
'D', 0x00, /* wcChar12 */
|
||||
' ', 0x00, /* wcChar13 */
|
||||
'D', 0x00, /* wcChar14 */
|
||||
'E', 0x00, /* wcChar15 */
|
||||
'M', 0x00, /* wcChar16 */
|
||||
'O', 0x00, /* wcChar17 */
|
||||
///////////////////////////////////////
|
||||
/// string3 descriptor
|
||||
///////////////////////////////////////
|
||||
0x16, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'2', 0x00, /* wcChar0 */
|
||||
'0', 0x00, /* wcChar1 */
|
||||
'2', 0x00, /* wcChar2 */
|
||||
'2', 0x00, /* wcChar3 */
|
||||
'1', 0x00, /* wcChar4 */
|
||||
'2', 0x00, /* wcChar5 */
|
||||
'3', 0x00, /* wcChar6 */
|
||||
'4', 0x00, /* wcChar7 */
|
||||
'5', 0x00, /* wcChar8 */
|
||||
'6', 0x00, /* wcChar9 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
};
|
||||
|
||||
/* USB HID device Configuration Descriptor */
|
||||
static uint8_t hid_desc[9] __ALIGN_END = {
|
||||
/* 18 */
|
||||
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_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
|
||||
0x00,
|
||||
};
|
||||
|
||||
static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = {
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x06, // USAGE (Keyboard)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
||||
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
|
||||
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
0x95, 0x08, // REPORT_COUNT (8)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x81, 0x03, // INPUT (Cnst,Var,Abs)
|
||||
0x95, 0x05, // REPORT_COUNT (5)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
0x05, 0x08, // USAGE_PAGE (LEDs)
|
||||
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
|
||||
0x29, 0x05, // USAGE_MAXIMUM (Kana)
|
||||
0x91, 0x02, // OUTPUT (Data,Var,Abs)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x75, 0x03, // REPORT_SIZE (3)
|
||||
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
|
||||
0x95, 0x06, // REPORT_COUNT (6)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0xFF, // LOGICAL_MAXIMUM (255)
|
||||
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
||||
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
|
||||
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
|
||||
0x81, 0x00, // INPUT (Data,Ary,Abs)
|
||||
0xc0 // END_COLLECTION
|
||||
};
|
||||
|
||||
#define HID_STATE_IDLE 0
|
||||
#define HID_STATE_BUSY 1
|
||||
|
||||
/*!< hid state ! Data can be sent only when state is idle */
|
||||
static volatile uint8_t hid_state = HID_STATE_IDLE;
|
||||
|
||||
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:
|
||||
hid_state = HID_STATE_IDLE;
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
hid_state = HID_STATE_IDLE;
|
||||
}
|
||||
|
||||
static struct usbd_endpoint hid_in_ep = {
|
||||
.ep_cb = usbd_hid_int_callback,
|
||||
.ep_addr = HID_INT_EP
|
||||
};
|
||||
|
||||
static struct usbd_interface intf0;
|
||||
|
||||
void webusb_hid_keyboard_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, webusb_hid_descriptor);
|
||||
usbd_bos_desc_register(busid, &bos_desc);
|
||||
usbd_msosv2_desc_register(busid, &msosv2_desc);
|
||||
usbd_webusb_desc_register(busid, &webusb_url_desc);
|
||||
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE));
|
||||
usbd_add_endpoint(busid, &hid_in_ep);
|
||||
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
}
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[64];
|
||||
|
||||
void hid_keyboard_test(uint8_t busid)
|
||||
{
|
||||
const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
if(usb_device_is_configured(busid) == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(write_buffer, sendbuffer, 8);
|
||||
hid_state = HID_STATE_BUSY;
|
||||
usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8);
|
||||
while (hid_state == HID_STATE_BUSY) {
|
||||
}
|
||||
}
|
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_cdc_acm.h"
|
||||
|
||||
#define WCID_VENDOR_CODE 0x17
|
||||
|
||||
@@ -151,18 +151,16 @@ __ALIGN_BEGIN const uint8_t WINUSB_IF1_WCIDProperties [142] __ALIGN_END = {
|
||||
|
||||
const uint8_t *WINUSB_IFx_WCIDProperties[] = {
|
||||
WINUSB_IF0_WCIDProperties,
|
||||
#if DOUBLE_WINUSB == 1
|
||||
WINUSB_IF1_WCIDProperties,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct usb_msosv1_descriptor msosv1_desc = {
|
||||
.string = WCID_StringDescriptor_MSOS,
|
||||
.vendor_code = WCID_VENDOR_CODE,
|
||||
.compat_id = WINUSB_WCIDDescriptor,
|
||||
#if DOUBLE_WINUSB == 0
|
||||
.comp_id_property = &WINUSB_IF0_WCIDProperties,
|
||||
#else
|
||||
.comp_id_property = WINUSB_IFx_WCIDProperties,
|
||||
#endif
|
||||
};
|
||||
|
||||
#define WINUSB_IN_EP 0x81
|
||||
@@ -328,7 +326,7 @@ const uint8_t winusb_descriptor[] = {
|
||||
0x02,
|
||||
0x01,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
@@ -446,7 +444,7 @@ struct usbd_interface intf1;
|
||||
|
||||
#endif
|
||||
|
||||
void winusb_init(uint8_t busid, uint32_t reg_base)
|
||||
void winusb_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, winusb_descriptor);
|
||||
usbd_msosv1_desc_register(busid, &msosv1_desc);
|
||||
|
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_cdc_acm.h"
|
||||
|
||||
#define WINUSB_IN_EP 0x81
|
||||
#define WINUSB_OUT_EP 0x02
|
||||
@@ -219,7 +219,7 @@ const uint8_t winusbv2_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
/* End */
|
||||
@@ -318,7 +318,7 @@ struct usb_bos_descriptor bos_desc = {
|
||||
.string_len = USBD_BOS_WTOTALLENGTH
|
||||
};
|
||||
|
||||
void winusbv2_init(uint8_t busid, uint32_t reg_base)
|
||||
void winusbv2_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, winusbv2_descriptor);
|
||||
usbd_bos_desc_register(busid, &bos_desc);
|
||||
|
@@ -255,7 +255,7 @@ const uint8_t winusbv2_descriptor[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
/* End */
|
||||
@@ -422,7 +422,7 @@ struct usb_bos_descriptor bos_desc = {
|
||||
.string_len = USBD_BOS_WTOTALLENGTH
|
||||
};
|
||||
|
||||
void winusbv2_init(uint8_t busid, uint32_t reg_base)
|
||||
void winusbv2_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, winusbv2_descriptor);
|
||||
usbd_bos_desc_register(busid, &bos_desc);
|
||||
|
Reference in New Issue
Block a user