hpw422移植新的sdk

This commit is contained in:
xushaoxiang
2026-07-03 18:08:25 +08:00
commit 945a5a5b0b
2583 changed files with 713209 additions and 0 deletions
@@ -0,0 +1,106 @@
/*!
* \file diskio.h
*
* \brief Target disk I/O implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "integer.h"
/*------------------------------------------------------------------------------------
Macros
------------------------------------------- -----------------------------------------*/
#define _USE_WRITE 1 /* 1: Enable disk_write function */
#define _USE_IOCTL 1 /* 1: Enable disk_ioctl function */
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
/*------------------------------------------------------------------------------------
Typedef
------------------------------------------------------------------------------------*/
/* Status of Disk Functions */
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
DWORD get_fattime (void);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,54 @@
/*!
* \file fatfs.h
*
* \brief Target FatFS implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __fatfs_H
#define __fatfs_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "ff.h"
#include "ff_gen_drv.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
extern char Path[4]; /* USER logical drive path */
extern FATFS FatFS; /* File system object for USER logical drive */
extern FIL File; /* File object for USER */
/*------------------------------------------------------------------------------------
Exported Functions
------------------------------------------- -----------------------------------------*/
void FATFS_Init(void);
#ifdef __cplusplus
}
#endif
#endif /*__fatfs_H */
@@ -0,0 +1,362 @@
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT file system module R0.12c /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2017, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/----------------------------------------------------------------------------*/
#ifndef _FF_H
#define _FF_H 68300 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h" /* Basic integer types */
#include "ffconf.h" /* FatFs configuration options */
#if _FF_H != _FFCONF
#error Wrong configuration file (ffconf.h).
#endif
/* Definitions of volume management */
#if _MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
#endif
/* Type of path name strings on FatFs API */
#if _LFN_UNICODE /* Unicode (UTF-16) string */
#if _USE_LFN == 0
#error _LFN_UNICODE must be 0 at non-LFN cfg.
#endif
#ifndef _INC_TCHAR
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#endif
#else /* ANSI/OEM string */
#ifndef _INC_TCHAR
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* Type of file size variables */
#if _FS_EXFAT
#if _USE_LFN == 0
#error LFN must be enabled when enable exFAT
#endif
typedef QWORD FSIZE_t;
#else
typedef DWORD FSIZE_t;
#endif
/* File system object structure (FATFS) */
typedef struct {
BYTE fs_type; /* File system type (0:N/A) */
BYTE drv; /* Physical drive number */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
WORD id; /* File system mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
WORD csize; /* Cluster size [sectors] */
#if _MAX_SS != _MIN_SS
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
#endif
#if _USE_LFN != 0
WCHAR* lfnbuf; /* LFN working buffer */
#endif
#if _FS_EXFAT
BYTE* dirbuf; /* Directory entry block scratchpad buffer */
#endif
#if _FS_REENTRANT
_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !_FS_READONLY
DWORD last_clst; /* Last allocated cluster */
DWORD free_clst; /* Number of free clusters */
#endif
#if _FS_RPATH != 0
DWORD cdir; /* Current directory start cluster (0:root) */
#if _FS_EXFAT
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */
DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */
#endif
#endif
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
DWORD fsize; /* Size of an FAT [sectors] */
DWORD volbase; /* Volume base sector */
DWORD fatbase; /* FAT base sector */
DWORD dirbase; /* Root directory base sector/cluster */
DWORD database; /* Data base sector */
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFS;
/* Object ID and allocation information (_FDID) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
BYTE attr; /* Object attribute */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous (no data on FAT), =3:flagmented in this session, b2:sub-directory stretched) */
DWORD sclust; /* Object start cluster (0:no cluster or root directory) */
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
#if _FS_EXFAT
DWORD n_cont; /* Size of first fragment, clusters - 1 (valid when stat == 3) */
DWORD n_frag; /* Size of last fragment needs to be written (valid when not zero) */
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
DWORD c_ofs; /* Offset in the containing directory (valid when sclust != 0 and non-directory object) */
#endif
#if _FS_LOCK != 0
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif
} _FDID;
/* File object structure (FIL) */
typedef struct {
_FDID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */
DWORD sect; /* Sector number appearing in buf[] (0:invalid) */
#if !_FS_READONLY
DWORD dir_sect; /* Sector number containing the directory entry */
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
#endif
#if _USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS]; /* File private data read/write window */
#endif
} FIL;
/* Directory object structure (DIR) */
typedef struct {
_FDID obj; /* Object identifier */
DWORD dptr; /* Current read/write offset */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector (0:Read operation has terminated) */
BYTE* dir; /* Pointer to the directory item in the win[] */
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */
#if _USE_LFN != 0
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
#endif
#if _USE_FIND
const TCHAR* pat; /* Pointer to the name matching pattern */
#endif
} DIR;
/* File information structure (FILINFO) */
typedef struct {
FSIZE_t fsize; /* File size */
WORD fdate; /* Modified date */
WORD ftime; /* Modified time */
BYTE fattrib; /* File attribute */
#if _USE_LFN != 0
TCHAR altname[13]; /* Alternative file name */
TCHAR fname[_MAX_LFN + 1]; /* Primary file name */
#else
TCHAR fname[13]; /* File name */
#endif
} FILINFO;
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_LOCK */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
FRESULT f_close (FIL* fp); /* Close an open file object */
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */
FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */
FRESULT f_truncate (FIL* fp); /* Truncate the file */
FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
FRESULT f_closedir (DIR* dp); /* Close an open directory */
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */
FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->obj.objsize)
#define f_rewind(fp) f_lseek((fp), 0)
#define f_rewinddir(dp) f_readdir((dp), 0)
#define f_rmdir(path) f_unlink(path)
#define f_unmount(path) f_mount(0, path, 0)
#ifndef EOF
#define EOF (-1)
#endif
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* RTC function */
#if !_FS_READONLY && !_FS_NORTC
DWORD get_fattime (void);
#endif
/* Unicode support functions */
#if _USE_LFN != 0 /* Unicode - OEM code conversion */
WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */
WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */
#if _USE_LFN == 3 /* Memory functions */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
#endif
#endif
/* Sync functions */
#if _FS_REENTRANT
int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */
int ff_req_grant (_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* File access mode and open method flags (3rd argument of f_open) */
#define FA_READ 0x01
#define FA_WRITE 0x02
#define FA_OPEN_EXISTING 0x00
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA_OPEN_APPEND 0x30
/* Fast seek controls (2nd argument of f_lseek) */
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
/* Format options (2nd argument of f_mkfs) */
#define FM_FAT 0x01
#define FM_FAT32 0x02
#define FM_EXFAT 0x04
#define FM_ANY 0x07
#define FM_SFD 0x08
/* Filesystem type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
#define FS_EXFAT 4
/* File attribute bits for directory entry (FILINFO.fattrib) */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
#ifdef __cplusplus
}
#endif
#endif /* _FATFS */
@@ -0,0 +1,80 @@
/**
******************************************************************************
* @file ff_gen_drv.h
* @author MCD Application Team
* @brief Header for ff_gen_drv.c module.
*****************************************************************************
* @attention
*
* Copyright (c) 2017 STMicroelectronics. All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
**/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __FF_GEN_DRV_H
#define __FF_GEN_DRV_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "diskio.h"
#include "ff.h"
#include "stdint.h"
/* Exported types ------------------------------------------------------------*/
/**
* @brief Disk IO Driver structure definition
*/
typedef struct
{
DSTATUS (*disk_initialize) (BYTE); /*!< Initialize Disk Drive */
DSTATUS (*disk_status) (BYTE); /*!< Get Disk Status */
DRESULT (*disk_read) (BYTE, BYTE*, DWORD, UINT); /*!< Read Sector(s) */
#if _USE_WRITE == 1
DRESULT (*disk_write) (BYTE, const BYTE*, DWORD, UINT); /*!< Write Sector(s) when _USE_WRITE = 0 */
#endif /* _USE_WRITE == 1 */
#if _USE_IOCTL == 1
DRESULT (*disk_ioctl) (BYTE, BYTE, void*); /*!< I/O control operation when _USE_IOCTL = 1 */
#endif /* _USE_IOCTL == 1 */
}Diskio_drvTypeDef;
/**
* @brief Global Disk IO Drivers structure definition
*/
typedef struct
{
uint8_t is_initialized[_VOLUMES];
const Diskio_drvTypeDef *drv[_VOLUMES];
uint8_t lun[_VOLUMES];
volatile uint8_t nbr;
}Disk_drvTypeDef;
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
uint8_t FATFS_LinkDriver(const Diskio_drvTypeDef *drv, char *path);
uint8_t FATFS_UnLinkDriver(char *path);
uint8_t FATFS_LinkDriverEx(const Diskio_drvTypeDef *drv, char *path, BYTE lun);
uint8_t FATFS_UnLinkDriverEx(char *path, BYTE lun);
uint8_t FATFS_GetAttachedDriversNbr(void);
#ifdef __cplusplus
}
#endif
#endif /* __FF_GEN_DRV_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,267 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* FatFs - Generic FAT file system module R0.12c (C)ChaN, 2017
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
#ifndef _FFCONF
#define _FFCONF 68300 /* Revision ID */
/*-----------------------------------------------------------------------------/
/ Additional user header to be used
/-----------------------------------------------------------------------------*/
//#include "main.h"
//#include "stm32f4xx_hal.h"
/*-----------------------------------------------------------------------------/
/ Function Configurations
/-----------------------------------------------------------------------------*/
#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/ and optional writing functions as well. */
#define _FS_MINIMIZE 0 /* 0 to 3 */
/* This option defines minimization level to remove some basic API functions.
/
/ 0: All basic functions are enabled.
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
/ are removed.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
#define _USE_STRFUNC 2 /* 0:Disable or 1-2:Enable */
/* This option switches string functions, f_gets(), f_putc(), f_puts() and
/ f_printf().
/
/ 0: Disable string functions.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
#define _USE_FIND 0
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
#define _USE_MKFS 1
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#define _USE_FASTSEEK 1
/* This option switches fast seek feature. (0:Disable or 1:Enable) */
#define _USE_EXPAND 0
/* This option switches f_expand function. (0:Disable or 1:Enable) */
#define _USE_CHMOD 0
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
/ (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */
#define _USE_LABEL 1
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */
#define _USE_FORWARD 0
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
/*-----------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/-----------------------------------------------------------------------------*/
#define _CODE_PAGE 437//850
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
/ 1 - ASCII (No extended character. Non-LFN cfg. only)
/ 437 - U.S.
/ 720 - Arabic
/ 737 - Greek
/ 771 - KBL
/ 775 - Baltic
/ 850 - Latin 1
/ 852 - Latin 2
/ 855 - Cyrillic
/ 857 - Turkish
/ 860 - Portuguese
/ 861 - Icelandic
/ 862 - Hebrew
/ 863 - Canadian French
/ 864 - Arabic
/ 865 - Nordic
/ 866 - Russian
/ 869 - Greek 2
/ 932 - Japanese (DBCS)
/ 936 - Simplified Chinese (DBCS)
/ 949 - Korean (DBCS)
/ 950 - Traditional Chinese (DBCS)
*/
#define _USE_LFN 0 /* 0 to 3 */
#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
/* The _USE_LFN switches the support of long file name (LFN).
/
/ 0: Disable support of LFN. _MAX_LFN has no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added
/ to the project. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and
/ additional 608 bytes at exFAT enabled. _MAX_LFN can be in range from 12 to 255.
/ It should be set 255 to support full featured LFN operations.
/ When use stack for the working buffer, take care on stack overflow. When use heap
/ memory for the working buffer, memory management functions, ff_memalloc() and
/ ff_memfree(), must be added to the project. */
#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */
/* This option switches character encoding on the API. (0:ANSI/OEM or 1:UTF-16)
/ To use Unicode string for the path name, enable LFN and set _LFN_UNICODE = 1.
/ This option also affects behavior of string I/O functions. */
#define _STRF_ENCODE 3
/* When _LFN_UNICODE == 1, this option selects the character encoding ON THE FILE to
/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
/
/ 0: ANSI/OEM
/ 1: UTF-16LE
/ 2: UTF-16BE
/ 3: UTF-8
/
/ This option has no effect when _LFN_UNICODE == 0. */
#define _FS_RPATH 0 /* 0 to 2 */
/* This option configures support of relative path.
/
/ 0: Disable relative path and remove related functions.
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
/ 2: f_getcwd() function is available in addition to 1.
*/
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/----------------------------------------------------------------------------*/
#define _VOLUMES 1
/* Number of volumes (logical drives) to be used. */
/* USER CODE BEGIN Volumes */
#define _STR_VOLUME_ID 0 /* 0:Use only 0-9 for drive ID, 1:Use strings for drive ID */
#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
/* _STR_VOLUME_ID switches string support of volume ID.
/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
/ the drive ID strings are: A-Z and 0-9. */
/* USER CODE END Volumes */
#define _MULTI_PARTITION 0 /* 0:Single partition, 1:Multiple partition */
/* This option switches support of multi-partition on a physical drive.
/ By default (0), each logical drive number is bound to the same physical drive
/ number and only an FAT volume found on the physical drive will be mounted.
/ When multi-partition is enabled (1), each logical drive number can be bound to
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
/ function will be available. */
#define _MIN_SS 512 /* 512, 1024, 2048 or 4096 */
#define _MAX_SS 512//4096 /* 512, 1024, 2048 or 4096 */
/* These options configure the range of sector size to be supported. (512, 1024,
/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
/ disk_ioctl() function. */
#define _USE_TRIM 0
/* This option switches support of ATA-TRIM. (0:Disable or 1:Enable)
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
/ disk_ioctl() function. */
#define _FS_NOFSINFO 0 /* 0,1,2 or 3 */
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
/ bit0=1: Do not trust free cluster count in the FSINFO.
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
*/
/*---------------------------------------------------------------------------/
/ System Configurations
/----------------------------------------------------------------------------*/
#define _FS_TINY 0 /* 0:Normal or 1:Tiny */
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of file object (FIL) is reduced _MAX_SS bytes.
/ Instead of private sector buffer eliminated from the file object, common sector
/ buffer in the file system object (FATFS) is used for the file data transfer. */
#define _FS_EXFAT 0
/* This option switches support of exFAT file system. (0:Disable or 1:Enable)
/ When enable exFAT, also LFN needs to be enabled. (_USE_LFN >= 1)
/ Note that enabling exFAT discards C89 compatibility. */
#define _FS_NORTC 0
#define _NORTC_MON 6
#define _NORTC_MDAY 4
#define _NORTC_YEAR 2015
/* The option _FS_NORTC switches timestamp functiton. If the system does not have
/ any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable
/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time.
/ To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be
/ added to the project to get current time form real-time clock. _NORTC_MON,
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
/ These options have no effect at read-only configuration (_FS_READONLY = 1). */
#define _FS_LOCK 2 /* 0:Disable or >=1:Enable */
/* The option _FS_LOCK switches file lock function to control duplicated file open
/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
/ is 1.
/
/ 0: Disable file lock function. To avoid volume corruption, application program
/ should avoid illegal open, remove and rename to the open objects.
/ >0: Enable file lock function. The value defines how many files/sub-directories
/ can be opened simultaneously under file lock control. Note that the file
/ lock control is independent of re-entrancy. */
#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */
#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */
#define _SYNC_t NULL
/* The option _FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
/ module itself. Note that regardless of this option, file access to different
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
/ to the same volume is under control of this function.
/
/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
/ function, must be added to the project. Samples are available in
/ option/syscall.c.
/
/ The _FS_TIMEOUT defines timeout period in unit of time tick.
/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.h. */
/* define the ff_malloc ff_free macros as standard malloc free */
#if !defined(ff_malloc) && !defined(ff_free)
#include <stdlib.h>
#define ff_malloc malloc
#define ff_free free
#endif
#endif /* _FFCONF */
@@ -0,0 +1,38 @@
/*-------------------------------------------*/
/* Integer type definitions for FatFs module */
/*-------------------------------------------*/
#ifndef _FF_INTEGER
#define _FF_INTEGER
#ifdef _WIN32 /* FatFs development platform */
#include <windows.h>
#include <tchar.h>
typedef unsigned __int64 QWORD;
#else /* Embedded platform */
/* These types MUST be 16-bit or 32-bit */
typedef int INT;
typedef unsigned int UINT;
/* This type MUST be 8-bit */
typedef unsigned char BYTE;
/* These types MUST be 16-bit */
typedef short SHORT;
typedef unsigned short WORD;
typedef unsigned short WCHAR;
/* These types MUST be 32-bit */
typedef long LONG;
typedef unsigned long DWORD;
/* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */
typedef unsigned long long QWORD;
#endif
#endif
@@ -0,0 +1,254 @@
/*!
* \file diskio.c
*
* \brief Target disk I/O implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "diskio.h"
#include "ff_gen_drv.h"
#include "usbd_msc_flash.h"
#include "time_conv.h"
/*------------------------------------------------------------------------------------
Macros
------------------------------------------- -----------------------------------------*/
#if defined ( __GNUC__ )
#ifndef __weak
#define __weak __attribute__((weak))
#endif
#endif
#define DEV_USB 0 /* Example: Map USB MSD to physical drive 0 */
/*------------------------------------------------------------------------------------
Global Variables
------------------------------------------- -----------------------------------------*/
extern Disk_drvTypeDef disk;
/*------------------------------------------------------------------------------------
Functions
------------------------------------------- -----------------------------------------*/
/**
* @brief Gets Disk Status
* @param pdrv: Physical drive number (0..)
* @retval DSTATUS: Operation status
*/
DSTATUS disk_status (
BYTE pdrv /* Physical drive number to identify the drive */
)
{
DSTATUS stat = STA_NOINIT;
// stat = disk.drv[pdrv]->disk_status(disk.lun[pdrv]);
if( FAT_FLASH_ID == Fat_Flash_ReadID( ) )
{
stat = RES_OK;
}
else
{
stat = STA_NOINIT;
}
return stat;
}
/**
* @brief Initializes a Drive
* @param pdrv: Physical drive number (0..)
* @retval DSTATUS: Operation status
*/
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat = STA_NOINIT;
switch(pdrv)
{
case DEV_USB:
{
if( true == Disk_Init() )
stat = RES_OK;
}
break;
}
// if(disk.is_initialized[pdrv] == 0)
// {
// disk.is_initialized[pdrv] = 1;
// stat = disk.drv[pdrv]->disk_initialize(disk.lun[pdrv]);
// }
return stat;
}
/**
* @brief Reads Sector(s)
* @param pdrv: Physical drive number (0..)
* @param *buff: Data buffer to store read data
* @param sector: Sector address (LBA)
* @param count: Number of sectors to read (1..128)
* @retval DRESULT: Operation result
*/
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to read */
)
{
DRESULT res = RES_ERROR;
switch (pdrv)
{
case DEV_USB:
{
if( Disk_UnitRead(sector, count, buff) == true )
{
res = RES_OK;
}
}
break;
}
// res = disk.drv[pdrv]->disk_read(disk.lun[pdrv], buff, sector, count);
return res;
}
/**
* @brief Writes Sector(s)
* @param pdrv: Physical drive number (0..)
* @param *buff: Data to be written
* @param sector: Sector address (LBA)
* @param count: Number of sectors to write (1..128)
* @retval DRESULT: Operation result
*/
#if _USE_WRITE == 1
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res = RES_ERROR;
switch(pdrv)
{
case DEV_USB:
{
if( Disk_UnitWrite(sector, count, (uint8_t *)buff) == true )
{
res = RES_OK;
}
}
break;
}
// res = disk.drv[pdrv]->disk_write(disk.lun[pdrv], buff, sector, count);
return res;
}
#endif /* _USE_WRITE == 1 */
/**
* @brief I/O control operation
* @param pdrv: Physical drive number (0..)
* @param cmd: Control code
* @param *buff: Buffer to send/receive control data
* @retval DRESULT: Operation result
*/
#if _USE_IOCTL == 1
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res = RES_PARERR;
switch(pdrv)
{
case DEV_USB:
{
switch(cmd)
{
case CTRL_SYNC:
res = RES_OK;
break;
case GET_SECTOR_COUNT:
{
*(DWORD *)buff = Disk_UnitCount( );
res = RES_OK;
break;
}
case GET_SECTOR_SIZE:
{
*(DWORD *)buff = Disk_UnitSize( );
res = RES_OK;
break;
}
case GET_BLOCK_SIZE:
{
*(DWORD *)buff = 1;
res = RES_OK;
break;
}
default:
res = RES_PARERR;
break;
}
}
break;
}
// res = disk.drv[pdrv]->disk_ioctl(disk.lun[pdrv], cmd, buff);
return res;
}
#endif /* _USE_IOCTL == 1 */
/**
* @brief Gets Time from RTC
* @param None
* @retval Time in DWORD
*/
__weak DWORD get_fattime (void)
{
uint32_t fattime;
// utc sec convert to utc date
DateTime_t tmp_date = UTC_SecToDate(Utc_TotalSec);
tmp_date = UTC_DateToZoneDate(TIME_ZONE, YEAR_BASE, tmp_date.year, tmp_date.month,
tmp_date.day, tmp_date.hour, tmp_date.min,
tmp_date.sec, tmp_date.week);
fattime = ((YEAR_BASE + tmp_date.year - 1980) << 25) | (tmp_date.month << 21) |
(tmp_date.day << 16) | (tmp_date.hour <<11) | (tmp_date.min << 5) |
(tmp_date.sec >> 1);
return fattime;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,78 @@
/*!
* \file fatfs.c
*
* \brief Target FatFS implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "fatfs.h"
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
char Path[4]; /* Logical drive path */
FATFS FatFS; /* File system object for Logical drive */
FIL File; /* File object */
DIR Dir;
uint8_t buffer[_MAX_SS];
/*------------------------------------------------------------------------------------
Functions
------------------------------------------------------------------------------------*/
/**
* @brief FatFS Initalization
* @param void
* @retval void
*/
void FATFS_Init(void)
{
FRESULT res;
DEBUG("FatFS Init\r\n");
res = f_mount(&FatFS, "0:", 1);
DEBUG("Mount FRESULT: %d\r\n", res);
res = f_opendir(&Dir, "0:");
DEBUG("Read Dir: %d\r\n", res);
if (FR_NO_FILESYSTEM == res) {
res = f_mkfs("0:", FM_FAT, _MAX_SS, buffer, sizeof(buffer));
DEBUG("Format FRESULT: %d\r\n", res);
res = f_unmount("0:");
DEBUG("Umount FRESULT: %d\r\n", res);
// res = f_setlabel( "XinChip" );
// DEBUG("Set label: %d\r\n", res);
res = f_mount(&FatFS, "0:", 1);
DEBUG("Remount FRESULT: %d\r\n", res);
res = f_unmount("0:");
DEBUG("Umount FRESULT: %d\r\n", res);
} else {
res = f_unmount("0:");
DEBUG("Umount FRESULT: %d\r\n", res);
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,122 @@
/**
******************************************************************************
* @file ff_gen_drv.c
* @author MCD Application Team
* @brief FatFs generic low level driver.
*****************************************************************************
* @attention
*
* Copyright (c) 2017 STMicroelectronics. All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
**/
/* Includes ------------------------------------------------------------------*/
#include "ff_gen_drv.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
Disk_drvTypeDef disk = {{0},{0},{0},0};
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief Links a compatible diskio driver/lun id and increments the number of active
* linked drivers.
* @note The number of linked drivers (volumes) is up to 10 due to FatFs limits.
* @param drv: pointer to the disk IO Driver structure
* @param path: pointer to the logical drive path
* @param lun : only used for USB Key Disk to add multi-lun management
else the parameter must be equal to 0
* @retval Returns 0 in case of success, otherwise 1.
*/
uint8_t FATFS_LinkDriverEx(const Diskio_drvTypeDef *drv, char *path, uint8_t lun)
{
uint8_t ret = 1;
uint8_t DiskNum = 0;
if(disk.nbr < _VOLUMES)
{
disk.is_initialized[disk.nbr] = 0;
disk.drv[disk.nbr] = drv;
disk.lun[disk.nbr] = lun;
DiskNum = disk.nbr++;
path[0] = DiskNum + '0';
path[1] = ':';
path[2] = '/';
path[3] = 0;
ret = 0;
}
return ret;
}
/**
* @brief Links a compatible diskio driver and increments the number of active
* linked drivers.
* @note The number of linked drivers (volumes) is up to 10 due to FatFs limits
* @param drv: pointer to the disk IO Driver structure
* @param path: pointer to the logical drive path
* @retval Returns 0 in case of success, otherwise 1.
*/
uint8_t FATFS_LinkDriver(const Diskio_drvTypeDef *drv, char *path)
{
return FATFS_LinkDriverEx(drv, path, 0);
}
/**
* @brief Unlinks a diskio driver and decrements the number of active linked
* drivers.
* @param path: pointer to the logical drive path
* @param lun : not used
* @retval Returns 0 in case of success, otherwise 1.
*/
uint8_t FATFS_UnLinkDriverEx(char *path, uint8_t lun)
{
uint8_t DiskNum = 0;
uint8_t ret = 1;
if(disk.nbr >= 1)
{
DiskNum = path[0] - '0';
if(disk.drv[DiskNum] != 0)
{
disk.drv[DiskNum] = 0;
disk.lun[DiskNum] = 0;
disk.nbr--;
ret = 0;
}
}
return ret;
}
/**
* @brief Unlinks a diskio driver and decrements the number of active linked
* drivers.
* @param path: pointer to the logical drive path
* @retval Returns 0 in case of success, otherwise 1.
*/
uint8_t FATFS_UnLinkDriver(char *path)
{
return FATFS_UnLinkDriverEx(path, 0);
}
/**
* @brief Gets number of linked drivers to the FatFs module.
* @param None
* @retval Number of attached drivers.
*/
uint8_t FATFS_GetAttachedDriversNbr(void)
{
return disk.nbr;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,183 @@
/*!
* \file usbd_cdc.h
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_CDC_H
#define __USB_CDC_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @defgroup usbd_cdc
* @brief This file is the Header file for usbd_cdc.c
* @{
*/
/** @defgroup usbd_cdc_Exported_Defines
* @{
*/
#ifndef CDC_IN_EP
#define CDC_IN_EP 0x81U /* EP1 for data IN */
#endif /* CDC_IN_EP */
#ifndef CDC_OUT_EP
#define CDC_OUT_EP 0x01U /* EP1 for data OUT */
#endif /* CDC_OUT_EP */
#ifndef CDC_CMD_EP
#define CDC_CMD_EP 0x82U /* EP2 for CDC commands */
#endif /* CDC_CMD_EP */
#define SECOND_CDC_OUT_EP 0x03U /* EP3 for CDC data OUT */
#define SECOND_CDC_IN_EP 0x83U /* EP3 for CDC data IN */
#define SECOND_CDC_CMD_EP 0x84U /* EP4 for CDC commands */
#ifndef CDC_HS_BINTERVAL
#define CDC_HS_BINTERVAL 0x10U
#endif /* CDC_HS_BINTERVAL */
#ifndef CDC_FS_BINTERVAL
#define CDC_FS_BINTERVAL 0x10U
#endif /* CDC_FS_BINTERVAL */
/* CDC Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */
#define CDC_DATA_HS_MAX_PACKET_SIZE 512U /* Endpoint IN & OUT Packet size */
#define CDC_DATA_FS_MAX_PACKET_SIZE 64U /* Endpoint IN & OUT Packet size */
#define CDC_CMD_PACKET_SIZE 8U /* Control Endpoint Packet size */
#define USB_CDC_CONFIG_DESC_SIZ 67U
#define CDC_DATA_HS_IN_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE
#define CDC_DATA_HS_OUT_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE
#define CDC_DATA_FS_IN_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE
#define CDC_DATA_FS_OUT_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE
#define CDC_REQ_MAX_DATA_SIZE 0x7U
/*---------------------------------------------------------------------*/
/* CDC definitions */
/*---------------------------------------------------------------------*/
#define CDC_SEND_ENCAPSULATED_COMMAND 0x00U
#define CDC_GET_ENCAPSULATED_RESPONSE 0x01U
#define CDC_SET_COMM_FEATURE 0x02U
#define CDC_GET_COMM_FEATURE 0x03U
#define CDC_CLEAR_COMM_FEATURE 0x04U
#define CDC_SET_LINE_CODING 0x20U
#define CDC_GET_LINE_CODING 0x21U
#define CDC_SET_CONTROL_LINE_STATE 0x22U
#define CDC_SEND_BREAK 0x23U
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
/**
* @}
*/
typedef struct
{
uint32_t bitrate;
uint8_t format;
uint8_t paritytype;
uint8_t datatype;
} USBD_CDC_LineCodingTypeDef;
typedef struct _USBD_CDC_Itf
{
int8_t (* Init)(void);
int8_t (* DeInit)(void);
int8_t (* Control)(uint8_t cmd, uint8_t *pbuf, uint16_t length);
int8_t (* Receive)(uint8_t *Buf, uint32_t *Len);
int8_t (* TransmitCplt)(uint8_t *Buf, uint32_t *Len, uint8_t epnum);
} USBD_CDC_ItfTypeDef;
typedef struct
{
uint32_t data[CDC_DATA_FS_MAX_PACKET_SIZE / 4U]; /* Force 32-bit alignment */
uint8_t CmdOpCode;
uint8_t CmdLength;
uint8_t *RxBuffer;
uint8_t *TxBuffer;
uint32_t RxLength;
uint32_t TxLength;
__IO uint32_t TxState;
__IO uint32_t RxState;
} USBD_CDC_HandleTypeDef;
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_CDC;
#define USBD_CDC_CLASS &USBD_CDC
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev,
USBD_CDC_ItfTypeDef *fops);
uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff,
uint32_t length);
uint8_t USBD_CDC_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff);
uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev);
uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_CDC_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,877 @@
/*!
* \file usbd_cdc.c
*
* \brief This file provides the high layer firmware functions to manage the
* following functionalities of the USB CDC Class:
* - Initialization and Configuration of high and low layer
* - Enumeration as CDC Device (and enumeration for each implemented
* memory interface)
* - OUT/IN data transfer
* - Command IN transfer (class requests management)
* - Error management
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*
******************************************************************************
* @verbatim
*
* ===================================================================
* CDC Class Driver Description
* ===================================================================
* This driver manages the "Universal Serial Bus Class Definitions for Communications Devices
* Revision 1.2 November 16, 2007" and the sub-protocol specification of "Universal Serial Bus
* Communications Class Subclass Specification for PSTN Devices Revision 1.2 February 9, 2007"
* This driver implements the following aspects of the specification:
* - Device descriptor management
* - Configuration descriptor management
* - Enumeration as CDC device with 2 data endpoints (IN and OUT) and 1 command endpoint (IN)
* - Requests management (as described in section 6.2 in specification)
* - Abstract Control Model compliant
* - Union Functional collection (using 1 IN endpoint for control)
* - Data interface class
*
* These aspects may be enriched or modified for a specific user application.
*
* This driver doesn't implement the following aspects of the specification
* (but it is possible to manage these features with some modifications on this driver):
* - Any class-specific aspect relative to communication classes should be managed by user application.
* - All communication classes other than PSTN are not managed
*
* @endverbatim
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc.h"
#include "usbd_ctlreq.h"
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev);
#ifndef USE_USBD_COMPOSITE
static uint8_t *USBD_CDC_GetFSCfgDesc(uint16_t *length);
static uint8_t *USBD_CDC_GetHSCfgDesc(uint16_t *length);
static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length);
uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length);
#endif /* USE_USBD_COMPOSITE */
#ifndef USE_USBD_COMPOSITE
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_CDC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
};
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* CDC interface class callbacks structure */
USBD_ClassTypeDef USBD_CDC =
{
USBD_CDC_Init,
USBD_CDC_DeInit,
USBD_CDC_Setup,
NULL, /* EP0_TxSent */
USBD_CDC_EP0_RxReady,
USBD_CDC_DataIn,
USBD_CDC_DataOut,
NULL,
NULL,
NULL,
#ifdef USE_USBD_COMPOSITE
NULL,
NULL,
NULL,
NULL,
#else
USBD_CDC_GetHSCfgDesc,
USBD_CDC_GetFSCfgDesc,
USBD_CDC_GetOtherSpeedCfgDesc,
USBD_CDC_GetDeviceQualifierDescriptor,
#endif /* USE_USBD_COMPOSITE */
};
#ifndef USE_USBD_COMPOSITE
/* USB CDC device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_CDC_CfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
{
/* Configuration Descriptor */
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength */
0x00,
0x02, /* bNumInterfaces: 2 interfaces */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor
describing the configuration */
#if (USBD_SELF_POWERED == 1U)
0xE0, /* bmAttributes: Bus Powered according to user configuration */
#else
0xA0, /* bmAttributes: Bus Powered according to user configuration */
#endif /* USBD_SELF_POWERED */
USBD_MAX_POWER, /* MaxPower (mA) */
/*---------------------------------------------------------------------------*/
/* Interface Descriptor */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
/* Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoint used */
0x02, /* bInterfaceClass: Communication Interface Class */
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */
0x00, /* iInterface */
/* Header Functional Descriptor */
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
/* Call Management Functional Descriptor */
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00, /* bmCapabilities: D0+D1 */
0x01, /* bDataInterface */
/* ACM Functional Descriptor */
0x04, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities */
/* Union Functional Descriptor */
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
0x00, /* bMasterInterface: Communication class interface */
0x01, /* bSlaveInterface0: Data Class Interface */
/* Endpoint 2 Descriptor */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_CMD_EP, /* bEndpointAddress */
0x03, /* bmAttributes: Interrupt */
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize */
HIBYTE(CDC_CMD_PACKET_SIZE),
CDC_FS_BINTERVAL, /* bInterval */
/*---------------------------------------------------------------------------*/
/* Data class interface descriptor */
0x09, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
0x01, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0x0A, /* bInterfaceClass: CDC */
0x00, /* bInterfaceSubClass */
0x00, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Endpoint OUT Descriptor */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_OUT_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval */
/* Endpoint IN Descriptor */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_IN_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00 /* bInterval */
};
#endif /* USE_USBD_COMPOSITE */
static uint8_t CDCInEpAdd = CDC_IN_EP;
static uint8_t CDCOutEpAdd = CDC_OUT_EP;
static uint8_t CDCCmdEpAdd = CDC_CMD_EP;
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Functions
* @{
*/
/**
* @brief USBD_CDC_Init
* Initialize the CDC interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
USBD_CDC_HandleTypeDef *hcdc;
hcdc = (USBD_CDC_HandleTypeDef *)USBD_malloc(sizeof(USBD_CDC_HandleTypeDef));
if (hcdc == NULL)
{
pdev->pClassDataCmsit[pdev->classId] = NULL;
return (uint8_t)USBD_EMEM;
}
(void)USBD_memset(hcdc, 0, sizeof(USBD_CDC_HandleTypeDef));
pdev->pClassDataCmsit[pdev->classId] = (void *)hcdc;
pdev->pClassData = pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
CDCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK);
CDCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK);
CDCCmdEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR);
#endif /* USE_USBD_COMPOSITE */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, CDCInEpAdd, USBD_EP_TYPE_BULK,
CDC_DATA_HS_IN_PACKET_SIZE);
pdev->ep_in[CDCInEpAdd & 0xFU].is_used = 1U;
/* Open EP OUT */
(void)USBD_LL_OpenEP(pdev, CDCOutEpAdd, USBD_EP_TYPE_BULK,
CDC_DATA_HS_OUT_PACKET_SIZE);
pdev->ep_out[CDCOutEpAdd & 0xFU].is_used = 1U;
/* Set bInterval for CDC CMD Endpoint */
pdev->ep_in[CDCCmdEpAdd & 0xFU].bInterval = CDC_HS_BINTERVAL;
}
else
{
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, CDCInEpAdd, USBD_EP_TYPE_BULK,
CDC_DATA_FS_IN_PACKET_SIZE);
pdev->ep_in[CDCInEpAdd & 0xFU].is_used = 1U;
/* Open EP OUT */
(void)USBD_LL_OpenEP(pdev, CDCOutEpAdd, USBD_EP_TYPE_BULK,
CDC_DATA_FS_OUT_PACKET_SIZE);
pdev->ep_out[CDCOutEpAdd & 0xFU].is_used = 1U;
/* Set bInterval for CMD Endpoint */
pdev->ep_in[CDCCmdEpAdd & 0xFU].bInterval = CDC_FS_BINTERVAL;
}
/* Open Command IN EP */
(void)USBD_LL_OpenEP(pdev, CDCCmdEpAdd, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);
pdev->ep_in[CDCCmdEpAdd & 0xFU].is_used = 1U;
hcdc->RxBuffer = NULL;
/* Init physical Interface components */
((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->Init();
/* Init Xfer states */
hcdc->TxState = 0U;
hcdc->RxState = 0U;
if (hcdc->RxBuffer == NULL)
{
return (uint8_t)USBD_EMEM;
}
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Prepare Out endpoint to receive next packet */
(void)USBD_LL_PrepareReceive(pdev, CDCOutEpAdd, hcdc->RxBuffer,
CDC_DATA_HS_OUT_PACKET_SIZE);
}
else
{
/* Prepare Out endpoint to receive next packet */
(void)USBD_LL_PrepareReceive(pdev, CDCOutEpAdd, hcdc->RxBuffer,
CDC_DATA_FS_OUT_PACKET_SIZE);
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CDC_Init
* DeInitialize the CDC layer
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this CDC class instance */
CDCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK);
CDCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK);
CDCCmdEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR);
#endif /* USE_USBD_COMPOSITE */
/* Close EP IN */
(void)USBD_LL_CloseEP(pdev, CDCInEpAdd);
pdev->ep_in[CDCInEpAdd & 0xFU].is_used = 0U;
/* Close EP OUT */
(void)USBD_LL_CloseEP(pdev, CDCOutEpAdd);
pdev->ep_out[CDCOutEpAdd & 0xFU].is_used = 0U;
/* Close Command IN EP */
(void)USBD_LL_CloseEP(pdev, CDCCmdEpAdd);
pdev->ep_in[CDCCmdEpAdd & 0xFU].is_used = 0U;
pdev->ep_in[CDCCmdEpAdd & 0xFU].bInterval = 0U;
/* DeInit physical Interface components */
if (pdev->pClassDataCmsit[pdev->classId] != NULL)
{
((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->DeInit();
(void)USBD_free(pdev->pClassDataCmsit[pdev->classId]);
pdev->pClassDataCmsit[pdev->classId] = NULL;
pdev->pClassData = NULL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CDC_Setup
* Handle the CDC specific requests
* @param pdev: instance
* @param req: usb requests
* @retval status
*/
static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req)
{
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
uint16_t len;
uint8_t ifalt = 0U;
uint16_t status_info = 0U;
USBD_StatusTypeDef ret = USBD_OK;
if (hcdc == NULL)
{
return (uint8_t)USBD_FAIL;
}
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_CLASS:
if (req->wLength != 0U)
{
if ((req->bmRequest & 0x80U) != 0U)
{
((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->Control(req->bRequest,
(uint8_t *)hcdc->data,
req->wLength);
len = MIN(CDC_REQ_MAX_DATA_SIZE, req->wLength);
(void)USBD_CtlSendData(pdev, (uint8_t *)hcdc->data, len);
}
else
{
hcdc->CmdOpCode = req->bRequest;
hcdc->CmdLength = (uint8_t)MIN(req->wLength, USB_MAX_EP0_SIZE);
(void)USBD_CtlPrepareRx(pdev, (uint8_t *)hcdc->data, hcdc->CmdLength);
}
}
else
{
((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->Control(req->bRequest,
(uint8_t *)req, 0U);
}
break;
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest)
{
case USB_REQ_GET_STATUS:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_GET_INTERFACE:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, &ifalt, 1U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_SET_INTERFACE:
if (pdev->dev_state != USBD_STATE_CONFIGURED)
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_CLEAR_FEATURE:
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
return (uint8_t)ret;
}
/**
* @brief USBD_CDC_DataIn
* Data sent on non-control IN endpoint
* @param pdev: device instance
* @param epnum: endpoint number
* @retval status
*/
static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
USBD_CDC_HandleTypeDef *hcdc;
PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef *)pdev->pData;
if (pdev->pClassDataCmsit[pdev->classId] == NULL)
{
return (uint8_t)USBD_FAIL;
}
hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if ((pdev->ep_in[epnum & 0xFU].total_length > 0U) &&
((pdev->ep_in[epnum & 0xFU].total_length % hpcd->IN_ep[epnum & 0xFU].maxpacket) == 0U))
{
/* Update the packet total length */
pdev->ep_in[epnum & 0xFU].total_length = 0U;
/* Send ZLP */
(void)USBD_LL_Transmit(pdev, epnum, NULL, 0U);
}
else
{
hcdc->TxState = 0U;
if (((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->TransmitCplt != NULL)
{
((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->TransmitCplt(hcdc->TxBuffer, &hcdc->TxLength, epnum);
}
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CDC_DataOut
* Data received on non-control Out endpoint
* @param pdev: device instance
* @param epnum: endpoint number
* @retval status
*/
static uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (pdev->pClassDataCmsit[pdev->classId] == NULL)
{
return (uint8_t)USBD_FAIL;
}
/* Get the received data length */
hcdc->RxLength = USBD_LL_GetRxDataSize(pdev, epnum);
/* USB data will be immediately processed, this allow next USB traffic being
NAKed till the end of the application Xfer */
((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->Receive(hcdc->RxBuffer, &hcdc->RxLength);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CDC_EP0_RxReady
* Handle EP0 Rx Ready event
* @param pdev: device instance
* @retval status
*/
static uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev)
{
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hcdc == NULL)
{
return (uint8_t)USBD_FAIL;
}
if ((pdev->pUserData[pdev->classId] != NULL) && (hcdc->CmdOpCode != 0xFFU))
{
((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->Control(hcdc->CmdOpCode,
(uint8_t *)hcdc->data,
(uint16_t)hcdc->CmdLength);
hcdc->CmdOpCode = 0xFFU;
}
return (uint8_t)USBD_OK;
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief USBD_CDC_GetFSCfgDesc
* Return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CDC_GetFSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpCmdDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_CMD_EP);
USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_OUT_EP);
USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_IN_EP);
if (pEpCmdDesc != NULL)
{
pEpCmdDesc->bInterval = CDC_FS_BINTERVAL;
}
if (pEpOutDesc != NULL)
{
pEpOutDesc->wMaxPacketSize = CDC_DATA_FS_MAX_PACKET_SIZE;
}
if (pEpInDesc != NULL)
{
pEpInDesc->wMaxPacketSize = CDC_DATA_FS_MAX_PACKET_SIZE;
}
*length = (uint16_t)sizeof(USBD_CDC_CfgDesc);
return USBD_CDC_CfgDesc;
}
/**
* @brief USBD_CDC_GetHSCfgDesc
* Return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CDC_GetHSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpCmdDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_CMD_EP);
USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_OUT_EP);
USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_IN_EP);
if (pEpCmdDesc != NULL)
{
pEpCmdDesc->bInterval = CDC_HS_BINTERVAL;
}
if (pEpOutDesc != NULL)
{
pEpOutDesc->wMaxPacketSize = CDC_DATA_HS_MAX_PACKET_SIZE;
}
if (pEpInDesc != NULL)
{
pEpInDesc->wMaxPacketSize = CDC_DATA_HS_MAX_PACKET_SIZE;
}
*length = (uint16_t)sizeof(USBD_CDC_CfgDesc);
return USBD_CDC_CfgDesc;
}
/**
* @brief USBD_CDC_GetOtherSpeedCfgDesc
* Return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpCmdDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_CMD_EP);
USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_OUT_EP);
USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_IN_EP);
if (pEpCmdDesc != NULL)
{
pEpCmdDesc->bInterval = CDC_FS_BINTERVAL;
}
if (pEpOutDesc != NULL)
{
pEpOutDesc->wMaxPacketSize = CDC_DATA_FS_MAX_PACKET_SIZE;
}
if (pEpInDesc != NULL)
{
pEpInDesc->wMaxPacketSize = CDC_DATA_FS_MAX_PACKET_SIZE;
}
*length = (uint16_t)sizeof(USBD_CDC_CfgDesc);
return USBD_CDC_CfgDesc;
}
/**
* @brief USBD_CDC_GetDeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_CDC_DeviceQualifierDesc);
return USBD_CDC_DeviceQualifierDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @brief USBD_CDC_RegisterInterface
* @param pdev: device instance
* @param fops: CD Interface callback
* @retval status
*/
uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev,
USBD_CDC_ItfTypeDef *fops)
{
if (fops == NULL)
{
return (uint8_t)USBD_FAIL;
}
pdev->pUserData[pdev->classId] = fops;
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CDC_SetTxBuffer
* @param pdev: device instance
* @param pbuff: Tx Buffer
* @param length: Tx Buffer length
* @retval status
*/
uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev,
uint8_t *pbuff, uint32_t length)
{
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hcdc == NULL)
{
return (uint8_t)USBD_FAIL;
}
hcdc->TxBuffer = pbuff;
hcdc->TxLength = length;
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CDC_SetRxBuffer
* @param pdev: device instance
* @param pbuff: Rx Buffer
* @retval status
*/
uint8_t USBD_CDC_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff)
{
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hcdc == NULL)
{
return (uint8_t)USBD_FAIL;
}
hcdc->RxBuffer = pbuff;
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CDC_TransmitPacket
* Transmit packet on IN endpoint
* @param pdev: device instance
* @retval status
*/
uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev)
{
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
USBD_StatusTypeDef ret = USBD_BUSY;
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
CDCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK);
#endif /* USE_USBD_COMPOSITE */
if (pdev->pClassDataCmsit[pdev->classId] == NULL)
{
return (uint8_t)USBD_FAIL;
}
if (hcdc->TxState == 0U)
{
/* Tx Transfer in progress */
hcdc->TxState = 1U;
/* Update the packet total length */
pdev->ep_in[CDCInEpAdd & 0xFU].total_length = hcdc->TxLength;
/* Transmit next packet */
(void)USBD_LL_Transmit(pdev, CDCInEpAdd, hcdc->TxBuffer, hcdc->TxLength);
ret = USBD_OK;
}
return (uint8_t)ret;
}
/**
* @brief USBD_CDC_ReceivePacket
* prepare OUT Endpoint for reception
* @param pdev: device instance
* @retval status
*/
uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev)
{
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
CDCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK);
#endif /* USE_USBD_COMPOSITE */
if (pdev->pClassDataCmsit[pdev->classId] == NULL)
{
return (uint8_t)USBD_FAIL;
}
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Prepare Out endpoint to receive next packet */
(void)USBD_LL_PrepareReceive(pdev, CDCOutEpAdd, hcdc->RxBuffer,
CDC_DATA_HS_OUT_PACKET_SIZE);
}
else
{
/* Prepare Out endpoint to receive next packet */
(void)USBD_LL_PrepareReceive(pdev, CDCOutEpAdd, hcdc->RxBuffer,
CDC_DATA_FS_OUT_PACKET_SIZE);
}
return (uint8_t)USBD_OK;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,308 @@
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_COMPOSITE_BUILDER_H__
#define __USBD_COMPOSITE_BUILDER_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
#if USBD_CMPSIT_ACTIVATE_HID_MOUSE == 1U
#include "usbd_hid_mouse.h"
#endif /* USBD_CMPSIT_ACTIVATE_HID_MOUSE */
#if USBD_CMPSIT_ACTIVATE_HID_KEYBOARD == 1U
#include "usbd_hid_keyboard.h"
#endif /* USBD_CMPSIT_ACTIVATE_HID_KEYBOARD */
#if USBD_CMPSIT_ACTIVATE_HID_CUSTOM == 1U
#include "usbd_hid_custom.h"
#endif /* USBD_CMPSIT_ACTIVATE_HID_CUSTOM */
#if USBD_CMPSIT_ACTIVATE_MSC == 1U
#include "usbd_msc.h"
#endif /* USBD_CMPSIT_ACTIVATE_MSC */
#if USBD_CMPSIT_ACTIVATE_CDC == 1U
#include "usbd_cdc.h"
#endif /* USBD_CMPSIT_ACTIVATE_CDC */
#if USBD_CMPSIT_ACTIVATE_DFU == 1U
#include "usbd_dfu.h"
#endif /* USBD_CMPSIT_ACTIVATE_DFU */
#if USBD_CMPSIT_ACTIVATE_RNDIS == 1U
#include "usbd_cdc_rndis.h"
#endif /* USBD_CMPSIT_ACTIVATE_RNDIS */
#if USBD_CMPSIT_ACTIVATE_CDC_ECM == 1U
#include "usbd_cdc_ecm.h"
#ifndef __USBD_CDC_ECM_IF_H
#include "usbd_cdc_ecm_if_template.h"
#endif /* __USBD_CDC_ECM_IF_H */
#endif /* USBD_CMPSIT_ACTIVATE_CDC_ECM */
#if USBD_CMPSIT_ACTIVATE_AUDIO == 1
#include "usbd_audio.h"
#endif /* USBD_CMPSIT_ACTIVATE_AUDIO */
#if USBD_CMPSIT_ACTIVATE_CUSTOMHID == 1
#include "usbd_customhid.h"
#endif /* USBD_CMPSIT_ACTIVATE_CUSTOMHID */
#if USBD_CMPSIT_ACTIVATE_VIDEO == 1
#include "usbd_video.h"
#endif /* USBD_CMPSIT_ACTIVATE_VIDEO */
#if USBD_CMPSIT_ACTIVATE_PRINTER == 1
#include "usbd_printer.h"
#endif /* USBD_CMPSIT_ACTIVATE_PRINTER */
#if USBD_CMPSIT_ACTIVATE_CCID == 1U
#include "usbd_ccid.h"
#endif /* USBD_CMPSIT_ACTIVATE_CCID */
#if USBD_CMPSIT_ACTIVATE_MTP == 1U
#include "usbd_mtp.h"
#endif /* USBD_CMPSIT_ACTIVATE_MTP */
#if USBD_CMPSIT_ACTIVATE_MICROPHONE == 1U
#include "usbd_microphone.h"
#endif /* USBD_CMPSIT_ACTIVATE_MICROPHONE */
#if USBD_CMPSIT_ACTIVATE_HEADPHONE == 1U
#include "usbd_headphone.h"
#endif /* USBD_CMPSIT_ACTIVATE_HEADPHONE */
/* Private defines -----------------------------------------------------------*/
/* By default all classes are deactivated, in order to activate a class
define its value to zero */
#ifndef USBD_CMPSIT_ACTIVATE_HID_MOUSE
#define USBD_CMPSIT_ACTIVATE_HID_MOUSE 0U
#endif /* USBD_CMPSIT_ACTIVATE_HID_MOUSE */
#ifndef USBD_CMPSIT_ACTIVATE_HID_KEYBOARD
#define USBD_CMPSIT_ACTIVATE_HID_KEYBOARD 0U
#endif /* USBD_CMPSIT_ACTIVATE_HID_MOUSE */
#ifndef USBD_CMPSIT_ACTIVATE_HID_CUSTOM
#define USBD_CMPSIT_ACTIVATE_HID_CUSTOM 0U
#endif /* USBD_CMPSIT_ACTIVATE_HID_MOUSE */
#ifndef USBD_CMPSIT_ACTIVATE_MSC
#define USBD_CMPSIT_ACTIVATE_MSC 0U
#endif /* USBD_CMPSIT_ACTIVATE_MSC */
#ifndef USBD_CMPSIT_ACTIVATE_DFU
#define USBD_CMPSIT_ACTIVATE_DFU 0U
#endif /* USBD_CMPSIT_ACTIVATE_DFU */
#ifndef USBD_CMPSIT_ACTIVATE_CDC
#define USBD_CMPSIT_ACTIVATE_CDC 0U
#endif /* USBD_CMPSIT_ACTIVATE_CDC */
#ifndef USBD_CMPSIT_ACTIVATE_CDC_ECM
#define USBD_CMPSIT_ACTIVATE_CDC_ECM 0U
#endif /* USBD_CMPSIT_ACTIVATE_CDC_ECM */
#ifndef USBD_CMPSIT_ACTIVATE_RNDIS
#define USBD_CMPSIT_ACTIVATE_RNDIS 0U
#endif /* USBD_CMPSIT_ACTIVATE_RNDIS */
#ifndef USBD_CMPSIT_ACTIVATE_AUDIO
#define USBD_CMPSIT_ACTIVATE_AUDIO 0U
#endif /* USBD_CMPSIT_ACTIVATE_AUDIO */
#ifndef USBD_CMPSIT_ACTIVATE_CUSTOMHID
#define USBD_CMPSIT_ACTIVATE_CUSTOMHID 0U
#endif /* USBD_CMPSIT_ACTIVATE_CUSTOMHID */
#ifndef USBD_CMPSIT_ACTIVATE_VIDEO
#define USBD_CMPSIT_ACTIVATE_VIDEO 0U
#endif /* USBD_CMPSIT_ACTIVATE_VIDEO */
#ifndef USBD_CMPSIT_ACTIVATE_PRINTER
#define USBD_CMPSIT_ACTIVATE_PRINTER 0U
#endif /* USBD_CMPSIT_ACTIVATE_PRINTER */
#ifndef USBD_CMPSIT_ACTIVATE_CCID
#define USBD_CMPSIT_ACTIVATE_CCID 0U
#endif /* USBD_CMPSIT_ACTIVATE_CCID */
#ifndef USBD_CMPSIT_ACTIVATE_MTP
#define USBD_CMPSIT_ACTIVATE_MTP 0U
#endif /* USBD_CMPSIT_ACTIVATE_MTP */
#ifndef USBD_CMPSIT_ACTIVATE_MICROPHONE
#define USBD_CMPSIT_ACTIVATE_MICROPHONE 0U
#endif /* USBD_CMPSIT_ACTIVATE_MICROPHONE */
#ifndef USBD_CMPSIT_ACTIVATE_HEADPHONE
#define USBD_CMPSIT_ACTIVATE_HEADPHONE 0U
#endif /* USBD_CMPSIT_ACTIVATE_HEADPHONE */
/* This is the maximum supported configuration descriptor size
User may define this value in usbd_conf.h in order to optimize footprint */
#ifndef USBD_CMPST_MAX_CONFDESC_SZ
#define USBD_CMPST_MAX_CONFDESC_SZ 512U
#endif /* USBD_CMPST_MAX_CONFDESC_SZ */
#ifndef USBD_CONFIG_STR_DESC_IDX
#define USBD_CONFIG_STR_DESC_IDX 2U
#endif /* USBD_CONFIG_STR_DESC_IDX */
#define AUDIO_SMAPLE_RATE_HZ 16000U
/* Exported types ------------------------------------------------------------*/
/* USB Iad descriptors structure */
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bFirstInterface;
uint8_t bInterfaceCount;
uint8_t bFunctionClass;
uint8_t bFunctionSubClass;
uint8_t bFunctionProtocol;
uint8_t iFunction;
} USBD_IadDescTypeDef;
/* USB interface descriptors structure */
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
} USBD_IfDescTypeDef;
#if (USBD_CMPSIT_ACTIVATE_CDC == 1) || (USBD_CMPSIT_ACTIVATE_RNDIS == 1) || (USBD_CMPSIT_ACTIVATE_CDC_ECM == 1) || (USBD_CMPSIT_ACTIVATE_MULTI_CDC == 1)
typedef struct
{
/*
* CDC Class specification revision 1.2
* Table 15: Class-Specific Descriptor Header Format
*/
/* Header Functional Descriptor */
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint16_t bcdCDC;
} __PACKED USBD_CDCHeaderFuncDescTypeDef;
typedef struct
{
/* Call Management Functional Descriptor */
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bmCapabilities;
uint8_t bDataInterface;
} USBD_CDCCallMgmFuncDescTypeDef;
typedef struct
{
/* ACM Functional Descriptor */
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bmCapabilities;
} USBD_CDCACMFuncDescTypeDef;
typedef struct
{
/*
* CDC Class specification revision 1.2
* Table 16: Union Interface Functional Descriptor
*/
/* Union Functional Descriptor */
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bMasterInterface;
uint8_t bSlaveInterface;
} USBD_CDCUnionFuncDescTypeDef;
#endif /* (USBD_CMPSIT_ACTIVATE_CDC == 1) || (USBD_CMPSIT_ACTIVATE_RNDIS == 1) || (USBD_CMPSIT_ACTIVATE_CDC_ECM == 1)*/
extern USBD_ClassTypeDef USBD_CMPSIT;
/* Exported functions prototypes ---------------------------------------------*/
uint8_t USBD_CMPSIT_AddToConfDesc(USBD_HandleTypeDef *pdev);
#ifdef USE_USBD_COMPOSITE
uint8_t USBD_CMPSIT_AddClass(USBD_HandleTypeDef *pdev,
USBD_ClassTypeDef *pclass,
USBD_CompositeClassTypeDef class,
uint8_t cfgidx);
uint32_t USBD_CMPSIT_SetClassID(USBD_HandleTypeDef *pdev,
USBD_CompositeClassTypeDef Class,
uint32_t Instance);
uint32_t USBD_CMPSIT_GetClassID(USBD_HandleTypeDef *pdev,
USBD_CompositeClassTypeDef Class,
uint32_t Instance);
uint8_t USBD_CMPSIT_GetClassID_ByAdd(USBD_HandleTypeDef *pdev,
uint8_t ep_add,
uint8_t ep_type);
#endif /* USE_USBD_COMPOSITE */
uint8_t USBD_CMPST_ClearConfDesc(USBD_HandleTypeDef *pdev);
/* Private macro -----------------------------------------------------------*/
#define __USBD_CMPSIT_SET_EP(epadd, eptype, epsize, HSinterval, FSinterval) \
do { \
/* Append Endpoint descriptor to Configuration descriptor */ \
pEpDesc = ((USBD_EpDescTypeDef*)((uint32_t)pConf + *Sze)); \
pEpDesc->bLength = (uint8_t)sizeof(USBD_EpDescTypeDef); \
pEpDesc->bDescriptorType = USB_DESC_TYPE_ENDPOINT; \
pEpDesc->bEndpointAddress = (epadd); \
pEpDesc->bmAttributes = (eptype); \
pEpDesc->wMaxPacketSize = (epsize); \
if(speed == (uint8_t)USBD_SPEED_HIGH) \
{ \
pEpDesc->bInterval = HSinterval; \
} \
else \
{ \
pEpDesc->bInterval = FSinterval; \
} \
*Sze += (uint32_t)sizeof(USBD_EpDescTypeDef); \
} while(0)
#define __USBD_CMPSIT_SET_IF(ifnum, alt, eps, class, subclass, protocol, istring) \
do { \
/* Interface Descriptor */ \
pIfDesc = ((USBD_IfDescTypeDef*)((uint32_t)pConf + *Sze)); \
pIfDesc->bLength = (uint8_t)sizeof(USBD_IfDescTypeDef); \
pIfDesc->bDescriptorType = USB_DESC_TYPE_INTERFACE; \
pIfDesc->bInterfaceNumber = ifnum; \
pIfDesc->bAlternateSetting = alt; \
pIfDesc->bNumEndpoints = eps; \
pIfDesc->bInterfaceClass = class; \
pIfDesc->bInterfaceSubClass = subclass; \
pIfDesc->bInterfaceProtocol = protocol; \
pIfDesc->iInterface = istring; \
*Sze += (uint32_t)sizeof(USBD_IfDescTypeDef); \
} while(0)
#ifdef __cplusplus
}
#endif
#endif /* __USBD_COMPOSITE_BUILDER_H__ */
/**
* @}
*/
@@ -0,0 +1,179 @@
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_HID_CUSTOM_H
#define __USB_HID_CUSTOM_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @defgroup USBD_HID
* @brief This file is the Header file for usbd_hid.c
* @{
*/
/** @defgroup USBD_HID_Exported_Defines
* @{
*/
#ifndef HID_CUSTOM_EPIN_ADDR
#define HID_CUSTOM_EPIN_ADDR 0x83U
#endif /* HID_EPIN_ADDR */
#define HID_CUSTOM_EPIN_SIZE 0x40U
#ifndef HID_CUSTOM_EPOUT_ADDR
#define HID_CUSTOM_EPOUT_ADDR 0x03U
#endif /* HID_CUSTOM_EPOUT_ADDR */
#define HID_CUSTOM_EPOUT_SIZE 0x40U
#define USB_HID_CUSTOM_CONFIG_DESC_SIZ 41U
#define USB_HID_CUSTOM_DESC_SIZ 9U
#define HID_CUSTOM_REPORT_DESC_SIZE 38+45U
#define HID_CUSTOM_DESCRIPTOR_TYPE 0x21U
#define HID_CUSTOM_REPORT_DESC 0x22U
#ifndef HID_CUSTOM_HS_BINTERVAL
#define HID_CUSTOM_HS_BINTERVAL 0x07U
#endif /* HID_HS_BINTERVAL */
#ifndef HID_CUSTOM_FS_BINTERVAL
#define HID_CUSTOM_FS_BINTERVAL 0x0AU
#endif /* HID_FS_BINTERVAL */
#ifndef USBD_CUSTOM_OUTREPORT_BUF_SIZE
#define USBD_CUSTOM_OUTREPORT_BUF_SIZE 0x02U
#endif /* USBD_CUSTOM_OUTREPORT_BUF_SIZE */
#define HID_CUSTOM_REQ_SET_PROTOCOL 0x0BU
#define HID_CUSTOM_REQ_GET_PROTOCOL 0x03U
#define HID_CUSTOM_REQ_SET_IDLE 0x0AU
#define HID_CUSTOM_REQ_GET_IDLE 0x02U
#define HID_CUSTOM_REQ_SET_REPORT 0x09U
#define HID_CUSTOM_REQ_GET_REPORT 0x01U
#ifndef HID_CUSTOM_EP0_SET_REPORT_BUF_SIZE
#define HID_CUSTOM_EP0_SET_REPORT_BUF_SIZE 0x10U
#endif /* HID_CUSTOM_EP0_SET_REPORT_BUF_SIZE */
#ifndef HID_CUSTOM_EP0_GET_REPORT_BUF_SIZE
#define HID_CUSTOM_EP0_GET_REPORT_BUF_SIZE 0x10U
#endif /* HID_CUSTOM_EP0_GET_REPORT_BUF_SIZE */
/**
* @}
*/
#define USB_DFU_REPORT_MAP \
0x06, 0x86, 0x19, /* Usage Page (ByteX)*/\
0x09, 0x10, /* Usage (0x10)*/\
0xA1, 0x01, /* Collection (Application)*/\
0x85, 0xFA, /* Report ID (-79)*/\
0x15, 0x00, /* Logical Minimum (0)*/\
0x25, 0xFF, /* Logical Maximum (-1)*/\
0x09, 0x00, /* Usage (Unassigned)*/\
0x19, 0x00, /* Usage (Unassigned)*/\
0x29, 0xFF, /* Usage Maximum (0xFF)*/\
0x75, 0x08, /* Report Size (8)*/\
0x95, 63, /* Report Count (63)*/\
0x81, 0x02, /* Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)*/\
0x85, 0xFB, /* Report ID (-78)*/\
0x15, 0x00, /* Logical Minimum (0)*/\
0x25, 0xFF, /* Logical Maximum (-1)*/\
0x09, 0x00, /* Usage (Unassigned)*/\
0x19, 0x00, /* Usage (Unassigned)*/\
0x29, 0xFF, /* Usage Maximum (0xFF)*/\
0x75, 0x08, /* Report Size (8)*/\
0x96, 0xFF, 0x01, /* Report Count (511)*/\
0x91, 0x02, /* Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)*/\
0xC0
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef enum
{
CUSTOM_HID_IDLE = 0,
CUSTOM_HID_BUSY,
} HID_Custom_StateTypeDef;
typedef struct
{
uint8_t EP0_ReportBuff[HID_CUSTOM_EP0_SET_REPORT_BUF_SIZE];
uint8_t EP0_ReportLen;
uint8_t Report_buf[USBD_CUSTOM_OUTREPORT_BUF_SIZE];
uint32_t Protocol;
uint32_t IdleState;
uint32_t AltSetting;
HID_Custom_StateTypeDef state;
} USBD_HID_Custom_HandleTypeDef;
/*
* HID Class specification version 1.1
* 6.2.1 HID Descriptor
*/
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bHIDDescriptorType;
uint16_t wItemLength;
} __PACKED USBD_HID_CustomDescTypeDef;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_HID_CUSTOM;
#define USBD_HID_CUSTOM_CLASS &USBD_HID_CUSTOM
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_HID_CUSTOM_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
uint32_t USBD_HID_CUSTOM_GetPollingInterval(USBD_HandleTypeDef *pdev);
uint8_t USBD_HID_Custom_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
uint8_t USBD_HID_Custom_FirstSendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HID_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,156 @@
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_HID_KEYBOARD_H
#define __USB_HID_KEYBOARD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @defgroup USBD_HID
* @brief This file is the Header file for usbd_hid.c
* @{
*/
/** @defgroup USBD_HID_Exported_Defines
* @{
*/
#ifndef HID_KEYBOARD_EPIN_ADDR
#define HID_KEYBOARD_EPIN_ADDR 0x82U
#endif /* HID_EPIN_ADDR */
#define HID_KEYBOARD_EPIN_SIZE 0x08U
#ifndef HID_KEYBOARD_EPOUT_ADDR
#define HID_KEYBOARD_EPOUT_ADDR 0x02U
#endif /* HID_EPIN_ADDR */
#define HID_KEYBOARD_EPOUT_SIZE 0x01U
#define USB_HID_KEYBOARD_CONFIG_DESC_SIZ 41U
#define USB_HID_KEYBOARD_DESC_SIZ 9U
#define HID_KEYBOARD_REPORT_DESC_SIZE 63U
#define HID_KEYBOARD_DESCRIPTOR_TYPE 0x21U
#define HID_KEYBOARD_REPORT_DESC 0x22U
#ifndef HID_KEYBOARD_HS_BINTERVAL
#define HID_KEYBOARD_HS_BINTERVAL 0x07U
#endif /* HID_HS_BINTERVAL */
#ifndef HID_KEYBOARD_FS_BINTERVAL
#define HID_KEYBOARD_FS_BINTERVAL 0x0AU
#endif /* HID_FS_BINTERVAL */
#ifndef USBD_KEYBOARD_OUTREPORT_BUF_SIZE
#define USBD_KEYBOARD_OUTREPORT_BUF_SIZE 0x02U
#endif /* USBD_KEYBOARD_OUTREPORT_BUF_SIZE */
#define HID_KEYBOARD_REQ_SET_PROTOCOL 0x0BU
#define HID_KEYBOARD_REQ_GET_PROTOCOL 0x03U
#define HID_KEYBOARD_REQ_SET_IDLE 0x0AU
#define HID_KEYBOARD_REQ_GET_IDLE 0x02U
#define HID_KEYBOARD_REQ_SET_REPORT 0x09U
#define HID_KEYBOARD_REQ_GET_REPORT 0x01U
#ifndef HID_KEYBOARD_EP0_SET_REPORT_BUF_SIZE
#define HID_KEYBOARD_EP0_SET_REPORT_BUF_SIZE 0x10U
#endif /* HID_KEYBOARD_EP0_SET_REPORT_BUF_SIZE */
#ifndef HID_KEYBOARD_EP0_GET_REPORT_BUF_SIZE
#define HID_KEYBOARD_EP0_GET_REPORT_BUF_SIZE 0x10U
#endif /* HID_KEYBOARD_EP0_GET_REPORT_BUF_SIZE */
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef enum
{
KEYBOARD_HID_IDLE = 0,
KEYBOARD_HID_BUSY,
} HID_Keyboard_StateTypeDef;
typedef struct
{
uint8_t EP0_ReportBuff[HID_KEYBOARD_EP0_SET_REPORT_BUF_SIZE];
uint8_t EP0_ReportLen;
uint8_t Report_buf[USBD_KEYBOARD_OUTREPORT_BUF_SIZE];
uint32_t Protocol;
uint32_t IdleState;
uint32_t AltSetting;
HID_Keyboard_StateTypeDef state;
} USBD_HID_Keyboard_HandleTypeDef;
/*
* HID Class specification version 1.1
* 6.2.1 HID Descriptor
*/
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bHIDDescriptorType;
uint16_t wItemLength;
} __PACKED USBD_HID_KeyboardDescTypeDef;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_HID_KEYBOARD;
#define USBD_HID_KEYBOARD_CLASS &USBD_HID_KEYBOARD
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_HID_Keyboard_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
uint32_t USBD_HID_GetPollingInterval(USBD_HandleTypeDef *pdev);
uint8_t USBD_HID_Keyboard_FirstSendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HID_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,172 @@
/*!
* \file usbd_hid.h
*
* \brief This file provides the HID core functions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_HID_MOUSE_H
#define __USB_HID_MOUSE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @defgroup USBD_HID
* @brief This file is the Header file for usbd_hid.c
* @{
*/
/** @defgroup USBD_HID_Exported_Defines
* @{
*/
#ifndef HID_MOUSE_EPIN_ADDR
#define HID_MOUSE_EPIN_ADDR 0x81U
#endif /* HID_EPIN_ADDR */
#define HID_MOUSE_EPIN_SIZE 0x04U
#define USB_HID_MOUSE_CONFIG_DESC_SIZ 34U
#define USB_HID_MOUSE_DESC_SIZ 9U
#define HID_MOUSE_REPORT_DESC_SIZE 74U
#define HID_MOUSE_DESCRIPTOR_TYPE 0x21U
#define HID_MOUSE_REPORT_DESC 0x22U
#ifndef HID_MOUSE_HS_BINTERVAL
#define HID_MOUSE_HS_BINTERVAL 0x07U
#endif /* HID_HS_BINTERVAL */
#ifndef HID_MOUSE_FS_BINTERVAL
#define HID_MOUSE_FS_BINTERVAL 0x01U
#endif /* HID_FS_BINTERVAL */
#define HID_MOUSE_REQ_SET_PROTOCOL 0x0BU
#define HID_MOUSE_REQ_GET_PROTOCOL 0x03U
#define HID_MOUSE_REQ_SET_IDLE 0x0AU
#define HID_MOUSE_REQ_GET_IDLE 0x02U
#define HID_MOUSE_REQ_SET_REPORT 0x09U
#define HID_MOUSE_REQ_GET_REPORT 0x01U
#ifndef HID_MOUSE_EP0_SET_REPORT_BUF_SIZE
#define HID_MOUSE_EP0_SET_REPORT_BUF_SIZE 0x10U
#endif /* HID_MOUSE_EP0_SET_REPORT_BUF_SIZE */
#ifndef HID_MOUSE_EP0_GET_REPORT_BUF_SIZE
#define HID_MOUSE_EP0_GET_REPORT_BUF_SIZE 0x10U
#endif /* HID_MOUSE_EP0_GET_REPORT_BUF_SIZE */
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef enum
{
MOUSE_HID_IDLE = 0,
MOUSE_HID_BUSY,
} HID_Mouse_StateTypeDef;
typedef struct
{
uint8_t EP0_ReportBuff[HID_MOUSE_EP0_SET_REPORT_BUF_SIZE];
uint8_t EP0_ReportLen;
uint32_t Protocol;
uint32_t IdleState;
uint32_t AltSetting;
HID_Mouse_StateTypeDef state;
} USBD_HID_Mouse_HandleTypeDef;
/*
* HID Class specification version 1.1
* 6.2.1 HID Descriptor
*/
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bHIDDescriptorType;
uint16_t wItemLength;
} __PACKED USBD_HID_MouseDescTypeDef;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_HID_MOUSE;
#define USBD_HID_MOUSE_CLASS &USBD_HID_MOUSE
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_HID_Mouse_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
uint32_t USBD_HID_GetPollingInterval(USBD_HandleTypeDef *pdev);
uint8_t USBD_HID_Mouse_FirstSendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HID_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,879 @@
/*!
* \file usbd_hid_custom.c
*
* \brief This file provides the HID core functions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*
* @verbatim
*
* ===================================================================
* HID Class Description
* ===================================================================
* This module manages the HID class V1.11 following the "Device Class Definition
* for Human Interface Devices (HID) Version 1.11 Jun 27, 2001".
* This driver implements the following aspects of the specification:
* - The Boot Interface Subclass
* - The Mouse protocol
* - Usage Page : Generic Desktop
* - Usage : Custom
* - Collection : Application
*
* @note In HS mode and when the DMA is used, all variables and data structures
* dealing with the DMA during the transaction process should be 32-bit aligned.
*
*
* @endverbatim
*
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_hid_custom.h"
#include "usbd_ctlreq.h"
#ifdef USE_USBD_COMPOSITE
#include "usbd_composite_builder.h"
#endif
/** @defgroup USBD_HID
* @brief usbd core module
* @{
*/
/** @defgroup USBD_HID_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_FunctionPrototypes
* @{
*/
static uint8_t USBD_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_HID_EP0_RxReady(USBD_HandleTypeDef *pdev);
static uint8_t USBD_HID_Custom_SetReport_Setup_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data);
static uint8_t USBD_HID_Custom_SetReport_Token_Stage(USBD_HandleTypeDef *pdev);
static uint8_t USBD_HID_Custom_GetReport_Token_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data);
#ifndef USE_USBD_COMPOSITE
static uint8_t *USBD_HID_GetFSCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetHSCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetOtherSpeedCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetDeviceQualifierDesc(uint16_t *length);
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/** @defgroup USBD_HID_Private_Variables
* @{
*/
USBD_ClassTypeDef USBD_HID_CUSTOM =
{
USBD_HID_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL, /* EP0_TxSent */
USBD_HID_EP0_RxReady, /* EP0_RxReady */
USBD_HID_DataIn, /* DataIn */
USBD_HID_DataOut, /* DataOut */
NULL, /* SOF */
NULL,
NULL,
#ifdef USE_USBD_COMPOSITE
NULL,
NULL,
NULL,
NULL,
#else
USBD_HID_GetHSCfgDesc,
USBD_HID_GetFSCfgDesc,
USBD_HID_GetOtherSpeedCfgDesc,
USBD_HID_GetDeviceQualifierDesc,
#endif /* USE_USBD_COMPOSITE */
};
#ifndef USE_USBD_COMPOSITE
/* USB HID device FS Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_CUSTOM_CfgDesc[USB_HID_CUSTOM_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_HID_CUSTOM_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */
0x00,
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor
describing the configuration */
#if (USBD_SELF_POWERED == 1U)
0xE0, /* bmAttributes: Bus Powered according to user configuration */
#else
0xA0, /* bmAttributes: Bus Powered according to user configuration */
#endif /* USBD_SELF_POWERED */
USBD_MAX_POWER, /* MaxPower (mA) */
/************** Descriptor of Custom interface ****************/
/* 09 */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints */
0x03, /* bInterfaceClass: HID */
0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0, /* iInterface: Index of string descriptor */
/******************** Descriptor of Joystick Custom HID ********************/
/* 18 */
0x09, /* bLength: HID Descriptor size */
HID_CUSTOM_DESCRIPTOR_TYPE, /* bDescriptorType: HID */
0x11, /* bcdHID: HID Class Spec release number */
0x01,
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
0x22, /* bDescriptorType */
HID_CUSTOM_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
0x00,
/******************** Descriptor of Custom endpoint ********************/
/* 27 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType:*/
HID_CUSTOM_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
HID_CUSTOM_EPIN_SIZE, /* wMaxPacketSize: 4 Bytes max */
0x00,
HID_CUSTOM_FS_BINTERVAL, /* bInterval: Polling Interval */
/******************** Descriptor of Custom endpoint ********************/
/* 34 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType:*/
HID_CUSTOM_EPOUT_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
HID_CUSTOM_EPOUT_SIZE, /* wMaxPacketSize: 4 Bytes max */
0x00,
HID_CUSTOM_FS_BINTERVAL, /* bInterval: Polling Interval */
/* 41 */
};
#endif /* USE_USBD_COMPOSITE */
/* USB HID device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_Desc[USB_HID_CUSTOM_DESC_SIZ] __ALIGN_END =
{
/* 18 */
0x09, /* bLength: HID Descriptor size */
HID_CUSTOM_DESCRIPTOR_TYPE, /* bDescriptorType: HID */
0x11, /* bcdHID: HID Class Spec release number */
0x01,
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
0x22, /* bDescriptorType */
HID_CUSTOM_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
0x00,
};
#ifndef USE_USBD_COMPOSITE
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
};
#endif /* USE_USBD_COMPOSITE */
__ALIGN_BEGIN static uint8_t HID_Custom_ReportDesc[HID_CUSTOM_REPORT_DESC_SIZE] __ALIGN_END =
{
0x06, 0x00, 0xff, //USAGE_PAGE(Vendor Defined Page 1)
0x09, 0x01, //USAGE(Vendor Usage 1)
0xa1, 0x01, //COLLECTION (Application)
0x85, 0x01, //REPORT ID (0x01)
0x09, 0x01, //USAGE(Vendor Usage 1)
0x15, 0x00, //LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, //LOGICAL_MAXIMUM (255)
0x95, 0x40-0x01, //REPORT_COUNT (63)
0x75, 0x08, //REPORT_SIZE (8)
0x81, 0x02, //INPUT (Data,Var,Abs)
0x85, 0x02, //REPORT ID (0x02)
0x09, 0x01, //USAGE(Vendor Usage 1)
0x15, 0x00, //LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, //LOGICAL_MAXIMUM (255)
0x95, 0x40-0x01, //REPORT_COUNT (63)
0x75, 0x08, //REPORT_SIZE (8)
0x91, 0x02, //OUTPUT (Data,Var,Abs)
0xc0, //END_COLLECTION
USB_DFU_REPORT_MAP
};
static uint8_t HIDInEpAdd = HID_CUSTOM_EPIN_ADDR;
/**
* @}
*/
/** @defgroup USBD_HID_Private_Functions
* @{
*/
/**
* @brief USBD_HID_Init
* Initialize the HID interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
USBD_HID_Custom_HandleTypeDef *hhid;
hhid = (USBD_HID_Custom_HandleTypeDef *)USBD_malloc(sizeof(USBD_HID_Custom_HandleTypeDef));
DEBUG("sizeof(USBD_HID_Custom_HandleTypeDef)=0x%x\n",sizeof(USBD_HID_Custom_HandleTypeDef));
if (hhid == NULL)
{
pdev->pClassDataCmsit[pdev->classId] = NULL;
return (uint8_t)USBD_EMEM;
}
pdev->pClassDataCmsit[pdev->classId] = (void *)hhid;
pdev->pClassData = pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
HIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR);
#endif /* USE_USBD_COMPOSITE */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = HID_CUSTOM_HS_BINTERVAL;
}
else /* LOW and FULL-speed endpoints */
{
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = HID_CUSTOM_FS_BINTERVAL;
}
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, HIDInEpAdd, USBD_EP_TYPE_INTR, HID_CUSTOM_EPIN_SIZE);
pdev->ep_in[HIDInEpAdd & 0xFU].is_used = 1U;
/* Open EP OUT */
(void)USBD_LL_OpenEP(pdev, HID_CUSTOM_EPOUT_ADDR, USBD_EP_TYPE_INTR, HID_CUSTOM_EPOUT_SIZE);
pdev->ep_out[HID_CUSTOM_EPOUT_ADDR & 0xFU].is_used = 1U;
/* Prepare Out endpoint to receive 1st packet */
(void)USBD_LL_PrepareReceive(pdev, HID_CUSTOM_EPOUT_ADDR, hhid->Report_buf,
HID_CUSTOM_EPOUT_SIZE);
hhid->state = CUSTOM_HID_IDLE;
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_HID_DeInit
* DeInitialize the HID layer
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
HIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR);
#endif /* USE_USBD_COMPOSITE */
/* Close HID EPs */
(void)USBD_LL_CloseEP(pdev, HIDInEpAdd);
pdev->ep_in[HIDInEpAdd & 0xFU].is_used = 0U;
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = 0U;
/* Free allocated memory */
if (pdev->pClassDataCmsit[pdev->classId] != NULL)
{
(void)USBD_free(pdev->pClassDataCmsit[pdev->classId]);
pdev->pClassDataCmsit[pdev->classId] = NULL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_HID_Setup
* Handle the HID specific requests
* @param pdev: instance
* @param req: usb requests
* @retval status
*/
static uint8_t USBD_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
USBD_StatusTypeDef ret = USBD_OK;
uint16_t len;
uint8_t *pbuf;
uint16_t status_info = 0U;
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_CLASS :
switch (req->bRequest)
{
case HID_CUSTOM_REQ_SET_PROTOCOL:
hhid->Protocol = (uint8_t)(req->wValue);
break;
case HID_CUSTOM_REQ_GET_PROTOCOL:
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->Protocol, 1U);
break;
case HID_CUSTOM_REQ_SET_IDLE:
hhid->IdleState = (uint8_t)(req->wValue >> 8);
break;
case HID_CUSTOM_REQ_GET_IDLE:
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->IdleState, 1U);
break;
case HID_CUSTOM_REQ_SET_REPORT:
USBD_HID_Custom_SetReport_Setup_Stage(pdev, req);
break;
case HID_CUSTOM_REQ_GET_REPORT:
USBD_HID_Custom_GetReport_Token_Stage(pdev, req);
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest)
{
case USB_REQ_GET_STATUS:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_GET_DESCRIPTOR:
if ((req->wValue >> 8) == HID_CUSTOM_REPORT_DESC)
{
len = MIN(HID_CUSTOM_REPORT_DESC_SIZE, req->wLength);
pbuf = HID_Custom_ReportDesc;
}
else if ((req->wValue >> 8) == HID_CUSTOM_DESCRIPTOR_TYPE)
{
pbuf = USBD_HID_Desc;
len = MIN(USB_HID_CUSTOM_DESC_SIZ, req->wLength);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
(void)USBD_CtlSendData(pdev, pbuf, len);
break;
case USB_REQ_GET_INTERFACE :
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->AltSetting, 1U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_SET_INTERFACE:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
hhid->AltSetting = (uint8_t)(req->wValue);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_CLEAR_FEATURE:
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
return (uint8_t)ret;
}
/**
* @brief USBD_HID_Custom_SendReport
* Send HID Report
* @param pdev: device instance
* @param buff: pointer to report
* @retval status
*/
uint8_t USBD_HID_Custom_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len)
{
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_CUSTOM_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if (hhid->state == CUSTOM_HID_IDLE)
{
hhid->state = CUSTOM_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_CUSTOM_EPIN_ADDR, report, len);
}
}
return (uint8_t)USBD_OK;
#else
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if (hhid->state == CUSTOM_HID_IDLE)
{
hhid->state = CUSTOM_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_CUSTOM_EPIN_ADDR, report, len);
}
}
return (uint8_t)USBD_OK;
#endif
}
extern uint8_t epnm_flag;
/**
* @brief USBD_HID_Custom_FirstSendReport
* Send HID Report
* @param pdev: device instance
* @param buff: pointer to report
* @retval status
*/
uint8_t USBD_HID_Custom_FirstSendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len)
{
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
uint8_t ep_id = HID_CUSTOM_EPIN_ADDR & 0xF;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_CUSTOM_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
PCD_HandleTypeDef *pcd = (PCD_HandleTypeDef *)(pdev->pData);
uint32_t USBx_BASE = (uint32_t)(PCD_HandleTypeDef *)pcd->Instance;
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if ((hhid->state == CUSTOM_HID_IDLE)||(epnm_flag == 0x01))
{
if(USBx_INEP(ep_id)->DIEPINT & USB_OTG_DIEPINT_ITTXFE)
{
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_ITTXFE;
hhid->state = CUSTOM_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_CUSTOM_EPIN_ADDR, report, len);
}
else{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_NAK){
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_NAK;
USBx_INEP(ep_id)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
}
}
if(epnm_flag == 0x01){
epnm_flag = 0x00;
}
}
}
return (uint8_t)USBD_OK;
#else
uint8_t ep_id = HID_CUSTOM_EPIN_ADDR & 0xF;
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
PCD_HandleTypeDef *pcd = (PCD_HandleTypeDef *)(pdev->pData);
uint32_t USBx_BASE = (uint32_t)(PCD_HandleTypeDef *)pcd->Instance;
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if ((hhid->state == CUSTOM_HID_IDLE)||(epnm_flag == 0x01))
{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_ITTXFE)
{
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_ITTXFE;
hhid->state = CUSTOM_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_CUSTOM_EPIN_ADDR, report, len);
}
else{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_NAK){
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_NAK;
USBx_INEP(ep_id)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
}
}
if(epnm_flag == 0x01){
epnm_flag = 0x00;
}
}
}
return (uint8_t)USBD_OK;
#endif
}
/**
* @brief USBD_HID_GetPollingInterval
* return polling interval from endpoint descriptor
* @param pdev: device instance
* @retval polling interval
*/
uint32_t USBD_HID_Custom_GetPollingInterval(USBD_HandleTypeDef *pdev)
{
uint32_t polling_interval;
/* HIGH-speed endpoints */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Sets the data transfer polling interval for high speed transfers.
Values between 1..16 are allowed. Values correspond to interval
of 2 ^ (bInterval-1). This option (8 ms, corresponds to HID_HS_BINTERVAL */
polling_interval = (((1U << (HID_CUSTOM_HS_BINTERVAL - 1U))) / 8U);
}
else /* LOW and FULL-speed endpoints */
{
/* Sets the data transfer polling interval for low and full
speed transfers */
polling_interval = HID_CUSTOM_FS_BINTERVAL;
}
return ((uint32_t)(polling_interval));
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief USBD_HID_GetCfgFSDesc
* return FS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetFSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CUSTOM_CfgDesc, HID_CUSTOM_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_CUSTOM_FS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CUSTOM_CfgDesc);
return USBD_HID_CUSTOM_CfgDesc;
}
/**
* @brief USBD_HID_GetCfgHSDesc
* return HS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetHSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CUSTOM_CfgDesc, HID_CUSTOM_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_CUSTOM_HS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CUSTOM_CfgDesc);
return USBD_HID_CUSTOM_CfgDesc;
}
/**
* @brief USBD_HID_GetOtherSpeedCfgDesc
* return other speed configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetOtherSpeedCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CUSTOM_CfgDesc, HID_CUSTOM_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_CUSTOM_FS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CUSTOM_CfgDesc);
return USBD_HID_CUSTOM_CfgDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @brief USBD_HID_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
UNUSED(epnum);
/* Ensure that the FIFO is empty before a new transfer, this condition could
be caused by a new transfer before the end of the previous transfer */
((USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId])->state = CUSTOM_HID_IDLE;
return (uint8_t)USBD_OK;
}
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
/**
* @brief USBD_HID_DataOut
* handle data OUT Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
UNUSED(epnum);
uint8_t size_num;
USBD_HID_Custom_HandleTypeDef *hhid;
hhid = pdev->pClassData;
/* Ensure that the FIFO is empty before a new transfer, this condition could
be caused by a new transfer before the end of the previous transfer */
size_num = HAL_PCD_EP_GetRxCount(&hpcd_USB_OTG_FS,HID_CUSTOM_EPOUT_ADDR);
(void)USBD_LL_PrepareReceive(pdev, HID_CUSTOM_EPOUT_ADDR, hhid->Report_buf,HID_CUSTOM_EPOUT_SIZE);
for(int i=0;i<size_num;i++)
{
DEBUG("0x%x ",hhid->Report_buf[i]);
}
DEBUG("\n");
hhid->state = CUSTOM_HID_IDLE;
return (uint8_t)USBD_OK;
}
static uint8_t USBD_HID_EP0_RxReady(USBD_HandleTypeDef *pdev)
{
DEBUG("Custom USBD_HID_EP0_RxReady\r\n");
USBD_HID_Custom_SetReport_Token_Stage(pdev);
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Custom_SetReport_Setup_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data)
{
uint8_t report_type;
uint8_t report_id;
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_CUSTOM_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
report_type = (setup_data->wValue >> 8) & 0xFF;
report_id = setup_data->wValue & 0xFF;
hhid->EP0_ReportLen = setup_data->wLength;
DEBUG("Setup_Stage report_type=%02x, report_id=%02x, report_len=%d\r\n",report_type, report_id, hhid->EP0_ReportLen);
(void)USBD_CtlPrepareRx(pdev, hhid->EP0_ReportBuff, hhid->EP0_ReportLen);
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Custom_SetReport_Token_Stage(USBD_HandleTypeDef *pdev)
{
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_CUSTOM_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
DEBUG("Token_Stage recv len = %d\n", hhid->EP0_ReportLen);
for(int i=0;i<hhid->EP0_ReportLen;i++){
DEBUG("0x%x ", hhid->EP0_ReportBuff[i]);
}DEBUG("\n");
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Custom_GetReport_Token_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data)
{
uint16_t report_length;
uint8_t data[HID_CUSTOM_EP0_GET_REPORT_BUF_SIZE];
DEBUG("%s,%d\n",__func__,__LINE__);
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_CUSTOM_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
for(int i=0;i<HID_CUSTOM_EP0_GET_REPORT_BUF_SIZE;i++)
{
data[i] = i;
}
report_length = setup_data->wLength;
USBD_CtlSendData(pdev, data, report_length);
return (uint8_t)USBD_OK;
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetDeviceQualifierDesc(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_HID_DeviceQualifierDesc);
return USBD_HID_DeviceQualifierDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,864 @@
/*!
* \file usbd_hid_keyboard.c
*
* \brief This file provides the HID core functions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*
* @verbatim
*
* ===================================================================
* HID Class Description
* ===================================================================
* This module manages the HID class V1.11 following the "Device Class Definition
* for Human Interface Devices (HID) Version 1.11 Jun 27, 2001".
* This driver implements the following aspects of the specification:
* - The Boot Interface Subclass
* - The Mouse protocol
* - Usage Page : Generic Desktop
* - Usage : Keyboard
* - Collection : Application
*
* @note In HS mode and when the DMA is used, all variables and data structures
* dealing with the DMA during the transaction process should be 32-bit aligned.
*
*
* @endverbatim
*
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_hid_keyboard.h"
#include "usbd_ctlreq.h"
#ifdef USE_USBD_COMPOSITE
#include "usbd_composite_builder.h"
#endif
/** @defgroup USBD_HID
* @brief usbd core module
* @{
*/
/** @defgroup USBD_HID_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_FunctionPrototypes
* @{
*/
static uint8_t USBD_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_HID_EP0_RxReady(USBD_HandleTypeDef *pdev);
static uint8_t USBD_HID_Keyboard_SetReport_Setup_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data);
static uint8_t USBD_HID_Keyboard_SetReport_Token_Stage(USBD_HandleTypeDef *pdev);
static uint8_t USBD_HID_Keyboard_GetReport_Token_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data);
#ifndef USE_USBD_COMPOSITE
static uint8_t *USBD_HID_GetFSCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetHSCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetOtherSpeedCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetDeviceQualifierDesc(uint16_t *length);
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/** @defgroup USBD_HID_Private_Variables
* @{
*/
USBD_ClassTypeDef USBD_HID_KEYBOARD =
{
USBD_HID_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL, /* EP0_TxSent */
USBD_HID_EP0_RxReady, /* EP0_RxReady */
USBD_HID_DataIn, /* DataIn */
USBD_HID_DataOut, /* DataOut */
NULL, /* SOF */
NULL,
NULL,
#ifdef USE_USBD_COMPOSITE
NULL,
NULL,
NULL,
NULL,
#else
USBD_HID_GetHSCfgDesc,
USBD_HID_GetFSCfgDesc,
USBD_HID_GetOtherSpeedCfgDesc,
USBD_HID_GetDeviceQualifierDesc,
#endif /* USE_USBD_COMPOSITE */
};
#ifndef USE_USBD_COMPOSITE
/* USB HID device FS Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_KEYBOARD_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_HID_KEYBOARD_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */
0x00,
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor
describing the configuration */
#if (USBD_SELF_POWERED == 1U)
0xE0, /* bmAttributes: Bus Powered according to user configuration */
#else
0xA0, /* bmAttributes: Bus Powered according to user configuration */
#endif /* USBD_SELF_POWERED */
USBD_MAX_POWER, /* MaxPower (mA) */
/************** Descriptor of Keyboard interface ****************/
/* 09 */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints */
0x03, /* bInterfaceClass: HID */
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x01, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0, /* iInterface: Index of string descriptor */
/******************** Descriptor of Keyboard HID ********************/
/* 18 */
0x09, /* bLength: HID Descriptor size */
HID_KEYBOARD_DESCRIPTOR_TYPE, /* 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 Keyboard endpoint ********************/
/* 27 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType:*/
HID_KEYBOARD_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
HID_KEYBOARD_EPIN_SIZE, /* wMaxPacketSize: 4 Byte max */
0x00,
HID_KEYBOARD_FS_BINTERVAL, /* bInterval: Polling Interval */
/* 34 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType:*/
HID_KEYBOARD_EPOUT_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
HID_KEYBOARD_EPOUT_SIZE, /* wMaxPacketSize: 4 Byte max */
0x00,
HID_KEYBOARD_FS_BINTERVAL, /* bInterval: Polling Interval */
/* 41 */
};
#endif /* USE_USBD_COMPOSITE */
/* USB HID device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_Desc[USB_HID_KEYBOARD_DESC_SIZ] __ALIGN_END =
{
/* 18 */
0x09, /* bLength: HID Descriptor size */
HID_KEYBOARD_DESCRIPTOR_TYPE, /* 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,
};
#ifndef USE_USBD_COMPOSITE
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
};
#endif /* USE_USBD_COMPOSITE */
__ALIGN_BEGIN static uint8_t HID_Keyboard_ReportDesc[HID_KEYBOARD_REPORT_DESC_SIZE] __ALIGN_END =
{
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection (Application)
0x05, 0x07, // Usage Page (Kbrd/Keypad)
0x19, 0xE0, // Usage Minimum (0xE0)
0x29, 0xE7, // Usage Maximum (0xE7)
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,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
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,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x91, 0x03, // Output (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x95, 0x06, // Report Count (6)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x65, // Logical Maximum (101)
0x05, 0x07, // Usage Page (Kbrd/Keypad)
0x19, 0x00, // Usage Minimum (Reserved (no event indicated))
0x29, 0x65, // Usage Maximum (0x65)
0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
};
static uint8_t HIDInEpAdd = HID_KEYBOARD_EPIN_ADDR;
/**
* @}
*/
/** @defgroup USBD_HID_Private_Functions
* @{
*/
/**
* @brief USBD_HID_Init
* Initialize the HID interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
USBD_HID_Keyboard_HandleTypeDef *hhid;
hhid = (USBD_HID_Keyboard_HandleTypeDef *)USBD_malloc(sizeof(USBD_HID_Keyboard_HandleTypeDef));
DEBUG("sizeof(USBD_HID_Keyboard_HandleTypeDef)=0x%x\n",sizeof(USBD_HID_Keyboard_HandleTypeDef));
if (hhid == NULL)
{
pdev->pClassDataCmsit[pdev->classId] = NULL;
return (uint8_t)USBD_EMEM;
}
pdev->pClassDataCmsit[pdev->classId] = (void *)hhid;
pdev->pClassData = pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
HIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR);
#endif /* USE_USBD_COMPOSITE */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = HID_KEYBOARD_HS_BINTERVAL;
}
else /* LOW and FULL-speed endpoints */
{
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = HID_KEYBOARD_FS_BINTERVAL;
}
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, HIDInEpAdd, USBD_EP_TYPE_INTR, HID_KEYBOARD_EPIN_SIZE);
pdev->ep_in[HIDInEpAdd & 0xFU].is_used = 1U;
/* Open EP OUT */
(void)USBD_LL_OpenEP(pdev, HID_KEYBOARD_EPOUT_ADDR, USBD_EP_TYPE_INTR, HID_KEYBOARD_EPOUT_SIZE);
pdev->ep_out[HID_KEYBOARD_EPOUT_ADDR & 0xFU].is_used = 1U;
/* Prepare Out endpoint to receive 1st packet */
(void)USBD_LL_PrepareReceive(pdev, HID_KEYBOARD_EPOUT_ADDR, hhid->Report_buf,
USBD_KEYBOARD_OUTREPORT_BUF_SIZE);
hhid->state = KEYBOARD_HID_IDLE;
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_HID_DeInit
* DeInitialize the HID layer
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
HIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR);
#endif /* USE_USBD_COMPOSITE */
/* Close HID EPs */
(void)USBD_LL_CloseEP(pdev, HIDInEpAdd);
pdev->ep_in[HIDInEpAdd & 0xFU].is_used = 0U;
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = 0U;
/* Free allocated memory */
if (pdev->pClassDataCmsit[pdev->classId] != NULL)
{
(void)USBD_free(pdev->pClassDataCmsit[pdev->classId]);
pdev->pClassDataCmsit[pdev->classId] = NULL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_HID_Setup
* Handle the HID specific requests
* @param pdev: instance
* @param req: usb requests
* @retval status
*/
static uint8_t USBD_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
USBD_StatusTypeDef ret = USBD_OK;
uint16_t len;
uint8_t *pbuf;
uint16_t status_info = 0U;
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_CLASS :
switch (req->bRequest)
{
case HID_KEYBOARD_REQ_SET_PROTOCOL:
hhid->Protocol = (uint8_t)(req->wValue);
break;
case HID_KEYBOARD_REQ_GET_PROTOCOL:
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->Protocol, 1U);
break;
case HID_KEYBOARD_REQ_SET_IDLE:
hhid->IdleState = (uint8_t)(req->wValue >> 8);
break;
case HID_KEYBOARD_REQ_GET_IDLE:
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->IdleState, 1U);
break;
case HID_KEYBOARD_REQ_SET_REPORT:
USBD_HID_Keyboard_SetReport_Setup_Stage(pdev, req);
break;
case HID_KEYBOARD_REQ_GET_REPORT:
USBD_HID_Keyboard_GetReport_Token_Stage(pdev, req);
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest)
{
case USB_REQ_GET_STATUS:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_GET_DESCRIPTOR:
if ((req->wValue >> 8) == HID_KEYBOARD_REPORT_DESC)
{
len = MIN(HID_KEYBOARD_REPORT_DESC_SIZE, req->wLength);
pbuf = HID_Keyboard_ReportDesc;
}
else if ((req->wValue >> 8) == HID_KEYBOARD_DESCRIPTOR_TYPE)
{
pbuf = USBD_HID_Desc;
len = MIN(USB_HID_KEYBOARD_DESC_SIZ, req->wLength);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
(void)USBD_CtlSendData(pdev, pbuf, len);
break;
case USB_REQ_GET_INTERFACE :
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->AltSetting, 1U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_SET_INTERFACE:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
hhid->AltSetting = (uint8_t)(req->wValue);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_CLEAR_FEATURE:
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
return (uint8_t)ret;
}
/**
* @brief USBD_HID_Keyboard_SendReport
* Send HID Report
* @param pdev: device instance
* @param buff: pointer to report
* @retval status
*/
uint8_t USBD_HID_Keyboard_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len)
{
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_KEYBOARD_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if (hhid->state == KEYBOARD_HID_IDLE)
{
hhid->state = KEYBOARD_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_KEYBOARD_EPIN_ADDR, report, len);
}
}
#endif
return (uint8_t)USBD_OK;
}
extern uint8_t epnm_flag;
uint8_t USBD_HID_Keyboard_FirstSendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len)
{
#ifdef USE_USBD_COMPOSITE
static uint8_t first_send_flag = 0;
uint8_t class_id;
uint8_t ep_id = HID_KEYBOARD_EPIN_ADDR & 0xF;
if(first_send_flag == 1){
return (uint8_t)USBD_OK;
}
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_KEYBOARD_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
PCD_HandleTypeDef *pcd = (PCD_HandleTypeDef *)(pdev->pData);
uint32_t USBx_BASE = (uint32_t)(PCD_HandleTypeDef *)pcd->Instance;
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if ((hhid->state == KEYBOARD_HID_IDLE)||(epnm_flag == 0x01))
{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_ITTXFE)
{
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_ITTXFE;
hhid->state = KEYBOARD_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_KEYBOARD_EPIN_ADDR, report, len);
}
else{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_NAK){
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_NAK;
USBx_INEP(ep_id)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
}
}
if(epnm_flag == 0x01){
epnm_flag = 0x00;
}
}
}
return (uint8_t)USBD_OK;
#else
uint8_t ep_id = HID_KEYBOARD_EPIN_ADDR & 0xF;
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
PCD_HandleTypeDef *pcd = (PCD_HandleTypeDef *)(pdev->pData);
uint32_t USBx_BASE = (uint32_t)(PCD_HandleTypeDef *)pcd->Instance;
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if ((hhid->state == KEYBOARD_HID_IDLE)||(epnm_flag == 0x01))
{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_ITTXFE)
{
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_ITTXFE ;
hhid->state = KEYBOARD_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_KEYBOARD_EPIN_ADDR, report, len);
}
else{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_NAK){
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_NAK;
USBx_INEP(ep_id)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
}
}
if(epnm_flag == 0x01){
epnm_flag = 0x00;
}
}
}
return (uint8_t)USBD_OK;
#endif
}
/**
* @brief USBD_HID_GetPollingInterval
* return polling interval from endpoint descriptor
* @param pdev: device instance
* @retval polling interval
*/
uint32_t USBD_HID_KEYBOARD_GetPollingInterval(USBD_HandleTypeDef *pdev)
{
uint32_t polling_interval;
/* HIGH-speed endpoints */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Sets the data transfer polling interval for high speed transfers.
Values between 1..16 are allowed. Values correspond to interval
of 2 ^ (bInterval-1). This option (8 ms, corresponds to HID_HS_BINTERVAL */
polling_interval = (((1U << (HID_KEYBOARD_HS_BINTERVAL - 1U))) / 8U);
}
else /* LOW and FULL-speed endpoints */
{
/* Sets the data transfer polling interval for low and full
speed transfers */
polling_interval = HID_KEYBOARD_FS_BINTERVAL;
}
return ((uint32_t)(polling_interval));
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief USBD_HID_GetCfgFSDesc
* return FS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetFSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CfgDesc, HID_KEYBOARD_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_KEYBOARD_FS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CfgDesc);
return USBD_HID_CfgDesc;
}
/**
* @brief USBD_HID_GetCfgHSDesc
* return HS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetHSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CfgDesc, HID_KEYBOARD_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_KEYBOARD_HS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CfgDesc);
return USBD_HID_CfgDesc;
}
/**
* @brief USBD_HID_GetOtherSpeedCfgDesc
* return other speed configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetOtherSpeedCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CfgDesc, HID_KEYBOARD_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_KEYBOARD_FS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CfgDesc);
return USBD_HID_CfgDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @brief USBD_HID_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
UNUSED(epnum);
/* Ensure that the FIFO is empty before a new transfer, this condition could
be caused by a new transfer before the end of the previous transfer */
((USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId])->state = KEYBOARD_HID_IDLE;
return (uint8_t)USBD_OK;
}
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
/**
* @brief USBD_CUSTOM_HID_DataOut
* handle data OUT Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
DEBUG("line=%d,epnum=0x%x\n",__LINE__,epnum);
uint8_t size_num;
USBD_HID_Keyboard_HandleTypeDef *hhid;
hhid = pdev->pClassData;
/* Ensure that the FIFO is empty before a new transfer, this condition could
be caused by a new transfer before the end of the previous transfer */
size_num = HAL_PCD_EP_GetRxCount(&hpcd_USB_OTG_FS,HID_KEYBOARD_EPOUT_ADDR);
(void)USBD_LL_PrepareReceive(pdev, HID_KEYBOARD_EPOUT_ADDR, hhid->Report_buf,HID_KEYBOARD_EPOUT_SIZE);
for(int i=0;i<size_num;i++)
{
DEBUG("0x%x ", hhid->Report_buf[i]);
}
DEBUG("\n");
hhid->state = KEYBOARD_HID_IDLE;
return (uint8_t)USBD_OK;
}
static uint8_t USBD_HID_EP0_RxReady(USBD_HandleTypeDef *pdev)
{
DEBUG("Keyboard USBD_HID_EP0_RxReady\r\n");
USBD_HID_Keyboard_SetReport_Token_Stage(pdev);
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Keyboard_SetReport_Setup_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data)
{
uint8_t report_type;
uint8_t report_id;
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_KEYBOARD_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
report_type = (setup_data->wValue >> 8) & 0xFF;
report_id = setup_data->wValue & 0xFF;
hhid->EP0_ReportLen = setup_data->wLength;
DEBUG("Setup_Stage report_type=%02x, report_id=%02x, report_len=%d\r\n",report_type, report_id, hhid->EP0_ReportLen);
(void)USBD_CtlPrepareRx(pdev, hhid->EP0_ReportBuff, hhid->EP0_ReportLen);
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Keyboard_SetReport_Token_Stage(USBD_HandleTypeDef *pdev)
{
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_KEYBOARD_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
DEBUG("Token_Stage recv len = %d\n", hhid->EP0_ReportLen);
for(int i=0;i<hhid->EP0_ReportLen;i++){
DEBUG("0x%x ", hhid->EP0_ReportBuff[i]);
}DEBUG("\n");
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Keyboard_GetReport_Token_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data)
{
uint16_t report_length;
uint8_t data[HID_KEYBOARD_EP0_GET_REPORT_BUF_SIZE];
DEBUG("%s,%d\n",__func__,__LINE__);
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_KEYBOARD_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
for(int i=0;i<HID_KEYBOARD_EP0_GET_REPORT_BUF_SIZE;i++)
{
data[i] = i;
}
report_length = setup_data->wLength;
USBD_CtlSendData(pdev, data, report_length);
return (uint8_t)USBD_OK;
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetDeviceQualifierDesc(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_HID_DeviceQualifierDesc);
return USBD_HID_DeviceQualifierDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,842 @@
/*!
* \file usbd_hid_mouse.c
*
* \brief This file provides the HID core functions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*
* @verbatim
*
* ===================================================================
* HID Class Description
* ===================================================================
* This module manages the HID class V1.11 following the "Device Class Definition
* for Human Interface Devices (HID) Version 1.11 Jun 27, 2001".
* This driver implements the following aspects of the specification:
* - The Boot Interface Subclass
* - The Mouse protocol
* - Usage Page : Generic Desktop
* - Usage : Mouse
* - Collection : Application
*
* @note In HS mode and when the DMA is used, all variables and data structures
* dealing with the DMA during the transaction process should be 32-bit aligned.
*
*
* @endverbatim
*
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_hid_mouse.h"
#include "usbd_ctlreq.h"
#ifdef USE_USBD_COMPOSITE
#include "usbd_composite_builder.h"
#endif
/** @defgroup USBD_HID
* @brief usbd core module
* @{
*/
/** @defgroup USBD_HID_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_FunctionPrototypes
* @{
*/
static uint8_t USBD_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_HID_EP0_RxReady(USBD_HandleTypeDef *pdev);
static uint8_t USBD_HID_Mouse_SetReport_Setup_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data);
static uint8_t USBD_HID_Mouse_SetReport_Token_Stage(USBD_HandleTypeDef *pdev);
static uint8_t USBD_HID_Mouse_GetReport_Token_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data);
#ifndef USE_USBD_COMPOSITE
static uint8_t *USBD_HID_GetFSCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetHSCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetOtherSpeedCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetDeviceQualifierDesc(uint16_t *length);
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/** @defgroup USBD_HID_Private_Variables
* @{
*/
USBD_ClassTypeDef USBD_HID_MOUSE =
{
USBD_HID_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL, /* EP0_TxSent */
USBD_HID_EP0_RxReady, /* EP0_RxReady */
USBD_HID_DataIn, /* DataIn */
NULL, /* DataOut */
NULL, /* SOF */
NULL,
NULL,
#ifdef USE_USBD_COMPOSITE
NULL,
NULL,
NULL,
NULL,
#else
USBD_HID_GetHSCfgDesc,
USBD_HID_GetFSCfgDesc,
USBD_HID_GetOtherSpeedCfgDesc,
USBD_HID_GetDeviceQualifierDesc,
#endif /* USE_USBD_COMPOSITE */
};
#ifndef USE_USBD_COMPOSITE
/* USB HID device FS Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_MOUSE_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_HID_MOUSE_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */
0x00,
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor
describing the configuration */
#if (USBD_SELF_POWERED == 1U)
0xE0, /* bmAttributes: Bus Powered according to user configuration */
#else
0xA0, /* bmAttributes: Bus Powered according to user configuration */
#endif /* USBD_SELF_POWERED */
USBD_MAX_POWER, /* MaxPower (mA) */
/************** Descriptor of Joystick Mouse interface ****************/
/* 09 */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_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_MOUSE_DESCRIPTOR_TYPE, /* 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_DESC_TYPE_ENDPOINT, /* bDescriptorType:*/
HID_MOUSE_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
HID_MOUSE_EPIN_SIZE, /* wMaxPacketSize: 4 Bytes max */
0x00,
HID_MOUSE_FS_BINTERVAL, /* bInterval: Polling Interval */
/* 34 */
};
#endif /* USE_USBD_COMPOSITE */
/* USB HID device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_Desc[USB_HID_MOUSE_DESC_SIZ] __ALIGN_END =
{
/* 18 */
0x09, /* bLength: HID Descriptor size */
HID_MOUSE_DESCRIPTOR_TYPE, /* 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,
};
#ifndef USE_USBD_COMPOSITE
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
};
#endif /* USE_USBD_COMPOSITE */
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */
0x09, 0x02, /* Usage (Mouse) */
0xA1, 0x01, /* Collection (Application) */
0x09, 0x01, /* Usage (Pointer) */
0xA1, 0x00, /* Collection (Physical) */
0x05, 0x09, /* Usage Page (Button) */
0x19, 0x01, /* Usage Minimum (0x01) */
0x29, 0x03, /* Usage Maximum (0x03) */
0x15, 0x00, /* Logical Minimum (0) */
0x25, 0x01, /* Logical Maximum (1) */
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 (Const,Array,Abs) */
0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */
0x09, 0x30, /* Usage (X) */
0x09, 0x31, /* Usage (Y) */
0x09, 0x38, /* Usage (Wheel) */
0x15, 0x81, /* Logical Minimum (-127) */
0x25, 0x7F, /* Logical Maximum (127) */
0x75, 0x08, /* Report Size (8) */
0x95, 0x03, /* Report Count (3) */
0x81, 0x06, /* Input (Data,Var,Rel) */
0xC0, /* End Collection */
0x09, 0x3C, /* Usage (Motion Wakeup) */
0x05, 0xFF, /* Usage Page (Reserved 0xFF) */
0x09, 0x01, /* Usage (0x01) */
0x15, 0x00, /* Logical Minimum (0) */
0x25, 0x01, /* Logical Maximum (1) */
0x75, 0x01, /* Report Size (1) */
0x95, 0x02, /* Report Count (2) */
0xB1, 0x22, /* Feature (Data,Var,Abs,NoWrp) */
0x75, 0x06, /* Report Size (6) */
0x95, 0x01, /* Report Count (1) */
0xB1, 0x01, /* Feature (Const,Array,Abs,NoWrp) */
0xC0 /* End Collection */
};
static uint8_t HIDInEpAdd = HID_MOUSE_EPIN_ADDR;
/**
* @}
*/
/** @defgroup USBD_HID_Private_Functions
* @{
*/
/**
* @brief USBD_HID_Init
* Initialize the HID interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
USBD_HID_Mouse_HandleTypeDef *hhid;
hhid = (USBD_HID_Mouse_HandleTypeDef *)USBD_malloc(sizeof(USBD_HID_Mouse_HandleTypeDef));
printf("sizeof(USBD_HID_Mouse_HandleTypeDef)=0x%x\n",sizeof(USBD_HID_Mouse_HandleTypeDef));
if (hhid == NULL)
{
pdev->pClassDataCmsit[pdev->classId] = NULL;
return (uint8_t)USBD_EMEM;
}
pdev->pClassDataCmsit[pdev->classId] = (void *)hhid;
pdev->pClassData = pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
HIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR);
#endif /* USE_USBD_COMPOSITE */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = HID_MOUSE_HS_BINTERVAL;
}
else /* LOW and FULL-speed endpoints */
{
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = HID_MOUSE_FS_BINTERVAL;
}
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, HIDInEpAdd, USBD_EP_TYPE_INTR, HID_MOUSE_EPIN_SIZE);
pdev->ep_in[HIDInEpAdd & 0xFU].is_used = 1U;
hhid->state = MOUSE_HID_IDLE;
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_HID_DeInit
* DeInitialize the HID layer
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
HIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR);
#endif /* USE_USBD_COMPOSITE */
/* Close HID EPs */
(void)USBD_LL_CloseEP(pdev, HIDInEpAdd);
pdev->ep_in[HIDInEpAdd & 0xFU].is_used = 0U;
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = 0U;
/* Free allocated memory */
if (pdev->pClassDataCmsit[pdev->classId] != NULL)
{
(void)USBD_free(pdev->pClassDataCmsit[pdev->classId]);
pdev->pClassDataCmsit[pdev->classId] = NULL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_HID_Setup
* Handle the HID specific requests
* @param pdev: instance
* @param req: usb requests
* @retval status
*/
static uint8_t USBD_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
USBD_StatusTypeDef ret = USBD_OK;
uint16_t len;
uint8_t *pbuf;
uint16_t status_info = 0U;
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_CLASS :
switch (req->bRequest)
{
case HID_MOUSE_REQ_SET_PROTOCOL:
hhid->Protocol = (uint8_t)(req->wValue);
break;
case HID_MOUSE_REQ_GET_PROTOCOL:
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->Protocol, 1U);
break;
case HID_MOUSE_REQ_SET_IDLE:
hhid->IdleState = (uint8_t)(req->wValue >> 8);
break;
case HID_MOUSE_REQ_GET_IDLE:
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->IdleState, 1U);
break;
case HID_MOUSE_REQ_SET_REPORT:
USBD_HID_Mouse_SetReport_Setup_Stage(pdev, req);
break;
case HID_MOUSE_REQ_GET_REPORT:
USBD_HID_Mouse_GetReport_Token_Stage(pdev, req);
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest)
{
case USB_REQ_GET_STATUS:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_GET_DESCRIPTOR:
if ((req->wValue >> 8) == HID_MOUSE_REPORT_DESC)
{
len = MIN(HID_MOUSE_REPORT_DESC_SIZE, req->wLength);
pbuf = HID_MOUSE_ReportDesc;
}
else if ((req->wValue >> 8) == HID_MOUSE_DESCRIPTOR_TYPE)
{
pbuf = USBD_HID_Desc;
len = MIN(USB_HID_MOUSE_DESC_SIZ, req->wLength);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
(void)USBD_CtlSendData(pdev, pbuf, len);
break;
case USB_REQ_GET_INTERFACE :
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->AltSetting, 1U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_SET_INTERFACE:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
hhid->AltSetting = (uint8_t)(req->wValue);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_CLEAR_FEATURE:
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
return (uint8_t)ret;
}
/**
* @brief USBD_HID_Mouse_SendReport
* Send HID Report
* @param pdev: device instance
* @param buff: pointer to report
* @retval status
*/
uint8_t USBD_HID_Mouse_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len)
{
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_MOUSE_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if (hhid->state == MOUSE_HID_IDLE)
{
hhid->state = MOUSE_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_MOUSE_EPIN_ADDR, report, len);
}
}
return (uint8_t)USBD_OK;
#else
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if (hhid->state == MOUSE_HID_IDLE)
{
hhid->state = MOUSE_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_MOUSE_EPIN_ADDR, report, len);
}
}
return (uint8_t)USBD_OK;
#endif
}
extern uint8_t epnm_flag;
uint8_t USBD_HID_Mouse_FirstSendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len)
{
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
uint8_t ep_id = HID_MOUSE_EPIN_ADDR & 0xF;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_MOUSE_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
PCD_HandleTypeDef *pcd = (PCD_HandleTypeDef *)(pdev->pData);
uint32_t USBx_BASE = (uint32_t)(PCD_HandleTypeDef *)pcd->Instance;
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if ((hhid->state == MOUSE_HID_IDLE)||(epnm_flag == 0x01))
{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_ITTXFE)
{
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_ITTXFE;
hhid->state = MOUSE_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_MOUSE_EPIN_ADDR, report, len);
}
else{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_NAK){
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_NAK;
USBx_INEP(ep_id)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
}
}
if(epnm_flag == 0x01){
epnm_flag = 0x00;
}
}
}
return (uint8_t)USBD_OK;
#else
uint8_t ep_id = HID_MOUSE_EPIN_ADDR & 0xF;
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
PCD_HandleTypeDef *pcd = (PCD_HandleTypeDef *)(pdev->pData);
uint32_t USBx_BASE = (uint32_t)(PCD_HandleTypeDef *)pcd->Instance;
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if ((hhid->state == MOUSE_HID_IDLE)||(epnm_flag == 0x01))
{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_ITTXFE)
{
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_ITTXFE;
hhid->state = MOUSE_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_MOUSE_EPIN_ADDR, report, len);
}
else{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_NAK){
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_NAK;
USBx_INEP(ep_id)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
}
}
if(epnm_flag == 0x01){
epnm_flag = 0x00;
}
}
}
return (uint8_t)USBD_OK;
#endif
}
/**
* @brief USBD_HID_GetPollingInterval
* return polling interval from endpoint descriptor
* @param pdev: device instance
* @retval polling interval
*/
uint32_t USBD_HID_GetPollingInterval(USBD_HandleTypeDef *pdev)
{
uint32_t polling_interval;
/* HIGH-speed endpoints */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Sets the data transfer polling interval for high speed transfers.
Values between 1..16 are allowed. Values correspond to interval
of 2 ^ (bInterval-1). This option (8 ms, corresponds to HID_MOUSE_HS_BINTERVAL */
polling_interval = (((1U << (HID_MOUSE_HS_BINTERVAL - 1U))) / 8U);
}
else /* LOW and FULL-speed endpoints */
{
/* Sets the data transfer polling interval for low and full
speed transfers */
polling_interval = HID_MOUSE_FS_BINTERVAL;
}
return ((uint32_t)(polling_interval));
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief USBD_HID_GetCfgFSDesc
* return FS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetFSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CfgDesc, HID_MOUSE_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_MOUSE_FS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CfgDesc);
return USBD_HID_CfgDesc;
}
/**
* @brief USBD_HID_GetCfgHSDesc
* return HS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetHSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CfgDesc, HID_MOUSE_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_MOUSE_HS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CfgDesc);
return USBD_HID_CfgDesc;
}
/**
* @brief USBD_HID_GetOtherSpeedCfgDesc
* return other speed configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetOtherSpeedCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CfgDesc, HID_MOUSE_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_MOUSE_FS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CfgDesc);
return USBD_HID_CfgDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @brief USBD_HID_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
UNUSED(epnum);
/* Ensure that the FIFO is empty before a new transfer, this condition could
be caused by a new transfer before the end of the previous transfer */
((USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId])->state = MOUSE_HID_IDLE;
#ifdef APP_USB_MOUSE_FAST_SEND_DATA
extern void app_usb_mouse_fast_send_data(USBD_HandleTypeDef *pdev);
app_usb_mouse_fast_send_data(pdev);
#endif
return (uint8_t)USBD_OK;
}
static uint8_t USBD_HID_EP0_RxReady(USBD_HandleTypeDef *pdev)
{
DEBUG("Mouse USBD_HID_EP0_RxReady\r\n");
USBD_HID_Mouse_SetReport_Token_Stage(pdev);
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Mouse_SetReport_Setup_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data)
{
uint8_t report_type;
uint8_t report_id;
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_MOUSE_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
report_type = (setup_data->wValue >> 8) & 0xFF;
report_id = setup_data->wValue & 0xFF;
hhid->EP0_ReportLen = setup_data->wLength;
DEBUG("Setup_Stage report_type=%02x, report_id=%02x, report_len=%d\r\n",report_type, report_id, hhid->EP0_ReportLen);
(void)USBD_CtlPrepareRx(pdev, hhid->EP0_ReportBuff, hhid->EP0_ReportLen);
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Mouse_SetReport_Token_Stage(USBD_HandleTypeDef *pdev)
{
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_MOUSE_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
DEBUG("Token_Stage recv len = %d\n", hhid->EP0_ReportLen);
for(int i=0;i<hhid->EP0_ReportLen;i++){
DEBUG("0x%x ", hhid->EP0_ReportBuff[i]);
}DEBUG("\n");
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Mouse_GetReport_Token_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data)
{
uint16_t report_length;
uint8_t data[HID_MOUSE_EP0_GET_REPORT_BUF_SIZE];
DEBUG("%s,%d\n",__func__,__LINE__);
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_MOUSE_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
for(int i=0;i<HID_MOUSE_EP0_GET_REPORT_BUF_SIZE;i++)
{
data[i] = i;
}
report_length = setup_data->wLength;
USBD_CtlSendData(pdev, data, report_length);
return (uint8_t)USBD_OK;
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetDeviceQualifierDesc(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_HID_DeviceQualifierDesc);
return USBD_HID_DeviceQualifierDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,180 @@
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_HID_CUSTOM_H
#define __USB_HID_CUSTOM_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @defgroup USBD_HID
* @brief This file is the Header file for usbd_hid.c
* @{
*/
/** @defgroup USBD_HID_Exported_Defines
* @{
*/
#ifndef HID_CUSTOM_EPIN_ADDR
#define HID_CUSTOM_EPIN_ADDR 0x83U
#endif /* HID_EPIN_ADDR */
#define HID_CUSTOM_EPIN_SIZE 0x40U
#ifndef HID_CUSTOM_EPOUT_ADDR
#define HID_CUSTOM_EPOUT_ADDR 0x03U
#endif /* HID_CUSTOM_EPOUT_ADDR */
#define HID_CUSTOM_EPOUT_SIZE 0x40U
#define USB_HID_CUSTOM_CONFIG_DESC_SIZ 34U
#define USB_HID_CUSTOM_DESC_SIZ 9U
#define HID_CUSTOM_REPORT_DESC_SIZE 38+45U
#define HID_CUSTOM_DESCRIPTOR_TYPE 0x21U
#define HID_CUSTOM_REPORT_DESC 0x22U
#ifndef HID_CUSTOM_HS_BINTERVAL
#define HID_CUSTOM_HS_BINTERVAL 0x07U
#endif /* HID_HS_BINTERVAL */
#ifndef HID_CUSTOM_FS_BINTERVAL
#define HID_CUSTOM_FS_BINTERVAL 0x0AU
#endif /* HID_FS_BINTERVAL */
#ifndef USBD_CUSTOM_OUTREPORT_BUF_SIZE
#define USBD_CUSTOM_OUTREPORT_BUF_SIZE 0x02U
#endif /* USBD_CUSTOM_OUTREPORT_BUF_SIZE */
#define HID_CUSTOM_REQ_SET_PROTOCOL 0x0BU
#define HID_CUSTOM_REQ_GET_PROTOCOL 0x03U
#define HID_CUSTOM_REQ_SET_IDLE 0x0AU
#define HID_CUSTOM_REQ_GET_IDLE 0x02U
#define HID_CUSTOM_REQ_SET_REPORT 0x09U
#define HID_CUSTOM_REQ_GET_REPORT 0x01U
#ifndef HID_CUSTOM_EP0_SET_REPORT_BUF_SIZE
#define HID_CUSTOM_EP0_SET_REPORT_BUF_SIZE 0x10U
#endif /* HID_CUSTOM_EP0_SET_REPORT_BUF_SIZE */
#ifndef HID_CUSTOM_EP0_GET_REPORT_BUF_SIZE
#define HID_CUSTOM_EP0_GET_REPORT_BUF_SIZE 0x10U
#endif /* HID_CUSTOM_EP0_GET_REPORT_BUF_SIZE */
/**
* @}
*/
#define USB_DFU_REPORT_MAP \
0x06, 0x86, 0x19, /* Usage Page (ByteX)*/\
0x09, 0x10, /* Usage (0x10)*/\
0xA1, 0x01, /* Collection (Application)*/\
0x85, 0xFA, /* Report ID (-79)*/\
0x15, 0x00, /* Logical Minimum (0)*/\
0x25, 0xFF, /* Logical Maximum (-1)*/\
0x09, 0x00, /* Usage (Unassigned)*/\
0x19, 0x00, /* Usage (Unassigned)*/\
0x29, 0xFF, /* Usage Maximum (0xFF)*/\
0x75, 0x08, /* Report Size (8)*/\
0x95, 63, /* Report Count (63)*/\
0x81, 0x02, /* Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)*/\
0x85, 0xFB, /* Report ID (-78)*/\
0x15, 0x00, /* Logical Minimum (0)*/\
0x25, 0xFF, /* Logical Maximum (-1)*/\
0x09, 0x00, /* Usage (Unassigned)*/\
0x19, 0x00, /* Usage (Unassigned)*/\
0x29, 0xFF, /* Usage Maximum (0xFF)*/\
0x75, 0x08, /* Report Size (8)*/\
0x96, 0xFF, 0x01, /* Report Count (511)*/\
0x91, 0x02, /* Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)*/\
0xC0
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef enum
{
CUSTOM_HID_IDLE = 0,
CUSTOM_HID_BUSY,
} HID_Custom_StateTypeDef;
typedef struct
{
uint8_t EP0_ReportBuff[HID_CUSTOM_EP0_SET_REPORT_BUF_SIZE];
uint8_t EP0_ReportLen;
uint8_t Report_buf[USBD_CUSTOM_OUTREPORT_BUF_SIZE];
uint32_t Protocol;
uint32_t IdleState;
uint32_t AltSetting;
HID_Custom_StateTypeDef state;
} USBD_HID_Custom_HandleTypeDef;
/*
* HID Class specification version 1.1
* 6.2.1 HID Descriptor
*/
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bHIDDescriptorType;
uint16_t wItemLength;
} __PACKED USBD_HID_CustomDescTypeDef;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_HID_CUSTOM;
#define USBD_HID_CUSTOM_CLASS &USBD_HID_CUSTOM
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_HID_CUSTOM_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
uint32_t USBD_HID_CUSTOM_GetPollingInterval(USBD_HandleTypeDef *pdev);
uint8_t USBD_HID_Custom_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
uint8_t USBD_HID_Custom_FirstSendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HID_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,156 @@
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_HID_KEYBOARD_H
#define __USB_HID_KEYBOARD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @defgroup USBD_HID
* @brief This file is the Header file for usbd_hid.c
* @{
*/
/** @defgroup USBD_HID_Exported_Defines
* @{
*/
#ifndef HID_KEYBOARD_EPIN_ADDR
#define HID_KEYBOARD_EPIN_ADDR 0x82U
#endif /* HID_EPIN_ADDR */
#define HID_KEYBOARD_EPIN_SIZE 0x08U
#ifndef HID_KEYBOARD_EPOUT_ADDR
#define HID_KEYBOARD_EPOUT_ADDR 0x02U
#endif /* HID_EPIN_ADDR */
#define HID_KEYBOARD_EPOUT_SIZE 0x01U
#define USB_HID_KEYBOARD_CONFIG_DESC_SIZ 41U
#define USB_HID_KEYBOARD_DESC_SIZ 9U
#define HID_KEYBOARD_REPORT_DESC_SIZE 63U
#define HID_KEYBOARD_DESCRIPTOR_TYPE 0x21U
#define HID_KEYBOARD_REPORT_DESC 0x22U
#ifndef HID_KEYBOARD_HS_BINTERVAL
#define HID_KEYBOARD_HS_BINTERVAL 0x07U
#endif /* HID_HS_BINTERVAL */
#ifndef HID_KEYBOARD_FS_BINTERVAL
#define HID_KEYBOARD_FS_BINTERVAL 0x0AU
#endif /* HID_FS_BINTERVAL */
#ifndef USBD_KEYBOARD_OUTREPORT_BUF_SIZE
#define USBD_KEYBOARD_OUTREPORT_BUF_SIZE 0x02U
#endif /* USBD_KEYBOARD_OUTREPORT_BUF_SIZE */
#define HID_KEYBOARD_REQ_SET_PROTOCOL 0x0BU
#define HID_KEYBOARD_REQ_GET_PROTOCOL 0x03U
#define HID_KEYBOARD_REQ_SET_IDLE 0x0AU
#define HID_KEYBOARD_REQ_GET_IDLE 0x02U
#define HID_KEYBOARD_REQ_SET_REPORT 0x09U
#define HID_KEYBOARD_REQ_GET_REPORT 0x01U
#ifndef HID_KEYBOARD_EP0_SET_REPORT_BUF_SIZE
#define HID_KEYBOARD_EP0_SET_REPORT_BUF_SIZE 0x10U
#endif /* HID_KEYBOARD_EP0_SET_REPORT_BUF_SIZE */
#ifndef HID_KEYBOARD_EP0_GET_REPORT_BUF_SIZE
#define HID_KEYBOARD_EP0_GET_REPORT_BUF_SIZE 0x10U
#endif /* HID_KEYBOARD_EP0_GET_REPORT_BUF_SIZE */
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef enum
{
KEYBOARD_HID_IDLE = 0,
KEYBOARD_HID_BUSY,
} HID_Keyboard_StateTypeDef;
typedef struct
{
uint8_t EP0_ReportBuff[HID_KEYBOARD_EP0_SET_REPORT_BUF_SIZE];
uint8_t EP0_ReportLen;
uint8_t Report_buf[USBD_KEYBOARD_OUTREPORT_BUF_SIZE];
uint32_t Protocol;
uint32_t IdleState;
uint32_t AltSetting;
HID_Keyboard_StateTypeDef state;
} USBD_HID_Keyboard_HandleTypeDef;
/*
* HID Class specification version 1.1
* 6.2.1 HID Descriptor
*/
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bHIDDescriptorType;
uint16_t wItemLength;
} __PACKED USBD_HID_KeyboardDescTypeDef;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_HID_KEYBOARD;
#define USBD_HID_KEYBOARD_CLASS &USBD_HID_KEYBOARD
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_HID_Keyboard_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
uint32_t USBD_HID_GetPollingInterval(USBD_HandleTypeDef *pdev);
uint8_t USBD_HID_Keyboard_FirstSendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HID_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,172 @@
/*!
* \file usbd_hid.h
*
* \brief This file provides the HID core functions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_HID_MOUSE_H
#define __USB_HID_MOUSE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @defgroup USBD_HID
* @brief This file is the Header file for usbd_hid.c
* @{
*/
/** @defgroup USBD_HID_Exported_Defines
* @{
*/
#ifndef HID_MOUSE_EPIN_ADDR
#define HID_MOUSE_EPIN_ADDR 0x81U
#endif /* HID_EPIN_ADDR */
#define HID_MOUSE_EPIN_SIZE 0x04U
#define USB_HID_MOUSE_CONFIG_DESC_SIZ 34U
#define USB_HID_MOUSE_DESC_SIZ 9U
#define HID_MOUSE_REPORT_DESC_SIZE 74U
#define HID_MOUSE_DESCRIPTOR_TYPE 0x21U
#define HID_MOUSE_REPORT_DESC 0x22U
#ifndef HID_MOUSE_HS_BINTERVAL
#define HID_MOUSE_HS_BINTERVAL 0x07U
#endif /* HID_HS_BINTERVAL */
#ifndef HID_MOUSE_FS_BINTERVAL
#define HID_MOUSE_FS_BINTERVAL 0x01U
#endif /* HID_FS_BINTERVAL */
#define HID_MOUSE_REQ_SET_PROTOCOL 0x0BU
#define HID_MOUSE_REQ_GET_PROTOCOL 0x03U
#define HID_MOUSE_REQ_SET_IDLE 0x0AU
#define HID_MOUSE_REQ_GET_IDLE 0x02U
#define HID_MOUSE_REQ_SET_REPORT 0x09U
#define HID_MOUSE_REQ_GET_REPORT 0x01U
#ifndef HID_MOUSE_EP0_SET_REPORT_BUF_SIZE
#define HID_MOUSE_EP0_SET_REPORT_BUF_SIZE 0x10U
#endif /* HID_MOUSE_EP0_SET_REPORT_BUF_SIZE */
#ifndef HID_MOUSE_EP0_GET_REPORT_BUF_SIZE
#define HID_MOUSE_EP0_GET_REPORT_BUF_SIZE 0x10U
#endif /* HID_MOUSE_EP0_GET_REPORT_BUF_SIZE */
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef enum
{
MOUSE_HID_IDLE = 0,
MOUSE_HID_BUSY,
} HID_Mouse_StateTypeDef;
typedef struct
{
uint8_t EP0_ReportBuff[HID_MOUSE_EP0_SET_REPORT_BUF_SIZE];
uint8_t EP0_ReportLen;
uint32_t Protocol;
uint32_t IdleState;
uint32_t AltSetting;
HID_Mouse_StateTypeDef state;
} USBD_HID_Mouse_HandleTypeDef;
/*
* HID Class specification version 1.1
* 6.2.1 HID Descriptor
*/
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bHIDDescriptorType;
uint16_t wItemLength;
} __PACKED USBD_HID_MouseDescTypeDef;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_HID_MOUSE;
#define USBD_HID_MOUSE_CLASS &USBD_HID_MOUSE
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_HID_Mouse_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
uint32_t USBD_HID_GetPollingInterval(USBD_HandleTypeDef *pdev);
uint8_t USBD_HID_Mouse_FirstSendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HID_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,865 @@
/*!
* \file usbd_hid_custom.c
*
* \brief This file provides the HID core functions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*
* @verbatim
*
* ===================================================================
* HID Class Description
* ===================================================================
* This module manages the HID class V1.11 following the "Device Class Definition
* for Human Interface Devices (HID) Version 1.11 Jun 27, 2001".
* This driver implements the following aspects of the specification:
* - The Boot Interface Subclass
* - The Mouse protocol
* - Usage Page : Generic Desktop
* - Usage : Custom
* - Collection : Application
*
* @note In HS mode and when the DMA is used, all variables and data structures
* dealing with the DMA during the transaction process should be 32-bit aligned.
*
*
* @endverbatim
*
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_hid_custom.h"
#include "usbd_ctlreq.h"
#ifdef USE_USBD_COMPOSITE
#include "usbd_composite_builder.h"
#endif
/** @defgroup USBD_HID
* @brief usbd core module
* @{
*/
/** @defgroup USBD_HID_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_FunctionPrototypes
* @{
*/
static uint8_t USBD_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_HID_EP0_RxReady(USBD_HandleTypeDef *pdev);
static uint8_t USBD_HID_Custom_SetReport_Setup_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data);
static uint8_t USBD_HID_Custom_SetReport_Token_Stage(USBD_HandleTypeDef *pdev);
static uint8_t USBD_HID_Custom_GetReport_Token_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data);
#ifndef USE_USBD_COMPOSITE
static uint8_t *USBD_HID_GetFSCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetHSCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetOtherSpeedCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetDeviceQualifierDesc(uint16_t *length);
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/** @defgroup USBD_HID_Private_Variables
* @{
*/
USBD_ClassTypeDef USBD_HID_CUSTOM =
{
USBD_HID_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL, /* EP0_TxSent */
USBD_HID_EP0_RxReady, /* EP0_RxReady */
USBD_HID_DataIn, /* DataIn */
USBD_HID_DataOut, /* DataOut */
NULL, /* SOF */
NULL,
NULL,
#ifdef USE_USBD_COMPOSITE
NULL,
NULL,
NULL,
NULL,
#else
USBD_HID_GetHSCfgDesc,
USBD_HID_GetFSCfgDesc,
USBD_HID_GetOtherSpeedCfgDesc,
USBD_HID_GetDeviceQualifierDesc,
#endif /* USE_USBD_COMPOSITE */
};
#ifndef USE_USBD_COMPOSITE
/* USB HID device FS Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_CUSTOM_CfgDesc[USB_HID_CUSTOM_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_HID_CUSTOM_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */
0x00,
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor
describing the configuration */
#if (USBD_SELF_POWERED == 1U)
0xE0, /* bmAttributes: Bus Powered according to user configuration */
#else
0xA0, /* bmAttributes: Bus Powered according to user configuration */
#endif /* USBD_SELF_POWERED */
USBD_MAX_POWER, /* MaxPower (mA) */
/************** Descriptor of Custom interface ****************/
/* 09 */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints */
0x03, /* bInterfaceClass: HID */
0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0, /* iInterface: Index of string descriptor */
/******************** Descriptor of Joystick Custom HID ********************/
/* 18 */
0x09, /* bLength: HID Descriptor size */
HID_CUSTOM_DESCRIPTOR_TYPE, /* bDescriptorType: HID */
0x11, /* bcdHID: HID Class Spec release number */
0x01,
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
0x22, /* bDescriptorType */
HID_CUSTOM_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
0x00,
/******************** Descriptor of Custom endpoint ********************/
/* 27 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType:*/
HID_CUSTOM_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
HID_CUSTOM_EPIN_SIZE, /* wMaxPacketSize: 4 Bytes max */
0x00,
HID_CUSTOM_FS_BINTERVAL, /* bInterval: Polling Interval */
/* 34 */
};
#endif /* USE_USBD_COMPOSITE */
/* USB HID device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_Desc[USB_HID_CUSTOM_DESC_SIZ] __ALIGN_END =
{
/* 18 */
0x09, /* bLength: HID Descriptor size */
HID_CUSTOM_DESCRIPTOR_TYPE, /* bDescriptorType: HID */
0x11, /* bcdHID: HID Class Spec release number */
0x01,
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
0x22, /* bDescriptorType */
HID_CUSTOM_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
0x00,
};
#ifndef USE_USBD_COMPOSITE
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
};
#endif /* USE_USBD_COMPOSITE */
__ALIGN_BEGIN static uint8_t HID_Custom_ReportDesc[HID_CUSTOM_REPORT_DESC_SIZE] __ALIGN_END =
{
0x06, 0x00, 0xff, //USAGE_PAGE(Vendor Defined Page 1)
0x09, 0x01, //USAGE(Vendor Usage 1)
0xa1, 0x01, //COLLECTION (Application)
0x85, 0x01, //REPORT ID (0x01)
0x09, 0x01, //USAGE(Vendor Usage 1)
0x15, 0x00, //LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, //LOGICAL_MAXIMUM (255)
0x95, 0x40-0x01, //REPORT_COUNT (63)
0x75, 0x08, //REPORT_SIZE (8)
0x81, 0x02, //INPUT (Data,Var,Abs)
0x85, 0x02, //REPORT ID (0x02)
0x09, 0x01, //USAGE(Vendor Usage 1)
0x15, 0x00, //LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, //LOGICAL_MAXIMUM (255)
0x95, 0x40-0x01, //REPORT_COUNT (63)
0x75, 0x08, //REPORT_SIZE (8)
0x91, 0x02, //OUTPUT (Data,Var,Abs)
0xc0, //END_COLLECTION
USB_DFU_REPORT_MAP
};
static uint8_t HIDInEpAdd = HID_CUSTOM_EPIN_ADDR;
/**
* @}
*/
/** @defgroup USBD_HID_Private_Functions
* @{
*/
/**
* @brief USBD_HID_Init
* Initialize the HID interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
USBD_HID_Custom_HandleTypeDef *hhid;
hhid = (USBD_HID_Custom_HandleTypeDef *)USBD_malloc(sizeof(USBD_HID_Custom_HandleTypeDef));
DEBUG("sizeof(USBD_HID_Custom_HandleTypeDef)=0x%x\n",sizeof(USBD_HID_Custom_HandleTypeDef));
if (hhid == NULL)
{
pdev->pClassDataCmsit[pdev->classId] = NULL;
return (uint8_t)USBD_EMEM;
}
pdev->pClassDataCmsit[pdev->classId] = (void *)hhid;
pdev->pClassData = pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
HIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR);
#endif /* USE_USBD_COMPOSITE */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = HID_CUSTOM_HS_BINTERVAL;
}
else /* LOW and FULL-speed endpoints */
{
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = HID_CUSTOM_FS_BINTERVAL;
}
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, HIDInEpAdd, USBD_EP_TYPE_INTR, HID_CUSTOM_EPIN_SIZE);
pdev->ep_in[HIDInEpAdd & 0xFU].is_used = 1U;
/* Open EP OUT */
(void)USBD_LL_OpenEP(pdev, HID_CUSTOM_EPOUT_ADDR, USBD_EP_TYPE_INTR, HID_CUSTOM_EPOUT_SIZE);
pdev->ep_out[HID_CUSTOM_EPOUT_ADDR & 0xFU].is_used = 1U;
/* Prepare Out endpoint to receive 1st packet */
(void)USBD_LL_PrepareReceive(pdev, HID_CUSTOM_EPOUT_ADDR, hhid->Report_buf,
HID_CUSTOM_EPOUT_SIZE);
hhid->state = CUSTOM_HID_IDLE;
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_HID_DeInit
* DeInitialize the HID layer
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
HIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR);
#endif /* USE_USBD_COMPOSITE */
/* Close HID EPs */
(void)USBD_LL_CloseEP(pdev, HIDInEpAdd);
pdev->ep_in[HIDInEpAdd & 0xFU].is_used = 0U;
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = 0U;
/* Free allocated memory */
if (pdev->pClassDataCmsit[pdev->classId] != NULL)
{
(void)USBD_free(pdev->pClassDataCmsit[pdev->classId]);
pdev->pClassDataCmsit[pdev->classId] = NULL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_HID_Setup
* Handle the HID specific requests
* @param pdev: instance
* @param req: usb requests
* @retval status
*/
static uint8_t USBD_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
USBD_StatusTypeDef ret = USBD_OK;
uint16_t len;
uint8_t *pbuf;
uint16_t status_info = 0U;
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_CLASS :
switch (req->bRequest)
{
case HID_CUSTOM_REQ_SET_PROTOCOL:
hhid->Protocol = (uint8_t)(req->wValue);
break;
case HID_CUSTOM_REQ_GET_PROTOCOL:
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->Protocol, 1U);
break;
case HID_CUSTOM_REQ_SET_IDLE:
hhid->IdleState = (uint8_t)(req->wValue >> 8);
break;
case HID_CUSTOM_REQ_GET_IDLE:
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->IdleState, 1U);
break;
case HID_CUSTOM_REQ_SET_REPORT:
USBD_HID_Custom_SetReport_Setup_Stage(pdev, req);
break;
case HID_CUSTOM_REQ_GET_REPORT:
USBD_HID_Custom_GetReport_Token_Stage(pdev, req);
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest)
{
case USB_REQ_GET_STATUS:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_GET_DESCRIPTOR:
if ((req->wValue >> 8) == HID_CUSTOM_REPORT_DESC)
{
len = MIN(HID_CUSTOM_REPORT_DESC_SIZE, req->wLength);
pbuf = HID_Custom_ReportDesc;
}
else if ((req->wValue >> 8) == HID_CUSTOM_DESCRIPTOR_TYPE)
{
pbuf = USBD_HID_Desc;
len = MIN(USB_HID_CUSTOM_DESC_SIZ, req->wLength);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
(void)USBD_CtlSendData(pdev, pbuf, len);
break;
case USB_REQ_GET_INTERFACE :
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->AltSetting, 1U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_SET_INTERFACE:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
hhid->AltSetting = (uint8_t)(req->wValue);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_CLEAR_FEATURE:
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
return (uint8_t)ret;
}
/**
* @brief USBD_HID_Custom_SendReport
* Send HID Report
* @param pdev: device instance
* @param buff: pointer to report
* @retval status
*/
uint8_t USBD_HID_Custom_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len)
{
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_CUSTOM_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if (hhid->state == CUSTOM_HID_IDLE)
{
hhid->state = CUSTOM_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_CUSTOM_EPIN_ADDR, report, len);
}
}
return (uint8_t)USBD_OK;
#else
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if (hhid->state == CUSTOM_HID_IDLE)
{
hhid->state = CUSTOM_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_CUSTOM_EPIN_ADDR, report, len);
}
}
return (uint8_t)USBD_OK;
#endif
}
extern uint8_t epnm_flag;
/**
* @brief USBD_HID_Custom_FirstSendReport
* Send HID Report
* @param pdev: device instance
* @param buff: pointer to report
* @retval status
*/
uint8_t USBD_HID_Custom_FirstSendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len)
{
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
uint8_t ep_id = HID_CUSTOM_EPIN_ADDR & 0xF;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_CUSTOM_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
PCD_HandleTypeDef *pcd = (PCD_HandleTypeDef *)(pdev->pData);
uint32_t USBx_BASE = (uint32_t)(PCD_HandleTypeDef *)pcd->Instance;
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if ((hhid->state == CUSTOM_HID_IDLE)||(epnm_flag == 0x01))
{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_ITTXFE)
{
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_ITTXFE;
hhid->state = CUSTOM_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_CUSTOM_EPIN_ADDR, report, len);
}
else{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_NAK){
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_NAK;
USBx_INEP(ep_id)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
}
}
if(epnm_flag == 0x01){
epnm_flag = 0x00;
}
}
}
return (uint8_t)USBD_OK;
#else
uint8_t ep_id = HID_CUSTOM_EPIN_ADDR & 0xF;
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
PCD_HandleTypeDef *pcd = (PCD_HandleTypeDef *)(pdev->pData);
uint32_t USBx_BASE = (uint32_t)(PCD_HandleTypeDef *)pcd->Instance;
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if ((hhid->state == CUSTOM_HID_IDLE)||(epnm_flag == 0x01))
{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_ITTXFE)
{
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_ITTXFE;
hhid->state = CUSTOM_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_CUSTOM_EPIN_ADDR, report, len);
}
else{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_NAK){
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_NAK;
USBx_INEP(ep_id)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
}
}
if(epnm_flag == 0x01){
epnm_flag = 0x00;
}
}
}
return (uint8_t)USBD_OK;
#endif
}
/**
* @brief USBD_HID_GetPollingInterval
* return polling interval from endpoint descriptor
* @param pdev: device instance
* @retval polling interval
*/
uint32_t USBD_HID_Custom_GetPollingInterval(USBD_HandleTypeDef *pdev)
{
uint32_t polling_interval;
/* HIGH-speed endpoints */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Sets the data transfer polling interval for high speed transfers.
Values between 1..16 are allowed. Values correspond to interval
of 2 ^ (bInterval-1). This option (8 ms, corresponds to HID_HS_BINTERVAL */
polling_interval = (((1U << (HID_CUSTOM_HS_BINTERVAL - 1U))) / 8U);
}
else /* LOW and FULL-speed endpoints */
{
/* Sets the data transfer polling interval for low and full
speed transfers */
polling_interval = HID_CUSTOM_FS_BINTERVAL;
}
return ((uint32_t)(polling_interval));
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief USBD_HID_GetCfgFSDesc
* return FS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetFSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CUSTOM_CfgDesc, HID_CUSTOM_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_CUSTOM_FS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CUSTOM_CfgDesc);
return USBD_HID_CUSTOM_CfgDesc;
}
/**
* @brief USBD_HID_GetCfgHSDesc
* return HS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetHSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CUSTOM_CfgDesc, HID_CUSTOM_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_CUSTOM_HS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CUSTOM_CfgDesc);
return USBD_HID_CUSTOM_CfgDesc;
}
/**
* @brief USBD_HID_GetOtherSpeedCfgDesc
* return other speed configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetOtherSpeedCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CUSTOM_CfgDesc, HID_CUSTOM_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_CUSTOM_FS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CUSTOM_CfgDesc);
return USBD_HID_CUSTOM_CfgDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @brief USBD_HID_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
UNUSED(epnum);
/* Ensure that the FIFO is empty before a new transfer, this condition could
be caused by a new transfer before the end of the previous transfer */
((USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId])->state = CUSTOM_HID_IDLE;
return (uint8_t)USBD_OK;
}
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
/**
* @brief USBD_HID_DataOut
* handle data OUT Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
UNUSED(epnum);
uint8_t size_num;
USBD_HID_Custom_HandleTypeDef *hhid;
hhid = pdev->pClassData;
/* Ensure that the FIFO is empty before a new transfer, this condition could
be caused by a new transfer before the end of the previous transfer */
size_num = HAL_PCD_EP_GetRxCount(&hpcd_USB_OTG_FS,HID_CUSTOM_EPOUT_ADDR);
(void)USBD_LL_PrepareReceive(pdev, HID_CUSTOM_EPOUT_ADDR, hhid->Report_buf,HID_CUSTOM_EPOUT_SIZE);
for(int i=0;i<size_num;i++)
{
DEBUG("0x%x ", hhid->Report_buf[i]);
}
DEBUG("\n");
hhid->state = CUSTOM_HID_IDLE;
return (uint8_t)USBD_OK;
}
static uint8_t USBD_HID_EP0_RxReady(USBD_HandleTypeDef *pdev)
{
DEBUG("Custom USBD_HID_EP0_RxReady\r\n");
USBD_HID_Custom_SetReport_Token_Stage(pdev);
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Custom_SetReport_Setup_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data)
{
uint8_t report_type;
uint8_t report_id;
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_CUSTOM_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
report_type = (setup_data->wValue >> 8) & 0xFF;
report_id = setup_data->wValue & 0xFF;
hhid->EP0_ReportLen = setup_data->wLength;
DEBUG("Setup_Stage report_type=%02x, report_id=%02x, report_len=%d\r\n",report_type, report_id, hhid->EP0_ReportLen);
(void)USBD_CtlPrepareRx(pdev, hhid->EP0_ReportBuff, hhid->EP0_ReportLen);
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Custom_SetReport_Token_Stage(USBD_HandleTypeDef *pdev)
{
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_CUSTOM_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
DEBUG("Token_Stage recv len = %d\n", hhid->EP0_ReportLen);
for(int i=0;i<hhid->EP0_ReportLen;i++){
DEBUG("0x%x ", hhid->EP0_ReportBuff[i]);
}DEBUG("\n");
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Custom_GetReport_Token_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data)
{
uint16_t report_length;
uint8_t data[HID_CUSTOM_EP0_GET_REPORT_BUF_SIZE];
DEBUG("%s,%d\n",__func__,__LINE__);
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_CUSTOM_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Custom_HandleTypeDef *hhid = (USBD_HID_Custom_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
for(int i=0;i<HID_CUSTOM_EP0_GET_REPORT_BUF_SIZE;i++)
{
data[i] = i;
}
report_length = setup_data->wLength;
USBD_CtlSendData(pdev, data, report_length);
return (uint8_t)USBD_OK;
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetDeviceQualifierDesc(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_HID_DeviceQualifierDesc);
return USBD_HID_DeviceQualifierDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,863 @@
/*!
* \file usbd_hid_keyboard.c
*
* \brief This file provides the HID core functions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*
* @verbatim
*
* ===================================================================
* HID Class Description
* ===================================================================
* This module manages the HID class V1.11 following the "Device Class Definition
* for Human Interface Devices (HID) Version 1.11 Jun 27, 2001".
* This driver implements the following aspects of the specification:
* - The Boot Interface Subclass
* - The Mouse protocol
* - Usage Page : Generic Desktop
* - Usage : Keyboard
* - Collection : Application
*
* @note In HS mode and when the DMA is used, all variables and data structures
* dealing with the DMA during the transaction process should be 32-bit aligned.
*
*
* @endverbatim
*
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_hid_keyboard.h"
#include "usbd_ctlreq.h"
#ifdef USE_USBD_COMPOSITE
#include "usbd_composite_builder.h"
#endif
/** @defgroup USBD_HID
* @brief usbd core module
* @{
*/
/** @defgroup USBD_HID_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_FunctionPrototypes
* @{
*/
static uint8_t USBD_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_HID_EP0_RxReady(USBD_HandleTypeDef *pdev);
static uint8_t USBD_HID_Keyboard_SetReport_Setup_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data);
static uint8_t USBD_HID_Keyboard_SetReport_Token_Stage(USBD_HandleTypeDef *pdev);
static uint8_t USBD_HID_Keyboard_GetReport_Token_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data);
#ifndef USE_USBD_COMPOSITE
static uint8_t *USBD_HID_GetFSCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetHSCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetOtherSpeedCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetDeviceQualifierDesc(uint16_t *length);
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/** @defgroup USBD_HID_Private_Variables
* @{
*/
USBD_ClassTypeDef USBD_HID_KEYBOARD =
{
USBD_HID_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL, /* EP0_TxSent */
USBD_HID_EP0_RxReady, /* EP0_RxReady */
USBD_HID_DataIn, /* DataIn */
USBD_HID_DataOut, /* DataOut */
NULL, /* SOF */
NULL,
NULL,
#ifdef USE_USBD_COMPOSITE
NULL,
NULL,
NULL,
NULL,
#else
USBD_HID_GetHSCfgDesc,
USBD_HID_GetFSCfgDesc,
USBD_HID_GetOtherSpeedCfgDesc,
USBD_HID_GetDeviceQualifierDesc,
#endif /* USE_USBD_COMPOSITE */
};
#ifndef USE_USBD_COMPOSITE
/* USB HID device FS Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_KEYBOARD_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_HID_KEYBOARD_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */
0x00,
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor
describing the configuration */
#if (USBD_SELF_POWERED == 1U)
0xE0, /* bmAttributes: Bus Powered according to user configuration */
#else
0xA0, /* bmAttributes: Bus Powered according to user configuration */
#endif /* USBD_SELF_POWERED */
USBD_MAX_POWER, /* MaxPower (mA) */
/************** Descriptor of Keyboard interface ****************/
/* 09 */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints */
0x03, /* bInterfaceClass: HID */
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x01, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0, /* iInterface: Index of string descriptor */
/******************** Descriptor of Keyboard HID ********************/
/* 18 */
0x09, /* bLength: HID Descriptor size */
HID_KEYBOARD_DESCRIPTOR_TYPE, /* 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 Keyboard endpoint ********************/
/* 27 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType:*/
HID_KEYBOARD_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
HID_KEYBOARD_EPIN_SIZE, /* wMaxPacketSize: 4 Byte max */
0x00,
HID_KEYBOARD_FS_BINTERVAL, /* bInterval: Polling Interval */
/* 34 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType:*/
HID_KEYBOARD_EPOUT_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
HID_KEYBOARD_EPOUT_SIZE, /* wMaxPacketSize: 4 Byte max */
0x00,
HID_KEYBOARD_FS_BINTERVAL, /* bInterval: Polling Interval */
/* 41 */
};
#endif /* USE_USBD_COMPOSITE */
/* USB HID device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_Desc[USB_HID_KEYBOARD_DESC_SIZ] __ALIGN_END =
{
/* 18 */
0x09, /* bLength: HID Descriptor size */
HID_KEYBOARD_DESCRIPTOR_TYPE, /* 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,
};
#ifndef USE_USBD_COMPOSITE
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
};
#endif /* USE_USBD_COMPOSITE */
__ALIGN_BEGIN static uint8_t HID_Keyboard_ReportDesc[HID_KEYBOARD_REPORT_DESC_SIZE] __ALIGN_END =
{
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection (Application)
0x05, 0x07, // Usage Page (Kbrd/Keypad)
0x19, 0xE0, // Usage Minimum (0xE0)
0x29, 0xE7, // Usage Maximum (0xE7)
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,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
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,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x91, 0x03, // Output (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x95, 0x06, // Report Count (6)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x65, // Logical Maximum (101)
0x05, 0x07, // Usage Page (Kbrd/Keypad)
0x19, 0x00, // Usage Minimum (Reserved (no event indicated))
0x29, 0x65, // Usage Maximum (0x65)
0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
};
static uint8_t HIDInEpAdd = HID_KEYBOARD_EPIN_ADDR;
/**
* @}
*/
/** @defgroup USBD_HID_Private_Functions
* @{
*/
/**
* @brief USBD_HID_Init
* Initialize the HID interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
USBD_HID_Keyboard_HandleTypeDef *hhid;
hhid = (USBD_HID_Keyboard_HandleTypeDef *)USBD_malloc(sizeof(USBD_HID_Keyboard_HandleTypeDef));
DEBUG("sizeof(USBD_HID_Keyboard_HandleTypeDef)=0x%x\n",sizeof(USBD_HID_Keyboard_HandleTypeDef));
if (hhid == NULL)
{
pdev->pClassDataCmsit[pdev->classId] = NULL;
return (uint8_t)USBD_EMEM;
}
pdev->pClassDataCmsit[pdev->classId] = (void *)hhid;
pdev->pClassData = pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
HIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR);
#endif /* USE_USBD_COMPOSITE */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = HID_KEYBOARD_HS_BINTERVAL;
}
else /* LOW and FULL-speed endpoints */
{
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = HID_KEYBOARD_FS_BINTERVAL;
}
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, HIDInEpAdd, USBD_EP_TYPE_INTR, HID_KEYBOARD_EPIN_SIZE);
pdev->ep_in[HIDInEpAdd & 0xFU].is_used = 1U;
/* Open EP OUT */
(void)USBD_LL_OpenEP(pdev, HID_KEYBOARD_EPOUT_ADDR, USBD_EP_TYPE_INTR, HID_KEYBOARD_EPOUT_SIZE);
pdev->ep_out[HID_KEYBOARD_EPOUT_ADDR & 0xFU].is_used = 1U;
/* Prepare Out endpoint to receive 1st packet */
(void)USBD_LL_PrepareReceive(pdev, HID_KEYBOARD_EPOUT_ADDR, hhid->Report_buf,
USBD_KEYBOARD_OUTREPORT_BUF_SIZE);
hhid->state = KEYBOARD_HID_IDLE;
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_HID_DeInit
* DeInitialize the HID layer
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
HIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR);
#endif /* USE_USBD_COMPOSITE */
/* Close HID EPs */
(void)USBD_LL_CloseEP(pdev, HIDInEpAdd);
pdev->ep_in[HIDInEpAdd & 0xFU].is_used = 0U;
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = 0U;
/* Free allocated memory */
if (pdev->pClassDataCmsit[pdev->classId] != NULL)
{
(void)USBD_free(pdev->pClassDataCmsit[pdev->classId]);
pdev->pClassDataCmsit[pdev->classId] = NULL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_HID_Setup
* Handle the HID specific requests
* @param pdev: instance
* @param req: usb requests
* @retval status
*/
static uint8_t USBD_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
USBD_StatusTypeDef ret = USBD_OK;
uint16_t len;
uint8_t *pbuf;
uint16_t status_info = 0U;
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_CLASS :
switch (req->bRequest)
{
case HID_KEYBOARD_REQ_SET_PROTOCOL:
hhid->Protocol = (uint8_t)(req->wValue);
break;
case HID_KEYBOARD_REQ_GET_PROTOCOL:
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->Protocol, 1U);
break;
case HID_KEYBOARD_REQ_SET_IDLE:
hhid->IdleState = (uint8_t)(req->wValue >> 8);
break;
case HID_KEYBOARD_REQ_GET_IDLE:
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->IdleState, 1U);
break;
case HID_KEYBOARD_REQ_SET_REPORT:
USBD_HID_Keyboard_SetReport_Setup_Stage(pdev, req);
break;
case HID_KEYBOARD_REQ_GET_REPORT:
USBD_HID_Keyboard_GetReport_Token_Stage(pdev, req);
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest)
{
case USB_REQ_GET_STATUS:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_GET_DESCRIPTOR:
if ((req->wValue >> 8) == HID_KEYBOARD_REPORT_DESC)
{
len = MIN(HID_KEYBOARD_REPORT_DESC_SIZE, req->wLength);
pbuf = HID_Keyboard_ReportDesc;
}
else if ((req->wValue >> 8) == HID_KEYBOARD_DESCRIPTOR_TYPE)
{
pbuf = USBD_HID_Desc;
len = MIN(USB_HID_KEYBOARD_DESC_SIZ, req->wLength);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
(void)USBD_CtlSendData(pdev, pbuf, len);
break;
case USB_REQ_GET_INTERFACE :
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->AltSetting, 1U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_SET_INTERFACE:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
hhid->AltSetting = (uint8_t)(req->wValue);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_CLEAR_FEATURE:
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
return (uint8_t)ret;
}
/**
* @brief USBD_HID_Keyboard_SendReport
* Send HID Report
* @param pdev: device instance
* @param buff: pointer to report
* @retval status
*/
uint8_t USBD_HID_Keyboard_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len)
{
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_KEYBOARD_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if (hhid->state == KEYBOARD_HID_IDLE)
{
hhid->state = KEYBOARD_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_KEYBOARD_EPIN_ADDR, report, len);
}
}
#endif
return (uint8_t)USBD_OK;
}
extern uint8_t epnm_flag;
uint8_t USBD_HID_Keyboard_FirstSendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len)
{
#ifdef USE_USBD_COMPOSITE
static uint8_t first_send_flag = 0;
uint8_t class_id;
uint8_t ep_id = HID_KEYBOARD_EPIN_ADDR & 0xF;
if(first_send_flag == 1){
return (uint8_t)USBD_OK;
}
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_KEYBOARD_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
PCD_HandleTypeDef *pcd = (PCD_HandleTypeDef *)(pdev->pData);
uint32_t USBx_BASE = (uint32_t)(PCD_HandleTypeDef *)pcd->Instance;
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if ((hhid->state == KEYBOARD_HID_IDLE)||(epnm_flag == 0x01))
{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_ITTXFE)
{
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_ITTXFE;
hhid->state = KEYBOARD_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_KEYBOARD_EPIN_ADDR, report, len);
}
else{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_NAK){
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_NAK;
USBx_INEP(ep_id)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
}
}
if(epnm_flag == 0x01){
epnm_flag = 0x00;
}
}
}
return (uint8_t)USBD_OK;
#else
uint8_t ep_id = HID_KEYBOARD_EPIN_ADDR & 0xF;
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
PCD_HandleTypeDef *pcd = (PCD_HandleTypeDef *)(pdev->pData);
uint32_t USBx_BASE = (uint32_t)(PCD_HandleTypeDef *)pcd->Instance;
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if ((hhid->state == KEYBOARD_HID_IDLE)||(epnm_flag == 0x01))
{
if(USBx_INEP(ep_id)->DIEPINT&SB_OTG_DIEPINT_ITTXFE)
{
USBx_INEP(ep_id)->DIEPINT |= SB_OTG_DIEPINT_ITTXFE;
hhid->state = KEYBOARD_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_KEYBOARD_EPIN_ADDR, report, len);
}
else{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_NAK){
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_NAK;
USBx_INEP(ep_id)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
}
}
if(epnm_flag == 0x01){
epnm_flag = 0x00;
}
}
}
return (uint8_t)USBD_OK;
#endif
}
/**
* @brief USBD_HID_GetPollingInterval
* return polling interval from endpoint descriptor
* @param pdev: device instance
* @retval polling interval
*/
uint32_t USBD_HID_KEYBOARD_GetPollingInterval(USBD_HandleTypeDef *pdev)
{
uint32_t polling_interval;
/* HIGH-speed endpoints */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Sets the data transfer polling interval for high speed transfers.
Values between 1..16 are allowed. Values correspond to interval
of 2 ^ (bInterval-1). This option (8 ms, corresponds to HID_HS_BINTERVAL */
polling_interval = (((1U << (HID_KEYBOARD_HS_BINTERVAL - 1U))) / 8U);
}
else /* LOW and FULL-speed endpoints */
{
/* Sets the data transfer polling interval for low and full
speed transfers */
polling_interval = HID_KEYBOARD_FS_BINTERVAL;
}
return ((uint32_t)(polling_interval));
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief USBD_HID_GetCfgFSDesc
* return FS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetFSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CfgDesc, HID_KEYBOARD_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_KEYBOARD_FS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CfgDesc);
return USBD_HID_CfgDesc;
}
/**
* @brief USBD_HID_GetCfgHSDesc
* return HS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetHSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CfgDesc, HID_KEYBOARD_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_KEYBOARD_HS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CfgDesc);
return USBD_HID_CfgDesc;
}
/**
* @brief USBD_HID_GetOtherSpeedCfgDesc
* return other speed configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetOtherSpeedCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CfgDesc, HID_KEYBOARD_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_KEYBOARD_FS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CfgDesc);
return USBD_HID_CfgDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @brief USBD_HID_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
UNUSED(epnum);
/* Ensure that the FIFO is empty before a new transfer, this condition could
be caused by a new transfer before the end of the previous transfer */
((USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId])->state = KEYBOARD_HID_IDLE;
return (uint8_t)USBD_OK;
}
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
/**
* @brief USBD_CUSTOM_HID_DataOut
* handle data OUT Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
DEBUG("line=%d,epnum=0x%x\n",__LINE__,epnum);
uint8_t size_num;
USBD_HID_Keyboard_HandleTypeDef *hhid;
hhid = pdev->pClassData;
/* Ensure that the FIFO is empty before a new transfer, this condition could
be caused by a new transfer before the end of the previous transfer */
size_num = HAL_PCD_EP_GetRxCount(&hpcd_USB_OTG_FS,HID_KEYBOARD_EPOUT_ADDR);
(void)USBD_LL_PrepareReceive(pdev, HID_KEYBOARD_EPOUT_ADDR, hhid->Report_buf,HID_KEYBOARD_EPOUT_SIZE);
for(int i=0;i<size_num;i++)
{
DEBUG("0x%x ", hhid->Report_buf[i]);
}
DEBUG("\n");
hhid->state = KEYBOARD_HID_IDLE;
return (uint8_t)USBD_OK;
}
static uint8_t USBD_HID_EP0_RxReady(USBD_HandleTypeDef *pdev)
{
DEBUG("Keyboard USBD_HID_EP0_RxReady\r\n");
USBD_HID_Keyboard_SetReport_Token_Stage(pdev);
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Keyboard_SetReport_Setup_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data)
{
uint8_t report_type;
uint8_t report_id;
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_KEYBOARD_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
report_type = (setup_data->wValue >> 8) & 0xFF;
report_id = setup_data->wValue & 0xFF;
hhid->EP0_ReportLen = setup_data->wLength;
DEBUG("Setup_Stage report_type=%02x, report_id=%02x, report_len=%d\r\n",report_type, report_id, hhid->EP0_ReportLen);
(void)USBD_CtlPrepareRx(pdev, hhid->EP0_ReportBuff, hhid->EP0_ReportLen);
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Keyboard_SetReport_Token_Stage(USBD_HandleTypeDef *pdev)
{
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_KEYBOARD_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
DEBUG("Token_Stage recv len = %d\n", hhid->EP0_ReportLen);
for(int i=0;i<hhid->EP0_ReportLen;i++){
DEBUG("0x%x ", hhid->EP0_ReportBuff[i]);
}DEBUG("\n");
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Keyboard_GetReport_Token_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data)
{
uint16_t report_length;
uint8_t data[HID_KEYBOARD_EP0_GET_REPORT_BUF_SIZE];
DEBUG("%s,%d\n",__func__,__LINE__);
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_KEYBOARD_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
for(int i=0;i<HID_KEYBOARD_EP0_GET_REPORT_BUF_SIZE;i++)
{
data[i] = i;
}
report_length = setup_data->wLength;
USBD_CtlSendData(pdev, data, report_length);
return (uint8_t)USBD_OK;
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetDeviceQualifierDesc(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_HID_DeviceQualifierDesc);
return USBD_HID_DeviceQualifierDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,841 @@
/*!
* \file usbd_hid_mouse.c
*
* \brief This file provides the HID core functions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*
* @verbatim
*
* ===================================================================
* HID Class Description
* ===================================================================
* This module manages the HID class V1.11 following the "Device Class Definition
* for Human Interface Devices (HID) Version 1.11 Jun 27, 2001".
* This driver implements the following aspects of the specification:
* - The Boot Interface Subclass
* - The Mouse protocol
* - Usage Page : Generic Desktop
* - Usage : Mouse
* - Collection : Application
*
* @note In HS mode and when the DMA is used, all variables and data structures
* dealing with the DMA during the transaction process should be 32-bit aligned.
*
*
* @endverbatim
*
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_hid_mouse.h"
#include "usbd_ctlreq.h"
#ifdef USE_USBD_COMPOSITE
#include "usbd_composite_builder.h"
#endif
/** @defgroup USBD_HID
* @brief usbd core module
* @{
*/
/** @defgroup USBD_HID_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_FunctionPrototypes
* @{
*/
static uint8_t USBD_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_HID_EP0_RxReady(USBD_HandleTypeDef *pdev);
static uint8_t USBD_HID_Mouse_SetReport_Setup_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data);
static uint8_t USBD_HID_Mouse_SetReport_Token_Stage(USBD_HandleTypeDef *pdev);
static uint8_t USBD_HID_Mouse_GetReport_Token_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data);
#ifndef USE_USBD_COMPOSITE
static uint8_t *USBD_HID_GetFSCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetHSCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetOtherSpeedCfgDesc(uint16_t *length);
static uint8_t *USBD_HID_GetDeviceQualifierDesc(uint16_t *length);
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/** @defgroup USBD_HID_Private_Variables
* @{
*/
USBD_ClassTypeDef USBD_HID_MOUSE =
{
USBD_HID_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL, /* EP0_TxSent */
USBD_HID_EP0_RxReady, /* EP0_RxReady */
USBD_HID_DataIn, /* DataIn */
NULL, /* DataOut */
NULL, /* SOF */
NULL,
NULL,
#ifdef USE_USBD_COMPOSITE
NULL,
NULL,
NULL,
NULL,
#else
USBD_HID_GetHSCfgDesc,
USBD_HID_GetFSCfgDesc,
USBD_HID_GetOtherSpeedCfgDesc,
USBD_HID_GetDeviceQualifierDesc,
#endif /* USE_USBD_COMPOSITE */
};
#ifndef USE_USBD_COMPOSITE
/* USB HID device FS Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_MOUSE_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_HID_MOUSE_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */
0x00,
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor
describing the configuration */
#if (USBD_SELF_POWERED == 1U)
0xE0, /* bmAttributes: Bus Powered according to user configuration */
#else
0xA0, /* bmAttributes: Bus Powered according to user configuration */
#endif /* USBD_SELF_POWERED */
USBD_MAX_POWER, /* MaxPower (mA) */
/************** Descriptor of Joystick Mouse interface ****************/
/* 09 */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_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_MOUSE_DESCRIPTOR_TYPE, /* 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_DESC_TYPE_ENDPOINT, /* bDescriptorType:*/
HID_MOUSE_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
HID_MOUSE_EPIN_SIZE, /* wMaxPacketSize: 4 Bytes max */
0x00,
HID_MOUSE_FS_BINTERVAL, /* bInterval: Polling Interval */
/* 34 */
};
#endif /* USE_USBD_COMPOSITE */
/* USB HID device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_Desc[USB_HID_MOUSE_DESC_SIZ] __ALIGN_END =
{
/* 18 */
0x09, /* bLength: HID Descriptor size */
HID_MOUSE_DESCRIPTOR_TYPE, /* 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,
};
#ifndef USE_USBD_COMPOSITE
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
};
#endif /* USE_USBD_COMPOSITE */
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */
0x09, 0x02, /* Usage (Mouse) */
0xA1, 0x01, /* Collection (Application) */
0x09, 0x01, /* Usage (Pointer) */
0xA1, 0x00, /* Collection (Physical) */
0x05, 0x09, /* Usage Page (Button) */
0x19, 0x01, /* Usage Minimum (0x01) */
0x29, 0x03, /* Usage Maximum (0x03) */
0x15, 0x00, /* Logical Minimum (0) */
0x25, 0x01, /* Logical Maximum (1) */
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 (Const,Array,Abs) */
0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */
0x09, 0x30, /* Usage (X) */
0x09, 0x31, /* Usage (Y) */
0x09, 0x38, /* Usage (Wheel) */
0x15, 0x81, /* Logical Minimum (-127) */
0x25, 0x7F, /* Logical Maximum (127) */
0x75, 0x08, /* Report Size (8) */
0x95, 0x03, /* Report Count (3) */
0x81, 0x06, /* Input (Data,Var,Rel) */
0xC0, /* End Collection */
0x09, 0x3C, /* Usage (Motion Wakeup) */
0x05, 0xFF, /* Usage Page (Reserved 0xFF) */
0x09, 0x01, /* Usage (0x01) */
0x15, 0x00, /* Logical Minimum (0) */
0x25, 0x01, /* Logical Maximum (1) */
0x75, 0x01, /* Report Size (1) */
0x95, 0x02, /* Report Count (2) */
0xB1, 0x22, /* Feature (Data,Var,Abs,NoWrp) */
0x75, 0x06, /* Report Size (6) */
0x95, 0x01, /* Report Count (1) */
0xB1, 0x01, /* Feature (Const,Array,Abs,NoWrp) */
0xC0 /* End Collection */
};
static uint8_t HIDInEpAdd = HID_MOUSE_EPIN_ADDR;
/**
* @}
*/
/** @defgroup USBD_HID_Private_Functions
* @{
*/
/**
* @brief USBD_HID_Init
* Initialize the HID interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
USBD_HID_Mouse_HandleTypeDef *hhid;
hhid = (USBD_HID_Mouse_HandleTypeDef *)USBD_malloc(sizeof(USBD_HID_Mouse_HandleTypeDef));
printf("sizeof(USBD_HID_Mouse_HandleTypeDef)=0x%x\n",sizeof(USBD_HID_Mouse_HandleTypeDef));
if (hhid == NULL)
{
pdev->pClassDataCmsit[pdev->classId] = NULL;
return (uint8_t)USBD_EMEM;
}
pdev->pClassDataCmsit[pdev->classId] = (void *)hhid;
pdev->pClassData = pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
HIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR);
#endif /* USE_USBD_COMPOSITE */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = HID_MOUSE_HS_BINTERVAL;
}
else /* LOW and FULL-speed endpoints */
{
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = HID_MOUSE_FS_BINTERVAL;
}
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, HIDInEpAdd, USBD_EP_TYPE_INTR, HID_MOUSE_EPIN_SIZE);
pdev->ep_in[HIDInEpAdd & 0xFU].is_used = 1U;
hhid->state = MOUSE_HID_IDLE;
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_HID_DeInit
* DeInitialize the HID layer
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
HIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR);
#endif /* USE_USBD_COMPOSITE */
/* Close HID EPs */
(void)USBD_LL_CloseEP(pdev, HIDInEpAdd);
pdev->ep_in[HIDInEpAdd & 0xFU].is_used = 0U;
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = 0U;
/* Free allocated memory */
if (pdev->pClassDataCmsit[pdev->classId] != NULL)
{
(void)USBD_free(pdev->pClassDataCmsit[pdev->classId]);
pdev->pClassDataCmsit[pdev->classId] = NULL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_HID_Setup
* Handle the HID specific requests
* @param pdev: instance
* @param req: usb requests
* @retval status
*/
static uint8_t USBD_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
USBD_StatusTypeDef ret = USBD_OK;
uint16_t len;
uint8_t *pbuf;
uint16_t status_info = 0U;
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_CLASS :
switch (req->bRequest)
{
case HID_MOUSE_REQ_SET_PROTOCOL:
hhid->Protocol = (uint8_t)(req->wValue);
break;
case HID_MOUSE_REQ_GET_PROTOCOL:
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->Protocol, 1U);
break;
case HID_MOUSE_REQ_SET_IDLE:
hhid->IdleState = (uint8_t)(req->wValue >> 8);
break;
case HID_MOUSE_REQ_GET_IDLE:
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->IdleState, 1U);
break;
case HID_MOUSE_REQ_SET_REPORT:
USBD_HID_Mouse_SetReport_Setup_Stage(pdev, req);
break;
case HID_MOUSE_REQ_GET_REPORT:
USBD_HID_Mouse_GetReport_Token_Stage(pdev, req);
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest)
{
case USB_REQ_GET_STATUS:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_GET_DESCRIPTOR:
if ((req->wValue >> 8) == HID_MOUSE_REPORT_DESC)
{
len = MIN(HID_MOUSE_REPORT_DESC_SIZE, req->wLength);
pbuf = HID_MOUSE_ReportDesc;
}
else if ((req->wValue >> 8) == HID_MOUSE_DESCRIPTOR_TYPE)
{
pbuf = USBD_HID_Desc;
len = MIN(USB_HID_MOUSE_DESC_SIZ, req->wLength);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
(void)USBD_CtlSendData(pdev, pbuf, len);
break;
case USB_REQ_GET_INTERFACE :
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->AltSetting, 1U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_SET_INTERFACE:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
hhid->AltSetting = (uint8_t)(req->wValue);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_CLEAR_FEATURE:
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
return (uint8_t)ret;
}
/**
* @brief USBD_HID_Mouse_SendReport
* Send HID Report
* @param pdev: device instance
* @param buff: pointer to report
* @retval status
*/
uint8_t USBD_HID_Mouse_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len)
{
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_MOUSE_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if (hhid->state == MOUSE_HID_IDLE)
{
hhid->state = MOUSE_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_MOUSE_EPIN_ADDR, report, len);
}
}
return (uint8_t)USBD_OK;
#else
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if (hhid->state == MOUSE_HID_IDLE)
{
hhid->state = MOUSE_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_MOUSE_EPIN_ADDR, report, len);
}
}
return (uint8_t)USBD_OK;
#endif
}
extern uint8_t epnm_flag;
uint8_t USBD_HID_Mouse_FirstSendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len)
{
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
uint8_t ep_id = HID_MOUSE_EPIN_ADDR & 0xF;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_MOUSE_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
PCD_HandleTypeDef *pcd = (PCD_HandleTypeDef *)(pdev->pData);
uint32_t USBx_BASE = (uint32_t)(PCD_HandleTypeDef *)pcd->Instance;
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if ((hhid->state == MOUSE_HID_IDLE)||(epnm_flag == 0x01))
{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_ITTXFE)
{
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_ITTXFE;
hhid->state = MOUSE_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_MOUSE_EPIN_ADDR, report, len);
}
else{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_NAK){
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_NAK;
USBx_INEP(ep_id)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
}
}
if(epnm_flag == 0x01){
epnm_flag = 0x00;
}
}
}
return (uint8_t)USBD_OK;
#else
uint8_t ep_id = HID_MOUSE_EPIN_ADDR & 0xF;
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
PCD_HandleTypeDef *pcd = (PCD_HandleTypeDef *)(pdev->pData);
uint32_t USBx_BASE = (uint32_t)(PCD_HandleTypeDef *)pcd->Instance;
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if ((hhid->state == MOUSE_HID_IDLE)||(epnm_flag == 0x01))
{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_ITTXFE)
{
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_ITTXFE;
hhid->state = MOUSE_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HID_MOUSE_EPIN_ADDR, report, len);
}
else{
if(USBx_INEP(ep_id)->DIEPINT&USB_OTG_DIEPINT_NAK){
USBx_INEP(ep_id)->DIEPINT |= USB_OTG_DIEPINT_NAK;
USBx_INEP(ep_id)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
}
}
if(epnm_flag == 0x01){
epnm_flag = 0x00;
}
}
}
return (uint8_t)USBD_OK;
#endif
}
/**
* @brief USBD_HID_GetPollingInterval
* return polling interval from endpoint descriptor
* @param pdev: device instance
* @retval polling interval
*/
uint32_t USBD_HID_GetPollingInterval(USBD_HandleTypeDef *pdev)
{
uint32_t polling_interval;
/* HIGH-speed endpoints */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Sets the data transfer polling interval for high speed transfers.
Values between 1..16 are allowed. Values correspond to interval
of 2 ^ (bInterval-1). This option (8 ms, corresponds to HID_MOUSE_HS_BINTERVAL */
polling_interval = (((1U << (HID_MOUSE_HS_BINTERVAL - 1U))) / 8U);
}
else /* LOW and FULL-speed endpoints */
{
/* Sets the data transfer polling interval for low and full
speed transfers */
polling_interval = HID_MOUSE_FS_BINTERVAL;
}
return ((uint32_t)(polling_interval));
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief USBD_HID_GetCfgFSDesc
* return FS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetFSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CfgDesc, HID_MOUSE_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_MOUSE_FS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CfgDesc);
return USBD_HID_CfgDesc;
}
/**
* @brief USBD_HID_GetCfgHSDesc
* return HS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetHSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CfgDesc, HID_MOUSE_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_MOUSE_HS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CfgDesc);
return USBD_HID_CfgDesc;
}
/**
* @brief USBD_HID_GetOtherSpeedCfgDesc
* return other speed configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetOtherSpeedCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpDesc = USBD_GetEpDesc(USBD_HID_CfgDesc, HID_MOUSE_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_MOUSE_FS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_HID_CfgDesc);
return USBD_HID_CfgDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @brief USBD_HID_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
UNUSED(epnum);
/* Ensure that the FIFO is empty before a new transfer, this condition could
be caused by a new transfer before the end of the previous transfer */
((USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId])->state = MOUSE_HID_IDLE;
#ifdef APP_USB_MOUSE_FAST_SEND_DATA
extern void app_usb_mouse_fast_send_data(USBD_HandleTypeDef *pdev);
app_usb_mouse_fast_send_data(pdev);
#endif
return (uint8_t)USBD_OK;
}
static uint8_t USBD_HID_EP0_RxReady(USBD_HandleTypeDef *pdev)
{
DEBUG("Mouse USBD_HID_EP0_RxReady\r\n");
USBD_HID_Mouse_SetReport_Token_Stage(pdev);
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Mouse_SetReport_Setup_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data)
{
uint8_t report_type;
uint8_t report_id;
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_MOUSE_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
report_type = (setup_data->wValue >> 8) & 0xFF;
report_id = setup_data->wValue & 0xFF;
hhid->EP0_ReportLen = setup_data->wLength;
DEBUG("Setup_Stage report_type=%02x, report_id=%02x, report_len=%d\r\n",report_type, report_id, hhid->EP0_ReportLen);
(void)USBD_CtlPrepareRx(pdev, hhid->EP0_ReportBuff, hhid->EP0_ReportLen);
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Mouse_SetReport_Token_Stage(USBD_HandleTypeDef *pdev)
{
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_MOUSE_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
DEBUG("Token_Stage recv len = %d\n", hhid->EP0_ReportLen);
for(int i=0;i<hhid->EP0_ReportLen;i++){
DEBUG("0x%x ", hhid->EP0_ReportBuff[i]);
}DEBUG("\n");
return (uint8_t)USBD_OK;
}
uint8_t USBD_HID_Mouse_GetReport_Token_Stage(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *setup_data)
{
uint16_t report_length;
uint8_t data[HID_MOUSE_EP0_GET_REPORT_BUF_SIZE];
DEBUG("%s,%d\n",__func__,__LINE__);
#ifdef USE_USBD_COMPOSITE
uint8_t class_id;
class_id = USBD_CMPSIT_GetClassID_ByAdd(pdev, HID_MOUSE_EPIN_ADDR, USBD_EP_TYPE_INTR);
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[class_id];
#else
USBD_HID_Mouse_HandleTypeDef *hhid = (USBD_HID_Mouse_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
for(int i=0;i<HID_MOUSE_EP0_GET_REPORT_BUF_SIZE;i++)
{
data[i] = i;
}
report_length = setup_data->wLength;
USBD_CtlSendData(pdev, data, report_length);
return (uint8_t)USBD_OK;
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetDeviceQualifierDesc(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_HID_DeviceQualifierDesc);
return USBD_HID_DeviceQualifierDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,136 @@
/*!
* \file usbd_msc.h
*
* \brief Header for the usbd_msc.c file
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_MSC_H
#define __USBD_MSC_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_msc_bot.h"
#include "usbd_msc_scsi.h"
#include "usbd_ioreq.h"
/** @addtogroup USBD_MSC_BOT
* @{
*/
/** @defgroup USBD_MSC
* @brief This file is the Header file for usbd_msc.c
* @{
*/
/** @defgroup USBD_BOT_Exported_Defines
* @{
*/
/* MSC Class Config */
#ifndef MSC_MEDIA_PACKET
#define MSC_MEDIA_PACKET 512U
#endif /* MSC_MEDIA_PACKET */
#define MSC_MAX_FS_PACKET 0x40U
#define MSC_MAX_HS_PACKET 0x200U
#define BOT_GET_MAX_LUN 0xFE
#define BOT_RESET 0xFF
#define USB_MSC_CONFIG_DESC_SIZ 32
#ifndef MSC_EPIN_ADDR
#define MSC_EPIN_ADDR 0x81U
#endif /* MSC_EPIN_ADDR */
#ifndef MSC_EPOUT_ADDR
#define MSC_EPOUT_ADDR 0x01U
#endif /* MSC_EPOUT_ADDR */
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Types
* @{
*/
typedef struct _USBD_STORAGE
{
int8_t (* Init)(uint8_t lun);
int8_t (* GetCapacity)(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
int8_t (* IsReady)(uint8_t lun);
int8_t (* IsWriteProtected)(uint8_t lun);
int8_t (* Read)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
int8_t (* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
int8_t (* GetMaxLun)(void);
int8_t *pInquiry;
} USBD_StorageTypeDef;
typedef struct
{
uint32_t max_lun;
uint32_t interface;
uint8_t bot_state;
uint8_t bot_status;
uint32_t bot_data_length;
uint8_t bot_data[MSC_MEDIA_PACKET];
USBD_MSC_BOT_CBWTypeDef cbw;
USBD_MSC_BOT_CSWTypeDef csw;
USBD_SCSI_SenseTypeDef scsi_sense [SENSE_LIST_DEEPTH];
uint8_t scsi_sense_head;
uint8_t scsi_sense_tail;
uint8_t scsi_medium_state;
uint16_t scsi_blk_size;
uint32_t scsi_blk_nbr;
uint32_t scsi_blk_addr;
uint32_t scsi_blk_len;
} USBD_MSC_BOT_HandleTypeDef;
/* Structure for MSC process */
extern USBD_ClassTypeDef USBD_MSC;
#define USBD_MSC_CLASS &USBD_MSC
uint8_t USBD_MSC_RegisterStorage(USBD_HandleTypeDef *pdev,
USBD_StorageTypeDef *fops);
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_MSC_H */
/**
* @}
*/
@@ -0,0 +1,150 @@
/*!
* \file usbd_msc_bot.h
*
* \brief Header for the usbd_msc_bot.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_MSC_BOT_H
#define __USBD_MSC_BOT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_core.h"
/** @defgroup MSC_BOT
* @brief This file is the Header file for usbd_msc_bot.c
* @{
*/
/** @defgroup USBD_CORE_Exported_Defines
* @{
*/
#define USBD_BOT_IDLE 0U /* Idle state */
#define USBD_BOT_DATA_OUT 1U /* Data Out state */
#define USBD_BOT_DATA_IN 2U /* Data In state */
#define USBD_BOT_LAST_DATA_IN 3U /* Last Data In Last */
#define USBD_BOT_SEND_DATA 4U /* Send Immediate data */
#define USBD_BOT_NO_DATA 5U /* No data Stage */
#define USBD_BOT_CBW_SIGNATURE 0x43425355U
#define USBD_BOT_CSW_SIGNATURE 0x53425355U
#define USBD_BOT_CBW_LENGTH 31U
#define USBD_BOT_CSW_LENGTH 13U
#define USBD_BOT_MAX_DATA 256U
/* CSW Status Definitions */
#define USBD_CSW_CMD_PASSED 0x00U
#define USBD_CSW_CMD_FAILED 0x01U
#define USBD_CSW_PHASE_ERROR 0x02U
/* BOT Status */
#define USBD_BOT_STATUS_NORMAL 0U
#define USBD_BOT_STATUS_RECOVERY 1U
#define USBD_BOT_STATUS_ERROR 2U
#define USBD_DIR_IN 0U
#define USBD_DIR_OUT 1U
#define USBD_BOTH_DIR 2U
/**
* @}
*/
/** @defgroup MSC_CORE_Private_TypesDefinitions
* @{
*/
typedef struct
{
uint32_t dSignature;
uint32_t dTag;
uint32_t dDataLength;
uint8_t bmFlags;
uint8_t bLUN;
uint8_t bCBLength;
uint8_t CB[16];
uint8_t ReservedForAlign;
} USBD_MSC_BOT_CBWTypeDef;
typedef struct
{
uint32_t dSignature;
uint32_t dTag;
uint32_t dDataResidue;
uint8_t bStatus;
uint8_t ReservedForAlign[3];
} USBD_MSC_BOT_CSWTypeDef;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_FunctionsPrototypes
* @{
*/
void MSC_BOT_Init(USBD_HandleTypeDef *pdev);
void MSC_BOT_Reset(USBD_HandleTypeDef *pdev);
void MSC_BOT_DeInit(USBD_HandleTypeDef *pdev);
void MSC_BOT_DataIn(USBD_HandleTypeDef *pdev,
uint8_t epnum);
void MSC_BOT_DataOut(USBD_HandleTypeDef *pdev,
uint8_t epnum);
void MSC_BOT_SendCSW(USBD_HandleTypeDef *pdev,
uint8_t CSW_Status);
void MSC_BOT_CplClrFeature(USBD_HandleTypeDef *pdev,
uint8_t epnum);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_MSC_BOT_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,106 @@
/*!
* \file usbd_msc_data.h
*
* \brief Header for the usbd_msc_data.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_MSC_DATA_H
#define __USBD_MSC_DATA_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_conf.h"
/** @defgroup USB_INFO
* @brief general defines for the usb device library file
* @{
*/
/** @defgroup USB_INFO_Exported_Defines
* @{
*/
#define MODE_SENSE6_LEN 0x17U
#define MODE_SENSE10_LEN 0x1BU
#define LENGTH_INQUIRY_PAGE00 0x06U
#define LENGTH_INQUIRY_PAGE80 0x08U
#define LENGTH_FORMAT_CAPACITIES 0x14U
/**
* @}
*/
/** @defgroup USBD_INFO_Exported_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_INFO_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_INFO_Exported_Variables
* @{
*/
extern uint8_t MSC_Page00_Inquiry_Data[LENGTH_INQUIRY_PAGE00];
extern uint8_t MSC_Page80_Inquiry_Data[LENGTH_INQUIRY_PAGE80];
extern uint8_t MSC_Mode_Sense6_data[MODE_SENSE6_LEN];
extern uint8_t MSC_Mode_Sense10_data[MODE_SENSE10_LEN];
/**
* @}
*/
/** @defgroup USBD_INFO_Exported_FunctionsPrototype
* @{
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_MSC_DATA_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,186 @@
/*!
* \file usbd_msc_scsi.h
*
* \brief Header for the usbd_msc_scsi.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_MSC_SCSI_H
#define __USBD_MSC_SCSI_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_def.h"
/** @defgroup USBD_SCSI
* @brief header file for the storage disk file
* @{
*/
/** @defgroup USBD_SCSI_Exported_Defines
* @{
*/
#define SENSE_LIST_DEEPTH 4U
/* SCSI Commands */
#define SCSI_FORMAT_UNIT 0x04U
#define SCSI_INQUIRY 0x12U
#define SCSI_MODE_SELECT6 0x15U
#define SCSI_MODE_SELECT10 0x55U
#define SCSI_MODE_SENSE6 0x1AU
#define SCSI_MODE_SENSE10 0x5AU
#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1EU
#define SCSI_READ6 0x08U
#define SCSI_READ10 0x28U
#define SCSI_READ12 0xA8U
#define SCSI_READ16 0x88U
#define SCSI_READ_CAPACITY10 0x25U
#define SCSI_READ_CAPACITY16 0x9EU
#define SCSI_REQUEST_SENSE 0x03U
#define SCSI_START_STOP_UNIT 0x1BU
#define SCSI_TEST_UNIT_READY 0x00U
#define SCSI_WRITE6 0x0AU
#define SCSI_WRITE10 0x2AU
#define SCSI_WRITE12 0xAAU
#define SCSI_WRITE16 0x8AU
#define SCSI_VERIFY10 0x2FU
#define SCSI_VERIFY12 0xAFU
#define SCSI_VERIFY16 0x8FU
#define SCSI_SEND_DIAGNOSTIC 0x1DU
#define SCSI_READ_FORMAT_CAPACITIES 0x23U
#define NO_SENSE 0U
#define RECOVERED_ERROR 1U
#define NOT_READY 2U
#define MEDIUM_ERROR 3U
#define HARDWARE_ERROR 4U
#define ILLEGAL_REQUEST 5U
#define UNIT_ATTENTION 6U
#define DATA_PROTECT 7U
#define BLANK_CHECK 8U
#define VENDOR_SPECIFIC 9U
#define COPY_ABORTED 10U
#define ABORTED_COMMAND 11U
#define VOLUME_OVERFLOW 13U
#define MISCOMPARE 14U
#define INVALID_CDB 0x20U
#define INVALID_FIELED_IN_COMMAND 0x24U
#define PARAMETER_LIST_LENGTH_ERROR 0x1AU
#define INVALID_FIELD_IN_PARAMETER_LIST 0x26U
#define ADDRESS_OUT_OF_RANGE 0x21U
#define MEDIUM_NOT_PRESENT 0x3AU
#define MEDIUM_HAVE_CHANGED 0x28U
#define WRITE_PROTECTED 0x27U
#define UNRECOVERED_READ_ERROR 0x11U
#define WRITE_FAULT 0x03U
#define READ_FORMAT_CAPACITY_DATA_LEN 0x0CU
#define READ_CAPACITY10_DATA_LEN 0x08U
#define REQUEST_SENSE_DATA_LEN 0x12U
#define STANDARD_INQUIRY_DATA_LEN 0x24U
#define BLKVFY 0x04U
#define SCSI_MEDIUM_UNLOCKED 0x00U
#define SCSI_MEDIUM_LOCKED 0x01U
#define SCSI_MEDIUM_EJECTED 0x02U
/**
* @}
*/
/** @defgroup USBD_SCSI_Exported_TypesDefinitions
* @{
*/
typedef struct _SENSE_ITEM
{
uint8_t Skey;
union
{
struct _ASCs
{
uint8_t ASC;
uint8_t ASCQ;
} b;
uint8_t ASC;
uint8_t *pData;
} w;
} USBD_SCSI_SenseTypeDef;
/**
* @}
*/
/** @defgroup USBD_SCSI_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_SCSI_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBD_SCSI_Exported_FunctionsPrototype
* @{
*/
int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *cmd);
void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey,
uint8_t ASC);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_MSC_SCSI_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,579 @@
/*!
* \file usbd_msc.c
*
* \brief This file provides all the MSC core functions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
* @verbatim
*
* ===================================================================
* MSC Class Description
* ===================================================================
* This module manages the MSC class V1.0 following the "Universal
* Serial Bus Mass Storage Class (MSC) Bulk-Only Transport (BOT) Version 1.0
* Sep. 31, 1999".
* This driver implements the following aspects of the specification:
* - Bulk-Only Transport protocol
* - Subclass : SCSI transparent command set (ref. SCSI Primary Commands - 3 (SPC-3))
*
* @endverbatim
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_msc.h"
/** @defgroup MSC_CORE
* @brief Mass storage core module
* @{
*/
/** @defgroup MSC_CORE_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup MSC_CORE_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup MSC_CORE_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup MSC_CORE_Private_FunctionPrototypes
* @{
*/
uint8_t USBD_MSC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
uint8_t USBD_MSC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
uint8_t USBD_MSC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
uint8_t USBD_MSC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
uint8_t USBD_MSC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
#ifndef USE_USBD_COMPOSITE
uint8_t *USBD_MSC_GetHSCfgDesc(uint16_t *length);
uint8_t *USBD_MSC_GetFSCfgDesc(uint16_t *length);
uint8_t *USBD_MSC_GetOtherSpeedCfgDesc(uint16_t *length);
uint8_t *USBD_MSC_GetDeviceQualifierDescriptor(uint16_t *length);
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/** @defgroup MSC_CORE_Private_Variables
* @{
*/
USBD_ClassTypeDef USBD_MSC =
{
USBD_MSC_Init,
USBD_MSC_DeInit,
USBD_MSC_Setup,
NULL, /*EP0_TxSent*/
NULL, /*EP0_RxReady*/
USBD_MSC_DataIn,
USBD_MSC_DataOut,
NULL, /*SOF */
NULL,
NULL,
#ifdef USE_USBD_COMPOSITE
NULL,
NULL,
NULL,
NULL,
#else
USBD_MSC_GetHSCfgDesc,
USBD_MSC_GetFSCfgDesc,
USBD_MSC_GetOtherSpeedCfgDesc,
USBD_MSC_GetDeviceQualifierDescriptor,
#endif /* USE_USBD_COMPOSITE */
};
/* USB Mass storage device Configuration Descriptor */
#ifndef USE_USBD_COMPOSITE
/* USB Mass storage device Configuration Descriptor */
/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
__ALIGN_BEGIN static uint8_t USBD_MSC_CfgDesc[USB_MSC_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_MSC_CONFIG_DESC_SIZ,
0x00,
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue */
0x04, /* iConfiguration */
#if (USBD_SELF_POWERED == 1U)
0xC0, /* bmAttributes: Bus Powered according to user configuration */
#else
0x80, /* bmAttributes: Bus Powered according to user configuration */
#endif /* USBD_SELF_POWERED */
USBD_MAX_POWER, /* MaxPower (mA) */
/******************** Mass Storage interface ********************/
0x09, /* bLength: Interface Descriptor size */
0x04, /* bDescriptorType: */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints */
0x08, /* bInterfaceClass: MSC Class */
0x06, /* bInterfaceSubClass : SCSI transparent*/
0x50, /* nInterfaceProtocol */
0x05, /* iInterface: */
/******************** Mass Storage Endpoints ********************/
0x07, /* Endpoint descriptor length = 7 */
0x05, /* Endpoint descriptor type */
MSC_EPIN_ADDR, /* Endpoint address (IN, address 1) */
0x02, /* Bulk endpoint type */
LOBYTE(MSC_MAX_FS_PACKET),
HIBYTE(MSC_MAX_FS_PACKET),
0x00, /* Polling interval in milliseconds */
0x07, /* Endpoint descriptor length = 7 */
0x05, /* Endpoint descriptor type */
MSC_EPOUT_ADDR, /* Endpoint address (OUT, address 1) */
0x02, /* Bulk endpoint type */
LOBYTE(MSC_MAX_FS_PACKET),
HIBYTE(MSC_MAX_FS_PACKET),
0x00 /* Polling interval in milliseconds */
};
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_MSC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
MSC_MAX_FS_PACKET,
0x01,
0x00,
};
#endif /* USE_USBD_COMPOSITE */
uint8_t MSCInEpAdd = MSC_EPIN_ADDR;
uint8_t MSCOutEpAdd = MSC_EPOUT_ADDR;
/**
* @}
*/
/** @defgroup MSC_CORE_Private_Functions
* @{
*/
/**
* @brief USBD_MSC_Init
* Initialize the mass storage configuration
* @param pdev: device instance
* @param cfgidx: configuration index
* @retval status
*/
uint8_t USBD_MSC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
USBD_MSC_BOT_HandleTypeDef *hmsc;
hmsc = (USBD_MSC_BOT_HandleTypeDef *)USBD_malloc(sizeof(USBD_MSC_BOT_HandleTypeDef));
DEBUG("sizeof(USBD_MSC_BOT_HandleTypeDef)=0x%x\n",sizeof(USBD_MSC_BOT_HandleTypeDef));
if (hmsc == NULL)
{
pdev->pClassDataCmsit[pdev->classId] = NULL;
return (uint8_t)USBD_EMEM;
}
pdev->pClassDataCmsit[pdev->classId] = (void *)hmsc;
pdev->pClassData = pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
MSCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK);
MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK);
#endif /* USE_USBD_COMPOSITE */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Open EP OUT */
(void)USBD_LL_OpenEP(pdev, MSCOutEpAdd, USBD_EP_TYPE_BULK, MSC_MAX_HS_PACKET);
pdev->ep_out[MSCOutEpAdd & 0xFU].is_used = 1U;
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, MSCInEpAdd, USBD_EP_TYPE_BULK, MSC_MAX_HS_PACKET);
pdev->ep_in[MSCInEpAdd & 0xFU].is_used = 1U;
}
else
{
/* Open EP OUT */
(void)USBD_LL_OpenEP(pdev, MSCOutEpAdd, USBD_EP_TYPE_BULK, MSC_MAX_FS_PACKET);
pdev->ep_out[MSCOutEpAdd & 0xFU].is_used = 1U;
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, MSCInEpAdd, USBD_EP_TYPE_BULK, MSC_MAX_FS_PACKET);
pdev->ep_in[MSCInEpAdd & 0xFU].is_used = 1U;
}
/* Init the BOT layer */
MSC_BOT_Init(pdev);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_MSC_DeInit
* DeInitialize the mass storage configuration
* @param pdev: device instance
* @param cfgidx: configuration index
* @retval status
*/
uint8_t USBD_MSC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
MSCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK);
MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK);
#endif /* USE_USBD_COMPOSITE */
/* Close MSC EPs */
(void)USBD_LL_CloseEP(pdev, MSCOutEpAdd);
pdev->ep_out[MSCOutEpAdd & 0xFU].is_used = 0U;
/* Close EP IN */
(void)USBD_LL_CloseEP(pdev, MSCInEpAdd);
pdev->ep_in[MSCInEpAdd & 0xFU].is_used = 0U;
/* Free MSC Class Resources */
if (pdev->pClassDataCmsit[pdev->classId] != NULL)
{
/* De-Init the BOT layer */
MSC_BOT_DeInit(pdev);
(void)USBD_free(pdev->pClassDataCmsit[pdev->classId]);
pdev->pClassDataCmsit[pdev->classId] = NULL;
pdev->pClassData = NULL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_MSC_Setup
* Handle the MSC specific requests
* @param pdev: device instance
* @param req: USB request
* @retval status
*/
uint8_t USBD_MSC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
USBD_StatusTypeDef ret = USBD_OK;
uint16_t status_info = 0U;
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
MSCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK);
MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK);
#endif /* USE_USBD_COMPOSITE */
if (hmsc == NULL)
{
return (uint8_t)USBD_FAIL;
}
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
/* Class request */
case USB_REQ_TYPE_CLASS:
switch (req->bRequest)
{
case BOT_GET_MAX_LUN:
if ((req->wValue == 0U) && (req->wLength == 1U) &&
((req->bmRequest & 0x80U) == 0x80U))
{
hmsc->max_lun = (uint32_t)((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->GetMaxLun();
(void)USBD_CtlSendData(pdev, (uint8_t *)&hmsc->max_lun, 1U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case BOT_RESET :
if ((req->wValue == 0U) && (req->wLength == 0U) &&
((req->bmRequest & 0x80U) != 0x80U))
{
MSC_BOT_Reset(pdev);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
/* Interface & Endpoint request */
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest)
{
case USB_REQ_GET_STATUS:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_GET_INTERFACE:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, (uint8_t *)&hmsc->interface, 1U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_SET_INTERFACE:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
hmsc->interface = (uint8_t)(req->wValue);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_CLEAR_FEATURE:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if (req->wValue == USB_FEATURE_EP_HALT)
{
/* Flush the FIFO */
(void)USBD_LL_FlushEP(pdev, (uint8_t)req->wIndex);
/* Handle BOT error */
MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex);
}
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
return (uint8_t)ret;
}
/**
* @brief USBD_MSC_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
uint8_t USBD_MSC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
MSC_BOT_DataIn(pdev, epnum);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_MSC_DataOut
* handle data OUT Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
uint8_t USBD_MSC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
MSC_BOT_DataOut(pdev, epnum);
return (uint8_t)USBD_OK;
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief USBD_MSC_GetHSCfgDesc
* return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_MSC_GetHSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPIN_ADDR);
USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPOUT_ADDR);
if (pEpInDesc != NULL)
{
pEpInDesc->wMaxPacketSize = MSC_MAX_HS_PACKET;
}
if (pEpOutDesc != NULL)
{
pEpOutDesc->wMaxPacketSize = MSC_MAX_HS_PACKET;
}
*length = (uint16_t)sizeof(USBD_MSC_CfgDesc);
return USBD_MSC_CfgDesc;
}
/**
* @brief USBD_MSC_GetFSCfgDesc
* return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_MSC_GetFSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPIN_ADDR);
USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPOUT_ADDR);
if (pEpInDesc != NULL)
{
pEpInDesc->wMaxPacketSize = MSC_MAX_FS_PACKET;
}
if (pEpOutDesc != NULL)
{
pEpOutDesc->wMaxPacketSize = MSC_MAX_FS_PACKET;
}
*length = (uint16_t)sizeof(USBD_MSC_CfgDesc);
return USBD_MSC_CfgDesc;
}
/**
* @brief USBD_MSC_GetOtherSpeedCfgDesc
* return other speed configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_MSC_GetOtherSpeedCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPIN_ADDR);
USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPOUT_ADDR);
if (pEpInDesc != NULL)
{
pEpInDesc->wMaxPacketSize = MSC_MAX_FS_PACKET;
}
if (pEpOutDesc != NULL)
{
pEpOutDesc->wMaxPacketSize = MSC_MAX_FS_PACKET;
}
*length = (uint16_t)sizeof(USBD_MSC_CfgDesc);
return USBD_MSC_CfgDesc;
}
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_MSC_GetDeviceQualifierDescriptor(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_MSC_DeviceQualifierDesc);
return USBD_MSC_DeviceQualifierDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @brief USBD_MSC_RegisterStorage
* @param fops: storage callback
* @retval status
*/
uint8_t USBD_MSC_RegisterStorage(USBD_HandleTypeDef *pdev, USBD_StorageTypeDef *fops)
{
if (fops == NULL)
{
return (uint8_t)USBD_FAIL;
}
pdev->pUserData[pdev->classId] = fops;
return (uint8_t)USBD_OK;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,478 @@
/*!
* \file usbd_msc_bot.c
*
* \brief This file provides all the BOT protocol core functions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_msc_bot.h"
#include "usbd_msc.h"
#include "usbd_msc_scsi.h"
#include "usbd_ioreq.h"
/** @defgroup MSC_BOT
* @brief BOT protocol module
* @{
*/
/** @defgroup MSC_BOT_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup MSC_BOT_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup MSC_BOT_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup MSC_BOT_Private_Variables
* @{
*/
extern uint8_t MSCInEpAdd;
extern uint8_t MSCOutEpAdd;
/**
* @}
*/
/** @defgroup MSC_BOT_Private_FunctionPrototypes
* @{
*/
static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint32_t len);
static void MSC_BOT_CBW_Decode(USBD_HandleTypeDef *pdev);
static void MSC_BOT_Abort(USBD_HandleTypeDef *pdev);
/**
* @}
*/
/** @defgroup MSC_BOT_Private_Functions
* @{
*/
/**
* @brief MSC_BOT_Init
* Initialize the BOT Process
* @param pdev: device instance
* @retval None
*/
void MSC_BOT_Init(USBD_HandleTypeDef *pdev)
{
USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
MSCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK);
MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK);
#endif /* USE_USBD_COMPOSITE */
if (hmsc == NULL)
{
return;
}
hmsc->bot_state = USBD_BOT_IDLE;
hmsc->bot_status = USBD_BOT_STATUS_NORMAL;
hmsc->scsi_sense_tail = 0U;
hmsc->scsi_sense_head = 0U;
hmsc->scsi_medium_state = SCSI_MEDIUM_UNLOCKED;
((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->Init(0U);
(void)USBD_LL_FlushEP(pdev, MSCOutEpAdd);
(void)USBD_LL_FlushEP(pdev, MSCInEpAdd);
/* Prepare EP to Receive First BOT Cmd */
(void)USBD_LL_PrepareReceive(pdev, MSCOutEpAdd, (uint8_t *)&hmsc->cbw,
USBD_BOT_CBW_LENGTH);
}
/**
* @brief MSC_BOT_Reset
* Reset the BOT Machine
* @param pdev: device instance
* @retval None
*/
void MSC_BOT_Reset(USBD_HandleTypeDef *pdev)
{
USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
MSCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK);
MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK);
#endif /* USE_USBD_COMPOSITE */
if (hmsc == NULL)
{
return;
}
hmsc->bot_state = USBD_BOT_IDLE;
hmsc->bot_status = USBD_BOT_STATUS_RECOVERY;
(void)USBD_LL_ClearStallEP(pdev, MSCInEpAdd);
(void)USBD_LL_ClearStallEP(pdev, MSCOutEpAdd);
/* Prepare EP to Receive First BOT Cmd */
(void)USBD_LL_PrepareReceive(pdev, MSCOutEpAdd, (uint8_t *)&hmsc->cbw,
USBD_BOT_CBW_LENGTH);
}
/**
* @brief MSC_BOT_DeInit
* DeInitialize the BOT Machine
* @param pdev: device instance
* @retval None
*/
void MSC_BOT_DeInit(USBD_HandleTypeDef *pdev)
{
USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hmsc != NULL)
{
hmsc->bot_state = USBD_BOT_IDLE;
}
}
/**
* @brief MSC_BOT_DataIn
* Handle BOT IN data stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval None
*/
void MSC_BOT_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
UNUSED(epnum);
USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hmsc == NULL)
{
return;
}
switch (hmsc->bot_state)
{
case USBD_BOT_DATA_IN:
if (SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0)
{
MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_FAILED);
}
break;
case USBD_BOT_SEND_DATA:
case USBD_BOT_LAST_DATA_IN:
MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_PASSED);
break;
default:
break;
}
}
/**
* @brief MSC_BOT_DataOut
* Process MSC OUT data
* @param pdev: device instance
* @param epnum: endpoint index
* @retval None
*/
void MSC_BOT_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
UNUSED(epnum);
USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hmsc == NULL)
{
return;
}
switch (hmsc->bot_state)
{
case USBD_BOT_IDLE:
MSC_BOT_CBW_Decode(pdev);
break;
case USBD_BOT_DATA_OUT:
if (SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0)
{
MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_FAILED);
}
break;
default:
break;
}
}
/**
* @brief MSC_BOT_CBW_Decode
* Decode the CBW command and set the BOT state machine accordingly
* @param pdev: device instance
* @retval None
*/
static void MSC_BOT_CBW_Decode(USBD_HandleTypeDef *pdev)
{
USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
MSCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK);
MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK);
#endif /* USE_USBD_COMPOSITE */
if (hmsc == NULL)
{
return;
}
hmsc->csw.dTag = hmsc->cbw.dTag;
hmsc->csw.dDataResidue = hmsc->cbw.dDataLength;
if ((USBD_LL_GetRxDataSize(pdev, MSCOutEpAdd) != USBD_BOT_CBW_LENGTH) ||
(hmsc->cbw.dSignature != USBD_BOT_CBW_SIGNATURE) ||
(hmsc->cbw.bLUN > 1U) || (hmsc->cbw.bCBLength < 1U) ||
(hmsc->cbw.bCBLength > 16U))
{
SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);
hmsc->bot_status = USBD_BOT_STATUS_ERROR;
MSC_BOT_Abort(pdev);
}
else
{
if (SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0)
{
if (hmsc->bot_state == USBD_BOT_NO_DATA)
{
MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_FAILED);
}
else
{
MSC_BOT_Abort(pdev);
}
}
/* Burst xfer handled internally */
else if ((hmsc->bot_state != USBD_BOT_DATA_IN) &&
(hmsc->bot_state != USBD_BOT_DATA_OUT) &&
(hmsc->bot_state != USBD_BOT_LAST_DATA_IN))
{
if (hmsc->bot_data_length > 0U)
{
MSC_BOT_SendData(pdev, hmsc->bot_data, hmsc->bot_data_length);
}
else if (hmsc->bot_data_length == 0U)
{
MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_PASSED);
}
else
{
MSC_BOT_Abort(pdev);
}
}
else
{
return;
}
}
}
/**
* @brief MSC_BOT_SendData
* Send the requested data
* @param pdev: device instance
* @param buf: pointer to data buffer
* @param len: Data Length
* @retval None
*/
static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint32_t len)
{
USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
uint32_t length;
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
MSCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK);
MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK);
#endif /* USE_USBD_COMPOSITE */
if (hmsc == NULL)
{
return;
}
length = MIN(hmsc->cbw.dDataLength, len);
hmsc->csw.dDataResidue -= len;
hmsc->csw.bStatus = USBD_CSW_CMD_PASSED;
hmsc->bot_state = USBD_BOT_SEND_DATA;
(void)USBD_LL_Transmit(pdev, MSCInEpAdd, pbuf, length);
}
/**
* @brief MSC_BOT_SendCSW
* Send the Command Status Wrapper
* @param pdev: device instance
* @param status : CSW status
* @retval None
*/
void MSC_BOT_SendCSW(USBD_HandleTypeDef *pdev, uint8_t CSW_Status)
{
USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
MSCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK);
MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK);
#endif /* USE_USBD_COMPOSITE */
if (hmsc == NULL)
{
return;
}
hmsc->csw.dSignature = USBD_BOT_CSW_SIGNATURE;
hmsc->csw.bStatus = CSW_Status;
hmsc->bot_state = USBD_BOT_IDLE;
(void)USBD_LL_Transmit(pdev, MSCInEpAdd, (uint8_t *)&hmsc->csw,
USBD_BOT_CSW_LENGTH);
/* Prepare EP to Receive next Cmd */
(void)USBD_LL_PrepareReceive(pdev, MSCOutEpAdd, (uint8_t *)&hmsc->cbw,
USBD_BOT_CBW_LENGTH);
}
/**
* @brief MSC_BOT_Abort
* Abort the current transfer
* @param pdev: device instance
* @retval status
*/
static void MSC_BOT_Abort(USBD_HandleTypeDef *pdev)
{
USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
MSCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK);
MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK);
#endif /* USE_USBD_COMPOSITE */
if (hmsc == NULL)
{
return;
}
if ((hmsc->cbw.bmFlags == 0U) &&
(hmsc->cbw.dDataLength != 0U) &&
(hmsc->bot_status == USBD_BOT_STATUS_NORMAL))
{
(void)USBD_LL_StallEP(pdev, MSCOutEpAdd);
}
(void)USBD_LL_StallEP(pdev, MSCInEpAdd);
if (hmsc->bot_status == USBD_BOT_STATUS_ERROR)
{
(void)USBD_LL_StallEP(pdev, MSCInEpAdd);
(void)USBD_LL_StallEP(pdev, MSCOutEpAdd);
}
}
/**
* @brief MSC_BOT_CplClrFeature
* Complete the clear feature request
* @param pdev: device instance
* @param epnum: endpoint index
* @retval None
*/
void MSC_BOT_CplClrFeature(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
MSCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK);
MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK);
#endif /* USE_USBD_COMPOSITE */
if (hmsc == NULL)
{
return;
}
if (hmsc->bot_status == USBD_BOT_STATUS_ERROR) /* Bad CBW Signature */
{
(void)USBD_LL_StallEP(pdev, MSCInEpAdd);
(void)USBD_LL_StallEP(pdev, MSCOutEpAdd);
}
else if (((epnum & 0x80U) == 0x80U) && (hmsc->bot_status != USBD_BOT_STATUS_RECOVERY))
{
MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_FAILED);
}
else
{
return;
}
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,161 @@
/*!
* \file usbd_msc_data.c
*
* \brief This file provides all the vital inquiry pages and sense data.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_msc_data.h"
/** @defgroup MSC_DATA_Private_Defines
* @{
*/
/** @defgroup MSC_DATA_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup MSC_DATA_Private_Variables
* @{
*/
/* USB Mass storage Page 0 Inquiry Data */
uint8_t MSC_Page00_Inquiry_Data[LENGTH_INQUIRY_PAGE00] =
{
0x00,
0x00,
0x00,
(LENGTH_INQUIRY_PAGE00 - 4U),
0x00,
0x80
};
/* USB Mass storage VPD Page 0x80 Inquiry Data for Unit Serial Number */
uint8_t MSC_Page80_Inquiry_Data[LENGTH_INQUIRY_PAGE80] =
{
0x00,
0x80,
0x00,
LENGTH_INQUIRY_PAGE80,
0x20, /* Put Product Serial number */
0x20,
0x20,
0x20
};
/* USB Mass storage sense 6 Data */
uint8_t MSC_Mode_Sense6_data[MODE_SENSE6_LEN] =
{
0x22,
0x00,
0x00,
0x00,
0x08,
0x12,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00
};
/* USB Mass storage sense 10 Data */
uint8_t MSC_Mode_Sense10_data[MODE_SENSE10_LEN] =
{
0x00,
0x26,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x08,
0x12,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00
};
/**
* @}
*/
/** @defgroup MSC_DATA_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup MSC_DATA_Private_Functions
* @{
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,176 @@
/*!
* \file usbd_core.h
*
* \brief Header file for usbd_core.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CORE_H
#define __USBD_CORE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_conf.h"
#include "usbd_def.h"
#include "usbd_ioreq.h"
#include "usbd_ctlreq.h"
/** @defgroup USBD_CORE
* @brief This file is the Header file for usbd_core.c file
* @{
*/
/** @defgroup USBD_CORE_Exported_Defines
* @{
*/
#ifndef USBD_DEBUG_LEVEL
#define USBD_DEBUG_LEVEL 0U
#endif /* USBD_DEBUG_LEVEL */
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
#define USBD_SOF USBD_LL_SOF
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_FunctionsPrototype
* @{
*/
USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id);
USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_Start(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_Stop(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass);
#ifdef USE_USBD_COMPOSITE
USBD_StatusTypeDef USBD_RegisterClassComposite(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass,
USBD_CompositeClassTypeDef classtype, uint8_t *EpAddr);
USBD_StatusTypeDef USBD_UnRegisterClassComposite(USBD_HandleTypeDef *pdev);
uint8_t USBD_CoreGetEPAdd(USBD_HandleTypeDef *pdev, uint8_t ep_dir, uint8_t ep_type);
#endif /* USE_USBD_COMPOSITE */
uint8_t USBD_CoreFindIF(USBD_HandleTypeDef *pdev, uint8_t index);
uint8_t USBD_CoreFindEP(USBD_HandleTypeDef *pdev, uint8_t index);
USBD_StatusTypeDef USBD_RunTestMode(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup);
USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t *pdata);
USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t *pdata);
USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed);
USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev);
/* USBD Low Level Driver */
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr,
uint8_t ep_type, uint16_t ep_mps);
USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr);
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr,
uint8_t *pbuf, uint32_t size);
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr,
uint8_t *pbuf, uint32_t size);
#ifdef USBD_HS_TESTMODE_ENABLE
USBD_StatusTypeDef USBD_LL_SetTestMode(USBD_HandleTypeDef *pdev, uint8_t testmode);
#endif /* USBD_HS_TESTMODE_ENABLE */
uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
void USBD_LL_Delay(uint32_t Delay);
void *USBD_GetEpDesc(uint8_t *pConfDesc, uint8_t EpAddr);
USBD_DescHeaderTypeDef *USBD_GetNextDesc(uint8_t *pbuf, uint16_t *ptr);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CORE_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,114 @@
/*!
* \file usbd_ctlreq.h
*
* \brief Header file for the usbd_req.c file
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_REQUEST_H
#define __USB_REQUEST_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_def.h"
/** @defgroup USBD_REQ
* @brief header file for the usbd_req.c file
* @{
*/
/** @defgroup USBD_REQ_Exported_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_REQ_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USBD_REQ_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_REQ_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBD_REQ_Exported_FunctionsPrototype
* @{
*/
#ifdef OS_FEATURE
enum
{
OS_WIN = 0,//windows os
OS_MAC = 1,//mac os
};
#endif
USBD_StatusTypeDef USBD_StdDevReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
USBD_StatusTypeDef USBD_StdItfReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
USBD_StatusTypeDef USBD_StdEPReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
void USBD_CtlError(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata);
void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_REQUEST_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,522 @@
/*!
* \file usbd_def.h
*
* \brief General defines for the usb device library
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_DEF_H
#define __USBD_DEF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_conf.h"
#include "xc_hal_pcd_np.h"
/** @defgroup USB_DEF
* @brief general defines for the usb device library file
* @{
*/
/** @defgroup USB_DEF_Exported_Defines
* @{
*/
#ifndef NULL
#define NULL 0U
#endif /* NULL */
#ifndef USBD_MAX_NUM_INTERFACES
#define USBD_MAX_NUM_INTERFACES 1U
#endif /* USBD_MAX_NUM_CONFIGURATION */
#ifndef USBD_MAX_NUM_CONFIGURATION
#define USBD_MAX_NUM_CONFIGURATION 1U
#endif /* USBD_MAX_NUM_CONFIGURATION */
#ifdef USE_USBD_COMPOSITE
#ifndef USBD_MAX_SUPPORTED_CLASS
#define USBD_MAX_SUPPORTED_CLASS 5U
#endif /* USBD_MAX_SUPPORTED_CLASS */
#else
#ifndef USBD_MAX_SUPPORTED_CLASS
#define USBD_MAX_SUPPORTED_CLASS 1U
#endif /* USBD_MAX_SUPPORTED_CLASS */
#endif /* USE_USBD_COMPOSITE */
#ifndef USBD_MAX_CLASS_ENDPOINTS
#define USBD_MAX_CLASS_ENDPOINTS 5U
#endif /* USBD_MAX_CLASS_ENDPOINTS */
#ifndef USBD_MAX_CLASS_INTERFACES
#define USBD_MAX_CLASS_INTERFACES 5U
#endif /* USBD_MAX_CLASS_INTERFACES */
#ifndef USBD_LPM_ENABLED
#define USBD_LPM_ENABLED 0U
#endif /* USBD_LPM_ENABLED */
#ifndef USBD_SELF_POWERED
#define USBD_SELF_POWERED 1U
#endif /*USBD_SELF_POWERED */
#ifndef USBD_MAX_POWER
#define USBD_MAX_POWER 0x32U /* 100 mA */
#endif /* USBD_MAX_POWER */
#ifndef USBD_SUPPORT_USER_STRING_DESC
#define USBD_SUPPORT_USER_STRING_DESC 0U
#endif /* USBD_SUPPORT_USER_STRING_DESC */
#ifndef USBD_CLASS_USER_STRING_DESC
#define USBD_CLASS_USER_STRING_DESC 0U
#endif /* USBD_CLASS_USER_STRING_DESC */
#define USB_LEN_DEV_QUALIFIER_DESC 0x0AU
#define USB_LEN_DEV_DESC 0x12U
#define USB_LEN_CFG_DESC 0x09U
#define USB_LEN_IF_DESC 0x09U
#define USB_LEN_EP_DESC 0x07U
#define USB_LEN_OTG_DESC 0x03U
#define USB_LEN_LANGID_STR_DESC 0x04U
#define USB_LEN_OTHER_SPEED_DESC_SIZ 0x09U
#define USBD_IDX_LANGID_STR 0x00U
#define USBD_IDX_MFC_STR 0x01U
#define USBD_IDX_PRODUCT_STR 0x02U
#define USBD_IDX_SERIAL_STR 0x03U
#define USBD_IDX_CONFIG_STR 0x04U
#define USBD_IDX_INTERFACE_STR 0x05U
#define USB_REQ_TYPE_STANDARD 0x00U
#define USB_REQ_TYPE_CLASS 0x20U
#define USB_REQ_TYPE_VENDOR 0x40U
#define USB_REQ_TYPE_MASK 0x60U
#define USB_REQ_RECIPIENT_DEVICE 0x00U
#define USB_REQ_RECIPIENT_INTERFACE 0x01U
#define USB_REQ_RECIPIENT_ENDPOINT 0x02U
#define USB_REQ_RECIPIENT_MASK 0x03U
#define USB_REQ_GET_STATUS 0x00U
#define USB_REQ_CLEAR_FEATURE 0x01U
#define USB_REQ_SET_FEATURE 0x03U
#define USB_REQ_SET_ADDRESS 0x05U
#define USB_REQ_GET_DESCRIPTOR 0x06U
#define USB_REQ_SET_DESCRIPTOR 0x07U
#define USB_REQ_GET_CONFIGURATION 0x08U
#define USB_REQ_SET_CONFIGURATION 0x09U
#define USB_REQ_GET_INTERFACE 0x0AU
#define USB_REQ_SET_INTERFACE 0x0BU
#define USB_REQ_SYNCH_FRAME 0x0CU
#define USB_DESC_TYPE_DEVICE 0x01U
#define USB_DESC_TYPE_CONFIGURATION 0x02U
#define USB_DESC_TYPE_STRING 0x03U
#define USB_DESC_TYPE_INTERFACE 0x04U
#define USB_DESC_TYPE_ENDPOINT 0x05U
#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06U
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07U
#define USB_DESC_TYPE_IAD 0x0BU
#define USB_DESC_TYPE_BOS 0x0FU
#define USB_CONFIG_REMOTE_WAKEUP 0x02U
#define USB_CONFIG_SELF_POWERED 0x01U
#define USB_FEATURE_EP_HALT 0x00U
#define USB_FEATURE_REMOTE_WAKEUP 0x01U
#define USB_FEATURE_TEST_MODE 0x02U
#define USB_DEVICE_CAPABITY_TYPE 0x10U
#define USB_CONF_DESC_SIZE 0x09U
#define USB_IF_DESC_SIZE 0x09U
#define USB_EP_DESC_SIZE 0x07U
#define USB_IAD_DESC_SIZE 0x08U
#define USB_HS_MAX_PACKET_SIZE 512U
#define USB_FS_MAX_PACKET_SIZE 64U
#define USB_MAX_EP0_SIZE 64U
/* Device Status */
#define USBD_STATE_DEFAULT 0x01U
#define USBD_STATE_ADDRESSED 0x02U
#define USBD_STATE_CONFIGURED 0x03U
#define USBD_STATE_SUSPENDED 0x04U
/* EP0 State */
#define USBD_EP0_IDLE 0x00U
#define USBD_EP0_SETUP 0x01U
#define USBD_EP0_DATA_IN 0x02U
#define USBD_EP0_DATA_OUT 0x03U
#define USBD_EP0_STATUS_IN 0x04U
#define USBD_EP0_STATUS_OUT 0x05U
#define USBD_EP0_STALL 0x06U
#define USBD_EP_TYPE_CTRL 0x00U
#define USBD_EP_TYPE_ISOC 0x01U
#define USBD_EP_TYPE_BULK 0x02U
#define USBD_EP_TYPE_INTR 0x03U
#ifdef USE_USBD_COMPOSITE
#define USBD_EP_IN 0x80U
#define USBD_EP_OUT 0x00U
#define USBD_FUNC_DESCRIPTOR_TYPE 0x24U
#define USBD_DESC_SUBTYPE_ACM 0x0FU
#define USBD_DESC_ECM_BCD_LOW 0x00U
#define USBD_DESC_ECM_BCD_HIGH 0x10U
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/** @defgroup USBD_DEF_Exported_TypesDefinitions
* @{
*/
typedef struct usb_setup_req
{
uint8_t bmRequest;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} USBD_SetupReqTypedef;
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
} __PACKED USBD_ConfigDescTypeDef;
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumDeviceCaps;
} USBD_BosDescTypeDef;
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
} __PACKED USBD_EpDescTypeDef;
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
} USBD_DescHeaderTypeDef;
struct _USBD_HandleTypeDef;
typedef struct _Device_cb
{
uint8_t (*Init)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx);
uint8_t (*DeInit)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx);
/* Control Endpoints*/
uint8_t (*Setup)(struct _USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
uint8_t (*EP0_TxSent)(struct _USBD_HandleTypeDef *pdev);
uint8_t (*EP0_RxReady)(struct _USBD_HandleTypeDef *pdev);
/* Class Specific Endpoints*/
uint8_t (*DataIn)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
uint8_t (*DataOut)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
uint8_t (*SOF)(struct _USBD_HandleTypeDef *pdev);
uint8_t (*IsoINIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
uint8_t (*IsoOUTIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
uint8_t *(*GetHSConfigDescriptor)(uint16_t *length);
uint8_t *(*GetFSConfigDescriptor)(uint16_t *length);
uint8_t *(*GetOtherSpeedConfigDescriptor)(uint16_t *length);
uint8_t *(*GetDeviceQualifierDescriptor)(uint16_t *length);
#if (USBD_SUPPORT_USER_STRING_DESC == 1U)
uint8_t *(*GetUsrStrDescriptor)(struct _USBD_HandleTypeDef *pdev, uint8_t index, uint16_t *length);
#endif /* USBD_SUPPORT_USER_STRING_DESC */
} USBD_ClassTypeDef;
/* Following USB Device Speed */
typedef enum
{
USBD_SPEED_HIGH = 0U,
USBD_SPEED_FULL = 1U,
USBD_SPEED_LOW = 2U,
} USBD_SpeedTypeDef;
/* Following USB Device status */
typedef enum
{
USBD_OK = 0U,
USBD_BUSY,
USBD_EMEM,
USBD_FAIL,
} USBD_StatusTypeDef;
/* USB Device descriptors structure */
typedef struct
{
uint8_t *(*GetDeviceDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetLangIDStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetManufacturerStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetProductStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetSerialStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetConfigurationStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetInterfaceStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
#if (USBD_CLASS_USER_STRING_DESC == 1)
uint8_t *(*GetUserStrDescriptor)(USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length);
#endif /* USBD_CLASS_USER_STRING_DESC */
#if ((USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1))
uint8_t *(*GetBOSDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
#endif /* (USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1) */
} USBD_DescriptorsTypeDef;
/* USB Device handle structure */
typedef struct
{
uint32_t status;
uint32_t total_length;
uint32_t rem_length;
uint32_t maxpacket;
uint16_t is_used;
uint16_t bInterval;
} USBD_EndpointTypeDef;
#ifdef USE_USBD_COMPOSITE
typedef enum
{
CLASS_TYPE_NONE = 0,
CLASS_TYPE_HID_MOUSE = 1,
CLASS_TYPE_CDC = 2,
CLASS_TYPE_MSC = 3,
CLASS_TYPE_DFU = 4,
CLASS_TYPE_CHID = 5,
CLASS_TYPE_AUDIO = 6,
CLASS_TYPE_ECM = 7,
CLASS_TYPE_RNDIS = 8,
CLASS_TYPE_MTP = 9,
CLASS_TYPE_VIDEO = 10,
CLASS_TYPE_PRINTER = 11,
CLASS_TYPE_CCID = 12,
CLASS_TYPE_MICROPHONE = 13,
CLASS_TYPE_HEADPHONE = 14,
CLASS_TYPE_HID_KEYBOARD = 15,
CLASS_TYPE_HID_CUSTOM = 16,
} USBD_CompositeClassTypeDef;
/* USB Device handle structure */
typedef struct
{
uint8_t add;
uint8_t type;
uint8_t size;
uint8_t is_used;
} USBD_EPTypeDef;
/* USB Device handle structure */
typedef struct
{
USBD_CompositeClassTypeDef ClassType;
uint32_t ClassId;
uint32_t Active;
uint32_t NumEps;
USBD_EPTypeDef Eps[USBD_MAX_CLASS_ENDPOINTS];
uint8_t *EpAdd;
uint32_t NumIf;
uint8_t Ifs[USBD_MAX_CLASS_INTERFACES];
uint32_t CurrPcktSze;
} USBD_CompositeElementTypeDef;
#endif /* USE_USBD_COMPOSITE */
/* USB Device handle structure */
typedef struct _USBD_HandleTypeDef
{
uint8_t id;
uint32_t dev_config;
uint32_t dev_default_config;
uint32_t dev_config_status;
USBD_SpeedTypeDef dev_speed;
USBD_EndpointTypeDef ep_in[16];
USBD_EndpointTypeDef ep_out[16];
__IO uint32_t ep0_state;
uint32_t ep0_data_len;
__IO uint8_t dev_state;
__IO uint8_t dev_old_state;
uint8_t dev_address;
uint8_t dev_connection_status;
uint8_t dev_test_mode;
uint32_t dev_remote_wakeup;
uint8_t ConfIdx;
USBD_SetupReqTypedef request;
USBD_DescriptorsTypeDef *pDesc;
USBD_ClassTypeDef *pClass[USBD_MAX_SUPPORTED_CLASS];
void *pClassData;
void *pClassDataCmsit[USBD_MAX_SUPPORTED_CLASS];
void *pUserData[USBD_MAX_SUPPORTED_CLASS];
void *pData;
void *pBosDesc;
void *pConfDesc;
uint32_t classId;
uint32_t NumClasses;
#ifdef USE_USBD_COMPOSITE
USBD_CompositeElementTypeDef tclasslist[USBD_MAX_SUPPORTED_CLASS];
#endif /* USE_USBD_COMPOSITE */
} USBD_HandleTypeDef;
/* USB Device endpoint direction */
typedef enum
{
OUT = 0x00,
IN = 0x80,
} USBD_EPDirectionTypeDef;
typedef enum
{
NETWORK_CONNECTION = 0x00,
RESPONSE_AVAILABLE = 0x01,
CONNECTION_SPEED_CHANGE = 0x2A
} USBD_CDC_NotifCodeTypeDef;
/**
* @}
*/
/** @defgroup USBD_DEF_Exported_Macros
* @{
*/
__STATIC_INLINE uint16_t SWAPBYTE(uint8_t *addr)
{
uint16_t _SwapVal, _Byte1, _Byte2;
uint8_t *_pbuff = addr;
_Byte1 = *(uint8_t *)_pbuff;
_pbuff++;
_Byte2 = *(uint8_t *)_pbuff;
_SwapVal = (_Byte2 << 8) | _Byte1;
return _SwapVal;
}
#ifndef LOBYTE
#define LOBYTE(x) ((uint8_t)((x) & 0x00FFU))
#endif /* LOBYTE */
#ifndef HIBYTE
#define HIBYTE(x) ((uint8_t)(((x) & 0xFF00U) >> 8U))
#endif /* HIBYTE */
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif /* MIN */
#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif /* MAX */
#if defined ( __GNUC__ )
#ifndef __weak
#define __weak __attribute__((weak))
#endif /* __weak */
#ifndef __packed
#define __packed __attribute__((__packed__))
#endif /* __packed */
#endif /* __GNUC__ */
/* In HS mode and when the DMA is used, all variables and data structures dealing
with the DMA during the transaction process should be 4-bytes aligned */
#if defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */
#ifndef __ALIGN_END
#define __ALIGN_END __attribute__ ((aligned (4U)))
#endif /* __ALIGN_END */
#ifndef __ALIGN_BEGIN
#define __ALIGN_BEGIN
#endif /* __ALIGN_BEGIN */
#else
#ifndef __ALIGN_END
#define __ALIGN_END
#endif /* __ALIGN_END */
#ifndef __ALIGN_BEGIN
#if defined (__CC_ARM) /* ARM Compiler */
#define __ALIGN_BEGIN __align(4U)
#elif defined (__ICCARM__) /* IAR Compiler */
#define __ALIGN_BEGIN
#endif /* __CC_ARM */
#endif /* __ALIGN_BEGIN */
#endif /* __GNUC__ */
/**
* @}
*/
/** @defgroup USBD_DEF_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBD_DEF_Exported_FunctionsPrototype
* @{
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_DEF_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,117 @@
/*!
* \file usbd_ioreq.h
*
* \brief Header file for the usbd_ioreq.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_IOREQ_H
#define __USBD_IOREQ_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_def.h"
#include "usbd_core.h"
/** @defgroup USBD_IOREQ
* @brief header file for the usbd_ioreq.c file
* @{
*/
/** @defgroup USBD_IOREQ_Exported_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Exported_FunctionsPrototype
* @{
*/
USBD_StatusTypeDef USBD_CtlSendData(USBD_HandleTypeDef *pdev,
uint8_t *pbuf, uint32_t len);
USBD_StatusTypeDef USBD_CtlContinueSendData(USBD_HandleTypeDef *pdev,
uint8_t *pbuf, uint32_t len);
USBD_StatusTypeDef USBD_CtlPrepareRx(USBD_HandleTypeDef *pdev,
uint8_t *pbuf, uint32_t len);
USBD_StatusTypeDef USBD_CtlContinueRx(USBD_HandleTypeDef *pdev,
uint8_t *pbuf, uint32_t len);
USBD_StatusTypeDef USBD_CtlSendStatus(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_CtlReceiveStatus(USBD_HandleTypeDef *pdev);
uint32_t USBD_GetRxCount(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_IOREQ_H */
/**
* @}
*/
/**
* @}
*/
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,228 @@
/*!
* \file usbd_ioreq.c
*
* \brief This file provides the IO requests APIs for control endpoints.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @defgroup USBD_IOREQ
* @brief control I/O requests module
* @{
*/
/** @defgroup USBD_IOREQ_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Private_Functions
* @{
*/
/**
* @brief USBD_CtlSendData
* send data on the ctl pipe
* @param pdev: device instance
* @param buff: pointer to data buffer
* @param len: length of data to be sent
* @retval status
*/
USBD_StatusTypeDef USBD_CtlSendData(USBD_HandleTypeDef *pdev,
uint8_t *pbuf, uint32_t len)
{
/* Set EP0 State */
pdev->ep0_state = USBD_EP0_DATA_IN;
pdev->ep_in[0].total_length = len;
#ifdef USBD_AVOID_PACKET_SPLIT_MPS
pdev->ep_in[0].rem_length = 0U;
#else
pdev->ep_in[0].rem_length = len;
#endif /* USBD_AVOID_PACKET_SPLIT_MPS */
/* Start the transfer */
(void)USBD_LL_Transmit(pdev, 0x00U, pbuf, len);
return USBD_OK;
}
/**
* @brief USBD_CtlContinueSendData
* continue sending data on the ctl pipe
* @param pdev: device instance
* @param buff: pointer to data buffer
* @param len: length of data to be sent
* @retval status
*/
USBD_StatusTypeDef USBD_CtlContinueSendData(USBD_HandleTypeDef *pdev,
uint8_t *pbuf, uint32_t len)
{
/* Start the next transfer */
(void)USBD_LL_Transmit(pdev, 0x00U, pbuf, len);
return USBD_OK;
}
/**
* @brief USBD_CtlPrepareRx
* receive data on the ctl pipe
* @param pdev: device instance
* @param buff: pointer to data buffer
* @param len: length of data to be received
* @retval status
*/
USBD_StatusTypeDef USBD_CtlPrepareRx(USBD_HandleTypeDef *pdev,
uint8_t *pbuf, uint32_t len)
{
/* Set EP0 State */
pdev->ep0_state = USBD_EP0_DATA_OUT;
pdev->ep_out[0].total_length = len;
#ifdef USBD_AVOID_PACKET_SPLIT_MPS
pdev->ep_out[0].rem_length = 0U;
#else
pdev->ep_out[0].rem_length = len;
#endif /* USBD_AVOID_PACKET_SPLIT_MPS */
/* Start the transfer */
(void)USBD_LL_PrepareReceive(pdev, 0U, pbuf, len);
return USBD_OK;
}
/**
* @brief USBD_CtlContinueRx
* continue receive data on the ctl pipe
* @param pdev: device instance
* @param buff: pointer to data buffer
* @param len: length of data to be received
* @retval status
*/
USBD_StatusTypeDef USBD_CtlContinueRx(USBD_HandleTypeDef *pdev,
uint8_t *pbuf, uint32_t len)
{
(void)USBD_LL_PrepareReceive(pdev, 0U, pbuf, len);
return USBD_OK;
}
/**
* @brief USBD_CtlSendStatus
* send zero lzngth packet on the ctl pipe
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_CtlSendStatus(USBD_HandleTypeDef *pdev)
{
/* Set EP0 State */
pdev->ep0_state = USBD_EP0_STATUS_IN;
/* Start the transfer */
(void)USBD_LL_Transmit(pdev, 0x00U, NULL, 0U);
return USBD_OK;
}
/**
* @brief USBD_CtlReceiveStatus
* receive zero lzngth packet on the ctl pipe
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_CtlReceiveStatus(USBD_HandleTypeDef *pdev)
{
/* Set EP0 State */
pdev->ep0_state = USBD_EP0_STATUS_OUT;
/* Start the transfer */
(void)USBD_LL_PrepareReceive(pdev, 0U, NULL, 0U);
return USBD_OK;
}
/**
* @brief USBD_GetRxCount
* returns the received data length
* @param pdev: device instance
* @param ep_addr: endpoint address
* @retval Rx Data blength
*/
uint32_t USBD_GetRxCount(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
return USBD_LL_GetRxDataSize(pdev, ep_addr);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,57 @@
/*!
* \file rtc.h
*
* \brief Target rtc implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __RTC_H__
#define __RTC_H__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdint.h>
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
extern volatile uint32_t Utc_TotalSec;
// Test val
extern uint8_t Sec_Flag;
/*------------------------------------------------------------------------------------
Exported Functions
------------------------------------------- -----------------------------------------*/
void rtc_sec_handler(void);
void RTC_Config( void );
#ifdef __cplusplus
}
#endif
#endif /* __RTC_H__ */
@@ -0,0 +1,86 @@
/*!
* \file time_conv.h
*
* \brief Target time convert implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __TIME_CONV_H__
#define __TIME_CONV_H__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdint.h>
#include <time.h>
#include "rtc.h"
/*------------------------------------------------------------------------------------
Macros
------------------------------------------- -----------------------------------------*/
#define YEAR_BASE 2000U
#define TIME_ZONE (8)
#define M_JAN 1U
#define M_FEB 2U
#define M_MAR 3U
#define M_APR 4U
#define M_MAY 5U
#define M_JUN 6U
#define M_JUL 7U
#define M_AUG 8U
#define M_SEP 9U
#define M_OCT 10U
#define M_NOV 11U
#define M_DEC 12U
/*------------------------------------------------------------------------------------
Typedef
-------------------------------------------------------------------------------------*/
typedef struct tm Utc_Date_t;
typedef struct
{
uint8_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t min;
uint8_t sec;
uint8_t week;
} DateTime_t;
/*------------------------------------------------------------------------------------
Exported Functions
------------------------------------------- -----------------------------------------*/
DateTime_t UTC_SecToDate( uint32_t utc_sec );
DateTime_t UTC_DateToZoneDate(int8_t zone_num, uint16_t year_base, uint8_t u_year, uint8_t u_month,
uint8_t u_day, uint8_t u_hour, uint8_t u_min, uint8_t u_sec, uint8_t u_week);
#ifdef __cplusplus
}
#endif
#endif /* __TIME_CONV_H__ */
@@ -0,0 +1,103 @@
/*!
* \file rtc.c
*
* \brief Target rtc implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "rtc.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------
-----------------------------------------*/
#define MANUF_UTC_SEC 1680516516 // rtc start time
/*------------------------------------------------------------------------------------
Constant
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
volatile uint32_t Utc_TotalSec = MANUF_UTC_SEC;
// Test val
uint8_t Sec_Flag = false;
/*------------------------------------------------------------------------------------
Functions
------------------------------------------------------------------------------------*/
/**
* @brief RTC handler func
* @param xinc_drv_rtc_int_type_t - type
* @retval void
*/
uint8_t Sec_Callback(void)
{
Utc_TotalSec += 1;
Sec_Flag = true;
return 0;
}
/**
* @brief RTC config func
* @param void
* @retval void
*/
void RTC_Config(void)
{
// Initialize RTC instance
RTC_InitCfg_t rtc_cfg = {0};
NVIC_DisableIRQ(RTC_IRQn);
// rtc_cfg.Date.Sec = 0;
// rtc_cfg.Date.Min = 0;
// rtc_cfg.Date.Hour = 18;
// rtc_cfg.Date.Day = 93;
// rtc_cfg.Date.Week = 1;
rtc_cfg.Date.Sec = 0;
rtc_cfg.Date.Min = 45;
rtc_cfg.Date.Hour = 19;
rtc_cfg.Date.Day = 340;
rtc_cfg.Date.Week = 2;
rtc_cfg.DateLimit.SecLimit = 60;
rtc_cfg.DateLimit.MinLimit = 60;
rtc_cfg.DateLimit.HourLimit = 24;
rtc_cfg.MatchTimeEnable = false;
rtc_cfg.SecIT_Enable = true;
rtc_cfg.MinIT_Enable = false;
rtc_cfg.HourIT_Enable = false;
rtc_cfg.DayIT_Enable = false;
// Rtc enable
xc_rtc_init(&rtc_cfg);
NVIC_EnableIRQ(RTC_IRQn);
xc_rtc_start();
}
@@ -0,0 +1,168 @@
/*!
* \file time_conv.c
*
* \brief Target time convert implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "time_conv.h"
/*------------------------------------------------------------------------------------
Functions
------------------------------------------------------------------------------------*/
/**
* @brief UTC second convert to date and time.
* @details
* @param[in] uint32_t - utc_sec
* @param[out] void
* @retval DateTime_t
* @retval void
* @par identifier
* reserve
* @par other
* void
* @par change log
* Alex created on 2022-09-09
*/
DateTime_t UTC_SecToDate(uint32_t utc_sec)
{
Utc_Date_t tmp;
DateTime_t ret;
tmp = *localtime(&utc_sec);
ret.year = tmp.tm_year;
ret.month = tmp.tm_mon;
ret.day = tmp.tm_mday;
ret.hour = tmp.tm_hour;
ret.min = tmp.tm_min;
ret.sec = tmp.tm_sec;
ret.week = tmp.tm_wday;
return ret;
}
/**
* @brief Convert the date in the UTC time zone to the date in the
* corresponding time zone.
* @details
* @param[in] int8_t - zone_num
* uint16_t - year_base
* uint8_t - u_year, u_month, u_day, u_hour, u_min, u_sec, u_week
* @param[out] void
* @retval DateTime_t
* @retval void
* @par identifier
* reserve
* @par other
* void
* @par change log
* Alex created on 2022-09-09
*/
DateTime_t UTC_DateToZoneDate(int8_t zone_num, uint16_t year_base,
uint8_t u_year, uint8_t u_month, uint8_t u_day,
uint8_t u_hour, uint8_t u_min, uint8_t u_sec,
uint8_t u_week)
{
DateTime_t zonedate;
int t_year = 0;
int lastday = 0; // last day of the month
int lastmon_lastday = 0; // last day of last month
int8_t t_hour = 0;
t_year = u_year - 100 + year_base;
zonedate.month = u_month + 1;
zonedate.day = u_day;
zonedate.hour = u_hour;
zonedate.min = u_min;
zonedate.sec = u_sec;
zonedate.week = u_week;
// Determine days by month
if (M_JAN == zonedate.month || M_MAR == zonedate.month ||
M_MAY == zonedate.month || M_JUL == zonedate.month ||
M_AUG == zonedate.month || M_OCT == zonedate.month ||
M_DEC == zonedate.month) {
lastday = 31;
if (M_MAR == zonedate.month) {
// leap year determination
if ((t_year % 400 == 0) || (t_year % 4 == 0 && t_year % 100 != 0))
lastmon_lastday = 29;
else
lastmon_lastday = 28;
}
if (M_AUG == zonedate.month)
lastmon_lastday = 31;
} else if (M_APR == zonedate.month || M_JUN == zonedate.month ||
M_SEP == zonedate.month || M_NOV == zonedate.month) {
lastday = 30;
lastmon_lastday = 31;
} else {
lastmon_lastday = 31;
// leap year determination
if ((t_year % 400 == 0) || (t_year % 4 == 0 && t_year % 100 != 0))
lastday = 29;
else
lastday = 28;
}
t_hour = (int8_t)zonedate.hour + zone_num;
if (t_hour >= 24) {
zonedate.hour = (uint8_t)t_hour - 24;
zonedate.day += 1;
if (zonedate.day > lastday) {
zonedate.day -= lastday;
zonedate.month += 1;
if (zonedate.month > M_DEC) {
zonedate.month -= M_DEC;
t_year += 1;
}
}
if (zonedate.week < 6)
zonedate.week += 1;
else
zonedate.week = 0;
} else if (t_hour < 0) {
zonedate.hour = (uint8_t)(t_hour + 24);
zonedate.day -= 1;
if (zonedate.day == 0) {
zonedate.day = lastmon_lastday;
zonedate.month -= 1;
if (zonedate.month == 0) {
zonedate.month = M_DEC;
t_year -= 1;
}
}
if ((zonedate.week > 0) && (zonedate.week <= 6))
zonedate.week -= 1;
else
zonedate.week = 6;
} else
zonedate.hour = t_hour;
zonedate.year = t_year - year_base;
return zonedate;
}
@@ -0,0 +1,95 @@
/*!
* \file usb_device.c
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Includes ------------------------------------------------------------------*/
#include "usb_device.h"
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_cdc.h"
#include "usbd_cdc_if.h"
#include "usbd_cdc.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE END PFP */
/* USB Device Core handle declaration. */
USBD_HandleTypeDef hUsbDeviceFS;
/*
* -- Insert your variables declaration here --
*/
/* USER CODE BEGIN 0 */
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
/* USER CODE END 0 */
/*
* -- Insert your external function declaration here --
*/
void USB_Handler(void) { HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); }
/**
* Init USB device Library, add supported class and start the library
* @retval None
*/
void USB_DEVICE_Init(void)
{
/* Init Device Library, add supported class and start the library. */
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
{
Error_Handler();
}
if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK)
{
Error_Handler();
}
if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_CDC_Interface_fops_FS) != USBD_OK)
{
Error_Handler();
}
if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
{
Error_Handler();
}
}
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,104 @@
/*!
* \file usb_device.h
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_DEVICE_H
#define __USB_DEVICE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_def.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup USBD_OTG_DRIVER
* @{
*/
/** @defgroup USBD_DEVICE USBD_DEVICE
* @brief Device file for Usb otg low level driver.
* @{
*/
/** @defgroup USBD_DEVICE_Exported_Variables USBD_DEVICE_Exported_Variables
* @brief Public variables.
* @{
*/
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/*
* -- Insert your variables declaration here --
*/
/* USER CODE BEGIN VARIABLES */
/* USER CODE END VARIABLES */
/**
* @}
*/
/** @defgroup USBD_DEVICE_Exported_FunctionsPrototype USBD_DEVICE_Exported_FunctionsPrototype
* @brief Declaration of public functions for Usb device.
* @{
*/
/** USB Device initialization function. */
void USB_DEVICE_Init(void);
/*
* -- Insert functions declaration here --
*/
/* USER CODE BEGIN FD */
/* USER CODE END FD */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_DEVICE_H */
@@ -0,0 +1,367 @@
/*!
* \file usbd_cdc_if.c
*
* \brief Usb device for Virtual Com Port.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @brief Usb device library.
* @{
*/
/** @addtogroup USBD_CDC_IF
* @{
*/
/** @defgroup USBD_CDC_IF_Private_TypesDefinitions USBD_CDC_IF_Private_TypesDefinitions
* @brief Private types.
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Private_Defines USBD_CDC_IF_Private_Defines
* @brief Private defines.
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Private_Macros USBD_CDC_IF_Private_Macros
* @brief Private macros.
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Private_Variables USBD_CDC_IF_Private_Variables
* @brief Private variables.
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/** Received data over USB are stored in this buffer */
uint8_t CDC_UserRxBufferFS[APP_RX_DATA_SIZE];
/** Data to send over USB CDC are stored in this buffer */
uint8_t CDC_UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* CDC Instance 0 Variables */
uint8_t UserRxBuffer0[APP_RX_DATA_SIZE];/* Received Data over USB are stored in this buffer */
uint8_t UserTxBuffer0[APP_TX_DATA_SIZE];/* Received Data over UART (CDC interface) are stored in this buffer */
uint8_t UserRxBuffer1[APP_RX_DATA_SIZE];/* Received Data over USB are stored in this buffer */
uint8_t UserTxBuffer1[APP_TX_DATA_SIZE];/* Received Data over UART (CDC interface) are stored in this buffer */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables
* @brief Public variables.
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Private_FunctionPrototypes USBD_CDC_IF_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static int8_t CDC_Init_FS(void);
static int8_t CDC_DeInit_FS(void);
static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS(uint8_t* pbuf, uint32_t *Len);
static int8_t CDC_TransmitCplt_FS(uint8_t *pbuf, uint32_t *Len, uint8_t epnum);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_CDC_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS,
CDC_TransmitCplt_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief Initializes the CDC media low layer over the FS USB IP
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
#ifdef USE_USBD_COMPOSITE
/* Set Application Buffers */
/* Check if the class ID corresponds to instance 0 */
if (hUsbDeviceFS.classId == USBD_CMPSIT_GetClassID(&hUsbDeviceFS, CLASS_TYPE_CDC, 0))
{
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBuffer0, 0);
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBuffer0);
return (USBD_OK);
}
/* Check if the class ID corresponds to instance 1 */
else if (hUsbDeviceFS.classId == USBD_CMPSIT_GetClassID(&hUsbDeviceFS, CLASS_TYPE_CDC, 1))
{
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBuffer1, 0);
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBuffer1);
return (USBD_OK);
}
else
{
/* Error: no instancecorresponds to this class ID */
return USBD_FAIL;
}
#else
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBuffer0, 0);
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBuffer0);
return (USBD_OK);
#endif
/* USER CODE END 3 */
}
/**
* @brief DeInitializes the CDC media low layer
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch(cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will issue a NAK packet on any OUT packet received on
* USB endpoint until exiting this function. If you exit this function
* before transfer is complete on CDC interface (ie. using DMA controller)
* it will result in receiving more data while previous ones are still
* not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @param epnum: Êä³ö¶ËµãµØÖ·
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
CDC_Transmit_FS(Buf, *Len);
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data to send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be sent
* @param Len: Number of data to be sent (in bytes)
* @retval USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassDataCmsit[hUsbDeviceFS.classId];
if (hcdc->TxState != 0){
hcdc->TxState = 0;
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/**
* @brief CDC_TransmitCplt_FS
* Data transmitted callback
*
* @note
* This function is IN transfer complete callback used to inform user that
* the submitted Data is successfully sent over USB.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_TransmitCplt_FS(uint8_t *Buf, uint32_t *Len, uint8_t epnum)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 13 */
UNUSED(Buf);
UNUSED(Len);
UNUSED(epnum);
/* USER CODE END 13 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,136 @@
/*!
* \file usbd_cdc_if.h
*
* \brief Header for usbd_cdc_if.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CDC_IF_H
#define __USBD_CDC_IF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @brief For Usb device.
* @{
*/
/** @defgroup USBD_CDC_IF USBD_CDC_IF
* @brief Usb VCP device module
* @{
*/
/** @defgroup USBD_CDC_IF_Exported_Defines USBD_CDC_IF_Exported_Defines
* @brief Defines.
* @{
*/
/* Define size for the receive and transmit buffer over CDC */
#define APP_RX_DATA_SIZE 64
#define APP_TX_DATA_SIZE 64
/* USER CODE BEGIN EXPORTED_DEFINES */
/* USER CODE END EXPORTED_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Types USBD_CDC_IF_Exported_Types
* @brief Types.
* @{
*/
/* USER CODE BEGIN EXPORTED_TYPES */
/* USER CODE END EXPORTED_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Macros USBD_CDC_IF_Exported_Macros
* @brief Aliases.
* @{
*/
/* USER CODE BEGIN EXPORTED_MACRO */
/* USER CODE END EXPORTED_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables
* @brief Public variables.
* @{
*/
/** CDC Interface callback. */
extern USBD_CDC_ItfTypeDef USBD_CDC_Interface_fops_FS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_FunctionsPrototype USBD_CDC_IF_Exported_FunctionsPrototype
* @brief Public functions declaration.
* @{
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);
/* USER CODE BEGIN EXPORTED_FUNCTIONS */
/* USER CODE END EXPORTED_FUNCTIONS */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CDC_IF_H */
@@ -0,0 +1,493 @@
/*!
* \file usbd_desc.c
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_conf.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @addtogroup USBD_DESC
* @{
*/
/** @defgroup USBD_DESC_Private_TypesDefinitions USBD_DESC_Private_TypesDefinitions
* @brief Private types.
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_DESC_Private_Defines USBD_DESC_Private_Defines
* @brief Private defines.
* @{
*/
#define USBD_VID 0x0483
#define USBD_LANGID_STRING 0x0409
#define USBD_MANUFACTURER_STRING "XinChip"
#define USBD_PID_FS 22336
#define USBD_PRODUCT_STRING_FS "XinChip Virtual ComPort"
#define USBD_CONFIGURATION_STRING_FS "CDC Config"
#define USBD_INTERFACE_STRING_FS "CDC Interface"
#define USB_SIZ_BOS_DESC 0x0C
/* USER CODE BEGIN PRIVATE_DEFINES */
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/** @defgroup USBD_DESC_Private_Macros USBD_DESC_Private_Macros
* @brief Private macros.
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_DESC_Private_FunctionPrototypes USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static void Get_SerialNum(void);
static void IntToUnicode(uint32_t value, uint8_t * pbuf, uint8_t len);
/**
* @}
*/
/** @defgroup USBD_DESC_Private_FunctionPrototypes USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration for FS.
* @{
*/
uint8_t * USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t * USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t * USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t * USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t * USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t * USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t * USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
#if (USBD_LPM_ENABLED == 1)
uint8_t * USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
#endif /* (USBD_LPM_ENABLED == 1) */
/**
* @}
*/
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
USBD_DescriptorsTypeDef FS_Desc =
{
USBD_FS_DeviceDescriptor
, USBD_FS_LangIDStrDescriptor
, USBD_FS_ManufacturerStrDescriptor
, USBD_FS_ProductStrDescriptor
, USBD_FS_SerialStrDescriptor
, USBD_FS_ConfigStrDescriptor
, USBD_FS_InterfaceStrDescriptor
#if (USBD_LPM_ENABLED == 1)
, USBD_FS_USR_BOSDescriptor
#endif /* (USBD_LPM_ENABLED == 1) */
};
#if defined ( __ICCARM__ ) /* IAR Compiler */
#pragma data_alignment=4
#endif /* defined ( __ICCARM__ ) */
#ifdef USE_USBD_COMPOSITE
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =
{
0x12, /*bLength */
USB_DESC_TYPE_DEVICE, /*bDescriptorType*/
0x00, /*bcdUSB */
0x02,
#if USE_USBD_COMPOSITE /* Audio Class */
#if USBD_COMPOSITE_USE_IAD
0xEF, /*bDeviceClass*/
0x02, /*bDeviceSubClass*/
0x01, /*bDeviceProtocol*/
#else
#if USBD_CMPSIT_ACTIVATE_CDC || USBD_CMPSIT_ACTIVATE_MULTI_CDC
/* CDC 02 02 00 */
0x02,
0x02,
0x00,
#else
/* normal */
0x00, /*bDeviceClass*/
0x00, /*bDeviceSubClass*/
0x00, /*bDeviceProtocol*/
#endif
#endif
#else /* CDC 02 02 00 */
0x00, /*bDeviceClass*/
0x00, /*bDeviceSubClass*/
0x00, /*bDeviceProtocol*/
#endif
USB_MAX_EP0_SIZE, /*bMaxPacketSize*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
LOBYTE(USBD_PID_FS), /*idProduct*/
HIBYTE(USBD_PID_FS), /*idProduct*/
0x00, /*bcdDevice rel. 2.00*/
0x02,
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
USBD_IDX_PRODUCT_STR, /*Index of product string*/
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/
};
#else
/** USB standard device descriptor. */
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =
{
0x12, /*bLength */
USB_DESC_TYPE_DEVICE, /*bDescriptorType*/
#if (USBD_LPM_ENABLED == 1)
0x01, /*bcdUSB */ /* changed to USB version 2.01
in order to support LPM L1 suspend
resume test of USBCV3.0*/
#else
0x00, /*bcdUSB */
#endif /* (USBD_LPM_ENABLED == 1) */
0x02,
0x02, /*bDeviceClass*/
0x02, /*bDeviceSubClass*/
0x00, /*bDeviceProtocol*/
USB_MAX_EP0_SIZE, /*bMaxPacketSize*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
LOBYTE(USBD_PID_FS), /*idProduct*/
HIBYTE(USBD_PID_FS), /*idProduct*/
0x00, /*bcdDevice rel. 2.00*/
0x02,
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
USBD_IDX_PRODUCT_STR, /*Index of product string*/
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/
};
#endif
/* USB_DeviceDescriptor */
/** BOS descriptor. */
#if (USBD_LPM_ENABLED == 1)
#if defined ( __ICCARM__ ) /* IAR Compiler */
#pragma data_alignment=4
#endif /* defined ( __ICCARM__ ) */
__ALIGN_BEGIN uint8_t USBD_FS_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END =
{
0x5,
USB_DESC_TYPE_BOS,
0xC,
0x0,
0x1, /* 1 device capability*/
/* device capability*/
0x7,
USB_DEVICE_CAPABITY_TYPE,
0x2,
0x2, /* LPM capability bit set*/
0x0,
0x0,
0x0
};
#endif /* (USBD_LPM_ENABLED == 1) */
/**
* @}
*/
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
#if defined ( __ICCARM__ ) /* IAR Compiler */
#pragma data_alignment=4
#endif /* defined ( __ICCARM__ ) */
/** USB lang identifier descriptor. */
__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END =
{
USB_LEN_LANGID_STR_DESC,
USB_DESC_TYPE_STRING,
LOBYTE(USBD_LANGID_STRING),
HIBYTE(USBD_LANGID_STRING)
};
#if defined ( __ICCARM__ ) /* IAR Compiler */
#pragma data_alignment=4
#endif /* defined ( __ICCARM__ ) */
/* Internal string descriptor. */
__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = {
USB_SIZ_STRING_SERIAL,
USB_DESC_TYPE_STRING,
};
/**
* @}
*/
/** @defgroup USBD_DESC_Private_Functions USBD_DESC_Private_Functions
* @brief Private functions.
* @{
*/
/**
* @brief Return the device descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t * USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_FS_DeviceDesc);
return USBD_FS_DeviceDesc;
}
/**
* @brief Return the LangID string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t * USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_LangIDDesc);
return USBD_LangIDDesc;
}
/**
* @brief Return the product string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t * USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if(speed == USBD_SPEED_HIGH)
{
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
}
else
{
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/**
* @brief Return the manufacturer string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t * USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
return USBD_StrDesc;
}
/**
* @brief Return the serial number string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t * USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = USB_SIZ_STRING_SERIAL;
/* Update the serial number string descriptor with the data from the unique
* ID */
Get_SerialNum();
/* USER CODE BEGIN USBD_FS_SerialStrDescriptor */
/* USER CODE END USBD_FS_SerialStrDescriptor */
return (uint8_t *) USBD_StringSerial;
}
/**
* @brief Return the configuration string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t * USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if(speed == USBD_SPEED_HIGH)
{
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length);
}
else
{
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/**
* @brief Return the interface string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t * USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if(speed == 0)
{
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
}
else
{
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
#if (USBD_LPM_ENABLED == 1)
/**
* @brief Return the BOS descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t * USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_FS_BOSDesc);
return (uint8_t*)USBD_FS_BOSDesc;
}
#endif /* (USBD_LPM_ENABLED == 1) */
/**
* @brief Create the serial number string descriptor
* @param None
* @retval None
*/
static void Get_SerialNum(void)
{
uint32_t deviceserial0;
uint32_t deviceserial1;
uint32_t deviceserial2;
deviceserial0 = DEVICE_ID1;
deviceserial1 = DEVICE_ID2;
deviceserial2 = DEVICE_ID3;
deviceserial0 += deviceserial2;
if (deviceserial0 != 0)
{
IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8);
IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4);
}
}
/**
* @brief Convert Hex 32Bits value into char
* @param value: value to convert
* @param pbuf: pointer to the buffer
* @param len: buffer length
* @retval None
*/
static void IntToUnicode(uint32_t value, uint8_t * pbuf, uint8_t len)
{
uint8_t idx = 0;
for (idx = 0; idx < len; idx++)
{
if (((value >> 28)) < 0xA)
{
pbuf[2 * idx] = (value >> 28) + '0';
}
else
{
pbuf[2 * idx] = (value >> 28) + 'A' - 10;
}
value = value << 4;
pbuf[2 * idx + 1] = 0;
}
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,148 @@
/*!
* \file usbd_desc.h
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_DESC__C
#define __USBD_DESC__C
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_def.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_DESC USBD_DESC
* @brief Usb device descriptors module.
* @{
*/
/** @defgroup USBD_DESC_Exported_Constants USBD_DESC_Exported_Constants
* @brief Constants.
* @{
*/
#define DEVICE_ID1 (0x20220000)
#define DEVICE_ID2 (0x1B0000)
#define DEVICE_ID3 (0x0914)
#define USB_SIZ_STRING_SERIAL 0x1A
/* USER CODE BEGIN EXPORTED_CONSTANTS */
/* USER CODE END EXPORTED_CONSTANTS */
/**
* @}
*/
/** @defgroup USBD_DESC_Exported_Defines USBD_DESC_Exported_Defines
* @brief Defines.
* @{
*/
/* USER CODE BEGIN EXPORTED_DEFINES */
/* USER CODE END EXPORTED_DEFINES */
/**
* @}
*/
/** @defgroup USBD_DESC_Exported_TypesDefinitions USBD_DESC_Exported_TypesDefinitions
* @brief Types.
* @{
*/
/* USER CODE BEGIN EXPORTED_TYPES */
/* USER CODE END EXPORTED_TYPES */
/**
* @}
*/
/** @defgroup USBD_DESC_Exported_Macros USBD_DESC_Exported_Macros
* @brief Aliases.
* @{
*/
/* USER CODE BEGIN EXPORTED_MACRO */
/* USER CODE END EXPORTED_MACRO */
/**
* @}
*/
/** @defgroup USBD_DESC_Exported_Variables USBD_DESC_Exported_Variables
* @brief Public variables.
* @{
*/
/** Descriptor for the Usb device. */
extern USBD_DescriptorsTypeDef FS_Desc;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_DESC_Exported_FunctionsPrototype USBD_DESC_Exported_FunctionsPrototype
* @brief Public functions declaration.
* @{
*/
/* USER CODE BEGIN EXPORTED_FUNCTIONS */
/* USER CODE END EXPORTED_FUNCTIONS */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_DESC__C */
@@ -0,0 +1,119 @@
/*!
* \file usb_device.c
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Includes ------------------------------------------------------------------*/
#include "usb_device.h"
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_hid_mouse.h"
#include "usbd_hid_keyboard.h"
#include "usbd_hid_custom.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE END PFP */
/* USB Device Core handle declaration. */
USBD_HandleTypeDef hUsbDeviceFS;
/*
* -- Insert your variables declaration here --
*/
/* USER CODE BEGIN 0 */
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
/* USER CODE END 0 */
/*
* -- Insert your external function declaration here --
*/
void USB_Handler(void) { HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); }
/**
* Init USB device Library, add supported class and start the library
* @retval None
*/
void USB_DEVICE_Init(void)
{
static uint8_t HID_Mouse_EP_Addr[] = {HID_MOUSE_EPIN_ADDR };
static uint8_t HID_Keyboard_EP_Addr[] = {HID_KEYBOARD_EPIN_ADDR, HID_KEYBOARD_EPOUT_ADDR };
static uint8_t HID_Custom_EP_Addr[] = {HID_CUSTOM_EPIN_ADDR, HID_CUSTOM_EPOUT_ADDR };
#ifdef USE_USBD_COMPOSITE
if(USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
{
Error_Handler();
}
#if USBD_CMPSIT_ACTIVATE_HID_MOUSE
/* Register HID class second instance */
if(USBD_RegisterClassComposite(&hUsbDeviceFS, USBD_HID_MOUSE_CLASS, CLASS_TYPE_HID_MOUSE, HID_Mouse_EP_Addr) != USBD_OK)
{
Error_Handler();
}
#endif
#if USBD_CMPSIT_ACTIVATE_HID_KEYBOARD
if(USBD_RegisterClassComposite(&hUsbDeviceFS, USBD_HID_KEYBOARD_CLASS, CLASS_TYPE_HID_KEYBOARD, HID_Keyboard_EP_Addr) != USBD_OK)
{
Error_Handler();
}
#endif
#if USBD_CMPSIT_ACTIVATE_HID_CUSTOM
if(USBD_RegisterClassComposite(&hUsbDeviceFS, USBD_HID_CUSTOM_CLASS, CLASS_TYPE_HID_CUSTOM, HID_Custom_EP_Addr) != USBD_OK)
{
Error_Handler();
}
#endif
if(USBD_Start(&hUsbDeviceFS) != USBD_OK)
{
Error_Handler();
}
#endif
}
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,52 @@
/*!
* \file usb_device.h
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_DEVICE_H__
#define __USB_DEVICE_H__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
extern USBD_HandleTypeDef hUsbDeviceFS;
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void USB_DEVICE_Init( void );
#ifdef __cplusplus
}
#endif
#endif /* __USB_DEVICE_H__ */
@@ -0,0 +1,351 @@
/*!
* \file usbd_desc.c
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_desc.h"
#include "usbd_conf.h"
#include "usbd_core.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------
-----------------------------------------*/
/** @defgroup USBD_DESC_Private_Defines USBD_DESC_Private_Defines
* @brief Private defines.
* @{
*/
#define USBD_VID VID_VAL
#define USBD_LANGID_STRING LANG_ID_STR
#define USBD_MANUFACTURER_STRING "XinChip"
#define USBD_PID_FS PID_FS_VAL
#define USBD_PRODUCT_STRING_FS "XinChip Human interface"
#define USBD_CONFIGURATION_STRING_FS "HID Config"
#define USBD_INTERFACE_STRING_FS "HID Interface"
#define USB_SIZ_BOS_DESC 0x0C
/*------------------------------------------------------------------------------------
Func Prototypes
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static void Get_SerialNum(void);
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len);
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration for FS.
* @{
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
#if (USBD_LPM_ENABLED == 1)
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
#endif /* (USBD_LPM_ENABLED == 1) */
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
USBD_DescriptorsTypeDef FS_Desc = {USBD_FS_DeviceDescriptor,
USBD_FS_LangIDStrDescriptor,
USBD_FS_ManufacturerStrDescriptor,
USBD_FS_ProductStrDescriptor,
USBD_FS_SerialStrDescriptor,
USBD_FS_ConfigStrDescriptor,
USBD_FS_InterfaceStrDescriptor
#if (USBD_LPM_ENABLED == 1)
,
USBD_FS_USR_BOSDescriptor
#endif /* (USBD_LPM_ENABLED == 1) */
};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB standard device descriptor. */
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
0x12, /*bLength */
USB_DESC_TYPE_DEVICE, /*bDescriptorType*/
#if (USBD_LPM_ENABLED == 1)
0x01,
/*bcdUSB */ /* changed to USB version 2.01
in order to support LPM L1 suspend
resume test of USBCV3.0*/
#else
0x00, /*bcdUSB */
#endif /* (USBD_LPM_ENABLED == 1) */
0x02,
DEV_CLASS, /*bDeviceClass*/
DEV_SUB_CLASS, /*bDeviceSubClass*/
DEV_PROTOCOL, /*bDeviceProtocol*/
USB_MAX_EP0_SIZE, /*bMaxPacketSize*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
LOBYTE(USBD_PID_FS), /*idProduct*/
HIBYTE(USBD_PID_FS), /*idProduct*/
0x00, /*bcdDevice rel. 2.00*/
0x02,
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
USBD_IDX_PRODUCT_STR, /*Index of product string*/
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/
};
/* USB_DeviceDescriptor */
/** BOS descriptor. */
#if (USBD_LPM_ENABLED == 1)
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
__ALIGN_BEGIN uint8_t USBD_FS_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END = {
0x5, USB_DESC_TYPE_BOS, 0xC, 0x0, 0x1, /* 1 device capability*/
/* device capability*/
0x7, USB_DEVICE_CAPABITY_TYPE, 0x2, 0x2, /* LPM capability bit set*/
0x0, 0x0, 0x0};
#endif /* (USBD_LPM_ENABLED == 1) */
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB lang identifier descriptor. */
__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
USB_LEN_LANGID_STR_DESC, USB_DESC_TYPE_STRING, LOBYTE(USBD_LANGID_STRING),
HIBYTE(USBD_LANGID_STRING)};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/* Internal string descriptor. */
__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
#if defined(__ICCARM__) /*!< IAR Compiler */
#pragma data_alignment = 4
#endif
__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = {
USB_SIZ_STRING_SERIAL,
USB_DESC_TYPE_STRING,
};
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief Return the device descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
*length = sizeof(USBD_FS_DeviceDesc);
return USBD_FS_DeviceDesc;
}
/**
* @brief Return the LangID string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_LangIDDesc);
return USBD_LangIDDesc;
}
/**
* @brief Return the product string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
} else {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/**
* @brief Return the manufacturer string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
UNUSED(speed);
USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
return USBD_StrDesc;
}
/**
* @brief Return the serial number string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = USB_SIZ_STRING_SERIAL;
/* Update the serial number string descriptor with the data from the unique
* ID */
Get_SerialNum();
/* USER CODE BEGIN USBD_FS_SerialStrDescriptor */
/* USER CODE END USBD_FS_SerialStrDescriptor */
return (uint8_t *)USBD_StringSerial;
}
/**
* @brief Return the configuration string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == USBD_SPEED_HIGH) {
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
/**
* @brief Return the interface string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
#if (USBD_LPM_ENABLED == 1)
/**
* @brief Return the BOS descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_FS_BOSDesc);
return (uint8_t *)USBD_FS_BOSDesc;
}
#endif /* (USBD_LPM_ENABLED == 1) */
/**
* @brief Create the serial number string descriptor
* @param None
* @retval None
*/
static void Get_SerialNum(void)
{
uint32_t deviceserial0, deviceserial1, deviceserial2;
deviceserial0 = DEVICE_ID1;
deviceserial1 = DEVICE_ID2;
deviceserial2 = DEVICE_ID3;
deviceserial0 += deviceserial2;
if (deviceserial0 != 0) {
IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8);
IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4);
}
}
/**
* @brief Convert Hex 32Bits value into char
* @param value: value to convert
* @param pbuf: pointer to the buffer
* @param len: buffer length
* @retval None
*/
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len)
{
uint8_t idx = 0;
for (idx = 0; idx < len; idx++) {
if (((value >> 28)) < 0xA) {
pbuf[2 * idx] = (value >> 28) + '0';
} else {
pbuf[2 * idx] = (value >> 28) + 'A' - 10;
}
value = value << 4;
pbuf[2 * idx + 1] = 0;
}
}
/**
* @}
*/
@@ -0,0 +1,77 @@
/*!
* \file usbd_desc.h
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_DESC__C__
#define __USBD_DESC__C__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Exported_Constants USBD_DESC_Exported_Constants
* @brief Constants.
* @{
*/
#define VID_VAL 0x0483
#define LANG_ID_STR 1033
#define PID_FS_VAL 0x572a//0x572a // 0xdf11
#define DEVICE_ID1 0x20860000
#define DEVICE_ID2 0x5330
#define DEVICE_ID3 0x6336
#define DEV_CLASS 0x00
#define DEV_SUB_CLASS 0x00
#define DEV_PROTOCOL 0x00
#define USB_SIZ_STRING_SERIAL 0x1A
/**
* @}
*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/** Descriptor for the Usb device. */
extern USBD_DescriptorsTypeDef FS_Desc;
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_DESC__C__ */
@@ -0,0 +1,90 @@
/*!
* \file usb_device.c
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Includes ------------------------------------------------------------------*/
#include "usb_device.h"
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_hid_custom.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE END PFP */
/* USB Device Core handle declaration. */
USBD_HandleTypeDef hUsbDeviceFS;
/*
* -- Insert your variables declaration here --
*/
/* USER CODE BEGIN 0 */
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
/* USER CODE END 0 */
/*
* -- Insert your external function declaration here --
*/
void USB_Handler(void) { HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); }
/**
* Init USB device Library, add supported class and start the library
* @retval None
*/
void USB_DEVICE_Init(void)
{
/* Init Device Library, add supported class and start the library. */
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
{
Error_Handler();
}
if (USBD_RegisterClass(&hUsbDeviceFS, USBD_HID_CUSTOM_CLASS) != USBD_OK)
{
Error_Handler();
}
if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
{
Error_Handler();
}
}
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,52 @@
/*!
* \file usb_device.h
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_DEVICE_H__
#define __USB_DEVICE_H__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
extern USBD_HandleTypeDef hUsbDeviceFS;
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void USB_DEVICE_Init( void );
#ifdef __cplusplus
}
#endif
#endif /* __USB_DEVICE_H__ */
@@ -0,0 +1,350 @@
/*!
* \file usbd_desc.c
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_desc.h"
#include "usbd_conf.h"
#include "usbd_core.h"
/*------------------------------------------------------------------------------------
Macros
------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_Defines USBD_DESC_Private_Defines
* @brief Private defines.
* @{
*/
#define USBD_VID VID_VAL
#define USBD_LANGID_STRING LANG_ID_STR
#define USBD_MANUFACTURER_STRING "XinChip"
#define USBD_PID_FS PID_FS_VAL
#define USBD_PRODUCT_STRING_FS "XinChip HID Keyboard Product"
#define USBD_CONFIGURATION_STRING_FS "HID Keyboard Config"
#define USBD_INTERFACE_STRING_FS "HID Keyboard Interface"
#define USB_SIZ_BOS_DESC 0x0C
/*------------------------------------------------------------------------------------
Func Prototypes
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static void Get_SerialNum(void);
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len);
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration for FS.
* @{
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
#if (USBD_LPM_ENABLED == 1)
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
#endif /* (USBD_LPM_ENABLED == 1) */
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
USBD_DescriptorsTypeDef FS_Desc = {USBD_FS_DeviceDescriptor,
USBD_FS_LangIDStrDescriptor,
USBD_FS_ManufacturerStrDescriptor,
USBD_FS_ProductStrDescriptor,
USBD_FS_SerialStrDescriptor,
USBD_FS_ConfigStrDescriptor,
USBD_FS_InterfaceStrDescriptor
#if (USBD_LPM_ENABLED == 1)
,
USBD_FS_USR_BOSDescriptor
#endif /* (USBD_LPM_ENABLED == 1) */
};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB standard device descriptor. */
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
0x12, /*bLength */
USB_DESC_TYPE_DEVICE, /*bDescriptorType*/
#if (USBD_LPM_ENABLED == 1)
0x01,
/*bcdUSB */ /* changed to USB version 2.01
in order to support LPM L1 suspend
resume test of USBCV3.0*/
#else
0x00, /*bcdUSB */
#endif /* (USBD_LPM_ENABLED == 1) */
0x02,
DEV_CLASS, /*bDeviceClass*/
DEV_SUB_CLASS, /*bDeviceSubClass*/
DEV_PROTOCOL, /*bDeviceProtocol*/
USB_MAX_EP0_SIZE, /*bMaxPacketSize*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
LOBYTE(USBD_PID_FS), /*idProduct*/
HIBYTE(USBD_PID_FS), /*idProduct*/
0x00, /*bcdDevice rel. 2.00*/
0x02,
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
USBD_IDX_PRODUCT_STR, /*Index of product string*/
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/
};
/* USB_DeviceDescriptor */
/** BOS descriptor. */
#if (USBD_LPM_ENABLED == 1)
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
__ALIGN_BEGIN uint8_t USBD_FS_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END = {
0x5, USB_DESC_TYPE_BOS, 0xC, 0x0, 0x1, /* 1 device capability*/
/* device capability*/
0x7, USB_DEVICE_CAPABITY_TYPE, 0x2, 0x2, /* LPM capability bit set*/
0x0, 0x0, 0x0};
#endif /* (USBD_LPM_ENABLED == 1) */
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB lang identifier descriptor. */
__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
USB_LEN_LANGID_STR_DESC, USB_DESC_TYPE_STRING, LOBYTE(USBD_LANGID_STRING),
HIBYTE(USBD_LANGID_STRING)};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/* Internal string descriptor. */
__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
#if defined(__ICCARM__) /*!< IAR Compiler */
#pragma data_alignment = 4
#endif
__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = {
USB_SIZ_STRING_SERIAL,
USB_DESC_TYPE_STRING,
};
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief Return the device descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
*length = sizeof(USBD_FS_DeviceDesc);
return USBD_FS_DeviceDesc;
}
/**
* @brief Return the LangID string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_LangIDDesc);
return USBD_LangIDDesc;
}
/**
* @brief Return the product string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
} else {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/**
* @brief Return the manufacturer string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
UNUSED(speed);
USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
return USBD_StrDesc;
}
/**
* @brief Return the serial number string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = USB_SIZ_STRING_SERIAL;
/* Update the serial number string descriptor with the data from the unique
* ID */
Get_SerialNum();
/* USER CODE BEGIN USBD_FS_SerialStrDescriptor */
/* USER CODE END USBD_FS_SerialStrDescriptor */
return (uint8_t *)USBD_StringSerial;
}
/**
* @brief Return the configuration string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == USBD_SPEED_HIGH) {
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
/**
* @brief Return the interface string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
#if (USBD_LPM_ENABLED == 1)
/**
* @brief Return the BOS descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_FS_BOSDesc);
return (uint8_t *)USBD_FS_BOSDesc;
}
#endif /* (USBD_LPM_ENABLED == 1) */
/**
* @brief Create the serial number string descriptor
* @param None
* @retval None
*/
static void Get_SerialNum(void)
{
uint32_t deviceserial0, deviceserial1, deviceserial2;
deviceserial0 = DEVICE_ID1;
deviceserial1 = DEVICE_ID2;
deviceserial2 = DEVICE_ID3;
deviceserial0 += deviceserial2;
if (deviceserial0 != 0) {
IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8);
IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4);
}
}
/**
* @brief Convert Hex 32Bits value into char
* @param value: value to convert
* @param pbuf: pointer to the buffer
* @param len: buffer length
* @retval None
*/
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len)
{
uint8_t idx = 0;
for (idx = 0; idx < len; idx++) {
if (((value >> 28)) < 0xA) {
pbuf[2 * idx] = (value >> 28) + '0';
} else {
pbuf[2 * idx] = (value >> 28) + 'A' - 10;
}
value = value << 4;
pbuf[2 * idx + 1] = 0;
}
}
/**
* @}
*/
@@ -0,0 +1,77 @@
/*!
* \file usbd_desc.h
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_DESC__C__
#define __USBD_DESC__C__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Exported_Constants USBD_DESC_Exported_Constants
* @brief Constants.
* @{
*/
#define VID_VAL 0x0483
#define LANG_ID_STR 1033
#define PID_FS_VAL 0x572a//0x572a // 0xdf11
#define DEVICE_ID1 0x20860000
#define DEVICE_ID2 0x5330
#define DEVICE_ID3 0x6336
#define DEV_CLASS 0x00
#define DEV_SUB_CLASS 0x00
#define DEV_PROTOCOL 0x00
#define USB_SIZ_STRING_SERIAL 0x1A
/**
* @}
*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/** Descriptor for the Usb device. */
extern USBD_DescriptorsTypeDef FS_Desc;
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_DESC__C__ */
@@ -0,0 +1,90 @@
/*!
* \file usb_device.c
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Includes ------------------------------------------------------------------*/
#include "usb_device.h"
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_hid_keyboard.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE END PFP */
/* USB Device Core handle declaration. */
USBD_HandleTypeDef hUsbDeviceFS;
/*
* -- Insert your variables declaration here --
*/
/* USER CODE BEGIN 0 */
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
/* USER CODE END 0 */
/*
* -- Insert your external function declaration here --
*/
void USB_Handler(void) { HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); }
/**
* Init USB device Library, add supported class and start the library
* @retval None
*/
void USB_DEVICE_Init(void)
{
/* Init Device Library, add supported class and start the library. */
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
{
Error_Handler();
}
if (USBD_RegisterClass(&hUsbDeviceFS, USBD_HID_KEYBOARD_CLASS) != USBD_OK)
{
Error_Handler();
}
if(USBD_Start(&hUsbDeviceFS) != USBD_OK)
{
Error_Handler();
}
}
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,52 @@
/*!
* \file usb_device.h
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_DEVICE_H__
#define __USB_DEVICE_H__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
extern USBD_HandleTypeDef hUsbDeviceFS;
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void USB_DEVICE_Init( void );
#ifdef __cplusplus
}
#endif
#endif /* __USB_DEVICE_H__ */
@@ -0,0 +1,350 @@
/*!
* \file usbd_desc.c
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_desc.h"
#include "usbd_conf.h"
#include "usbd_core.h"
/*------------------------------------------------------------------------------------
Macros
------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_Defines USBD_DESC_Private_Defines
* @brief Private defines.
* @{
*/
#define USBD_VID VID_VAL
#define USBD_LANGID_STRING LANG_ID_STR
#define USBD_MANUFACTURER_STRING "XinChip"
#define USBD_PID_FS PID_FS_VAL
#define USBD_PRODUCT_STRING_FS "XinChip HID Keyboard Product"
#define USBD_CONFIGURATION_STRING_FS "HID Keyboard Config"
#define USBD_INTERFACE_STRING_FS "HID Keyboard Interface"
#define USB_SIZ_BOS_DESC 0x0C
/*------------------------------------------------------------------------------------
Func Prototypes
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static void Get_SerialNum(void);
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len);
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration for FS.
* @{
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
#if (USBD_LPM_ENABLED == 1)
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
#endif /* (USBD_LPM_ENABLED == 1) */
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
USBD_DescriptorsTypeDef FS_Desc = {USBD_FS_DeviceDescriptor,
USBD_FS_LangIDStrDescriptor,
USBD_FS_ManufacturerStrDescriptor,
USBD_FS_ProductStrDescriptor,
USBD_FS_SerialStrDescriptor,
USBD_FS_ConfigStrDescriptor,
USBD_FS_InterfaceStrDescriptor
#if (USBD_LPM_ENABLED == 1)
,
USBD_FS_USR_BOSDescriptor
#endif /* (USBD_LPM_ENABLED == 1) */
};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB standard device descriptor. */
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
0x12, /*bLength */
USB_DESC_TYPE_DEVICE, /*bDescriptorType*/
#if (USBD_LPM_ENABLED == 1)
0x01,
/*bcdUSB */ /* changed to USB version 2.01
in order to support LPM L1 suspend
resume test of USBCV3.0*/
#else
0x00, /*bcdUSB */
#endif /* (USBD_LPM_ENABLED == 1) */
0x02,
DEV_CLASS, /*bDeviceClass*/
DEV_SUB_CLASS, /*bDeviceSubClass*/
DEV_PROTOCOL, /*bDeviceProtocol*/
USB_MAX_EP0_SIZE, /*bMaxPacketSize*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
LOBYTE(USBD_PID_FS), /*idProduct*/
HIBYTE(USBD_PID_FS), /*idProduct*/
0x00, /*bcdDevice rel. 2.00*/
0x02,
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
USBD_IDX_PRODUCT_STR, /*Index of product string*/
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/
};
/* USB_DeviceDescriptor */
/** BOS descriptor. */
#if (USBD_LPM_ENABLED == 1)
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
__ALIGN_BEGIN uint8_t USBD_FS_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END = {
0x5, USB_DESC_TYPE_BOS, 0xC, 0x0, 0x1, /* 1 device capability*/
/* device capability*/
0x7, USB_DEVICE_CAPABITY_TYPE, 0x2, 0x2, /* LPM capability bit set*/
0x0, 0x0, 0x0};
#endif /* (USBD_LPM_ENABLED == 1) */
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB lang identifier descriptor. */
__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
USB_LEN_LANGID_STR_DESC, USB_DESC_TYPE_STRING, LOBYTE(USBD_LANGID_STRING),
HIBYTE(USBD_LANGID_STRING)};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/* Internal string descriptor. */
__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
#if defined(__ICCARM__) /*!< IAR Compiler */
#pragma data_alignment = 4
#endif
__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = {
USB_SIZ_STRING_SERIAL,
USB_DESC_TYPE_STRING,
};
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief Return the device descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
*length = sizeof(USBD_FS_DeviceDesc);
return USBD_FS_DeviceDesc;
}
/**
* @brief Return the LangID string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_LangIDDesc);
return USBD_LangIDDesc;
}
/**
* @brief Return the product string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
} else {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/**
* @brief Return the manufacturer string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
UNUSED(speed);
USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
return USBD_StrDesc;
}
/**
* @brief Return the serial number string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = USB_SIZ_STRING_SERIAL;
/* Update the serial number string descriptor with the data from the unique
* ID */
Get_SerialNum();
/* USER CODE BEGIN USBD_FS_SerialStrDescriptor */
/* USER CODE END USBD_FS_SerialStrDescriptor */
return (uint8_t *)USBD_StringSerial;
}
/**
* @brief Return the configuration string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == USBD_SPEED_HIGH) {
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
/**
* @brief Return the interface string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
#if (USBD_LPM_ENABLED == 1)
/**
* @brief Return the BOS descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_FS_BOSDesc);
return (uint8_t *)USBD_FS_BOSDesc;
}
#endif /* (USBD_LPM_ENABLED == 1) */
/**
* @brief Create the serial number string descriptor
* @param None
* @retval None
*/
static void Get_SerialNum(void)
{
uint32_t deviceserial0, deviceserial1, deviceserial2;
deviceserial0 = DEVICE_ID1;
deviceserial1 = DEVICE_ID2;
deviceserial2 = DEVICE_ID3;
deviceserial0 += deviceserial2;
if (deviceserial0 != 0) {
IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8);
IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4);
}
}
/**
* @brief Convert Hex 32Bits value into char
* @param value: value to convert
* @param pbuf: pointer to the buffer
* @param len: buffer length
* @retval None
*/
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len)
{
uint8_t idx = 0;
for (idx = 0; idx < len; idx++) {
if (((value >> 28)) < 0xA) {
pbuf[2 * idx] = (value >> 28) + '0';
} else {
pbuf[2 * idx] = (value >> 28) + 'A' - 10;
}
value = value << 4;
pbuf[2 * idx + 1] = 0;
}
}
/**
* @}
*/
@@ -0,0 +1,77 @@
/*!
* \file usbd_desc.h
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_DESC__C__
#define __USBD_DESC__C__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Exported_Constants USBD_DESC_Exported_Constants
* @brief Constants.
* @{
*/
#define VID_VAL 0x0483
#define LANG_ID_STR 1033
#define PID_FS_VAL 0x572a//0x572a // 0xdf11
#define DEVICE_ID1 0x20860000
#define DEVICE_ID2 0x5330
#define DEVICE_ID3 0x6336
#define DEV_CLASS 0x00
#define DEV_SUB_CLASS 0x00
#define DEV_PROTOCOL 0x00
#define USB_SIZ_STRING_SERIAL 0x1A
/**
* @}
*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/** Descriptor for the Usb device. */
extern USBD_DescriptorsTypeDef FS_Desc;
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_DESC__C__ */
@@ -0,0 +1,73 @@
/*!
* \file usb_device.c
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usb_device.h"
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_hid_mouse.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/* USB Device Core handle declaration. */
USBD_HandleTypeDef hUsbDeviceFS;
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief This function handles USB On The Go FS global interrupt.
* @param void
* @retval void
*/
void USB_Handler(void) { HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); }
/**
* @brief Init USB device Library, add supported class and start the library
* @param void
* @retval void
*/
void USB_DEVICE_Init(void)
{
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
{
Error_Handler();
}
if (USBD_RegisterClass(&hUsbDeviceFS, USBD_HID_MOUSE_CLASS) != USBD_OK)
{
Error_Handler();
}
if(USBD_Start(&hUsbDeviceFS) != USBD_OK)
{
Error_Handler();
}
}
@@ -0,0 +1,52 @@
/*!
* \file usb_device.h
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_DEVICE_H__
#define __USB_DEVICE_H__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
extern USBD_HandleTypeDef hUsbDeviceFS;
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void USB_DEVICE_Init( void );
#ifdef __cplusplus
}
#endif
#endif /* __USB_DEVICE_H__ */
@@ -0,0 +1,350 @@
/*!
* \file usbd_desc.c
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_desc.h"
#include "usbd_conf.h"
#include "usbd_core.h"
/*------------------------------------------------------------------------------------
Macros
------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_Defines USBD_DESC_Private_Defines
* @brief Private defines.
* @{
*/
#define USBD_VID VID_VAL
#define USBD_LANGID_STRING LANG_ID_STR
#define USBD_MANUFACTURER_STRING "XinChip"
#define USBD_PID_FS PID_FS_VAL
#define USBD_PRODUCT_STRING_FS "XinChip HID Mouse Product"
#define USBD_CONFIGURATION_STRING_FS "HID Mouse Config"
#define USBD_INTERFACE_STRING_FS "HID Mouse Interface"
#define USB_SIZ_BOS_DESC 0x0C
/*------------------------------------------------------------------------------------
Func Prototypes
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static void Get_SerialNum(void);
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len);
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration for FS.
* @{
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
#if (USBD_LPM_ENABLED == 1)
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
#endif /* (USBD_LPM_ENABLED == 1) */
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
USBD_DescriptorsTypeDef FS_Desc = {USBD_FS_DeviceDescriptor,
USBD_FS_LangIDStrDescriptor,
USBD_FS_ManufacturerStrDescriptor,
USBD_FS_ProductStrDescriptor,
USBD_FS_SerialStrDescriptor,
USBD_FS_ConfigStrDescriptor,
USBD_FS_InterfaceStrDescriptor
#if (USBD_LPM_ENABLED == 1)
,
USBD_FS_USR_BOSDescriptor
#endif /* (USBD_LPM_ENABLED == 1) */
};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB standard device descriptor. */
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
0x12, /*bLength */
USB_DESC_TYPE_DEVICE, /*bDescriptorType*/
#if (USBD_LPM_ENABLED == 1)
0x01,
/*bcdUSB */ /* changed to USB version 2.01
in order to support LPM L1 suspend
resume test of USBCV3.0*/
#else
0x00, /*bcdUSB */
#endif /* (USBD_LPM_ENABLED == 1) */
0x02,
DEV_CLASS, /*bDeviceClass*/
DEV_SUB_CLASS, /*bDeviceSubClass*/
DEV_PROTOCOL, /*bDeviceProtocol*/
USB_MAX_EP0_SIZE, /*bMaxPacketSize*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
LOBYTE(USBD_PID_FS), /*idProduct*/
HIBYTE(USBD_PID_FS), /*idProduct*/
0x00, /*bcdDevice rel. 2.00*/
0x02,
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
USBD_IDX_PRODUCT_STR, /*Index of product string*/
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/
};
/* USB_DeviceDescriptor */
/** BOS descriptor. */
#if (USBD_LPM_ENABLED == 1)
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
__ALIGN_BEGIN uint8_t USBD_FS_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END = {
0x5, USB_DESC_TYPE_BOS, 0xC, 0x0, 0x1, /* 1 device capability*/
/* device capability*/
0x7, USB_DEVICE_CAPABITY_TYPE, 0x2, 0x2, /* LPM capability bit set*/
0x0, 0x0, 0x0};
#endif /* (USBD_LPM_ENABLED == 1) */
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB lang identifier descriptor. */
__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
USB_LEN_LANGID_STR_DESC, USB_DESC_TYPE_STRING, LOBYTE(USBD_LANGID_STRING),
HIBYTE(USBD_LANGID_STRING)};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/* Internal string descriptor. */
__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
#if defined(__ICCARM__) /*!< IAR Compiler */
#pragma data_alignment = 4
#endif
__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = {
USB_SIZ_STRING_SERIAL,
USB_DESC_TYPE_STRING,
};
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief Return the device descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
*length = sizeof(USBD_FS_DeviceDesc);
return USBD_FS_DeviceDesc;
}
/**
* @brief Return the LangID string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_LangIDDesc);
return USBD_LangIDDesc;
}
/**
* @brief Return the product string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
} else {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/**
* @brief Return the manufacturer string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
UNUSED(speed);
USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
return USBD_StrDesc;
}
/**
* @brief Return the serial number string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = USB_SIZ_STRING_SERIAL;
/* Update the serial number string descriptor with the data from the unique
* ID */
Get_SerialNum();
/* USER CODE BEGIN USBD_FS_SerialStrDescriptor */
/* USER CODE END USBD_FS_SerialStrDescriptor */
return (uint8_t *)USBD_StringSerial;
}
/**
* @brief Return the configuration string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == USBD_SPEED_HIGH) {
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
/**
* @brief Return the interface string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
#if (USBD_LPM_ENABLED == 1)
/**
* @brief Return the BOS descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_FS_BOSDesc);
return (uint8_t *)USBD_FS_BOSDesc;
}
#endif /* (USBD_LPM_ENABLED == 1) */
/**
* @brief Create the serial number string descriptor
* @param None
* @retval None
*/
static void Get_SerialNum(void)
{
uint32_t deviceserial0, deviceserial1, deviceserial2;
deviceserial0 = DEVICE_ID1;
deviceserial1 = DEVICE_ID2;
deviceserial2 = DEVICE_ID3;
deviceserial0 += deviceserial2;
if (deviceserial0 != 0) {
IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8);
IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4);
}
}
/**
* @brief Convert Hex 32Bits value into char
* @param value: value to convert
* @param pbuf: pointer to the buffer
* @param len: buffer length
* @retval None
*/
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len)
{
uint8_t idx = 0;
for (idx = 0; idx < len; idx++) {
if (((value >> 28)) < 0xA) {
pbuf[2 * idx] = (value >> 28) + '0';
} else {
pbuf[2 * idx] = (value >> 28) + 'A' - 10;
}
value = value << 4;
pbuf[2 * idx + 1] = 0;
}
}
/**
* @}
*/
@@ -0,0 +1,76 @@
/*!
* \file usbd_desc.h
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_DESC__C__
#define __USBD_DESC__C__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_def.h"
/* Macros ------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Exported_Constants USBD_DESC_Exported_Constants
* @brief Constants.
* @{
*/
#define VID_VAL 1155
#define LANG_ID_STR 1033
#define PID_FS_VAL 17799
#define DEVICE_ID1 0x20220000
#define DEVICE_ID2 0x1D0000
#define DEVICE_ID3 0x1122
#define DEV_CLASS 0x00
#define DEV_SUB_CLASS 0x00
#define DEV_PROTOCOL 0x00
#define USB_SIZ_STRING_SERIAL 0x1A
/**
* @}
*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/** Descriptor for the Usb device. */
extern USBD_DescriptorsTypeDef FS_Desc;
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_DESC__C__ */
@@ -0,0 +1,98 @@
/*!
* \file usb_device.c
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Includes ------------------------------------------------------------------*/
#include "usb_device.h"
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_msc.h"
#include "usbd_storage_if.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE END PFP */
/* USB Device Core handle declaration. */
USBD_HandleTypeDef hUsbDeviceFS;
/*
* -- Insert your variables declaration here --
*/
/* USER CODE BEGIN 0 */
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
/* USER CODE END 0 */
/*
* -- Insert your external function declaration here --
*/
void USB_Handler(void) { HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); }
/**
* Init USB device Library, add supported class and start the library
* @retval None
*/
void USB_DEVICE_Init(void)
{
/* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */
/* Init Device Library, add supported class and start the library. */
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
{
Error_Handler();
}
if (USBD_RegisterClass(&hUsbDeviceFS, USBD_MSC_CLASS) != USBD_OK)
{
Error_Handler();
}
if (USBD_MSC_RegisterStorage(&hUsbDeviceFS, &USBD_Storage_Interface_fops_FS) != USBD_OK)
{
Error_Handler();
}
if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */
}
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,47 @@
/*!
* \file usb_device.h
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_DEVICE_H__
#define __USB_DEVICE_H__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void USB_DEVICE_Init( void );
#ifdef __cplusplus
}
#endif
#endif /* __USB_DEVICE_H__ */
@@ -0,0 +1,350 @@
/*!
* \file usbd_desc.c
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_desc.h"
#include "usbd_conf.h"
#include "usbd_core.h"
/*------------------------------------------------------------------------------------
Macros
------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_Defines USBD_DESC_Private_Defines
* @brief Private defines.
* @{
*/
#define USBD_VID VID_VAL
#define USBD_LANGID_STRING LANG_ID_STR
#define USBD_MANUFACTURER_STRING "XinChip"
#define USBD_PID_FS PID_FS_VAL
#define USBD_PRODUCT_STRING_FS "XinChip Mass Storage"
#define USBD_CONFIGURATION_STRING_FS "MSC Config"
#define USBD_INTERFACE_STRING_FS "MSC Interface"
#define USB_SIZ_BOS_DESC 0x0C
/*------------------------------------------------------------------------------------
Func Prototypes
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static void Get_SerialNum(void);
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len);
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration for FS.
* @{
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
#if (USBD_LPM_ENABLED == 1)
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
#endif /* (USBD_LPM_ENABLED == 1) */
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
USBD_DescriptorsTypeDef FS_Desc = {USBD_FS_DeviceDescriptor,
USBD_FS_LangIDStrDescriptor,
USBD_FS_ManufacturerStrDescriptor,
USBD_FS_ProductStrDescriptor,
USBD_FS_SerialStrDescriptor,
USBD_FS_ConfigStrDescriptor,
USBD_FS_InterfaceStrDescriptor
#if (USBD_LPM_ENABLED == 1)
,
USBD_FS_USR_BOSDescriptor
#endif /* (USBD_LPM_ENABLED == 1) */
};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB standard device descriptor. */
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
0x12, /*bLength */
USB_DESC_TYPE_DEVICE, /*bDescriptorType*/
#if (USBD_LPM_ENABLED == 1)
0x01,
/*bcdUSB */ /* changed to USB version 2.01
in order to support LPM L1 suspend
resume test of USBCV3.0*/
#else
0x00, /*bcdUSB */
#endif /* (USBD_LPM_ENABLED == 1) */
0x02,
DEV_CLASS, /*bDeviceClass*/
DEV_SUB_CLASS, /*bDeviceSubClass*/
DEV_PROTOCOL, /*bDeviceProtocol*/
USB_MAX_EP0_SIZE, /*bMaxPacketSize*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
LOBYTE(USBD_PID_FS), /*idProduct*/
HIBYTE(USBD_PID_FS), /*idProduct*/
0x00, /*bcdDevice rel. 2.00*/
0x02,
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
USBD_IDX_PRODUCT_STR, /*Index of product string*/
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/
};
/* USB_DeviceDescriptor */
/** BOS descriptor. */
#if (USBD_LPM_ENABLED == 1)
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
__ALIGN_BEGIN uint8_t USBD_FS_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END = {
0x5, USB_DESC_TYPE_BOS, 0xC, 0x0, 0x1, /* 1 device capability*/
/* device capability*/
0x7, USB_DEVICE_CAPABITY_TYPE, 0x2, 0x2, /* LPM capability bit set*/
0x0, 0x0, 0x0};
#endif /* (USBD_LPM_ENABLED == 1) */
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB lang identifier descriptor. */
__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
USB_LEN_LANGID_STR_DESC, USB_DESC_TYPE_STRING, LOBYTE(USBD_LANGID_STRING),
HIBYTE(USBD_LANGID_STRING)};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/* Internal string descriptor. */
__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
#if defined(__ICCARM__) /*!< IAR Compiler */
#pragma data_alignment = 4
#endif
__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = {
USB_SIZ_STRING_SERIAL,
USB_DESC_TYPE_STRING,
};
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief Return the device descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
*length = sizeof(USBD_FS_DeviceDesc);
return USBD_FS_DeviceDesc;
}
/**
* @brief Return the LangID string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_LangIDDesc);
return USBD_LangIDDesc;
}
/**
* @brief Return the product string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
} else {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/**
* @brief Return the manufacturer string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
UNUSED(speed);
USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
return USBD_StrDesc;
}
/**
* @brief Return the serial number string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = USB_SIZ_STRING_SERIAL;
/* Update the serial number string descriptor with the data from the unique
* ID */
Get_SerialNum();
/* USER CODE BEGIN USBD_FS_SerialStrDescriptor */
/* USER CODE END USBD_FS_SerialStrDescriptor */
return (uint8_t *)USBD_StringSerial;
}
/**
* @brief Return the configuration string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == USBD_SPEED_HIGH) {
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
/**
* @brief Return the interface string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
#if (USBD_LPM_ENABLED == 1)
/**
* @brief Return the BOS descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_FS_BOSDesc);
return (uint8_t *)USBD_FS_BOSDesc;
}
#endif /* (USBD_LPM_ENABLED == 1) */
/**
* @brief Create the serial number string descriptor
* @param None
* @retval None
*/
static void Get_SerialNum(void)
{
uint32_t deviceserial0, deviceserial1, deviceserial2;
deviceserial0 = DEVICE_ID1;
deviceserial1 = DEVICE_ID2;
deviceserial2 = DEVICE_ID3;
deviceserial0 += deviceserial2;
if (deviceserial0 != 0) {
IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8);
IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4);
}
}
/**
* @brief Convert Hex 32Bits value into char
* @param value: value to convert
* @param pbuf: pointer to the buffer
* @param len: buffer length
* @retval None
*/
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len)
{
uint8_t idx = 0;
for (idx = 0; idx < len; idx++) {
if (((value >> 28)) < 0xA) {
pbuf[2 * idx] = (value >> 28) + '0';
} else {
pbuf[2 * idx] = (value >> 28) + 'A' - 10;
}
value = value << 4;
pbuf[2 * idx + 1] = 0;
}
}
/**
* @}
*/
@@ -0,0 +1,78 @@
/*!
* \file usbd_desc.h
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_DESC__C__
#define __USBD_DESC__C__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Exported_Constants USBD_DESC_Exported_Constants
* @brief Constants.
* @{
*/
#define VID_VAL 0x0483
#define LANG_ID_STR 0x0409
#define PID_FS_VAL 0x572a
#define DEVICE_ID1 0x20220000
#define DEVICE_ID2 0x1A0000
#define DEVICE_ID3 0x0902
#define DEV_CLASS 0x00
#define DEV_SUB_CLASS 0x00
#define DEV_PROTOCOL 0x00
#define USB_SIZ_STRING_SERIAL 0x1A
/**
* @}
*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/** Descriptor for the Usb device. */
extern USBD_DescriptorsTypeDef FS_Desc;
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_DESC__C__ */
@@ -0,0 +1,245 @@
/*!
* \file msc_flash.c
*
* \brief Target fatfs flash implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_msc_flash.h"
/*------------------------------------------------------------------------------------
Local Variables
------------------------------------------------------------------------------------*/
uint8_t spim_init = false;
#define FLASH_SECTOR_ALIGN(address) \
((uint32_t)(address) & ~(FAT_FLASH_SECTOR_SIZE - 1))
#define FLASH_SECTOR_OFFSET(address) \
((uint32_t)(address) & (FAT_FLASH_SECTOR_SIZE - 1))
/*------------------------------------------------------------------------------------
Functions
------------------------------------------------------------------------------------*/
/**
* @brief FatFs flash read id
* @param void
* @retval uint32_t - id
*/
uint32_t Fat_Flash_ReadID(void)
{
uint32_t id = 0;
xc_fmc_spi_flash_rdid((uint8_t *)&id);
DEBUG("read id :0x%08x\r\n", id);
return id;
}
/**
* @brief FatFs flash chip erase
* @param void
* @retval bool - true or false
*/
bool Fat_Flash_ChipErase(void)
{
uint32_t offset_cnt = (FAT_FLASH_END_ADDR - FAT_FLASH_START_ADDR + 1) / FAT_FLASH_SECTOR_SIZE;
for (uint32_t i = 0; i < offset_cnt; i++) {
xc_fmc_spi_flash_erase_sector(FAT_FLASH_START_ADDR + i * FAT_FLASH_SECTOR_SIZE);
}
return true;
}
/**
* @brief FatFs flash sector erase
* @param void
* @retval bool - true or false
*/
bool Fat_Flash_SectorErase(uint32_t address)
{
xc_fmc_spi_flash_erase_sector(address);
return true;
}
/**
* @brief FatFs flash write data
* @param void
* @retval bool - true or false
*/
bool Fat_Flash_WriteData(uint32_t address, uint8_t *buffer, uint16_t length)
{
uint16_t writeLen, pageOff;
while (length > 0) {
pageOff = FLASH_PAGE_SIZE - (address % FLASH_PAGE_SIZE);
writeLen = length > pageOff ? pageOff : length;
xc_fmc_spi_flash_write(address, buffer, writeLen);
length -= writeLen;
address += writeLen;
buffer += writeLen;
}
return true;
}
/**
* @brief FatFs flash read data
* @param void
* @retval bool - true or false
*/
bool Fat_Flash_ReadData(uint32_t address, uint8_t *buffer, uint16_t length)
{
xc_fmc_spi_flash_read(address, buffer, length);
return true;
}
/**
* @brief FatFs flash data are write in units of 512 bytes
* @param void
* @retval bool - true or false
*/
bool Fat_Flash_Write_512B(uint32_t address, uint8_t count, uint8_t *data)
{
uint32_t write_addr;
uint32_t size;
write_addr = address + FAT_FLASH_START_ADDR;
size = count * DISK_UNIT_SIZE;
if(write_addr >= FAT_FLASH_END_ADDR)
{
return false;
}
xc_fmc_spi_flash_write(write_addr, data, size);
return true;
}
/**
* @brief FatFs flash data are read in units of 512 bytes
* @param void
* @retval bool - true or false
*/
bool Fat_Flash_Read_512B(uint32_t address, uint8_t count, uint8_t *data)
{
uint32_t read_addr;
uint32_t size;
read_addr = address + FAT_FLASH_START_ADDR;
size = count * DISK_UNIT_SIZE;
if (read_addr >= FAT_FLASH_END_ADDR)
return false;
xc_fmc_spi_flash_read(read_addr, data, size);
return true;
}
/*----------------------------- Disk Map -----------------------------------*/
/**
* @brief Disk init
* @param void
* @retval bool - true or false
*/
bool Disk_Init(void)
{
//xc_fmc_spi_init_oprt();
return true;
}
/**
* @brief Disk erase
* @param void
* @retval bool - true or false
*/
bool Disk_Erase(void)
{
if (true == Fat_Flash_ChipErase())
return true;
return false;
}
/**
* @brief Disk unit size
* @param void
* @retval uint16_t - size
*/
uint16_t Disk_UnitSize(void)
{
return DISK_UNIT_SIZE;
}
/**
* @brief Disk unit count
* @param void
* @retval uint32_t - count
*/
uint32_t Disk_UnitCount(void)
{
uint32_t count = 0;
count = (FAT_FLASH_END_ADDR - FAT_FLASH_START_ADDR + 1) / DISK_UNIT_SIZE;
return count;
}
/**
* @brief Disk unit data read
* @param void
* @retval bool - true or false
*/
bool Disk_UnitRead(uint32_t unitAddr, uint16_t unitCount, uint8_t *data)
{
if (true != Fat_Flash_Read_512B(unitAddr * DISK_UNIT_SIZE, unitCount, data))
{
return false;
}
return true;
}
/**
* @brief Disk unit data write
* @param void
* @retval bool - true or false
*/
bool Disk_UnitWrite(uint32_t unitAddr, uint16_t unitCount, uint8_t *data)
{
if (true != Fat_Flash_Write_512B(unitAddr * DISK_UNIT_SIZE, unitCount, data))
{
return false;
}
return true;
}
/*--------------------------------------------------------------------------*/
@@ -0,0 +1,72 @@
/*!
* \file msc_flash.h
*
* \brief Target msc flash implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_MSC_FLASH_H
#define __USBD_MSC_FLASH_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define FAT_FLASH_ID 0x0010bd00//0x001364c8 //0x12408500 //0x00136085
#define FAT_FLASH_PAGE_SIZE 256U
#define FAT_FLASH_SECTOR_SIZE 4096u
#define FAT_FLASH_START_ADDR 0x10000
#define FAT_FLASH_END_ADDR 0x17800
#define DISK_UNIT_SIZE 512U
/*------------------------------------------------------------------------------------
Exported Functions
------------------------------------------- -----------------------------------------*/
uint32_t Fat_Flash_ReadID( void );
bool Disk_Init( void );
bool Disk_Erase( void );
uint16_t Disk_UnitSize( void );
uint32_t Disk_UnitCount( void );
bool Disk_UnitRead( uint32_t unitAddr, uint16_t unitCount, uint8_t *data );
bool Disk_UnitWrite( uint32_t unitAddr, uint16_t unitCount, uint8_t *data );
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
@@ -0,0 +1,297 @@
/*!
* \file usbd_storage_if.c
*
* \brief Memory management layer.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_storage_if.h"
/* USER CODE BEGIN INCLUDE */
#include "usbd_msc_flash.h"
/* USER CODE END INCLUDE */
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/** @defgroup USBD_STORAGE
* @brief Usb mass storage device module
* @{
*/
/** @defgroup USBD_STORAGE_Private_TypesDefinitions
* @brief Private types.
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Private_Defines
* @brief Private defines.
* @{
*/
#define STORAGE_LUN_NBR 1
#define STORAGE_BLK_NBR 60
#define STORAGE_BLK_SIZ 0x200
/* USER CODE BEGIN PRIVATE_DEFINES */
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Private_Macros
* @brief Private macros.
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Private_Variables
* @brief Private variables.
* @{
*/
/* USER CODE BEGIN INQUIRY_DATA_FS */
/** USB Mass storage Standard Inquiry Data. */
const int8_t STORAGE_Inquirydata_FS[] = {/* 36 */
/* LUN 0 */
0x00,
0x80,
0x02,
0x02,
(STANDARD_INQUIRY_DATA_LEN - 5),
0x00,
0x00,
0x00,
'X', 'i', 'n', 'C', 'h', 'i', 'p', ' ', /* Manufacturer : 8 bytes */
'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product : 16 Bytes */
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
'0', '.', '0' ,'1' /* Version : 4 Bytes */
};
/* USER CODE END INQUIRY_DATA_FS */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Exported_Variables
* @brief Public variables.
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static int8_t STORAGE_Init_FS(uint8_t lun);
static int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
static int8_t STORAGE_IsReady_FS(uint8_t lun);
static int8_t STORAGE_IsWriteProtected_FS(uint8_t lun);
static int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
static int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
static int8_t STORAGE_GetMaxLun_FS(void);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
{
STORAGE_Init_FS,
STORAGE_GetCapacity_FS,
STORAGE_IsReady_FS,
STORAGE_IsWriteProtected_FS,
STORAGE_Read_FS,
STORAGE_Write_FS,
STORAGE_GetMaxLun_FS,
(int8_t *)STORAGE_Inquirydata_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief Initializes the storage unit (medium) over USB FS IP
* @param lun: Logical unit number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Init_FS(uint8_t lun)
{
/* USER CODE BEGIN 2 */
UNUSED(lun);
return (USBD_OK);
/* USER CODE END 2 */
}
/**
* @brief Returns the medium capacity.
* @param lun: Logical unit number.
* @param block_num: Number of total block number.
* @param block_size: Block size.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
/* USER CODE BEGIN 3 */
UNUSED(lun);
*block_num = STORAGE_BLK_NBR;
*block_size = STORAGE_BLK_SIZ;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief Checks whether the medium is ready.
* @param lun: Logical unit number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_IsReady_FS(uint8_t lun)
{
/* USER CODE BEGIN 4 */
UNUSED(lun);
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief Checks whether the medium is write protected.
* @param lun: Logical unit number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_IsWriteProtected_FS(uint8_t lun)
{
/* USER CODE BEGIN 5 */
UNUSED(lun);
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief Reads data from the medium.
* @param lun: Logical unit number.
* @param buf: data buffer.
* @param blk_addr: Logical block address.
* @param blk_len: Blocks number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 6 */
UNUSED(lun);
UNUSED(buf);
UNUSED(blk_addr);
UNUSED(blk_len);
Disk_UnitRead( blk_addr, blk_len, buf );
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief Writes data into the medium.
* @param lun: Logical unit number.
* @param buf: data buffer.
* @param blk_addr: Logical block address.
* @param blk_len: Blocks number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 7 */
UNUSED(lun);
UNUSED(buf);
UNUSED(blk_addr);
UNUSED(blk_len);
Disk_UnitWrite( blk_addr, blk_len, buf );
return (USBD_OK);
/* USER CODE END 7 */
}
/**
* @brief Returns the Max Supported LUNs.
* @param None
* @retval Lun(s) number.
*/
int8_t STORAGE_GetMaxLun_FS(void)
{
/* USER CODE BEGIN 8 */
return (STORAGE_LUN_NBR - 1);
/* USER CODE END 8 */
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,129 @@
/*!
* \file usbd_storage_if.h
*
* \brief Header for usbd_storage_if.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_STORAGE_IF_H__
#define __USBD_STORAGE_IF_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_msc.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @defgroup USBD_STORAGE USBD_STORAGE
* @brief Header file for the usb_storage_if.c file
* @{
*/
/** @defgroup USBD_STORAGE_Exported_Defines USBD_STORAGE_Exported_Defines
* @brief Defines.
* @{
*/
/* USER CODE BEGIN EXPORTED_DEFINES */
/* USER CODE END EXPORTED_DEFINES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Exported_Types USBD_STORAGE_Exported_Types
* @brief Types.
* @{
*/
/* USER CODE BEGIN EXPORTED_TYPES */
/* USER CODE END EXPORTED_TYPES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Exported_Macros USBD_STORAGE_Exported_Macros
* @brief Aliases.
* @{
*/
/* USER CODE BEGIN EXPORTED_MACRO */
/* USER CODE END EXPORTED_MACRO */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Exported_Variables USBD_STORAGE_Exported_Variables
* @brief Public variables.
* @{
*/
/** STORAGE Interface callback. */
extern USBD_StorageTypeDef USBD_Storage_Interface_fops_FS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Exported_FunctionsPrototype USBD_STORAGE_Exported_FunctionsPrototype
* @brief Public functions declaration.
* @{
*/
/* USER CODE BEGIN EXPORTED_FUNCTIONS */
/* USER CODE END EXPORTED_FUNCTIONS */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_STORAGE_IF_H__ */
@@ -0,0 +1,636 @@
/*!
* \file usbd_conf.c
*
* \brief This file implements the board support package for the USB device
* library
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_core.h"
#include "usbd_def.h"
#include "xc_hal_usb.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
PCD_HandleTypeDef hpcd_USB_OTG_FS;
/*------------------------------------------------------------------------------------
Func Prototypes
------------------------------------------------------------------------------------*/
void Error_Handler(void);
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status);
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state
*/
GLOBAL_INT_DISABLE();
while (1) {
}
GLOBAL_INT_RESTORE();
/* USER CODE END Error_Handler_Debug */
}
/*******************************************************************************
LL Driver Callbacks (PCD -> USB Device Library)
*******************************************************************************/
/* MSP Init */
void HAL_PCD_MspInit(PCD_HandleTypeDef *pcdHandle)
{
USB_Phy_Init();
USB_Phy_Enable();
USB_Current_Ctrl(1);
// NVIC_SetPriority(USB_IRQn, 0); // MSC mode do not SET!!!!
USB_Phy_DP_Oprt(PULL_UP);
// HAL_Delay(100); // for(int i = 0; i < 0x455000*2; i++);
NVIC_EnableIRQ(USB_IRQn);
}
/* MSP DeInit */
void HAL_PCD_MspDeInit(PCD_HandleTypeDef *pcdHandle) { USB_Phy_Deinit(); }
/**
* @brief Setup stage callback
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup);
}
/**
* @brief Data Out stage callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
}
/**
* @brief Data In stage callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DataInStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff);
}
/**
* @brief SOF callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Reset callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_SpeedTypeDef speed = USBD_SPEED_FULL;
if ( hpcd->Init.speed == PCD_SPEED_HIGH)
{
speed = USBD_SPEED_HIGH;
}
else if ( hpcd->Init.speed == PCD_SPEED_FULL)
{
speed = USBD_SPEED_FULL;
}
else
{
Error_Handler();
}
/* Set Speed. */
USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed);
/* Reset Device. */
USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Suspend callback.
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
/* Inform USB library that core enters in suspend Mode. */
USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData);
__HAL_PCD_GATE_PHYCLOCK(hpcd);
/* Enter in STOP mode. */
/* USER CODE BEGIN 2 */
if (hpcd->Init.low_power_enable)
{
/* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */
SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
}
/* USER CODE END 2 */
}
/**
* @brief Resume callback.
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief ISOOUTIncomplete callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}
/**
* @brief ISOINIncomplete callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}
/**
* @brief Connect callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Disconnect callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData);
}
/*******************************************************************************
LL Driver Interface (USB Device Library --> PCD)
*******************************************************************************/
/**
* @brief Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
/* Init USB Ip. */
if (pdev->id == DEVICE_FS) {
/* Link the driver to the stack. */
hpcd_USB_OTG_FS.pData = pdev;
pdev->pData = &hpcd_USB_OTG_FS;
hpcd_USB_OTG_FS.Instance = XC_USB_OTG_FS;
hpcd_USB_OTG_FS.Init.dev_endpoints = 2;
hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
hpcd_USB_OTG_FS.Init.dma_enable = DISABLE;
hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
hpcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
hpcd_USB_OTG_FS.Init.low_power_enable = DISABLE;
hpcd_USB_OTG_FS.Init.lpm_enable = DISABLE;
hpcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = DISABLE;
if (HAL_PCD_Init(&hpcd_USB_OTG_FS) != HAL_OK)
{
Error_Handler( );
}
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
/* Register USB PCD CallBacks */
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SOF_CB_ID, PCD_SOFCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SETUPSTAGE_CB_ID, PCD_SetupStageCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESET_CB_ID, PCD_ResetCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SUSPEND_CB_ID, PCD_SuspendCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESUME_CB_ID, PCD_ResumeCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_CONNECT_CB_ID, PCD_ConnectCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_DISCONNECT_CB_ID, PCD_DisconnectCallback);
HAL_PCD_RegisterDataOutStageCallback(&hpcd_USB_OTG_FS, PCD_DataOutStageCallback);
HAL_PCD_RegisterDataInStageCallback(&hpcd_USB_OTG_FS, PCD_DataInStageCallback);
HAL_PCD_RegisterIsoOutIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOOUTIncompleteCallback);
HAL_PCD_RegisterIsoInIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOINIncompleteCallback);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x40);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x10);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 2, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 3, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 4, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 5, 0x10);
}
return USBD_OK;
}
/**
* @brief De-Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_DeInit(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Starts the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Start(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Stops the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Stop(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Opens an endpoint of the low level driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param ep_type: Endpoint type
* @param ep_mps: Endpoint max packet size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Closes an endpoint of the low level driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Flushes an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Sets a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Clears a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Returns Stall condition.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval Stall (1: Yes, 0: No)
*/
uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*) pdev->pData;
if((ep_addr & 0x80) == 0x80)
{
return hpcd->IN_ep[ep_addr & 0x7F].is_stall;
}
else
{
return hpcd->OUT_ep[ep_addr & 0x7F].is_stall;
}
}
/**
* @brief Assigns a USB address to the device.
* @param pdev: Device handle
* @param dev_addr: Device address
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Transmits data over an endpoint.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param pbuf: Pointer to data to be sent
* @param size: Data size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Prepares an endpoint for reception.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param pbuf: Pointer to data to be received
* @param size: Data size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Returns the last transferred packet size.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval Received Data Size
*/
uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef*) pdev->pData, ep_addr);
}
#ifdef USBD_HS_TESTMODE_ENABLE
/**
* @brief Set High speed Test mode.
* @param pdev: Device handle
* @param testmode: test mode
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_SetTestMode(USBD_HandleTypeDef *pdev, uint8_t testmode)
{
UNUSED(pdev);
UNUSED(testmode);
return USBD_OK;
}
#endif /* USBD_HS_TESTMODE_ENABLE */
/**
* @brief Static single allocation.
* @param size: Size of allocated memory
* @retval None
*/
void *USBD_static_malloc(uint32_t size)
{
return NULL;
}
/**
* @brief Dummy memory free
* @param p: Pointer to allocated memory address
* @retval None
*/
void USBD_static_free(void *p)
{
}
/**
* @brief Delays routine for the USB Device Library.
* @param Delay: Delay in ms
* @retval None
*/
void USBD_LL_Delay(uint32_t Delay)
{
HAL_Delay(Delay);
}
/**
* @brief Returns the USB status depending on the HAL status:
* @param hal_status: HAL status
* @retval USB status
*/
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status)
{
USBD_StatusTypeDef usb_status = USBD_OK;
switch (hal_status)
{
case HAL_OK :
usb_status = USBD_OK;
break;
case HAL_ERROR :
usb_status = USBD_FAIL;
break;
case HAL_BUSY :
usb_status = USBD_BUSY;
break;
case HAL_TIMEOUT :
usb_status = USBD_FAIL;
break;
default :
usb_status = USBD_FAIL;
break;
}
return usb_status;
}
@@ -0,0 +1,173 @@
/*!
* \file usbd_conf.h
*
* \brief Header for usbd_conf.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CONF__H
#define __USBD_CONF__H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xc6xxx.h"
/* USER CODE BEGIN INCLUDE */
// user config
#define USBD_CALSS_MSC_ENABLE 1
#define USBD_COMPOSITE_USE_IAD 0
#define USBD_CMPSIT_ACTIVATE_HID_MOUSE 0
#define USBD_CMPSIT_ACTIVATE_HID_KEYBOARD 0
#define USBD_CMPSIT_ACTIVATE_HID_CUSTOM 0
#define USBD_CMPSIT_ACTIVATE_CDC 0
#define USBD_CMPSIT_ACTIVATE_DFU 0
/* USER CODE END INCLUDE */
/** @addtogroup USBD_OTG_DRIVER
* @brief Driver for Usb device.
* @{
*/
/** @defgroup USBD_CONF USBD_CONF
* @brief Configuration file for Usb otg low level driver.
* @{
*/
/** @defgroup USBD_CONF_Exported_Variables USBD_CONF_Exported_Variables
* @brief Public variables.
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines
* @brief Defines for configuration of the Usb device.
* @{
*/
/*---------- -----------*/
#define USBD_MAX_NUM_INTERFACES 5U
/*---------- -----------*/
#define USBD_MAX_NUM_CONFIGURATION 1U
/*---------- -----------*/
#define USBD_MAX_STR_DESC_SIZ 512U
/*---------- -----------*/
#define USBD_DEBUG_LEVEL 0U
/*---------- -----------*/
#define USBD_LPM_ENABLED 0U
/*---------- -----------*/
#define USBD_SELF_POWERED 1U
/****************************************/
/* #define for FS and HS identification */
#define DEVICE_FS 1
#define DEVICE_HS 0
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Macros USBD_CONF_Exported_Macros
* @brief Aliases.
* @{
*/
/* Memory management macros make sure to use static memory allocation */
/** Alias for memory allocation. */
#define USBD_malloc malloc
/** Alias for memory release. */
#define USBD_free free
/** Alias for memory set. */
#define USBD_memset memset
/** Alias for memory copy. */
#define USBD_memcpy memcpy
/** Alias for delay. */
#define USBD_Delay HAL_Delay
/* DEBUG macros */
#if (USBD_DEBUG_LEVEL > 0)
#define USBD_UsrLog(...) printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_UsrLog(...)
#endif /* (USBD_DEBUG_LEVEL > 0U) */
#if (USBD_DEBUG_LEVEL > 1)
#define USBD_ErrLog(...) printf("ERROR: ");\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_ErrLog(...)
#endif /* (USBD_DEBUG_LEVEL > 1U) */
#if (USBD_DEBUG_LEVEL > 2)
#define USBD_DbgLog(...) printf("DEBUG : ");\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_DbgLog(...)
#endif /* (USBD_DEBUG_LEVEL > 2U) */
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void *USBD_static_malloc(uint32_t size);
void USBD_static_free(void *p);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CONF__H__ */
@@ -0,0 +1,636 @@
/*!
* \file usbd_conf.c
*
* \brief This file implements the board support package for the USB device
* library
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_core.h"
#include "usbd_def.h"
#include "xc_hal_usb.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
PCD_HandleTypeDef hpcd_USB_OTG_FS;
/*------------------------------------------------------------------------------------
Func Prototypes
------------------------------------------------------------------------------------*/
void Error_Handler(void);
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status);
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state
*/
GLOBAL_INT_DISABLE();
while (1) {
}
GLOBAL_INT_RESTORE();
/* USER CODE END Error_Handler_Debug */
}
/*******************************************************************************
LL Driver Callbacks (PCD -> USB Device Library)
*******************************************************************************/
/* MSP Init */
void HAL_PCD_MspInit(PCD_HandleTypeDef *pcdHandle)
{
USB_Phy_Init();
USB_Phy_Enable();
USB_Current_Ctrl(1);
// NVIC_SetPriority(USB_IRQn, 0); // MSC mode do not SET!!!!
USB_Phy_DP_Oprt(PULL_UP);
// HAL_Delay(100); // for(int i = 0; i < 0x455000*2; i++);
NVIC_EnableIRQ(USB_IRQn);
}
/* MSP DeInit */
void HAL_PCD_MspDeInit(PCD_HandleTypeDef *pcdHandle) { USB_Phy_Deinit(); }
/**
* @brief Setup stage callback
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup);
}
/**
* @brief Data Out stage callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
}
/**
* @brief Data In stage callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DataInStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff);
}
/**
* @brief SOF callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Reset callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_SpeedTypeDef speed = USBD_SPEED_FULL;
if ( hpcd->Init.speed == PCD_SPEED_HIGH)
{
speed = USBD_SPEED_HIGH;
}
else if ( hpcd->Init.speed == PCD_SPEED_FULL)
{
speed = USBD_SPEED_FULL;
}
else
{
Error_Handler();
}
/* Set Speed. */
USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed);
/* Reset Device. */
USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Suspend callback.
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
/* Inform USB library that core enters in suspend Mode. */
USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData);
__HAL_PCD_GATE_PHYCLOCK(hpcd);
/* Enter in STOP mode. */
/* USER CODE BEGIN 2 */
if (hpcd->Init.low_power_enable)
{
/* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */
SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
}
/* USER CODE END 2 */
}
/**
* @brief Resume callback.
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief ISOOUTIncomplete callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}
/**
* @brief ISOINIncomplete callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}
/**
* @brief Connect callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Disconnect callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData);
}
/*******************************************************************************
LL Driver Interface (USB Device Library --> PCD)
*******************************************************************************/
/**
* @brief Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
/* Init USB Ip. */
if (pdev->id == DEVICE_FS) {
/* Link the driver to the stack. */
hpcd_USB_OTG_FS.pData = pdev;
pdev->pData = &hpcd_USB_OTG_FS;
hpcd_USB_OTG_FS.Instance = XC_USB_OTG_FS;
hpcd_USB_OTG_FS.Init.dev_endpoints = 2;
hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
hpcd_USB_OTG_FS.Init.dma_enable = DISABLE;
hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
hpcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
hpcd_USB_OTG_FS.Init.low_power_enable = DISABLE;
hpcd_USB_OTG_FS.Init.lpm_enable = DISABLE;
hpcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = DISABLE;
if (HAL_PCD_Init(&hpcd_USB_OTG_FS) != HAL_OK)
{
Error_Handler( );
}
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
/* Register USB PCD CallBacks */
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SOF_CB_ID, PCD_SOFCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SETUPSTAGE_CB_ID, PCD_SetupStageCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESET_CB_ID, PCD_ResetCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SUSPEND_CB_ID, PCD_SuspendCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESUME_CB_ID, PCD_ResumeCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_CONNECT_CB_ID, PCD_ConnectCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_DISCONNECT_CB_ID, PCD_DisconnectCallback);
HAL_PCD_RegisterDataOutStageCallback(&hpcd_USB_OTG_FS, PCD_DataOutStageCallback);
HAL_PCD_RegisterDataInStageCallback(&hpcd_USB_OTG_FS, PCD_DataInStageCallback);
HAL_PCD_RegisterIsoOutIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOOUTIncompleteCallback);
HAL_PCD_RegisterIsoInIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOINIncompleteCallback);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x40);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x10);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 2, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 3, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 4, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 5, 0x10);
}
return USBD_OK;
}
/**
* @brief De-Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_DeInit(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Starts the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Start(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Stops the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Stop(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Opens an endpoint of the low level driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param ep_type: Endpoint type
* @param ep_mps: Endpoint max packet size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Closes an endpoint of the low level driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Flushes an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Sets a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Clears a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Returns Stall condition.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval Stall (1: Yes, 0: No)
*/
uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*) pdev->pData;
if((ep_addr & 0x80) == 0x80)
{
return hpcd->IN_ep[ep_addr & 0x7F].is_stall;
}
else
{
return hpcd->OUT_ep[ep_addr & 0x7F].is_stall;
}
}
/**
* @brief Assigns a USB address to the device.
* @param pdev: Device handle
* @param dev_addr: Device address
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Transmits data over an endpoint.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param pbuf: Pointer to data to be sent
* @param size: Data size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Prepares an endpoint for reception.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param pbuf: Pointer to data to be received
* @param size: Data size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Returns the last transferred packet size.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval Received Data Size
*/
uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef*) pdev->pData, ep_addr);
}
#ifdef USBD_HS_TESTMODE_ENABLE
/**
* @brief Set High speed Test mode.
* @param pdev: Device handle
* @param testmode: test mode
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_SetTestMode(USBD_HandleTypeDef *pdev, uint8_t testmode)
{
UNUSED(pdev);
UNUSED(testmode);
return USBD_OK;
}
#endif /* USBD_HS_TESTMODE_ENABLE */
/**
* @brief Static single allocation.
* @param size: Size of allocated memory
* @retval None
*/
void *USBD_static_malloc(uint32_t size)
{
}
/**
* @brief Dummy memory free
* @param p: Pointer to allocated memory address
* @retval None
*/
void USBD_static_free(void *p)
{
}
/**
* @brief Delays routine for the USB Device Library.
* @param Delay: Delay in ms
* @retval None
*/
void USBD_LL_Delay(uint32_t Delay)
{
HAL_Delay(Delay);
}
/**
* @brief Returns the USB status depending on the HAL status:
* @param hal_status: HAL status
* @retval USB status
*/
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status)
{
USBD_StatusTypeDef usb_status = USBD_OK;
switch (hal_status)
{
case HAL_OK :
usb_status = USBD_OK;
break;
case HAL_ERROR :
usb_status = USBD_FAIL;
break;
case HAL_BUSY :
usb_status = USBD_BUSY;
break;
case HAL_TIMEOUT :
usb_status = USBD_FAIL;
break;
default :
usb_status = USBD_FAIL;
break;
}
return usb_status;
}
@@ -0,0 +1,174 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : usbd_conf.h
* @version : v1.0_Cube
* @brief : Header for usbd_conf.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CONF__H__
#define __USBD_CONF__H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xc6xxx.h"
/* USER CODE BEGIN INCLUDE */
// user config
#define USBD_CALSS_MSC_ENABLE 1
#define USBD_COMPOSITE_USE_IAD 0
#define USBD_CMPSIT_ACTIVATE_HID_MOUSE 0
#define USBD_CMPSIT_ACTIVATE_HID_KEYBOARD 0
#define USBD_CMPSIT_ACTIVATE_HID_CUSTOM 0
#define USBD_CMPSIT_ACTIVATE_CDC 0
#define USBD_CMPSIT_ACTIVATE_DFU 0
/* USER CODE END INCLUDE */
/** @addtogroup USBD_OTG_DRIVER
* @brief Driver for Usb device.
* @{
*/
/** @defgroup USBD_CONF USBD_CONF
* @brief Configuration file for Usb otg low level driver.
* @{
*/
/** @defgroup USBD_CONF_Exported_Variables USBD_CONF_Exported_Variables
* @brief Public variables.
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines
* @brief Defines for configuration of the Usb device.
* @{
*/
/*---------- -----------*/
#define USBD_MAX_NUM_INTERFACES 5U
/*---------- -----------*/
#define USBD_MAX_NUM_CONFIGURATION 1U
/*---------- -----------*/
#define USBD_MAX_STR_DESC_SIZ 512U
/*---------- -----------*/
#define USBD_DEBUG_LEVEL 0U
/*---------- -----------*/
#define USBD_LPM_ENABLED 0U
/*---------- -----------*/
#define USBD_SELF_POWERED 1U
/****************************************/
/* #define for FS and HS identification */
#define DEVICE_FS 1
#define DEVICE_HS 0
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Macros USBD_CONF_Exported_Macros
* @brief Aliases.
* @{
*/
/* Memory management macros make sure to use static memory allocation */
/** Alias for memory allocation. */
#define USBD_malloc malloc
/** Alias for memory release. */
#define USBD_free free
/** Alias for memory set. */
#define USBD_memset memset
/** Alias for memory copy. */
#define USBD_memcpy memcpy
/** Alias for delay. */
#define USBD_Delay HAL_Delay
/* DEBUG macros */
#if (USBD_DEBUG_LEVEL > 0)
#define USBD_UsrLog(...) printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_UsrLog(...)
#endif /* (USBD_DEBUG_LEVEL > 0U) */
#if (USBD_DEBUG_LEVEL > 1)
#define USBD_ErrLog(...) printf("ERROR: ");\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_ErrLog(...)
#endif /* (USBD_DEBUG_LEVEL > 1U) */
#if (USBD_DEBUG_LEVEL > 2)
#define USBD_DbgLog(...) printf("DEBUG : ");\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_DbgLog(...)
#endif /* (USBD_DEBUG_LEVEL > 2U) */
#if USB_HID
#define HID_MOUSE 0x01
#define HID_KEYBOARD 0x02
#define HID_CUSTOM 0x04
#define HID_DOUBLE_CUSTOM 0X08
#define HID_CLASS_MODE HID_KEYBOARD
#endif
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void *USBD_static_malloc(uint32_t size);
void USBD_static_free(void *p);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CONF__H__ */
@@ -0,0 +1,632 @@
/*!
* \file usbd_conf.c
*
* \brief This file implements the board support package for the USB device
* library
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_core.h"
#include "usbd_def.h"
#include "xc_hal_usb.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
PCD_HandleTypeDef hpcd_USB_OTG_FS;
/*------------------------------------------------------------------------------------
Func Prototypes
------------------------------------------------------------------------------------*/
void Error_Handler(void);
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status);
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state
*/
GLOBAL_INT_DISABLE();
while (1) {
}
GLOBAL_INT_RESTORE();
/* USER CODE END Error_Handler_Debug */
}
/*******************************************************************************
LL Driver Callbacks (PCD -> USB Device Library)
*******************************************************************************/
/* MSP Init */
void HAL_PCD_MspInit(PCD_HandleTypeDef *pcdHandle)
{
USB_Phy_Init();
USB_Phy_Enable();
USB_Current_Ctrl(1);
// NVIC_SetPriority(USB_IRQn, 0); // MSC mode do not SET!!!!
USB_Phy_DP_Oprt(PULL_UP);
// HAL_Delay(100); // for(int i = 0; i < 0x455000*2; i++);
NVIC_EnableIRQ(USB_IRQn);
}
/* MSP DeInit */
void HAL_PCD_MspDeInit(PCD_HandleTypeDef *pcdHandle) { USB_Phy_Deinit(); }
/**
* @brief Setup stage callback
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup);
}
/**
* @brief Data Out stage callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
}
/**
* @brief Data In stage callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DataInStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff);
}
/**
* @brief SOF callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Reset callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_SpeedTypeDef speed = USBD_SPEED_FULL;
if ( hpcd->Init.speed == PCD_SPEED_HIGH)
{
speed = USBD_SPEED_HIGH;
}
else if ( hpcd->Init.speed == PCD_SPEED_FULL)
{
speed = USBD_SPEED_FULL;
}
else
{
Error_Handler();
}
/* Set Speed. */
USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed);
/* Reset Device. */
USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Suspend callback.
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
/* Inform USB library that core enters in suspend Mode. */
USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData);
__HAL_PCD_GATE_PHYCLOCK(hpcd);
/* Enter in STOP mode. */
/* USER CODE BEGIN 2 */
if (hpcd->Init.low_power_enable)
{
/* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */
SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
}
/* USER CODE END 2 */
}
/**
* @brief Resume callback.
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief ISOOUTIncomplete callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}
/**
* @brief ISOINIncomplete callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}
/**
* @brief Connect callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Disconnect callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData);
}
/*******************************************************************************
LL Driver Interface (USB Device Library --> PCD)
*******************************************************************************/
/**
* @brief Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
/* Init USB Ip. */
if (pdev->id == DEVICE_FS) {
/* Link the driver to the stack. */
hpcd_USB_OTG_FS.pData = pdev;
pdev->pData = &hpcd_USB_OTG_FS;
hpcd_USB_OTG_FS.Instance = XC_USB_OTG_FS;
hpcd_USB_OTG_FS.Init.dev_endpoints = 3;
hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
hpcd_USB_OTG_FS.Init.dma_enable = DISABLE;
hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
hpcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
hpcd_USB_OTG_FS.Init.low_power_enable = DISABLE;
hpcd_USB_OTG_FS.Init.lpm_enable = DISABLE;
hpcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = DISABLE;
if (HAL_PCD_Init(&hpcd_USB_OTG_FS) != HAL_OK)
{
Error_Handler( );
}
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
/* Register USB PCD CallBacks */
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SOF_CB_ID, PCD_SOFCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SETUPSTAGE_CB_ID, PCD_SetupStageCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESET_CB_ID, PCD_ResetCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SUSPEND_CB_ID, PCD_SuspendCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESUME_CB_ID, PCD_ResumeCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_CONNECT_CB_ID, PCD_ConnectCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_DISCONNECT_CB_ID, PCD_DisconnectCallback);
HAL_PCD_RegisterDataOutStageCallback(&hpcd_USB_OTG_FS, PCD_DataOutStageCallback);
HAL_PCD_RegisterDataInStageCallback(&hpcd_USB_OTG_FS, PCD_DataInStageCallback);
HAL_PCD_RegisterIsoOutIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOOUTIncompleteCallback);
HAL_PCD_RegisterIsoInIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOINIncompleteCallback);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x30);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x20);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x10);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 2, 0x10);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 3, 0x10);
}
return USBD_OK;
}
/**
* @brief De-Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_DeInit(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Starts the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Start(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Stops the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Stop(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Opens an endpoint of the low level driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param ep_type: Endpoint type
* @param ep_mps: Endpoint max packet size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Closes an endpoint of the low level driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Flushes an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Sets a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Clears a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Returns Stall condition.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval Stall (1: Yes, 0: No)
*/
uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*) pdev->pData;
if((ep_addr & 0x80) == 0x80)
{
return hpcd->IN_ep[ep_addr & 0x7F].is_stall;
}
else
{
return hpcd->OUT_ep[ep_addr & 0x7F].is_stall;
}
}
/**
* @brief Assigns a USB address to the device.
* @param pdev: Device handle
* @param dev_addr: Device address
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Transmits data over an endpoint.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param pbuf: Pointer to data to be sent
* @param size: Data size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Prepares an endpoint for reception.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param pbuf: Pointer to data to be received
* @param size: Data size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Returns the last transferred packet size.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval Received Data Size
*/
uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef*) pdev->pData, ep_addr);
}
#ifdef USBD_HS_TESTMODE_ENABLE
/**
* @brief Set High speed Test mode.
* @param pdev: Device handle
* @param testmode: test mode
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_SetTestMode(USBD_HandleTypeDef *pdev, uint8_t testmode)
{
UNUSED(pdev);
UNUSED(testmode);
return USBD_OK;
}
#endif /* USBD_HS_TESTMODE_ENABLE */
/**
* @brief Static single allocation.
* @param size: Size of allocated memory
* @retval None
*/
void *USBD_static_malloc(uint32_t size)
{
return NULL;
}
/**
* @brief Dummy memory free
* @param p: Pointer to allocated memory address
* @retval None
*/
void USBD_static_free(void *p)
{
}
/**
* @brief Delays routine for the USB Device Library.
* @param Delay: Delay in ms
* @retval None
*/
void USBD_LL_Delay(uint32_t Delay)
{
HAL_Delay(Delay);
}
/**
* @brief Returns the USB status depending on the HAL status:
* @param hal_status: HAL status
* @retval USB status
*/
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status)
{
USBD_StatusTypeDef usb_status = USBD_OK;
switch (hal_status)
{
case HAL_OK :
usb_status = USBD_OK;
break;
case HAL_ERROR :
usb_status = USBD_FAIL;
break;
case HAL_BUSY :
usb_status = USBD_BUSY;
break;
case HAL_TIMEOUT :
usb_status = USBD_FAIL;
break;
default :
usb_status = USBD_FAIL;
break;
}
return usb_status;
}
@@ -0,0 +1,169 @@
/*!
* \file usbd_conf.h
*
* \brief Header for usbd_conf.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CONF__H
#define __USBD_CONF__H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xc6xxx.h"
/* USER CODE BEGIN INCLUDE */
// user config
#define USBD_COMPOSITE_USE_IAD 0
#define USBD_CMPSIT_ACTIVATE_HID_MOUSE 1
#define USBD_CMPSIT_ACTIVATE_HID_KEYBOARD 1
#define USBD_CMPSIT_ACTIVATE_HID_CUSTOM 1
#define USBD_CMPSIT_ACTIVATE_CDC 0
#define USBD_CMPSIT_ACTIVATE_DFU 0
/* USER CODE END INCLUDE */
/** @addtogroup USBD_OTG_DRIVER
* @brief Driver for Usb device.
* @{
*/
/** @defgroup USBD_CONF USBD_CONF
* @brief Configuration file for Usb otg low level driver.
* @{
*/
/** @defgroup USBD_CONF_Exported_Variables USBD_CONF_Exported_Variables
* @brief Public variables.
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines
* @brief Defines for configuration of the Usb device.
* @{
*/
/*---------- -----------*/
#define USBD_MAX_NUM_INTERFACES 5U
/*---------- -----------*/
#define USBD_MAX_NUM_CONFIGURATION 1U
/*---------- -----------*/
#define USBD_MAX_STR_DESC_SIZ 512U
/*---------- -----------*/
#define USBD_DEBUG_LEVEL 0U
/*---------- -----------*/
#define USBD_LPM_ENABLED 0U
/*---------- -----------*/
#define USBD_SELF_POWERED 1U
/****************************************/
/* #define for FS and HS identification */
#define DEVICE_FS 1
#define DEVICE_HS 0
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Macros USBD_CONF_Exported_Macros
* @brief Aliases.
* @{
*/
/* Memory management macros make sure to use static memory allocation */
/** Alias for memory allocation. */
#define USBD_malloc malloc
/** Alias for memory release. */
#define USBD_free free
/** Alias for memory set. */
#define USBD_memset memset
/** Alias for memory copy. */
#define USBD_memcpy memcpy
/** Alias for delay. */
#define USBD_Delay HAL_Delay
/* DEBUG macros */
#if (USBD_DEBUG_LEVEL > 0)
#define USBD_UsrLog(...) printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_UsrLog(...)
#endif /* (USBD_DEBUG_LEVEL > 0U) */
#if (USBD_DEBUG_LEVEL > 1)
#define USBD_ErrLog(...) printf("ERROR: ");\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_ErrLog(...)
#endif /* (USBD_DEBUG_LEVEL > 1U) */
#if (USBD_DEBUG_LEVEL > 2)
#define USBD_DbgLog(...) printf("DEBUG : ");\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_DbgLog(...)
#endif /* (USBD_DEBUG_LEVEL > 2U) */
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void *USBD_static_malloc(uint32_t size);
void USBD_static_free(void *p);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CONF__H__ */
@@ -0,0 +1,634 @@
/*!
* \file usbd_conf.c
*
* \brief This file implements the board support package for the USB device
* library
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_core.h"
#include "usbd_def.h"
#include "xc_hal_usb.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
PCD_HandleTypeDef hpcd_USB_OTG_FS;
/*------------------------------------------------------------------------------------
Func Prototypes
------------------------------------------------------------------------------------*/
void Error_Handler(void);
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status);
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state
*/
GLOBAL_INT_DISABLE();
while (1) {
}
GLOBAL_INT_RESTORE();
/* USER CODE END Error_Handler_Debug */
}
/*******************************************************************************
LL Driver Callbacks (PCD -> USB Device Library)
*******************************************************************************/
/* MSP Init */
void HAL_PCD_MspInit(PCD_HandleTypeDef *pcdHandle)
{
USB_Phy_Init();
USB_Phy_Enable();
USB_Current_Ctrl(1);
// NVIC_SetPriority(USB_IRQn, 0); // MSC mode do not SET!!!!
USB_Phy_DP_Oprt(PULL_UP);
HAL_Delay(100); // for(int i = 0; i < 0x455000*2; i++);
NVIC_EnableIRQ(USB_IRQn);
}
/* MSP DeInit */
void HAL_PCD_MspDeInit(PCD_HandleTypeDef *pcdHandle) { USB_Phy_Deinit(); }
/**
* @brief Setup stage callback
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup);
}
/**
* @brief Data Out stage callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
}
/**
* @brief Data In stage callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DataInStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff);
}
/**
* @brief SOF callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Reset callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_SpeedTypeDef speed = USBD_SPEED_FULL;
if ( hpcd->Init.speed == PCD_SPEED_HIGH)
{
speed = USBD_SPEED_HIGH;
}
else if ( hpcd->Init.speed == PCD_SPEED_FULL)
{
speed = USBD_SPEED_FULL;
}
else
{
Error_Handler();
}
/* Set Speed. */
USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed);
/* Reset Device. */
USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Suspend callback.
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
/* Inform USB library that core enters in suspend Mode. */
USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData);
__HAL_PCD_GATE_PHYCLOCK(hpcd);
/* Enter in STOP mode. */
/* USER CODE BEGIN 2 */
if (hpcd->Init.low_power_enable)
{
/* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */
SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
}
/* USER CODE END 2 */
}
/**
* @brief Resume callback.
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief ISOOUTIncomplete callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}
/**
* @brief ISOINIncomplete callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}
/**
* @brief Connect callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Disconnect callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData);
}
/*******************************************************************************
LL Driver Interface (USB Device Library --> PCD)
*******************************************************************************/
/**
* @brief Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
/* Init USB Ip. */
if (pdev->id == DEVICE_FS) {
/* Link the driver to the stack. */
hpcd_USB_OTG_FS.pData = pdev;
pdev->pData = &hpcd_USB_OTG_FS;
hpcd_USB_OTG_FS.Instance = XC_USB_OTG_FS;
hpcd_USB_OTG_FS.Init.dev_endpoints = 5;
hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
hpcd_USB_OTG_FS.Init.dma_enable = DISABLE;
hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
hpcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
hpcd_USB_OTG_FS.Init.low_power_enable = DISABLE;
hpcd_USB_OTG_FS.Init.lpm_enable = DISABLE;
hpcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = DISABLE;
if (HAL_PCD_Init(&hpcd_USB_OTG_FS) != HAL_OK)
{
Error_Handler( );
}
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
/* Register USB PCD CallBacks */
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SOF_CB_ID, PCD_SOFCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SETUPSTAGE_CB_ID, PCD_SetupStageCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESET_CB_ID, PCD_ResetCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SUSPEND_CB_ID, PCD_SuspendCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESUME_CB_ID, PCD_ResumeCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_CONNECT_CB_ID, PCD_ConnectCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_DISCONNECT_CB_ID, PCD_DisconnectCallback);
HAL_PCD_RegisterDataOutStageCallback(&hpcd_USB_OTG_FS, PCD_DataOutStageCallback);
HAL_PCD_RegisterDataInStageCallback(&hpcd_USB_OTG_FS, PCD_DataInStageCallback);
HAL_PCD_RegisterIsoOutIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOOUTIncompleteCallback);
HAL_PCD_RegisterIsoInIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOINIncompleteCallback);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x40);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x10);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x10);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 2, 0x10);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 3, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 4, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 5, 0x10);
}
return USBD_OK;
}
/**
* @brief De-Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_DeInit(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Starts the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Start(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Stops the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Stop(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Opens an endpoint of the low level driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param ep_type: Endpoint type
* @param ep_mps: Endpoint max packet size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Closes an endpoint of the low level driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Flushes an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Sets a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Clears a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Returns Stall condition.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval Stall (1: Yes, 0: No)
*/
uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*) pdev->pData;
if((ep_addr & 0x80) == 0x80)
{
return hpcd->IN_ep[ep_addr & 0x7F].is_stall;
}
else
{
return hpcd->OUT_ep[ep_addr & 0x7F].is_stall;
}
}
/**
* @brief Assigns a USB address to the device.
* @param pdev: Device handle
* @param dev_addr: Device address
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Transmits data over an endpoint.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param pbuf: Pointer to data to be sent
* @param size: Data size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Prepares an endpoint for reception.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param pbuf: Pointer to data to be received
* @param size: Data size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Returns the last transferred packet size.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval Received Data Size
*/
uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef*) pdev->pData, ep_addr);
}
#ifdef USBD_HS_TESTMODE_ENABLE
/**
* @brief Set High speed Test mode.
* @param pdev: Device handle
* @param testmode: test mode
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_SetTestMode(USBD_HandleTypeDef *pdev, uint8_t testmode)
{
UNUSED(pdev);
UNUSED(testmode);
return USBD_OK;
}
#endif /* USBD_HS_TESTMODE_ENABLE */
/**
* @brief Static single allocation.
* @param size: Size of allocated memory
* @retval None
*/
void *USBD_static_malloc(uint32_t size)
{
return NULL;
}
/**
* @brief Dummy memory free
* @param p: Pointer to allocated memory address
* @retval None
*/
void USBD_static_free(void *p)
{
}
/**
* @brief Delays routine for the USB Device Library.
* @param Delay: Delay in ms
* @retval None
*/
void USBD_LL_Delay(uint32_t Delay)
{
HAL_Delay(Delay);
}
/**
* @brief Returns the USB status depending on the HAL status:
* @param hal_status: HAL status
* @retval USB status
*/
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status)
{
USBD_StatusTypeDef usb_status = USBD_OK;
switch (hal_status)
{
case HAL_OK :
usb_status = USBD_OK;
break;
case HAL_ERROR :
usb_status = USBD_FAIL;
break;
case HAL_BUSY :
usb_status = USBD_BUSY;
break;
case HAL_TIMEOUT :
usb_status = USBD_FAIL;
break;
default :
usb_status = USBD_FAIL;
break;
}
return usb_status;
}
@@ -0,0 +1,167 @@
/*!
* \file usbd_conf.h
*
* \brief Header for usbd_conf.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CONF__H
#define __USBD_CONF__H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xc6xxx.h"
/* USER CODE BEGIN INCLUDE */
#define USBD_COMPOSITE_USE_IAD 0
#define USBD_CMPSIT_ACTIVATE_HID_MOUSE 0
#define USBD_CMPSIT_ACTIVATE_HID_KEYBOARD 0
#define USBD_CMPSIT_ACTIVATE_HID_CUSTOM 0
#define USBD_CMPSIT_ACTIVATE_CDC 0
#define USBD_CMPSIT_ACTIVATE_DFU 0
/* USER CODE END INCLUDE */
/** @addtogroup USBD_OTG_DRIVER
* @brief Driver for Usb device.
* @{
*/
/** @defgroup USBD_CONF USBD_CONF
* @brief Configuration file for Usb otg low level driver.
* @{
*/
/** @defgroup USBD_CONF_Exported_Variables USBD_CONF_Exported_Variables
* @brief Public variables.
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines
* @brief Defines for configuration of the Usb device.
* @{
*/
/*---------- -----------*/
#define USBD_MAX_NUM_INTERFACES 5U
/*---------- -----------*/
#define USBD_MAX_NUM_CONFIGURATION 1U
/*---------- -----------*/
#define USBD_MAX_STR_DESC_SIZ 512U
/*---------- -----------*/
#define USBD_DEBUG_LEVEL 0U
/*---------- -----------*/
#define USBD_LPM_ENABLED 0U
/*---------- -----------*/
#define USBD_SELF_POWERED 1U
/****************************************/
/* #define for FS and HS identification */
#define DEVICE_FS 1
#define DEVICE_HS 0
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Macros USBD_CONF_Exported_Macros
* @brief Aliases.
* @{
*/
/* Memory management macros make sure to use static memory allocation */
/** Alias for memory allocation. */
#define USBD_malloc malloc
/** Alias for memory release. */
#define USBD_free free
/** Alias for memory set. */
#define USBD_memset memset
/** Alias for memory copy. */
#define USBD_memcpy memcpy
/** Alias for delay. */
#define USBD_Delay HAL_Delay
/* DEBUG macros */
#if (USBD_DEBUG_LEVEL > 0)
#define USBD_UsrLog(...) printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_UsrLog(...)
#endif /* (USBD_DEBUG_LEVEL > 0U) */
#if (USBD_DEBUG_LEVEL > 1)
#define USBD_ErrLog(...) printf("ERROR: ");\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_ErrLog(...)
#endif /* (USBD_DEBUG_LEVEL > 1U) */
#if (USBD_DEBUG_LEVEL > 2)
#define USBD_DbgLog(...) printf("DEBUG : ");\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_DbgLog(...)
#endif /* (USBD_DEBUG_LEVEL > 2U) */
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void *USBD_static_malloc(uint32_t size);
void USBD_static_free(void *p);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CONF__H__ */
@@ -0,0 +1,635 @@
/*!
* \file usbd_conf.c
*
* \brief This file implements the board support package for the USB device
* library
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_core.h"
#include "usbd_def.h"
#include "xc_hal_usb.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
PCD_HandleTypeDef hpcd_USB_OTG_FS;
/*------------------------------------------------------------------------------------
Func Prototypes
------------------------------------------------------------------------------------*/
void Error_Handler(void);
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status);
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state
*/
GLOBAL_INT_DISABLE();
while (1) {
}
GLOBAL_INT_RESTORE();
/* USER CODE END Error_Handler_Debug */
}
/*******************************************************************************
LL Driver Callbacks (PCD -> USB Device Library)
*******************************************************************************/
/* MSP Init */
void HAL_PCD_MspInit(PCD_HandleTypeDef *pcdHandle)
{
USB_Phy_Init();
USB_Phy_Enable();
USB_Current_Ctrl(1);
// NVIC_SetPriority(USB_IRQn, 0); // MSC mode do not SET!!!!
USB_Phy_DP_Oprt(PULL_UP);
HAL_Delay(100); // for(int i = 0; i < 0x455000*2; i++);
NVIC_EnableIRQ(USB_IRQn);
}
/* MSP DeInit */
void HAL_PCD_MspDeInit(PCD_HandleTypeDef *pcdHandle) { USB_Phy_Deinit(); }
/**
* @brief Setup stage callback
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup);
}
/**
* @brief Data Out stage callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
}
/**
* @brief Data In stage callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DataInStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff);
}
/**
* @brief SOF callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Reset callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_SpeedTypeDef speed = USBD_SPEED_FULL;
if ( hpcd->Init.speed == PCD_SPEED_HIGH)
{
speed = USBD_SPEED_HIGH;
}
else if ( hpcd->Init.speed == PCD_SPEED_FULL)
{
speed = USBD_SPEED_FULL;
}
else
{
Error_Handler();
}
/* Set Speed. */
USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed);
/* Reset Device. */
USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Suspend callback.
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
/* Inform USB library that core enters in suspend Mode. */
USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData);
__HAL_PCD_GATE_PHYCLOCK(hpcd);
/* Enter in STOP mode. */
/* USER CODE BEGIN 2 */
if (hpcd->Init.low_power_enable)
{
/* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */
SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
}
/* USER CODE END 2 */
}
/**
* @brief Resume callback.
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief ISOOUTIncomplete callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}
/**
* @brief ISOINIncomplete callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}
/**
* @brief Connect callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Disconnect callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData);
}
/*******************************************************************************
LL Driver Interface (USB Device Library --> PCD)
*******************************************************************************/
/**
* @brief Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
/* Init USB Ip. */
if (pdev->id == DEVICE_FS) {
/* Link the driver to the stack. */
hpcd_USB_OTG_FS.pData = pdev;
pdev->pData = &hpcd_USB_OTG_FS;
hpcd_USB_OTG_FS.Instance = XC_USB_OTG_FS;
hpcd_USB_OTG_FS.Init.dev_endpoints = 2;
hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
hpcd_USB_OTG_FS.Init.dma_enable = DISABLE;
hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
hpcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
hpcd_USB_OTG_FS.Init.low_power_enable = DISABLE;
hpcd_USB_OTG_FS.Init.lpm_enable = DISABLE;
hpcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = DISABLE;
if (HAL_PCD_Init(&hpcd_USB_OTG_FS) != HAL_OK)
{
Error_Handler( );
}
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
/* Register USB PCD CallBacks */
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SOF_CB_ID, PCD_SOFCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SETUPSTAGE_CB_ID, PCD_SetupStageCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESET_CB_ID, PCD_ResetCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SUSPEND_CB_ID, PCD_SuspendCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESUME_CB_ID, PCD_ResumeCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_CONNECT_CB_ID, PCD_ConnectCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_DISCONNECT_CB_ID, PCD_DisconnectCallback);
HAL_PCD_RegisterDataOutStageCallback(&hpcd_USB_OTG_FS, PCD_DataOutStageCallback);
HAL_PCD_RegisterDataInStageCallback(&hpcd_USB_OTG_FS, PCD_DataInStageCallback);
HAL_PCD_RegisterIsoOutIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOOUTIncompleteCallback);
HAL_PCD_RegisterIsoInIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOINIncompleteCallback);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x40);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x10);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 2, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 3, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 4, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 5, 0x10);
}
return USBD_OK;
}
/**
* @brief De-Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_DeInit(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Starts the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Start(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Stops the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Stop(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Opens an endpoint of the low level driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param ep_type: Endpoint type
* @param ep_mps: Endpoint max packet size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Closes an endpoint of the low level driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Flushes an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Sets a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Clears a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Returns Stall condition.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval Stall (1: Yes, 0: No)
*/
uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*) pdev->pData;
if((ep_addr & 0x80) == 0x80)
{
return hpcd->IN_ep[ep_addr & 0x7F].is_stall;
}
else
{
return hpcd->OUT_ep[ep_addr & 0x7F].is_stall;
}
}
/**
* @brief Assigns a USB address to the device.
* @param pdev: Device handle
* @param dev_addr: Device address
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Transmits data over an endpoint.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param pbuf: Pointer to data to be sent
* @param size: Data size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Prepares an endpoint for reception.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param pbuf: Pointer to data to be received
* @param size: Data size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Returns the last transferred packet size.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval Received Data Size
*/
uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef*) pdev->pData, ep_addr);
}
#ifdef USBD_HS_TESTMODE_ENABLE
/**
* @brief Set High speed Test mode.
* @param pdev: Device handle
* @param testmode: test mode
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_SetTestMode(USBD_HandleTypeDef *pdev, uint8_t testmode)
{
UNUSED(pdev);
UNUSED(testmode);
return USBD_OK;
}
#endif /* USBD_HS_TESTMODE_ENABLE */
/**
* @brief Static single allocation.
* @param size: Size of allocated memory
* @retval None
*/
void *USBD_static_malloc(uint32_t size)
{
return NULL;
}
/**
* @brief Dummy memory free
* @param p: Pointer to allocated memory address
* @retval None
*/
void USBD_static_free(void *p)
{
}
/**
* @brief Delays routine for the USB Device Library.
* @param Delay: Delay in ms
* @retval None
*/
void USBD_LL_Delay(uint32_t Delay)
{
HAL_Delay(Delay);
}
/**
* @brief Returns the USB status depending on the HAL status:
* @param hal_status: HAL status
* @retval USB status
*/
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status)
{
USBD_StatusTypeDef usb_status = USBD_OK;
switch (hal_status)
{
case HAL_OK :
usb_status = USBD_OK;
break;
case HAL_ERROR :
usb_status = USBD_FAIL;
break;
case HAL_BUSY :
usb_status = USBD_BUSY;
break;
case HAL_TIMEOUT :
usb_status = USBD_FAIL;
break;
default :
usb_status = USBD_FAIL;
break;
}
return usb_status;
}
@@ -0,0 +1,167 @@
/*!
* \file usbd_conf.h
*
* \brief Header for usbd_conf.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CONF__H
#define __USBD_CONF__H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xc6xxx.h"
/* USER CODE BEGIN INCLUDE */
#define USBD_COMPOSITE_USE_IAD 0
#define USBD_CMPSIT_ACTIVATE_HID_MOUSE 0
#define USBD_CMPSIT_ACTIVATE_HID_KEYBOARD 0
#define USBD_CMPSIT_ACTIVATE_HID_CUSTOM 0
#define USBD_CMPSIT_ACTIVATE_CDC 0
#define USBD_CMPSIT_ACTIVATE_DFU 0
/* USER CODE END INCLUDE */
/** @addtogroup USBD_OTG_DRIVER
* @brief Driver for Usb device.
* @{
*/
/** @defgroup USBD_CONF USBD_CONF
* @brief Configuration file for Usb otg low level driver.
* @{
*/
/** @defgroup USBD_CONF_Exported_Variables USBD_CONF_Exported_Variables
* @brief Public variables.
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines
* @brief Defines for configuration of the Usb device.
* @{
*/
/*---------- -----------*/
#define USBD_MAX_NUM_INTERFACES 5U
/*---------- -----------*/
#define USBD_MAX_NUM_CONFIGURATION 1U
/*---------- -----------*/
#define USBD_MAX_STR_DESC_SIZ 512U
/*---------- -----------*/
#define USBD_DEBUG_LEVEL 0U
/*---------- -----------*/
#define USBD_LPM_ENABLED 0U
/*---------- -----------*/
#define USBD_SELF_POWERED 1U
/****************************************/
/* #define for FS and HS identification */
#define DEVICE_FS 1
#define DEVICE_HS 0
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Macros USBD_CONF_Exported_Macros
* @brief Aliases.
* @{
*/
/* Memory management macros make sure to use static memory allocation */
/** Alias for memory allocation. */
#define USBD_malloc malloc
/** Alias for memory release. */
#define USBD_free free
/** Alias for memory set. */
#define USBD_memset memset
/** Alias for memory copy. */
#define USBD_memcpy memcpy
/** Alias for delay. */
#define USBD_Delay HAL_Delay
/* DEBUG macros */
#if (USBD_DEBUG_LEVEL > 0)
#define USBD_UsrLog(...) printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_UsrLog(...)
#endif /* (USBD_DEBUG_LEVEL > 0U) */
#if (USBD_DEBUG_LEVEL > 1)
#define USBD_ErrLog(...) printf("ERROR: ");\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_ErrLog(...)
#endif /* (USBD_DEBUG_LEVEL > 1U) */
#if (USBD_DEBUG_LEVEL > 2)
#define USBD_DbgLog(...) printf("DEBUG : ");\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_DbgLog(...)
#endif /* (USBD_DEBUG_LEVEL > 2U) */
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void *USBD_static_malloc(uint32_t size);
void USBD_static_free(void *p);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CONF__H__ */
@@ -0,0 +1,635 @@
/*!
* \file usbd_conf.c
*
* \brief This file implements the board support package for the USB device
* library
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_core.h"
#include "usbd_def.h"
#include "xc_hal_usb.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
PCD_HandleTypeDef hpcd_USB_OTG_FS;
/*------------------------------------------------------------------------------------
Func Prototypes
------------------------------------------------------------------------------------*/
void Error_Handler(void);
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status);
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state
*/
GLOBAL_INT_DISABLE();
while (1) {
}
GLOBAL_INT_RESTORE();
/* USER CODE END Error_Handler_Debug */
}
/*******************************************************************************
LL Driver Callbacks (PCD -> USB Device Library)
*******************************************************************************/
/* MSP Init */
void HAL_PCD_MspInit(PCD_HandleTypeDef *pcdHandle)
{
USB_Phy_Init();
USB_Phy_Enable();
USB_Current_Ctrl(1);
// NVIC_SetPriority(USB_IRQn, 0); // MSC mode do not SET!!!!
USB_Phy_DP_Oprt(PULL_UP);
HAL_Delay(100); // for(int i = 0; i < 0x455000*2; i++);
NVIC_EnableIRQ(USB_IRQn);
}
/* MSP DeInit */
void HAL_PCD_MspDeInit(PCD_HandleTypeDef *pcdHandle) { USB_Phy_Deinit(); }
/**
* @brief Setup stage callback
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup);
}
/**
* @brief Data Out stage callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
}
/**
* @brief Data In stage callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DataInStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff);
}
/**
* @brief SOF callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Reset callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_SpeedTypeDef speed = USBD_SPEED_FULL;
if ( hpcd->Init.speed == PCD_SPEED_HIGH)
{
speed = USBD_SPEED_HIGH;
}
else if ( hpcd->Init.speed == PCD_SPEED_FULL)
{
speed = USBD_SPEED_FULL;
}
else
{
Error_Handler();
}
/* Set Speed. */
USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed);
/* Reset Device. */
USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Suspend callback.
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
/* Inform USB library that core enters in suspend Mode. */
USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData);
__HAL_PCD_GATE_PHYCLOCK(hpcd);
/* Enter in STOP mode. */
/* USER CODE BEGIN 2 */
if (hpcd->Init.low_power_enable)
{
/* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */
SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
}
/* USER CODE END 2 */
}
/**
* @brief Resume callback.
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief ISOOUTIncomplete callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}
/**
* @brief ISOINIncomplete callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}
/**
* @brief Connect callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Disconnect callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData);
}
/*******************************************************************************
LL Driver Interface (USB Device Library --> PCD)
*******************************************************************************/
/**
* @brief Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
/* Init USB Ip. */
if (pdev->id == DEVICE_FS) {
/* Link the driver to the stack. */
hpcd_USB_OTG_FS.pData = pdev;
pdev->pData = &hpcd_USB_OTG_FS;
hpcd_USB_OTG_FS.Instance = XC_USB_OTG_FS;
hpcd_USB_OTG_FS.Init.dev_endpoints = 2;
hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
hpcd_USB_OTG_FS.Init.dma_enable = DISABLE;
hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
hpcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
hpcd_USB_OTG_FS.Init.low_power_enable = DISABLE;
hpcd_USB_OTG_FS.Init.lpm_enable = DISABLE;
hpcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = DISABLE;
if (HAL_PCD_Init(&hpcd_USB_OTG_FS) != HAL_OK)
{
Error_Handler( );
}
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
/* Register USB PCD CallBacks */
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SOF_CB_ID, PCD_SOFCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SETUPSTAGE_CB_ID, PCD_SetupStageCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESET_CB_ID, PCD_ResetCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SUSPEND_CB_ID, PCD_SuspendCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESUME_CB_ID, PCD_ResumeCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_CONNECT_CB_ID, PCD_ConnectCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_DISCONNECT_CB_ID, PCD_DisconnectCallback);
HAL_PCD_RegisterDataOutStageCallback(&hpcd_USB_OTG_FS, PCD_DataOutStageCallback);
HAL_PCD_RegisterDataInStageCallback(&hpcd_USB_OTG_FS, PCD_DataInStageCallback);
HAL_PCD_RegisterIsoOutIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOOUTIncompleteCallback);
HAL_PCD_RegisterIsoInIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOINIncompleteCallback);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x40);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x10);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 2, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 3, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 4, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 5, 0x10);
}
return USBD_OK;
}
/**
* @brief De-Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_DeInit(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Starts the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Start(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Stops the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Stop(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Opens an endpoint of the low level driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param ep_type: Endpoint type
* @param ep_mps: Endpoint max packet size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Closes an endpoint of the low level driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Flushes an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Sets a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Clears a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Returns Stall condition.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval Stall (1: Yes, 0: No)
*/
uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*) pdev->pData;
if((ep_addr & 0x80) == 0x80)
{
return hpcd->IN_ep[ep_addr & 0x7F].is_stall;
}
else
{
return hpcd->OUT_ep[ep_addr & 0x7F].is_stall;
}
}
/**
* @brief Assigns a USB address to the device.
* @param pdev: Device handle
* @param dev_addr: Device address
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Transmits data over an endpoint.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param pbuf: Pointer to data to be sent
* @param size: Data size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Prepares an endpoint for reception.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param pbuf: Pointer to data to be received
* @param size: Data size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Returns the last transferred packet size.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval Received Data Size
*/
uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef*) pdev->pData, ep_addr);
}
#ifdef USBD_HS_TESTMODE_ENABLE
/**
* @brief Set High speed Test mode.
* @param pdev: Device handle
* @param testmode: test mode
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_SetTestMode(USBD_HandleTypeDef *pdev, uint8_t testmode)
{
UNUSED(pdev);
UNUSED(testmode);
return USBD_OK;
}
#endif /* USBD_HS_TESTMODE_ENABLE */
/**
* @brief Static single allocation.
* @param size: Size of allocated memory
* @retval None
*/
void *USBD_static_malloc(uint32_t size)
{
return NULL;
}
/**
* @brief Dummy memory free
* @param p: Pointer to allocated memory address
* @retval None
*/
void USBD_static_free(void *p)
{
}
/**
* @brief Delays routine for the USB Device Library.
* @param Delay: Delay in ms
* @retval None
*/
void USBD_LL_Delay(uint32_t Delay)
{
HAL_Delay(Delay);
}
/**
* @brief Returns the USB status depending on the HAL status:
* @param hal_status: HAL status
* @retval USB status
*/
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status)
{
USBD_StatusTypeDef usb_status = USBD_OK;
switch (hal_status)
{
case HAL_OK :
usb_status = USBD_OK;
break;
case HAL_ERROR :
usb_status = USBD_FAIL;
break;
case HAL_BUSY :
usb_status = USBD_BUSY;
break;
case HAL_TIMEOUT :
usb_status = USBD_FAIL;
break;
default :
usb_status = USBD_FAIL;
break;
}
return usb_status;
}
@@ -0,0 +1,167 @@
/*!
* \file usbd_conf.h
*
* \brief Header for usbd_conf.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CONF__H
#define __USBD_CONF__H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xc6xxx.h"
/* USER CODE BEGIN INCLUDE */
#define USBD_COMPOSITE_USE_IAD 0
#define USBD_CMPSIT_ACTIVATE_HID_MOUSE 0
#define USBD_CMPSIT_ACTIVATE_HID_KEYBOARD 0
#define USBD_CMPSIT_ACTIVATE_HID_CUSTOM 0
#define USBD_CMPSIT_ACTIVATE_CDC 0
#define USBD_CMPSIT_ACTIVATE_DFU 0
/* USER CODE END INCLUDE */
/** @addtogroup USBD_OTG_DRIVER
* @brief Driver for Usb device.
* @{
*/
/** @defgroup USBD_CONF USBD_CONF
* @brief Configuration file for Usb otg low level driver.
* @{
*/
/** @defgroup USBD_CONF_Exported_Variables USBD_CONF_Exported_Variables
* @brief Public variables.
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines
* @brief Defines for configuration of the Usb device.
* @{
*/
/*---------- -----------*/
#define USBD_MAX_NUM_INTERFACES 5U
/*---------- -----------*/
#define USBD_MAX_NUM_CONFIGURATION 1U
/*---------- -----------*/
#define USBD_MAX_STR_DESC_SIZ 512U
/*---------- -----------*/
#define USBD_DEBUG_LEVEL 0U
/*---------- -----------*/
#define USBD_LPM_ENABLED 0U
/*---------- -----------*/
#define USBD_SELF_POWERED 1U
/****************************************/
/* #define for FS and HS identification */
#define DEVICE_FS 1
#define DEVICE_HS 0
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Macros USBD_CONF_Exported_Macros
* @brief Aliases.
* @{
*/
/* Memory management macros make sure to use static memory allocation */
/** Alias for memory allocation. */
#define USBD_malloc malloc
/** Alias for memory release. */
#define USBD_free free
/** Alias for memory set. */
#define USBD_memset memset
/** Alias for memory copy. */
#define USBD_memcpy memcpy
/** Alias for delay. */
#define USBD_Delay HAL_Delay
/* DEBUG macros */
#if (USBD_DEBUG_LEVEL > 0)
#define USBD_UsrLog(...) printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_UsrLog(...)
#endif /* (USBD_DEBUG_LEVEL > 0U) */
#if (USBD_DEBUG_LEVEL > 1)
#define USBD_ErrLog(...) printf("ERROR: ");\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_ErrLog(...)
#endif /* (USBD_DEBUG_LEVEL > 1U) */
#if (USBD_DEBUG_LEVEL > 2)
#define USBD_DbgLog(...) printf("DEBUG : ");\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_DbgLog(...)
#endif /* (USBD_DEBUG_LEVEL > 2U) */
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void *USBD_static_malloc(uint32_t size);
void USBD_static_free(void *p);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CONF__H__ */
@@ -0,0 +1,636 @@
/*!
* \file usbd_conf.c
*
* \brief This file implements the board support package for the USB device
* library
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_core.h"
#include "usbd_def.h"
#include "xc_hal_usb.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
PCD_HandleTypeDef hpcd_USB_OTG_FS;
/*------------------------------------------------------------------------------------
Func Prototypes
------------------------------------------------------------------------------------*/
void Error_Handler(void);
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status);
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state
*/
GLOBAL_INT_DISABLE();
while (1) {
}
GLOBAL_INT_RESTORE();
/* USER CODE END Error_Handler_Debug */
}
/*******************************************************************************
LL Driver Callbacks (PCD -> USB Device Library)
*******************************************************************************/
/* MSP Init */
void HAL_PCD_MspInit(PCD_HandleTypeDef *pcdHandle)
{
USB_Phy_Init();
USB_Phy_Enable();
USB_Current_Ctrl(1);
// NVIC_SetPriority(USB_IRQn, 0); // MSC mode do not SET!!!!
USB_Phy_DP_Oprt(PULL_UP);
// HAL_Delay(100); // for(int i = 0; i < 0x455000*2; i++);
NVIC_EnableIRQ(USB_IRQn);
}
/* MSP DeInit */
void HAL_PCD_MspDeInit(PCD_HandleTypeDef *pcdHandle) { USB_Phy_Deinit(); }
/**
* @brief Setup stage callback
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup);
}
/**
* @brief Data Out stage callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
}
/**
* @brief Data In stage callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DataInStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff);
}
/**
* @brief SOF callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Reset callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_SpeedTypeDef speed = USBD_SPEED_FULL;
if ( hpcd->Init.speed == PCD_SPEED_HIGH)
{
speed = USBD_SPEED_HIGH;
}
else if ( hpcd->Init.speed == PCD_SPEED_FULL)
{
speed = USBD_SPEED_FULL;
}
else
{
Error_Handler();
}
/* Set Speed. */
USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed);
/* Reset Device. */
USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Suspend callback.
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
/* Inform USB library that core enters in suspend Mode. */
USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData);
__HAL_PCD_GATE_PHYCLOCK(hpcd);
/* Enter in STOP mode. */
/* USER CODE BEGIN 2 */
if (hpcd->Init.low_power_enable)
{
/* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */
SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
}
/* USER CODE END 2 */
}
/**
* @brief Resume callback.
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief ISOOUTIncomplete callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}
/**
* @brief ISOINIncomplete callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#else
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}
/**
* @brief Connect callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData);
}
/**
* @brief Disconnect callback.
* @param hpcd: PCD handle
* @retval None
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
static void PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
#else
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData);
}
/*******************************************************************************
LL Driver Interface (USB Device Library --> PCD)
*******************************************************************************/
/**
* @brief Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
/* Init USB Ip. */
if (pdev->id == DEVICE_FS) {
/* Link the driver to the stack. */
hpcd_USB_OTG_FS.pData = pdev;
pdev->pData = &hpcd_USB_OTG_FS;
hpcd_USB_OTG_FS.Instance = XC_USB_OTG_FS;
hpcd_USB_OTG_FS.Init.dev_endpoints = 4;
hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
hpcd_USB_OTG_FS.Init.dma_enable = DISABLE;
hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
hpcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
hpcd_USB_OTG_FS.Init.low_power_enable = DISABLE;
hpcd_USB_OTG_FS.Init.lpm_enable = DISABLE;
hpcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = DISABLE;
if (HAL_PCD_Init(&hpcd_USB_OTG_FS) != HAL_OK)
{
Error_Handler( );
}
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
/* Register USB PCD CallBacks */
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SOF_CB_ID, PCD_SOFCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SETUPSTAGE_CB_ID, PCD_SetupStageCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESET_CB_ID, PCD_ResetCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SUSPEND_CB_ID, PCD_SuspendCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESUME_CB_ID, PCD_ResumeCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_CONNECT_CB_ID, PCD_ConnectCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_DISCONNECT_CB_ID, PCD_DisconnectCallback);
HAL_PCD_RegisterDataOutStageCallback(&hpcd_USB_OTG_FS, PCD_DataOutStageCallback);
HAL_PCD_RegisterDataInStageCallback(&hpcd_USB_OTG_FS, PCD_DataInStageCallback);
HAL_PCD_RegisterIsoOutIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOOUTIncompleteCallback);
HAL_PCD_RegisterIsoInIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOINIncompleteCallback);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x40);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x20);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 2, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 3, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 4, 0x10);
// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 5, 0x10);
}
return USBD_OK;
}
/**
* @brief De-Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_DeInit(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Starts the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Start(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Stops the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Stop(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Opens an endpoint of the low level driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param ep_type: Endpoint type
* @param ep_mps: Endpoint max packet size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Closes an endpoint of the low level driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Flushes an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Sets a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Clears a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Returns Stall condition.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval Stall (1: Yes, 0: No)
*/
uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*) pdev->pData;
if((ep_addr & 0x80) == 0x80)
{
return hpcd->IN_ep[ep_addr & 0x7F].is_stall;
}
else
{
return hpcd->OUT_ep[ep_addr & 0x7F].is_stall;
}
}
/**
* @brief Assigns a USB address to the device.
* @param pdev: Device handle
* @param dev_addr: Device address
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Transmits data over an endpoint.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param pbuf: Pointer to data to be sent
* @param size: Data size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Prepares an endpoint for reception.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param pbuf: Pointer to data to be received
* @param size: Data size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Returns the last transferred packet size.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval Received Data Size
*/
uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef*) pdev->pData, ep_addr);
}
#ifdef USBD_HS_TESTMODE_ENABLE
/**
* @brief Set High speed Test mode.
* @param pdev: Device handle
* @param testmode: test mode
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_SetTestMode(USBD_HandleTypeDef *pdev, uint8_t testmode)
{
UNUSED(pdev);
UNUSED(testmode);
return USBD_OK;
}
#endif /* USBD_HS_TESTMODE_ENABLE */
/**
* @brief Static single allocation.
* @param size: Size of allocated memory
* @retval None
*/
void *USBD_static_malloc(uint32_t size)
{
return NULL;
}
/**
* @brief Dummy memory free
* @param p: Pointer to allocated memory address
* @retval None
*/
void USBD_static_free(void *p)
{
}
/**
* @brief Delays routine for the USB Device Library.
* @param Delay: Delay in ms
* @retval None
*/
void USBD_LL_Delay(uint32_t Delay)
{
HAL_Delay(Delay);
}
/**
* @brief Returns the USB status depending on the HAL status:
* @param hal_status: HAL status
* @retval USB status
*/
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status)
{
USBD_StatusTypeDef usb_status = USBD_OK;
switch (hal_status)
{
case HAL_OK :
usb_status = USBD_OK;
break;
case HAL_ERROR :
usb_status = USBD_FAIL;
break;
case HAL_BUSY :
usb_status = USBD_BUSY;
break;
case HAL_TIMEOUT :
usb_status = USBD_FAIL;
break;
default :
usb_status = USBD_FAIL;
break;
}
return usb_status;
}
@@ -0,0 +1,165 @@
/*!
* \file usbd_conf.h
*
* \brief Header for usbd_conf.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CONF__H
#define __USBD_CONF__H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xc6xxx.h"
/* USER CODE BEGIN INCLUDE */
#define USBD_COMPOSITE_USE_IAD 0
#define USBD_CMPSIT_ACTIVATE_HID_MOUSE 0
#define USBD_CMPSIT_ACTIVATE_HID_KEYBOARD 0
#define USBD_CMPSIT_ACTIVATE_HID_CUSTOM 0
#define USBD_CMPSIT_ACTIVATE_CDC 0
#define USBD_CMPSIT_ACTIVATE_DFU 0
/* USER CODE END INCLUDE */
/** @addtogroup USBD_OTG_DRIVER
* @brief Driver for Usb device.
* @{
*/
/** @defgroup USBD_CONF USBD_CONF
* @brief Configuration file for Usb otg low level driver.
* @{
*/
/** @defgroup USBD_CONF_Exported_Variables USBD_CONF_Exported_Variables
* @brief Public variables.
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines
* @brief Defines for configuration of the Usb device.
* @{
*/
/*---------- -----------*/
#define USBD_MAX_NUM_INTERFACES 5U
/*---------- -----------*/
#define USBD_MAX_NUM_CONFIGURATION 1U
/*---------- -----------*/
#define USBD_MAX_STR_DESC_SIZ 512U
/*---------- -----------*/
#define USBD_DEBUG_LEVEL 0U
/*---------- -----------*/
#define USBD_LPM_ENABLED 0U
/*---------- -----------*/
#define USBD_SELF_POWERED 1U
/****************************************/
/* #define for FS and HS identification */
#define DEVICE_FS 1
#define DEVICE_HS 0
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Macros USBD_CONF_Exported_Macros
* @brief Aliases.
* @{
*/
/* Memory management macros make sure to use static memory allocation */
/** Alias for memory allocation. */
#define USBD_malloc malloc
/** Alias for memory release. */
#define USBD_free free
/** Alias for memory set. */
#define USBD_memset memset
/** Alias for memory copy. */
#define USBD_memcpy memcpy
/** Alias for delay. */
#define USBD_Delay HAL_Delay
/* DEBUG macros */
#if (USBD_DEBUG_LEVEL > 0)
#define USBD_UsrLog(...) printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_UsrLog(...)
#endif /* (USBD_DEBUG_LEVEL > 0U) */
#if (USBD_DEBUG_LEVEL > 1)
#define USBD_ErrLog(...) printf("ERROR: ");\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_ErrLog(...)
#endif /* (USBD_DEBUG_LEVEL > 1U) */
#if (USBD_DEBUG_LEVEL > 2)
#define USBD_DbgLog(...) printf("DEBUG : ");\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_DbgLog(...)
#endif /* (USBD_DEBUG_LEVEL > 2U) */
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void *USBD_static_malloc(uint32_t size);
void USBD_static_free(void *p);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CONF__H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,639 @@
/*!
* \file xc_hal_ll_usb_np.h
*
* \brief USB Low Layer HAL module driver.(use non-periodic fifo)
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
#ifndef __XC_HAL_LL_USB_NP_H
#define __XC_HAL_LL_USB_NP_H
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_usb_bitfields.h"
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Typedef
------------------------------------------------------------------------------------*/
#if defined (USB_OTG_FS)
/**
* @brief USB Mode definition
*/
typedef enum
{
USB_DEVICE_MODE = 0,
USB_HOST_MODE = 1,
USB_DRD_MODE = 2
} USB_OTG_ModeTypeDef;
/**
* @brief URB States definition
*/
typedef enum
{
URB_IDLE = 0,
URB_DONE,
URB_NOTREADY,
URB_NYET,
URB_ERROR,
URB_STALL
} USB_OTG_URBStateTypeDef;
/**
* @brief Host channel States definition
*/
//typedef enum
//{
// HC_IDLE = 0,
// HC_XFRC,
// HC_HALTED,
// HC_NAK,
// HC_NYET,
// HC_STALL,
// HC_XACTERR,
// HC_BBLERR,
// HC_DATATGLERR
//} USB_OTG_HCStateTypeDef;
/**
* @brief USB Instance Initialization Structure definition
*/
typedef struct
{
uint32_t dev_endpoints; /*!< Device Endpoints number.
This parameter depends on the used USB core.
This parameter must be a number between Min_Data = 1 and Max_Data = 15 */
uint32_t Host_channels; /*!< Host Channels number.
This parameter Depends on the used USB core.
This parameter must be a number between Min_Data = 1 and Max_Data = 15 */
uint32_t speed; /*!< USB Core speed.
This parameter can be any value of @ref PCD_Speed/HCD_Speed
(HCD_SPEED_xxx, HCD_SPEED_xxx) */
uint32_t dma_enable; /*!< Enable or disable of the USB embedded DMA used only for OTG HS. */
uint32_t ep0_mps; /*!< Set the Endpoint 0 Max Packet size. */
uint32_t phy_itface; /*!< Select the used PHY interface.
This parameter can be any value of @ref PCD_PHY_Module/HCD_PHY_Module */
uint32_t Sof_enable; /*!< Enable or disable the output of the SOF signal. */
uint32_t low_power_enable; /*!< Enable or disable the low power mode. */
uint32_t lpm_enable; /*!< Enable or disable Link Power Management. */
uint32_t battery_charging_enable; /*!< Enable or disable Battery charging. */
uint32_t vbus_sensing_enable; /*!< Enable or disable the VBUS Sensing feature. */
uint32_t use_dedicated_ep1; /*!< Enable or disable the use of the dedicated EP1 interrupt. */
uint32_t use_external_vbus; /*!< Enable or disable the use of the external VBUS. */
} USB_OTG_CfgTypeDef;
typedef struct
{
uint8_t num; /*!< Endpoint number
This parameter must be a number between Min_Data = 1 and Max_Data = 15 */
uint8_t is_in; /*!< Endpoint direction
This parameter must be a number between Min_Data = 0 and Max_Data = 1 */
uint8_t is_stall; /*!< Endpoint stall condition
This parameter must be a number between Min_Data = 0 and Max_Data = 1 */
uint8_t is_iso_incomplete; /*!< Endpoint isoc condition
This parameter must be a number between Min_Data = 0 and Max_Data = 1 */
uint8_t type; /*!< Endpoint type
This parameter can be any value of @ref USB_LL_EP_Type */
uint8_t data_pid_start; /*!< Initial data PID
This parameter must be a number between Min_Data = 0 and Max_Data = 1 */
uint8_t even_odd_frame; /*!< IFrame parity
This parameter must be a number between Min_Data = 0 and Max_Data = 1 */
uint16_t tx_fifo_num; /*!< Transmission FIFO number
This parameter must be a number between Min_Data = 1 and Max_Data = 15 */
uint32_t maxpacket; /*!< Endpoint Max packet size
This parameter must be a number between Min_Data = 0 and Max_Data = 64KB */
uint8_t *xfer_buff; /*!< Pointer to transfer buffer */
uint32_t dma_addr; /*!< 32 bits aligned transfer buffer address */
uint32_t xfer_len; /*!< Current transfer length */
uint32_t xfer_count; /*!< Partial transfer length in case of multi packet transfer */
} USB_OTG_EPTypeDef;
typedef struct
{
uint8_t dev_addr; /*!< USB device address.
This parameter must be a number between Min_Data = 1 and Max_Data = 255 */
uint8_t ch_num; /*!< Host channel number.
This parameter must be a number between Min_Data = 1 and Max_Data = 15 */
uint8_t ep_num; /*!< Endpoint number.
This parameter must be a number between Min_Data = 1 and Max_Data = 15 */
uint8_t ep_is_in; /*!< Endpoint direction
This parameter must be a number between Min_Data = 0 and Max_Data = 1 */
uint8_t speed; /*!< USB Host Channel speed.
This parameter can be any value of @ref HCD_Device_Speed:
(HCD_DEVICE_SPEED_xxx) */
uint8_t do_ping; /*!< Enable or disable the use of the PING protocol for HS mode. */
uint8_t process_ping; /*!< Execute the PING protocol for HS mode. */
uint8_t ep_type; /*!< Endpoint Type.
This parameter can be any value of @ref USB_LL_EP_Type */
uint16_t max_packet; /*!< Endpoint Max packet size.
This parameter must be a number between Min_Data = 0 and Max_Data = 64KB */
uint8_t data_pid; /*!< Initial data PID.
This parameter must be a number between Min_Data = 0 and Max_Data = 1 */
uint8_t *xfer_buff; /*!< Pointer to transfer buffer. */
uint32_t XferSize; /*!< OTG Channel transfer size. */
uint32_t xfer_len; /*!< Current transfer length. */
uint32_t xfer_count; /*!< Partial transfer length in case of multi packet transfer. */
uint8_t toggle_in; /*!< IN transfer current toggle flag.
This parameter must be a number between Min_Data = 0 and Max_Data = 1 */
uint8_t toggle_out; /*!< OUT transfer current toggle flag
This parameter must be a number between Min_Data = 0 and Max_Data = 1 */
uint32_t dma_addr; /*!< 32 bits aligned transfer buffer address. */
uint32_t ErrCnt; /*!< Host channel error count. */
USB_OTG_URBStateTypeDef urb_state; /*!< URB state.
This parameter can be any value of @ref USB_OTG_URBStateTypeDef */
// USB_OTG_HCStateTypeDef state; /*!< Host Channel state.
// This parameter can be any value of @ref USB_OTG_HCStateTypeDef */
} USB_OTG_HCTypeDef;
/**
* This union represents the bit fields in the User HW Config2
* Register. Read the register into the <i>d32</i> element then read
* out the bits using the <i>b</i>it elements.
*/
typedef union _USB_OTG_HWCFG2_TypeDef {
/** raw register data */
uint32_t d32;
/** register bits */
struct {
/* GHWCFG2 */
unsigned op_mode:3;
unsigned architecture:2;
unsigned point2point:1;
unsigned hs_phy_type:2;
unsigned fs_phy_type:2;
unsigned num_dev_ep:4;
unsigned num_host_chan:4;
unsigned perio_ep_supported:1;
unsigned dynamic_fifo:1;
unsigned multi_proc_int:1;
unsigned reserved21:1;
unsigned nonperio_tx_q_depth:2;
unsigned host_perio_tx_q_depth:2;
unsigned dev_token_q_depth:5;
unsigned otg_enable_ic_usb:1;
} b;
}USB_OTG_HWCFG2_TypeDef;
typedef union _USB_OTG_DTKNQ1_TypeDef {
/** raw register data */
uint32_t d32;
/** register bits */
struct {
/** In Token Queue Write Pointer */
unsigned intknwptr:5;
/** Reserved */
unsigned reserved05_06:2;
/** write pointer has wrapped. */
unsigned wrap_bit:1;
/** EP Numbers of IN Tokens 0 ... 4 */
unsigned epnums0_5:24;
} b;
} USB_OTG_DTKNQ1_TypeDef;
/* =========================================================================================================================== */
/* ================ USB ================ */
/* =========================================================================================================================== */
/**
* @brief USB_OTG_Core_Registers
*/
typedef struct
{
__IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register 000h */
__IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register 004h */
__IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register 008h */
__IO uint32_t GUSBCFG; /*!< Core USB Configuration Register 00Ch */
__IO uint32_t GRSTCTL; /*!< Core Reset Register 010h */
__IO uint32_t GINTSTS; /*!< Core Interrupt Register 014h */
__IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register 018h */
__IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register 01Ch */
__IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register 020h */
__IO uint32_t GRXFSIZ; /*!< Receive FIFO Size Register 024h */
__IO uint32_t GNPTXFSIZ; /*!< Non Periodic Tx FIFO Size Register 028h */
__IO uint32_t GNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg 02Ch */
uint32_t Reserved30[4]; /*!< Reserved 0x30-0x3C */
__I uint32_t GSNPSID; /*!< Synopsys ID Register 40Ch */
__I uint32_t GHWCFG1; /*!< User Hardware Configuration 1 Register 44Ch */
__IO uint32_t GHWCFG2; /*!< User Hardware Configuration 2 Register 48Ch */
__I uint32_t GHWCFG3;
__I uint32_t GHWCFG4;
uint32_t Reserved50[44]; /*!< Reserved 0x50-0x100h */
__IO uint32_t DPTXFSIZ[4]; /*!< Device Periodic Transmit FIFO1 0x104-0x100h */
} USB_OTG_GlobalTypeDef;
/**
* @brief USB_OTG_device_Registers
*/
typedef struct
{
__IO uint32_t DCFG; /*!< dev Configuration Register 800h */
__IO uint32_t DCTL; /*!< dev Control Register 804h */
__IO uint32_t DSTS; /*!< dev Status Register (RO) 808h */
uint32_t Reserved0C; /*!< Reserved 80Ch */
__IO uint32_t DIEPMSK; /*!< dev IN Endpoint Mask 810h */
__IO uint32_t DOEPMSK; /*!< dev OUT Endpoint Mask 814h */
__IO uint32_t DAINT; /*!< dev All Endpoints Itr Reg 818h */
__IO uint32_t DAINTMSK; /*!< dev All Endpoints Itr Mask 81Ch */
__IO uint32_t DTKNQR1; /*!< dev IN Token Seq Reg 1 820h */
__IO uint32_t DTKNQR2; /*!< dev IN Token Seq Reg 2 824h */
__IO uint32_t DVBUSDIS; /*!< dev VBUS discharge Register 828h */
__IO uint32_t DVBUSPULSE; /*!< dev VBUS Pulse Register 82Ch */
__IO uint32_t DTKNQR3; /*!< dev IN Token Seq Reg 3 830h */
__IO uint32_t DTKNQR4; /*!< dev IN Token Seq Reg 4 834h */
} USB_OTG_DeviceTypeDef;
/**
* @brief USB_OTG_IN_Endpoint-Specific_Register
*/
typedef struct
{
__IO uint32_t DIEPCTL; /*!< dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h */
uint32_t Reserved04; /*!< Reserved 900h + (ep_num * 20h) + 04h */
__IO uint32_t DIEPINT; /*!< dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h */
uint32_t Reserved0C; /*!< Reserved 900h + (ep_num * 20h) + 0Ch */
__IO uint32_t DIEPTSIZ; /*!< IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h */
uint32_t Reserved14; /*!< Reserved 900h + (ep_num * 20h) + 14h */
__IO uint32_t DTXFSTS; /*!< IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h */
uint32_t Reserved18; /*!< Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch */
} USB_OTG_INEndpointTypeDef;
/**
* @brief USB_OTG_OUT_Endpoint-Specific_Registers
*/
/**
* @brief USB_OTG_OUT_Endpoint-Specific_Registers
*/
typedef struct
{
__IO uint32_t DOEPCTL; /*!< dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h */
uint32_t Reserved04; /*!< Reserved B00h + (ep_num * 20h) + 04h */
__IO uint32_t DOEPINT; /*!< dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h */
uint32_t Reserved0C; /*!< Reserved B00h + (ep_num * 20h) + 0Ch */
__IO uint32_t DOEPTSIZ; /*!< dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h */
uint32_t Reserved14[5]; /*!< Reserved B00h + (ep_num * 20h) + 14h - B00h + (ep_num * 20h) + 1Ch */
} USB_OTG_OUTEndpointTypeDef;
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define XC_USB_FS_PERIPH_BASE 0x50010000UL
#define XC_USB_OTG_FS ((USB_OTG_GlobalTypeDef *) XC_USB_FS_PERIPH_BASE)
#define XC_USB_OTG_DEVICE_FS ((USB_OTG_DeviceTypeDef *) (XC_USB_FS_PERIPH_BASE + USB_OTG_DEVICE_BASE)
#define XC_USB_OTG_IN_ENDPOINT0_FS ((USB_OTG_INEndpointTypeDef *) (XC_USB_FS_PERIPH_BASE + USB_OTG_IN_ENDPOINT_BASE + ((0) * USB_OTG_EP_REG_SIZE)))
#define XC_USB_OTG_IN_ENDPOINT1_FS ((USB_OTG_INEndpointTypeDef *) (XC_USB_FS_PERIPH_BASE + USB_OTG_IN_ENDPOINT_BASE + ((1) * USB_OTG_EP_REG_SIZE)))
#define XC_USB_OTG_IN_ENDPOINT2_FS ((USB_OTG_INEndpointTypeDef *) (XC_USB_FS_PERIPH_BASE + USB_OTG_IN_ENDPOINT_BASE + ((2) * USB_OTG_EP_REG_SIZE)))
#define XC_USB_OTG_IN_ENDPOINT3_FS ((USB_OTG_INEndpointTypeDef *) (XC_USB_FS_PERIPH_BASE + USB_OTG_IN_ENDPOINT_BASE + ((3) * USB_OTG_EP_REG_SIZE)))
#define XC_USB_OTG_IN_ENDPOINT4_FS ((USB_OTG_INEndpointTypeDef *) (XC_USB_FS_PERIPH_BASE + USB_OTG_IN_ENDPOINT_BASE + ((4) * USB_OTG_EP_REG_SIZE)))
#define XC_USB_OTG_IN_ENDPOINT5_FS ((USB_OTG_INEndpointTypeDef *) (XC_USB_FS_PERIPH_BASE + USB_OTG_IN_ENDPOINT_BASE + ((5) * USB_OTG_EP_REG_SIZE)))
#define XC_USB_OTG_OUT_ENDPOINT0_FS ((USB_OTG_OUTEndpointTypeDef *) (XC_USB_FS_PERIPH_BASE +USB_OTG_OUT_ENDPOINT_BASE + ((0) * USB_OTG_EP_REG_SIZE)))
#define XC_USB_OTG_OUT_ENDPOINT1_FS ((USB_OTG_OUTEndpointTypeDef *) (XC_USB_FS_PERIPH_BASE +USB_OTG_OUT_ENDPOINT_BASE + ((1) * USB_OTG_EP_REG_SIZE)))
#define XC_USB_OTG_OUT_ENDPOINT2_FS ((USB_OTG_OUTEndpointTypeDef *) (XC_USB_FS_PERIPH_BASE +USB_OTG_OUT_ENDPOINT_BASE + ((2) * USB_OTG_EP_REG_SIZE)))
#define XC_USB_OTG_OUT_ENDPOINT3_FS ((USB_OTG_OUTEndpointTypeDef *) (XC_USB_FS_PERIPH_BASE +USB_OTG_OUT_ENDPOINT_BASE + ((3) * USB_OTG_EP_REG_SIZE)))
#define XC_USB_OTG_OUT_ENDPOINT4_FS ((USB_OTG_OUTEndpointTypeDef *) (XC_USB_FS_PERIPH_BASE +USB_OTG_OUT_ENDPOINT_BASE + ((4) * USB_OTG_EP_REG_SIZE)))
#define XC_USB_OTG_OUT_ENDPOINT5_FS ((USB_OTG_OUTEndpointTypeDef *) (XC_USB_FS_PERIPH_BASE +USB_OTG_OUT_ENDPOINT_BASE + ((5) * USB_OTG_EP_REG_SIZE)))
/** @defgroup USB_OTG_CORE VERSION ID
* @{
*/
#define USB_OTG_CORE_ID_300A 0x4F54300AU
#define USB_OTG_CORE_ID_310A 0x4F54310AU
/**
* @}
*/
/** @defgroup USB_Core_Mode_ USB Core Mode
* @{
*/
#define USB_OTG_MODE_DEVICE 0U
#define USB_OTG_MODE_HOST 1U
#define USB_OTG_MODE_DRD 2U
/**
* @}
*/
/** @defgroup USB_LL Device Speed
* @{
*/
#define USBD_HS_SPEED 0U
#define USBD_HSINFS_SPEED 1U
#define USBH_HS_SPEED 0U
#define USBD_FS_SPEED 2U
#define USBH_FSLS_SPEED 1U
/**
* @}
*/
/** @defgroup USB_LL_Core_Speed USB Low Layer Core Speed
* @{
*/
#define USB_OTG_SPEED_HIGH 0U
#define USB_OTG_SPEED_HIGH_IN_FULL 1U
#define USB_OTG_SPEED_FULL 3U
/**
* @}
*/
/** @defgroup USB_LL_Core_PHY USB Low Layer Core PHY
* @{
*/
#define USB_OTG_ULPI_PHY 1U
#define USB_OTG_EMBEDDED_PHY 2U
/**
* @}
*/
/** @defgroup USB_LL_Turnaround_Timeout Turnaround Timeout Value
* @{
*/
#ifndef USBD_HS_TRDT_VALUE
#define USBD_HS_TRDT_VALUE 9U
#endif /* USBD_HS_TRDT_VALUE */
#ifndef USBD_FS_TRDT_VALUE
#define USBD_FS_TRDT_VALUE 5U
#define USBD_DEFAULT_TRDT_VALUE 9U
#endif /* USBD_HS_TRDT_VALUE */
/**
* @}
*/
/** @defgroup USB_LL_Core_MPS USB Low Layer Core MPS
* @{
*/
#define USB_OTG_HS_MAX_PACKET_SIZE 512U
#define USB_OTG_FS_MAX_PACKET_SIZE 64U
#define USB_OTG_MAX_EP0_SIZE 64U
/**
* @}
*/
/** @defgroup USB_LL_Core_PHY_Frequency USB Low Layer Core PHY Frequency
* @{
*/
#define DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ (0U << 1)
#define DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ (1U << 1)
#define DSTS_ENUMSPD_FS_PHY_48MHZ (3U << 1)
/**
* @}
*/
/** @defgroup USB_LL_CORE_Frame_Interval USB Low Layer Core Frame Interval
* @{
*/
#define DCFG_FRAME_INTERVAL_80 0U
#define DCFG_FRAME_INTERVAL_85 1U
#define DCFG_FRAME_INTERVAL_90 2U
#define DCFG_FRAME_INTERVAL_95 3U
/**
* @}
*/
/** @defgroup USB_LL_EP0_MPS USB Low Layer EP0 MPS
* @{
*/
#define EP_MPS_64 0U
#define EP_MPS_32 1U
#define EP_MPS_16 2U
#define EP_MPS_8 3U
/**
* @}
*/
/** @defgroup USB_LL_EP_Speed USB Low Layer EP Speed
* @{
*/
#define EP_SPEED_LOW 0U
#define EP_SPEED_FULL 1U
#define EP_SPEED_HIGH 2U
/**
* @}
*/
/** @defgroup USB_LL_EP_Type USB Low Layer EP Type
* @{
*/
#define EP_TYPE_CTRL 0U
#define EP_TYPE_ISOC 1U
#define EP_TYPE_BULK 2U
#define EP_TYPE_INTR 3U
#define EP_TYPE_MSK 3U
/**
* @}
*/
/** @defgroup USB_LL_STS_Defines USB Low Layer STS Defines
* @{
*/
#define STS_GOUT_NAK 1U
#define STS_DATA_UPDT 2U
#define STS_XFER_COMP 3U
#define STS_SETUP_COMP 4U
#define STS_SETUP_UPDT 6U
/**
* @}
*/
/** @defgroup USB_LL_HCFG_SPEED_Defines USB Low Layer HCFG Speed Defines
* @{
*/
#define HCFG_30_60_MHZ 0U
#define HCFG_48_MHZ 1U
#define HCFG_6_MHZ 2U
/**
* @}
*/
/** @defgroup USB_LL_HPRT0_PRTSPD_SPEED_Defines USB Low Layer HPRT0 PRTSPD Speed Defines
* @{
*/
#define HPRT0_PRTSPD_HIGH_SPEED 0U
#define HPRT0_PRTSPD_FULL_SPEED 1U
#define HPRT0_PRTSPD_LOW_SPEED 2U
/**
* @}
*/
#define HCCHAR_CTRL 0U
#define HCCHAR_ISOC 1U
#define HCCHAR_BULK 2U
#define HCCHAR_INTR 3U
#define HC_PID_DATA0 0U
#define HC_PID_DATA2 1U
#define HC_PID_DATA1 2U
#define HC_PID_SETUP 3U
#define GRXSTS_PKTSTS_IN 2U
#define GRXSTS_PKTSTS_IN_XFER_COMP 3U
#define GRXSTS_PKTSTS_DATA_TOGGLE_ERR 5U
#define GRXSTS_PKTSTS_CH_HALTED 7U
#define USBx_PCGCCTL *(__IO uint32_t *)((uint32_t)USBx_BASE + USB_OTG_PCGCCTL_BASE)
#define USBx_HPRT0 *(__IO uint32_t *)((uint32_t)USBx_BASE + USB_OTG_HOST_PORT_BASE)
#define USBx_DEVICE ((USB_OTG_DeviceTypeDef *)(USBx_BASE + USB_OTG_DEVICE_BASE))
#define USBx_INEP(i) ((USB_OTG_INEndpointTypeDef *)(USBx_BASE\
+ USB_OTG_IN_ENDPOINT_BASE + ((i) * USB_OTG_EP_REG_SIZE)))
#define USBx_OUTEP(i) ((USB_OTG_OUTEndpointTypeDef *)(USBx_BASE\
+ USB_OTG_OUT_ENDPOINT_BASE + ((i) * USB_OTG_EP_REG_SIZE)))
#define USBx_DFIFO(i) *(__IO uint32_t *)(USBx_BASE + USB_OTG_FIFO_BASE + ((i) * USB_OTG_FIFO_SIZE))
#define USBx_HOST ((USB_OTG_HostTypeDef *)(USBx_BASE + USB_OTG_HOST_BASE))
#define USBx_HC(i) ((USB_OTG_HostChannelTypeDef *)(USBx_BASE\
+ USB_OTG_HOST_CHANNEL_BASE\
+ ((i) * USB_OTG_HOST_CHANNEL_SIZE)))
#define EP_ADDR_MSK 0xFU
/**
* @}
*/
/** @defgroup USB_LL_Exported_Macros USB Low Layer Exported Macros
* @{
*/
#define USB_MASK_INTERRUPT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->GINTMSK &= ~(__INTERRUPT__))
#define USB_UNMASK_INTERRUPT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->GINTMSK |= (__INTERRUPT__))
#define CLEAR_IN_EP_INTR(__EPNUM__, __INTERRUPT__) (USBx_INEP(__EPNUM__)->DIEPINT = (__INTERRUPT__))
#define CLEAR_OUT_EP_INTR(__EPNUM__, __INTERRUPT__) (USBx_OUTEP(__EPNUM__)->DOEPINT = (__INTERRUPT__))
/**
* @}
*/
/*------------------------------------------------------------------------------------
Exported Functions
------------------------------------------------------------------------------------*/
/** @addtogroup USB_LL_Exported_Functions USB Low Layer Exported Functions
* @{
*/
HAL_StatusTypeDef USB_CoreInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg);
HAL_StatusTypeDef USB_DevInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg);
HAL_StatusTypeDef USB_EnableGlobalInt(USB_OTG_GlobalTypeDef *USBx);
HAL_StatusTypeDef USB_DisableGlobalInt(USB_OTG_GlobalTypeDef *USBx);
HAL_StatusTypeDef USB_SetTurnaroundTime(USB_OTG_GlobalTypeDef *USBx, uint32_t hclk, uint8_t speed);
HAL_StatusTypeDef USB_SetCurrentMode(USB_OTG_GlobalTypeDef *USBx, USB_OTG_ModeTypeDef mode);
HAL_StatusTypeDef USB_SetDevSpeed(USB_OTG_GlobalTypeDef *USBx, uint8_t speed);
HAL_StatusTypeDef USB_FlushRxFifo(USB_OTG_GlobalTypeDef *USBx);
HAL_StatusTypeDef USB_FlushTxFifo(USB_OTG_GlobalTypeDef *USBx, uint32_t num);
HAL_StatusTypeDef USB_ActivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep);
HAL_StatusTypeDef USB_DeactivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep);
HAL_StatusTypeDef USB_ActivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep);
HAL_StatusTypeDef USB_DeactivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep);
HAL_StatusTypeDef USB_EPStartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep, uint8_t dma);
HAL_StatusTypeDef USB_EP0StartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep, uint8_t dma);
HAL_StatusTypeDef USB_WritePacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *src,
uint8_t ch_ep_num, uint16_t len, uint8_t dma);
void *USB_ReadPacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *dest, uint16_t len);
HAL_StatusTypeDef USB_EPSetStall(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep);
HAL_StatusTypeDef USB_EPClearStall(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep);
HAL_StatusTypeDef USB_EPStopXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep);
HAL_StatusTypeDef USB_SetDevAddress(USB_OTG_GlobalTypeDef *USBx, uint8_t address);
HAL_StatusTypeDef USB_DevConnect(USB_OTG_GlobalTypeDef *USBx);
HAL_StatusTypeDef USB_DevDisconnect(USB_OTG_GlobalTypeDef *USBx);
HAL_StatusTypeDef USB_StopDevice(USB_OTG_GlobalTypeDef *USBx);
HAL_StatusTypeDef USB_ActivateSetup(USB_OTG_GlobalTypeDef *USBx);
HAL_StatusTypeDef USB_EP0_OutStart(USB_OTG_GlobalTypeDef *USBx, uint8_t dma, uint8_t *psetup);
uint8_t USB_GetDevSpeed(USB_OTG_GlobalTypeDef *USBx);
uint32_t USB_GetMode(USB_OTG_GlobalTypeDef *USBx);
uint32_t USB_ReadInterrupts(USB_OTG_GlobalTypeDef *USBx);
uint32_t USB_ReadDevAllOutEpInterrupt(USB_OTG_GlobalTypeDef *USBx);
uint32_t USB_ReadDevOutEPInterrupt(USB_OTG_GlobalTypeDef *USBx, uint8_t epnum);
uint32_t USB_ReadDevAllInEpInterrupt(USB_OTG_GlobalTypeDef *USBx);
uint32_t USB_ReadDevInEPInterrupt(USB_OTG_GlobalTypeDef *USBx, uint8_t epnum);
void USB_ClearInterrupts(USB_OTG_GlobalTypeDef *USBx, uint32_t interrupt);
HAL_StatusTypeDef USB_HostInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg);
HAL_StatusTypeDef USB_InitFSLSPClkSel(USB_OTG_GlobalTypeDef *USBx, uint8_t freq);
HAL_StatusTypeDef USB_ResetPort(USB_OTG_GlobalTypeDef *USBx);
HAL_StatusTypeDef USB_DriveVbus(USB_OTG_GlobalTypeDef *USBx, uint8_t state);
uint32_t USB_GetHostSpeed(USB_OTG_GlobalTypeDef *USBx);
uint32_t USB_GetCurrentFrame(USB_OTG_GlobalTypeDef *USBx);
HAL_StatusTypeDef USB_HC_Init(USB_OTG_GlobalTypeDef *USBx, uint8_t ch_num,
uint8_t epnum, uint8_t dev_address, uint8_t speed,
uint8_t ep_type, uint16_t mps);
HAL_StatusTypeDef USB_HC_StartXfer(USB_OTG_GlobalTypeDef *USBx,
USB_OTG_HCTypeDef *hc, uint8_t dma);
uint32_t USB_HC_ReadInterrupt(USB_OTG_GlobalTypeDef *USBx);
HAL_StatusTypeDef USB_HC_Halt(USB_OTG_GlobalTypeDef *USBx, uint8_t hc_num);
HAL_StatusTypeDef USB_DoPing(USB_OTG_GlobalTypeDef *USBx, uint8_t ch_num);
HAL_StatusTypeDef USB_StopHost(USB_OTG_GlobalTypeDef *USBx);
HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_OTG_GlobalTypeDef *USBx);
HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_OTG_GlobalTypeDef *USBx);
/**
* @}
*/
#endif /* defined (USB_OTG_FS) */
#endif /* __XC_HAL_LL_USB_NP_H */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,680 @@
/*!
* \file xc_hal_pcd_np.h
*
* \brief PCD HAL module driver.(use non-periodic fifo)
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
#ifndef __XC_HAL_PCD_NP_H
#define __XC_HAL_PCD_NP_H
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_hal_ll_usb_np.h"
#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
/*------------------------------------------------------------------------------------
Typedef
------------------------------------------------------------------------------------*/
/**
* @brief PCD State structure definition
*/
typedef enum
{
HAL_PCD_STATE_RESET = 0x00,
HAL_PCD_STATE_READY = 0x01,
HAL_PCD_STATE_ERROR = 0x02,
HAL_PCD_STATE_BUSY = 0x03,
HAL_PCD_STATE_TIMEOUT = 0x04
} PCD_StateTypeDef;
/* Device LPM suspend state */
typedef enum
{
LPM_L0 = 0x00, /* on */
LPM_L1 = 0x01, /* LPM L1 sleep */
LPM_L2 = 0x02, /* suspend */
LPM_L3 = 0x03, /* off */
} PCD_LPM_StateTypeDef;
typedef enum
{
PCD_LPM_L0_ACTIVE = 0x00, /* on */
PCD_LPM_L1_ACTIVE = 0x01, /* LPM L1 sleep */
} PCD_LPM_MsgTypeDef;
typedef enum
{
PCD_BCD_ERROR = 0xFF,
PCD_BCD_CONTACT_DETECTION = 0xFE,
PCD_BCD_STD_DOWNSTREAM_PORT = 0xFD,
PCD_BCD_CHARGING_DOWNSTREAM_PORT = 0xFC,
PCD_BCD_DEDICATED_CHARGING_PORT = 0xFB,
PCD_BCD_DISCOVERY_COMPLETED = 0x00,
} PCD_BCD_MsgTypeDef;
#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
typedef USB_OTG_GlobalTypeDef PCD_TypeDef;
typedef USB_OTG_CfgTypeDef PCD_InitTypeDef;
typedef USB_OTG_EPTypeDef PCD_EPTypeDef;
#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
/**
* @brief PCD Handle Structure definition
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
typedef struct __PCD_HandleTypeDef
#else
typedef struct
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
PCD_TypeDef *Instance; /*!< Register base address */
PCD_InitTypeDef Init; /*!< PCD required parameters */
__IO uint8_t USB_Address; /*!< USB Address */
PCD_EPTypeDef IN_ep[16]; /*!< IN endpoint parameters */
PCD_EPTypeDef OUT_ep[16]; /*!< OUT endpoint parameters */
HAL_LockTypeDef Lock; /*!< PCD peripheral status */
__IO PCD_StateTypeDef State; /*!< PCD communication state */
__IO uint32_t ErrorCode; /*!< PCD Error code */
uint32_t Setup[12]; /*!< Setup packet buffer */
PCD_LPM_StateTypeDef LPM_State; /*!< LPM State */
uint32_t BESL;
uint32_t FrameNumber; /*!< Store Current Frame number */
uint32_t lpm_active; /*!< Enable or disable the Link Power Management .
This parameter can be set to ENABLE or DISABLE */
uint32_t battery_charging_active; /*!< Enable or disable Battery charging.
This parameter can be set to ENABLE or DISABLE */
void *pData; /*!< Pointer to upper stack Handler */
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
void (* SOFCallback)(struct __PCD_HandleTypeDef *hpcd); /*!< USB OTG PCD SOF callback */
void (* SetupStageCallback)(struct __PCD_HandleTypeDef *hpcd); /*!< USB OTG PCD Setup Stage callback */
void (* ResetCallback)(struct __PCD_HandleTypeDef *hpcd); /*!< USB OTG PCD Reset callback */
void (* SuspendCallback)(struct __PCD_HandleTypeDef *hpcd); /*!< USB OTG PCD Suspend callback */
void (* ResumeCallback)(struct __PCD_HandleTypeDef *hpcd); /*!< USB OTG PCD Resume callback */
void (* ConnectCallback)(struct __PCD_HandleTypeDef *hpcd); /*!< USB OTG PCD Connect callback */
void (* DisconnectCallback)(struct __PCD_HandleTypeDef *hpcd); /*!< USB OTG PCD Disconnect callback */
void (* DataOutStageCallback)(struct __PCD_HandleTypeDef *hpcd, uint8_t epnum); /*!< USB OTG PCD Data OUT Stage callback */
void (* DataInStageCallback)(struct __PCD_HandleTypeDef *hpcd, uint8_t epnum); /*!< USB OTG PCD Data IN Stage callback */
void (* ISOOUTIncompleteCallback)(struct __PCD_HandleTypeDef *hpcd, uint8_t epnum); /*!< USB OTG PCD ISO OUT Incomplete callback */
void (* ISOINIncompleteCallback)(struct __PCD_HandleTypeDef *hpcd, uint8_t epnum); /*!< USB OTG PCD ISO IN Incomplete callback */
void (* BCDCallback)(struct __PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg); /*!< USB OTG PCD BCD callback */
void (* LPMCallback)(struct __PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg); /*!< USB OTG PCD LPM callback */
void (* MspInitCallback)(struct __PCD_HandleTypeDef *hpcd); /*!< USB OTG PCD Msp Init callback */
void (* MspDeInitCallback)(struct __PCD_HandleTypeDef *hpcd); /*!< USB OTG PCD Msp DeInit callback */
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
} PCD_HandleTypeDef;
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/** @defgroup PCD_Speed PCD Speed
* @{
*/
#define PCD_SPEED_HIGH USBD_HS_SPEED
#define PCD_SPEED_HIGH_IN_FULL USBD_HSINFS_SPEED
#define PCD_SPEED_FULL USBD_FS_SPEED
/**
* @}
*/
/** @defgroup PCD_PHY_Module PCD PHY Module
* @{
*/
#define PCD_PHY_ULPI 1U
#define PCD_PHY_EMBEDDED 2U
#define PCD_PHY_UTMI 3U
/**
* @}
*/
/** @defgroup PCD_Error_Code_definition PCD Error Code definition
* @brief PCD Error Code definition
* @{
*/
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
#define HAL_PCD_ERROR_INVALID_CALLBACK (0x00000010U) /*!< Invalid Callback error */
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
/** @defgroup PCD_Exported_Macros PCD Exported Macros
* @brief macros to handle interrupts and specific clock configurations
* @{
*/
#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
#define __HAL_PCD_ENABLE(__HANDLE__) (void)USB_EnableGlobalInt ((__HANDLE__)->Instance)
#define __HAL_PCD_DISABLE(__HANDLE__) (void)USB_DisableGlobalInt ((__HANDLE__)->Instance)
#define __HAL_PCD_GET_FLAG(__HANDLE__, __INTERRUPT__) \
((USB_ReadInterrupts((__HANDLE__)->Instance) & (__INTERRUPT__)) == (__INTERRUPT__))
#define __HAL_PCD_CLEAR_FLAG(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->GINTSTS) &= (__INTERRUPT__))
#define __HAL_PCD_IS_INVALID_INTERRUPT(__HANDLE__) (USB_ReadInterrupts((__HANDLE__)->Instance) == 0U)
#define __HAL_PCD_UNGATE_PHYCLOCK(__HANDLE__) \
*(__IO uint32_t *)((uint32_t)((__HANDLE__)->Instance) + USB_OTG_PCGCCTL_BASE) &= ~(USB_OTG_PCGCCTL_STOPCLK)
#define __HAL_PCD_GATE_PHYCLOCK(__HANDLE__) \
*(__IO uint32_t *)((uint32_t)((__HANDLE__)->Instance) + USB_OTG_PCGCCTL_BASE) |= USB_OTG_PCGCCTL_STOPCLK
#define __HAL_PCD_IS_PHY_SUSPENDED(__HANDLE__) \
((*(__IO uint32_t *)((uint32_t)((__HANDLE__)->Instance) + USB_OTG_PCGCCTL_BASE)) & 0x10U)
#define __HAL_USB_OTG_HS_WAKEUP_EXTI_ENABLE_IT() EXTI->IMR |= (USB_OTG_HS_WAKEUP_EXTI_LINE)
#define __HAL_USB_OTG_HS_WAKEUP_EXTI_DISABLE_IT() EXTI->IMR &= ~(USB_OTG_HS_WAKEUP_EXTI_LINE)
#define __HAL_USB_OTG_HS_WAKEUP_EXTI_GET_FLAG() EXTI->PR & (USB_OTG_HS_WAKEUP_EXTI_LINE)
#define __HAL_USB_OTG_HS_WAKEUP_EXTI_CLEAR_FLAG() EXTI->PR = (USB_OTG_HS_WAKEUP_EXTI_LINE)
#define __HAL_USB_OTG_HS_WAKEUP_EXTI_ENABLE_RISING_EDGE() \
do { \
EXTI->FTSR &= ~(USB_OTG_HS_WAKEUP_EXTI_LINE); \
EXTI->RTSR |= USB_OTG_HS_WAKEUP_EXTI_LINE; \
} while(0U)
#define __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_IT() EXTI->IMR |= USB_OTG_FS_WAKEUP_EXTI_LINE
#define __HAL_USB_OTG_FS_WAKEUP_EXTI_DISABLE_IT() EXTI->IMR &= ~(USB_OTG_FS_WAKEUP_EXTI_LINE)
#define __HAL_USB_OTG_FS_WAKEUP_EXTI_GET_FLAG() EXTI->PR & (USB_OTG_FS_WAKEUP_EXTI_LINE)
#define __HAL_USB_OTG_FS_WAKEUP_EXTI_CLEAR_FLAG() EXTI->PR = USB_OTG_FS_WAKEUP_EXTI_LINE
#define __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_RISING_EDGE() \
do { \
EXTI->FTSR &= ~(USB_OTG_FS_WAKEUP_EXTI_LINE); \
EXTI->RTSR |= USB_OTG_FS_WAKEUP_EXTI_LINE; \
} while(0U)
#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
/** @defgroup USB_EXTI_Line_Interrupt USB EXTI line interrupt
* @{
*/
#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
#define USB_OTG_FS_WAKEUP_EXTI_LINE (0x1U << 18) /*!< USB FS EXTI Line WakeUp Interrupt */
#define USB_OTG_HS_WAKEUP_EXTI_LINE (0x1U << 20) /*!< USB HS EXTI Line WakeUp Interrupt */
#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
/**
* @}
*/
#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
#ifndef USB_OTG_DOEPINT_OTEPSPR
#define USB_OTG_DOEPINT_OTEPSPR (0x1UL << 5) /*!< Status Phase Received interrupt */
#endif /* defined USB_OTG_DOEPINT_OTEPSPR */
#ifndef USB_OTG_DOEPMSK_OTEPSPRM
#define USB_OTG_DOEPMSK_OTEPSPRM (0x1UL << 5) /*!< Setup Packet Received interrupt mask */
#endif /* defined USB_OTG_DOEPMSK_OTEPSPRM */
#ifndef USB_OTG_DOEPINT_NAK
#define USB_OTG_DOEPINT_NAK (0x1UL << 13) /*!< NAK interrupt */
#endif /* defined USB_OTG_DOEPINT_NAK */
#ifndef USB_OTG_DOEPMSK_NAKM
#define USB_OTG_DOEPMSK_NAKM (0x1UL << 13) /*!< OUT Packet NAK interrupt mask */
#endif /* defined USB_OTG_DOEPMSK_NAKM */
#ifndef USB_OTG_DOEPINT_STPKTRX
#define USB_OTG_DOEPINT_STPKTRX (0x1UL << 15) /*!< Setup Packet Received interrupt */
#endif /* defined USB_OTG_DOEPINT_STPKTRX */
#ifndef USB_OTG_DOEPMSK_NYETM
#define USB_OTG_DOEPMSK_NYETM (0x1UL << 14) /*!< Setup Packet Received interrupt mask */
#endif /* defined USB_OTG_DOEPMSK_NYETM */
#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
/*------------------------------------------------------------------------------------
Exported Functions
------------------------------------------------------------------------------------*/
/* Initialization/de-initialization functions ********************************/
/** @addtogroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
* @{
*/
HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd);
void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd);
void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCDEx_SetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo, uint16_t size);
HAL_StatusTypeDef HAL_PCDEx_SetRxFiFo(PCD_HandleTypeDef *hpcd, uint16_t size);
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
/** @defgroup HAL_PCD_Callback_ID_enumeration_definition HAL USB OTG PCD Callback ID enumeration definition
* @brief HAL USB OTG PCD Callback ID enumeration definition
* @{
*/
typedef enum
{
HAL_PCD_SOF_CB_ID = 0x01, /*!< USB PCD SOF callback ID */
HAL_PCD_SETUPSTAGE_CB_ID = 0x02, /*!< USB PCD Setup Stage callback ID */
HAL_PCD_RESET_CB_ID = 0x03, /*!< USB PCD Reset callback ID */
HAL_PCD_SUSPEND_CB_ID = 0x04, /*!< USB PCD Suspend callback ID */
HAL_PCD_RESUME_CB_ID = 0x05, /*!< USB PCD Resume callback ID */
HAL_PCD_CONNECT_CB_ID = 0x06, /*!< USB PCD Connect callback ID */
HAL_PCD_DISCONNECT_CB_ID = 0x07, /*!< USB PCD Disconnect callback ID */
HAL_PCD_MSPINIT_CB_ID = 0x08, /*!< USB PCD MspInit callback ID */
HAL_PCD_MSPDEINIT_CB_ID = 0x09 /*!< USB PCD MspDeInit callback ID */
} HAL_PCD_CallbackIDTypeDef;
/**
* @}
*/
/** @defgroup HAL_PCD_Callback_pointer_definition HAL USB OTG PCD Callback pointer definition
* @brief HAL USB OTG PCD Callback pointer definition
* @{
*/
typedef void (*pPCD_CallbackTypeDef)(PCD_HandleTypeDef *hpcd); /*!< pointer to a common USB OTG PCD callback function */
typedef void (*pPCD_DataOutStageCallbackTypeDef)(PCD_HandleTypeDef *hpcd, uint8_t epnum); /*!< pointer to USB OTG PCD Data OUT Stage callback */
typedef void (*pPCD_DataInStageCallbackTypeDef)(PCD_HandleTypeDef *hpcd, uint8_t epnum); /*!< pointer to USB OTG PCD Data IN Stage callback */
typedef void (*pPCD_IsoOutIncpltCallbackTypeDef)(PCD_HandleTypeDef *hpcd, uint8_t epnum); /*!< pointer to USB OTG PCD ISO OUT Incomplete callback */
typedef void (*pPCD_IsoInIncpltCallbackTypeDef)(PCD_HandleTypeDef *hpcd, uint8_t epnum); /*!< pointer to USB OTG PCD ISO IN Incomplete callback */
typedef void (*pPCD_LpmCallbackTypeDef)(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg); /*!< pointer to USB OTG PCD LPM callback */
typedef void (*pPCD_BcdCallbackTypeDef)(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg); /*!< pointer to USB OTG PCD BCD callback */
/**
* @}
*/
HAL_StatusTypeDef HAL_PCD_RegisterCallback(PCD_HandleTypeDef *hpcd,
HAL_PCD_CallbackIDTypeDef CallbackID,
pPCD_CallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef *hpcd,
HAL_PCD_CallbackIDTypeDef CallbackID);
HAL_StatusTypeDef HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd,
pPCD_DataOutStageCallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef *hpcd,
pPCD_DataInStageCallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd,
pPCD_IsoOutIncpltCallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd,
pPCD_IsoInIncpltCallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_RegisterBcdCallback(PCD_HandleTypeDef *hpcd,
pPCD_BcdCallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_PCD_UnRegisterBcdCallback(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_RegisterLpmCallback(PCD_HandleTypeDef *hpcd,
pPCD_LpmCallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_PCD_UnRegisterLpmCallback(PCD_HandleTypeDef *hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
/**
* @}
*/
/* I/O operation functions ***************************************************/
/* Non-Blocking mode: Interrupt */
/** @addtogroup PCD_Exported_Functions_Group2 Input and Output operation functions
* @{
*/
HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd);
void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd);
void HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef *hpcd);
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd);
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd);
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd);
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd);
void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd);
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd);
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd);
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum);
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum);
void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum);
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum);
/**
* @}
*/
/* Peripheral Control functions **********************************************/
/** @addtogroup PCD_Exported_Functions_Group3 Peripheral Control functions
* @{
*/
HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address);
HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
uint16_t ep_mps, uint8_t ep_type);
HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
uint8_t *pBuf, uint32_t len);
HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
uint8_t *pBuf, uint32_t len);
HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_EP_Abort(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
/**
* @}
*/
/* Peripheral State functions ************************************************/
/** @addtogroup PCD_Exported_Functions_Group4 Peripheral State functions
* @{
*/
PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd);
/**
* @}
*/
#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
#ifdef __cplusplus
}
#endif
#if 0
#if defined(USB_OTG_FS)
/*------------------------------------------------------------------------------------
Typedef
------------------------------------------------------------------------------------*/
/**
* @brief PCD State structure definition
*/
typedef enum
{
HAL_PCD_STATE_RESET = 0x00,
HAL_PCD_STATE_READY = 0x01,
HAL_PCD_STATE_ERROR = 0x02,
HAL_PCD_STATE_BUSY = 0x03,
HAL_PCD_STATE_TIMEOUT = 0x04
} PCD_StateTypeDef;
/* Device LPM suspend state */
typedef enum
{
LPM_L0 = 0x00, /* on */
LPM_L1 = 0x01, /* LPM L1 sleep */
LPM_L2 = 0x02, /* suspend */
LPM_L3 = 0x03, /* off */
} PCD_LPM_StateTypeDef;
typedef enum
{
PCD_LPM_L0_ACTIVE = 0x00, /* on */
PCD_LPM_L1_ACTIVE = 0x01, /* LPM L1 sleep */
} PCD_LPM_MsgTypeDef;
typedef enum
{
PCD_BCD_ERROR = 0xFF,
PCD_BCD_CONTACT_DETECTION = 0xFE,
PCD_BCD_STD_DOWNSTREAM_PORT = 0xFD,
PCD_BCD_CHARGING_DOWNSTREAM_PORT = 0xFC,
PCD_BCD_DEDICATED_CHARGING_PORT = 0xFB,
PCD_BCD_DISCOVERY_COMPLETED = 0x00,
} PCD_BCD_MsgTypeDef;
typedef USB_OTG_GlobalTypeDef PCD_TypeDef;
typedef USB_OTG_CfgTypeDef PCD_InitTypeDef;
typedef USB_OTG_EPTypeDef PCD_EPTypeDef;
/**
* @brief PCD Handle Structure definition
*/
typedef struct
{
PCD_TypeDef *Instance; /*!< Register base address */
PCD_InitTypeDef Init; /*!< PCD required parameters */
__IO uint8_t USB_Address; /*!< USB Address */
PCD_EPTypeDef IN_ep[16]; /*!< IN endpoint parameters */
PCD_EPTypeDef OUT_ep[16]; /*!< OUT endpoint parameters */
HAL_LockTypeDef Lock; /*!< PCD peripheral status */
__IO PCD_StateTypeDef State; /*!< PCD communication state */
__IO uint32_t ErrorCode; /*!< PCD Error code */
uint32_t Setup[12]; /*!< Setup packet buffer */
PCD_LPM_StateTypeDef LPM_State; /*!< LPM State */
uint32_t BESL;
uint32_t FrameNumber; /*!< Store Current Frame number */
uint32_t lpm_active; /*!< Enable or disable the Link Power Management .
This parameter can be set to ENABLE or DISABLE */
uint32_t battery_charging_active; /*!< Enable or disable Battery charging.
This parameter can be set to ENABLE or DISABLE */
void *pData; /*!< Pointer to upper stack Handler */
} PCD_HandleTypeDef;
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/** @defgroup PCD_Speed PCD Speed
* @{
*/
//#define PCD_SPEED_HIGH USBD_HS_SPEED
//#define PCD_SPEED_HIGH_IN_FULL USBD_HSINFS_SPEED
#define PCD_SPEED_FULL USBD_FS_SPEED
/**
* @}
*/
/** @defgroup PCD_PHY_Module PCD PHY Module
* @{
*/
#define PCD_PHY_ULPI 1U
#define PCD_PHY_EMBEDDED 2U
#define PCD_PHY_UTMI 3U
/**
* @}
*/
/** @defgroup PCD_Exported_Macros PCD Exported Macros
* @brief macros to handle interrupts and specific clock configurations
* @{
*/
#define __HAL_PCD_ENABLE(__HANDLE__) (void)USB_EnableGlobalInt ((__HANDLE__)->Instance)
#define __HAL_PCD_DISABLE(__HANDLE__) (void)USB_DisableGlobalInt ((__HANDLE__)->Instance)
#define __HAL_PCD_GET_FLAG(__HANDLE__, __INTERRUPT__) \
((USB_ReadInterrupts((__HANDLE__)->Instance) & (__INTERRUPT__)) == (__INTERRUPT__))
#define __HAL_PCD_CLEAR_FLAG(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->GINTSTS) &= (__INTERRUPT__))
#define __HAL_PCD_IS_INVALID_INTERRUPT(__HANDLE__) (USB_ReadInterrupts((__HANDLE__)->Instance) == 0U)
#define __HAL_PCD_UNGATE_PHYCLOCK(__HANDLE__) \
*(__IO uint32_t *)((uint32_t)((__HANDLE__)->Instance) + USB_OTG_PCGCCTL_BASE) &= ~(USB_OTG_PCGCCTL_STOPCLK)
#define __HAL_PCD_GATE_PHYCLOCK(__HANDLE__) \
*(__IO uint32_t *)((uint32_t)((__HANDLE__)->Instance) + USB_OTG_PCGCCTL_BASE) |= USB_OTG_PCGCCTL_STOPCLK
#define __HAL_PCD_IS_PHY_SUSPENDED(__HANDLE__) \
((*(__IO uint32_t *)((uint32_t)((__HANDLE__)->Instance) + USB_OTG_PCGCCTL_BASE)) & 0x10U)
//#define __HAL_USB_OTG_HS_WAKEUP_EXTI_ENABLE_IT() EXTI->IMR |= (USB_OTG_HS_WAKEUP_EXTI_LINE)
//#define __HAL_USB_OTG_HS_WAKEUP_EXTI_DISABLE_IT() EXTI->IMR &= ~(USB_OTG_HS_WAKEUP_EXTI_LINE)
//#define __HAL_USB_OTG_HS_WAKEUP_EXTI_GET_FLAG() EXTI->PR & (USB_OTG_HS_WAKEUP_EXTI_LINE)
//#define __HAL_USB_OTG_HS_WAKEUP_EXTI_CLEAR_FLAG() EXTI->PR = (USB_OTG_HS_WAKEUP_EXTI_LINE)
//#define __HAL_USB_OTG_HS_WAKEUP_EXTI_ENABLE_RISING_EDGE() \
// do { \
// EXTI->FTSR &= ~(USB_OTG_HS_WAKEUP_EXTI_LINE); \
// EXTI->RTSR |= USB_OTG_HS_WAKEUP_EXTI_LINE; \
// } while(0U)
#define __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_IT() EXTI->IMR |= USB_OTG_FS_WAKEUP_EXTI_LINE
#define __HAL_USB_OTG_FS_WAKEUP_EXTI_DISABLE_IT() EXTI->IMR &= ~(USB_OTG_FS_WAKEUP_EXTI_LINE)
#define __HAL_USB_OTG_FS_WAKEUP_EXTI_GET_FLAG() EXTI->PR & (USB_OTG_FS_WAKEUP_EXTI_LINE)
#define __HAL_USB_OTG_FS_WAKEUP_EXTI_CLEAR_FLAG() EXTI->PR = USB_OTG_FS_WAKEUP_EXTI_LINE
#define __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_RISING_EDGE() \
do { \
EXTI->FTSR &= ~(USB_OTG_FS_WAKEUP_EXTI_LINE); \
EXTI->RTSR |= USB_OTG_FS_WAKEUP_EXTI_LINE; \
} while(0U)
/** @defgroup USB_EXTI_Line_Interrupt USB EXTI line interrupt
* @{
*/
#define USB_OTG_FS_WAKEUP_EXTI_LINE (0x1U << 18) /*!< USB FS EXTI Line WakeUp Interrupt */
//#define USB_OTG_HS_WAKEUP_EXTI_LINE (0x1U << 20) /*!< USB HS EXTI Line WakeUp Interrupt */
/**
* @}
*/
#ifndef USB_OTG_DOEPINT_OTEPSPR
#define USB_OTG_DOEPINT_OTEPSPR (0x1UL << 5) /*!< Status Phase Received interrupt */
#endif /* defined USB_OTG_DOEPINT_OTEPSPR */
#ifndef USB_OTG_DOEPMSK_OTEPSPRM
#define USB_OTG_DOEPMSK_OTEPSPRM (0x1UL << 5) /*!< Setup Packet Received interrupt mask */
#endif /* defined USB_OTG_DOEPMSK_OTEPSPRM */
#ifndef USB_OTG_DOEPINT_NAK
#define USB_OTG_DOEPINT_NAK (0x1UL << 13) /*!< NAK interrupt */
#endif /* defined USB_OTG_DOEPINT_NAK */
#ifndef USB_OTG_DOEPMSK_NAKM
#define USB_OTG_DOEPMSK_NAKM (0x1UL << 13) /*!< OUT Packet NAK interrupt mask */
#endif /* defined USB_OTG_DOEPMSK_NAKM */
#ifndef USB_OTG_DOEPINT_STPKTRX
#define USB_OTG_DOEPINT_STPKTRX (0x1UL << 15) /*!< Setup Packet Received interrupt */
#endif /* defined USB_OTG_DOEPINT_STPKTRX */
#ifndef USB_OTG_DOEPMSK_NYETM
#define USB_OTG_DOEPMSK_NYETM (0x1UL << 14) /*!< Setup Packet Received interrupt mask */
#endif /* defined USB_OTG_DOEPMSK_NYETM */
/*------------------------------------------------------------------------------------
Exported Functions
------------------------------------------------------------------------------------*/
/* Initialization/de-initialization functions ********************************/
/** @addtogroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
* @{
*/
HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd);
void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd);
void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCDEx_SetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo, uint16_t size);
HAL_StatusTypeDef HAL_PCDEx_SetRxFiFo(PCD_HandleTypeDef *hpcd, uint16_t size);
/**
* @}
*/
/* I/O operation functions ***************************************************/
/* Non-Blocking mode: Interrupt */
/** @addtogroup PCD_Exported_Functions_Group2 Input and Output operation functions
* @{
*/
HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd);
void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd);
void HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef *hpcd);
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd);
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd);
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd);
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd);
void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd);
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd);
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd);
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum);
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum);
void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum);
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum);
/**
* @}
*/
/* Peripheral Control functions **********************************************/
/** @addtogroup PCD_Exported_Functions_Group3 Peripheral Control functions
* @{
*/
HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address);
HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
uint16_t ep_mps, uint8_t ep_type);
HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
uint8_t *pBuf, uint32_t len);
HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
uint8_t *pBuf, uint32_t len);
HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd);
HAL_StatusTypeDef HAL_PCD_EP_Abort(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
/**
* @}
*/
/* Peripheral State functions ************************************************/
/** @addtogroup PCD_Exported_Functions_Group4 Peripheral State functions
* @{
*/
PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd);
/**
* @}
*/
#endif /* defined (USB_OTG_FS) */
#endif
#endif /* __XC_HAL_PCD_NP_H */
@@ -0,0 +1,272 @@
/*!
* \file xc_hal_usb.c
*
* \brief Target xinchip hal usb implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_hal_usb.h"
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define USB_RESET_ON( ) cpr_rf_reg1__usb_rstn_reg__setf(0)//CLEAR_BIT(XC_CPR->RF_REG1, (1 << 20))
#define USB_RESET_OFF( ) cpr_rf_reg1__usb_rstn_reg__setf(1)//SET_BIT(XC_CPR->RF_REG1, (1 << 20))
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief usb phy dm operation
* @param uint32_t - bit
* @retval None
*/
void USB_Phy_DM_Oprt(uint32_t bit)
{
cpr_rf_reg5__usb_rwreg__setf(bit << 3);
// if(bit == PULL_UP)
// SET_BIT(XC_CPR->RF_REG5, (bit << 3));
// else if(bit == PULL_DOWN)
// CLEAR_BIT(XC_CPR->RF_REG5, (bit << 3));
}
/**
* @brief usb phy dp operation
* @param uint32_t - bit
* @retval None
*/
void USB_Phy_DP_Oprt(uint32_t bit)
{
cpr_rf_reg5__usb_rwreg__setf(bit << 2);
// if(bit == PULL_UP)
// SET_BIT(XC_CPR->RF_REG5, (bit << 2));
// else if(bit == PULL_DOWN)
// CLEAR_BIT(XC_CPR->RF_REG5, (bit << 2));
}
/**
* @brief usb phy enable
* @param void
* @retval None
*/
void USB_Phy_Enable( void )
{
cpr_rf_reg5__usb_rwreg__setf(0 << 4);
// CLEAR_BIT(XC_CPR->RF_REG5, (1 << 4));
// SET_BIT(XC_CPR->RF_REG5, (1 << 4));
}
/**
* @brief usb phy disable
* @param void
* @retval None
*/
void USB_Phy_Disable( void )
{
cpr_rf_reg5__usb_rwreg__setf(1 << 4);
// SET_BIT(XC_CPR->RF_REG5, (1 << 4));
}
#define readl(addr) (*(volatile unsigned int *) (addr))
#define writel(addr, value) (*(volatile unsigned int *) (addr) = (value))
/**
* @brief 32M OSC multiper bbpll to 96M
* @param void
* @retval None
*/
void OSC32M_Multi_BBPLL_96M( void )
{
#if (XC6XX_5C != 1)
if(xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_32M)
{
xc_clock_bbpll_common_cfg( );
rf_ana27__bbpll_16m_sel__setf(DISABLE);
rf_ana27__bbpll_core_96m_en__setf(ENABLE);
rf_ana26__bbpll_loopdiv__setf(0x06);
rf_ana26__clk_bbpll_en__setf(ENABLE);
rf_ana26__clk_bbpll_rstn__setf(ENABLE);
rf_ana26__bbpll_en__setf(ENABLE);
rf_ana26__bbpll_core_64m_en__setf(ENABLE);
// /* BT_CLK 时钟控制寄存器 */
// XC_CPR->BT_CLK_CTL = (CPR_BT_CLK_CTL_BT_CLK_EN_ENABLE | (CPR_BT_CLK_CTL_BT_CLK_EN_Msk << 16));
// /* BT_MODEM_CLK 时钟控制寄存器 */
//// XC_CPR->BT_MODEM_CTL = (CPR_BT_MODEM_CLK_CTL_BT_MODEM_CLK_EN_ENABLE |
//// (CPR_BT_MODEM_CLK_CTL_BT_MODEM_CLK_EN_Msk << 16));
// /* 配置 BT_PCLK_EN 使能 */
// XC_CPR->CTLAPBCLKEN_GRCTL |= (CPR_CTLAPBCLKEN_GRCTL_BT_PCLK_EN_ENABLE |
// (CPR_CTLAPBCLKEN_GRCTL_BT_PCLK_EN_Msk << CPR_CTLAPBCLKEN_GRCTL_MASK_OFFSET));
//
// SET_BIT(XC_BT_RF->BT.rx_pm_reg_l, (1 << 14));
// XC_CPR_AO->AON_CORERFLDO_EN = 0x1;
// SET_BIT(XC_BT_RF->ana26_reg_l, (0xf << 12));
// SET_BIT(XC_BT_RF->ana27_reg_l, 0x02); // ana27 div 2
// SET_BIT(XC_BT_RF->ana26_reg_l, 0x06); // ana26 6*32 / 2 = 192M / 2 = 96M
}
#else
uint32_t last_idx = xc_clock_hfclk_in_get()/1000000;
// CLEAR_BIT(XC_CPR->RF_REG4, (uint32_t)0x1f);
// SET_BIT(XC_CPR->RF_REG4, (uint32_t)0x11);
// CLEAR_BIT(XC_CPR->RF_REG3, (uint32_t)(0x07 | (0x1f<<8) | (0x3f<<14)));
// SET_BIT(XC_CPR->RF_REG3, (uint32_t)((0x1 << 1) | (0x07<<8) | (0x08<<14)));
uint32_t val = XC_CPR->RF_REG4;
XC_CPR->RF_REG4 = (val & 0xFFFFFFE0) | 0x11; // div2
val = XC_CPR->RF_REG3;
//[00-OSC32M],[01-bbpll direct output],[10-bbpll div output],[11-rc16M]
XC_CPR->RF_REG3 = (val & (~(uint32_t)(0x07 | (0x1f<<8) | (0x3f<<14)))) |
(0x1 << 1) | (0x07<<8) | (0x08<<14);
m_clock_cb.hfclk_in = CLOCK_HFCLK_IN_96M;
uint32_t baudrate, uart_clk, div, mul, clk_ctl, adj_div;
uart_clk = xc_clock_hfclk_in_get();
baudrate = XC_CPR->UART0_CLK_CTL;
mul = (baudrate >> 16) & 0xFFFF;
div = (baudrate & 0xFFFF);
adj_div = uart_clk / 1000000;
clk_ctl = (mul << 16 ) | ( div * adj_div / last_idx);
XC_CPR->UART0_CLK_CTL = clk_ctl;
SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
SysTick_Config(xc_clock_hfclk_in_get() / 100);
#endif
}
/**
* @brief usb bbpll close
* @param void
* @retval None
*/
void USB_BBPLL_Close( void )
{
rf_ana26__bbpll_core_64m_en__setf(DISABLE);
rf_ana26__bbpll_en__setf(DISABLE);
rf_ana26__clk_bbpll_rstn__setf(DISABLE);
rf_ana26__clk_bbpll_en__setf(DISABLE);
rf_ana26__bbpll_loopdiv__setf(0x00);
// CLEAR_BIT(XC_BT_RF->ana26_reg_l, (0xf << 12));
// CLEAR_BIT(XC_BT_RF->ana26_reg_l, 0x06);
}
/**
* @brief usb pll enable
* @param void
* @retval None
*/
void USB_PLL_Enable( void )
{
clock_cb.hfclk_src = CLOCK_HFCLK_SRC_XTAL;
clock_cb.hfclk_in = CLOCK_HFCLK_IN_48M;
extern void xc_clock_set_osc32m_bbpll_48m(CLOCK_InitCfg_t *cb);
xc_clock_set_osc32m_bbpll_48m(&clock_cb);
clock_cb.hfclk_in = CLOCK_HFCLK_IN_48M;
clock_cb.systick_unit = SYSTICK_UNIT_IN_48M;
cpr_rf_reg1__usb_mclk_div__setf(1);
cpr_rf_reg1__usb_hclk_en__setf(1);
cpr_rf_reg1__usb_mclk_en__setf(1);
cpr_rf_reg1__usb_utmi_clk_div__setf(1);
cpr_rf_reg1__usb_utmi_clk_en__setf(1);
// WRITE_REG(XC_CPR->RF_REG1, (XC_CPR->RF_REG1 & 0xE0FFCFF0) | 0x11003001); // usb clk enable
}
/**
* @brief usb pll disable
* @param void
* @retval None
*/
void USB_PLL_Disable( void )
{
USB_BBPLL_Close( );
}
/**
* @brief usb phy init
* @param void
* @retval None
*/
void USB_Phy_Init( void )
{
USB_PLL_Enable( );
USB_RESET_ON( );
HAL_Delay(100);//for(int i = 0; i < 0x4550; i++);//HAL_Delay(100);
USB_RESET_OFF( );
}
/**
* @brief usb phy deinit
* @param void
* @retval None
*/
void USB_Phy_Deinit( void )
{
cpr_rf_reg1__usb_utmi_clk_en__setf(0);
cpr_rf_reg1__usb_utmi_clk_div__setf(0);
cpr_rf_reg1__usb_hclk_en__setf(0);
cpr_rf_reg1__usb_mclk_en__setf(0);
// WRITE_REG(XC_CPR->RF_REG1, (XC_CPR->RF_REG1 & 0xE0FFCFF0) | (~0x00003000)); // usb clk disable
USB_Phy_Disable( );
NVIC_DisableIRQ(USB_IRQn);
}
/**
* @brief usb phy reset
* @param void
* @retval None
*/
void USB_Phy_Reset( void )
{
USB_RESET_ON( );
HAL_Delay(150); //for(int i = 0; i < 0x4550; i++);//HAL_Delay(100);
USB_RESET_OFF( );
HAL_Delay(10);
}
/**
* @brief usb current control
* @param uint8_t - val
* @retval None
*/
void USB_Current_Ctrl( uint8_t val )
{
cpr_rf_reg5__usbphy_usb_ibc__setf(val);
// CLEAR_BIT(XC_CPR->RF_REG5, (3 << 21));
// SET_BIT(XC_CPR->RF_REG5, (val << 21));
}
@@ -0,0 +1,68 @@
/*!
* \file xc_hal_usb.h
*
* \brief The header of xc_hal_usb.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
#ifndef __XC_HAL_USB_H_
#define __XC_HAL_USB_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdint.h>
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
//#define SET_REG_BIT(REG, BIT) ((REG) |= (BIT))
//#define CLEAR_REG_BIT(REG, BIT) ((REG) &= ~(BIT))
//#define READ_BIT(REG, BIT) ((REG) & (BIT))
//#define CLEAR_REG(REG) ((REG) = (0x0))
//#define WRITE_REG(REG, VAL) ((REG) = (VAL))
//#define READ_REG(REG) ((REG))
#define PULL_UP 1U
#define PULL_DOWN 0U
/*------------------------------------------------------------------------------------
Exported Functions
------------------------------------------- -----------------------------------------*/
void USB_Phy_DM_Oprt(uint32_t bit);
void USB_Phy_DP_Oprt(uint32_t bit);
void USB_Phy_Enable( void );
void USB_Phy_Disable( void );
void USB_PLL_Enable( void );
void USB_PLL_Disable( void );
void USB_Phy_Init( void );
void USB_Phy_Deinit( void );
void USB_Phy_Reset( void );
void USB_Current_Ctrl( uint8_t val );
#endif /* __XC_HAL_USB_H_ */
File diff suppressed because it is too large Load Diff