Sync inav to Gitea
Make sure docs are updated / settings_md (push) Canceled after 0s
Build firmware / test (push) Canceled after 0s
Build firmware / build-SITL-Windows (push) Canceled after 0s
Build firmware / build-SITL-Mac (push) Canceled after 0s
Build firmware / build-SITL-Linux (push) Canceled after 0s
Build firmware / build-SITL-Linux-arm64 (push) Canceled after 0s
Build firmware / upload-artifacts (push) Canceled after 0s
Build firmware / build-single-target (push) Canceled after 0s
Build firmware / build (9) (push) Canceled after 0s
Build firmware / build (8) (push) Canceled after 0s
Build firmware / build (7) (push) Canceled after 0s
Build firmware / build (6) (push) Canceled after 0s
Build firmware / build (5) (push) Canceled after 0s
Build firmware / build (4) (push) Canceled after 0s
Build firmware / build (3) (push) Canceled after 0s
Build firmware / build (2) (push) Canceled after 0s
Build firmware / build (14) (push) Canceled after 0s
Build firmware / build (13) (push) Canceled after 0s
Build firmware / build (12) (push) Canceled after 0s
Build firmware / build (11) (push) Canceled after 0s
Build firmware / build (10) (push) Canceled after 0s
Build firmware / build (1) (push) Canceled after 0s
Build firmware / build (0) (push) Canceled after 0s
Build firmware / detect (push) Canceled after 0s
Build pre-release / build (push) Canceled after 0s
Build pre-release / Release (push) Canceled after 0s

This commit is contained in:
2026-08-03 16:37:40 +08:00
commit dac37fd077
14095 changed files with 5603119 additions and 0 deletions
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

@@ -0,0 +1,3 @@
# This middleware library is unavailable in this repository
In this repository, this middleware library **along with** the projects (demos, applications, and examples) using it, are **not available**. Please refer to the [README.md](../../../README.md#some-middleware-libraries-and-projects-are-unavailable-in-this-repository) file at the root of this repository for further details.
@@ -0,0 +1,219 @@
/**
******************************************************************************
* @file net_address.h
* @author MCD Application Team
* @brief Header for the network address management functions
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#ifndef NET_ADDRESS_H
#define NET_ADDRESS_H
#include "string.h"
#include <stdlib.h>
#include "net_types.h"
#define NET_ZERO(a) (void) memset(&a,0,sizeof(a))
#define NET_EQUAL(a,b) (memcmp(&(a),&(b),sizeof(a))==0)
#define NET_DIFF(a,b) (memcmp(&(a),&(b),sizeof(a))!=0)
#define NET_COPY(a,b) (void) memcpy(&a,&b,sizeof(a))
#ifdef NET_USE_LWIP_DEFINITIONS
/*cstat -MISRAC* -DEFINE-* -CERT-EXP19* */
#include "lwip/sockets.h"
#include "lwip/ip_addr.h"
#include "lwip/inet.h"
/*cstat +MISRAC* +DEFINE-* +CERT-EXP19* */
typedef struct sockaddr_in net_sockaddr_in_t;
typedef struct sockaddr_in6 net_sockaddr_in6_t;
typedef struct sockaddr net_sockaddr_t;
typedef ip_addr_t net_ip_addr_t;
typedef in_addr_t net_in_addr_t;
#define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \
(sin)->sin_len = (uint8_t) sizeof(struct sockaddr_in); \
(sin)->sin_family = AF_INET; \
(sin)->sin_port = lwip_htons((port)); \
inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \
(void) memset((void*)(sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0)
#define NET_IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \
IP4ADDR_PORT_TO_SOCKADDR(( struct sockaddr_in*)( void*)(sockaddr), ipaddr, port)
#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \
inet_addr_to_ip4addr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \
(port) = lwip_ntohs((sin)->sin_port); }while(0)
#define NET_SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \
SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, port)
#define NET_IP_ADDR_CMP ip_addr_cmp
#define NET_IP_ADDR_ISANY_VAL ip_addr_isany_val
#define NET_IP_ADDR_COPY ip_addr_copy
#define NET_HTONL htonl
#define NET_NTOHL ntohl
#define NET_HTONS htons
#define NET_NTOHS ntohs
#define NET_NTOA_R ipaddr_ntoa_r
#define NET_NTOA ipaddr_ntoa
#define NET_ATON ip4addr_aton
#define NET_ATON_R ipaddr_addr
#define NET_IPADDR4_INIT(u32val) { u32val }
#define NET_IPADDR4_INIT_BYTES(a,b,c,d) NET_IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d)))
#else /* NET_USE_LWIP_DEFINTIONS */
#define NET_IP_ADDR_CMP(addr1, addr2) ((addr1)->addr == (addr2)->addr)
#define NET_IP_ADDR_COPY(dest, src) ((dest).addr = (src).addr)
/** Safely copy one IP address to another (src may be NULL) */
#define NET_IP_ADDR_SET(dest, src) ((dest)->addr = \
((src) == NULL ? 0 : \
(src)->addr))
/** Set complete address to zero */
#define NET_IP_ADDR_SET_ZERO(ipaddr) ((ipaddr)->addr = 0U)
#define NET_IP_ADDR_ISANY_VAL(addr1) ((addr1).addr == 0U)
#define NET_SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) do { \
(ipaddr)->addr = (sockaddr)->sin_addr.s_addr;\
(port) = NET_NTOHS((sockaddr)->sin_port); }while(0)
#define NET_IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \
(sin)->sin_len = (uint8_t) sizeof(net_sockaddr_in_t); \
(sin)->sin_family = NET_AF_INET; \
(sin)->sin_port = NET_HTONS((port)); \
(sin)->sin_addr.s_addr = (ipaddr)->addr;\
memset((void*)(sin)->sin_zero, 0, NET_SIN_ZERO_LEN); }while(0)
#define NET_IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \
NET_IP4ADDR_PORT_TO_SOCKADDR(( net_sockaddr_in_t*)( void*)(sockaddr), ipaddr, port)
#define NET_HTONL(A) ((((uint32_t)(A) & 0xff000000U) >> 24) | \
(((uint32_t)(A) & 0x00ff0000U) >> 8) | \
(((uint32_t)(A) & 0x0000ff00U) << 8) | \
(((uint32_t)(A) & 0x000000ffU) << 24))
#define NET_NTOHL NET_HTONL
#define NET_HTONS(A) ((((uint16_t)(A) & 0xff00U) >> 8U) | \
(((uint16_t)(A) & 0x00ffU) << 8U))
#define NET_NTOHS NET_HTONS
#define NET_NTOA net_ntoa
#define NET_NTOA_R net_ntoa_r
#define NET_ATON net_aton
#define NET_ATON_R net_aton_r
#define NET_NULL_IP_ADDR 0U
#define NET_PP_HTONL(x) ((((x) & 0x000000ffUL) << 24) | \
(((x) & 0x0000ff00UL) << 8) | \
(((x) & 0x00ff0000UL) >> 8) | \
(((x) & 0xff000000UL) >> 24))
#define NET_ASLWIP_MAKEU32(a,b,c,d) (((uint32_t)((a) & 0xff) << 24) | \
((uint32_t)((b) & 0xff) << 16) | \
((uint32_t)((c) & 0xff) << 8) | \
(uint32_t)((d) & 0xff))
#define NET_IPADDR4_INIT(u32val) { u32val }
#define NET_IPADDR4_INIT_BYTES(a,b,c,d) NET_IPADDR4_INIT(NET_PP_HTONL(NET_ASLWIP_MAKEU32(a,b,c,d)))
#define inet_addr_from_ip4addr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr))
#define inet_addr_to_ip4addr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr))
/* ATTENTION: the next define only works because both s_addr and ip4_addr_t are an u32_t effectively! */
#define inet_addr_to_ip4addr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*\
)&((source_inaddr)->s_addr))
/** IPv4 only: set the IP address given as an u32_t */
#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32))
/** IPv4 only: get the IP address as an u32_t */
#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr)
/* generic socket address structure to support IPV6 and IPV4 */
/* size is 16 bytes and is aligned on LWIP definition to ease integration */
typedef struct
{
uint32_t addr;
} net_ip4_addr_t;
typedef struct net_in_addr
{
uint32_t s_addr;
} net_in_addr_t;
/* Only IPv4 is managed */
typedef net_ip4_addr_t net_ip_addr_t;
typedef struct net_sockaddr
{
uint8_t sa_len;
uint8_t sa_family;
char_t sa_data[14];
} net_sockaddr_t;
/* IPV4 address , with 8 stuffing byte */
#define NET_SIN_ZERO_LEN 8
typedef struct net_sockaddr_in
{
uint8_t sin_len;
uint8_t sin_family;
uint16_t sin_port;
net_in_addr_t sin_addr;
char_t sin_zero[NET_SIN_ZERO_LEN];
} net_sockaddr_in_t;
char_t *net_ntoa(const net_ip_addr_t *addr);
char_t *net_ntoa_r(const net_ip_addr_t *addr, char_t *buf, int32_t buflen);
int32_t net_aton_r(const char_t *cp);
int32_t net_aton(const char_t *cp, net_ip_addr_t *addr);
#endif /* NET_USE_LWIP_DEFINTIONS */
#define S_ADDR(a) (a).s_addr
typedef net_sockaddr_in_t sockaddr_in_t;
#if NET_USE_IPV6
typedef net_sockaddr_in6_t sockaddr_in6_t;
#endif /* NET_USE_IPV6 */
typedef net_sockaddr_t sockaddr_t;
/** MAC address. */
typedef struct
{
uint8_t mac[6];
} macaddr_t;
void net_set_port(net_sockaddr_t *addr, uint16_t port);
uint16_t net_get_port(net_sockaddr_t *addr);
net_ip_addr_t net_get_ip_addr(net_sockaddr_t *addr);
typedef struct net_if_handle_s net_if_handle_t;
#endif /* NET_ADDRESS_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,31 @@
/**
******************************************************************************
* @file net_buffers.h
* @author MCD Application Team
* @brief Defines buffer allocation functions
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#ifndef NET_BUFFERS_H
#define NET_BUFFERS_H
#include "lwip/pbuf.h"
#define NET_BUF_ALLOC(n) (net_buf_t*)pbuf_alloc(PBUF_RAW, n, PBUF_POOL)
#define NET_BUF_REF_ALLOC() (net_buf_t*)pbuf_alloc(PBUF_RAW, 0, PBUF_REF);
#define NET_BUF_FREE(p) pbuf_free((struct pbuf*)p);
#define NET_BUF_REF(p) pbuf_ref((struct pbuf*)p);
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
#endif /* NET_BUFFERS_H */
@@ -0,0 +1,83 @@
/**
******************************************************************************
* @file net_cellular.h
* @author MCD Application Team
* @brief Header for the network Cellular class.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#ifndef NET_CELLULAR_H
#define NET_CELLULAR_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef NET_CELLULAR_CREDENTIAL_V2
/* SIM socket type */
#define NET_SIM_SLOT_MODEM_SOCKET 0 /* Modem Socket SIM Slot */
#define NET_SIM_SLOT_MODEM_EMBEDDED_SIM 1 /* Modem Embedded SIM Slot */
#define NET_CELLULAR_MAX_SUPPORTED_SLOT 2 /* Number max of supported SIM slot */
#define NET_CELLULAR_DEFAULT_SIM_SLOT NET_SIM_SLOT_MODEM_SOCKET /* Default SIM Slot */
typedef char_t net_sim_slot_type_t ;
/* SIM Slot parameters */
typedef struct net_cellular_sim_slot_s
{
net_sim_slot_type_t sim_slot_type; /* sim slot type */
char_t *apn; /* APN (string) */
char_t cid; /* CID (1-9) */
char_t *username; /* username: empty string => no username */
char_t *password; /* password (used only is username is defined) */
} net_cellular_sim_slot_t;
/* Credential configuration */
typedef struct net_cellular_credentials_s
{
uint8_t sim_socket_nb; /* number of sim slot used */
net_cellular_sim_slot_t sim_slot[NET_CELLULAR_MAX_SUPPORTED_SLOT]; /* sim slot parameters */
} net_cellular_credentials_t;
#else /*NET_CELLULAR_CREDENTIAL_V2 */
/* Credential configuration */
typedef struct net_cellular_credentials_s
{
const char_t *apn;
const char_t *username;
const char_t *password;
bool_t use_internal_sim;
} net_cellular_credentials_t;
#endif /* NET_CELLULAR_CREDENTIAL_V2 */
/* Network radio results */
typedef struct net_cellular_radio_results_s
{
int8_t signal_level_db;
} net_cellular_radio_results_t;
/* network extension for Cellular class interface */
int32_t net_cellular_set_credentials(net_if_handle_t *pnetif, const net_cellular_credentials_t *credentials);
int32_t net_cellular_get_radio_results(net_if_handle_t *pnetif, net_cellular_radio_results_t *results);
/* Declaration of cellular network interface constructor */
int32_t cellular_net_driver(net_if_handle_t *pnetif);
#ifdef __cplusplus
}
#endif
#endif /* NET_CELLULAR_H */
@@ -0,0 +1,71 @@
/**
******************************************************************************
* @file net_class_extension.h
* @author MCD Application Team
* @brief Header for the network class extensions
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef NET_CLASS_EXTENSION_H
#define NET_CLASS_EXTENSION_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct net_if_wifi_class_extension_s
{
int32_t (*scan)(net_if_handle_t *pnetif, net_wifi_scan_mode_t mode, char *ssid);
int32_t (*get_scan_results)(net_if_handle_t *pnetif, net_wifi_scan_results_t *results, uint8_t number);
int32_t (*set_credentials)(const net_wifi_credentials_t *cred);
int32_t (*get_system_info)(const net_wifi_system_info_t info, void *data);
int32_t (*set_param)(const net_wifi_param_t info, void *data);
const net_wifi_credentials_t *credentials;
net_wifi_mode_t mode;
/* Acces Point parameter */
uint8_t access_channel;
uint8_t max_connections;
bool AP_hidden;
const net_wifi_powersave_t *powersave;
void *ifp; /* Interface STA or AP handler */
} net_if_wifi_class_extension_t;
typedef struct net_if_ethernet_class_extension_s
{
int32_t (*version)(void);
} net_if_ethernet_class_extension_t;
typedef struct net_if_cellular_class_extension_s
{
int32_t (*get_radio_results)(net_cellular_radio_results_t *results);
const net_cellular_credentials_t *credentials;
} net_if_cellular_class_extension_t;
typedef struct net_if_custom_class_extension_s
{
int32_t (*version)(void);
} net_if_custom_class_extension_t;
#ifdef __cplusplus
}
#endif
#endif /* NET_CLASS_EXTENSION_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,206 @@
/**
******************************************************************************
* @file net_conf_template.h
* @author MCD Application Team
* @brief Configures the network socket APIs.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef NET_CONF_TEMPLATE_H
#define NET_CONF_TEMPLATE_H
#ifdef __cplusplus
extern "C" {
#endif
/* disable Misra rule to enable doxigen comment , A sectio of code appear to have been commented out */
/*cstat -MISRAC2012-Dir-4.4 */
/*cstat -MISRAC* -DEFINE-* -CERT-EXP19* */
#include <stdio.h>
/*cstat +MISRAC* +DEFINE-* +CERT-EXP19* */
/* Please uncomment if you want socket address defintion from LWIP include file rather than local one */
/* This is recommended if network interface uses LWIP to save some code size. This is required if */
/* project uses IPv6 */
/* #define NET_USE_LWIP_DEFINITIONS */
/* Experimental : Please uncomment if you want to use only control part of network library */
/* net_socket api are directly redifined to LWIP ,NET_MBEDTLS_HOST_SUPPORT is not supported with */
/* this mode, dedicated to save memory (4K code) */
/* #define NET_BYPASS_NET_SOCKET */
/* Please uncomment if secure socket have to be supported and is implemented thanks to MBEDTLS running on MCU */
/* #define NET_MBEDTLS_HOST_SUPPORT */
/* Please uncomment if device supports internally Secure TCP connection */
/* #define NET_MBEDTLS_DEVICE_SUPPORT */
#ifdef NET_USE_RTOS
/*cstat -MISRAC* -DEFINE-* -CERT-EXP19* */
#include "cmsis_os.h"
/*cstat +MISRAC* +DEFINE-* +CERT-EXP19* */
#endif /* NET_USE_RTOS */
/* when using LWIP , size of hostname */
#define NET_IP_HOSTNAME_MAX_LEN 32
#ifndef NET_USE_IPV6
#define NET_USE_IPV6 0
#endif /* NET_USE_IPV6 */
#if NET_USE_IPV6 && !defined(NET_USE_LWIP_DEFINTIONS)
#error "NET IPV6 required to define NET_USE_LWIP_DEFINTIONS"
#endif /* NET_USE_IPV6 */
/* MbedTLS configuration */
#ifdef NET_MBEDTLS_HOST_SUPPORT
#if !defined NET_MBEDTLS_DEBUG_LEVEL
#define NET_MBEDTLS_DEBUG_LEVEL 1
#endif /* NET_MBEDTLS_DEBUG_LEVEL */
#if !defined NET_MBEDTLS_CONNECT_TIMEOUT
#define NET_MBEDTLS_CONNECT_TIMEOUT 10000U
#endif /* NET_MBEDTLS_CONNECT_TIMEOUT */
#if !defined(MBEDTLS_CONFIG_FILE)
#define MBEDTLS_CONFIG_FILE "mbedtls/config.h"
#endif /* MBEDTLS_CONFIG_FILE */
#endif /* NET_MBEDTLS_HOST_SUPPORT */
#if !defined(NET_MAX_SOCKETS_NBR)
#define NET_MAX_SOCKETS_NBR 5
#endif /* NET_MAX_SOCKETS_NBR */
#define NET_IF_NAME_LEN 128
#define NET_DEVICE_NAME_LEN 64
#define NET_DEVICE_ID_LEN 64
#define NET_DEVICE_VER_LEN 64
#define NET_SOCK_DEFAULT_RECEIVE_TO 60000
#define NET_SOCK_DEFAULT_SEND_TO 60000
#define NET_UDP_MAX_SEND_BLOCK_TO 1024
#if !defined(NET_USE_DEFAULT_INTERFACE)
#define NET_USE_DEFAULT_INTERFACE 1
#endif /* NET_USE_DEFAULT_INTERFACE */
#ifdef NET_USE_RTOS
#if ( osCMSIS < 0x20000U)
#define RTOS_SUSPEND if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { (void) vTaskSuspendAll(); }
#define RTOS_RESUME if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { (void) xTaskResumeAll(); }
#else
#define RTOS_SUSPEND (void) osKernelLock()
#define RTOS_RESUME (void) osKernelUnlock()
#endif /* osCMSIS */
#else
#define RTOS_SUSPEND
#define RTOS_RESUME
#endif /* NET_USE_RTOS */
#if !defined(NET_DBG_INFO)
#define NET_DBG_INFO(...)
/*
#define NET_DBG_INFO(...) do { \
RTOS_SUSPEND; \
(void) printf(__VA_ARGS__); \
RTOS_RESUME; \
} while (0)
*/
#endif /* NET_DBG_INFO */
#if !defined(NET_DBG_ERROR)
#define NET_DBG_ERROR(...) do { \
RTOS_SUSPEND; \
(void) printf("\nERROR: %s:%d ",__FILE__,__LINE__) ;\
(void)printf(__VA_ARGS__);\
(void)printf("\n"); \
RTOS_RESUME; \
} while (false)
#endif /* NET_DBG_ERROR */
#if !defined(NET_DBG_PRINT)
#define NET_DBG_PRINT(...) do { \
RTOS_SUSPEND; \
(void)printf("%s:%d ",__FILE__,__LINE__) ;\
(void)printf(__VA_ARGS__);\
(void)printf("\n"); \
RTOS_RESUME; \
} while (false)
#endif /* NET_DBG_PRINT */
#if !defined(NET_ASSERT)
#define NET_ASSERT(test,...) do { if (!(test)) {\
RTOS_SUSPEND; \
(void) printf("Assert Failed %s %d :",__FILE__,__LINE__);\
(void) printf(__VA_ARGS__);\
RTOS_RESUME; \
while(true) {}; }\
} while (false)
#endif /* NET_ASSERT */
#if !defined(NET_PRINT)
#define NET_PRINT(...) do { \
RTOS_SUSPEND; \
(void) printf(__VA_ARGS__);\
(void) printf("\n"); \
RTOS_RESUME; \
} while (false)
#endif /* NET_PRINT */
#if !defined(NET_PRINT_WO_CR)
#define NET_PRINT_WO_CR(...) do { \
RTOS_SUSPEND; \
(void) printf(__VA_ARGS__);\
RTOS_RESUME; \
} while (false)
#endif /* NET_PRINT_WO_CR */
#if !defined(NET_WARNING)
#define NET_WARNING(...) do { \
RTOS_SUSPEND; \
(void) printf("Warning %s:%d ",__FILE__,__LINE__) ;\
(void) printf(__VA_ARGS__);\
(void) printf("\n"); \
RTOS_RESUME; \
} while (false)
#endif /* NET_WARNING */
#ifndef NET_PERF_MAXTHREAD
#define NET_PERF_MAXTHREAD 10U
#endif /* NET_PERF_MAXTHREAD */
#ifdef __cplusplus
}
#endif
#endif /* NET_CONF_TEMPLATE_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,312 @@
/**
******************************************************************************
* @file net_connect.h
* @author MCD Application Team
* @brief Provides the network interface APIs.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#ifndef NET_CONNECT_H
#define NET_CONNECT_H
#ifdef __cplusplus
extern "C" {
#endif
#include "net_types.h"
#include "net_conf.h"
#include "net_mem.h"
#include "net_perf.h"
#include "net_address.h"
#include "net_errors.h"
#include "net_wifi.h"
#include "net_cellular.h"
/* flags */
#define NET_ETHERNET_FLAG_DEFAULT_IF 1
/* Socket family */
#define NET_AF_INET 2
#define NET_AF_UNSPEC 0
#define NET_AF_INET6 10
#define NET_IPADDR_ANY ((u32_t)0x00000000UL)
/* Socket types */
#define NET_SOCK_STREAM 1
#define NET_SOCK_DGRAM 2
#define NET_SOCK_RAW 3
/* Socket protocol */
#define NET_IPPROTO_TCP 6
#define NET_IPPROTO_ICMP 1
#define NET_IPPROTO_UDP 17
#define NET_IPPROTO_TCP_TLS 36
#define NET_SHUTDOWN_R 0
#define NET_SHUTDOWN_W 1
#define NET_SHUTDOWN_RW 2
#define NET_SOL_SOCKET 0xfff
/** @defgroup Socket
* @{
*/
typedef enum
{
NET_SO_RCVTIMEO = 0x1006,/**< to set received timeout in ms, option type is an integer value */
NET_SO_SNDTIMEO = 0x1005,/**< to set send timeout in ms, option type is an integer value */
NET_SO_BINDTODEVICE = 3,/**< to map socket to a specific network interface, no implemented so far , normal bind should make the job */
NET_SO_BLOCKING = 4,/**< to set blocking or none blocking mode, option type is an boolean, true means blocking (default value), false non blocking */
NET_SO_SECURE = 5,/**< to set a socket a a secure socket, no option argument, setsock option must be done before any connection */
NET_SO_TLS_CA_CERT = 7,/**< to pass root ca to secure socket, option type is a pointer to a string , certificat is pem format string */
NET_SO_TLS_CA_CRL = 8,/**< to pass revocation certificat list, this is not supported */
NET_SO_TLS_DEV_KEY = 9,/**< to pass device key to secure socket, option type is a pointer to a string , key is pem format string */
NET_SO_TLS_DEV_CERT = 10,/**< to pass device certificat to secure socket, option type is a pointer to a string , certificat is pem format string */
NET_SO_TLS_SERVER_VERIFICATION = 11,/**< to define verification mode for secure socket,option type is a boolean, True to check server name */
NET_SO_TLS_SERVER_NAME = 12,/**< to define server name to check again,option type is a point to a null terminated string */
NET_SO_TLS_PASSWORD = 13,/**< to define passwd (if any) used to encrypt the device key, option type is pointer to a null terminated string */
NET_SO_TLS_CERT_PROF = 14,/**< to set the X509 security profile , option type is pointer to mbedtls_x509_crt_profile structure */
}
net_socketoption_t;
/** @defgroup Socket
* @}
*/
#define NET_MSG_DONTWAIT 0x08U /* Nonblocking i/o for this operation only */
typedef struct pbuf net_buf_t;
/**
* TOPPP transition are requested by application. "ING" state are transitioning state, meaning that application has required a transition and the transition is ongoing. "ED" states are stable state.
*/
typedef enum
{
NET_EVENT_STATE_CHANGE,
NET_EVENT,
NET_EVENT_WIFI,
} net_evt_t;
/** @defgroup State
* @{
* State transition are requested by application. "ING" state are transitioning state, meaning that application has required a transition and the transition is ongoing. "ED" states are stable state.
*/
typedef enum enum_state
{
NET_STATE_DEINITIALIZED = 0,
NET_STATE_INITIALIZED, /**< basic memory allocation for driver and network interface have been performed */
NET_STATE_STARTING, /**< Network interface interface is starting, application waits for event from network interface to signal transition is performed to NET_STATE_STARTED */
NET_STATE_READY, /**< Network interface interface is started, MAC address can be retrieved */
NET_STATE_CONNECTING,/**< Network interface interface is connecting */
NET_STATE_CONNECTED,/**< Network interface interface is connected, IP address can be retrieved , socket operation can be performed*/
NET_STATE_STOPPING, /**< Network interface interface is stopping */
NET_STATE_DISCONNECTING, /**< Network interface interface is disconnecting */
NET_STATE_CONNECTION_LOST, /**< Network interface connection is lost , this can be a transient state , it can return to connected state without application specific action*/
} net_state_t;
/** @defgroup State
* @}
*/
/** Network state events. */
typedef enum
{
NET_EVENT_CMD_INIT = 0,
NET_EVENT_CMD_START,
NET_EVENT_CMD_CONNECT,
NET_EVENT_CMD_DISCONNECT,
NET_EVENT_CMD_STOP,
NET_EVENT_CMD_DEINIT,
NET_EVENT_INTERFACE_INITIALIZED,
NET_EVENT_INTERFACE_READY,
NET_EVENT_LINK_UP,
NET_EVENT_LINK_DOWN,
NET_EVENT_IPADDR,
} net_state_event_t;
/** Network events. */
typedef enum
{
NET_EVENT_POWERSAVE_ENABLED = 0,
} net_event_t;
typedef struct net_if_drv_s net_if_drv_t;
typedef struct net_ip_if_s net_ip_if_t;
typedef void(* net_if_notify_func)(void *context, uint32_t event_class, uint32_t event_id, void *event_data);
typedef struct
{
net_if_notify_func callback;
void *context;
} net_event_handler_t;
struct net_if_handle_s
{
struct net_if_handle_s *next;
net_ip_addr_t ipaddr;
net_ip_addr_t gateway;
net_ip_addr_t netmask;
net_ip_addr_t static_ipaddr;
net_ip_addr_t static_gateway;
net_ip_addr_t static_netmask;
net_ip_addr_t static_dnserver;
bool_t dhcp_mode;
bool_t dhcp_inform_flag;
bool_t dhcp_enabled;
bool_t dhcp_release_on_link_lost;
char_t DeviceName[NET_DEVICE_NAME_LEN];
char_t DeviceID [NET_DEVICE_ID_LEN];
char_t DeviceVer [NET_DEVICE_VER_LEN];
macaddr_t macaddr;
net_state_t state;
net_if_drv_t *pdrv;
struct netif *netif;
const net_event_handler_t *event_handler;
} ;
typedef int32_t(* net_if_driver_init_func)(net_if_handle_t *pnetif);
/* network state control functions */
int32_t net_if_init(net_if_handle_t *pnetif, net_if_driver_init_func driver_init,
const net_event_handler_t *event_handler);
int32_t net_if_deinit(net_if_handle_t *pnetif);
int32_t net_if_start(net_if_handle_t *pnetif);
int32_t net_if_stop(net_if_handle_t *pnetif);
/* network io data receive process, called in main loop */
int32_t net_if_yield(net_if_handle_t *pnetif, uint32_t timeout);
int32_t net_if_connect(net_if_handle_t *pnetif);
int32_t net_if_disconnect(net_if_handle_t *pnetif);
int32_t net_if_getState(net_if_handle_t *pnetif, net_state_t *state);
int32_t net_if_wait_state(net_if_handle_t *pnetif, net_state_t state, uint32_t timeout);
/* network event management */
void net_if_notify(net_if_handle_t *pnetif, net_evt_t event_class, uint32_t event_if, void *event_data);
/* network parameter and status functions */
int32_t net_if_set_dhcp_mode(net_if_handle_t *pnetif, bool_t mode);
int32_t net_if_set_ipaddr(net_if_handle_t *pnetif, net_ip_addr_t ipaddr, net_ip_addr_t gateway, net_ip_addr_t netmask);
int32_t net_if_get_mac_address(net_if_handle_t *pnetif, macaddr_t *mac);
int32_t net_if_get_ip_address(net_if_handle_t *pnetif, net_ip_addr_t *ip);
int32_t net_if_gethostbyname(net_if_handle_t *pnetif, net_sockaddr_t *addr, char_t *name);
int32_t net_if_ping(net_if_handle_t *pnetif, net_sockaddr_t *addr, int32_t count, int32_t delay, int32_t reponse[]);
/* networtk interface power management */
int32_t net_if_powersave_enable(net_if_handle_t *pnetif);
int32_t net_if_powersave_disable(net_if_handle_t *pnetif);
#if 0
int32_t net_if_sleep(net_if_handle_t *pnetif);
int32_t net_if_wakeup(net_if_handle_t *pnetif);
#endif /* 0 */
/* network socket API */
#ifdef NET_BYPASS_NET_SOCKET
/*cstat -MISRAC* -DEFINE-* -CERT-EXP19* */
#include "lwip/netdb.h"
#include "lwip/dhcp.h"
#include "lwip/tcpip.h"
#include "lwip/etharp.h"
/*cstat +MISRAC* +DEFINE-* -CERT-EXP19* */
#define net_socket lwip_socket
#define net_bind lwip_bind
#define net_accept lwip_accept
#define net_closesocket lwip_close
#define net_shutdown lwip_shutdown
#define net_setsockopt lwip_setsockopt
#define net_getsockopt lwip_getsockopt
#define net_connect lwip_connect
#define net_listen lwip_listen
#define net_send lwip_send
#define net_recv lwip_recv
#define net_sendto lwip_sendto
#define net_recvfrom lwip_recvfrom
#define net_getsockname lwip_getsockname
#define net_getpeername lwip_getpeeername
#else
int32_t net_socket(int32_t Domain, int32_t Type, int32_t Protocol);
int32_t net_bind(int32_t sock, net_sockaddr_t *addr, uint32_t addrlen);
int32_t net_accept(int32_t sock, net_sockaddr_t *addr, uint32_t *addrlen);
int32_t net_closesocket(int32_t sock);
int32_t net_shutdown(int32_t sock, int32_t mode);
int32_t net_setsockopt(int32_t sock, int32_t level, net_socketoption_t optname, const void *optvalue, uint32_t optlen);
int32_t net_getsockopt(int32_t sock, int32_t level, net_socketoption_t optname, void *optvalue, uint32_t *optlen);
int32_t net_connect(int32_t sock, net_sockaddr_t *addr, uint32_t addrlen);
int32_t net_listen(int32_t sock, int32_t backlog);
int32_t net_send(int32_t sock, uint8_t *buf, uint32_t len, int32_t flags);
int32_t net_recv(int32_t sock, uint8_t *buf, uint32_t len, int32_t flags);
int32_t net_sendto(int32_t sock, uint8_t *buf, uint32_t len, int32_t flags, net_sockaddr_t *to, uint32_t tolen);
int32_t net_recvfrom(int32_t sock, uint8_t *buf, uint32_t len, int32_t flags, net_sockaddr_t *from, uint32_t *fromlen);
int32_t net_getsockname(int32_t sock, net_sockaddr_t *name, uint32_t *namelen);
int32_t net_getpeername(int32_t sock, net_sockaddr_t *name, uint32_t *namelen);
#endif /* NET_BYPASS_NET_SOCKET */
extern const int32_t net_tls_sizeof_suite_structure;
extern const void *net_tls_user_suite0;
extern const void *net_tls_user_suite1;
extern const void *net_tls_user_suite2;
extern const void *net_tls_user_suite3;
extern const void *net_tls_user_suite4;
#ifdef __cplusplus
}
#endif
#endif /* NET_CONNECT_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,216 @@
/**
******************************************************************************
* @file net_core.h
* @author MCD Application Team
* @brief Provides the network interface driver APIs.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef NET_CORE_H
#define NET_CORE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "net_state.h"
#include "net_wifi.h"
#include "net_class_extension.h"
/*cstat -MISRAC* -DEFINE-* -CERT-EXP19* */
/* #include "lwip/err.h" */
/*cstat +MISRAC* +DEFINE-* +CERT-EXP19* */
int32_t icmp_ping(net_if_handle_t *netif, net_sockaddr_t *addr, int32_t count, int32_t timeout, int32_t response[]);
#ifdef NET_USE_RTOS
void net_init_locks(void);
void net_destroy_locks(void);
void net_lock(int32_t idx, uint32_t to);
void net_unlock(int32_t idx);
void net_lock_nochk(int32_t idx, uint32_t to);
void net_unlock_nochk(int32_t idx);
/* OS */
#define NET_OS_WAIT_FOREVER 0xffffffffU
#define NET_LOCK_SOCKET_ARRAY NET_MAX_SOCKETS_NBR
#define NET_LOCK_NETIF_LIST NET_MAX_SOCKETS_NBR+1
#define NET_LOCK_STATE_EVENT NET_MAX_SOCKETS_NBR+2
#define NET_LOCK_NUMBER (NET_LOCK_STATE_EVENT+1)
#define LOCK_SOCK(s) net_lock((int32_t)s,NET_OS_WAIT_FOREVER)
#define UNLOCK_SOCK(s) net_unlock(s)
#define LOCK_SOCK_ARRAY() net_lock(NET_LOCK_SOCKET_ARRAY,NET_OS_WAIT_FOREVER)
#define UNLOCK_SOCK_ARRAY() net_unlock(NET_LOCK_SOCKET_ARRAY )
#define LOCK_NETIF_LIST() net_lock(NET_LOCK_NETIF_LIST,NET_OS_WAIT_FOREVER )
#define UNLOCK_NETIF_LIST() net_unlock(NET_LOCK_NETIF_LIST )
#define WAIT_STATE_CHANGE(to) net_lock_nochk(NET_LOCK_STATE_EVENT,to )
#define SIGNAL_STATE_CHANGE() net_unlock_nochk(NET_LOCK_STATE_EVENT )
#else
#define LOCK_SOCK(s)
#define UNLOCK_SOCK(s)
#define LOCK_SOCK_ARRAY()
#define UNLOCK_SOCK_ARRAY()
#define LOCK_NETIF_LIST()
#define UNLOCK_NETIF_LIST()
#define WAIT_STATE_CHANGE(to) pnetif->pdrv->if_yield(pnetif, 10)
#define SIGNAL_STATE_CHANGE()
#endif /* NET_USE_RTOS */
typedef enum
{
NET_INTERFACE_CLASS_WIFI,
NET_INTERFACE_CLASS_CELLULAR,
NET_INTERFACE_CLASS_ETHERNET,
NET_INTERFACE_CLASS_CUSTOM
}
net_interface_class_t;
typedef enum
{
NET_ACCESS_SOCKET,
NET_ACCESS_BIND,
NET_ACCESS_LISTEN,
NET_ACCESS_CONNECT,
NET_ACCESS_SEND,
NET_ACCESS_SENDTO,
NET_ACCESS_RECV,
NET_ACCESS_RECVFROM,
NET_ACCESS_CLOSE,
NET_ACCESS_SETSOCKOPT,
}
net_access_t;
struct net_if_drv_s
{
net_interface_class_t if_class;
/* Interface APIs */
int32_t (* if_init)(net_if_handle_t *pnetif);
int32_t (* if_deinit)(net_if_handle_t *pnetif);
int32_t (* if_start)(net_if_handle_t *pnetif);
int32_t (* if_stop)(net_if_handle_t *pnetif);
int32_t (* if_yield)(net_if_handle_t *pnetif, uint32_t timeout);
int32_t (* if_connect)(net_if_handle_t *pnetif);
int32_t (* if_disconnect)(net_if_handle_t *pnetif);
int32_t (* if_powersave_enable)(net_if_handle_t *pnetif);
int32_t (* if_powersave_disable)(net_if_handle_t *pnetif);
void *netif;
void *context;
#ifndef NET_BYPASS_NET_SOCKET
/* Socket BSD Like APIs */
int32_t (* psocket)(int32_t domain, int32_t type, int32_t protocol);
int32_t (* pbind)(int32_t sock, const net_sockaddr_t *addr, uint32_t addrlen);
int32_t (* plisten)(int32_t sock, int32_t backlog);
int32_t (* paccept)(int32_t sock, net_sockaddr_t *addr, uint32_t *addrlen);
int32_t (* pconnect)(int32_t sock, const net_sockaddr_t *addr, uint32_t addrlen);
int32_t (* psend)(int32_t sock, uint8_t *buf, int32_t len, int32_t flags);
int32_t (* precv)(int32_t sock, uint8_t *buf, int32_t len, int32_t flags);
int32_t (* psendto)(int32_t sock, uint8_t *buf, int32_t len, int32_t flags, net_sockaddr_t *to, uint32_t tolen);
int32_t (* precvfrom)(int32_t sock, uint8_t *buf, int32_t len, int32_t flags, net_sockaddr_t *from, uint32_t *flen);
int32_t (* psetsockopt)(int32_t sock, int32_t level, int32_t optname, const void *optvalue, uint32_t optlen);
int32_t (* pgetsockopt)(int32_t sock, int32_t level, int32_t optname, void *optvalue, uint32_t *optlen);
int32_t (* pgetsockname)(int32_t sock, net_sockaddr_t *name, uint32_t *namelen);
int32_t (* pgetpeername)(int32_t sock, net_sockaddr_t *name, uint32_t *namelen);
int32_t (* pclose)(int32_t sock, bool Clone);
int32_t (* pshutdown)(int32_t sock, int32_t mode);
#endif /* NET_BYPASS_NET_SOCKET */
/* Service */
int32_t (* pgethostbyname)(net_if_handle_t *, net_sockaddr_t *addr, char_t *name);
int32_t (* pping)(net_if_handle_t *, net_sockaddr_t *addr, int32_t count, int32_t delay, int32_t reponse[]);
/* class extension */
struct
{
net_if_wifi_class_extension_t *wifi;
net_if_ethernet_class_extension_t *ethernet;
net_if_cellular_class_extension_t *cellular;
net_if_custom_class_extension_t *custom;
} extension;
};
net_if_handle_t *net_if_find(net_sockaddr_t *addr);
net_if_handle_t *netif_check(net_if_handle_t *pnetif);
bool net_access_control(net_if_handle_t *pnetif, net_access_t access, int32_t *l);
typedef void (*sock_notify_func)(int32_t, int32_t, const uint8_t *, uint32_t);
typedef struct net_tls_data net_tls_data_t;
typedef int32_t net_ulsock_t;
typedef enum { SOCKET_NOT_ALIVE = 0, SOCKET_ALLOCATED, SOCKET_CONNECTED } socket_state_t;
typedef struct net_socket_s
{
net_if_handle_t *pnetif;
net_ulsock_t ulsocket;
socket_state_t status;
int32_t domain;
int32_t type;
int32_t protocol;
bool cloneserver;
bool connected;
#ifdef NET_MBEDTLS_HOST_SUPPORT
bool is_secure;
net_tls_data_t *tlsData;
bool tls_started;
#endif /* NET_MBEDTLS_HOST_SUPPORT */
int32_t read_timeout;
int32_t write_timeout;
bool blocking;
int32_t idx;
} net_socket_t;
#ifdef NET_MBEDTLS_HOST_SUPPORT
/*cstat -MISRAC* -DEFINE-* -CERT-EXP19* */
#include "net_mbedtls.h"
/*cstat +MISRAC* +DEFINE-* +CERT-EXP19* */
#endif /* NET_MBEDTLS_HOST_SUPPORT */
#ifdef __cplusplus
}
#endif
#endif /* NET_CORE_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,83 @@
/**
******************************************************************************
* @file net_errors.h
* @author MCD Application Team
* @brief Defines the network interface error codes
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef NET_ERRORS_H
#define NET_ERRORS_H
#ifdef __cplusplus
extern "C" {
#endif
#define NET_OK 0 /*!< no error */
#define NET_TIMEOUT -1 /*!< Timeout rearched during a blocking operation. */
#define NET_ERROR_WOULD_BLOCK -2 /*!< no data is available but call is non-blocking */
#define NET_ERROR_UNSUPPORTED -3 /*!< unsupported functionality */
#define NET_ERROR_PARAMETER -4 /*!< invalid parameter/configuration */
#define NET_ERROR_NO_CONNECTION -5 /*!< not connected to a network */
#define NET_ERROR_INVALID_SOCKET -6 /*!< socket invalid */
#define NET_ERROR_NO_ADDRESS -7 /*!< IP address is not known */
#define NET_ERROR_NO_MEMORY -8 /*!< memory resource not available */
#define NET_ERROR_NO_SSID -9 /*!< ssid not found */
#define NET_ERROR_DNS_FAILURE -10 /*!< DNS failed to complete successfully */
#define NET_ERROR_DHCP_FAILURE -11 /*!< DHCP failed to complete successfully */
#define NET_ERROR_AUTH_FAILURE -12 /*!< connection to access point failed */
#define NET_ERROR_DEVICE_ERROR -13 /*!< failure interfacing with the network processor */
#define NET_ERROR_IN_PROGRESS -14 /*!< operation (eg connect) in progress */
#define NET_ERROR_ALREADY -15 /*!< operation (eg connect) already in progress */
#define NET_ERROR_IS_CONNECTED -16 /*!< socket is already connected */
#define NET_ERROR_INTERFACE_FAILURE -17 /*!< an error in interface level */
#define NET_ERROR_DATA -18 /*!< an error in interface level */
#define NET_ERROR_SOCKET_FAILURE -19 /*!< an error in interface level */
#define NET_ERROR_OUT_OF_SOCKET -20 /*!< no more available socket , open failed */
#define NET_ERROR_CLOSE_SOCKET -21 /*!< error while closing socket */
#define NET_ERROR_DISCONNECTED -22 /*!< Connection dropped during the operation. */
#define NET_ERROR_CREATE_SECURE_SOCKET -23 /*!< failed to create the secure socket */
#define NET_ERROR_IS_NOT_SECURE -24 /*!< try to set secure option on a non secure socket */
#define NET_ERROR_FRAMEWORK -25 /*!< should never happen */
#define NET_ERROR_STATE_TRANSITION -26 /*!< should never happen */
#define NET_ERROR_INVALID_STATE_TRANSITION -27 /*!< should never happen */
#define NET_ERROR_INVALID_STATE -28 /*!< should never happen */
#define NET_ERROR_GENERIC -29 /*!< generic error */
#define NET_ERROR_MODULE_INITIALIZATION -30 /*!< module is not able to initialized */
#define NET_ERROR_WIFI_CANT_JOIN -31 /*!< wifi module is not able to join */
#define NET_ERROR_MBEDTLS_ENTROPY -100/*!<mbedtls enthropy setup failed */
#define NET_ERROR_MBEDTLS_CRT_PARSE -101/*!<mbedtls parsing certificat failed */
#define NET_ERROR_MBEDTLS_KEY_PARSE -102/*!<mbedtls parsing key failed */
#define NET_ERROR_MBEDTLS_SET_HOSTNAME -103/*!<mbedtls cannot setup hostname*/
#define NET_ERROR_MBEDTLS_SEED -104/*!<mbedtls seed setup failed */
#define NET_ERROR_MBEDTLS_REMOTE_AUTH -105/*!<mbedtls remote host could not be authentified */
#define NET_ERROR_MBEDTLS_CONFIG -106/*!<mbedtls error in config */
#define NET_ERROR_MBEDTLS_SSL_SETUP -107/*!<mbedtls error setting setup */
#define NET_ERROR_MBEDTLS_CONNECT -108/*!<mbedtls error while connecting */
#define NET_ERROR_MBEDTLS -109/*!<mbedtls error while reading writing data */
#ifdef __cplusplus
}
#endif
#endif /* NET_ERRORS_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,32 @@
/**
******************************************************************************
* @file net_internals.h
* @author MCD Application Team
* @brief Header for the network interface with mbedTLS (if used)
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef NET_INTERNALS_H
#define NET_INTERNALS_H
#include "net_core.h"
#ifdef NET_MBEDTLS_HOST_SUPPORT
/*cstat -MISRAC* -DEFINE-* -CERT-EXP19* */
#include "net_mbedtls.h"
/*cstat +MISRAC* +DEFINE-* +CERT-EXP19* */
#endif /* NET_MBEDTLS_HOST_SUPPORT */
#endif /* NET_INTERNALS_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,41 @@
/**
******************************************************************************
* @file net_ip_ethernet.h
* @author MCD Application Team
* @brief Header for the network interface on ethernet
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#ifndef NET_IP_ETHERNET_H
#define NET_IP_ETHERNET_H
#include "net_connect.h"
#include "net_internals.h"
/*cstat -MISRAC* -DEFINE-* -CERT-EXP19* */
#include "lwip/netif.h"
/*cstat +MISRAC* -DEFINE-* -CERT-EXP19* */
/* Within 'USER CODE' section, code will be kept by default at each generation */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* Exported functions ------------------------------------------------------- */
void net_ethernetif_deinit(void);
void net_ethernetif_get_mac_addr(uint8_t *mac_addr);
uint8_t net_ethernetif_get_link_status(void);
err_t net_ethernetif_init(struct netif *netif);
int32_t net_ethernetif_output(void *context, net_buf_t *net_buf);
#endif /* NET_IP_ETHERNET_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,58 @@
/**
******************************************************************************
* @file net_ip_lwip.h
* @author MCD Application Team
* @brief Header for the network IP functions.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#ifndef NET_IP_LWIP_H
#define NET_IP_LWIP_H
#include "net_connect.h"
#include "net_internals.h"
/*cstat -MISRAC* -DEFINE-* -CERT-EXP19* */
#include "lwip/netdb.h"
#include "lwip/dhcp.h"
#include "lwip/tcpip.h"
#include "lwip/etharp.h"
/*cstat +MISRAC* +DEFINE-* -CERT-EXP19* */
#define NET_IP_IF_TIMEOUT 1000
#define NET_IP_INPUT_QUEUE_TIMEOUT 1000
#define NET_IP_INPUT_QUEUE_SIZE 128
#define NET_IP_THREAD_SIZE 1024
#define NET_IP_FLAG_DEFAULT_INTERFACE (1U<<0)
#define NET_IP_FLAG_TCPIP_STARTED_EXTERNALLY (1U<<1)
void net_ip_init(void);
int32_t net_ip_add_if(net_if_handle_t *pnetif, err_t (*if_init)(struct netif *netif), uint32_t flag);
int32_t net_ip_remove_if(net_if_handle_t *pnetif, err_t (*if_deinit)(struct netif *netif));
int32_t net_ip_connect(net_if_handle_t *pnetif);
int32_t net_ip_disconnect(net_if_handle_t *pnetif);
void net_ip_status_cb(struct netif *netif);
void net_ip_link_status(struct netif *netif, uint8_t status);
int32_t returncode_lwip2net(int32_t ret);
#endif /* NET_IP_LWIP_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,69 @@
/**
******************************************************************************
* @file net_mbedtls.h
* @author MCD Application Team
* @brief Header for the network TLS functions.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef MBEDTLS_NET_H
#define MBEDTLS_NET_H
/* Includes ------------------------------------------------------------------*/
#include "mbedtls/platform.h"
#include "mbedtls/ssl.h"
#include "mbedtls/certs.h"
#include "mbedtls/x509.h"
#include "mbedtls/error.h"
#include "mbedtls/debug.h"
#include "mbedtls/timing.h"
/* Private defines -----------------------------------------------------------*/
struct net_tls_data
{
const char_t *tls_ca_certs; /**< Socket option. */
const char_t *tls_ca_crl; /**< Socket option. */
const char_t *tls_dev_cert; /**< Socket option. */
const char_t *tls_dev_key; /**< Socket option. */
const uint8_t *tls_dev_pwd; /**< Socket option. */
size_t tls_dev_pwd_len; /**< Socket option / meta. */
bool tls_srv_verification; /**< Socket option. */
const char_t *tls_srv_name; /**< Socket option. */
/* mbedTLS objects */
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
uint32_t flags;
mbedtls_x509_crt cacert;
mbedtls_x509_crt clicert;
mbedtls_pk_context pkey;
const mbedtls_x509_crt_profile *tls_cert_prof; /**< Socket option. */
} ;
void net_tls_init(void);
void net_tls_destroy(void);
int32_t net_mbedtls_start(net_socket_t *sockhnd);
int32_t net_mbedtls_stop(net_socket_t *sockhnd);
int32_t net_mbedtls_sock_recv(net_socket_t *sockhnd, uint8_t *buf, size_t len);
int32_t net_mbedtls_sock_send(net_socket_t *sockhnd, const uint8_t *buf, size_t len);
bool net_mbedtls_check_tlsdata(net_socket_t *sockhnd);
void net_mbedtls_set_read_timeout(net_socket_t *sock);
#endif /* MBEDTLS_NET_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,110 @@
/**
******************************************************************************
* @file net_mem.h
* @author MCD Application Team
* @brief Memory allocator functions
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef NET_MEM_H
#define NET_MEM_H
#include "net_conf.h"
#include "net_types.h"
/* disable Misra rule to enable doxigen comment , A sectio of code appear to have been commented out */
/*cstat -MISRAC2012-Dir-4.4 */
#ifdef __cplusplus
extern "C" {
#endif
#ifdef NET_ALLOC_DEBUG
#if !defined NET_ALLOC_MAX_NODE
#define NET_ALLOC_MAX_NODE 50U
#endif /* NET_ALLOC_MAX_NODE */
#if !defined NET_DISPLAY_TAB
#define NET_DISPLAY_TAB 4U
#endif /* NET_DISPLAY_TAB */
#if !defined NET_DISPLAY_WIDTH
#define NET_DISPLAY_WIDTH 120U
#endif /* NET_DISPLAY_WIDTH */
#if !defined NET_DISPLAY_RESULT_WIDTH
#define NET_DISPLAY_RESULT_WIDTH 8U
#endif /* NET_DISPLAY_RESULT_WIDTH */
#if !defined NET_DISPLAY_DIRNAME_LEN
#define NET_DISPLAY_DIRNAME_LEN 30U
#endif /* NET_DISPLAY_DIRNAME_LEN */
#if !defined NET_ALLOC_VERBOSE
#define NET_ALLOC_VERBOSE 0
#endif /* NET_ALLOC_VERBOSE */
#ifndef NET_LEAKAGE_ARRAY
#define NET_LEAKAGE_ARRAY 300U
#endif /* NET_LEAKAGE_ARRAY */
#ifndef NET_ALLOC_BREAK
#define NET_ALLOC_BREAK 0xFFFFFFFFU
#endif /* NET_ALLOC_BREAK */
#define NET_CALLOC(a,b) net_calloc_debug(a,b,__FILE__,__LINE__)
#define NET_REALLOC(a,b) net_realloc_debug(a,b,__FILE__,__LINE__)
#define NET_MALLOC(a) net_malloc_debug(a,__FILE__,__LINE__)
#define NET_FREE(a) net_free_debug(a)
void *net_calloc_debug(size_t m, size_t n, const char *s, uint32_t line);
void *net_malloc_debug(size_t m, const char *s, uint32_t line);
void *net_realloc_debug(void *p, size_t size, const char_t *filename, uint32_t line);
void net_free_debug(void *p);
void net_alloc_report(void);
#else /* !NET_ALLOC_DEBUG */
#ifdef NET_USE_RTOS
#define NET_CALLOC net_calloc
#define NET_REALLOC net_realloc
#define NET_MALLOC pvPortMalloc
#define NET_FREE vPortFree
void *net_calloc(size_t n, size_t m);
void *net_realloc(void *p, size_t m);
#else
#define NET_CALLOC calloc
#define NET_REALLOC realloc
#define NET_MALLOC malloc
#define NET_FREE free
#endif /* NET_USE_RTOS */
#endif /* NET_ALLOC_DEBUG */
#ifdef __cplusplus
}
#endif
#endif /* NET_MEM_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,112 @@
/**
******************************************************************************
* @file net_perf.h
* @author MCD Application Team
* @brief Memory allocator functions
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef NET_PERF_H
#define NET_PERF_H
/* disable Misra rule to enable doxigen comment , A sectio of code appear to have been commented out */
/*cstat -MISRAC2012-Dir-4.4 */
#ifdef __cplusplus
extern "C" {
#endif
#include "net_conf.h"
#include "net_types.h"
#ifdef NET_USE_RTOS
#if (osCMSIS < 0x20000U)
#define NET_TICK osKernelSysTick
#else
#define NET_TICK osKernelGetTickCount
#endif /* osCMSIS */
#else
#define NET_TICK HAL_GetTick
#endif /* NET_USE_RTOS */
/*cstat -MISRAC2012-Rule-21.1 */
#ifndef __IO
#define __IO volatile
#endif /* __IO */
/*cstat +MISRAC2012-Rule-21.1 */
#define NET_DWT_CONTROL (*((__IO uint32_t*)0xE0001000U))
#define NET_DWT_CYCCNTENA_BIT (1UL<<0U)
/*!< DWT Cycle Counter register */
#define NET_DWT_CYCCNT (*((__IO uint32_t*)0xE0001004U))
/*!< DEMCR: Debug Exception and Monitor Control Register */
#define NET_DEMCR (*((__IO uint32_t*)0xE000EDFCU))
/*!< Trace enable bit in DEMCR register */
#define NET_TRCENA_BIT (1UL<<24U)
static inline uint32_t net_get_cycle(void)
{
/*cstat -MISRAC2012-Rule-11.4 */
return NET_DWT_CYCCNT;
/*cstat +MISRAC2012-Rule-11.4 */
}
static inline void net_stop_cycle(void)
{
/*cstat -MISRAC2012-Rule-11.4 */
NET_DWT_CONTROL &= ~NET_DWT_CYCCNTENA_BIT ;
/*cstat +MISRAC2012-Rule-11.4 */
}
static inline void net_start_cycle(void)
{
/*cstat -MISRAC2012-Rule-11.4 */
NET_DWT_CONTROL |= NET_DWT_CYCCNTENA_BIT ;
/*cstat +MISRAC2012-Rule-11.4 */
}
void net_perf_start(void);
void net_perf_report(void);
#ifdef NET_USE_RTOS
#if defined(NET_PERF_TASK) && !defined(NET_FREERTOS_PERF)
#warning "To use NET_PERF_TASK please add followings lines to FreeRTOSConfig.h"
#warning " void net_perf_task_in(void);"
#warning " void net_perf_task_out(void);"
#warning " #define NET_FREERTOS_PERF"
#warning " #define traceTASK_SWITCHED_IN net_perf_task_in"
#warning " #define traceTASK_SWITCHED_OUT net_perf_task_out"
#endif /* NET_PERF_TASK */
#endif /* NET_USE_RTOS */
#ifdef __cplusplus
}
#endif
#endif /* NET_PERF_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,27 @@
/**
******************************************************************************
* @file net_state.h
* @author MCD Application Team
* @brief Header for the network state management functions
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#ifndef NET_STATE_H
#define NET_STATE_H
int32_t net_state_manage_event(net_if_handle_t *pnetif, net_state_event_t state_to);
void net_state_transition_done(net_if_handle_t *pnetif, net_state_t state_to);
#endif /* NET_STATE_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,36 @@
/**
******************************************************************************
* @file net_types.h
* @author MCD Application Team
* @brief Header for the network types definitions
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#ifndef NET_TYPES_H
#define NET_TYPES_H
#include "stdint.h"
#include "stdbool.h"
/*cstat -MISRAC2012-Dir-4.6_b */
typedef char char_t;
typedef unsigned char uchar_t;
/*cstat +MISRAC2012-Dir-4.6_b */
typedef bool bool_t;
#endif /* NET_TYPES_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,195 @@
/**
******************************************************************************
* @file net_wifi.h
* @author MCD Application Team
* @brief Header for the network Wi-Fi class.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#ifndef NET_WIFI_H
#define NET_WIFI_H
#ifdef __cplusplus
extern "C" {
#endif
#define NET_WIFI_MAC_ADDRESS_SIZE 6
#define NET_WIFI_MAX_SSID_SIZE 32
#define NET_WEP_ENABLED 0x0001U /**< Flag to enable WEP Security */
#define NET_TKIP_ENABLED 0x0002U /**< Flag to enable TKIP Encryption */
#define NET_AES_ENABLED 0x0004U /**< Flag to enable AES Encryption */
#define NET_SHARED_ENABLED 0x00008000U /**< Flag to enable Shared key Security */
#define NET_WPA_SECURITY 0x00200000U /**< Flag to enable WPA Security */
#define NET_WPA2_SECURITY 0x00400000U /**< Flag to enable WPA2 Security */
#define NET_WPA3_SECURITY 0x01000000U /**< Flag to enable WPA3 PSK Security */
#define NET_ENTERPRISE_ENABLED 0x02000000U /**< Flag to enable Enterprise Security */
#define NET_WPS_ENABLED 0x10000000U /**< Flag to enable WPS Security */
#define NET_IBSS_ENABLED 0x20000000U /**< Flag to enable IBSS mode */
#define NET_FBT_ENABLED 0x40000000U /**< Flag to enable FBT */
#define NET_WIFI_SM_OPEN 0U
/**< Open security */
#define NET_WIFI_SM_WEP_PSK NET_WEP_ENABLED
/**< WEP PSK Security with open authentication */
#define NET_WIFI_SM_WEP_SHARED (NET_WEP_ENABLED | NET_SHARED_ENABLED)
/**< WEP PSK Security with shared authentication */
#define NET_WIFI_SM_WPA_TKIP_PSK (NET_WPA_SECURITY | NET_TKIP_ENABLED)
/**< WPA PSK Security with TKIP */
#define NET_WIFI_SM_WPA_AES_PSK (NET_WPA_SECURITY | NET_AES_ENABLED)
/**< WPA PSK Security with AES */
#define NET_WIFI_SM_WPA_MIXED_PSK (NET_WPA_SECURITY | NET_AES_ENABLED | NET_TKIP_ENABLED)
/**< WPA PSK Security with AES & TKIP */
#define NET_WIFI_SM_WPA2_AES_PSK (NET_WPA2_SECURITY | NET_AES_ENABLED)
/**< WPA2 PSK Security with AES */
#define NET_WIFI_SM_WPA2_WPA_PSK (NET_WPA2_SECURITY | NET_WPA_SECURITY)
/**< WPA2 PSK Security with AES */
#define NET_WIFI_SM_WPA2_TKIP_PSK (NET_WPA2_SECURITY | NET_TKIP_ENABLED)
/**< WPA2 PSK Security with TKIP */
#define NET_WIFI_SM_WPA2_MIXED_PSK (NET_WPA2_SECURITY | NET_AES_ENABLED | NET_TKIP_ENABLED)
/**< WPA2 PSK Security with AES & TKIP */
#define NET_WIFI_SM_WPA2_FBT_PSK (NET_WPA2_SECURITY | NET_AES_ENABLED | NET_FBT_ENABLED)
/**< WPA2 FBT PSK Security with AES & TKIP */
#define NET_WIFI_SM_WPA3_SAE (NET_WPA3_SECURITY | NET_AES_ENABLED)
/**< WPA3 Security with AES */
#define NET_WIFI_SM_WPA3_WPA2_PSK (NET_WPA3_SECURITY | NET_WPA2_SECURITY | NET_AES_ENABLED)
/**< WPA3 WPA2 PSK Security with AES */
#define NET_WIFI_SM_WPA_TKIP_ENT (NET_ENTERPRISE_ENABLED | NET_WPA_SECURITY | NET_TKIP_ENABLED)
/**< WPA Enterprise Security with TKIP */
#define NET_WIFI_SM_WPA_AES_ENT (NET_ENTERPRISE_ENABLED | NET_WPA_SECURITY | NET_AES_ENABLED)
/**< WPA Enterprise Security with AES */
#define NET_WIFI_SM_WPA_MIXED_ENT (NET_ENTERPRISE_ENABLED\
| NET_WPA_SECURITY | NET_AES_ENABLED | NET_TKIP_ENABLED)
/**< WPA Enterprise Security with AES & TKIP */
#define NET_WIFI_SM_WPA2_TKIP_ENT (NET_ENTERPRISE_ENABLED | NET_WPA2_SECURITY | NET_TKIP_ENABLED)
/**< WPA2 Enterprise Security with TKIP */
#define NET_WIFI_SM_WPA2_AES_ENT (NET_ENTERPRISE_ENABLED | NET_WPA2_SECURITY | NET_AES_ENABLED)
/**< WPA2 Enterprise Security with AES */
#define NET_WIFI_SM_WPA2_MIXED_ENT (NET_ENTERPRISE_ENABLED\
| NET_WPA2_SECURITY | NET_AES_ENABLED | NET_TKIP_ENABLED)
/**< WPA2 Enterprise Security with AES & TKIP */
#define NET_WIFI_SM_WPA2_FBT_ENT (NET_ENTERPRISE_ENABLED\
| NET_WPA2_SECURITY | NET_AES_ENABLED | NET_FBT_ENABLED)
/**< WPA2 Enterprise Security with AES & FBT */
#define NET_WIFI_SM_IBSS_OPEN (NET_IBSS_ENABLED)
/**< Open security on IBSS ad-hoc network */
#define NET_WIFI_SM_WPS_OPEN (NET_WPS_ENABLED)
/**< WPS with open security */
#define NET_WIFI_SM_WPS_SECURE (NET_WPS_ENABLED | NET_AES_ENABLED)
/**< WPS with AES security */
#define NET_WIFI_SM_UNKNOWN 0xFFFFFFFFU
/**< UNKNOWN security */
#define NET_WIFI_SM_AUTO 0xFFFFFFF0U
/**< Auto Mode */
/* Wi-Fi events */
typedef enum
{
NET_WIFI_SCAN_RESULTS_READY
} net_wifi_event_t;
/* Mode */
typedef enum
{
NET_WIFI_MODE_STA,
NET_WIFI_MODE_AP
} net_wifi_mode_t;
/* MAC address */
typedef uint8_t net_wifi_mac_t[NET_WIFI_MAC_ADDRESS_SIZE];
/* SSID , max 32 alpha string chain*/
typedef struct
{
uint8_t length; /**< SSID length */
uint8_t value[NET_WIFI_MAX_SSID_SIZE]; /**< SSID name (AP name) */
} net_wifi_ssid_t;
/* Scan */
typedef enum
{
NET_WIFI_SCAN_PASSIVE,
NET_WIFI_SCAN_ACTIVE,
NET_WIFI_SCAN_AUTO
} net_wifi_scan_mode_t;
typedef struct net_wifi_scan_bss_s
{
net_wifi_ssid_t ssid;
net_wifi_mac_t bssid;
uint32_t security;
uint8_t channel;
uint8_t country[4]; /* one more char for null terminated string */
int8_t rssi;
} net_wifi_scan_bss_t;
#if 0
typedef struct net_wifi_scan_results_s
{
uint16_t number;
net_wifi_scan_bss_t *bss;
} net_wifi_scan_results_t;
#else
typedef net_wifi_scan_bss_t net_wifi_scan_results_t;
#endif /* old definiton */
/* Param */
typedef enum
{
NET_WIFI_MODE,
} net_wifi_param_t;
/* System info */
typedef enum
{
NET_WIFI_SCAN_RESULTS_NUMBER,
} net_wifi_system_info_t;
/* Credential configuration */
typedef struct net_wifi_credentials_s
{
const char_t *ssid;
const char_t *psk;
int32_t security_mode;
} net_wifi_credentials_t;
/* Powersave */
typedef enum
{
WIFI_POWERSAVE_ACTIVE,
WIFI_POWERSAVE_LIGHT_SLEEP,
WIFI_POWERSAVE_DEEP_SLEEP
}
net_wifi_powersave_t;
const char_t *net_wifi_security_to_string(uint32_t sec);
uint32_t net_wifi_string_to_security(char *sec);
int32_t net_wifi_scan(net_if_handle_t *pnetif, net_wifi_scan_mode_t mode, char *ssid);
int32_t net_wifi_get_scan_results(net_if_handle_t *pnetif, net_wifi_scan_results_t *results, uint8_t number);
int32_t net_wifi_set_credentials(net_if_handle_t *pnetif, const net_wifi_credentials_t *credentials);
int32_t net_wifi_set_access_mode(net_if_handle_t *pnetif, net_wifi_mode_t mode);
int32_t net_wifi_set_access_channel(net_if_handle_t *pnetif, uint8_t channel);
int32_t net_wifi_set_powersave(net_if_handle_t *pnetif, const net_wifi_powersave_t *powersave);
int32_t net_wifi_set_param(net_if_handle_t *pnetif, const net_wifi_param_t param, void *data);
#ifdef __cplusplus
}
#endif
#endif /* NET_WIFI_H */
@@ -0,0 +1 @@
STM32 Network Library Framework
@@ -0,0 +1,370 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>Release Notes for STM32 Network Library</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
<link rel="stylesheet" href="_htmresc/mini-st.css" />
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
<link rel="icon" type="image/x-icon" href="_htmresc/favicon.png" />
</head>
<body>
<p>::: {.row} ::: {.col-sm-12 .col-lg-4}</p>
<div class="card fluid">
<div class="sectione dark">
<center>
<h1 id="release-notes-for-stm32-network-library"><small>Release Notes for</small> <mark>STM32 Network Library</mark></h1>
<p>Copyright © 2019 STMicroelectronics<br />
Microcontrollers Division - Application Team</p>
<a href="https://www.st.com" class="logo"><img src="_htmresc/st_logo.png" alt="ST logo" /></a>
</center>
</div>
</div>
<h1 id="license">License</h1>
<p>Licensed under ST license SLA0044 (the “License”). You may not use this package except in compliance with the License.</p>
<p>You may obtain a copy of the License at: <a href="http://www.st.com/software_license_agreement_liberty_v2">SLA0044 Software license agreement</a>.</p>
<h1 id="purpose">Purpose</h1>
<p>The <mark>STM32 Network Library</mark> is a middleware providing network services on STM32 devices. It provides a socket API (BSD like style) with support of secure or non secure connection and an API to control the lifecycle of the network adapters.</p>
<p>Three classes of network adapters are supported WIFI, Ethernet and Cellular. Different WIFI modules are supported from third party vendors.</p>
<h1 id="documentation">Documentation</h1>
<p><a href="./NetworkLib.chm">Doxygen documentation</a> :::</p>
<div class="col-sm-12 col-lg-8">
<h1 id="update-history">Update History</h1>
<div class="collapse">
<input type="checkbox" id="collapse-section8" checked aria-hidden="false"> <label for="collapse-section8" aria-hidden="true">V2.1.0 / 2020-Mai-04</label>
<div>
<h2 id="main-changes">Main changes</h2>
<h3 id="network-library-core">Network library core</h3>
<ul>
<li>Improve performance monitoring primitives adding Thread display support</li>
<li>Improve Memory debug primitive</li>
<li>Add Node Tree display for dynamic memory allocation</li>
</ul>
<h3 id="mxchip-wifi-network-interface">MXCHIP WIFI Network interface</h3>
<ul>
<li>Add support of UART interrupt module</li>
</ul>
<h3 id="bug-fixes">Bug fixes</h3>
<ul>
<li>Fix uninitialized variable for all WIFI network interface to force default to AP mode when connecting</li>
<li>Fix memory leakage for MXCHIP network interface</li>
</ul>
<h2 id="development-toolchains-and-compilers">Development Toolchains and Compilers</h2>
<ul>
<li>IAR Embedded Workbench for ARM (EWARM). Version 8.32.3</li>
<li>Keil Microcontroller Development Kit (MDK-ARM) Version 5.27.1</li>
<li>System Workbench for STM32. Version 2.8.1.</li>
</ul>
<h2 id="supported-devices-and-boards">Supported Devices and Boards</h2>
<ul>
<li>B-L475E-IOT01A board (MB1297 rev D).</li>
<li>32F413HDISCOVERY board (MB1274 rev B).</li>
<li>32F769IDISCOVERY board (MB1225 rev B).</li>
<li>P-L496G-CELL02 board package including the 32L496G-Discovery board (MB1261 rev B) and the Cellular Add-on board based on BG96 4G Modem (MB1329 rev B)</li>
<li>STM32H743I-EVAL (with Ethernet interface)</li>
</ul>
<h2 id="known-limitations">Known Limitations</h2>
<ul>
<li>Cellular on P-L496G-CELL02:</li>
<li>Server sockets are not supported</li>
</ul>
</div>
</div>
<div class="col-sm-12 col-lg-8">
<h1 id="update-history-1">Update History</h1>
<div class="collapse">
<input type="checkbox" id="collapse-section7" checked aria-hidden="false"> <label for="collapse-section7" aria-hidden="true">V2.0.0 / 2020-April-08</label>
<div>
<h2 id="main-changes-1">Main changes</h2>
<h3 id="network-library-core-1">Network library core</h3>
<ul>
<li>Prepare support of IPv6 addresses, making code independent from network address definition</li>
<li>Clean up template of configuration file to allow application to overwrite default definition</li>
<li>Add performance monitoring primitives</li>
<li>Add memory allocation primitive to track leakage</li>
<li>Add yield feature for specific network interface</li>
</ul>
<h3 id="wifi-generic-support">WIFI generic support</h3>
<ul>
<li>Add WIFI Access point support, with needed new API (set_channel, set mode )</li>
<li>Update state machine management to support AP and STA connection</li>
<li>Add support of concurrent interface, for instance an AP running in parallel with a STA</li>
<li>Extend list of supported security mode</li>
</ul>
<h3 id="cellular-network-interface">Cellular Network interface</h3>
<ul>
<li>Add compatibility until XCube Cellular package 1.5.0</li>
</ul>
<h3 id="cypress-wifi-network-interface">Cypress WIFI Network interface</h3>
<ul>
<li>Add support of Access Point mode</li>
</ul>
<h3 id="mxchip-wifi-network-interface-1">MXCHIP WIFI Network interface</h3>
<ul>
<li>Newly supported WIFI module</li>
<li>Add support of UART and SPI based module</li>
<li>Add templates files</li>
</ul>
<h3 id="inventek-wifi-network-interface">Inventek WIFI network interface</h3>
<ul>
<li>Add support of net_getpeername and net_getsocketinfo API</li>
</ul>
<h3 id="bug-fixes-1">Bug fixes</h3>
<ul>
<li>Fix memory leakage for Cypress WHD based devices</li>
<li>Fix memory leakage for secure socket (based on MbedTLS )</li>
<li>Fix timeout definition for Cellular devices on connection</li>
<li>Fix state machine on deinitialization transition</li>
</ul>
<h2 id="development-toolchains-and-compilers-1">Development Toolchains and Compilers</h2>
<ul>
<li>IAR Embedded Workbench for ARM (EWARM). Version 8.32.3</li>
<li>Keil Microcontroller Development Kit (MDK-ARM) Version 5.27.1</li>
<li>System Workbench for STM32. Version 2.8.1.</li>
</ul>
<h2 id="supported-devices-and-boards-1">Supported Devices and Boards</h2>
<ul>
<li>B-L475E-IOT01A board (MB1297 rev D).</li>
<li>32F413HDISCOVERY board (MB1274 rev B).</li>
<li>32F769IDISCOVERY board (MB1225 rev B).</li>
<li>P-L496G-CELL02 board package including the 32L496G-Discovery board (MB1261 rev B) and the Cellular Add-on board based on BG96 4G Modem (MB1329 rev B)</li>
<li>STM32H743I-EVAL (with Ethernet interface)</li>
</ul>
<h2 id="known-limitations-1">Known Limitations</h2>
<ul>
<li>Cellular on P-L496G-CELL02:</li>
<li>Server sockets are not supported</li>
</ul>
</div>
</div>
<div class="collapse">
<input type="checkbox" id="collapse-section6" aria-hidden="true"> <label for="collapse-section6" aria-hidden="true">V1.1.0 / 2019-November-27</label>
<div>
<h2 id="main-changes-2">Main changes</h2>
<ul>
<li>Add support for WIFI-WHD devices, create a new network interface</li>
<li>Add support of ethernet on H7 device (STM32H743I-EVAL board)</li>
<li>Restructure code regarding LWIP based network interface</li>
<li>lwip related initialisation is moved to net_conf.c</li>
<li>Compliant with ST-Quality standard
<ul>
<li>Pass MISRA check list</li>
<li>Pass CodeSonar test<br />
</li>
<li>Enforce ST coding style rules</li>
</ul></li>
</ul>
<h3 id="bug-fixes-2">Bug fixes</h3>
<h2 id="development-toolchains-and-compilers-2">Development Toolchains and Compilers</h2>
<ul>
<li>IAR Embedded Workbench for ARM (EWARM). Version 8.30.1.</li>
<li>Keil Microcontroller Development Kit (MDK-ARM) Version 5.26.</li>
<li>System Workbench for STM32. Version 2.8.1.</li>
</ul>
<h2 id="supported-devices-and-boards-2">Supported Devices and Boards</h2>
<ul>
<li>B-L475E-IOT01A board (MB1297 rev D).</li>
<li>32F413HDISCOVERY board (MB1274 rev B).</li>
<li>32F769IDISCOVERY board (MB1225 rev B).</li>
<li>P-L496G-CELL02 board package including the 32L496G-Discovery board (MB1261 rev B) and the Cellular Add-on board based on BG96 4G Modem (MB1329 rev B)</li>
<li>STM32H743I-EVAL (with Ethernet interface)</li>
</ul>
<h2 id="known-limitations-2">Known Limitations</h2>
<ul>
<li>Cellular on P-L496G-CELL02:
<ul>
<li>Server sockets are not supported</li>
</ul></li>
</ul>
</div>
</div>
<div class="collapse">
<input type="checkbox" id="collapse-section5" aria-hidden="true"> <label for="collapse-section5" aria-hidden="true">V1.0.5 / 2019-October-8</label>
<div>
<h2 id="main-changes-3">Main changes</h2>
<ul>
<li>Add support for CMSIS-OS2</li>
</ul>
<h3 id="bug-fixes-3">Bug fixes</h3>
<ul>
<li>Fix cellular network interface, required to used firmware version &gt;= BG96MAR02A08M1G.</li>
<li>Fix message order on notification</li>
</ul>
<h2 id="development-toolchains-and-compilers-3">Development Toolchains and Compilers</h2>
<ul>
<li>IAR Embedded Workbench for ARM (EWARM). Version 8.30.1.</li>
<li>Keil Microcontroller Development Kit (MDK-ARM) Version 5.26.</li>
<li>System Workbench for STM32. Version 2.8.1.</li>
</ul>
<h2 id="supported-devices-and-boards-3">Supported Devices and Boards</h2>
<ul>
<li>B-L475E-IOT01A board (MB1297 rev D).</li>
<li>32F413HDISCOVERY board (MB1274 rev B).</li>
<li>32F769IDISCOVERY board (MB1225 rev B).</li>
<li>P-L496G-CELL02 board package including the 32L496G-Discovery board (MB1261 rev B) and the Cellular Add-on board based on BG96 4G Modem (MB1329 rev B)</li>
</ul>
<h2 id="known-limitations-3">Known Limitations</h2>
<ul>
<li>Cellular on P-L496G-CELL02:
<ul>
<li>Server sockets are not supported</li>
</ul></li>
</ul>
</div>
</div>
<div class="collapse">
<input type="checkbox" id="collapse-section4" aria-hidden="true"> <label for="collapse-section4" aria-hidden="true">V1.0.4 / 2019-August-1</label>
<div>
<h2 id="main-changes-4">Main changes</h2>
<ul>
<li>Renamed STM32 Connectivity library as STM32 Network library</li>
<li>Re-implement State management of network interface ,renamed states from INITIALIZED to READY , suppress some unused states</li>
<li>Add and test support of embedded Inventek WIFI TLS socket</li>
<li>Run MISRA checks</li>
</ul>
<h3 id="bug-fixes-4">Bug fixes</h3>
<ul>
<li>Ethernet template: properly clear the “Receive buffer unavailable status” in case of RX descriptor underflow.</li>
<li>Fix missing semaphore on net_wait API</li>
</ul>
<h2 id="development-toolchains-and-compilers-4">Development Toolchains and Compilers</h2>
<ul>
<li>IAR Embedded Workbench for ARM (EWARM). Version 8.30.1.</li>
<li>Keil Microcontroller Development Kit (MDK-ARM) Version 5.26.</li>
<li>System Workbench for STM32. Version 2.8.1.</li>
</ul>
<h2 id="supported-devices-and-boards-4">Supported Devices and Boards</h2>
<ul>
<li>B-L475E-IOT01A board (MB1297 rev D).</li>
<li>32F413HDISCOVERY board (MB1274 rev B).</li>
<li>32F769IDISCOVERY board (MB1225 rev B).</li>
<li>P-L496G-CELL02 board package including the 32L496G-Discovery board (MB1261 rev B) and the Cellular Add-on board based on BG96 4G Modem (MB1329 rev B)</li>
</ul>
<h2 id="known-limitations-4">Known Limitations</h2>
<ul>
<li>Cellular on P-L496G-CELL02:
<ul>
<li>Server sockets are not supported</li>
</ul></li>
</ul>
</div>
</div>
<div class="collapse">
<input type="checkbox" id="collapse-section3" aria-hidden="true"> <label for="collapse-section3" aria-hidden="true">V1.0.3 / 2019-july-05</label>
<div>
<h2 id="main-changes-5">Main changes</h2>
<h3 id="bug-fixes-5">Bug fixes</h3>
<ul>
<li>Run Astyle checks</li>
<li>Add doxygen doc generation</li>
<li>Fix issue on F769 Ethernet interface , avoid blocking thread on alloc failure from LWIP pool</li>
</ul>
<h2 id="development-toolchains-and-compilers-5">Development Toolchains and Compilers</h2>
<ul>
<li>IAR Embedded Workbench for ARM (EWARM). Version 8.32.3.</li>
<li>Keil Microcontroller Development Kit (MDK-ARM) Version 5.26.</li>
<li>System Workbench for STM32. Version 2.8.1.</li>
</ul>
<h2 id="supported-devices-and-boards-5">Supported Devices and Boards</h2>
<ul>
<li>B-L475E-IOT01A board (MB1297 rev D).</li>
<li>32F413HDISCOVERY board (MB1274 rev B).</li>
<li>32F769IDISCOVERY board (MB1225 rev B).</li>
<li>P-L496G-CELL02 board package including the 32L496G-Discovery board (MB1261 rev B) and the Cellular Add-on board based on BG96 4G Modem (MB1329 rev B)</li>
</ul>
<h2 id="known-limitations-5">Known Limitations</h2>
<ul>
<li>Cellular on P-L496G-CELL02:
<ul>
<li>Server sockets are not supported</li>
</ul></li>
</ul>
</div>
</div>
<div class="collapse">
<input type="checkbox" id="collapse-section2" aria-hidden="true"> <label for="collapse-section2" aria-hidden="true">V1.0.2 / 2019-june-07</label>
<div>
<h2 id="main-changes-6">Main changes</h2>
<h3 id="bug-fixes-6">Bug fixes</h3>
<ul>
<li>Ethernet template: properly clear the “Receive buffer unavailable status” in case of RX descriptor underflow.</li>
</ul>
<h2 id="development-toolchains-and-compilers-6">Development Toolchains and Compilers</h2>
<ul>
<li>IAR Embedded Workbench for ARM (EWARM). Version 8.32.3.</li>
<li>Keil Microcontroller Development Kit (MDK-ARM) Version 5.26.</li>
<li>System Workbench for STM32. Version 2.8.1.</li>
</ul>
<h2 id="supported-devices-and-boards-6">Supported Devices and Boards</h2>
<ul>
<li>B-L475E-IOT01A board (MB1297 rev D).</li>
<li>32F413HDISCOVERY board (MB1274 rev B).</li>
<li>32F769IDISCOVERY board (MB1225 rev B).</li>
<li>P-L496G-CELL02 board package including the 32L496G-Discovery board (MB1261 rev B) and the Cellular Add-on board based on BG96 4G Modem (MB1329 rev B)</li>
</ul>
<h2 id="known-limitations-6">Known Limitations</h2>
<ul>
<li>Cellular on P-L496G-CELL02:
<ul>
<li>Server sockets are not supported</li>
</ul></li>
</ul>
</div>
</div>
<div class="collapse">
<input type="checkbox" id="collapse-section1" aria-hidden="true"> <label for="collapse-section1" aria-hidden="true">V1.0.0 / 2019-april-26</label>
<div>
<h2 id="initial-version">Initial version</h2>
<ul>
<li>Features supported:
<ul>
<li>BSD socket like API</li>
<li>Network interface control API (init, start, stop, …)</li>
<li>TCP and UPD protocols</li>
<li>Client and server connections</li>
<li>DNS and ping services</li>
<li>Secure socket on top of mbedTLS</li>
<li>RTOS and bare metal applications are supported</li>
<li>IPv4 address only is supported (IPv6 will be available in a future version)</li>
<li>Wi-Fi, Ethernet and cellular connectivities</li>
</ul></li>
</ul>
<h2 id="development-toolchains-and-compilers-7">Development Toolchains and Compilers</h2>
<ul>
<li>IAR Embedded Workbench for ARM (EWARM). Version 8.30.1.</li>
<li>Keil Microcontroller Development Kit (MDK-ARM) Version 5.26.</li>
<li>System Workbench for STM32. Version 2.8.1.</li>
</ul>
<h2 id="supported-devices-and-boards-7">Supported Devices and Boards</h2>
<ul>
<li>B-L475E-IOT01A board (MB1297 rev D).</li>
<li>32F413HDISCOVERY board (MB1274 rev B).</li>
<li>32F769IDISCOVERY board (MB1225 rev B).</li>
<li>P-L496G-CELL02 board package including the 32L496G-Discovery board (MB1261 rev B) and the Cellular Add-on board based on BG96 4G Modem (MB1329 rev B)</li>
</ul>
<h2 id="known-limitations-7">Known Limitations</h2>
<ul>
<li>Cellular on P-L496G-CELL02
<ul>
<li>UDP sockets are not supported</li>
<li>Server sockets are not supported</li>
</ul></li>
</ul>
</div>
</div>
</div>
</div>
<footer class="sticky">
For complete documentation on <mark>STM32</mark> microcontrollers please visit <a href="http://www.st.com/stm32" class="uri">http://www.st.com/stm32</a>
</footer>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

@@ -0,0 +1,319 @@
/**
******************************************************************************
* @file net_address.c
* @author MCD Application Team
* @brief Implements network address conversion routines
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#include "net_connect.h"
#include "net_internals.h"
#define NET_IN_RANGE(c, lo, up) (((c) >= (lo)) && ((c) <= (up)))
#define NET_IS_PRINT(c) (NET_IN_RANGE(c, 0x20, 0x7f))
#define NET_ISDIGIT(c) (NET_IN_RANGE(c, '0', '9'))
#define NET_ISXDIGIT(c) (NET_ISDIGIT(c) || NET_IN_RANGE(c, 'a', 'f') || NET_IN_RANGE(c, 'A', 'F'))
#define NET_ISLOWER(c) (NET_IN_RANGE(c, 'a', 'z'))
#define NET_ISSPACE(c) (((c) == ' ')\
|| ((c) == '\f') || ((c) == '\n') || ((c) == '\r') || ((c) == '\t') || ((c) == '\v'))
/**
* @brief Function description
* @param Params
* @retval socket status
*/
#if !defined(NET_USE_LWIP_DEFINITIONS)
char_t *net_ntoa_r(const net_ip_addr_t *addr, char_t *buf, int32_t buflen)
{
uint32_t NET_S_ADDR;
uint8_t val;
char_t inv[3];
uint8_t *ap;
uint8_t rem;
uint8_t i;
int32_t len = 0;
char_t *buf_ret;
NET_S_ADDR = addr->addr;
ap = (uint8_t *)&NET_S_ADDR;
for (uint8_t n = 0; n < (uint8_t) 4; n++)
{
i = 0;
val = ap[n];
do
{
rem = val % 10U;
val /= 10U;
inv[i] = (char_t)'0' + rem;
i++;
} while (val != 0U);
while (i != 0U)
{
i--;
if (len < buflen)
{
buf[len] = inv[i];
len++;
}
}
if ((n < 3U) && (len < buflen))
{
buf[len] = (char_t) '.';
len++;
}
}
if (len < buflen)
{
buf[len] = (char_t) '\0';
buf_ret = buf;
}
else
{
buf_ret = NULL;
}
return buf_ret;
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
char_t *net_ntoa(const net_ip_addr_t *addr)
{
static char_t str[16];
return net_ntoa_r(addr, str, 16);
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
int32_t net_aton(const char_t *ptr, net_ip_addr_t *addr)
{
uint32_t val = 0;
uint32_t base;
char_t c0;
const char_t *cp = ptr;
uint32_t parts[4];
uint32_t *pp = parts;
int32_t ret = 1;
int32_t done;
c0 = *cp;
done = 0;
for (;;)
{
/*
* Collect number up to ``.''.
* Values are specified as for C:
* 0x=hex, 0=octal, 1-9=decimal.
*/
if (done == 1)
{
break;
}
if (!NET_ISDIGIT(c0))
{
ret = 0;
done = 1;
}
else
{
val = 0;
base = 10;
if (c0 == '0')
{
++cp;
c0 = (char_t) * cp;
if ((c0 == (char_t) 'x') || (c0 == (char_t) 'X'))
{
base = 16;
++cp;
c0 = (char_t) * cp;
}
else
{
base = 8;
}
}
for (;;)
{
if (NET_ISDIGIT(c0))
{
val = (val * base) + (uint32_t)c0 - (uint32_t) '0';
++cp;
c0 = (char_t) * cp;
}
else if ((base == 16U) && NET_ISXDIGIT(c0))
{
val = (val << 4) | ((uint32_t)c0 + 10U - (uint32_t)(NET_ISLOWER(c0) ? 'a' : 'A'));
++cp;
c0 = (char_t) * cp;
}
else
{
break;
}
}
if (c0 == '.')
{
/*
* Internet format:
* a.b.c.d
* a.b.c (with c treated as 16 bits)
* a.b (with b treated as 24 bits)
*/
if (pp >= (parts + 3))
{
ret = 0;
done = 1;
}
else
{
*pp = val;
pp++;
++cp;
c0 = (char_t) * cp;
}
}
else
{
done = 1;
}
}
}
/*
* Check for trailing characters.
*/
if ((c0 != (char_t)'\0') && (NET_ISSPACE((c0)) == false))
{
ret = 0;
}
else
/*
* Concoct the address according to
* the number of parts specified.
*/
{
switch (pp - parts + 1)
{
case 0:
ret = 0; /* initial nondigit */
break;
case 1: /* a -- 32 bits */
break;
case 2: /* a.b -- 8.24 bits */
if (val > 0xffffffUL)
{
ret = 0;
}
val |= parts[0] << 24;
break;
case 3: /* a.b.c -- 8.8.16 bits */
if (val > 0xffffU)
{
ret = 0;
break;
}
val |= (parts[0] << 24) | (parts[1] << 16);
break;
case 4: /* a.b.c.d -- 8.8.8.8 bits */
if (val > 0xffU)
{
ret = 0;
break;
}
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
break;
default:
ret = 0;
break;
}
}
if (ret == 1)
{
if (addr != NULL)
{
addr->addr = NET_HTONL(val);
}
}
return ret;
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
int32_t net_aton_r(const char_t *cp)
{
net_ip_addr_t val;
int32_t ret;
val.addr = 0;
if (net_aton(cp, &val) != 0)
{
ret = (int32_t) val.addr;
}
else
{
ret = 0;
}
return (ret);
}
#endif /* NET_USE_LWIP_DEFINITIONS */
uint16_t net_get_port(net_sockaddr_t *addr)
{
/*cstat -MISRAC2012-Rule-11.3 -MISRAC2012-Rule-11.8 */
return (NET_NTOHS(((net_sockaddr_in_t *)addr)->sin_port));
/*cstat +MISRAC2012-Rule-11.3 +MISRAC2012-Rule-11.8 +MISRAC2012-Rule-10.8 Cast */
}
void net_set_port(net_sockaddr_t *addr, uint16_t port)
{
/*cstat -MISRAC2012-Rule-11.3 Cast */
((net_sockaddr_in_t *)addr)->sin_port = NET_HTONS(port);
/*cstat +MISRAC2012-Rule-11.3 Cast */
}
net_ip_addr_t net_get_ip_addr(net_sockaddr_t *addr)
{
net_ip_addr_t ipaddr;
uint32_t addrv;
/*cstat -MISRAC2012-Rule-11.3 Cast */
addrv = ((net_sockaddr_in_t *)addr)->sin_addr.s_addr;
/*cstat +MISRAC2012-Rule-11.3 Cast */
NET_COPY(ipaddr, addrv);
return ipaddr;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,431 @@
/**
******************************************************************************
* @file net_class_extension.c
* @author MCD Application Team
* @brief Specific class interface function implementation
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#include "net_connect.h"
#include "net_internals.h"
#define MATCH(a,b) (a & (b) == (b))
/**
* @brief Convert wifi security enum value to string
* @param sec is an unsigned integer
* @retval a constant string , for instance "Open" or "WPA2-AES"
*/
const char_t *net_wifi_security_to_string(uint32_t sec)
{
const char_t *s;
if (sec == NET_WIFI_SM_OPEN)
{
s = "Open";
}
else if (sec == NET_WIFI_SM_WEP_SHARED)
{
s = "WEP-shared";
}
else if (sec == NET_WIFI_SM_WPA_TKIP_PSK)
{
s = "WPA-TKIP";
}
else if (sec == NET_WIFI_SM_WPA_MIXED_PSK)
{
s = "WPA-Mixed";
}
else if (sec == NET_WIFI_SM_WPA2_AES_PSK)
{
s = "WPA2-AES";
}
else if (sec == NET_WIFI_SM_WPA2_TKIP_PSK)
{
s = "WPA2-TKIP";
}
else if (sec == NET_WIFI_SM_WPA2_MIXED_PSK)
{
s = "WPA2_Mixed";
}
else if (sec == NET_WIFI_SM_WPA2_FBT_PSK)
{
s = "WPA2-FBT";
}
else if (sec == NET_WIFI_SM_WPA3_SAE)
{
s = "WPA3";
}
else if (sec == NET_WIFI_SM_WPA3_WPA2_PSK)
{
s = "WPA3-WPA2";
}
else if (sec == NET_WIFI_SM_WPA_TKIP_ENT)
{
s = "WPA-TKIP-Ent";
}
else if (sec == NET_WIFI_SM_WPA_AES_ENT)
{
s = "WPA-AES-Ent";
}
else if (sec == NET_WIFI_SM_WPA2_TKIP_ENT)
{
s = "WPA2-TKIP-Ent";
}
else if (sec == NET_WIFI_SM_WPA2_AES_ENT)
{
s = "WPA2-AES-Ent";
}
else if (sec == NET_WIFI_SM_WPA2_MIXED_ENT)
{
s = "WPA2-Mixed-Ent";
}
else if (sec == NET_WIFI_SM_WPA2_FBT_ENT)
{
s = "WPA-FBT-Ent";
}
else if (sec == NET_WIFI_SM_IBSS_OPEN)
{
s = "IBS";
}
else if (sec == NET_WIFI_SM_WPS_OPEN)
{
s = "WPS";
}
else if (sec == NET_WIFI_SM_WPS_SECURE)
{
s = "WPS-AES";
}
else
{
s = "unknown";
}
return s;
}
/**
* @brief Convert a string to a security enum value
* @param sec is a pointer to a string
*/
uint32_t net_wifi_string_to_security(char_t *sec)
{
uint32_t ret = NET_WIFI_SM_UNKNOWN;
if (strcmp(sec, "Open") == 0)
{
ret = NET_WIFI_SM_OPEN;
}
if (strcmp(sec, "WEP-shared") == 0)
{
ret = NET_WIFI_SM_WEP_SHARED;
}
if (strcmp(sec, "WPA-TKIP") == 0)
{
ret = NET_WIFI_SM_WPA_TKIP_PSK;
}
if (strcmp(sec, "WPA-Mixed") == 0)
{
ret = NET_WIFI_SM_WPA_MIXED_PSK;
}
if (strcmp(sec, "WPA2-AES") == 0)
{
ret = NET_WIFI_SM_WPA2_AES_PSK;
}
if (strcmp(sec, "WPA2-TKIP") == 0)
{
ret = NET_WIFI_SM_WPA2_TKIP_PSK;
}
if (strcmp(sec, "WPA2-Mixed") == 0)
{
ret = NET_WIFI_SM_WPA2_MIXED_PSK;
}
if (strcmp(sec, "WPA2-DBT") == 0)
{
ret = NET_WIFI_SM_WPA2_FBT_PSK;
}
if (strcmp(sec, "WPA3") == 0)
{
ret = NET_WIFI_SM_WPA3_SAE;
}
if (strcmp(sec, "WPA3-WPA2") == 0)
{
ret = NET_WIFI_SM_WPA3_WPA2_PSK;
}
if (strcmp(sec, "WPA-TKIP-Ent") == 0)
{
ret = NET_WIFI_SM_WPA_TKIP_ENT;
}
if (strcmp(sec, "WPA-AES-Ent") == 0)
{
ret = NET_WIFI_SM_WPA_AES_ENT;
}
if (strcmp(sec, "WPA2-TKIP-Ent") == 0)
{
ret = NET_WIFI_SM_WPA2_TKIP_ENT;
}
if (strcmp(sec, "WPA2-AES-Ent") == 0)
{
ret = NET_WIFI_SM_WPA2_AES_ENT;
}
if (strcmp(sec, "WPA2-Mixed-Ent") == 0)
{
ret = NET_WIFI_SM_WPA2_MIXED_ENT;
}
if (strcmp(sec, "WPA-FBT-Ent") == 0)
{
ret = NET_WIFI_SM_WPA2_FBT_ENT;
}
if (strcmp(sec, "IBS") == 0)
{
ret = NET_WIFI_SM_IBSS_OPEN;
}
if (strcmp(sec, "WPS") == 0)
{
ret = NET_WIFI_SM_WPS_OPEN;
}
if (strcmp(sec, "WPS-AES") == 0)
{
ret = NET_WIFI_SM_WPS_SECURE;
}
return ret;
}
/**
* @brief start a wifi scan operation
* @param pnetif_in is a pointer to an allocated network interface structure
* @param mode is an enum to specify type of scan mode to be performed
* @param ssid is a pointer to a string, when not null, scan searches only this ssid
* @retval return the number of found access point , max value is "number".
* This function is a synchronous function.
*/
int32_t net_wifi_scan(net_if_handle_t *pnetif_in, net_wifi_scan_mode_t mode, char_t *ssid)
{
int32_t ret = NET_OK;
net_if_handle_t *pnetif;
pnetif = netif_check(pnetif_in);
if (pnetif == NULL)
{
NET_DBG_ERROR("No network interface defined");
ret = NET_ERROR_PARAMETER;
}
else if (pnetif->pdrv->if_class != NET_INTERFACE_CLASS_WIFI)
{
NET_DBG_ERROR("Incorrect class interface when calling net_wifi_scan function\n");
ret = NET_ERROR_PARAMETER;
}
else
{
if (pnetif->pdrv->extension.wifi->scan(pnetif, mode, ssid) != NET_OK)
{
NET_DBG_ERROR("Error when executing net_wifi_scan function\n");
ret = NET_ERROR_GENERIC;
}
}
return ret;
}
/**
* @brief Get the result of scan operation , once event has been recevied
* @param pnetif_is a pointer to an allocated network interface structure
* @param results is a pointer to an allocated array of net_wifi_scan_results_t
* @param number is unsigned integer , size of the array 'results'
* @retval return the number of found access point , max value is "number".
*/
int32_t net_wifi_get_scan_results(net_if_handle_t *pnetif_in, net_wifi_scan_results_t *results, uint8_t number)
{
int32_t ret;
net_if_handle_t *pnetif;
pnetif = netif_check(pnetif_in);
if (pnetif == NULL)
{
NET_DBG_ERROR("No network interface defined");
ret = NET_ERROR_PARAMETER;
}
else if (pnetif->pdrv->if_class != NET_INTERFACE_CLASS_WIFI)
{
NET_DBG_ERROR("Incorrect class interface when calling net_wifi_scan function\n");
ret = NET_ERROR_PARAMETER;
}
else
{
ret = pnetif->pdrv->extension.wifi->get_scan_results(pnetif, results, number);
}
return ret;
}
/**
* @brief set the credential of a wifi interface, can be AP or STA credentials
* @param pnetif_is a pointer to an allocated network interface structure
* @param credentials a pointer to a const allocated structure which contain credentials values (ssid , passwd)
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_wifi_set_credentials(net_if_handle_t *pnetif, const net_wifi_credentials_t *credentials)
{
pnetif->pdrv->extension.wifi->credentials = credentials;
return NET_OK;
}
/**
* @brief set the acess mode for a wifi interface: AP or STA mode
* @param pnetif_is a pointer to an allocated network interface structure
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_wifi_set_access_mode(net_if_handle_t *pnetif, net_wifi_mode_t mode)
{
pnetif->pdrv->extension.wifi->mode = mode;
return NET_OK;
}
/**
* @brief set the wifi channel to used for an AP
* @param pnetif_is a pointer to an allocated network interface structure
* @param channel is an unsigned 8 bit integer
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_wifi_set_access_channel(net_if_handle_t *pnetif, uint8_t channel)
{
pnetif->pdrv->extension.wifi->access_channel = channel;
return NET_OK;
}
/**
* @brief set wifi power save mode
* @param pnetif_is a pointer to an allocated network interface structure
* @param powersave is a pointer to an allocated structute to define the powersave mode
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_wifi_set_powersave(net_if_handle_t *pnetif_in, const net_wifi_powersave_t *powersave)
{
int32_t ret = NET_OK;
net_if_handle_t *pnetif;
pnetif = netif_check(pnetif_in);
if (pnetif == NULL)
{
NET_DBG_ERROR("No network interface defined");
ret = NET_ERROR_PARAMETER;
}
else
{
if (pnetif->pdrv->if_class != NET_INTERFACE_CLASS_WIFI)
{
NET_DBG_ERROR("Incorrect class interface when calling net_wifi_set_powersave function\n");
ret = NET_ERROR_PARAMETER;
}
else
{
pnetif->pdrv->extension.wifi->powersave = powersave;
}
}
return ret;
}
/**
* @brief set wifi extension parameter
* @param pnetif_is a pointer to an allocated network interface structure
* @param param is an enum value to specify which parameter to set
* @param data is a pointer to an allocated opaque structure to specify the parameter value
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_wifi_set_param(net_if_handle_t *pnetif, const net_wifi_param_t param, void *data)
{
int32_t ret;
if (pnetif->pdrv->if_class != NET_INTERFACE_CLASS_WIFI)
{
NET_DBG_ERROR("Incorrect class interface when calling net_wifi_set_param function\n");
ret = NET_ERROR_PARAMETER;
}
else
{
ret = pnetif->pdrv->extension.wifi->set_param(param, data);
}
return ret;
}
/**
* @brief set the credential of a cellular interface
* @param pnetif_is a pointer to an allocated network interface structure
* @param credentials a pointer to a const allocated structure which contains credentials values (ssid , passwd)
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_cellular_set_credentials(net_if_handle_t *pnetif_in, const net_cellular_credentials_t *credentials)
{
int32_t ret;
net_if_handle_t *pnetif;
pnetif = netif_check(pnetif_in);
if (pnetif == NULL)
{
NET_DBG_ERROR("No network interface defined");
ret = NET_ERROR_PARAMETER;
}
else
{
if (pnetif->pdrv->if_class != NET_INTERFACE_CLASS_CELLULAR)
{
NET_DBG_ERROR("Incorrect class interface when calling net_cellular_get_radio_results function\n");
ret = NET_ERROR_PARAMETER;
}
else
{
pnetif->pdrv->extension.cellular->credentials = credentials;
ret = NET_OK;
}
}
return ret;
}
/**
* @brief get cellular radio information
* @param pnetif_is a pointer to an allocated network interface structure
* @param reults is a pointer to an allocated net_cellular_radio_results_t structure
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_cellular_get_radio_results(net_if_handle_t *pnetif_in, net_cellular_radio_results_t *results)
{
int32_t ret;
net_if_handle_t *pnetif;
pnetif = netif_check(pnetif_in);
if (pnetif == NULL)
{
NET_DBG_ERROR("No network interface defined");
ret = NET_ERROR_PARAMETER;
}
else
{
if (pnetif->pdrv->if_class != NET_INTERFACE_CLASS_CELLULAR)
{
NET_DBG_ERROR("Incorrect class interface when calling net_cellular_get_radio_results function\n");
ret = NET_ERROR_PARAMETER;
}
else
{
ret = pnetif->pdrv->extension.cellular->get_radio_results(results);
}
}
return ret;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,569 @@
/**
******************************************************************************
* @file net_core.c
* @author MCD Application Team
* @brief Network interface core implementation
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#include "net_connect.h"
#include "net_internals.h"
static void netif_add_to_list(net_if_handle_t *pnetif);
static void netif_remove_from_list(net_if_handle_t *pnetif);
static net_if_handle_t *net_if_list = NULL;
#ifndef __IO
/*cstat -MISRAC2012-Rule-21.1 */
#define __IO volatile
/*cstat +MISRAC2012-Rule-21.1 */
#endif /* IO */
static void netif_add_to_list(net_if_handle_t *pnetif)
{
LOCK_NETIF_LIST();
if (net_if_list == NULL)
{
net_if_list = pnetif;
}
else
{
/*add it to end of the list*/
net_if_handle_t *plastnetif;
plastnetif = net_if_list;
while (plastnetif->next != NULL)
{
plastnetif = plastnetif->next;
}
plastnetif->next = pnetif;
}
UNLOCK_NETIF_LIST();
}
static void netif_remove_from_list(net_if_handle_t *pnetif)
{
net_if_handle_t *pnetif_prev;
LOCK_NETIF_LIST();
if (net_if_list == pnetif)
{
net_if_list = net_if_list->next;
}
else
{
for (pnetif_prev = net_if_list; pnetif_prev->next != NULL; pnetif_prev = pnetif_prev->next)
{
if (pnetif_prev->next == pnetif)
{
pnetif_prev->next = pnetif->next;
break;
}
}
}
UNLOCK_NETIF_LIST();
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
net_if_handle_t *net_if_find(net_sockaddr_t *addr)
{
net_if_handle_t *ptr;
net_ip_addr_t ipaddr;
net_ip_addr_t ipaddr_zero;
NET_ZERO(ipaddr_zero);
NET_ZERO(ipaddr);
if (addr != NULL)
{
ipaddr = net_get_ip_addr(addr);
}
LOCK_NETIF_LIST();
ptr = net_if_list;
if (NET_DIFF(ipaddr, ipaddr_zero) != 0)
{
do
{
if (NET_EQUAL(ptr->ipaddr, ipaddr))
{
break;
}
ptr = ptr->next;
} while (ptr != NULL);
}
UNLOCK_NETIF_LIST();
return ptr;
}
net_if_handle_t *netif_check(net_if_handle_t *pnetif_in)
{
net_if_handle_t *pnetif = pnetif_in;
if (pnetif == NULL)
{
/* get default interface*/
pnetif = net_if_find(NULL);
if (pnetif == NULL)
{
NET_DBG_ERROR("No network interface defined");
}
}
return pnetif;
}
/**
* @brief Wait for state transtion
* @param pnetif a pointer to the selected network interface
* @param state the expected state
* @param timeout max time to wait in ms for the transition
* @retval 0 in case of success, an error code otherwise
*/
extern uint32_t HAL_GetTick(void);
int32_t net_if_wait_state(net_if_handle_t *pnetif, net_state_t state, uint32_t timeout)
{
int32_t ret = NET_OK;
__IO net_state_t *p;
p = &pnetif->state;
uint32_t start_time = HAL_GetTick();
while (*p != state)
{
if (HAL_GetTick() >= (start_time + timeout))
{
ret = NET_TIMEOUT;
break;
}
WAIT_STATE_CHANGE(timeout);
}
return ret;
}
void net_if_notify(net_if_handle_t *pnetif, net_evt_t event_class, uint32_t event_id, void *event_data)
{
/* call the user Handler first ,FIXME , first or not , race between wait state transition and user handler */
if ((NULL != pnetif->event_handler) && (NULL != pnetif->event_handler->callback))
{
pnetif->event_handler->callback(pnetif->event_handler->context, event_class, event_id, event_data);
}
}
#ifdef NET_USE_RTOS
static int32_t net_initialized = 0;
#endif /* NET_USE_RTOS */
/** @defgroup State State Management Network Framework
* Application uses this set of function to control the network interface state.
* Normal state flow is init => start => connect.
* Socket interface can be used when connected state is reached.Network interface is connected and got an IP address.
* To finish, flow is disconnect,stop,deinit. All connection are closed and allocated resources are freed.
* State transition are asynchronous but could be implemented in a synchronous way depending on the selected
* network interface. Once a transition is requested,the net_wait_state primitive should be used to wait
* for transition to occur.
* @{
*/
/**
* @brief Perform network interface initialization
* @param pnetif a pointer to an allocated network interface structure
* @param driver_init a pointer to a function which define the driver to use
* @param event_handler a calback function to manage event from network framework
* @retval 0 in case of success, an error code otherwise
* This function is a synchronous function.
*/
int32_t net_if_init(net_if_handle_t *pnetif_in, net_if_driver_init_func driver_init,
const net_event_handler_t *event_handler)
{
int32_t ret;
net_if_handle_t *pnetif = pnetif_in;
#ifdef NET_USE_RTOS
if (net_initialized == 0)
{
net_init_locks();
net_initialized = 1;
}
#endif /* NET_USE_RTOS */
if (pnetif != NULL)
{
pnetif->event_handler = event_handler;
pnetif->state = NET_STATE_INITIALIZED;
netif_add_to_list(pnetif);
ret = (*driver_init)(pnetif);
if (NET_OK != ret)
{
NET_DBG_ERROR("Interface cannot be initialized.");
ret = NET_ERROR_INTERFACE_FAILURE;
}
}
else
{
NET_DBG_ERROR("Invalid interface.");
ret = NET_ERROR_PARAMETER;
}
return ret;
}
/**
* @brief Perform network interface de-initialization
* @param pnetif a pointer to an allocated network interface structure
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_if_deinit(net_if_handle_t *pnetif)
{
int32_t ret;
ret = net_state_manage_event(pnetif, NET_EVENT_CMD_DEINIT);
pnetif->state = NET_STATE_DEINITIALIZED;
if (ret == NET_OK)
{
netif_remove_from_list(pnetif);
}
#ifdef NET_USE_RTOS
if (net_initialized == 1)
{
net_destroy_locks();
net_initialized = 0;
}
#endif /* NET_USE_RTOS */
return ret;
}
/**
* @brief Start network interface
* @param pnetif a pointer to an allocated network interface structure
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_if_start(net_if_handle_t *pnetif)
{
return net_state_manage_event(pnetif, NET_EVENT_CMD_START);
}
/**
* @brief Stop network interface
* @param pnetif a pointer to an allocated network interface structure
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_if_stop(net_if_handle_t *pnetif)
{
return net_state_manage_event(pnetif, NET_EVENT_CMD_STOP);
}
/**
* @brief Yield data from network interface
* @param pnetif a pointer to an allocated network interface structure
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_if_yield(net_if_handle_t *pnetif_in, uint32_t timeout)
{
int32_t ret = NET_OK;
net_if_handle_t *pnetif;
net_state_t state;
pnetif = netif_check(pnetif_in);
if (pnetif != NULL)
{
(void) net_if_getState(pnetif, &state);
if (state == NET_STATE_CONNECTED)
{
if (NULL != pnetif->pdrv->if_yield)
{
ret = pnetif->pdrv->if_yield(pnetif, timeout);
}
if (ret != NET_OK)
{
NET_DBG_ERROR("Interface yield failed!!!");
ret = NET_ERROR_STATE_TRANSITION;
}
}
else
{
NET_DBG_ERROR("Incorrect requested State transition");
ret = NET_ERROR_INVALID_STATE_TRANSITION;
}
}
else
{
NET_DBG_ERROR("Invalid interface.");
ret = NET_ERROR_PARAMETER;
}
return ret;
}
/**
* @brief Connect network interface
* @param pnetif a pointer to an allocated network interface structure
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_if_connect(net_if_handle_t *pnetif)
{
return net_state_manage_event(pnetif, NET_EVENT_CMD_CONNECT);
}
/**
* @brief Disconnect network interface
* @param pnetif a pointer to an allocated network interface structure
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_if_disconnect(net_if_handle_t *pnetif)
{
return net_state_manage_event(pnetif, NET_EVENT_CMD_DISCONNECT);
}
/**
* @brief get network interface state
* @param pnetif a pointer to an allocated network interface structure
* @param state a pointer to a net_state_t enum
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_if_getState(net_if_handle_t *pnetif_in, net_state_t *state)
{
int32_t ret;
net_if_handle_t *pnetif;
pnetif = netif_check(pnetif_in);
if (pnetif != NULL)
{
*state = pnetif->state;
ret = NET_OK;
}
else
{
NET_DBG_ERROR("Invalid interface.");
ret = NET_ERROR_PARAMETER;
}
return ret;
}
/** @defgroup State
* @}
*/
/**
* @brief Enable power save mode
* @param pnetif a pointer to an allocated network interface structure
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_if_powersave_enable(net_if_handle_t *pnetif_in)
{
int32_t ret;
net_if_handle_t *pnetif;
pnetif = netif_check(pnetif_in);
if (pnetif != NULL)
{
if (pnetif->state == NET_STATE_CONNECTED)
{
ret = pnetif->pdrv->if_powersave_enable(pnetif);
}
else
{
NET_DBG_ERROR("Power-save cannot be enabled when the device is not connected");
ret = NET_ERROR_INVALID_STATE_TRANSITION;
}
}
else
{
ret = NET_ERROR_PARAMETER;
NET_DBG_ERROR("Invalid interface.");
}
return ret;
}
/** @defgroup GetAndSet Get and Set Network Interface information
* @{
*/
/**
* @brief get MAC address
* @param pnetif a pointer to an allocated network interface structure
* @param mac a pointer to an allocated macaddr_t structure
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_if_get_mac_address(net_if_handle_t *pnetif_in, macaddr_t *mac)
{
int32_t ret;
net_if_handle_t *pnetif;
pnetif = netif_check(pnetif_in);
if (pnetif != NULL)
{
if (NET_STATE_DEINITIALIZED != pnetif->state)
{
(void) memcpy(mac, &pnetif->macaddr, sizeof(macaddr_t));
ret = NET_OK;
}
else
{
ret = NET_ERROR_INTERFACE_FAILURE;
NET_DBG_ERROR("Interface not yet initialized or in error state");
}
}
else
{
NET_DBG_ERROR("Invalid interface.");
ret = NET_ERROR_PARAMETER;
}
return ret;
}
/**
* @brief get IP address
* @param pnetif a pointer to an allocated network interface structure
* @param ip a pointer to an allocated net_ip_addr_t structure
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_if_get_ip_address(net_if_handle_t *pnetif_in, net_ip_addr_t *ip)
{
int32_t ret;
net_if_handle_t *pnetif;
pnetif = netif_check(pnetif_in);
if (pnetif != NULL)
{
if (pnetif->state == NET_STATE_CONNECTED)
{
*ip = pnetif->ipaddr;
ret = NET_OK;
}
else
{
NET_DBG_ERROR("Can get ipaddr for un connected network interface");
ret = NET_ERROR_INTERFACE_FAILURE;
}
}
else
{
NET_DBG_ERROR("Invalid interface.");
ret = NET_ERROR_PARAMETER;
}
return ret;
}
/**
* @brief get host by name
* @param pnetif a pointer to an allocated network interface structure
* @param name is a pointer to the hostname string
* @param addr is a pointer to the structure net_sockaddr_t
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_if_gethostbyname(net_if_handle_t *pnetif_in, net_sockaddr_t *addr, char_t *name)
{
int32_t ret = NET_ERROR_FRAMEWORK;
net_if_handle_t *pnetif;
pnetif = netif_check(pnetif_in);
if (pnetif != NULL)
{
ret = pnetif->pdrv->pgethostbyname(pnetif, addr, name);
}
return ret;
}
/**
* @brief ping a remote machine
* @param pnetif a pointer to an allocated network interface structure
* @param addr is a pointer to the socketaddr of the remote host
* @param count is an integer, number of iteration to ping the remote machine
* @param delay is an integer, maximum delay in millisecond to wait for remote answer
* @param response is an array of <count> integer, containing the time to get response for each iteration.
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_if_ping(net_if_handle_t *pnetif_in, net_sockaddr_t *addr, int32_t count, int32_t delay, int32_t response[])
{
int32_t ret = NET_ERROR_FRAMEWORK;
net_if_handle_t *pnetif;
pnetif = netif_check(pnetif_in);
if (pnetif != NULL)
{
ret = pnetif->pdrv->pping(pnetif, addr, count, delay, response);
}
return ret;
}
/**
* @brief enable or disable dhcp mode
* @param pnetif a pointer to an allocated network interface structure
* @param mode is a boolean , true to activate DHCP
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_if_set_dhcp_mode(net_if_handle_t *pnetif_in, bool mode)
{
int32_t ret = NET_ERROR_FRAMEWORK;
net_if_handle_t *pnetif;
pnetif = netif_check(pnetif_in);
if (pnetif != NULL)
{
pnetif->dhcp_mode = mode;
ret = NET_OK;
}
return ret;
}
/**
* @brief setting ipaddr , gateway and netmask forcurrent network interface
* @param pnetif a pointer to an allocated network interface structure
* @param ipaddr is a pointer to and net_ip_addr_t structure used as ip address
* @param gateway is a pointer to the net_ip_addr_t structure used as gateway address
* @param netmask is a pointer to the net_ip_addr_t structure used as the netmask
* @retval 0 in case of success, an error code otherwise
*/
int32_t net_if_set_ipaddr(net_if_handle_t *pnetif_in, net_ip_addr_t ipaddr,
net_ip_addr_t gateway, net_ip_addr_t netmask)
{
int32_t ret = NET_ERROR_FRAMEWORK;
net_if_handle_t *pnetif;
pnetif = netif_check(pnetif_in);
if (pnetif != NULL)
{
pnetif->static_ipaddr = ipaddr;
pnetif->static_gateway = gateway;
pnetif->static_netmask = netmask;
ret = NET_OK;
}
return ret;
}
/** @defgroup GetAndSet
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,819 @@
/**
******************************************************************************
* @file net_os.c
* @author MCD Application Team
* @brief OS needed functions implementation
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#include "net_connect.h"
#include "net_internals.h"
#include "stdarg.h"
#ifdef NET_USE_RTOS
#if (osCMSIS >= 0x20000U)
#define OSSEMAPHOREWAIT osSemaphoreAcquire
#else
#define OSSEMAPHOREWAIT osSemaphoreWait
#endif /* osCMSIS */
extern void *pxCurrentTCB;
static osSemaphoreId net_mutex[NET_LOCK_NUMBER];
void net_init_locks(void)
{
#if (osCMSIS < 0x20000U)
static osSemaphoreDef_t mutex_def[NET_LOCK_NUMBER] = {0};
#endif /* osCMSIS */
#ifdef NET_MBEDTLS_HOST_SUPPORT
net_tls_init();
#endif /* NET_MBEDTLS_HOST_SUPPORT */
for (int32_t i = 0; i < NET_LOCK_NUMBER; i++)
{
#if (osCMSIS < 0x20000U)
net_mutex[i] = osSemaphoreCreate(&mutex_def[i], 1);
#else
net_mutex[i] = osSemaphoreNew(1, 1, NULL);
#endif /* osCMSIS */
NET_ASSERT(net_mutex[i] > 0, "Failed on mutex creation");
}
}
void net_destroy_locks(void)
{
#ifdef NET_MBEDTLS_HOST_SUPPORT
net_tls_destroy();
#endif /* NET_MBEDTLS_HOST_SUPPORT */
for (int32_t i = 0; i < NET_LOCK_NUMBER; i++)
{
(void)osSemaphoreDelete(net_mutex[i]);
}
}
void net_lock(int32_t sock, uint32_t timeout_in)
{
int32_t ret;
uint32_t timeout = timeout_in;
if (timeout == NET_OS_WAIT_FOREVER)
{
/*MISRA issue so hand coded osWaitForever*/
timeout = 0xffffffffU;
}
ret = (int32_t) OSSEMAPHOREWAIT(net_mutex[sock], timeout);
NET_ASSERT(ret == 0, "Failed locking mutex");
}
void net_unlock(int32_t sock)
{
int32_t ret;
ret = (int32_t) osSemaphoreRelease(net_mutex[sock]);
NET_ASSERT(ret == 0, "Failed unlocking mutex");
}
void net_lock_nochk(int32_t sock, uint32_t timeout_in)
{
uint32_t timeout = timeout_in;
if (timeout == NET_OS_WAIT_FOREVER)
{
/* MISRA issue so hand coded t osWaitForever*/
timeout = 0xffffffffU;
}
(void) OSSEMAPHOREWAIT(net_mutex[sock], timeout);
}
void net_unlock_nochk(int32_t sock)
{
(void) osSemaphoreRelease(net_mutex[sock]);
}
#if !defined(NET_ALLOC_DEBUG)
/*cstat -MISRAC2012-Rule-21.2 */
void *net_calloc(size_t n, size_t m)
{
void *p;
/*cstat -MISRAC2012-Rule-21.3 -MISRAC2012-Dir-4.12 */
p = pvPortMalloc(n * m);
/*cstat +MISRAC2012-Rule-21.3 +MISRAC2012-Dir-4.12 */
if (p != NULL)
{
(void) memset(p, 0, n * m);
}
return p;
}
void *net_realloc(void *ptr, size_t size)
{
void *ret;
if (ptr == NULL)
{
if (size != (size_t) 0)
{
/*cstat -MISRAC2012-Rule-21.3 -MISRAC2012-Dir-4.12 */
ret = pvPortMalloc(size);
/*cstat +MISRAC2012-Rule-21.3 +MISRAC2012-Dir-4.12 */
if (ret == NULL)
{
/* to avoid erroneous MISRA detection */
ret = NULL;
}
}
else
{
ret = NULL;
}
}
else
{
if (size != (size_t) 0)
{
void *new_ptr;
/*cstat -MISRAC2012-Rule-21.3 -MISRAC2012-Dir-4.12 */
new_ptr = pvPortMalloc(size);
/*cstat +MISRAC2012-Rule-21.3 +MISRAC2012-Dir-4.12 */
if (new_ptr != NULL)
{
(void) memcpy(new_ptr, ptr, size);
/*cstat -MISRAC2012-Rule-21.3 -MISRAC2012-Dir-4.12 */
vPortFree(ptr);
/*cstat +MISRAC2012-Rule-21.3 +MISRAC2012-Dir-4.12 */
ret = new_ptr;
}
else
{
ret = NULL;
}
}
else
{
/*cstat -MISRAC2012-Rule-21.3 -MISRAC2012-Dir-4.12 */
vPortFree(ptr);
/*cstat +MISRAC2012-Rule-21.3 +MISRAC2012-Dir-4.12 */
ret = NULL;
}
}
return ret;
}
#endif /* !NET_ALLOC_DEBUG */
/* below function are not supposed to be used , all malloc /free should be mapped to NET_MALLOC/NET_FREE macros */
/* if not the case , it means that some mapping are missing */
/* Using directly the malloc/free prevent to track orginal locatino of memory leakages */
/*cstat -MISRAC2012-Rule-21.2 */
void *realloc(void *p, size_t n)
{
return NET_REALLOC(p, n);
}
void *calloc(size_t n, size_t m)
{
return NET_CALLOC(n, m);
}
void *malloc(size_t n)
{
return NET_MALLOC(n);
}
void free(void *p)
{
NET_FREE(p);
}
/*cstat +MISRAC2012-Rule-21.2 */
#endif /* NET_USE_RTOS */
#ifdef NET_ALLOC_DEBUG
#ifdef NET_ALLOC_DEBUG_TREE
#define NET_DISPLAY_RESULT_COLUMN (NET_DISPLAY_WIDTH-((2U*NET_DISPLAY_RESULT_WIDTH)+1U))
typedef struct net_alloc_node_s
{
const char_t *name;
uint32_t namelen;
struct net_alloc_node_s *down;
struct net_alloc_node_s *up;
struct net_alloc_node_s *neighbour;
uint32_t current_alloc;
uint32_t max_total_alloc;
}
net_alloc_node_t;
static net_alloc_node_t node[NET_ALLOC_MAX_NODE + 1];
static net_alloc_node_t *root_node;
static uint32_t max_node;
#endif /* NET_ALLOC_DEBUG_TREE */
typedef struct net_debug_alloc
{
const char_t *filename;
uint16_t line;
uint16_t iter;
uint32_t size;
void *p;
#ifdef NET_ALLOC_DEBUG_TREE
net_alloc_node_t *node;
#endif /* NET_ALLOC_DEBUG_TREE */
} net_debug_alloc_t;
static uint32_t current_alloc = 0;
static uint32_t max_total_alloc = 0;
static uint32_t iteralloc = 0;
static uint32_t iterfree = 0;
static uint32_t max_alive_alloc = 0;
static net_debug_alloc_t allocated_info[NET_LEAKAGE_ARRAY];
void *net_calloc_debug(size_t n, size_t msize, const char_t *filename, uint32_t line)
{
/*cstat -MISRAC2012-Dir-4.12 */
void *p = net_malloc_debug(n * msize, filename, line);
/*cstat +MISRAC2012-Dir-4.12 */
if (p != NULL)
{
(void) memset(p, 0, n * msize);
}
return p;
}
void *net_realloc_debug(void *p, size_t size, const char_t *filename, uint32_t line)
{
void *ret;
if (p == NULL)
{
if (size != (size_t) 0)
{
/*cstat -MISRAC2012-Rule-21.3 -MISRAC2012-Dir-4.12 */
ret = net_malloc_debug(size, filename, line);
/*cstat +MISRAC2012-Rule-21.3 +MISRAC2012-Dir-4.12 */
if (ret == NULL)
{
/* to avoid erroneous MISRA detection */
ret = NULL;
}
}
else
{
ret = NULL;
}
}
else
{
if (size != (size_t) 0)
{
void *new_ptr;
/*cstat -MISRAC2012-Rule-21.3 -MISRAC2012-Dir-4.12 */
new_ptr = net_malloc_debug(size, filename, line);
/*cstat +MISRAC2012-Rule-21.3 +MISRAC2012-Dir-4.12 */
if (new_ptr != NULL)
{
(void) memcpy(new_ptr, p, size);
/*cstat -MISRAC2012-Rule-21.3 -MISRAC2012-Dir-4.12 */
net_free_debug(p);
/*cstat +MISRAC2012-Rule-21.3 +MISRAC2012-Dir-4.12 */
ret = new_ptr;
}
else
{
ret = NULL;
}
}
else
{
/*cstat -MISRAC2012-Rule-21.3 -MISRAC2012-Dir-4.12 */
net_free_debug(p);
/*cstat +MISRAC2012-Rule-21.3 +MISRAC2012-Dir-4.12 */
ret = NULL;
}
}
return ret;
}
#ifdef NET_ALLOC_DEBUG_TREE
static uint32_t getdirlen(const char_t *filename_in)
{
uint32_t len = 0;
const char_t *filename = filename_in;
if (*filename != '\0')
{
if (*filename == '\\')
{
len = 1;
filename++;
}
if ((filename[0] == 'C') && (filename[1] == ':') && (filename[2] == '\\'))
{
len = 3;
filename++;
filename++;
filename++;
}
while ((*filename != '\0') && (*filename != '\\'))
{
len++;
filename++;
}
}
return len;
}
static net_alloc_node_t *get_new_node(const char_t *filename, uint32_t dir_name_len, uint32_t n)
{
net_alloc_node_t *p = &node[max_node];
uint32_t next_dir_name_len = getdirlen(&filename[dir_name_len]);
max_node++;
p->current_alloc = n;
p->max_total_alloc = n;
p->name = filename;
p->namelen = dir_name_len;
if (max_node == NET_ALLOC_MAX_NODE)
{
while (true)
{
(void) printf("ERROR: Please increase NET_ALLOC_MAX_NODE, current value %lu is too low\n", NET_ALLOC_MAX_NODE);
}
}
if (next_dir_name_len != 0U)
{
/*cstat -MISRAC2012-Rule-17.2_a */
p->down = get_new_node(&filename[dir_name_len], next_dir_name_len, n);
/*cstat +MISRAC2012-Rule-17.2_a */
p->down->up = p;
}
return p;
}
static net_alloc_node_t *net_walk_malloc_node(net_alloc_node_t *root, const char_t *filename, uint32_t n)
{
net_alloc_node_t *p = root;
uint32_t dir_name_len = getdirlen(filename);
/* search amoung the neighbour (same level tree) */
while (NULL != p)
{
if (strncmp(p->name, filename, dir_name_len) == 0)
{
/* find a matching neighbour */
p->current_alloc += n;
if (p->current_alloc > p->max_total_alloc)
{
p->max_total_alloc = p->current_alloc;
}
/*printf("ALLOC %s %d %d inc %d\n",filename,p->max_total_alloc,p->current_alloc,n);*/
/* Did not reach a leaf so continue down in the tree */
if (filename[dir_name_len] != '\0')
{
/*cstat -MISRAC2012-Rule-17.2_a */
p = net_walk_malloc_node(p->down, &filename[dir_name_len], n);
/*cstat +MISRAC2012-Rule-17.2_a */
}
break;
}
p = p->neighbour;
}
if (NULL == p)
{
/* create a new neighbour and all the associated tree */
p = get_new_node(filename, dir_name_len, n);
/* add to neighbour list */
if (NULL != root)
{
p->up = root->up;
p->neighbour = root->neighbour;
root->neighbour = p;
}
/* but we should return the leaf */
while (NULL != p->down)
{
p = p->down;
}
}
return p;
}
static void net_walk_free_node(net_alloc_node_t *node_in, uint32_t n)
{
net_alloc_node_t *node = node_in;
while (NULL != node)
{
node->current_alloc -= n;
/*printf("FREE %s %d %d inc %d\n",node->name,node->max_total_alloc,node->current_alloc,n);*/
node = node->up;
}
}
static net_alloc_node_t *net_malloc_tree_start(net_alloc_node_t *root)
{
net_alloc_node_t *p = root;
while (NULL == p->down->neighbour)
{
p = p->down;
}
return p;
}
static void net_malloc_tree_print(net_alloc_node_t *root, uint32_t level)
{
net_alloc_node_t *p = root;
if (level == 0U)
{
(void) printf("\n### Dynamic Allocation tree report, uses %lu nodes out of %lu (%lu bytes)\n", max_node,
NET_ALLOC_MAX_NODE, max_node * sizeof(net_alloc_node_t));
for (uint32_t i = 0U; i < NET_DISPLAY_RESULT_COLUMN; i++)
{
(void) printf("-");
}
(void) printf("%*s %*s", NET_DISPLAY_RESULT_WIDTH, "Maximum", NET_DISPLAY_RESULT_WIDTH, "Leakage");
(void) printf("\n");
}
while (NULL != p)
{
{
char_t s[100];
uint32_t w = level;
uint32_t n = NET_DISPLAY_RESULT_COLUMN - ((level + 1U) * NET_DISPLAY_TAB) - NET_DISPLAY_DIRNAME_LEN;
(void) strncpy(s, &p->name[1], p->namelen - 1U);
s[p->namelen - 1U] = '\0';
(void) printf("%*c", NET_DISPLAY_TAB, ' ');
while (w != 0U)
{
w--;
(void) printf(".");
#if (NET_DISPLAY_TAB>1)
(void)printf("%*c", NET_DISPLAY_TAB - 1U, ' ');
#endif /* NET_DISPLAY_TAB */
}
(void) printf("%-*s", NET_DISPLAY_DIRNAME_LEN, s);
if ((NULL != p->down) && (p->down->max_total_alloc == p->max_total_alloc)
&& (p->down->current_alloc == p->current_alloc))
{
(void) printf("\n");
}
else
{
(void) printf("%*c%*d %*d\n", n, ' ', NET_DISPLAY_RESULT_WIDTH, p->max_total_alloc, NET_DISPLAY_RESULT_WIDTH,
p->current_alloc);
}
}
/*cstat -MISRAC2012-Rule-17.2_a */
net_malloc_tree_print(p->down, level + 1U);
/*cstat +MISRAC2012-Rule-17.2_a */
p = p->neighbour;
}
}
#endif /* NET_ALLOC_DEBUG_TREE */
void *net_malloc_debug(size_t n, const char_t *filename, uint32_t line)
{
void *p;
uint32_t i;
#ifdef NET_USE_RTOS
vTaskSuspendAll();
#endif /* NET_USE_RTOS */
if (iteralloc == 0U)
{
(void) memset(allocated_info, 0, sizeof(allocated_info));
current_alloc = 0;
max_total_alloc = 0;
#ifdef NET_ALLOC_DEBUG_TREE
max_node = 0;
root_node = NULL;
(void) memset(node, 0, sizeof(node));
#endif /* NET_ALLOC_DEBUG_TREE */
}
iteralloc++;
current_alloc += n;
if (current_alloc > max_total_alloc)
{
max_total_alloc = current_alloc;
}
/*printf("-ALLOC- Max %d Current %d inc %d\n",max_total_alloc,current_alloc,n);*/
#ifdef NET_USE_RTOS
p = pvPortMalloc(n);
#else
/*cstat -MISRAC2012-Dir-4.12 -MISRAC2012-Dir-4.7_b -MISRAC2012-Rule-21.3 */
p = malloc(n);
/*cstat +MISRAC2012-Dir-4.12 +MISRAC2012-Dir-4.7_b +MISRAC2012-Rule-21.3 */
#endif /* NET_USE_RTOS */
if ((iteralloc - iterfree) > max_alive_alloc)
{
max_alive_alloc = iteralloc - iterfree;
}
for (i = 0; i < NET_LEAKAGE_ARRAY ; i++)
{
if (allocated_info[i].p == 0U)
{
allocated_info[i].p = p ;
allocated_info[i].size = n ;
allocated_info[i].line = (uint16_t) line ;
allocated_info[i].filename = filename;
allocated_info[i].iter = (uint16_t) iteralloc;
#ifdef NET_ALLOC_DEBUG_TREE
allocated_info[i].node = net_walk_malloc_node(root_node, filename, n);
if (NULL == root_node)
{
root_node = allocated_info[i].node;
/* we got the leaf , so move to top */
while (NULL != root_node->up)
{
root_node = root_node->up;
}
}
#endif /* NET_ALLOC_DEBUG_TREE */
break;
}
}
NET_ASSERT((iteralloc != NET_ALLOC_BREAK), "Reach Allocation break\n");
NET_ASSERT((i != NET_LEAKAGE_ARRAY), "Too much allocations,Please increase NET_LEAKAGE_ARRAY (%lu)in net_conf.h",
NET_LEAKAGE_ARRAY);
#if NET_ALLOC_VERBOSE
(void) printf("%lu bytes allocated: Allocating size %lu at %s:%lu\n", total_alloc, allocated_info[i].size,
allocated_info[i].filename, allocated_info[i].line);
#endif /* NET_ALLOC_VERBOSE */
#ifdef NET_USE_RTOS
(void) xTaskResumeAll();
#endif /* NET_USE_RTOS */
return p;
}
void net_free_debug(void *p)
{
uint32_t i;
#ifdef NET_USE_RTOS
vPortFree(p);
vTaskSuspendAll();
#else
/*cstat -MISRAC2012-Rule-21.3 */
free(p);
/*cstat +MISRAC2012-Rule-21.3 */
#endif /* NET_USE_RTOS */
#ifdef NET_FREE_STOP_ON_NULL_POINTER
if (NULL == p)
{
(void) printf("Free function : Freeing a NULL pointer, seriously ?\n");
while (1);
}
#endif /* NET_STOP_ON_FREEING_NULL_POINTER */
if (NULL != p)
{
iterfree++;
for (i = 0; i < NET_LEAKAGE_ARRAY; i++)
{
if (allocated_info[i].p == p)
{
allocated_info[i].p = NULL;
current_alloc -= allocated_info[i].size;
/*printf("-FREE- Max %d Current %d inc %d\n",max_total_alloc,current_alloc,allocated_info[i].size);*/
#ifdef NET_ALLOC_DEBUG_TREE
net_walk_free_node(allocated_info[i].node, allocated_info[i].size);
#endif /* NET_ALLOC_DEBUG_TREE */
allocated_info[i].size = 0;
break;
}
}
if (i == NET_LEAKAGE_ARRAY)
{
/*cstat -MISRAC2012-Rule-1.3_o -MISRAC2012-Rule-1.3_p -MISRAC2012-Dir-4.7_b -MISRAC2012-Dir-4.13_e -MISRAC2012-Dir-4.13_d */
(void) printf("Free function : did not find this segment %p\n", p);
/*cstat +MISRAC2012-Rule-1.3_o +MISRAC2012-Rule-1.3_p +MISRAC2012-Dir-4.7_b +MISRAC2012-Dir-4.13_e +MISRAC2012-Dir-4.13_d */
while (true) {};
}
}
#ifdef NET_USE_RTOS
(void) xTaskResumeAll();
#endif /* NET_USE_RTOS */
}
void net_alloc_report(void)
{
uint32_t i;
uint32_t count = 0;
uint32_t leak = 0;
#ifdef NET_USE_RTOS
vTaskSuspendAll();
#endif /* NET_USE_RTOS */
(void) printf("\n### Net Malloc report: max alloc: %lu bytes, current leakage: %lu bytes, number of allocation: %lu, number of free: %lu, alloc table usage %lu/%lu (%lu) bytes\n\n",
max_total_alloc, current_alloc, iteralloc, iterfree, max_alive_alloc, NET_LEAKAGE_ARRAY, sizeof(allocated_info));
for (i = 0; i < NET_LEAKAGE_ARRAY; i++)
{
if (allocated_info[i].p != 0)
{
count++;
leak += allocated_info[i].size;
(void) printf("\tAllocation number #%lu Not free %p size %lu at %s:%lu\n", allocated_info[i].iter, allocated_info[i].p,
allocated_info[i].size, allocated_info[i].filename, allocated_info[i].line);
}
}
(void) printf("\n%lu allocation not freed %lu bytes out of %lu allocated byte\n\n", count, leak, max_total_alloc);
#ifdef NET_ALLOC_DEBUG_TREE
net_malloc_tree_print(net_malloc_tree_start(root_node), 0);
#endif /* NET_ALLOC_DEBUG_TREE */
(void) printf("\n### Net Malloc end report\n");
#ifdef NET_USE_RTOS
(void) xTaskResumeAll();
#endif /* NET_USE_RTOS */
}
#endif /* NET_DEBUG_ALLOC */
static struct net_perf
{
uint32_t total;
#if defined(NET_USE_RTOS) && defined(NET_PERF_TASK)
uint32_t elapsed_cycle[NET_PERF_MAXTHREAD];
TaskHandle_t handle[NET_PERF_MAXTHREAD];
#endif
}
perf;
#if defined(NET_PERF_TASK)
/**
* @brief Executed for each context switch in
* @param None
* @retval None
*/
#if !defined(NET_USE_RTOS)
#error "NET_USE_RTOS must be defined to use NET_PERF_TASK"
#endif /* NET_USE_RTOS */
void net_perf_task_in(void)
{
uint32_t i;
TaskHandle_t xHandle = xTaskGetCurrentTaskHandle();
for (i = 0; i < NET_PERF_MAXTHREAD; i++)
{
if (NULL == perf.handle[i])
{
/* new thread */
perf.handle[i] = xHandle;
}
if (xHandle == perf.handle[i])
{
perf.elapsed_cycle[i] -= net_get_cycle();
break;
}
}
NET_ASSERT(NET_PERF_MAXTHREAD != i, "Net perf ,please increase NET_PERF_MAX_THREAD");
}
/**
* @brief Executed for each context switch out
* @param None
* @retval None
*/
void net_perf_task_out(void)
{
uint32_t i;
TaskHandle_t xHandle = xTaskGetCurrentTaskHandle();
for (i = 0; i < NET_PERF_MAXTHREAD; i++)
{
if (NULL == perf.handle[i])
{
/* new thread */
perf.handle[i] = xHandle;
while (true) { };
}
if (xHandle == perf.handle[i])
{
perf.elapsed_cycle[i] += net_get_cycle();
break;
}
}
NET_ASSERT(NET_PERF_MAXTHREAD != i, "Net perf ,please increase NET_PERF_MAX_THREAD");
}
static const char_t *GetTaskName(TaskHandle_t xHandle)
{
TaskStatus_t xTaskDetails;
vTaskGetInfo( /* The handle of the task being queried. */
xHandle,
/* The TaskStatus_t structure to complete with information
on xTask. */
&xTaskDetails,
/* Include the stack high water mark value in the
TaskStatus_t structure. */
pdTRUE,
/* Include the task state in the TaskStatus_t structure. */
eInvalid);
return (const char_t *)xTaskDetails.pcTaskName;
}
#endif /* NET_PERF_TASK */
void net_perf_start(void)
{
/*cstat -MISRAC2012-Rule-11.4 */
NET_DWT_CONTROL |= NET_DWT_CYCCNTENA_BIT ;
NET_DWT_CYCCNT = 0U;
/*cstat +MISRAC2012-Rule-11.4 */
(void) memset(&perf, 0, sizeof(perf));
#if defined(NET_PERF_TASK)
net_perf_task_in();
#endif /* NET_PERF_TASK */
}
void net_perf_report(void)
{
extern uint32_t SystemCoreClock;
#if defined(NET_PERF_TASK)
net_perf_task_out();
#endif /* NET_PERF_TASK */
perf.total += net_get_cycle();
(void) printf("\n### Net Performance report CPU Freq %3lu Mhz\n\n", SystemCoreClock / 1000000U);
(void) printf("\tTotal %12lu cycles %8lu ms\n", perf.total, perf.total / (SystemCoreClock / 1000U));
#if defined(NET_PERF_TASK)
uint32_t count = 0;
(void) printf("\n");
while (perf.handle[count] != 0)
{
(void) printf("\tthread #%lu %25s : %12lu cycles %7lu ms\n", count, GetTaskName(perf.handle[count]),
perf.elapsed_cycle[count], perf.elapsed_cycle[count] / (SystemCoreClock / 1000U));
count++;
}
#endif /* NET_PERF_TASK */
(void) printf("\n### Net Performance end report\n\n");
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,292 @@
/**
******************************************************************************
* @file net_state.c
* @author MCD Application Team
* @brief Management of state machine for network interfaces
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#include "net_connect.h"
#include "net_internals.h"
#include "stdarg.h"
#ifdef DEBUGSTATE
static const char_t *eventstr[] =
{
"NET_EVENT_CMD_INIT",
"NET_EVENT_CMD_START",
"NET_EVENT_CMD_CONNECT",
"NET_EVENT_CMD_DISCONNECT",
"NET_EVENT_CMD_STOP",
"NET_EVENT_CMD_DEINIT",
"NET_EVENT_INTERFACE_INITIALIZED",
"NET_EVENT_INTERFACE_READY",
"NET_EVENT_LINK_UP",
"NET_EVENT_LINK_DOWN",
"NET_EVENT_IPADDR",
};
static const char_t *statestr[] =
{
"NET_STATE_DEINITIALIZED",
"NET_STATE_INITIALIZED",
"NET_STATE_STARTING",
"NET_STATE_READY",
"NET_STATE_CONNECTING",
"NET_STATE_CONNECTED",
"NET_STATE_STOPPING",
"NET_STATE_DISCONNECTING",
"NET_STATE_CONNECTION_LOST",
};
#endif /* DEBUGSTATE */
static void set_state(net_if_handle_t *pnetif, net_state_t state)
{
pnetif->state = state;
net_if_notify(pnetif, NET_EVENT_STATE_CHANGE, (uint32_t) state, NULL);
SIGNAL_STATE_CHANGE();
}
static int32_t net_state_initialized(net_if_handle_t *pnetif, net_state_event_t event)
{
int32_t ret = NET_OK;
switch (event)
{
case NET_EVENT_CMD_START:
set_state(pnetif, NET_STATE_STARTING);
ret = pnetif->pdrv->if_start(pnetif);
if (NET_OK != ret)
{
NET_DBG_ERROR("Interface cannot be started.");
ret = NET_ERROR_INTERFACE_FAILURE;
}
break;
case NET_EVENT_CMD_DEINIT:
ret = pnetif->pdrv->if_deinit(pnetif);
set_state(pnetif, NET_STATE_DEINITIALIZED);
if (NET_OK != ret)
{
NET_DBG_ERROR("Interface cannot be deinitialized.");
ret = NET_ERROR_INTERFACE_FAILURE;
}
break;
default:
break;
}
return ret;
}
static int32_t net_state_starting(net_if_handle_t *pnetif, net_state_event_t event)
{
int32_t ret = NET_OK;
switch (event)
{
case NET_EVENT_INTERFACE_READY:
set_state(pnetif, NET_STATE_READY);
break;
default:
break;
}
return ret;
}
static int32_t net_state_ready(net_if_handle_t *pnetif, net_state_event_t event)
{
int32_t ret = NET_OK;
switch (event)
{
case NET_EVENT_CMD_CONNECT:
set_state(pnetif, NET_STATE_CONNECTING);
ret = pnetif->pdrv->if_connect(pnetif);
if (NET_OK != ret)
{
NET_DBG_ERROR("Interface cannot connect.");
ret = NET_ERROR_INTERFACE_FAILURE;
}
break;
case NET_EVENT_CMD_STOP:
set_state(pnetif, NET_STATE_STOPPING);
ret = pnetif->pdrv->if_stop(pnetif);
if (NET_OK != ret)
{
NET_DBG_ERROR("Interface cannot stop.");
ret = NET_ERROR_INTERFACE_FAILURE;
}
break;
default:
break;
}
return ret;
}
static int32_t net_state_connecting(net_if_handle_t *pnetif, net_state_event_t event)
{
int32_t ret = NET_OK;
switch (event)
{
case NET_EVENT_IPADDR:
set_state(pnetif, NET_STATE_CONNECTED);
break;
case NET_EVENT_CMD_DISCONNECT:
set_state(pnetif, NET_STATE_READY);
break;
default:
break;
}
return ret;
}
static int32_t net_state_connected(net_if_handle_t *pnetif, net_state_event_t event)
{
int32_t ret = NET_OK;
switch (event)
{
case NET_EVENT_CMD_DISCONNECT:
set_state(pnetif, NET_STATE_DISCONNECTING);
ret = pnetif->pdrv->if_disconnect(pnetif);
if (NET_OK != ret)
{
NET_DBG_ERROR("Interface cannot disconnect.");
ret = NET_ERROR_INTERFACE_FAILURE;
}
break;
case NET_EVENT_LINK_DOWN:
set_state(pnetif, NET_STATE_CONNECTION_LOST);
break;
default:
break;
}
return ret;
}
static int32_t net_state_disconnecting(net_if_handle_t *pnetif, net_state_event_t event)
{
int32_t ret = NET_OK;
switch (event)
{
case NET_EVENT_INTERFACE_READY:
set_state(pnetif, NET_STATE_READY);
break;
default:
break;
}
return ret;
}
static int32_t net_state_stopping(net_if_handle_t *pnetif, net_state_event_t event)
{
int32_t ret = NET_OK;
switch (event)
{
case NET_EVENT_INTERFACE_INITIALIZED:
set_state(pnetif, NET_STATE_INITIALIZED);
break;
default:
break;
}
return ret;
}
static int32_t net_state_connection_lost(net_if_handle_t *pnetif, net_state_event_t event)
{
int32_t ret = NET_OK;
switch (event)
{
case NET_EVENT_LINK_UP:
set_state(pnetif, NET_STATE_CONNECTED);
break;
default:
break;
}
return ret;
}
int32_t net_state_manage_event(net_if_handle_t *pnetif_in, net_state_event_t event)
{
int32_t ret;
net_if_handle_t *pnetif;
pnetif = netif_check(pnetif_in);
if (pnetif == NULL)
{
NET_DBG_ERROR("Invalid interface.");
ret = NET_ERROR_PARAMETER;
}
else
{
#ifdef DEBUGSTATE
printf("In state %s , received event %s\n", statestr[pnetif->state], eventstr[event]);
#endif /* DEBUGSTATE */
switch (pnetif->state)
{
case NET_STATE_INITIALIZED:
ret = net_state_initialized(pnetif, event);
break;
case NET_STATE_STARTING:
ret = net_state_starting(pnetif, event);
break;
case NET_STATE_READY:
ret = net_state_ready(pnetif, event);
break;
case NET_STATE_CONNECTING:
ret = net_state_connecting(pnetif, event);
break;
case NET_STATE_CONNECTED:
ret = net_state_connected(pnetif, event);
break;
case NET_STATE_DISCONNECTING:
ret = net_state_disconnecting(pnetif, event);
break;
case NET_STATE_CONNECTION_LOST:
ret = net_state_connection_lost(pnetif, event);
break;
case NET_STATE_STOPPING:
ret = net_state_stopping(pnetif, event);
break;
default:
ret = NET_ERROR_INVALID_STATE;
break;
}
}
return ret;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1 @@
/C/users/gentit/Doxygen/bin/Release/doxygen.exe doxyconfig
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,143 @@
/**
******************************************************************************
* @file net_ethernet_driver.c
* @author MCD Application Team
* @brief Ethernet specific BSD-like socket wrapper
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#include "net_connect.h"
#include "net_internals.h"
#include "net_ip_ethernet.h"
#include "net_ip_lwip.h"
/* global constructor of the ethernet network interface */
int32_t ethernet_net_driver(net_if_handle_t *pnetif);
static int32_t net_ethernet_if_init(net_if_handle_t *pnetif);
static int32_t net_ethernet_if_deinit(net_if_handle_t *pnetif);
static int32_t net_ethernet_if_start(net_if_handle_t *pnetif);
static int32_t net_ethernet_if_stop(net_if_handle_t *pnetif);
static int32_t net_ethernet_if_connect(net_if_handle_t *pnetif);
static int32_t net_ethernet_if_disconnect(net_if_handle_t *pnetif);
err_t ethernetif_init(struct netif *netif);
err_t ethernetif_deinit(struct netif *netif);
/**
* @brief Function description
* @param Params
* @retval socket status
*/
int32_t ethernet_net_driver(net_if_handle_t *pnetif)
{
int32_t ret;
net_ip_init();
ret = net_ethernet_if_init(pnetif);
return ret;
}
static int32_t net_ethernet_if_init(net_if_handle_t *pnetif)
{
int32_t ret;
/*cstat -MISRAC2012-Rule-11.5 malloc cast*/
net_if_drv_t *pdrv = NET_MALLOC(sizeof(net_if_drv_t));
/*cstat +MISRAC2012-Rule-11.5 */
if (pdrv != NULL)
{
pdrv->if_class = NET_INTERFACE_CLASS_ETHERNET;
pdrv->if_init = net_ethernet_if_init;
pdrv->if_deinit = net_ethernet_if_deinit;
pdrv->if_start = net_ethernet_if_start;
pdrv->if_stop = net_ethernet_if_stop;
pdrv->if_connect = net_ethernet_if_connect;
pdrv->if_disconnect = net_ethernet_if_disconnect;
pdrv->pping = icmp_ping;
pnetif->pdrv = pdrv;
(void) net_state_manage_event(pnetif, NET_EVENT_INTERFACE_INITIALIZED);
ret = NET_OK;
}
else
{
NET_DBG_ERROR("can't allocate memory for es_wifi_driver class\n");
ret = NET_ERROR_NO_MEMORY;
}
return ret;
}
int32_t net_ethernet_if_start(net_if_handle_t *pnetif)
{
int32_t ret;
ret = net_ip_add_if(pnetif, ethernetif_init, NET_ETHERNET_FLAG_DEFAULT_IF);
if (ret == NET_OK)
{
(void) strncpy(pnetif->DeviceName, "Ethernet IF", sizeof(pnetif->DeviceName));
(void) strncpy(pnetif->DeviceID, "Unknown", sizeof(pnetif->DeviceID));
(void) strncpy(pnetif->DeviceVer, "Unknown", sizeof(pnetif->DeviceVer));
/* set call back , here to not loose first linkup when if_init is performed */
netif_set_down(pnetif->netif);
netif_set_link_down(pnetif->netif);
netif_set_status_callback(pnetif->netif, net_ip_status_cb);
netif_set_link_callback(pnetif->netif, net_ip_status_cb);
netif_set_link_up(pnetif->netif);
netif_set_up(pnetif->netif);
(void) net_state_manage_event(pnetif, NET_EVENT_INTERFACE_READY);
}
return ret;
}
static int32_t net_ethernet_if_connect(net_if_handle_t *pnetif)
{
int32_t ret;
ret = net_ip_connect(pnetif);
return ret;
}
static int32_t net_ethernet_if_disconnect(net_if_handle_t *pnetif)
{
int32_t ret;
(void) net_ip_disconnect(pnetif);
ret = net_state_manage_event(pnetif, NET_EVENT_INTERFACE_READY);
return ret;
}
static int32_t net_ethernet_if_stop(net_if_handle_t *pnetif)
{
int32_t ret;
(void) net_ip_remove_if(pnetif, ethernetif_deinit);
ret = net_state_manage_event(pnetif, NET_EVENT_INTERFACE_INITIALIZED);
return ret;
}
static int32_t net_ethernet_if_deinit(net_if_handle_t *pnetif)
{
int32_t ret = NET_OK;
NET_FREE(pnetif->pdrv);
pnetif->pdrv = NULL;
return ret;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,675 @@
/**
******************************************************************************
* @file net_ethernet_driver.c
* @author MCD Application Team
* @brief Ethernet specific BSD-like socket wrapper
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#include <string.h>
#include "net_connect.h"
#include "net_internals.h"
#include "net_ip_lwip.h"
/*cstat -MISRAC* -DEFINE-* -CERT-EXP19* */
#include "whd.h"
#include "whd_debug.h"
#include "whd_resource_api.h"
#include "whd_wifi_api.h"
#include "whd_network_types.h"
#include "whd_types_int.h"
/*cstat +MISRAC* +DEFINE-* +CERT-EXP19* */
#define NET_CYPRESS_MAX_INTERFACE 4
typedef struct net_cypress_key
{
void *key;
void *value;
} net_cypress_key_t;
static net_cypress_key_t netif2ifp[NET_CYPRESS_MAX_INTERFACE];
static uint32_t cypress_alive_interface_count = 0;
static whd_driver_t whd_driver;
/* create and boot WHD driver */
cy_rslt_t whd_boot(whd_driver_t *whd_driver);
cy_rslt_t whd_powerdown(whd_driver_t *whd_driver);
/* global constructor of the ethernet network interface */
int32_t cypress_whd_net_driver(net_if_handle_t *pnetif);
static err_t low_level_output(struct netif *netif, struct pbuf *p);
static err_t low_level_init(struct netif *netif);
static int32_t net_cypress_whd_if_init(net_if_handle_t *pnetif);
static int32_t net_cypress_whd_if_deinit(net_if_handle_t *pnetif);
static int32_t net_cypress_whd_if_start(net_if_handle_t *pnetif);
static int32_t net_cypress_whd_if_stop(net_if_handle_t *pnetif);
static int32_t net_cypress_whd_if_connect(net_if_handle_t *pnetif);
static int32_t net_cypress_whd_if_disconnect(net_if_handle_t *pnetif);
static int32_t net_cypress_whd_scan(net_if_handle_t *pnetif, net_wifi_scan_mode_t mode, char *ssid);
static int32_t net_cypress_whd_scan_result(net_if_handle_t *pnetif, net_wifi_scan_results_t *results, uint8_t number);
/**
* @brief Function description
* @param Params
* @retval socket status
*/
int32_t cypress_whd_net_driver(net_if_handle_t *pnetif)
{
int32_t ret;
/* init lwip library here if not already done by another network interface */
net_ip_init();
ret = net_cypress_whd_if_init(pnetif);
return ret;
}
static int32_t net_cypress_whd_if_init(net_if_handle_t *pnetif)
{
int32_t ret = NET_OK;
net_if_drv_t *pdrv = NET_MALLOC(sizeof(net_if_drv_t));
if (pdrv != NULL)
{
pdrv->if_class = NET_INTERFACE_CLASS_WIFI;
pdrv->if_init = net_cypress_whd_if_init;
pdrv->if_deinit = net_cypress_whd_if_deinit;
pdrv->if_start = net_cypress_whd_if_start;
pdrv->if_stop = net_cypress_whd_if_stop;
pdrv->if_connect = net_cypress_whd_if_connect;
pdrv->if_disconnect = net_cypress_whd_if_disconnect;
pdrv->pping = icmp_ping;
pnetif->pdrv = pdrv;
pdrv->extension.wifi = NET_MALLOC(sizeof(net_if_wifi_class_extension_t));
if (NULL == pdrv->extension.wifi)
{
NET_DBG_ERROR("can't allocate memory for wifi extension\n");
NET_FREE(pdrv);
ret = NET_ERROR_NO_MEMORY;
}
else
{
(void) memset(pdrv->extension.wifi, 0, sizeof(net_if_wifi_class_extension_t));
pdrv->extension.wifi->scan = net_cypress_whd_scan;
pdrv->extension.wifi->get_scan_results = net_cypress_whd_scan_result;
if (cypress_alive_interface_count == 0)
{
/* Boot cypress module and start whd driver for very first interface */
if (WHD_SUCCESS != whd_boot(&whd_driver))
{
NET_DBG_ERROR("can't perform intialization of whd driver and module\n");
ret = NET_ERROR_MODULE_INITIALIZATION;
}
NET_DBG_PRINT("WHD init driver done\n");
(void) memset(netif2ifp, 0, sizeof(netif2ifp));
if (NET_OK == ret)
{
if (WHD_SUCCESS != whd_wifi_on(whd_driver, (whd_interface_t *) &pdrv->extension.wifi->ifp))
{
NET_DBG_PRINT("Failed when creating WIFI default interface\n");
NET_FREE(pdrv->extension.wifi);
NET_FREE(pdrv);
ret = NET_ERROR_MODULE_INITIALIZATION;
}
else
{
NET_DBG_PRINT("WHD init interface done\n");
cypress_alive_interface_count++;
ret = NET_OK;
}
}
}
else
{
whd_mac_t mac_addr = {0xA0, 0xC9, 0xA0, 0X3D, 0x43, 0x41};
if (WHD_SUCCESS != whd_add_secondary_interface(whd_driver, &mac_addr, (whd_interface_t *) &pdrv->extension.wifi->ifp))
{
NET_DBG_PRINT("Failed when creating WIFI default interface\n");
NET_FREE(pdrv->extension.wifi);
NET_FREE(pdrv);
ret = NET_ERROR_MODULE_INITIALIZATION;
}
else
{
NET_DBG_PRINT("WHD init interface done\n");
cypress_alive_interface_count++;
ret = NET_OK;
}
}
}
}
else
{
NET_DBG_ERROR("can't allocate memory for WHD driver class\n");
ret = NET_ERROR_NO_MEMORY;
}
return ret;
}
static void convert_credential(const net_wifi_credentials_t *credentials, whd_security_t *privacy, whd_ssid_t *myssid)
{
*privacy = (whd_security_t) credentials->security_mode;
strcpy((char *) myssid->value, (char *) credentials->ssid);
myssid->length = strlen((char *)myssid->value);
}
static int32_t net_cypress_whd_if_start_sta(net_if_handle_t *pnetif)
{
int32_t ret = 0;
whd_security_t privacy;
whd_ssid_t myssid;
const net_wifi_credentials_t *credentials = pnetif->pdrv->extension.wifi->credentials;
convert_credential(credentials, &privacy, &myssid);
NET_DBG_PRINT("Joinning ... %s\n", myssid.value);
ret = whd_wifi_join((whd_interface_t)pnetif->pdrv->extension.wifi->ifp, (whd_ssid_t const *) &myssid, privacy,
(uint8_t const *) credentials->psk, strlen(credentials->psk));
if (ret != 0)
{
NET_DBG_ERROR("can't join %s\n", myssid.value);
ret = NET_ERROR_MODULE_INITIALIZATION;
}
else
{
NET_DBG_PRINT("Joined Access point %s\n", myssid.value);
ret = net_ip_add_if(pnetif, low_level_init, NET_ETHERNET_FLAG_DEFAULT_IF);
if (ret == NET_OK)
{
(void) strncpy(pnetif->DeviceName, "Wlan WHD murata 1LD", sizeof(pnetif->DeviceName));
(void) strncpy(pnetif->DeviceID, "Unknown", sizeof(pnetif->DeviceID));
(void) strncpy(pnetif->DeviceVer, "Unknown", sizeof(pnetif->DeviceVer));
(void) net_state_manage_event(pnetif, NET_EVENT_INTERFACE_READY);
netif_set_link_up(pnetif->netif);
}
else
{
NET_DBG_ERROR("can't add interface (netif)\n");
}
}
return ret;
}
static int32_t net_cypress_whd_if_start_ap(net_if_handle_t *pnetif)
{
int32_t ret = 0;
whd_security_t privacy;
whd_ssid_t myssid;
const net_wifi_credentials_t *credentials = pnetif->pdrv->extension.wifi->credentials;
NET_DBG_PRINT("Init Access Point ... %s\n", myssid.value);
convert_credential(credentials, &privacy, &myssid);
ret = whd_wifi_init_ap((whd_interface_t)pnetif->pdrv->extension.wifi->ifp, &myssid, privacy,
(uint8_t const *) credentials->psk, strlen(credentials->psk),
pnetif->pdrv->extension.wifi->access_channel);
if (ret != 0)
{
NET_DBG_ERROR("can't init access point %s\n", myssid.value);
ret = NET_ERROR_MODULE_INITIALIZATION;
}
else
{
ret = whd_wifi_start_ap((whd_interface_t)pnetif->pdrv->extension.wifi->ifp);
if (ret != 0)
{
NET_DBG_ERROR("can't start access point %s\n", myssid.value);
ret = NET_ERROR_MODULE_INITIALIZATION;
}
else
{
NET_DBG_PRINT("Start Access point %s\n", myssid.value);
ret = net_ip_add_if(pnetif, low_level_init, NET_ETHERNET_FLAG_DEFAULT_IF);
if (ret == NET_OK)
{
(void) strncpy(pnetif->DeviceName, "Wlan WHD murata 1LD", sizeof(pnetif->DeviceName));
(void) strncpy(pnetif->DeviceID, "Unknown", sizeof(pnetif->DeviceID));
(void) strncpy(pnetif->DeviceVer, "Unknown", sizeof(pnetif->DeviceVer));
(void) net_state_manage_event(pnetif, NET_EVENT_INTERFACE_READY);
netif_set_link_up(pnetif->netif);
}
else
{
NET_DBG_ERROR("can't add interface (netif)\n");
}
}
}
return ret;
}
int32_t net_cypress_whd_if_start(net_if_handle_t *pnetif)
{
int32_t ret = 0;
if (pnetif->pdrv->extension.wifi->mode == NET_WIFI_MODE_STA)
{
ret = net_cypress_whd_if_start_sta(pnetif);
}
else
{
ret = net_cypress_whd_if_start_ap(pnetif);
}
return ret;
}
static int32_t net_cypress_whd_if_connect(net_if_handle_t *pnetif)
{
int32_t ret;
ret = net_ip_connect(pnetif);
if (ret != NET_OK)
{
NET_DBG_ERROR("Failed to connect\n");
ret = NET_ERROR_NO_CONNECTION;
}
return ret;
}
static int32_t net_cypress_whd_if_disconnect(net_if_handle_t *pnetif)
{
int32_t ret;
ret = net_ip_disconnect(pnetif);
if (ret == NET_OK)
{
ret = net_state_manage_event(pnetif, NET_EVENT_INTERFACE_READY);
}
return ret;
}
static int32_t net_cypress_whd_if_stop(net_if_handle_t *pnetif)
{
int32_t ret;
ret = net_ip_remove_if(pnetif, NULL);
if (ret == NET_OK)
{
ret = net_state_manage_event(pnetif, NET_EVENT_INTERFACE_INITIALIZED);
}
if (pnetif->pdrv->extension.wifi->mode == NET_WIFI_MODE_STA)
{
whd_wifi_leave(pnetif->pdrv->extension.wifi->ifp);
}
else
{
whd_wifi_stop_ap((whd_interface_t)pnetif->pdrv->extension.wifi->ifp);
}
return ret;
}
static int32_t net_cypress_whd_if_deinit(net_if_handle_t *pnetif)
{
int32_t ret = NET_OK;
uint32_t i;
/*Switch off Wifi*/
whd_wifi_off(pnetif->pdrv->extension.wifi->ifp);
for (i = 0; i < NET_CYPRESS_MAX_INTERFACE; i++)
{
if (netif2ifp[i].key == pnetif->pdrv->extension.wifi->ifp)
{
break;
}
}
if (i == NET_CYPRESS_MAX_INTERFACE)
{
WPRINT_WHD_DEBUG(("Couldn't find the interface \n"));
return ERR_VAL;
}
else
{
netif2ifp[i].key = NULL;
netif2ifp[i].value = NULL;
if (cypress_alive_interface_count == 1)
{
/*Deletes all the interface and De-init the whd, free whd_driver memory */
whd_deinit(pnetif->pdrv->extension.wifi->ifp);
whd_powerdown(&whd_driver);
}
cypress_alive_interface_count--;
NET_FREE(pnetif->pdrv->extension.wifi);
NET_FREE(pnetif->pdrv);
pnetif->pdrv = NULL;
}
return ret;
}
static err_t low_level_init(struct netif *netif)
{
err_t ret = ERR_VAL;
/*
* Initialize the snmp variables and counters inside the struct netif.
* The last argument should be replaced with your link speed, in units
* of bits per second.
*/
net_if_handle_t *pnetif = netif->state;
whd_interface_t ifp = pnetif->pdrv->extension.wifi->ifp;
/* to retrieve back netif from ifp */
for (int32_t i = 0; i < NET_CYPRESS_MAX_INTERFACE; i++)
{
if (netif2ifp[i].key == NULL)
{
netif2ifp[i].key = ifp;
netif2ifp[i].value = netif;
ret = (err_t) ERR_OK;
break;
}
}
netif->name[0] = 'c';
netif->name[1] = 'y';
/* We directly use etharp_output() here to save a function call.
* You can instead declare your own function an call etharp_output()
* from it if you have to do some checks before sending (e.g. if link
* is available...)
*/
netif->output = etharp_output;
#if LWIP_IPV6
netif->output_ip6 = ethip6_output;
#endif /* LWIP_IPV6 */
netif->linkoutput = low_level_output;
/* Set MAC hardware address length ( 6)*/
netif->hwaddr_len = (u8_t) ETHARP_HWADDR_LEN;
/* Setup the physical address of this IP instance. */
if (whd_wifi_get_mac_address(ifp, (whd_mac_t *) netif->hwaddr) != WHD_SUCCESS)
{
WPRINT_WHD_DEBUG(("Couldn't get MAC address\n"));
return ERR_VAL;
}
WPRINT_WHD_DEBUG((" MAC address %x.%x.%x.%x.%x.%x\n", netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2],
netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]));
/* Set Maximum Transfer Unit */
netif->mtu = (u16_t) WHD_PAYLOAD_MTU;
/* Set device capabilities. Don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
netif->flags = (u8_t)(NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET);
/* Do whatever else is needed to initialize interface. */
#if LWIP_IGMP
netif->flags |= NETIF_FLAG_IGMP;
netif_set_igmp_mac_filter(netif, lwip_igmp_mac_filter);
#endif /* LWIP_IGMP */
/* Register a handler for any address changes and when interface goes up or down*/
netif_set_status_callback(netif, net_ip_status_cb);
netif_set_link_callback(netif, net_ip_status_cb);
return ret;
}
/* This function should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf
* might be chained.
*
* @param netif the lwip network interface structure for this ethernetif
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
* @return ERR_OK if the packet could be sent
* an err_t value if the packet couldn't be sent
*
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
* strange results. You might consider waiting for space in the DMA queue
* to become availale since the stack doesn't retry to send a packet
* dropped because of memory failure (except for the TCP timers).
*/
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
net_if_handle_t *pnetif = netif->state;
whd_interface_t ifp = pnetif->pdrv->extension.wifi->ifp;
if (whd_wifi_is_ready_to_transceive(ifp) == WHD_SUCCESS)
{
/* Take a reference to this packet */
pbuf_ref(p);
#if 0
NET_DBG_PRINT("Transmit buffer 1 %x next=%p tot-len=%d len=%d\n", p, p->next, p->tot_len, p->len);
#endif /* for debug */
LWIP_ASSERT("No chained buffers", ((p->next == NULL) && ((p->tot_len == p->len))));
#ifdef NET_PERF
stat.whd_send_cycle -= net_get_cycle();
#endif /* NET_PERF */
whd_network_send_ethernet_data((whd_interface_t) ifp, p);
#ifdef NET_PERF
/*stat.whd_send_cycle += net_get_cycle();*/
#endif /* NET_PERF */
LINK_STATS_INC(link.xmit);
return (err_t) ERR_OK;
}
else
{
NET_DBG_PRINT("cannot transmit wifi not rdy\n");
/* Stop lint warning about packet not being freed - it is not being referenced */ /*@-mustfree@*/
return (err_t) ERR_INPROGRESS; /* Note that signalling ERR_CLSD or ERR_CONN causes loss of connectivity on a roam */
/*@+mustfree@*/
}
}
uint32_t cy_callback_tcpip = 0;
uint32_t cy_callback = 0;
/**
* This function should be called when a packet is ready to be read
* from the interface. It uses the function low_level_input() that
* should handle the actual reception of bytes from the network
* interface. Then the type of the received packet is determined and
* the appropriate input function is called.
*
* @param p : the incoming ethernet packet
*/
void cy_network_process_ethernet_data(whd_interface_t interface, whd_buffer_t buff)
{
struct eth_hdr *ethernet_header;
struct netif *tmp_netif;
u8_t result;
uint16_t ethertype;
struct pbuf *buffer = (struct pbuf *) buff;
if (buffer == NULL)
{
return;
}
/* points to packet payload, which starts with an Ethernet header */
ethernet_header = (struct eth_hdr *) buffer->payload;
ethertype = lwip_htons(ethernet_header->type);
#ifdef FILTER
if (filter_ethernet_packet_callback != NULL && filter_ethertype == ethertype && filter_interface == interface)
{
filter_ethernet_packet_callback(buffer->payload, filter_userdata);
}
#endif /* FILTER */
/* Check if this is an 802.1Q VLAN tagged packet */
if (ethertype == WHD_ETHERTYPE_8021Q)
{
/* Need to remove the 4 octet VLAN Tag, by moving src and dest addresses 4 octets to the right,
* and then read the actual ethertype. The VLAN ID and priority fields are currently ignored. */
uint8_t temp_buffer[ 12 ];
memcpy(temp_buffer, buffer->payload, 12);
memcpy(((uint8_t *) buffer->payload) + 4, temp_buffer, 12);
buffer->payload = ((uint8_t *) buffer->payload) + 4;
buffer->len = (u16_t)(buffer->len - 4);
ethernet_header = (struct eth_hdr *) buffer->payload;
ethertype = lwip_htons(ethernet_header->type);
}
#ifdef DEEP_SLEEP
if (WHD_DEEP_SLEEP_IS_ENABLED() && (WHD_DEEP_SLEEP_SAVE_PACKETS_NUM != 0))
{
if (wiced_deep_sleep_save_packet(buffer, interface))
{
return;
}
}
#endif /* DEEP_SLEEP */
cy_callback++;
switch (ethertype)
{
case WHD_ETHERTYPE_IPv4:
case WHD_ETHERTYPE_ARP:
#if PPPOE_SUPPORT
/* PPPoE packet? */
case ETHTYPE_PPPOEDISC:
case ETHTYPE_PPPOE:
#endif /* PPPOE_SUPPORT */
/* Find the netif object matching the provided interface */
tmp_netif = NULL;
for (int32_t i = 0; i < NET_CYPRESS_MAX_INTERFACE; i++)
{
if (netif2ifp[i].key == interface)
{
tmp_netif = netif2ifp[i].value;
break;
}
}
/*NET_DBG_PRINT("Recv %d for netif %x ifp %x\n",buffer->len,tmp_netif,interface);*/
if (tmp_netif == NULL)
{
NET_DBG_PRINT("This buffer is not for this interface !\n");
/* Received a packet for a network interface is not initialised Cannot do anything with packet
- just drop it. */
result = pbuf_free(buffer);
LWIP_ASSERT("Failed to release packet buffer", (result != (u8_t)0));
buffer = NULL;
return;
}
#if 0
NET_DBG_PRINT("process input packet ethertype %x size %d\n", ethertype, buffer->len);
#endif /* debug */
/* Send to packet to tcpip_thread to process */
cy_callback_tcpip++;
if (tcpip_input(buffer, tmp_netif) != ERR_OK)
{
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
/* Stop lint warning - packet has not been released in this case */ /*@-usereleased@*/
result = pbuf_free(buffer);
/*@+usereleased@*/
LWIP_ASSERT("Failed to release packet buffer", (result != (u8_t)0));
buffer = NULL;
}
break;
#if 0
/*FIXME , not supported todays */
case WHD_ETHERTYPE_EAPOL:
whd_eapol_receive_eapol_packet(buffer, interface);
break;
#endif /* 0 */
default:
result = pbuf_free(buffer);
LWIP_ASSERT("Failed to release packet buffer", (result != (u8_t)0));
buffer = NULL;
break;
}
}
static int32_t net_cypress_whd_scan(net_if_handle_t *pnetif, net_wifi_scan_mode_t mode, char *ssid)
{
(void) pnetif;
(void) mode;
(void) ssid;
return NET_OK;
}
static int32_t net_cypress_whd_scan_result(net_if_handle_t *pnetif, net_wifi_scan_results_t *scan_bss, uint8_t number)
{
int32_t ret = NET_ERROR_GENERIC;
whd_sync_scan_result_t *scan_result;
if ((NULL == scan_bss) || (0 == number))
{
return NET_ERROR_PARAMETER;
}
scan_result = (whd_sync_scan_result_t *)NET_MALLOC(sizeof(whd_sync_scan_result_t) * number);
if (NULL == scan_result)
{
return NET_ERROR_NO_MEMORY;
}
else
{
uint32_t apcount;
whd_sync_scan_result_t *scan_result_info = scan_result;
memset(scan_result, 0, sizeof(whd_sync_scan_result_t) * number);
apcount = whd_wifi_scan_synch((whd_interface_t) pnetif->pdrv->extension.wifi->ifp, scan_result, number);
for (uint32_t i = 0; i < apcount; i++)
{
memset(scan_bss, 0, sizeof(net_wifi_scan_bss_t));
memcpy(scan_bss->ssid.value, (void *) scan_result_info->SSID.value, scan_result_info->SSID.length);
scan_bss->ssid.value[scan_result_info->SSID.length] = 0;
scan_bss->ssid.length = scan_result_info->SSID.length;
scan_bss->security = scan_result_info->security;
memcpy(&scan_bss->bssid, scan_result_info->BSSID.octet, NET_WIFI_MAC_ADDRESS_SIZE);
scan_bss->rssi = (int8_t)scan_result_info->signal_strength;
scan_bss->channel = scan_result_info->channel;
memcpy(scan_bss->country, ".CN", 4); /* NOT SUPPORT for MX_WIFI */
scan_bss++;
scan_result_info++;
}
ret = apcount;
}
free((void *) scan_result);
return ret;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,715 @@
/**
******************************************************************************
* @file net_mx_wifi.c
* @author MCD Application Team
* @brief MXCHIP Wi-Fi specific BSD-like socket wrapper
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/*cstat -MISRAC2012-* */
#include "net_connect.h"
#include "net_internals.h"
/*cstat +MISRAC2012-* */
#include "mx_wifi.h"
#ifdef MX_WIFI_API_DEBUG
#define DEBUG_LOG(M, ...) printf(M, ##__VA_ARGS__);
#else
#define DEBUG_LOG(M, ...)
#endif /* MX_WIFI_API_DEBUG */
#define MXWIFI_MAX_CHANNEL_NBR 4
#define WIFI_FREE_SOCKET 0U
#define WIFI_ALLOCATED_SOCKET 1U
#define WIFI_BIND_SOCKET 2U
#define WIFI_SEND_OK 4U
#define WIFI_RECV_OK 8U
#define WIFI_CONNECTED_SOCKET 16U
#define WIFI_STARTED_CLIENT_SOCKET 32U
#define WIFI_STARTED_SERVER_SOCKET 64U
#define WIFI_CONNECTED_SOCKET_RW (WIFI_CONNECTED_SOCKET | WIFI_SEND_OK | WIFI_RECV_OK)
#define NET_ARTON(A) ((uint32_t)(((uint32_t)A[3] << 24U) |\
((uint32_t)A[2] << 16U) |\
((uint32_t)A[1] << 8U) |\
((uint32_t)A[0] << 0U)))
/* Declaration of generic class functions */
void HAL_Delay(uint32_t delay);
int32_t mx_wifi_driver(net_if_handle_t *pnetif);
static int32_t mx_wifi_if_init(net_if_handle_t *pnetif);
static int32_t mx_wifi_if_deinit(net_if_handle_t *pnetif);
static int32_t mx_wifi_if_start(net_if_handle_t *pnetif);
static int32_t mx_wifi_if_stop(net_if_handle_t *pnetif);
static int32_t mx_wifi_if_yield(net_if_handle_t *pnetif, uint32_t timeout);
static int32_t mx_wifi_if_connect(net_if_handle_t *pnetif);
static int32_t mx_wifi_if_disconnect(net_if_handle_t *pnetif);
static int32_t mx_wifi_socket(int32_t domain, int32_t type, int32_t protocol);
static int32_t mx_wifi_bind(int32_t sock, const net_sockaddr_t *addr, uint32_t addrlen);
static int32_t mx_wifi_listen(int32_t sock, int32_t backlog);
static int32_t mx_wifi_accept(int32_t sock, net_sockaddr_t *addr, uint32_t *addrlen);
static int32_t mx_wifi_connect(int32_t sock, const net_sockaddr_t *addr, uint32_t addrlen);
static int32_t mx_wifi_send(int32_t sock, uint8_t *buf, int32_t len, int32_t flags);
static int32_t mx_wifi_recv(int32_t sock, uint8_t *buf, int32_t len, int32_t flags);
static int32_t mx_wifi_sendto(int32_t sock, uint8_t *buf, int32_t len, int32_t flags, net_sockaddr_t *to,
uint32_t tolen);
static int32_t mx_wifi_recvfrom(int32_t sock, uint8_t *buf, int32_t len, int32_t flags, net_sockaddr_t *from,
uint32_t *fromlen);
static int32_t mx_wifi_setsockopt(int32_t sock, int32_t level, int32_t optname, const void *optvalue, uint32_t optlen);
static int32_t mx_wifi_getsockopt(int32_t sock, int32_t level, int32_t optname, void *optvalue, uint32_t *optlen);
static int32_t mx_wifi_getsockname(int32_t sock, net_sockaddr_t *name, uint32_t *namelen);
static int32_t mx_wifi_getpeername(int32_t sock, net_sockaddr_t *name, uint32_t *namelen);
static int32_t mx_wifi_close(int32_t sock, bool isaclone);
static int32_t mx_wifi_shutdown(int32_t sock, int32_t mode);
static int32_t mx_wifi_gethostbyname(net_if_handle_t *pnetif, net_sockaddr_t *addr, char_t *name);
static int32_t mx_wifi_ping(net_if_handle_t *pnetif, net_sockaddr_t *addr, int32_t count, int32_t delay,
int32_t response[]);
/* Declaration and definition of class-specific functions */
static int32_t mx_wifi_scan(net_if_handle_t *pnetif, net_wifi_scan_mode_t mode, char *ssid);
static int32_t mx_wifi_get_scan_result(net_if_handle_t *pnetif, net_wifi_scan_results_t *results, uint8_t number);
extern int32_t wifi_probe(void **ll_drv_context);
extern MX_WIFIObject_t *wifi_obj_get(void);
/* internal structure to mabage es_wfi socket */
typedef struct mxwifi_tls_data_s
{
char *tls_ca_certs; /**< Socket option. */
char *tls_ca_crl; /**< Socket option. */
char *tls_dev_cert; /**< Socket option. */
char *tls_dev_key; /**< Socket option. */
uint8_t *tls_dev_pwd; /**< Socket option. */
bool tls_srv_verification; /**< Socket option. */
char *tls_srv_name; /**< Socket option. */
} mxwifi_tls_data_t;
int32_t mx_wifi_driver(net_if_handle_t *pnetif)
{
return mx_wifi_if_init(pnetif);
}
int32_t mx_wifi_if_init(net_if_handle_t *pnetif)
{
int32_t ret;
net_if_drv_t *p;
void *ptmp;
ptmp = NET_MALLOC(sizeof(net_if_drv_t));
(void)memcpy(&p, &ptmp, sizeof(p));
if (p != NULL)
{
p->if_class = NET_INTERFACE_CLASS_WIFI;
p->if_init = mx_wifi_if_init;
p->if_deinit = mx_wifi_if_deinit;
p->if_start = mx_wifi_if_start;
p->if_stop = mx_wifi_if_stop;
p->if_yield = mx_wifi_if_yield;
p->if_connect = mx_wifi_if_connect;
p->if_disconnect = mx_wifi_if_disconnect;
p->psocket = mx_wifi_socket;
p->pbind = mx_wifi_bind;
p->plisten = mx_wifi_listen;
p->paccept = mx_wifi_accept;
p->pconnect = mx_wifi_connect;
p->psend = mx_wifi_send;
p->precv = mx_wifi_recv;
p->psendto = mx_wifi_sendto;
p->precvfrom = mx_wifi_recvfrom;
p->psetsockopt = mx_wifi_setsockopt;
p->pgetsockopt = mx_wifi_getsockopt;
p->pgetsockname = mx_wifi_getsockname;
p->pgetpeername = mx_wifi_getpeername;
p->pclose = mx_wifi_close;
p->pshutdown = mx_wifi_shutdown;
p->pgethostbyname = mx_wifi_gethostbyname;
p->pping = mx_wifi_ping;
p->extension.wifi = NET_MALLOC(sizeof(net_if_wifi_class_extension_t));
if (NULL == p->extension.wifi)
{
NET_DBG_ERROR("can't allocate memory for mx_wifi_driver class\n");
NET_FREE(p);
ret = NET_ERROR_NO_MEMORY;
}
else
{
(void) memset(p->extension.wifi, 0, sizeof(net_if_wifi_class_extension_t));
pnetif->dhcp_mode = true;
pnetif->pdrv = p;
p->extension.wifi->scan = mx_wifi_scan;
p->extension.wifi->get_scan_results = mx_wifi_get_scan_result;
ret = NET_OK;
}
}
else
{
NET_DBG_ERROR("can't allocate memory for mx_wifi_driver class\n");
ret = NET_ERROR_NO_MEMORY;
}
return ret;
}
static int32_t mx_wifi_if_deinit(net_if_handle_t *pnetif)
{
NET_FREE(pnetif->pdrv->extension.wifi);
pnetif->pdrv->extension.wifi = NULL;
NET_FREE(pnetif->pdrv);
pnetif->pdrv = NULL;
return NET_OK;
}
static int32_t mx_wifi_if_start(net_if_handle_t *pnetif)
{
int32_t ret;
MX_WIFIObject_t *pMxWifiObj;
if (wifi_probe(&pnetif->pdrv->context) == NET_OK)
{
DEBUG_LOG("MX_WIFI IO [OK]\r\n");
pMxWifiObj = wifi_obj_get();
/* wifi module hardware reboot */
DEBUG_LOG("MX_WIFI REBOOT(HW) ...\r\n");
if (MX_WIFI_STATUS_OK != MX_WIFI_HardResetModule(pMxWifiObj))
{
ret = NET_ERROR_DEVICE_ERROR;
}
else
{
#ifdef NET_USE_RTOS
(void)osDelay(500);
#else
HAL_Delay(500);
#endif /* NET_USE_RTOS */
/* Init the WiFi module */
if (MX_WIFI_STATUS_OK != MX_WIFI_Init(pMxWifiObj))
{
ret = NET_ERROR_INTERFACE_FAILURE;
}
else
{
DEBUG_LOG("MX_WIFI_Init [OK]\r\n");
/* Retrieve the WiFi module information */
(void)strncpy(pnetif->DeviceName, (char_t *)pMxWifiObj->SysInfo.Product_Name, NET_DEVICE_NAME_LEN);
(void)strncpy(pnetif->DeviceID, (char_t *)pMxWifiObj->SysInfo.Product_ID, NET_DEVICE_ID_LEN);
(void)strncpy(pnetif->DeviceVer, (char_t *)pMxWifiObj->SysInfo.FW_Rev, NET_DEVICE_VER_LEN);
(void)MX_WIFI_GetMACAddress(pMxWifiObj, pnetif->macaddr.mac);
(void)net_state_manage_event(pnetif, NET_EVENT_INTERFACE_READY);
ret = NET_OK;
}
}
}
else
{
ret = NET_ERROR_DEVICE_ERROR;
}
return ret;
}
static int32_t mx_wifi_if_stop(net_if_handle_t *pnetif)
{
int32_t ret;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
if (MX_WIFI_STATUS_OK != MX_WIFI_DeInit(pMxWifiObj))
{
ret = NET_ERROR_GENERIC;
}
else
{
(void) net_state_manage_event(pnetif, NET_EVENT_INTERFACE_INITIALIZED);
ret = NET_OK;
}
return ret;
}
static int32_t mx_wifi_if_yield(net_if_handle_t *pnetif, uint32_t timeout)
{
int32_t ret;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
(void)pnetif;
ret = MX_WIFI_IO_YIELD(pMxWifiObj, timeout);
return ret;
}
static void mx_wifi_status_changed(uint8_t cate, uint8_t status, void *arg)
{
net_if_handle_t *pnetif;
uint8_t addr[4];
net_state_t net_state;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
(void)memcpy(&pnetif, &arg, sizeof(pnetif));
if ((uint8_t)MC_STATION == cate)
{
switch (status)
{
case MC_STA_DOWN:
DEBUG_LOG("MC_STA_DOWN\r\n");
(void) net_if_getState(pnetif, &net_state);
if (NET_STATE_CONNECTED == net_state)
{
(void)net_state_manage_event(pnetif, NET_EVENT_LINK_DOWN);
}
else
{
(void)net_state_manage_event(pnetif, NET_EVENT_INTERFACE_READY);
}
break;
case MC_STA_UP:
DEBUG_LOG("MC_STA_UP\r\n");
(void)net_state_manage_event(pnetif, NET_EVENT_LINK_UP);
break;
case MC_STA_GOT_IP:
DEBUG_LOG("MC_STA_GOT_IP\r\n");
(void) memcpy(addr, pMxWifiObj->NetSettings.IP_Addr, 4);
pnetif->ipaddr.addr = NET_ARTON(pMxWifiObj->NetSettings.IP_Addr);
(void) memcpy(addr, pMxWifiObj->NetSettings.IP_Mask, 4);
pnetif->netmask.addr = NET_ARTON(pMxWifiObj->NetSettings.IP_Mask);
(void) memcpy(addr, pMxWifiObj->NetSettings.Gateway_Addr, 4);
pnetif->gateway.addr = NET_ARTON(pMxWifiObj->NetSettings.Gateway_Addr);
(void) net_state_manage_event(pnetif, NET_EVENT_IPADDR);
break;
default:
break;
}
}
else if ((uint8_t)MC_SOFTAP == cate)
{
switch (status)
{
case MC_AP_DOWN:
DEBUG_LOG("MC_AP_DOWN\r\n");
net_if_notify(pnetif, NET_EVENT_STATE_CHANGE, (uint32_t) NET_STATE_CONNECTION_LOST, NULL);
break;
case MC_AP_UP:
DEBUG_LOG("MC_AP_UP\r\n");
pnetif->ipaddr.addr = pnetif->static_ipaddr.addr;
pnetif->gateway.addr = pnetif->static_gateway.addr;
pnetif->netmask.addr = pnetif->static_netmask.addr;
(void) net_state_manage_event(pnetif, NET_EVENT_IPADDR);
break;
default:
break;
}
}
else
{
/* nothing */
}
}
static MX_WIFI_SecurityType_t convert(int security_mode)
{
#if 0
MX_WIFI_SEC_NONE, /**< Open system. */
MX_WIFI_SEC_WEP, /**< Wired Equivalent Privacy. WEP security. */
MX_WIFI_SEC_WPA_TKIP, /**< WPA /w TKIP */
MX_WIFI_SEC_WPA_AES, /**< WPA /w AES */
MX_WIFI_SEC_WPA2_TKIP, /**< WPA2 /w TKIP */
MX_WIFI_SEC_WPA2_AES, /**< WPA2 /w AES */
MX_WIFI_SEC_WPA2_MIXED, /**< WPA2 /w AES or TKIP */
#endif
return MX_WIFI_SEC_AUTO;
}
static int32_t mx_wifi_if_connect_sta(net_if_handle_t *pnetif)
{
int32_t ret;
MX_WIFI_SecurityType_t secure_type;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
const net_wifi_credentials_t *credentials = pnetif->pdrv->extension.wifi->credentials;
if (false == pnetif->dhcp_mode)
{
pMxWifiObj->NetSettings.DHCP_IsEnabled = 0;
(void)memcpy(pMxWifiObj->NetSettings.IP_Addr, &(pnetif->ipaddr), 4);
(void)memcpy(pMxWifiObj->NetSettings.IP_Mask, &(pnetif->netmask), 4);
(void)memcpy(pMxWifiObj->NetSettings.Gateway_Addr, &(pnetif->gateway), 4);
}
else
{
pMxWifiObj->NetSettings.DHCP_IsEnabled = 1;
}
(void)MX_WIFI_RegisterStatusCallback(pMxWifiObj, mx_wifi_status_changed, pnetif);
secure_type = convert(credentials->security_mode);
ret = MX_WIFI_Connect(pMxWifiObj, credentials->ssid, credentials->psk, secure_type);
return ret;
}
#define BYTEN(A,n) ((A)>>(8u*(n))) & 0xffu
#define BYTE3(A) BYTEN((A),3u)
#define BYTE2(A) BYTEN((A),2u)
#define BYTE1(A) BYTEN((A),1u)
#define BYTE0(A) BYTEN((A),0u)
#define ADDR(a) BYTE0(a),BYTE1(a),BYTE2(a),BYTE3(a)
static int32_t mx_wifi_if_connect_ap(net_if_handle_t *pnetif)
{
int32_t ret = NET_ERROR_GENERIC;
MX_WIFI_APSettings_t ap_cfg;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
const net_wifi_credentials_t *credentials = pnetif->pdrv->extension.wifi->credentials;
(void) memset(&ap_cfg, 0, sizeof(ap_cfg));
(void) strcpy(ap_cfg.SSID, credentials->ssid);
(void) strcpy(ap_cfg.pswd, credentials->psk);
ap_cfg.channel = pnetif->pdrv->extension.wifi->access_channel;
(void) sprintf(ap_cfg.ip.localip, "%ld.%ld.%ld.%ld", ADDR(pnetif->static_ipaddr.addr));
(void) sprintf(ap_cfg.ip.netmask, "%ld.%ld.%ld.%ld", ADDR(pnetif->static_gateway.addr));
(void) sprintf(ap_cfg.ip.gateway, "%ld.%ld.%ld.%ld", ADDR(pnetif->static_netmask.addr));
(void) sprintf(ap_cfg.ip.dnserver, "%ld.%ld.%ld.%ld", ADDR(pnetif->static_dnserver.addr));
(void) MX_WIFI_RegisterStatusCallback(pMxWifiObj, mx_wifi_status_changed, pnetif);
if (MX_WIFI_STATUS_OK == MX_WIFI_StartAP(pMxWifiObj, &ap_cfg))
{
ret = NET_OK;
}
return ret;
}
static int32_t mx_wifi_if_disconnect(net_if_handle_t *pnetif)
{
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
if (pnetif->pdrv->extension.wifi->mode == NET_WIFI_MODE_STA)
{
(void)MX_WIFI_Disconnect(pMxWifiObj);
}
else
{
(void) MX_WIFI_StopAP(pMxWifiObj);
}
(void) net_state_manage_event(pnetif, NET_EVENT_INTERFACE_READY);
return NET_OK;
}
static int32_t mx_wifi_if_connect(net_if_handle_t *pnetif)
{
int32_t ret;
if (pnetif->pdrv->extension.wifi->mode == NET_WIFI_MODE_STA)
{
ret = mx_wifi_if_connect_sta(pnetif);
}
else
{
ret = mx_wifi_if_connect_ap(pnetif);
}
return ret;
}
static int32_t mx_wifi_scan(net_if_handle_t *pnetif, net_wifi_scan_mode_t mode, char_t *ssid)
{
int32_t ret;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
uint32_t len = 0u;
(void) pnetif;
if (ssid != NULL)
{
len = strlen(ssid);
}
ret = MX_WIFI_Scan(pMxWifiObj, (uint8_t)mode, ssid, (int32_t) len);
return ret;
}
static int32_t mx_wifi_get_scan_result(net_if_handle_t *pnetif, net_wifi_scan_results_t *scan_bss_array,
uint8_t scan_bss_array_size)
{
int32_t ret;
uint8_t number = scan_bss_array_size;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
mc_wifi_ap_info_t *ap_list_head;
net_wifi_scan_results_t *scan_bss = scan_bss_array;
(void)pnetif;
static uint32_t mxsec[] =
{
NET_WIFI_SM_OPEN,
NET_WIFI_SM_WEP_PSK, /**< Wired Equivalent Privacy. WEP security. */
NET_WIFI_SM_WPA_TKIP_PSK, /**< WPA /w TKIP */
NET_WIFI_SM_WPA_AES_PSK, /**< WPA /w AES */
NET_WIFI_SM_WPA2_TKIP_PSK, /**< WPA2 /w TKIP */
NET_WIFI_SM_WPA2_AES_PSK, /**< WPA2 /w AES */
NET_WIFI_SM_WPA2_MIXED_PSK, /**< WPA2 /w AES or TKIP */
};
if ((NULL == scan_bss_array) || (0u == number))
{
ret = NET_ERROR_PARAMETER;
}
else
{
/* create buff for mc_wifi results */
void *ptmp = NET_MALLOC(sizeof(mc_wifi_ap_info_t) * number);
(void) memcpy(&ap_list_head, &ptmp, sizeof(ap_list_head));
if (NULL == ap_list_head)
{
ret = NET_ERROR_NO_MEMORY;
}
else
{
mc_wifi_ap_info_t *ap_info = ap_list_head;
(void) memset(ap_list_head, 0, sizeof(mc_wifi_ap_info_t) * number);
/* get real mc_wifi scan results data */
number = (uint8_t) MX_WIFI_Get_scan_result(pMxWifiObj, (uint8_t *) ap_info, number);
for (uint32_t i = 0U; i < number; i++)
{
(void) memset(scan_bss, 0, sizeof(net_wifi_scan_bss_t));
(void) memcpy(scan_bss->ssid.value, ap_info->ssid, NET_WIFI_MAX_SSID_SIZE);
scan_bss->ssid.length = (uint8_t) strlen(ap_info->ssid);
scan_bss->security = mxsec[ap_info->security];
(void) memcpy(&scan_bss->bssid, ap_info->bssid, NET_WIFI_MAC_ADDRESS_SIZE);
scan_bss->rssi = (int8_t)ap_info->rssi;
scan_bss->channel = ap_info->channel;
(void) memcpy(scan_bss->country, ".CN", 4); /* NOT SUPPORT for MX_WIFI */
scan_bss++;
ap_info++;
}
ret = (int32_t) number;
NET_FREE((void *) ap_list_head);
}
}
return ret;
}
static int32_t mx_wifi_socket(int32_t domain, int32_t type, int32_t protocol)
{
int32_t ret;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
ret = MX_WIFI_Socket_create(pMxWifiObj, domain, type, protocol);
return ret;
}
static int32_t mx_wifi_setsockopt(int32_t sock, int32_t level, int32_t optname, const void *optvalue, uint32_t optlen)
{
int32_t ret;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
ret = MX_WIFI_Socket_setsockopt(pMxWifiObj, sock, level, optname, optvalue, (int32_t)optlen);
return ret;
}
static int32_t mx_wifi_getsockopt(int32_t sock, int32_t level, int32_t optname, void *optvalue, uint32_t *optlen)
{
int32_t ret;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
ret = MX_WIFI_Socket_getsockopt(pMxWifiObj, sock, level, optname, optvalue, optlen);
return ret;
}
static int32_t mx_wifi_bind(int32_t sock, const net_sockaddr_t *addr, uint32_t addrlen)
{
int32_t ret;
struct sockaddr mx_addr;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
(void)memcpy(&mx_addr, addr, sizeof(mx_addr));
ret = MX_WIFI_Socket_bind(pMxWifiObj, sock, &mx_addr, (int32_t)addrlen);
return ret;
}
static int32_t mx_wifi_listen(int32_t sock, int32_t backlog)
{
int32_t ret;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
ret = MX_WIFI_Socket_listen(pMxWifiObj, sock, backlog);
return ret;
}
static int32_t mx_wifi_accept(int32_t sock, net_sockaddr_t *addr, uint32_t *addrlen)
{
int32_t ret;
struct sockaddr mx_addr;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
(void)memcpy(&mx_addr, addr, sizeof(mx_addr));
ret = MX_WIFI_Socket_accept(pMxWifiObj, sock, &mx_addr, addrlen);
return ret;
}
static int32_t mx_wifi_connect(int32_t sock, const net_sockaddr_t *addr, uint32_t addrlen)
{
int32_t ret;
struct sockaddr mx_addr;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
(void)memcpy(&mx_addr, addr, sizeof(mx_addr));
ret = MX_WIFI_Socket_connect(pMxWifiObj, sock, &mx_addr, (int32_t)addrlen);
return ret;
}
static int32_t mx_wifi_shutdown(int32_t sock, int32_t mode)
{
int32_t ret;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
ret = MX_WIFI_Socket_shutdown(pMxWifiObj, sock, mode);
return ret;
}
static int32_t mx_wifi_close(int32_t sock, bool isaclone)
{
int32_t ret;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
(void)isaclone;
ret = MX_WIFI_Socket_close(pMxWifiObj, sock);
return ret;
}
static int32_t mx_wifi_send(int32_t sock, uint8_t *buf, int32_t len, int32_t flags)
{
int32_t ret;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
ret = MX_WIFI_Socket_send(pMxWifiObj, sock, buf, len, flags);
return ret;
}
static int32_t mx_wifi_recv(int32_t sock, uint8_t *buf, int32_t len, int32_t flags)
{
int32_t ret;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
ret = MX_WIFI_Socket_recv(pMxWifiObj, sock, buf, len, flags);
return ret;
}
static int32_t mx_wifi_sendto(int32_t sock, uint8_t *buf, int32_t len, int32_t flags, net_sockaddr_t *to,
uint32_t tolen)
{
int32_t ret;
struct sockaddr mx_addr;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
(void)memcpy(&mx_addr, to, sizeof(mx_addr));
ret = MX_WIFI_Socket_sendto(pMxWifiObj, sock, buf, len, flags, &mx_addr, (int32_t)tolen);
return ret;
}
static int32_t mx_wifi_recvfrom(int32_t sock, uint8_t *buf, int32_t len, int32_t flags, net_sockaddr_t *from,
uint32_t *fromlen)
{
int32_t ret;
struct sockaddr mx_addr;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
(void)memcpy(&mx_addr, from, sizeof(mx_addr));
ret = MX_WIFI_Socket_recvfrom(pMxWifiObj, sock, buf, len, flags, &mx_addr, fromlen);
return ret;
}
static int32_t mx_wifi_gethostbyname(net_if_handle_t *pnetif, net_sockaddr_t *addr, char_t *name)
{
int32_t ret;
struct sockaddr mx_addr;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
(void)pnetif;
ret = MX_WIFI_Socket_gethostbyname(pMxWifiObj, &mx_addr, (char_t *)name);
(void)memcpy(addr, &mx_addr, sizeof(mx_addr));
return ret;
}
int32_t mx_wifi_ping(net_if_handle_t *pnetif, net_sockaddr_t *addr, int32_t count, int32_t delay, int32_t response[])
{
int32_t ret;
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
net_sockaddr_in_t addr_in;
net_ip_addr_t ip_addr;
(void)pnetif;
(void)memcpy(&addr_in, addr, sizeof(addr_in));
ip_addr.addr = addr_in.sin_addr.s_addr;
ret = MX_WIFI_Socket_ping(pMxWifiObj, (char_t *)net_ntoa(&ip_addr), count, delay, response);
return ret;
}
static int32_t mx_wifi_getsockname(int32_t sock, net_sockaddr_t *name, uint32_t *namelen)
{
DEBUG_LOG("mx_wifi_getsockname UNSUPPORTED!");
(void)sock;
(void)name;
(void)namelen;
return NET_ERROR_UNSUPPORTED;
}
static int32_t mx_wifi_getpeername(int32_t sock, net_sockaddr_t *name, uint32_t *namelen)
{
DEBUG_LOG("mx_wifi_getpeername UNSUPPORTED!");
(void)sock;
(void)name;
(void)namelen;
return NET_ERROR_UNSUPPORTED;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,556 @@
/**
******************************************************************************
* @file net_st_wifi.c
* @author MCD Application Team
* @brief ST Wi-Fi specific BSD-like socket wrapper
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#include "net_connect.h"
#include "net_internals.h"
#include "net_buffers.h"
#include "net_wifi.h"
#include "net_ip_lwip.h"
#include "wifi.h"
#define MAX_MTU 1500
/* Wi-Fi Driver */
extern wifi_driver_t stw_driver;
wifi_driver_t *wifi_driver = &stw_driver;
int32_t st_wifi_driver(net_if_handle_t *pnetif);
/* STM32 Network library Framework */
static int32_t st_wifi_if_init(net_if_handle_t *pnetif);
static int32_t st_wifi_if_deinit(net_if_handle_t *pnetif);
static int32_t st_wifi_if_start(net_if_handle_t *pnetif);
static int32_t st_wifi_if_stop(net_if_handle_t *pnetif);
static int32_t st_wifi_if_connect(net_if_handle_t *pnetif);
static int32_t st_wifi_if_disconnect(net_if_handle_t *pnetif);
static int32_t st_wifi_if_powersave_enable(net_if_handle_t *pnetif);
static int32_t st_wifi_if_powersave_disable(net_if_handle_t *pnetif);
/*static int32_t st_wifi_if_sleep(net_if_handle_t * pnetif); */
/*static int32_t st_wifi_if_wakeup(net_if_handle_t * pnetif); */
/* Class extension */
static int32_t st_wifi_scan(net_if_handle_t *pnetif, net_wifi_scan_mode_t mode, char *ssid);
static int32_t st_wifi_get_scan_results(net_if_handle_t *pnetif, net_wifi_scan_results_t *results, uint8_t number);
static int32_t st_wifi_get_system_info(net_wifi_system_info_t info, void *data);
static int32_t st_wifi_set_param(net_wifi_param_t info, void *data);
int32_t st_wifi_event_callback(void *context, wifi_event_t event, void *data);
static err_t net_wifi_if_init(struct netif *netif);
static int32_t st_wifi_transmit(struct netif *netif, net_buf_t *net_buf);
/*******************************************************************************
Wi-Fi Driver
*******************************************************************************/
int32_t st_wifi_driver(net_if_handle_t *pnetif)
{
net_ip_init();
return st_wifi_if_init(pnetif);
}
/*******************************************************************************
STM32 Network library Framework
*******************************************************************************/
/* Init */
int32_t st_wifi_if_init(net_if_handle_t *pnetif)
{
int32_t ret;
net_if_drv_t *p = NET_MALLOC(sizeof(net_if_drv_t));
if (p)
{
p->if_class = NET_INTERFACE_CLASS_WIFI;
p->if_init = st_wifi_if_init;
p->if_deinit = st_wifi_if_deinit;
p->if_start = st_wifi_if_start;
p->if_stop = st_wifi_if_stop;
p->if_connect = st_wifi_if_connect;
p->if_disconnect = st_wifi_if_disconnect;
p->if_powersave_enable = st_wifi_if_powersave_enable;
p->if_powersave_disable = st_wifi_if_powersave_disable;
p->pping = icmp_ping;
p->extension.wifi = NET_MALLOC(sizeof(net_if_wifi_class_extension_t));
if (NULL == p->extension.wifi)
{
NET_DBG_ERROR("can't allocate memory for st_wifi_driver class\n");
NET_FREE(p);
ret = NET_ERROR_NO_MEMORY;
}
else
{
pnetif->pdrv = p;
(void) memset(p->extension.wifi, 0, sizeof(net_if_wifi_class_extension_t));
p->extension.wifi->scan = st_wifi_scan;
p->extension.wifi->get_scan_results = st_wifi_get_scan_results;
p->extension.wifi->get_system_info = st_wifi_get_system_info;
p->extension.wifi->set_param = st_wifi_set_param;
(void) net_state_manage_event(pnetif, NET_EVENT_INTERFACE_INITIALIZED);
ret = NET_OK;
}
}
else
{
NET_DBG_ERROR("can't allocate memory for st_wifi_driver class\n");
ret = NET_ERROR_NO_MEMORY;
}
if (wifi_probe(&pnetif->pdrv->context) == NET_OK)
{
if (wifi_init(wifi_driver, st_wifi_event_callback, NULL, pnetif) != WIFI_STATUS_OK)
{
ret = NET_ERROR_INTERFACE_FAILURE;
}
}
else
{
ret = NET_ERROR_DEVICE_ERROR;
}
return ret;
}
/* Deinit */
int32_t st_wifi_if_deinit(net_if_handle_t *pnetif)
{
int32_t ret = NET_OK;
if (wifi_deinit(wifi_driver) != WIFI_STATUS_OK)
{
ret = NET_ERROR_INTERFACE_FAILURE;
}
else
{
ret = NET_OK;
}
NET_FREE(pnetif->pdrv->extension.wifi);
pnetif->pdrv->extension.wifi = NULL;
NET_FREE(pnetif->pdrv);
pnetif->pdrv = NULL;
return ret;
}
/* Start */
int32_t st_wifi_if_start(net_if_handle_t *pnetif)
{
int32_t ret = NET_OK;
net_wifi_powersave_t wifi_powersave =
{
WIFI_POWERSAVE_LIGHT_SLEEP
};
if (wifi_start() != WIFI_STATUS_OK)
{
ret = NET_ERROR_INTERFACE_FAILURE;
}
else
{
/* STA mode */
if (wifi_obj->mode == WIFI_MODE_STA)
{
/* Retrieve Wi-Fi device information */
char device_name[NET_DEVICE_NAME_LEN];
wifi_get_system_info(WIFI_SYSINFO_DEVICE_NAME, (void *)device_name);
strncpy(pnetif->DeviceName, device_name, NET_DEVICE_NAME_LEN);
wifi_get_system_info(WIFI_SYSINFO_WLAN_MAC, pnetif->macaddr.mac);
/* Set default values */
pnetif->pdrv->extension.wifi->powersave = &wifi_powersave;
}
/* AP mode */
if (wifi_obj->mode == WIFI_MODE_AP)
{
#if 0
const net_wifi_credentials_t *credentials = pnetif->pdrv->extension.wifi->credentials;
wifi_privacy_t privacy = WIFI_PRIVACY_NONE;
if (credentials->security_mode & NET_WPA_SECURITY)
{
privacy = WIFI_PRIVACY_WPA;
}
if (credentials->security_mode & NET_WPA2_SECURITY)
{
privacy = WIFI_PRIVACY_WPA;
}
#endif /* FIXME */
}
/* Add IP interface */
ret = net_ip_add_if(pnetif, net_wifi_if_init, NET_ETHERNET_FLAG_DEFAULT_IF);
if (ret == NET_OK)
{
/*Forcing a UP at that stage , would expect msg from WIFI to trigger it
netif_set_link_up(pnetif->netif); */
if (wifi_obj->mode == WIFI_MODE_STA)
{
(void) net_state_manage_event(pnetif, NET_EVENT_INTERFACE_READY);
}
}
}
return ret;
}
/* Stop */
int32_t st_wifi_if_stop(net_if_handle_t *pnetif)
{
int32_t ret = NET_OK;
if (wifi_stop() != WIFI_STATUS_OK)
{
ret = NET_ERROR_INTERFACE_FAILURE;
}
if (ret == NET_OK)
{
ret = net_state_manage_event(pnetif, NET_EVENT_INTERFACE_INITIALIZED);
}
return ret;
}
/* Connect */
static int32_t st_wifi_if_connect(net_if_handle_t *pnetif)
{
int32_t ret = NET_OK;
const net_wifi_credentials_t *credentials = pnetif->pdrv->extension.wifi->credentials;
wifi_privacy_t privacy = WIFI_PRIVACY_NONE;
if (credentials->security_mode & NET_WPA_SECURITY)
{
privacy = WIFI_PRIVACY_WPA;
}
if (credentials->security_mode & NET_WPA2_SECURITY)
{
privacy = WIFI_PRIVACY_WPA;
}
if (wifi_connect((char *)credentials->ssid, (char *)credentials->psk, privacy, 0) != WIFI_STATUS_OK)
{
ret = NET_ERROR_AUTH_FAILURE;
}
else
{
ret = net_ip_connect(pnetif);
}
return ret;
}
/* Disconnect */
static int32_t st_wifi_if_disconnect(net_if_handle_t *pnetif)
{
int32_t ret = NET_ERROR_FRAMEWORK;
if (wifi_disconnect() != WIFI_STATUS_OK)
{
ret = NET_ERROR_FRAMEWORK;
}
else
{
ret = net_state_manage_event(pnetif, NET_EVENT_INTERFACE_READY);
ret = NET_OK;
}
return ret;
}
/* Power-save */
static int32_t st_wifi_if_powersave_enable(net_if_handle_t *pnetif)
{
int32_t ret = NET_OK;
wifi_power_mode(*(pnetif->pdrv->extension.wifi->powersave));
return ret;
}
static int32_t st_wifi_if_powersave_disable(net_if_handle_t *pnetif)
{
int32_t ret = NET_OK;
wifi_power_mode(WIFI_POWER_MODE_ACTIVE);
return ret;
}
/*******************************************************************************
Class extension
*******************************************************************************/
/* Scan */
static int32_t st_wifi_scan(net_if_handle_t *pnetif, net_wifi_scan_mode_t mode, char *ssid)
{
int32_t ret = NET_ERROR_FRAMEWORK;
(void) ssid;
wifi_scan_t params;
switch (mode)
{
case NET_WIFI_SCAN_PASSIVE:
params.mode = WIFI_SCAN_MODE_PASSIVE;
break;
case NET_WIFI_SCAN_ACTIVE:
params.mode = WIFI_SCAN_MODE_ACTIVE;
break;
case NET_WIFI_SCAN_AUTO:
params.mode = WIFI_SCAN_MODE_AUTO;
break;
default:
params.mode = WIFI_SCAN_MODE_AUTO;
}
params.ssid.length = 0;
params.channels = 0;
if (wifi_scan(params) != WIFI_STATUS_OK)
{
ret = NET_ERROR_GENERIC;
}
else
{
ret = NET_OK;
}
return ret;
}
/* Get scan results */
static int32_t st_wifi_get_scan_results(net_if_handle_t *pnetif, net_wifi_scan_results_t *results, uint8_t number)
{
int32_t ret = NET_ERROR_FRAMEWORK;
uint8_t nb;
wifi_get_system_info(WIFI_SYSINFO_LAST_SCAN_RESULTS_NUMBER, (void *)&nb);
if (nb > number)
{
nb = number;
}
wifi_scan_results_t res;
res.number = nb;
res.bss = NET_MALLOC(number * sizeof(wifi_scan_bss_t));
if (wifi_get_scan_results(&res, nb) == WIFI_STATUS_OK)
{
for (uint8_t i = 0; i < nb; i++)
{
results->ssid.length = res.bss[i].ssid.length;
memcpy(results->ssid.value, res.bss[i].ssid.value, res.bss[i].ssid.length);
memcpy(results->bssid, res.bss[i].bssid, sizeof(wifi_mac_t));
results->channel = res.bss[i].channel;
memcpy(results->country, res.bss[i].country, 3);
results->rssi = res.bss[i].rssi;
results++;
}
ret = nb;
}
else
{
ret = NET_ERROR_GENERIC;
}
NET_FREE((void *)(res.bss));
return ret;
}
/* Get system info */
static int32_t st_wifi_get_system_info(net_wifi_system_info_t info, void *data)
{
int32_t ret = NET_OK;
wifi_system_info_t wifi_info;
switch (info)
{
case NET_WIFI_SCAN_RESULTS_NUMBER:
wifi_info = WIFI_SYSINFO_LAST_SCAN_RESULTS_NUMBER;
break;
default:
return NET_ERROR_PARAMETER;
break;
}
if (wifi_get_system_info(wifi_info, data) != WIFI_STATUS_OK)
{
ret = NET_ERROR_PARAMETER;
}
else
{
ret = NET_OK;
}
return ret;
}
/* Set param */
static int32_t st_wifi_set_param(net_wifi_param_t param, void *data)
{
int32_t ret = NET_OK;
wifi_params_t wifi_param;
void *wifi_data;
switch (param)
{
case NET_WIFI_MODE:
{
wifi_param = WIFI_MODE;
wifi_data = wifi_os_malloc(1);
switch (*(uint8_t *)data)
{
case NET_WIFI_MODE_STA:
*(uint8_t *)wifi_data = WIFI_MODE_STA;
break;
case NET_WIFI_MODE_AP:
*(uint8_t *)wifi_data = WIFI_MODE_AP;
break;
default:
return NET_ERROR_PARAMETER;
break;
}
break;
}
default:
return NET_ERROR_PARAMETER;
break;
}
if (wifi_set_param(wifi_param, wifi_data) != WIFI_STATUS_OK)
{
ret = NET_ERROR_PARAMETER;
}
else
{
ret = NET_OK;
}
wifi_os_free(wifi_data);
return ret;
}
/* Event callback */
int32_t st_wifi_event_callback(void *context, wifi_event_t event, void *data)
{
net_if_handle_t *pnetif = context;
switch (event)
{
case WIFI_EVENT_LINK_DOWN:
if (wifi_obj->mode == WIFI_MODE_STA)
{
netif_set_link_down(pnetif->netif);
}
break;
case WIFI_EVENT_LINK_UP:
if (wifi_obj->mode == WIFI_MODE_STA)
{
netif_set_link_up(pnetif->netif);
}
if (wifi_obj->mode == WIFI_MODE_AP)
{
(void) net_state_manage_event(pnetif, NET_EVENT_INTERFACE_READY);
}
break;
case WIFI_EVENT_SCAN_COMPLETE:
net_if_notify(pnetif, NET_EVENT_WIFI, NET_WIFI_SCAN_RESULTS_READY, (void *)data);
break;
case WIFI_EVENT_POWER_MODE_COMPLETE:
net_if_notify(pnetif, NET_EVENT, NET_EVENT_POWERSAVE_ENABLED, (void *)data);
break;
case WIFI_EVENT_RX_DATA:
{
wifi_rx_data_t *eth_frame = (wifi_rx_data_t *)data;
net_buf_t *buf = NET_BUF_ALLOC(eth_frame->len + sizeof(wifi_eth_t));
if (buf == NULL)
{
wifi_os_delay(1);
}
wifi_eth_receive((uint8_t *)(buf->payload), data);
tcpip_input(buf, pnetif->netif);
break;
}
default:
break;
}
return 0;
}
static err_t net_wifi_if_init(struct netif *netif)
{
err_t ret = ERR_OK;
char *hostname = NET_MALLOC(sizeof(char) * ((uint16_t) NET_IP_HOSTNAME_MAX_LEN + 1U));
if (hostname == NULL)
{
return (err_t) ERR_MEM;
}
(void) snprintf(hostname, NET_IP_HOSTNAME_MAX_LEN + 1, "generic eth if #%d", netif->num);
netif->hostname = hostname;
netif->name[0] = 's';
netif->name[1] = 't';
netif->hwaddr_len = 6;
netif->mtu = MAX_MTU;
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
netif->output = etharp_output;
wifi_get_system_info(WIFI_SYSINFO_WLAN_MAC, netif->hwaddr);
#if LWIP_IPV6
netif->output_ip6 = ethip6_output;
#endif /* LWIP_IPV6 */
/* set call back , here to not loose first linkup when if_init is performed */
netif_set_status_callback(netif, net_ip_status_cb);
netif_set_link_callback(netif, net_ip_status_cb);
/* output to the device */
netif->linkoutput = (netif_linkoutput_fn)st_wifi_transmit;
return ret;
}
/*******************************************************************************
TCP/IP Library
*******************************************************************************/
/* Transmit */
static int32_t st_wifi_transmit(struct netif *netif, net_buf_t *net_buf)
{
int32_t ret = NET_OK;
if (wifi_eth_transmit((uint8_t *)(net_buf->payload), (uint16_t)(net_buf->len)) != WIFI_STATUS_OK)
{
ret = NET_ERROR_DATA;
}
return ret;
}
@@ -0,0 +1,530 @@
/**
******************************************************************************
* @file net_ip_lwip.c
* @author MCD Application Team
* @brief lwIP network interface functions
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#include "net_connect.h"
#include "net_internals.h"
#include "net_ip_lwip.h"
#include "net_buffers.h"
#define YES (u8_t)1
#define NO (u8_t)0
static void link_socket_to_lwip(net_if_drv_t *drv);
#ifndef NET_BYPASS_NET_SOCKET
static int32_t net_lwip_socket(int32_t domain, int32_t type, int32_t protocol);
static int32_t net_lwip_bind(int32_t sock, const net_sockaddr_t *addr, uint32_t addrlen);
static int32_t net_lwip_listen(int32_t sock, int32_t backlog);
static int32_t net_lwip_accept(int32_t sock, net_sockaddr_t *addr, uint32_t *addrlen);
static int32_t net_lwip_connect(int32_t sock, const net_sockaddr_t *addr, uint32_t addrlen);
static int32_t net_lwip_send(int32_t sock, uint8_t *buf, int32_t len, int32_t flags);
static int32_t net_lwip_recv(int32_t sock, uint8_t *buf, int32_t len, int32_t flags);
static int32_t net_lwip_sendto(int32_t sock, uint8_t *buf, int32_t len, int32_t flags, net_sockaddr_t *to,
uint32_t tolen);
static int32_t net_lwip_recvfrom(int32_t sock, uint8_t *buf, int32_t len, int32_t flags, net_sockaddr_t *from,
uint32_t *fromlen);
static int32_t net_lwip_setsockopt(int32_t sock, int32_t level, int32_t optname, const void *optvalue, uint32_t optlen);
static int32_t net_lwip_getsockopt(int32_t sock, int32_t level, int32_t optname, void *optvalue, uint32_t *optlen);
static int32_t net_lwip_getsockname(int32_t sock, net_sockaddr_t *name, uint32_t *namelen);
static int32_t net_lwip_getpeername(int32_t sock, net_sockaddr_t *name, uint32_t *namelen);
static int32_t net_lwip_close(int32_t sock, bool clone);
static int32_t net_lwip_shutdown(int32_t sock, int32_t mode);
#endif /* NET_BYPASS_NET_SOCKET */
static int32_t net_lwip_gethostbyname(net_if_handle_t *pnetif, net_sockaddr_t *addr, char_t *name);
#define NETIF_IS_LINK_UP(netif) (((netif)->flags & NETIF_FLAG_LINK_UP)!=0U)
/* Manage init of LWIP libraryu as a singleton */
void net_ip_init(void)
{
static bool tcpip_init_done = 0;
if (false == tcpip_init_done)
{
tcpip_init(NULL, NULL);
tcpip_init_done = true;
}
}
/* Add of a new network interface */
int32_t net_ip_add_if(net_if_handle_t *pnetif, err_t (*if_init)(struct netif *netif), uint32_t flag)
{
int32_t ret;
struct netif *netif;
/*cstat -MISRAC2012-Rule-11.5 Malloc*/
netif = (struct netif *)(void *) NET_MALLOC(sizeof(struct netif));
/*cstat +MISRAC2012-Rule-11.5 */
if (NULL != netif)
{
pnetif->netif = netif;
(void) memset(netif, 0x00, sizeof(struct netif));
netif = netif_add(netif, NULL, NULL, NULL, pnetif, if_init, tcpip_input);
if ((flag & NET_IP_FLAG_DEFAULT_INTERFACE) != 0U)
{
netif_set_default(netif);
}
/* Get MAC hardware address from netif */
(void) memcpy(pnetif->macaddr.mac, netif->hwaddr, sizeof(netif->hwaddr));
/* link current network interface to LWIP library */
link_socket_to_lwip(pnetif->pdrv);
#if 0 /*FIXME*/
#if LWIP_IPV6
/* Set the IPv6 linklocal address using our MAC */
NET_DBG_PRINT("Setting IPv6 link-local address\n");
netif_create_ip6_linklocal_address(netif, 1);
IP_HANDLE(interface).ip6_autoconfig_enabled = 1;
#endif /* LWIP_IPV6 */
#endif /* FIXME */
ret = NET_OK;
}
else
{
ret = NET_ERROR_GENERIC;
}
return ret;
}
static ip4_addr_t const *ip4_addr(net_ip_addr_t *ipaddr)
{
/*cstat -MISRAC2012-Rule-11.3 Const casting*/
return (ip4_addr_t const *) ipaddr;
/*cstat +MISRAC2012-Rule-11.3*/
}
/* CONNECTION */
int32_t net_ip_connect(net_if_handle_t *pnetif)
{
int32_t ret;
struct netif *netif = (struct netif *)pnetif->netif;
if (NULL != netif)
{
if (!pnetif->dhcp_mode && (NET_IP_ADDR_ISANY_VAL(pnetif->static_ipaddr)))
{
ret = NET_ERROR_PARAMETER;
}
else
{
netif_set_up(netif);
if (pnetif->dhcp_mode)
{
(void) dhcp_start(netif);
}
else
{
netif_set_addr(netif, ip4_addr(&pnetif->static_ipaddr), ip4_addr(&pnetif->static_netmask),
ip4_addr(&pnetif->static_gateway));
dhcp_inform(netif);
}
ret = NET_OK;
}
}
else
{
ret = NET_ERROR_PARAMETER;
}
return ret;
}
int32_t net_ip_disconnect(net_if_handle_t *pnetif)
{
struct netif *netif = pnetif->netif;
/*cstat -MISRAC2012-Rule-11.5 LWIP function*/
if (netif_dhcp_data(netif) != NULL)
/*cstat +MISRAC2012-Rule-11.5 */
{
(void) dhcp_release(netif);
dhcp_stop(netif);
dhcp_cleanup(netif);
}
else
{
netif_set_addr(netif, NULL, NULL, NULL);
pnetif->dhcp_inform_flag = false;
dhcp_inform(netif);
}
return (int32_t) ERR_OK;
}
int32_t net_ip_remove_if(net_if_handle_t *pnetif, err_t (*if_deinit)(struct netif *netif))
{
if (pnetif != NULL)
{
struct netif *netif = pnetif->netif;
if (netif != NULL)
{
netif_set_down(netif);
netif_set_link_down(netif);
netif_remove(netif);
if (NULL != if_deinit)
{
(*if_deinit)(netif);
}
NET_FREE(netif);
pnetif->netif = NULL;
}
}
return NET_OK;
}
void net_ip_status_cb(struct netif *netif)
{
net_ip_addr_t ipaddr_zero;
/*cstat -MISRAC2012-Rule-11.5 casting state pointer by defintion from LWIP */
net_if_handle_t *pnetif = (net_if_handle_t *) netif->state;
/*cstat +MISRAC2012-Rule-11.5 */
NET_ZERO(ipaddr_zero);
if (pnetif->dhcp_enabled)
{
/* lost connection */
if (NET_DIFF(netif->ip_addr, ipaddr_zero) && (!NETIF_IS_LINK_UP(netif)) && pnetif->dhcp_release_on_link_lost)
{
NET_DBG_PRINT("Callback lost connection so release connection\n");
(void) dhcp_release(netif);
(void) dhcp_start(netif);
}
/* up connection , so need to inform other at first time */
if (pnetif->dhcp_inform_flag && NETIF_IS_LINK_UP(netif))
{
NET_DBG_PRINT("Callback get connection\n");
dhcp_inform(netif);
pnetif->dhcp_inform_flag = false;
}
}
if (!NET_IP_ADDR_CMP(&pnetif->ipaddr, &netif->ip_addr))
{
NET_IP_ADDR_COPY(pnetif->ipaddr, netif->ip_addr);
NET_IP_ADDR_COPY(pnetif->netmask, netif->netmask);
NET_IP_ADDR_COPY(pnetif->gateway, netif->gw);
/* FIXME for IPV6 support */
if (!NET_IP_ADDR_ISANY_VAL(pnetif->ipaddr))
{
(void) net_state_manage_event(pnetif, NET_EVENT_IPADDR);
}
}
if (NETIF_IS_LINK_UP(netif))
{
(void) net_state_manage_event(pnetif, NET_EVENT_LINK_UP);
}
else
{
(void) net_state_manage_event(pnetif, NET_EVENT_LINK_DOWN);
}
}
/* UTILITIES */
void link_socket_to_lwip(net_if_drv_t *drv)
{
#ifndef NET_BYPASS_NET_SOCKET
drv->psocket = net_lwip_socket;
drv->pbind = net_lwip_bind;
drv->plisten = net_lwip_listen;
drv->paccept = net_lwip_accept;
drv->pconnect = net_lwip_connect;
drv->psend = net_lwip_send;
drv->precv = net_lwip_recv;
drv->psendto = net_lwip_sendto;
drv->precvfrom = net_lwip_recvfrom;
drv->psetsockopt = net_lwip_setsockopt;
drv->pgetsockopt = net_lwip_getsockopt;
drv->pgetsockname = net_lwip_getsockname;
drv->pgetpeername = net_lwip_getpeername;
drv->pclose = net_lwip_close;
drv->pshutdown = net_lwip_shutdown;
#endif /* NET_BYPASS_NET_SOCKET */
/* Service */
drv->pgethostbyname = net_lwip_gethostbyname;
}
int32_t returncode_lwip2net(int32_t ret_in)
{
int32_t ret = ret_in;
if (ret_in == -1)
{
if (errno == EWOULDBLOCK)
{
ret = 0;
}
}
else if (ret_in == 0)
{
/* connection close */
ret = NET_ERROR_DISCONNECTED;
}
else
{
/* do not catch ret valie otherwise */
ret = ret_in;
}
return ret;
}
#ifndef NET_BYPASS_NET_SOCKET
/**
* @brief Function description
* @param Params
* @retval socket status
*/
static int32_t net_lwip_socket(int32_t domain, int32_t type, int32_t protocol)
{
int32_t sock;
sock = (int32_t) lwip_socket(domain, type, protocol);
return (sock);
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
static struct sockaddr *getsockaddr(const net_sockaddr_t *addr)
{
/*cstat -MISRAC2012-Rule-11.8 const*/
return (struct sockaddr *) addr;
/*cstat +MISRAC2012-Rule-11.8 const*/
}
static int32_t net_lwip_bind(int32_t sock, const net_sockaddr_t *addr, uint32_t addrlen)
{
int32_t ret = lwip_bind(sock, getsockaddr(addr), addrlen);
return ret;
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
static int32_t net_lwip_listen(int32_t sock, int32_t backlog)
{
int32_t ret;
ret = lwip_listen(sock, backlog);
return ret;
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
static int32_t net_lwip_accept(int32_t sock, net_sockaddr_t *addr, uint32_t *addrlen)
{
int32_t ret;
ret = lwip_accept(sock, getsockaddr(addr), addrlen);
return ret;
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
static int32_t net_lwip_connect(int32_t sock, const net_sockaddr_t *addr, uint32_t addrlen)
{
int32_t ret;
ret = lwip_connect(sock, getsockaddr(addr), addrlen);
return ret;
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
static int32_t net_lwip_send(int32_t sock, uint8_t *buf, int32_t len, int32_t flags)
{
int32_t ret;
ret = lwip_send(sock, buf, (uint32_t) len, flags);
return returncode_lwip2net(ret);
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
static int32_t net_lwip_recv(int32_t sock, uint8_t *buf, int32_t len, int32_t flags)
{
int32_t ret;
ret = lwip_recv(sock, buf, (uint32_t) len, flags);
return returncode_lwip2net(ret);
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
static int32_t net_lwip_sendto(int32_t sock, uint8_t *buf, int32_t len, int32_t flags, net_sockaddr_t *to,
uint32_t tolen)
{
int32_t ret = lwip_sendto(sock, buf, (uint32_t) len, flags, getsockaddr(to), tolen);
return returncode_lwip2net(ret);
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
static int32_t net_lwip_recvfrom(int32_t sock, uint8_t *buf, int32_t len, int32_t flags, net_sockaddr_t *from,
uint32_t *fromlen)
{
int32_t ret = lwip_recvfrom(sock, buf, (uint32_t) len, flags, getsockaddr(from), fromlen);
return returncode_lwip2net(ret);
}
/**
* @brief function description
* @param Params
* @retval socket status
*/
static int32_t net_lwip_setsockopt(int32_t sock, int32_t level, int32_t optname, const void *optvalue, uint32_t optlen)
{
int32_t ret = lwip_setsockopt(sock, level, optname, optvalue, optlen);
return ret;
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
static int32_t net_lwip_getsockopt(int32_t sock, int32_t level, int32_t optname, void *optvalue, uint32_t *optlen)
{
int32_t ret = lwip_getsockopt(sock, level, optname, optvalue, optlen);
return ret;
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
static int32_t net_lwip_getsockname(int32_t sock, net_sockaddr_t *name, uint32_t *namelen)
{
int32_t ret = lwip_getsockname(sock, getsockaddr(name), namelen);
return ret;
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
static int32_t net_lwip_getpeername(int32_t sock, net_sockaddr_t *name, uint32_t *namelen)
{
int32_t ret = lwip_getpeername(sock, getsockaddr(name), namelen);
return ret;
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
static int32_t net_lwip_close(int32_t sock, bool clone)
{
(void) clone;
int32_t ret = lwip_close(sock);
return ret;
}
/**
* @brief Function description
* @param Params
* @retval socket status
*/
static int32_t net_lwip_shutdown(int32_t sock, int32_t mode)
{
int32_t ret = lwip_shutdown(sock, mode);
return ret;
}
#endif /* NET_BYPASS_NET_SOCKET */
/**
* @brief Function description
* @param Params
* @retval socket status
*/
static int32_t net_lwip_gethostbyname(net_if_handle_t *pnetif, net_sockaddr_t *addr, char_t *name)
{
int32_t ret = NET_ERROR_DNS_FAILURE;
struct addrinfo *hostinfo;
struct addrinfo hints;
(void) pnetif;
if (addr->sa_len < sizeof(net_sockaddr_in_t))
{
ret = NET_ERROR_PARAMETER;
}
else
{
(void) memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
if (0 == lwip_getaddrinfo((char_t *)name, NULL, &hints, &hostinfo))
{
if (hostinfo->ai_family == AF_INET)
{
uint8_t len = addr->sa_len;
net_sockaddr_in_t *saddr = (net_sockaddr_in_t *) addr;
(void) memset(saddr, 0, len);
saddr->sin_len = len;
saddr->sin_family = NET_AF_INET;
(void) memcpy(&saddr->sin_addr, &((net_sockaddr_in_t *)(hostinfo->ai_addr))->sin_addr, 4);
ret = NET_OK;
}
lwip_freeaddrinfo(hostinfo);
}
}
return ret;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,629 @@
/**
******************************************************************************
* @file net_mbedtls.c
* @author MCD Application Team
* @brief Network abstraction at transport layer level. mbedTLS implementation.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#include "net_connect.h"
#include "net_internals.h"
#ifdef NET_MBEDTLS_HOST_SUPPORT
#if (osCMSIS >= 0x20000U)
#define OSSEMAPHOREWAIT osSemaphoreAcquire
#else
#define OSSEMAPHOREWAIT osSemaphoreWait
#endif /* osCMSIS */
int32_t mbedtls_rng_raw(void *data, uchar_t *output, size_t len);
extern struct __RNG_HandleTypeDef hrng;
/* Private defines -----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static void mbedtls_free_resource(net_socket_t *sock);
static int32_t mbedtls_net_recv(void *ctx, uchar_t *buf, size_t len, uint32_t timeout);
static int32_t mbedtls_net_send(void *ctx, const uchar_t *buf, size_t len);
#ifdef NET_USE_RTOS
extern void *pxCurrentTCB;
#ifdef MBEDTLS_THREADING_ALT
void mutex_init(mbedtls_threading_mutex_t *mutex);
void mutex_free(mbedtls_threading_mutex_t *mutex);
int32_t mutex_lock(mbedtls_threading_mutex_t *mutex);
int32_t mutex_unlock(mbedtls_threading_mutex_t *mutex);
void mutex_init(mbedtls_threading_mutex_t *mutex)
{
#if (osCMSIS >= 0x20000U)
mutex->id = osSemaphoreNew(1, 1, NULL);
#else
mutex->id = osSemaphoreCreate(&mutex->def, 1);
#endif /* osCMSIS */
}
void mutex_free(mbedtls_threading_mutex_t *mutex)
{
(void) osSemaphoreDelete(mutex->id);
}
#define WAITFOREVER 0xFFFFFFFFU /* redefined for MISRA checks */
int32_t mutex_lock(mbedtls_threading_mutex_t *mutex)
{
BaseType_t ret;
ret = (BaseType_t) OSSEMAPHOREWAIT(mutex->id, WAITFOREVER);
return (ret >= 0) ? 0 : -1;
}
int32_t mutex_unlock(mbedtls_threading_mutex_t *mutex)
{
BaseType_t ret;
ret = (BaseType_t) osSemaphoreRelease(mutex->id);
return (ret >= 0) ? 0 : -1;
}
#endif /* MBEDTLS_THREADING_ALT */
#endif /* NET_USE_RTOS */
void net_tls_init(void)
{
#ifdef MBEDTLS_THREADING_ALT
mbedtls_threading_set_alt(mutex_init, mutex_free, mutex_lock, mutex_unlock);
#endif /* MBEDTLS_THREADING_ALT */
}
void net_tls_destroy(void)
{
#ifdef MBEDTLS_THREADING_ALT
mbedtls_threading_free_alt();
#endif /* MBEDTLS_THREADING_ALT */
}
/* Functions Definition ------------------------------------------------------*/
bool net_mbedtls_check_tlsdata(net_socket_t *sock)
{
bool ret = true;
void *p;
if (NULL == sock->tlsData)
{
/*cstat -MISRAC2012-Rule-21.3 -MISRAC2012-Dir-4.12 */
p = NET_MALLOC(sizeof(net_tls_data_t));
/*cstat +MISRAC2012-Rule-21.3 +MISRAC2012-Dir-4.12 */
if (p == NULL)
{
NET_DBG_ERROR("Error during setting option.\n");
ret = false;
}
else
{
/*cstat -MISRAC2012-Rule-11.5 */
sock->tlsData = p;
/*cstat +MISRAC2012-Rule-11.5 */
(void) memset(sock->tlsData, 0, sizeof(net_tls_data_t));
sock->tlsData->tls_srv_verification = true;
}
}
return ret;
}
static void DebugPrint(void *ctx,
int32_t level,
const char_t *file,
int32_t line,
const char_t *str)
{
/* Unused parameters. */
(void)ctx;
(void) level;
#ifdef NET_USE_RTOS
NET_PRINT_WO_CR("%p => %s:%04ld: %s\n", pxCurrentTCB, file, (int32_t) line, str);
#else
NET_PRINT_WO_CR("%s:%04ld: %s\n", file, (uint32_t) line, str);
#endif /* NET_USE_RTOS */
}
void net_mbedtls_set_read_timeout(net_socket_t *sock)
{
net_tls_data_t *tlsData = sock->tlsData;
if (tlsData != NULL)
{
mbedtls_ssl_conf_read_timeout(&tlsData->conf, (uint32_t) sock->read_timeout);
}
}
static void *net_wrapper_calloc(size_t n, size_t m)
{
/*cstat -MISRAC2012-Dir-4.12 -MISRAC2012-Rule-21.3 */
return NET_CALLOC(n, m);
/*cstat +MISRAC2012-Dir-4.12 +MISRAC2012-Rule-21.3 */
}
/*cstat -MISRAC2012-Dir-4.6_b */
typedef void (*mbedtls_debug_func_t)(void *, int, const char *, int, const char *);
typedef int (*mbedtls_rng_func_t)(void *, unsigned char *, size_t);
/*cstat +MISRAC2012-Dir-4.6_b */
static void net_wrapper_free(void *p)
{
/*cstat -MISRAC2012-Rule-21.3 */
NET_FREE(p);
/*cstat +MISRAC2012-Rule-21.3 */
}
uint32_t NET_TICK(void);
int32_t net_mbedtls_start(net_socket_t *sock)
{
int32_t ret = NET_OK;
net_tls_data_t *tlsData = sock->tlsData;
uint32_t start_tick;
(void) mbedtls_platform_set_calloc_free(net_wrapper_calloc, net_wrapper_free);
mbedtls_ssl_init(&tlsData->ssl);
mbedtls_ssl_config_init(&tlsData->conf);
/*cstat -MISRAC2012-Rule-11.1 */
mbedtls_ssl_conf_dbg(&tlsData->conf, (mbedtls_debug_func_t) DebugPrint, NULL);
/*cstat +MISRAC2012-Rule-11.1 */
mbedtls_debug_set_threshold(NET_MBEDTLS_DEBUG_LEVEL);
mbedtls_x509_crt_init(&tlsData->cacert);
if (tlsData->tls_dev_cert != NULL)
{
mbedtls_x509_crt_init(&tlsData->clicert);
}
if (tlsData->tls_dev_key != NULL)
{
mbedtls_pk_init(&tlsData->pkey);
}
/* Root CA */
if (tlsData->tls_ca_certs != NULL)
{
ret = mbedtls_x509_crt_parse(&tlsData->cacert, (uchar_t const *) tlsData->tls_ca_certs,
strlen((char_t const *) tlsData->tls_ca_certs) + 1U);
if (ret != 0)
{
NET_DBG_ERROR(" failed\n ! mbedtls_x509_crt_parse returned 0x%lx while parsing root cert\n", ret);
mbedtls_free_resource(sock);
ret = NET_ERROR_MBEDTLS_CRT_PARSE;
}
}
else
{
/*no root so cannot check server identification ?
tlsData->tls_srv_verification = */
}
/* Client cert. and key */
if ((ret == NET_OK) && (tlsData->tls_dev_cert != NULL) && (tlsData->tls_dev_key != NULL))
{
ret = mbedtls_x509_crt_parse(&tlsData->clicert, (uchar_t const *) tlsData->tls_dev_cert,
strlen((char_t const *)tlsData->tls_dev_cert) + 1U);
if (ret != 0)
{
NET_DBG_ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%lx while parsing device cert\n", -ret);
mbedtls_free_resource(sock);
ret = NET_ERROR_MBEDTLS_CRT_PARSE;
}
else
{
ret = mbedtls_pk_parse_key(&tlsData->pkey, (uchar_t const *)tlsData->tls_dev_key,
strlen((char_t const *)tlsData->tls_dev_key) + 1U,
(uchar_t const *)tlsData->tls_dev_pwd, tlsData->tls_dev_pwd_len);
if (ret != 0)
{
NET_DBG_ERROR(" failed\n ! mbedtls_pk_parse_key returned -0x%lx while parsing private key\n\n", -ret);
mbedtls_free_resource(sock);
ret = NET_ERROR_MBEDTLS_KEY_PARSE;
}
}
}
/* TLS Connection */
if (ret == NET_OK)
{
ret = mbedtls_ssl_config_defaults(&tlsData->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT);
if (ret != 0)
{
NET_DBG_ERROR(" failed\n ! mbedtls_ssl_config_defaults returned -0x%lx\n\n", -ret);
mbedtls_free_resource(sock);
ret = NET_ERROR_MBEDTLS_CONFIG;
}
}
if (ret == NET_OK)
{
/* Allow the user to select a TLS profile? */
if (tlsData->tls_cert_prof != NULL)
{
mbedtls_ssl_conf_cert_profile(&tlsData->conf, tlsData->tls_cert_prof);
}
/* Only for debug
* mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL); */
if (tlsData->tls_srv_verification == true)
{
mbedtls_ssl_conf_authmode(&tlsData->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
}
else
{
mbedtls_ssl_conf_authmode(&tlsData->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
}
/* no verification because no certificat */
/*
if (tlsData->tls_ca_certs == NULL)
{
mbedtls_ssl_conf_authmode(&tlsData->conf, MBEDTLS_SSL_VERIFY_NONE);
}
*/
/*cstat -MISRAC2012-Rule-11.1 */
mbedtls_ssl_conf_rng(&tlsData->conf, (mbedtls_rng_func_t) mbedtls_rng_raw, &hrng);
/*cstat +MISRAC2012-Rule-11.1 */
mbedtls_ssl_conf_ca_chain(&tlsData->conf, &tlsData->cacert, NULL);
if ((tlsData->tls_dev_cert != NULL) && (tlsData->tls_dev_key != NULL))
{
ret = mbedtls_ssl_conf_own_cert(&tlsData->conf, &tlsData->clicert, &tlsData->pkey);
if (ret != 0)
{
NET_DBG_ERROR(" failed\n ! mbedtls_ssl_conf_own_cert returned -0x%lx\n\n", -ret);
mbedtls_free_resource(sock);
ret = NET_ERROR_MBEDTLS_CONFIG;
}
}
}
if (ret == NET_OK)
{
ret = mbedtls_ssl_setup(&tlsData->ssl, &tlsData->conf);
if (ret != 0)
{
NET_DBG_ERROR(" failed\n ! mbedtls_ssl_setup returned -0x%lx\n\n", -ret);
mbedtls_free_resource(sock);
ret = NET_ERROR_MBEDTLS_SSL_SETUP;
}
}
if ((ret == NET_OK) && (tlsData->tls_srv_name != NULL))
{
ret = mbedtls_ssl_set_hostname(&tlsData->ssl, (char_t const *)tlsData->tls_srv_name);
if (ret != 0)
{
NET_DBG_ERROR(" failed\n ! mbedtls_ssl_set_hostname returned %ld\n\n", ret);
mbedtls_free_resource(sock);
ret = NET_ERROR_MBEDTLS_SET_HOSTNAME;
}
}
if (ret == NET_OK)
{
/*cstat -MISRAC2012-Rule-11.1 */
mbedtls_ssl_set_bio(&tlsData->ssl, sock, (mbedtls_ssl_send_t *) mbedtls_net_send, NULL,
(mbedtls_ssl_recv_timeout_t *) mbedtls_net_recv);
/*cstat +MISRAC2012-Rule-11.1 */
mbedtls_ssl_conf_read_timeout(&tlsData->conf, (uint32_t)sock->read_timeout);
NET_DBG_INFO("\n\nSSL state connect : %d ", sock->tlsData->ssl.state);
NET_DBG_INFO("\n\nSSL state connect : %d ", sock->tlsData->ssl.state);
NET_DBG_INFO(" . Performing the SSL/TLS handshake...");
ret = mbedtls_ssl_handshake(&tlsData->ssl);
start_tick = NET_TICK();
while (ret != 0)
{
uint32_t elapsed_tick = NET_TICK() - start_tick;
if (elapsed_tick > NET_MBEDTLS_CONNECT_TIMEOUT)
{
mbedtls_free_resource(sock);
ret = NET_ERROR_MBEDTLS_CONNECT;
break;
}
if ((ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE))
{
tlsData->flags = mbedtls_ssl_get_verify_result(&tlsData->ssl);
if (tlsData->flags != 0U)
{
char_t vrfy_buf[512];
(void) mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", tlsData->flags);
if (tlsData->tls_srv_verification == true)
{
NET_DBG_ERROR("Server verification:\n%s\n", vrfy_buf);
}
else
{
NET_DBG_INFO("Server verification:\n%s\n", vrfy_buf);
}
}
NET_DBG_ERROR(" failed\n ! mbedtls_ssl_handshake returned -0x%lx\n", -ret);
mbedtls_free_resource(sock);
ret = (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) ? NET_ERROR_MBEDTLS_REMOTE_AUTH : NET_ERROR_MBEDTLS_CONNECT;
/*cstat -MISRAC2012-Rule-15.4 */
break;
/*cstat +MISRAC2012-Rule-15.4 */
}
ret = mbedtls_ssl_handshake(&tlsData->ssl);
}
if (ret == NET_OK)
{
int32_t exp;
NET_DBG_INFO(" ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n",
mbedtls_ssl_get_version(&sock->tlsData->ssl),
mbedtls_ssl_get_ciphersuite(&sock->tlsData->ssl));
exp = mbedtls_ssl_get_record_expansion(&tlsData->ssl);
if (exp >= 0)
{
NET_DBG_INFO(" [ Record expansion is %d ]\n", exp);
}
else
{
NET_DBG_INFO(" [ Record expansion is unknown (compression) ]\n");
}
NET_DBG_INFO(" . Verifying peer X.509 certificate...");
#ifdef NET_DBG_INFO
#define NET_CERTIFICATE_DISPLAY_LEN 2048U
if (mbedtls_ssl_get_peer_cert(&sock->tlsData->ssl) != NULL)
{
/*cstat -MISRAC2012-Rule-11.5 -MISRAC2012-Rule-21.3 -MISRAC2012-Dir-4.12 */
char_t *buf = NET_MALLOC(sizeof(char_t) * NET_CERTIFICATE_DISPLAY_LEN);
/*cstat +MISRAC2012-Rule-11.5 +MISRAC2012-Rule-21.3 +MISRAC2012-Dir-4.12 */
if (buf != NULL)
{
NET_DBG_INFO(" . Peer certificate information ...\n");
(void) mbedtls_x509_crt_info(buf, NET_CERTIFICATE_DISPLAY_LEN - 1U, " ",
mbedtls_ssl_get_peer_cert(&sock->tlsData->ssl));
NET_DBG_INFO("%s\n", buf);
/*cstat -MISRAC2012-Rule-21.3 */
NET_FREE(buf);
/*cstat +MISRAC2012-Rule-21.3 */
}
else
{
NET_DBG_INFO(" . Cannot allocate memory to display certificate information ...\n");
}
}
#endif /* NET_DBG_INFO */
}
}
return ret;
}
int32_t net_mbedtls_sock_recv(net_socket_t *sock, uint8_t *buf, size_t len)
{
net_tls_data_t *tlsData = sock->tlsData;
int32_t ret;
ret = mbedtls_ssl_read(&tlsData->ssl, buf, len);
if (ret <= 0)
{
switch (ret)
{
case 0:
ret = NET_ERROR_DISCONNECTED;
break;
case MBEDTLS_ERR_SSL_TIMEOUT: /* In case a blocking read function was passed through mbedtls_ssl_set_bio() */
ret = NET_TIMEOUT;
break;
case MBEDTLS_ERR_SSL_WANT_READ:
ret = NET_TIMEOUT;
break;
default:
NET_DBG_ERROR(" failed\n ! mbedtls_ssl_read returned -0x%lx\n\n", -ret);
ret = NET_ERROR_MBEDTLS;
break;
}
}
return ret;
}
int32_t net_mbedtls_sock_send(net_socket_t *sock, const uint8_t *buf, size_t len)
{
int32_t ret;
net_tls_data_t *tlsData = sock->tlsData;
#if PERF
stat.mbedtls_send_cycle -= net_get_cycle();
#endif /* PERF */
ret = mbedtls_ssl_write(&tlsData->ssl, buf, len);
if (ret == 0)
{
ret = NET_ERROR_DISCONNECTED;
}
else if (ret < 0)
{
NET_DBG_ERROR(" failed\n ! mbedtls_ssl_write returned -0x%lx\n\n", -ret);
ret = NET_ERROR_MBEDTLS;
}
else
{
/* ret > 0 nothing to do , MISRA checks */
}
#if PERF
stat.mbedtls_send_cycle += net_get_cycle();
#endif /* PERF */
return (ret);
}
int32_t net_mbedtls_stop(net_socket_t *sock)
{
int32_t ret;
/* Closure notification is required by TLS if the session was not already closed by the remote host. */
net_tls_data_t *tlsData = sock->tlsData;
do
{
ret = mbedtls_ssl_close_notify(&tlsData->ssl);
} while ((ret == MBEDTLS_ERR_SSL_WANT_WRITE) || (ret == MBEDTLS_ERR_SSL_WANT_READ));
/* All other negative return values indicate connection needs to be reset.
* No further action required since this is disconnect call */
mbedtls_free_resource(sock);
return NET_OK;
}
static void mbedtls_free_resource(net_socket_t *sock)
{
net_tls_data_t *tlsData = sock->tlsData;
mbedtls_x509_crt_free(&tlsData->clicert);
mbedtls_pk_free(&tlsData->pkey);
mbedtls_x509_crt_free(&tlsData->cacert);
mbedtls_ssl_free(&tlsData->ssl);
mbedtls_ssl_config_free(&tlsData->conf);
/*cstat -MISRAC2012-Rule-21.3 */
NET_FREE(tlsData);
/*cstat +MISRAC2012-Rule-21.3 */
sock->tlsData = 0;
return;
}
/* received interface implementation.*/
static int32_t mbedtls_net_recv(void *ctx, uchar_t *buf, size_t len, uint32_t timeout)
{
int32_t ret = NET_OK;
int32_t flags = 0;
/*cstat -MISRAC2012-Rule-11.5 */
net_socket_t *pSocket = (net_socket_t *) ctx;
/*cstat +MISRAC2012-Rule-11.5 */
if (pSocket->read_timeout != (int32_t)timeout)
{
ret = pSocket->pnetif->pdrv->psetsockopt(pSocket->ulsocket,
NET_SOL_SOCKET, NET_SO_RCVTIMEO, &timeout, sizeof(uint32_t));
if (ret == NET_OK)
{
pSocket->read_timeout = (int32_t) timeout;
}
}
if (ret == NET_OK)
{
if (pSocket->read_timeout == 0)
{
flags = (int8_t) NET_MSG_DONTWAIT;
}
UNLOCK_SOCK(pSocket->idx);
ret = pSocket->pnetif->pdrv->precv(pSocket->ulsocket, buf, len, flags);
LOCK_SOCK(pSocket->idx);
if (ret <= 0)
{
switch (ret)
{
case 0:
ret = MBEDTLS_ERR_SSL_WANT_READ;
break;
case NET_TIMEOUT:
/* According to mbedtls headers, MBEDTLS_ERR_SSL_TIMEOUT should be returned. */
/* But it saturates the error log with false errors. By contrast, */
/* MBEDTLS_ERR_SSL_WANT_READ does not raise any error. */
ret = MBEDTLS_ERR_SSL_WANT_READ;
break;
default:
NET_DBG_ERROR("mbedtls_net_recv() : error %ld in recv() - requestedLen=%d\n", ret, len);
ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
break;
}
}
}
return ret;
}
static int32_t mbedtls_net_send(void *ctx, const uchar_t *buf, size_t len)
{
/*cstat -MISRAC2012-Rule-11.5 */
net_socket_t *pSocket = (net_socket_t *) ctx;
/*cstat +MISRAC2012-Rule-11.5 */
int32_t ret;
int32_t flags = 0;
if (pSocket->write_timeout == 0)
{
flags = (int8_t) NET_MSG_DONTWAIT;
}
UNLOCK_SOCK(pSocket->idx);
/*cstat -MISRAC2012-Rule-11.8 removing const attribute */
ret = pSocket->pnetif->pdrv->psend(pSocket->ulsocket, (uchar_t *) buf, len, flags);
/*cstat +MISRAC2012-Rule-11.8 */
LOCK_SOCK(pSocket->idx);
if (ret >= 0)
{
if (ret == 0)
{
ret = MBEDTLS_ERR_SSL_WANT_WRITE;
}
}
else
{
NET_DBG_ERROR("mbedtls_net_send(): error %ld in send() - requestedLen=%d\n", ret, len);
/* TODO: The underlying layers do not allow to distinguish between
* MBEDTLS_ERR_SSL_INTERNAL_ERROR,
* MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY,
* MBEDTLS_ERR_SSL_CONN_EOF.
* Most often, the error is due to the closure of the connection by the remote host. */
ret = MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY;
}
return ret;
}
#endif /* NET_MBEDTLS_HOST_SUPPORT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,187 @@
/**
******************************************************************************
* @file net_ping.c
* @author MCD Application Team
* @brief application to send icmp ping
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#include "net_connect.h"
#include "net_internals.h"
/*cstat -MISRAC* -DEFINE-* -CERT-EXP19* */
#include "lwip/tcpip.h"
#include "lwip/icmp.h"
#include "lwip/inet_chksum.h"
#include "lwip/api.h" /* HAL_GetTick() */
#include "lwip/ip4.h"
/*cstat +MISRAC* +DEFINE-* +CERT-EXP19* */
/* Private macro -------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** ping identifier - must fit on a u16_t */
#ifndef PING_ID
#define PING_ID 0xAFAF
#endif /* PING_ID */
/** ping additional data size to include in the packet */
#ifndef PING_DATA_SIZE
#define PING_DATA_SIZE 32
#endif /* PING_DATA_SIZE */
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
static void ping_prepare_echo(struct icmp_echo_hdr *iecho, uint16_t len, uint16_t ping_seq_num)
{
size_t i;
size_t data_len = len - sizeof(struct icmp_echo_hdr);
ICMPH_TYPE_SET(iecho, ICMP_ECHO);
ICMPH_CODE_SET(iecho, 0);
iecho->chksum = 0;
iecho->id = PING_ID;
iecho->seqno = (uint16_t) lwip_htons(ping_seq_num);
/* fill the additional data buffer with some data */
for (i = 0; i < data_len; i++)
{
((char_t *)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char_t)i;
}
/* Ping data are sent in RAM mode , so LWIP is not computing the checksum by SW */
#ifndef CHECKSUM_BY_HARDWARE
iecho->chksum = inet_chksum(iecho, len);
#endif /* CHECKSUM_BY_HARDWARE */
}
uint32_t sys_now(void);
#define NET_IPH_HL(hdr) ((hdr)->_v_hl & 0x0fU)
int32_t icmp_ping(net_if_handle_t *pnetif, net_sockaddr_t *addr, int32_t count, int32_t timeout, int32_t response[])
{
int32_t sock;
int32_t ret = 0;
uint32_t ping_start_time;
net_sockaddr_t from;
uint32_t fromlen;
int32_t len;
static int32_t ping_seq_num = 1;
char_t buf[64] = "";
struct ip_hdr *iphdr;
struct icmp_echo_hdr *iecho, *pecho = NULL;
size_t ping_size = sizeof(struct icmp_echo_hdr) + (uint32_t) PING_DATA_SIZE;
u16_t seqnum;
(void) pnetif;
sock = net_socket(NET_AF_INET, NET_SOCK_RAW, NET_IPPROTO_ICMP);
if (sock < 0)
{
NET_DBG_ERROR("ping: socket fail\r\n");
ret = -1;
}
else if (net_setsockopt(sock, NET_SOL_SOCKET, NET_SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0)
{
NET_DBG_ERROR("ping: setsockopt() fail\r\n");
ret = -1;
}
else
{
/*cstat -MISRAC2012-Rule-11.5 Malloc */
pecho = (struct icmp_echo_hdr *)mem_malloc((mem_size_t)ping_size);
/*cstat +MISRAC2012-Rule-11.5 */
if (pecho == NULL)
{
NET_DBG_ERROR("ping_client_process : message alloc fails\r\n");
ret = -1;
}
}
if (ret == 0)
{
addr->sa_family = NET_AF_INET;
net_set_port(addr, 0U);
for (int32_t i = 0; i < count; i++)
{
response[i] = -1;
/* add useless test for MISRA on pecho */
if (pecho != NULL)
{
ping_prepare_echo(pecho, (uint16_t) ping_size, (uint16_t) ping_seq_num);
}
if (net_sendto(sock, (uint8_t *)pecho, (int32_t) ping_size, 0, addr, (int32_t) sizeof(net_sockaddr_t)) < 0)
{
NET_DBG_INFO("ping_client_process : send fail\r\n");
break;
}
ping_start_time = sys_now();
do
{
len = net_recvfrom(sock, (uint8_t *)buf, (int32_t) ping_size, 0, &from, &fromlen);
if (len >= (int32_t)(sizeof(struct ip_hdr) + sizeof(struct icmp_echo_hdr)))
{
/*cstat -MISRAC2012-Rule-11.3 Cast */
iphdr = (struct ip_hdr *)buf;
iecho = (struct icmp_echo_hdr *)(buf + ((NET_IPH_HL(iphdr)) * 4U));
/*cstat +MISRAC2012-Rule-11.3 Cast */
seqnum = lwip_htons((uint16_t) ping_seq_num);
if ((iecho->id == (uint16_t)PING_ID) && (iecho->seqno == seqnum))
{
if (ICMPH_TYPE(iecho) == (uint8_t) ICMP_ER)
{
uint32_t delta;
ret = 0;
delta = sys_now() - ping_start_time;
response[i] = (int32_t) delta;
break;
}
else
{
NET_DBG_ERROR("ICMP Other Response received \r\n");
}
}
}
else
{
uint32_t now = sys_now();
NET_DBG_ERROR("no data start %ld : %lu .. %lu\r\n", len, ping_start_time, now);
}
} while (sys_now() < (ping_start_time + (uint32_t) timeout));
ping_seq_num++;
}
if (pecho != NULL)
{
mem_free(pecho);
}
(void) net_closesocket(sock);
}
return ret;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,62 @@
/**
******************************************************************************
* @file net_conf.c
* @author MCD Application Team
* @brief Implement cellular_probe() called to initialize the Cellular low level driver
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#include "net_connect.h"
/* Private functions ---------------------------------------------------------*/
int32_t cellular_probe(void **ll_drv_context);
int32_t cellular_probe(void **ll_drv_context)
{
return 0;
}
#ifdef GENERATOR_AWS_CLOUD
#include "mbedtls/x509_crt.h"
/*
* Amazon Profile
*/
const mbedtls_x509_crt_profile mbedtls_x509_crt_amazon_suite =
{
/* Only SHA-256 and 384 */
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384),
/* Only ECDSA */
MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_RSA) | /* */
MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECKEY) | /* */
MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECDSA),
#if defined(MBEDTLS_ECP_C)
/* Only NIST P-256 and P-384 */
MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) |
MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1),
#else
0,
#endif /* MBEDTLS_ECP_C */
2048
};
const int32_t net_tls_sizeof_suite_structure = sizeof(mbedtls_x509_crt_profile);
const void *net_tls_user_suite0 = (void *) &mbedtls_x509_crt_amazon_suite;
#endif /* GENERATOR_AWS_CLOUD */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,79 @@
/**
******************************************************************************
* @file net_conf.h
* @author MCD Application Team
* @brief This file provides the configuration for net
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#ifndef NET_CONF_H
#define NET_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
#define MDM_SIM_SELECT_0_Pin GPIO_PIN_2
#define MDM_SIM_SELECT_0_GPIO_Port GPIOC
#define MDM_SIM_SELECT_1_Pin GPIO_PIN_3
#define MDM_SIM_SELECT_1_GPIO_Port GPIOI
#define MDM_SIM_CLK_Pin GPIO_PIN_4
#define MDM_SIM_CLK_GPIO_Port GPIOA
#define MDM_SIM_DATA_Pin GPIO_PIN_12
#define MDM_SIM_DATA_GPIO_Port GPIOB
#define MDM_SIM_RST_Pin GPIO_PIN_7
#define MDM_SIM_RST_GPIO_Port GPIOC
#define MDM_PWR_EN_Pin GPIO_PIN_3
#define MDM_PWR_EN_GPIO_Port GPIOD
#define MDM_DTR_Pin GPIO_PIN_0
#define MDM_DTR_GPIO_Port GPIOA
#define MDM_RST_Pin GPIO_PIN_2
#define MDM_RST_GPIO_Port GPIOB
#define USART1_TX_Pin GPIO_PIN_6
#define USART1_TX_GPIO_Port GPIOB
#define UART1_RX_Pin GPIO_PIN_10
#define UART1_RX_GPIO_Port GPIOG
#define UART1_CTS_Pin GPIO_PIN_11
#define UART1_CTS_GPIO_Port GPIOG
#define UART1_RTS_Pin GPIO_PIN_12
#define UART1_RTS_GPIO_Port GPIOG
#define NET_USE_RTOS
#ifndef GENERATOR_WAKAAMACLIENT_CLOUD
#define NET_MBEDTLS_HOST_SUPPORT
#endif /* GENERATOR_WAKAAMACLIENT_CLOUD */
#include "net_conf_template.h"
#ifdef __cplusplus
}
#endif
#endif /* NET_CONF_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,834 @@
/**
******************************************************************************
* @file es_wifi_io.c
* @author MCD Application Team
* @brief This file implements the IO operations to deal with the es-wifi
* module. It mainly Inits and Deinits the SPI interface. Send and
* receive data over it.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#if defined(TARGET_STM32F413H_DISCOVERY)
#include "stm32f4xx_hal.h"
#define DATA_READY_IRQ EXTI15_10_IRQn
#endif /* TARGET_STM32F413H_DISCOVERY */
#if defined(TARGET_B_L475E_IOT01)
#include "stm32l4xx_hal.h"
#define DATA_READY_IRQ EXTI1_IRQn
#endif /* TARGET_B_L475E_IOT01 */
#if defined(TARGET_STM32H7B3I_DISCOVERY)
#include "stm32h7xx_hal.h"
#define DATA_READY_IRQ EXTI9_5_IRQn
#endif /* TARGET_STM32H7B3I_DISCOVERY */
#if defined(TARGET_STM32F413H_DISCOVERY) || defined(TARGET_B_L475E_IOT01)
#include <core_cm4.h>
#endif /* TARGET_STM32F413H_DISCOVERY || TARGET_B_L475E_IOT01 */
#if defined(TARGET_STM32H7B3I_DISCOVERY)
#include <core_cm7.h>
#endif /* TARGET_STM32H7B3I_DISCOVERY */
#include <string.h>
#include "es_wifi.h"
#include "es_wifi_conf.h"
#include "net_conf.h"
#ifdef GENERATOR_AWS_CLOUD
#include "mbedtls/x509_crt.h"
#endif /* GENERATOR_AWS_CLOUD */
/* Global variables --------------------------------------------------------*/
SPI_HandleTypeDef hspi;
/* Function definitions --------------------------------------------------------*/
static void SPI_WIFI_MspInit(SPI_HandleTypeDef *hspi);
/* Private define ------------------------------------------------------------*/
#if defined(TARGET_STM32F413H_DISCOVERY)
#define WIFI_RESET_MODULE() do{\
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_1, GPIO_PIN_RESET);\
HAL_Delay(10);\
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_1, GPIO_PIN_SET);\
HAL_Delay(500);\
}while(0);
#define WIFI_ENABLE_NSS() do{ \
HAL_GPIO_WritePin( GPIOG, GPIO_PIN_11, GPIO_PIN_RESET );\
}while(0);
#define WIFI_DISABLE_NSS() do{ \
HAL_GPIO_WritePin( GPIOG, GPIO_PIN_11, GPIO_PIN_SET );\
}while(0);
#define WIFI_IS_CMDDATA_READY() (HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_12) == GPIO_PIN_SET)
#endif /* TARGET_STM32F413H_DISCOVERY */
#if defined(TARGET_B_L475E_IOT01)
#define WIFI_RESET_MODULE() do{\
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_8, GPIO_PIN_RESET);\
HAL_Delay(10);\
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_8, GPIO_PIN_SET);\
HAL_Delay(500);\
}while(0);
#define WIFI_ENABLE_NSS() do{ \
HAL_GPIO_WritePin( GPIOE, GPIO_PIN_0, GPIO_PIN_RESET );\
}while(0);
#define WIFI_DISABLE_NSS() do{ \
HAL_GPIO_WritePin( GPIOE, GPIO_PIN_0, GPIO_PIN_SET );\
}while(0);
#define WIFI_IS_CMDDATA_READY() (HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_1) == GPIO_PIN_SET)
#endif /* TARGET_B_L475E_IOT01 */
#if defined(TARGET_STM32H7B3I_DISCOVERY)
#define WIFI_RESET_MODULE() do{\
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_1, GPIO_PIN_RESET);\
HAL_Delay(10);\
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_1, GPIO_PIN_SET);\
HAL_Delay(500);\
}while(0);
#define WIFI_ENABLE_NSS() do{ \
HAL_GPIO_WritePin( GPIOA, GPIO_PIN_11, GPIO_PIN_RESET );\
}while(0);
#define WIFI_DISABLE_NSS() do{ \
HAL_GPIO_WritePin( GPIOA, GPIO_PIN_11, GPIO_PIN_SET );\
}while(0);
#define WIFI_IS_CMDDATA_READY() (HAL_GPIO_ReadPin(GPIOI, GPIO_PIN_5) == GPIO_PIN_SET)
#define SPI_INTERFACE_PRIO 0
#endif /* TARGET_STM32H7B3I_DISCOVERY */
/* Private typedef -----------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static int32_t __IO spi_rx_event = 0;
static int32_t __IO spi_tx_event = 0;
static int32_t __IO cmddata_rdy_rising_event = 0;
#ifdef WIFI_USE_CMSIS_OS
osMutexId es_wifi_mutex;
osMutexDef(es_wifi_mutex);
static osMutexId spi_mutex;
osMutexDef(spi_mutex);
static osSemaphoreId spi_rx_sem;
osSemaphoreDef(spi_rx_sem);
static osSemaphoreId spi_tx_sem;
osSemaphoreDef(spi_tx_sem);
static osSemaphoreId cmddata_rdy_rising_sem;
osSemaphoreDef(cmddata_rdy_rising_sem);
#endif /* WIFI_USE_CMSIS_OS */
/* Private function prototypes -----------------------------------------------*/
static int32_t wait_cmddata_rdy_high(int32_t timeout);
static int32_t wait_cmddata_rdy_rising_event(int32_t timeout);
static int32_t wait_spi_tx_event(int32_t timeout);
static int32_t wait_spi_rx_event(int32_t timeout);
static void SPI_WIFI_DelayUs(uint32_t);
static int8_t SPI_WIFI_DeInit(void);
static int8_t SPI_WIFI_Init(uint16_t mode);
static int8_t SPI_WIFI_ResetModule(void);
static int16_t SPI_WIFI_ReceiveData(uint8_t *pData, uint16_t len, uint32_t timeout);
static int16_t SPI_WIFI_SendData(uint8_t *pData, uint16_t len, uint32_t timeout);
/* Private functions ---------------------------------------------------------*/
#ifdef GENERATOR_AWS_CLOUD
/*
* Amazon Profile
*/
const mbedtls_x509_crt_profile mbedtls_x509_crt_amazon_suite =
{
/* Only SHA-256 and 384 */
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384),
/* Only ECDSA */
MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_RSA) | /* */
MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECKEY) | /* */
MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECDSA),
#if defined(MBEDTLS_ECP_C)
/* Only NIST P-256 and P-384 */
MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) |
MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1),
#else
0,
#endif /* MBEDTLS_ECP_C */
2048
};
const int32_t net_tls_sizeof_suite_structure = sizeof(mbedtls_x509_crt_profile);
const void *net_tls_user_suite0 = (void *) &mbedtls_x509_crt_amazon_suite;
#endif /* GENERATOR_AWS_CLOUD */
int32_t wifi_probe(void **ll_drv_context);
ES_WIFIObject_t EsWifiObj;
/*******************************************************************************
COM Driver Interface (SPI)
*******************************************************************************/
/**
* @brief Initialize SPI MSP
* @param hspi: SPI handle
* @retval None
*/
static void SPI_WIFI_MspInit(SPI_HandleTypeDef *hspi)
{
GPIO_InitTypeDef GPIO_Init;
#if defined(TARGET_STM32F413H_DISCOVERY)
__HAL_RCC_SPI3_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
/* configure Wake up pin */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, GPIO_PIN_RESET);
GPIO_Init.Pin = GPIO_PIN_15;
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_Init);
/* configure Data ready pin */
GPIO_Init.Pin = GPIO_PIN_12;
GPIO_Init.Mode = GPIO_MODE_IT_RISING;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOG, &GPIO_Init);
/* configure Reset pin */
GPIO_Init.Pin = GPIO_PIN_1;
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_Init.Alternate = 0;
HAL_GPIO_Init(GPIOH, &GPIO_Init);
/* configure SPI NSS pin pin */
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_11, GPIO_PIN_SET);
GPIO_Init.Pin = GPIO_PIN_11;
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM;
HAL_GPIO_Init(GPIOG, &GPIO_Init);
/* configure SPI CLK pin */
GPIO_Init.Pin = GPIO_PIN_12;
GPIO_Init.Mode = GPIO_MODE_AF_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_Init.Alternate = GPIO_AF7_SPI3;
HAL_GPIO_Init(GPIOB, &GPIO_Init);
/* configure SPI MOSI pin */
GPIO_Init.Pin = GPIO_PIN_5;
GPIO_Init.Mode = GPIO_MODE_AF_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_Init.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOB, &GPIO_Init);
/* configure SPI MISO pin */
GPIO_Init.Pin = GPIO_PIN_4;
GPIO_Init.Mode = GPIO_MODE_AF_PP;
GPIO_Init.Pull = GPIO_PULLUP;
GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_Init.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOB, &GPIO_Init);
#endif /* TARGET_STM32F413H_DISCOVERY */
#if defined(TARGET_B_L475E_IOT01)
__HAL_RCC_SPI3_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
/* configure Wake up pin */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);
GPIO_Init.Pin = GPIO_PIN_13;
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_Init);
/* configure Data ready pin */
GPIO_Init.Pin = GPIO_PIN_1;
GPIO_Init.Mode = GPIO_MODE_IT_RISING;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_Init);
/* configure Reset pin */
GPIO_Init.Pin = GPIO_PIN_8;
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_Init.Alternate = 0;
HAL_GPIO_Init(GPIOE, &GPIO_Init);
/* configure SPI NSS pin pin */
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_0, GPIO_PIN_SET);
GPIO_Init.Pin = GPIO_PIN_0;
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM;
HAL_GPIO_Init(GPIOE, &GPIO_Init);
/* configure SPI CLK pin */
GPIO_Init.Pin = GPIO_PIN_10;
GPIO_Init.Mode = GPIO_MODE_AF_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_Init.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOC, &GPIO_Init);
/* configure SPI MOSI pin */
GPIO_Init.Pin = GPIO_PIN_12;
GPIO_Init.Mode = GPIO_MODE_AF_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_Init.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOC, &GPIO_Init);
/* configure SPI MISO pin */
GPIO_Init.Pin = GPIO_PIN_11;
GPIO_Init.Mode = GPIO_MODE_AF_PP;
GPIO_Init.Pull = GPIO_PULLUP;
GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_Init.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOC, &GPIO_Init);
#endif /* TARGET_B_L475E_IOT01 */
#if defined(TARGET_STM32H7B3I_DISCOVERY)
__HAL_RCC_SPI2_CLK_ENABLE();
__HAL_RCC_SPI2_FORCE_RESET();
__HAL_RCC_SPI2_RELEASE_RESET();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOI_CLK_ENABLE();
/* configure Wake up pin */
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_2, GPIO_PIN_RESET);
GPIO_Init.Pin = GPIO_PIN_2;
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM;
HAL_GPIO_Init(GPIOI, &GPIO_Init);
/* configure Data ready pin */
GPIO_Init.Pin = GPIO_PIN_5;
GPIO_Init.Mode = GPIO_MODE_IT_RISING;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOI, &GPIO_Init);
/* configure Reset pin */
GPIO_Init.Pin = GPIO_PIN_1;
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_Init.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOI, &GPIO_Init);
/* configure SPI NSS pin pin */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_SET);
GPIO_Init.Pin = GPIO_PIN_11;
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM;
HAL_GPIO_Init(GPIOA, &GPIO_Init);
/* configure SPI CLK pin */
GPIO_Init.Pin = GPIO_PIN_12;
GPIO_Init.Mode = GPIO_MODE_AF_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_Init.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOA, &GPIO_Init);
/* configure SPI MOSI pin */
GPIO_Init.Pin = GPIO_PIN_3;
GPIO_Init.Mode = GPIO_MODE_AF_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_Init.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC, &GPIO_Init);
/* configure SPI MISO pin */
GPIO_Init.Pin = GPIO_PIN_2;
GPIO_Init.Mode = GPIO_MODE_AF_PP;
GPIO_Init.Pull = GPIO_PULLUP;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_Init.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC, &GPIO_Init);
#endif /* TARGET_STM32H7B3I_DISCOVERY */
}
#if defined(TARGET_STM32F413H_DISCOVERY) || defined(TARGET_B_L475E_IOT01)
/**
* @brief Initialize the SPI3
* @param None
* @retval None
*/
#endif /* TARGET_STM32F413H_DISCOVERY || TARGET_B_L475E_IOT01 */
#if defined(TARGET_STM32H7B3I_DISCOVERY)
/**
* @brief Initialize the SPI2
* @param None
* @retval None
*/
#endif /* TARGET_STM32H7B3I_DISCOVERY */
static int8_t SPI_WIFI_Init(uint16_t mode)
{
int8_t rc = 0;
if (mode == ES_WIFI_INIT)
{
#if defined(TARGET_STM32F413H_DISCOVERY) || defined(TARGET_B_L475E_IOT01)
hspi.Instance = SPI3;
#endif /* TARGET_STM32F413H_DISCOVERY || TARGET_B_L475E_IOT01 */
#if defined(TARGET_STM32H7B3I_DISCOVERY)
hspi.Instance = SPI2;
#endif /* TARGET_STM32H7B3I_DISCOVERY */
SPI_WIFI_MspInit(&hspi);
hspi.Init.Mode = SPI_MODE_MASTER;
hspi.Init.Direction = SPI_DIRECTION_2LINES;
hspi.Init.DataSize = SPI_DATASIZE_16BIT;
hspi.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi.Init.NSS = SPI_NSS_SOFT;
hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; /* 80/8= 10MHz (Inventek WIFI module supports up to 20MHz)*/
hspi.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi.Init.TIMode = SPI_TIMODE_DISABLE;
hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi.Init.CRCPolynomial = 0;
if (HAL_SPI_Init(&hspi) != HAL_OK)
{
return -1;
}
/* Enable Interrupt for Data Ready pin , GPIO_PIN1 */
HAL_NVIC_SetPriority((IRQn_Type)DATA_READY_IRQ, SPI_INTERFACE_PRIO, 0x00);
HAL_NVIC_EnableIRQ((IRQn_Type)DATA_READY_IRQ);
/* Enable Interrupt for SPI tx and rx */
#if defined(TARGET_STM32F413H_DISCOVERY) || defined(TARGET_B_L475E_IOT01)
HAL_NVIC_SetPriority((IRQn_Type)SPI3_IRQn, SPI_INTERFACE_PRIO, 0);
HAL_NVIC_EnableIRQ((IRQn_Type)SPI3_IRQn);
#endif /* TARGET_STM32F413H_DISCOVERY || TARGET_B_L475E_IOT01 */
#if defined(TARGET_STM32H7B3I_DISCOVERY)
HAL_NVIC_SetPriority((IRQn_Type)SPI2_IRQn, SPI_INTERFACE_PRIO, 0);
HAL_NVIC_EnableIRQ((IRQn_Type)SPI2_IRQn);
#endif /* TARGET_STM32H7B3I_DISCOVERY */
#ifdef WIFI_USE_CMSIS_OS
cmddata_rdy_rising_event = 0;
es_wifi_mutex = osMutexCreate(osMutex(es_wifi_mutex));
spi_mutex = osMutexCreate(osMutex(spi_mutex));
spi_rx_sem = osSemaphoreCreate(osSemaphore(spi_rx_sem), 1);
spi_tx_sem = osSemaphoreCreate(osSemaphore(spi_tx_sem), 1);
cmddata_rdy_rising_sem = osSemaphoreCreate(osSemaphore(cmddata_rdy_rising_sem), 1);
/* take semaphore */
SEM_WAIT(cmddata_rdy_rising_sem, 1);
SEM_WAIT(spi_rx_sem, 1);
SEM_WAIT(spi_tx_sem, 1);
#endif /* WIFI_USE_CMSIS_OS */
/* first call used for calibration */
SPI_WIFI_DelayUs(10);
}
rc = SPI_WIFI_ResetModule();
return rc;
}
static int8_t SPI_WIFI_ResetModule(void)
{
uint32_t tickstart = HAL_GetTick();
uint8_t Prompt[6];
uint8_t count = 0;
HAL_StatusTypeDef Status;
WIFI_RESET_MODULE();
WIFI_ENABLE_NSS();
SPI_WIFI_DelayUs(15);
while (WIFI_IS_CMDDATA_READY())
{
Status = HAL_SPI_Receive(&hspi, &Prompt[count], 1, 0xFFFF);
count += 2;
if (((HAL_GetTick() - tickstart) > 0xFFFF) || (Status != HAL_OK))
{
WIFI_DISABLE_NSS();
return -1;
}
}
WIFI_DISABLE_NSS();
if ((Prompt[0] != 0x15) || (Prompt[1] != 0x15) || (Prompt[2] != '\r') ||
(Prompt[3] != '\n') || (Prompt[4] != '>') || (Prompt[5] != ' '))
{
return -1;
}
return 0;
}
/**
* @brief DeInitialize the SPI
* @param None
* @retval None
*/
static int8_t SPI_WIFI_DeInit(void)
{
HAL_SPI_DeInit(&hspi);
#ifdef WIFI_USE_CMSIS_OS
osMutexDelete(spi_mutex);
osMutexDelete(es_wifi_mutex);
osSemaphoreDelete(spi_tx_sem);
osSemaphoreDelete(spi_rx_sem);
osSemaphoreDelete(cmddata_rdy_rising_sem);
#endif /* WIFI_USE_CMSIS_OS */
return 0;
}
/**
* @brief Receive wifi Data from SPI
* @param pdata : pointer to data
* @param len : Data length
* @param timeout : send timeout in mS
* @retval Length of received data (payload)
*/
int32_t wait_cmddata_rdy_high(int32_t timeout)
{
int32_t tickstart = HAL_GetTick();
while (WIFI_IS_CMDDATA_READY() == 0)
{
if ((HAL_GetTick() - tickstart) > timeout)
{
return -1;
}
}
return 0;
}
int32_t wait_cmddata_rdy_rising_event(int32_t timeout)
{
#ifdef SEM_WAIT
return SEM_WAIT(cmddata_rdy_rising_sem, timeout);
#else
int32_t tickstart = HAL_GetTick();
while (cmddata_rdy_rising_event == 1)
{
if ((HAL_GetTick() - tickstart) > timeout)
{
return -1;
}
}
return 0;
#endif /* SEM_WAIT */
}
int32_t wait_spi_rx_event(int32_t timeout)
{
#ifdef SEM_WAIT
return SEM_WAIT(spi_rx_sem, timeout);
#else
int32_t tickstart = HAL_GetTick();
while (spi_rx_event == 1)
{
if ((HAL_GetTick() - tickstart) > timeout)
{
return -1;
}
}
return 0;
#endif /* SEM_WAIT */
}
int32_t wait_spi_tx_event(int32_t timeout)
{
#ifdef SEM_WAIT
return SEM_WAIT(spi_tx_sem, timeout);
#else
int32_t tickstart = HAL_GetTick();
while (spi_tx_event == 1)
{
if ((HAL_GetTick() - tickstart) > timeout)
{
return -1;
}
}
return 0;
#endif /* SEM_WAIT */
}
int16_t SPI_WIFI_ReceiveData(uint8_t *pData, uint16_t len, uint32_t timeout)
{
int16_t length = 0;
uint8_t tmp[2];
WIFI_DISABLE_NSS();
UNLOCK_SPI();
SPI_WIFI_DelayUs(3);
if (wait_cmddata_rdy_rising_event(timeout) < 0)
{
return ES_WIFI_ERROR_WAITING_DRDY_FALLING;
}
LOCK_SPI();
WIFI_ENABLE_NSS();
SPI_WIFI_DelayUs(15);
while (WIFI_IS_CMDDATA_READY())
{
if ((length < len) || (!len))
{
spi_rx_event = 1;
if (HAL_SPI_Receive_IT(&hspi, tmp, 1) != HAL_OK)
{
WIFI_DISABLE_NSS();
UNLOCK_SPI();
return ES_WIFI_ERROR_SPI_FAILED;
}
wait_spi_rx_event(timeout);
pData[0] = tmp[0];
pData[1] = tmp[1];
length += 2;
pData += 2;
if (length >= ES_WIFI_DATA_SIZE)
{
WIFI_DISABLE_NSS();
SPI_WIFI_ResetModule();
UNLOCK_SPI();
return ES_WIFI_ERROR_STUFFING_FOREVER;
}
}
else
{
break;
}
}
WIFI_DISABLE_NSS();
UNLOCK_SPI();
return length;
}
/**
* @brief Send wifi Data thru SPI
* @param pdata : pointer to data
* @param len : Data length
* @param timeout : send timeout in mS
* @retval Length of sent data
*/
int16_t SPI_WIFI_SendData(uint8_t *pdata, uint16_t len, uint32_t timeout)
{
uint8_t Padding[2];
if (wait_cmddata_rdy_high(timeout) < 0)
{
return ES_WIFI_ERROR_SPI_FAILED;
}
/* arm to detect rising event */
cmddata_rdy_rising_event = 1;
LOCK_SPI();
WIFI_ENABLE_NSS();
SPI_WIFI_DelayUs(15);
if (len > 1)
{
spi_tx_event = 1;
if (HAL_SPI_Transmit_IT(&hspi, (uint8_t *)pdata, len / 2) != HAL_OK)
{
WIFI_DISABLE_NSS();
UNLOCK_SPI();
return ES_WIFI_ERROR_SPI_FAILED;
}
wait_spi_tx_event(timeout);
}
if (len & 1)
{
Padding[0] = pdata[len - 1];
Padding[1] = '\n';
spi_tx_event = 1;
if (HAL_SPI_Transmit_IT(&hspi, Padding, 1) != HAL_OK)
{
WIFI_DISABLE_NSS();
UNLOCK_SPI();
return ES_WIFI_ERROR_SPI_FAILED;
}
wait_spi_tx_event(timeout);
}
return len;
}
/**
* @brief Delay
* @param Delay in us
* @retval None
*/
void SPI_WIFI_DelayUs(uint32_t n)
{
__IO uint32_t ct = 0;
uint32_t loop_per_us = 0;
static uint32_t cycle_per_loop = 0;
/* calibration happen on first call for a duration of 1 ms * nbcycle per loop */
/* 10 cycle for STM32L4 */
if (cycle_per_loop == 0)
{
uint32_t cycle_per_ms = (SystemCoreClock / 1000UL);
uint32_t tick = 0;
ct = cycle_per_ms;
tick = HAL_GetTick();
while (ct)
{
ct--;
}
cycle_per_loop = HAL_GetTick() - tick;
if (cycle_per_loop == 0)
{
cycle_per_loop = 1;
}
}
loop_per_us = SystemCoreClock / 1000000UL / cycle_per_loop;
ct = n * loop_per_us;
while (ct)
{
ct--;
}
return;
}
/**
* @brief Rx Transfer completed callback.
* @param hspi: pointer to a SPI_HandleTypeDef structure that contains
* the configuration information for SPI module.
* @retval None
*/
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
if (spi_rx_event)
{
SEM_SIGNAL(spi_rx_sem);
spi_rx_event = 0;
}
}
/**
* @brief Tx Transfer completed callback.
* @param hspi: pointer to a SPI_HandleTypeDef structure that contains
* the configuration information for SPI module.
* @retval None
*/
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
if (spi_tx_event)
{
SEM_SIGNAL(spi_tx_sem);
spi_tx_event = 0;
}
}
/**
* @brief Interrupt handler for Data RDY signal
* @param None
* @retval None
*/
void SPI_WIFI_ISR(void)
{
if (cmddata_rdy_rising_event == 1)
{
SEM_SIGNAL(cmddata_rdy_rising_sem);
cmddata_rdy_rising_event = 0;
}
}
/**
* @brief probe function to register wifi to Network library framework
* @param None
* @retval None
*/
int32_t wifi_probe(void **ll_drv_context)
{
if (ES_WIFI_RegisterBusIO(&EsWifiObj,
SPI_WIFI_Init,
SPI_WIFI_DeInit,
HAL_Delay,
SPI_WIFI_SendData,
SPI_WIFI_ReceiveData) == 0)
{
*ll_drv_context = &EsWifiObj;
return 0;
}
return -1;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,53 @@
/**
******************************************************************************
* @file net_conf.h
* @author MCD Application Team
* @brief This file provides the configuration for net
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#ifndef NET_CONF_H
#define NET_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef GENERATOR_WAKAAMACLIENT_CLOUD
#define NET_MBEDTLS_HOST_SUPPORT
#endif /* GENERATOR_WAKAAMACLIENT_CLOUD */
#include "net_conf_template.h"
/* to use Inventek Wifi native TLS */
#if 0
#undef NET_MBEDTLS_HOST_SUPPORT
#define NET_MBEDTLS_WIFI_MODULE_SUPPORT
#endif /* 9 */
int32_t wifi_probe(void **ll_drv_obj);
void SPI_WIFI_ISR(void);
#ifdef __cplusplus
}
#endif
#endif /* NET_CONF_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,709 @@
/**
******************************************************************************
* @file LwIP/LwIP_TCP_Echo_Client/Src/ethernetif.c
* @author MCD Application Team
* @brief This file implements Ethernet network interface drivers for lwIP
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32h7xx_hal.h"
#include "stm32h7xx_ll_utils.h"
#include "lwip/opt.h"
#include "lwip/timeouts.h"
#include "lwip/netif.h"
#include "lwip/tcpip.h"
#include "netif/etharp.h"
#include "ethernetif.h"
#include "net_connect.h"
#include "net_buffers.h"
#define GENERATOR_WAKAAMACLIENT_CLOUD
#ifdef NET_ETHERNET_MAC_GENERATION_FROM_MBEDTLS
#include "mbedtls/sha256.h"
#endif /* NET_ETHERNET_MAC_GENERATION_FROM_MBEDTLS */
#include "../Components/lan8742/lan8742.h"
#include <string.h>
err_t ethernetif_init(struct netif *netif);
void ethernetif_input(struct netif *netif);
void ethernet_link_check_state(struct netif *netif);
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#if (osCMSIS >= 0x20000U)
#define OSSEMAPHOREWAIT osSemaphoreAcquire
#else
#define OSSEMAPHOREWAIT osSemaphoreWait
#endif /* osCMSIS */
/* Network interface name */
#define IFNAME0 's'
#define IFNAME1 't'
#define ETH_RX_BUFFER_SIZE (1536UL)
#define ETH_DMA_TRANSMIT_TIMEOUT (20U)
/* Stack size of the interface thread */
#define INTERFACE_THREAD_STACK_SIZE 1024
#define TIME_WAITING_FOR_INPUT ( 250 ) /*( portMAX_DELAY )*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/*
@Note: This interface is implemented to operate in zero-copy mode only:
- Rx buffers are allocated statically and passed directly to the LwIP stack
they will return back to DMA after been processed by the stack.
- Tx Buffers will be allocated from LwIP stack memory heap,
then passed to ETH HAL driver.
@Notes:
1.a. ETH DMA Rx descriptors must be contiguous, the default count is 4,
to customize it please redefine ETH_RX_DESC_CNT in stm32xxxx_hal_conf.h
1.b. ETH DMA Tx descriptors must be contiguous, the default count is 4,
to customize it please redefine ETH_TX_DESC_CNT in stm32xxxx_hal_conf.h
2.a. Rx Buffers number must be between ETH_RX_DESC_CNT and 2*ETH_RX_DESC_CNT
2.b. Rx Buffers must have the same size: ETH_RX_BUFFER_SIZE, this value must
passed to ETH DMA in the init field (EthHandle.Init.RxBuffLen)
*/
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma location=0x30040000
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
#pragma location=0x30040060
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
#pragma location=0x30040200
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffers */
#elif defined ( __CC_ARM ) /* MDK ARM Compiler */
__attribute__((section(".RxDecripSection"))) ETH_DMADescTypeDef
DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
__attribute__((section(".TxDecripSection"))) ETH_DMADescTypeDef
DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
__attribute__((section(".RxArraySection"))) uint8_t
Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffer */
#elif defined ( __GNUC__ ) /* GNU Compiler */
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((
section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT
__attribute__((section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE] __attribute__((
section(".RxArraySection"))); /* Ethernet Receive Buffers */
#endif /* __ICCARM__ */
/* Semaphore to signal incoming packets */
static osSemaphoreId s_xSemaphore = NULL;
static osThreadId ethernetif_thread_handle = NULL;
static void ethernetif_task(void *context);
#if (osCMSIS >= 0x20000U )
static const osThreadAttr_t attr =
{
.name = "EthIf",
.priority = osPriorityHigh,
. stack_size = INTERFACE_THREAD_STACK_SIZE
};
#endif /* osCMSIS */
ETH_HandleTypeDef EthHandle;
ETH_TxPacketConfig TxConfig;
lan8742_Object_t LAN8742;
/* Private function prototypes -----------------------------------------------*/
u32_t sys_now(void);
void pbuf_free_custom(struct pbuf *p);
int32_t ETH_PHY_IO_Init(void);
int32_t ETH_PHY_IO_DeInit(void);
int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal);
int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal);
int32_t ETH_PHY_IO_GetTick(void);
lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init,
ETH_PHY_IO_DeInit,
ETH_PHY_IO_WriteReg,
ETH_PHY_IO_ReadReg,
ETH_PHY_IO_GetTick
};
LWIP_MEMPOOL_DECLARE(RX_POOL, 10, sizeof(struct pbuf_custom), "Zero-copy RX PBUF pool");
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
LL Driver Interface ( LwIP stack --> ETH)
*******************************************************************************/
/**
* @brief In this function, the hardware should be initialized.
* Called from ethernetif_init().
*
* @param netif the already initialized lwip network interface structure
* for this ethernetif
*/
static void low_level_init(struct netif *netif)
{
uint32_t idx = 0;
uint8_t macaddress[6] = {ETH_MAC_ADDR0, ETH_MAC_ADDR1, ETH_MAC_ADDR2, ETH_MAC_ADDR3, ETH_MAC_ADDR4, ETH_MAC_ADDR5};
/* Generate an MCU-unique MAC address */
#ifdef NET_ETHERNET_MAC_GENERATION_FROM_MBEDTLS
#define HASH_OUTPUT_LENGTH 32
unsigned char output[HASH_OUTPUT_LENGTH];
uint32_t UID[3];
/* Generate a hash digest from the unique CPU ID */
UID[0] = LL_GetUID_Word0();
UID[1] = LL_GetUID_Word1();
UID[2] = LL_GetUID_Word2();
/* Hash with mbedTLS */
int32_t hash_success = 0;
mbedtls_sha256_context sha_context;
mbedtls_sha256_init(&sha_context);
if (0 == mbedtls_sha256_starts_ret(&sha_context, 0))
{
if (0 == mbedtls_sha256_update_ret(&sha_context, (const unsigned char *) UID, sizeof(UID)))
{
if (0 == mbedtls_sha256_finish_ret(&sha_context, output))
{
hash_success = 1;
}
}
}
mbedtls_sha256_free(&sha_context);
while (hash_success == 0)
{
;
}
/* Copy the 3 first bytes of the digest to the second half of the MAC address. */
memcpy(&macaddress[3], output, 3);
#endif /* NET_ETHERNET_MAC_GENERATION_FROM_MBEDTLS */
EthHandle.Instance = ETH;
EthHandle.Init.MACAddr = macaddress;
EthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE;
EthHandle.Init.RxDesc = DMARxDscrTab;
EthHandle.Init.TxDesc = DMATxDscrTab;
EthHandle.Init.RxBuffLen = ETH_RX_BUFFER_SIZE;
/* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
HAL_ETH_Init(&EthHandle);
/* set MAC hardware address length */
netif->hwaddr_len = ETHARP_HWADDR_LEN;
/* set MAC hardware address */
for (uint32_t i = 0; i < sizeof(macaddress) / sizeof(uint8_t); i++)
{
netif->hwaddr[i] = macaddress[i];
}
/* maximum transfer unit */
netif->mtu = ETH_MAX_PAYLOAD;
/* device capabilities */
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
for (idx = 0; idx < ETH_RX_DESC_CNT; idx ++)
{
HAL_ETH_DescAssignMemory(&EthHandle, idx, Rx_Buff[idx], NULL);
}
/* Initialize the RX POOL */
LWIP_MEMPOOL_INIT(RX_POOL);
/* Set Tx packet config common parameters */
memset(&TxConfig, 0, sizeof(ETH_TxPacketConfig));
TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
/* Set PHY IO functions */
LAN8742_RegisterBusIO(&LAN8742, &LAN8742_IOCtx);
/* Initialize the LAN8742 ETH PHY */
LAN8742_Init(&LAN8742);
ethernet_link_check_state(netif);
}
/**
* @brief This function should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf
* might be chained.
*
* @param netif the lwip network interface structure for this ethernetif
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
* @return ERR_OK if the packet could be sent
* an err_t value if the packet couldn't be sent
*
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
* strange results. You might consider waiting for space in the DMA queue
* to become availale since the stack doesn't retry to send a packet
* dropped because of memory failure (except for the TCP timers).
*/
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
uint32_t i = 0;
uint32_t framelen = 0;
struct pbuf *q;
err_t errval = ERR_OK;
ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT];
memset(Txbuffer, 0, ETH_TX_DESC_CNT * sizeof(ETH_BufferTypeDef));
for (q = p; q != NULL; q = q->next)
{
if (i >= ETH_TX_DESC_CNT)
{
return ERR_IF;
}
Txbuffer[i].buffer = q->payload;
Txbuffer[i].len = q->len;
framelen += q->len;
if (i > 0)
{
Txbuffer[i - 1].next = &Txbuffer[i];
}
if (q->next == NULL)
{
Txbuffer[i].next = NULL;
}
i++;
}
TxConfig.Length = framelen;
TxConfig.TxBuffer = Txbuffer;
HAL_ETH_Transmit(&EthHandle, &TxConfig, ETH_DMA_TRANSMIT_TIMEOUT);
return errval;
}
/**
* @brief Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf.
*
* @param netif the lwip network interface structure for this ethernetif
* @return a pbuf filled with the received packet (including MAC header)
* NULL on memory error
*/
static struct pbuf *low_level_input(struct netif *netif)
{
struct pbuf *p = NULL;
ETH_BufferTypeDef RxBuff;
uint32_t framelength = 0;
struct pbuf_custom *custom_pbuf;
if (HAL_ETH_IsRxDataAvailable(&EthHandle))
{
HAL_ETH_GetRxDataBuffer(&EthHandle, &RxBuff);
HAL_ETH_GetRxDataLength(&EthHandle, &framelength);
/* Build Rx descriptor to be ready for next data reception */
HAL_ETH_BuildRxDescriptors(&EthHandle);
/* Invalidate data cache for ETH Rx Buffers */
SCB_InvalidateDCache_by_Addr((uint32_t *)RxBuff.buffer, framelength);
custom_pbuf = (struct pbuf_custom *)LWIP_MEMPOOL_ALLOC(RX_POOL);
custom_pbuf->custom_free_function = pbuf_free_custom;
p = pbuf_alloced_custom(PBUF_RAW, framelength, PBUF_REF, custom_pbuf, RxBuff.buffer, ETH_RX_BUFFER_SIZE);
return p;
}
else
{
return NULL;
}
}
/**
* @brief Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
* This function should be passed as a parameter to netif_add().
*
* @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t ethernetif_init(struct netif *netif)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));
#if LWIP_NETIF_HOSTNAME
/* Initialize interface hostname */
netif->hostname = "lwip";
#endif /* LWIP_NETIF_HOSTNAME */
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
/* We directly use etharp_output() here to save a function call.
* You can instead declare your own function an call etharp_output()
* from it if you have to do some checks before sending (e.g. if link
* is available...) */
netif->output = etharp_output;
netif->linkoutput = low_level_output;
/* initialize the hardware */
low_level_init(netif);
/* create a semaphore used for informing ethernetif of frame reception */
/* ethernet link list is 4 buffers, set semaphore size to 4 to not miss */
/* interrupt (1 is not working ) */
#if (osCMSIS >= 0x20000U)
s_xSemaphore = osSemaphoreNew(4, 4, NULL);
#else
osSemaphoreDef(SEM);
s_xSemaphore = osSemaphoreCreate(osSemaphore(SEM), 4);
#endif /* osCMSIS */
/* create the task that handles the received data */
#if (osCMSIS < 0x20000U )
osThreadDef(EthIf, (os_pthread) ethernetif_task, osPriorityHigh, 0, INTERFACE_THREAD_STACK_SIZE);
ethernetif_thread_handle = osThreadCreate(osThread(EthIf), netif);
#else
ethernetif_thread_handle = osThreadNew((osThreadFunc_t)ethernetif_task, netif, &attr);
#endif /* osCMSIS */
return ERR_OK;
}
err_t ethernetif_deinit(struct netif *netif)
{
/* join will be welcome first ? */
(void) osThreadTerminate(ethernetif_thread_handle);
return ERR_OK;
}
/**
* @brief Custom Rx pbuf free callback
* @param pbuf: pbuf to be freed
* @retval None
*/
void pbuf_free_custom(struct pbuf *p)
{
struct pbuf_custom *custom_pbuf = (struct pbuf_custom *)p;
/* Invalidate data cache: lwIP and/or application may have written into buffer */
SCB_InvalidateDCache_by_Addr((uint32_t *)p->payload, p->tot_len);
LWIP_MEMPOOL_FREE(RX_POOL, custom_pbuf);
}
/**
* @brief Returns the current time in milliseconds
* when LWIP_TIMERS == 1 and NO_SYS == 1
* @param None
* @retval Current Time value
*/
u32_t sys_now(void)
{
return HAL_GetTick();
}
/*******************************************************************************
Ethernet MSP Routines
*******************************************************************************/
/**
* @brief Initializes the ETH MSP.
* @param heth: ETH handle
* @retval None
*/
void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Ethernett MSP init: RMII Mode
RX_CLK --------------> PA1
TXD0 --------------> PB12
TXD1 --------------> PB13
RXD0 --------------> PC4
RXD1 --------------> PC5
TX_EN --------------> PB11
RX_DV --------------> PA7
MDC --------------> PC1
MDIO --------------> PA2
*/
/* Enable GPIOs clocks */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
/* Configure PA1, PA2 , PA7 */
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL ;
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure PG11, PG12 and PG13 */
GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
/* Configure PC1, PC4 and PC5 */
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Enable the Ethernet global Interrupt */
HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0);
HAL_NVIC_EnableIRQ(ETH_IRQn);
/* Enable Ethernet clocks */
__HAL_RCC_ETH1MAC_CLK_ENABLE();
__HAL_RCC_ETH1TX_CLK_ENABLE();
__HAL_RCC_ETH1RX_CLK_ENABLE();
}
/**
* @brief Ethernet Rx Transfer completed callback
* @param heth: ETH handle
* @retval None
*/
void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
{
osSemaphoreRelease(s_xSemaphore);
}
/*******************************************************************************
PHI IO Functions
*******************************************************************************/
/**
* @brief Initializes the MDIO interface GPIO and clocks.
* @param None
* @retval 0 if OK, -1 if ERROR
*/
int32_t ETH_PHY_IO_Init(void)
{
/* We assume that MDIO GPIO configuration is already done
in the ETH_MspInit() else it should be done here
*/
/* Configure the MDIO Clock */
HAL_ETH_SetMDIOClockRange(&EthHandle);
return 0;
}
/**
* @brief De-Initializes the MDIO interface .
* @param None
* @retval 0 if OK, -1 if ERROR
*/
int32_t ETH_PHY_IO_DeInit(void)
{
return 0;
}
/**
* @brief Read a PHY register through the MDIO interface.
* @param DevAddr: PHY port address
* @param RegAddr: PHY register address
* @param pRegVal: pointer to hold the register value
* @retval 0 if OK -1 if Error
*/
int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal)
{
if (HAL_ETH_ReadPHYRegister(&EthHandle, DevAddr, RegAddr, pRegVal) != HAL_OK)
{
return -1;
}
return 0;
}
/**
* @brief Write a value to a PHY register through the MDIO interface.
* @param DevAddr: PHY port address
* @param RegAddr: PHY register address
* @param RegVal: Value to be written
* @retval 0 if OK -1 if Error
*/
int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal)
{
if (HAL_ETH_WritePHYRegister(&EthHandle, DevAddr, RegAddr, RegVal) != HAL_OK)
{
return -1;
}
return 0;
}
/**
* @brief Get the time in millisecons used for internal PHY driver process.
* @retval Time value
*/
int32_t ETH_PHY_IO_GetTick(void)
{
return HAL_GetTick();
}
/**
* @brief
* @retval None
*/
void ethernet_link_check_state(struct netif *netif)
{
ETH_MACConfigTypeDef MACConf;
uint32_t PHYLinkState;
uint32_t linkchanged = 0;
uint32_t speed = 0;
uint32_t duplex = 0;
PHYLinkState = LAN8742_GetLinkState(&LAN8742);
if (netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN))
{
HAL_ETH_Stop_IT(&EthHandle);
netif_set_down(netif);
netif_set_link_down(netif);
}
else if (!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN))
{
switch (PHYLinkState)
{
case LAN8742_STATUS_100MBITS_FULLDUPLEX:
duplex = ETH_FULLDUPLEX_MODE;
speed = ETH_SPEED_100M;
linkchanged = 1;
break;
case LAN8742_STATUS_100MBITS_HALFDUPLEX:
duplex = ETH_HALFDUPLEX_MODE;
speed = ETH_SPEED_100M;
linkchanged = 1;
break;
case LAN8742_STATUS_10MBITS_FULLDUPLEX:
duplex = ETH_FULLDUPLEX_MODE;
speed = ETH_SPEED_10M;
linkchanged = 1;
break;
case LAN8742_STATUS_10MBITS_HALFDUPLEX:
duplex = ETH_HALFDUPLEX_MODE;
speed = ETH_SPEED_10M;
linkchanged = 1;
break;
default:
break;
}
if (linkchanged)
{
/* Get MAC Config MAC */
HAL_ETH_GetMACConfig(&EthHandle, &MACConf);
MACConf.DuplexMode = duplex;
MACConf.Speed = speed;
HAL_ETH_SetMACConfig(&EthHandle, &MACConf);
HAL_ETH_Start_IT(&EthHandle);
netif_set_up(netif);
netif_set_link_up(netif);
}
}
}
uint8_t ethernetif_low_get_link_status(void)
{
uint8_t ret;
uint32_t PHYLinkState;
PHYLinkState = LAN8742_GetLinkState(&LAN8742);
if (PHYLinkState > LAN8742_STATUS_LINK_DOWN)
{
ret = 1;
}
else
{
ret = 0;
}
return ret;
}
static void ethernetif_task(void *context)
{
struct netif *netif = context;
int32_t semaphore_retval;
static uint8_t link_status = 0;
if (link_status)
{
netif_set_link_up(netif);
}
else netif_set_link_down(netif);
for (;;)
{
semaphore_retval = OSSEMAPHOREWAIT(s_xSemaphore, TIME_WAITING_FOR_INPUT);
if (ethernetif_low_get_link_status() != link_status)
{
link_status = 1U - link_status;
if (link_status)
{
netif_set_link_up(netif);
}
else netif_set_link_down(netif);
}
if (semaphore_retval == (int32_t) osOK)
{
struct pbuf *p;
/* move received packet into a new pbuf */
p = low_level_input(netif);
/* no packet could be read, silently ignore this */
if (p)
{
err_t err;
/* entry point to the LwIP stack */
err = netif->input(p, netif);
if (err != ERR_OK)
{
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
pbuf_free(p);
}
}
}
}
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,57 @@
/**
******************************************************************************
* @file net_conf.h
* @author MCD Application Team
* @brief This file provides the configuration for net
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#ifndef NET_CONF_H
#define NET_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void ethernetif_low_init(void (*event_callback)(void), void (*buffer_output_callback)(uint8_t *));
void ethernetif_low_deinit(void);
int16_t ethernetif_low_inputsize(void);
int16_t ethernetif_low_input(uint8_t *payload, uint16_t len);
int16_t ethernetif_low_output(uint8_t *payload, uint16_t len);
void ethernetif_low_get_mac_addr(uint8_t *MACAddr_in);
uint8_t ethernetif_low_get_link_status(void);
#define NET_USE_RTOS
#define ETHERNET_MAC_GENERATION_FROM_SHA256
#ifdef GENERATOR_WAKAAMACLIENT_CLOUD
#define USE_TINY_DTLS
#else
#define NET_MBEDTLS_HOST_SUPPORT
#endif /* GENERATOR_WAKAAMACLIENT_CLOUD */
#include "net_conf_template.h"
#ifdef __cplusplus
}
#endif
#endif /* NET_CONF_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,835 @@
/**
******************************************************************************
* @file Ethernetif.c
* @author MCD Application Team
* @brief Implement functions called to initialize the Ethernet low level driver
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#ifdef STM32F429xx
#include "stm32f4xx_hal.h"
#include "stm32f4xx_ll_utils.h"
#endif /* STM32F429xx */
#ifdef STM32F769xx
#include "stm32f7xx_hal.h"
#include "stm32f7xx_ll_utils.h"
#endif /* STM32F769xx */
#include "lwip/netif.h"
#include "lwip/tcpip.h"
#include "lwip/etharp.h"
#include "net_connect.h"
#include "net_buffers.h"
#ifdef GENERATOR_WAKAAMACLIENT_CLOUD
#define USED_TINY_DTLS
#endif /* GENERATOR_WAKAAMACLIENT_CLOUD */
/* Use a tinydtls hash function to generate an 'MCU-unique' MAC address */
#ifdef ETHERNET_MAC_GENERATION_FROM_SHA256
#ifdef USED_TINY_DTLS
#include "sha2/sha2.h"
#ifndef WITH_SHA256
#error "WITH_SHA256 must be enabled in the tinydtls configuration file"
#endif /* WITH_SHA256 */
#define HASH_OUTPUT_LENGTH DTLS_SHA256_DIGEST_STRING_LENGTH
#else /* USED_TINY_DTLS */
#include "mbedtls/sha256.h"
#define HASH_OUTPUT_LENGTH 32
#endif /* USED_TINY_DTLS */
#endif /* ETHERNET_MAC_GENERATION_FROM_SHA256 */
err_t ethernetif_init(struct netif *netif);
void ethernetif_deinit(struct netif *netif);
#define MAX_MTU 1500
#if (osCMSIS >= 0x20000U)
#define OSSEMAPHOREWAIT osSemaphoreAcquire
#else
#define OSSEMAPHOREWAIT osSemaphoreWait
#endif /* osCMSIS */
/* The time to block waiting for input. */
#define TIME_WAITING_FOR_INPUT ( 250 ) /*( portMAX_DELAY )*/
/* Stack size of the interface thread */
#define INTERFACE_THREAD_STACK_SIZE 1024
/* buffer management list */
#define BUFFER_LIST_SIZE 10
#define CIRCULAR_INC(a) (a)++;if ((a)==BUFFER_LIST_SIZE) {(a)=0;}
/* Within 'USER CODE' section, code will be kept by default at each generation */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* Private function ---------------------------------------------------------*/
static void ethernetif_low_init(void);
static void ethernetif_low_deinit(void);
static void ethernetif_low_get_mac_addr(uint8_t *MACAddr_in);
static uint8_t ethernetif_low_get_link_status(void);
static int16_t ethernetif_low_inputsize(void);
static int16_t ethernetif_low_input(uint8_t *payload, uint16_t len);
static int16_t ethernetif_low_output(uint8_t *payload, uint16_t len);
static int32_t ethernetif_output(void *context, net_buf_t *netbuf);
static void ethernetif_low_errhandle(void);
static void ethernetif_task(void *context);
static void ethernetif_write_done(void);
/* Private variables ---------------------------------------------------------*/
static uint8_t MACAddr[6];
/* Semaphore to signal incoming packets */
static osSemaphoreId s_xSemaphore = NULL;
static osThreadId ethernetif_thread_handle = NULL;
static __IO int32_t free_buffer_index;
static int32_t write_buffer_index;
static int32_t busy_buffer_index;
static net_buf_t *sent_write_buffer[BUFFER_LIST_SIZE];
/* Global Ethernet handle */
ETH_HandleTypeDef EthHandle;
#ifdef DATA_CACHE_ENABLED
#ifdef USE_CACHED_ETH_BUFFERS
#define SECTION_ETHERNET_BUFFERS ".ram_cache"
#else
#define SECTION_ETHERNET_BUFFERS ".sram2_non_cached_normal"
#endif /* USE_CACHED_ETH_BUFFERS */
#else
#define SECTION_ETHERNET_BUFFERS ".ram"
#endif /* DATA_CACHE_ENABLED */
#if defined ( __ICCARM__ )
#pragma data_alignment = 4
#pragma location = ".sram2_non_cached_device"
static ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB];/* Ethernet Rx MA Descriptor */
#pragma data_alignment = 4
#pragma location = ".sram2_non_cached_device"
static ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB];/* Ethernet Tx DMA Descriptor */
#pragma data_alignment = 4
#pragma location = SECTION_ETHERNET_BUFFERS
static uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE]; /* Ethernet Receive Buffer */
#pragma data_alignment = 4
#pragma location = SECTION_ETHERNET_BUFFERS
static uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE]; /* Ethernet Transmit Buffer */
#elif defined(__CC_ARM)
ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB] __attribute__((section(".sram2_non_cached_device"),
zero_init)); /* Ethernet Rx DMA Descriptor */
ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB] __attribute__((section(".sram2_non_cached_device"),
zero_init)); /* Ethernet Tx DMA Descriptor */
uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __attribute__((section(".sram2_non_cached_normal"),
zero_init)); /* Ethernet Receive Buffer */
uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __attribute__((section(".sram2_non_cached_normal"),
zero_init)); /* Ethernet Transmit Buffer */
#elif defined (__GNUC__)
/* Ethernet Rx MA Descriptor */
ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB] __attribute__((
section(".sram2_non_cached_device")));
/* Ethernet Tx DMA Descriptor */
ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB] __attribute__((
section(".sram2_non_cached_device")));
/* Ethernet Received Buffer */
uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __attribute__((
section(".sram2_non_cached_normal")));
/* Ethernet Transmit Buffer */
uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __attribute__((
section(".sram2_non_cached_normal")));
#endif /* __CC_ARM */
void HAL_ETH_MspInit(ETH_HandleTypeDef *EthHandle)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOs clocks */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
/* Ethernet pins configuration ************************************************/
/*
RMII_REF_CLK ----------------------> PA1
RMII_MDIO -------------------------> PA2
RMII_MDC --------------------------> PC1
RMII_MII_CRS_DV -------------------> PA7
RMII_MII_RXD0 ---------------------> PC4
RMII_MII_RXD1 ---------------------> PC5
RMII_MII_RXER ---------------------> PG2
RMII_MII_TX_EN --------------------> PG11
RMII_MII_TXD0 ---------------------> PG13
RMII_MII_TXD1 ---------------------> PG14
*/
#ifdef STM32F429xx
GPIO_InitStructure.Pin = RMII_MDC_Pin | RMII_RXD0_Pin | RMII_RXD1_Pin;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.Pin = RMII_REF_CLK_Pin | RMII_MDIO_Pin | RMII_CRS_DV_Pin;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.Pin = RMII_TXD1_Pin;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(RMII_TXD1_GPIO_Port, &GPIO_InitStructure);
GPIO_InitStructure.Pin = RMII_TX_EN_Pin | RMII_TXD0_Pin;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
#endif /* STM32F429xx */
#ifdef STM32F769xx
/* Configure PA1, PA2 and PA7 */
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure PC1, PC4 and PC5 */
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure PG2, PG11, PG13 and PG14 */
GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
#endif /* STM32F769xx */
/* Enable the Ethernet global Interrupt */
HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0);
HAL_NVIC_EnableIRQ(ETH_IRQn);
/* Enable ETHERNET clock */
__HAL_RCC_ETH_CLK_ENABLE();
}
void HAL_ETH_MspDeInit(ETH_HandleTypeDef *ethHandle)
{
if (ethHandle->Instance == ETH)
{
/* USER CODE BEGIN ETH_MspDeInit 0 */
/* USER CODE END ETH_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_ETH_CLK_DISABLE();
/**ETH GPIO Configuration
PC1 ------> ETH_MDC
PA1 ------> ETH_REF_CLK
PA2 ------> ETH_MDIO
PA7 ------> ETH_CRS_DV
PC4 ------> ETH_RXD0
PC5 ------> ETH_RXD1
PB13 ------> ETH_TXD1
PG11 ------> ETH_TX_EN
PG13 ------> ETH_TXD0
*/
#if 0
HAL_GPIO_DeInit(GPIOC, RMII_MDC_Pin | RMII_RXD0_Pin | RMII_RXD1_Pin);
HAL_GPIO_DeInit(GPIOA, RMII_REF_CLK_Pin | RMII_MDIO_Pin | RMII_CRS_DV_Pin);
HAL_GPIO_DeInit(RMII_TXD1_GPIO_Port, RMII_TXD1_Pin);
HAL_GPIO_DeInit(GPIOG, RMII_TX_EN_Pin | RMII_TXD0_Pin);
/* Peripheral interrupt Deinit*/
HAL_NVIC_DisableIRQ(ETH_IRQn);
#endif /* 0 */
/* USER CODE BEGIN ETH_MspDeInit 1 */
/* USER CODE END ETH_MspDeInit 1 */
}
}
/**
* @brief Ethernet Rx Transfer completed callback
* @param EthHandle: ETH handle
* @retval None
*/
void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *EthHandle)
{
(void) osSemaphoreRelease(s_xSemaphore);
}
void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *EthHandle)
{
if (__HAL_ETH_DMA_GET_FLAG(EthHandle, ETH_DMASR_RBUS))
{
/* The Receive Buffer Unavailable interrupt is cleared by the Ethernet HAL handler before the
Ethernet task is scheduled.
Temporarily mask it so that the Ethernet task is scheduled before a new IT is trigged.
*/
__HAL_ETH_DMA_DISABLE_IT(EthHandle, ETH_DMA_IT_RBU);
}
}
static void ethernetif_low_init(void)
{
#ifdef PHY_ISFR
uint32_t regvalue;
#endif /* PHY_ISFR */
/* Init ETH */
EthHandle.Instance = ETH;
EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
EthHandle.Init.PhyAddress = LAN8742A_PHY_ADDRESS;
MACAddr[0] = 0x00;
MACAddr[1] = 0x80;
MACAddr[2] = 0xE1;
MACAddr[3] = 0x00;
MACAddr[4] = 0x00;
MACAddr[5] = 0x01;
/* Generate an MCU-unique MAC address */
#ifdef ETHERNET_MAC_GENERATION_FROM_SHA256
unsigned char output[HASH_OUTPUT_LENGTH];
uint32_t UID[3];
/* Generate a hash digest from the unique CPU ID */
UID[0] = LL_GetUID_Word0();
UID[1] = LL_GetUID_Word1();
UID[2] = LL_GetUID_Word2();
#ifdef USE_TINY_DTLS
/* Hash with tinydtls */
dtls_sha256_data((uint8_t *) UID, sizeof(UID), (char *) output);
#else /* USED_TINY_DTLS */
/* Hash with mbedTLS */
int32_t hash_success = 0;
mbedtls_sha256_context sha_context;
mbedtls_sha256_init(&sha_context);
if (0 == mbedtls_sha256_starts_ret(&sha_context, 0))
{
if (0 == mbedtls_sha256_update_ret(&sha_context, (const unsigned char *) UID, sizeof(UID)))
{
if (0 == mbedtls_sha256_finish_ret(&sha_context, output))
{
hash_success = 1;
}
}
}
mbedtls_sha256_free(&sha_context);
while (hash_success == 0)
{
;
}
#endif /* USE_TINY_DTLS */
/* Copy the 3 first bytes of the digest to the second half of the MAC address. */
memcpy(&MACAddr[3], output, 3);
#endif /* ETHERNET_MAC_GENERATION_FROM_SHA256 */
EthHandle.Init.MACAddr = &MACAddr[0];
EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE;
#ifdef CHECKSUM_BY_HARDWARE
EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
#else
EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;
#endif /* CHECKSUM_BY_HARDWARE */
EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
EthHandle.Init.Speed = ETH_SPEED_100M;
EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
HAL_ETH_Init(&EthHandle);
/* Enable both the transmission and the read buffer underflow interrupts. */
__HAL_ETH_DMA_ENABLE_IT(&EthHandle, ETH_DMA_IT_NIS | ETH_DMA_IT_R | ETH_DMA_IT_T | ETH_DMA_IT_AIS | ETH_DMA_IT_RBU);
/* Initialize Tx Descriptors list: Chain Mode */
HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, 0, ETH_TXBUFNB);
for (int32_t i = 0; i < ETH_TXBUFNB; i++)
{
DMATxDscrTab[i].Buffer1Addr = 0;
}
/* Initialize Rx Descriptors list: Chain Mode */
HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
/* Enable MAC and DMA transmission and reception */
HAL_ETH_Start(&EthHandle);
/* USER CODE BEGIN PHY_PRE_CONFIG */
/* USER CODE END PHY_PRE_CONFIG */
#ifdef PHY_ISFR
/* Read Register Configuration */
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ISFR, &regvalue);
regvalue |= (PHY_ISFR_INT4);
/* Enable Interrupt on change of link status */
HAL_ETH_WritePHYRegister(&EthHandle, PHY_ISFR, regvalue);
/* Read Register Configuration */
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ISFR, &regvalue);
#endif /* PHY_ISFR */
/* USER CODE BEGIN PHY_POST_CONFIG */
/* USER CODE END PHY_POST_CONFIG */
}
static void ethernetif_low_deinit(void)
{
#ifdef PHY_ISFR
uint32_t regvalue;
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ISFR, &regvalue);
regvalue &= (~PHY_ISFR_INT4);
HAL_ETH_WritePHYRegister(&EthHandle, PHY_ISFR, regvalue);
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ISFR, &regvalue);
#endif /* PHY_ISFR */
HAL_ETH_Stop(&EthHandle);
memset(&EthHandle, 0x00, sizeof(EthHandle));
memset(MACAddr, 0x00, 6);
/* return pending buffers */
for (int32_t i = 0; i < ETH_TXBUFNB; i++)
{
if ((DMATxDscrTab[i].Buffer1Addr != 0))
{
ethernetif_write_done();
DMATxDscrTab[i].Buffer1Addr = 0;
}
}
}
static int16_t ethernetif_low_inputsize(void)
{
if (HAL_ETH_GetReceivedFrame_IT(&EthHandle) != HAL_OK)
{
ethernetif_low_errhandle();
return -1;
}
return EthHandle.RxFrameInfos.length;
}
static int16_t ethernetif_low_input(uint8_t *payload, uint16_t len)
{
__IO ETH_DMADescTypeDef *dmarxdesc;
uint32_t rlen = 0;
/* Obtain the size of the packet and put it into the "len" variable. */
rlen = EthHandle.RxFrameInfos.length;
dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc;
if ((payload == NULL) || (len < rlen))
{
NET_DBG_INFO("LwIP pool is full or buffer is too small. Dropping an Ethernet RX frame of size %lu.\n", rlen);
}
else
{
#if defined(DATA_CACHE_ENABLE) && defined(USE_CACHED_ETH_BUFFERS)
SCB_InvalidateDCache_by_Addr((uint32_t *)dmarxdesc->Buffer1Addr, rlen);
#endif /* USE_CACHED_ETH_BUFFERS */
memcpy(payload, (uint8_t *) dmarxdesc->Buffer1Addr, rlen);
}
/* Clear Segment_Count */
NET_ASSERT(EthHandle.RxFrameInfos.SegCount == 1, " multiple segments only 1 supported\n");
EthHandle.RxFrameInfos.SegCount = 0;
dmarxdesc->Status |= ETH_DMARXDESC_OWN;
/* ETH_DMA_IT_R and ETH_DMA_IT_RBU may be raised simultaneously.
Run the error handling.
*/
ethernetif_low_errhandle();
return rlen;
}
static void ethernetif_low_errhandle(void)
{
if (__HAL_ETH_DMA_GET_FLAG(&EthHandle, ETH_DMASR_RBUS))
{
NET_DBG_INFO("DMA underflow\n");
/* Re-enable the Receive Buffer Unavailable interrupt */
__HAL_ETH_DMA_ENABLE_IT(&EthHandle, ETH_DMA_IT_RBU);
/* Clear RBUS ETHERNET DMA flag */
__HAL_ETH_DMA_CLEAR_FLAG(&EthHandle, ETH_DMASR_RBUS);
/* Resume DMA reception */
EthHandle.Instance->DMARPDR = 0;
/* The ETH_DMA_IT_R interrupt is not raised when restarting after a Receive Buffer Unavailable.
Poll again.
*/
}
}
static int16_t ethernetif_low_output(uint8_t *payload, uint16_t len)
{
int16_t errval = 0;
__IO ETH_DMADescTypeDef *DmaTxDesc = EthHandle.TxDesc;
/* NET_DBG_PRINT ("ethernetif_low_output %d\n",len); */
/* Count number of buffer that have been sent */
for (int32_t i = 0; i < ETH_TXBUFNB; i++)
{
if ((DMATxDscrTab[i].Buffer1Addr != 0) && !(DMATxDscrTab[i].Status & ETH_DMATXDESC_OWN))
{
CIRCULAR_INC(free_buffer_index);
DMATxDscrTab[i].Buffer1Addr = 0;
}
}
if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
{
errval = -1;
goto error;
}
DmaTxDesc->Buffer1Addr = (uint32_t) payload;
#if defined(DATA_CACHE_ENABLE) && defined(USE_CACHED_ETH_BUFFERS)
SCB_CleanDCache_by_Addr(((uint32_t *)DmaTxDesc->Buffer1Addr), len + 32);
#endif /* Cache Buffers */
/* Prepare transmit descriptors to give to DMA */
if (HAL_ETH_TransmitFrame(&EthHandle, len))
{
errval = -1;
}
error:
/* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
if ((EthHandle.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET)
{
/* Clear TUS ETHERNET DMA flag */
EthHandle.Instance->DMASR = ETH_DMASR_TUS;
/* Resume DMA transmission*/
EthHandle.Instance->DMATPDR = 0;
}
return errval;
}
static void ethernetif_low_get_mac_addr(uint8_t *MACAddr_in)
{
MACAddr_in[0] = MACAddr[0];
MACAddr_in[1] = MACAddr[1];
MACAddr_in[2] = MACAddr[2];
MACAddr_in[3] = MACAddr[3];
MACAddr_in[4] = MACAddr[4];
MACAddr_in[5] = MACAddr[5];
}
static uint8_t ethernetif_low_get_link_status(void)
{
uint32_t phyreg;
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BSR, &phyreg);
return (uint8_t)((phyreg & PHY_LINKED_STATUS) > 0);
}
static int32_t ethernetif_output(void *context, net_buf_t *netbuf)
{
int32_t ret;
uint16_t len = 0u;
int32_t nb = 0;
net_buf_t *q;
/* release returned buffers */
while (busy_buffer_index != free_buffer_index)
{
CIRCULAR_INC(busy_buffer_index);
(void) NET_BUF_FREE(sent_write_buffer[busy_buffer_index]);
sent_write_buffer[busy_buffer_index] = 0;
}
for (q = netbuf; q != NULL ; q = q->next)
{
len += q->len;
nb++;
}
if (nb == 1)
{
NET_BUF_REF(netbuf);
CIRCULAR_INC(write_buffer_index);
sent_write_buffer[write_buffer_index] = netbuf;
ret = ethernetif_low_output(netbuf->payload, netbuf->len);
}
else
{
net_buf_t *p;
p = NET_BUF_ALLOC(len);
if (p != NULL)
{
uint8_t *pp = p->payload;
for (q = netbuf; q != NULL ; q = q->next)
{
(void) memcpy(pp, q->payload, q->len);
pp = &pp[q->len];
}
p->len = (uint16_t) len;
CIRCULAR_INC(write_buffer_index);
sent_write_buffer[write_buffer_index] = p;
ret = ethernetif_low_output(p->payload, p->len);
}
else
{
while (true) {};
}
}
return ret;
}
static void ethernetif_write_done(void)
{
CIRCULAR_INC(free_buffer_index);
}
static void ethernetif_task(void *context)
{
struct netif *netif = context;
int32_t semaphore_retval;
net_buf_t *netbuf;
uint8_t *payload;
int16_t len;
static uint8_t link_status = 0;
if (link_status)
{
netif_set_link_up(netif);
}
else netif_set_link_down(netif);
for (;;)
{
semaphore_retval = OSSEMAPHOREWAIT(s_xSemaphore, TIME_WAITING_FOR_INPUT);
if (ethernetif_low_get_link_status() != link_status)
{
link_status = 1U - link_status;
if (link_status)
{
netif_set_link_up(netif);
}
else netif_set_link_down(netif);
}
if (semaphore_retval == (int32_t) osOK)
{
/*NET_DBG_PRINT ("Wakeup Input data\n");*/
while ((len = ethernetif_low_inputsize()) > 0)
{
payload = NULL;
netbuf = NET_BUF_ALLOC((uint16_t)len);
if (netbuf != NULL)
{
payload = netbuf->payload;
}
if (ethernetif_low_input(payload, (uint16_t) len) > 0)
{
tcpip_input(netbuf, netif);
}
}
}
}
}
#if (osCMSIS >= 0x20000U )
static const osThreadAttr_t attr =
{
.name = "EthIf",
.priority = osPriorityHigh,
. stack_size = INTERFACE_THREAD_STACK_SIZE
};
#endif /* osCMSIS */
err_t ethernetif_init(struct netif *netif)
{
err_t ret = ERR_OK;
char *hostname = NET_MALLOC(sizeof(char) * ((uint16_t) NET_IP_HOSTNAME_MAX_LEN + 1U));
if (hostname == NULL)
{
return (err_t) ERR_MEM;
}
(void) snprintf(hostname, NET_IP_HOSTNAME_MAX_LEN + 1, "generic eth if #%d", netif->num);
netif->hostname = hostname;
netif->name[0] = 's';
netif->name[1] = 't';
netif->hwaddr_len = 6;
netif->mtu = MAX_MTU;
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
netif->output = etharp_output;
#if LWIP_IPV6
netif->output_ip6 = ethip6_output;
#endif /* LWIP_IPV6 */
/* output to the device */
netif->linkoutput = (netif_linkoutput_fn)ethernetif_output;
free_buffer_index = 0;
write_buffer_index = 0;
busy_buffer_index = 0;
(void) memset(sent_write_buffer, 0, sizeof(sent_write_buffer));
/* create a semaphore used for informing ethernetif of frame reception */
/* ethernet link list is 4 buffers, set semaphore size to 4 to not miss */
/* interrupt (1 is not working ) */
#if (osCMSIS >= 0x20000U)
s_xSemaphore = osSemaphoreNew(4, 4, NULL);
#else
osSemaphoreDef(SEM);
s_xSemaphore = osSemaphoreCreate(osSemaphore(SEM), 4);
#endif /* osCMSIS */
ethernetif_low_init();
ethernetif_low_get_mac_addr(netif->hwaddr);
/* create the task that handles the ETH_MAC */
#if (osCMSIS < 0x20000U )
osThreadDef(EthIf, (os_pthread) ethernetif_task, osPriorityHigh, 0, INTERFACE_THREAD_STACK_SIZE);
ethernetif_thread_handle = osThreadCreate(osThread(EthIf), netif);
#else
ethernetif_thread_handle = osThreadNew((osThreadFunc_t)ethernetif_task, netif, &attr);
#endif /* osCMSIS */
/* USER CODE BEGIN LOW_LEVEL_INIT */
/* USER CODE END LOW_LEVEL_INIT */
return ret;
}
void ethernetif_deinit(struct netif *netif)
{
while (busy_buffer_index != free_buffer_index)
{
CIRCULAR_INC(busy_buffer_index);
(void) NET_BUF_FREE(sent_write_buffer[busy_buffer_index]);
sent_write_buffer[busy_buffer_index] = 0;
}
if (netif->hostname)
{
NET_FREE((void *) netif->hostname);
netif->hostname = 0;
}
(void) osThreadTerminate(ethernetif_thread_handle);
ethernetif_thread_handle = NULL;
(void) osSemaphoreDelete(s_xSemaphore);
s_xSemaphore = NULL;
ethernetif_low_deinit();
}
#ifdef GENERATOR_AWS_CLOUD
#include "mbedtls/x509_crt.h"
/*
* Amazon Profile
*/
const mbedtls_x509_crt_profile mbedtls_x509_crt_amazon_suite =
{
/* Only SHA-256 and 384 */
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384),
/* Only ECDSA */
MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_RSA) | /* */
MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECKEY) | /* */
MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECDSA),
#if defined(MBEDTLS_ECP_C)
/* Only NIST P-256 and P-384 */
MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) |
MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1),
#else
0,
#endif /* MBEDTLS_ECP_C */
2048
};
const int32_t net_tls_sizeof_suite_structure = sizeof(mbedtls_x509_crt_profile);
const void *net_tls_user_suite0 = (void *) &mbedtls_x509_crt_amazon_suite;
#endif /* GENERATOR_AWS_CLOUD */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,49 @@
/**
******************************************************************************
* @file net_conf.h
* @author MCD Application Team
* @brief This file provides the configuration for net
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#ifndef NET_CONF_H
#define NET_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
#define NET_USE_RTOS
#define NET_USE_HARDWARE_CHKSUM
#define ETHERNET_MAC_GENERATION_FROM_SHA256
#ifdef GENERATOR_WAKAAMACLIENT_CLOUD
#define USE_TINY_DTLS
#else
#define NET_MBEDTLS_HOST_SUPPORT
#endif /* GENERATOR_WAKAAMACLIENT_CLOUD */
#include "net_conf_template.h"
#ifdef __cplusplus
}
#endif
#endif /* NET_CONF_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,488 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file mx_wifi_io.c
* @author MCD Application Team
* @brief This file implements the IO operations to deal with the mx_wifi
* module. It mainly Inits and Deinits the SPI/UART interface. Send and
* receive data over it.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <main.h>
#include <string.h>
#include "net_conf.h"
#include "mx_wifi.h"
#if (MX_WIFI_USE_SPI == 1)
/* Private define ------------------------------------------------------------*/
#if (osCMSIS < 0x20000U )
#define OSSEMAPHOREWAIT osSemaphoreWait
#else
#define OSSEMAPHOREWAIT osSemaphoreAcquire
#endif /* osCMSIS */
#define SPI_READ (0xBE)
#define SPI_WRITE (0xEF)
#define MX_WIFI_RESET_MODULE() do{\
HAL_GPIO_WritePin(MX_WIFI_RESET_IO_PORT, MX_WIFI_RESET_IO_PIN, GPIO_PIN_RESET);\
HAL_Delay(10);\
HAL_GPIO_WritePin(MX_WIFI_RESET_IO_PORT, MX_WIFI_RESET_IO_PIN, GPIO_PIN_SET);\
HAL_Delay(10);\
}while(0);
#define MX_WIFI_SPI_CS_ENABLE() do{ \
HAL_GPIO_WritePin( MX_WIFI_SPI_SW_CS_PORT, MX_WIFI_SPI_SW_CS_PIN, GPIO_PIN_RESET );\
}while(0);
#define MX_WIFI_SPI_CS_DISABLE() do{ \
HAL_GPIO_WritePin( MX_WIFI_SPI_SW_CS_PORT, MX_WIFI_SPI_SW_CS_PIN, GPIO_PIN_SET );\
}while(0);
/* Private variables ---------------------------------------------------------*/
static MX_WIFIObject_t MxWifiObj;
static __IO int32_t spi_slave_notify_event = 0;
static __IO int32_t spi_slave_flow_event = 0;
#if MX_WIFI_USE_CMSIS_OS
osSemaphoreId slave_notify_sem;
osSemaphoreDef(slave_notify_sem);
osSemaphoreId slave_flow_sem;
osSemaphoreDef(slave_flow_sem);
#endif /* WIFI_USE_CMSIS_OS */
/* Global variables --------------------------------------------------------*/
SPI_HandleTypeDef hspi_mx;
DMA_HandleTypeDef hdma_spi_mxc_tx;
DMA_HandleTypeDef hdma_spi_mxc_rx;
MX_WIFIObject_t *wifi_obj_get(void);
static void MX_WIFI_IO_DELAY(uint32_t ms)
{
#if MX_WIFI_USE_CMSIS_OS
osDelay(ms);
#else
HAL_Delay(ms);
#endif /* WIFI_USE_CMSIS_OS */
}
MX_WIFIObject_t *wifi_obj_get(void)
{
return &MxWifiObj;
}
/**
* @brief GPIO Initialization Function for WIFI reset IO
* @param None
* @retval None
*/
static void MX_WIFI_RESET_IO_Init(void)
{
GPIO_InitTypeDef GPIO_Init;
MX_WIFI_RESET_IO_CLK_ENABLE();
/* configure Reset pin PA4 */
HAL_GPIO_WritePin(MX_WIFI_RESET_IO_PORT, MX_WIFI_RESET_IO_PIN, GPIO_PIN_SET);
GPIO_Init.Pin = MX_WIFI_RESET_IO_PIN;
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(MX_WIFI_RESET_IO_PORT, &GPIO_Init);
}
/**
* @brief Initialize the flow, notify and software CS IO for SPI
* @param None
* @retval None
*/
static void MX_WIFI_SPI_IO_Init(void)
{
GPIO_InitTypeDef GPIO_Init;
/* GPIO Ports Clock Enable */
MX_WIFI_SPI_IO_FLOW_CLK_ENABLE();
MX_WIFI_SPI_IO_NOTIFY_CLK_ENABLE();
MX_WIFI_SPI_SW_CS_CLK_ENABLE();
/* configure slave data notify pin */
GPIO_Init.Pin = MX_WIFI_SPI_IO_NOTIFY_PIN;
GPIO_Init.Mode = GPIO_MODE_IT_RISING_FALLING;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(MX_WIFI_SPI_IO_NOTIFY_PORT, &GPIO_Init);
/* configure slave flow control pin */
GPIO_Init.Pin = MX_WIFI_SPI_IO_FLOW_PIN;
GPIO_Init.Mode = GPIO_MODE_IT_RISING_FALLING;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(MX_WIFI_SPI_IO_FLOW_PORT, &GPIO_Init);
/* Enable Interrupt for slave flow control pin , PA3 */
HAL_NVIC_SetPriority((IRQn_Type)MX_WIFI_SPI_IO_FLOW_IRQ, SPI_INTERFACE_IO_PRIO, 0x00);
HAL_NVIC_EnableIRQ((IRQn_Type)MX_WIFI_SPI_IO_FLOW_IRQ);
/* Enable Interrupt for slave Data Ready pin , PB0 */
HAL_NVIC_SetPriority((IRQn_Type)MX_WIFI_SPI_IO_NOTIFY_IRQ, SPI_INTERFACE_IO_PRIO, 0x00);
HAL_NVIC_EnableIRQ((IRQn_Type)MX_WIFI_SPI_IO_NOTIFY_IRQ);
/* SPI soft-NSS */
HAL_GPIO_WritePin(MX_WIFI_SPI_SW_CS_PORT, MX_WIFI_SPI_SW_CS_PIN, GPIO_PIN_RESET);
GPIO_Init.Pin = MX_WIFI_SPI_SW_CS_PIN;
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(MX_WIFI_SPI_SW_CS_PORT, &GPIO_Init);
}
/**
* @brief Initialize the SPI1 hardware
* @param None
* @retval None
*/
static void MX_SPI_Init(void)
{
/* SPI1 parameter configuration*/
hspi_mx.Instance = SPI1;
hspi_mx.Init.Mode = SPI_MODE_MASTER;
hspi_mx.Init.Direction = SPI_DIRECTION_2LINES;
hspi_mx.Init.DataSize = SPI_DATASIZE_8BIT;
hspi_mx.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi_mx.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi_mx.Init.NSS = SPI_NSS_SOFT;
hspi_mx.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
hspi_mx.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi_mx.Init.TIMode = SPI_TIMODE_DISABLE;
hspi_mx.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi_mx.Init.CRCPolynomial = 7;
hspi_mx.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi_mx.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi_mx) != HAL_OK)
{
/*Error_Handler();*/
}
}
/**
* @brief Initialize the SPI1
* @param None
* @retval None
*/
static int8_t MX_WIFI_SPI_Init(uint16_t mode)
{
int8_t rc = 0;
MX_WIFI_RESET_IO_Init();
if (MX_WIFI_RESET == mode)
{
MX_WIFI_RESET_MODULE();
rc = 0;
}
else
{
MX_WIFI_SPI_IO_Init();
MX_SPI_Init();
#if MX_WIFI_USE_CMSIS_OS
#if (osCMSIS < 0x20000U )
slave_notify_sem = osSemaphoreCreate(osSemaphore(slave_notify_sem), 1);
slave_flow_sem = osSemaphoreCreate(osSemaphore(slave_flow_sem), 1);
#else
slave_notify_sem = osSemaphoreNew(1, 1, NULL);
slave_flow_sem = osSemaphoreNew(1, 1, NULL);
#endif /* osCMSIS < 0x20000U*/
/* take semaphore */
OSSEMAPHOREWAIT(slave_notify_sem, 1);
OSSEMAPHOREWAIT(slave_flow_sem, 1);
#endif /* WIFI_USE_CMSIS_OS */
rc = 0;
}
return rc;
}
/**
* @brief DeInitialize the SPI
* @param None
* @retval None
*/
static int8_t MX_WIFI_SPI_DeInit(void)
{
HAL_SPI_DeInit(&hspi_mx);
#ifdef WIFI_USE_CMSIS_OS
osSemaphoreDelete(slave_notify_sem);
osSemaphoreDelete(slave_flow_sem);
#endif /* WIFI_USE_CMSIS_OS */
return 0;
}
/**
* @brief SPI read/write cmd byte
*/
static int32_t wait_wifi_notify_event(int32_t timeout)
{
#ifdef WIFI_USE_CMSIS_OS
if (osOK != OSSEMAPHOREWAIT(slave_notify_sem, timeout))
{
return -1;
}
#else
int32_t tickstart = HAL_GetTick();
while (0 == spi_slave_notify_event)
{
if ((HAL_GetTick() - tickstart) > timeout)
{
return -1;
}
}
spi_slave_notify_event = 0;
#endif /* WIFI_USE_CMSIS_OS */
return 0;
}
static int32_t wait_wifi_idle(int32_t timeout)
{
#ifdef WIFI_USE_CMSIS_OS
if (osOK != OSSEMAPHOREWAIT(slave_flow_sem, timeout))
{
return -1;
}
#else
int32_t tickstart = HAL_GetTick();
while (0 == spi_slave_flow_event)
{
if ((HAL_GetTick() - tickstart) > timeout)
{
return -1;
}
}
spi_slave_flow_event = 0;
#endif /* WIFI_USE_CMSIS_OS */
return 0;
}
/**
* @brief Interrupt handler for Data RDY signal
* @param None
* @retval None
*/
void SPI_WIFI_ISR(uint16_t isr_source)
{
if (MX_WIFI_SPI_IO_NOTIFY_PIN == isr_source)
{
#ifdef WIFI_USE_CMSIS_OS
osSemaphoreRelease(slave_notify_sem);
#else
spi_slave_notify_event = 1;
#endif /* WIFI_USE_CMSIS_OS */
}
else if (MX_WIFI_SPI_IO_FLOW_PIN == isr_source)
{
#ifdef WIFI_USE_CMSIS_OS
osSemaphoreRelease(slave_flow_sem);
#else
spi_slave_flow_event = 1;
#endif /* WIFI_USE_CMSIS_OS */
}
else
{
}
}
/**
* @brief Recv wifi Data thru SPI
* @param pdata : pointer to data
* @param len : Data length
* @param timeout : send timeout in mS
* @retval Length of recved data
*/
int16_t MX_WIFI_SPI_ReceiveData(uint8_t *pdata, uint16_t len, uint32_t timeout_ms)
{
int16_t rc = -1;
uint8_t type = SPI_READ;
uint16_t read_len = 0;
MX_WIFI_SPI_CS_ENABLE();
if (wait_wifi_notify_event(timeout_ms) < 0)
{
/*DEBUG_LOG("DEBUG: spi recv: wait wifi data timeout.\r\n");*/
rc = MX_WIFI_STATUS_IO_ERROR;
goto error_exit;
}
if (HAL_SPI_Transmit(&hspi_mx, &type, 1, 5) != HAL_OK)
{
DEBUG_LOG("** ERROR: spi recv: send READ(1) error !\r\n");
rc = MX_WIFI_STATUS_IO_ERROR;
goto error_exit;
}
if (wait_wifi_idle(timeout_ms + 10) < 0)
{
DEBUG_LOG("** ERROR: spi recv: wait READ ack timeout !\r\n");
rc = MX_WIFI_STATUS_IO_ERROR;
goto error_exit;
}
DEBUG_LOG("spi READ cmd ok.\r\n");
if (HAL_SPI_Receive(&hspi_mx, (uint8_t *)&read_len, 2, 10) != HAL_OK)
{
DEBUG_LOG("** ERROR: spi recv: recv READ_LEN(2) error !\r\n");
rc = MX_WIFI_STATUS_IO_ERROR;
goto error_exit;
}
if (wait_wifi_idle(timeout_ms + 10) < 0)
{
DEBUG_LOG("** ERROR: spi recv: wait READ len ack timeout !\r\n");
rc = MX_WIFI_STATUS_IO_ERROR;
goto error_exit;
}
read_len = (read_len > len) ? len : read_len;
DEBUG_LOG("spi READ len(%d) ok.\r\n", read_len);
if (HAL_SPI_Receive(&hspi_mx, pdata, read_len, 200) != HAL_OK)
{
DEBUG_LOG("** ERROR: spi recv: recv DATA(%d) error !\r\n", read_len);
rc = MX_WIFI_STATUS_IO_ERROR;
goto error_exit;
}
if (wait_wifi_idle(timeout_ms + 100) < 0)
{
DEBUG_LOG("** ERROR: spi recv: wait DATA ack timeout !\r\n");
rc = MX_WIFI_STATUS_IO_ERROR;
goto error_exit;
}
DEBUG_LOG("spi READ data(%d) ok.\r\n", read_len);
rc = read_len;
error_exit:
MX_WIFI_SPI_CS_DISABLE();
return rc;
}
/**
* @brief Send wifi Data thru SPI
* @param pdata : pointer to data
* @param len : Data length
* @param timeout : send timeout in mS
* @retval Length of sent data
*/
static int16_t MX_WIFI_SPI_SendData(uint8_t *pdata, uint16_t len, uint32_t timeout_ms)
{
int16_t rc = -1;
uint8_t type = SPI_WRITE;
uint16_t send_len = len;
MX_WIFI_SPI_CS_ENABLE();
#ifdef WIFI_USE_CMSIS_OS
OSSEMAPHOREWAIT(slave_flow_sem, 1);
OSSEMAPHOREWAIT(slave_notify_sem, 1);
#else
spi_slave_notify_event = 0;
spi_slave_flow_event = 0;
#endif /* WIFI_USE_CMSIS_OS */
if (HAL_SPI_Transmit(&hspi_mx, (uint8_t *)&type, 1, 5) != HAL_OK)
{
DEBUG_LOG("** ERROR: spi send: send WRITE(1) error !\r\n");
rc = MX_WIFI_STATUS_IO_ERROR;
goto error_exit;
}
if (wait_wifi_idle(timeout_ms) < 0)
{
DEBUG_LOG("** ERROR: spi send: wait WRITE ACK timeout !\r\n");
rc = MX_WIFI_STATUS_IO_ERROR;
goto error_exit;
}
DEBUG_LOG("spi WRITE cmd ok.\r\n");
if (HAL_SPI_Transmit(&hspi_mx, (uint8_t *)&send_len, 2, 10) != HAL_OK)
{
DEBUG_LOG("** ERROR: spi send: send WRITE_LEN(2) error !\r\n");
rc = MX_WIFI_STATUS_IO_ERROR;
goto error_exit;
}
if (wait_wifi_idle(timeout_ms) < 0)
{
DEBUG_LOG("** ERROR: spi send: wait WRITE_LEN ACK timeout !\r\n");
rc = MX_WIFI_STATUS_IO_ERROR;
goto error_exit;
}
DEBUG_LOG("spi WRITE len(%d) ok.\r\n", send_len);
if (HAL_SPI_Transmit(&hspi_mx, pdata, send_len, 200) != HAL_OK)
{
DEBUG_LOG("** ERROR: spi send: send DATA(%d) error !\r\n", send_len);
rc = MX_WIFI_STATUS_IO_ERROR;
goto error_exit;
}
if (wait_wifi_idle(timeout_ms + 100) < 0)
{
DEBUG_LOG("** ERROR: spi send: wait DATA ACK timeout !\r\n");
rc = MX_WIFI_STATUS_IO_ERROR;
goto error_exit;
}
DEBUG_LOG("spi WRITE data(%d) ok.\r\n", send_len);
rc = send_len;
error_exit:
MX_WIFI_SPI_CS_DISABLE();
return rc;
}
/**
* @brief probe function to register wifi to connectivity framwotk
* @param None
* @retval None
*/
int32_t wifi_probe(void **ll_drv_context)
{
if (MX_WIFI_RegisterBusIO(&MxWifiObj,
MX_WIFI_SPI_Init,
MX_WIFI_SPI_DeInit,
MX_WIFI_IO_DELAY,
MX_WIFI_SPI_SendData,
MX_WIFI_SPI_ReceiveData) == 0)
{
*ll_drv_context = &MxWifiObj;
return 0;
}
return -1;
}
#endif /* (MX_WIFI_USE_SPI == 1) */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,408 @@
/**
******************************************************************************
* @file mx_wifi_io.c
* @author MCD Application Team
* @brief This file implements the IO operations to deal with the mx_wifi
* module. It mainly Inits and Deinits the UART interface. Send and
* receive data over it.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/*****************************************************************************
* this file can be copy and renamed as net_conf.c or use directly from its
* orginal location STM32_Network_lib/templates. There is no need to chnage it.
*
* It performs the connection between the mxchip BSP driver and the UART
*
* Expectaction is that UART pins labels are defined in main.h (when using
* CUbeMX) or in net_conf.h.
*
* function HAL_UART_MspInit(UART_HandleTypeDef* huart) in file
* stm32xxxx_hal_msp.c must performed the init of the selected UART interface
* This function can be manualy written or generated by cubeMX
*
* UART parameter init is done in this file in a redundant way from
* the HAL_UART_MspInit function.CubeMX user does not have to know the exact
* configuratino of the UART , but only the pin out connections.
*
* When interrupt are used (NET_USE_RTOS) , the function MXchip_UART_RxCpltCallback
* must be called from HAL_UART_RxCpltCallback located in main.c. A dedicated
* IRQHandler must be added to the file stm32xxx_it.C to call the HAL_UART_IRQHandler
*
* the function MX_WIFI_RESET_IO_Initconfigure the reset pins. It should be generated by
* CubeMX et being located in main.c
*/
/* Includes ------------------------------------------------------------------*/
/* Private includes ----------------------------------------------------------*/
#include <main.h>
#include <string.h>
#include "net_conf.h"
#include "mx_wifi.h"
#if (MX_WIFI_USE_SPI == 0)
/* Private define ------------------------------------------------------------*/
#if (osCMSIS < 0x20000U )
#define OSSEMAPHOREWAIT osSemaphoreWait
#else
#define OSSEMAPHOREWAIT osSemaphoreAcquire
#endif /* osCMSIS */
#define MX_WIFI_RESET_MODULE() do{\
HAL_GPIO_WritePin(MX_WIFI_RESET_IO_PORT, MX_WIFI_RESET_IO_PIN, GPIO_PIN_RESET);\
HAL_Delay(10);\
HAL_GPIO_WritePin(MX_WIFI_RESET_IO_PORT, MX_WIFI_RESET_IO_PIN, GPIO_PIN_SET);\
HAL_Delay(10);\
}while(0);
#if MX_WIFI_USE_UART_INTERRUPT
#define RING_BUFFER_SIZE (MX_WIFI_DATA_SIZE + 500)
typedef struct
{
uint8_t data[RING_BUFFER_SIZE];
__IO uint16_t tail;
__IO uint16_t head;
} RingBuffer_t;
#endif /* MX_WIFI_USE_UART_INTERRUPT */
MX_WIFIObject_t *wifi_obj_get(void);
UART_HandleTypeDef mx_uart;
static MX_WIFIObject_t MxWifiObj;
#if MX_WIFI_USE_UART_INTERRUPT
__IO RingBuffer_t WiFiRxBuffer;
#endif /* MX_WIFI_USE_UART_INTERRUPT */
#ifdef NET_USE_RTOS
osSemaphoreId wifi_uart_rx_sem;
osSemaphoreDef(wifi_uart_rx_sem);
#endif /* NET_USE_RTOS */
/* Private variables ---------------------------------------------------------*/
MX_WIFIObject_t *wifi_obj_get(void)
{
return &MxWifiObj;
}
static void MX_WIFI_IO_DELAY(uint32_t ms)
{
#if MX_WIFI_USE_CMSIS_OS
osDelay(ms);
#else
HAL_Delay(ms);
#endif /* MX_WIFI_USE_CMSIS_OS */
}
/**
* @brief GPIO Initialization Function for WIFI reset IO
* @param None
* @retval None
*/
static void MX_WIFI_RESET_IO_Init(void)
{
GPIO_InitTypeDef GPIO_Init;
MX_WIFI_RESET_IO_CLK_ENABLE();
/* configure Reset pin for Mxchip */
HAL_GPIO_WritePin(MX_WIFI_RESET_IO_PORT, MX_WIFI_RESET_IO_PIN, GPIO_PIN_SET);
GPIO_Init.Pin = MX_WIFI_RESET_IO_PIN;
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(MX_WIFI_RESET_IO_PORT, &GPIO_Init);
}
#ifdef NET_MXCHIP_LOCAL_MSP
/**
* @brief UART MSP Initialization
* This function configures the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (huart->Instance == USARTmxc)
{
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* Enable GPIO TX/RX clock */
USARTmxc_TX_GPIO_CLK_ENABLE();
USARTmxc_RX_GPIO_CLK_ENABLE();
/* Enable USARTx clock */
USARTmxc_CLK_ENABLE();
/*##-2- Configure peripheral GPIO ##########################################*/
/* UART TX GPIO pin configuration */
GPIO_InitStruct.Pin = USARTmxc_TX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = USARTmxc_TX_AF;
HAL_GPIO_Init(USARTmxc_TX_GPIO_PORT, &GPIO_InitStruct);
/* UART RX GPIO pin configuration */
GPIO_InitStruct.Pin = USARTmxc_RX_PIN;
GPIO_InitStruct.Alternate = USARTmxc_RX_AF;
HAL_GPIO_Init(USARTmxc_RX_GPIO_PORT, &GPIO_InitStruct);
}
}
/**
* @brief UART MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspDeInit(UART_HandleTypeDef *huart)
{
if (huart->Instance == USARTmxc)
{
USARTmxc_FORCE_RESET();
USARTmxc_RELEASE_RESET();
USARTmxc_CLK_DISABLE();
/*##-2- Disable peripherals and GPIO Clocks ################################*/
/* Configure UART Tx as alternate function */
HAL_GPIO_DeInit(USARTmxc_TX_GPIO_PORT, USARTmxc_TX_PIN);
/* Configure UART Rx as alternate function */
HAL_GPIO_DeInit(USARTmxc_RX_GPIO_PORT, USARTmxc_RX_PIN);
}
}
#endif /* NET_MXCHIP_LOCAL_MSP */
/**
* @brief Initialize the UART
* @param None
* @retval None
*/
static int8_t MX_WIFI_UART_Init(uint16_t mode)
{
int8_t rc = 0;
MX_WIFI_RESET_IO_Init();
if (MX_WIFI_RESET == mode)
{
MX_WIFI_RESET_MODULE();
}
else
{
/* Configurate the UART to correct speed */
mx_uart.Instance = USARTmxc;
mx_uart.Init.BaudRate = MX_WIFI_UART_BAUDRATE;
mx_uart.Init.WordLength = UART_WORDLENGTH_8B;
mx_uart.Init.StopBits = UART_STOPBITS_1;
mx_uart.Init.Parity = UART_PARITY_NONE;
mx_uart.Init.Mode = UART_MODE_TX_RX;
mx_uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
mx_uart.Init.OverSampling = UART_OVERSAMPLING_16;
mx_uart.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
#ifdef UART_PRESCALER_DIV1
mx_uart.Init.ClockPrescaler = UART_PRESCALER_DIV1;
#endif /* UART_PRESCALER_DIV1 */
mx_uart.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&mx_uart) != HAL_OK)
{
while (1);
}
#if MX_WIFI_USE_UART_INTERRUPT
WiFiRxBuffer.head = 0;
WiFiRxBuffer.tail = 0;
#endif /* MX_WIFI_USE_UART_INTERRUPT */
#ifdef NET_USE_RTOS
#if (osCMSIS < 0x20000U )
wifi_uart_rx_sem = osSemaphoreCreate(osSemaphore(wifi_uart_rx_sem), 1);
#else
wifi_uart_rx_sem = osSemaphoreNew(1, 1, NULL);
#endif /* osCMSIS */
OSSEMAPHOREWAIT(wifi_uart_rx_sem, 1);
HAL_NVIC_SetPriority(UARTmxc_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY, 0);
#else
HAL_NVIC_SetPriority(UARTmxc_IRQn, 16, 0);
#endif /* NET_USE_RTOS */
HAL_NVIC_EnableIRQ(UARTmxc_IRQn);
#if MX_WIFI_USE_UART_INTERRUPT
HAL_UART_Receive_IT(&mx_uart, (uint8_t *)&WiFiRxBuffer.data[WiFiRxBuffer.tail], 1);
#endif /* MX_WIFI_USE_UART_INTERRUPT */
}
return rc;
}
/**
* @brief Deinitialize the UART
* @param None
* @retval None
*/
static int8_t MX_WIFI_UART_DeInit(void)
{
int8_t rc = 0;
if (HAL_UART_DeInit(&mx_uart) != HAL_OK)
{
while (1);
}
#ifdef NET_USE_RTOS
osSemaphoreDelete(wifi_uart_rx_sem);
#endif /* NET_USE_RTOS */
return rc;
}
#if MX_WIFI_USE_UART_INTERRUPT
/**
* @brief Rx Callback when new data is received on the UART.
* @param UartHandle: Uart handle receiving the data.
* @retval None.
*/
void MXchip_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle);
void MXchip_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
uint32_t tail;
/* WIFI UART */
/* If ring buffer end is reached reset tail pointer to start of buffer */
if (++WiFiRxBuffer.tail >= RING_BUFFER_SIZE)
{
WiFiRxBuffer.tail = 0;
}
/* ringbuffer full, overlap head */
tail = WiFiRxBuffer.tail;
if (tail == WiFiRxBuffer.head)
{
WiFiRxBuffer.head++;
}
// fired next reception
HAL_UART_Receive_IT(UartHandle, (uint8_t *)&WiFiRxBuffer.data[WiFiRxBuffer.tail], 1);
#ifdef NET_USE_RTOS
osSemaphoreRelease(wifi_uart_rx_sem);
#endif /* NET_USE_RTOS */
}
#endif /* MX_WIFI_USE_UART_INTERRUPT */
/**
* @brief Send wifi Data thru UART
* @param pdata : pointer to data
* @param len : Data length
* @param timeout : send timeout in mS
* @retval Length of sent data
*/
static int16_t MX_WIFI_UART_SendData(uint8_t *pdata, uint16_t len, uint32_t timeout)
{
int16_t rc = 0;
if (HAL_UART_Transmit(&mx_uart, pdata, len, timeout) != HAL_OK)
{
return MX_WIFI_STATUS_IO_ERROR;
}
rc = len;
/*DEBUG_LOG("MX_WIFI_TX: %d bytes, [%.*s]\r\n", len, len, pdata);*/
return rc;
}
static int16_t MX_WIFI_UART_ReceiveData(uint8_t *pdata, uint16_t request_len, uint32_t timeout)
{
int16_t len = 0;
#if MX_WIFI_USE_UART_INTERRUPT==0
len = request_len;
if (HAL_UART_Receive(&mx_uart, pdata, len, timeout) != HAL_OK)
{
return MX_WIFI_STATUS_IO_ERROR;
}
/*DEBUG_LOG("MX_WIFI_RX: %d bytes, [%.*s]\r\n", len, len, pdata);*/
#else
int32_t tail;
#ifdef NET_USE_RTOS
OSSEMAPHOREWAIT(wifi_uart_rx_sem, 1);
#endif /* NET_USE_RTOS */
tail = WiFiRxBuffer.tail;
len = ((RING_BUFFER_SIZE + tail - WiFiRxBuffer.head) % RING_BUFFER_SIZE);
if (len == 0)
{
return 0;
}
if (len > request_len)
{
len = request_len;
}
/*copy from buffer */
for (uint32_t i = 0; i < len; i++)
{
*pdata++ = WiFiRxBuffer.data[WiFiRxBuffer.head++];
if (WiFiRxBuffer.head >= RING_BUFFER_SIZE)
{
/* wrap */
WiFiRxBuffer.head = 0;
}
}
#endif /* MX_WIFI_USE_UART_INTERRUPT */
return len;
}
/**
* @brief probe function to register wifi to connectivity framwotk
* @param None
* @retval None
*/
int32_t wifi_probe(void **ll_drv_context)
{
if (MX_WIFI_RegisterBusIO(&MxWifiObj,
MX_WIFI_UART_Init,
MX_WIFI_UART_DeInit,
MX_WIFI_IO_DELAY,
MX_WIFI_UART_SendData,
MX_WIFI_UART_ReceiveData) == 0)
{
*ll_drv_context = &MxWifiObj;
return 0;
}
return -1;
}
#endif /* MX_WIFI_USE_SPI */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,66 @@
/**
******************************************************************************
* @file net_conf.h
* @author MCD Application Team
* @brief This file provides the configuration for net
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#ifndef NET_CONF_H
#define NET_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
/*#define NET_MBEDTLS_HOST_SUPPORT*/
#define NET_DBG_INFO(...)
#define NET_DBG_ERROR(...)
#define NET_DBG_PRINT(...)
#define NET_ASSERT(a,b) do { } while((a)==false)
#define NET_PRINT(...)
#define NET_PRINT_WO_CR(...)
#define NET_WARNING(...)
#define NET_USE_LWIP_DEFINITIONS
#define NET_ALLOC_BREAK 0xFFFFFFFFU
/*#define NET_ALLOC_DEBUG*/
#define NET_BYPASS_NET_SOCKET
#include <stdint.h>
void ethernetif_low_init(void (*event_callback)(void), void (*buffer_output_callback)(uint8_t *));
void ethernetif_low_deinit(void);
int16_t ethernetif_low_inputsize(void);
int16_t ethernetif_low_input(uint8_t *payload, uint16_t len);
int16_t ethernetif_low_output(uint8_t *payload, uint16_t len);
void ethernetif_low_get_mac_addr(uint8_t *MACAddr_in);
uint8_t ethernetif_low_get_link_status(void);
#define NET_USE_RTOS
#ifndef GENERATOR_WAKAAMACLIENT_CLOUD
/*#define NET_MBEDTLS_HOST_SUPPORT*/
#endif /* GENERATOR_WAKAAMACLIENT_CLOUD */
/*cstat -MISRAC2012-Rule-20.1 */
#include "net_conf_template.h"
/*cstat +MISRAC2012-Rule-20.1 */
#ifdef __cplusplus
}
#endif
#endif /* NET_CONF_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,332 @@
/**
******************************************************************************
* @file usbd_audio.h
* @author MCD Application Team
* @brief header file for the usbd_audio.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_AUDIO_H
#define __USB_AUDIO_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_AUDIO
* @brief This file is the Header file for usbd_audio.c
* @{
*/
/** @defgroup USBD_AUDIO_Exported_Defines
* @{
*/
#ifndef USBD_AUDIO_FREQ
/* AUDIO Class Config */
#define USBD_AUDIO_FREQ 48000U
#endif /* USBD_AUDIO_FREQ */
#ifndef USBD_MAX_NUM_INTERFACES
#define USBD_MAX_NUM_INTERFACES 1U
#endif /* USBD_AUDIO_FREQ */
#ifndef AUDIO_HS_BINTERVAL
#define AUDIO_HS_BINTERVAL 0x01U
#endif /* AUDIO_HS_BINTERVAL */
#ifndef AUDIO_FS_BINTERVAL
#define AUDIO_FS_BINTERVAL 0x01U
#endif /* AUDIO_FS_BINTERVAL */
#ifndef AUDIO_OUT_EP
#define AUDIO_OUT_EP 0x01U
#endif /* AUDIO_OUT_EP */
#define USB_AUDIO_CONFIG_DESC_SIZ 0x6DU
#define AUDIO_INTERFACE_DESC_SIZE 0x09U
#define USB_AUDIO_DESC_SIZ 0x09U
#define AUDIO_STANDARD_ENDPOINT_DESC_SIZE 0x09U
#define AUDIO_STREAMING_ENDPOINT_DESC_SIZE 0x07U
#define AUDIO_DESCRIPTOR_TYPE 0x21U
#define USB_DEVICE_CLASS_AUDIO 0x01U
#define AUDIO_SUBCLASS_AUDIOCONTROL 0x01U
#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02U
#define AUDIO_PROTOCOL_UNDEFINED 0x00U
#define AUDIO_STREAMING_GENERAL 0x01U
#define AUDIO_STREAMING_FORMAT_TYPE 0x02U
/* Audio Descriptor Types */
#define AUDIO_INTERFACE_DESCRIPTOR_TYPE 0x24U
#define AUDIO_ENDPOINT_DESCRIPTOR_TYPE 0x25U
/* Audio Control Interface Descriptor Subtypes */
#define AUDIO_CONTROL_HEADER 0x01U
#define AUDIO_CONTROL_INPUT_TERMINAL 0x02U
#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03U
#define AUDIO_CONTROL_FEATURE_UNIT 0x06U
#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0CU
#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09U
#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07U
#define AUDIO_CONTROL_MUTE 0x0001U
#define AUDIO_FORMAT_TYPE_I 0x01U
#define AUDIO_FORMAT_TYPE_III 0x03U
#define AUDIO_ENDPOINT_GENERAL 0x01U
#define AUDIO_REQ_GET_CUR 0x81U
#define AUDIO_REQ_SET_CUR 0x01U
#define AUDIO_OUT_STREAMING_CTRL 0x02U
#define AUDIO_OUT_TC 0x01U
#define AUDIO_IN_TC 0x02U
#define AUDIO_OUT_PACKET (uint16_t)(((USBD_AUDIO_FREQ * 2U * 2U) / 1000U))
#define AUDIO_DEFAULT_VOLUME 70U
/* Number of sub-packets in the audio transfer buffer. You can modify this value but always make sure
that it is an even number and higher than 3 */
#define AUDIO_OUT_PACKET_NUM 80U
/* Total size of the audio transfer buffer */
#define AUDIO_TOTAL_BUF_SIZE ((uint16_t)(AUDIO_OUT_PACKET * AUDIO_OUT_PACKET_NUM))
/* Audio Commands enumeration */
typedef enum
{
AUDIO_CMD_START = 1,
AUDIO_CMD_PLAY,
AUDIO_CMD_STOP,
} AUDIO_CMD_TypeDef;
typedef enum
{
AUDIO_OFFSET_NONE = 0,
AUDIO_OFFSET_HALF,
AUDIO_OFFSET_FULL,
AUDIO_OFFSET_UNKNOWN,
} AUDIO_OffsetTypeDef;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef struct
{
uint8_t cmd;
uint8_t data[USB_MAX_EP0_SIZE];
uint8_t len;
uint8_t unit;
} USBD_AUDIO_ControlTypeDef;
typedef struct
{
uint32_t alt_setting;
uint8_t buffer[AUDIO_TOTAL_BUF_SIZE];
AUDIO_OffsetTypeDef offset;
uint8_t rd_enable;
uint16_t rd_ptr;
uint16_t wr_ptr;
USBD_AUDIO_ControlTypeDef control;
} USBD_AUDIO_HandleTypeDef;
typedef struct
{
int8_t (*Init)(uint32_t AudioFreq, uint32_t Volume, uint32_t options);
int8_t (*DeInit)(uint32_t options);
int8_t (*AudioCmd)(uint8_t *pbuf, uint32_t size, uint8_t cmd);
int8_t (*VolumeCtl)(uint8_t vol);
int8_t (*MuteCtl)(uint8_t cmd);
int8_t (*PeriodicTC)(uint8_t *pbuf, uint32_t size, uint8_t cmd);
int8_t (*GetState)(void);
} USBD_AUDIO_ItfTypeDef;
/*
* Audio Class specification release 1.0
*/
/* Table 4-2: Class-Specific AC Interface Header Descriptor */
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint16_t bcdADC;
uint16_t wTotalLength;
uint8_t bInCollection;
uint8_t baInterfaceNr;
} __PACKED USBD_SpeakerIfDescTypeDef;
/* Table 4-3: Input Terminal Descriptor */
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bTerminalID;
uint16_t wTerminalType;
uint8_t bAssocTerminal;
uint8_t bNrChannels;
uint16_t wChannelConfig;
uint8_t iChannelNames;
uint8_t iTerminal;
} __PACKED USBD_SpeakerInDescTypeDef;
/* USB Speaker Audio Feature Unit Descriptor */
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bUnitID;
uint8_t bSourceID;
uint8_t bControlSize;
uint16_t bmaControls;
uint8_t iTerminal;
} __PACKED USBD_SpeakerFeatureDescTypeDef;
/* Table 4-4: Output Terminal Descriptor */
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bTerminalID;
uint16_t wTerminalType;
uint8_t bAssocTerminal;
uint8_t bSourceID;
uint8_t iTerminal;
} __PACKED USBD_SpeakerOutDescTypeDef;
/* Table 4-19: Class-Specific AS Interface Descriptor */
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bTerminalLink;
uint8_t bDelay;
uint16_t wFormatTag;
} __PACKED USBD_SpeakerStreamIfDescTypeDef;
/* USB Speaker Audio Type III Format Interface Descriptor */
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bFormatType;
uint8_t bNrChannels;
uint8_t bSubFrameSize;
uint8_t bBitResolution;
uint8_t bSamFreqType;
uint8_t tSamFreq2;
uint8_t tSamFreq1;
uint8_t tSamFreq0;
} USBD_SpeakerIIIFormatIfDescTypeDef;
/* Table 4-17: Standard AC Interrupt Endpoint Descriptor */
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
uint8_t bRefresh;
uint8_t bSynchAddress;
} __PACKED USBD_SpeakerEndDescTypeDef;
/* Table 4-21: Class-Specific AS Isochronous Audio Data Endpoint Descriptor */
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptor;
uint8_t bmAttributes;
uint8_t bLockDelayUnits;
uint16_t wLockDelay;
} __PACKED USBD_SpeakerEndStDescTypeDef;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_AUDIO;
#define USBD_AUDIO_CLASS &USBD_AUDIO
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_AUDIO_RegisterInterface(USBD_HandleTypeDef *pdev,
USBD_AUDIO_ItfTypeDef *fops);
void USBD_AUDIO_Sync(USBD_HandleTypeDef *pdev, AUDIO_OffsetTypeDef offset);
#ifdef USE_USBD_COMPOSITE
uint32_t USBD_AUDIO_GetEpPcktSze(USBD_HandleTypeDef *pdev, uint8_t If, uint8_t Ep);
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_AUDIO_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,42 @@
/**
******************************************************************************
* @file usbd_audio_if_template.h
* @author MCD Application Team
* @brief Header for usbd_audio_if_template.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_AUDIO_IF_TEMPLATE_H
#define __USBD_AUDIO_IF_TEMPLATE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_audio.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
extern USBD_AUDIO_ItfTypeDef USBD_AUDIO_Template_fops;
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /* __USBD_AUDIO_IF_TEMPLATE_H */
@@ -0,0 +1,980 @@
/**
******************************************************************************
* @file usbd_audio.c
* @author MCD Application Team
* @brief This file provides the Audio core functions.
*
*
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
* @verbatim
*
* ===================================================================
* AUDIO Class Description
* ===================================================================
* This driver manages the Audio Class 1.0 following the "USB Device Class Definition for
* Audio Devices V1.0 Mar 18, 98".
* This driver implements the following aspects of the specification:
* - Device descriptor management
* - Configuration descriptor management
* - Standard AC Interface Descriptor management
* - 1 Audio Streaming Interface (with single channel, PCM, Stereo mode)
* - 1 Audio Streaming Endpoint
* - 1 Audio Terminal Input (1 channel)
* - Audio Class-Specific AC Interfaces
* - Audio Class-Specific AS Interfaces
* - AudioControl Requests: only SET_CUR and GET_CUR requests are supported (for Mute)
* - Audio Feature Unit (limited to Mute control)
* - Audio Synchronization type: Asynchronous
* - Single fixed audio sampling rate (configurable in usbd_conf.h file)
* The current audio class version supports the following audio features:
* - Pulse Coded Modulation (PCM) format
* - sampling rate: 48KHz.
* - Bit resolution: 16
* - Number of channels: 2
* - No volume control
* - Mute/Unmute capability
* - Asynchronous Endpoints
*
* @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
******************************************************************************
*/
/* BSPDependencies
- "stm32xxxxx_{eval}{discovery}.c"
- "stm32xxxxx_{eval}{discovery}_io.c"
- "stm32xxxxx_{eval}{discovery}_audio.c"
EndBSPDependencies */
/* Includes ------------------------------------------------------------------*/
#include "usbd_audio.h"
#include "usbd_ctlreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_AUDIO
* @brief usbd core module
* @{
*/
/** @defgroup USBD_AUDIO_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_AUDIO_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_AUDIO_Private_Macros
* @{
*/
#define AUDIO_SAMPLE_FREQ(frq) \
(uint8_t)(frq), (uint8_t)((frq >> 8)), (uint8_t)((frq >> 16))
#define AUDIO_PACKET_SZE(frq) \
(uint8_t)(((frq * 2U * 2U) / 1000U) & 0xFFU), (uint8_t)((((frq * 2U * 2U) / 1000U) >> 8) & 0xFFU)
#ifdef USE_USBD_COMPOSITE
#define AUDIO_PACKET_SZE_WORD(frq) (uint32_t)((((frq) * 2U * 2U)/1000U))
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/** @defgroup USBD_AUDIO_Private_FunctionPrototypes
* @{
*/
static uint8_t USBD_AUDIO_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_AUDIO_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_AUDIO_Setup(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req);
#ifndef USE_USBD_COMPOSITE
static uint8_t *USBD_AUDIO_GetCfgDesc(uint16_t *length);
static uint8_t *USBD_AUDIO_GetDeviceQualifierDesc(uint16_t *length);
#endif /* USE_USBD_COMPOSITE */
static uint8_t USBD_AUDIO_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_AUDIO_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_AUDIO_EP0_RxReady(USBD_HandleTypeDef *pdev);
static uint8_t USBD_AUDIO_EP0_TxReady(USBD_HandleTypeDef *pdev);
static uint8_t USBD_AUDIO_SOF(USBD_HandleTypeDef *pdev);
static uint8_t USBD_AUDIO_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_AUDIO_IsoOutIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
static void AUDIO_REQ_GetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static void AUDIO_REQ_SetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static void *USBD_AUDIO_GetAudioHeaderDesc(uint8_t *pConfDesc);
/**
* @}
*/
/** @defgroup USBD_AUDIO_Private_Variables
* @{
*/
USBD_ClassTypeDef USBD_AUDIO =
{
USBD_AUDIO_Init,
USBD_AUDIO_DeInit,
USBD_AUDIO_Setup,
USBD_AUDIO_EP0_TxReady,
USBD_AUDIO_EP0_RxReady,
USBD_AUDIO_DataIn,
USBD_AUDIO_DataOut,
USBD_AUDIO_SOF,
USBD_AUDIO_IsoINIncomplete,
USBD_AUDIO_IsoOutIncomplete,
#ifdef USE_USBD_COMPOSITE
NULL,
NULL,
NULL,
NULL,
#else
USBD_AUDIO_GetCfgDesc,
USBD_AUDIO_GetCfgDesc,
USBD_AUDIO_GetCfgDesc,
USBD_AUDIO_GetDeviceQualifierDesc,
#endif /* USE_USBD_COMPOSITE */
};
#ifndef USE_USBD_COMPOSITE
/* USB AUDIO device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_AUDIO_CfgDesc[USB_AUDIO_CONFIG_DESC_SIZ] __ALIGN_END =
{
/* Configuration 1 */
0x09, /* bLength */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType */
LOBYTE(USB_AUDIO_CONFIG_DESC_SIZ), /* wTotalLength */
HIBYTE(USB_AUDIO_CONFIG_DESC_SIZ),
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* 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) */
/* 09 byte*/
/* USB Speaker Standard interface descriptor */
AUDIO_INTERFACE_DESC_SIZE, /* bLength */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOCONTROL, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* 09 byte*/
/* USB Speaker Class-specific AC Interface Descriptor */
AUDIO_INTERFACE_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_HEADER, /* bDescriptorSubtype */
0x00, /* 1.00 */ /* bcdADC */
0x01,
0x27, /* wTotalLength */
0x00,
0x01, /* bInCollection */
0x01, /* baInterfaceNr */
/* 09 byte*/
/* USB Speaker Input Terminal Descriptor */
AUDIO_INPUT_TERMINAL_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_INPUT_TERMINAL, /* bDescriptorSubtype */
0x01, /* bTerminalID */
0x01, /* wTerminalType AUDIO_TERMINAL_USB_STREAMING 0x0101 */
0x01,
0x00, /* bAssocTerminal */
0x01, /* bNrChannels */
0x00, /* wChannelConfig 0x0000 Mono */
0x00,
0x00, /* iChannelNames */
0x00, /* iTerminal */
/* 12 byte*/
/* USB Speaker Audio Feature Unit Descriptor */
0x09, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_FEATURE_UNIT, /* bDescriptorSubtype */
AUDIO_OUT_STREAMING_CTRL, /* bUnitID */
0x01, /* bSourceID */
0x01, /* bControlSize */
AUDIO_CONTROL_MUTE, /* bmaControls(0) */
0, /* bmaControls(1) */
0x00, /* iTerminal */
/* 09 byte */
/* USB Speaker Output Terminal Descriptor */
0x09, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_OUTPUT_TERMINAL, /* bDescriptorSubtype */
0x03, /* bTerminalID */
0x01, /* wTerminalType 0x0301 */
0x03,
0x00, /* bAssocTerminal */
0x02, /* bSourceID */
0x00, /* iTerminal */
/* 09 byte */
/* USB Speaker Standard AS Interface Descriptor - Audio Streaming Zero Bandwidth */
/* Interface 1, Alternate Setting 0 */
AUDIO_INTERFACE_DESC_SIZE, /* bLength */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* 09 byte*/
/* USB Speaker Standard AS Interface Descriptor - Audio Streaming Operational */
/* Interface 1, Alternate Setting 1 */
AUDIO_INTERFACE_DESC_SIZE, /* bLength */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x01, /* bAlternateSetting */
0x01, /* bNumEndpoints */
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* 09 byte*/
/* USB Speaker Audio Streaming Interface Descriptor */
AUDIO_STREAMING_INTERFACE_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */
0x01, /* bTerminalLink */
0x01, /* bDelay */
0x01, /* wFormatTag AUDIO_FORMAT_PCM 0x0001 */
0x00,
/* 07 byte*/
/* USB Speaker Audio Type III Format Interface Descriptor */
0x0B, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */
AUDIO_FORMAT_TYPE_I, /* bFormatType */
0x02, /* bNrChannels */
0x02, /* bSubFrameSize : 2 Bytes per frame (16bits) */
16, /* bBitResolution (16-bits per sample) */
0x01, /* bSamFreqType only one frequency supported */
AUDIO_SAMPLE_FREQ(USBD_AUDIO_FREQ), /* Audio sampling frequency coded on 3 bytes */
/* 11 byte*/
/* Endpoint 1 - Standard Descriptor */
AUDIO_STANDARD_ENDPOINT_DESC_SIZE, /* bLength */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType */
AUDIO_OUT_EP, /* bEndpointAddress 1 out endpoint */
USBD_EP_TYPE_ISOC, /* bmAttributes */
AUDIO_PACKET_SZE(USBD_AUDIO_FREQ), /* wMaxPacketSize in Bytes (Freq(Samples)*2(Stereo)*2(HalfWord)) */
AUDIO_FS_BINTERVAL, /* bInterval */
0x00, /* bRefresh */
0x00, /* bSynchAddress */
/* 09 byte*/
/* Endpoint - Audio Streaming Descriptor */
AUDIO_STREAMING_ENDPOINT_DESC_SIZE, /* bLength */
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_ENDPOINT_GENERAL, /* bDescriptor */
0x00, /* bmAttributes */
0x00, /* bLockDelayUnits */
0x00, /* wLockDelay */
0x00,
/* 07 byte*/
} ;
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_AUDIO_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 */
static uint8_t AUDIOOutEpAdd = AUDIO_OUT_EP;
/**
* @}
*/
/** @defgroup USBD_AUDIO_Private_Functions
* @{
*/
/**
* @brief USBD_AUDIO_Init
* Initialize the AUDIO interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_AUDIO_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
USBD_AUDIO_HandleTypeDef *haudio;
/* Allocate Audio structure */
haudio = (USBD_AUDIO_HandleTypeDef *)USBD_malloc(sizeof(USBD_AUDIO_HandleTypeDef));
if (haudio == NULL)
{
pdev->pClassDataCmsit[pdev->classId] = NULL;
return (uint8_t)USBD_EMEM;
}
pdev->pClassDataCmsit[pdev->classId] = (void *)haudio;
pdev->pClassData = pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
AUDIOOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_ISOC, (uint8_t)pdev->classId);
#endif /* USE_USBD_COMPOSITE */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
pdev->ep_out[AUDIOOutEpAdd & 0xFU].bInterval = AUDIO_HS_BINTERVAL;
}
else /* LOW and FULL-speed endpoints */
{
pdev->ep_out[AUDIOOutEpAdd & 0xFU].bInterval = AUDIO_FS_BINTERVAL;
}
/* Open EP OUT */
(void)USBD_LL_OpenEP(pdev, AUDIOOutEpAdd, USBD_EP_TYPE_ISOC, AUDIO_OUT_PACKET);
pdev->ep_out[AUDIOOutEpAdd & 0xFU].is_used = 1U;
haudio->alt_setting = 0U;
haudio->offset = AUDIO_OFFSET_UNKNOWN;
haudio->wr_ptr = 0U;
haudio->rd_ptr = 0U;
haudio->rd_enable = 0U;
/* Initialize the Audio output Hardware layer */
if (((USBD_AUDIO_ItfTypeDef *)pdev->pUserData[pdev->classId])->Init(USBD_AUDIO_FREQ,
AUDIO_DEFAULT_VOLUME,
0U) != 0U)
{
return (uint8_t)USBD_FAIL;
}
/* Prepare Out endpoint to receive 1st packet */
(void)USBD_LL_PrepareReceive(pdev, AUDIOOutEpAdd, haudio->buffer,
AUDIO_OUT_PACKET);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_AUDIO_Init
* DeInitialize the AUDIO layer
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_AUDIO_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
AUDIOOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_ISOC, (uint8_t)pdev->classId);
#endif /* USE_USBD_COMPOSITE */
/* Open EP OUT */
(void)USBD_LL_CloseEP(pdev, AUDIOOutEpAdd);
pdev->ep_out[AUDIOOutEpAdd & 0xFU].is_used = 0U;
pdev->ep_out[AUDIOOutEpAdd & 0xFU].bInterval = 0U;
/* DeInit physical Interface components */
if (pdev->pClassDataCmsit[pdev->classId] != NULL)
{
((USBD_AUDIO_ItfTypeDef *)pdev->pUserData[pdev->classId])->DeInit(0U);
(void)USBD_free(pdev->pClassDataCmsit[pdev->classId]);
pdev->pClassDataCmsit[pdev->classId] = NULL;
pdev->pClassData = NULL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_AUDIO_Setup
* Handle the AUDIO specific requests
* @param pdev: instance
* @param req: usb requests
* @retval status
*/
static uint8_t USBD_AUDIO_Setup(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req)
{
USBD_AUDIO_HandleTypeDef *haudio;
uint16_t len;
uint8_t *pbuf;
uint16_t status_info = 0U;
USBD_StatusTypeDef ret = USBD_OK;
haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (haudio == NULL)
{
return (uint8_t)USBD_FAIL;
}
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_CLASS:
switch (req->bRequest)
{
case AUDIO_REQ_GET_CUR:
AUDIO_REQ_GetCurrent(pdev, req);
break;
case AUDIO_REQ_SET_CUR:
AUDIO_REQ_SetCurrent(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) == AUDIO_DESCRIPTOR_TYPE)
{
pbuf = (uint8_t *)USBD_AUDIO_GetAudioHeaderDesc(pdev->pConfDesc);
if (pbuf != NULL)
{
len = MIN(USB_AUDIO_DESC_SIZ, req->wLength);
(void)USBD_CtlSendData(pdev, pbuf, len);
}
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 *)&haudio->alt_setting, 1U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_SET_INTERFACE:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if ((uint8_t)(req->wValue) <= USBD_MAX_NUM_INTERFACES)
{
haudio->alt_setting = (uint8_t)(req->wValue);
}
else
{
/* Call the error management function (command will be NAKed */
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
}
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;
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief USBD_AUDIO_GetCfgDesc
* return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_AUDIO_GetCfgDesc(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_AUDIO_CfgDesc);
return USBD_AUDIO_CfgDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @brief USBD_AUDIO_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_AUDIO_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
UNUSED(pdev);
UNUSED(epnum);
/* Only OUT data are processed */
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_AUDIO_EP0_RxReady
* handle EP0 Rx Ready event
* @param pdev: device instance
* @retval status
*/
static uint8_t USBD_AUDIO_EP0_RxReady(USBD_HandleTypeDef *pdev)
{
USBD_AUDIO_HandleTypeDef *haudio;
haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (haudio == NULL)
{
return (uint8_t)USBD_FAIL;
}
if (haudio->control.cmd == AUDIO_REQ_SET_CUR)
{
/* In this driver, to simplify code, only SET_CUR request is managed */
if (haudio->control.unit == AUDIO_OUT_STREAMING_CTRL)
{
((USBD_AUDIO_ItfTypeDef *)pdev->pUserData[pdev->classId])->MuteCtl(haudio->control.data[0]);
haudio->control.cmd = 0U;
haudio->control.len = 0U;
}
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_AUDIO_EP0_TxReady
* handle EP0 TRx Ready event
* @param pdev: device instance
* @retval status
*/
static uint8_t USBD_AUDIO_EP0_TxReady(USBD_HandleTypeDef *pdev)
{
UNUSED(pdev);
/* Only OUT control data are processed */
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_AUDIO_SOF
* handle SOF event
* @param pdev: device instance
* @retval status
*/
static uint8_t USBD_AUDIO_SOF(USBD_HandleTypeDef *pdev)
{
UNUSED(pdev);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_AUDIO_SOF
* handle SOF event
* @param pdev: device instance
* @param offset: audio offset
* @retval status
*/
void USBD_AUDIO_Sync(USBD_HandleTypeDef *pdev, AUDIO_OffsetTypeDef offset)
{
USBD_AUDIO_HandleTypeDef *haudio;
uint32_t BufferSize = AUDIO_TOTAL_BUF_SIZE / 2U;
if (pdev->pClassDataCmsit[pdev->classId] == NULL)
{
return;
}
haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
haudio->offset = offset;
if (haudio->rd_enable == 1U)
{
haudio->rd_ptr += (uint16_t)BufferSize;
if (haudio->rd_ptr == AUDIO_TOTAL_BUF_SIZE)
{
/* roll back */
haudio->rd_ptr = 0U;
}
}
if (haudio->rd_ptr > haudio->wr_ptr)
{
if ((haudio->rd_ptr - haudio->wr_ptr) < AUDIO_OUT_PACKET)
{
BufferSize += 4U;
}
else
{
if ((haudio->rd_ptr - haudio->wr_ptr) > (AUDIO_TOTAL_BUF_SIZE - AUDIO_OUT_PACKET))
{
BufferSize -= 4U;
}
}
}
else
{
if ((haudio->wr_ptr - haudio->rd_ptr) < AUDIO_OUT_PACKET)
{
BufferSize -= 4U;
}
else
{
if ((haudio->wr_ptr - haudio->rd_ptr) > (AUDIO_TOTAL_BUF_SIZE - AUDIO_OUT_PACKET))
{
BufferSize += 4U;
}
}
}
if (haudio->offset == AUDIO_OFFSET_FULL)
{
((USBD_AUDIO_ItfTypeDef *)pdev->pUserData[pdev->classId])->AudioCmd(&haudio->buffer[0],
BufferSize, AUDIO_CMD_PLAY);
haudio->offset = AUDIO_OFFSET_NONE;
}
}
/**
* @brief USBD_AUDIO_IsoINIncomplete
* handle data ISO IN Incomplete event
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_AUDIO_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
UNUSED(pdev);
UNUSED(epnum);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_AUDIO_IsoOutIncomplete
* handle data ISO OUT Incomplete event
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_AUDIO_IsoOutIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
USBD_AUDIO_HandleTypeDef *haudio;
if (pdev->pClassDataCmsit[pdev->classId] == NULL)
{
return (uint8_t)USBD_FAIL;
}
haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
/* Prepare Out endpoint to receive next audio packet */
(void)USBD_LL_PrepareReceive(pdev, epnum,
&haudio->buffer[haudio->wr_ptr],
AUDIO_OUT_PACKET);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_AUDIO_DataOut
* handle data OUT Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_AUDIO_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
uint16_t PacketSize;
USBD_AUDIO_HandleTypeDef *haudio;
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
AUDIOOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_ISOC, (uint8_t)pdev->classId);
#endif /* USE_USBD_COMPOSITE */
haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (haudio == NULL)
{
return (uint8_t)USBD_FAIL;
}
if (epnum == AUDIOOutEpAdd)
{
/* Get received data packet length */
PacketSize = (uint16_t)USBD_LL_GetRxDataSize(pdev, epnum);
/* Packet received Callback */
((USBD_AUDIO_ItfTypeDef *)pdev->pUserData[pdev->classId])->PeriodicTC(&haudio->buffer[haudio->wr_ptr],
PacketSize, AUDIO_OUT_TC);
/* Increment the Buffer pointer or roll it back when all buffers are full */
haudio->wr_ptr += PacketSize;
if (haudio->wr_ptr >= AUDIO_TOTAL_BUF_SIZE)
{
/* All buffers are full: roll back */
haudio->wr_ptr = 0U;
if (haudio->offset == AUDIO_OFFSET_UNKNOWN)
{
((USBD_AUDIO_ItfTypeDef *)pdev->pUserData[pdev->classId])->AudioCmd(&haudio->buffer[0],
AUDIO_TOTAL_BUF_SIZE / 2U,
AUDIO_CMD_START);
haudio->offset = AUDIO_OFFSET_NONE;
}
}
if (haudio->rd_enable == 0U)
{
if (haudio->wr_ptr == (AUDIO_TOTAL_BUF_SIZE / 2U))
{
haudio->rd_enable = 1U;
}
}
/* Prepare Out endpoint to receive next audio packet */
(void)USBD_LL_PrepareReceive(pdev, AUDIOOutEpAdd,
&haudio->buffer[haudio->wr_ptr],
AUDIO_OUT_PACKET);
}
return (uint8_t)USBD_OK;
}
/**
* @brief AUDIO_Req_GetCurrent
* Handles the GET_CUR Audio control request.
* @param pdev: device instance
* @param req: setup class request
* @retval status
*/
static void AUDIO_REQ_GetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
USBD_AUDIO_HandleTypeDef *haudio;
haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (haudio == NULL)
{
return;
}
(void)USBD_memset(haudio->control.data, 0, USB_MAX_EP0_SIZE);
/* Send the current mute state */
(void)USBD_CtlSendData(pdev, haudio->control.data,
MIN(req->wLength, USB_MAX_EP0_SIZE));
}
/**
* @brief AUDIO_Req_SetCurrent
* Handles the SET_CUR Audio control request.
* @param pdev: device instance
* @param req: setup class request
* @retval status
*/
static void AUDIO_REQ_SetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
USBD_AUDIO_HandleTypeDef *haudio;
haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (haudio == NULL)
{
return;
}
if (req->wLength != 0U)
{
haudio->control.cmd = AUDIO_REQ_SET_CUR; /* Set the request value */
haudio->control.len = (uint8_t)MIN(req->wLength, USB_MAX_EP0_SIZE); /* Set the request data length */
haudio->control.unit = HIBYTE(req->wIndex); /* Set the request target unit */
/* Prepare the reception of the buffer over EP0 */
(void)USBD_CtlPrepareRx(pdev, haudio->control.data, haudio->control.len);
}
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_AUDIO_GetDeviceQualifierDesc(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_AUDIO_DeviceQualifierDesc);
return USBD_AUDIO_DeviceQualifierDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @brief USBD_AUDIO_RegisterInterface
* @param pdev: device instance
* @param fops: Audio interface callback
* @retval status
*/
uint8_t USBD_AUDIO_RegisterInterface(USBD_HandleTypeDef *pdev,
USBD_AUDIO_ItfTypeDef *fops)
{
if (fops == NULL)
{
return (uint8_t)USBD_FAIL;
}
pdev->pUserData[pdev->classId] = fops;
return (uint8_t)USBD_OK;
}
#ifdef USE_USBD_COMPOSITE
/**
* @brief USBD_AUDIO_GetEpPcktSze
* @param pdev: device instance (reserved for future use)
* @param If: Interface number (reserved for future use)
* @param Ep: Endpoint number (reserved for future use)
* @retval status
*/
uint32_t USBD_AUDIO_GetEpPcktSze(USBD_HandleTypeDef *pdev, uint8_t If, uint8_t Ep)
{
uint32_t mps;
UNUSED(pdev);
UNUSED(If);
UNUSED(Ep);
mps = AUDIO_PACKET_SZE_WORD(USBD_AUDIO_FREQ);
/* Return the wMaxPacketSize value in Bytes (Freq(Samples)*2(Stereo)*2(HalfWord)) */
return mps;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @brief USBD_AUDIO_GetAudioHeaderDesc
* This function return the Audio descriptor
* @param pdev: device instance
* @param pConfDesc: pointer to Bos descriptor
* @retval pointer to the Audio AC Header descriptor
*/
static void *USBD_AUDIO_GetAudioHeaderDesc(uint8_t *pConfDesc)
{
USBD_ConfigDescTypeDef *desc = (USBD_ConfigDescTypeDef *)(void *)pConfDesc;
USBD_DescHeaderTypeDef *pdesc = (USBD_DescHeaderTypeDef *)(void *)pConfDesc;
uint8_t *pAudioDesc = NULL;
uint16_t ptr;
if (desc->wTotalLength > desc->bLength)
{
ptr = desc->bLength;
while (ptr < desc->wTotalLength)
{
pdesc = USBD_GetNextDesc((uint8_t *)pdesc, &ptr);
if ((pdesc->bDescriptorType == AUDIO_INTERFACE_DESCRIPTOR_TYPE) &&
(pdesc->bDescriptorSubType == AUDIO_CONTROL_HEADER))
{
pAudioDesc = (uint8_t *)pdesc;
break;
}
}
}
return pAudioDesc;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,198 @@
/**
******************************************************************************
* @file usbd_cdc_if_template.c
* @author MCD Application Team
* @brief Generic media access Layer.
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* BSPDependencies
- "stm32xxxxx_{eval}{discovery}.c"
- "stm32xxxxx_{eval}{discovery}_io.c"
- "stm32xxxxx_{eval}{discovery}_audio.c"
EndBSPDependencies */
/* Includes ------------------------------------------------------------------*/
#include "usbd_audio_if_template.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_AUDIO
* @brief usbd core module
* @{
*/
/** @defgroup USBD_AUDIO_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_AUDIO_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_AUDIO_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_AUDIO_Private_FunctionPrototypes
* @{
*/
static int8_t TEMPLATE_Init(uint32_t AudioFreq, uint32_t Volume, uint32_t options);
static int8_t TEMPLATE_DeInit(uint32_t options);
static int8_t TEMPLATE_AudioCmd(uint8_t *pbuf, uint32_t size, uint8_t cmd);
static int8_t TEMPLATE_VolumeCtl(uint8_t vol);
static int8_t TEMPLATE_MuteCtl(uint8_t cmd);
static int8_t TEMPLATE_PeriodicTC(uint8_t *pbuf, uint32_t size, uint8_t cmd);
static int8_t TEMPLATE_GetState(void);
USBD_AUDIO_ItfTypeDef USBD_AUDIO_Template_fops =
{
TEMPLATE_Init,
TEMPLATE_DeInit,
TEMPLATE_AudioCmd,
TEMPLATE_VolumeCtl,
TEMPLATE_MuteCtl,
TEMPLATE_PeriodicTC,
TEMPLATE_GetState,
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief TEMPLATE_Init
* Initializes the AUDIO media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_Init(uint32_t AudioFreq, uint32_t Volume, uint32_t options)
{
UNUSED(AudioFreq);
UNUSED(Volume);
UNUSED(options);
/*
Add your initialization code here
*/
return (0);
}
/**
* @brief TEMPLATE_DeInit
* DeInitializes the AUDIO media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_DeInit(uint32_t options)
{
UNUSED(options);
/*
Add your deinitialization code here
*/
return (0);
}
/**
* @brief TEMPLATE_AudioCmd
* AUDIO command handler
* @param Buf: Buffer of data to be sent
* @param size: Number of data to be sent (in bytes)
* @param cmd: command opcode
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_AudioCmd(uint8_t *pbuf, uint32_t size, uint8_t cmd)
{
UNUSED(pbuf);
UNUSED(size);
UNUSED(cmd);
return (0);
}
/**
* @brief TEMPLATE_VolumeCtl
* @param vol: volume level (0..100)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_VolumeCtl(uint8_t vol)
{
UNUSED(vol);
return (0);
}
/**
* @brief TEMPLATE_MuteCtl
* @param cmd: vmute command
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_MuteCtl(uint8_t cmd)
{
UNUSED(cmd);
return (0);
}
/**
* @brief TEMPLATE_PeriodicTC
* @param cmd
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_PeriodicTC(uint8_t *pbuf, uint32_t size, uint8_t cmd)
{
UNUSED(pbuf);
UNUSED(size);
UNUSED(cmd);
return (0);
}
/**
* @brief TEMPLATE_GetState
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_GetState(void)
{
return (0);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,160 @@
/**
******************************************************************************
* @file usbd_billboard.h
* @author MCD Application Team
* @brief Header file for the usbd_billboard.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2019 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_BB_H
#define __USB_BB_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
#include "usbd_desc.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_BB
* @brief This file is the Header file for usbd_billboard.c
* @{
*/
/** @defgroup USBD_BB_Exported_Defines
* @{
*/
#define USB_BB_CONFIG_DESC_SIZ 18U
#ifndef USB_BB_MAX_NUM_ALT_MODE
#define USB_BB_MAX_NUM_ALT_MODE 0x2U
#endif /* USB_BB_MAX_NUM_ALT_MODE */
#ifndef USBD_BB_IF_STRING_INDEX
#define USBD_BB_IF_STRING_INDEX 0x10U
#endif /* USBD_BB_IF_STRING_INDEX */
#define USBD_BILLBOARD_CAPABILITY 0x0DU
#define USBD_BILLBOARD_ALTMODE_CAPABILITY 0x0FU
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef struct _BB_DescHeader
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDevCapabilityType;
}
USBD_BB_DescHeader_t;
typedef struct
{
uint16_t wSVID;
uint8_t bAlternateMode;
uint8_t iAlternateModeString;
} USBD_BB_AltModeTypeDef;
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDevCapabilityType;
uint8_t bIndex;
uint32_t dwAlternateModeVdo;
} USBD_BB_AltModeCapDescTypeDef;
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDevCapabilityType;
uint8_t iAddtionalInfoURL;
uint8_t bNbrOfAltModes;
uint8_t bPreferredAltMode;
uint16_t VconnPwr;
uint8_t bmConfigured[32];
uint16_t bcdVersion;
uint8_t bAdditionalFailureInfo;
uint8_t bReserved;
USBD_BB_AltModeTypeDef wSVID[USB_BB_MAX_NUM_ALT_MODE];
} USBD_BosBBCapDescTypedef;
typedef enum
{
UNSPECIFIED_ERROR = 0,
CONFIGURATION_NOT_ATTEMPTED,
CONFIGURATION_UNSUCCESSFUL,
CONFIGURATION_SUCCESSFUL,
} BB_AltModeState;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_BB;
#define USBD_BB_CLASS &USBD_BB
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
#if (USBD_CLASS_BOS_ENABLED == 1)
void *USBD_BB_GetCapDesc(USBD_HandleTypeDef *pdev, uint8_t *buf);
void *USBD_BB_GetAltModeDesc(USBD_HandleTypeDef *pdev, uint8_t *buf, uint8_t idx);
#endif /* (USBD_CLASS_BOS_ENABLED == 1) */
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_BB_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,502 @@
/**
******************************************************************************
* @file usbd_billboard.c
* @author MCD Application Team
* @brief This file provides the high layer firmware functions to manage the
* following functionalities of the USB BillBoard Class:
* - Initialization and Configuration of high and low layer
* - Enumeration as BillBoard Device
* - Error management
******************************************************************************
* @attention
*
* Copyright (c) 2019 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.
*
******************************************************************************
* @verbatim
*
* ===================================================================
* BillBoard Class Description
* ===================================================================
* This module manages the BillBoard class V1.2.1 following the "Device Class Definition
* for BillBoard Devices (BB) Version R1.2.1 Sept 08, 2016".
* This driver implements the following aspects of the specification:
* - Device descriptor management
* - Configuration descriptor management
* - Enumeration as an USB BillBoard device
* - Enumeration & management of BillBoard device supported alternate modes
*
* @endverbatim
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_billboard.h"
#include "usbd_ctlreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_BB
* @brief usbd core module
* @{
*/
/** @defgroup USBD_BB_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_BB_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_BB_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_BB_Private_FunctionPrototypes
* @{
*/
static uint8_t USBD_BB_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_BB_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_BB_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static uint8_t USBD_BB_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_BB_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_BB_EP0_RxReady(USBD_HandleTypeDef *pdev);
static uint8_t *USBD_BB_GetCfgDesc(uint16_t *length);
static uint8_t *USBD_BB_GetDeviceQualifierDesc(uint16_t *length);
static uint8_t *USBD_BB_GetOtherSpeedCfgDesc(uint16_t *length);
#if (USBD_CLASS_BOS_ENABLED == 1)
USBD_BB_DescHeader_t *USBD_BB_GetNextDesc(uint8_t *pbuf, uint16_t *ptr);
#endif /* USBD_CLASS_BOS_ENABLED */
/**
* @}
*/
/** @defgroup USBD_BB_Private_Variables
* @{
*/
USBD_ClassTypeDef USBD_BB =
{
USBD_BB_Init, /* Init */
USBD_BB_DeInit, /* DeInit */
USBD_BB_Setup, /* Setup */
NULL, /* EP0_TxSent */
USBD_BB_EP0_RxReady, /* EP0_RxReady */
USBD_BB_DataIn, /* DataIn */
USBD_BB_DataOut, /* DataOut */
NULL, /* SOF */
NULL,
NULL,
USBD_BB_GetCfgDesc,
USBD_BB_GetCfgDesc,
USBD_BB_GetOtherSpeedCfgDesc,
USBD_BB_GetDeviceQualifierDesc,
#if (USBD_SUPPORT_USER_STRING_DESC == 1U)
NULL,
#endif /* USBD_SUPPORT_USER_STRING_DESC */
};
/* USB Standard Device Qualifier Descriptor */
__ALIGN_BEGIN static uint8_t USBD_BB_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC, /* bLength */
USB_DESC_TYPE_DEVICE_QUALIFIER, /* bDescriptorType */
0x01, /* bcdUSB */
0x20,
0x11, /* bDeviceClass */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
0x40, /* bMaxPacketSize0 */
0x01, /* bNumConfigurations */
0x00, /* bReserved */
};
/* USB device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_BB_CfgDesc[USB_BB_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_BB_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */
0x00,
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue: Configuration value */
USBD_IDX_CONFIG_STR, /* iConfiguration: Index of string descriptor describing the configuration */
#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) */
/* 09 */
/************** Descriptor of BillBoard interface ****************/
/* 09 */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x00, /* bNumEndpoints */
0x11, /* bInterfaceClass: billboard */
0x00, /* bInterfaceSubClass */
0x00, /* nInterfaceProtocol */
USBD_BB_IF_STRING_INDEX, /* iInterface: Index of string descriptor */
};
/* USB device Other Speed Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_BB_OtherSpeedCfgDesc[USB_BB_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION,
USB_BB_CONFIG_DESC_SIZ,
0x00,
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue */
USBD_IDX_CONFIG_STR, /* 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) */
/************** Descriptor of BillBoard interface ****************/
/* 09 */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x00, /* bNumEndpoints*/
0x11, /* bInterfaceClass: billboard */
0x00, /* bInterfaceSubClass */
0x00, /* nInterfaceProtocol */
USBD_BB_IF_STRING_INDEX, /* iInterface: Index of string descriptor */
} ;
/**
* @}
*/
/** @defgroup USBD_BB_Private_Functions
* @{
*/
/**
* @brief USBD_BB_Init
* Initialize the BB interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_BB_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
/* Prevent unused argument compilation warning */
UNUSED(pdev);
UNUSED(cfgidx);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_BB_Init
* DeInitialize the BB layer
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_BB_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
/* Prevent unused argument compilation warning */
UNUSED(pdev);
UNUSED(cfgidx);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_BB_Setup
* Handle the BB specific requests
* @param pdev: instance
* @param req: usb requests
* @retval status
*/
static uint8_t USBD_BB_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
USBD_StatusTypeDef ret = USBD_OK;
uint16_t status_info = 0U;
uint16_t AltSetting = 0U;
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_CLASS:
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, (uint8_t *)&AltSetting, 1U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_SET_INTERFACE:
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_BB_DataIn
* Data sent on non-control IN endpoint
* @param pdev: device instance
* @param epnum: endpoint number
* @retval status
*/
static uint8_t USBD_BB_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
/* Prevent unused argument compilation warning */
UNUSED(pdev);
UNUSED(epnum);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_BB_DataOut
* Data received on non-control Out endpoint
* @param pdev: device instance
* @param epnum: endpoint number
* @retval status
*/
static uint8_t USBD_BB_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
/* Prevent unused argument compilation warning */
UNUSED(pdev);
UNUSED(epnum);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_BB_EP0_RxReady
* Handle EP0 Rx Ready event
* @param pdev: device instance
* @retval status
*/
static uint8_t USBD_BB_EP0_RxReady(USBD_HandleTypeDef *pdev)
{
/* Prevent unused argument compilation warning */
UNUSED(pdev);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_BB_GetCfgDesc
* return configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_BB_GetCfgDesc(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_BB_CfgDesc);
return USBD_BB_CfgDesc;
}
/**
* @brief USBD_BB_GetOtherSpeedCfgDesc
* return other speed configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_BB_GetOtherSpeedCfgDesc(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_BB_OtherSpeedCfgDesc);
return USBD_BB_OtherSpeedCfgDesc;
}
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_BB_GetDeviceQualifierDesc(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_BB_DeviceQualifierDesc);
return USBD_BB_DeviceQualifierDesc;
}
#if (USBD_CLASS_BOS_ENABLED == 1U)
/**
* @brief USBD_BB_GetNextDesc
* This function return the next descriptor header
* @param buf: Buffer where the descriptor is available
* @param ptr: data pointer inside the descriptor
* @retval next header
*/
USBD_BB_DescHeader_t *USBD_BB_GetNextDesc(uint8_t *pbuf, uint16_t *ptr)
{
USBD_BB_DescHeader_t *pnext = (USBD_BB_DescHeader_t *)(void *)pbuf;
*ptr += pnext->bLength;
pnext = (USBD_BB_DescHeader_t *)(void *)(pbuf + pnext->bLength);
return (pnext);
}
/**
* @brief USBD_BB_GetCapDesc
* This function return the Billboard Capability descriptor
* @param pdev: device instance
* @param pBosDesc: pointer to Bos descriptor
* @retval pointer to Billboard Capability descriptor
*/
void *USBD_BB_GetCapDesc(USBD_HandleTypeDef *pdev, uint8_t *pBosDesc)
{
UNUSED(pdev);
USBD_BB_DescHeader_t *pdesc = (USBD_BB_DescHeader_t *)(void *)pBosDesc;
USBD_BosDescTypeDef *desc = (USBD_BosDescTypeDef *)(void *)pBosDesc;
USBD_BosBBCapDescTypedef *pCapDesc = NULL;
uint16_t ptr;
if (desc->wTotalLength > desc->bLength)
{
ptr = desc->bLength;
while (ptr < desc->wTotalLength)
{
pdesc = USBD_BB_GetNextDesc((uint8_t *)pdesc, &ptr);
if (pdesc->bDevCapabilityType == USBD_BILLBOARD_CAPABILITY)
{
pCapDesc = (USBD_BosBBCapDescTypedef *)(void *)pdesc;
break;
}
}
}
return (void *)pCapDesc;
}
/**
* @brief USBD_BB_GetAltModeDesc
* This function return the Billboard Alternate Mode descriptor
* @param pdev: device instance
* @param pBosDesc: pointer to Bos descriptor
* @param idx: Index of requested Alternate Mode descriptor
* @retval pointer to Alternate Mode descriptor
*/
void *USBD_BB_GetAltModeDesc(USBD_HandleTypeDef *pdev, uint8_t *pBosDesc, uint8_t idx)
{
UNUSED(pdev);
USBD_BB_DescHeader_t *pdesc = (USBD_BB_DescHeader_t *)(void *)pBosDesc;
USBD_BosDescTypeDef *desc = (USBD_BosDescTypeDef *)(void *)pBosDesc;
USBD_BB_AltModeCapDescTypeDef *pAltModDesc = NULL;
uint8_t cnt = 0U;
uint16_t ptr;
if (desc->wTotalLength > desc->bLength)
{
ptr = desc->bLength;
while (ptr < desc->wTotalLength)
{
pdesc = USBD_BB_GetNextDesc((uint8_t *)pdesc, &ptr);
if (pdesc->bDevCapabilityType == USBD_BILLBOARD_ALTMODE_CAPABILITY)
{
if (cnt == idx)
{
pAltModDesc = (USBD_BB_AltModeCapDescTypeDef *)(void *)pdesc;
break;
}
else
{
cnt++;
}
}
}
}
return (void *)pAltModDesc;
}
#endif /* USBD_CLASS_BOS_ENABLED */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,373 @@
/**
******************************************************************************
* @file usbd_ccid.h
* @author MCD Application Team
* @brief header file for the usbd_ccid.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2021 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CCID_H
#define __USBD_CCID_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup usbd_cdc
* @brief This file is the Header file for usbd_ccid.c
* @{
*/
/** @defgroup usbd_cdc_Exported_Defines
* @{
*/
#ifndef CCID_IN_EP
#define CCID_IN_EP 0x81U /* EP1 for data IN */
#endif /* CCID_IN_EP */
#ifndef CCID_OUT_EP
#define CCID_OUT_EP 0x01U /* EP1 for data OUT */
#endif /* CCID_OUT_EP */
#ifndef CCID_CMD_EP
#define CCID_CMD_EP 0x82U /* EP2 for CCID commands */
#endif /* CCID_CMD_EP */
#ifndef CCID_CMD_HS_BINTERVAL
#define CCID_CMD_HS_BINTERVAL 0x10U
#endif /* CCID_CMD_HS_BINTERVAL */
#ifndef CCID_CMD_FS_BINTERVAL
#define CCID_CMD_FS_BINTERVAL 0x10U
#endif /* CCID_CMD_FS_BINTERVAL */
#define CCID_DATA_HS_MAX_PACKET_SIZE 512U /* Endpoint IN & OUT Packet size */
#define CCID_DATA_FS_MAX_PACKET_SIZE 64U /* Endpoint IN & OUT Packet size */
#define CCID_CMD_PACKET_SIZE 8U /* Control Endpoint Packet size */
#define USB_CCID_CONFIG_DESC_SIZ 93U
#define CCID_DATA_HS_IN_PACKET_SIZE CCID_DATA_HS_MAX_PACKET_SIZE
#define CCID_DATA_HS_OUT_PACKET_SIZE CCID_DATA_HS_MAX_PACKET_SIZE
#define CCID_DATA_FS_IN_PACKET_SIZE CCID_DATA_FS_MAX_PACKET_SIZE
#define CCID_DATA_FS_OUT_PACKET_SIZE CCID_DATA_FS_MAX_PACKET_SIZE
/*---------------------------------------------------------------------*/
/* CCID definitions */
/*---------------------------------------------------------------------*/
#define CCID_SEND_ENCAPSULATED_COMMAND 0x00U
#define CCID_GET_ENCAPSULATED_RESPONSE 0x01U
#define CCID_SET_COMM_FEATURE 0x02U
#define CCID_GET_COMM_FEATURE 0x03U
#define CCID_CLEAR_COMM_FEATURE 0x04U
#define CCID_SET_LINE_CODING 0x20U
#define CCID_GET_LINE_CODING 0x21U
#define CCID_SET_CONTROL_LINE_STATE 0x22U
#define CCID_SEND_BREAK 0x23U
/*---------------------------------------------------------------------*/
#define REQUEST_ABORT 0x01U
#define REQUEST_GET_CLOCK_FREQUENCIES 0x02U
#define REQUEST_GET_DATA_RATES 0x03U
/*---------------------------------------------------------------------*/
/* The Smart Card Device Class Descriptor definitions */
/*---------------------------------------------------------------------*/
#define CCID_INTERFACE_DESC_SIZE 0x09U
#define USB_DEVICE_CLASS_CCID 0x0BU
#define CCID_CLASS_DESC_SIZE 0x36U
#define CCID_DESC_TYPE 0x21U
#ifndef CCID_VOLTAGE_SUPP
#define CCID_VOLTAGE_SUPP 0x07U
#endif /* CCID_VOLTAGE_SUPP */
#ifndef USBD_CCID_PROTOCOL
#define USBD_CCID_PROTOCOL 0x03U
#endif /* USBD_CCID_PROTOCOL */
#ifndef USBD_CCID_DEFAULT_CLOCK_FREQ
#define USBD_CCID_DEFAULT_CLOCK_FREQ 3600U
#endif /* USBD_CCID_DEFAULT_CLOCK_FREQ */
#ifndef USBD_CCID_MAX_CLOCK_FREQ
#define USBD_CCID_MAX_CLOCK_FREQ USBD_CCID_DEFAULT_CLOCK_FREQ
#endif /* USBD_CCID_MAX_CLOCK_FREQ */
#ifndef USBD_CCID_DEFAULT_DATA_RATE
#define USBD_CCID_DEFAULT_DATA_RATE 9677U
#endif /* USBD_CCID_DEFAULT_DATA_RATE */
#ifndef USBD_CCID_MAX_DATA_RATE
#define USBD_CCID_MAX_DATA_RATE USBD_CCID_DEFAULT_DATA_RATE
#endif /* USBD_CCID_MAX_DATA_RATE */
#ifndef USBD_CCID_MAX_INF_FIELD_SIZE
#define USBD_CCID_MAX_INF_FIELD_SIZE 254U
#endif /* USBD_CCID_MAX_INF_FIELD_SIZE */
#ifndef CCID_MAX_BLOCK_SIZE_HEADER
#define CCID_MAX_BLOCK_SIZE_HEADER 271U
#endif /* CCID_MAX_BLOCK_SIZE_HEADER */
#define TPDU_EXCHANGE 0x01U
#define SHORT_APDU_EXCHANGE 0x02U
#define EXTENDED_APDU_EXCHANGE 0x04U
#define CHARACTER_EXCHANGE 0x00U
#ifndef EXCHANGE_LEVEL_FEATURE
#define EXCHANGE_LEVEL_FEATURE TPDU_EXCHANGE
#endif /* EXCHANGE_LEVEL_FEATURE */
#define CCID_ENDPOINT_DESC_SIZE 0x07U
#ifndef CCID_EP0_BUFF_SIZ
#define CCID_EP0_BUFF_SIZ 64U
#endif /* CCID_EP0_BUFF_SIZ */
#ifndef CCID_BULK_EPIN_SIZE
#define CCID_BULK_EPIN_SIZE 64U
#endif /* CCID_BULK_EPIN_SIZE */
#define CCID_INT_BUFF_SIZ 2U
/*---------------------------------------------------------------------*/
/*
* CCID Class specification revision 1.1
* Command Pipe. Bulk Messages
*/
/* CCID Bulk Out Command definitions */
#define PC_TO_RDR_ICCPOWERON 0x62U
#define PC_TO_RDR_ICCPOWEROFF 0x63U
#define PC_TO_RDR_GETSLOTSTATUS 0x65U
#define PC_TO_RDR_XFRBLOCK 0x6FU
#define PC_TO_RDR_GETPARAMETERS 0x6CU
#define PC_TO_RDR_RESETPARAMETERS 0x6DU
#define PC_TO_RDR_SETPARAMETERS 0x61U
#define PC_TO_RDR_ESCAPE 0x6BU
#define PC_TO_RDR_ICCCLOCK 0x6EU
#define PC_TO_RDR_T0APDU 0x6AU
#define PC_TO_RDR_SECURE 0x69U
#define PC_TO_RDR_MECHANICAL 0x71U
#define PC_TO_RDR_ABORT 0x72U
#define PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY 0x73U
/* CCID Bulk In Command definitions */
#define RDR_TO_PC_DATABLOCK 0x80U
#define RDR_TO_PC_SLOTSTATUS 0x81U
#define RDR_TO_PC_PARAMETERS 0x82U
#define RDR_TO_PC_ESCAPE 0x83U
#define RDR_TO_PC_DATARATEANDCLOCKFREQUENCY 0x84U
/* CCID Interrupt In Command definitions */
#define RDR_TO_PC_NOTIFYSLOTCHANGE 0x50U
#define RDR_TO_PC_HARDWAREERROR 0x51U
/* Bulk-only Command Block Wrapper */
#define ABDATA_SIZE 261U
#define CCID_CMD_HEADER_SIZE 10U
#define CCID_RESPONSE_HEADER_SIZE 10U
/* Number of SLOTS. For single card, this value is 1 */
#define CCID_NUMBER_OF_SLOTS 1U
#define CARD_SLOT_FITTED 1U
#define CARD_SLOT_REMOVED 0U
#define OFFSET_INT_BMESSAGETYPE 0x00U
#define OFFSET_INT_BMSLOTICCSTATE 0x01U
#define SLOT_ICC_PRESENT 0x01U
/* LSb : (0b = no ICC present, 1b = ICC present) */
#define SLOT_ICC_CHANGE 0x02U
/* MSb : (0b = no change, 1b = change) */
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
/**
* @}
*/
typedef struct
{
uint32_t bitrate;
uint8_t format;
uint8_t paritytype;
uint8_t datatype;
} USBD_CCID_LineCodingTypeDef;
typedef struct
{
uint8_t bMessageType; /* Offset = 0*/
uint32_t dwLength; /* Offset = 1, The length field (dwLength) is the length
of the message not including the 10-byte header.*/
uint8_t bSlot; /* Offset = 5*/
uint8_t bSeq; /* Offset = 6*/
uint8_t bSpecific_0; /* Offset = 7*/
uint8_t bSpecific_1; /* Offset = 8*/
uint8_t bSpecific_2; /* Offset = 9*/
uint8_t abData [ABDATA_SIZE]; /* Offset = 10, For reference, the absolute
maximum block size for a TPDU T=0 block is 260 bytes
(5 bytes command; 255 bytes data),
or for a TPDU T=1 block is 259 bytes,
or for a short APDU T=1 block is 261 bytes,
or for an extended APDU T=1 block is 65544 bytes.*/
} __PACKED USBD_CCID_BulkOut_DataTypeDef;
typedef struct
{
uint8_t bMessageType; /* Offset = 0 */
uint32_t dwLength; /* Offset = 1 */
uint8_t bSlot; /* Offset = 5, Same as Bulk-OUT message */
uint8_t bSeq; /* Offset = 6, Same as Bulk-OUT message */
uint8_t bStatus; /* Offset = 7, Slot status as defined in section 6.2.6 */
uint8_t bError; /* Offset = 8, Slot error as defined in section 6.2.6 */
uint8_t bSpecific; /* Offset = 9 */
uint8_t abData[ABDATA_SIZE]; /* Offset = 10 */
uint16_t u16SizeToSend;
} __PACKED USBD_CCID_BulkIn_DataTypeDef;
typedef struct
{
__IO uint8_t SlotStatus;
__IO uint8_t SlotStatusChange;
} USBD_CCID_SlotStatusTypeDef;
typedef struct
{
__IO uint8_t bAbortRequestFlag;
__IO uint8_t bSeq;
__IO uint8_t bSlot;
} USBD_CCID_ParamTypeDef;
/*
* CCID Class specification revision 1.1
* Smart Card Device Class Descriptor Table
*/
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdCCID;
uint8_t bMaxSlotIndex;
uint8_t bVoltageSupport;
uint32_t dwProtocols;
uint32_t dwDefaultClock;
uint32_t dwMaximumClock;
uint8_t bNumClockSupported;
uint32_t dwDataRate;
uint32_t dwMaxDataRate;
uint8_t bNumDataRatesSupported;
uint32_t dwMaxIFSD;
uint32_t dwSynchProtocols;
uint32_t dwMechanical;
uint32_t dwFeatures;
uint32_t dwMaxCCIDMessageLength;
uint8_t bClassGetResponse;
uint8_t bClassEnvelope;
uint16_t wLcdLayout;
uint8_t bPINSupport;
uint8_t bMaxCCIDBusySlots;
} __PACKED USBD_CCID_DescTypeDef;
typedef struct
{
uint8_t data[CCID_DATA_HS_MAX_PACKET_SIZE / 4U]; /* Force 32-bit alignment */
uint32_t UsbMessageLength;
uint8_t UsbIntData[CCID_CMD_PACKET_SIZE]; /* Buffer for the Interrupt In Data */
uint32_t alt_setting;
USBD_CCID_BulkIn_DataTypeDef UsbBlkInData; /* Buffer for the Out Data */
USBD_CCID_BulkOut_DataTypeDef UsbBlkOutData; /* Buffer for the In Data */
USBD_CCID_SlotStatusTypeDef SlotStatus;
USBD_CCID_ParamTypeDef USBD_CCID_Param;
__IO uint32_t MaxPcktLen;
__IO uint8_t blkt_state; /* Bulk transfer state */
uint16_t slot_nb;
uint16_t seq_nb;
} USBD_CCID_HandleTypeDef;
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_CCID;
#define USBD_CCID_CLASS &USBD_CCID
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
typedef struct _USBD_CCID_Itf
{
uint8_t (* Init)(USBD_HandleTypeDef *pdev);
uint8_t (* DeInit)(USBD_HandleTypeDef *pdev);
uint8_t (* Control)(uint8_t req, uint8_t *pbuf, uint16_t *length);
uint8_t (* Response_SendData)(USBD_HandleTypeDef *pdev, uint8_t *buf, uint16_t len);
uint8_t (* Send_Process)(uint8_t *Command, uint8_t *Data);
uint8_t (* SetSlotStatus)(USBD_HandleTypeDef *pdev);
} USBD_CCID_ItfTypeDef;
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_CCID_RegisterInterface(USBD_HandleTypeDef *pdev,
USBD_CCID_ItfTypeDef *fops);
uint8_t USBD_CCID_IntMessage(USBD_HandleTypeDef *pdev);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CCID_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,222 @@
/**
******************************************************************************
* @file usbd_ccid_cmd.h
* @author MCD Application Team
* @brief header file for the usbd_ccid_cmd.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2021 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CCID_CMD_H
#define __USBD_CCID_CMD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#ifndef __USBD_CCID_IF_H
#include "usbd_ccid_if_template.h"
#endif /* __USBD_CCID_IF_H */
#ifndef __USBD_CCID_SC_IF_H
#include "usbd_ccid_sc_if_template.h"
#endif /* __USBD_CCID_SC_IF_H */
/* Exported types ------------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/******************************************************************************/
/* ERROR CODES for USB Bulk In Messages : bError */
/******************************************************************************/
#define SLOT_NO_ERROR 0x81U
#define SLOTERROR_UNKNOWN 0x82U
/*----------------------------------------------------------------------------*/
/* Index of not supported / incorrect message parameter : 7Fh to 01h */
/* These Values are used for Return Types between Firmware Layers */
/*
Failure of a command
The CCID cannot parse one parameter or the ICC is not supporting one parameter.
Then the Slot Error register contains the index of the first bad parameter as a
positive number (1-127). For instance, if the CCID receives an ICC command to
an unimplemented slot, then the Slot Error register shall be set to 5 (index of bSlot field) */
/*
* CCID Class specification revision 1.1
*/
/* Following Parameters used in PC_to_RDR_XfrBlock */
#define SLOTERROR_BAD_LENTGH 0x01U
#define SLOTERROR_BAD_SLOT 0x05U
#define SLOTERROR_BAD_POWERSELECT 0x07U
#define SLOTERROR_BAD_PROTOCOLNUM 0x07U
#define SLOTERROR_BAD_CLOCKCOMMAND 0x07U
#define SLOTERROR_BAD_ABRFU_3B 0x07U
#define SLOTERROR_BAD_BMCHANGES 0x07U
#define SLOTERROR_BAD_BFUNCTION_MECHANICAL 0x07U
#define SLOTERROR_BAD_ABRFU_2B 0x08U
#define SLOTERROR_BAD_LEVELPARAMETER 0x08U
#define SLOTERROR_BAD_FIDI 0x0AU
#define SLOTERROR_BAD_T01CONVCHECKSUM 0x0BU
#define SLOTERROR_BAD_GUARDTIME 0x0CU
#define SLOTERROR_BAD_WAITINGINTEGER 0x0DU
#define SLOTERROR_BAD_CLOCKSTOP 0x0EU
#define SLOTERROR_BAD_IFSC 0x0FU
#define SLOTERROR_BAD_NAD 0x10U
#define SLOTERROR_BAD_DWLENGTH 0x08U
/*---------- Table 6.2-2 Slot error register when bmCommandStatus = 1 */
#define SLOTERROR_CMD_ABORTED 0xFFU
#define SLOTERROR_ICC_MUTE 0xFEU
#define SLOTERROR_XFR_PARITY_ERROR 0xFDU
#define SLOTERROR_XFR_OVERRUN 0xFCU
#define SLOTERROR_HW_ERROR 0xFBU
#define SLOTERROR_BAD_ATR_TS 0xF8U
#define SLOTERROR_BAD_ATR_TCK 0xF7U
#define SLOTERROR_ICC_PROTOCOL_NOT_SUPPORTED 0xF6U
#define SLOTERROR_ICC_CLASS_NOT_SUPPORTED 0xF5U
#define SLOTERROR_PROCEDURE_BYTE_CONFLICT 0xF4U
#define SLOTERROR_DEACTIVATED_PROTOCOL 0xF3U
#define SLOTERROR_BUSY_WITH_AUTO_SEQUENCE 0xF2U
#define SLOTERROR_PIN_TIMEOUT 0xF0U
#define SLOTERROR_PIN_CANCELLED 0xEFU
#define SLOTERROR_CMD_SLOT_BUSY 0xE0U
#define SLOTERROR_CMD_NOT_SUPPORTED 0x00U
/* Following Parameters used in PC_to_RDR_ResetParameters */
/* DEFAULT_FIDI_VALUE */
#ifndef DEFAULT_FIDI
#define DEFAULT_FIDI 0x11U
#endif /* DEFAULT_FIDI */
#ifndef DEFAULT_T01CONVCHECKSUM
#define DEFAULT_T01CONVCHECKSUM 0x00U
#endif /* DEFAULT_T01CONVCHECKSUM */
#ifndef DEFAULT_EXTRA_GUARDTIME
#define DEFAULT_EXTRA_GUARDTIME 0x00U
#endif /* DEFAULT_EXTRA_GUARDTIME */
#ifndef DEFAULT_WAITINGINTEGER
#define DEFAULT_WAITINGINTEGER 0x0AU
#endif /* DEFAULT_WAITINGINTEGER */
#ifndef DEFAULT_CLOCKSTOP
#define DEFAULT_CLOCKSTOP 0x00U
#endif /* DEFAULT_CLOCKSTOP */
#ifndef DEFAULT_IFSC
#define DEFAULT_IFSC 0x20U
#endif /* DEFAULT_IFSC */
#ifndef DEFAULT_NAD
#define DEFAULT_NAD 0x00U
#endif /* DEFAULT_NAD */
/* Following Parameters used in PC_to_RDR_IccPowerOn */
#define VOLTAGE_SELECTION_AUTOMATIC 0xFFU
#define VOLTAGE_SELECTION_3V 0x02U
#define VOLTAGE_SELECTION_5V 0x01U
#define VOLTAGE_SELECTION_1V8 0x03U
/*
Offset=0 bmICCStatus 2 bit 0, 1, 2
0 - An ICC is present and active (power is on and stable, RST is inactive)
1 - An ICC is present and inactive (not activated or shut down by hardware error)
2 - No ICC is present
3 - RFU
Offset=0 bmRFU 4 bits 0 RFU
Offset=6 bmCommandStatus 2 bits 0, 1, 2
0 - Processed without error
1 - Failed (error code provided by the error register)
2 - Time Extension is requested
3 - RFU
*/
#define BM_ICC_PRESENT_ACTIVE 0x00U
#define BM_ICC_PRESENT_INACTIVE 0x01U
#define BM_ICC_NO_ICC_PRESENT 0x02U
#define BM_COMMAND_STATUS_OFFSET 0x06U
#define BM_COMMAND_STATUS_NO_ERROR 0x00U
#define BM_COMMAND_STATUS_FAILED (0x01U << BM_COMMAND_STATUS_OFFSET)
#define BM_COMMAND_STATUS_TIME_EXTN (0x02 << BM_COMMAND_STATUS_OFFSET)
#if (ATR_T01 == 0)
#define SIZE_OF_ATR 19U
#else
#define SIZE_OF_ATR 15U
#endif /* (ATR_T01 == 0) */
/* defines for the CCID_CMD Layers */
#define LEN_PROTOCOL_STRUCT_T0 5U
#define LEN_PROTOCOL_STRUCT_T1 7U
#define BPROTOCOL_NUM_T0 0U
#define BPROTOCOL_NUM_T1 1U
/************************************************************************************/
/* ERROR CODES for RDR_TO_PC_HARDWAREERROR Message : bHardwareErrorCode */
/************************************************************************************/
#define HARDWAREERRORCODE_OVERCURRENT 0x01U
#define HARDWAREERRORCODE_VOLTAGEERROR 0x02U
#define HARDWAREERRORCODE_OVERCURRENT_IT 0x04U
#define HARDWAREERRORCODE_VOLTAGEERROR_IT 0x08U
#define CHK_PARAM_SLOT 0x01U
#define CHK_PARAM_DWLENGTH 0x02U
#define CHK_PARAM_ABRFU2 0x04U
#define CHK_PARAM_ABRFU3 0x08U
#define CHK_PARAM_CARD_PRESENT 0x10U
#define CHK_PARAM_ABORT 0x20U
#define CHK_ACTIVE_STATE 0x40U
/* Exported functions ------------------------------------------------------- */
uint8_t PC_to_RDR_IccPowerOn(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_IccPowerOff(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_GetSlotStatus(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_XfrBlock(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_GetParameters(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_ResetParameters(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_SetParameters(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_Escape(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_IccClock(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_Abort(USBD_HandleTypeDef *pdev);
uint8_t PC_TO_RDR_T0Apdu(USBD_HandleTypeDef *pdev);
uint8_t PC_TO_RDR_Mechanical(USBD_HandleTypeDef *pdev);
uint8_t PC_TO_RDR_SetDataRateAndClockFrequency(USBD_HandleTypeDef *pdev);
uint8_t PC_TO_RDR_Secure(USBD_HandleTypeDef *pdev);
void RDR_to_PC_DataBlock(uint8_t errorCode, USBD_HandleTypeDef *pdev);
void RDR_to_PC_NotifySlotChange(USBD_HandleTypeDef *pdev);
void RDR_to_PC_SlotStatus(uint8_t errorCode, USBD_HandleTypeDef *pdev);
void RDR_to_PC_Parameters(uint8_t errorCode, USBD_HandleTypeDef *pdev);
void RDR_to_PC_Escape(uint8_t errorCode, USBD_HandleTypeDef *pdev);
void RDR_to_PC_DataRateAndClockFrequency(uint8_t errorCode, USBD_HandleTypeDef *pdev);
void CCID_UpdSlotStatus(USBD_HandleTypeDef *pdev, uint8_t slotStatus);
void CCID_UpdSlotChange(USBD_HandleTypeDef *pdev, uint8_t changeStatus);
uint8_t CCID_IsSlotStatusChange(USBD_HandleTypeDef *pdev);
uint8_t CCID_CmdAbort(USBD_HandleTypeDef *pdev, uint8_t slot, uint8_t seq);
uint8_t USBD_CCID_Transfer_Data_Request(USBD_HandleTypeDef *pdev,
uint8_t *dataPointer, uint16_t dataLen);
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CCID_CMD_H */
@@ -0,0 +1,76 @@
/**
******************************************************************************
* @file usbd_ccid_if_template.h
* @author MCD Application Team
* @brief header file for the usbd_ccid_if_template.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2021 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CCID_IF_TEMPLATE_H
#define __USBD_CCID_IF_TEMPLATE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ccid.h"
#include "usbd_ccid_cmd.h"
#ifndef __USBD_CCID_SMARTCARD_H
#include "usbd_ccid_smartcard_template.h"
#endif /* __USBD_CCID_SMARTCARD_H */
/* Exported defines ----------------------------------------------------------*/
/*****************************************************************************/
/*********************** CCID Bulk Transfer State machine ********************/
/*****************************************************************************/
#define CCID_STATE_IDLE 0U
#define CCID_STATE_DATA_OUT 1U
#define CCID_STATE_RECEIVE_DATA 2U
#define CCID_STATE_SEND_RESP 3U
#define CCID_STATE_DATAIN 4U
#define CCID_STATE_UNCORRECT_LENGTH 5U
#define DIR_IN 0U
#define DIR_OUT 1U
#define BOTH_DIR 2U
/************ Value of the Interrupt transfer status to set ******************/
#define INTRSTATUS_COMPLETE 1U
#define INTRSTATUS_RESET 0U
/************** slot change status *******************************************/
#define SLOTSTATUS_CHANGED 1U
#define SLOTSTATUS_RESET 0U
/* Exported types ------------------------------------------------------------*/
extern USBD_HandleTypeDef USBD_Device;
/* CCID Interface callback */
extern USBD_CCID_ItfTypeDef USBD_CCID_If_fops;
/* Exported macros -----------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CCID_IF_TEMPLATE_H */
@@ -0,0 +1,100 @@
/**
******************************************************************************
* @file usbd_ccid_sc_if_template.h
* @author MCD Application Team
* @brief header file for the usbd_ccid_sc_if_template.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2021 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CCID_SC_IF_TEMPLATE_H
#define __USBD_CCID_SC_IF_TEMPLATE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ccid.h"
#include "usbd_ccid_cmd.h"
#ifndef __USBD_CCID_SMARTCARD_H
#include "usbd_ccid_smartcard_template.h"
#endif /* __USBD_CCID_SMARTCARD_H */
/* Exported constants --------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
typedef struct
{
uint8_t voltage; /* Voltage for the Card Already Selected */
uint8_t USART_GuardTime;
uint8_t SC_A2R_FiDi;
uint8_t SC_hostFiDi;
uint8_t USART_DefaultGuardTime;
uint32_t USART_BaudRate;
} SC_Param_t;
#pragma pack(1)
typedef struct
{
uint8_t bmFindexDindex;
uint8_t bmTCCKST0;
uint8_t bGuardTimeT0;
uint8_t bWaitingIntegerT0;
uint8_t bClockStop;
uint8_t bIfsc;
uint8_t bNad;
} Protocol_01_DataTypeDef;
#pragma pack()
extern Protocol_01_DataTypeDef ProtocolData;
extern SC_Param_t SC_Param;
/* Exported macro ------------------------------------------------------------*/
#define MAX_EXTRA_GUARD_TIME (0xFF - DEFAULT_EXTRA_GUARDTIME)
/* Following macros are used for SC_XferBlock command */
#define XFER_BLK_SEND_DATA 1U /* Command is for issuing the data */
#define XFER_BLK_RECEIVE_DATA 2U /* Command is for receiving the data */
#define XFER_BLK_NO_DATA 3U /* Command type is No data exchange */
/* Exported functions ------------------------------------------------------- */
/* APPLICATION LAYER ---------------------------------------------------------*/
void SC_Itf_InitParams(void);
void SC_Itf_IccPowerOn(uint8_t voltage);
void SC_Itf_IccPowerOff(void);
uint8_t SC_GetState(void);
uint8_t SC_Itf_XferBlock(uint8_t *ptrBlock, uint32_t blockLen,
uint16_t expectedLen,
USBD_CCID_BulkIn_DataTypeDef *CCID_BulkIn_Data);
uint8_t SC_Itf_SetParams(Protocol_01_DataTypeDef *pPtr, uint8_t T_01);
uint8_t SC_Itf_Escape(uint8_t *escapePtr, uint32_t escapeLen,
uint8_t *responseBuff, uint32_t *responseLen);
uint8_t SC_Itf_SetClock(uint8_t bClockCommand);
uint8_t SC_Itf_T0Apdu(uint8_t bmChanges, uint8_t bClassGetResponse,
uint8_t bClassEnvelope);
uint8_t SC_Itf_Mechanical(uint8_t bFunction);
uint8_t SC_Itf_SetDataRateAndClockFrequency(uint32_t dwClockFrequency,
uint32_t dwDataRate);
uint8_t SC_Itf_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter,
uint8_t *pbuf, uint32_t *returnLen);
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CCID_SC_IF_TEMPLATE_H */
@@ -0,0 +1,279 @@
/**
******************************************************************************
* @file usbd_ccid_smartcard_template.h
* @author MCD Application Team
* @brief header file for the usbd_ccid_smartcard_template.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2021 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CCID_SMARTCARD_TEMPLATE_H
#define __USBD_CCID_SMARTCARD_TEMPLATE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#ifndef __USBD_CCID_IF_H
#include "usbd_ccid_if_template.h"
#endif /* __USBD_CCID_IF_H */
/* Exported constants --------------------------------------------------------*/
#define T0_PROTOCOL 0x00U /* T0 protocol */
#define T1_PROTOCOL 0x01U /* T1 protocol */
#define DIRECT 0x3BU /* Direct bit convention */
#define INDIRECT 0x3FU /* Indirect bit convention */
#define SETUP_LENGTH 20U
#define HIST_LENGTH 20U
#define SC_TRANSMIT_TIMEOUT 200U /* Direction to transmit */
#define MAX_PROTOCOLLEVEL 7U /* Maximum levels of protocol */
#define MAX_INTERFACEBYTE 4U /* Maximum number of interface bytes per protocol */
#define LC_MAX 24U
#define SC_RECEIVE_TIMEOUT 0x8000U /* Direction to reader */
/* T=1 protocol constants */
#define T1_I_BLOCK 0x00U /* PCB (I-block: b8 = 0) */
#define T1_R_BLOCK 0x80U /* PCB (R-block: b8 b7 = 10) */
#define T1_S_BLOCK 0xC0U /* PCB (S-block: b8 b7 = 11) */
/* I block */
#define T1_I_SEQ_SHIFT 6U /* N(S) position (bit 7) */
/* R block */
#define T1_IS_ERROR(pcb) ((pcb) & 0x0FU)
#define T1_EDC_ERROR 0x01U /* [b6..b1] = 0-N(R)-0001 */
#define T1_OTHER_ERROR 0x02U /* [b6..b1] = 0-N(R)-0010 */
#define T1_R_SEQ_SHIFT 4U /* N(R) position (b5) */
/* S block */
#define T1_S_RESPONSE 0x20U /* If response: set bit b6, if request reset b6 in PCB S-Block */
#define T1_S_RESYNC 0x00U /* RESYNCH: b6->b1: 000000 of PCB S-Block */
#define T1_S_IFS 0x01U /* IFS: b6->b1: 000001 of PCB S-Block */
#define T1_S_ABORT 0x02U /* ABORT: b6->b1: 000010 of PCB S-Block */
#define T1_S_WTX 0x03U /* WTX: b6->b1: 000011 of PCB S-Block */
#define NAD 0U /* NAD byte position in the block */
#define PCB 1U /* PCB byte position in the block */
#define LEN 2U /* LEN byte position in the block */
#define DATA 3U /* The position of the first byte of INF field in the block */
/* Modifiable parameters */
#define SAD 0x0U /* Source address: reader (allowed values 0 -> 7) */
#define DAD 0x0U /* Destination address: card (allowed values 0 -> 7) */
#define IFSD_VALUE 254U /* Max length of INF field Supported by the reader */
#define SC_FILE_SIZE 0x100U /* File size */
#define SC_FILE_ID 0x0001U /* File identifier */
#define SC_CLASS 0x00U
/* Constant parameters */
#define INS_SELECT_FILE 0xA4U /* Select file instruction */
#define INS_READ_FILE 0xB0U /* Read file instruction */
#define INS_WRITE_FILE 0xD6U /* Write file instruction */
#define TRAILER_LENGTH 2U /* Trailer length (SW1 and SW2: 2 bytes) */
#define SC_T1_RECEIVE_SUCCESS 0U
#define SC_T1_BWT_TIMEOUT 1U
#define SC_T1_CWT_TIMEOUT 2U
#define DEFAULT_FIDI_VALUE 0x11U
#define PPS_REQUEST 0xFFU
/* SC Tree Structure -----------------------------------------------------------
MasterFile
________|___________
| | |
System UserData Note
------------------------------------------------------------------------------*/
/* SC ADPU Command: Operation Code -------------------------------------------*/
#define SC_CLA_NAME 0x00U
/*------------------------ Data Area Management Commands ---------------------*/
#define SC_SELECT_FILE 0xA4U
#define SC_GET_RESPONCE 0xC0U
#define SC_STATUS 0xF2U
#define SC_UPDATE_BINARY 0xD6U
#define SC_READ_BINARY 0xB0U
#define SC_WRITE_BINARY 0xD0U
#define SC_UPDATE_RECORD 0xDCU
#define SC_READ_RECORD 0xB2U
/*-------------------------- Administrative Commands -------------------------*/
#define SC_CREATE_FILE 0xE0U
/*-------------------------- Safety Management Commands ----------------------*/
#define SC_VERIFY 0x20U
#define SC_CHANGE 0x24U
#define SC_DISABLE 0x26U
#define SC_ENABLE 0x28U
#define SC_UNBLOCK 0x2CU
#define SC_EXTERNAL_AUTH 0x82U
#define SC_GET_CHALLENGE 0x84U
/*-------------------------- Smartcard Interface Byte-------------------------*/
#define SC_INTERFACEBYTE_TA 0U /* Interface byte TA(i) */
#define SC_INTERFACEBYTE_TB 1U /* Interface byte TB(i) */
#define SC_INTERFACEBYTE_TC 2U /* Interface byte TC(i) */
#define SC_INTERFACEBYTE_TD 3U /* Interface byte TD(i) */
/*-------------------------- Answer to reset Commands ------------------------*/
#define SC_GET_A2R 0x00U
/* SC STATUS: Status Code ----------------------------------------------------*/
#define SC_EF_SELECTED 0x9FU
#define SC_DF_SELECTED 0x9FU
#define SC_OP_TERMINATED 0x9000U
/* Smartcard Voltage */
#define SC_VOLTAGE_5V 0x00U
#define SC_VOLTAGE_3V 0x01U
#define SC_VOLTAGE_NOINIT 0xFFU
/*----------------- ATR Protocole supported ----------------------------------*/
#define ATR_T01 0x00U
/* Exported types ------------------------------------------------------------*/
typedef enum
{
SC_POWER_ON = 0x00,
SC_RESET_LOW = 0x01,
SC_RESET_HIGH = 0x02,
SC_ACTIVE = 0x03,
SC_ACTIVE_ON_T0 = 0x04,
SC_ACTIVE_ON_T1 = 0x05,
SC_POWER_OFF = 0x06,
SC_NO_INIT = 0x07
} SC_State;
/* Interface Byte structure - TA(i), TB(i), TC(i) and TD(i) ------------------*/
typedef struct
{
uint8_t Status; /* The Presence of the Interface byte */
uint8_t Value; /* The Value of the Interface byte */
} SC_InterfaceByteTypeDef;
/* Protocol Level structure - ------------------------------------------------*/
typedef struct
{
SC_InterfaceByteTypeDef InterfaceByte[MAX_INTERFACEBYTE]; /* The Values of the Interface byte
TA(i), TB(i), TC(i)and TD(i) */
} SC_ProtocolLevelTypeDef;
/* ATR structure - Answer To Reset -------------------------------------------*/
typedef struct
{
uint8_t TS; /* Bit Convention Direct/Indirect */
uint8_t T0; /* Each bit in the high nibble = Presence of the further interface byte;
Low nibble = Number of historical byte */
SC_ProtocolLevelTypeDef T[MAX_PROTOCOLLEVEL]; /* Setup array */
uint8_t Historical[HIST_LENGTH]; /* Historical array */
uint8_t Tlength; /* Setup array dimension */
uint8_t Hlength; /* Historical array dimension */
uint8_t TCK;
} SC_ATRTypeDef;
/* ADPU-Header command structure ---------------------------------------------*/
typedef struct
{
uint8_t CLA; /* Command class */
uint8_t INS; /* Operation code */
uint8_t P1; /* Selection Mode */
uint8_t P2; /* Selection Option */
} SC_HeaderTypeDef;
/* ADPU-Body command structure -----------------------------------------------*/
typedef struct
{
uint8_t LC; /* Data field length */
uint8_t Data[LC_MAX]; /* Command parameters */
uint8_t LE; /* Expected length of data to be returned */
} SC_BodyTypeDef;
/* ADPU Command structure ----------------------------------------------------*/
typedef struct
{
SC_HeaderTypeDef Header;
SC_BodyTypeDef Body;
} SC_ADPU_CommandsTypeDef;
/* SC response structure -----------------------------------------------------*/
typedef struct
{
uint8_t Data[LC_MAX]; /* Data returned from the card */
uint8_t SW1; /* Command Processing status */
uint8_t SW2; /* Command Processing qualification */
} SC_ADPU_ResponseTypeDef;
/* SC Command Status -----------------------------------------------------*/
typedef enum
{
SC_CS_FAILED = 0x00,
SC_CS_PIN_ENABLED = 0x01,
SC_CS_PIN_VERIFIED = 0x02,
SC_CS_READ = 0x03,
SC_CS_PIN_CHANGED = 0x04
} SC_Command_State;
/* SC Response Status -----------------------------------------------------*/
typedef enum
{
REP_OK = 0x00,
REP_NOT_OK = 0x01,
REP_NOT_SUPP = 0x02,
REP_ENABLED = 0x03,
REP_CHANGE = 0x04
} REP_Command_t;
/* Conforming of Command with ICC APP -----------------------------------------------------*/
typedef enum
{
Command_OK = 0x00,
Command_NOT_OK = 0x01,
} Command_State_t;
typedef enum
{
SC_DISABLED = 0U,
SC_ENABLED = !SC_DISABLED
} SCPowerState;
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/* APPLICATION LAYER ---------------------------------------------------------*/
void SC_Handler(SC_State *SCState, SC_ADPU_CommandsTypeDef *SC_ADPU, SC_ADPU_ResponseTypeDef *SC_Response);
void SC_PowerCmd(SCPowerState NewState);
void SC_ParityErrorHandler(void);
void SC_PTSConfig(void);
uint8_t SC_Detect(void);
uint32_t SC_GetDTableValue(uint32_t idx);
void SC_VoltageConfig(uint32_t SC_Voltage);
void SC_SetState(SC_State scState);
void SC_IOConfig(void);
extern uint8_t SC_ATR_Table[40];
extern SC_ATRTypeDef SC_A2R;
extern SC_ADPU_ResponseTypeDef SC_Response;
extern uint8_t ProtocolNUM_OUT;
extern SC_ADPU_CommandsTypeDef SC_ADPU;
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CCID_SMARTCARD_TEMPLATE_H */
@@ -0,0 +1,969 @@
/**
******************************************************************************
* @file usbd_ccid.c
* @author MCD Application Team
* @brief This file provides the high layer firmware functions to manage
* all the functionalities of the USB CCID Class:
*
******************************************************************************
* @attention
*
* Copyright (c) 2021 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.
*
******************************************************************************
* @verbatim
*
* ===================================================================
* CCID Class Driver Description
* ===================================================================
* This module manages the Specification for Integrated Circuit(s)
* Cards Interface Revision 1.1
* This driver implements the following aspects of the specification:
* - Device descriptor management
* - Configuration descriptor management
* - Enumeration as CCID device with 2 data endpoints (IN and OUT) and 1 command endpoint (IN)
* and enumeration for each implemented memory interface
* - Bulk OUT/IN data Transfers
* - Requests management
*
* @endverbatim
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_ccid.h"
#include "usbd_ccid_cmd.h"
#include "usbd_ctlreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CCID
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CCID_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CCID_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CCID_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CCID_Private_FunctionPrototypes
* @{
*/
static uint8_t USBD_CCID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_CCID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_CCID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static uint8_t USBD_CCID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_CCID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_CCID_DispatchCommand(USBD_HandleTypeDef *pdev);
static uint8_t USBD_CCID_ReceiveCmdHeader(USBD_HandleTypeDef *pdev,
uint8_t *pDst, uint16_t u8length);
#ifndef USE_USBD_COMPOSITE
static uint8_t *USBD_CCID_GetHSCfgDesc(uint16_t *length);
static uint8_t *USBD_CCID_GetFSCfgDesc(uint16_t *length);
static uint8_t *USBD_CCID_GetOtherSpeedCfgDesc(uint16_t *length);
static uint8_t *USBD_CCID_GetDeviceQualifierDescriptor(uint16_t *length);
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/** @defgroup USBD_CCID_Private_Variables
* @{
*/
static uint8_t CCIDInEpAdd = CCID_IN_EP;
static uint8_t CCIDOutEpAdd = CCID_OUT_EP;
static uint8_t CCIDCmdEpAdd = CCID_CMD_EP;
/* CCID interface class callbacks structure */
USBD_ClassTypeDef USBD_CCID =
{
USBD_CCID_Init,
USBD_CCID_DeInit,
USBD_CCID_Setup,
NULL, /*EP0_TxSent*/
NULL, /*EP0_RxReady*/
USBD_CCID_DataIn,
USBD_CCID_DataOut,
NULL, /*SOF */
NULL, /*ISOIn*/
NULL, /*ISOOut*/
#ifdef USE_USBD_COMPOSITE
NULL,
NULL,
NULL,
NULL,
#else
USBD_CCID_GetHSCfgDesc,
USBD_CCID_GetFSCfgDesc,
USBD_CCID_GetOtherSpeedCfgDesc,
USBD_CCID_GetDeviceQualifierDescriptor,
#endif /* USE_USBD_COMPOSITE */
};
#ifndef USE_USBD_COMPOSITE
/* USB CCID device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_CCID_CfgDesc[USB_CCID_CONFIG_DESC_SIZ] __ALIGN_END =
{
/* Configuration Descriptor */
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_CCID_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */
0x00,
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue: */
0x00, /* 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) */
/******************** CCID **** interface ********************/
CCID_INTERFACE_DESC_SIZE, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x03, /* bNumEndpoints: 3 endpoints used */
USB_DEVICE_CLASS_CCID, /* bInterfaceClass: user's interface for CCID */
0x00, /* bInterfaceSubClass : No subclass,
can be changed but no description in USB 2.0 Spec */
0x00, /* nInterfaceProtocol : None */
0x00, /* iInterface */
/******************* CCID class descriptor ********************/
CCID_CLASS_DESC_SIZE, /* bLength: CCID Descriptor size */
CCID_DESC_TYPE, /* bDescriptorType: Functional Descriptor type. */
0x10, /* bcdCCID(LSB): CCID Class Spec release number (1.1) */
0x01, /* bcdCCID(MSB) */
0x00, /* bMaxSlotIndex :highest available slot on this device */
CCID_VOLTAGE_SUPP, /* bVoltageSupport: bVoltageSupport: 5v, 3v and 1.8v */
LOBYTE(USBD_CCID_PROTOCOL), /* dwProtocols: supports T=0 and T=1 */
HIBYTE(USBD_CCID_PROTOCOL),
0x00,
0x00,
LOBYTE(USBD_CCID_DEFAULT_CLOCK_FREQ), /* dwDefaultClock: 3.6Mhz */
HIBYTE(USBD_CCID_DEFAULT_CLOCK_FREQ),
0x00,
0x00,
LOBYTE(USBD_CCID_MAX_CLOCK_FREQ), /* dwMaximumClock */
HIBYTE(USBD_CCID_MAX_CLOCK_FREQ),
0x00,
0x00,
0x00, /* bNumClockSupported */
LOBYTE(USBD_CCID_DEFAULT_DATA_RATE), /* dwDataRate: 9677 bps */
HIBYTE(USBD_CCID_DEFAULT_DATA_RATE),
0x00,
0x00,
LOBYTE(USBD_CCID_MAX_DATA_RATE), /* dwMaxDataRate */
HIBYTE(USBD_CCID_MAX_DATA_RATE),
0x00,
0x00,
0x35, /* bNumDataRatesSupported */
LOBYTE(USBD_CCID_MAX_INF_FIELD_SIZE), /* dwMaxIFSD: maximum IFSD supported for T=1 */
HIBYTE(USBD_CCID_MAX_INF_FIELD_SIZE),
0x00,
0x00,
0x00, 0x00, 0x00, 0x00, /* dwSynchProtocols */
0x00, 0x00, 0x00, 0x00, /* dwMechanical: no special characteristics */
0xBA, 0x04, EXCHANGE_LEVEL_FEATURE, 0x00, /* dwFeatures */
LOBYTE(CCID_MAX_BLOCK_SIZE_HEADER), /* dwMaxCCIDMessageLength: Maximum block size + header*/
HIBYTE(CCID_MAX_BLOCK_SIZE_HEADER),
0x00,
0x00,
0x00, /* bClassGetResponse*/
0x00, /* bClassEnvelope */
0x00, 0x00, /* wLcdLayout : 0000h no LCD. */
0x03, /* bPINSupport : PIN verification and PIN modification */
0x01, /* bMaxCCIDBusySlots */
/******************** CCID Endpoints ********************/
CCID_ENDPOINT_DESC_SIZE, /* Endpoint descriptor length = 7 */
USB_DESC_TYPE_ENDPOINT, /* Endpoint descriptor type */
CCID_IN_EP, /* Endpoint address (IN, address 1) */
USBD_EP_TYPE_BULK, /* Bulk endpoint type */
LOBYTE(CCID_DATA_FS_MAX_PACKET_SIZE),
HIBYTE(CCID_DATA_FS_MAX_PACKET_SIZE),
0x00, /* Polling interval in milliseconds */
CCID_ENDPOINT_DESC_SIZE, /* Endpoint descriptor length = 7 */
USB_DESC_TYPE_ENDPOINT, /* Endpoint descriptor type */
CCID_OUT_EP, /* Endpoint address (OUT, address 1) */
USBD_EP_TYPE_BULK, /* Bulk endpoint type */
LOBYTE(CCID_DATA_FS_MAX_PACKET_SIZE),
HIBYTE(CCID_DATA_FS_MAX_PACKET_SIZE),
0x00, /* Polling interval in milliseconds */
CCID_ENDPOINT_DESC_SIZE, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType:*/
CCID_CMD_EP, /* bEndpointAddress: Endpoint Address (IN) */
USBD_EP_TYPE_INTR, /* bmAttributes: Interrupt endpoint */
LOBYTE(CCID_CMD_PACKET_SIZE),
HIBYTE(CCID_CMD_PACKET_SIZE),
CCID_CMD_FS_BINTERVAL /* Polling interval in milliseconds */
};
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_CCID_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_CCID_Private_Functions
* @{
*/
/**
* @brief USBD_CCID_Init
* Initialize the CCID interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_CCID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
USBD_CCID_HandleTypeDef *hccid;
UNUSED(cfgidx);
/* Allocate CCID structure */
hccid = (USBD_CCID_HandleTypeDef *)USBD_malloc(sizeof(USBD_CCID_HandleTypeDef));
if (hccid == NULL)
{
pdev->pClassDataCmsit[pdev->classId] = NULL;
return (uint8_t)USBD_EMEM;
}
pdev->pClassDataCmsit[pdev->classId] = (void *)hccid;
pdev->pClassData = pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
CCIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
CCIDOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
CCIDCmdEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR, (uint8_t)pdev->classId);
#endif /* USE_USBD_COMPOSITE */
/* Init the CCID parameters into a state where it can receive a new command message */
hccid->USBD_CCID_Param.bAbortRequestFlag = 0U;
hccid->USBD_CCID_Param.bSeq = 0U;
hccid->USBD_CCID_Param.bSlot = 0U;
hccid->MaxPcktLen = (pdev->dev_speed == USBD_SPEED_HIGH) ? \
CCID_DATA_HS_MAX_PACKET_SIZE : CCID_DATA_FS_MAX_PACKET_SIZE;
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, CCIDInEpAdd, USBD_EP_TYPE_BULK, (uint16_t)hccid->MaxPcktLen);
pdev->ep_in[CCIDInEpAdd & 0xFU].is_used = 1U;
/* Open EP OUT */
(void)USBD_LL_OpenEP(pdev, CCIDOutEpAdd, USBD_EP_TYPE_BULK, (uint16_t)hccid->MaxPcktLen);
pdev->ep_out[CCIDOutEpAdd & 0xFU].is_used = 1U;
/* Open INTR EP IN */
(void)USBD_LL_OpenEP(pdev, CCIDCmdEpAdd,
USBD_EP_TYPE_INTR, CCID_CMD_PACKET_SIZE);
pdev->ep_in[CCIDCmdEpAdd & 0xFU].is_used = 1U;
/* Init physical Interface components */
((USBD_CCID_ItfTypeDef *)pdev->pUserData[pdev->classId])->Init(pdev);
/* Prepare Out endpoint to receive next packet */
(void)USBD_LL_PrepareReceive(pdev, CCIDOutEpAdd,
hccid->data, hccid->MaxPcktLen);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CCID_DeInit
* DeInitialize the CCID layer
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_CCID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
CCIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
CCIDOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
CCIDCmdEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR, (uint8_t)pdev->classId);
#endif /* USE_USBD_COMPOSITE */
/* Close EP IN */
(void)USBD_LL_CloseEP(pdev, CCIDInEpAdd);
pdev->ep_in[CCIDInEpAdd & 0xFU].is_used = 0U;
/* Close EP OUT */
(void)USBD_LL_CloseEP(pdev, CCIDOutEpAdd);
pdev->ep_out[CCIDOutEpAdd & 0xFU].is_used = 0U;
/* Close EP Command */
(void)USBD_LL_CloseEP(pdev, CCIDCmdEpAdd);
pdev->ep_in[CCIDCmdEpAdd & 0xFU].is_used = 0U;
/* DeInit physical Interface components */
if (pdev->pClassDataCmsit[pdev->classId] != NULL)
{
((USBD_CCID_ItfTypeDef *)pdev->pUserData[pdev->classId])->DeInit(pdev);
(void)USBD_free(pdev->pClassDataCmsit[pdev->classId]);
pdev->pClassDataCmsit[pdev->classId] = NULL;
pdev->pClassData = NULL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CCID_Setup
* Handle the CCID specific requests
* @param pdev: instance
* @param req: usb requests
* @retval status
*/
static uint8_t USBD_CCID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
USBD_CCID_ItfTypeDef *hCCIDitf = (USBD_CCID_ItfTypeDef *)pdev->pUserData[pdev->classId];
USBD_StatusTypeDef ret = USBD_OK;
uint8_t ifalt = 0U;
uint16_t status_info = 0U;
uint16_t len;
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
/* Class request */
case USB_REQ_TYPE_CLASS :
if (req->wLength != 0U)
{
len = MIN(CCID_EP0_BUFF_SIZ, req->wLength);
if ((req->bmRequest & 0x80U) != 0U)
{
hCCIDitf->Control(req->bRequest, hccid->data, &len);
(void)USBD_CtlSendData(pdev, hccid->data, len);
}
else
{
(void)USBD_CtlPrepareRx(pdev, hccid->data, len);
}
}
else
{
len = 0U;
hCCIDitf->Control(req->bRequest, (uint8_t *)&req->wValue, &len);
}
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, &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_CCID_DataIn
* Data sent on non-control IN endpoint
* @param pdev: device instance
* @param epnum: endpoint number
* @retval status
*/
static uint8_t USBD_CCID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
CCIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
CCIDCmdEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR, (uint8_t)pdev->classId);
#endif /* USE_USBD_COMPOSITE */
if (epnum == (CCIDInEpAdd & 0x7FU))
{
/* Filter the epnum by masking with 0x7f (mask of IN Direction) */
/*************** Handle Bulk Transfer IN data completion *****************/
switch (hccid->blkt_state)
{
case CCID_STATE_SEND_RESP:
/* won't wait ack to avoid missing a command */
hccid->blkt_state = CCID_STATE_IDLE;
/* Prepare EP to Receive Cmd */
(void)USBD_LL_PrepareReceive(pdev, CCID_OUT_EP,
hccid->data, hccid->MaxPcktLen);
break;
default:
break;
}
}
else if (epnum == (CCIDCmdEpAdd & 0x7FU))
{
/* Filter the epnum by masking with 0x7f (mask of IN Direction) */
/*************** Handle Interrupt Transfer IN data completion *****************/
(void)USBD_CCID_IntMessage(pdev);
}
else
{
return (uint8_t)USBD_FAIL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CCID_DataOut
* Data received on non-control Out endpoint
* @param pdev: device instance
* @param epnum: endpoint number
* @retval status
*/
static uint8_t USBD_CCID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
uint16_t CurrPcktLen;
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
CCIDOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
#endif /* USE_USBD_COMPOSITE */
if (hccid == NULL)
{
return (uint8_t)USBD_EMEM;
}
if (epnum == CCIDOutEpAdd)
{
CurrPcktLen = (uint16_t)USBD_GetRxCount(pdev, epnum);
switch (hccid->blkt_state)
{
case CCID_STATE_IDLE:
if (CurrPcktLen >= (uint16_t)CCID_CMD_HEADER_SIZE)
{
hccid->UsbMessageLength = CurrPcktLen; /* Store for future use */
/* Fill CCID_BulkOut Data Buffer from USB Buffer */
(void)USBD_CCID_ReceiveCmdHeader(pdev, (uint8_t *)&hccid->UsbBlkOutData.bMessageType,
(uint16_t)CurrPcktLen);
/*
Refer : 6 CCID Messages
The response messages always contain the exact same slot number,
and sequence number fields from the header that was contained in
the Bulk-OUT command message.
*/
hccid->UsbBlkInData.bSlot = hccid->UsbBlkOutData.bSlot;
hccid->UsbBlkInData.bSeq = hccid->UsbBlkOutData.bSeq;
if (CurrPcktLen < hccid->MaxPcktLen)
{
/* Short message, less than the EP Out Size, execute the command,
if parameter like dwLength is too big, the appropriate command will
give an error */
(void)USBD_CCID_DispatchCommand(pdev);
}
else
{
/* Check if length of data to be sent by host is > buffer size */
if (hccid->UsbBlkOutData.dwLength > (uint32_t)ABDATA_SIZE)
{
/* Too long data received.... Error ! */
hccid->blkt_state = CCID_STATE_UNCORRECT_LENGTH;
}
else
{
/* Expect more data on OUT EP */
hccid->blkt_state = CCID_STATE_RECEIVE_DATA;
/* Prepare EP to Receive next Cmd */
(void)USBD_LL_PrepareReceive(pdev, CCID_OUT_EP,
hccid->data, hccid->MaxPcktLen);
} /* if (CurrPcktLen == CCID_DATA_MAX_PACKET_SIZE) ends */
} /* if (CurrPcktLen >= CCID_DATA_MAX_PACKET_SIZE) ends */
} /* if (CurrPcktLen >= CCID_CMD_HEADER_SIZE) ends */
else
{
if (CurrPcktLen == 0x00U) /* Zero Length Packet Received */
{
hccid->blkt_state = CCID_STATE_IDLE;
}
}
break;
case CCID_STATE_RECEIVE_DATA:
hccid->UsbMessageLength += CurrPcktLen;
if (CurrPcktLen < hccid->MaxPcktLen)
{
/* Short message, less than the EP Out Size, execute the command,
if parameter like dwLength is too big, the appropriate command will
give an error */
/* Full command is received, process the Command */
(void)USBD_CCID_ReceiveCmdHeader(pdev, (uint8_t *)&hccid->UsbBlkOutData.bMessageType,
(uint16_t)CurrPcktLen);
(void)USBD_CCID_DispatchCommand(pdev);
}
else if (CurrPcktLen == hccid->MaxPcktLen)
{
if (hccid->UsbMessageLength < (hccid->UsbBlkOutData.dwLength + (uint32_t)CCID_CMD_HEADER_SIZE))
{
(void)USBD_CCID_ReceiveCmdHeader(pdev, (uint8_t *)&hccid->UsbBlkOutData.bMessageType,
(uint16_t)CurrPcktLen); /* Copy data */
/* Prepare EP to Receive next Cmd */
(void)USBD_LL_PrepareReceive(pdev, CCID_OUT_EP,
hccid->data, hccid->MaxPcktLen);
}
else if (hccid->UsbMessageLength == (hccid->UsbBlkOutData.dwLength + (uint32_t)CCID_CMD_HEADER_SIZE))
{
/* Full command is received, process the Command */
(void)USBD_CCID_ReceiveCmdHeader(pdev, (uint8_t *)&hccid->UsbBlkOutData.bMessageType,
(uint16_t)CurrPcktLen);
(void)USBD_CCID_DispatchCommand(pdev);
}
else
{
/* Too long data received.... Error ! */
hccid->blkt_state = CCID_STATE_UNCORRECT_LENGTH;
}
}
else
{
/* Too long data received.... Error ! */
hccid->blkt_state = CCID_STATE_UNCORRECT_LENGTH;
}
break;
case CCID_STATE_UNCORRECT_LENGTH:
hccid->blkt_state = CCID_STATE_IDLE;
break;
default:
break;
}
}
else
{
return (uint8_t)USBD_FAIL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CCID_DispatchCommand
* Parse the commands and Process command
* @param pdev: device instance
* @retval status value
*/
static uint8_t USBD_CCID_DispatchCommand(USBD_HandleTypeDef *pdev)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
uint8_t errorCode;
switch (hccid->UsbBlkOutData.bMessageType)
{
case PC_TO_RDR_ICCPOWERON:
errorCode = PC_to_RDR_IccPowerOn(pdev);
RDR_to_PC_DataBlock(errorCode, pdev);
break;
case PC_TO_RDR_ICCPOWEROFF:
errorCode = PC_to_RDR_IccPowerOff(pdev);
RDR_to_PC_SlotStatus(errorCode, pdev);
break;
case PC_TO_RDR_GETSLOTSTATUS:
errorCode = PC_to_RDR_GetSlotStatus(pdev);
RDR_to_PC_SlotStatus(errorCode, pdev);
break;
case PC_TO_RDR_XFRBLOCK:
errorCode = PC_to_RDR_XfrBlock(pdev);
RDR_to_PC_DataBlock(errorCode, pdev);
break;
case PC_TO_RDR_GETPARAMETERS:
errorCode = PC_to_RDR_GetParameters(pdev);
RDR_to_PC_Parameters(errorCode, pdev);
break;
case PC_TO_RDR_RESETPARAMETERS:
errorCode = PC_to_RDR_ResetParameters(pdev);
RDR_to_PC_Parameters(errorCode, pdev);
break;
case PC_TO_RDR_SETPARAMETERS:
errorCode = PC_to_RDR_SetParameters(pdev);
RDR_to_PC_Parameters(errorCode, pdev);
break;
case PC_TO_RDR_ESCAPE:
errorCode = PC_to_RDR_Escape(pdev);
RDR_to_PC_Escape(errorCode, pdev);
break;
case PC_TO_RDR_ICCCLOCK:
errorCode = PC_to_RDR_IccClock(pdev);
RDR_to_PC_SlotStatus(errorCode, pdev);
break;
case PC_TO_RDR_ABORT:
errorCode = PC_to_RDR_Abort(pdev);
RDR_to_PC_SlotStatus(errorCode, pdev);
break;
case PC_TO_RDR_T0APDU:
errorCode = PC_TO_RDR_T0Apdu(pdev);
RDR_to_PC_SlotStatus(errorCode, pdev);
break;
case PC_TO_RDR_MECHANICAL:
errorCode = PC_TO_RDR_Mechanical(pdev);
RDR_to_PC_SlotStatus(errorCode, pdev);
break;
case PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY:
errorCode = PC_TO_RDR_SetDataRateAndClockFrequency(pdev);
RDR_to_PC_DataRateAndClockFrequency(errorCode, pdev);
break;
case PC_TO_RDR_SECURE:
errorCode = PC_TO_RDR_Secure(pdev);
RDR_to_PC_DataBlock(errorCode, pdev);
break;
default:
RDR_to_PC_SlotStatus(SLOTERROR_CMD_NOT_SUPPORTED, pdev);
break;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CCID_Transfer_Data_Request
* Prepare the request response to be sent to the host
* @param pdev: device instance
* @param dataPointer: Pointer to the data buffer to send
* @param dataLen : number of bytes to send
* @retval status value
*/
uint8_t USBD_CCID_Transfer_Data_Request(USBD_HandleTypeDef *pdev,
uint8_t *dataPointer, uint16_t dataLen)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
USBD_CCID_ItfTypeDef *hCCIDitf = (USBD_CCID_ItfTypeDef *)pdev->pUserData[pdev->classId];
UNUSED(dataPointer);
hccid->blkt_state = CCID_STATE_SEND_RESP;
hccid->UsbMessageLength = (uint32_t)dataLen; /* Store for future use */
/* use the header declared size packet must be well formed */
hCCIDitf->Response_SendData(pdev, (uint8_t *)&hccid->UsbBlkInData,
(uint16_t)MIN(CCID_DATA_FS_MAX_PACKET_SIZE, hccid->UsbMessageLength));
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CCID_ReceiveCmdHeader
* Receive the Data from USB BulkOut Buffer to Pointer
* @param pdev: device instance
* @param pDst: destination address to copy the buffer
* @param u8length: length of data to copy
* @retval status
*/
static uint8_t USBD_CCID_ReceiveCmdHeader(USBD_HandleTypeDef *pdev,
uint8_t *pDst, uint16_t u8length)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
uint8_t *pdst = pDst;
uint32_t Counter;
for (Counter = 0U; Counter < u8length; Counter++)
{
*pdst = hccid->data[Counter];
pdst++;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CCID_IntMessage
* Send the Interrupt-IN data to the host
* @param pdev: device instance
* @retval None
*/
uint8_t USBD_CCID_IntMessage(USBD_HandleTypeDef *pdev)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
CCIDCmdEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR, (uint8_t)pdev->classId);
#endif /* USE_USBD_COMPOSITE */
/* Check if there is change in Smartcard Slot status */
if (CCID_IsSlotStatusChange(pdev) != 0U)
{
/* Check Slot Status is changed. Card is Removed/Fitted */
RDR_to_PC_NotifySlotChange(pdev);
/* Set the Slot status */
((USBD_CCID_ItfTypeDef *)pdev->pUserData[pdev->classId])->SetSlotStatus(pdev);
(void)USBD_LL_Transmit(pdev, CCIDCmdEpAdd, hccid->UsbIntData, 2U);
}
else
{
/* Set the Slot status */
((USBD_CCID_ItfTypeDef *)pdev->pUserData[pdev->classId])->SetSlotStatus(pdev);
}
return (uint8_t)USBD_OK;
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief USBD_CCID_GetHSCfgDesc
* Return configuration descriptor
* @param length pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CCID_GetHSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CCID_CfgDesc, CCID_IN_EP);
USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_CCID_CfgDesc, CCID_OUT_EP);
USBD_EpDescTypeDef *pEpCmdDesc = USBD_GetEpDesc(USBD_CCID_CfgDesc, CCID_CMD_EP);
if (pEpInDesc != NULL)
{
pEpInDesc->wMaxPacketSize = CCID_DATA_HS_MAX_PACKET_SIZE;
}
if (pEpOutDesc != NULL)
{
pEpOutDesc->wMaxPacketSize = CCID_DATA_HS_MAX_PACKET_SIZE;
}
if (pEpCmdDesc != NULL)
{
pEpCmdDesc->bInterval = CCID_CMD_HS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_CCID_CfgDesc);
return USBD_CCID_CfgDesc;
}
/**
* @brief USBD_CCID_GetFSCfgDesc
* Return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CCID_GetFSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CCID_CfgDesc, CCID_IN_EP);
USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_CCID_CfgDesc, CCID_OUT_EP);
USBD_EpDescTypeDef *pEpCmdDesc = USBD_GetEpDesc(USBD_CCID_CfgDesc, CCID_CMD_EP);
if (pEpInDesc != NULL)
{
pEpInDesc->wMaxPacketSize = CCID_DATA_FS_MAX_PACKET_SIZE;
}
if (pEpOutDesc != NULL)
{
pEpOutDesc->wMaxPacketSize = CCID_DATA_FS_MAX_PACKET_SIZE;
}
if (pEpCmdDesc != NULL)
{
pEpCmdDesc->bInterval = CCID_CMD_FS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_CCID_CfgDesc);
return USBD_CCID_CfgDesc;
}
/**
* @brief USBD_CCID_GetOtherSpeedCfgDesc
* Return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CCID_GetOtherSpeedCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CCID_CfgDesc, CCID_IN_EP);
USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_CCID_CfgDesc, CCID_OUT_EP);
USBD_EpDescTypeDef *pEpCmdDesc = USBD_GetEpDesc(USBD_CCID_CfgDesc, CCID_CMD_EP);
if (pEpInDesc != NULL)
{
pEpInDesc->wMaxPacketSize = CCID_DATA_FS_MAX_PACKET_SIZE;
}
if (pEpOutDesc != NULL)
{
pEpOutDesc->wMaxPacketSize = CCID_DATA_FS_MAX_PACKET_SIZE;
}
if (pEpCmdDesc != NULL)
{
pEpCmdDesc->bInterval = CCID_CMD_FS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_CCID_CfgDesc);
return USBD_CCID_CfgDesc;
}
/**
* @brief USBD_CCID_GetDeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CCID_GetDeviceQualifierDescriptor(uint16_t *length)
{
*length = (uint16_t)(sizeof(USBD_CCID_DeviceQualifierDesc));
return USBD_CCID_DeviceQualifierDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @brief USBD_CCID_RegisterInterface
* @param pdev: device instance
* @param fops: CD Interface callback
* @retval status
*/
uint8_t USBD_CCID_RegisterInterface(USBD_HandleTypeDef *pdev,
USBD_CCID_ItfTypeDef *fops)
{
if (fops == NULL)
{
return (uint8_t)USBD_FAIL;
}
pdev->pUserData[pdev->classId] = fops;
return (uint8_t)USBD_OK;
}
/**
* @}
*/
@@ -0,0 +1,270 @@
/**
******************************************************************************
* @file usbd_ccid_if_template.c
* @author MCD Application Team
* @brief This file provides all the functions for USB Interface for CCID
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_ccid.h"
#include "usbd_ccid_if_template.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static REP_Command_t REP_command;
/* Private function prototypes -----------------------------------------------*/
static uint8_t CCID_Init(USBD_HandleTypeDef *pdev);
static uint8_t CCID_DeInit(USBD_HandleTypeDef *pdev);
static uint8_t CCID_ControlReq(uint8_t req, uint8_t *pbuf, uint16_t *length);
static uint8_t CCID_Response_SendData(USBD_HandleTypeDef *pdev, uint8_t *buf, uint16_t len);
static uint8_t CCID_Send_Process(uint8_t *Command, uint8_t *Data);
static uint8_t CCID_Response_Process(void);
static uint8_t CCID_SetSlotStatus(USBD_HandleTypeDef *pdev);
/* Private functions ---------------------------------------------------------*/
/**
* @}
*/
USBD_CCID_ItfTypeDef USBD_CCID_If_fops =
{
CCID_Init,
CCID_DeInit,
CCID_ControlReq,
CCID_Response_SendData,
CCID_Send_Process,
CCID_SetSlotStatus,
};
/**
* @brief CCID_Init
* Initialize the CCID USB Layer
* @param pdev: device instance
* @retval status value
*/
uint8_t CCID_Init(USBD_HandleTypeDef *pdev)
{
#ifdef USE_USBD_COMPOSITE
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#else
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassData;
#endif /* USE_USBD_COMPOSITE */
/* CCID Related Initialization */
hccid->blkt_state = CCID_STATE_IDLE;
return (uint8_t)USBD_OK;
}
/**
* @brief CCID_DeInit
* Uninitialize the CCID Machine
* @param pdev: device instance
* @retval status value
*/
uint8_t CCID_DeInit(USBD_HandleTypeDef *pdev)
{
#ifdef USE_USBD_COMPOSITE
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#else
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassData;
#endif /* USE_USBD_COMPOSITE */
hccid->blkt_state = CCID_STATE_IDLE;
return (uint8_t)USBD_OK;
}
/**
* @brief CCID_ControlReq
* Manage the CCID class requests
* @param Cmd: Command code
* @param Buf: Buffer containing command data (request parameters)
* @param Len: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static uint8_t CCID_ControlReq(uint8_t req, uint8_t *pbuf, uint16_t *length)
{
#ifdef USE_USBD_COMPOSITE
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)USBD_Device.pClassDataCmsit[USBD_Device.classId];
#else
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)USBD_Device.pClassData;
#endif /* USE_USBD_COMPOSITE */
UNUSED(length);
switch (req)
{
case REQUEST_ABORT:
/* The wValue field contains the slot number (bSlot) in the low byte
and the sequence number (bSeq) in the high byte.*/
hccid->slot_nb = ((uint16_t) * pbuf & 0x0fU);
hccid->seq_nb = (((uint16_t) * pbuf & 0xf0U) >> 8);
if (CCID_CmdAbort(&USBD_Device, (uint8_t)hccid->slot_nb, (uint8_t)hccid->seq_nb) != 0U)
{
/* If error is returned by lower layer :
Generally Slot# may not have matched */
return (int8_t)USBD_FAIL;
}
break;
case REQUEST_GET_CLOCK_FREQUENCIES:
/* User have to fill the pbuf with the GetClockFrequency data buffer */
break;
case REQUEST_GET_DATA_RATES:
/* User have to fill the pbuf with the GetDataRates data buffer */
break;
default:
break;
}
UNUSED(pbuf);
return ((int8_t)USBD_OK);
}
/**
* @brief CCID_Response_SendData
* Send the data on bulk-in EP
* @param pdev: device instance
* @param buf: pointer to data buffer
* @param len: Data Length
* @retval status value
*/
uint8_t CCID_Response_SendData(USBD_HandleTypeDef *pdev, uint8_t *buf, uint16_t len)
{
(void)USBD_LL_Transmit(pdev, CCID_IN_EP, buf, len);
return (uint8_t)USBD_OK;
}
/**
* @brief CCID_SEND_Process
* @param Command: pointer to a buffer containing command header
* @param Data: pointer to a buffer containing data sent from Host
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static uint8_t CCID_Send_Process(uint8_t *Command, uint8_t *Data)
{
Command_State_t Command_State = Command_NOT_OK;
/* Initialize ICC APP header */
uint8_t SC_Command[5] = {0};
UNUSED(Data);
UNUSED(Command_State);
UNUSED(SC_Command);
/* Start SC Demo ---------------------------------------------------------*/
switch (Command[1]) /* type of instruction */
{
case SC_ENABLE:
/* Add your code here */
break;
case SC_VERIFY:
/* Add your code here */
break;
case SC_READ_BINARY :
/* Add your code here */
break;
case SC_CHANGE :
/* Add your code here */
break;
default:
break;
}
/* check if Command header is OK */
(void)CCID_Response_Process(); /* Get ICC response */
return ((uint8_t)USBD_OK);
}
/**
* @brief CCID_Response_Process
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static uint8_t CCID_Response_Process(void)
{
switch (REP_command)
{
case REP_OK:
/* Add your code here */
break;
case REP_NOT_OK :
/* Add your code here */
break;
case REP_NOT_SUPP :
/* Add your code here */
break;
case REP_ENABLED :
/* Add your code here */
break;
case REP_CHANGE :
/* Add your code here */
break;
default:
break;
}
return ((uint8_t)USBD_OK);
}
/**
* @brief CCID_SetSlotStatus
* Set Slot Status of the Interrupt Transfer
* @param pdev: device instance
* @retval status
*/
uint8_t CCID_SetSlotStatus(USBD_HandleTypeDef *pdev)
{
/* Get the CCID handler pointer */
#ifdef USE_USBD_COMPOSITE
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#else
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassData;
#endif /* USE_USBD_COMPOSITE */
if ((hccid->SlotStatus.SlotStatus) == 1U) /* Transfer Complete Status
of previous Interrupt transfer */
{
/* Add your code here */
}
else
{
/* Add your code here */
}
return (uint8_t)USBD_OK;
}
@@ -0,0 +1,473 @@
/**
******************************************************************************
* @file usbd_ccid_sc_if_template.c
* @author MCD Application Team
* @brief SmartCard Interface file
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_ccid_sc_if_template.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* State Machine for the SmartCard Interface */
static SC_State SCState = SC_POWER_OFF;
/* APDU Transport Structures */
SC_ADPU_CommandsTypeDef SC_ADPU;
SC_ADPU_ResponseTypeDef SC_Response;
SC_Param_t SC_Param;
Protocol_01_DataTypeDef ProtocolData;
/* Extern variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static void SC_SaveVoltage(uint8_t voltage);
static void SC_Itf_UpdateParams(void);
/* Private functions ---------------------------------------------------------*/
/**
* @brief SC_Itf_IccPowerOn Manages the Warm and Cold Reset
and get the Answer to Reset from ICC
* @param voltage: required by host
* @retval None
*/
void SC_Itf_IccPowerOn(uint8_t voltage)
{
SCState = SC_POWER_ON;
SC_ADPU.Header.CLA = 0x00U;
SC_ADPU.Header.INS = SC_GET_A2R;
SC_ADPU.Header.P1 = 0x00U;
SC_ADPU.Header.P2 = 0x00U;
SC_ADPU.Body.LC = 0x00U;
/* Power ON the card */
SC_PowerCmd(SC_ENABLED);
/* Configure the Voltage, Even if IO is still not configured */
SC_VoltageConfig(voltage);
while ((SCState != SC_ACTIVE_ON_T0) && (SCState != SC_ACTIVE_ON_T1)
&& (SCState != SC_NO_INIT))
{
/* If Either The Card has become Active or Become De-Active */
SC_Handler(&SCState, &SC_ADPU, &SC_Response);
}
if ((SCState == SC_ACTIVE_ON_T0) || (SCState == SC_ACTIVE_ON_T1))
{
SC_Itf_UpdateParams();
/* Apply the Procedure Type Selection (PTS) */
SC_PTSConfig();
/* Save Voltage for Future use */
SC_SaveVoltage(voltage);
}
return;
}
/**
* @brief SC_Itf_IccPowerOff Power OFF the card
* @param None
* @retval None
*/
void SC_Itf_IccPowerOff(void)
{
SC_PowerCmd(SC_DISABLED);
SC_SetState(SC_POWER_OFF);
return;
}
/**
* @brief Initialize the parameters structures to the default value
* @param None
* @retval None
*/
void SC_Itf_InitParams(void)
{
/*
FI, the reference to a clock rate conversion factor
over the bits b8 to b5
- DI, the reference to a baud rate adjustment factor
over the bits b4 to bl
*/
SC_Param.SC_A2R_FiDi = DEFAULT_FIDI;
SC_Param.SC_hostFiDi = DEFAULT_FIDI;
ProtocolData.bmFindexDindex = DEFAULT_FIDI;
/* Placeholder, Ignored */
/* 0 = Direct, first byte of the ICC ATR data. */
ProtocolData.bmTCCKST0 = DEFAULT_T01CONVCHECKSUM;
/* Extra GuardTime = 0 etu */
ProtocolData.bGuardTimeT0 = DEFAULT_EXTRA_GUARDTIME;
ProtocolData.bWaitingIntegerT0 = DEFAULT_WAITINGINTEGER;
ProtocolData.bClockStop = 0U; /* Stopping the Clock is not allowed */
/*T=1 protocol */
ProtocolData.bIfsc = DEFAULT_IFSC;
ProtocolData.bNad = DEFAULT_NAD;
return;
}
/**
* @brief Save the A2R Parameters for further usage
* @param None
* @retval None
*/
static void SC_Itf_UpdateParams(void)
{
/*
FI, the reference to a clock rate conversion factor
over the bits b8 to b5
DI, the reference to a baud rate adjustment factor
over the bits b4 to bl
*/
SC_Param.SC_A2R_FiDi = SC_A2R.T[0].InterfaceByte[0].Value;
SC_Param.SC_hostFiDi = SC_A2R.T[0].InterfaceByte[0].Value;
ProtocolData.bmFindexDindex = SC_A2R.T[0].InterfaceByte[0].Value;
return;
}
/**
* @brief SC_Itf_SetParams
* Set the parameters for CCID/USART interface
* @param pPtr: pointer to buffer containing the
* parameters to be set in USART
* @param T_01: type of protocol, T=1 or T=0
* @retval status value
*/
uint8_t SC_Itf_SetParams(Protocol_01_DataTypeDef *pPtr, uint8_t T_01)
{
/* uint16_t guardTime; */ /* Keep it 16b for handling 8b additions */
uint32_t fi_new;
uint32_t di_new;
Protocol_01_DataTypeDef New_DataStructure;
fi_new = pPtr->bmFindexDindex;
di_new = pPtr->bmFindexDindex;
New_DataStructure.bmTCCKST0 = pPtr->bmTCCKST0;
New_DataStructure.bGuardTimeT0 = pPtr->bGuardTimeT0;
New_DataStructure.bWaitingIntegerT0 = pPtr->bWaitingIntegerT0;
New_DataStructure.bClockStop = pPtr->bClockStop;
if (T_01 == 0x01U)
{
New_DataStructure.bIfsc = pPtr->bIfsc;
New_DataStructure.bNad = pPtr->bNad;
}
else
{
New_DataStructure.bIfsc = 0x00U;
New_DataStructure.bNad = 0x00U;
}
/* Check for the FIDI Value set by Host */
di_new &= (uint8_t)0x0F;
if (SC_GetDTableValue(di_new) == 0U)
{
return SLOTERROR_BAD_FIDI;
}
fi_new >>= 4U;
fi_new &= 0x0FU;
if (SC_GetDTableValue(fi_new) == 0U)
{
return SLOTERROR_BAD_FIDI;
}
if ((T_01 == 0x00U)
&& (New_DataStructure.bmTCCKST0 != 0x00U)
&& (New_DataStructure.bmTCCKST0 != 0x02U))
{
return SLOTERROR_BAD_T01CONVCHECKSUM;
}
if ((T_01 == 0x01U)
&& (New_DataStructure.bmTCCKST0 != 0x10U)
&& (New_DataStructure.bmTCCKST0 != 0x11U)
&& (New_DataStructure.bmTCCKST0 != 0x12U)
&& (New_DataStructure.bmTCCKST0 != 0x13U))
{
return SLOTERROR_BAD_T01CONVCHECKSUM;
}
if ((New_DataStructure.bWaitingIntegerT0 >= 0xA0U)
&& ((New_DataStructure.bmTCCKST0 & 0x10U) == 0x10U))
{
return SLOTERROR_BAD_WAITINGINTEGER;
}
if ((New_DataStructure.bClockStop != 0x00U)
&& (New_DataStructure.bClockStop != 0x03U))
{
return SLOTERROR_BAD_CLOCKSTOP;
}
if (New_DataStructure.bNad != 0x00U)
{
return SLOTERROR_BAD_NAD;
}
/* Put Total GuardTime in USART Settings */
/* USART_SetGuardTime(SC_USART, (uint8_t)(guardTime + DEFAULT_EXTRA_GUARDTIME)); */
/* Save Extra GuardTime Value */
ProtocolData.bGuardTimeT0 = New_DataStructure.bGuardTimeT0;
ProtocolData.bmTCCKST0 = New_DataStructure.bmTCCKST0;
ProtocolData.bWaitingIntegerT0 = New_DataStructure.bWaitingIntegerT0;
ProtocolData.bClockStop = New_DataStructure.bClockStop;
ProtocolData.bIfsc = New_DataStructure.bIfsc;
ProtocolData.bNad = New_DataStructure.bNad;
/* Save New bmFindexDindex */
SC_Param.SC_hostFiDi = pPtr->bmFindexDindex;
SC_PTSConfig();
ProtocolData.bmFindexDindex = pPtr->bmFindexDindex;
return SLOT_NO_ERROR;
}
/**
* @brief SC_Itf_Escape function from the host
* This is user implementable
* @param ptrEscape: pointer to buffer containing the Escape data
* @param escapeLen: length of escaped data
* @param responseBuff: pointer containing escape buffer response
* @param responseLen: length of escape response buffer
* @retval status value
*/
uint8_t SC_Itf_Escape(uint8_t *ptrEscape, uint32_t escapeLen,
uint8_t *responseBuff, uint32_t *responseLen)
{
UNUSED(ptrEscape);
UNUSED(escapeLen);
UNUSED(responseBuff);
UNUSED(responseLen);
/* Manufacturer specific implementation ... */
/*
uint32_t idx;
uint8_t *pResBuff = responseBuff;
uint8_t *pEscape = ptrEscape;
for(idx = 0; idx < escapeLen; idx++)
{
*pResBuff = *pEscape;
pResBuff++;
pEscape++;
}
*responseLen = escapeLen;
*/
return SLOT_NO_ERROR;
}
/**
* @brief SC_Itf_SetClock function to define Clock Status request from the host.
* This is user implementable
* @param bClockCommand: Clock status from the host
* @retval status value
*/
uint8_t SC_Itf_SetClock(uint8_t bClockCommand)
{
/* bClockCommand
00h restarts Clock
01h Stops Clock in the state shown in the bClockStop
field of the PC_to_RDR_SetParameters command
and RDR_to_PC_Parameters message.*/
if (bClockCommand == 0U)
{
/* 00h restarts Clock : Since Clock is always running, PASS this command */
return SLOT_NO_ERROR;
}
else
{
if (bClockCommand == 1U)
{
return SLOTERROR_BAD_CLOCKCOMMAND;
}
}
return SLOTERROR_CMD_NOT_SUPPORTED;
}
/**
* @brief SC_Itf_XferBlock function from the host.
* This is user implementable
* @param ptrBlock : Pointer containing the data from host
* @param blockLen : length of block data for the data transfer
* @param expectedLen: expected length of data transfer
* @param CCID_BulkIn_Data: Pointer containing the CCID Bulk In Data Structure
* @retval status value
*/
uint8_t SC_Itf_XferBlock(uint8_t *ptrBlock, uint32_t blockLen, uint16_t expectedLen,
USBD_CCID_BulkIn_DataTypeDef *CCID_BulkIn_Data)
{
uint8_t ErrorCode = SLOT_NO_ERROR;
UNUSED(CCID_BulkIn_Data);
UNUSED(expectedLen);
UNUSED(blockLen);
UNUSED(ptrBlock);
if (ProtocolNUM_OUT == 0x00U)
{
/* Add your code here */
}
if (ProtocolNUM_OUT == 0x01U)
{
/* Add your code here */
}
if (ErrorCode != SLOT_NO_ERROR)
{
return ErrorCode;
}
return ErrorCode;
}
/**
* @brief SC_Itf_T0Apdu
Class Specific Request from the host to provide supported data rates
* This is Optional function & user implementable
* @param bmChanges : value specifying which parameter is valid in
* command among next bClassGetResponse, bClassEnvelope
* @param bClassGetResponse : Value to force the class byte of the
* header in a Get Response command.
* @param bClassEnvelope : Value to force the class byte of the header
* in a Envelope command.
* @retval status value
*/
uint8_t SC_Itf_T0Apdu(uint8_t bmChanges, uint8_t bClassGetResponse,
uint8_t bClassEnvelope)
{
UNUSED(bClassEnvelope);
UNUSED(bClassGetResponse);
/* User have to fill the pbuf with the GetDataRates data buffer */
if (bmChanges == 0U)
{
/* Bit cleared indicates that the associated field is not significant and
that default behaviour defined in CCID class descriptor is selected */
return SLOT_NO_ERROR;
}
return SLOTERROR_CMD_NOT_SUPPORTED;
}
/**
* @brief SC_Itf_Mechanical
Mechanical Function being requested by Host
* This is Optional function & user implementable
* @param bFunction : value corresponds to the mechanical function
* being requested by host
* @retval status value
*/
uint8_t SC_Itf_Mechanical(uint8_t bFunction)
{
UNUSED(bFunction);
return SLOTERROR_CMD_NOT_SUPPORTED;
}
/**
* @brief SC_Itf_SetDataRateAndClockFrequency
* Set the Clock and data Rate of the Interface
* This is Optional function & user implementable
* @param dwClockFrequency : value of clock in kHz requested by host
* @param dwDataRate : value of data rate requested by host
* @retval status value
*/
uint8_t SC_Itf_SetDataRateAndClockFrequency(uint32_t dwClockFrequency,
uint32_t dwDataRate)
{
/* User have to fill the pbuf with the GetDataRates data buffer */
if ((dwDataRate == USBD_CCID_DEFAULT_DATA_RATE) &&
(dwClockFrequency == USBD_CCID_DEFAULT_CLOCK_FREQ))
{
return SLOT_NO_ERROR;
}
return SLOTERROR_CMD_NOT_SUPPORTED;
}
/**
* @brief SC_Itf_Secure
* Process the Secure command
* This is Optional function & user implementable
* @param dwLength : length of data from the host
* @param bBWI : Block Waiting Timeout sent by host
* @param wLevelParameter : Parameters sent by host
* @param pbuf : buffer containing the data
* @param returnLen : Length of data expected to return
* @retval status value
*/
uint8_t SC_Itf_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter,
uint8_t *pbuf, uint32_t *returnLen)
{
UNUSED(pbuf);
UNUSED(wLevelParameter);
UNUSED(bBWI);
UNUSED(dwLength);
*returnLen = 0U;
return SLOTERROR_CMD_NOT_SUPPORTED;
}
/**
* @brief SC_SaveVoltage
Saves the voltage value to be saved for further usage
* @param voltage: voltage value to be saved for further usage
* @retval None
*/
static void SC_SaveVoltage(uint8_t voltage)
{
SC_Param.voltage = voltage;
return;
}
/**
* @brief Provides the value of SCState variable
* @param None
* @retval uint8_t SCState
*/
uint8_t SC_GetState(void)
{
return (uint8_t)SCState;
}
/**
* @brief Set the value of SCState variable to Off
* @param scState: value of SCState to be updated
* @retval None
*/
void SC_SetState(SC_State scState)
{
SCState = scState;
return;
}
@@ -0,0 +1,486 @@
/**
******************************************************************************
* @file usbd_ccid_smartcard_template.c
* @author MCD Application Team
* @brief This file provides all the Smartcard firmware functions.
******************************************************************************
* @attention
*
* Copyright (c) 2021 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.
*
******************************************************************************
*/
/** @addtogroup usbd_ccid_Smartcard
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_ccid_smartcard_template.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Directories & Files ID */
/*The following Directories & Files ID can take any of following Values and can
be used in the smartcard application */
/*
const uint8_t MasterRoot[2] = {0x3F, 0x00};
const uint8_t GSMDir[2] = {0x7F, 0x20};
const uint8_t ICCID[2] = {0x2F, 0xE2};
const uint8_t IMSI[2] = {0x6F, 0x07};
__IO uint8_t ICCID_Content[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint32_t CHV1Status = 0U;
uint8_t CHV1[8] = {'0', '0', '0', '0', '0', '0', '0', '0'};
__IO uint8_t IMSI_Content[9] = {0x01, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
*/
/* F Table: Clock Rate Conversion Table from ISO/IEC 7816-3 */
/* static uint32_t F_Table[16] = {372, 372, 558, 744, 1116, 1488, 1860, 0, 0, 512, 768,
1024, 1536, 2048, 0, 0
}; */
/* D Table: Baud Rate Adjustment Factor Table from ISO/IEC 7816-3 */
static uint32_t D_Table[16] = {0, 1, 2, 4, 8, 16, 32, 64, 12, 20, 0, 0, 0, 0, 0, 0};
/* Global variables definition and initialization ----------------------------*/
SC_ATRTypeDef SC_A2R;
uint8_t SC_ATR_Table[40];
uint8_t ProtocolNUM_OUT;
/* Private function prototypes -----------------------------------------------*/
static void SC_Init(void);
static void SC_DeInit(void);
static void SC_AnswerReq(SC_State *SC_state, uint8_t *card, uint8_t length); /* Ask ATR */
static uint8_t SC_decode_Answer2reset(uint8_t *card); /* Decode ATR */
static void SC_SendData(SC_ADPU_CommandsTypeDef *SCADPU, SC_ADPU_ResponseTypeDef *SC_ResponseStatus);
/* static void SC_Reset(GPIO_PinState ResetState); */
/* Private functions ---------------------------------------------------------*/
/**
* @brief Handles all Smartcard states and serves to send and receive all
* communication data between Smartcard and reader.
* @param SCState: pointer to an SC_State enumeration that will contain the
* Smartcard state.
* @param SC_ADPU: pointer to an SC_ADPU_Commands structure that will be initialized.
* @param SC_Response: pointer to a SC_ADPU_Response structure which will be initialized.
* @retval None
*/
void SC_Handler(SC_State *SCState, SC_ADPU_CommandsTypeDef *SC_ADPU, SC_ADPU_ResponseTypeDef *SC_Response)
{
uint32_t i;
uint32_t j;
switch (*SCState)
{
case SC_POWER_ON:
if (SC_ADPU->Header.INS == SC_GET_A2R)
{
/* Smartcard initialization */
SC_Init();
/* Reset Data from SC buffer */
for (i = 0U; i < 40U; i++)
{
SC_ATR_Table[i] = 0;
}
/* Reset SC_A2R Structure */
SC_A2R.TS = 0U;
SC_A2R.T0 = 0U;
for (i = 0U; i < MAX_PROTOCOLLEVEL; i++)
{
for (j = 0U; j < MAX_INTERFACEBYTE; j++)
{
SC_A2R.T[i].InterfaceByte[j].Status = 0U;
SC_A2R.T[i].InterfaceByte[j].Value = 0U;
}
}
for (i = 0U; i < HIST_LENGTH; i++)
{
SC_A2R.Historical[i] = 0U;
}
SC_A2R.Tlength = 0U;
SC_A2R.Hlength = 0U;
/* Next State */
*SCState = SC_RESET_LOW;
}
break;
case SC_RESET_LOW:
if (SC_ADPU->Header.INS == SC_GET_A2R)
{
/* If card is detected then Power ON, Card Reset and wait for an answer) */
if (SC_Detect() != 0U)
{
while (((*SCState) != SC_POWER_OFF) && ((*SCState) != SC_ACTIVE))
{
SC_AnswerReq(SCState, &SC_ATR_Table[0], 40U); /* Check for answer to reset */
}
}
else
{
(*SCState) = SC_POWER_OFF;
}
}
break;
case SC_ACTIVE:
if (SC_ADPU->Header.INS == SC_GET_A2R)
{
uint8_t protocol = SC_decode_Answer2reset(&SC_ATR_Table[0]);
if (protocol == T0_PROTOCOL)
{
(*SCState) = SC_ACTIVE_ON_T0;
ProtocolNUM_OUT = T0_PROTOCOL;
}
else if (protocol == T1_PROTOCOL)
{
(*SCState) = SC_ACTIVE_ON_T1;
ProtocolNUM_OUT = T1_PROTOCOL;
}
else
{
(*SCState) = SC_POWER_OFF;
}
}
break;
case SC_ACTIVE_ON_T0:
/* process commands other than ATR */
SC_SendData(SC_ADPU, SC_Response);
break;
case SC_ACTIVE_ON_T1:
/* process commands other than ATR */
SC_SendData(SC_ADPU, SC_Response);
break;
case SC_POWER_OFF:
SC_DeInit(); /* Disable Smartcard interface */
break;
default:
(*SCState) = SC_POWER_OFF;
break;
}
}
/**
* @brief Enables or disables the power to the Smartcard.
* @param NewState: new state of the Smartcard power supply.
* This parameter can be: SC_ENABLED or SC_DISABLED.
* @retval None
*/
void SC_PowerCmd(SCPowerState NewState)
{
UNUSED(NewState);
/* enable or disable smartcard pin */
return;
}
/**
* @brief Sets or clears the Smartcard reset pin.
* @param ResetState: this parameter specifies the state of the Smartcard
* reset pin. BitVal must be one of the BitAction enum values:
* @arg Bit_RESET: to clear the port pin.
* @arg Bit_SET: to set the port pin.
* @retval None
*/
/* static void SC_Reset(GPIO_PinState ResetState)
{
UNUSED(ResetState);
return;
}
*/
/**
* @brief Resends the byte that failed to be received (by the Smartcard) correctly.
* @param None
* @retval None
*/
void SC_ParityErrorHandler(void)
{
/* Add your code here */
return;
}
/**
* @brief Configures the IO speed (BaudRate) communication.
* @param None
* @retval None
*/
void SC_PTSConfig(void)
{
/* Add your code here */
return;
}
/**
* @brief Manages the Smartcard transport layer: send APDU commands and receives
* the APDU response.
* @param SC_ADPU: pointer to a SC_ADPU_Commands structure which will be initialized.
* @param SC_Response: pointer to a SC_ADPU_Response structure which will be initialized.
* @retval None
*/
static void SC_SendData(SC_ADPU_CommandsTypeDef *SCADPU, SC_ADPU_ResponseTypeDef *SC_ResponseStatus)
{
uint8_t i;
uint8_t SC_Command[5];
uint8_t SC_DATA[LC_MAX];
UNUSED(SCADPU);
/* Reset response buffer */
for (i = 0U; i < LC_MAX; i++)
{
SC_ResponseStatus->Data[i] = 0U;
SC_DATA[i] = 0U;
}
/* User to add code here */
/* send command to ICC and get response status */
USBD_CCID_If_fops.Send_Process((uint8_t *)&SC_Command, (uint8_t *)&SC_DATA);
}
/**
* @brief SC_AnswerReq
Requests the reset answer from card.
* @param SC_state: pointer to an SC_State enumeration that will contain the Smartcard state.
* @param atr_buffer: pointer to a buffer which will contain the card ATR.
* @param length: maximum ATR length
* @retval None
*/
static void SC_AnswerReq(SC_State *SC_state, uint8_t *atr_buffer, uint8_t length)
{
UNUSED(length);
UNUSED(atr_buffer);
/* to be implemented by USER */
switch (*SC_state)
{
case SC_RESET_LOW:
/* Check response with reset low */
(*SC_state) = SC_ACTIVE;
break;
case SC_ACTIVE:
break;
case SC_RESET_HIGH:
/* Check response with reset high */
break;
case SC_POWER_OFF:
/* Close Connection if no answer received */
break;
default:
(*SC_state) = SC_RESET_LOW;
break;
}
return;
}
/**
* @brief SC_decode_Answer2reset
Decodes the Answer to reset received from card.
* @param card: pointer to the buffer containing the card ATR.
* @retval None
*/
static uint8_t SC_decode_Answer2reset(uint8_t *card)
{
uint32_t i = 0U;
uint32_t flag = 0U;
uint32_t protocol;
uint8_t index = 0U;
uint8_t level = 0U;
/******************************TS/T0 Decode************************************/
index++;
SC_A2R.TS = card[index]; /* Initial character */
index++;
SC_A2R.T0 = card[index]; /* Format character */
/*************************Historical Table Length Decode***********************/
SC_A2R.Hlength = SC_A2R.T0 & 0x0FU;
/******************************Protocol Level(1) Decode************************/
/* Check TD(1) if present */
if ((SC_A2R.T0 & 0x80U) == 0x80U)
{
flag = 1U;
}
/* Each bits in the T0 high nibble(b8 to b5) equal to 1 indicates the presence
of a further interface byte */
for (i = 0U; i < 4U; i++)
{
if ((((SC_A2R.T0 & 0xF0U) >> (4U + i)) & 0x1U) != 0U)
{
SC_A2R.T[level].InterfaceByte[i].Status = 1U;
index++;
SC_A2R.T[level].InterfaceByte[i].Value = card[index];
SC_A2R.Tlength++;
}
}
/*****************************T Decode*****************************************/
if (SC_A2R.T[level].InterfaceByte[3].Status == 1U)
{
/* Only the protocol(parameter T) present in TD(1) is detected
if two or more values of parameter T are present in TD(1), TD(2)..., so the
firmware should be updated to support them */
protocol = (uint8_t)(SC_A2R.T[level].InterfaceByte[SC_INTERFACEBYTE_TD].Value & 0x0FU);
}
else
{
protocol = 0U;
}
/* Protocol Level Increment */
/******************************Protocol Level(n>1) Decode**********************/
while (flag != 0U)
{
if ((SC_A2R.T[level].InterfaceByte[SC_INTERFACEBYTE_TD].Value & 0x80U) == 0x80U)
{
flag = 1U;
}
else
{
flag = 0U;
}
/* Each bits in the high nibble(b8 to b5) for the TD(i) equal to 1 indicates
the presence of a further interface byte */
for (i = 0U; i < 4U; i++)
{
if ((((SC_A2R.T[level].InterfaceByte[SC_INTERFACEBYTE_TD].Value & 0xF0U) >> (4U + i)) & 0x1U) != 0U)
{
SC_A2R.T[level + 1U].InterfaceByte[i].Status = 1U;
index++;
SC_A2R.T[level + 1U].InterfaceByte[i].Value = card[index];
SC_A2R.Tlength++;
}
}
level++;
}
for (i = 0U; i < SC_A2R.Hlength; i++)
{
SC_A2R.Historical[i] = card[i + 2U + SC_A2R.Tlength];
}
/*************************************TCK Decode*******************************/
SC_A2R.TCK = card[SC_A2R.Hlength + 2U + SC_A2R.Tlength];
return (uint8_t)protocol;
}
/**
* @brief Initializes all peripheral used for Smartcard interface.
* @param None
* @retval None
*/
static void SC_Init(void)
{
/*
Add your initialization code here
*/
return;
}
/**
* @brief Deinitializes all resources used by the Smartcard interface.
* @param None
* @retval None
*/
static void SC_DeInit(void)
{
/*
Add your deinitialization code here
*/
return;
}
/**
* @brief Configures the card power voltage.
* @param SC_Voltage: specifies the card power voltage.
* This parameter can be one of the following values:
* @arg SC_VOLTAGE_5V: 5V cards.
* @arg SC_VOLTAGE_3V: 3V cards.
* @retval None
*/
void SC_VoltageConfig(uint32_t SC_Voltage)
{
UNUSED(SC_Voltage);
/* Add your code here */
return;
}
/**
* @brief Configures GPIO hardware resources used for Samrtcard.
* @param None
* @retval None
*/
void SC_IOConfig(void)
{
/* Add your code here */
return;
}
/**
* @brief Detects whether the Smartcard is present or not.
* @param None.
* @retval 1 - Smartcard inserted
* 0 - Smartcard not inserted
*/
uint8_t SC_Detect(void)
{
uint8_t PIN_State = 0U;
/* Add your code here */
return PIN_State;
}
/**
* @brief Get the Right Value from the D_Table Index
* @param idx : Index to Read from the Table
* @retval Value read from the Table
*/
uint32_t SC_GetDTableValue(uint32_t idx)
{
return D_Table[idx];
}
@@ -0,0 +1,184 @@
/**
******************************************************************************
* @file usbd_cdc.h
* @author MCD Application Team
* @brief header file for the usbd_cdc.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_CDC_H
#define __USB_CDC_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @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 */
#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_HS_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);
#ifdef USE_USBD_COMPOSITE
uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff,
uint32_t length, uint8_t ClassId);
uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev, uint8_t ClassId);
#else
uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff,
uint32_t length);
uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev);
#endif /* USE_USBD_COMPOSITE */
uint8_t USBD_CDC_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff);
uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_CDC_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,43 @@
/**
******************************************************************************
* @file usbd_cdc_if_template.h
* @author MCD Application Team
* @brief Header for usbd_cdc_if_template.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CDC_IF_TEMPLATE_H
#define __USBD_CDC_IF_TEMPLATE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
extern USBD_CDC_ItfTypeDef USBD_CDC_Template_fops;
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CDC_IF_TEMPLATE_H */
@@ -0,0 +1,893 @@
/**
******************************************************************************
* @file usbd_cdc.c
* @author MCD Application Team
* @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
*
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
* @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
*
******************************************************************************
*/
/* BSPDependencies
- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c"
- "stm32xxxxx_{eval}{discovery}_io.c"
EndBSPDependencies */
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc.h"
#include "usbd_ctlreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @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)
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) */
/*---------------------------------------------------------------------------*/
/* 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, (uint8_t)pdev->classId);
CDCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
CDCCmdEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR, (uint8_t)pdev->classId);
#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, (uint8_t)pdev->classId);
CDCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
CDCCmdEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR, (uint8_t)pdev->classId);
#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: length of data to be sent
* @param ClassId: The Class ID
* @retval status
*/
#ifdef USE_USBD_COMPOSITE
uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev,
uint8_t *pbuff, uint32_t length, uint8_t ClassId)
{
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[ClassId];
#else
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];
#endif /* USE_USBD_COMPOSITE */
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
* @param ClassId: The Class ID
* @retval status
*/
#ifdef USE_USBD_COMPOSITE
uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev, uint8_t ClassId)
{
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[ClassId];
#else
uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev)
{
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif /* USE_USBD_COMPOSITE */
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, ClassId);
#endif /* USE_USBD_COMPOSITE */
if (hcdc == 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, (uint8_t)pdev->classId);
#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,247 @@
/**
******************************************************************************
* @file usbd_cdc_if_template.c
* @author MCD Application Team
* @brief Generic media access Layer.
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* BSPDependencies
- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c"
- "stm32xxxxx_{eval}{discovery}_io.c"
EndBSPDependencies */
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if_template.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @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 int8_t TEMPLATE_Init(void);
static int8_t TEMPLATE_DeInit(void);
static int8_t TEMPLATE_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length);
static int8_t TEMPLATE_Receive(uint8_t *pbuf, uint32_t *Len);
static int8_t TEMPLATE_TransmitCplt(uint8_t *pbuf, uint32_t *Len, uint8_t epnum);
USBD_CDC_ItfTypeDef USBD_CDC_Template_fops =
{
TEMPLATE_Init,
TEMPLATE_DeInit,
TEMPLATE_Control,
TEMPLATE_Receive,
TEMPLATE_TransmitCplt
};
USBD_CDC_LineCodingTypeDef linecoding =
{
115200, /* baud rate*/
0x00, /* stop bits-1*/
0x00, /* parity - none*/
0x08 /* nb. of bits 8*/
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief TEMPLATE_Init
* Initializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_Init(void)
{
/*
Add your initialization code here
*/
return (0);
}
/**
* @brief TEMPLATE_DeInit
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_DeInit(void)
{
/*
Add your deinitialization code here
*/
return (0);
}
/**
* @brief TEMPLATE_Control
* Manage the CDC class requests
* @param Cmd: Command code
* @param Buf: Buffer containing command data (request parameters)
* @param Len: 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 TEMPLATE_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length)
{
UNUSED(length);
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
/* Add your code here */
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
/* Add your code here */
break;
case CDC_SET_COMM_FEATURE:
/* Add your code here */
break;
case CDC_GET_COMM_FEATURE:
/* Add your code here */
break;
case CDC_CLEAR_COMM_FEATURE:
/* Add your code here */
break;
case CDC_SET_LINE_CODING:
linecoding.bitrate = (uint32_t)(pbuf[0] | (pbuf[1] << 8) | \
(pbuf[2] << 16) | (pbuf[3] << 24));
linecoding.format = pbuf[4];
linecoding.paritytype = pbuf[5];
linecoding.datatype = pbuf[6];
/* Add your code here */
break;
case CDC_GET_LINE_CODING:
pbuf[0] = (uint8_t)(linecoding.bitrate);
pbuf[1] = (uint8_t)(linecoding.bitrate >> 8);
pbuf[2] = (uint8_t)(linecoding.bitrate >> 16);
pbuf[3] = (uint8_t)(linecoding.bitrate >> 24);
pbuf[4] = linecoding.format;
pbuf[5] = linecoding.paritytype;
pbuf[6] = linecoding.datatype;
/* Add your code here */
break;
case CDC_SET_CONTROL_LINE_STATE:
/* Add your code here */
break;
case CDC_SEND_BREAK:
/* Add your code here */
break;
default:
break;
}
return (0);
}
/**
* @brief TEMPLATE_Receive
* 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)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_Receive(uint8_t *Buf, uint32_t *Len)
{
UNUSED(Buf);
UNUSED(Len);
return (0);
}
/**
* @brief TEMPLATE_TransmitCplt
* 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 TEMPLATE_TransmitCplt(uint8_t *Buf, uint32_t *Len, uint8_t epnum)
{
UNUSED(Buf);
UNUSED(Len);
UNUSED(epnum);
return (0);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,278 @@
/**
******************************************************************************
* @file usbd_cdc_ecm.h
* @author MCD Application Team
* @brief header file for the usbd_cdc_ecm.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2019 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_CDC_ECM_H
#define __USB_CDC_ECM_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup usbd_cdc_ecm
* @brief This file is the Header file for usbd_cdc_ecm.c
* @{
*/
/** @defgroup usbd_cdc_ecm_Exported_Defines
* @{
*/
/* Comment this define in order to disable the CDC ECM Notification pipe */
#ifndef CDC_ECM_IN_EP
#define CDC_ECM_IN_EP 0x81U /* EP1 for data IN */
#endif /* CDC_ECM_IN_EP */
#ifndef CDC_ECM_OUT_EP
#define CDC_ECM_OUT_EP 0x01U /* EP1 for data OUT */
#endif /* CDC_ECM_OUT_EP */
#ifndef CDC_ECM_CMD_EP
#define CDC_ECM_CMD_EP 0x82U /* EP2 for CDC ECM commands */
#endif /* CDC_ECM_CMD_EP */
#ifndef CDC_ECM_CMD_ITF_NBR
#define CDC_ECM_CMD_ITF_NBR 0x00U /* Command Interface Number 0 */
#endif /* CDC_ECM_CMD_ITF_NBR */
#ifndef CDC_ECM_COM_ITF_NBR
#define CDC_ECM_COM_ITF_NBR 0x01U /* Communication Interface Number 0 */
#endif /* CDC_ECM_CMD_ITF_NBR */
#ifndef CDC_ECM_HS_BINTERVAL
#define CDC_ECM_HS_BINTERVAL 0x10U
#endif /* CDC_ECM_HS_BINTERVAL */
#ifndef CDC_ECM_FS_BINTERVAL
#define CDC_ECM_FS_BINTERVAL 0x10U
#endif /* CDC_ECM_FS_BINTERVAL */
#ifndef USBD_SUPPORT_USER_STRING_DESC
#define USBD_SUPPORT_USER_STRING_DESC 1U
#endif /* USBD_SUPPORT_USER_STRING_DESC */
/* CDC_ECM Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */
#define CDC_ECM_DATA_HS_MAX_PACKET_SIZE 512U /* Endpoint IN & OUT Packet size */
#define CDC_ECM_DATA_FS_MAX_PACKET_SIZE 64U /* Endpoint IN & OUT Packet size */
#define CDC_ECM_CMD_PACKET_SIZE 16U /* Control Endpoint Packet size */
#define CDC_ECM_CONFIG_DESC_SIZ 79U
#define CDC_ECM_DATA_BUFFER_SIZE 2000U
#define CDC_ECM_DATA_HS_IN_PACKET_SIZE CDC_ECM_DATA_HS_MAX_PACKET_SIZE
#define CDC_ECM_DATA_HS_OUT_PACKET_SIZE CDC_ECM_DATA_HS_MAX_PACKET_SIZE
#define CDC_ECM_DATA_FS_IN_PACKET_SIZE CDC_ECM_DATA_FS_MAX_PACKET_SIZE
#define CDC_ECM_DATA_FS_OUT_PACKET_SIZE CDC_ECM_DATA_FS_MAX_PACKET_SIZE
/*---------------------------------------------------------------------*/
/* CDC_ECM definitions */
/*---------------------------------------------------------------------*/
#define CDC_ECM_SEND_ENCAPSULATED_COMMAND 0x00U
#define CDC_ECM_GET_ENCAPSULATED_RESPONSE 0x01U
#define CDC_ECM_SET_ETH_MULTICAST_FILTERS 0x40U
#define CDC_ECM_SET_ETH_PWRM_PATTERN_FILTER 0x41U
#define CDC_ECM_GET_ETH_PWRM_PATTERN_FILTER 0x42U
#define CDC_ECM_SET_ETH_PACKET_FILTER 0x43U
#define CDC_ECM_GET_ETH_STATISTIC 0x44U
#define CDC_ECM_NET_DISCONNECTED 0x00U
#define CDC_ECM_NET_CONNECTED 0x01U
/* Ethernet statistics definitions */
#define CDC_ECM_XMIT_OK_VAL CDC_ECM_ETH_STATS_VAL_ENABLED
#define CDC_ECM_XMIT_OK 0x01U
#define CDC_ECM_RVC_OK 0x02U
#define CDC_ECM_XMIT_ERROR 0x04U
#define CDC_ECM_RCV_ERROR 0x08U
#define CDC_ECM_RCV_NO_BUFFER 0x10U
#define CDC_ECM_DIRECTED_BYTES_XMIT 0x20U
#define CDC_ECM_DIRECTED_FRAMES_XMIT 0x40U
#define CDC_ECM_MULTICAST_BYTES_XMIT 0x80U
#define CDC_ECM_MULTICAST_FRAMES_XMIT 0x01U
#define CDC_ECM_BROADCAST_BYTES_XMIT 0x02U
#define CDC_ECM_BROADCAST_FRAMES_XMIT 0x04U
#define CDC_ECM_DIRECTED_BYTES_RCV 0x08U
#define CDC_ECM_DIRECTED_FRAMES_RCV 0x10U
#define CDC_ECM_MULTICAST_BYTES_RCV 0x20U
#define CDC_ECM_MULTICAST_FRAMES_RCV 0x40U
#define CDC_ECM_BROADCAST_BYTES_RCV 0x80U
#define CDC_ECM_BROADCAST_FRAMES_RCV 0x01U
#define CDC_ECM_RCV_CRC_ERROR 0x02U
#define CDC_ECM_TRANSMIT_QUEUE_LENGTH 0x04U
#define CDC_ECM_RCV_ERROR_ALIGNMENT 0x08U
#define CDC_ECM_XMIT_ONE_COLLISION 0x10U
#define CDC_ECM_XMIT_MORE_COLLISIONS 0x20U
#define CDC_ECM_XMIT_DEFERRED 0x40U
#define CDC_ECM_XMIT_MAX_COLLISIONS 0x80U
#define CDC_ECM_RCV_OVERRUN 0x40U
#define CDC_ECM_XMIT_UNDERRUN 0x40U
#define CDC_ECM_XMIT_HEARTBEAT_FAILURE 0x40U
#define CDC_ECM_XMIT_TIMES_CRS_LOST 0x40U
#define CDC_ECM_XMIT_LATE_COLLISIONS 0x40U
#define CDC_ECM_ETH_STATS_RESERVED 0xE0U
#define CDC_ECM_BMREQUEST_TYPE_ECM 0xA1U
/* MAC String index */
#define CDC_ECM_MAC_STRING_INDEX 6U
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
/**
* @}
*/
typedef struct
{
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);
int8_t (* Process)(USBD_HandleTypeDef *pdev);
const uint8_t *pStrDesc;
} USBD_CDC_ECM_ItfTypeDef;
typedef struct
{
uint8_t bmRequest;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
uint8_t data[8];
} USBD_CDC_ECM_NotifTypeDef;
/*
* ECM Class specification revision 1.2
* Table 3: Ethernet Networking Functional Descriptor
*/
typedef struct
{
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t iMacAddress;
uint8_t bEthernetStatistics3;
uint8_t bEthernetStatistics2;
uint8_t bEthernetStatistics1;
uint8_t bEthernetStatistics0;
uint16_t wMaxSegmentSize;
uint16_t bNumberMCFiltes;
uint8_t bNumberPowerFiltes;
} __PACKED USBD_ECMFuncDescTypeDef;
typedef struct
{
uint32_t data[CDC_ECM_DATA_BUFFER_SIZE / 4U]; /* Force 32-bit alignment */
uint8_t CmdOpCode;
uint8_t CmdLength;
uint8_t Reserved1; /* Reserved Byte to force 4 bytes alignment of following fields */
uint8_t Reserved2; /* Reserved Byte to force 4 bytes alignment of following fields */
uint8_t *RxBuffer;
uint8_t *TxBuffer;
uint32_t RxLength;
uint32_t TxLength;
__IO uint32_t TxState;
__IO uint32_t RxState;
__IO uint32_t MaxPcktLen;
__IO uint32_t LinkStatus;
__IO uint32_t NotificationStatus;
USBD_CDC_ECM_NotifTypeDef Req;
} USBD_CDC_ECM_HandleTypeDef;
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_CDC_ECM;
#define USBD_CDC_ECM_CLASS &USBD_CDC_ECM
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_CDC_ECM_RegisterInterface(USBD_HandleTypeDef *pdev,
USBD_CDC_ECM_ItfTypeDef *fops);
uint8_t USBD_CDC_ECM_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff);
uint8_t USBD_CDC_ECM_ReceivePacket(USBD_HandleTypeDef *pdev);
#ifdef USE_USBD_COMPOSITE
uint8_t USBD_CDC_ECM_TransmitPacket(USBD_HandleTypeDef *pdev, uint8_t ClassId);
uint8_t USBD_CDC_ECM_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff,
uint32_t length, uint8_t ClassId);
#else
uint8_t USBD_CDC_ECM_TransmitPacket(USBD_HandleTypeDef *pdev);
uint8_t USBD_CDC_ECM_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff,
uint32_t length);
#endif /* USE_USBD_COMPOSITE */
uint8_t USBD_CDC_ECM_SendNotification(USBD_HandleTypeDef *pdev,
USBD_CDC_NotifCodeTypeDef Notif,
uint16_t bVal, uint8_t *pData);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_CDC_ECM_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,80 @@
/**
******************************************************************************
* @file Inc/usbd_cdc_ecm_if_template.h
* @author MCD Application Team
* @brief Header for usbd_cdc_ecm_if_template.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2019 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CDC_ECM_IF_H
#define __USBD_CDC_ECM_IF_H
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_ecm.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Ensure this MAC address value is same as MAC_ADDRx declared in STM32xxx_conf.h */
#define CDC_ECM_MAC_STR_DESC (uint8_t *)"000202030000"
#define CDC_ECM_MAC_ADDR0 0x00U /* 01 */
#define CDC_ECM_MAC_ADDR1 0x02U /* 02 */
#define CDC_ECM_MAC_ADDR2 0x02U /* 03 */
#define CDC_ECM_MAC_ADDR3 0x03U /* 00 */
#define CDC_ECM_MAC_ADDR4 0x00U /* 00 */
#define CDC_ECM_MAC_ADDR5 0x00U /* 00 */
/* Max Number of Trials waiting for Tx ready */
#define CDC_ECM_MAX_TX_WAIT_TRIALS 1000000U
#define CDC_ECM_ETH_STATS_BYTE0 0U
/*(uint8_t)(CDC_ECM_XMIT_OK_VAL | CDC_ECM_RVC_OK_VAL | CDC_ECM_XMIT_ERROR_VAL | \
CDC_ECM_RCV_ERROR_VAL | CDC_ECM_RCV_NO_BUFFER_VAL | CDC_ECM_DIRECTED_BYTES_XMIT_VAL | \
CDC_ECM_DIRECTED_FRAMES_XMIT_VAL | CDC_ECM_MULTICAST_BYTES_XMIT_VAL) */
#define CDC_ECM_ETH_STATS_BYTE1 0U
/*(uint8_t)(CDC_ECM_MULTICAST_FRAMES_XMIT_VAL | CDC_ECM_BROADCAST_BYTES_XMIT_VAL | \
CDC_ECM_BROADCAST_FRAMES_XMIT_VAL | CDC_ECM_DIRECTED_BYTES_RCV_VAL | \
CDC_ECM_DIRECTED_FRAMES_RCV_VAL | CDC_ECM_MULTICAST_BYTES_RCV_VAL | \
CDC_ECM_MULTICAST_FRAMES_RCV_VAL | CDC_ECM_BROADCAST_BYTES_RCV_VAL) */
#define CDC_ECM_ETH_STATS_BYTE2 0U
/*(uint8_t)(CDC_ECM_BROADCAST_FRAMES_RCV_VAL | CDC_ECM_RCV_CRC_ERROR_VAL | \
CDC_ECM_TRANSMIT_QUEUE_LENGTH_VAL | CDC_ECM_RCV_ERROR_ALIGNMENT_VAL | \
CDC_ECM_XMIT_ONE_COLLISION_VAL | CDC_ECM_XMIT_MORE_COLLISIONS_VAL | \
CDC_ECM_XMIT_DEFERRED_VAL | CDC_ECM_XMIT_MAX_COLLISIONS_VAL) */
#define CDC_ECM_ETH_STATS_BYTE3 0U
/*(uint8_t)(CDC_ECM_RCV_OVERRUN_VAL | CDC_ECM_XMIT_UNDERRUN_VAL | CDC_ECM_XMIT_HEARTBEAT_FAILURE_VAL | \
CDC_ECM_XMIT_TIMES_CRS_LOST_VAL | CDC_ECM_XMIT_LATE_COLLISIONS_VAL | CDC_ECM_ETH_STATS_RESERVED) */
/* Ethernet Maximum Segment size, typically 1514 bytes */
#define CDC_ECM_ETH_MAX_SEGSZE 1514U
/* Number of Ethernet multicast filters */
#define CDC_ECM_ETH_NBR_MACFILTERS 0U
/* Number of wakeup power filters */
#define CDC_ECM_ETH_NBR_PWRFILTERS 0U
#define CDC_ECM_CONNECT_SPEED_UPSTREAM 0x004C4B40U /* 5Mbps */
#define CDC_ECM_CONNECT_SPEED_DOWNSTREAM 0x004C4B40U /* 5Mbps */
extern USBD_CDC_ECM_ItfTypeDef USBD_CDC_ECM_fops;
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#endif /* __USBD_CDC_ECM_IF_H */
@@ -0,0 +1,274 @@
/**
******************************************************************************
* @file Src/usbd_cdc_ecm_if_template.c
* @author MCD Application Team
* @brief Source file for USBD CDC_ECM interface
******************************************************************************
* @attention
*
* Copyright (c) 2019 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_ecm_if_template.h"
/*
Include here LwIP files if used
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Received Data over USB are stored in this buffer */
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif /* ( __ICCARM__ ) */
__ALIGN_BEGIN static uint8_t UserRxBuffer[CDC_ECM_ETH_MAX_SEGSZE + 100]__ALIGN_END;
/* Transmitted Data over CDC_ECM (CDC_ECM interface) are stored in this buffer */
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif /* ( __ICCARM__ ) */
__ALIGN_BEGIN static uint8_t UserTxBuffer[CDC_ECM_ETH_MAX_SEGSZE + 100]__ALIGN_END;
static uint8_t CDC_ECMInitialized = 0U;
/* USB handler declaration */
extern USBD_HandleTypeDef USBD_Device;
/* Private function prototypes -----------------------------------------------*/
static int8_t CDC_ECM_Itf_Init(void);
static int8_t CDC_ECM_Itf_DeInit(void);
static int8_t CDC_ECM_Itf_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length);
static int8_t CDC_ECM_Itf_Receive(uint8_t *pbuf, uint32_t *Len);
static int8_t CDC_ECM_Itf_TransmitCplt(uint8_t *pbuf, uint32_t *Len, uint8_t epnum);
static int8_t CDC_ECM_Itf_Process(USBD_HandleTypeDef *pdev);
USBD_CDC_ECM_ItfTypeDef USBD_CDC_ECM_fops =
{
CDC_ECM_Itf_Init,
CDC_ECM_Itf_DeInit,
CDC_ECM_Itf_Control,
CDC_ECM_Itf_Receive,
CDC_ECM_Itf_TransmitCplt,
CDC_ECM_Itf_Process,
(uint8_t *)CDC_ECM_MAC_STR_DESC,
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_ECM_Itf_Init
* Initializes the CDC_ECM media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_ECM_Itf_Init(void)
{
if (CDC_ECMInitialized == 0U)
{
/*
Initialize the TCP/IP stack here
*/
CDC_ECMInitialized = 1U;
}
/* Set Application Buffers */
#ifdef USE_USBD_COMPOSITE
(void)USBD_CDC_ECM_SetTxBuffer(&USBD_Device, UserTxBuffer, 0U, 0U);
#else
(void)USBD_CDC_ECM_SetTxBuffer(&USBD_Device, UserTxBuffer, 0U);
#endif /* USE_USBD_COMPOSITE */
(void)USBD_CDC_ECM_SetRxBuffer(&USBD_Device, UserRxBuffer);
return (0);
}
/**
* @brief CDC_ECM_Itf_DeInit
* DeInitializes the CDC_ECM media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_ECM_Itf_DeInit(void)
{
#ifdef USE_USBD_COMPOSITE
USBD_CDC_ECM_HandleTypeDef *hcdc_cdc_ecm = (USBD_CDC_ECM_HandleTypeDef *) \
(USBD_Device.pClassDataCmsit[USBD_Device.classId]);
#else
USBD_CDC_ECM_HandleTypeDef *hcdc_cdc_ecm = (USBD_CDC_ECM_HandleTypeDef *)(USBD_Device.pClassData);
#endif /* USE_USBD_COMPOSITE */
/* Notify application layer that link is down */
hcdc_cdc_ecm->LinkStatus = 0U;
return (0);
}
/**
* @brief CDC_ECM_Itf_Control
* Manage the CDC_ECM class requests
* @param Cmd: Command code
* @param Buf: Buffer containing command data (request parameters)
* @param Len: 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_ECM_Itf_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length)
{
#ifdef USE_USBD_COMPOSITE
USBD_CDC_ECM_HandleTypeDef *hcdc_cdc_ecm = (USBD_CDC_ECM_HandleTypeDef *) \
(USBD_Device.pClassDataCmsit[USBD_Device.classId]);
#else
USBD_CDC_ECM_HandleTypeDef *hcdc_cdc_ecm = (USBD_CDC_ECM_HandleTypeDef *)(USBD_Device.pClassData);
#endif /* USE_USBD_COMPOSITE */
switch (cmd)
{
case CDC_ECM_SEND_ENCAPSULATED_COMMAND:
/* Add your code here */
break;
case CDC_ECM_GET_ENCAPSULATED_RESPONSE:
/* Add your code here */
break;
case CDC_ECM_SET_ETH_MULTICAST_FILTERS:
/* Add your code here */
break;
case CDC_ECM_SET_ETH_PWRM_PATTERN_FILTER:
/* Add your code here */
break;
case CDC_ECM_GET_ETH_PWRM_PATTERN_FILTER:
/* Add your code here */
break;
case CDC_ECM_SET_ETH_PACKET_FILTER:
/* Check if this is the first time we enter */
if (hcdc_cdc_ecm->LinkStatus == 0U)
{
/*
Setup the Link up at TCP/IP level
*/
hcdc_cdc_ecm->LinkStatus = 1U;
/* Modification for MacOS which doesn't send SetInterface before receiving INs */
if (hcdc_cdc_ecm->NotificationStatus == 0U)
{
/* Send notification: NETWORK_CONNECTION Event */
(void)USBD_CDC_ECM_SendNotification(&USBD_Device, NETWORK_CONNECTION,
CDC_ECM_NET_CONNECTED, NULL);
/* Prepare for sending Connection Speed Change notification */
hcdc_cdc_ecm->NotificationStatus = 1U;
}
}
/* Add your code here */
break;
case CDC_ECM_GET_ETH_STATISTIC:
/* Add your code here */
break;
default:
break;
}
UNUSED(length);
UNUSED(pbuf);
return (0);
}
/**
* @brief CDC_ECM_Itf_Receive
* Data received over USB OUT endpoint are sent over CDC_ECM interface
* through this function.
* @param Buf: Buffer of data to be transmitted
* @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_ECM_Itf_Receive(uint8_t *Buf, uint32_t *Len)
{
/* Get the CDC_ECM handler pointer */
#ifdef USE_USBD_COMPOSITE
USBD_CDC_ECM_HandleTypeDef *hcdc_cdc_ecm = (USBD_CDC_ECM_HandleTypeDef *) \
(USBD_Device.pClassDataCmsit[USBD_Device.classId]);
#else
USBD_CDC_ECM_HandleTypeDef *hcdc_cdc_ecm = (USBD_CDC_ECM_HandleTypeDef *)(USBD_Device.pClassData);
#endif /* USE_USBD_COMPOSITE */
/* Call Eth buffer processing */
hcdc_cdc_ecm->RxState = 1U;
UNUSED(Len);
UNUSED(Buf);
return (0);
}
/**
* @brief CDC_ECM_Itf_TransmitCplt
* 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_ECM_Itf_TransmitCplt(uint8_t *Buf, uint32_t *Len, uint8_t epnum)
{
UNUSED(Buf);
UNUSED(Len);
UNUSED(epnum);
return (0);
}
/**
* @brief CDC_ECM_Itf_Process
* Data received over USB OUT endpoint are sent over CDC_ECM interface
* through this function.
* @param pdef: pointer to the USB Device Handle
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_ECM_Itf_Process(USBD_HandleTypeDef *pdev)
{
/* Get the CDC_ECM handler pointer */
#ifdef USE_USBD_COMPOSITE
USBD_CDC_ECM_HandleTypeDef *hcdc_cdc_ecm = (USBD_CDC_ECM_HandleTypeDef *)(pdev->pClassDataCmsit[pdev->classId]);
#else
USBD_CDC_ECM_HandleTypeDef *hcdc_cdc_ecm = (USBD_CDC_ECM_HandleTypeDef *)(pdev->pClassData);
#endif /* USE_USBD_COMPOSITE */
if (hcdc_cdc_ecm == NULL)
{
return (-1);
}
if (hcdc_cdc_ecm->LinkStatus != 0U)
{
/*
Read a received packet from the Ethernet buffers and send it
to the lwIP for handling
Call here the TCP/IP background tasks.
*/
}
return (0);
}
@@ -0,0 +1,527 @@
/**
******************************************************************************
* @file usbd_cdc_rndis.h
* @author MCD Application Team
* @brief header file for the usbd_cdc_rndis.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2019 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_CDC_RNDIS_H
#define __USB_CDC_RNDIS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup usbd_cdc_rndis
* @brief This file is the Header file for usbd_cdc_rndis.c
* @{
*/
/** @defgroup usbd_cdc_rndis_Exported_Defines
* @{
*/
#ifndef CDC_RNDIS_IN_EP
#define CDC_RNDIS_IN_EP 0x81U /* EP1 for data IN */
#endif /* CDC_RNDIS_IN_EP */
#ifndef CDC_RNDIS_OUT_EP
#define CDC_RNDIS_OUT_EP 0x01U /* EP1 for data OUT */
#endif /* CDC_RNDIS_OUT_EP */
#ifndef CDC_RNDIS_CMD_EP
#define CDC_RNDIS_CMD_EP 0x82U /* EP2 for CDC_RNDIS commands */
#endif /* CDC_RNDIS_CMD_EP */
#ifndef CDC_RNDIS_CMD_ITF_NBR
#define CDC_RNDIS_CMD_ITF_NBR 0x00U /* Command Interface Number 0 */
#endif /* CDC_RNDIS_CMD_ITF_NBR */
#ifndef CDC_RNDIS_COM_ITF_NBR
#define CDC_RNDIS_COM_ITF_NBR 0x01U /* Communication Interface Number 0 */
#endif /* CDC_RNDIS_CMD_ITF_NBR */
#ifndef CDC_RNDIS_HS_BINTERVAL
#define CDC_RNDIS_HS_BINTERVAL 0x10U
#endif /* CDC_RNDIS_HS_BINTERVAL */
#ifndef CDC_RNDIS_FS_BINTERVAL
#define CDC_RNDIS_FS_BINTERVAL 0x10U
#endif /* CDC_RNDIS_FS_BINTERVAL */
/* CDC_RNDIS Endpoints parameters: you can fine tune these values
depending on the needed baudrates and performance. */
#define CDC_RNDIS_DATA_HS_MAX_PACKET_SIZE 512U /* Endpoint IN & OUT Packet size */
#define CDC_RNDIS_DATA_FS_MAX_PACKET_SIZE 64U /* Endpoint IN & OUT Packet size */
#define CDC_RNDIS_CMD_PACKET_SIZE 16U /* Control Endpoint Packet size */
#define CDC_RNDIS_CONFIG_DESC_SIZ 75U
#define CDC_RNDIS_DATA_HS_IN_PACKET_SIZE CDC_RNDIS_DATA_HS_MAX_PACKET_SIZE
#define CDC_RNDIS_DATA_HS_OUT_PACKET_SIZE CDC_RNDIS_DATA_HS_MAX_PACKET_SIZE
#define CDC_RNDIS_DATA_FS_IN_PACKET_SIZE CDC_RNDIS_DATA_FS_MAX_PACKET_SIZE
#define CDC_RNDIS_DATA_FS_OUT_PACKET_SIZE CDC_RNDIS_DATA_FS_MAX_PACKET_SIZE
/*---------------------------------------------------------------------*/
/* CDC_RNDIS definitions */
/*---------------------------------------------------------------------*/
/** Implemented CDC_RNDIS Version Major */
#define CDC_RNDIS_VERSION_MAJOR 0x01U
/* Implemented CDC_RNDIS Version Minor */
#define CDC_RNDIS_VERSION_MINOR 0x00U
/* Maximum size in bytes of a CDC_RNDIS control message
which can be sent or received */
#define CDC_RNDIS_MESSAGE_BUFFER_SIZE 128U
/* Maximum size in bytes of an Ethernet frame
according to the Ethernet standard */
#define CDC_RNDIS_ETH_FRAME_SIZE_MAX 1536U
/* Maximum size allocated for buffer
inside Query messages structures */
#define CDC_RNDIS_MAX_INFO_BUFF_SZ 200U
#define CDC_RNDIS_MAX_DATA_SZE 2000U
/* Notification request value for a CDC_RNDIS
Response Available notification */
#define CDC_RNDIS_NOTIFICATION_RESP_AVAILABLE 0x00000001UL
#define CDC_RNDIS_PACKET_MSG_ID 0x00000001UL
#define CDC_RNDIS_INITIALIZE_MSG_ID 0x00000002UL
#define CDC_RNDIS_HALT_MSG_ID 0x00000003UL
#define CDC_RNDIS_QUERY_MSG_ID 0x00000004UL
#define CDC_RNDIS_SET_MSG_ID 0x00000005UL
#define CDC_RNDIS_RESET_MSG_ID 0x00000006UL
#define CDC_RNDIS_INDICATE_STATUS_MSG_ID 0x00000007UL
#define CDC_RNDIS_KEEPALIVE_MSG_ID 0x00000008UL
#define CDC_RNDIS_INITIALIZE_CMPLT_ID 0x80000002UL
#define CDC_RNDIS_QUERY_CMPLT_ID 0x80000004UL
#define CDC_RNDIS_SET_CMPLT_ID 0x80000005UL
#define CDC_RNDIS_RESET_CMPLT_ID 0x80000006UL
#define CDC_RNDIS_KEEPALIVE_CMPLT_ID 0x80000008UL
#define CDC_RNDIS_STATUS_SUCCESS 0x00000000UL
#define CDC_RNDIS_STATUS_FAILURE 0xC0000001UL
#define CDC_RNDIS_STATUS_INVALID_DATA 0xC0010015UL
#define CDC_RNDIS_STATUS_NOT_SUPPORTED 0xC00000BBUL
#define CDC_RNDIS_STATUS_MEDIA_CONNECT 0x4001000BUL
#define CDC_RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000CUL
/** Media state */
#define CDC_RNDIS_MEDIA_STATE_CONNECTED 0x00000000UL
#define CDC_RNDIS_MEDIA_STATE_DISCONNECTED 0x00000001UL
/** Media types */
#define CDC_RNDIS_MEDIUM_802_3 0x00000000UL
#define CDC_RNDIS_DF_CONNECTIONLESS 0x00000001UL
#define CDC_RNDIS_DF_CONNECTION_ORIENTED 0x00000002UL
/** Hardware status of the underlying NIC */
#define CDC_RNDIS_HW_STS_READY 0x00000000UL
#define CDC_RNDIS_HW_STS_INITIALIZING 0x00000001UL
#define CDC_RNDIS_HW_STS_RESET 0x00000002UL
#define CDC_RNDIS_HW_STS_CLOSING 0x00000003UL
#define CDC_RNDIS_HW_STS_NOT_READY 0x00000004UL
/** Packet filter */
#define CDC_RNDIS_PACKET_DIRECTED 0x00000001UL
#define CDC_RNDIS_PACKET_MULTICAST 0x00000002UL
#define CDC_RNDIS_PACKET_ALL_MULTICAST 0x00000004UL
#define CDC_RNDIS_PACKET_BROADCAST 0x00000008UL
#define CDC_RNDIS_PACKET_SOURCE_ROUTING 0x00000010UL
#define CDC_RNDIS_PACKET_PROMISCUOUS 0x00000020UL
#define CDC_RNDIS_PACKET_SMT 0x00000040UL
#define CDC_RNDIS_PACKET_ALL_LOCAL 0x00000080UL
#define CDC_RNDIS_PACKET_GROUP 0x00001000UL
#define CDC_RNDIS_PACKET_ALL_FUNCTIONAL 0x00002000UL
#define CDC_RNDIS_PACKET_FUNCTIONAL 0x00004000UL
#define CDC_RNDIS_PACKET_MAC_FRAME 0x00008000UL
#define OID_GEN_SUPPORTED_LIST 0x00010101UL
#define OID_GEN_HARDWARE_STATUS 0x00010102UL
#define OID_GEN_MEDIA_SUPPORTED 0x00010103UL
#define OID_GEN_MEDIA_IN_USE 0x00010104UL
#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106UL
#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL
#define OID_GEN_LINK_SPEED 0x00010107UL
#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010AUL
#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010BUL
#define OID_GEN_VENDOR_ID 0x0001010CUL
#define OID_GEN_VENDOR_DESCRIPTION 0x0001010DUL
#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010EUL
#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114UL
#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115UL
#define OID_GEN_PHYSICAL_MEDIUM 0x00010202UL
#define OID_GEN_XMIT_OK 0x00020101UL
#define OID_GEN_RCV_OK 0x00020102UL
#define OID_GEN_XMIT_ERROR 0x00020103UL
#define OID_GEN_RCV_ERROR 0x00020104UL
#define OID_GEN_RCV_NO_BUFFER 0x00020105UL
#define OID_GEN_CDC_RNDIS_CONFIG_PARAMETER 0x0001021BUL
#define OID_802_3_PERMANENT_ADDRESS 0x01010101UL
#define OID_802_3_CURRENT_ADDRESS 0x01010102UL
#define OID_802_3_MULTICAST_LIST 0x01010103UL
#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104UL
#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101UL
#define OID_802_3_XMIT_ONE_COLLISION 0x01020102UL
#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103UL
#define CDC_RNDIS_SEND_ENCAPSULATED_COMMAND 0x00U
#define CDC_RNDIS_GET_ENCAPSULATED_RESPONSE 0x01U
#define CDC_RNDIS_NET_DISCONNECTED 0x00U
#define CDC_RNDIS_NET_CONNECTED 0x01U
#define CDC_RNDIS_BMREQUEST_TYPE_RNDIS 0xA1U
#define CDC_RNDIS_PCKTMSG_DATAOFFSET_OFFSET 8U
/* MAC String index */
#define CDC_RNDIS_MAC_STRING_INDEX 6U
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
/**
* @}
*/
typedef struct _USBD_CDC_RNDIS_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);
int8_t (* Process)(USBD_HandleTypeDef *pdev);
uint8_t *pStrDesc;
} USBD_CDC_RNDIS_ItfTypeDef;
/* CDC_RNDIS State values */
typedef enum
{
CDC_RNDIS_STATE_UNINITIALIZED = 0,
CDC_RNDIS_STATE_BUS_INITIALIZED = 1,
CDC_RNDIS_STATE_INITIALIZED = 2,
CDC_RNDIS_STATE_DATA_INITIALIZED = 3
} USBD_CDC_RNDIS_StateTypeDef;
typedef struct
{
uint8_t bmRequest;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
uint8_t data[8];
} USBD_CDC_RNDIS_NotifTypeDef;
typedef struct
{
uint32_t data[CDC_RNDIS_MAX_DATA_SZE / 4U]; /* Force 32-bit alignment */
uint8_t CmdOpCode;
uint8_t CmdLength;
uint8_t ResponseRdy; /* Indicates if the Device Response to an CDC_RNDIS msg is ready */
uint8_t Reserved1; /* Reserved Byte to force 4 bytes alignment of following fields */
uint8_t *RxBuffer;
uint8_t *TxBuffer;
uint32_t RxLength;
uint32_t TxLength;
USBD_CDC_RNDIS_NotifTypeDef Req;
USBD_CDC_RNDIS_StateTypeDef State;
__IO uint32_t TxState;
__IO uint32_t RxState;
__IO uint32_t MaxPcktLen;
__IO uint32_t LinkStatus;
__IO uint32_t NotificationStatus;
__IO uint32_t PacketFilter;
} USBD_CDC_RNDIS_HandleTypeDef;
/* Messages Sent by the Host ---------------------*/
/* Type define for a CDC_RNDIS Initialize command message */
typedef struct
{
uint32_t MsgType;
uint32_t MsgLength;
uint32_t ReqId;
uint32_t MajorVersion;
uint32_t MinorVersion;
uint32_t MaxTransferSize;
} USBD_CDC_RNDIS_InitMsgTypeDef;
/* Type define for a CDC_RNDIS Halt Message */
typedef struct
{
uint32_t MsgType;
uint32_t MsgLength;
uint32_t ReqId;
} USBD_CDC_RNDIS_HaltMsgTypeDef;
/* Type define for a CDC_RNDIS Query command message */
typedef struct
{
uint32_t MsgType;
uint32_t MsgLength;
uint32_t RequestId;
uint32_t Oid;
uint32_t InfoBufLength;
uint32_t InfoBufOffset;
uint32_t DeviceVcHandle;
uint32_t InfoBuf[CDC_RNDIS_MAX_INFO_BUFF_SZ];
} USBD_CDC_RNDIS_QueryMsgTypeDef;
/* Type define for a CDC_RNDIS Set command message */
typedef struct
{
uint32_t MsgType;
uint32_t MsgLength;
uint32_t ReqId;
uint32_t Oid;
uint32_t InfoBufLength;
uint32_t InfoBufOffset;
uint32_t DeviceVcHandle;
uint32_t InfoBuf[CDC_RNDIS_MAX_INFO_BUFF_SZ];
} USBD_CDC_RNDIS_SetMsgTypeDef;
/* Type define for a CDC_RNDIS Reset message */
typedef struct
{
uint32_t MsgType;
uint32_t MsgLength;
uint32_t Reserved;
} USBD_CDC_RNDIS_ResetMsgTypeDef;
/* Type define for a CDC_RNDIS Keepalive command message */
typedef struct
{
uint32_t MsgType;
uint32_t MsgLength;
uint32_t ReqId;
} USBD_CDC_RNDIS_KpAliveMsgTypeDef;
/* Messages Sent by the Device ---------------------*/
/* Type define for a CDC_RNDIS Initialize complete response message */
typedef struct
{
uint32_t MsgType;
uint32_t MsgLength;
uint32_t ReqId;
uint32_t Status;
uint32_t MajorVersion;
uint32_t MinorVersion;
uint32_t DeviceFlags;
uint32_t Medium;
uint32_t MaxPacketsPerTransfer;
uint32_t MaxTransferSize;
uint32_t PacketAlignmentFactor;
uint32_t AFListOffset;
uint32_t AFListSize;
} USBD_CDC_RNDIS_InitCpltMsgTypeDef;
/* Type define for a CDC_RNDIS Query complete response message */
typedef struct
{
uint32_t MsgType;
uint32_t MsgLength;
uint32_t ReqId;
uint32_t Status;
uint32_t InfoBufLength;
uint32_t InfoBufOffset;
uint32_t InfoBuf[CDC_RNDIS_MAX_INFO_BUFF_SZ];
} USBD_CDC_RNDIS_QueryCpltMsgTypeDef;
/* Type define for a CDC_RNDIS Set complete response message */
typedef struct
{
uint32_t MsgType;
uint32_t MsgLength;
uint32_t ReqId;
uint32_t Status;
} USBD_CDC_RNDIS_SetCpltMsgTypeDef;
/* Type define for a CDC_RNDIS Reset complete message */
typedef struct
{
uint32_t MsgType;
uint32_t MsgLength;
uint32_t Status;
uint32_t AddrReset;
} USBD_CDC_RNDIS_ResetCpltMsgTypeDef;
/* Type define for CDC_RNDIS struct to indicate a change
in the status of the device */
typedef struct
{
uint32_t MsgType;
uint32_t MsgLength;
uint32_t Status;
uint32_t StsBufLength;
uint32_t StsBufOffset;
} USBD_CDC_RNDIS_StsChangeMsgTypeDef;
/* Type define for a CDC_RNDIS Keepalive complete message */
typedef struct
{
uint32_t MsgType;
uint32_t MsgLength;
uint32_t ReqId;
uint32_t Status;
} USBD_CDC_RNDIS_KpAliveCpltMsgTypeDef;
/* Messages Sent by both Host and Device ---------------------*/
/* Type define for a CDC_RNDIS packet message, used to encapsulate
Ethernet packets sent to and from the adapter */
typedef struct
{
uint32_t MsgType;
uint32_t MsgLength;
uint32_t DataOffset;
uint32_t DataLength;
uint32_t OOBDataOffset;
uint32_t OOBDataLength;
uint32_t NumOOBDataElements;
uint32_t PerPacketInfoOffset;
uint32_t PerPacketInfoLength;
uint32_t VcHandle;
uint32_t Reserved;
} USBD_CDC_RNDIS_PacketMsgTypeDef;
/* Miscellaneous types used for parsing ---------------------*/
/* The common part for all CDC_RNDIS messages Complete response */
typedef struct
{
uint32_t MsgType;
uint32_t MsgLength;
uint32_t ReqId;
uint32_t Status;
} USBD_CDC_RNDIS_CommonCpltMsgTypeDef;
/* Type define for a single parameter structure */
typedef struct
{
uint32_t ParamNameOffset;
uint32_t ParamNameLength;
uint32_t ParamType;
uint32_t ParamValueOffset;
uint32_t ParamValueLength;
} USBD_CDC_RNDIS_ParamStructTypeDef;
/* Type define of a single CDC_RNDIS OOB data record */
typedef struct
{
uint32_t Size;
uint32_t Type;
uint32_t ClassInfoType;
uint32_t OOBData[sizeof(uint32_t)];
} USBD_CDC_RNDIS_OOBPacketTypeDef;
/* Type define for notification structure */
typedef struct
{
uint32_t notification;
uint32_t reserved;
} USBD_CDC_RNDIS_NotifStructTypeDef;
/* This structure will be used to store the type, the size and ID for any
received message from the control endpoint */
typedef struct
{
uint32_t MsgType;
uint32_t MsgLength;
} USBD_CDC_RNDIS_CtrlMsgTypeDef;
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_CDC_RNDIS;
#define USBD_CDC_RNDIS_CLASS &USBD_CDC_RNDIS
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_CDC_RNDIS_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff);
uint8_t USBD_CDC_RNDIS_ReceivePacket(USBD_HandleTypeDef *pdev);
uint8_t USBD_CDC_RNDIS_RegisterInterface(USBD_HandleTypeDef *pdev,
USBD_CDC_RNDIS_ItfTypeDef *fops);
#ifdef USE_USBD_COMPOSITE
uint8_t USBD_CDC_RNDIS_TransmitPacket(USBD_HandleTypeDef *pdev, uint8_t ClassId);
uint8_t USBD_CDC_RNDIS_SetTxBuffer(USBD_HandleTypeDef *pdev,
uint8_t *pbuff, uint32_t length, uint8_t ClassId);
#else
uint8_t USBD_CDC_RNDIS_TransmitPacket(USBD_HandleTypeDef *pdev);
uint8_t USBD_CDC_RNDIS_SetTxBuffer(USBD_HandleTypeDef *pdev,
uint8_t *pbuff, uint32_t length);
#endif /* USE_USBD_COMPOSITE */
uint8_t USBD_CDC_RNDIS_SendNotification(USBD_HandleTypeDef *pdev,
USBD_CDC_NotifCodeTypeDef Notif,
uint16_t bVal, uint8_t *pData);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_CDC_RNDIS_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,58 @@
/**
******************************************************************************
* @file usbd_cdc_rndis_if_template.h
* @author MCD Application Team
* @brief Header for usbd_cdc_rndis_if.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2019 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CDC_RNDIS_IF_H
#define __USBD_CDC_RNDIS_IF_H
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_rndis.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Ensure this MAC address value is same as MAC_ADDRx declared in STM32xxx_conf.h */
#define CDC_RNDIS_MAC_STR_DESC (uint8_t *)"000202030000"
#define CDC_RNDIS_MAC_ADDR0 0x00U /* 01 */
#define CDC_RNDIS_MAC_ADDR1 0x02U /* 02 */
#define CDC_RNDIS_MAC_ADDR2 0x02U /* 03 */
#define CDC_RNDIS_MAC_ADDR3 0x03U /* 00 */
#define CDC_RNDIS_MAC_ADDR4 0x00U /* 00 */
#define CDC_RNDIS_MAC_ADDR5 0x00U /* 00 */
#define USBD_CDC_RNDIS_VENDOR_DESC "STMicroelectronics"
#define USBD_CDC_RNDIS_LINK_SPEED 100000U /* 10Mbps */
#define USBD_CDC_RNDIS_VID 0x0483U
/* Max Number of Trials waiting for Tx ready */
#define CDC_RNDIS_MAX_TX_WAIT_TRIALS 1000000U
/* Ethernet Maximum Segment size, typically 1514 bytes */
#define CDC_RNDIS_ETH_MAX_SEGSZE 1514U
#define CDC_RNDIS_CONNECT_SPEED_UPSTREAM 0x1E000000U
#define CDC_RNDIS_CONNECT_SPEED_DOWNSTREAM 0x1E000000U
extern USBD_CDC_RNDIS_ItfTypeDef USBD_CDC_RNDIS_fops;
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#endif /* __USBD_CDC_RNDIS_IF_H */
@@ -0,0 +1,261 @@
/**
******************************************************************************
* @file usbd_cdc_rndis_if_template.c
* @author MCD Application Team
* @brief Source file for USBD CDC_RNDIS interface template
******************************************************************************
* @attention
*
* Copyright (c) 2019 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
/* Include TCP/IP stack header files */
/*
#include "lwip/opt.h"
#include "lwip/init.h"
#include "lwip/dhcp.h"
#include "lwip/netif.h"
#include "lwip/timeouts.h"
#include "netif/etharp.h"
#include "http_cgi_ssi.h"
#include "ethernetif.h"
*/
#include "usbd_cdc_rndis_if_template.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Received Data over USB are stored in this buffer */
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif /* __ICCARM__ */
__ALIGN_BEGIN uint8_t UserRxBuffer[CDC_RNDIS_ETH_MAX_SEGSZE + 100] __ALIGN_END;
/* Transmitted Data over CDC_RNDIS (CDC_RNDIS interface) are stored in this buffer */
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif /* __ICCARM__ */
__ALIGN_BEGIN static uint8_t UserTxBuffer[CDC_RNDIS_ETH_MAX_SEGSZE + 100] __ALIGN_END;
static uint8_t CDC_RNDISInitialized = 0U;
/* USB handler declaration */
extern USBD_HandleTypeDef USBD_Device;
/* Private function prototypes -----------------------------------------------*/
static int8_t CDC_RNDIS_Itf_Init(void);
static int8_t CDC_RNDIS_Itf_DeInit(void);
static int8_t CDC_RNDIS_Itf_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length);
static int8_t CDC_RNDIS_Itf_Receive(uint8_t *pbuf, uint32_t *Len);
static int8_t CDC_RNDIS_Itf_TransmitCplt(uint8_t *pbuf, uint32_t *Len, uint8_t epnum);
static int8_t CDC_RNDIS_Itf_Process(USBD_HandleTypeDef *pdev);
USBD_CDC_RNDIS_ItfTypeDef USBD_CDC_RNDIS_fops =
{
CDC_RNDIS_Itf_Init,
CDC_RNDIS_Itf_DeInit,
CDC_RNDIS_Itf_Control,
CDC_RNDIS_Itf_Receive,
CDC_RNDIS_Itf_TransmitCplt,
CDC_RNDIS_Itf_Process,
(uint8_t *)CDC_RNDIS_MAC_STR_DESC,
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_RNDIS_Itf_Init
* Initializes the CDC_RNDIS media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_RNDIS_Itf_Init(void)
{
if (CDC_RNDISInitialized == 0U)
{
/*
Initialize the LwIP stack
Add your code here
*/
CDC_RNDISInitialized = 1U;
}
/* Set Application Buffers */
#ifdef USE_USBD_COMPOSITE
(void)USBD_CDC_RNDIS_SetTxBuffer(&USBD_Device, UserTxBuffer, 0U, 0U);
#else
(void)USBD_CDC_RNDIS_SetTxBuffer(&USBD_Device, UserTxBuffer, 0U);
#endif /* USE_USBD_COMPOSITE */
(void)USBD_CDC_RNDIS_SetRxBuffer(&USBD_Device, UserRxBuffer);
return (0);
}
/**
* @brief CDC_RNDIS_Itf_DeInit
* DeInitializes the CDC_RNDIS media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_RNDIS_Itf_DeInit(void)
{
#ifdef USE_USBD_COMPOSITE
USBD_CDC_RNDIS_HandleTypeDef *hcdc_cdc_rndis = (USBD_CDC_RNDIS_HandleTypeDef *) \
(USBD_Device.pClassDataCmsit[USBD_Device.classId]);
#else
USBD_CDC_RNDIS_HandleTypeDef *hcdc_cdc_rndis = (USBD_CDC_RNDIS_HandleTypeDef *)(USBD_Device.pClassData);
#endif /* USE_USBD_COMPOSITE */
/*
Add your code here
*/
/* Notify application layer that link is down */
hcdc_cdc_rndis->LinkStatus = 0U;
return (0);
}
/**
* @brief CDC_RNDIS_Itf_Control
* Manage the CDC_RNDIS class requests
* @param Cmd: Command code
* @param Buf: Buffer containing command data (request parameters)
* @param Len: 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_RNDIS_Itf_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length)
{
#ifdef USE_USBD_COMPOSITE
USBD_CDC_RNDIS_HandleTypeDef *hcdc_cdc_rndis = (USBD_CDC_RNDIS_HandleTypeDef *) \
(USBD_Device.pClassDataCmsit[USBD_Device.classId]);
#else
USBD_CDC_RNDIS_HandleTypeDef *hcdc_cdc_rndis = (USBD_CDC_RNDIS_HandleTypeDef *)(USBD_Device.pClassData);
#endif /* USE_USBD_COMPOSITE */
switch (cmd)
{
case CDC_RNDIS_SEND_ENCAPSULATED_COMMAND:
/* Add your code here */
break;
case CDC_RNDIS_GET_ENCAPSULATED_RESPONSE:
/* Check if this is the first time we enter */
if (hcdc_cdc_rndis->LinkStatus == 0U)
{
/* Setup the Link up at TCP/IP stack level */
hcdc_cdc_rndis->LinkStatus = 1U;
/*
Add your code here
*/
}
/* Add your code here */
break;
default:
/* Add your code here */
break;
}
UNUSED(length);
UNUSED(pbuf);
return (0);
}
/**
* @brief CDC_RNDIS_Itf_Receive
* Data received over USB OUT endpoint are sent over CDC_RNDIS interface
* through this function.
* @param Buf: Buffer of data to be transmitted
* @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_RNDIS_Itf_Receive(uint8_t *Buf, uint32_t *Len)
{
/* Get the CDC_RNDIS handler pointer */
#ifdef USE_USBD_COMPOSITE
USBD_CDC_RNDIS_HandleTypeDef *hcdc_cdc_rndis = (USBD_CDC_RNDIS_HandleTypeDef *) \
(USBD_Device.pClassDataCmsit[USBD_Device.classId]);
#else
USBD_CDC_RNDIS_HandleTypeDef *hcdc_cdc_rndis = (USBD_CDC_RNDIS_HandleTypeDef *)(USBD_Device.pClassData);
#endif /* USE_USBD_COMPOSITE */
/* Call Eth buffer processing */
hcdc_cdc_rndis->RxState = 1U;
UNUSED(Buf);
UNUSED(Len);
return (0);
}
/**
* @brief CDC_RNDIS_Itf_TransmitCplt
* 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)
* @param epnum: EP number
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_RNDIS_Itf_TransmitCplt(uint8_t *Buf, uint32_t *Len, uint8_t epnum)
{
UNUSED(Buf);
UNUSED(Len);
UNUSED(epnum);
return (0);
}
/**
* @brief CDC_RNDIS_Itf_Process
* Data received over USB OUT endpoint are sent over CDC_RNDIS interface
* through this function.
* @param pdef: pointer to the USB Device Handle
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_RNDIS_Itf_Process(USBD_HandleTypeDef *pdev)
{
/* Get the CDC_RNDIS handler pointer */
#ifdef USE_USBD_COMPOSITE
USBD_CDC_RNDIS_HandleTypeDef *hcdc_cdc_rndis = (USBD_CDC_RNDIS_HandleTypeDef *)(pdev->pClassDataCmsit[pdev->classId]);
#else
USBD_CDC_RNDIS_HandleTypeDef *hcdc_cdc_rndis = (USBD_CDC_RNDIS_HandleTypeDef *)(pdev->pClassData);
#endif /* USE_USBD_COMPOSITE */
if (hcdc_cdc_rndis == NULL)
{
return (-1);
}
if (hcdc_cdc_rndis->LinkStatus != 0U)
{
/*
Add your code here
Read a received packet from the Ethernet buffers and send it
to the lwIP for handling
*/
}
return (0);
}
@@ -0,0 +1,289 @@
/**
******************************************************************************
* @file usbd_composite_builder.h
* @author MCD Application Team
* @brief Header for the usbd_composite_builder.c file
******************************************************************************
* @attention
*
* Copyright (c) 2021 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.
*
******************************************************************************
*/
/* 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 == 1U
#include "usbd_hid.h"
#endif /* USBD_CMPSIT_ACTIVATE_HID */
#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 */
/* Private defines -----------------------------------------------------------*/
/* By default all classes are deactivated, in order to activate a class
define its value to zero */
#ifndef USBD_CMPSIT_ACTIVATE_HID
#define USBD_CMPSIT_ACTIVATE_HID 0U
#endif /* USBD_CMPSIT_ACTIVATE_HID */
#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 */
/* 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 300U
#endif /* USBD_CMPST_MAX_CONFDESC_SZ */
#ifndef USBD_CONFIG_STR_DESC_IDX
#define USBD_CONFIG_STR_DESC_IDX 4U
#endif /* USBD_CONFIG_STR_DESC_IDX */
/* 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)
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);
#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 = (uint16_t)(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,198 @@
/**
******************************************************************************
* @file usbd_customhid.h
* @author MCD Application Team
* @brief header file for the usbd_customhid.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_CUSTOMHID_H
#define __USB_CUSTOMHID_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CUSTOM_HID
* @brief This file is the Header file for USBD_customhid.c
* @{
*/
/** @defgroup USBD_CUSTOM_HID_Exported_Defines
* @{
*/
#ifndef CUSTOM_HID_EPIN_ADDR
#define CUSTOM_HID_EPIN_ADDR 0x81U
#endif /* CUSTOM_HID_EPIN_ADDR */
#ifndef CUSTOM_HID_EPIN_SIZE
#define CUSTOM_HID_EPIN_SIZE 0x02U
#endif /* CUSTOM_HID_EPIN_SIZE */
#ifndef CUSTOM_HID_EPOUT_ADDR
#define CUSTOM_HID_EPOUT_ADDR 0x01U
#endif /* CUSTOM_HID_EPOUT_ADDR */
#ifndef CUSTOM_HID_EPOUT_SIZE
#define CUSTOM_HID_EPOUT_SIZE 0x02U
#endif /* CUSTOM_HID_EPOUT_SIZE*/
#define USB_CUSTOM_HID_CONFIG_DESC_SIZ 41U
#define USB_CUSTOM_HID_DESC_SIZ 9U
#ifndef CUSTOM_HID_HS_BINTERVAL
#define CUSTOM_HID_HS_BINTERVAL 0x05U
#endif /* CUSTOM_HID_HS_BINTERVAL */
#ifndef CUSTOM_HID_FS_BINTERVAL
#define CUSTOM_HID_FS_BINTERVAL 0x05U
#endif /* CUSTOM_HID_FS_BINTERVAL */
#ifndef USBD_CUSTOMHID_OUTREPORT_BUF_SIZE
#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE 0x02U
#endif /* USBD_CUSTOMHID_OUTREPORT_BUF_SIZE */
#ifndef USBD_CUSTOM_HID_REPORT_DESC_SIZE
#define USBD_CUSTOM_HID_REPORT_DESC_SIZE 163U
#endif /* USBD_CUSTOM_HID_REPORT_DESC_SIZE */
#define CUSTOM_HID_DESCRIPTOR_TYPE 0x21U
#define CUSTOM_HID_REPORT_DESC 0x22U
#define CUSTOM_HID_REQ_SET_PROTOCOL 0x0BU
#define CUSTOM_HID_REQ_GET_PROTOCOL 0x03U
#define CUSTOM_HID_REQ_SET_IDLE 0x0AU
#define CUSTOM_HID_REQ_GET_IDLE 0x02U
#define CUSTOM_HID_REQ_SET_REPORT 0x09U
#define CUSTOM_HID_REQ_GET_REPORT 0x01U
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef enum
{
CUSTOM_HID_IDLE = 0U,
CUSTOM_HID_BUSY,
} CUSTOM_HID_StateTypeDef;
typedef struct _USBD_CUSTOM_HID_Itf
{
uint8_t *pReport;
int8_t (* Init)(void);
int8_t (* DeInit)(void);
int8_t (* OutEvent)(uint8_t event_idx, uint8_t state);
#ifdef USBD_CUSTOMHID_CTRL_REQ_COMPLETE_CALLBACK_ENABLED
int8_t (* CtrlReqComplete)(uint8_t request, uint16_t wLength);
#endif /* USBD_CUSTOMHID_CTRL_REQ_COMPLETE_CALLBACK_ENABLED */
#ifdef USBD_CUSTOMHID_CTRL_REQ_GET_REPORT_ENABLED
uint8_t *(* GetReport)(uint16_t *ReportLength);
#endif /* USBD_CUSTOMHID_CTRL_REQ_GET_REPORT_ENABLED */
} USBD_CUSTOM_HID_ItfTypeDef;
typedef struct
{
uint8_t Report_buf[USBD_CUSTOMHID_OUTREPORT_BUF_SIZE];
uint32_t Protocol;
uint32_t IdleState;
uint32_t AltSetting;
uint32_t IsReportAvailable;
CUSTOM_HID_StateTypeDef state;
} USBD_CUSTOM_HID_HandleTypeDef;
/*
* HID Class specification version 1.1
* 6.2.1 HID Descriptor
*/
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorTypeCHID;
uint16_t bcdCUSTOM_HID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bDescriptorType;
uint16_t wItemLength;
} __PACKED USBD_DescTypeDef;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_CUSTOM_HID;
#define USBD_CUSTOM_HID_CLASS &USBD_CUSTOM_HID
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
#ifdef USE_USBD_COMPOSITE
uint8_t USBD_CUSTOM_HID_SendReport(USBD_HandleTypeDef *pdev,
uint8_t *report, uint16_t len, uint8_t ClassId);
#else
uint8_t USBD_CUSTOM_HID_SendReport(USBD_HandleTypeDef *pdev,
uint8_t *report, uint16_t len);
#endif /* USE_USBD_COMPOSITE */
uint8_t USBD_CUSTOM_HID_ReceivePacket(USBD_HandleTypeDef *pdev);
uint8_t USBD_CUSTOM_HID_RegisterInterface(USBD_HandleTypeDef *pdev,
USBD_CUSTOM_HID_ItfTypeDef *fops);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_CUSTOMHID_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,41 @@
/**
******************************************************************************
* @file usbd_customhid_if_template.h
* @author MCD Application Team
* @brief Header for usbd_customhid_if_template.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CUSTOMHID_IF_TEMPLATE_H
#define __USBD_CUSTOMHID_IF_TEMPLATE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_customhid.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
extern USBD_CUSTOM_HID_ItfTypeDef USBD_CustomHID_template_fops;
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CUSTOMHID_IF_TEMPLATE_H */
@@ -0,0 +1,811 @@
/**
******************************************************************************
* @file usbd_customhid.c
* @author MCD Application Team
* @brief This file provides the CUSTOM_HID core functions.
*
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
* @verbatim
*
* ===================================================================
* CUSTOM_HID Class Description
* ===================================================================
* This module manages the CUSTOM_HID class V1.11 following the "Device Class Definition
* for Human Interface Devices (CUSTOM_HID) Version 1.11 Jun 27, 2001".
* This driver implements the following aspects of the specification:
* - The Boot Interface Subclass
* - Usage Page : Generic Desktop
* - Usage : Vendor
* - 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
*
******************************************************************************
*/
/* BSPDependencies
- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c"
- "stm32xxxxx_{eval}{discovery}_io.c"
EndBSPDependencies */
/* Includes ------------------------------------------------------------------*/
#include "usbd_customhid.h"
#include "usbd_ctlreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CUSTOM_HID
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CUSTOM_HID_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CUSTOM_HID_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CUSTOM_HID_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CUSTOM_HID_Private_FunctionPrototypes
* @{
*/
static uint8_t USBD_CUSTOM_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_CUSTOM_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_CUSTOM_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static uint8_t USBD_CUSTOM_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_CUSTOM_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_CUSTOM_HID_EP0_RxReady(USBD_HandleTypeDef *pdev);
#ifndef USE_USBD_COMPOSITE
static uint8_t *USBD_CUSTOM_HID_GetFSCfgDesc(uint16_t *length);
static uint8_t *USBD_CUSTOM_HID_GetHSCfgDesc(uint16_t *length);
static uint8_t *USBD_CUSTOM_HID_GetOtherSpeedCfgDesc(uint16_t *length);
static uint8_t *USBD_CUSTOM_HID_GetDeviceQualifierDesc(uint16_t *length);
#endif /* USE_USBD_COMPOSITE */
/**
* @}
*/
/** @defgroup USBD_CUSTOM_HID_Private_Variables
* @{
*/
USBD_ClassTypeDef USBD_CUSTOM_HID =
{
USBD_CUSTOM_HID_Init,
USBD_CUSTOM_HID_DeInit,
USBD_CUSTOM_HID_Setup,
NULL, /*EP0_TxSent*/
USBD_CUSTOM_HID_EP0_RxReady, /*EP0_RxReady*/ /* STATUS STAGE IN */
USBD_CUSTOM_HID_DataIn, /*DataIn*/
USBD_CUSTOM_HID_DataOut,
NULL, /*SOF */
NULL,
NULL,
#ifdef USE_USBD_COMPOSITE
NULL,
NULL,
NULL,
NULL,
#else
USBD_CUSTOM_HID_GetHSCfgDesc,
USBD_CUSTOM_HID_GetFSCfgDesc,
USBD_CUSTOM_HID_GetOtherSpeedCfgDesc,
USBD_CUSTOM_HID_GetDeviceQualifierDesc,
#endif /* USE_USBD_COMPOSITE */
};
#ifndef USE_USBD_COMPOSITE
/* USB CUSTOM_HID device FS Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_CUSTOM_HID_CfgDesc[USB_CUSTOM_HID_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
LOBYTE(USB_CUSTOM_HID_CONFIG_DESC_SIZ), /* wTotalLength: Bytes returned */
HIBYTE(USB_CUSTOM_HID_CONFIG_DESC_SIZ),
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor
describing the configuration */
#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) */
/************** Descriptor of CUSTOM HID 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: CUSTOM_HID */
0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0x00, /* iInterface: Index of string descriptor */
/******************** Descriptor of CUSTOM_HID *************************/
/* 18 */
0x09, /* bLength: CUSTOM_HID Descriptor size */
CUSTOM_HID_DESCRIPTOR_TYPE, /* bDescriptorType: CUSTOM_HID */
0x11, /* bCUSTOM_HIDUSTOM_HID: CUSTOM_HID Class Spec release number */
0x01,
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of CUSTOM_HID class descriptors
to follow */
0x22, /* bDescriptorType */
LOBYTE(USBD_CUSTOM_HID_REPORT_DESC_SIZE), /* wItemLength: Total length of Report descriptor */
HIBYTE(USBD_CUSTOM_HID_REPORT_DESC_SIZE),
/******************** Descriptor of Custom HID endpoints ********************/
/* 27 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */
CUSTOM_HID_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
LOBYTE(CUSTOM_HID_EPIN_SIZE), /* wMaxPacketSize: 2 Bytes max */
HIBYTE(CUSTOM_HID_EPIN_SIZE),
CUSTOM_HID_FS_BINTERVAL, /* bInterval: Polling Interval */
/* 34 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */
CUSTOM_HID_EPOUT_ADDR, /* bEndpointAddress: Endpoint Address (OUT) */
0x03, /* bmAttributes: Interrupt endpoint */
LOBYTE(CUSTOM_HID_EPOUT_SIZE), /* wMaxPacketSize: 2 Bytes max */
HIBYTE(CUSTOM_HID_EPOUT_SIZE),
CUSTOM_HID_FS_BINTERVAL, /* bInterval: Polling Interval */
/* 41 */
};
#endif /* USE_USBD_COMPOSITE */
/* USB CUSTOM_HID device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_CUSTOM_HID_Desc[USB_CUSTOM_HID_DESC_SIZ] __ALIGN_END =
{
/* 18 */
0x09, /* bLength: CUSTOM_HID Descriptor size */
CUSTOM_HID_DESCRIPTOR_TYPE, /* bDescriptorType: CUSTOM_HID */
0x11, /* bCUSTOM_HIDUSTOM_HID: CUSTOM_HID Class Spec release number */
0x01,
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of CUSTOM_HID class descriptors
to follow */
0x22, /* bDescriptorType */
LOBYTE(USBD_CUSTOM_HID_REPORT_DESC_SIZE), /* wItemLength: Total length of Report descriptor */
HIBYTE(USBD_CUSTOM_HID_REPORT_DESC_SIZE),
};
#ifndef USE_USBD_COMPOSITE
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_CUSTOM_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 */
static uint8_t CUSTOMHIDInEpAdd = CUSTOM_HID_EPIN_ADDR;
static uint8_t CUSTOMHIDOutEpAdd = CUSTOM_HID_EPOUT_ADDR;
/**
* @}
*/
/** @defgroup USBD_CUSTOM_HID_Private_Functions
* @{
*/
/**
* @brief USBD_CUSTOM_HID_Init
* Initialize the CUSTOM_HID interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_CUSTOM_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
USBD_CUSTOM_HID_HandleTypeDef *hhid;
hhid = (USBD_CUSTOM_HID_HandleTypeDef *)USBD_malloc(sizeof(USBD_CUSTOM_HID_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 */
CUSTOMHIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR, (uint8_t)pdev->classId);
CUSTOMHIDOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_INTR, (uint8_t)pdev->classId);
#endif /* USE_USBD_COMPOSITE */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
pdev->ep_in[CUSTOMHIDInEpAdd & 0xFU].bInterval = CUSTOM_HID_HS_BINTERVAL;
pdev->ep_out[CUSTOMHIDOutEpAdd & 0xFU].bInterval = CUSTOM_HID_HS_BINTERVAL;
}
else /* LOW and FULL-speed endpoints */
{
pdev->ep_in[CUSTOMHIDInEpAdd & 0xFU].bInterval = CUSTOM_HID_FS_BINTERVAL;
pdev->ep_out[CUSTOMHIDOutEpAdd & 0xFU].bInterval = CUSTOM_HID_FS_BINTERVAL;
}
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, CUSTOMHIDInEpAdd, USBD_EP_TYPE_INTR,
CUSTOM_HID_EPIN_SIZE);
pdev->ep_in[CUSTOMHIDInEpAdd & 0xFU].is_used = 1U;
/* Open EP OUT */
(void)USBD_LL_OpenEP(pdev, CUSTOMHIDOutEpAdd, USBD_EP_TYPE_INTR,
CUSTOM_HID_EPOUT_SIZE);
pdev->ep_out[CUSTOMHIDOutEpAdd & 0xFU].is_used = 1U;
hhid->state = CUSTOM_HID_IDLE;
((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData[pdev->classId])->Init();
#ifndef USBD_CUSTOMHID_OUT_PREPARE_RECEIVE_DISABLED
/* Prepare Out endpoint to receive 1st packet */
(void)USBD_LL_PrepareReceive(pdev, CUSTOMHIDOutEpAdd, hhid->Report_buf,
USBD_CUSTOMHID_OUTREPORT_BUF_SIZE);
#endif /* USBD_CUSTOMHID_OUT_PREPARE_RECEIVE_DISABLED */
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CUSTOM_HID_Init
* DeInitialize the CUSTOM_HID layer
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_CUSTOM_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
CUSTOMHIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR, (uint8_t)pdev->classId);
CUSTOMHIDOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_INTR, (uint8_t)pdev->classId);
#endif /* USE_USBD_COMPOSITE */
/* Close CUSTOM_HID EP IN */
(void)USBD_LL_CloseEP(pdev, CUSTOMHIDInEpAdd);
pdev->ep_in[CUSTOMHIDInEpAdd & 0xFU].is_used = 0U;
pdev->ep_in[CUSTOMHIDInEpAdd & 0xFU].bInterval = 0U;
/* Close CUSTOM_HID EP OUT */
(void)USBD_LL_CloseEP(pdev, CUSTOMHIDOutEpAdd);
pdev->ep_out[CUSTOMHIDOutEpAdd & 0xFU].is_used = 0U;
pdev->ep_out[CUSTOMHIDOutEpAdd & 0xFU].bInterval = 0U;
/* Free allocated memory */
if (pdev->pClassDataCmsit[pdev->classId] != NULL)
{
((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData[pdev->classId])->DeInit();
USBD_free(pdev->pClassDataCmsit[pdev->classId]);
pdev->pClassDataCmsit[pdev->classId] = NULL;
pdev->pClassData = NULL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CUSTOM_HID_Setup
* Handle the CUSTOM_HID specific requests
* @param pdev: instance
* @param req: usb requests
* @retval status
*/
static uint8_t USBD_CUSTOM_HID_Setup(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req)
{
USBD_CUSTOM_HID_HandleTypeDef *hhid = (USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
uint16_t len = 0U;
#ifdef USBD_CUSTOMHID_CTRL_REQ_GET_REPORT_ENABLED
uint16_t ReportLength = 0U;
#endif /* USBD_CUSTOMHID_CTRL_REQ_GET_REPORT_ENABLED */
uint8_t *pbuf = NULL;
uint16_t status_info = 0U;
USBD_StatusTypeDef ret = USBD_OK;
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_CLASS:
switch (req->bRequest)
{
case CUSTOM_HID_REQ_SET_PROTOCOL:
hhid->Protocol = (uint8_t)(req->wValue);
break;
case CUSTOM_HID_REQ_GET_PROTOCOL:
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->Protocol, 1U);
break;
case CUSTOM_HID_REQ_SET_IDLE:
hhid->IdleState = (uint8_t)(req->wValue >> 8);
break;
case CUSTOM_HID_REQ_GET_IDLE:
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->IdleState, 1U);
break;
case CUSTOM_HID_REQ_SET_REPORT:
#ifdef USBD_CUSTOMHID_CTRL_REQ_COMPLETE_CALLBACK_ENABLED
if (((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData[pdev->classId])->CtrlReqComplete != NULL)
{
/* Let the application decide when to enable EP0 to receive the next report */
((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData[pdev->classId])->CtrlReqComplete(req->bRequest,
req->wLength);
}
#endif /* USBD_CUSTOMHID_CTRL_REQ_COMPLETE_CALLBACK_ENABLED */
#ifndef USBD_CUSTOMHID_EP0_OUT_PREPARE_RECEIVE_DISABLED
hhid->IsReportAvailable = 1U;
(void)USBD_CtlPrepareRx(pdev, hhid->Report_buf,
MIN(req->wLength, USBD_CUSTOMHID_OUTREPORT_BUF_SIZE));
#endif /* USBD_CUSTOMHID_EP0_OUT_PREPARE_RECEIVE_DISABLED */
break;
#ifdef USBD_CUSTOMHID_CTRL_REQ_GET_REPORT_ENABLED
case CUSTOM_HID_REQ_GET_REPORT:
if (((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData[pdev->classId])->GetReport != NULL)
{
ReportLength = req->wLength;
/* Get report data buffer */
pbuf = ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData[pdev->classId])->GetReport(&ReportLength);
}
if ((pbuf != NULL) && (ReportLength != 0U))
{
len = MIN(ReportLength, req->wLength);
/* Send the report data over EP0 */
(void)USBD_CtlSendData(pdev, pbuf, len);
}
else
{
#ifdef USBD_CUSTOMHID_CTRL_REQ_COMPLETE_CALLBACK_ENABLED
if (((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData[pdev->classId])->CtrlReqComplete != NULL)
{
/* Let the application decide what to do, keep EP0 data phase in NAK state and
use USBD_CtlSendData() when data become available or stall the EP0 data phase */
((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData[pdev->classId])->CtrlReqComplete(req->bRequest,
req->wLength);
}
else
{
/* Stall EP0 if no data available */
USBD_CtlError(pdev, req);
}
#else
/* Stall EP0 if no data available */
USBD_CtlError(pdev, req);
#endif /* USBD_CUSTOMHID_CTRL_REQ_COMPLETE_CALLBACK_ENABLED */
}
break;
#endif /* USBD_CUSTOMHID_CTRL_REQ_GET_REPORT_ENABLED */
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) == CUSTOM_HID_REPORT_DESC)
{
len = MIN(USBD_CUSTOM_HID_REPORT_DESC_SIZE, req->wLength);
pbuf = ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData[pdev->classId])->pReport;
}
else
{
if ((req->wValue >> 8) == CUSTOM_HID_DESCRIPTOR_TYPE)
{
pbuf = USBD_CUSTOM_HID_Desc;
len = MIN(USB_CUSTOM_HID_DESC_SIZ, req->wLength);
}
}
if (pbuf != NULL)
{
(void)USBD_CtlSendData(pdev, pbuf, len);
}
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 *)&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_CUSTOM_HID_SendReport
* Send CUSTOM_HID Report
* @param pdev: device instance
* @param buff: pointer to report
* @param ClassId: The Class ID
* @retval status
*/
#ifdef USE_USBD_COMPOSITE
uint8_t USBD_CUSTOM_HID_SendReport(USBD_HandleTypeDef *pdev,
uint8_t *report, uint16_t len, uint8_t ClassId)
{
USBD_CUSTOM_HID_HandleTypeDef *hhid = (USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassDataCmsit[ClassId];
#else
uint8_t USBD_CUSTOM_HID_SendReport(USBD_HandleTypeDef *pdev,
uint8_t *report, uint16_t len)
{
USBD_CUSTOM_HID_HandleTypeDef *hhid = (USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif /* USE_USBD_COMPOSITE */
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
#ifdef USE_USBD_COMPOSITE
/* Get Endpoint IN address allocated for this class instance */
CUSTOMHIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR, ClassId);
#endif /* USE_USBD_COMPOSITE */
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if (hhid->state == CUSTOM_HID_IDLE)
{
hhid->state = CUSTOM_HID_BUSY;
(void)USBD_LL_Transmit(pdev, CUSTOMHIDInEpAdd, report, len);
}
else
{
return (uint8_t)USBD_BUSY;
}
}
return (uint8_t)USBD_OK;
}
#ifndef USE_USBD_COMPOSITE
/**
* @brief USBD_CUSTOM_HID_GetFSCfgDesc
* return FS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CUSTOM_HID_GetFSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CUSTOM_HID_CfgDesc, CUSTOM_HID_EPIN_ADDR);
USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_CUSTOM_HID_CfgDesc, CUSTOM_HID_EPOUT_ADDR);
if (pEpInDesc != NULL)
{
pEpInDesc->wMaxPacketSize = CUSTOM_HID_EPIN_SIZE;
pEpInDesc->bInterval = CUSTOM_HID_FS_BINTERVAL;
}
if (pEpOutDesc != NULL)
{
pEpOutDesc->wMaxPacketSize = CUSTOM_HID_EPOUT_SIZE;
pEpOutDesc->bInterval = CUSTOM_HID_FS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_CUSTOM_HID_CfgDesc);
return USBD_CUSTOM_HID_CfgDesc;
}
/**
* @brief USBD_CUSTOM_HID_GetHSCfgDesc
* return HS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CUSTOM_HID_GetHSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CUSTOM_HID_CfgDesc, CUSTOM_HID_EPIN_ADDR);
USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_CUSTOM_HID_CfgDesc, CUSTOM_HID_EPOUT_ADDR);
if (pEpInDesc != NULL)
{
pEpInDesc->wMaxPacketSize = CUSTOM_HID_EPIN_SIZE;
pEpInDesc->bInterval = CUSTOM_HID_HS_BINTERVAL;
}
if (pEpOutDesc != NULL)
{
pEpOutDesc->wMaxPacketSize = CUSTOM_HID_EPOUT_SIZE;
pEpOutDesc->bInterval = CUSTOM_HID_HS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_CUSTOM_HID_CfgDesc);
return USBD_CUSTOM_HID_CfgDesc;
}
/**
* @brief USBD_CUSTOM_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_CUSTOM_HID_GetOtherSpeedCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CUSTOM_HID_CfgDesc, CUSTOM_HID_EPIN_ADDR);
USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_CUSTOM_HID_CfgDesc, CUSTOM_HID_EPOUT_ADDR);
if (pEpInDesc != NULL)
{
pEpInDesc->wMaxPacketSize = CUSTOM_HID_EPIN_SIZE;
pEpInDesc->bInterval = CUSTOM_HID_FS_BINTERVAL;
}
if (pEpOutDesc != NULL)
{
pEpOutDesc->wMaxPacketSize = CUSTOM_HID_EPOUT_SIZE;
pEpOutDesc->bInterval = CUSTOM_HID_FS_BINTERVAL;
}
*length = (uint16_t)sizeof(USBD_CUSTOM_HID_CfgDesc);
return USBD_CUSTOM_HID_CfgDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @brief USBD_CUSTOM_HID_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_CUSTOM_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_CUSTOM_HID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId])->state = CUSTOM_HID_IDLE;
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CUSTOM_HID_DataOut
* handle data OUT Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_CUSTOM_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
UNUSED(epnum);
USBD_CUSTOM_HID_HandleTypeDef *hhid;
if (pdev->pClassDataCmsit[pdev->classId] == NULL)
{
return (uint8_t)USBD_FAIL;
}
hhid = (USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
/* USB data will be immediately processed, this allow next USB traffic being
NAKed till the end of the application processing */
((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData[pdev->classId])->OutEvent(hhid->Report_buf[0],
hhid->Report_buf[1]);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CUSTOM_HID_ReceivePacket
* prepare OUT Endpoint for reception
* @param pdev: device instance
* @retval status
*/
uint8_t USBD_CUSTOM_HID_ReceivePacket(USBD_HandleTypeDef *pdev)
{
USBD_CUSTOM_HID_HandleTypeDef *hhid;
if (pdev->pClassDataCmsit[pdev->classId] == NULL)
{
return (uint8_t)USBD_FAIL;
}
#ifdef USE_USBD_COMPOSITE
/* Get OUT Endpoint address allocated for this class instance */
CUSTOMHIDOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_INTR, (uint8_t)pdev->classId);
#endif /* USE_USBD_COMPOSITE */
hhid = (USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
/* Resume USB Out process */
(void)USBD_LL_PrepareReceive(pdev, CUSTOMHIDOutEpAdd, hhid->Report_buf,
USBD_CUSTOMHID_OUTREPORT_BUF_SIZE);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CUSTOM_HID_EP0_RxReady
* Handles control request data.
* @param pdev: device instance
* @retval status
*/
static uint8_t USBD_CUSTOM_HID_EP0_RxReady(USBD_HandleTypeDef *pdev)
{
USBD_CUSTOM_HID_HandleTypeDef *hhid = (USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
if (hhid->IsReportAvailable == 1U)
{
((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData[pdev->classId])->OutEvent(hhid->Report_buf[0],
hhid->Report_buf[1]);
hhid->IsReportAvailable = 0U;
}
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_CUSTOM_HID_GetDeviceQualifierDesc(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_CUSTOM_HID_DeviceQualifierDesc);
return USBD_CUSTOM_HID_DeviceQualifierDesc;
}
#endif /* USE_USBD_COMPOSITE */
/**
* @brief USBD_CUSTOM_HID_RegisterInterface
* @param pdev: device instance
* @param fops: CUSTOMHID Interface callback
* @retval status
*/
uint8_t USBD_CUSTOM_HID_RegisterInterface(USBD_HandleTypeDef *pdev,
USBD_CUSTOM_HID_ItfTypeDef *fops)
{
if (fops == NULL)
{
return (uint8_t)USBD_FAIL;
}
pdev->pUserData[pdev->classId] = fops;
return (uint8_t)USBD_OK;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,158 @@
/**
******************************************************************************
* @file usbd_customhid_if_template.c
* @author MCD Application Team
* @brief USB Device Custom HID interface file.
* This template should be copied to the user folder, renamed and customized
* following user needs.
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* BSPDependencies
- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c"
- "stm32xxxxx_{eval}{discovery}_io.c"
EndBSPDependencies */
/* Includes ------------------------------------------------------------------*/
#include "usbd_customhid_if_template.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static int8_t TEMPLATE_CUSTOM_HID_Init(void);
static int8_t TEMPLATE_CUSTOM_HID_DeInit(void);
static int8_t TEMPLATE_CUSTOM_HID_OutEvent(uint8_t event_idx, uint8_t state);
#ifdef USBD_CUSTOMHID_CTRL_REQ_COMPLETE_CALLBACK_ENABLED
static int8_t TEMPLATE_CUSTOM_HID_CtrlReqComplete(uint8_t request, uint16_t wLength);
#endif /* USBD_CUSTOMHID_CTRL_REQ_COMPLETE_CALLBACK_ENABLED */
#ifdef USBD_CUSTOMHID_CTRL_REQ_GET_REPORT_ENABLED
static uint8_t *TEMPLATE_CUSTOM_HID_GetReport(uint16_t *ReportLength);
#endif /* USBD_CUSTOMHID_CTRL_REQ_GET_REPORT_ENABLED */
/* Private variables ---------------------------------------------------------*/
extern USBD_HandleTypeDef USBD_Device;
__ALIGN_BEGIN static uint8_t TEMPLATE_CUSTOM_HID_ReportDesc[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END = {0};
USBD_CUSTOM_HID_ItfTypeDef USBD_CustomHID_template_fops =
{
TEMPLATE_CUSTOM_HID_ReportDesc,
TEMPLATE_CUSTOM_HID_Init,
TEMPLATE_CUSTOM_HID_DeInit,
TEMPLATE_CUSTOM_HID_OutEvent,
#ifdef USBD_CUSTOMHID_CTRL_REQ_COMPLETE_CALLBACK_ENABLED
TEMPLATE_CUSTOM_HID_CtrlReqComplete,
#endif /* USBD_CUSTOMHID_CTRL_REQ_COMPLETE_CALLBACK_ENABLED */
#ifdef USBD_CUSTOMHID_CTRL_REQ_GET_REPORT_ENABLED
TEMPLATE_CUSTOM_HID_GetReport,
#endif /* USBD_CUSTOMHID_CTRL_REQ_GET_REPORT_ENABLED */
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief TEMPLATE_CUSTOM_HID_Init
* Initializes the CUSTOM HID media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_CUSTOM_HID_Init(void)
{
return (0);
}
/**
* @brief TEMPLATE_CUSTOM_HID_DeInit
* DeInitializes the CUSTOM HID media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_CUSTOM_HID_DeInit(void)
{
/*
Add your deinitialization code here
*/
return (0);
}
/**
* @brief TEMPLATE_CUSTOM_HID_Control
* Manage the CUSTOM HID class events
* @param event_idx: event index
* @param state: event state
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_CUSTOM_HID_OutEvent(uint8_t event_idx, uint8_t state)
{
UNUSED(event_idx);
UNUSED(state);
/* Start next USB packet transfer once data processing is completed */
if (USBD_CUSTOM_HID_ReceivePacket(&USBD_Device) != (uint8_t)USBD_OK)
{
return -1;
}
return (0);
}
#ifdef USBD_CUSTOMHID_CTRL_REQ_COMPLETE_CALLBACK_ENABLED
/**
* @brief TEMPLATE_CUSTOM_HID_CtrlReqComplete
* Manage the CUSTOM HID control request complete
* @param request: control request
* @param wLength: request wLength
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_CUSTOM_HID_CtrlReqComplete(uint8_t request, uint16_t wLength)
{
UNUSED(wLength);
switch (request)
{
case CUSTOM_HID_REQ_SET_REPORT:
break;
case CUSTOM_HID_REQ_GET_REPORT:
break;
default:
break;
}
return (0);
}
#endif /* USBD_CUSTOMHID_CTRL_REQ_COMPLETE_CALLBACK_ENABLED */
#ifdef USBD_CUSTOMHID_CTRL_REQ_GET_REPORT_ENABLED
/**
* @brief TEMPLATE_CUSTOM_HID_GetReport
* Manage the CUSTOM HID control Get Report request
* @param event_idx: event index
* @param state: event state
* @retval return pointer to HID report
*/
static uint8_t *TEMPLATE_CUSTOM_HID_GetReport(uint16_t *ReportLength)
{
UNUSED(ReportLength);
uint8_t *pbuff;
return (pbuff);
}
#endif /* USBD_CUSTOMHID_CTRL_REQ_GET_REPORT_ENABLED */
@@ -0,0 +1,271 @@
/**
******************************************************************************
* @file usbd_dfu.h
* @author MCD Application Team
* @brief Header file for the usbd_dfu.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_DFU_H
#define __USB_DFU_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_DFU
* @brief This file is the Header file for usbd_dfu.c
* @{
*/
/** @defgroup USBD_DFU_Exported_Defines
* @{
*/
#ifndef USBD_DFU_MAX_ITF_NUM
#define USBD_DFU_MAX_ITF_NUM 1U
#endif /* USBD_DFU_MAX_ITF_NUM */
#ifndef USBD_DFU_XFER_SIZE
#define USBD_DFU_XFER_SIZE 1024U
#endif /* USBD_DFU_XFER_SIZE */
#ifndef USBD_DFU_APP_DEFAULT_ADD
#define USBD_DFU_APP_DEFAULT_ADD 0x08008000U /* The first sector (32 KB) is reserved for DFU code */
#endif /* USBD_DFU_APP_DEFAULT_ADD */
#ifndef USBD_DFU_BM_ATTRIBUTES
#define USBD_DFU_BM_ATTRIBUTES 0x0BU
#endif /* USBD_DFU_BM_ATTRIBUTES */
#ifndef USBD_DFU_DETACH_TIMEOUT
#define USBD_DFU_DETACH_TIMEOUT 0xFFU
#endif /* USBD_DFU_DETACH_TIMEOUT */
#define USB_DFU_CONFIG_DESC_SIZ (18U + (9U * USBD_DFU_MAX_ITF_NUM))
#define USB_DFU_DESC_SIZ 9U
#define DFU_DESCRIPTOR_TYPE 0x21U
#define DFU_VENDOR_CMD_MAX 32U
/**************************************************/
/* DFU Requests DFU states */
/**************************************************/
#define APP_STATE_IDLE 0U
#define APP_STATE_DETACH 1U
#define DFU_STATE_IDLE 2U
#define DFU_STATE_DNLOAD_SYNC 3U
#define DFU_STATE_DNLOAD_BUSY 4U
#define DFU_STATE_DNLOAD_IDLE 5U
#define DFU_STATE_MANIFEST_SYNC 6U
#define DFU_STATE_MANIFEST 7U
#define DFU_STATE_MANIFEST_WAIT_RESET 8U
#define DFU_STATE_UPLOAD_IDLE 9U
#define DFU_STATE_ERROR 10U
/**************************************************/
/* DFU errors */
/**************************************************/
#define DFU_ERROR_NONE 0x00U
#define DFU_ERROR_TARGET 0x01U
#define DFU_ERROR_FILE 0x02U
#define DFU_ERROR_WRITE 0x03U
#define DFU_ERROR_ERASE 0x04U
#define DFU_ERROR_CHECK_ERASED 0x05U
#define DFU_ERROR_PROG 0x06U
#define DFU_ERROR_VERIFY 0x07U
#define DFU_ERROR_ADDRESS 0x08U
#define DFU_ERROR_NOTDONE 0x09U
#define DFU_ERROR_FIRMWARE 0x0AU
#define DFU_ERROR_VENDOR 0x0BU
#define DFU_ERROR_USB 0x0CU
#define DFU_ERROR_POR 0x0DU
#define DFU_ERROR_UNKNOWN 0x0EU
#define DFU_ERROR_STALLEDPKT 0x0FU
/**************************************************/
/* DFU Manifestation State */
/**************************************************/
#define DFU_MANIFEST_COMPLETE 0x00U
#define DFU_MANIFEST_IN_PROGRESS 0x01U
/**************************************************/
/* Special Commands with Download Request */
/**************************************************/
#define DFU_CMD_GETCOMMANDS 0x00U
#define DFU_CMD_SETADDRESSPOINTER 0x21U
#define DFU_CMD_ERASE 0x41U
#define DFU_MEDIA_ERASE 0x00U
#define DFU_MEDIA_PROGRAM 0x01U
/**************************************************/
/* Other defines */
/**************************************************/
/* Bit Detach capable = bit 3 in bmAttributes field */
#define DFU_DETACH_MASK (1U << 3)
#define DFU_MANIFEST_MASK (1U << 2)
#define DFU_STATUS_DEPTH 6U
#define IS_DFU_DOWNLOAD 0x0DFDFU
#define IS_DFU_UPLOAD 0x1DFDFU
#define IS_DFU_SETADDRESSPOINTER 0x2DFDFU
#define IS_DFU_PHY_ADDRESS 0x3DFDFU
typedef enum
{
DFU_DETACH = 0U,
DFU_DNLOAD,
DFU_UPLOAD,
DFU_GETSTATUS,
DFU_CLRSTATUS,
DFU_GETSTATE,
DFU_ABORT
} DFU_RequestTypeDef;
typedef void (*pFunction)(void);
/********** Descriptor of DFU interface 0 Alternate setting n ****************/
#define USBD_DFU_IF_DESC(n) \
0x09, /* bLength: Interface Descriptor size */ \
USB_DESC_TYPE_INTERFACE, /* bDescriptorType */ \
0x00, /* bInterfaceNumber: Number of Interface */ \
(n), /* bAlternateSetting: Alternate setting */ \
0x00, /* bNumEndpoints*/ \
0xFE, /* bInterfaceClass: Application Specific Class Code */ \
0x01, /* bInterfaceSubClass : Device Firmware Upgrade Code */ \
0x02, /* nInterfaceProtocol: DFU mode protocol */ \
USBD_IDX_INTERFACE_STR + (n) + 1U /* iInterface: Index of string descriptor */
#define TRANSFER_SIZE_BYTES(size) ((uint8_t)(size)), ((uint8_t)((size) >> 8))
#define IS_PROTECTED_AREA(add) (uint8_t)((((add) >= 0x08000000) && ((add) < (APP_DEFAULT_ADD))) ? 1 : 0)
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef struct
{
union
{
uint32_t d32[USBD_DFU_XFER_SIZE / 4U];
uint8_t d8[USBD_DFU_XFER_SIZE];
} buffer;
uint32_t wblock_num;
uint32_t wlength;
uint32_t data_ptr;
uint32_t app_addr_ptr;
uint32_t alt_setting;
uint8_t dev_status[DFU_STATUS_DEPTH];
uint8_t ReservedForAlign[2];
uint8_t dev_state;
uint8_t manif_state;
} USBD_DFU_HandleTypeDef;
typedef struct
{
const uint8_t *pStrDesc;
uint16_t (* Init)(void);
uint16_t (* DeInit)(void);
uint16_t (* Erase)(uint32_t Add);
uint16_t (* Write)(uint8_t *src, uint8_t *dest, uint32_t Len);
uint8_t *(* Read)(uint8_t *src, uint8_t *dest, uint32_t Len);
uint16_t (* GetStatus)(uint32_t Add, uint8_t cmd, uint8_t *buff);
#if (USBD_DFU_VENDOR_CMD_ENABLED == 1U)
uint16_t (* GetVendorCMD)(uint8_t *cmd, uint8_t *cmdlength);
uint16_t (* VendorDownloadCMD)(uint8_t *pbuf, uint32_t BlockNumber, uint32_t wlength, uint32_t *status);
uint16_t (* VendorUploadCMD)(uint32_t Add, uint32_t BlockNumber, uint32_t *status);
#endif /* USBD_DFU_VENDOR_CMD_ENABLED */
#if (USBD_DFU_VENDOR_CHECK_ENABLED == 1U)
uint16_t (* VendorCheck)(uint8_t *pbuf, uint32_t ReqType, uint32_t *status);
#endif /* USBD_DFU_VENDOR_CHECK_ENABLED */
#if (USBD_DFU_VENDOR_EXIT_ENABLED == 1U)
uint16_t (* LeaveDFU)(uint32_t Add);
#endif /* USBD_DFU_VENDOR_EXIT_ENABLED */
} USBD_DFU_MediaTypeDef;
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bmAttributes;
uint16_t wDetachTimeout;
uint16_t wTransferSze;
uint16_t bcdDFUVersion;
} __PACKED USBD_DFUFuncDescTypeDef;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_DFU;
#define USBD_DFU_CLASS &USBD_DFU
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_DFU_RegisterMedia(USBD_HandleTypeDef *pdev,
USBD_DFU_MediaTypeDef *fops);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_DFU_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,95 @@
/**
******************************************************************************
* @file usbd_dfu_media_template.h
* @author MCD Application Team
* @brief header file for the usbd_dfu_media_template.c file
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_DFU_MEDIA_TEMPLATE_H
#define __USBD_DFU_MEDIA_TEMPLATE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_dfu.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_MEDIA
* @brief header file for the usbd_dfu_media_template.c file
* @{
*/
/** @defgroup USBD_MEDIA_Exported_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_MEDIA_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USBD_MEDIA_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_MEDIA_Exported_Variables
* @{
*/
extern USBD_DFU_MediaTypeDef USBD_DFU_MEDIA_Template_fops;
/**
* @}
*/
/** @defgroup USBD_MEDIA_Exported_FunctionsPrototype
* @{
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_DFU_MEDIA_TEMPLATE_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,250 @@
/**
******************************************************************************
* @file usbd_dfu_media_template.c
* @author MCD Application Team
* @brief Memory management layer
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* BSPDependencies
- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c"
- "stm32xxxxx_{eval}{discovery}_io.c"
EndBSPDependencies */
/* Includes ------------------------------------------------------------------*/
#include "usbd_dfu_media_template.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Extern function prototypes ------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
uint16_t MEM_If_Init(void);
uint16_t MEM_If_Erase(uint32_t Add);
uint16_t MEM_If_Write(uint8_t *src, uint8_t *dest, uint32_t Len);
uint8_t *MEM_If_Read(uint8_t *src, uint8_t *dest, uint32_t Len);
uint16_t MEM_If_DeInit(void);
uint16_t MEM_If_GetStatus(uint32_t Add, uint8_t Cmd, uint8_t *buffer);
#if (USBD_DFU_VENDOR_CMD_ENABLED == 1U)
uint16_t MEM_If_GetVendorCMD(uint8_t *cmd, uint8_t *cmdlength);
uint16_t MEM_If_VendorDownloadCMD(uint8_t *pbuf, uint32_t BlockNumber, uint32_t wlength, uint32_t *status);
uint16_t MEM_If_VendorUploadCMD(uint32_t Add, uint32_t BlockNumber, uint32_t *status);
#endif /* USBD_DFU_VENDOR_CMD_ENABLED */
#if (USBD_DFU_VENDOR_CHECK_ENABLED == 1U)
uint16_t MEM_If_VendorCheck(uint8_t *pbuf, uint32_t ReqType, uint32_t *status);
#endif /* USBD_DFU_VENDOR_CHECK_ENABLED */
#if (USBD_DFU_VENDOR_EXIT_ENABLED == 1U)
uint16_t MEM_If_LeaveDFU(uint32_t Add);
#endif /* USBD_DFU_VENDOR_EXIT_ENABLED */
USBD_DFU_MediaTypeDef USBD_DFU_MEDIA_Template_fops =
{
(uint8_t *)"DFU MEDIA",
MEM_If_Init,
MEM_If_DeInit,
MEM_If_Erase,
MEM_If_Write,
MEM_If_Read,
MEM_If_GetStatus,
#if (USBD_DFU_VENDOR_CMD_ENABLED == 1U)
MEM_If_GetVendorCMD,
MEM_If_VendorDownloadCMD,
MEM_If_VendorUploadCMD,
#endif /* USBD_DFU_VENDOR_CMD_ENABLED */
#if (USBD_DFU_VENDOR_CHECK_ENABLED == 1U)
MEM_If_VendorCheck,
#endif /* USBD_DFU_VENDOR_CHECK_ENABLED */
#if (USBD_DFU_VENDOR_EXIT_ENABLED == 1U)
MEM_If_LeaveDFU
#endif /* USBD_DFU_VENDOR_EXIT_ENABLED */
};
/**
* @brief MEM_If_Init
* Memory initialization routine.
* @param None
* @retval 0 if operation is successful, MAL_FAIL else.
*/
uint16_t MEM_If_Init(void)
{
return 0;
}
/**
* @brief MEM_If_DeInit
* Memory deinitialization routine.
* @param None
* @retval 0 if operation is successful, MAL_FAIL else.
*/
uint16_t MEM_If_DeInit(void)
{
return 0;
}
/**
* @brief MEM_If_Erase
* Erase sector.
* @param Add: Address of sector to be erased.
* @retval 0 if operation is successful, MAL_FAIL else.
*/
uint16_t MEM_If_Erase(uint32_t Add)
{
UNUSED(Add);
return 0;
}
/**
* @brief MEM_If_Write
* Memory write routine.
* @param Add: Address to be written to.
* @param Len: Number of data to be written (in bytes).
* @retval 0 if operation is successful, MAL_FAIL else.
*/
uint16_t MEM_If_Write(uint8_t *src, uint8_t *dest, uint32_t Len)
{
UNUSED(src);
UNUSED(dest);
UNUSED(Len);
return 0;
}
/**
* @brief MEM_If_Read
* Memory read routine.
* @param Add: Address to be read from.
* @param Len: Number of data to be read (in bytes).
* @retval Pointer to the physical address where data should be read.
*/
uint8_t *MEM_If_Read(uint8_t *src, uint8_t *dest, uint32_t Len)
{
UNUSED(src);
UNUSED(dest);
UNUSED(Len);
/* Return a valid address to avoid HardFault */
return NULL;
}
/**
* @brief Flash_If_GetStatus
* Memory read routine.
* @param Add: Address to be read from.
* @param cmd: Number of data to be read (in bytes).
* @retval Pointer to the physical address where data should be read.
*/
uint16_t MEM_If_GetStatus(uint32_t Add, uint8_t Cmd, uint8_t *buffer)
{
UNUSED(Add);
UNUSED(buffer);
switch (Cmd)
{
case DFU_MEDIA_PROGRAM:
break;
case DFU_MEDIA_ERASE:
default:
break;
}
return (0);
}
#if (USBD_DFU_VENDOR_CMD_ENABLED == 1U)
/**
* @brief Get supported vendor specific commands
* @param pointer to supported vendor commands
* @param pointer to length of supported vendor commands
* @retval 0 if operation is successful
*/
uint16_t MEM_If_GetVendorCMD(uint8_t *cmd, uint8_t *cmdlength)
{
UNUSED(cmd);
UNUSED(cmdlength);
return 0U;
}
/**
* @brief Vendor specific download commands
* @param pbuf DFU data buffer
* @param BlockNumber DFU memory block number
* @param wLength DFU request length
* @param pointer to DFU status
* @retval 0 if operation is successful
*/
uint16_t MEM_If_VendorDownloadCMD(uint8_t *pbuf, uint32_t BlockNumber, uint32_t wlength, uint32_t *status)
{
UNUSED(pbuf);
UNUSED(BlockNumber);
UNUSED(wlength);
UNUSED(status);
return 0U;
}
/**
* @brief Vendor specific upload commands
* @param Add memory Address
* @param BlockNumber DFU memory block number
* @param pointer to DFU status
* @retval 0 if operation is successful
*/
uint16_t MEM_If_VendorUploadCMD(uint32_t Add, uint32_t BlockNumber, uint32_t *status)
{
UNUSED(Add);
UNUSED(BlockNumber);
UNUSED(status);
return 0U;
}
#endif /* USBD_DFU_VENDOR_CMD_ENABLED */
#if (USBD_DFU_VENDOR_CHECK_ENABLED == 1U)
/**
* @brief Vendor memory check
* @param pbuf DFU data buffer
* @param ReqType IS_DFU_SETADDRESSPOINTER/DOWNLOAD/UPLOAD
* @param pointer to DFU status
* @retval 0 if operation is successful
*/
uint16_t MEM_If_VendorCheck(uint8_t *pbuf, uint32_t ReqType, uint32_t *status)
{
UNUSED(pbuf);
UNUSED(ReqType);
UNUSED(status);
return 0U;
}
#endif /* USBD_DFU_VENDOR_CHECK_ENABLED */
#if (USBD_DFU_VENDOR_EXIT_ENABLED == 1U)
/**
* @brief Vendor Leave DFU
* @param Application address
* @retval 0 if operation is successful
*/
uint16_t MEM_If_LeaveDFU(uint32_t Add)
{
UNUSED(Add);
return 0U;
}
#endif /* USBD_DFU_VENDOR_EXIT_ENABLED */
@@ -0,0 +1,160 @@
/**
******************************************************************************
* @file usbd_hid.h
* @author MCD Application Team
* @brief Header file for the usbd_hid_core.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_HID_H
#define __USB_HID_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_HID
* @brief This file is the Header file for usbd_hid.c
* @{
*/
/** @defgroup USBD_HID_Exported_Defines
* @{
*/
#ifndef HID_EPIN_ADDR
#define HID_EPIN_ADDR 0x81U
#endif /* HID_EPIN_ADDR */
#define HID_EPIN_SIZE 0x04U
#define USB_HID_CONFIG_DESC_SIZ 34U
#define USB_HID_DESC_SIZ 9U
#define HID_MOUSE_REPORT_DESC_SIZE 74U
#define HID_DESCRIPTOR_TYPE 0x21U
#define HID_REPORT_DESC 0x22U
#ifndef HID_HS_BINTERVAL
#define HID_HS_BINTERVAL 0x07U
#endif /* HID_HS_BINTERVAL */
#ifndef HID_FS_BINTERVAL
#define HID_FS_BINTERVAL 0x0AU
#endif /* HID_FS_BINTERVAL */
#define USBD_HID_REQ_SET_PROTOCOL 0x0BU
#define USBD_HID_REQ_GET_PROTOCOL 0x03U
#define USBD_HID_REQ_SET_IDLE 0x0AU
#define USBD_HID_REQ_GET_IDLE 0x02U
#define USBD_HID_REQ_SET_REPORT 0x09U
#define USBD_HID_REQ_GET_REPORT 0x01U
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef enum
{
USBD_HID_IDLE = 0,
USBD_HID_BUSY,
} USBD_HID_StateTypeDef;
typedef struct
{
uint32_t Protocol;
uint32_t IdleState;
uint32_t AltSetting;
USBD_HID_StateTypeDef state;
} USBD_HID_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_HIDDescTypeDef;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_HID;
#define USBD_HID_CLASS &USBD_HID
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
#ifdef USE_USBD_COMPOSITE
uint8_t USBD_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len, uint8_t ClassId);
#else
uint8_t USBD_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
#endif /* USE_USBD_COMPOSITE */
uint32_t USBD_HID_GetPollingInterval(USBD_HandleTypeDef *pdev);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HID_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,650 @@
/**
******************************************************************************
* @file usbd_hid.c
* @author MCD Application Team
* @brief This file provides the HID core functions.
*
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
* @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 : Joystick
* - 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
*
******************************************************************************
*/
/* BSPDependencies
- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c"
- "stm32xxxxx_{eval}{discovery}_io.c"
EndBSPDependencies */
/* Includes ------------------------------------------------------------------*/
#include "usbd_hid.h"
#include "usbd_ctlreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @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);
#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 =
{
USBD_HID_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL, /* EP0_TxSent */
NULL, /* 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_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_HID_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_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_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
HID_EPIN_SIZE, /* wMaxPacketSize: 4 Bytes max */
0x00,
HID_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_DESC_SIZ] __ALIGN_END =
{
/* 18 */
0x09, /* bLength: HID Descriptor size */
HID_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_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_HandleTypeDef *hhid;
hhid = (USBD_HID_HandleTypeDef *)USBD_malloc(sizeof(USBD_HID_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, (uint8_t)pdev->classId);
#endif /* USE_USBD_COMPOSITE */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = HID_HS_BINTERVAL;
}
else /* LOW and FULL-speed endpoints */
{
pdev->ep_in[HIDInEpAdd & 0xFU].bInterval = HID_FS_BINTERVAL;
}
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, HIDInEpAdd, USBD_EP_TYPE_INTR, HID_EPIN_SIZE);
pdev->ep_in[HIDInEpAdd & 0xFU].is_used = 1U;
hhid->state = USBD_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, (uint8_t)pdev->classId);
#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_HandleTypeDef *hhid = (USBD_HID_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 USBD_HID_REQ_SET_PROTOCOL:
hhid->Protocol = (uint8_t)(req->wValue);
break;
case USBD_HID_REQ_GET_PROTOCOL:
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->Protocol, 1U);
break;
case USBD_HID_REQ_SET_IDLE:
hhid->IdleState = (uint8_t)(req->wValue >> 8);
break;
case USBD_HID_REQ_GET_IDLE:
(void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->IdleState, 1U);
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_REPORT_DESC)
{
len = MIN(HID_MOUSE_REPORT_DESC_SIZE, req->wLength);
pbuf = HID_MOUSE_ReportDesc;
}
else if ((req->wValue >> 8) == HID_DESCRIPTOR_TYPE)
{
pbuf = USBD_HID_Desc;
len = MIN(USB_HID_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_SendReport
* Send HID Report
* @param pdev: device instance
* @param buff: pointer to report
* @param ClassId: The Class ID
* @retval status
*/
#ifdef USE_USBD_COMPOSITE
uint8_t USBD_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len, uint8_t ClassId)
{
USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef *)pdev->pClassDataCmsit[ClassId];
#else
uint8_t USBD_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len)
{
USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
#endif /* USE_USBD_COMPOSITE */
if (hhid == NULL)
{
return (uint8_t)USBD_FAIL;
}
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
HIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR, ClassId);
#endif /* USE_USBD_COMPOSITE */
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if (hhid->state == USBD_HID_IDLE)
{
hhid->state = USBD_HID_BUSY;
(void)USBD_LL_Transmit(pdev, HIDInEpAdd, report, len);
}
}
return (uint8_t)USBD_OK;
}
/**
* @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_HS_BINTERVAL */
polling_interval = (((1U << (HID_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_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_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_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_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_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_EPIN_ADDR);
if (pEpDesc != NULL)
{
pEpDesc->bInterval = HID_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_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId])->state = USBD_HID_IDLE;
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,130 @@
/**
******************************************************************************
* @file usbd_msc.h
* @author MCD Application Team
* @brief Header for the usbd_msc.c file
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* 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,146 @@
/**
******************************************************************************
* @file usbd_msc_bot.h
* @author MCD Application Team
* @brief Header for the usbd_msc_bot.c file
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* 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"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @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,102 @@
/**
******************************************************************************
* @file usbd_msc_data.h
* @author MCD Application Team
* @brief Header for the usbd_msc_data.c file
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* 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"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USB_INFO
* @brief general defines for the usb device library file
* @{
*/
/** @defgroup USB_INFO_Exported_Defines
* @{
*/
#define MODE_SENSE6_LEN 0x04U
#define MODE_SENSE10_LEN 0x08U
#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,182 @@
/**
******************************************************************************
* @file usbd_msc_scsi.h
* @author MCD Application Team
* @brief Header for the usbd_msc_scsi.c file
******************************************************************************
* @attention
*
* Copyright (c) 2015 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.
*
******************************************************************************
*/
/* 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"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @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 MSC_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 */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/

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