diff options
Diffstat (limited to 'components/drivers')
47 files changed, 2709 insertions, 1315 deletions
diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index b0caabc73c..d3fd14b52d 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -24,22 +24,30 @@ if RT_USING_DEVICE_IPC endif endif -config RT_USING_SERIAL - bool "Using serial device drivers" +menuconfig RT_USING_SERIAL + bool "USING Serial device drivers" select RT_USING_DEVICE_IPC select RT_USING_DEVICE default y -if RT_USING_SERIAL - config RT_SERIAL_USING_DMA - bool "Enable serial DMA mode" - default y - - config RT_SERIAL_RB_BUFSZ - int "Set RX buffer size" - default 64 + if RT_USING_SERIAL + choice + prompt "Choice Serial version" + default RT_USING_SERIAL_V1 + config RT_USING_SERIAL_V1 + bool "RT_USING_SERIAL_V1" + config RT_USING_SERIAL_V2 + bool "RT_USING_SERIAL_V2" + endchoice + config RT_SERIAL_USING_DMA + bool "Enable serial DMA mode" + default y -endif + config RT_SERIAL_RB_BUFSZ + int "Set RX buffer size" + depends on !RT_USING_SERIAL_V2 + default 64 + endif config RT_USING_CAN bool "Using CAN device drivers" @@ -153,20 +161,6 @@ config RT_USING_RTC config RT_USING_SOFT_RTC bool "Using software simulation RTC device" default n - - config RTC_SYNC_USING_NTP - bool "Using NTP auto sync RTC time" - depends on PKG_NETUTILS_NTP - default y - - if RTC_SYNC_USING_NTP - config RTC_NTP_FIRST_SYNC_DELAY - int "NTP first sync delay time(second) for network connect" - default 30 - config RTC_NTP_SYNC_PERIOD - int "NTP auto sync period(second)" - default 3600 - endif endif config RT_USING_SDIO diff --git a/components/drivers/cputime/cputime.c b/components/drivers/cputime/cputime.c index 4a9eee3a71..750733f366 100644 --- a/components/drivers/cputime/cputime.c +++ b/components/drivers/cputime/cputime.c @@ -10,6 +10,7 @@ #include <rtdevice.h> #include <rtthread.h> +#include <sys/errno.h> static const struct rt_clock_cputime_ops *_cputime_ops = RT_NULL; @@ -24,7 +25,7 @@ float clock_cpu_getres(void) if (_cputime_ops) return _cputime_ops->cputime_getres(); - rt_set_errno(-ENOSYS); + rt_set_errno(ENOSYS); return 0; } @@ -38,7 +39,7 @@ uint32_t clock_cpu_gettime(void) if (_cputime_ops) return _cputime_ops->cputime_gettime(); - rt_set_errno(-ENOSYS); + rt_set_errno(ENOSYS); return 0; } diff --git a/components/drivers/i2c/i2c_core.c b/components/drivers/i2c/i2c_core.c index 87178e37d5..47ba76d2be 100644 --- a/components/drivers/i2c/i2c_core.c +++ b/components/drivers/i2c/i2c_core.c @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2012-04-25 weety first version + * 2021-04-20 RiceChen added support for bus control api */ #include <rtdevice.h> @@ -81,6 +82,26 @@ rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, } } +rt_err_t rt_i2c_control(struct rt_i2c_bus_device *bus, + rt_uint32_t cmd, + rt_uint32_t arg) +{ + rt_err_t ret; + + if(bus->ops->i2c_bus_control) + { + ret = bus->ops->i2c_bus_control(bus, cmd, arg); + + return ret; + } + else + { + LOG_E("I2C bus operation not supported"); + + return 0; + } +} + rt_size_t rt_i2c_master_send(struct rt_i2c_bus_device *bus, rt_uint16_t addr, rt_uint16_t flags, diff --git a/components/drivers/i2c/i2c_dev.c b/components/drivers/i2c/i2c_dev.c index 4f567f8227..c30bb62a92 100644 --- a/components/drivers/i2c/i2c_dev.c +++ b/components/drivers/i2c/i2c_dev.c @@ -7,6 +7,7 @@ * Date Author Notes * 2012-04-25 weety first version * 2014-08-03 bernard fix some compiling warning + * 2021-04-20 RiceChen added support for bus clock control */ #include <rtdevice.h> @@ -66,6 +67,7 @@ static rt_err_t i2c_bus_device_control(rt_device_t dev, rt_err_t ret; struct rt_i2c_priv_data *priv_data; struct rt_i2c_bus_device *bus = (struct rt_i2c_bus_device *)dev->user_data; + rt_uint32_t bus_clock; RT_ASSERT(bus != RT_NULL); @@ -89,6 +91,14 @@ static rt_err_t i2c_bus_device_control(rt_device_t dev, return -RT_EIO; } break; + case RT_I2C_DEV_CTRL_CLK: + bus_clock = *(rt_uint32_t *)args; + ret = rt_i2c_control(bus, cmd, bus_clock); + if (ret < 0) + { + return -RT_EIO; + } + break; default: break; } diff --git a/components/drivers/include/drivers/i2c.h b/components/drivers/include/drivers/i2c.h index 50ce021d53..7bf99d26cc 100644 --- a/components/drivers/include/drivers/i2c.h +++ b/components/drivers/include/drivers/i2c.h @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2012-04-25 weety first version + * 2021-04-20 RiceChen added support for bus control api */ #ifndef __I2C_H__ @@ -74,6 +75,9 @@ struct rt_i2c_bus_device *rt_i2c_bus_device_find(const char *bus_name); rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num); +rt_err_t rt_i2c_control(struct rt_i2c_bus_device *bus, + rt_uint32_t cmd, + rt_uint32_t arg); rt_size_t rt_i2c_master_send(struct rt_i2c_bus_device *bus, rt_uint16_t addr, rt_uint16_t flags, diff --git a/components/drivers/include/drivers/i2c_dev.h b/components/drivers/include/drivers/i2c_dev.h index 94f110c055..080ff26f87 100644 --- a/components/drivers/include/drivers/i2c_dev.h +++ b/components/drivers/include/drivers/i2c_dev.h @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2012-04-25 weety first version + * 2021-04-20 RiceChen added bus clock command */ #ifndef __I2C_DEV_H__ @@ -21,6 +22,7 @@ extern "C" { #define RT_I2C_DEV_CTRL_ADDR 0x21 #define RT_I2C_DEV_CTRL_TIMEOUT 0x22 #define RT_I2C_DEV_CTRL_RW 0x23 +#define RT_I2C_DEV_CTRL_CLK 0x24 struct rt_i2c_priv_data { diff --git a/components/drivers/include/drivers/mmcsd_core.h b/components/drivers/include/drivers/mmcsd_core.h index 11b1386b23..51263d35f2 100644 --- a/components/drivers/include/drivers/mmcsd_core.h +++ b/components/drivers/include/drivers/mmcsd_core.h @@ -234,7 +234,6 @@ struct rt_mmcsd_host *mmcsd_alloc_host(void); void mmcsd_free_host(struct rt_mmcsd_host *host); int rt_mmcsd_core_init(void); -int rt_mmcsd_blk_init(void); rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card); void rt_mmcsd_blk_remove(struct rt_mmcsd_card *card); diff --git a/components/drivers/include/drivers/pin.h b/components/drivers/include/drivers/pin.h index 5ba1e6c8ea..38e5abea2a 100644 --- a/components/drivers/include/drivers/pin.h +++ b/components/drivers/include/drivers/pin.h @@ -13,7 +13,6 @@ #define PIN_H__ #include <rtthread.h> -#include <rtdevice.h> #ifdef __cplusplus extern "C" { @@ -68,8 +67,6 @@ struct rt_pin_ops void (*pin_mode)(struct rt_device *device, rt_base_t pin, rt_base_t mode); void (*pin_write)(struct rt_device *device, rt_base_t pin, rt_base_t value); int (*pin_read)(struct rt_device *device, rt_base_t pin); - - /* TODO: add GPIO interrupt */ rt_err_t (*pin_attach_irq)(struct rt_device *device, rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args); rt_err_t (*pin_detach_irq)(struct rt_device *device, rt_int32_t pin); @@ -79,8 +76,6 @@ struct rt_pin_ops int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data); -/* Get pin number by name,such as PA.0,P0.12 */ -rt_base_t rt_pin_get(const char *name); void rt_pin_mode(rt_base_t pin, rt_base_t mode); void rt_pin_write(rt_base_t pin, rt_base_t value); int rt_pin_read(rt_base_t pin); @@ -88,6 +83,8 @@ rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args); rt_err_t rt_pin_detach_irq(rt_int32_t pin); rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled); +/* Get pin number by name,such as PA.0,P0.12 */ +rt_base_t rt_pin_get(const char *name); #ifdef __cplusplus } diff --git a/components/drivers/include/drivers/rtc.h b/components/drivers/include/drivers/rtc.h index 4845937113..0bafbad7ad 100644 --- a/components/drivers/include/drivers/rtc.h +++ b/components/drivers/include/drivers/rtc.h @@ -6,15 +6,45 @@ * Change Logs: * Date Author Notes * 2012-10-10 aozima first version. + * 2021-06-11 iysheng implement RTC framework V2.0 + * 2021-07-30 Meco Man move rtc_core.h to rtc.h */ #ifndef __RTC_H__ #define __RTC_H__ +#include <rtdef.h> + +#define RT_DEVICE_CTRL_RTC_GET_TIME 0x10 /**< get second time */ +#define RT_DEVICE_CTRL_RTC_SET_TIME 0x11 /**< set second time */ +#define RT_DEVICE_CTRL_RTC_GET_TIME_US 0x12 /**< get microsecond time */ +#define RT_DEVICE_CTRL_RTC_SET_TIME_US 0x13 /**< set microsecond time */ +#define RT_DEVICE_CTRL_RTC_GET_ALARM 0x14 /**< get alarm */ +#define RT_DEVICE_CTRL_RTC_SET_ALARM 0x15 /**< set alarm */ + +struct rt_rtc_ops +{ + rt_err_t (*init)(void); + rt_err_t (*get_secs)(void *arg); + rt_err_t (*set_secs)(void *arg); + rt_err_t (*get_alarm)(void *arg); + rt_err_t (*set_alarm)(void *arg); + rt_err_t (*get_usecs)(void *arg); + rt_err_t (*set_usecs)(void *arg); +}; + +typedef struct rt_rtc_device +{ + struct rt_device parent; + const struct rt_rtc_ops *ops; +} rt_rtc_dev_t; + +rt_err_t rt_hw_rtc_register(rt_rtc_dev_t *rtc, + const char *name, + rt_uint32_t flag, + void *data); + rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day); rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second); -int rt_soft_rtc_init(void); -int rt_rtc_ntp_sync_init(void); - #endif /* __RTC_H__ */ diff --git a/components/drivers/include/drivers/sensor.h b/components/drivers/include/drivers/sensor.h new file mode 100644 index 0000000000..ede8d11c99 --- /dev/null +++ b/components/drivers/include/drivers/sensor.h @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-01-31 flybreak first version + */ + +#ifndef __SENSOR_H__ +#define __SENSOR_H__ + +#include <rtthread.h> +#include "pin.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef RT_USING_RTC +#define rt_sensor_get_ts() time(RT_NULL) /* API for the sensor to get the timestamp */ +#else +#define rt_sensor_get_ts() rt_tick_get() /* API for the sensor to get the timestamp */ +#endif + +#define RT_PIN_NONE 0xFFFF /* RT PIN NONE */ +#define RT_DEVICE_FLAG_FIFO_RX 0x200 /* Flag to use when the sensor is open by fifo mode */ + +#define RT_SENSOR_MODULE_MAX (3) /* The maximum number of members of a sensor module */ + +/* Sensor types */ + +#define RT_SENSOR_CLASS_NONE (0) +#define RT_SENSOR_CLASS_ACCE (1) /* Accelerometer */ +#define RT_SENSOR_CLASS_GYRO (2) /* Gyroscope */ +#define RT_SENSOR_CLASS_MAG (3) /* Magnetometer */ +#define RT_SENSOR_CLASS_TEMP (4) /* Temperature */ +#define RT_SENSOR_CLASS_HUMI (5) /* Relative Humidity */ +#define RT_SENSOR_CLASS_BARO (6) /* Barometer */ +#define RT_SENSOR_CLASS_LIGHT (7) /* Ambient light */ +#define RT_SENSOR_CLASS_PROXIMITY (8) /* Proximity */ +#define RT_SENSOR_CLASS_HR (9) /* Heart Rate */ +#define RT_SENSOR_CLASS_TVOC (10) /* TVOC Level */ +#define RT_SENSOR_CLASS_NOISE (11) /* Noise Loudness */ +#define RT_SENSOR_CLASS_STEP (12) /* Step sensor */ +#define RT_SENSOR_CLASS_FORCE (13) /* Force sensor */ +#define RT_SENSOR_CLASS_DUST (14) /* Dust sensor */ +#define RT_SENSOR_CLASS_ECO2 (15) /* eCO2 sensor */ +#define RT_SENSOR_CLASS_GNSS (16) /* GPS/GNSS sensor */ +#define RT_SENSOR_CLASS_TOF (17) /* TOF sensor */ +#define RT_SENSOR_CLASS_SPO2 (18) /* SpO2 sensor */ + +/* Sensor vendor types */ + +#define RT_SENSOR_VENDOR_UNKNOWN (0) +#define RT_SENSOR_VENDOR_STM (1) /* STMicroelectronics */ +#define RT_SENSOR_VENDOR_BOSCH (2) /* Bosch */ +#define RT_SENSOR_VENDOR_INVENSENSE (3) /* Invensense */ +#define RT_SENSOR_VENDOR_SEMTECH (4) /* Semtech */ +#define RT_SENSOR_VENDOR_GOERTEK (5) /* Goertek */ +#define RT_SENSOR_VENDOR_MIRAMEMS (6) /* MiraMEMS */ +#define RT_SENSOR_VENDOR_DALLAS (7) /* Dallas */ +#define RT_SENSOR_VENDOR_ASAIR (8) /* Aosong */ +#define RT_SENSOR_VENDOR_SHARP (9) /* Sharp */ +#define RT_SENSOR_VENDOR_SENSIRION (10) /* Sensirion */ +#define RT_SENSOR_VENDOR_TI (11) /* Texas Instruments */ +#define RT_SENSOR_VENDOR_PLANTOWER (12) /* Plantower */ +#define RT_SENSOR_VENDOR_AMS (13) /* ams AG */ +#define RT_SENSOR_VENDOR_MAXIM (14) /* Maxim Integrated */ + + +/* Sensor unit types */ + +#define RT_SENSOR_UNIT_NONE (0) +#define RT_SENSOR_UNIT_MG (1) /* Accelerometer unit: mG */ +#define RT_SENSOR_UNIT_MDPS (2) /* Gyroscope unit: mdps */ +#define RT_SENSOR_UNIT_MGAUSS (3) /* Magnetometer unit: mGauss */ +#define RT_SENSOR_UNIT_LUX (4) /* Ambient light unit: lux */ +#define RT_SENSOR_UNIT_CM (5) /* Distance unit: cm */ +#define RT_SENSOR_UNIT_PA (6) /* Barometer unit: pa */ +#define RT_SENSOR_UNIT_PERMILLAGE (7) /* Relative Humidity unit: permillage */ +#define RT_SENSOR_UNIT_DCELSIUS (8) /* Temperature unit: dCelsius */ +#define RT_SENSOR_UNIT_HZ (9) /* Frequency unit: HZ */ +#define RT_SENSOR_UNIT_ONE (10) /* Dimensionless quantity unit: 1 */ +#define RT_SENSOR_UNIT_BPM (11) /* Heart rate unit: bpm */ +#define RT_SENSOR_UNIT_MM (12) /* Distance unit: mm */ +#define RT_SENSOR_UNIT_MN (13) /* Force unit: mN */ +#define RT_SENSOR_UNIT_PPM (14) /* Concentration unit: ppm */ +#define RT_SENSOR_UNIT_PPB (15) /* Concentration unit: ppb */ +#define RT_SENSOR_UNIT_DMS (16) /* Coordinates unit: DMS */ +#define RT_SENSOR_UNIT_DD (17) /* Coordinates unit: DD */ +/* Sensor communication interface types */ + +#define RT_SENSOR_INTF_I2C (1 << 0) +#define RT_SENSOR_INTF_SPI (1 << 1) +#define RT_SENSOR_INTF_UART (1 << 2) +#define RT_SENSOR_INTF_ONEWIRE (1 << 3) + +/* Sensor power mode types */ + +#define RT_SENSOR_POWER_NONE (0) +#define RT_SENSOR_POWER_DOWN (1) /* power down mode */ +#define RT_SENSOR_POWER_NORMAL (2) /* normal-power mode */ +#define RT_SENSOR_POWER_LOW (3) /* low-power mode */ +#define RT_SENSOR_POWER_HIGH (4) /* high-power mode */ + +/* Sensor work mode types */ + +#define RT_SENSOR_MODE_NONE (0) +#define RT_SENSOR_MODE_POLLING (1) /* One shot only read a data */ +#define RT_SENSOR_MODE_INT (2) /* TODO: One shot interrupt only read a data */ +#define RT_SENSOR_MODE_FIFO (3) /* TODO: One shot interrupt read all fifo data */ + +/* Sensor control cmd types */ + +#define RT_SENSOR_CTRL_GET_ID (0) /* Get device id */ +#define RT_SENSOR_CTRL_GET_INFO (1) /* Get sensor info */ +#define RT_SENSOR_CTRL_SET_RANGE (2) /* Set the measure range of sensor. unit is info of sensor */ +#define RT_SENSOR_CTRL_SET_ODR (3) /* Set output date rate. unit is HZ */ +#define RT_SENSOR_CTRL_SET_MODE (4) /* Set sensor's work mode. ex. RT_SENSOR_MODE_POLLING,RT_SENSOR_MODE_INT */ +#define RT_SENSOR_CTRL_SET_POWER (5) /* Set power mode. args type of sensor power mode. ex. RT_SENSOR_POWER_DOWN,RT_SENSOR_POWER_NORMAL */ +#define RT_SENSOR_CTRL_SELF_TEST (6) /* Take a self test */ + +#define RT_SENSOR_CTRL_USER_CMD_START 0x100 /* User commands should be greater than 0x100 */ + +struct rt_sensor_info +{ + rt_uint8_t type; /* The sensor type */ + rt_uint8_t vendor; /* Vendor of sensors */ + const char *model; /* model name of sensor */ + rt_uint8_t unit; /* unit of measurement */ + rt_uint8_t intf_type; /* Communication interface type */ + rt_int32_t range_max; /* maximum range of this sensor's value. unit is 'unit' */ + rt_int32_t range_min; /* minimum range of this sensor's value. unit is 'unit' */ + rt_uint32_t period_min; /* Minimum measurement period,unit:ms. zero = not a constant rate */ + rt_uint8_t fifo_max; +}; + +struct rt_sensor_intf +{ + char *dev_name; /* The name of the communication device */ + rt_uint8_t type; /* Communication interface type */ + void *user_data; /* Private data for the sensor. ex. i2c addr,spi cs,control I/O */ +}; + +struct rt_sensor_config +{ + struct rt_sensor_intf intf; /* sensor interface config */ + struct rt_device_pin_mode irq_pin; /* Interrupt pin, The purpose of this pin is to notification read data */ + rt_uint8_t mode; /* sensor work mode */ + rt_uint8_t power; /* sensor power mode */ + rt_uint16_t odr; /* sensor out data rate */ + rt_int32_t range; /* sensor range of measurement */ +}; + +typedef struct rt_sensor_device *rt_sensor_t; + +struct rt_sensor_device +{ + struct rt_device parent; /* The standard device */ + + struct rt_sensor_info info; /* The sensor info data */ + struct rt_sensor_config config; /* The sensor config data */ + + void *data_buf; /* The buf of the data received */ + rt_size_t data_len; /* The size of the data received */ + + const struct rt_sensor_ops *ops; /* The sensor ops */ + + struct rt_sensor_module *module; /* The sensor module */ + + rt_err_t (*irq_handle)(rt_sensor_t sensor); /* Called when an interrupt is generated, registered by the driver */ +}; + +struct rt_sensor_module +{ + rt_mutex_t lock; /* The module lock */ + + rt_sensor_t sen[RT_SENSOR_MODULE_MAX]; /* The module contains a list of sensors */ + rt_uint8_t sen_num; /* Number of sensors contained in the module */ +}; + +/* 3-axis Data Type */ +struct sensor_3_axis +{ + rt_int32_t x; + rt_int32_t y; + rt_int32_t z; +}; + +struct coordinates +{ + double longitude; + double latitude; +}; + +struct rt_sensor_data +{ + rt_uint32_t timestamp; /* The timestamp when the data was received */ + rt_uint8_t type; /* The sensor type of the data */ + union + { + struct sensor_3_axis acce; /* Accelerometer. unit: mG */ + struct sensor_3_axis gyro; /* Gyroscope. unit: mdps */ + struct sensor_3_axis mag; /* Magnetometer. unit: mGauss */ + struct coordinates coord; /* Coordinates unit: degrees */ + rt_int32_t temp; /* Temperature. unit: dCelsius */ + rt_int32_t humi; /* Relative humidity. unit: permillage */ + rt_int32_t baro; /* Pressure. unit: pascal (Pa) */ + rt_int32_t light; /* Light. unit: lux */ + rt_int32_t proximity; /* Distance. unit: centimeters */ + rt_int32_t hr; /* Heart rate. unit: bpm */ + rt_int32_t tvoc; /* TVOC. unit: permillage */ + rt_int32_t noise; /* Noise Loudness. unit: HZ */ + rt_uint32_t step; /* Step sensor. unit: 1 */ + rt_int32_t force; /* Force sensor. unit: mN */ + rt_uint32_t dust; /* Dust sensor. unit: ug/m3 */ + rt_uint32_t eco2; /* eCO2 sensor. unit: ppm */ + rt_uint32_t spo2; /* SpO2 sensor. unit: permillage */ + } data; +}; + +struct rt_sensor_ops +{ + rt_size_t (*fetch_data)(struct rt_sensor_device *sensor, void *buf, rt_size_t len); + rt_err_t (*control)(struct rt_sensor_device *sensor, int cmd, void *arg); +}; + +int rt_hw_sensor_register(rt_sensor_t sensor, + const char *name, + rt_uint32_t flag, + void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* __SENSOR_H__ */ diff --git a/components/drivers/include/drivers/serial_v2.h b/components/drivers/include/drivers/serial_v2.h new file mode 100644 index 0000000000..3ba46bdcdd --- /dev/null +++ b/components/drivers/include/drivers/serial_v2.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-06-01 KyleChan first version + */ + +#ifndef __SERIAL_V2_H__ +#define __SERIAL_V2_H__ + +#include <rtthread.h> + +#define BAUD_RATE_2400 2400 +#define BAUD_RATE_4800 4800 +#define BAUD_RATE_9600 9600 +#define BAUD_RATE_19200 19200 +#define BAUD_RATE_38400 38400 +#define BAUD_RATE_57600 57600 +#define BAUD_RATE_115200 115200 +#define BAUD_RATE_230400 230400 +#define BAUD_RATE_460800 460800 +#define BAUD_RATE_921600 921600 +#define BAUD_RATE_2000000 2000000 +#define BAUD_RATE_3000000 3000000 + +#define DATA_BITS_5 5 +#define DATA_BITS_6 6 +#define DATA_BITS_7 7 +#define DATA_BITS_8 8 +#define DATA_BITS_9 9 + +#define STOP_BITS_1 0 +#define STOP_BITS_2 1 +#define STOP_BITS_3 2 +#define STOP_BITS_4 3 + +#ifdef _WIN32 +#include <windows.h> +#else +#define PARITY_NONE 0 +#define PARITY_ODD 1 +#define PARITY_EVEN 2 +#endif + +#define BIT_ORDER_LSB 0 +#define BIT_ORDER_MSB 1 + +#define NRZ_NORMAL 0 /* Non Return to Zero : normal mode */ +#define NRZ_INVERTED 1 /* Non Return to Zero : inverted mode */ + +#define RT_DEVICE_FLAG_RX_BLOCKING 0x1000 +#define RT_DEVICE_FLAG_RX_NON_BLOCKING 0x2000 + +#define RT_DEVICE_FLAG_TX_BLOCKING 0x4000 +#define RT_DEVICE_FLAG_TX_NON_BLOCKING 0x8000 + +#define RT_SERIAL_RX_BLOCKING RT_DEVICE_FLAG_RX_BLOCKING +#define RT_SERIAL_RX_NON_BLOCKING RT_DEVICE_FLAG_RX_NON_BLOCKING +#define RT_SERIAL_TX_BLOCKING RT_DEVICE_FLAG_TX_BLOCKING +#define RT_SERIAL_TX_NON_BLOCKING RT_DEVICE_FLAG_TX_NON_BLOCKING + +#define RT_DEVICE_CHECK_OPTMODE 0x20 + +#define RT_SERIAL_EVENT_RX_IND 0x01 /* Rx indication */ +#define RT_SERIAL_EVENT_TX_DONE 0x02 /* Tx complete */ +#define RT_SERIAL_EVENT_RX_DMADONE 0x03 /* Rx DMA transfer done */ +#define RT_SERIAL_EVENT_TX_DMADONE 0x04 /* Tx DMA transfer done */ +#define RT_SERIAL_EVENT_RX_TIMEOUT 0x05 /* Rx timeout */ + +#define RT_SERIAL_ERR_OVERRUN 0x01 +#define RT_SERIAL_ERR_FRAMING 0x02 +#define RT_SERIAL_ERR_PARITY 0x03 + +#define RT_SERIAL_TX_DATAQUEUE_SIZE 2048 +#define RT_SERIAL_TX_DATAQUEUE_LWM 30 + +#define RT_SERIAL_RX_MINBUFSZ 64 +#define RT_SERIAL_TX_MINBUFSZ 64 + +#define RT_SERIAL_TX_BLOCKING_BUFFER 1 +#define RT_SERIAL_TX_BLOCKING_NO_BUFFER 0 + +/* Default config for serial_configure structure */ +#define RT_SERIAL_CONFIG_DEFAULT \ +{ \ + BAUD_RATE_115200, /* 115200 bits/s */ \ + DATA_BITS_8, /* 8 databits */ \ + STOP_BITS_1, /* 1 stopbit */ \ + PARITY_NONE, /* No parity */ \ + BIT_ORDER_LSB, /* LSB first sent */ \ + NRZ_NORMAL, /* Normal mode */ \ + RT_SERIAL_RX_MINBUFSZ, /* rxBuf size */ \ + RT_SERIAL_TX_MINBUFSZ, /* txBuf size */ \ + 0 \ +} + +struct serial_configure +{ + rt_uint32_t baud_rate; + + rt_uint32_t data_bits :4; + rt_uint32_t stop_bits :2; + rt_uint32_t parity :2; + rt_uint32_t bit_order :1; + rt_uint32_t invert :1; + rt_uint32_t rx_bufsz :16; + rt_uint32_t tx_bufsz :16; + rt_uint32_t reserved :6; +}; + +/* + * Serial Receive FIFO mode + */ +struct rt_serial_rx_fifo +{ + struct rt_ringbuffer rb; + + struct rt_completion rx_cpt; + + rt_uint16_t rx_cpt_index; + + /* software fifo */ + rt_uint8_t buffer[]; +}; + +/* + * Serial Transmit FIFO mode + */ +struct rt_serial_tx_fifo +{ + struct rt_ringbuffer rb; + + rt_size_t put_size; + + rt_bool_t activated; + + struct rt_completion tx_cpt; + + /* software fifo */ + rt_uint8_t buffer[]; +}; + +struct rt_serial_device +{ + struct rt_device parent; + + const struct rt_uart_ops *ops; + struct serial_configure config; + + void *serial_rx; + void *serial_tx; +}; + +/** + * uart operators + */ +struct rt_uart_ops +{ + rt_err_t (*configure)(struct rt_serial_device *serial, + struct serial_configure *cfg); + + rt_err_t (*control)(struct rt_serial_device *serial, + int cmd, + void *arg); + + int (*putc)(struct rt_serial_device *serial, char c); + int (*getc)(struct rt_serial_device *serial); + + rt_size_t (*transmit)(struct rt_serial_device *serial, + rt_uint8_t *buf, + rt_size_t size, + rt_uint32_t tx_flag); +}; + +void rt_hw_serial_isr(struct rt_serial_device *serial, int event); + +rt_err_t rt_hw_serial_register(struct rt_serial_device *serial, + const char *name, + rt_uint32_t flag, + void *data); + +#endif diff --git a/components/drivers/include/drivers/usb_common.h b/components/drivers/include/drivers/usb_common.h index 9c29a0d0df..920a85e61b 100644 --- a/components/drivers/include/drivers/usb_common.h +++ b/components/drivers/include/drivers/usb_common.h @@ -112,7 +112,7 @@ extern "C" { #define USB_STRING_CONFIG_INDEX 0x04 #define USB_STRING_INTERFACE_INDEX 0x05 #define USB_STRING_OS_INDEX 0x06 -#define USB_STRING_MAX USB_STRING_OS_INDEX +#define USB_STRING_MAX 0xff #define USB_STRING_OS "MSFT100A" @@ -301,7 +301,7 @@ struct uconfig_descriptor rt_uint8_t iConfiguration; rt_uint8_t bmAttributes; rt_uint8_t MaxPower; - rt_uint8_t data[256]; + rt_uint8_t data[2048]; }; typedef struct uconfig_descriptor* ucfg_desc_t; diff --git a/components/drivers/include/drivers/usb_device.h b/components/drivers/include/drivers/usb_device.h index 1e76477dbc..3ce051dfaa 100644 --- a/components/drivers/include/drivers/usb_device.h +++ b/components/drivers/include/drivers/usb_device.h @@ -34,6 +34,10 @@ extern "C" { #define _PRODUCT_ID 0x0001 #endif +#ifndef MAX_INTF_STR +#define MAX_INTF_STR 20 +#endif + #define USB_BCD_DEVICE 0x0200 /* USB Specification Release Number in Binary-Coded Decimal */ #define USB_BCD_VERSION 0x0200 /* USB 2.0 */ #define EP0_IN_ADDR 0x80 @@ -193,7 +197,7 @@ struct udevice struct usb_qualifier_descriptor * dev_qualifier; usb_os_comp_id_desc_t os_comp_id_desc; const char** str; - + const char *str_intf[MAX_INTF_STR]; udevice_state_t state; rt_list_t cfg_list; uconfig_t curr_cfg; @@ -260,6 +264,7 @@ rt_err_t rt_usbd_event_signal(struct udev_msg* msg); rt_err_t rt_usbd_device_set_controller(udevice_t device, udcd_t dcd); rt_err_t rt_usbd_device_set_descriptor(udevice_t device, udev_desc_t dev_desc); rt_err_t rt_usbd_device_set_string(udevice_t device, const char** ustring); +rt_err_t rt_usbd_device_set_interface_string(udevice_t device, int index, const char* string); rt_err_t rt_usbd_device_set_qualifier(udevice_t device, struct usb_qualifier_descriptor* qualifier); rt_err_t rt_usbd_device_set_os_comp_id_desc(udevice_t device, usb_os_comp_id_desc_t os_comp_id_desc); rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg); diff --git a/components/drivers/include/ipc/workqueue.h b/components/drivers/include/ipc/workqueue.h index ccbc42b226..03904d852e 100644 --- a/components/drivers/include/ipc/workqueue.h +++ b/components/drivers/include/ipc/workqueue.h @@ -5,6 +5,7 @@ * * Change Logs: * Date Author Notes + * 2021-08-01 Meco Man remove rt_delayed_work_init() and rt_delayed_work structure */ #ifndef WORKQUEUE_H__ #define WORKQUEUE_H__ @@ -48,11 +49,6 @@ struct rt_work struct rt_workqueue *workqueue; }; -struct rt_delayed_work -{ - struct rt_work work; -}; - #ifdef RT_USING_HEAP /** * WorkQueue for DeviceDriver @@ -64,11 +60,12 @@ rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *wo rt_err_t rt_workqueue_cancel_work(struct rt_workqueue *queue, struct rt_work *work); rt_err_t rt_workqueue_cancel_work_sync(struct rt_workqueue *queue, struct rt_work *work); rt_err_t rt_workqueue_cancel_all_work(struct rt_workqueue *queue); +rt_err_t rt_workqueue_critical_work(struct rt_workqueue *queue, struct rt_work *work); #ifdef RT_USING_SYSTEM_WORKQUEUE rt_err_t rt_work_submit(struct rt_work *work, rt_tick_t time); rt_err_t rt_work_cancel(struct rt_work *work); -#endif +#endif /* RT_USING_SYSTEM_WORKQUEUE */ rt_inline void rt_work_init(struct rt_work *work, void (*work_func)(struct rt_work *work, void *work_data), void *work_data) @@ -81,10 +78,6 @@ rt_inline void rt_work_init(struct rt_work *work, void (*work_func)(struct rt_wo work->type = 0; } -void rt_delayed_work_init(struct rt_delayed_work *work, void (*work_func)(struct rt_work *work, - void *work_data), void *work_data); - -int rt_work_sys_workqueue_init(void); -#endif +#endif /* RT_USING_HEAP */ #endif diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index 82868e5aef..07a2be361e 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -57,7 +57,11 @@ extern "C" { #endif /* RT_USING_USB_HOST */ #ifdef RT_USING_SERIAL +#ifdef RT_USING_SERIAL_V2 +#include "drivers/serial_v2.h" +#else #include "drivers/serial.h" +#endif #endif /* RT_USING_SERIAL */ #ifdef RT_USING_I2C @@ -78,70 +82,76 @@ extern "C" { #include "drivers/mmcsd_core.h" #include "drivers/sd.h" #include "drivers/sdio.h" -#endif +#endif /* RT_USING_SDIO */ + #ifdef RT_USING_WDT #include "drivers/watchdog.h" -#endif +#endif /* RT_USING_WDT */ #ifdef RT_USING_PIN #include "drivers/pin.h" -#endif +#endif /* RT_USING_PIN */ + +#ifdef RT_USING_SENSOR +#include "drivers/sensor.h" +#endif /* RT_USING_SENSOR */ #ifdef RT_USING_CAN #include "drivers/can.h" -#endif +#endif /* RT_USING_CAN */ #ifdef RT_USING_HWTIMER #include "drivers/hwtimer.h" -#endif +#endif /* RT_USING_HWTIMER */ #ifdef RT_USING_AUDIO #include "drivers/audio.h" -#endif +#endif /* RT_USING_AUDIO */ #ifdef RT_USING_CPUTIME #include "drivers/cputime.h" -#endif +#endif /* RT_USING_CPUTIME */ #ifdef RT_USING_ADC #include "drivers/adc.h" -#endif +#endif /* RT_USING_ADC */ #ifdef RT_USING_DAC #include "drivers/dac.h" -#endif +#endif /* RT_USING_DAC */ #ifdef RT_USING_PWM #include "drivers/rt_drv_pwm.h" -#endif +#endif /* RT_USING_PWM */ #ifdef RT_USING_PM #include "drivers/pm.h" -#endif +#endif /* RT_USING_PM */ #ifdef RT_USING_WIFI #include "drivers/wlan.h" -#endif +#endif /* RT_USING_WIFI */ #ifdef MTD_USING_NOR #include "drivers/mtdnor.h" -#endif +#endif /* MTD_USING_NOR */ + #ifdef MTD_USING_NAND #include "drivers/mtdnand.h" -#endif +#endif /* MTD_USING_NAND */ #ifdef RT_USING_HWCRYPTO #include "drivers/crypto.h" -#endif +#endif /* RT_USING_HWCRYPTO */ #ifdef RT_USING_PULSE_ENCODER #include "drivers/pulse_encoder.h" -#endif +#endif /* RT_USING_PULSE_ENCODER */ #ifdef RT_USING_INPUT_CAPTURE #include "drivers/rt_inputcapture.h" -#endif +#endif /* RT_USING_INPUT_CAPTURE */ #ifdef __cplusplus } diff --git a/components/drivers/misc/pin.c b/components/drivers/misc/pin.c index 91bf7058dc..666d221fa6 100644 --- a/components/drivers/misc/pin.c +++ b/components/drivers/misc/pin.c @@ -47,7 +47,7 @@ static rt_size_t _pin_write(rt_device_t dev, rt_off_t pos, const void *buffer, r return size; } -static rt_err_t _pin_control(rt_device_t dev, int cmd, void *args) +static rt_err_t _pin_control(rt_device_t dev, int cmd, void *args) { struct rt_device_pin_mode *mode; struct rt_device_pin *pin = (struct rt_device_pin *)dev; @@ -111,6 +111,7 @@ rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode, } return -RT_ENOSYS; } + rt_err_t rt_pin_detach_irq(rt_int32_t pin) { RT_ASSERT(_hw_pin.ops != RT_NULL); @@ -146,7 +147,7 @@ void rt_pin_write(rt_base_t pin, rt_base_t value) } FINSH_FUNCTION_EXPORT_ALIAS(rt_pin_write, pinWrite, write value to hardware pin); -int rt_pin_read(rt_base_t pin) +int rt_pin_read(rt_base_t pin) { RT_ASSERT(_hw_pin.ops != RT_NULL); return _hw_pin.ops->pin_read(&_hw_pin.parent, pin); @@ -166,4 +167,3 @@ rt_base_t rt_pin_get(const char *name) return _hw_pin.ops->pin_get(name); } FINSH_FUNCTION_EXPORT_ALIAS(rt_pin_get, pinGet, get pin number from hardware pin); - diff --git a/components/drivers/pm/pm.c b/components/drivers/pm/pm.c index 80ed101498..cf488a9ce1 100644 --- a/components/drivers/pm/pm.c +++ b/components/drivers/pm/pm.c @@ -836,12 +836,10 @@ rt_uint32_t rt_pm_module_get_status(void) rt_uint32_t req_status = 0x00; pm = &_pm; - for (index = 0; index < 32; index ++) + for (index = 0; index < PM_MODULE_MAX_ID; index ++) { if (pm->module_status[index].req_status == 0x01) req_status |= 1<<index; - if (index >= PM_MODULE_MAX_ID) - break; } return req_status; diff --git a/components/drivers/rtc/README.md b/components/drivers/rtc/README.md index 23010cf4b7..dff71f9d67 100644 --- a/components/drivers/rtc/README.md +++ b/components/drivers/rtc/README.md @@ -55,26 +55,11 @@ msh />date 2018 02 16 01 15 30 # 设置当前时间为 2018-02-16 01:15:30 msh /> ``` -### 2.4 启用 NTP 时间自动同步 - -如果 RT-Thread 已接入互联网,可启用 NTP 时间自动同步功能,定期同步本地时间。 - -在 menuconfig 中启用 `RTC_SYNC_USING_NTP` 配置。启用该功能后,会自动开启 [netutils package](https://github.com/RT-Thread-packages/netutils) 的 NTP 功能。同时务必确保 RT-Thread 网络访问正常。 - -启用该配置后,还有两个配置是用户可选配置: - -- `RTC_NTP_FIRST_SYNC_DELAY`: 首次执行 NTP 时间同步的延时。延时的目的在于,给网络连接预留一定的时间,尽量提高第一次执行 NTP 时间同步时的成功率。默认时间为 30S; -- `RTC_NTP_SYNC_PERIOD`: NTP 自动同步周期,单位为秒,默认一小时(即 3600S)同步一次。 - -> 注意:如果没有使用组件自动初始化功能,则需手动调用 `int rt_rtc_ntp_sync_init(void)` ,完成该功能初始化。 - -### 2.5 启用 Soft RTC (软件模拟 RTC) +### 2.4 启用 Soft RTC (软件模拟 RTC) 这个模式非常适用于对时间精度要求不高,没有硬件 RTC 的产品。 -#### 2.5.1 使用方法 +#### 2.4.1 使用方法 在 menuconfig 中启用 `RT_USING_SOFT_RTC` 配置。 -> 注意:如果没有使用组件自动初始化功能,则需手动调用 `int rt_soft_rtc_init(void)` ,完成该功能初始化。 - diff --git a/components/drivers/rtc/SConscript b/components/drivers/rtc/SConscript index e1f8f433c1..6ec8bcb3c5 100644 --- a/components/drivers/rtc/SConscript +++ b/components/drivers/rtc/SConscript @@ -3,21 +3,15 @@ from building import * cwd = GetCurrentDir() src = [] -rtc = ['rtc.c'] - -rtc_alarm = ['alarm.c'] - -soft_rtc = ['soft_rtc.c'] - CPPPATH = [cwd + '/../include'] group = [] if GetDepend(['RT_USING_RTC']): - src = src + rtc + src = src + ['rtc.c'] if GetDepend(['RT_USING_ALARM']): - src = src + rtc_alarm + src = src + ['alarm.c'] if GetDepend(['RT_USING_SOFT_RTC']): - src = src + soft_rtc + src = src + ['soft_rtc.c'] group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_RTC'], CPPPATH = CPPPATH) diff --git a/components/drivers/rtc/rtc.c b/components/drivers/rtc/rtc.c index 98b60f9f95..5eabeed2dd 100644 --- a/components/drivers/rtc/rtc.c +++ b/components/drivers/rtc/rtc.c @@ -9,25 +9,130 @@ * 2012-04-12 aozima optimization: find rtc device only first. * 2012-04-16 aozima add scheduler lock for set_date and set_time. * 2018-02-16 armink add auto sync time by NTP + * 2021-05-09 Meco Man remove NTP + * 2021-06-11 iysheng implement RTC framework V2.0 + * 2021-07-30 Meco Man move rtc_core.c to rtc.c */ -#include <sys/time.h> +#include <time.h> #include <string.h> +#include <stdlib.h> #include <rtthread.h> +#include <drivers/rtc.h> #ifdef RT_USING_RTC -/* Using NTP auto sync RTC time */ -#ifdef RTC_SYNC_USING_NTP -/* NTP first sync delay time for network connect, unit: second */ -#ifndef RTC_NTP_FIRST_SYNC_DELAY -#define RTC_NTP_FIRST_SYNC_DELAY (30) -#endif -/* NTP sync period, unit: second */ -#ifndef RTC_NTP_SYNC_PERIOD -#define RTC_NTP_SYNC_PERIOD (1L*60L*60L) -#endif -#endif /* RTC_SYNC_USING_NTP */ +/* + * This function initializes rtc_core + */ +static rt_err_t rt_rtc_init(struct rt_device *dev) +{ + rt_rtc_dev_t *rtc_core; + + RT_ASSERT(dev != RT_NULL); + rtc_core = (rt_rtc_dev_t *)dev; + if (rtc_core->ops->init) + { + return (rtc_core->ops->init()); + } + + return -RT_ENOSYS; +} + +static rt_err_t rt_rtc_open(struct rt_device *dev, rt_uint16_t oflag) +{ + return RT_EOK; +} + +static rt_err_t rt_rtc_close(struct rt_device *dev) +{ + /* Add close member function in rt_rtc_ops when need, + * then call that function here. + * */ + return RT_EOK; +} + +static rt_err_t rt_rtc_control(struct rt_device *dev, int cmd, void *args) +{ +#define TRY_DO_RTC_FUNC(rt_rtc_dev, func_name, args) \ + rt_rtc_dev->ops->func_name ? rt_rtc_dev->ops->func_name(args) : -RT_EINVAL; + + rt_rtc_dev_t *rtc_device; + rt_err_t ret = -RT_EINVAL; + + RT_ASSERT(dev != RT_NULL); + rtc_device = (rt_rtc_dev_t *)dev; + + switch (cmd) + { + case RT_DEVICE_CTRL_RTC_GET_TIME: + ret = TRY_DO_RTC_FUNC(rtc_device, get_secs, args); + break; + case RT_DEVICE_CTRL_RTC_SET_TIME: + ret = TRY_DO_RTC_FUNC(rtc_device, set_secs, args); + break; + case RT_DEVICE_CTRL_RTC_GET_TIME_US: + ret = TRY_DO_RTC_FUNC(rtc_device, get_usecs, args); + break; + case RT_DEVICE_CTRL_RTC_SET_TIME_US: + ret = TRY_DO_RTC_FUNC(rtc_device, set_usecs, args); + break; + case RT_DEVICE_CTRL_RTC_GET_ALARM: + ret = TRY_DO_RTC_FUNC(rtc_device, get_alarm, args); + break; + case RT_DEVICE_CTRL_RTC_SET_ALARM: + ret = TRY_DO_RTC_FUNC(rtc_device, set_alarm, args); + break; + default: + break; + } + + return ret; + +#undef TRY_DO_RTC_FUNC +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops rtc_core_ops = +{ + rt_rtc_init, + rt_rtc_open, + rt_rtc_close, + RT_NULL, + RT_NULL, + rt_rtc_control, +}; +#endif /* RT_USING_DEVICE_OPS */ + +rt_err_t rt_hw_rtc_register(rt_rtc_dev_t *rtc, + const char *name, + rt_uint32_t flag, + void *data) +{ + struct rt_device *device; + RT_ASSERT(rtc != RT_NULL); + + device = &(rtc->parent); + + device->type = RT_Device_Class_RTC; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &rtc_core_ops; +#else + device->init = rt_rtc_init; + device->open = rt_rtc_open; + device->close = rt_rtc_close; + device->read = RT_NULL; + device->write = RT_NULL; + device->control = rt_rtc_control; +#endif /* RT_USING_DEVICE_OPS */ + device->user_data = data; + + /* register a character device */ + return rt_device_register(device, name, flag); +} /** * Set system date(time not modify, local timezone). @@ -37,12 +142,10 @@ * @param rt_uint32_t day e.g: 31. * * @return rt_err_t if set success, return RT_EOK. - * */ rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day) { time_t now; - struct tm *p_tm; struct tm tm_new; rt_device_t device; rt_err_t ret = -RT_ERROR; @@ -50,14 +153,8 @@ rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day) /* get current time */ now = time(RT_NULL); - /* lock scheduler. */ - rt_enter_critical(); /* converts calendar time into local time. */ - p_tm = localtime(&now); - /* copy the statically located variable */ - rt_memcpy(&tm_new, p_tm, sizeof(struct tm)); - /* unlock scheduler. */ - rt_exit_critical(); + localtime_r(&now, &tm_new); /* update date. */ tm_new.tm_year = year - 1900; @@ -87,12 +184,10 @@ rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day) * @param rt_uint32_t second e.g: 0~59. * * @return rt_err_t if set success, return RT_EOK. - * */ rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second) { time_t now; - struct tm *p_tm; struct tm tm_new; rt_device_t device; rt_err_t ret = -RT_ERROR; @@ -100,14 +195,8 @@ rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second) /* get current time */ now = time(RT_NULL); - /* lock scheduler. */ - rt_enter_critical(); /* converts calendar time into local time. */ - p_tm = localtime(&now); - /* copy the statically located variable */ - rt_memcpy(&tm_new, p_tm, sizeof(struct tm)); - /* unlock scheduler. */ - rt_exit_critical(); + localtime_r(&now, &tm_new); /* update time. */ tm_new.tm_hour = hour; @@ -129,67 +218,8 @@ rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second) return ret; } -#ifdef RTC_SYNC_USING_NTP -static void ntp_sync_thread_enrty(void *param) -{ - extern time_t ntp_sync_to_rtc(const char *host_name); - /* first sync delay for network connect */ - rt_thread_delay(RTC_NTP_FIRST_SYNC_DELAY * RT_TICK_PER_SECOND); - - while (1) - { - ntp_sync_to_rtc(NULL); - rt_thread_delay(RTC_NTP_SYNC_PERIOD * RT_TICK_PER_SECOND); - } -} - -int rt_rtc_ntp_sync_init(void) -{ - static rt_bool_t init_ok = RT_FALSE; - rt_thread_t thread; - - if (init_ok) - { - return 0; - } - - thread = rt_thread_create("ntp_sync", ntp_sync_thread_enrty, RT_NULL, 1536, 26, 2); - if (thread) - { - rt_thread_startup(thread); - } - else - { - return -RT_ENOMEM; - } - - init_ok = RT_TRUE; - - return RT_EOK; -} -INIT_COMPONENT_EXPORT(rt_rtc_ntp_sync_init); -#endif /* RTC_SYNC_USING_NTP */ - -#ifdef RT_USING_FINSH +#ifdef FINSH_USING_MSH #include <finsh.h> -#include <rtdevice.h> - -/** - * show date and time (local timezone) - */ -void list_date(void) -{ - time_t now; - - now = time(RT_NULL); - rt_kprintf("%.*s\n", 25, ctime(&now)); -} -FINSH_FUNCTION_EXPORT(list_date, show date and time (local timezone)) -FINSH_FUNCTION_EXPORT(set_date, set date(local timezone) e.g: set_date(2010,2,28)) -FINSH_FUNCTION_EXPORT(set_time, set time(local timezone) e.g: set_time(23,59,59)) - - -#if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) /** * get date and time or set (local timezone) [year month day hour min sec] */ @@ -252,9 +282,7 @@ static void date(uint8_t argc, char **argv) rt_kprintf("e.g: date 2018 01 01 23 59 59 or date\n"); } } -MSH_CMD_EXPORT(list_date, show date and time (local timezone)) MSH_CMD_EXPORT(date, get date and time or set (local timezone) [year month day hour min sec]) +#endif /* FINSH_USING_MSH */ -#endif /* defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) */ -#endif /* RT_USING_FINSH */ #endif /* RT_USING_RTC */ diff --git a/components/drivers/rtc/soft_rtc.c b/components/drivers/rtc/soft_rtc.c index 9e1b7c35fd..255579f35e 100644 --- a/components/drivers/rtc/soft_rtc.c +++ b/components/drivers/rtc/soft_rtc.c @@ -104,7 +104,7 @@ const static struct rt_device_ops soft_rtc_ops = }; #endif -int rt_soft_rtc_init(void) +static int rt_soft_rtc_init(void) { static rt_bool_t init_ok = RT_FALSE; struct tm time_new = SOFT_RTC_TIME_DEFAULT; diff --git a/components/drivers/sdio/block_dev.c b/components/drivers/sdio/block_dev.c index f2ce09a83f..2acbc44fa3 100644 --- a/components/drivers/sdio/block_dev.c +++ b/components/drivers/sdio/block_dev.c @@ -515,15 +515,3 @@ void rt_mmcsd_blk_remove(struct rt_mmcsd_card *card) } } } - -/* - * This function will initialize block device on the mmc/sd. - * - * @deprecated since 2.1.0, this function does not need to be invoked - * in the system initialization. - */ -int rt_mmcsd_blk_init(void) -{ - /* nothing */ - return 0; -} diff --git a/components/drivers/sdio/mmc.c b/components/drivers/sdio/mmc.c index 5aba3dba7a..bebfa39ea2 100644 --- a/components/drivers/sdio/mmc.c +++ b/components/drivers/sdio/mmc.c @@ -122,7 +122,7 @@ static int mmc_get_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t **new_ext_csd) *new_ext_csd = RT_NULL; - if (GET_BITS(card->resp_cid, 122, 4) < 4) + if (GET_BITS(card->resp_csd, 122, 4) < 4) return 0; /* @@ -300,10 +300,10 @@ static int mmc_select_bus_width(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd) MMCSD_BUS_WIDTH_1 }; struct rt_mmcsd_host *host = card->host; - unsigned idx, bus_width = 0; + unsigned idx, trys, bus_width = 0; int err = 0; - if (GET_BITS(card->resp_cid, 122, 4) < 4) + if (GET_BITS(card->resp_csd, 122, 4) < 4) return 0; /* @@ -335,10 +335,13 @@ static int mmc_select_bus_width(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd) if (err) continue; - bus_width = bus_widths[idx]; - mmcsd_set_bus_width(host, bus_width); - mmcsd_delay_ms(20); //delay 10ms - err = mmc_compare_ext_csds(card, ext_csd, bus_width); + for(trys = 0; trys < 5; trys++){ + mmcsd_set_bus_width(host, bus_width); + mmcsd_delay_ms(10); + err = mmc_compare_ext_csds(card, ext_csd, bus_width); + if(!err) + break; + } if (!err) { err = bus_width; break; diff --git a/components/drivers/sensors/sensor.c b/components/drivers/sensors/sensor.c index ccc1fca34e..8d43a7a905 100644 --- a/components/drivers/sensors/sensor.c +++ b/components/drivers/sensors/sensor.c @@ -36,7 +36,8 @@ static char *const sensor_name_str[] = "dust_", /* Dust sensor */ "eco2_", /* eCO2 sensor */ "gnss_", /* GPS/GNSS sensor */ - "tof_" /* TOF sensor */ + "tof_", /* TOF sensor */ + "spo2_" /* SpO2 sensor */ }; /* Sensor interrupt correlation function */ @@ -121,12 +122,30 @@ static rt_err_t rt_sensor_irq_init(rt_sensor_t sensor) return 0; } +// local rt_sensor_ops + +static rt_size_t local_fetch_data(struct rt_sensor_device *sensor, void *buf, rt_size_t len) +{ + LOG_D("Undefined fetch_data"); + return 0; +} +static rt_err_t local_control(struct rt_sensor_device *sensor, int cmd, void *arg) +{ + LOG_D("Undefined control"); + return RT_ERROR; +} +static struct rt_sensor_ops local_ops = { + .fetch_data = local_fetch_data, + .control = local_control +}; + /* RT-Thread Device Interface */ static rt_err_t rt_sensor_open(rt_device_t dev, rt_uint16_t oflag) { rt_sensor_t sensor = (rt_sensor_t)dev; RT_ASSERT(dev != RT_NULL); rt_err_t res = RT_EOK; + rt_err_t (*local_ctrl)(struct rt_sensor_device *sensor, int cmd, void *arg) = local_control; if (sensor->module) { @@ -144,37 +163,36 @@ static rt_err_t rt_sensor_open(rt_device_t dev, rt_uint16_t oflag) goto __exit; } } + if (sensor->ops->control != RT_NULL) + { + local_ctrl = sensor->ops->control; + } + sensor->config.mode = RT_SENSOR_MODE_POLLING; if (oflag & RT_DEVICE_FLAG_RDONLY && dev->flag & RT_DEVICE_FLAG_RDONLY) { - if (sensor->ops->control != RT_NULL) - { - /* If polling mode is supported, configure it to polling mode */ - sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_POLLING); - } - sensor->config.mode = RT_SENSOR_MODE_POLLING; + /* If polling mode is supported, configure it to polling mode */ + local_ctrl(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_POLLING); } else if (oflag & RT_DEVICE_FLAG_INT_RX && dev->flag & RT_DEVICE_FLAG_INT_RX) { - if (sensor->ops->control != RT_NULL) + /* If interrupt mode is supported, configure it to interrupt mode */ + if (local_ctrl(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_INT) == RT_EOK) { - /* If interrupt mode is supported, configure it to interrupt mode */ - sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_INT); + /* Initialization sensor interrupt */ + rt_sensor_irq_init(sensor); + sensor->config.mode = RT_SENSOR_MODE_INT; } - /* Initialization sensor interrupt */ - rt_sensor_irq_init(sensor); - sensor->config.mode = RT_SENSOR_MODE_INT; } else if (oflag & RT_DEVICE_FLAG_FIFO_RX && dev->flag & RT_DEVICE_FLAG_FIFO_RX) { - if (sensor->ops->control != RT_NULL) + /* If fifo mode is supported, configure it to fifo mode */ + if (local_ctrl(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_FIFO) == RT_EOK) { - /* If fifo mode is supported, configure it to fifo mode */ - sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_FIFO); + /* Initialization sensor interrupt */ + rt_sensor_irq_init(sensor); + sensor->config.mode = RT_SENSOR_MODE_FIFO; } - /* Initialization sensor interrupt */ - rt_sensor_irq_init(sensor); - sensor->config.mode = RT_SENSOR_MODE_FIFO; } else { @@ -183,7 +201,7 @@ static rt_err_t rt_sensor_open(rt_device_t dev, rt_uint16_t oflag) } /* Configure power mode to normal mode */ - if (sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_POWER, (void *)RT_SENSOR_POWER_NORMAL) == RT_EOK) + if (local_ctrl(sensor, RT_SENSOR_CTRL_SET_POWER, (void *)RT_SENSOR_POWER_NORMAL) == RT_EOK) { sensor->config.power = RT_SENSOR_POWER_NORMAL; } @@ -202,6 +220,7 @@ static rt_err_t rt_sensor_close(rt_device_t dev) { rt_sensor_t sensor = (rt_sensor_t)dev; int i; + rt_err_t (*local_ctrl)(struct rt_sensor_device * sensor, int cmd, void *arg) = local_control; RT_ASSERT(dev != RT_NULL); @@ -209,9 +228,13 @@ static rt_err_t rt_sensor_close(rt_device_t dev) { rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER); } + if (sensor->ops->control != RT_NULL) + { + local_ctrl = sensor->ops->control; + } /* Configure power mode to power down mode */ - if (sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_POWER, (void *)RT_SENSOR_POWER_DOWN) == RT_EOK) + if (local_ctrl(sensor, RT_SENSOR_CTRL_SET_POWER, (void *)RT_SENSOR_POWER_DOWN) == RT_EOK) { sensor->config.power = RT_SENSOR_POWER_DOWN; } @@ -234,10 +257,13 @@ static rt_err_t rt_sensor_close(rt_device_t dev) } } } - /* Sensor disable interrupt */ - if (sensor->config.irq_pin.pin != RT_PIN_NONE) + if (sensor->config.mode != RT_SENSOR_MODE_POLLING) { - rt_pin_irq_enable(sensor->config.irq_pin.pin, RT_FALSE); + /* Sensor disable interrupt */ + if (sensor->config.irq_pin.pin != RT_PIN_NONE) + { + rt_pin_irq_enable(sensor->config.irq_pin.pin, RT_FALSE); + } } __exit: @@ -282,7 +308,10 @@ static rt_size_t rt_sensor_read(rt_device_t dev, rt_off_t pos, void *buf, rt_siz else { /* If the buffer is empty read the data */ - result = sensor->ops->fetch_data(sensor, buf, len); + if (sensor->ops->fetch_data != RT_NULL) + { + result = sensor->ops->fetch_data(sensor, buf, len); + } } if (sensor->module) @@ -298,18 +327,23 @@ static rt_err_t rt_sensor_control(rt_device_t dev, int cmd, void *args) rt_sensor_t sensor = (rt_sensor_t)dev; rt_err_t result = RT_EOK; RT_ASSERT(dev != RT_NULL); + rt_err_t (*local_ctrl)(struct rt_sensor_device * sensor, int cmd, void *arg) = local_control; if (sensor->module) { rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER); } + if (sensor->ops->control != RT_NULL) + { + local_ctrl = sensor->ops->control; + } switch (cmd) { case RT_SENSOR_CTRL_GET_ID: if (args) { - result = sensor->ops->control(sensor, RT_SENSOR_CTRL_GET_ID, args); + result = local_ctrl(sensor, RT_SENSOR_CTRL_GET_ID, args); } break; case RT_SENSOR_CTRL_GET_INFO: @@ -319,19 +353,17 @@ static rt_err_t rt_sensor_control(rt_device_t dev, int cmd, void *args) } break; case RT_SENSOR_CTRL_SET_RANGE: - /* Configuration measurement range */ - result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_RANGE, args); + result = local_ctrl(sensor, RT_SENSOR_CTRL_SET_RANGE, args); if (result == RT_EOK) { sensor->config.range = (rt_int32_t)args; LOG_D("set range %d", sensor->config.range); - } + } break; case RT_SENSOR_CTRL_SET_ODR: - /* Configuration data output rate */ - result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_ODR, args); + result = local_ctrl(sensor, RT_SENSOR_CTRL_SET_ODR, args); if (result == RT_EOK) { sensor->config.odr = (rt_uint32_t)args & 0xFFFF; @@ -339,9 +371,8 @@ static rt_err_t rt_sensor_control(rt_device_t dev, int cmd, void *args) } break; case RT_SENSOR_CTRL_SET_POWER: - /* Configuration sensor power mode */ - result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_POWER, args); + result = local_ctrl(sensor, RT_SENSOR_CTRL_SET_POWER, args); if (result == RT_EOK) { sensor->config.power = (rt_uint32_t)args & 0xFF; @@ -349,16 +380,15 @@ static rt_err_t rt_sensor_control(rt_device_t dev, int cmd, void *args) } break; case RT_SENSOR_CTRL_SELF_TEST: - /* Device self-test */ - result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SELF_TEST, args); + result = local_ctrl(sensor, RT_SENSOR_CTRL_SELF_TEST, args); break; default: if (cmd > RT_SENSOR_CTRL_USER_CMD_START) { /* Custom commands */ - result = sensor->ops->control(sensor, cmd, args); + result = local_ctrl(sensor, cmd, args); } else { @@ -387,6 +417,7 @@ const static struct rt_device_ops rt_sensor_ops = }; #endif + /* * sensor register */ @@ -401,6 +432,11 @@ int rt_hw_sensor_register(rt_sensor_t sensor, char *sensor_name = RT_NULL, *device_name = RT_NULL; + if (sensor->ops == RT_NULL) + { + sensor->ops = &local_ops; + } + /* Add a type name for the sensor device */ sensor_name = sensor_name_str[sensor->info.type]; device_name = (char *)rt_calloc(1, rt_strlen(sensor_name) + 1 + rt_strlen(name)); @@ -444,12 +480,12 @@ int rt_hw_sensor_register(rt_sensor_t sensor, result = rt_device_register(device, device_name, flag | RT_DEVICE_FLAG_STANDALONE); if (result != RT_EOK) { + LOG_E("rt_sensor[%s] register err code: %d", device_name, result); rt_free(device_name); - LOG_E("rt_sensor register err code: %d", result); return result; } rt_free(device_name); - LOG_I("rt_sensor init success"); + LOG_I("rt_sensor[%s] init success", device_name); return RT_EOK; } diff --git a/components/drivers/sensors/sensor.h b/components/drivers/sensors/sensor.h index f54d4e8799..761ee49b4c 100755 --- a/components/drivers/sensors/sensor.h +++ b/components/drivers/sensors/sensor.h @@ -8,231 +8,7 @@ * 2019-01-31 flybreak first version */ -#ifndef __SENSOR_H__ -#define __SENSOR_H__ #include <rtthread.h> #include <rtdevice.h> -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef RT_USING_RTC -#define rt_sensor_get_ts() time(RT_NULL) /* API for the sensor to get the timestamp */ -#else -#define rt_sensor_get_ts() rt_tick_get() /* API for the sensor to get the timestamp */ -#endif - -#define RT_PIN_NONE 0xFFFF /* RT PIN NONE */ -#define RT_DEVICE_FLAG_FIFO_RX 0x200 /* Flag to use when the sensor is open by fifo mode */ - -#define RT_SENSOR_MODULE_MAX (3) /* The maximum number of members of a sensor module */ - -/* Sensor types */ - -#define RT_SENSOR_CLASS_NONE (0) -#define RT_SENSOR_CLASS_ACCE (1) /* Accelerometer */ -#define RT_SENSOR_CLASS_GYRO (2) /* Gyroscope */ -#define RT_SENSOR_CLASS_MAG (3) /* Magnetometer */ -#define RT_SENSOR_CLASS_TEMP (4) /* Temperature */ -#define RT_SENSOR_CLASS_HUMI (5) /* Relative Humidity */ -#define RT_SENSOR_CLASS_BARO (6) /* Barometer */ -#define RT_SENSOR_CLASS_LIGHT (7) /* Ambient light */ -#define RT_SENSOR_CLASS_PROXIMITY (8) /* Proximity */ -#define RT_SENSOR_CLASS_HR (9) /* Heart Rate */ -#define RT_SENSOR_CLASS_TVOC (10) /* TVOC Level */ -#define RT_SENSOR_CLASS_NOISE (11) /* Noise Loudness */ -#define RT_SENSOR_CLASS_STEP (12) /* Step sensor */ -#define RT_SENSOR_CLASS_FORCE (13) /* Force sensor */ -#define RT_SENSOR_CLASS_DUST (14) /* Dust sensor */ -#define RT_SENSOR_CLASS_ECO2 (15) /* eCO2 sensor */ -#define RT_SENSOR_CLASS_GNSS (16) /* GPS/GNSS sensor */ -#define RT_SENSOR_CLASS_TOF (17) /* TOF sensor */ - -/* Sensor vendor types */ - -#define RT_SENSOR_VENDOR_UNKNOWN (0) -#define RT_SENSOR_VENDOR_STM (1) /* STMicroelectronics */ -#define RT_SENSOR_VENDOR_BOSCH (2) /* Bosch */ -#define RT_SENSOR_VENDOR_INVENSENSE (3) /* Invensense */ -#define RT_SENSOR_VENDOR_SEMTECH (4) /* Semtech */ -#define RT_SENSOR_VENDOR_GOERTEK (5) /* Goertek */ -#define RT_SENSOR_VENDOR_MIRAMEMS (6) /* MiraMEMS */ -#define RT_SENSOR_VENDOR_DALLAS (7) /* Dallas */ -#define RT_SENSOR_VENDOR_ASAIR (8) /* Aosong */ -#define RT_SENSOR_VENDOR_SHARP (9) /* Sharp */ -#define RT_SENSOR_VENDOR_SENSIRION (10) /* Sensirion */ -#define RT_SENSOR_VENDOR_TI (11) /* Texas Instruments */ -#define RT_SENSOR_VENDOR_PLANTOWER (12) /* Plantower */ -#define RT_SENSOR_VENDOR_AMS (13) /* ams AG */ -#define RT_SENSOR_VENDOR_MAXIM (14) /* Maxim Integrated */ - - -/* Sensor unit types */ - -#define RT_SENSOR_UNIT_NONE (0) -#define RT_SENSOR_UNIT_MG (1) /* Accelerometer unit: mG */ -#define RT_SENSOR_UNIT_MDPS (2) /* Gyroscope unit: mdps */ -#define RT_SENSOR_UNIT_MGAUSS (3) /* Magnetometer unit: mGauss */ -#define RT_SENSOR_UNIT_LUX (4) /* Ambient light unit: lux */ -#define RT_SENSOR_UNIT_CM (5) /* Distance unit: cm */ -#define RT_SENSOR_UNIT_PA (6) /* Barometer unit: pa */ -#define RT_SENSOR_UNIT_PERMILLAGE (7) /* Relative Humidity unit: permillage */ -#define RT_SENSOR_UNIT_DCELSIUS (8) /* Temperature unit: dCelsius */ -#define RT_SENSOR_UNIT_HZ (9) /* Frequency unit: HZ */ -#define RT_SENSOR_UNIT_ONE (10) /* Dimensionless quantity unit: 1 */ -#define RT_SENSOR_UNIT_BPM (11) /* Heart rate unit: bpm */ -#define RT_SENSOR_UNIT_MM (12) /* Distance unit: mm */ -#define RT_SENSOR_UNIT_MN (13) /* Force unit: mN */ -#define RT_SENSOR_UNIT_PPM (14) /* Concentration unit: ppm */ -#define RT_SENSOR_UNIT_PPB (15) /* Concentration unit: ppb */ -#define RT_SENSOR_UNIT_DMS (16) /* Coordinates unit: DMS */ -#define RT_SENSOR_UNIT_DD (17) /* Coordinates unit: DD */ - -/* Sensor communication interface types */ - -#define RT_SENSOR_INTF_I2C (1 << 0) -#define RT_SENSOR_INTF_SPI (1 << 1) -#define RT_SENSOR_INTF_UART (1 << 2) -#define RT_SENSOR_INTF_ONEWIRE (1 << 3) - -/* Sensor power mode types */ - -#define RT_SENSOR_POWER_NONE (0) -#define RT_SENSOR_POWER_DOWN (1) /* power down mode */ -#define RT_SENSOR_POWER_NORMAL (2) /* normal-power mode */ -#define RT_SENSOR_POWER_LOW (3) /* low-power mode */ -#define RT_SENSOR_POWER_HIGH (4) /* high-power mode */ - -/* Sensor work mode types */ - -#define RT_SENSOR_MODE_NONE (0) -#define RT_SENSOR_MODE_POLLING (1) /* One shot only read a data */ -#define RT_SENSOR_MODE_INT (2) /* TODO: One shot interrupt only read a data */ -#define RT_SENSOR_MODE_FIFO (3) /* TODO: One shot interrupt read all fifo data */ - -/* Sensor control cmd types */ - -#define RT_SENSOR_CTRL_GET_ID (0) /* Get device id */ -#define RT_SENSOR_CTRL_GET_INFO (1) /* Get sensor info */ -#define RT_SENSOR_CTRL_SET_RANGE (2) /* Set the measure range of sensor. unit is info of sensor */ -#define RT_SENSOR_CTRL_SET_ODR (3) /* Set output date rate. unit is HZ */ -#define RT_SENSOR_CTRL_SET_MODE (4) /* Set sensor's work mode. ex. RT_SENSOR_MODE_POLLING,RT_SENSOR_MODE_INT */ -#define RT_SENSOR_CTRL_SET_POWER (5) /* Set power mode. args type of sensor power mode. ex. RT_SENSOR_POWER_DOWN,RT_SENSOR_POWER_NORMAL */ -#define RT_SENSOR_CTRL_SELF_TEST (6) /* Take a self test */ - -#define RT_SENSOR_CTRL_USER_CMD_START 0x100 /* User commands should be greater than 0x100 */ - -struct rt_sensor_info -{ - rt_uint8_t type; /* The sensor type */ - rt_uint8_t vendor; /* Vendor of sensors */ - const char *model; /* model name of sensor */ - rt_uint8_t unit; /* unit of measurement */ - rt_uint8_t intf_type; /* Communication interface type */ - rt_int32_t range_max; /* maximum range of this sensor's value. unit is 'unit' */ - rt_int32_t range_min; /* minimum range of this sensor's value. unit is 'unit' */ - rt_uint32_t period_min; /* Minimum measurement period,unit:ms. zero = not a constant rate */ - rt_uint8_t fifo_max; -}; - -struct rt_sensor_intf -{ - char *dev_name; /* The name of the communication device */ - rt_uint8_t type; /* Communication interface type */ - void *user_data; /* Private data for the sensor. ex. i2c addr,spi cs,control I/O */ -}; - -struct rt_sensor_config -{ - struct rt_sensor_intf intf; /* sensor interface config */ - struct rt_device_pin_mode irq_pin; /* Interrupt pin, The purpose of this pin is to notification read data */ - rt_uint8_t mode; /* sensor work mode */ - rt_uint8_t power; /* sensor power mode */ - rt_uint16_t odr; /* sensor out data rate */ - rt_int32_t range; /* sensor range of measurement */ -}; - -typedef struct rt_sensor_device *rt_sensor_t; - -struct rt_sensor_device -{ - struct rt_device parent; /* The standard device */ - - struct rt_sensor_info info; /* The sensor info data */ - struct rt_sensor_config config; /* The sensor config data */ - - void *data_buf; /* The buf of the data received */ - rt_size_t data_len; /* The size of the data received */ - - const struct rt_sensor_ops *ops; /* The sensor ops */ - - struct rt_sensor_module *module; /* The sensor module */ - - rt_err_t (*irq_handle)(rt_sensor_t sensor); /* Called when an interrupt is generated, registered by the driver */ -}; - -struct rt_sensor_module -{ - rt_mutex_t lock; /* The module lock */ - - rt_sensor_t sen[RT_SENSOR_MODULE_MAX]; /* The module contains a list of sensors */ - rt_uint8_t sen_num; /* Number of sensors contained in the module */ -}; - -/* 3-axis Data Type */ -struct sensor_3_axis -{ - rt_int32_t x; - rt_int32_t y; - rt_int32_t z; -}; - -struct coordinates -{ - double longitude; - double latitude; -}; - -struct rt_sensor_data -{ - rt_uint32_t timestamp; /* The timestamp when the data was received */ - rt_uint8_t type; /* The sensor type of the data */ - union - { - struct sensor_3_axis acce; /* Accelerometer. unit: mG */ - struct sensor_3_axis gyro; /* Gyroscope. unit: mdps */ - struct sensor_3_axis mag; /* Magnetometer. unit: mGauss */ - struct coordinates coord; /* Coordinates unit: degrees */ - rt_int32_t temp; /* Temperature. unit: dCelsius */ - rt_int32_t humi; /* Relative humidity. unit: permillage */ - rt_int32_t baro; /* Pressure. unit: pascal (Pa) */ - rt_int32_t light; /* Light. unit: lux */ - rt_int32_t proximity; /* Distance. unit: centimeters */ - rt_int32_t hr; /* Heart rate. unit: bpm */ - rt_int32_t tvoc; /* TVOC. unit: permillage */ - rt_int32_t noise; /* Noise Loudness. unit: HZ */ - rt_uint32_t step; /* Step sensor. unit: 1 */ - rt_int32_t force; /* Force sensor. unit: mN */ - rt_uint32_t dust; /* Dust sensor. unit: ug/m3 */ - rt_uint32_t eco2; /* eCO2 sensor. unit: ppm */ - } data; -}; - -struct rt_sensor_ops -{ - rt_size_t (*fetch_data)(struct rt_sensor_device *sensor, void *buf, rt_size_t len); - rt_err_t (*control)(struct rt_sensor_device *sensor, int cmd, void *arg); -}; - -int rt_hw_sensor_register(rt_sensor_t sensor, - const char *name, - rt_uint32_t flag, - void *data); - -#ifdef __cplusplus -} -#endif - -#endif /* __SENSOR_H__ */ diff --git a/components/drivers/sensors/sensor_cmd.c b/components/drivers/sensors/sensor_cmd.c index 5c2d22640c..0f0ab66d63 100755 --- a/components/drivers/sensors/sensor_cmd.c +++ b/components/drivers/sensors/sensor_cmd.c @@ -231,6 +231,7 @@ static void sensor_polling(int argc, char **argv) struct rt_sensor_data data; rt_size_t res, i; rt_int32_t delay; + rt_err_t result; dev = rt_device_find(argv[1]); if (dev == RT_NULL) @@ -244,9 +245,10 @@ static void sensor_polling(int argc, char **argv) sensor = (rt_sensor_t)dev; delay = sensor->info.period_min > 100 ? sensor->info.period_min : 100; - if (rt_device_open(dev, RT_DEVICE_FLAG_RDWR) != RT_EOK) + result = rt_device_open(dev, RT_DEVICE_FLAG_RDONLY); + if (result != RT_EOK) { - LOG_E("open device failed!"); + LOG_E("open device failed! error code : %d", result); return; } rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)100); @@ -451,7 +453,7 @@ static void sensor(int argc, char **argv) dev = rt_device_find(argv[2]); if (dev == RT_NULL) { - LOG_E("Can't find device:%s", argv[1]); + LOG_E("Can't find device:%s", argv[2]); return; } if (rt_device_open(dev, RT_DEVICE_FLAG_RDWR) != RT_EOK) diff --git a/components/drivers/serial/SConscript b/components/drivers/serial/SConscript index a6eb115919..81d791803a 100644 --- a/components/drivers/serial/SConscript +++ b/components/drivers/serial/SConscript @@ -1,8 +1,14 @@ from building import * -cwd = GetCurrentDir() -src = Glob('*.c') +cwd = GetCurrentDir() CPPPATH = [cwd + '/../include'] -group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SERIAL'], CPPPATH = CPPPATH) +group = [] +if GetDepend(['RT_USING_SERIAL']): + if GetDepend(['RT_USING_SERIAL_V2']): + src = Glob('serial_v2.c') + group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SERIAL_V2'], CPPPATH = CPPPATH) + else: + src = Glob('serial.c') + group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SERIAL'], CPPPATH = CPPPATH) Return('group') diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index d9a20f05a0..76298ea153 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -38,6 +38,7 @@ #ifdef RT_USING_POSIX #include <dfs_posix.h> #include <dfs_poll.h> +#include <sys/ioctl.h> #ifdef RT_USING_POSIX_TERMIOS #include <posix_termios.h> @@ -746,19 +747,24 @@ static rt_err_t rt_serial_close(struct rt_device *dev) { struct rt_serial_rx_fifo* rx_fifo; + /* configure low level device */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_RX); + dev->open_flag &= ~RT_DEVICE_FLAG_INT_RX; + rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx; RT_ASSERT(rx_fifo != RT_NULL); rt_free(rx_fifo); serial->serial_rx = RT_NULL; - dev->open_flag &= ~RT_DEVICE_FLAG_INT_RX; - /* configure low level device */ - serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_RX); } #ifdef RT_SERIAL_USING_DMA else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX) { + /* configure low level device */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *) RT_DEVICE_FLAG_DMA_RX); + dev->open_flag &= ~RT_DEVICE_FLAG_DMA_RX; + if (serial->config.bufsz == 0) { struct rt_serial_rx_dma* rx_dma; @@ -778,10 +784,7 @@ static rt_err_t rt_serial_close(struct rt_device *dev) rt_free(rx_fifo); } serial->serial_rx = RT_NULL; - dev->open_flag &= ~RT_DEVICE_FLAG_DMA_RX; - /* configure low level device */ - serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *) RT_DEVICE_FLAG_DMA_RX); } #endif /* RT_SERIAL_USING_DMA */ @@ -789,21 +792,26 @@ static rt_err_t rt_serial_close(struct rt_device *dev) { struct rt_serial_tx_fifo* tx_fifo; + serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_TX); + dev->open_flag &= ~RT_DEVICE_FLAG_INT_TX; + tx_fifo = (struct rt_serial_tx_fifo*)serial->serial_tx; RT_ASSERT(tx_fifo != RT_NULL); rt_free(tx_fifo); serial->serial_tx = RT_NULL; - dev->open_flag &= ~RT_DEVICE_FLAG_INT_TX; /* configure low level device */ - serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_TX); } #ifdef RT_SERIAL_USING_DMA else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX) { struct rt_serial_tx_dma* tx_dma; + /* configure low level device */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *) RT_DEVICE_FLAG_DMA_TX); + dev->open_flag &= ~RT_DEVICE_FLAG_DMA_TX; + tx_dma = (struct rt_serial_tx_dma*)serial->serial_tx; RT_ASSERT(tx_dma != RT_NULL); @@ -811,16 +819,13 @@ static rt_err_t rt_serial_close(struct rt_device *dev) rt_free(tx_dma); serial->serial_tx = RT_NULL; - dev->open_flag &= ~RT_DEVICE_FLAG_DMA_TX; - /* configure low level device */ - serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *) RT_DEVICE_FLAG_DMA_TX); } +#endif /* RT_SERIAL_USING_DMA */ serial->ops->control(serial, RT_DEVICE_CTRL_CLOSE, RT_NULL); dev->flag &= ~RT_DEVICE_FLAG_ACTIVATED; -#endif /* RT_SERIAL_USING_DMA */ return RT_EOK; } @@ -950,9 +955,7 @@ static void _tc_flush(struct rt_serial_device *serial, int queue) { RT_ASSERT(RT_NULL != rx_fifo); level = rt_hw_interrupt_disable(); - rt_memset(rx_fifo->buffer, 0, serial->config.bufsz); - rx_fifo->put_index = 0; - rx_fifo->get_index = 0; + rx_fifo->get_index = rx_fifo->put_index; rx_fifo->is_full = RT_FALSE; rt_hw_interrupt_enable(level); } diff --git a/components/drivers/serial/serial_v2.c b/components/drivers/serial/serial_v2.c new file mode 100644 index 0000000000..6e65457a5d --- /dev/null +++ b/components/drivers/serial/serial_v2.c @@ -0,0 +1,1268 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-06-01 KyleChan first version + */ + +#include <rthw.h> +#include <rtthread.h> +#include <rtdevice.h> + +#define DBG_TAG "UART" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +#ifdef RT_USING_POSIX +#include <dfs_posix.h> +#include <dfs_poll.h> +#include <sys/ioctl.h> + +#ifdef getc +#undef getc +#endif + +#ifdef putc +#undef putc +#endif + +static rt_err_t serial_fops_rx_ind(rt_device_t dev, rt_size_t size) +{ + rt_wqueue_wakeup(&(dev->wait_queue), (void*)POLLIN); + + return RT_EOK; +} + +/* fops for serial */ +static int serial_fops_open(struct dfs_fd *fd) +{ + rt_err_t ret = 0; + rt_uint16_t flags = 0; + rt_device_t device; + + device = (rt_device_t)fd->data; + RT_ASSERT(device != RT_NULL); + + switch (fd->flags & O_ACCMODE) + { + case O_RDONLY: + LOG_D("fops open: O_RDONLY!"); + flags = RT_DEVICE_FLAG_RDONLY; + break; + case O_WRONLY: + LOG_D("fops open: O_WRONLY!"); + flags = RT_DEVICE_FLAG_WRONLY; + break; + case O_RDWR: + LOG_D("fops open: O_RDWR!"); + flags = RT_DEVICE_FLAG_RDWR; + break; + default: + LOG_E("fops open: unknown mode - %d!", fd->flags & O_ACCMODE); + break; + } + + if ((fd->flags & O_ACCMODE) != O_WRONLY) + rt_device_set_rx_indicate(device, serial_fops_rx_ind); + ret = rt_device_open(device, flags); + if (ret == RT_EOK) return 0; + + return ret; +} + +static int serial_fops_close(struct dfs_fd *fd) +{ + rt_device_t device; + + device = (rt_device_t)fd->data; + + rt_device_set_rx_indicate(device, RT_NULL); + rt_device_close(device); + + return 0; +} + +static int serial_fops_ioctl(struct dfs_fd *fd, int cmd, void *args) +{ + rt_device_t device; + + device = (rt_device_t)fd->data; + switch (cmd) + { + case FIONREAD: + break; + case FIONWRITE: + break; + } + + return rt_device_control(device, cmd, args); +} + +static int serial_fops_read(struct dfs_fd *fd, void *buf, size_t count) +{ + int size = 0; + rt_device_t device; + + device = (rt_device_t)fd->data; + + do + { + size = rt_device_read(device, -1, buf, count); + if (size <= 0) + { + if (fd->flags & O_NONBLOCK) + { + size = -EAGAIN; + break; + } + + rt_wqueue_wait(&(device->wait_queue), 0, RT_WAITING_FOREVER); + } + }while (size <= 0); + + return size; +} + +static int serial_fops_write(struct dfs_fd *fd, const void *buf, size_t count) +{ + rt_device_t device; + + device = (rt_device_t)fd->data; + return rt_device_write(device, -1, buf, count); +} + +static int serial_fops_poll(struct dfs_fd *fd, struct rt_pollreq *req) +{ + int mask = 0; + int flags = 0; + rt_device_t device; + struct rt_serial_device *serial; + + device = (rt_device_t)fd->data; + RT_ASSERT(device != RT_NULL); + + serial = (struct rt_serial_device *)device; + + /* only support POLLIN */ + flags = fd->flags & O_ACCMODE; + if (flags == O_RDONLY || flags == O_RDWR) + { + rt_base_t level; + struct rt_serial_rx_fifo* rx_fifo; + + rt_poll_add(&(device->wait_queue), req); + + rx_fifo = (struct rt_serial_rx_fifo*) serial->serial_rx; + + level = rt_hw_interrupt_disable(); + + if (rt_ringbuffer_data_len(&rx_fifo->rb)) + mask |= POLLIN; + rt_hw_interrupt_enable(level); + } + // mask|=POLLOUT; + return mask; +} + +const static struct dfs_file_ops _serial_fops = +{ + serial_fops_open, + serial_fops_close, + serial_fops_ioctl, + serial_fops_read, + serial_fops_write, + RT_NULL, /* flush */ + RT_NULL, /* lseek */ + RT_NULL, /* getdents */ + serial_fops_poll, +}; +#endif + +static rt_size_t rt_serial_get_linear_buffer(struct rt_ringbuffer *rb, + rt_uint8_t **ptr) +{ + rt_size_t size; + + RT_ASSERT(rb != RT_NULL); + + *ptr = RT_NULL; + + /* whether has enough data */ + size = rt_ringbuffer_data_len(rb); + + /* no data */ + if (size == 0) + return 0; + + *ptr = &rb->buffer_ptr[rb->read_index]; + + if(rb->buffer_size - rb->read_index > size) + { + return size; + } + + return rb->buffer_size - rb->read_index; +} + +static rt_size_t rt_serial_update_read_index(struct rt_ringbuffer *rb, + rt_uint16_t read_index) +{ + rt_size_t size; + + RT_ASSERT(rb != RT_NULL); + + /* whether has enough data */ + size = rt_ringbuffer_data_len(rb); + + /* no data */ + if (size == 0) + return 0; + + /* less data */ + if(size < read_index) + read_index = size; + + if(rb->buffer_size - rb->read_index > read_index) + { + rb->read_index += read_index; + return read_index; + } + + read_index = rb->buffer_size - rb->read_index; + + /* we are going into the other side of the mirror */ + rb->read_mirror = ~rb->read_mirror; + rb->read_index = 0; + + return read_index; +} + +static rt_size_t rt_serial_update_write_index(struct rt_ringbuffer *rb, + rt_uint16_t write_index) +{ + rt_uint16_t size; + RT_ASSERT(rb != RT_NULL); + + /* whether has enough space */ + size = rt_ringbuffer_space_len(rb); + + /* no space */ + if (size == 0) + return 0; + + /* drop some data */ + if (size < write_index) + write_index = size; + + if (rb->buffer_size - rb->write_index > write_index) + { + /* this should not cause overflow because there is enough space for + * length of data in current mirror */ + rb->write_index += write_index; + return write_index; + } + + /* we are going into the other side of the mirror */ + rb->write_mirror = ~rb->write_mirror; + rb->write_index = write_index - (rb->buffer_size - rb->write_index); + + return write_index; +} + + +/** + * @brief Serial polling receive data routine, This function will receive data + * in a continuous loop by one by one byte. + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Receive data buffer. + * @param size Receive data buffer length. + * @return Return the final length of data received. + */ +rt_size_t _serial_poll_rx(struct rt_device *dev, + rt_off_t pos, + void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + rt_size_t getc_size; + int getc_element; /* Gets one byte of data received */ + rt_uint8_t *getc_buffer; /* Pointer to the receive data buffer */ + + RT_ASSERT(dev != RT_NULL); + + serial = (struct rt_serial_device *)dev; + RT_ASSERT(serial != RT_NULL); + getc_buffer = (rt_uint8_t *)buffer; + getc_size = size; + + while(size) + { + getc_element = serial->ops->getc(serial); + if (getc_element == -1) break; + + *getc_buffer = getc_element; + + ++ getc_buffer; + -- size; + + if (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM) + { + /* If open_flag satisfies RT_DEVICE_FLAG_STREAM + * and the received character is '\n', exit the loop directly */ + if (getc_element == '\n') break; + } + } + + return getc_size - size; +} + +/** + * @brief Serial polling transmit data routines, This function will transmit + * data in a continuous loop by one by one byte. + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Transmit data buffer. + * @param size Transmit data buffer length. + * @return Return the final length of data received. + */ +rt_size_t _serial_poll_tx(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + rt_size_t putc_size; + rt_uint8_t *putc_buffer; /* Pointer to the transmit data buffer */ + RT_ASSERT(dev != RT_NULL); + + serial = (struct rt_serial_device *)dev; + RT_ASSERT(serial != RT_NULL); + + putc_buffer = (rt_uint8_t *)buffer; + putc_size = size; + + while (size) + { + if (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM) + { + /* If open_flag satisfies RT_DEVICE_FLAG_STREAM and the received character is '\n', + * inserts '\r' character before '\n' character for the effect of carriage return newline */ + if (*putc_buffer == '\n') + serial->ops->putc(serial, '\r'); + } + serial->ops->putc(serial, *putc_buffer); + + ++ putc_buffer; + -- size; + } + + return putc_size - size; +} + +/** + * @brief Serial receive data routines, This function will receive + * data by using fifo + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Receive data buffer. + * @param size Receive data buffer length. + * @return Return the final length of data received. + */ +static rt_size_t _serial_fifo_rx(struct rt_device *dev, + rt_off_t pos, + void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + struct rt_serial_rx_fifo *rx_fifo; + rt_base_t level; + rt_size_t recv_len; /* The length of data from the ringbuffer */ + + RT_ASSERT(dev != RT_NULL); + if (size == 0) return 0; + + serial = (struct rt_serial_device *)dev; + + RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL)); + + rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; + + if (dev->open_flag & RT_SERIAL_RX_BLOCKING) + { + if (size > serial->config.rx_bufsz) + { + LOG_W("(%s) serial device received data:[%d] larger than " + "rx_bufsz:[%d], please increase the BSP_UARTx_RX_BUFSIZE option", + dev->parent.name, size, serial->config.rx_bufsz); + + return 0; + } + /* Get the length of the data from the ringbuffer */ + recv_len = rt_ringbuffer_data_len(&(rx_fifo->rb)); + + if (recv_len < size) + { + /* When recv_len is less than size, rx_cpt_index is updated to the size + * and rt_current_thread is suspend until rx_cpt_index is equal to 0 */ + rx_fifo->rx_cpt_index = size; + rt_completion_wait(&(rx_fifo->rx_cpt), RT_WAITING_FOREVER); + } + } + + /* This part of the code is open_flag as RT_SERIAL_RX_NON_BLOCKING */ + + level = rt_hw_interrupt_disable(); + /* When open_flag is RT_SERIAL_RX_NON_BLOCKING, + * the data is retrieved directly from the ringbuffer and returned */ + recv_len = rt_ringbuffer_get(&(rx_fifo->rb), buffer, size); + + rt_hw_interrupt_enable(level); + + return recv_len; +} + +/** + * @brief Serial transmit data routines, This function will transmit + * data by using blocking_nbuf. + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Transmit data buffer. + * @param size Transmit data buffer length. + * @return Return the final length of data transmit. + */ +static rt_size_t _serial_fifo_tx_blocking_nbuf(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + struct rt_serial_tx_fifo *tx_fifo = RT_NULL; + + RT_ASSERT(dev != RT_NULL); + if (size == 0) return 0; + + serial = (struct rt_serial_device *)dev; + RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL)); + tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + + /* When serial transmit in tx_blocking mode, + * if the activated mode is RT_TRUE, it will return directly */ + if (tx_fifo->activated == RT_TRUE) return 0; + + tx_fifo->activated = RT_TRUE; + /* Call the transmit interface for transmission */ + serial->ops->transmit(serial, + (rt_uint8_t *)buffer, + size, + RT_SERIAL_TX_BLOCKING); + /* Waiting for the transmission to complete */ + rt_completion_wait(&(tx_fifo->tx_cpt), RT_WAITING_FOREVER); + + return size; +} + +/** + * @brief Serial transmit data routines, This function will transmit + * data by using blocking_buf. + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Transmit data buffer. + * @param size Transmit data buffer length. + * @return Return the final length of data transmit. + */ +static rt_size_t _serial_fifo_tx_blocking_buf(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + struct rt_serial_tx_fifo *tx_fifo = RT_NULL; + + RT_ASSERT(dev != RT_NULL); + if (size == 0) return 0; + + serial = (struct rt_serial_device *)dev; + RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL)); + tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + /* When serial transmit in tx_blocking mode, + * if the activated mode is RT_TRUE, it will return directly */ + if (tx_fifo->activated == RT_TRUE) return 0; + + tx_fifo->activated = RT_TRUE; + rt_size_t length = size; + rt_size_t offset = 0; + + while (size) + { + /* Copy one piece of data into the ringbuffer at a time + * until the length of the data is equal to size */ + tx_fifo->put_size = rt_ringbuffer_put(&(tx_fifo->rb), + (rt_uint8_t *)buffer + offset, + size); + + offset += tx_fifo->put_size; + size -= tx_fifo->put_size; + /* Call the transmit interface for transmission */ + serial->ops->transmit(serial, + (rt_uint8_t *)buffer + offset, + tx_fifo->put_size, + RT_SERIAL_TX_BLOCKING); + /* Waiting for the transmission to complete */ + rt_completion_wait(&(tx_fifo->tx_cpt), RT_WAITING_FOREVER); + } + + return length; +} + +/** + * @brief Serial transmit data routines, This function will transmit + * data by using nonblocking. + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Transmit data buffer. + * @param size Transmit data buffer length. + * @return Return the final length of data transmit. + */ +static rt_size_t _serial_fifo_tx_nonblocking(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + struct rt_serial_tx_fifo *tx_fifo; + rt_base_t level; + rt_size_t length; + + RT_ASSERT(dev != RT_NULL); + if (size == 0) return 0; + + serial = (struct rt_serial_device *)dev; + RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL)); + tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx; + + level = rt_hw_interrupt_disable(); + + if (tx_fifo->activated == RT_FALSE) + { + /* When serial transmit in tx_non_blocking mode, if the activated mode is RT_FALSE, + * start copying data into the ringbuffer */ + tx_fifo->activated = RT_TRUE; + /* Copying data into the ringbuffer */ + length = rt_ringbuffer_put(&(tx_fifo->rb), buffer, size); + + rt_hw_interrupt_enable(level); + + rt_uint8_t *put_ptr = RT_NULL; + /* Get the linear length buffer from rinbuffer */ + tx_fifo->put_size = rt_serial_get_linear_buffer(&(tx_fifo->rb), &put_ptr); + /* Call the transmit interface for transmission */ + serial->ops->transmit(serial, + put_ptr, + tx_fifo->put_size, + RT_SERIAL_TX_NON_BLOCKING); + /* In tx_nonblocking mode, there is no need to call rt_completion_wait() APIs to wait + * for the rt_current_thread to resume */ + return length; + } + + /* If the activated mode is RT_FALSE, it means that serial device is transmitting, + * where only the data in the ringbuffer and there is no need to call the transmit() API. + * Note that this part of the code requires disable interrupts + * to prevent multi thread reentrant */ + + /* Copying data into the ringbuffer */ + length = rt_ringbuffer_put(&(tx_fifo->rb), buffer, size); + + rt_hw_interrupt_enable(level); + + return length; +} + + +/** + * @brief Enable serial transmit mode. + * @param dev The pointer of device driver structure + * @param rx_oflag The flag of that the serial port opens. + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_tx_enable(struct rt_device *dev, + rt_uint16_t tx_oflag) +{ + struct rt_serial_device *serial; + struct rt_serial_tx_fifo *tx_fifo = RT_NULL; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + if (serial->config.tx_bufsz == 0) + { + /* Cannot use RT_SERIAL_TX_NON_BLOCKING when tx_bufsz is 0 */ + if (tx_oflag == RT_SERIAL_TX_NON_BLOCKING) + { + LOG_E("(%s) serial device with misconfigure: tx_bufsz = 0", + dev->parent.name); + return -RT_EINVAL; + } + +#ifndef RT_USING_DEVICE_OPS + dev->write = _serial_poll_tx; +#endif + + dev->open_flag |= RT_SERIAL_TX_BLOCKING; + return RT_EOK; + } + /* Limits the minimum value of tx_bufsz */ + if (serial->config.tx_bufsz < RT_SERIAL_TX_MINBUFSZ) + serial->config.tx_bufsz = RT_SERIAL_TX_MINBUFSZ; + + if (tx_oflag == RT_SERIAL_TX_BLOCKING) + { + /* When using RT_SERIAL_TX_BLOCKING, it is necessary to determine + * whether serial device needs to use buffer */ + rt_err_t optmode; /* The operating mode used by serial device */ + /* Call the Control() API to get the operating mode */ + optmode = serial->ops->control(serial, + RT_DEVICE_CHECK_OPTMODE, + (void *)RT_DEVICE_FLAG_TX_BLOCKING); + if (optmode == RT_SERIAL_TX_BLOCKING_BUFFER) + { + /* If use RT_SERIAL_TX_BLOCKING_BUFFER, the ringbuffer is initialized */ + tx_fifo = (struct rt_serial_tx_fifo *) rt_malloc + (sizeof(struct rt_serial_tx_fifo) + serial->config.tx_bufsz); + RT_ASSERT(tx_fifo != RT_NULL); + + rt_ringbuffer_init(&(tx_fifo->rb), + tx_fifo->buffer, + serial->config.tx_bufsz); + serial->serial_tx = tx_fifo; + +#ifndef RT_USING_DEVICE_OPS + dev->write = _serial_fifo_tx_blocking_buf; +#endif + } + else + { + /* If not use RT_SERIAL_TX_BLOCKING_BUFFER, + * the control() API is called to configure the serial device */ + tx_fifo = (struct rt_serial_tx_fifo*) rt_malloc + (sizeof(struct rt_serial_tx_fifo)); + RT_ASSERT(tx_fifo != RT_NULL); + + serial->serial_tx = tx_fifo; + +#ifndef RT_USING_DEVICE_OPS + dev->write = _serial_fifo_tx_blocking_nbuf; +#endif + + /* Call the control() API to configure the serial device by RT_SERIAL_TX_BLOCKING*/ + serial->ops->control(serial, + RT_DEVICE_CTRL_CONFIG, + (void *)RT_SERIAL_TX_BLOCKING); + } + + tx_fifo->activated = RT_FALSE; + tx_fifo->put_size = 0; + rt_completion_init(&(tx_fifo->tx_cpt)); + dev->open_flag |= RT_SERIAL_TX_BLOCKING; + + return RT_EOK; + } + /* When using RT_SERIAL_TX_NON_BLOCKING, ringbuffer needs to be initialized, + * and initialize the tx_fifo->activated value is RT_FALSE. + */ + tx_fifo = (struct rt_serial_tx_fifo *) rt_malloc + (sizeof(struct rt_serial_tx_fifo) + serial->config.tx_bufsz); + RT_ASSERT(tx_fifo != RT_NULL); + + tx_fifo->activated = RT_FALSE; + tx_fifo->put_size = 0; + rt_ringbuffer_init(&(tx_fifo->rb), + tx_fifo->buffer, + serial->config.tx_bufsz); + serial->serial_tx = tx_fifo; + +#ifndef RT_USING_DEVICE_OPS + dev->write = _serial_fifo_tx_nonblocking; +#endif + + dev->open_flag |= RT_SERIAL_TX_NON_BLOCKING; + /* Call the control() API to configure the serial device by RT_SERIAL_TX_NON_BLOCKING*/ + serial->ops->control(serial, + RT_DEVICE_CTRL_CONFIG, + (void *)RT_SERIAL_TX_NON_BLOCKING); + + return RT_EOK; +} + + +/** + * @brief Enable serial receive mode. + * @param dev The pointer of device driver structure + * @param rx_oflag The flag of that the serial port opens. + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_rx_enable(struct rt_device *dev, + rt_uint16_t rx_oflag) +{ + struct rt_serial_device *serial; + struct rt_serial_rx_fifo *rx_fifo = RT_NULL; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + if (serial->config.rx_bufsz == 0) + { + /* Cannot use RT_SERIAL_RX_NON_BLOCKING when rx_bufsz is 0 */ + if (rx_oflag == RT_SERIAL_RX_NON_BLOCKING) + { + LOG_E("(%s) serial device with misconfigure: rx_bufsz = 0", + dev->parent.name); + return -RT_EINVAL; + } + +#ifndef RT_USING_DEVICE_OPS + dev->read = _serial_poll_rx; +#endif + + dev->open_flag |= RT_SERIAL_RX_BLOCKING; + return RT_EOK; + } + /* Limits the minimum value of rx_bufsz */ + if (serial->config.rx_bufsz < RT_SERIAL_RX_MINBUFSZ) + serial->config.rx_bufsz = RT_SERIAL_RX_MINBUFSZ; + + rx_fifo = (struct rt_serial_rx_fifo *) rt_malloc + (sizeof(struct rt_serial_rx_fifo) + serial->config.rx_bufsz); + + RT_ASSERT(rx_fifo != RT_NULL); + rt_ringbuffer_init(&(rx_fifo->rb), rx_fifo->buffer, serial->config.rx_bufsz); + + serial->serial_rx = rx_fifo; + +#ifndef RT_USING_DEVICE_OPS + dev->read = _serial_fifo_rx; +#endif + + if (rx_oflag == RT_SERIAL_RX_NON_BLOCKING) + { + dev->open_flag |= RT_SERIAL_RX_NON_BLOCKING; + /* Call the control() API to configure the serial device by RT_SERIAL_RX_NON_BLOCKING*/ + serial->ops->control(serial, + RT_DEVICE_CTRL_CONFIG, + (void *) RT_SERIAL_RX_NON_BLOCKING); + + return RT_EOK; + } + /* When using RT_SERIAL_RX_BLOCKING, rt_completion_init() and rx_cpt_index are initialized */ + rx_fifo->rx_cpt_index = 0; + rt_completion_init(&(rx_fifo->rx_cpt)); + dev->open_flag |= RT_SERIAL_RX_BLOCKING; + /* Call the control() API to configure the serial device by RT_SERIAL_RX_BLOCKING*/ + serial->ops->control(serial, + RT_DEVICE_CTRL_CONFIG, + (void *) RT_SERIAL_RX_BLOCKING); + + return RT_EOK; +} + +/** + * @brief Disable serial receive mode. + * @param dev The pointer of device driver structure + * @param rx_oflag The flag of that the serial port opens. + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_rx_disable(struct rt_device *dev, + rt_uint16_t rx_oflag) +{ + struct rt_serial_device *serial; + struct rt_serial_rx_fifo *rx_fifo; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + +#ifndef RT_USING_DEVICE_OPS + dev->read = RT_NULL; +#endif + + if (serial->serial_rx == RT_NULL) return RT_EOK; + + do + { + if (rx_oflag == RT_SERIAL_RX_NON_BLOCKING) + { + dev->open_flag &= ~ RT_SERIAL_RX_NON_BLOCKING; + serial->ops->control(serial, + RT_DEVICE_CTRL_CLR_INT, + (void *)RT_SERIAL_RX_NON_BLOCKING); + break; + } + + dev->open_flag &= ~ RT_SERIAL_RX_BLOCKING; + serial->ops->control(serial, + RT_DEVICE_CTRL_CLR_INT, + (void *)RT_SERIAL_RX_BLOCKING); + } while (0); + + rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); + rt_free(rx_fifo); + serial->serial_rx = RT_NULL; + + return RT_EOK; +} + +/** + * @brief Disable serial tranmit mode. + * @param dev The pointer of device driver structure + * @param rx_oflag The flag of that the serial port opens. + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_tx_disable(struct rt_device *dev, + rt_uint16_t tx_oflag) +{ + struct rt_serial_device *serial; + struct rt_serial_tx_fifo *tx_fifo; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + +#ifndef RT_USING_DEVICE_OPS + dev->write = RT_NULL; +#endif + + if (serial->serial_tx == RT_NULL) return RT_EOK; + + tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + + do + { + if (tx_oflag == RT_SERIAL_TX_NON_BLOCKING) + { + dev->open_flag &= ~ RT_SERIAL_TX_NON_BLOCKING; + + serial->ops->control(serial, + RT_DEVICE_CTRL_CLR_INT, + (void *)RT_SERIAL_TX_NON_BLOCKING); + break; + } + + rt_completion_done(&(tx_fifo->tx_cpt)); + dev->open_flag &= ~ RT_SERIAL_TX_BLOCKING; + serial->ops->control(serial, + RT_DEVICE_CTRL_CLR_INT, + (void *)RT_SERIAL_TX_BLOCKING); + } while (0); + + rt_free(tx_fifo); + serial->serial_tx = RT_NULL; + + return RT_EOK; +} + +/** + * @brief Initialize the serial device. + * @param dev The pointer of device driver structure + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_init(struct rt_device *dev) +{ + rt_err_t result = RT_EOK; + struct rt_serial_device *serial; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + /* initialize rx/tx */ + serial->serial_rx = RT_NULL; + serial->serial_tx = RT_NULL; + + /* apply configuration */ + if (serial->ops->configure) + result = serial->ops->configure(serial, &serial->config); + + return result; +} + +/** + * @brief Open the serial device. + * @param dev The pointer of device driver structure + * @param oflag The flag of that the serial port opens. + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) +{ + struct rt_serial_device *serial; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + /* Check that the device has been turned on */ + if ((dev->open_flag) & (15 << 12)) + { + LOG_D("(%s) serial device has already been opened, it will run in its original configuration", dev->parent.name); + return RT_EOK; + } + + LOG_D("open serial device: 0x%08x with open flag: 0x%04x", + dev, oflag); + + /* By default, the receive mode of a serial devide is RT_SERIAL_RX_NON_BLOCKING */ + if ((oflag & RT_SERIAL_RX_BLOCKING) == RT_SERIAL_RX_BLOCKING) + dev->open_flag |= RT_SERIAL_RX_BLOCKING; + else + dev->open_flag |= RT_SERIAL_RX_NON_BLOCKING; + + /* By default, the transmit mode of a serial devide is RT_SERIAL_TX_BLOCKING */ + if ((oflag & RT_SERIAL_TX_NON_BLOCKING) == RT_SERIAL_TX_NON_BLOCKING) + dev->open_flag |= RT_SERIAL_TX_NON_BLOCKING; + else + dev->open_flag |= RT_SERIAL_TX_BLOCKING; + + /* set steam flag */ + if ((oflag & RT_DEVICE_FLAG_STREAM) || + (dev->open_flag & RT_DEVICE_FLAG_STREAM)) + dev->open_flag |= RT_DEVICE_FLAG_STREAM; + + /* initialize the Rx structure according to open flag */ + if (serial->serial_rx == RT_NULL) + rt_serial_rx_enable(dev, dev->open_flag & + (RT_SERIAL_RX_BLOCKING | RT_SERIAL_RX_NON_BLOCKING)); + + /* initialize the Tx structure according to open flag */ + if (serial->serial_tx == RT_NULL) + rt_serial_tx_enable(dev, dev->open_flag & + (RT_SERIAL_TX_BLOCKING | RT_SERIAL_TX_NON_BLOCKING)); + + return RT_EOK; +} + + +/** + * @brief Close the serial device. + * @param dev The pointer of device driver structure + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_close(struct rt_device *dev) +{ + struct rt_serial_device *serial; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + /* this device has more reference count */ + if (dev->ref_count > 1) return -RT_ERROR; + /* Disable serial receive mode. */ + rt_serial_rx_disable(dev, dev->open_flag & + (RT_SERIAL_RX_BLOCKING | RT_SERIAL_RX_NON_BLOCKING)); + /* Disable serial tranmit mode. */ + rt_serial_tx_disable(dev, dev->open_flag & + (RT_SERIAL_TX_BLOCKING | RT_SERIAL_TX_NON_BLOCKING)); + + /* Clear the callback function */ + serial->parent.rx_indicate = RT_NULL; + serial->parent.tx_complete = RT_NULL; + + /* Call the control() API to close the serial device */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLOSE, RT_NULL); + dev->flag &= ~RT_DEVICE_FLAG_ACTIVATED; + + return RT_EOK; +} + +/** + * @brief Control the serial device. + * @param dev The pointer of device driver structure + * @param cmd The command value that controls the serial device + * @param args The parameter value that controls the serial device + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_control(struct rt_device *dev, + int cmd, + void *args) +{ + rt_err_t ret = RT_EOK; + struct rt_serial_device *serial; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + switch (cmd) + { + case RT_DEVICE_CTRL_SUSPEND: + /* suspend device */ + dev->flag |= RT_DEVICE_FLAG_SUSPENDED; + break; + + case RT_DEVICE_CTRL_RESUME: + /* resume device */ + dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED; + break; + + case RT_DEVICE_CTRL_CONFIG: + if (args != RT_NULL) + { + struct serial_configure *pconfig = (struct serial_configure *) args; + if (serial->parent.ref_count) + { + /*can not change buffer size*/ + return -RT_EBUSY; + } + /* set serial configure */ + serial->config = *pconfig; + serial->ops->configure(serial, + (struct serial_configure *) args); + } + + break; + + default : + /* control device */ + ret = serial->ops->control(serial, cmd, args); + break; + } + + return ret; +} + +#ifdef RT_USING_DEVICE_OPS +static rt_size_t rt_serial_read(struct rt_device *dev, + rt_off_t pos, + void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + + RT_ASSERT(dev != RT_NULL); + if (size == 0) return 0; + + serial = (struct rt_serial_device *)dev; + + if (serial->config.rx_bufsz) + { + return _serial_fifo_rx(dev, pos, buffer, size); + } + + return _serial_poll_rx(dev, pos, buffer, size); +} + + +static rt_size_t rt_serial_write(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + struct rt_serial_tx_fifo *tx_fifo; + + RT_ASSERT(dev != RT_NULL); + if (size == 0) return 0; + + serial = (struct rt_serial_device *)dev; + RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL)); + tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx; + + if (serial->config.tx_bufsz == 0) + { + return _serial_poll_tx(dev, pos, buffer, size); + } + + if (dev->open_flag | RT_SERIAL_TX_BLOCKING) + { + if ((tx_fifo->rb.buffer_ptr) == RT_NULL) + { + return _serial_fifo_tx_blocking_nbuf(dev, pos, buffer, size); + } + + return _serial_fifo_tx_blocking_buf(dev, pos, buffer, size); + } + + return _serial_fifo_tx_nonblocking(dev, pos, buffer, size); +} + +const static struct rt_device_ops serial_ops = +{ + rt_serial_init, + rt_serial_open, + rt_serial_close, + rt_serial_read, + rt_serial_write, + rt_serial_control +}; +#endif + +/** + * @brief Register the serial device. + * @param serial RT-thread serial device. + * @param name The device driver's name + * @param flag The capabilities flag of device. + * @param data The device driver's data. + * @return Return the status of the operation. + */ +rt_err_t rt_hw_serial_register(struct rt_serial_device *serial, + const char *name, + rt_uint32_t flag, + void *data) +{ + rt_err_t ret; + struct rt_device *device; + RT_ASSERT(serial != RT_NULL); + + device = &(serial->parent); + + device->type = RT_Device_Class_Char; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &serial_ops; +#else + device->init = rt_serial_init; + device->open = rt_serial_open; + device->close = rt_serial_close; + device->read = RT_NULL; + device->write = RT_NULL; + device->control = rt_serial_control; +#endif + device->user_data = data; + + /* register a character device */ + ret = rt_device_register(device, name, flag); + +#if defined(RT_USING_POSIX) + /* set fops */ + device->fops = &_serial_fops; +#endif + return ret; +} + +/** + * @brief ISR for serial interrupt + * @param serial RT-thread serial device. + * @param event ISR event type. + */ +void rt_hw_serial_isr(struct rt_serial_device *serial, int event) +{ + RT_ASSERT(serial != RT_NULL); + + switch (event & 0xff) + { + /* Interrupt receive event */ + case RT_SERIAL_EVENT_RX_IND: + case RT_SERIAL_EVENT_RX_DMADONE: + { + struct rt_serial_rx_fifo *rx_fifo; + rt_size_t rx_length = 0; + rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); + + /* If the event is RT_SERIAL_EVENT_RX_IND, rx_length is equal to 0 */ + rx_length = (event & (~0xff)) >> 8; + + if (rx_length) + rt_serial_update_write_index(&(rx_fifo->rb), rx_length); + + /* Get the length of the data from the ringbuffer */ + rx_length = rt_ringbuffer_data_len(&rx_fifo->rb); + if (rx_length == 0) break; + + if (serial->parent.open_flag & RT_SERIAL_RX_BLOCKING) + { + if (rx_fifo->rx_cpt_index && rx_length >= rx_fifo->rx_cpt_index ) + { + rx_fifo->rx_cpt_index = 0; + rt_completion_done(&(rx_fifo->rx_cpt)); + } + } + /* Trigger the receiving completion callback */ + if (serial->parent.rx_indicate != RT_NULL) + serial->parent.rx_indicate(&(serial->parent), rx_length); + break; + } + + /* Interrupt transmit event */ + case RT_SERIAL_EVENT_TX_DONE: + { + struct rt_serial_tx_fifo *tx_fifo; + rt_size_t tx_length = 0; + tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + + /* Get the length of the data from the ringbuffer */ + tx_length = rt_ringbuffer_data_len(&tx_fifo->rb); + /* If there is no data in tx_ringbuffer, + * then the transmit completion callback is triggered*/ + if (tx_length == 0) + { + tx_fifo->activated = RT_FALSE; + /* Trigger the transmit completion callback */ + if (serial->parent.tx_complete != RT_NULL) + serial->parent.tx_complete(&serial->parent, RT_NULL); + + if (serial->parent.open_flag & RT_SERIAL_TX_BLOCKING) + rt_completion_done(&(tx_fifo->tx_cpt)); + + break; + } + + /* Call the transmit interface for transmission again */ + /* Note that in interrupt mode, tx_fifo->buffer and tx_length + * are inactive parameters */ + serial->ops->transmit(serial, + tx_fifo->buffer, + tx_length, + serial->parent.open_flag & ( \ + RT_SERIAL_TX_BLOCKING | \ + RT_SERIAL_TX_NON_BLOCKING)); + break; + } + + case RT_SERIAL_EVENT_TX_DMADONE: + { + struct rt_serial_tx_fifo *tx_fifo; + tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + + tx_fifo->activated = RT_FALSE; + + /* Trigger the transmit completion callback */ + if (serial->parent.tx_complete != RT_NULL) + serial->parent.tx_complete(&serial->parent, RT_NULL); + + if (serial->parent.open_flag & RT_SERIAL_TX_BLOCKING) + { + rt_completion_done(&(tx_fifo->tx_cpt)); + break; + } + + rt_serial_update_read_index(&tx_fifo->rb, tx_fifo->put_size); + /* Get the length of the data from the ringbuffer. + * If there is some data in tx_ringbuffer, + * then call the transmit interface for transmission again */ + if (rt_ringbuffer_data_len(&tx_fifo->rb)) + { + tx_fifo->activated = RT_TRUE; + + rt_uint8_t *put_ptr = RT_NULL; + /* Get the linear length buffer from rinbuffer */ + tx_fifo->put_size = rt_serial_get_linear_buffer(&(tx_fifo->rb), &put_ptr); + /* Call the transmit interface for transmission again */ + serial->ops->transmit(serial, + put_ptr, + tx_fifo->put_size, + RT_SERIAL_TX_NON_BLOCKING); + } + + break; + } + + default: + break; + } +} diff --git a/components/drivers/spi/SConscript b/components/drivers/spi/SConscript index e19f30861f..d6cb93f7f1 100644 --- a/components/drivers/spi/SConscript +++ b/components/drivers/spi/SConscript @@ -28,7 +28,10 @@ if GetDepend('RT_USING_SFUD'): if rtconfig.CROSS_TOOL == 'gcc': LOCAL_CCFLAGS += ' -std=c99' elif rtconfig.CROSS_TOOL == 'keil': - LOCAL_CCFLAGS += ' --c99' + if rtconfig.PLATFORM == 'armcc': + LOCAL_CCFLAGS += ' --c99' + elif rtconfig.PLATFORM == 'armclang': + LOCAL_CCFLAGS += ' -std=c99' src += src_device diff --git a/components/drivers/spi/sfud/src/sfud.c b/components/drivers/spi/sfud/src/sfud.c index e5b03131ff..4078179262 100644 --- a/components/drivers/spi/sfud/src/sfud.c +++ b/components/drivers/spi/sfud/src/sfud.c @@ -218,7 +218,7 @@ sfud_err sfud_qspi_fast_read_enable(sfud_flash *flash, uint8_t data_line_width) break; case 2: if (read_mode & DUAL_IO) { - qspi_set_read_cmd_format(flash, SFUD_CMD_DUAL_IO_READ_DATA, 1, 2, 8, 2); + qspi_set_read_cmd_format(flash, SFUD_CMD_DUAL_IO_READ_DATA, 1, 2, 4, 2); } else if (read_mode & DUAL_OUTPUT) { qspi_set_read_cmd_format(flash, SFUD_CMD_DUAL_OUTPUT_READ_DATA, 1, 1, 8, 2); } else { diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c index 10b880ff7a..7fa5eb067d 100644 --- a/components/drivers/src/pipe.c +++ b/components/drivers/src/pipe.c @@ -11,11 +11,13 @@ #include <rthw.h> #include <rtdevice.h> #include <stdint.h> +#include <sys/errno.h> -#if defined(RT_USING_POSIX) +#ifdef RT_USING_POSIX #include <dfs_file.h> #include <dfs_posix.h> #include <dfs_poll.h> +#include <sys/ioctl.h> static int pipe_fops_open(struct dfs_fd *fd) { @@ -320,7 +322,7 @@ static const struct dfs_file_ops pipe_fops = }; #endif /* end of RT_USING_POSIX */ -rt_err_t rt_pipe_open (rt_device_t device, rt_uint16_t oflag) +rt_err_t rt_pipe_open(rt_device_t device, rt_uint16_t oflag) { rt_pipe_t *pipe = (rt_pipe_t *)device; rt_err_t ret = RT_EOK; @@ -348,7 +350,7 @@ __exit: return ret; } -rt_err_t rt_pipe_close (rt_device_t device) +rt_err_t rt_pipe_close(rt_device_t device) { rt_pipe_t *pipe = (rt_pipe_t *)device; @@ -366,7 +368,7 @@ rt_err_t rt_pipe_close (rt_device_t device) return RT_EOK; } -rt_size_t rt_pipe_read (rt_device_t device, rt_off_t pos, void *buffer, rt_size_t count) +rt_size_t rt_pipe_read(rt_device_t device, rt_off_t pos, void *buffer, rt_size_t count) { uint8_t *pbuf; rt_size_t read_bytes = 0; @@ -374,7 +376,7 @@ rt_size_t rt_pipe_read (rt_device_t device, rt_off_t pos, void *buffer, rt_siz if (device == RT_NULL) { - rt_set_errno(-EINVAL); + rt_set_errno(EINVAL); return 0; } if (count == 0) return 0; @@ -394,7 +396,7 @@ rt_size_t rt_pipe_read (rt_device_t device, rt_off_t pos, void *buffer, rt_siz return read_bytes; } -rt_size_t rt_pipe_write (rt_device_t device, rt_off_t pos, const void *buffer, rt_size_t count) +rt_size_t rt_pipe_write(rt_device_t device, rt_off_t pos, const void *buffer, rt_size_t count) { uint8_t *pbuf; rt_size_t write_bytes = 0; @@ -402,7 +404,7 @@ rt_size_t rt_pipe_write (rt_device_t device, rt_off_t pos, const void *buffer, if (device == RT_NULL) { - rt_set_errno(-EINVAL); + rt_set_errno(EINVAL); return 0; } if (count == 0) return 0; @@ -516,12 +518,12 @@ int rt_pipe_delete(const char *name) } else { - result = -ENODEV; + result = -RT_EINVAL; } } else { - result = -ENODEV; + result = -RT_EINVAL; } return result; @@ -531,8 +533,8 @@ int rt_pipe_delete(const char *name) int pipe(int fildes[2]) { rt_pipe_t *pipe; - char dname[8]; - char dev_name[32]; + char dname[RT_NAME_MAX]; + char dev_name[RT_NAME_MAX * 4]; static int pipeno = 0; rt_snprintf(dname, sizeof(dname), "pipe%d", pipeno++); diff --git a/components/drivers/src/ringblk_buf.c b/components/drivers/src/ringblk_buf.c index c9631b9d4a..c6688b3d2b 100644 --- a/components/drivers/src/ringblk_buf.c +++ b/components/drivers/src/ringblk_buf.c @@ -50,26 +50,26 @@ RTM_EXPORT(rt_rbb_init); * @param buf_size buffer size * @param blk_max_num max block number * - * @return != NULL: ring block buffer object - * NULL: create failed + * @return != RT_NULL: ring block buffer object + * RT_NULL: create failed */ rt_rbb_t rt_rbb_create(rt_size_t buf_size, rt_size_t blk_max_num) { - rt_rbb_t rbb = NULL; + rt_rbb_t rbb = RT_NULL; rt_uint8_t *buf; rt_rbb_blk_t blk_set; rbb = (rt_rbb_t)rt_malloc(sizeof(struct rt_rbb)); if (!rbb) { - return NULL; + return RT_NULL; } buf = (rt_uint8_t *)rt_malloc(buf_size); if (!buf) { rt_free(rbb); - return NULL; + return RT_NULL; } blk_set = (rt_rbb_blk_t)rt_malloc(sizeof(struct rt_rbb_blk) * blk_max_num); @@ -77,7 +77,7 @@ rt_rbb_t rt_rbb_create(rt_size_t buf_size, rt_size_t blk_max_num) { rt_free(buf); rt_free(rbb); - return NULL; + return RT_NULL; } rt_rbb_init(rbb, buf, buf_size, blk_set, blk_max_num); @@ -116,7 +116,7 @@ static rt_rbb_blk_t find_empty_blk_in_set(rt_rbb_t rbb) } } - return NULL; + return RT_NULL; } /** @@ -127,14 +127,14 @@ static rt_rbb_blk_t find_empty_blk_in_set(rt_rbb_t rbb) * * @note When your application need align access, please make the blk_szie is aligned. * - * @return != NULL: allocated block - * NULL: allocate failed + * @return != RT_NULL: allocated block + * RT_NULL: allocate failed */ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size) { rt_base_t level; rt_size_t empty1 = 0, empty2 = 0; - rt_rbb_blk_t head, tail, new_rbb = NULL; + rt_rbb_blk_t head, tail, new_rbb = RT_NULL; RT_ASSERT(rbb); RT_ASSERT(blk_size < (1L << 24)); @@ -178,7 +178,7 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size) else { /* no space */ - new_rbb = NULL; + new_rbb = RT_NULL; } } else @@ -202,7 +202,7 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size) else { /* no space */ - new_rbb = NULL; + new_rbb = RT_NULL; } } } @@ -217,7 +217,7 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size) } else { - new_rbb = NULL; + new_rbb = RT_NULL; } rt_hw_interrupt_enable(level); @@ -245,13 +245,13 @@ RTM_EXPORT(rt_rbb_blk_put); * * @param rbb ring block buffer object * - * @return != NULL: block - * NULL: get failed + * @return != RT_NULL: block + * RT_NULL: get failed */ rt_rbb_blk_t rt_rbb_blk_get(rt_rbb_t rbb) { rt_base_t level; - rt_rbb_blk_t block = NULL; + rt_rbb_blk_t block = RT_NULL; rt_slist_t *node; RT_ASSERT(rbb); @@ -271,7 +271,7 @@ rt_rbb_blk_t rt_rbb_blk_get(rt_rbb_t rbb) } } /* not found */ - block = NULL; + block = RT_NULL; __exit: @@ -364,7 +364,7 @@ rt_size_t rt_rbb_blk_queue_get(rt_rbb_t rbb, rt_size_t queue_data_len, rt_rbb_bl rt_base_t level; rt_size_t data_total_size = 0; rt_slist_t *node; - rt_rbb_blk_t last_block = NULL, block; + rt_rbb_blk_t last_block = RT_NULL, block; RT_ASSERT(rbb); RT_ASSERT(blk_queue); @@ -388,7 +388,7 @@ rt_size_t rt_rbb_blk_queue_get(rt_rbb_t rbb, rt_size_t queue_data_len, rt_rbb_bl else { /* the first block must be put status */ - last_block = NULL; + last_block = RT_NULL; continue; } } @@ -493,7 +493,7 @@ rt_size_t rt_rbb_next_blk_queue_len(rt_rbb_t rbb) rt_base_t level; rt_size_t data_len = 0; rt_slist_t *node; - rt_rbb_blk_t last_block = NULL, block; + rt_rbb_blk_t last_block = RT_NULL, block; RT_ASSERT(rbb); @@ -510,7 +510,7 @@ rt_size_t rt_rbb_next_blk_queue_len(rt_rbb_t rbb) if (last_block->status != RT_RBB_BLK_PUT) { /* the first block must be put status */ - last_block = NULL; + last_block = RT_NULL; continue; } } diff --git a/components/drivers/src/ringbuffer.c b/components/drivers/src/ringbuffer.c index 29de20b087..f01a594609 100644 --- a/components/drivers/src/ringbuffer.c +++ b/components/drivers/src/ringbuffer.c @@ -8,6 +8,7 @@ * 2012-09-30 Bernard first version. * 2013-05-08 Grissiom reimplement * 2016-08-18 heyuanjie add interface + * 2021-07-20 arminker fix write_index bug in function rt_ringbuffer_put_force */ #include <rtthread.h> @@ -138,7 +139,8 @@ rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb, if (length > space_length) { - rb->read_mirror = ~rb->read_mirror; + if (rb->write_index <= rb->read_index) + rb->read_mirror = ~rb->read_mirror; rb->read_index = rb->write_index; } diff --git a/components/drivers/src/workqueue.c b/components/drivers/src/workqueue.c index f195dad927..8fcfd52688 100644 --- a/components/drivers/src/workqueue.c +++ b/components/drivers/src/workqueue.c @@ -5,7 +5,8 @@ * * Change Logs: * Date Author Notes - * 2017-02-27 bernard fix the re-work issue. + * 2017-02-27 Bernard fix the re-work issue. + * 2021-08-01 Meco Man remove rt_delayed_work_init() */ #include <rthw.h> @@ -339,12 +340,6 @@ rt_err_t rt_workqueue_cancel_all_work(struct rt_workqueue *queue) return RT_EOK; } -void rt_delayed_work_init(struct rt_delayed_work *work, void (*work_func)(struct rt_work *work, - void *work_data), void *work_data) -{ - rt_work_init(&work->work, work_func, work_data); -} - #ifdef RT_USING_SYSTEM_WORKQUEUE static struct rt_workqueue *sys_workq; @@ -358,7 +353,7 @@ rt_err_t rt_work_cancel(struct rt_work *work) return rt_workqueue_cancel_work(sys_workq, work); } -int rt_work_sys_workqueue_init(void) +static int rt_work_sys_workqueue_init(void) { if (sys_workq != RT_NULL) return RT_EOK; @@ -370,5 +365,5 @@ int rt_work_sys_workqueue_init(void) return RT_EOK; } INIT_PREV_EXPORT(rt_work_sys_workqueue_init); -#endif -#endif +#endif /* RT_USING_SYSTEM_WORKQUEUE */ +#endif /* RT_USING_HEAP */ diff --git a/components/drivers/touch/touch.c b/components/drivers/touch/touch.c index abe2c0fe24..1a747d8669 100644 --- a/components/drivers/touch/touch.c +++ b/components/drivers/touch/touch.c @@ -77,6 +77,8 @@ static void rt_touch_irq_enable(rt_touch_t touch) { rt_pin_irq_enable(touch->config.irq_pin.pin, RT_TRUE); } +#else + touch->ops->touch_control(touch, RT_TOUCH_CTRL_ENABLE_INT, RT_NULL); #endif } @@ -88,6 +90,8 @@ static void rt_touch_irq_disable(rt_touch_t touch) { rt_pin_irq_enable(touch->config.irq_pin.pin, RT_FALSE); } +#else + touch->ops->touch_control(touch, RT_TOUCH_CTRL_DISABLE_INT, RT_NULL); #endif } @@ -144,28 +148,6 @@ static rt_err_t rt_touch_control(rt_device_t dev, int cmd, void *args) switch (cmd) { - case RT_TOUCH_CTRL_GET_ID: - if (args) - { - result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_GET_ID, args); - } - else - { - result = -RT_ERROR; - } - - break; - case RT_TOUCH_CTRL_GET_INFO: - if (args) - { - result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_GET_INFO, args); - } - else - { - result = -RT_ERROR; - } - - break; case RT_TOUCH_CTRL_SET_MODE: result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_SET_MODE, args); @@ -206,8 +188,11 @@ static rt_err_t rt_touch_control(rt_device_t dev, int cmd, void *args) case RT_TOUCH_CTRL_ENABLE_INT: rt_touch_irq_enable(touch); break; + + case RT_TOUCH_CTRL_GET_ID: + case RT_TOUCH_CTRL_GET_INFO: default: - return -RT_ERROR; + return touch->ops->touch_control(touch, cmd, args); } return result; diff --git a/components/drivers/usb/usbdevice/class/audio.h b/components/drivers/usb/usbdevice/class/audio.h deleted file mode 100644 index 4bb8994b47..0000000000 --- a/components/drivers/usb/usbdevice/class/audio.h +++ /dev/null @@ -1,676 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * <linux/usb/audio.h> -- USB Audio definitions. - * - * Copyright (C) 2006 Thumtronics Pty Ltd. - * Developed for Thumtronics by Grey Innovation - * Ben Williamson <[email protected]> - * - * This software is distributed under the terms of the GNU General Public - * License ("GPL") version 2, as published by the Free Software Foundation. - * - * This file holds USB constants and structures defined - * by the USB Device Class Definition for Audio Devices. - * Comments below reference relevant sections of that document: - * - * http://www.usb.org/developers/devclass_docs/audio10.pdf - * - * Types and defines in this file are either specific to version 1.0 of - * this standard or common for newer versions. - */ - -#ifndef _UAPI__LINUX_USB_AUDIO_H -#define _UAPI__LINUX_USB_AUDIO_H - -//#include <linux/types.h> -#include <rtthread.h> - -typedef int8_t __s8; -typedef uint8_t __u8; -typedef int16_t __s16; -typedef uint16_t __u16; -typedef int32_t __s32; -typedef uint32_t __u32; -typedef int64_t __s64; -typedef uint64_t __u64; - -#define UAC_USE_FEATURE_UNIT 0 /* Feature unit does not support */ - -/* - * Below are truly Linux-specific types that should never collide with - * any application/library that wants linux/types.h. - */ - -#ifdef __CHECKER__ -#define __bitwise__ __attribute__((bitwise)) -#else -#define __bitwise__ -#endif -#ifdef __CHECK_ENDIAN__ -#define __bitwise __bitwise__ -#else -#define __bitwise -#endif - -typedef __u16 __bitwise __le16; -typedef __u16 __bitwise __be16; -typedef __u32 __bitwise __le32; -typedef __u32 __bitwise __be32; -typedef __u64 __bitwise __le64; -typedef __u64 __bitwise __be64; - -typedef __u16 __bitwise __sum16; -typedef __u32 __bitwise __wsum; - -/* bInterfaceProtocol values to denote the version of the standard used */ -#define UAC_VERSION_1 0x00 -#define UAC_VERSION_2 0x20 -#define UAC_VERSION_3 0x30 - -/* A.2 Audio Interface Subclass Codes */ -#define USB_SUBCLASS_AUDIOCONTROL 0x01 -#define USB_SUBCLASS_AUDIOSTREAMING 0x02 -#define USB_SUBCLASS_MIDISTREAMING 0x03 - -/* A.5 Audio Class-Specific AC Interface Descriptor Subtypes */ -#define UAC_HEADER 0x01 -#define UAC_INPUT_TERMINAL 0x02 -#define UAC_OUTPUT_TERMINAL 0x03 -#define UAC_MIXER_UNIT 0x04 -#define UAC_SELECTOR_UNIT 0x05 -#define UAC_FEATURE_UNIT 0x06 -#define UAC1_PROCESSING_UNIT 0x07 -#define UAC1_EXTENSION_UNIT 0x08 - -/* A.6 Audio Class-Specific AS Interface Descriptor Subtypes */ -#define UAC_AS_GENERAL 0x01 -#define UAC_FORMAT_TYPE 0x02 -#define UAC_FORMAT_SPECIFIC 0x03 - -/* A.7 Processing Unit Process Types */ -#define UAC_PROCESS_UNDEFINED 0x00 -#define UAC_PROCESS_UP_DOWNMIX 0x01 -#define UAC_PROCESS_DOLBY_PROLOGIC 0x02 -#define UAC_PROCESS_STEREO_EXTENDER 0x03 -#define UAC_PROCESS_REVERB 0x04 -#define UAC_PROCESS_CHORUS 0x05 -#define UAC_PROCESS_DYN_RANGE_COMP 0x06 - -/* A.8 Audio Class-Specific Endpoint Descriptor Subtypes */ -#define UAC_EP_GENERAL 0x01 - -/* A.9 Audio Class-Specific Request Codes */ -#define UAC_SET_ 0x00 -#define UAC_GET_ 0x80 - -#define UAC__CUR 0x1 -#define UAC__MIN 0x2 -#define UAC__MAX 0x3 -#define UAC__RES 0x4 -#define UAC__MEM 0x5 - -#define UAC_SET_CUR (UAC_SET_ | UAC__CUR) -#define UAC_GET_CUR (UAC_GET_ | UAC__CUR) -#define UAC_SET_MIN (UAC_SET_ | UAC__MIN) -#define UAC_GET_MIN (UAC_GET_ | UAC__MIN) -#define UAC_SET_MAX (UAC_SET_ | UAC__MAX) -#define UAC_GET_MAX (UAC_GET_ | UAC__MAX) -#define UAC_SET_RES (UAC_SET_ | UAC__RES) -#define UAC_GET_RES (UAC_GET_ | UAC__RES) -#define UAC_SET_MEM (UAC_SET_ | UAC__MEM) -#define UAC_GET_MEM (UAC_GET_ | UAC__MEM) - -#define UAC_GET_STAT 0xff - -/* A.10 Control Selector Codes */ - -/* A.10.1 Terminal Control Selectors */ -#define UAC_TERM_COPY_PROTECT 0x01 - -/* A.10.2 Feature Unit Control Selectors */ -#define UAC_FU_MUTE 0x01 -#define UAC_FU_VOLUME 0x02 -#define UAC_FU_BASS 0x03 -#define UAC_FU_MID 0x04 -#define UAC_FU_TREBLE 0x05 -#define UAC_FU_GRAPHIC_EQUALIZER 0x06 -#define UAC_FU_AUTOMATIC_GAIN 0x07 -#define UAC_FU_DELAY 0x08 -#define UAC_FU_BASS_BOOST 0x09 -#define UAC_FU_LOUDNESS 0x0a - -#define UAC_CONTROL_BIT(CS) (1 << ((CS) - 1)) - -/* A.10.3.1 Up/Down-mix Processing Unit Controls Selectors */ -#define UAC_UD_ENABLE 0x01 -#define UAC_UD_MODE_SELECT 0x02 - -/* A.10.3.2 Dolby Prologic (tm) Processing Unit Controls Selectors */ -#define UAC_DP_ENABLE 0x01 -#define UAC_DP_MODE_SELECT 0x02 - -/* A.10.3.3 3D Stereo Extender Processing Unit Control Selectors */ -#define UAC_3D_ENABLE 0x01 -#define UAC_3D_SPACE 0x02 - -/* A.10.3.4 Reverberation Processing Unit Control Selectors */ -#define UAC_REVERB_ENABLE 0x01 -#define UAC_REVERB_LEVEL 0x02 -#define UAC_REVERB_TIME 0x03 -#define UAC_REVERB_FEEDBACK 0x04 - -/* A.10.3.5 Chorus Processing Unit Control Selectors */ -#define UAC_CHORUS_ENABLE 0x01 -#define UAC_CHORUS_LEVEL 0x02 -#define UAC_CHORUS_RATE 0x03 -#define UAC_CHORUS_DEPTH 0x04 - -/* A.10.3.6 Dynamic Range Compressor Unit Control Selectors */ -#define UAC_DCR_ENABLE 0x01 -#define UAC_DCR_RATE 0x02 -#define UAC_DCR_MAXAMPL 0x03 -#define UAC_DCR_THRESHOLD 0x04 -#define UAC_DCR_ATTACK_TIME 0x05 -#define UAC_DCR_RELEASE_TIME 0x06 - -/* A.10.4 Extension Unit Control Selectors */ -#define UAC_XU_ENABLE 0x01 - -/* MIDI - A.1 MS Class-Specific Interface Descriptor Subtypes */ -#define UAC_MS_HEADER 0x01 -#define UAC_MIDI_IN_JACK 0x02 -#define UAC_MIDI_OUT_JACK 0x03 - -/* MIDI - A.1 MS Class-Specific Endpoint Descriptor Subtypes */ -#define UAC_MS_GENERAL 0x01 - -/* Terminals - 2.1 USB Terminal Types */ -#define UAC_TERMINAL_UNDEFINED 0x100 -#define UAC_TERMINAL_STREAMING 0x101 -#define UAC_TERMINAL_VENDOR_SPEC 0x1FF - -/* Terminal Control Selectors */ -/* 4.3.2 Class-Specific AC Interface Descriptor */ -struct uac1_ac_header_descriptor { - __u8 bLength; /* 8 + n */ - __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ - __u8 bDescriptorSubtype; /* UAC_MS_HEADER */ - __le16 bcdADC; /* 0x0100 */ - __le16 wTotalLength; /* includes Unit and Terminal desc. */ - __u8 bInCollection; /* n */ - __u8 baInterfaceNr[]; /* [n] */ -} __attribute__ ((packed)); - -#define UAC_DT_AC_HEADER_SIZE(n) (8 + (n)) - -/* As above, but more useful for defining your own descriptors: */ -#define DECLARE_UAC_AC_HEADER_DESCRIPTOR(n) \ -struct uac1_ac_header_descriptor_##n { \ - __u8 bLength; \ - __u8 bDescriptorType; \ - __u8 bDescriptorSubtype; \ - __le16 bcdADC; \ - __le16 wTotalLength; \ - __u8 bInCollection; \ - __u8 baInterfaceNr[n]; \ -} __attribute__ ((packed)) - -/* 4.3.2.1 Input Terminal Descriptor */ -struct uac_input_terminal_descriptor { - __u8 bLength; /* in bytes: 12 */ - __u8 bDescriptorType; /* CS_INTERFACE descriptor type */ - __u8 bDescriptorSubtype; /* INPUT_TERMINAL descriptor subtype */ - __u8 bTerminalID; /* Constant uniquely terminal ID */ - __le16 wTerminalType; /* USB Audio Terminal Types */ - __u8 bAssocTerminal; /* ID of the Output Terminal associated */ - __u8 bNrChannels; /* Number of logical output channels */ - __le16 wChannelConfig; - __u8 iChannelNames; - __u8 iTerminal; -} __attribute__ ((packed)); - -#define UAC_DT_INPUT_TERMINAL_SIZE 12 - -/* Terminals - 2.2 Input Terminal Types */ -#define UAC_INPUT_TERMINAL_UNDEFINED 0x200 -#define UAC_INPUT_TERMINAL_MICROPHONE 0x201 -#define UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE 0x202 -#define UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE 0x203 -#define UAC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE 0x204 -#define UAC_INPUT_TERMINAL_MICROPHONE_ARRAY 0x205 -#define UAC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY 0x206 - -/* Terminals - control selectors */ - -#define UAC_TERMINAL_CS_COPY_PROTECT_CONTROL 0x01 - -/* 4.3.2.2 Output Terminal Descriptor */ -struct uac1_output_terminal_descriptor { - __u8 bLength; /* in bytes: 9 */ - __u8 bDescriptorType; /* CS_INTERFACE descriptor type */ - __u8 bDescriptorSubtype; /* OUTPUT_TERMINAL descriptor subtype */ - __u8 bTerminalID; /* Constant uniquely terminal ID */ - __le16 wTerminalType; /* USB Audio Terminal Types */ - __u8 bAssocTerminal; /* ID of the Input Terminal associated */ - __u8 bSourceID; /* ID of the connected Unit or Terminal*/ - __u8 iTerminal; -} __attribute__ ((packed)); - -#define UAC_DT_OUTPUT_TERMINAL_SIZE 9 - -/* Terminals - 2.3 Output Terminal Types */ -#define UAC_OUTPUT_TERMINAL_UNDEFINED 0x300 -#define UAC_OUTPUT_TERMINAL_SPEAKER 0x301 -#define UAC_OUTPUT_TERMINAL_HEADPHONES 0x302 -#define UAC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO 0x303 -#define UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER 0x304 -#define UAC_OUTPUT_TERMINAL_ROOM_SPEAKER 0x305 -#define UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER 0x306 -#define UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER 0x307 - -/* Terminals - 2.4 Bi-directional Terminal Types */ -#define UAC_BIDIR_TERMINAL_UNDEFINED 0x400 -#define UAC_BIDIR_TERMINAL_HANDSET 0x401 -#define UAC_BIDIR_TERMINAL_HEADSET 0x402 -#define UAC_BIDIR_TERMINAL_SPEAKER_PHONE 0x403 -#define UAC_BIDIR_TERMINAL_ECHO_SUPPRESSING 0x404 -#define UAC_BIDIR_TERMINAL_ECHO_CANCELING 0x405 - -/* Set bControlSize = 2 as default setting */ -#define UAC_DT_FEATURE_UNIT_SIZE(ch) (7 + ((ch) + 1) * 2) - -/* As above, but more useful for defining your own descriptors: */ -#define DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(ch) \ -struct uac_feature_unit_descriptor_##ch { \ - __u8 bLength; \ - __u8 bDescriptorType; \ - __u8 bDescriptorSubtype; \ - __u8 bUnitID; \ - __u8 bSourceID; \ - __u8 bControlSize; \ - __le16 bmaControls[ch + 1]; \ - __u8 iFeature; \ -} __attribute__ ((packed)) - -/* 4.3.2.3 Mixer Unit Descriptor */ -struct uac_mixer_unit_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubtype; - __u8 bUnitID; - __u8 bNrInPins; - __u8 baSourceID[]; -} __attribute__ ((packed)); - -static inline __u8 uac_mixer_unit_bNrChannels(struct uac_mixer_unit_descriptor *desc) -{ - return desc->baSourceID[desc->bNrInPins]; -} - -static inline __u32 uac_mixer_unit_wChannelConfig(struct uac_mixer_unit_descriptor *desc, - int protocol) -{ - if (protocol == UAC_VERSION_1) - return (desc->baSourceID[desc->bNrInPins + 2] << 8) | - desc->baSourceID[desc->bNrInPins + 1]; - else - return (desc->baSourceID[desc->bNrInPins + 4] << 24) | - (desc->baSourceID[desc->bNrInPins + 3] << 16) | - (desc->baSourceID[desc->bNrInPins + 2] << 8) | - (desc->baSourceID[desc->bNrInPins + 1]); -} - -static inline __u8 uac_mixer_unit_iChannelNames(struct uac_mixer_unit_descriptor *desc, - int protocol) -{ - return (protocol == UAC_VERSION_1) ? - desc->baSourceID[desc->bNrInPins + 3] : - desc->baSourceID[desc->bNrInPins + 5]; -} - -static inline __u8 *uac_mixer_unit_bmControls(struct uac_mixer_unit_descriptor *desc, - int protocol) -{ - switch (protocol) { - case UAC_VERSION_1: - return &desc->baSourceID[desc->bNrInPins + 4]; - case UAC_VERSION_2: - return &desc->baSourceID[desc->bNrInPins + 6]; - case UAC_VERSION_3: - return &desc->baSourceID[desc->bNrInPins + 2]; - default: - return NULL; - } -} - -static inline __u16 uac3_mixer_unit_wClusterDescrID(struct uac_mixer_unit_descriptor *desc) -{ - return (desc->baSourceID[desc->bNrInPins + 1] << 8) | - desc->baSourceID[desc->bNrInPins]; -} - -static inline __u8 uac_mixer_unit_iMixer(struct uac_mixer_unit_descriptor *desc) -{ - __u8 *raw = (__u8 *) desc; - return raw[desc->bLength - 1]; -} - -/* 4.3.2.4 Selector Unit Descriptor */ -struct uac_selector_unit_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubtype; - __u8 bUintID; - __u8 bNrInPins; - __u8 baSourceID[]; -} __attribute__ ((packed)); - -static inline __u8 uac_selector_unit_iSelector(struct uac_selector_unit_descriptor *desc) -{ - __u8 *raw = (__u8 *) desc; - return raw[desc->bLength - 1]; -} -#if UAC_USE_FEATURE_UNIT -/* 4.3.2.5 Feature Unit Descriptor */ -struct uac_feature_unit_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubtype; - __u8 bUnitID; - __u8 bSourceID; - __u8 bControlSize; - __u8 bmaControls[0]; /* variable length */ -} __attribute__((packed)); - -static inline __u8 uac_feature_unit_iFeature(struct uac_feature_unit_descriptor *desc) -{ - __u8 *raw = (__u8 *) desc; - return raw[desc->bLength - 1]; -} -#endif -/* 4.3.2.6 Processing Unit Descriptors */ -struct uac_processing_unit_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubtype; - __u8 bUnitID; - __le16 wProcessType; - __u8 bNrInPins; - __u8 baSourceID[]; -} __attribute__ ((packed)); - -static inline __u8 uac_processing_unit_bNrChannels(struct uac_processing_unit_descriptor *desc) -{ - return desc->baSourceID[desc->bNrInPins]; -} - -static inline __u32 uac_processing_unit_wChannelConfig(struct uac_processing_unit_descriptor *desc, - int protocol) -{ - if (protocol == UAC_VERSION_1) - return (desc->baSourceID[desc->bNrInPins + 2] << 8) | - desc->baSourceID[desc->bNrInPins + 1]; - else - return (desc->baSourceID[desc->bNrInPins + 4] << 24) | - (desc->baSourceID[desc->bNrInPins + 3] << 16) | - (desc->baSourceID[desc->bNrInPins + 2] << 8) | - (desc->baSourceID[desc->bNrInPins + 1]); -} - -static inline __u8 uac_processing_unit_iChannelNames(struct uac_processing_unit_descriptor *desc, - int protocol) -{ - return (protocol == UAC_VERSION_1) ? - desc->baSourceID[desc->bNrInPins + 3] : - desc->baSourceID[desc->bNrInPins + 5]; -} - -static inline __u8 uac_processing_unit_bControlSize(struct uac_processing_unit_descriptor *desc, - int protocol) -{ - switch (protocol) { - case UAC_VERSION_1: - return desc->baSourceID[desc->bNrInPins + 4]; - case UAC_VERSION_2: - return 2; /* in UAC2, this value is constant */ - case UAC_VERSION_3: - return 4; /* in UAC3, this value is constant */ - default: - return 1; - } -} - -static inline __u8 *uac_processing_unit_bmControls(struct uac_processing_unit_descriptor *desc, - int protocol) -{ - switch (protocol) { - case UAC_VERSION_1: - return &desc->baSourceID[desc->bNrInPins + 5]; - case UAC_VERSION_2: - return &desc->baSourceID[desc->bNrInPins + 6]; - case UAC_VERSION_3: - return &desc->baSourceID[desc->bNrInPins + 2]; - default: - return NULL; - } -} - -static inline __u8 uac_processing_unit_iProcessing(struct uac_processing_unit_descriptor *desc, - int protocol) -{ - __u8 control_size = uac_processing_unit_bControlSize(desc, protocol); - - switch (protocol) { - case UAC_VERSION_1: - case UAC_VERSION_2: - default: - return *(uac_processing_unit_bmControls(desc, protocol) - + control_size); - case UAC_VERSION_3: - return 0; /* UAC3 does not have this field */ - } -} - -static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc, - int protocol) -{ - __u8 control_size = uac_processing_unit_bControlSize(desc, protocol); - - switch (protocol) { - case UAC_VERSION_1: - case UAC_VERSION_2: - default: - return uac_processing_unit_bmControls(desc, protocol) - + control_size + 1; - case UAC_VERSION_3: - return uac_processing_unit_bmControls(desc, protocol) - + control_size; - } -} - -/* - * Extension Unit (XU) has almost compatible layout with Processing Unit, but - * on UAC2, it has a different bmControls size (bControlSize); it's 1 byte for - * XU while 2 bytes for PU. The last iExtension field is a one-byte index as - * well as iProcessing field of PU. - */ -static inline __u8 uac_extension_unit_bControlSize(struct uac_processing_unit_descriptor *desc, - int protocol) -{ - switch (protocol) { - case UAC_VERSION_1: - return desc->baSourceID[desc->bNrInPins + 4]; - case UAC_VERSION_2: - return 1; /* in UAC2, this value is constant */ - case UAC_VERSION_3: - return 4; /* in UAC3, this value is constant */ - default: - return 1; - } -} - -static inline __u8 uac_extension_unit_iExtension(struct uac_processing_unit_descriptor *desc, - int protocol) -{ - __u8 control_size = uac_extension_unit_bControlSize(desc, protocol); - - switch (protocol) { - case UAC_VERSION_1: - case UAC_VERSION_2: - default: - return *(uac_processing_unit_bmControls(desc, protocol) - + control_size); - case UAC_VERSION_3: - return 0; /* UAC3 does not have this field */ - } -} - -/* 4.5.2 Class-Specific AS Interface Descriptor */ -struct uac1_as_header_descriptor { - __u8 bLength; /* in bytes: 7 */ - __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ - __u8 bDescriptorSubtype; /* AS_GENERAL */ - __u8 bTerminalLink; /* Terminal ID of connected Terminal */ - __u8 bDelay; /* Delay introduced by the data path */ - __le16 wFormatTag; /* The Audio Data Format */ -} __attribute__ ((packed)); - -#define UAC_DT_AS_HEADER_SIZE 7 - -/* Formats - A.1.1 Audio Data Format Type I Codes */ -#define UAC_FORMAT_TYPE_I_UNDEFINED 0x0 -#define UAC_FORMAT_TYPE_I_PCM 0x1 -#define UAC_FORMAT_TYPE_I_PCM8 0x2 -#define UAC_FORMAT_TYPE_I_IEEE_FLOAT 0x3 -#define UAC_FORMAT_TYPE_I_ALAW 0x4 -#define UAC_FORMAT_TYPE_I_MULAW 0x5 - -struct uac_format_type_i_continuous_descriptor { - __u8 bLength; /* in bytes: 8 + (ns * 3) */ - __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ - __u8 bDescriptorSubtype; /* FORMAT_TYPE */ - __u8 bFormatType; /* FORMAT_TYPE_1 */ - __u8 bNrChannels; /* physical channels in the stream */ - __u8 bSubframeSize; /* */ - __u8 bBitResolution; - __u8 bSamFreqType; - __u8 tLowerSamFreq[3]; - __u8 tUpperSamFreq[3]; -} __attribute__ ((packed)); - -#define UAC_FORMAT_TYPE_I_CONTINUOUS_DESC_SIZE 14 - -struct uac_format_type_i_discrete_descriptor { - __u8 bLength; /* in bytes: 8 + (ns * 3) */ - __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ - __u8 bDescriptorSubtype; /* FORMAT_TYPE */ - __u8 bFormatType; /* FORMAT_TYPE_1 */ - __u8 bNrChannels; /* physical channels in the stream */ - __u8 bSubframeSize; /* */ - __u8 bBitResolution; - __u8 bSamFreqType; - __u8 tSamFreq[][3]; -} __attribute__ ((packed)); - -#define DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(n) \ -struct uac_format_type_i_discrete_descriptor_##n { \ - __u8 bLength; \ - __u8 bDescriptorType; \ - __u8 bDescriptorSubtype; \ - __u8 bFormatType; \ - __u8 bNrChannels; \ - __u8 bSubframeSize; \ - __u8 bBitResolution; \ - __u8 bSamFreqType; \ - __u8 tSamFreq[n][3]; \ -} __attribute__ ((packed)) - -#define UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(n) (8 + (n * 3)) - -struct uac_format_type_i_ext_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubtype; - __u8 bFormatType; - __u8 bSubslotSize; - __u8 bBitResolution; - __u8 bHeaderLength; - __u8 bControlSize; - __u8 bSideBandProtocol; -} __attribute__((packed)); - -/* Formats - Audio Data Format Type I Codes */ - -#define UAC_FORMAT_TYPE_II_MPEG 0x1001 -#define UAC_FORMAT_TYPE_II_AC3 0x1002 - -struct uac_format_type_ii_discrete_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubtype; - __u8 bFormatType; - __le16 wMaxBitRate; - __le16 wSamplesPerFrame; - __u8 bSamFreqType; - __u8 tSamFreq[][3]; -} __attribute__((packed)); - -struct uac_format_type_ii_ext_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubtype; - __u8 bFormatType; - __le16 wMaxBitRate; - __le16 wSamplesPerFrame; - __u8 bHeaderLength; - __u8 bSideBandProtocol; -} __attribute__((packed)); - -/* type III */ -#define UAC_FORMAT_TYPE_III_IEC1937_AC3 0x2001 -#define UAC_FORMAT_TYPE_III_IEC1937_MPEG1_LAYER1 0x2002 -#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_NOEXT 0x2003 -#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_EXT 0x2004 -#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER1_LS 0x2005 -#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER23_LS 0x2006 - -/* Formats - A.2 Format Type Codes */ -#define UAC_FORMAT_TYPE_UNDEFINED 0x0 -#define UAC_FORMAT_TYPE_I 0x1 -#define UAC_FORMAT_TYPE_II 0x2 -#define UAC_FORMAT_TYPE_III 0x3 -#define UAC_EXT_FORMAT_TYPE_I 0x81 -#define UAC_EXT_FORMAT_TYPE_II 0x82 -#define UAC_EXT_FORMAT_TYPE_III 0x83 - -struct uac_iso_endpoint_descriptor { - __u8 bLength; /* in bytes: 7 */ - __u8 bDescriptorType; /* USB_DT_CS_ENDPOINT */ - __u8 bDescriptorSubtype; /* EP_GENERAL */ - __u8 bmAttributes; - __u8 bLockDelayUnits; - __le16 wLockDelay; -} __attribute__((packed)); -#define UAC_ISO_ENDPOINT_DESC_SIZE 7 - -#define UAC_EP_CS_ATTR_SAMPLE_RATE 0x01 -#define UAC_EP_CS_ATTR_PITCH_CONTROL 0x02 -#define UAC_EP_CS_ATTR_FILL_MAX 0x80 - -/* status word format (3.7.1.1) */ - -#define UAC1_STATUS_TYPE_ORIG_MASK 0x0f -#define UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF 0x0 -#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_IF 0x1 -#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_EP 0x2 - -#define UAC1_STATUS_TYPE_IRQ_PENDING (1 << 7) -#define UAC1_STATUS_TYPE_MEM_CHANGED (1 << 6) - -struct uac1_status_word { - __u8 bStatusType; - __u8 bOriginator; -} __attribute__((packed)); - - -#endif /* _UAPI__LINUX_USB_AUDIO_H */ diff --git a/components/drivers/usb/usbdevice/class/audio_mic.c b/components/drivers/usb/usbdevice/class/audio_mic.c index 760c055d10..81170b8a72 100644 --- a/components/drivers/usb/usbdevice/class/audio_mic.c +++ b/components/drivers/usb/usbdevice/class/audio_mic.c @@ -11,7 +11,8 @@ #include <rthw.h> #include <rtdevice.h> #include "drivers/usb_device.h" -#include "audio.h" + +#include "uaudioreg.h" #define DBG_TAG "usbd.audio.mic" #define DBG_LVL DBG_INFO @@ -35,6 +36,7 @@ #define EVENT_RECORD_STOP (1 << 1) #define EVENT_RECORD_DATA (1 << 2) +#define MIC_INTF_STR_INDEX 8 /* * uac mic descriptor define */ @@ -45,9 +47,6 @@ #define UAC_MAX_PACKET_SIZE 64 #define UAC_EP_MAX_PACKET_SIZE 32 #define UAC_CHANNEL_NUM RECORD_CHANNEL -#define UAC_INTR_NUM 1 -#define UAC_CH_NUM 1 -#define UAC_FORMAT_NUM 1 struct uac_ac_descriptor { @@ -55,21 +54,21 @@ struct uac_ac_descriptor struct uiad_descriptor iad_desc; #endif struct uinterface_descriptor intf_desc; - DECLARE_UAC_AC_HEADER_DESCRIPTOR(UAC_INTR_NUM) hdr_desc; - struct uac_input_terminal_descriptor it_desc; - struct uac1_output_terminal_descriptor ot_desc; + struct usb_audio_control_descriptor hdr_desc; + struct usb_audio_input_terminal it_desc; + struct usb_audio_output_terminal ot_desc; #if UAC_USE_FEATURE_UNIT - DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(UAC_CH_NUM) feature_unit_desc; + struct usb_audio_feature_unit feature_unit_desc; #endif }; struct uac_as_descriptor { struct uinterface_descriptor intf_desc; - struct uac1_as_header_descriptor hdr_desc; - DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(UAC_FORMAT_NUM) format_type_desc; + struct usb_audio_streaming_interface_descriptor hdr_desc; + struct usb_audio_streaming_type1_descriptor format_type_desc; struct uendpoint_descriptor ep_desc; - struct uac_iso_endpoint_descriptor as_ep_desc; + struct usb_audio_streaming_endpoint_descriptor as_ep_desc; }; /* @@ -128,7 +127,7 @@ const static char *_ustring[] = { "Language", "RT-Thread Team.", - "Microphone", + "RT-Thread Audio Microphone", "32021919830108", "Configuration", "Interface", @@ -160,13 +159,17 @@ static struct uac_ac_descriptor ac_desc = USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, 0x00, +#ifdef RT_USB_DEVICE_COMPOSITE + MIC_INTF_STR_INDEX, +#else 0x00, +#endif }, /* Header Descriptor */ { - UAC_DT_AC_HEADER_SIZE(UAC_INTR_NUM), + sizeof(struct usb_audio_control_descriptor), UAC_CS_INTERFACE, - UAC_HEADER, + UDESCSUB_AC_HEADER, 0x0100, /* Version: 1.00 */ 0x001E, /* Total length: 30 */ 0x01, /* Total number of interfaces: 1 */ @@ -174,9 +177,9 @@ static struct uac_ac_descriptor ac_desc = }, /* Input Terminal Descriptor */ { - UAC_DT_INPUT_TERMINAL_SIZE, + sizeof(struct usb_audio_input_terminal), UAC_CS_INTERFACE, - UAC_INPUT_TERMINAL, + UDESCSUB_AC_INPUT, 0x01, /* Terminal ID: 1 */ 0x0201, /* Terminal Type: Microphone (0x0201) */ 0x00, /* Assoc Terminal: 0 */ @@ -187,9 +190,9 @@ static struct uac_ac_descriptor ac_desc = }, /* Output Terminal Descriptor */ { - UAC_DT_OUTPUT_TERMINAL_SIZE, + sizeof(struct usb_audio_output_terminal), UAC_CS_INTERFACE, - UAC_OUTPUT_TERMINAL, + UDESCSUB_AC_OUTPUT, 0x02, /* Terminal ID: 2 */ 0x0101, /* Terminal Type: USB Streaming (0x0101) */ 0x00, /* Assoc Terminal: 0 */ @@ -199,11 +202,12 @@ static struct uac_ac_descriptor ac_desc = #if UAC_USE_FEATURE_UNIT /* Feature unit Descriptor */ { - UAC_DT_FEATURE_UNIT_SIZE(UAC_CH_NUM), + sizeof(struct usb_audio_feature_unit), UAC_CS_INTERFACE, - UAC_FEATURE_UNIT, + UDESCSUB_AC_FEATURE, 0x02, - 0x0101, + 0x01, + 0x01, 0x00, 0x01, }, @@ -241,19 +245,19 @@ static struct uac_as_descriptor as_desc = }, /* General AS Descriptor */ { - UAC_DT_AS_HEADER_SIZE, + sizeof(struct usb_audio_streaming_interface_descriptor), UAC_CS_INTERFACE, - UAC_AS_GENERAL, + AS_GENERAL, 0x02, /* Terminal ID: 2 */ 0x01, /* Interface delay in frames: 1 */ - UAC_FORMAT_TYPE_I_PCM, + UA_FMT_PCM, }, /* Format type i Descriptor */ { - UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(UAC_FORMAT_NUM), + sizeof(struct usb_audio_streaming_type1_descriptor), UAC_CS_INTERFACE, - UAC_FORMAT_TYPE, - UAC_FORMAT_TYPE_I, + FORMAT_TYPE, + FORMAT_TYPE_I, UAC_CHANNEL_NUM, 2, /* Subframe Size: 2 */ RESOLUTION_BITS, @@ -271,9 +275,9 @@ static struct uac_as_descriptor as_desc = }, /* AS Endpoint Descriptor */ { - UAC_ISO_ENDPOINT_DESC_SIZE, + sizeof(struct usb_audio_streaming_endpoint_descriptor), UAC_CS_ENDPOINT, - UAC_MS_GENERAL, + AS_GENERAL, }, }; @@ -471,9 +475,9 @@ static rt_err_t _uac_descriptor_config(struct uac_ac_descriptor *ac, static rt_err_t _uac_samplerate_config(struct uac_as_descriptor *as, rt_uint32_t samplerate) { - as->format_type_desc.tSamFreq[0][2] = samplerate >> 16 & 0xff; - as->format_type_desc.tSamFreq[0][1] = samplerate >> 8 & 0xff; - as->format_type_desc.tSamFreq[0][0] = samplerate & 0xff; + as->format_type_desc.tSamFreq[0 * 3 + 2] = samplerate >> 16 & 0xff; + as->format_type_desc.tSamFreq[0 * 3 + 1] = samplerate >> 8 & 0xff; + as->format_type_desc.tSamFreq[0 * 3 + 0] = samplerate & 0xff; return RT_EOK; } @@ -495,9 +499,12 @@ ufunction_t rt_usbd_function_uac_mic_create(udevice_t device) /* parameter check */ RT_ASSERT(device != RT_NULL); +#ifdef RT_USB_DEVICE_COMPOSITE + rt_usbd_device_set_interface_string(device, MIC_INTF_STR_INDEX, _ustring[2]); +#else /* set usb device string description */ rt_usbd_device_set_string(device, _ustring); - +#endif /* create a uac function */ func = rt_usbd_function_new(device, &dev_desc, &ops); //not support HS diff --git a/components/drivers/usb/usbdevice/class/audio_speaker.c b/components/drivers/usb/usbdevice/class/audio_speaker.c index c8bbb9cb5e..6148478c02 100644 --- a/components/drivers/usb/usbdevice/class/audio_speaker.c +++ b/components/drivers/usb/usbdevice/class/audio_speaker.c @@ -11,7 +11,9 @@ #include <rthw.h> #include <rtdevice.h> #include "drivers/usb_device.h" -#include "audio.h" + +#define AUFMT_MAX_FREQUENCIES 1 +#include "uaudioreg.h" #define DBG_TAG "usbd.audio.speaker" #define DBG_LVL DBG_INFO @@ -35,6 +37,7 @@ #define EVENT_AUDIO_STOP (1 << 1) #define EVENT_AUDIO_DATA (1 << 2) +#define SPK_INTF_STR_INDEX 9 /* * uac speaker descriptor define */ @@ -45,9 +48,6 @@ #define UAC_MAX_PACKET_SIZE 64 #define UAC_EP_MAX_PACKET_SIZE 32 #define UAC_CHANNEL_NUM AUDIO_CHANNEL -#define UAC_INTR_NUM 1 -#define UAC_CH_NUM 1 -#define UAC_FORMAT_NUM 1 struct uac_ac_descriptor { @@ -55,21 +55,21 @@ struct uac_ac_descriptor struct uiad_descriptor iad_desc; #endif struct uinterface_descriptor intf_desc; - DECLARE_UAC_AC_HEADER_DESCRIPTOR(UAC_INTR_NUM) hdr_desc; - struct uac_input_terminal_descriptor it_desc; - struct uac1_output_terminal_descriptor ot_desc; + struct usb_audio_control_descriptor hdr_desc; + struct usb_audio_input_terminal it_desc; + struct usb_audio_output_terminal ot_desc; #if UAC_USE_FEATURE_UNIT - DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(UAC_CH_NUM) feature_unit_desc; + struct usb_audio_feature_unit feature_unit_desc; #endif }; struct uac_as_descriptor { struct uinterface_descriptor intf_desc; - struct uac1_as_header_descriptor hdr_desc; - DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(UAC_FORMAT_NUM) format_type_desc; + struct usb_audio_streaming_interface_descriptor hdr_desc; + struct usb_audio_streaming_type1_descriptor format_type_desc; struct uendpoint_descriptor ep_desc; - struct uac_iso_endpoint_descriptor as_ep_desc; + struct usb_audio_streaming_endpoint_descriptor as_ep_desc; }; /* @@ -128,7 +128,7 @@ const static char *_ustring[] = { "Language", "RT-Thread Team.", - "RT-Thread Speaker", + "RT-Thread Audio Speaker", "32021919830108", "Configuration", "Interface", @@ -160,13 +160,17 @@ static struct uac_ac_descriptor ac_desc = USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, 0x00, +#ifdef RT_USB_DEVICE_COMPOSITE + SPK_INTF_STR_INDEX, +#else 0x00, +#endif }, /* Header Descriptor */ { - UAC_DT_AC_HEADER_SIZE(UAC_INTR_NUM), + sizeof(struct usb_audio_control_descriptor), UAC_CS_INTERFACE, - UAC_HEADER, + UDESCSUB_AC_HEADER, 0x0100, /* Version: 1.00 */ 0x0027, /* Total length: 39 */ 0x01, /* Total number of interfaces: 1 */ @@ -174,9 +178,9 @@ static struct uac_ac_descriptor ac_desc = }, /* Input Terminal Descriptor */ { - UAC_DT_INPUT_TERMINAL_SIZE, + sizeof(struct usb_audio_input_terminal), UAC_CS_INTERFACE, - UAC_INPUT_TERMINAL, + UDESCSUB_AC_INPUT, 0x01, /* Terminal ID: 1 */ 0x0101, /* Terminal Type: USB Streaming (0x0101) */ 0x00, /* Assoc Terminal: 0 */ @@ -187,9 +191,9 @@ static struct uac_ac_descriptor ac_desc = }, /* Output Terminal Descriptor */ { - UAC_DT_OUTPUT_TERMINAL_SIZE, + sizeof(struct usb_audio_output_terminal), UAC_CS_INTERFACE, - UAC_OUTPUT_TERMINAL, + UDESCSUB_AC_OUTPUT, 0x02, /* Terminal ID: 2 */ 0x0302, /* Terminal Type: Headphones (0x0302) */ 0x00, /* Assoc Terminal: 0 */ @@ -241,19 +245,19 @@ static struct uac_as_descriptor as_desc = }, /* General AS Descriptor */ { - UAC_DT_AS_HEADER_SIZE, + sizeof(struct usb_audio_streaming_interface_descriptor), UAC_CS_INTERFACE, - UAC_AS_GENERAL, + AS_GENERAL, 0x01, /* Terminal ID: 1 */ 0x01, /* Interface delay in frames: 1 */ - UAC_FORMAT_TYPE_I_PCM, + UA_FMT_PCM, }, /* Format type i Descriptor */ { - UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(UAC_FORMAT_NUM), + sizeof(struct usb_audio_streaming_type1_descriptor), UAC_CS_INTERFACE, - UAC_FORMAT_TYPE, - UAC_FORMAT_TYPE_I, + FORMAT_TYPE, + FORMAT_TYPE_I, UAC_CHANNEL_NUM, 2, /* Subframe Size: 2 */ RESOLUTION_BITS, @@ -271,9 +275,9 @@ static struct uac_as_descriptor as_desc = }, /* AS Endpoint Descriptor */ { - UAC_ISO_ENDPOINT_DESC_SIZE, + sizeof(struct usb_audio_streaming_endpoint_descriptor), UAC_CS_ENDPOINT, - UAC_MS_GENERAL, + AS_GENERAL, }, }; @@ -472,9 +476,9 @@ static rt_err_t _uac_descriptor_config(struct uac_ac_descriptor *ac, static rt_err_t _uac_samplerate_config(struct uac_as_descriptor *as, rt_uint32_t samplerate) { - as->format_type_desc.tSamFreq[0][2] = samplerate >> 16 & 0xff; - as->format_type_desc.tSamFreq[0][1] = samplerate >> 8 & 0xff; - as->format_type_desc.tSamFreq[0][0] = samplerate & 0xff; + as->format_type_desc.tSamFreq[0 * 3 + 2] = samplerate >> 16 & 0xff; + as->format_type_desc.tSamFreq[0 * 3 + 1] = samplerate >> 8 & 0xff; + as->format_type_desc.tSamFreq[0 * 3 + 0] = samplerate & 0xff; return RT_EOK; } @@ -496,9 +500,12 @@ ufunction_t rt_usbd_function_uac_speaker_create(udevice_t device) /* parameter check */ RT_ASSERT(device != RT_NULL); +#ifdef RT_USB_DEVICE_COMPOSITE + rt_usbd_device_set_interface_string(device, SPK_INTF_STR_INDEX, _ustring[2]); +#else /* set usb device string description */ rt_usbd_device_set_string(device, _ustring); - +#endif /* create a uac function */ func = rt_usbd_function_new(device, &dev_desc, &ops); //not support HS diff --git a/components/drivers/usb/usbdevice/class/cdc_vcom.c b/components/drivers/usb/usbdevice/class/cdc_vcom.c index 996a12c308..3564330578 100644 --- a/components/drivers/usb/usbdevice/class/cdc_vcom.c +++ b/components/drivers/usb/usbdevice/class/cdc_vcom.c @@ -20,6 +20,7 @@ #ifdef RT_USB_DEVICE_CDC +#define VCOM_INTF_STR_INDEX 5 #ifdef RT_VCOM_TX_TIMEOUT #define VCOM_TX_TIMEOUT RT_VCOM_TX_TIMEOUT #else /*!RT_VCOM_TX_TIMEOUT*/ @@ -151,7 +152,11 @@ const static struct ucdc_comm_descriptor _comm_desc = USB_CDC_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_PROTOCOL_V25TER, - 0x00, +#ifdef RT_USB_DEVICE_COMPOSITE + VCOM_INTF_STR_INDEX, +#else + 0, +#endif }, /* Header Functional Descriptor */ { @@ -582,9 +587,12 @@ ufunction_t rt_usbd_function_cdc_create(udevice_t device) rt_memset(serno, 0, _SER_NO_LEN + 1); rt_memcpy(serno, _SER_NO, rt_strlen(_SER_NO)); } +#ifdef RT_USB_DEVICE_COMPOSITE + rt_usbd_device_set_interface_string(device, VCOM_INTF_STR_INDEX, _ustring[2]); +#else /* set usb device string description */ rt_usbd_device_set_string(device, _ustring); - +#endif /* create a cdc function */ func = rt_usbd_function_new(device, &dev_desc, &ops); diff --git a/components/drivers/usb/usbdevice/class/ecm.c b/components/drivers/usb/usbdevice/class/ecm.c index 1550f8e1e2..d6d98478f8 100644 --- a/components/drivers/usb/usbdevice/class/ecm.c +++ b/components/drivers/usb/usbdevice/class/ecm.c @@ -24,6 +24,7 @@ #define USB_ETH_MTU 1514 #endif #define MAX_ADDR_LEN 6 +#define ECM_INTF_STR_INDEX 10 struct rt_ecm_eth { @@ -96,7 +97,11 @@ const static struct ucdc_eth_descriptor _comm_desc = USB_CDC_CLASS_COMM, USB_CDC_SUBCLASS_ETH, USB_CDC_PROTOCOL_NONE, +#ifdef RT_USB_DEVICE_COMPOSITE + ECM_INTF_STR_INDEX, +#else 0x00, +#endif }, /* Header Functional Descriptor */ { @@ -560,8 +565,11 @@ ufunction_t rt_usbd_function_ecm_create(udevice_t device) RT_ASSERT(device != RT_NULL); /* set usb device string description */ +#ifdef RT_USB_DEVICE_COMPOSITE + rt_usbd_device_set_interface_string(device, ECM_INTF_STR_INDEX, _ustring[2]); +#else rt_usbd_device_set_string(device, _ustring); - +#endif /* create a cdc class */ cdc = rt_usbd_function_new(device, &_dev_desc, &ops); rt_usbd_device_set_qualifier(device, &dev_qualifier); diff --git a/components/drivers/usb/usbdevice/class/hid.c b/components/drivers/usb/usbdevice/class/hid.c index 5023be46eb..ddd4cb93a8 100644 --- a/components/drivers/usb/usbdevice/class/hid.c +++ b/components/drivers/usb/usbdevice/class/hid.c @@ -17,7 +17,7 @@ #include "hid.h" #ifdef RT_USB_DEVICE_HID - +#define HID_INTF_STR_INDEX 7 struct hid_s { struct rt_device parent; @@ -318,8 +318,12 @@ const static struct uhid_comm_descriptor _hid_comm_desc = #else USB_HID_PROTOCOL_MOUSE, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ #endif - 0, /* iInterface: Index of string descriptor */ - }, +#ifdef RT_USB_DEVICE_COMPOSITE + HID_INTF_STR_INDEX, /* iInterface: Index of string descriptor */ +#else + 0, +#endif + }, /* HID Descriptor */ { @@ -685,8 +689,11 @@ ufunction_t rt_usbd_function_hid_create(udevice_t device) RT_ASSERT(device != RT_NULL); /* set usb device string description */ +#ifdef RT_USB_DEVICE_COMPOSITE + rt_usbd_device_set_interface_string(device, HID_INTF_STR_INDEX, _ustring[2]); +#else rt_usbd_device_set_string(device, _ustring); - +#endif /* create a cdc function */ func = rt_usbd_function_new(device, &_dev_desc, &ops); diff --git a/components/drivers/usb/usbdevice/class/mstorage.c b/components/drivers/usb/usbdevice/class/mstorage.c index f14f6b0c24..97a189834b 100644 --- a/components/drivers/usb/usbdevice/class/mstorage.c +++ b/components/drivers/usb/usbdevice/class/mstorage.c @@ -18,8 +18,8 @@ #ifdef RT_USING_DFS_MNTTABLE #include "dfs_fs.h" #endif - #ifdef RT_USB_DEVICE_MSTORAGE +#define MSTRORAGE_INTF_STR_INDEX 11 enum STAT { @@ -131,7 +131,11 @@ const static struct umass_descriptor _mass_desc = USB_CLASS_MASS_STORAGE, //bInterfaceClass; 0x06, //bInterfaceSubClass; 0x50, //bInterfaceProtocol; +#ifdef RT_USB_DEVICE_COMPOSITE + MSTRORAGE_INTF_STR_INDEX, +#else 0x00, //iInterface; +#endif }, { @@ -1097,7 +1101,11 @@ ufunction_t rt_usbd_function_mstorage_create(udevice_t device) RT_ASSERT(device != RT_NULL); /* set usb device string description */ +#ifdef RT_USB_DEVICE_COMPOSITE + rt_usbd_device_set_interface_string(device, MSTRORAGE_INTF_STR_INDEX, _ustring[2]); +#else rt_usbd_device_set_string(device, _ustring); +#endif /* create a mass storage function */ func = rt_usbd_function_new(device, &dev_desc, &ops); diff --git a/components/drivers/usb/usbdevice/class/rndis.c b/components/drivers/usb/usbdevice/class/rndis.c index 391924dba0..ee25ec1ddf 100644 --- a/components/drivers/usb/usbdevice/class/rndis.c +++ b/components/drivers/usb/usbdevice/class/rndis.c @@ -28,7 +28,7 @@ #define DBG_SECTION_NAME "RNDIS" #include <rtdbg.h> - +#define RNDIS_INTF_STR_INDEX 12 /* RT-Thread LWIP ethernet interface */ #include <netif/ethernetif.h> @@ -123,7 +123,11 @@ const static struct ucdc_comm_descriptor _comm_desc = USB_CDC_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_PROTOCOL_VENDOR, +#ifdef RT_USB_DEVICE_COMPOSITE + RNDIS_INTF_STR_INDEX, +#else 0x00, +#endif }, /* Header Functional Descriptor */ { @@ -1318,8 +1322,11 @@ ufunction_t rt_usbd_function_rndis_create(udevice_t device) RT_ASSERT(device != RT_NULL); /* set usb device string description */ +#ifdef RT_USB_DEVICE_COMPOSITE + rt_usbd_device_set_interface_string(device, RNDIS_INTF_STR_INDEX, _ustring[2]); +#else rt_usbd_device_set_string(device, _ustring); - +#endif /* create a cdc class */ cdc = rt_usbd_function_new(device, &_dev_desc, &ops); rt_usbd_device_set_qualifier(device, &dev_qualifier); diff --git a/components/drivers/usb/usbdevice/class/uaudioreg.h b/components/drivers/usb/usbdevice/class/uaudioreg.h new file mode 100644 index 0000000000..6ed8614c39 --- /dev/null +++ b/components/drivers/usb/usbdevice/class/uaudioreg.h @@ -0,0 +1,418 @@ +/* $NetBSD: uaudioreg.h,v 1.15.38.1 2012/06/02 11:09:29 mrg Exp $ */ + +/* + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Lennart Augustsson ([email protected]) at + * Carlstedt Research & Technology. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rtdef.h> + +typedef uint8_t uByte; +typedef uint16_t uWord; + +#define UPACKED __attribute__ ((packed)) + +#define UAUDIO_VERSION 0x100 + +#define USB_SUBCLASS_AUDIOCONTROL 1 +#define USB_SUBCLASS_AUDIOSTREAMING 2 +#define USB_SUBCLASS_AUDIOMIDISTREAM 3 + +#define UDESC_CS_CONFIG 0x22 +#define UDESC_CS_STRING 0x23 +#define UDESC_CS_INTERFACE 0x24 +#define UDESC_CS_ENDPOINT 0x25 + +#define UDESCSUB_AC_HEADER 1 +#define UDESCSUB_AC_INPUT 2 +#define UDESCSUB_AC_OUTPUT 3 +#define UDESCSUB_AC_MIXER 4 +#define UDESCSUB_AC_SELECTOR 5 +#define UDESCSUB_AC_FEATURE 6 +#define UDESCSUB_AC_PROCESSING 7 +#define UDESCSUB_AC_EXTENSION 8 + +#ifndef AUFMT_MAX_FREQUENCIES +#define AUFMT_MAX_FREQUENCIES 1 +#endif + +/* The first fields are identical to usb_endpoint_descriptor_t */ +typedef struct { + uByte bLength; + uByte bDescriptorType; + uByte bEndpointAddress; + uByte bmAttributes; + uWord wMaxPacketSize; + uByte bInterval; + /* + * The following two entries are only used by the Audio Class. + * And according to the specs the Audio Class is the only one + * allowed to extend the endpoint descriptor. + * Who knows what goes on in the minds of the people in the USB + * standardization? :-( + */ + uByte bRefresh; + uByte bSynchAddress; +} UPACKED usb_endpoint_descriptor_audio_t; + +/* generic, for iteration */ +typedef struct { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; +} UPACKED uaudio_cs_descriptor_t; + +struct usb_audio_control_descriptor { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uWord bcdADC; + uWord wTotalLength; + uByte bInCollection; + uByte baInterfaceNr[1]; +} UPACKED; + +struct usb_audio_streaming_interface_descriptor { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bTerminalLink; + uByte bDelay; + uWord wFormatTag; +} UPACKED; + +struct usb_audio_streaming_endpoint_descriptor { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bmAttributes; +#define UA_SED_FREQ_CONTROL 0x01 +#define UA_SED_PITCH_CONTROL 0x02 +#define UA_SED_MAXPACKETSONLY 0x80 + uByte bLockDelayUnits; + uWord wLockDelay; +} UPACKED; + +struct usb_audio_streaming_type1_descriptor { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bFormatType; + uByte bNrChannels; + uByte bSubFrameSize; + uByte bBitResolution; + uByte bSamFreqType; +#define UA_SAMP_CONTNUOUS 0 + uByte tSamFreq[3*AUFMT_MAX_FREQUENCIES]; +#define UA_GETSAMP(p, n) ((p)->tSamFreq[(n)*3+0] | ((p)->tSamFreq[(n)*3+1] << 8) | ((p)->tSamFreq[(n)*3+2] << 16)) +#define UA_SAMP_LO(p) UA_GETSAMP(p, 0) +#define UA_SAMP_HI(p) UA_GETSAMP(p, 1) +} UPACKED; + +struct usb_audio_cluster { + uByte bNrChannels; + uWord wChannelConfig; +#define UA_CHANNEL_LEFT 0x0001 +#define UA_CHANNEL_RIGHT 0x0002 +#define UA_CHANNEL_CENTER 0x0004 +#define UA_CHANNEL_LFE 0x0008 +#define UA_CHANNEL_L_SURROUND 0x0010 +#define UA_CHANNEL_R_SURROUND 0x0020 +#define UA_CHANNEL_L_CENTER 0x0040 +#define UA_CHANNEL_R_CENTER 0x0080 +#define UA_CHANNEL_SURROUND 0x0100 +#define UA_CHANNEL_L_SIDE 0x0200 +#define UA_CHANNEL_R_SIDE 0x0400 +#define UA_CHANNEL_TOP 0x0800 + uByte iChannelNames; +} UPACKED; + +/* Shared by all units and terminals */ +struct usb_audio_unit { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bUnitId; +}; + +/* UDESCSUB_AC_INPUT */ +struct usb_audio_input_terminal { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bTerminalId; + uWord wTerminalType; + uByte bAssocTerminal; + uByte bNrChannels; + uWord wChannelConfig; + uByte iChannelNames; + uByte iTerminal; +} UPACKED; + +/* UDESCSUB_AC_OUTPUT */ +struct usb_audio_output_terminal { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bTerminalId; + uWord wTerminalType; + uByte bAssocTerminal; + uByte bSourceId; + uByte iTerminal; +} UPACKED; + +/* UDESCSUB_AC_MIXER */ +struct usb_audio_mixer_unit { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bUnitId; + uByte bNrInPins; + uByte baSourceId[255]; /* [bNrInPins] */ + /* struct usb_audio_mixer_unit_1 */ +} UPACKED; +struct usb_audio_mixer_unit_1 { + uByte bNrChannels; + uWord wChannelConfig; + uByte iChannelNames; + uByte bmControls[255]; /* [bNrChannels] */ + /*uByte iMixer;*/ +} UPACKED; + +/* UDESCSUB_AC_SELECTOR */ +struct usb_audio_selector_unit { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bUnitId; + uByte bNrInPins; + uByte baSourceId[255]; /* [bNrInPins] */ + /* uByte iSelector; */ +} UPACKED; + +/* UDESCSUB_AC_FEATURE */ +struct usb_audio_feature_unit { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bUnitId; + uByte bSourceId; + uByte bControlSize; + uByte bmaControls[2]; /* size for more than enough */ + /* uByte iFeature; */ +} UPACKED; + +/* UDESCSUB_AC_PROCESSING */ +struct usb_audio_processing_unit { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bUnitId; + uWord wProcessType; + uByte bNrInPins; + uByte baSourceId[255]; /* [bNrInPins] */ + /* struct usb_audio_processing_unit_1 */ +} UPACKED; +struct usb_audio_processing_unit_1{ + uByte bNrChannels; + uWord wChannelConfig; + uByte iChannelNames; + uByte bControlSize; + uByte bmControls[255]; /* [bControlSize] */ +#define UA_PROC_ENABLE_MASK 1 +} UPACKED; + +struct usb_audio_processing_unit_updown { + uByte iProcessing; + uByte bNrModes; + uWord waModes[255]; /* [bNrModes] */ +} UPACKED; + +/* UDESCSUB_AC_EXTENSION */ +struct usb_audio_extension_unit { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bUnitId; + uWord wExtensionCode; + uByte bNrInPins; + uByte baSourceId[255]; /* [bNrInPins] */ + /* struct usb_audio_extension_unit_1 */ +} UPACKED; +struct usb_audio_extension_unit_1 { + uByte bNrChannels; + uWord wChannelConfig; + uByte iChannelNames; + uByte bControlSize; + uByte bmControls[255]; /* [bControlSize] */ +#define UA_EXT_ENABLE_MASK 1 +#define UA_EXT_ENABLE 1 + /*uByte iExtension;*/ +} UPACKED; + +/* USB terminal types */ +#define UAT_UNDEFINED 0x0100 +#define UAT_STREAM 0x0101 +#define UAT_VENDOR 0x01ff +/* input terminal types */ +#define UATI_UNDEFINED 0x0200 +#define UATI_MICROPHONE 0x0201 +#define UATI_DESKMICROPHONE 0x0202 +#define UATI_PERSONALMICROPHONE 0x0203 +#define UATI_OMNIMICROPHONE 0x0204 +#define UATI_MICROPHONEARRAY 0x0205 +#define UATI_PROCMICROPHONEARR 0x0206 +/* output terminal types */ +#define UATO_UNDEFINED 0x0300 +#define UATO_SPEAKER 0x0301 +#define UATO_HEADPHONES 0x0302 +#define UATO_DISPLAYAUDIO 0x0303 +#define UATO_DESKTOPSPEAKER 0x0304 +#define UATO_ROOMSPEAKER 0x0305 +#define UATO_COMMSPEAKER 0x0306 +#define UATO_SUBWOOFER 0x0307 +/* bidir terminal types */ +#define UATB_UNDEFINED 0x0400 +#define UATB_HANDSET 0x0401 +#define UATB_HEADSET 0x0402 +#define UATB_SPEAKERPHONE 0x0403 +#define UATB_SPEAKERPHONEESUP 0x0404 +#define UATB_SPEAKERPHONEECANC 0x0405 +/* telephony terminal types */ +#define UATT_UNDEFINED 0x0500 +#define UATT_PHONELINE 0x0501 +#define UATT_TELEPHONE 0x0502 +#define UATT_DOWNLINEPHONE 0x0503 +/* external terminal types */ +#define UATE_UNDEFINED 0x0600 +#define UATE_ANALOGCONN 0x0601 +#define UATE_DIGITALAUIFC 0x0602 +#define UATE_LINECONN 0x0603 +#define UATE_LEGACYCONN 0x0604 +#define UATE_SPDIF 0x0605 +#define UATE_1394DA 0x0606 +#define UATE_1394DV 0x0607 +/* embedded function terminal types */ +#define UATF_UNDEFINED 0x0700 +#define UATF_CALIBNOISE 0x0701 +#define UATF_EQUNOISE 0x0702 +#define UATF_CDPLAYER 0x0703 +#define UATF_DAT 0x0704 +#define UATF_DCC 0x0705 +#define UATF_MINIDISK 0x0706 +#define UATF_ANALOGTAPE 0x0707 +#define UATF_PHONOGRAPH 0x0708 +#define UATF_VCRAUDIO 0x0709 +#define UATF_VIDEODISCAUDIO 0x070a +#define UATF_DVDAUDIO 0x070b +#define UATF_TVTUNERAUDIO 0x070c +#define UATF_SATELLITE 0x070d +#define UATF_CABLETUNER 0x070e +#define UATF_DSS 0x070f +#define UATF_RADIORECV 0x0710 +#define UATF_RADIOXMIT 0x0711 +#define UATF_MULTITRACK 0x0712 +#define UATF_SYNTHESIZER 0x0713 + + +#define SET_CUR 0x01 +#define GET_CUR 0x81 +#define SET_MIN 0x02 +#define GET_MIN 0x82 +#define SET_MAX 0x03 +#define GET_MAX 0x83 +#define SET_RES 0x04 +#define GET_RES 0x84 +#define SET_MEM 0x05 +#define GET_MEM 0x85 +#define GET_STAT 0xff + +#define MUTE_CONTROL 0x01 +#define VOLUME_CONTROL 0x02 +#define BASS_CONTROL 0x03 +#define MID_CONTROL 0x04 +#define TREBLE_CONTROL 0x05 +#define GRAPHIC_EQUALIZER_CONTROL 0x06 +#define AGC_CONTROL 0x07 +#define DELAY_CONTROL 0x08 +#define BASS_BOOST_CONTROL 0x09 +#define LOUDNESS_CONTROL 0x0a + +#define FU_MASK(u) (1 << ((u)-1)) + +#define MASTER_CHAN 0 + +#define AS_GENERAL 1 +#define FORMAT_TYPE 2 +#define FORMAT_SPECIFIC 3 + +#define UA_FMT_PCM 1 +#define UA_FMT_PCM8 2 +#define UA_FMT_IEEE_FLOAT 3 +#define UA_FMT_ALAW 4 +#define UA_FMT_MULAW 5 +#define UA_FMT_MPEG 0x1001 +#define UA_FMT_AC3 0x1002 + +#define SAMPLING_FREQ_CONTROL 0x01 +#define PITCH_CONTROL 0x02 + +#define FORMAT_TYPE_UNDEFINED 0 +#define FORMAT_TYPE_I 1 +#define FORMAT_TYPE_II 2 +#define FORMAT_TYPE_III 3 + +#define UA_PROC_MASK(n) (1<< ((n)-1)) +#define PROCESS_UNDEFINED 0 +#define XX_ENABLE_CONTROL 1 +#define UPDOWNMIX_PROCESS 1 +#define UD_ENABLE_CONTROL 1 +#define UD_MODE_SELECT_CONTROL 2 +#define DOLBY_PROLOGIC_PROCESS 2 +#define DP_ENABLE_CONTROL 1 +#define DP_MODE_SELECT_CONTROL 2 +#define P3D_STEREO_EXTENDER_PROCESS 3 +#define P3D_ENABLE_CONTROL 1 +#define P3D_SPACIOUSNESS_CONTROL 2 +#define REVERBATION_PROCESS 4 +#define RV_ENABLE_CONTROL 1 +#define RV_LEVEL_CONTROL 2 +#define RV_TIME_CONTROL 3 +#define RV_FEEDBACK_CONTROL 4 +#define CHORUS_PROCESS 5 +#define CH_ENABLE_CONTROL 1 +#define CH_LEVEL_CONTROL 2 +#define CH_RATE_CONTROL 3 +#define CH_DEPTH_CONTROL 4 +#define DYN_RANGE_COMP_PROCESS 6 +#define DR_ENABLE_CONTROL 1 +#define DR_COMPRESSION_RATE_CONTROL 2 +#define DR_MAXAMPL_CONTROL 3 +#define DR_THRESHOLD_CONTROL 4 +#define DR_ATTACK_TIME_CONTROL 5 +#define DR_RELEASE_TIME_CONTROL 6 diff --git a/components/drivers/usb/usbdevice/class/winusb.c b/components/drivers/usb/usbdevice/class/winusb.c index 0db3de794a..b5a169d2cb 100644 --- a/components/drivers/usb/usbdevice/class/winusb.c +++ b/components/drivers/usb/usbdevice/class/winusb.c @@ -19,7 +19,7 @@ struct winusb_device uep_t ep_out; uep_t ep_in; }; - +#define WINUSB_INTF_STR_INDEX 13 typedef struct winusb_device * winusb_device_t; ALIGN(4) @@ -82,7 +82,11 @@ struct winusb_descriptor _winusb_desc = 0xFF, //bInterfaceClass; 0x00, //bInterfaceSubClass; 0x00, //bInterfaceProtocol; +#ifdef RT_USB_DEVICE_COMPOSITE + WINUSB_INTF_STR_INDEX, +#else 0x00, //iInterface; +#endif }, /*endpoint descriptor*/ { @@ -308,7 +312,11 @@ ufunction_t rt_usbd_function_winusb_create(udevice_t device) RT_ASSERT(device != RT_NULL); /* set usb device string description */ +#ifdef RT_USB_DEVICE_COMPOSITE + rt_usbd_device_set_interface_string(device, WINUSB_INTF_STR_INDEX, _ustring[2]); +#else rt_usbd_device_set_string(device, _ustring); +#endif /* create a cdc function */ func = rt_usbd_function_new(device, &dev_desc, &ops); diff --git a/components/drivers/usb/usbdevice/core/usbdevice_core.c b/components/drivers/usb/usbdevice/core/usbdevice_core.c index fd205ad37f..c12636aaf5 100644 --- a/components/drivers/usb/usbdevice/core/usbdevice_core.c +++ b/components/drivers/usb/usbdevice/core/usbdevice_core.c @@ -123,12 +123,18 @@ static rt_err_t _get_string_descriptor(struct udevice* device, ureq_t setup) } else { - len = rt_strlen(device->str[index]); + if(index < 5) + len = rt_strlen(device->str[index]); + else + len = rt_strlen(device->str_intf[index]); str_desc.bLength = len*2 + 2; for(i=0; i<len; i++) { - str_desc.String[i*2] = device->str[index][i]; + if(index < 5) + str_desc.String[i*2] = device->str[index][i]; + else + str_desc.String[i*2] = device->str_intf[index][i]; str_desc.String[i*2 + 1] = 0; } } @@ -1044,6 +1050,28 @@ rt_err_t rt_usbd_device_set_string(udevice_t device, const char** ustring) return RT_EOK; } +/** + * This function will set usb device interface string description. + * + * @param device the usb device object. + * @param index of interface string + * @param string pointer to interface string description. + * + * @return RT_EOK. + */ +rt_err_t rt_usbd_device_set_interface_string(udevice_t device, int index, const char* string) +{ + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(string != RT_NULL); + RT_ASSERT(index < MAX_INTF_STR); + + /* set string descriptor array to the device object */ + device->str_intf[index] = string; + + return RT_EOK; +} + rt_err_t rt_usbd_device_set_os_comp_id_desc(udevice_t device, usb_os_comp_id_desc_t os_comp_id_desc) { /* parameter check */ |
