diff options
| author | armink <[email protected]> | 2019-12-17 20:11:46 +0800 |
|---|---|---|
| committer | armink <[email protected]> | 2019-12-17 20:11:46 +0800 |
| commit | 4875ee8a3ab95c4fbf1e09941d3f44d99a9a632b (patch) | |
| tree | 15c596c04a842bac747bbcf05a703b8da76f8eac /components/drivers | |
| parent | fa46d6ac861f26b472d62abdf1278c445431ce4c (diff) | |
Sync from master (75a3f3dd3a930eab1dc58fa0258a9d1605a0ac11)
Diffstat (limited to 'components/drivers')
96 files changed, 7467 insertions, 4648 deletions
diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index 792dc1b028..c567233c84 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -48,7 +48,7 @@ config RT_USING_CAN if RT_USING_CAN config RT_CAN_USING_HDR bool "Enable CAN hardware filter" - default y + default n endif config RT_USING_HWTIMER @@ -88,11 +88,21 @@ config RT_USING_I2C default n if RT_USING_I2C + config RT_I2C_DEBUG + bool "Use I2C debug mesage" + default n + config RT_USING_I2C_BITOPS bool "Use GPIO to simulate I2C" default y endif +if RT_USING_I2C_BITOPS + config RT_I2C_BITOPS_DEBUG + bool "Use simulate I2C debug mesage" + default n +endif + config RT_USING_PIN bool "Using generic GPIO device drivers" default y @@ -119,27 +129,12 @@ config RT_USING_MTD_NAND default n endif -config RT_USING_MTD - bool "Using Memory Technology Device (MTD)" - default n - - if RT_USING_MTD - config MTD_USING_NOR - bool "Using MTD Nor Flash device" - default n - - config MTD_USING_NAND - bool "Using MTD Nand Flash device" - default n - endif - config RT_USING_PM bool "Using Power Management device drivers" default n config RT_USING_RTC bool "Using RTC device drivers" - select RT_USING_LIBC default n if RT_USING_RTC @@ -212,6 +207,9 @@ config RT_USING_SPI config RT_USING_SFUD bool "Using Serial Flash Universal Driver" default n + help + An using JEDEC's SFDP standard serial (SPI) flash universal driver library + if RT_USING_SFUD config RT_SFUD_USING_SFDP bool "Using auto probe flash JEDEC SFDP parameter" @@ -226,19 +224,18 @@ config RT_USING_SPI select RT_USING_QSPI default n + config RT_SFUD_SPI_MAX_HZ + int "Default spi maximum speed(HZ)" + range 0 50000000 + default 50000000 + help + Read the JEDEC SFDP command must run at 50 MHz or less,and you also can use rt_spi_configure(); to config spi speed. + config RT_DEBUG_SFUD bool "Show more SFUD debug information" default n endif - config RT_USING_W25QXX - bool "Using W25QXX SPI NorFlash" - default n - - config RT_USING_GD - bool "Using GD SPI NorFlash" - default n - config RT_USING_ENC28J60 bool "Using ENC28J60 SPI Ethernet network interface" select RT_USING_LWIP @@ -257,6 +254,20 @@ config RT_USING_WDT config RT_USING_AUDIO bool "Using Audio device drivers" default n + + if RT_USING_AUDIO + config RT_AUDIO_REPLAY_MP_BLOCK_SIZE + int "Replay memmory pool block size" + default 4096 + + config RT_AUDIO_REPLAY_MP_BLOCK_COUNT + int "Replay memmory pool block count" + default 2 + + config RT_AUDIO_RECORD_PIPE_SIZE + int "Record pipe size" + default 2048 + endif config RT_USING_SENSOR bool "Using Sensor device drivers" @@ -269,67 +280,309 @@ if RT_USING_SENSOR default y endif -menu "Using WiFi" - config RT_USING_WIFI - bool "Using Wi-Fi framework" +config RT_USING_TOUCH + bool "Using Touch device drivers" + default n + +menuconfig RT_USING_HWCRYPTO + bool "Using Hardware Crypto drivers" default n + if RT_USING_HWCRYPTO + config RT_HWCRYPTO_DEFAULT_NAME + string "Hardware crypto device name" + default "hwcryto" + + config RT_HWCRYPTO_IV_MAX_SIZE + int "IV max size" + default "16" + + config RT_HWCRYPTO_KEYBIT_MAX_SIZE + int "Key max bit length" + default 256 + + config RT_HWCRYPTO_USING_GCM + bool "Using Hardware GCM" + default n + + config RT_HWCRYPTO_USING_AES + bool "Using Hardware AES" + default n + + if RT_HWCRYPTO_USING_AES + config RT_HWCRYPTO_USING_AES_ECB + bool "Using Hardware AES ECB mode" + default y + + config RT_HWCRYPTO_USING_AES_CBC + bool "Using Hardware AES CBC mode" + default n + + config RT_HWCRYPTO_USING_AES_CFB + bool "Using Hardware AES CFB mode" + default n + + config RT_HWCRYPTO_USING_AES_CTR + bool "Using Hardware AES CTR mode" + default n + + config RT_HWCRYPTO_USING_AES_OFB + bool "Using Hardware AES OFB mode" + default n + endif + + config RT_HWCRYPTO_USING_DES + bool "Using Hardware DES" + default n + + if RT_HWCRYPTO_USING_DES + config RT_HWCRYPTO_USING_DES_ECB + bool "Using Hardware DES ECB mode" + default y + + config RT_HWCRYPTO_USING_DES_CBC + bool "Using Hardware DES CBC mode" + default n + endif + + config RT_HWCRYPTO_USING_3DES + bool "Using Hardware 3DES" + default n + + if RT_HWCRYPTO_USING_3DES + config RT_HWCRYPTO_USING_3DES_ECB + bool "Using Hardware 3DES ECB mode" + default y + + config RT_HWCRYPTO_USING_3DES_CBC + bool "Using Hardware 3DES CBC mode" + default n + endif + + config RT_HWCRYPTO_USING_RC4 + bool "Using Hardware RC4" + default n + + config RT_HWCRYPTO_USING_MD5 + bool "Using Hardware MD5" + default n + + config RT_HWCRYPTO_USING_SHA1 + bool "Using Hardware SHA1" + default n + + config RT_HWCRYPTO_USING_SHA2 + bool "Using Hardware SHA2" + default n + + if RT_HWCRYPTO_USING_SHA2 + config RT_HWCRYPTO_USING_SHA2_224 + bool "Using Hardware SHA2_224 mode" + default n + + config RT_HWCRYPTO_USING_SHA2_256 + bool "Using Hardware SHA2_256 mode" + default y + + config RT_HWCRYPTO_USING_SHA2_384 + bool "Using Hardware SHA2_384 mode" + default n + + config RT_HWCRYPTO_USING_SHA2_512 + bool "Using Hardware SHA2_512 mode" + default n + endif + + config RT_HWCRYPTO_USING_RNG + bool "Using Hardware RNG" + default n + + config RT_HWCRYPTO_USING_CRC + bool "Using Hardware CRC" + default n + + if RT_HWCRYPTO_USING_CRC + config RT_HWCRYPTO_USING_CRC_07 + bool "Using Hardware CRC-8 0x07 polynomial" + default n + + config RT_HWCRYPTO_USING_CRC_8005 + bool "Using Hardware CRC-16 0x8005 polynomial" + default n + + config RT_HWCRYPTO_USING_CRC_1021 + bool "Using Hardware CRC-16 0x1021 polynomial" + default n + + config RT_HWCRYPTO_USING_CRC_3D65 + bool "Using Hardware CRC-16 0x3D65 polynomial" + default n + + config RT_HWCRYPTO_USING_CRC_04C11DB7 + bool "Using Hardware CRC-32 0x04C11DB7 polynomial" + default n + endif + + config RT_HWCRYPTO_USING_BIGNUM + bool "Using Hardware bignum" + default n + + if RT_HWCRYPTO_USING_BIGNUM + config RT_HWCRYPTO_USING_BIGNUM_EXPTMOD + bool "Using Hardware bignum expt_mod operation" + default y + + config RT_HWCRYPTO_USING_BIGNUM_MULMOD + bool "Using Hardware bignum mul_mod operation" + default y + + config RT_HWCRYPTO_USING_BIGNUM_MUL + bool "Using Hardware bignum mul operation" + default n + + config RT_HWCRYPTO_USING_BIGNUM_ADD + bool "Using Hardware bignum add operation" + default n + + config RT_HWCRYPTO_USING_BIGNUM_SUB + bool "Using Hardware bignum sub operation" + default n + endif + endif + +config RT_USING_PULSE_ENCODER + bool "Using PULSE ENCODER device drivers" + default n + +config RT_USING_INPUT_CAPTURE + bool "Using INPUT CAPTURE device drivers" + default n + +if RT_USING_INPUT_CAPTURE + config RT_INPUT_CAPTURE_RB_SIZE + int "Set input capture ringbuffer size" + default 100 +endif + +menuconfig RT_USING_WIFI + bool "Using Wi-Fi framework" + default n + if RT_USING_WIFI config RT_WLAN_DEVICE_STA_NAME - string "The WiFi device name for station" + string "The device name for station" default "wlan0" config RT_WLAN_DEVICE_AP_NAME - string "The WiFi device name for ap" + string "The device name for ap" default "wlan1" - config RT_WLAN_DEFAULT_PROT - string "Default transport protocol" - default "lwip" - - config RT_WLAN_SCAN_WAIT_MS - int "Set scan timeout time(ms)" - default 10000 - - config RT_WLAN_CONNECT_WAIT_MS - int "Set connect timeout time(ms)" - default 10000 - config RT_WLAN_SSID_MAX_LENGTH - int "SSID name maximum length" + int "SSID maximum length" default 32 config RT_WLAN_PASSWORD_MAX_LENGTH - int "Maximum password length" + int "Password maximum length" default 32 - config RT_WLAN_SCAN_SORT - bool "Automatic sorting of scan results" + config RT_WLAN_DEV_EVENT_NUM + int "Driver events maxcount" + default 2 + + config RT_WLAN_MANAGE_ENABLE + bool "Connection management Enable" default y - config RT_WLAN_CFG_INFO_MAX - int "Maximum number of WiFi information automatically saved" - default 3 + if RT_WLAN_MANAGE_ENABLE + config RT_WLAN_SCAN_WAIT_MS + int "Set scan timeout time(ms)" + default 10000 - config RT_WLAN_WORKQUEUE_THREAD_NAME - string "WiFi work queue thread name" - default "wlan_job" + config RT_WLAN_CONNECT_WAIT_MS + int "Set connect timeout time(ms)" + default 10000 - config RT_WLAN_WORKQUEUE_THREAD_SIZE - int "wifi work queue thread size" - default 2048 + config RT_WLAN_SCAN_SORT + bool "Automatic sorting of scan results" + default y - config RT_WLAN_WORKQUEUE_THREAD_PRIO - int "WiFi work queue thread priority" - default 22 + config RT_WLAN_MSH_CMD_ENABLE + bool "MSH command Enable" + default y - config RT_WLAN_DEV_EVENT_NUM - int "Maximum number of driver events" - default 2 + config RT_WLAN_AUTO_CONNECT_ENABLE + bool "Auto connect Enable" + select RT_WLAN_CFG_ENABLE + select RT_WLAN_WORK_THREAD_ENABLE + default y - config RT_WLAN_PROT_LWIP_PBUF_FORCE - bool "Forced use of PBUF transmission" - default n + if RT_WLAN_AUTO_CONNECT_ENABLE + config AUTO_CONNECTION_PERIOD_MS + int "Auto connect period(ms)" + default 2000 + endif + endif + + config RT_WLAN_CFG_ENABLE + bool "WiFi information automatically saved Enable" + default y + + if RT_WLAN_CFG_ENABLE + config RT_WLAN_CFG_INFO_MAX + int "Maximum number of WiFi information automatically saved" + default 3 + endif + + config RT_WLAN_PROT_ENABLE + bool "Transport protocol manage Enable" + default y + + if RT_WLAN_PROT_ENABLE + config RT_WLAN_PROT_NAME_LEN + int "Transport protocol name length" + default 8 + + config RT_WLAN_PROT_MAX + int "Transport protocol maxcount" + default 2 + + config RT_WLAN_DEFAULT_PROT + string "Default transport protocol" + default "lwip" + + config RT_WLAN_PROT_LWIP_ENABLE + bool "LWIP transport protocol Enable" + select RT_USING_LWIP + default y + + if RT_WLAN_PROT_LWIP_ENABLE + config RT_WLAN_PROT_LWIP_NAME + string "LWIP transport protocol name" + default "lwip" + + config RT_WLAN_PROT_LWIP_PBUF_FORCE + bool "Forced use of PBUF transmission" + default n + endif + endif + + config RT_WLAN_WORK_THREAD_ENABLE + bool "WLAN work queue thread Enable" + default y + + if RT_WLAN_WORK_THREAD_ENABLE + config RT_WLAN_WORKQUEUE_THREAD_NAME + string "WLAN work queue thread name" + default "wlan" + + config RT_WLAN_WORKQUEUE_THREAD_SIZE + int "WLAN work queue thread size" + default 2048 + + config RT_WLAN_WORKQUEUE_THREAD_PRIO + int "WLAN work queue thread priority" + default 15 + endif menuconfig RT_WLAN_DEBUG bool "Enable WLAN Debugging Options" @@ -361,7 +614,6 @@ menu "Using WiFi" default n endif endif -endmenu menu "Using USB" config RT_USING_USB_HOST @@ -424,6 +676,9 @@ menu "Using USB" config _RT_USB_DEVICE_WINUSB bool "Enable to use device as winusb device" select RT_USB_DEVICE_WINUSB + config _RT_USB_DEVICE_AUDIO + bool "Enable to use device as audio device" + select RT_USB_DEVICE_AUDIO endchoice if RT_USB_DEVICE_COMPOSITE config RT_USB_DEVICE_CDC @@ -449,6 +704,9 @@ menu "Using USB" config RT_USB_DEVICE_WINUSB bool "Enable to use device as winusb device" default n + config RT_USB_DEVICE_AUDIO + bool "Enable to use device as audio device" + default n endif if RT_USB_DEVICE_CDC config RT_VCOM_TASK_STK_SIZE @@ -477,6 +735,14 @@ menu "Using USB" string "msc class disk name" default "flash0" endif + + if RT_USB_DEVICE_RNDIS + config RNDIS_DELAY_LINK_UP + bool "Delay linkup media connection" + select RT_USING_TIMER_SOFT + default n + endif + if RT_USB_DEVICE_HID config RT_USB_DEVICE_HID_KEYBOARD bool "Use to HID device as Keyboard" @@ -508,6 +774,24 @@ menu "Using USB" bool "Use to HID device as media keyboard" default y endif + if RT_USB_DEVICE_AUDIO + config RT_USB_DEVICE_AUDIO_MIC + bool "Use usb mic device as audio device" + default n + if RT_USB_DEVICE_AUDIO_MIC + config RT_USBD_MIC_DEVICE_NAME + string "audio mic device name" + default "mic0" + endif + config RT_USB_DEVICE_AUDIO_SPEAKER + bool "Use usb speaker device as audio device" + default n + if RT_USB_DEVICE_AUDIO_SPEAKER + config RT_USBD_SPEAKER_DEVICE_NAME + string "audio speaker device name" + default "sound0" + endif + endif endif endmenu endmenu diff --git a/components/drivers/audio/audio.c b/components/drivers/audio/audio.c index 6a5ebc8741..28ddf0fe56 100644 --- a/components/drivers/audio/audio.c +++ b/components/drivers/audio/audio.c @@ -5,83 +5,208 @@ * * Change Logs: * Date Author Notes - * 2017-05-09 Urey first version + * 2017-05-09 Urey first version + * 2019-07-09 Zero-Free improve device ops interface and data flows */ #include <stdio.h> +#include <string.h> #include <rthw.h> #include <rtthread.h> #include <rtdevice.h> -#include <drivers/audio.h> +#define DBG_TAG "audio" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> -#include "audio_pipe.h" +#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -#define AUDIO_DEBUG 0 -#if AUDIO_DEBUG -#define AUDIO_DBG(...) printf("[AUDIO]:"),printf(__VA_ARGS__) -#else -#define AUDIO_DBG(...) -#endif - -static struct rt_audio_pipe audio_pipe; +enum +{ + REPLAY_EVT_NONE = 0x00, + REPLAY_EVT_START = 0x01, + REPLAY_EVT_STOP = 0x02, +}; static rt_err_t _audio_send_replay_frame(struct rt_audio_device *audio) { rt_err_t result = RT_EOK; - rt_base_t level; - struct rt_audio_frame frame; + rt_uint8_t *data; + rt_size_t dst_size, src_size; + rt_uint16_t position, remain_bytes, index = 0; + struct rt_audio_buf_info *buf_info; RT_ASSERT(audio != RT_NULL); - //check repaly queue is empty - if (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) != RT_EOK) + buf_info = &audio->replay->buf_info; + /* save current pos */ + position = audio->replay->pos; + dst_size = buf_info->block_size; + + /* check repaly queue is empty */ + if (rt_data_queue_peak(&audio->replay->queue, (const void **)&data, &src_size) != RT_EOK) { - AUDIO_DBG("TX queue is empty\n"); - result = -RT_EEMPTY; + /* ack stop event */ + if (audio->replay->event & REPLAY_EVT_STOP) + rt_completion_done(&audio->replay->cmp); - level = rt_hw_interrupt_disable(); - audio->replay->activated = RT_FALSE; - rt_hw_interrupt_enable(level); + /* send zero frames */ + memset(&buf_info->buffer[audio->replay->pos], 0, dst_size); - goto _exit; + audio->replay->pos += dst_size; + audio->replay->pos %= buf_info->total_size; } - - if (audio->ops->transmit != RT_NULL) + else { - AUDIO_DBG("audio transmit...\n"); - if (audio->ops->transmit(audio, frame.data_ptr, RT_NULL, frame.data_size) != frame.data_size) + memset(&buf_info->buffer[audio->replay->pos], 0, dst_size); + + /* copy data from memory pool to hardware device fifo */ + while (index < dst_size) { - result = -RT_EBUSY; + result = rt_data_queue_peak(&audio->replay->queue, (const void **)&data, &src_size); + if (result != RT_EOK) + { + LOG_D("under run %d, remain %d", audio->replay->pos, remain_bytes); + audio->replay->pos -= remain_bytes; + audio->replay->pos += dst_size; + audio->replay->pos %= buf_info->total_size; + audio->replay->read_index = 0; + result = -RT_EEMPTY; + break; + } + + remain_bytes = MIN((dst_size - index), (src_size - audio->replay->read_index)); + memcpy(&buf_info->buffer[audio->replay->pos], + &data[audio->replay->read_index], remain_bytes); + + index += remain_bytes; + audio->replay->read_index += remain_bytes; + audio->replay->pos += remain_bytes; + audio->replay->pos %= buf_info->total_size; + + if (audio->replay->read_index == src_size) + { + /* free memory */ + audio->replay->read_index = 0; + rt_data_queue_pop(&audio->replay->queue, (const void **)&data, &src_size, RT_WAITING_NO); + rt_mp_free(data); - goto _exit; + /* notify transmitted complete. */ + if (audio->parent.tx_complete != RT_NULL) + audio->parent.tx_complete(&audio->parent, (void *)data); + } } } - //pop the head frame... - rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER); + if (audio->ops->transmit != RT_NULL) + { + if (audio->ops->transmit(audio, &buf_info->buffer[position], RT_NULL, dst_size) != dst_size) + result = -RT_ERROR; + } - _exit: return result; + return result; } static rt_err_t _audio_flush_replay_frame(struct rt_audio_device *audio) { - struct rt_audio_frame frame; + rt_err_t result = RT_EOK; - if (audio->replay == RT_NULL) - return -RT_EIO; - while (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) == RT_EOK) + if (audio->replay->write_index) { - //pop the head frame... - rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER); + result = rt_data_queue_push(&audio->replay->queue, + (const void **)audio->replay->write_data, + audio->replay->write_index, + RT_WAITING_FOREVER); - /* notify transmitted complete. */ - if (audio->parent.tx_complete != RT_NULL) - audio->parent.tx_complete(&audio->parent, (void *) frame.data_ptr); + audio->replay->write_index = 0; } - return RT_EOK; + return result; +} + +static rt_err_t _aduio_replay_start(struct rt_audio_device *audio) +{ + rt_err_t result = RT_EOK; + + if (audio->replay->activated != RT_TRUE) + { + /* start playback hardware device */ + if (audio->ops->start) + result = audio->ops->start(audio, AUDIO_STREAM_REPLAY); + + audio->replay->activated = RT_TRUE; + LOG_D("start audio replay device"); + } + + return result; +} + +static rt_err_t _aduio_replay_stop(struct rt_audio_device *audio) +{ + rt_err_t result = RT_EOK; + + if (audio->replay->activated == RT_TRUE) + { + /* flush replay remian frames */ + _audio_flush_replay_frame(audio); + + /* notify irq(or thread) to stop the data transmission */ + audio->replay->event |= REPLAY_EVT_STOP; + + /* waiting for the remaining data transfer to complete */ + rt_completion_init(&audio->replay->cmp); + rt_completion_wait(&audio->replay->cmp, RT_WAITING_FOREVER); + audio->replay->event &= ~REPLAY_EVT_STOP; + + /* stop playback hardware device */ + if (audio->ops->stop) + result = audio->ops->stop(audio, AUDIO_STREAM_REPLAY); + + audio->replay->activated = RT_FALSE; + LOG_D("stop audio replay device"); + } + + return result; +} + +static rt_err_t _audio_record_start(struct rt_audio_device *audio) +{ + rt_err_t result = RT_EOK; + + if (audio->record->activated != RT_TRUE) + { + /* open audio record pipe */ + rt_device_open(RT_DEVICE(&audio->record->pipe), RT_DEVICE_OFLAG_RDONLY); + + /* start record hardware device */ + if (audio->ops->start) + result = audio->ops->start(audio, AUDIO_STREAM_RECORD); + + audio->record->activated = RT_TRUE; + LOG_D("start audio record device"); + } + + return result; +} + +static rt_err_t _audio_record_stop(struct rt_audio_device *audio) +{ + rt_err_t result = RT_EOK; + + if (audio->record->activated == RT_TRUE) + { + /* stop record hardware device */ + if (audio->ops->stop) + result = audio->ops->stop(audio, AUDIO_STREAM_RECORD); + + /* close audio record pipe */ + rt_device_close(RT_DEVICE(&audio->record->pipe)); + + audio->record->activated = RT_FALSE; + LOG_D("stop audio record device"); + } + + return result; } static rt_err_t _audio_dev_init(struct rt_device *dev) @@ -96,9 +221,68 @@ static rt_err_t _audio_dev_init(struct rt_device *dev) audio->replay = RT_NULL; audio->record = RT_NULL; - /* apply configuration */ + /* initialize replay */ + if (dev->flag & RT_DEVICE_FLAG_WRONLY) + { + struct rt_audio_replay *replay = (struct rt_audio_replay *) rt_malloc(sizeof(struct rt_audio_replay)); + + if (replay == RT_NULL) + return -RT_ENOMEM; + memset(replay, 0, sizeof(struct rt_audio_replay)); + + /* init memory pool for replay */ + replay->mp = rt_mp_create("adu_mp", RT_AUDIO_REPLAY_MP_BLOCK_COUNT, RT_AUDIO_REPLAY_MP_BLOCK_SIZE); + if (replay->mp == RT_NULL) + { + rt_free(replay); + LOG_E("create memory pool for repaly failed"); + return -RT_ENOMEM; + } + + /* init queue for audio replay */ + rt_data_queue_init(&replay->queue, CFG_AUDIO_REPLAY_QUEUE_COUNT, 0, RT_NULL); + + /* init mutex lock for audio replay */ + rt_mutex_init(&replay->lock, "replay", RT_IPC_FLAG_PRIO); + + replay->activated = RT_FALSE; + audio->replay = replay; + } + + /* initialize record */ + if (dev->flag & RT_DEVICE_FLAG_RDONLY) + { + struct rt_audio_record *record = (struct rt_audio_record *) rt_malloc(sizeof(struct rt_audio_record)); + rt_uint8_t *buffer; + + if (record == RT_NULL) + return -RT_ENOMEM; + memset(record, 0, sizeof(struct rt_audio_record)); + + /* init pipe for record*/ + buffer = rt_malloc(RT_AUDIO_RECORD_PIPE_SIZE); + if (buffer == RT_NULL) + { + rt_free(record); + LOG_E("malloc memory for for record pipe failed"); + return -RT_ENOMEM; + } + rt_audio_pipe_init(&record->pipe, "record", + (rt_int32_t)(RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD), + buffer, + RT_AUDIO_RECORD_PIPE_SIZE); + + record->activated = RT_FALSE; + audio->record = record; + } + + /* initialize hardware configuration */ if (audio->ops->init) - result = audio->ops->init(audio); + audio->ops->init(audio); + + /* get replay buffer information */ + if (audio->ops->buffer_info) + audio->ops->buffer_info(audio, &audio->replay->buf_info); return result; } @@ -122,65 +306,27 @@ static rt_err_t _audio_dev_open(struct rt_device *dev, rt_uint16_t oflag) /* initialize the Rx/Tx structure according to open flag */ if (oflag & RT_DEVICE_OFLAG_WRONLY) { - AUDIO_DBG("open audio device ,oflag = %x\n",oflag); - if (audio->replay == RT_NULL) + if (audio->replay->activated != RT_TRUE) { - struct rt_audio_replay *replay = (struct rt_audio_replay *) rt_malloc(sizeof(struct rt_audio_replay)); - - if (replay == RT_NULL) - { - AUDIO_DBG("request memory for replay error\n"); - return -RT_ENOMEM; - } - - //init queue for audio replay - rt_data_queue_init(&replay->queue, CFG_AUDIO_REPLAY_QUEUE_COUNT, CFG_AUDIO_REPLAY_QUEUE_COUNT / 2, RT_NULL); - - replay->activated = RT_FALSE; - audio->replay = replay; + LOG_D("open audio replay device, oflag = %x\n", oflag); + audio->replay->write_index = 0; + audio->replay->read_index = 0; + audio->replay->pos = 0; + audio->replay->event = REPLAY_EVT_NONE; } - dev->open_flag |= RT_DEVICE_OFLAG_WRONLY; } if (oflag & RT_DEVICE_OFLAG_RDONLY) { - if (audio->record == RT_NULL) + /* open record pipe */ + if (audio->record->activated != RT_TRUE) { - struct rt_audio_record *record = (struct rt_audio_record *) rt_malloc(sizeof(struct rt_audio_record)); - - if (record == RT_NULL) - { - AUDIO_DBG("request memory for record error\n"); - return -RT_ENOMEM; - } - - //init pipe for record - { - rt_uint8_t *buf = rt_malloc(CFG_AUDIO_RECORD_PIPE_SIZE); - - if (buf == RT_NULL) - { - rt_free(record); - AUDIO_DBG("request pipe memory error\n"); + LOG_D("open audio record device ,oflag = %x\n", oflag); - return -RT_ENOMEM; - } - - rt_audio_pipe_init(&audio_pipe, "recpipe", (rt_int32_t)(RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD), buf, - CFG_AUDIO_RECORD_PIPE_SIZE); - } - - record->activated = RT_FALSE; - audio->record = record; - } - - //open record pipe - if (audio->record != RT_NULL) - { - rt_device_open(RT_DEVICE(&audio_pipe), RT_DEVICE_OFLAG_RDONLY); + _audio_record_start(audio); + audio->record->activated = RT_TRUE; } - dev->open_flag |= RT_DEVICE_OFLAG_RDONLY; } @@ -193,39 +339,17 @@ static rt_err_t _audio_dev_close(struct rt_device *dev) RT_ASSERT(dev != RT_NULL); audio = (struct rt_audio_device *) dev; - //shutdown the lower device - if (audio->ops->shutdown != RT_NULL) - audio->ops->shutdown(audio); - if (dev->open_flag & RT_DEVICE_OFLAG_WRONLY) { - struct rt_audio_frame frame; - //stop replay stream - audio->ops->stop(audio, AUDIO_STREAM_REPLAY); - - //flush all frame - while (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) == RT_EOK) - { - //pop the head frame... - rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER); - - /* notify transmitted complete. */ - if (audio->parent.tx_complete != RT_NULL) - audio->parent.tx_complete(&audio->parent, (void *) frame.data_ptr); - } - + /* stop replay stream */ + _aduio_replay_stop(audio); dev->open_flag &= ~RT_DEVICE_OFLAG_WRONLY; } if (dev->open_flag & RT_DEVICE_OFLAG_RDONLY) { - //stop record stream - audio->ops->stop(audio, AUDIO_STREAM_RECORD); - - //close record pipe - if (audio->record != RT_NULL) - rt_device_close(RT_DEVICE(&audio_pipe)); - + /* stop record stream */ + _audio_record_stop(audio); dev->open_flag &= ~RT_DEVICE_OFLAG_RDONLY; } @@ -237,17 +361,19 @@ static rt_size_t _audio_dev_read(struct rt_device *dev, rt_off_t pos, void *buff struct rt_audio_device *audio; RT_ASSERT(dev != RT_NULL); audio = (struct rt_audio_device *) dev; + if (!(dev->open_flag & RT_DEVICE_OFLAG_RDONLY) || (audio->record == RT_NULL)) return 0; - return rt_device_read(RT_DEVICE(&audio_pipe), pos, buffer, size); + return rt_device_read(RT_DEVICE(&audio->record->pipe), pos, buffer, size); } static rt_size_t _audio_dev_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size) { - rt_err_t result = RT_EOK; - rt_base_t level; + struct rt_audio_device *audio; + rt_uint8_t *ptr; + rt_uint16_t block_size, remain_bytes, index = 0; RT_ASSERT(dev != RT_NULL); audio = (struct rt_audio_device *) dev; @@ -255,34 +381,46 @@ static rt_size_t _audio_dev_write(struct rt_device *dev, rt_off_t pos, const voi if (!(dev->open_flag & RT_DEVICE_OFLAG_WRONLY) || (audio->replay == RT_NULL)) return 0; - AUDIO_DBG("audio write : pos = %d,buffer = %x,size = %d\n",pos,(rt_uint32_t)buffer,size); - //push a new frame to tx queue + /* push a new frame to replay data queue */ + ptr = (rt_uint8_t *)buffer; + block_size = RT_AUDIO_REPLAY_MP_BLOCK_SIZE; + + rt_mutex_take(&audio->replay->lock, RT_WAITING_FOREVER); + while (index < size) { - result = rt_data_queue_push(&audio->replay->queue, buffer, size, - RT_WAITING_FOREVER); - if (result != RT_EOK) + /* request buffer from replay memory pool */ + if (audio->replay->write_index % block_size == 0) { - AUDIO_DBG("TX frame queue push error\n"); - rt_set_errno(-RT_EFULL); - return 0; + audio->replay->write_data = rt_mp_alloc(audio->replay->mp, RT_WAITING_FOREVER); + memset(audio->replay->write_data, 0, block_size); + } + + /* copy data to replay memory pool */ + remain_bytes = MIN((block_size - audio->replay->write_index), (size - index)); + memcpy(&audio->replay->write_data[audio->replay->write_index], &ptr[index], remain_bytes); + + index += remain_bytes; + audio->replay->write_index += remain_bytes; + audio->replay->write_index %= block_size; + + if (audio->replay->write_index == 0) + { + rt_data_queue_push(&audio->replay->queue, + audio->replay->write_data, + block_size, + RT_WAITING_FOREVER); } } + rt_mutex_release(&audio->replay->lock); - //check tx state... - level = rt_hw_interrupt_disable(); + /* check replay state */ if (audio->replay->activated != RT_TRUE) { + _aduio_replay_start(audio); audio->replay->activated = RT_TRUE; - rt_hw_interrupt_enable(level); - - _audio_send_replay_frame(audio); - } - else - { - rt_hw_interrupt_enable(level); } - return size; + return index; } static rt_err_t _audio_dev_control(struct rt_device *dev, int cmd, void *args) @@ -292,112 +430,70 @@ static rt_err_t _audio_dev_control(struct rt_device *dev, int cmd, void *args) RT_ASSERT(dev != RT_NULL); audio = (struct rt_audio_device *) dev; - //dev stat... + /* dev stat...*/ switch (cmd) { - case AUDIO_CTL_GETCAPS: - { - struct rt_audio_caps *caps = (struct rt_audio_caps *) args; + case AUDIO_CTL_GETCAPS: + { + struct rt_audio_caps *caps = (struct rt_audio_caps *) args; - AUDIO_DBG("AUDIO_CTL_GETCAPS: main_type = %d,sub_type = %d\n",caps->main_type,caps->sub_type); - if (audio->ops->getcaps != RT_NULL) - { - result = audio->ops->getcaps(audio, caps); - } - } - break; - case AUDIO_CTL_CONFIGURE: + LOG_D("AUDIO_CTL_GETCAPS: main_type = %d,sub_type = %d", caps->main_type, caps->sub_type); + if (audio->ops->getcaps != RT_NULL) { - struct rt_audio_caps *caps = (struct rt_audio_caps *) args; - - AUDIO_DBG("AUDIO_CTL_CONFIGURE: main_type = %d,sub_type = %d\n",caps->main_type,caps->sub_type); - if (audio->ops->configure != RT_NULL) - { - result = audio->ops->configure(audio, caps); - } + result = audio->ops->getcaps(audio, caps); } break; - case AUDIO_CTL_SHUTDOWN: - { - AUDIO_DBG("AUDIO_CTL_SHUTDOWN\n"); - - if (audio->ops->shutdown != RT_NULL) - result = audio->ops->shutdown(audio); + } - //flush replay frame... - _audio_flush_replay_frame(audio); - } - break; + case AUDIO_CTL_CONFIGURE: + { + struct rt_audio_caps *caps = (struct rt_audio_caps *) args; - case AUDIO_CTL_START: + LOG_D("AUDIO_CTL_CONFIGURE: main_type = %d,sub_type = %d", caps->main_type, caps->sub_type); + if (audio->ops->configure != RT_NULL) { - int stream = *(int *) args; - - AUDIO_DBG("AUDIO_CTL_START: stream = %d\n",stream); - if (audio->ops->start != RT_NULL) - result = audio->ops->start(audio, stream); + result = audio->ops->configure(audio, caps); } + break; - case AUDIO_CTL_STOP: - { - int stream = *(int *) args; + } - AUDIO_DBG("AUDIO_CTL_STOP: stream = %d\n",stream); - if (audio->ops->start != RT_NULL) - result = audio->ops->stop(audio, stream); + case AUDIO_CTL_START: + { + int stream = *(int *) args; - if (stream == AUDIO_STREAM_REPLAY) - { - _audio_flush_replay_frame(audio); - } - } - break; - case AUDIO_CTL_PAUSE: + LOG_D("AUDIO_CTL_START: stream = %d", stream); + if (stream == AUDIO_STREAM_REPLAY) { - int stream = *(int *) args; - - AUDIO_DBG("AUDIO_CTL_PAUSE: stream = %d\n",stream); - if (audio->ops->start != RT_NULL) - result = audio->ops->suspend(audio, stream); + result = _aduio_replay_start(audio); } - break; - case AUDIO_CTL_RESUME: + else { - int stream = *(int *) args; - - AUDIO_DBG("AUDIO_CTL_RESUME: stream = %d\n",stream); - if (audio->ops->start != RT_NULL) - result = audio->ops->resume(audio, stream); - - //resume tx frame... - if (stream == AUDIO_STREAM_REPLAY) - _audio_send_replay_frame(audio); + result = _audio_record_start(audio); } + break; - case AUDIO_CTL_ALLOCBUFFER: - { - struct rt_audio_buf_desc *desc = (struct rt_audio_buf_desc *) args; + } - if (desc) - { - desc->data_size = AUDIO_DEVICE_DECODE_MP_BLOCK_SZ * 2; - desc->data_ptr = rt_mp_alloc(&audio->mp, RT_WAITING_FOREVER); + case AUDIO_CTL_STOP: + { + int stream = *(int *) args; - result = RT_EOK; - } - else result = -RT_EIO; + LOG_D("AUDIO_CTL_STOP: stream = %d", stream); + if (stream == AUDIO_STREAM_REPLAY) + { + result = _aduio_replay_stop(audio); } - break; - case AUDIO_CTL_FREEBUFFER: + else { - rt_uint8_t *data_ptr = (rt_uint8_t *) args; - if (data_ptr) - rt_mp_free(data_ptr); + result = _audio_record_stop(audio); } + break; - default: - result = audio->ops->control(audio, cmd, args); + } + + default: break; } @@ -418,7 +514,9 @@ const static struct rt_device_ops audio_ops = rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data) { + rt_err_t result = RT_EOK; struct rt_device *device; + RT_ASSERT(audio != RT_NULL); device = &(audio->parent); @@ -438,15 +536,14 @@ rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_u #endif device->user_data = data; - //init memory pool for replay - { - rt_uint8_t *mempool = rt_malloc(AUDIO_DEVICE_DECODE_MP_SZ); - rt_mp_init(&audio->mp, "adu_mp", mempool, AUDIO_DEVICE_DECODE_MP_SZ, - AUDIO_DEVICE_DECODE_MP_BLOCK_SZ * 2); - } - /* register a character device */ - return rt_device_register(device, name, flag | RT_DEVICE_FLAG_REMOVABLE); + result = rt_device_register(device, name, flag | RT_DEVICE_FLAG_REMOVABLE); + + /* initialize audio device */ + if (result == RT_EOK) + result = rt_device_init(device); + + return result; } int rt_audio_samplerate_to_speed(rt_uint32_t bitValue) @@ -454,43 +551,43 @@ int rt_audio_samplerate_to_speed(rt_uint32_t bitValue) int speed = 0; switch (bitValue) { - case AUDIO_SAMP_RATE_8K: - speed = 8000; + case AUDIO_SAMP_RATE_8K: + speed = 8000; break; - case AUDIO_SAMP_RATE_11K: - speed = 11052; + case AUDIO_SAMP_RATE_11K: + speed = 11052; break; - case AUDIO_SAMP_RATE_16K: - speed = 16000; + case AUDIO_SAMP_RATE_16K: + speed = 16000; break; - case AUDIO_SAMP_RATE_22K: - speed = 22050; + case AUDIO_SAMP_RATE_22K: + speed = 22050; break; - case AUDIO_SAMP_RATE_32K: - speed = 32000; + case AUDIO_SAMP_RATE_32K: + speed = 32000; break; - case AUDIO_SAMP_RATE_44K: - speed = 44100; + case AUDIO_SAMP_RATE_44K: + speed = 44100; break; - case AUDIO_SAMP_RATE_48K: - speed = 48000; + case AUDIO_SAMP_RATE_48K: + speed = 48000; break; - case AUDIO_SAMP_RATE_96K: - speed = 96000; + case AUDIO_SAMP_RATE_96K: + speed = 96000; break; - case AUDIO_SAMP_RATE_128K: - speed = 128000; + case AUDIO_SAMP_RATE_128K: + speed = 128000; break; - case AUDIO_SAMP_RATE_160K: - speed = 160000; + case AUDIO_SAMP_RATE_160K: + speed = 160000; break; - case AUDIO_SAMP_RATE_172K: - speed = 176400; + case AUDIO_SAMP_RATE_172K: + speed = 176400; break; - case AUDIO_SAMP_RATE_192K: - speed = 192000; + case AUDIO_SAMP_RATE_192K: + speed = 192000; break; - default: + default: break; } @@ -498,46 +595,18 @@ int rt_audio_samplerate_to_speed(rt_uint32_t bitValue) return speed; } -rt_uint32_t rt_audio_format_to_bits(rt_uint32_t format) +void rt_audio_tx_complete(struct rt_audio_device *audio) { - switch (format) - { - case AUDIO_FMT_PCM_U8: - case AUDIO_FMT_PCM_S8: - return 8; - case AUDIO_FMT_PCM_S16_LE: - case AUDIO_FMT_PCM_S16_BE: - case AUDIO_FMT_PCM_U16_LE: - case AUDIO_FMT_PCM_U16_BE: - return 16; - default: - return 32; - }; -} - -void rt_audio_tx_complete(struct rt_audio_device *audio, rt_uint8_t *pbuf) -{ - rt_err_t result; - AUDIO_DBG("audio tx complete ptr=%x...\n",(rt_uint32_t)pbuf); - - //try to send all frame - do - { - result = _audio_send_replay_frame(audio); - } while (result == RT_EOK); - - /* notify transmitted complete. */ - if (audio->parent.tx_complete != RT_NULL) - audio->parent.tx_complete(&audio->parent, (void *) pbuf); + /* try to send next frame */ + _audio_send_replay_frame(audio); } void rt_audio_rx_done(struct rt_audio_device *audio, rt_uint8_t *pbuf, rt_size_t len) { - //save data to record pipe - rt_device_write(RT_DEVICE(RT_DEVICE(&audio_pipe)), 0, pbuf, len); + /* save data to record pipe */ + rt_device_write(RT_DEVICE(&audio->record->pipe), 0, pbuf, len); /* invoke callback */ if (audio->parent.rx_indicate != RT_NULL) audio->parent.rx_indicate(&audio->parent, len); } - diff --git a/components/drivers/audio/audio_pipe.c b/components/drivers/audio/audio_pipe.c index 4df9fd8a49..d7c37009b6 100644 --- a/components/drivers/audio/audio_pipe.c +++ b/components/drivers/audio/audio_pipe.c @@ -24,8 +24,8 @@ static void _rt_pipe_resume_writer(struct rt_audio_pipe *pipe) /* get suspended thread */ thread = rt_list_entry(pipe->suspended_write_list.next, - struct rt_thread, - tlist); + struct rt_thread, + tlist); /* resume the write thread */ rt_thread_resume(thread); @@ -50,7 +50,7 @@ static rt_size_t rt_pipe_read(rt_device_t dev, if (!(pipe->flag & RT_PIPE_FLAG_BLOCK_RD)) { level = rt_hw_interrupt_disable(); - read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), buffer, size); + read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), (rt_uint8_t *)buffer, size); /* if the ringbuffer is empty, there won't be any writer waiting */ if (read_nbytes) @@ -66,9 +66,10 @@ static rt_size_t rt_pipe_read(rt_device_t dev, /* current context checking */ RT_DEBUG_NOT_IN_INTERRUPT; - do { + do + { level = rt_hw_interrupt_disable(); - read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), buffer, size); + read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), (rt_uint8_t *)buffer, size); if (read_nbytes == 0) { rt_thread_suspend(thread); @@ -85,7 +86,8 @@ static rt_size_t rt_pipe_read(rt_device_t dev, rt_hw_interrupt_enable(level); break; } - } while (read_nbytes == 0); + } + while (read_nbytes == 0); return read_nbytes; } @@ -104,8 +106,8 @@ static void _rt_pipe_resume_reader(struct rt_audio_pipe *pipe) /* get suspended thread */ thread = rt_list_entry(pipe->suspended_read_list.next, - struct rt_thread, - tlist); + struct rt_thread, + tlist); /* resume the read thread */ rt_thread_resume(thread); @@ -128,16 +130,16 @@ static rt_size_t rt_pipe_write(rt_device_t dev, RT_ASSERT(pipe != RT_NULL); if ((pipe->flag & RT_PIPE_FLAG_FORCE_WR) || - !(pipe->flag & RT_PIPE_FLAG_BLOCK_WR)) + !(pipe->flag & RT_PIPE_FLAG_BLOCK_WR)) { level = rt_hw_interrupt_disable(); if (pipe->flag & RT_PIPE_FLAG_FORCE_WR) write_nbytes = rt_ringbuffer_put_force(&(pipe->ringbuffer), - buffer, size); + (const rt_uint8_t *)buffer, size); else write_nbytes = rt_ringbuffer_put(&(pipe->ringbuffer), - buffer, size); + (const rt_uint8_t *)buffer, size); _rt_pipe_resume_reader(pipe); @@ -151,9 +153,10 @@ static rt_size_t rt_pipe_write(rt_device_t dev, /* current context checking */ RT_DEBUG_NOT_IN_INTERRUPT; - do { + do + { level = rt_hw_interrupt_disable(); - write_nbytes = rt_ringbuffer_put(&(pipe->ringbuffer), buffer, size); + write_nbytes = rt_ringbuffer_put(&(pipe->ringbuffer), (const rt_uint8_t *)buffer, size); if (write_nbytes == 0) { /* pipe full, waiting on suspended write list */ @@ -171,7 +174,8 @@ static rt_size_t rt_pipe_write(rt_device_t dev, rt_hw_interrupt_enable(level); break; } - } while (write_nbytes == 0); + } + while (write_nbytes == 0); return write_nbytes; } @@ -183,7 +187,7 @@ static rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args) pipe = (struct rt_audio_pipe *)dev; if (cmd == PIPE_CTRL_GET_SPACE && args) - *(rt_size_t*)args = rt_ringbuffer_space_len(&pipe->ringbuffer); + *(rt_size_t *)args = rt_ringbuffer_space_len(&pipe->ringbuffer); return RT_EOK; } @@ -212,10 +216,10 @@ const static struct rt_device_ops audio_pipe_ops = * @return the operation status, RT_EOK on successful */ rt_err_t rt_audio_pipe_init(struct rt_audio_pipe *pipe, - const char *name, - rt_int32_t flag, - rt_uint8_t *buf, - rt_size_t size) + const char *name, + rt_int32_t flag, + rt_uint8_t *buf, + rt_size_t size) { RT_ASSERT(pipe); RT_ASSERT(buf); @@ -270,7 +274,7 @@ rt_err_t rt_audio_pipe_create(const char *name, rt_int32_t flag, rt_size_t size) return -RT_ENOMEM; /* create ring buffer of pipe */ - rb_memptr = rt_malloc(size); + rb_memptr = (rt_uint8_t *)rt_malloc(size); if (rb_memptr == RT_NULL) { rt_free(pipe); diff --git a/components/drivers/can/can.c b/components/drivers/can/can.c index 0769c79fd7..3d60dbaa55 100644 --- a/components/drivers/can/can.c +++ b/components/drivers/can/can.c @@ -27,10 +27,15 @@ static rt_err_t rt_can_init(struct rt_device *dev) /* initialize rx/tx */ can->can_rx = RT_NULL; can->can_tx = RT_NULL; +#ifdef RT_CAN_USING_HDR + can->hdr = RT_NULL; +#endif /* apply configuration */ if (can->ops->configure) result = can->ops->configure(can, &can->config); + else + result = -RT_ENOSYS; return result; } @@ -293,7 +298,7 @@ static rt_err_t rt_can_open(struct rt_device *dev, rt_uint16_t oflag) can->can_rx = rx_fifo; dev->open_flag |= RT_DEVICE_FLAG_INT_RX; - /* configure low level device */ + /* open can rx interrupt */ can->ops->control(can, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX); } } @@ -311,7 +316,7 @@ static rt_err_t rt_can_open(struct rt_device *dev, rt_uint16_t oflag) tx_fifo->buffer = (struct rt_can_sndbxinx_list *)(tx_fifo + 1); rt_memset(tx_fifo->buffer, 0, - can->config.sndboxnumber * sizeof(struct rt_can_sndbxinx_list)); + can->config.sndboxnumber * sizeof(struct rt_can_sndbxinx_list)); rt_list_init(&tx_fifo->freelist); for (i = 0; i < can->config.sndboxnumber; i++) { @@ -325,7 +330,7 @@ static rt_err_t rt_can_open(struct rt_device *dev, rt_uint16_t oflag) can->can_tx = tx_fifo; dev->open_flag |= RT_DEVICE_FLAG_INT_TX; - /* configure low level device */ + /* open can tx interrupt */ can->ops->control(can, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_TX); } } @@ -406,7 +411,7 @@ static rt_err_t rt_can_close(struct rt_device *dev) rt_free(rx_fifo); dev->open_flag &= ~RT_DEVICE_FLAG_INT_RX; can->can_rx = RT_NULL; - /* configure low level device */ + /* clear can rx interrupt */ can->ops->control(can, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX); } @@ -420,7 +425,7 @@ static rt_err_t rt_can_close(struct rt_device *dev) rt_free(tx_fifo); dev->open_flag &= ~RT_DEVICE_FLAG_INT_TX; can->can_tx = RT_NULL; - /* configure low level device */ + /* clear can tx interrupt */ can->ops->control(can, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_TX); } @@ -484,6 +489,7 @@ static rt_err_t rt_can_control(struct rt_device *dev, struct rt_can_device *can; rt_err_t res; + res = RT_EOK; RT_ASSERT(dev != RT_NULL); can = (struct rt_can_device *)dev; @@ -501,8 +507,9 @@ static rt_err_t rt_can_control(struct rt_device *dev, case RT_DEVICE_CTRL_CONFIG: /* configure device */ - can->ops->configure(can, (struct can_configure *)args); + res = can->ops->configure(can, (struct can_configure *)args); break; + case RT_CAN_CMD_SET_PRIV: /* configure device */ if ((rt_uint32_t)args != can->config.privmode) @@ -513,7 +520,6 @@ static rt_err_t rt_can_control(struct rt_device *dev, res = can->ops->control(can, cmd, args); if (res != RT_EOK) return res; - tx_fifo = (struct rt_can_tx_fifo *) can->can_tx; if (can->config.privmode) { @@ -522,11 +528,11 @@ static rt_err_t rt_can_control(struct rt_device *dev, level = rt_hw_interrupt_disable(); if(rt_list_isempty(&tx_fifo->buffer[i].list)) { - rt_sem_release(&(tx_fifo->sem)); + rt_sem_release(&(tx_fifo->sem)); } else { - rt_list_remove(&tx_fifo->buffer[i].list); + rt_list_remove(&tx_fifo->buffer[i].list); } rt_hw_interrupt_enable(level); } @@ -544,7 +550,6 @@ static rt_err_t rt_can_control(struct rt_device *dev, rt_hw_interrupt_enable(level); } } - return RT_EOK; } break; @@ -561,74 +566,73 @@ static rt_err_t rt_can_control(struct rt_device *dev, return res; } - { - struct rt_can_filter_config *pfilter; - struct rt_can_filter_item *pitem; - rt_uint32_t count; - rt_base_t level; + struct rt_can_filter_config *pfilter; + struct rt_can_filter_item *pitem; + rt_uint32_t count; + rt_base_t level; - pfilter = (struct rt_can_filter_config *)args; - count = pfilter->count; - pitem = pfilter->items; - if (pfilter->actived) + pfilter = (struct rt_can_filter_config *)args; + RT_ASSERT(pfilter); + count = pfilter->count; + pitem = pfilter->items; + if (pfilter->actived) + { + while (count) { - while (count) + if (pitem->hdr >= can->config.maxhdr || pitem->hdr < 0) { - if (pitem->hdr >= can->config.maxhdr || pitem->hdr < 0) - { - count--; - pitem++; - continue; - } - - level = rt_hw_interrupt_disable(); - if (!can->hdr[pitem->hdr].connected) - { - rt_hw_interrupt_enable(level); - rt_memcpy(&can->hdr[pitem->hdr].filter, pitem, - sizeof(struct rt_can_filter_item)); - level = rt_hw_interrupt_disable(); - can->hdr[pitem->hdr].connected = 1; - can->hdr[pitem->hdr].msgs = 0; - rt_list_init(&can->hdr[pitem->hdr].list); - } - rt_hw_interrupt_enable(level); - count--; pitem++; + continue; } + + level = rt_hw_interrupt_disable(); + if (!can->hdr[pitem->hdr].connected) + { + rt_hw_interrupt_enable(level); + rt_memcpy(&can->hdr[pitem->hdr].filter, pitem, + sizeof(struct rt_can_filter_item)); + level = rt_hw_interrupt_disable(); + can->hdr[pitem->hdr].connected = 1; + can->hdr[pitem->hdr].msgs = 0; + rt_list_init(&can->hdr[pitem->hdr].list); + } + rt_hw_interrupt_enable(level); + + count--; + pitem++; } - else + } + else + { + while (count) { - while (count) + if (pitem->hdr >= can->config.maxhdr || pitem->hdr < 0) { - if (pitem->hdr >= can->config.maxhdr || pitem->hdr < 0) - { - count--; - pitem++; - continue; - } - level = rt_hw_interrupt_disable(); + count--; + pitem++; + continue; + } + level = rt_hw_interrupt_disable(); - if (can->hdr[pitem->hdr].connected) + if (can->hdr[pitem->hdr].connected) + { + can->hdr[pitem->hdr].connected = 0; + can->hdr[pitem->hdr].msgs = 0; + if (!rt_list_isempty(&can->hdr[pitem->hdr].list)) { - can->hdr[pitem->hdr].connected = 0; - can->hdr[pitem->hdr].msgs = 0; - if (!rt_list_isempty(&can->hdr[pitem->hdr].list)) - { - rt_list_remove(can->hdr[pitem->hdr].list.next); - } - rt_hw_interrupt_enable(level); - rt_memset(&can->hdr[pitem->hdr].filter, 0, - sizeof(struct rt_can_filter_item)); + rt_list_remove(can->hdr[pitem->hdr].list.next); } - else - { - rt_hw_interrupt_enable(level); - } - count--; - pitem++; + rt_hw_interrupt_enable(level); + rt_memset(&can->hdr[pitem->hdr].filter, 0, + sizeof(struct rt_can_filter_item)); + } + else + { + rt_hw_interrupt_enable(level); } + count--; + pitem++; } } break; @@ -642,12 +646,16 @@ static rt_err_t rt_can_control(struct rt_device *dev, /* control device */ if (can->ops->control != RT_NULL) { - can->ops->control(can, cmd, args); + res = can->ops->control(can, cmd, args); + } + else + { + res = -RT_ENOSYS; } break; } - return RT_EOK; + return res; } /* @@ -655,8 +663,10 @@ static rt_err_t rt_can_control(struct rt_device *dev, */ static void cantimeout(void *arg) { - rt_can_t can = (rt_can_t)arg; + rt_can_t can; + can = (rt_can_t)arg; + RT_ASSERT(can); rt_device_control((rt_device_t)can, RT_CAN_CMD_GET_STATUS, (void *)&can->status); if (can->status_indicate.ind != RT_NULL) @@ -690,7 +700,7 @@ const static struct rt_device_ops can_device_ops = /* * can register */ -rt_err_t rt_hw_can_register(struct rt_can_device *can, +rt_err_t rt_hw_can_register(struct rt_can_device *can, const char *name, const struct rt_can_ops *ops, void *data) @@ -843,7 +853,10 @@ void rt_hw_can_isr(struct rt_can_device *can, int event) level = rt_hw_interrupt_disable(); rx_length = can->hdr[hdr].msgs * sizeof(struct rt_can_msg); rt_hw_interrupt_enable(level); - can->hdr[hdr].filter.ind(&can->parent, can->hdr[hdr].filter.args, hdr, rx_length); + if (rx_length) + { + can->hdr[hdr].filter.ind(&can->parent, can->hdr[hdr].filter.args, hdr, rx_length); + } } else #endif @@ -857,7 +870,10 @@ void rt_hw_can_isr(struct rt_can_device *can, int event) rx_length = rt_list_len(&rx_fifo->uselist)* sizeof(struct rt_can_msg); rt_hw_interrupt_enable(level); - can->parent.rx_indicate(&can->parent, rx_length); + if (rx_length) + { + can->parent.rx_indicate(&can->parent, rx_length); + } } } break; diff --git a/components/drivers/hwcrypto/SConscript b/components/drivers/hwcrypto/SConscript new file mode 100644 index 0000000000..90feff50b3 --- /dev/null +++ b/components/drivers/hwcrypto/SConscript @@ -0,0 +1,34 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() +CPPPATH = [cwd, str(Dir('#'))] + +src = ['hwcrypto.c'] + +if (GetDepend(['RT_HWCRYPTO_USING_AES']) or + GetDepend(['RT_HWCRYPTO_USING_DES']) or + GetDepend(['RT_HWCRYPTO_USING_3DES']) or + GetDepend(['RT_HWCRYPTO_USING_RC4'])): + src += ['hw_symmetric.c'] + if GetDepend(['RT_HWCRYPTO_USING_GCM']): + src += ['hw_gcm.c'] + +if (GetDepend(['RT_HWCRYPTO_USING_MD5']) or + GetDepend(['RT_HWCRYPTO_USING_SHA1']) or + GetDepend(['RT_HWCRYPTO_USING_SHA2'])): + src += ['hw_hash.c'] + +if GetDepend(['RT_HWCRYPTO_USING_RNG']): + src += ['hw_rng.c'] + +if GetDepend(['RT_HWCRYPTO_USING_CRC']): + src += ['hw_crc.c'] + +if GetDepend(['RT_HWCRYPTO_USING_BIGNUM']): + src += ['hw_bignum.c'] + +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_HWCRYPTO'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/hwcrypto/hw_bignum.c b/components/drivers/hwcrypto/hw_bignum.c new file mode 100644 index 0000000000..88813566b1 --- /dev/null +++ b/components/drivers/hwcrypto/hw_bignum.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_bignum.h> + +static struct rt_hwcrypto_ctx *bignum_default; + +rt_inline rt_err_t hwcrypto_bignum_dev_is_init(void) +{ + struct rt_hwcrypto_device *dev; + + if (bignum_default) + { + return RT_EOK; + } + dev = rt_hwcrypto_dev_default(); + if (dev == RT_NULL) + { + return -RT_ERROR; + } + return rt_hwcrypto_bignum_default(dev); +} + +/** + * @brief Setting bignum default devices + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_default(struct rt_hwcrypto_device *device) +{ + if (bignum_default) + { + rt_hwcrypto_ctx_destroy(bignum_default); + bignum_default = RT_NULL; + } + if (device == RT_NULL) + { + return RT_EOK; + } + bignum_default = rt_hwcrypto_ctx_create(device, HWCRYPTO_TYPE_BIGNUM, sizeof(struct hwcrypto_bignum)); + if (bignum_default == RT_NULL) + { + return -RT_ERROR; + } + return RT_EOK; +} + +/** + * @brief Init bignum obj + * + * @param n bignum obj + */ +void rt_hwcrypto_bignum_init(struct hw_bignum_mpi *n) +{ + if(n == RT_NULL) + return; + + n->sign = 1; + n->total = 0; + n->p = RT_NULL; +} + +/** + * @brief free a bignum obj + * + * @param Pointer to bignum obj + */ +void rt_hwcrypto_bignum_free(struct hw_bignum_mpi *n) +{ + if (n) + { + rt_free(n->p); + n->sign = 0; + n->total = 0; + n->p = RT_NULL; + } +} + +/** + * @brief Get length of bignum as an unsigned binary buffer + * + * @param n bignum obj + * + * @return binary buffer length + */ +int rt_hwcrypto_bignum_get_len(const struct hw_bignum_mpi *n) +{ + int tmp_len, total; + + if (n == RT_NULL || n->p == RT_NULL) + { + return 0; + } + tmp_len = 0; + total = n->total; + while ((total > 0) && (n->p[total - 1] == 0)) + { + tmp_len++; + total--; + } + return n->total - tmp_len; +} + +/** + * @brief Export n into unsigned binary data, big endian + * + * @param n bignum obj + * @param buf Buffer for the binary number + * @param len Length of the buffer + * + * @return export bin length + */ +int rt_hwcrypto_bignum_export_bin(struct hw_bignum_mpi *n, rt_uint8_t *buf, int len) +{ + int cp_len, i, j; + + if (n == RT_NULL || buf == RT_NULL) + { + return 0; + } + rt_memset(buf, 0, len); + cp_len = n->total > len ? len : n->total; + for(i = cp_len, j = 0; i > 0; i--, j++) + { + buf[i - 1] = n->p[j]; + } + + return cp_len; +} + +/** + * @brief Import n from unsigned binary data, big endian + * + * @param n bignum obj + * @param buf Buffer for the binary number + * @param len Length of the buffer + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_import_bin(struct hw_bignum_mpi *n, rt_uint8_t *buf, int len) +{ + int cp_len, i, j; + void *temp_p; + + if (n == RT_NULL || buf == RT_NULL) + { + return 0; + } + if (n->total < len) + { + temp_p = rt_malloc(len); + if (temp_p == RT_NULL) + { + return 0; + } + rt_memset(temp_p, 0, len); + rt_free(n->p); + n->p = temp_p; + n->total = len; + } + cp_len = n->total > len ? len : n->total; + + for(i = cp_len, j = 0; i > 0; i--, j++) + { + n->p[j] = buf[i - 1]; + } + + return cp_len; +} + +/** + * @brief x = a + b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_add(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b) +{ + struct hwcrypto_bignum *bignum_ctx; + + if (hwcrypto_bignum_dev_is_init() != RT_EOK) + { + return -RT_ERROR; + } + bignum_ctx = (struct hwcrypto_bignum *)bignum_default; + if (bignum_ctx->ops->add) + { + return bignum_ctx->ops->add(bignum_ctx, x, a, b); + } + return -RT_ERROR; +} + +/** + * @brief x = a - b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_sub(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b) +{ + struct hwcrypto_bignum *bignum_ctx; + + if (hwcrypto_bignum_dev_is_init() != RT_EOK) + { + return -RT_ERROR; + } + bignum_ctx = (struct hwcrypto_bignum *)bignum_default; + if (bignum_ctx->ops->sub) + { + return bignum_ctx->ops->sub(bignum_ctx, x, a, b); + } + return -RT_ERROR; +} + +/** + * @brief x = a * b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_mul(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b) +{ + struct hwcrypto_bignum *bignum_ctx; + + if (hwcrypto_bignum_dev_is_init() != RT_EOK) + { + return -RT_ERROR; + } + bignum_ctx = (struct hwcrypto_bignum *)bignum_default; + if (bignum_ctx->ops->mul) + { + return bignum_ctx->ops->mul(bignum_ctx, x, a, b); + } + return -RT_ERROR; +} + +/** + * @brief x = a * b (mod c) + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_mulmod(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c) +{ + struct hwcrypto_bignum *bignum_ctx; + + if (hwcrypto_bignum_dev_is_init() != RT_EOK) + { + return -RT_ERROR; + } + bignum_ctx = (struct hwcrypto_bignum *)bignum_default; + if (bignum_ctx->ops->mulmod) + { + return bignum_ctx->ops->mulmod(bignum_ctx, x, a, b, c); + } + return -RT_ERROR; +} + +/** + * @brief x = a ^ b (mod c) + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_exptmod(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c) +{ + struct hwcrypto_bignum *bignum_ctx; + + if (hwcrypto_bignum_dev_is_init() != RT_EOK) + { + return -RT_ERROR; + } + bignum_ctx = (struct hwcrypto_bignum *)bignum_default; + if (bignum_ctx->ops->exptmod) + { + return bignum_ctx->ops->exptmod(bignum_ctx, x, a, b, c); + } + return -RT_ERROR; +} diff --git a/components/drivers/hwcrypto/hw_bignum.h b/components/drivers/hwcrypto/hw_bignum.h new file mode 100644 index 0000000000..a1f567e68f --- /dev/null +++ b/components/drivers/hwcrypto/hw_bignum.h @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#ifndef __HW_BIGNUM_H__ +#define __HW_BIGNUM_H__ + +#include <hwcrypto.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_bignum; + +/* bignum obj */ +struct hw_bignum_mpi +{ + int sign; /**< integer sign */ + rt_size_t total; /**< total of limbs */ + rt_uint8_t *p; /**< pointer to limbs */ +}; + +struct hwcrypto_bignum_ops +{ + rt_err_t (*add)(struct hwcrypto_bignum *bignum_ctx, + struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); /**< x = a + b */ + rt_err_t (*sub)(struct hwcrypto_bignum *bignum_ctx, + struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); /**< x = a - b */ + rt_err_t (*mul)(struct hwcrypto_bignum *bignum_ctx, + struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); /**< x = a * b */ + rt_err_t (*mulmod)(struct hwcrypto_bignum *bignum_ctx, + struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c); /**< x = a * b (mod c) */ + rt_err_t (*exptmod)(struct hwcrypto_bignum *bignum_ctx, + struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c); /**< x = a ^ b (mod c) */ +}; + +/** + * @brief bignum context. Hardware driver usage + */ +struct hwcrypto_bignum +{ + struct rt_hwcrypto_ctx parent; /**< Inheritance from hardware crypto context */ + const struct hwcrypto_bignum_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Setting bignum default devices + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_default(struct rt_hwcrypto_device *device); + +/** + * @brief Init bignum obj + */ +void rt_hwcrypto_bignum_init(struct hw_bignum_mpi *n); + +/** + * @brief free a bignum obj + * + * @param Pointer to bignum obj + */ +void rt_hwcrypto_bignum_free(struct hw_bignum_mpi *n); + +/** + * @brief Get length of bignum as an unsigned binary buffer + * + * @param n bignum obj + * + * @return binary buffer Length + */ +int rt_hwcrypto_bignum_get_len(const struct hw_bignum_mpi *n); + +/** + * @brief Export n into unsigned binary data, big endian + * + * @param n bignum obj + * @param buf Buffer for the binary number + * @param len Length of the buffer + * + * @return export bin length + */ +int rt_hwcrypto_bignum_export_bin(struct hw_bignum_mpi *n, rt_uint8_t *buf, int len); + +/** + * @brief Import n from unsigned binary data, big endian + * + * @param n bignum obj + * @param buf Buffer for the binary number + * @param len Length of the buffer + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_import_bin(struct hw_bignum_mpi *n, rt_uint8_t *buf, int len); + +/** + * @brief x = a + b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_add(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); + +/** + * @brief x = a - b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_sub(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); + +/** + * @brief x = a * b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_mul(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); + +/** + * @brief x = a * b (mod c) + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_mulmod(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c); + +/** + * @brief x = a ^ b (mod c) + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_exptmod(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hw_crc.c b/components/drivers/hwcrypto/hw_crc.c new file mode 100644 index 0000000000..20579711e2 --- /dev/null +++ b/components/drivers/hwcrypto/hw_crc.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_crc.h> + +/** + * @brief Creating CRC Context + * + * @param device Hardware crypto device + * @param mode Setting default mode or custom mode + * + * @return CRC context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_crc_create(struct rt_hwcrypto_device *device, + hwcrypto_crc_mode mode) +{ + struct hwcrypto_crc *crc_ctx; + + crc_ctx = (struct hwcrypto_crc *)rt_hwcrypto_ctx_create(device, HWCRYPTO_TYPE_CRC, sizeof(struct hwcrypto_crc)); + if (crc_ctx == RT_NULL) + { + return RT_NULL; + } + + switch (mode) + { + case HWCRYPTO_CRC_CRC8: + { + struct hwcrypto_crc_cfg temp = HWCRYPTO_CRC8_CFG; + crc_ctx->crc_cfg = temp; + break; + } + case HWCRYPTO_CRC_CRC16: + { + struct hwcrypto_crc_cfg temp = HWCRYPTO_CRC16_CFG; + crc_ctx->crc_cfg = temp; + break; + } + case HWCRYPTO_CRC_CRC32: + { + struct hwcrypto_crc_cfg temp = HWCRYPTO_CRC32_CFG; + crc_ctx->crc_cfg = temp; + break; + } + case HWCRYPTO_CRC_CCITT: + { + struct hwcrypto_crc_cfg temp = HWCRYPTO_CRC_CCITT_CFG; + crc_ctx->crc_cfg = temp; + break; + } + case HWCRYPTO_CRC_DNP: + { + struct hwcrypto_crc_cfg temp = HWCRYPTO_CRC_DNP_CFG; + crc_ctx->crc_cfg = temp; + break; + } + default: + break; + } + + return &crc_ctx->parent; +} + +/** + * @brief Destroy CRC Context + * + * @param ctx CRC context + */ +void rt_hwcrypto_crc_destroy(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_ctx_destroy(ctx); +} + +/** + * @brief Processing a packet of data + * + * @param ctx CRC context + * @param input Data buffer to be Processed + * @param length Data Buffer length + * + * @return RT_EOK on success. + */ +rt_uint32_t rt_hwcrypto_crc_update(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *input, + rt_size_t length) +{ + struct hwcrypto_crc *crc_ctx = (struct hwcrypto_crc *)ctx; + if (ctx && crc_ctx->ops->update) + { + return crc_ctx->ops->update(crc_ctx, input, length); + } + return 0; +} + +/** + * @brief CRC context configuration + * + * @param ctx CRC context + * @param cfg CRC config + */ +void rt_hwcrypto_crc_cfg(struct rt_hwcrypto_ctx *ctx, + struct hwcrypto_crc_cfg *cfg) +{ + if (cfg) + { + ((struct hwcrypto_crc *)ctx)->crc_cfg = *cfg; + } +} diff --git a/components/drivers/hwcrypto/hw_crc.h b/components/drivers/hwcrypto/hw_crc.h new file mode 100644 index 0000000000..a6df92a2ef --- /dev/null +++ b/components/drivers/hwcrypto/hw_crc.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#ifndef __HW_CRC_H__ +#define __HW_CRC_H__ + +#include <hwcrypto.h> + +#define CRC_FLAG_REFIN (0x1 << 0) +#define CRC_FLAG_REFOUT (0x1 << 1) + +#define HWCRYPTO_CRC8_CFG \ +{ \ + .last_val = 0x00, \ + .poly = 0x07, \ + .width = 8, \ + .xorout = 0x00, \ + .flags = 0, \ +} + +#define HWCRYPTO_CRC16_CFG \ +{ \ + .last_val = 0x0000, \ + .poly = 0x8005, \ + .width = 16, \ + .xorout = 0x0000, \ + .flags = 0, \ +} + +#define HWCRYPTO_CRC32_CFG \ +{ \ + .last_val = 0x00000000, \ + .poly = 0x04C11DB7, \ + .width = 32, \ + .xorout = 0x00000000, \ + .flags = 0, \ +} + +#define HWCRYPTO_CRC_CCITT_CFG \ +{ \ + .last_val = 0x0000, \ + .poly = 0x1021, \ + .width = 16, \ + .xorout = 0x0000, \ + .flags = CRC_FLAG_REFIN | CRC_FLAG_REFOUT, \ +} + +#define HWCRYPTO_CRC_DNP_CFG \ +{ \ + .last_val = 0x0000, \ + .poly = 0x3D65, \ + .width = 16, \ + .xorout = 0xffff, \ + .flags = CRC_FLAG_REFIN | CRC_FLAG_REFOUT, \ +} + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_crc; + +typedef enum +{ + HWCRYPTO_CRC_CUSTOM, /**< Custom CRC mode */ + HWCRYPTO_CRC_CRC8, /**< poly : 0x07 */ + HWCRYPTO_CRC_CRC16, /**< poly : 0x8005 */ + HWCRYPTO_CRC_CRC32, /**< poly : 0x04C11DB7 */ + HWCRYPTO_CRC_CCITT, /**< poly : 0x1021 */ + HWCRYPTO_CRC_DNP, /**< poly : 0x3D65 */ +} hwcrypto_crc_mode; + +struct hwcrypto_crc_cfg +{ + rt_uint32_t last_val; /**< Last CRC value cache */ + rt_uint32_t poly; /**< CRC polynomial */ + rt_uint16_t width; /**< CRC value width */ + rt_uint32_t xorout; /**< Result XOR Value */ + rt_uint16_t flags; /**< Input or output data reverse. CRC_FLAG_REFIN or CRC_FLAG_REFOUT */ +}; + +struct hwcrypto_crc_ops +{ + rt_uint32_t (*update)(struct hwcrypto_crc *ctx, + const rt_uint8_t *in, rt_size_t length); /**< Perform a CRC calculation. return CRC value */ +}; + +/** + * @brief CRC context. Hardware driver usage + */ +struct hwcrypto_crc +{ + struct rt_hwcrypto_ctx parent; /**< Inherited from the standard device */ + struct hwcrypto_crc_cfg crc_cfg; /**< CRC configure */ + const struct hwcrypto_crc_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Creating CRC Context + * + * @param device Hardware crypto device + * @param mode Setting default mode or custom mode + * + * @return CRC context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_crc_create(struct rt_hwcrypto_device *device, + hwcrypto_crc_mode mode); + +/** + * @brief Destroy CRC Context + * + * @param ctx CRC context + */ +void rt_hwcrypto_crc_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Processing a packet of data + * + * @param ctx CRC context + * @param input Data buffer to be Processed + * @param length Data Buffer length + * + * @return CRC value + */ +rt_uint32_t rt_hwcrypto_crc_update(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *input, rt_size_t length); + +/** + * @brief CRC context configuration + * + * @param ctx CRC context + * @param cfg CRC config + */ +void rt_hwcrypto_crc_cfg(struct rt_hwcrypto_ctx *ctx, + struct hwcrypto_crc_cfg *cfg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hw_gcm.c b/components/drivers/hwcrypto/hw_gcm.c new file mode 100644 index 0000000000..8d0f49149a --- /dev/null +++ b/components/drivers/hwcrypto/hw_gcm.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-05-14 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_gcm.h> + +/** + * @brief Creating GCM Context + * + * @param device Hardware crypto device + * @param type Type of symmetric crypto context + * + * @return GCM context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_gcm_create(struct rt_hwcrypto_device *device, + hwcrypto_type crypt_type) +{ + struct rt_hwcrypto_ctx *ctx; + + ctx = rt_hwcrypto_ctx_create(device, HWCRYPTO_TYPE_GCM, sizeof(struct hwcrypto_gcm)); + if (ctx) + { + ((struct hwcrypto_gcm *)ctx)->crypt_type = crypt_type; + } + return ctx; +} + +/** + * @brief Destroy GCM Context + * + * @param ctx GCM context + */ +void rt_hwcrypto_gcm_destroy(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_ctx_destroy(ctx); +} + +/** + * @brief This function starts a GCM encryption or decryption operation + * + * @param ctx GCM context + * @param add The buffer holding the additional data + * @param add_len The length of the additional data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_start(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *add, + rt_size_t add_len) +{ + struct hwcrypto_gcm *gcm_ctx = (struct hwcrypto_gcm *)ctx; + + if (gcm_ctx && gcm_ctx->ops->start) + { + return gcm_ctx->ops->start(gcm_ctx, add, add_len); + } + return -RT_EINVAL; +} + +/** + * @brief This function finishes the GCM operation and generates the authentication tag + * + * @param ctx GCM context + * @param tag The buffer for holding the tag + * @param tag_len The length of the tag to generate + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_finish(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *tag, + rt_size_t tag_len) +{ + struct hwcrypto_gcm *gcm_ctx = (struct hwcrypto_gcm *)ctx; + + if (gcm_ctx && gcm_ctx->ops->finish) + { + return gcm_ctx->ops->finish(gcm_ctx, tag, tag_len); + } + return -RT_EINVAL; +} + +/** + * @brief This function performs a symmetric encryption or decryption operation + * + * @param ctx GCM context + * @param mode Operation mode. HWCRYPTO_MODE_ENCRYPT or HWCRYPTO_MODE_DECRYPT + * @param length The length of the input data in Bytes. This must be a multiple of the block size + * @param in The buffer holding the input data + * @param out The buffer holding the output data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_crypt(struct rt_hwcrypto_ctx *ctx, hwcrypto_mode mode, + rt_size_t length, const rt_uint8_t *in, rt_uint8_t *out) +{ + return rt_hwcrypto_symmetric_crypt(ctx, mode, length, in, out); +} + +/** + * @brief Set Symmetric Encryption and Decryption Key + * + * @param ctx GCM context + * @param key The crypto key + * @param bitlen The crypto key bit length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_setkey(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *key, rt_uint32_t bitlen) +{ + return rt_hwcrypto_symmetric_setkey(ctx, key, bitlen); +} + +/** + * @brief Get Symmetric Encryption and Decryption Key + * + * @param ctx GCM context + * @param key The crypto key buffer + * @param bitlen The crypto key bit length + * + * @return Key length of copy + */ +rt_err_t rt_hwcrypto_gcm_getkey(struct rt_hwcrypto_ctx *ctx, + rt_uint8_t *key, rt_uint32_t bitlen) +{ + return rt_hwcrypto_symmetric_getkey(ctx, key, bitlen); +} + +/** + * @brief Set Symmetric Encryption and Decryption initialization vector + * + * @param ctx GCM context + * @param iv The crypto initialization vector + * @param len The crypto initialization vector length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_setiv(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *iv, rt_size_t len) +{ + return rt_hwcrypto_symmetric_setiv(ctx, iv, len); +} + +/** + * @brief Get Symmetric Encryption and Decryption initialization vector + * + * @param ctx GCM context + * @param iv The crypto initialization vector buffer + * @param len The crypto initialization vector buffer length + * + * @return IV length of copy + */ +rt_err_t rt_hwcrypto_gcm_getiv(struct rt_hwcrypto_ctx *ctx, + rt_uint8_t *iv, rt_size_t len) +{ + return rt_hwcrypto_symmetric_getiv(ctx, iv, len); +} + +/** + * @brief Set offset in initialization vector + * + * @param ctx GCM context + * @param iv_off The offset in IV + */ +void rt_hwcrypto_gcm_set_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t iv_off) +{ + rt_hwcrypto_symmetric_set_ivoff(ctx, iv_off); +} + +/** + * @brief Get offset in initialization vector + * + * @param ctx GCM context + * @param iv_off It must point to a valid memory + */ +void rt_hwcrypto_gcm_get_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t *iv_off) +{ + rt_hwcrypto_symmetric_get_ivoff(ctx, iv_off); +} + +/** + * @brief This function copy GCM context + * + * @param des The destination GCM context + * @param src The GCM context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_cpy(struct rt_hwcrypto_ctx *des, + const struct rt_hwcrypto_ctx *src) +{ + struct hwcrypto_gcm *gcm_des = (struct hwcrypto_gcm *)des; + struct hwcrypto_gcm *gcm_src = (struct hwcrypto_gcm *)src; + + if (des != RT_NULL && src != RT_NULL) + { + gcm_des->crypt_type = gcm_src->crypt_type; + /* symmetric crypto context copy */ + return rt_hwcrypto_symmetric_cpy(des, src); + } + return -RT_EINVAL; +} + +/** + * @brief Reset GCM context + * + * @param ctx GCM context + */ +void rt_hwcrypto_gcm_reset(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_symmetric_reset(ctx); +} diff --git a/components/drivers/hwcrypto/hw_gcm.h b/components/drivers/hwcrypto/hw_gcm.h new file mode 100644 index 0000000000..a73b2b0634 --- /dev/null +++ b/components/drivers/hwcrypto/hw_gcm.h @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-05-14 tyx the first version + */ + +#ifndef __HW_GCM_H__ +#define __HW_GCM_H__ + +#include "hw_symmetric.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_gcm; + +struct hwcrypto_gcm_ops +{ + rt_err_t (*start)(struct hwcrypto_gcm *gcm_ctx, + const unsigned char *add, size_t add_len); /**< Set additional data. start GCM operation */ + rt_err_t (*finish)(struct hwcrypto_gcm *gcm_ctx, + const unsigned char *tag, size_t tag_len); /**< finish GCM operation. get tag */ +}; + +/** + * @brief GCM context. Hardware driver usage + */ +struct hwcrypto_gcm +{ + struct hwcrypto_symmetric parent; /**< Inheritance from hardware symmetric crypto context */ + hwcrypto_type crypt_type; /**< symmetric crypto type. eg: AES/DES */ + const struct hwcrypto_gcm_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Creating GCM Context + * + * @param device Hardware crypto device + * @param type Type of symmetric crypto context + * + * @return GCM context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_gcm_create(struct rt_hwcrypto_device *device, + hwcrypto_type crypt_type); + +/** + * @brief Destroy GCM Context + * + * @param ctx GCM context + */ +void rt_hwcrypto_gcm_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief This function starts a GCM encryption or decryption operation + * + * @param ctx GCM context + * @param add The buffer holding the additional data + * @param add_len The length of the additional data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_start(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *add, + rt_size_t add_len); + +/** + * @brief This function finishes the GCM operation and generates the authentication tag + * + * @param ctx GCM context + * @param tag The buffer for holding the tag + * @param tag_len The length of the tag to generate + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_finish(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *tag, + rt_size_t tag_len); + +/** + * @brief This function performs a symmetric encryption or decryption operation + * + * @param ctx GCM context + * @param mode Operation mode. HWCRYPTO_MODE_ENCRYPT or HWCRYPTO_MODE_DECRYPT + * @param length The length of the input data in Bytes. This must be a multiple of the block size + * @param in The buffer holding the input data + * @param out The buffer holding the output data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_crypt(struct rt_hwcrypto_ctx *ctx, hwcrypto_mode mode, + rt_size_t length, const rt_uint8_t *in, rt_uint8_t *out); + +/** + * @brief Set Symmetric Encryption and Decryption Key + * + * @param ctx GCM context + * @param key The crypto key + * @param bitlen The crypto key bit length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_setkey(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *key, rt_uint32_t bitlen); + +/** + * @brief Get Symmetric Encryption and Decryption Key + * + * @param ctx GCM context + * @param key The crypto key buffer + * @param bitlen The crypto key bit length + * + * @return Key length of copy + */ +rt_err_t rt_hwcrypto_gcm_getkey(struct rt_hwcrypto_ctx *ctx, + rt_uint8_t *key, rt_uint32_t bitlen); + +/** + * @brief Set Symmetric Encryption and Decryption initialization vector + * + * @param ctx GCM context + * @param iv The crypto initialization vector + * @param len The crypto initialization vector length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_setiv(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *iv, rt_size_t len); + +/** + * @brief Get Symmetric Encryption and Decryption initialization vector + * + * @param ctx GCM context + * @param iv The crypto initialization vector buffer + * @param len The crypto initialization vector buffer length + * + * @return IV length of copy + */ +rt_err_t rt_hwcrypto_gcm_getiv(struct rt_hwcrypto_ctx *ctx, + rt_uint8_t *iv, rt_size_t len); + +/** + * @brief Set offset in initialization vector + * + * @param ctx GCM context + * @param iv_off The offset in IV + */ +void rt_hwcrypto_gcm_set_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t iv_off); + +/** + * @brief Get offset in initialization vector + * + * @param ctx GCM context + * @param iv_off It must point to a valid memory + */ +void rt_hwcrypto_gcm_get_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t *iv_off); + +/** + * @brief This function copy GCM context + * + * @param des The destination GCM context + * @param src The GCM context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_cpy(struct rt_hwcrypto_ctx *des, + const struct rt_hwcrypto_ctx *src); + +/** + * @brief Reset GCM context + * + * @param ctx GCM context + */ +void rt_hwcrypto_gcm_reset(struct rt_hwcrypto_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hw_hash.c b/components/drivers/hwcrypto/hw_hash.c new file mode 100644 index 0000000000..b20069ac0e --- /dev/null +++ b/components/drivers/hwcrypto/hw_hash.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-23 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_hash.h> + +/** + * @brief Creating hash Context + * + * @param device Hardware crypto device + * @param type Type of hash context + * + * @return Hash context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_hash_create(struct rt_hwcrypto_device *device, hwcrypto_type type) +{ + struct rt_hwcrypto_ctx *ctx; + + ctx = rt_hwcrypto_ctx_create(device, type, sizeof(struct hwcrypto_hash)); + return ctx; +} + +/** + * @brief Destroy hash Context + * + * @param ctx Hash context + */ +void rt_hwcrypto_hash_destroy(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_ctx_destroy(ctx); +} + +/** + * @brief Get the final hash value + * + * @param ctx Hash context + * @param output Hash value buffer + * @param length Hash value buffer length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_finish(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *output, rt_size_t length) +{ + if (ctx && ((struct hwcrypto_hash *)ctx)->ops->finish) + { + return ((struct hwcrypto_hash *)ctx)->ops->finish((struct hwcrypto_hash *)ctx, output, length); + } + return -RT_ERROR; +} + +/** + * @brief Processing a packet of data + * + * @param ctx Hash context + * @param input Data buffer to be Processed + * @param length Data Buffer length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_update(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *input, rt_size_t length) +{ + if (ctx && ((struct hwcrypto_hash *)ctx)->ops->update) + { + return ((struct hwcrypto_hash *)ctx)->ops->update((struct hwcrypto_hash *)ctx, input, length); + } + return -RT_ERROR; +} + +/** + * @brief This function copy hash context + * + * @param des The destination hash context + * @param src The hash context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src) +{ + return rt_hwcrypto_ctx_cpy(des, src); +} + +/** + * @brief Reset hash context + * + * @param ctx Hash context + */ +void rt_hwcrypto_hash_reset(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_ctx_reset(ctx); +} + +/** + * @brief Setting hash context type + * + * @param ctx Hash context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type) +{ + return rt_hwcrypto_set_type(ctx, type); +} diff --git a/components/drivers/hwcrypto/hw_hash.h b/components/drivers/hwcrypto/hw_hash.h new file mode 100644 index 0000000000..de0310e84c --- /dev/null +++ b/components/drivers/hwcrypto/hw_hash.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-23 tyx the first version + */ + +#ifndef __HW_HASH_H__ +#define __HW_HASH_H__ + +#include <hwcrypto.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_hash; + +struct hwcrypto_hash_ops +{ + rt_err_t (*update)(struct hwcrypto_hash *hash_ctx, + const rt_uint8_t *in, rt_size_t length); /**< Processing a packet of data */ + rt_err_t (*finish)(struct hwcrypto_hash *hash_ctx, + rt_uint8_t *out, rt_size_t length); /**< Get the final hash value */ +}; + +/** + * @brief hash context. Hardware driver usage + */ +struct hwcrypto_hash +{ + struct rt_hwcrypto_ctx parent; /**< Inheritance from hardware crypto context */ + const struct hwcrypto_hash_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Creating hash Context + * + * @param device Hardware crypto device + * @param type Type of hash context + * + * @return Hash context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_hash_create(struct rt_hwcrypto_device *device, + hwcrypto_type type); + +/** + * @brief Destroy hash Context + * + * @param ctx Hash context + */ +void rt_hwcrypto_hash_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Get the final hash value + * + * @param ctx Hash context + * @param output Hash value buffer + * @param length Hash value buffer length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_finish(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *output, rt_size_t length); + +/** + * @brief Processing a packet of data + * + * @param ctx Hash context + * @param input Data buffer to be Processed + * @param length Data Buffer length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_update(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *input, rt_size_t length); + +/** + * @brief This function copy hash context + * + * @param des The destination hash context + * @param src The hash context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src); + +/** + * @brief Reset hash context + * + * @param ctx Hash context + */ +void rt_hwcrypto_hash_reset(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Setting hash context type + * + * @param ctx Hash context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hw_rng.c b/components/drivers/hwcrypto/hw_rng.c new file mode 100644 index 0000000000..13a17cc6be --- /dev/null +++ b/components/drivers/hwcrypto/hw_rng.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_rng.h> + +/* Used to save default RNG Context */ +static struct rt_hwcrypto_ctx *ctx_default; + +/** + * @brief Creating RNG Context + * + * @param device Hardware crypto device + * + * @return RNG context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_rng_create(struct rt_hwcrypto_device *device) +{ + struct rt_hwcrypto_ctx *ctx; + + ctx = rt_hwcrypto_ctx_create(device, HWCRYPTO_TYPE_RNG, sizeof(struct hwcrypto_rng)); + return ctx; +} + +/** + * @brief Destroy RNG Context + * + * @param ctx RNG context + */ +void rt_hwcrypto_rng_destroy(struct rt_hwcrypto_ctx *ctx) +{ + /* Destroy the defaule RNG Context ? */ + if (ctx == ctx_default) + { + ctx_default = RT_NULL; + } + rt_hwcrypto_ctx_destroy(ctx); +} + +/** + * @brief Setting RNG default devices + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_rng_default(struct rt_hwcrypto_device *device) +{ + struct rt_hwcrypto_ctx *tmp_ctx; + + /* if device is null, destroy default RNG Context */ + if (device == RT_NULL) + { + if (ctx_default) + { + rt_hwcrypto_rng_destroy(ctx_default); + ctx_default = RT_NULL; + } + return RT_EOK; + } + /* Try create RNG Context */ + tmp_ctx = rt_hwcrypto_rng_create(device); + if (tmp_ctx == RT_NULL) + { + return -RT_ERROR; + } + /* create RNG Context success, update default RNG Context */ + rt_hwcrypto_rng_destroy(ctx_default); + ctx_default = tmp_ctx; + + return RT_EOK; +} + +/** + * @brief Getting Random Numbers from RNG Context + * + * @param ctx RNG context + * + * @return Random number + */ +rt_uint32_t rt_hwcrypto_rng_update_ctx(struct rt_hwcrypto_ctx *ctx) +{ + if (ctx) + { + return ((struct hwcrypto_rng *)ctx)->ops->update((struct hwcrypto_rng *)ctx); + } + return 0; +} + +/** + * @brief Return a random number + * + * @return Random number + */ +rt_uint32_t rt_hwcrypto_rng_update(void) +{ + /* Default device does not exist ? */ + if (ctx_default == RT_NULL) + { + /* try create Context from default device */ + rt_hwcrypto_rng_default(rt_hwcrypto_dev_default()); + } + return rt_hwcrypto_rng_update_ctx(ctx_default); +} diff --git a/components/drivers/hwcrypto/hw_rng.h b/components/drivers/hwcrypto/hw_rng.h new file mode 100644 index 0000000000..fc28afdb1e --- /dev/null +++ b/components/drivers/hwcrypto/hw_rng.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#ifndef __HW_RNG_H__ +#define __HW_RNG_H__ + +#include <hwcrypto.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_rng; + +struct hwcrypto_rng_ops +{ + rt_uint32_t (*update)(struct hwcrypto_rng *ctx); /**< Return a random number */ +}; + +/** + * @brief random context. Hardware driver usage + */ +struct hwcrypto_rng +{ + struct rt_hwcrypto_ctx parent; /**< Inheritance from hardware crypto context */ + const struct hwcrypto_rng_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Creating RNG Context + * + * @param device Hardware crypto device + * + * @return RNG context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_rng_create(struct rt_hwcrypto_device *device); + +/** + * @brief Destroy RNG Context + * + * @param ctx RNG context + */ +void rt_hwcrypto_rng_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Setting RNG default devices + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_rng_default(struct rt_hwcrypto_device *device); + +/** + * @brief Getting Random Numbers from RNG Context + * + * @param ctx RNG context + * + * @return Random number + */ +rt_uint32_t rt_hwcrypto_rng_update_ctx(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Return a random number + * + * @return Random number + */ +rt_uint32_t rt_hwcrypto_rng_update(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hw_symmetric.c b/components/drivers/hwcrypto/hw_symmetric.c new file mode 100644 index 0000000000..789c5c1a2c --- /dev/null +++ b/components/drivers/hwcrypto/hw_symmetric.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_symmetric.h> + +/** + * @brief Creating Symmetric Encryption and Decryption Context + * + * @param device Hardware crypto device + * @param type Type of symmetric crypto context + * + * @return Symmetric crypto context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_symmetric_create(struct rt_hwcrypto_device *device, hwcrypto_type type) +{ + struct rt_hwcrypto_ctx *ctx; + + ctx = rt_hwcrypto_ctx_create(device, type, sizeof(struct hwcrypto_symmetric)); + return ctx; +} + +/** + * @brief Destroy Symmetric Encryption and Decryption Context + * + * @param ctx Symmetric crypto context + */ +void rt_hwcrypto_symmetric_destroy(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_ctx_destroy(ctx); +} + +/** + * @brief This function performs a symmetric encryption or decryption operation + * + * @param ctx Symmetric crypto context + * @param mode Operation mode. HWCRYPTO_MODE_ENCRYPT or HWCRYPTO_MODE_DECRYPT + * @param length The length of the input data in Bytes. This must be a multiple of the block size + * @param in The buffer holding the input data + * @param out The buffer holding the output data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_crypt(struct rt_hwcrypto_ctx *ctx, hwcrypto_mode mode, rt_size_t length, const rt_uint8_t *in, rt_uint8_t *out) +{ + struct hwcrypto_symmetric *symmetric_ctx; + struct hwcrypto_symmetric_info symmetric_info; + rt_err_t err; + + if (ctx == RT_NULL) + { + return -RT_EINVAL; + } + symmetric_ctx = (struct hwcrypto_symmetric *)ctx; + if (symmetric_ctx->ops->crypt == RT_NULL) + { + return -RT_ERROR; + } + if (mode != HWCRYPTO_MODE_ENCRYPT && mode != HWCRYPTO_MODE_DECRYPT) + { + return -EINVAL; + } + + /* Input information packaging */ + symmetric_info.mode = mode; + symmetric_info.in = in; + symmetric_info.out = out; + symmetric_info.length = length; + + /* Calling Hardware Encryption and Decryption Function */ + err = symmetric_ctx->ops->crypt(symmetric_ctx, &symmetric_info); + + /* clean up flags */ + symmetric_ctx->flags &= ~(SYMMTRIC_MODIFY_KEY | SYMMTRIC_MODIFY_IV | SYMMTRIC_MODIFY_IVOFF); + return err; +} + +/** + * @brief Set Symmetric Encryption and Decryption Key + * + * @param ctx Symmetric crypto context + * @param key The crypto key + * @param bitlen The crypto key bit length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_setkey(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *key, rt_uint32_t bitlen) +{ + struct hwcrypto_symmetric *symmetric_ctx; + + if (ctx && bitlen <= RT_HWCRYPTO_KEYBIT_MAX_SIZE) + { + symmetric_ctx = (struct hwcrypto_symmetric *)ctx; + rt_memcpy(symmetric_ctx->key, key, bitlen >> 3); + /* Record key length */ + symmetric_ctx->key_bitlen = bitlen; + /* Key change flag set up */ + symmetric_ctx->flags |= SYMMTRIC_MODIFY_KEY; + return RT_EOK; + } + + return -RT_EINVAL; +} + +/** + * @brief Get Symmetric Encryption and Decryption Key + * + * @param ctx Symmetric crypto context + * @param key The crypto key buffer + * @param bitlen The crypto key bit length + * + * @return Key length of copy + */ +int rt_hwcrypto_symmetric_getkey(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *key, rt_uint32_t bitlen) +{ + struct hwcrypto_symmetric *symmetric_ctx = (struct hwcrypto_symmetric *)ctx; + + if (ctx && bitlen >= symmetric_ctx->key_bitlen) + { + rt_memcpy(key, symmetric_ctx->key, symmetric_ctx->key_bitlen >> 3); + return symmetric_ctx->key_bitlen; + } + + return 0; +} + +/** + * @brief Set Symmetric Encryption and Decryption initialization vector + * + * @param ctx Symmetric crypto context + * @param iv The crypto initialization vector + * @param len The crypto initialization vector length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_setiv(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *iv, rt_size_t len) +{ + struct hwcrypto_symmetric *symmetric_ctx; + + if (ctx && len <= RT_HWCRYPTO_IV_MAX_SIZE) + { + symmetric_ctx = (struct hwcrypto_symmetric *)ctx; + rt_memcpy(symmetric_ctx->iv, iv, len); + symmetric_ctx->iv_len = len; + /* IV change flag set up */ + symmetric_ctx->flags |= SYMMTRIC_MODIFY_IV; + return RT_EOK; + } + + return -RT_EINVAL; +} + +/** + * @brief Get Symmetric Encryption and Decryption initialization vector + * + * @param ctx Symmetric crypto context + * @param iv The crypto initialization vector buffer + * @param len The crypto initialization vector buffer length + * + * @return IV length of copy + */ +int rt_hwcrypto_symmetric_getiv(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *iv, rt_size_t len) +{ + struct hwcrypto_symmetric *symmetric_ctx = (struct hwcrypto_symmetric *)ctx;; + + if (ctx && len >= symmetric_ctx->iv_len) + { + rt_memcpy(iv, symmetric_ctx->iv, symmetric_ctx->iv_len); + return symmetric_ctx->iv_len; + } + + return 0; +} + +/** + * @brief Set offset in initialization vector + * + * @param ctx Symmetric crypto context + * @param iv_off The offset in IV + */ +void rt_hwcrypto_symmetric_set_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t iv_off) +{ + if (ctx) + { + ((struct hwcrypto_symmetric *)ctx)->iv_off = iv_off; + /* iv_off change flag set up */ + ((struct hwcrypto_symmetric *)ctx)->flags |= SYMMTRIC_MODIFY_IVOFF; + } +} + +/** + * @brief Get offset in initialization vector + * + * @param ctx Symmetric crypto context + * @param iv_off It must point to a valid memory + */ +void rt_hwcrypto_symmetric_get_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t *iv_off) +{ + if (ctx && iv_off) + { + *iv_off = ((struct hwcrypto_symmetric *)ctx)->iv_off; + } +} + +/** + * @brief This function copy symmetric crypto context + * + * @param des The destination symmetric crypto context + * @param src The symmetric crypto context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src) +{ + struct hwcrypto_symmetric *symmetric_des = (struct hwcrypto_symmetric *)des; + struct hwcrypto_symmetric *symmetric_src = (struct hwcrypto_symmetric *)src; + + if (des != RT_NULL && src != RT_NULL) + { + /* Copy Symmetric Encryption and Decryption Context Information */ + symmetric_des->flags = symmetric_src->flags ; + symmetric_des->iv_len = symmetric_src->iv_len ; + symmetric_des->iv_off = symmetric_src->iv_off ; + symmetric_des->key_bitlen = symmetric_src->key_bitlen; + rt_memcpy(symmetric_des->iv, symmetric_src->iv, symmetric_src->iv_len); + rt_memcpy(symmetric_des->key, symmetric_src->key, symmetric_src->key_bitlen >> 3); + + /* Hardware context copy */ + return rt_hwcrypto_ctx_cpy(des, src); + } + return -RT_EINVAL; +} + +/** + * @brief Reset symmetric crypto context + * + * @param ctx Symmetric crypto context + */ +void rt_hwcrypto_symmetric_reset(struct rt_hwcrypto_ctx *ctx) +{ + struct hwcrypto_symmetric *symmetric_ctx = (struct hwcrypto_symmetric *)ctx; + if (ctx != RT_NULL) + { + /* Copy Symmetric Encryption and Decryption Context Information */ + symmetric_ctx->flags = 0x00; + symmetric_ctx->iv_len = 0x00; + symmetric_ctx->iv_off = 0x00; + symmetric_ctx->key_bitlen = 0x00; + rt_memset(symmetric_ctx->iv, 0, RT_HWCRYPTO_IV_MAX_SIZE); + rt_memset(symmetric_ctx->key, 0, RT_HWCRYPTO_KEYBIT_MAX_SIZE >> 3); + + /* Hardware context reset */ + rt_hwcrypto_ctx_reset(ctx); + } +} + +/** + * @brief Setting symmetric crypto context type + * + * @param ctx Symmetric crypto context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type) +{ + return rt_hwcrypto_set_type(ctx, type); +} diff --git a/components/drivers/hwcrypto/hw_symmetric.h b/components/drivers/hwcrypto/hw_symmetric.h new file mode 100644 index 0000000000..12f4dbec30 --- /dev/null +++ b/components/drivers/hwcrypto/hw_symmetric.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#ifndef __HW_SYMMETRIC_H__ +#define __HW_SYMMETRIC_H__ + +#include <hwcrypto.h> + +#ifndef RT_HWCRYPTO_IV_MAX_SIZE +#define RT_HWCRYPTO_IV_MAX_SIZE (16) +#endif +#ifndef RT_HWCRYPTO_KEYBIT_MAX_SIZE +#define RT_HWCRYPTO_KEYBIT_MAX_SIZE (256) +#endif + +#define SYMMTRIC_MODIFY_KEY (0x1 << 0) +#define SYMMTRIC_MODIFY_IV (0x1 << 1) +#define SYMMTRIC_MODIFY_IVOFF (0x1 << 2) + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_symmetric; +struct hwcrypto_symmetric_info; + +struct hwcrypto_symmetric_ops +{ + rt_err_t (*crypt)(struct hwcrypto_symmetric *symmetric_ctx, + struct hwcrypto_symmetric_info *symmetric_info); /**< Hardware Symmetric Encryption and Decryption Callback */ +}; + +/** + * @brief Hardware driver usage, including input and output information + */ +struct hwcrypto_symmetric_info +{ + hwcrypto_mode mode; /**< crypto mode. HWCRYPTO_MODE_ENCRYPT or HWCRYPTO_MODE_DECRYPT */ + const rt_uint8_t *in; /**< Input data */ + rt_uint8_t *out; /**< Output data will be written */ + rt_size_t length; /**< The length of the input data in Bytes. It's a multiple of block size. */ +}; + +/** + * @brief Symmetric crypto context. Hardware driver usage + */ +struct hwcrypto_symmetric +{ + struct rt_hwcrypto_ctx parent; /**< Inheritance from hardware crypto context */ + rt_uint32_t flags; /**< key or iv or ivoff has been changed. The flag will be set up */ + rt_int32_t iv_len; /**< initialization vector effective length */ + rt_int32_t iv_off; /**< The offset in IV */ + rt_uint8_t iv[RT_HWCRYPTO_IV_MAX_SIZE]; /**< The initialization vector */ + rt_uint8_t key[RT_HWCRYPTO_KEYBIT_MAX_SIZE >> 3]; /**< The crypto key */ + rt_int32_t key_bitlen; /**< The crypto key bit length */ + const struct hwcrypto_symmetric_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Creating Symmetric Encryption and Decryption Context + * + * @param device Hardware crypto device + * @param type Type of symmetric crypto context + * + * @return Symmetric crypto context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_symmetric_create(struct rt_hwcrypto_device *device, + hwcrypto_type type); + +/** + * @brief Destroy Symmetric Encryption and Decryption Context + * + * @param ctx Symmetric crypto context + */ +void rt_hwcrypto_symmetric_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief This function performs a symmetric encryption or decryption operation + * + * @param ctx Symmetric crypto context + * @param mode Operation mode. HWCRYPTO_MODE_ENCRYPT or HWCRYPTO_MODE_DECRYPT + * @param length The length of the input data in Bytes. This must be a multiple of the block size + * @param in The buffer holding the input data + * @param out The buffer holding the output data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_crypt(struct rt_hwcrypto_ctx *ctx, hwcrypto_mode mode, + rt_size_t length, const rt_uint8_t *in, rt_uint8_t *out); + +/** + * @brief Set Symmetric Encryption and Decryption Key + * + * @param ctx Symmetric crypto context + * @param key The crypto key + * @param bitlen The crypto key bit length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_setkey(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *key, rt_uint32_t bitlen); + +/** + * @brief Get Symmetric Encryption and Decryption Key + * + * @param ctx Symmetric crypto context + * @param key The crypto key buffer + * @param bitlen The crypto key bit length + * + * @return Key length of copy + */ +int rt_hwcrypto_symmetric_getkey(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *key, rt_uint32_t bitlen); + +/** + * @brief Set Symmetric Encryption and Decryption initialization vector + * + * @param ctx Symmetric crypto context + * @param iv The crypto initialization vector + * @param len The crypto initialization vector length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_setiv(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *iv, rt_size_t len); + +/** + * @brief Get Symmetric Encryption and Decryption initialization vector + * + * @param ctx Symmetric crypto context + * @param iv The crypto initialization vector buffer + * @param len The crypto initialization vector buffer length + * + * @return IV length of copy + */ +int rt_hwcrypto_symmetric_getiv(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *iv, rt_size_t len); + +/** + * @brief Set offset in initialization vector + * + * @param ctx Symmetric crypto context + * @param iv_off The offset in IV + */ +void rt_hwcrypto_symmetric_set_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t iv_off); + +/** + * @brief Get offset in initialization vector + * + * @param ctx Symmetric crypto context + * @param iv_off It must point to a valid memory + */ +void rt_hwcrypto_symmetric_get_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t *iv_off); + +/** + * @brief This function copy symmetric crypto context + * + * @param des The destination symmetric crypto context + * @param src The symmetric crypto context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src); + +/** + * @brief Reset symmetric crypto context + * + * @param ctx Symmetric crypto context + */ +void rt_hwcrypto_symmetric_reset(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Setting symmetric crypto context type + * + * @param ctx Symmetric crypto context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hwcrypto.c b/components/drivers/hwcrypto/hwcrypto.c new file mode 100644 index 0000000000..bbe1ff63fb --- /dev/null +++ b/components/drivers/hwcrypto/hwcrypto.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-23 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hwcrypto.h> + +/** + * @brief Setting context type (Direct calls are not recommended) + * + * @param ctx Crypto context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type) +{ + if (ctx) + { + /* Is it the same category? */ + if ((ctx->type & HWCRYPTO_MAIN_TYPE_MASK) == (type & HWCRYPTO_MAIN_TYPE_MASK)) + { + ctx->type = type; + return RT_EOK; + } + /* Context is empty type */ + else if (ctx->type == HWCRYPTO_TYPE_NULL) + { + ctx->type = type; + return RT_EOK; + } + else + { + return -RT_ERROR; + } + } + return -RT_EINVAL; +} + +/** + * @brief Reset context type (Direct calls are not recommended) + * + * @param ctx Crypto context + * + */ +void rt_hwcrypto_ctx_reset(struct rt_hwcrypto_ctx *ctx) +{ + if (ctx && ctx->device->ops->reset) + { + ctx->device->ops->reset(ctx); + } +} + +/** + * @brief Init crypto context + * + * @param ctx The context to initialize + * @param device Hardware crypto device + * @param type Type of context + * @param obj_size Size of context object + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_ctx_init(struct rt_hwcrypto_ctx *ctx, struct rt_hwcrypto_device *device, hwcrypto_type type) +{ + rt_err_t err; + + /* Setting context type */ + rt_hwcrypto_set_type(ctx, type); + ctx->device = device; + /* Create hardware context */ + err = ctx->device->ops->create(ctx); + if (err != RT_EOK) + { + return err; + } + return RT_EOK; +} + +/** + * @brief Create crypto context + * + * @param device Hardware crypto device + * @param type Type of context + * @param obj_size Size of context object + * + * @return Crypto context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_ctx_create(struct rt_hwcrypto_device *device, hwcrypto_type type, rt_uint32_t obj_size) +{ + struct rt_hwcrypto_ctx *ctx; + rt_err_t err; + + /* Parameter checking */ + if (device == RT_NULL || obj_size < sizeof(struct rt_hwcrypto_ctx)) + { + return RT_NULL; + } + ctx = rt_malloc(obj_size); + if (ctx == RT_NULL) + { + return ctx; + } + rt_memset(ctx, 0, obj_size); + /* Init context */ + err = rt_hwcrypto_ctx_init(ctx, device, type); + if (err != RT_EOK) + { + rt_free(ctx); + ctx = RT_NULL; + } + return ctx; +} + +/** + * @brief Destroy crypto context + * + * @param device Crypto context + */ +void rt_hwcrypto_ctx_destroy(struct rt_hwcrypto_ctx *ctx) +{ + if (ctx == RT_NULL) + { + return; + } + /* Destroy hardware context */ + if (ctx->device->ops->destroy) + { + ctx->device->ops->destroy(ctx); + } + /* Free the resources */ + rt_free(ctx); +} + +/** + * @brief Copy crypto context + * + * @param des The destination context + * @param src The context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_ctx_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src) +{ + if (des == RT_NULL || src == RT_NULL) + { + return -RT_EINVAL; + } + + /* The equipment is different or of different types and cannot be copied */ + if (des->device != src->device || + (des->type & HWCRYPTO_MAIN_TYPE_MASK) != (src->type & HWCRYPTO_MAIN_TYPE_MASK)) + { + return -RT_EINVAL; + } + des->type = src->type; + /* Calling Hardware Context Copy Function */ + return src->device->ops->copy(des, src); +} + +/** + * @brief Get the default hardware crypto device + * + * @return Hardware crypto device + * + */ +struct rt_hwcrypto_device *rt_hwcrypto_dev_default(void) +{ + static struct rt_hwcrypto_device *hwcrypto_dev; + + /* If there is a default device, return the device */ + if (hwcrypto_dev) + { + return hwcrypto_dev; + } + /* Find by default device name */ + hwcrypto_dev = (struct rt_hwcrypto_device *)rt_device_find(RT_HWCRYPTO_DEFAULT_NAME); + return hwcrypto_dev; +} + +/** + * @brief Get the unique ID of the device + * + * @param device Device object + * + * @return Device unique ID + */ +rt_uint64_t rt_hwcrypto_id(struct rt_hwcrypto_device *device) +{ + if (device) + { + return device->id; + } + return 0; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops hwcrypto_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL +}; +#endif + +/** + * @brief Register hardware crypto device + * + * @param device Hardware crypto device + * @param name Name of device + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_register(struct rt_hwcrypto_device *device, const char *name) +{ + rt_err_t err; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(name != RT_NULL); + RT_ASSERT(device->ops != RT_NULL); + RT_ASSERT(device->ops->create != RT_NULL); + RT_ASSERT(device->ops->destroy != RT_NULL); + RT_ASSERT(device->ops->copy != RT_NULL); + RT_ASSERT(device->ops->reset != RT_NULL); + + rt_memset(&device->parent, 0, sizeof(struct rt_device)); +#ifdef RT_USING_DEVICE_OPS + device->parent.ops = &hwcrypto_ops; +#else + device->parent.init = RT_NULL; + device->parent.open = RT_NULL; + device->parent.close = RT_NULL; + device->parent.read = RT_NULL; + device->parent.write = RT_NULL; + device->parent.control = RT_NULL; +#endif + + device->parent.user_data = RT_NULL; + device->parent.type = RT_Device_Class_Miscellaneous; + + /* Register device */ + err = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR); + + return err; +} diff --git a/components/drivers/hwcrypto/hwcrypto.h b/components/drivers/hwcrypto/hwcrypto.h new file mode 100644 index 0000000000..a428f4437d --- /dev/null +++ b/components/drivers/hwcrypto/hwcrypto.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-23 tyx the first version + */ + +#ifndef __HWCRYPTO_H__ +#define __HWCRYPTO_H__ + +#include <rtthread.h> + +#ifndef RT_HWCRYPTO_DEFAULT_NAME +#define RT_HWCRYPTO_DEFAULT_NAME ("hwcryto") +#endif + +#define HWCRYPTO_MAIN_TYPE_MASK (0xffffUL << 16) +#define HWCRYPTO_SUB_TYPE_MASK (0xffUL << 8) + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + HWCRYPTO_TYPE_NULL = 0x00000000, + + /* Main Type */ + /* symmetric Type */ + HWCRYPTO_TYPE_HEAD = __LINE__, + HWCRYPTO_TYPE_AES = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< AES */ + HWCRYPTO_TYPE_DES = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< DES */ + HWCRYPTO_TYPE_3DES = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< 3DES */ + HWCRYPTO_TYPE_RC4 = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< RC4 */ + HWCRYPTO_TYPE_GCM = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< GCM */ + /* HASH Type */ + HWCRYPTO_TYPE_MD5 = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< MD5 */ + HWCRYPTO_TYPE_SHA1 = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< SHA1 */ + HWCRYPTO_TYPE_SHA2 = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< SHA2 */ + /* Other Type */ + HWCRYPTO_TYPE_RNG = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< RNG */ + HWCRYPTO_TYPE_CRC = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< CRC */ + HWCRYPTO_TYPE_BIGNUM = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< BIGNUM */ + + /* AES Subtype */ + HWCRYPTO_TYPE_AES_ECB = HWCRYPTO_TYPE_AES | (0x01 << 8), + HWCRYPTO_TYPE_AES_CBC = HWCRYPTO_TYPE_AES | (0x02 << 8), + HWCRYPTO_TYPE_AES_CFB = HWCRYPTO_TYPE_AES | (0x03 << 8), + HWCRYPTO_TYPE_AES_CTR = HWCRYPTO_TYPE_AES | (0x04 << 8), + HWCRYPTO_TYPE_AES_OFB = HWCRYPTO_TYPE_AES | (0x05 << 8), + + /* DES Subtype */ + HWCRYPTO_TYPE_DES_ECB = HWCRYPTO_TYPE_DES | (0x01 << 8), + HWCRYPTO_TYPE_DES_CBC = HWCRYPTO_TYPE_DES | (0x02 << 8), + + /* 3DES Subtype */ + HWCRYPTO_TYPE_3DES_ECB = HWCRYPTO_TYPE_3DES | (0x01 << 8), + HWCRYPTO_TYPE_3DES_CBC = HWCRYPTO_TYPE_3DES | (0x02 << 8), + + /* SHA2 Subtype */ + HWCRYPTO_TYPE_SHA224 = HWCRYPTO_TYPE_SHA2 | (0x01 << 8), + HWCRYPTO_TYPE_SHA256 = HWCRYPTO_TYPE_SHA2 | (0x02 << 8), + HWCRYPTO_TYPE_SHA384 = HWCRYPTO_TYPE_SHA2 | (0x03 << 8), + HWCRYPTO_TYPE_SHA512 = HWCRYPTO_TYPE_SHA2 | (0x04 << 8), +} hwcrypto_type; + +typedef enum +{ + HWCRYPTO_MODE_ENCRYPT = 0x1, /**< Encryption operations */ + HWCRYPTO_MODE_DECRYPT = 0x2, /**< Decryption operations */ + HWCRYPTO_MODE_UNKNOWN = 0x7fffffff, /**< Unknown */ +} hwcrypto_mode; + +struct rt_hwcrypto_ctx; + +struct rt_hwcrypto_ops +{ + rt_err_t (*create)(struct rt_hwcrypto_ctx *ctx); /**< Creating hardware context */ + void (*destroy)(struct rt_hwcrypto_ctx *ctx); /**< Delete hardware context */ + rt_err_t (*copy)(struct rt_hwcrypto_ctx *des, + const struct rt_hwcrypto_ctx *src); /**< Cpoy hardware context */ + void (*reset)(struct rt_hwcrypto_ctx *ctx); /**< Reset hardware context */ +}; + +struct rt_hwcrypto_device +{ + struct rt_device parent; /**< Inherited from the standard device */ + const struct rt_hwcrypto_ops *ops; /**< Hardware crypto ops */ + rt_uint64_t id; /**< Unique id */ + void *user_data; /**< Device user data */ +}; + +struct rt_hwcrypto_ctx +{ + struct rt_hwcrypto_device *device; /**< Binding device */ + hwcrypto_type type; /**< Encryption and decryption types */ + void *contex; /**< Hardware context */ +}; + +/** + * @brief Setting context type (Direct calls are not recommended) + * + * @param ctx Crypto context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type); + +/** + * @brief Reset context type (Direct calls are not recommended) + * + * @param ctx Crypto context + */ +void rt_hwcrypto_ctx_reset(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Init crypto context (Direct calls are not recommended) + * + * @param ctx The context to initialize + * @param device Hardware crypto device + * @param type Type of context + * @param obj_size Size of context object + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_ctx_init(struct rt_hwcrypto_ctx *ctx, + struct rt_hwcrypto_device *device, hwcrypto_type type); + +/** + * @brief Create crypto context (Direct calls are not recommended) + * + * @param device Hardware crypto device + * @param type Type of context + * @param obj_size Size of context object + * + * @return Crypto context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_ctx_create(struct rt_hwcrypto_device *device, + hwcrypto_type type, rt_uint32_t obj_size); + +/** + * @brief Destroy crypto context (Direct calls are not recommended) + * + * @param device Crypto context + */ +void rt_hwcrypto_ctx_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Copy crypto context (Direct calls are not recommended) + * + * @param des The destination context + * @param src The context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_ctx_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src); + +/** + * @brief Register hardware crypto device + * + * @param device Hardware crypto device + * @param name Name of device + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_register(struct rt_hwcrypto_device *device, const char *name); + +/** + * @brief Get the default hardware crypto device + * + * @return Hardware crypto device + * + */ +struct rt_hwcrypto_device *rt_hwcrypto_dev_default(void); + +/** + * @brief Get the unique ID of the device + * + * @param device Device object + * + * @return Device unique ID + */ +rt_uint64_t rt_hwcrypto_id(struct rt_hwcrypto_device *device); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/i2c/fm24clxx.c b/components/drivers/i2c/fm24clxx.c deleted file mode 100644 index eecf3d455a..0000000000 --- a/components/drivers/i2c/fm24clxx.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017-07-14 aubr.cool 1st version - */ -#include <rtthread.h> -#include <rtdevice.h> -#include "fm24clxx.h" - -struct fm24clxx_device -{ - struct rt_device parent; - struct rt_i2c_bus_device *bus; -}; - -/* RT-Thread device interface */ - -static rt_err_t fm24clxx_init(rt_device_t dev) -{ - return RT_EOK; -} -static rt_err_t fm24clxx_open(rt_device_t dev, rt_uint16_t oflag) -{ - return RT_EOK; -} - -static rt_err_t fm24clxx_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t fm24clxx_control(rt_device_t dev, int cmd, void *args) -{ - return RT_EOK; -} - -static rt_size_t fm24clxx_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) -{ - struct fm24clxx_device *fm24clxx; - const struct fm24clxx_config *cfg; - struct rt_i2c_msg msg[2]; - rt_uint8_t mem_addr[2] = {0,}; - rt_size_t ret = 0; - RT_ASSERT(dev != 0); - - fm24clxx = (struct fm24clxx_device *) dev; - - RT_ASSERT(fm24clxx->parent.user_data != 0); - cfg = (const struct fm24clxx_config *) fm24clxx->parent.user_data; - - if(pos > cfg->size) - { - return 0; - } - - if(pos + size > cfg->size) - { - size = cfg->size - pos; - } - - msg[0].addr = cfg->addr; - msg[0].flags = cfg->flags | RT_I2C_WR; - mem_addr[0] = (pos >> 8); - mem_addr[1] = (rt_uint8_t) pos; - msg[0].buf = (rt_uint8_t *) mem_addr; - msg[0].len = 2; - - msg[1].addr = cfg->addr; - msg[1].flags = cfg->flags | RT_I2C_RD; - msg[1].buf = (rt_uint8_t *) buffer; - msg[1].len = size; - - ret = rt_i2c_transfer(fm24clxx->bus, msg, 2); - return (ret == 2) ? size : 0; -} - -static rt_size_t fm24clxx_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) -{ - struct fm24clxx_device *fm24clxx; - const struct fm24clxx_config *cfg; - struct rt_i2c_msg msg[2]; - rt_uint8_t mem_addr[2] = {0,}; - rt_size_t ret = 0; - RT_ASSERT(dev != 0); - - fm24clxx = (struct fm24clxx_device *) dev; - - RT_ASSERT(fm24clxx->parent.user_data != 0); - cfg = (const struct fm24clxx_config *) fm24clxx->parent.user_data; - - if(pos > cfg->size) - { - return 0; - } - - if(pos + size > cfg->size) - { - size = cfg->size - pos; - } - - msg[0].addr = cfg->addr; - msg[0].flags = cfg->flags | RT_I2C_WR; - mem_addr[0] = (pos >> 8); - mem_addr[1] = (rt_uint8_t) pos; - msg[0].buf = (rt_uint8_t *) mem_addr; - msg[0].len = 2; - - msg[1].addr = cfg->addr; - msg[1].flags = cfg->flags | RT_I2C_WR | RT_I2C_NO_START; - msg[1].buf = (rt_uint8_t *) buffer; - msg[1].len = size; - - ret = rt_i2c_transfer(fm24clxx->bus, msg, 2); - return (ret == 2) ? size : 0; -} - -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device fm24clxx_ops = -{ - fm24clxx_init, - fm24clxx_open, - fm24clxx_close, - fm24clxx_read, - fm24clxx_write, - fm24clxx_control -}; -#endif - -rt_err_t fm24clxx_register(const char *fm_device_name, const char *i2c_bus, void *user_data) -{ - static struct fm24clxx_device fm24clxx_drv; - struct rt_i2c_bus_device *bus; - - bus = rt_i2c_bus_device_find(i2c_bus); - if (bus == RT_NULL) - { - return RT_ENOSYS; - } - - fm24clxx_drv.bus = bus; - fm24clxx_drv.parent.type = RT_Device_Class_Block; -#ifdef RT_USING_DEVICE_OPS - fm24clxx_drv.parent.ops = &fm24clxx_ops; -#else - fm24clxx_drv.parent.init = fm24clxx_init; - fm24clxx_drv.parent.open = fm24clxx_open; - fm24clxx_drv.parent.close = fm24clxx_close; - fm24clxx_drv.parent.read = fm24clxx_read; - fm24clxx_drv.parent.write = fm24clxx_write; - fm24clxx_drv.parent.control = fm24clxx_control; -#endif - - fm24clxx_drv.parent.user_data = user_data; - - return rt_device_register(&fm24clxx_drv.parent, fm_device_name, RT_DEVICE_FLAG_RDWR); -}
\ No newline at end of file diff --git a/components/drivers/i2c/fm24clxx.h b/components/drivers/i2c/fm24clxx.h deleted file mode 100644 index 74ee065470..0000000000 --- a/components/drivers/i2c/fm24clxx.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017-07-14 aubr.cool 1st version - */ - -#ifndef __FM24CLXX_H__ -#define __FM24CLXX_H__ - -#include <rtthread.h> - -struct fm24clxx_config -{ - rt_uint32_t size; - rt_uint16_t addr; - rt_uint16_t flags; -}; - -extern rt_err_t fm24clxx_register(const char *e2m_device_name, - const char *i2c_bus, void *user_data); - -#endif /*__FM24CLXX_H__*/
\ No newline at end of file diff --git a/components/drivers/i2c/i2c-bit-ops.c b/components/drivers/i2c/i2c-bit-ops.c index 26479a1d68..99338eef54 100644 --- a/components/drivers/i2c/i2c-bit-ops.c +++ b/components/drivers/i2c/i2c-bit-ops.c @@ -10,11 +10,13 @@ #include <rtdevice.h> -#ifdef RT_I2C_BIT_DEBUG -#define bit_dbg(fmt, ...) rt_kprintf(fmt, ##__VA_ARGS__) +#define DBG_TAG "I2C" +#ifdef RT_I2C_BITOPS_DEBUG +#define DBG_LVL DBG_LOG #else -#define bit_dbg(fmt, ...) +#define DBG_LVL DBG_INFO #endif +#include <rtdbg.h> #define SET_SDA(ops, val) ops->set_sda(ops->data, val) #define SET_SCL(ops, val) ops->set_scl(ops->data, val) @@ -54,11 +56,11 @@ static rt_err_t SCL_H(struct rt_i2c_bit_ops *ops) return -RT_ETIMEOUT; rt_thread_delay((ops->timeout + 1) >> 1); } -#ifdef RT_I2C_BIT_DEBUG +#ifdef RT_I2C_BITOPS_DEBUG if (rt_tick_get() != start) { - bit_dbg("wait %ld tick for SCL line to go high\n", - rt_tick_get() - start); + LOG_D("wait %ld tick for SCL line to go high", + rt_tick_get() - start); } #endif @@ -70,14 +72,14 @@ done: static void i2c_start(struct rt_i2c_bit_ops *ops) { -#ifdef RT_I2C_BIT_DEBUG +#ifdef RT_I2C_BITOPS_DEBUG if (ops->get_scl && !GET_SCL(ops)) { - bit_dbg("I2C bus error, SCL line low\n"); + LOG_E("I2C bus error, SCL line low"); } if (ops->get_sda && !GET_SDA(ops)) { - bit_dbg("I2C bus error, SDA line low\n"); + LOG_E("I2C bus error, SDA line low"); } #endif SDA_L(ops); @@ -114,13 +116,13 @@ rt_inline rt_bool_t i2c_waitack(struct rt_i2c_bit_ops *ops) if (SCL_H(ops) < 0) { - bit_dbg("wait ack timeout\n"); + LOG_W("wait ack timeout"); return -RT_ETIMEOUT; } ack = !GET_SDA(ops); /* ACK : SDA pin is pulled low */ - bit_dbg("%s\n", ack ? "ACK" : "NACK"); + LOG_D("%s", ack ? "ACK" : "NACK"); SCL_L(ops); @@ -132,7 +134,7 @@ static rt_int32_t i2c_writeb(struct rt_i2c_bus_device *bus, rt_uint8_t data) rt_int32_t i; rt_uint8_t bit; - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; for (i = 7; i >= 0; i--) { @@ -142,8 +144,8 @@ static rt_int32_t i2c_writeb(struct rt_i2c_bus_device *bus, rt_uint8_t data) i2c_delay(ops); if (SCL_H(ops) < 0) { - bit_dbg("i2c_writeb: 0x%02x, " - "wait scl pin high timeout at bit %d\n", + LOG_D("i2c_writeb: 0x%02x, " + "wait scl pin high timeout at bit %d", data, i); return -RT_ETIMEOUT; @@ -159,7 +161,7 @@ static rt_int32_t i2c_readb(struct rt_i2c_bus_device *bus) { rt_uint8_t i; rt_uint8_t data = 0; - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; SDA_H(ops); i2c_delay(ops); @@ -169,8 +171,8 @@ static rt_int32_t i2c_readb(struct rt_i2c_bus_device *bus) if (SCL_H(ops) < 0) { - bit_dbg("i2c_readb: wait scl pin high " - "timeout at bit %d\n", 7 - i); + LOG_D("i2c_readb: wait scl pin high " + "timeout at bit %d", 7 - i); return -RT_ETIMEOUT; } @@ -205,13 +207,13 @@ static rt_size_t i2c_send_bytes(struct rt_i2c_bus_device *bus, } else if (ret == 0) { - i2c_dbg("send bytes: NACK.\n"); + LOG_D("send bytes: NACK."); return 0; } else { - i2c_dbg("send bytes: error %d\n", ret); + LOG_E("send bytes: error %d", ret); return ret; } @@ -222,14 +224,14 @@ static rt_size_t i2c_send_bytes(struct rt_i2c_bus_device *bus, static rt_err_t i2c_send_ack_or_nack(struct rt_i2c_bus_device *bus, int ack) { - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; if (ack) SET_SDA(ops, 0); i2c_delay(ops); if (SCL_H(ops) < 0) { - bit_dbg("ACK or NACK timeout\n"); + LOG_E("ACK or NACK timeout."); return -RT_ETIMEOUT; } @@ -263,7 +265,7 @@ static rt_size_t i2c_recv_bytes(struct rt_i2c_bus_device *bus, ptr ++; count --; - bit_dbg("recieve bytes: 0x%02x, %s\n", + LOG_D("recieve bytes: 0x%02x, %s", val, (flags & RT_I2C_NO_READ_ACK) ? "(No ACK/NACK)" : (count ? "ACK" : "NACK")); @@ -282,7 +284,7 @@ static rt_int32_t i2c_send_address(struct rt_i2c_bus_device *bus, rt_uint8_t addr, rt_int32_t retries) { - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; rt_int32_t i; rt_err_t ret = 0; @@ -291,10 +293,10 @@ static rt_int32_t i2c_send_address(struct rt_i2c_bus_device *bus, ret = i2c_writeb(bus, addr); if (ret == 1 || i == retries) break; - bit_dbg("send stop condition\n"); + LOG_D("send stop condition"); i2c_stop(ops); i2c_delay2(ops); - bit_dbg("send start condition\n"); + LOG_D("send start condition"); i2c_start(ops); } @@ -306,7 +308,7 @@ static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus, { rt_uint16_t flags = msg->flags; rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK; - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; rt_uint8_t addr1, addr2; rt_int32_t retries; @@ -319,12 +321,12 @@ static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus, addr1 = 0xf0 | ((msg->addr >> 7) & 0x06); addr2 = msg->addr & 0xff; - bit_dbg("addr1: %d, addr2: %d\n", addr1, addr2); + LOG_D("addr1: %d, addr2: %d", addr1, addr2); ret = i2c_send_address(bus, addr1, retries); if ((ret != 1) && !ignore_nack) { - bit_dbg("NACK: sending first addr\n"); + LOG_W("NACK: sending first addr"); return -RT_EIO; } @@ -332,19 +334,19 @@ static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus, ret = i2c_writeb(bus, addr2); if ((ret != 1) && !ignore_nack) { - bit_dbg("NACK: sending second addr\n"); + LOG_W("NACK: sending second addr"); return -RT_EIO; } if (flags & RT_I2C_RD) { - bit_dbg("send repeated start condition\n"); + LOG_D("send repeated start condition"); i2c_restart(ops); addr1 |= 0x01; ret = i2c_send_address(bus, addr1, retries); if ((ret != 1) && !ignore_nack) { - bit_dbg("NACK: sending repeated addr\n"); + LOG_E("NACK: sending repeated addr"); return -RT_EIO; } @@ -369,11 +371,11 @@ static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, rt_uint32_t num) { struct rt_i2c_msg *msg; - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; rt_int32_t i, ret; rt_uint16_t ignore_nack; - bit_dbg("send start condition\n"); + LOG_D("send start condition"); i2c_start(ops); for (i = 0; i < num; i++) { @@ -388,7 +390,7 @@ static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, ret = i2c_bit_send_address(bus, msg); if ((ret != RT_EOK) && !ignore_nack) { - bit_dbg("receive NACK from device addr 0x%02x msg %d\n", + LOG_D("receive NACK from device addr 0x%02x msg %d", msgs[i].addr, i); goto out; } @@ -397,7 +399,7 @@ static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, { ret = i2c_recv_bytes(bus, msg); if (ret >= 1) - bit_dbg("read %d byte%s\n", ret, ret == 1 ? "" : "s"); + LOG_D("read %d byte%s", ret, ret == 1 ? "" : "s"); if (ret < msg->len) { if (ret >= 0) @@ -409,7 +411,7 @@ static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, { ret = i2c_send_bytes(bus, msg); if (ret >= 1) - bit_dbg("write %d byte%s\n", ret, ret == 1 ? "" : "s"); + LOG_D("write %d byte%s", ret, ret == 1 ? "" : "s"); if (ret < msg->len) { if (ret >= 0) @@ -421,7 +423,7 @@ static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, ret = i; out: - bit_dbg("send stop condition\n"); + LOG_D("send stop condition"); i2c_stop(ops); return ret; diff --git a/components/drivers/i2c/i2c_core.c b/components/drivers/i2c/i2c_core.c index f245abb9ca..f358c2b758 100644 --- a/components/drivers/i2c/i2c_core.c +++ b/components/drivers/i2c/i2c_core.c @@ -10,6 +10,14 @@ #include <rtdevice.h> +#define DBG_TAG "I2C" +#ifdef RT_I2C_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif +#include <rtdbg.h> + rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, const char *bus_name) { @@ -21,7 +29,7 @@ rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, res = rt_i2c_bus_device_device_init(bus, bus_name); - i2c_dbg("I2C bus [%s] registered\n", bus_name); + LOG_I("I2C bus [%s] registered", bus_name); return res; } @@ -32,7 +40,7 @@ struct rt_i2c_bus_device *rt_i2c_bus_device_find(const char *bus_name) rt_device_t dev = rt_device_find(bus_name); if (dev == RT_NULL || dev->type != RT_Device_Class_I2CBUS) { - i2c_dbg("I2C bus %s not exist\n", bus_name); + LOG_E("I2C bus %s not exist", bus_name); return RT_NULL; } @@ -53,9 +61,9 @@ rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, #ifdef RT_I2C_DEBUG for (ret = 0; ret < num; ret++) { - i2c_dbg("msgs[%d] %c, addr=0x%02x, len=%d\n", ret, - (msgs[ret].flags & RT_I2C_RD) ? 'R' : 'W', - msgs[ret].addr, msgs[ret].len); + LOG_D("msgs[%d] %c, addr=0x%02x, len=%d", ret, + (msgs[ret].flags & RT_I2C_RD) ? 'R' : 'W', + msgs[ret].addr, msgs[ret].len); } #endif @@ -67,7 +75,7 @@ rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, } else { - i2c_dbg("I2C bus operation not supported\n"); + LOG_E("I2C bus operation not supported"); return 0; } @@ -83,7 +91,7 @@ rt_size_t rt_i2c_master_send(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msg; msg.addr = addr; - msg.flags = flags & RT_I2C_ADDR_10BIT; + msg.flags = flags; msg.len = count; msg.buf = (rt_uint8_t *)buf; @@ -103,8 +111,7 @@ rt_size_t rt_i2c_master_recv(struct rt_i2c_bus_device *bus, RT_ASSERT(bus != RT_NULL); msg.addr = addr; - msg.flags = flags & RT_I2C_ADDR_10BIT; - msg.flags |= RT_I2C_RD; + msg.flags = flags | RT_I2C_RD; msg.len = count; msg.buf = buf; diff --git a/components/drivers/i2c/i2c_dev.c b/components/drivers/i2c/i2c_dev.c index 6c7df8e427..59f728be09 100644 --- a/components/drivers/i2c/i2c_dev.c +++ b/components/drivers/i2c/i2c_dev.c @@ -11,6 +11,14 @@ #include <rtdevice.h> +#define DBG_TAG "I2C" +#ifdef RT_I2C_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif +#include <rtdbg.h> + static rt_size_t i2c_bus_device_read(rt_device_t dev, rt_off_t pos, void *buffer, @@ -23,12 +31,12 @@ static rt_size_t i2c_bus_device_read(rt_device_t dev, RT_ASSERT(bus != RT_NULL); RT_ASSERT(buffer != RT_NULL); - i2c_dbg("I2C bus dev [%s] reading %u bytes.\n", dev->parent.name, count); + LOG_D("I2C bus dev [%s] reading %u bytes.", dev->parent.name, count); addr = pos & 0xffff; flags = (pos >> 16) & 0xffff; - return rt_i2c_master_recv(bus, addr, flags, buffer, count); + return rt_i2c_master_recv(bus, addr, flags, (rt_uint8_t *)buffer, count); } static rt_size_t i2c_bus_device_write(rt_device_t dev, @@ -43,12 +51,12 @@ static rt_size_t i2c_bus_device_write(rt_device_t dev, RT_ASSERT(bus != RT_NULL); RT_ASSERT(buffer != RT_NULL); - i2c_dbg("I2C bus dev [%s] writing %u bytes.\n", dev->parent.name, count); + LOG_D("I2C bus dev [%s] writing %u bytes.", dev->parent.name, count); addr = pos & 0xffff; flags = (pos >> 16) & 0xffff; - return rt_i2c_master_send(bus, addr, flags, buffer, count); + return rt_i2c_master_send(bus, addr, flags, (const rt_uint8_t *)buffer, count); } static rt_err_t i2c_bus_device_control(rt_device_t dev, diff --git a/components/drivers/include/drivers/audio.h b/components/drivers/include/drivers/audio.h index 7d2cb36728..86057e7626 100644 --- a/components/drivers/include/drivers/audio.h +++ b/components/drivers/include/drivers/audio.h @@ -5,52 +5,30 @@ * * Change Logs: * Date Author Notes - * 2017-05-09 Urey first version + * 2017-05-09 Urey first version + * 2019-07-09 Zero-Free improve device ops interface and data flows + * */ #ifndef __AUDIO_H__ #define __AUDIO_H__ +#include "audio_pipe.h" + /* AUDIO command */ #define _AUDIO_CTL(a) (0x10 + a) #define AUDIO_CTL_GETCAPS _AUDIO_CTL(1) #define AUDIO_CTL_CONFIGURE _AUDIO_CTL(2) -#define AUDIO_CTL_SHUTDOWN _AUDIO_CTL(3) -#define AUDIO_CTL_START _AUDIO_CTL(4) -#define AUDIO_CTL_STOP _AUDIO_CTL(5) -#define AUDIO_CTL_PAUSE _AUDIO_CTL(6) -#define AUDIO_CTL_RESUME _AUDIO_CTL(7) -#define AUDIO_CTL_GETBUFFERINFO _AUDIO_CTL(8) -#define AUDIO_CTL_ALLOCBUFFER _AUDIO_CTL(9) -#define AUDIO_CTL_FREEBUFFER _AUDIO_CTL(10) -#define AUDIO_CTL_HWRESET _AUDIO_CTL(11) - +#define AUDIO_CTL_START _AUDIO_CTL(3) +#define AUDIO_CTL_STOP _AUDIO_CTL(4) +#define AUDIO_CTL_GETBUFFERINFO _AUDIO_CTL(5) /* Audio Device Types */ #define AUDIO_TYPE_QUERY 0x00 #define AUDIO_TYPE_INPUT 0x01 #define AUDIO_TYPE_OUTPUT 0x02 #define AUDIO_TYPE_MIXER 0x04 -#define AUDIO_TYPE_SELECTOR 0x08 -#define AUDIO_TYPE_EFFECT 0x10 - -/* Audio Format Types */ -#define AUDIO_FMT_PCM_U8 0x0001 -#define AUDIO_FMT_PCM_S8 0x0002 - -#define AUDIO_FMT_PCM_U16_LE 0x0010 -#define AUDIO_FMT_PCM_S16_BE 0x0020 -#define AUDIO_FMT_PCM_S16_LE 0x0040 -#define AUDIO_FMT_PCM_U16_BE 0x0080 -#define AUDIO_FMT_PCM_U24_LE 0x0100 -#define AUDIO_FMT_PCM_S24_BE 0x0200 -#define AUDIO_FMT_PCM_S24_LE 0x0400 -#define AUDIO_FMT_PCM_U24_BE 0x0800 -#define AUDIO_FMT_PCM_U32_LE 0x1000 -#define AUDIO_FMT_PCM_S32_BE 0x2000 -#define AUDIO_FMT_PCM_S32_LE 0x4000 -#define AUDIO_FMT_PCM_U32_BE 0x8000 /* Supported Sampling Rates */ #define AUDIO_SAMP_RATE_8K 0x0001 @@ -76,13 +54,11 @@ #define AUDIO_BIT_RATE_172K 0x40 #define AUDIO_BIT_RATE_192K 0x80 - - /* Support Dsp(input/output) Units controls */ #define AUDIO_DSP_PARAM 0 /* get/set all params */ -#define AUDIO_DSP_SAMPLERATE 1 /* é‡‡æ ·é¢‘çŽ‡ */ -#define AUDIO_DSP_FMT 2 -#define AUDIO_DSP_CHANNELS 3 +#define AUDIO_DSP_SAMPLERATE 1 /* samplerate */ +#define AUDIO_DSP_CHANNELS 2 /* channels */ +#define AUDIO_DSP_SAMPLEBITS 3 /* sample bits width */ /* Supported Mixer Units controls */ #define AUDIO_MIXER_QUERY 0x0000 @@ -95,15 +71,13 @@ #define AUDIO_MIXER_LINE 0x0040 #define AUDIO_MIXER_DIGITAL 0x0080 #define AUDIO_MIXER_MIC 0x0100 +#define AUDIO_MIXER_VITURAL 0x0200 +#define AUDIO_MIXER_EXTEND 0x8000 /* extend mixer command */ -#define AUDIO_MIXER_EXTEND 0x8000 //extend mixer command +#define AUDIO_VOLUME_MAX (100) +#define AUDIO_VOLUME_MIN (0) #define CFG_AUDIO_REPLAY_QUEUE_COUNT 4 -#define CFG_AUDIO_RECORD_PIPE_SIZE (8 * 1024) -#define AUDIO_DEVICE_MP_CNT (4) -#define AUDIO_DEVICE_DECODE_MP_BLOCK_SZ (4352 * 4) -#define AUDIO_DEVICE_DECODE_MP_SZ ((AUDIO_DEVICE_DECODE_MP_BLOCK_SZ*2 + 4)*AUDIO_DEVICE_MP_CNT) - enum { @@ -115,19 +89,10 @@ enum /* the preferred number and size of audio pipeline buffer for the audio device */ struct rt_audio_buf_info { - rt_uint32_t buffer_size; /* Preferred qty of buffers */ - rt_uint32_t buffer_count; /* Preferred size of the buffers */ -}; -struct rt_audio_buf_desc -{ - rt_uint8_t *data_ptr; - rt_size_t data_size; -}; - -struct rt_audio_frame -{ - const void *data_ptr; - rt_size_t data_size; + rt_uint8_t *buffer; + rt_uint16_t block_size; + rt_uint16_t block_count; + rt_uint32_t total_size; }; struct rt_audio_device; @@ -135,73 +100,68 @@ struct rt_audio_caps; struct rt_audio_configure; struct rt_audio_ops { - rt_err_t (*getcaps) (struct rt_audio_device *audio,struct rt_audio_caps *caps); - rt_err_t (*configure) (struct rt_audio_device *audio,struct rt_audio_caps *caps); - - rt_err_t (*init) (struct rt_audio_device *audio); - rt_err_t (*shutdown) (struct rt_audio_device *audio); - rt_err_t (*start) (struct rt_audio_device *audio,int stream); - rt_err_t (*stop) (struct rt_audio_device *audio,int stream); - rt_err_t (*suspend) (struct rt_audio_device *audio,int stream); - rt_err_t (*resume) (struct rt_audio_device *audio,int stream); - - rt_err_t (*control) (struct rt_audio_device *audio, int cmd, void *arg); - rt_size_t (*transmit) (struct rt_audio_device *audio, const void *writeBuf,void *readBuf, rt_size_t size); - - //get page size of codec or private buffer's info - void (*buffer_info) (struct rt_audio_device *audio,struct rt_audio_buf_info *info ); + rt_err_t (*getcaps)(struct rt_audio_device *audio, struct rt_audio_caps *caps); + rt_err_t (*configure)(struct rt_audio_device *audio, struct rt_audio_caps *caps); + rt_err_t (*init)(struct rt_audio_device *audio); + rt_err_t (*start)(struct rt_audio_device *audio, int stream); + rt_err_t (*stop)(struct rt_audio_device *audio, int stream); + rt_size_t (*transmit)(struct rt_audio_device *audio, const void *writeBuf, void *readBuf, rt_size_t size); + /* get page size of codec or private buffer's info */ + void (*buffer_info)(struct rt_audio_device *audio, struct rt_audio_buf_info *info); }; - struct rt_audio_configure { - rt_uint32_t channels; - - rt_uint32_t samplefmt; rt_uint32_t samplerate; - rt_uint32_t samplefmts; + rt_uint16_t channels; + rt_uint16_t samplebits; }; struct rt_audio_caps { - int main_type; - int sub_type; + int main_type; + int sub_type; - union - { - rt_uint32_t mask; - int value; - struct rt_audio_configure config; - }udata; + union + { + rt_uint32_t mask; + int value; + struct rt_audio_configure config; + } udata; }; struct rt_audio_replay { - rt_bool_t activated; + struct rt_mempool *mp; struct rt_data_queue queue; + struct rt_mutex lock; + struct rt_completion cmp; + struct rt_audio_buf_info buf_info; + rt_uint8_t *write_data; + rt_uint16_t write_index; + rt_uint16_t read_index; + rt_uint32_t pos; + rt_uint8_t event; + rt_bool_t activated; }; struct rt_audio_record { + struct rt_audio_pipe pipe; rt_bool_t activated; }; struct rt_audio_device { - struct rt_device parent; + struct rt_device parent; struct rt_audio_ops *ops; - - struct rt_mempool mp; - struct rt_audio_replay *replay; struct rt_audio_record *record; }; -rt_err_t rt_audio_register (struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data); -void rt_audio_tx_complete (struct rt_audio_device *audio,rt_uint8_t *pbuf); -void rt_audio_rx_done (struct rt_audio_device *audio,rt_uint8_t *pbuf,rt_size_t len); -rt_uint32_t rt_audio_format_to_bits (rt_uint32_t format); - +rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data); +void rt_audio_tx_complete(struct rt_audio_device *audio); +void rt_audio_rx_done(struct rt_audio_device *audio, rt_uint8_t *pbuf, rt_size_t len); /* Device Control Commands */ #define CODEC_CMD_RESET 0 diff --git a/components/drivers/include/drivers/can.h b/components/drivers/include/drivers/can.h index c61fb19eaa..d4fcc845b4 100644 --- a/components/drivers/include/drivers/can.h +++ b/components/drivers/include/drivers/can.h @@ -221,7 +221,7 @@ struct rt_can_msg rt_uint32_t rsv : 1; rt_uint32_t len : 8; rt_uint32_t priv : 8; - rt_uint32_t hdr : 8; + rt_int32_t hdr : 8; rt_uint32_t reserved : 8; rt_uint8_t data[8]; }; @@ -252,7 +252,7 @@ struct rt_can_rx_fifo #define RT_CAN_EVENT_RX_IND 0x01 /* Rx indication */ #define RT_CAN_EVENT_TX_DONE 0x02 /* Tx complete */ -#define RT_CAN_EVENT_TX_FAIL 0x03 /* Tx complete */ +#define RT_CAN_EVENT_TX_FAIL 0x03 /* Tx fail */ #define RT_CAN_EVENT_RX_TIMEOUT 0x05 /* Rx timeout */ #define RT_CAN_EVENT_RXOF_IND 0x06 /* Rx overflow */ @@ -278,7 +278,7 @@ struct rt_can_ops int (*recvmsg)(struct rt_can_device *can, void *buf, rt_uint32_t boxno); }; -rt_err_t rt_hw_can_register(struct rt_can_device *can, +rt_err_t rt_hw_can_register(struct rt_can_device *can, const char *name, const struct rt_can_ops *ops, void *data); diff --git a/components/drivers/include/drivers/crypto.h b/components/drivers/include/drivers/crypto.h new file mode 100644 index 0000000000..5341d9ee48 --- /dev/null +++ b/components/drivers/include/drivers/crypto.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-05-17 tyx the first version + */ + +#ifndef __CRYPTO_H__ +#define __CRYPTO_H__ + +#include <rtthread.h> +#include <hwcrypto.h> +#include <hw_symmetric.h> +#include <hw_rng.h> +#include <hw_hash.h> +#include <hw_crc.h> +#include <hw_gcm.h> +#include <hw_bignum.h> + +#endif diff --git a/components/drivers/include/drivers/i2c.h b/components/drivers/include/drivers/i2c.h index e2a9e7d0b8..17d57288cd 100644 --- a/components/drivers/include/drivers/i2c.h +++ b/components/drivers/include/drivers/i2c.h @@ -60,11 +60,12 @@ struct rt_i2c_bus_device void *priv; }; -#ifdef RT_I2C_DEBUG -#define i2c_dbg(fmt, ...) rt_kprintf(fmt, ##__VA_ARGS__) -#else -#define i2c_dbg(fmt, ...) -#endif +struct rt_i2c_client +{ + struct rt_device parent; + struct rt_i2c_bus_device *bus; + rt_uint16_t client_addr; +}; rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, const char *bus_name); diff --git a/components/drivers/include/drivers/mtd.h b/components/drivers/include/drivers/mtd.h deleted file mode 100644 index fb7ea4389d..0000000000 --- a/components/drivers/include/drivers/mtd.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#ifndef __MTD_H__ -#define __MTD_H__ - -#include <rtthread.h> -#include <stddef.h> -#include <stdint.h> - -#define MTD_TYPE_NOR 1 -#define MTD_TYPE_NAND 2 - - /** - * MTD operation modes - * - * @MTD_OPM_PLACE_OOB: OOB data are placed at the given offset (default) - * @MTD_OPM_AUTO_OOB: OOB data are automatically placed at the free areas - * @MTD_OPM_RAW: data are transferred as-is, with no error correction; - */ -enum mtd_opm -{ - MTD_OPM_PLACE_OOB = 0, - MTD_OPM_AUTO_OOB = 1, - MTD_OPM_RAW = 2, -}; - -#ifndef loff_t -typedef long loff_t; -#endif - -struct mtd_oob_region -{ - uint8_t offset; - uint8_t length; -}; - -typedef struct mtd_info -{ - struct rt_device parent; - - const struct mtd_ops *ops; - - uint16_t oob_size; - uint16_t sector_size; /* Minimal writable flash unit size */ - uint32_t block_size:28; /* Erase size for the device */ - uint32_t type:4; - - size_t size; /* Total size of the MTD */ - loff_t offset; /* At which this MTD starts, from the beginning of the MEMORY */ - struct mtd_info *master; - - void *priv; -}rt_mtd_t; - -struct mtd_io_desc -{ - uint8_t mode; /* operation mode(enum mtd_opm) */ - uint8_t ooblen; /* number of oob bytes to write/read */ - uint8_t oobretlen; /* number of oob bytes written/read */ - uint8_t ooboffs; /* offset in the oob area */ - uint8_t *oobbuf; - - size_t datlen; /* number of data bytes to write/read */ - size_t datretlen; /* number of data bytes written/read */ - uint8_t *datbuf; /* if NULL only oob are read/written */ -}; - -struct mtd_ops -{ - int(*erase)(rt_mtd_t *mtd, loff_t addr, size_t len); /* return 0 if success */ - int(*read) (rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *ops); /* return 0 if success */ - int(*write) (rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *ops); /* return 0 if success */ - int(*isbad) (rt_mtd_t *mtd, uint32_t block); /* return 1 if bad, 0 not bad */ - int(*markbad) (rt_mtd_t *mtd, uint32_t block); /* return 0 if success */ -}; - -struct mtd_part -{ - const char *name; /* name of the MTD partion */ - loff_t offset; /* start addr of partion */ - size_t size; /* size of partion */ -}; - -int rt_mtd_erase(rt_mtd_t *mtd, loff_t addr, size_t size); -int rt_mtd_block_erase(rt_mtd_t *mtd, uint32_t block); -int rt_mtd_read_oob(rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *desc); -int rt_mtd_write_oob(rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *desc); -int rt_mtd_read(rt_mtd_t *mtd, loff_t from, uint8_t *buf, size_t len); -int rt_mtd_write(rt_mtd_t *mtd, loff_t to, const uint8_t *buf, size_t len); -int rt_mtd_block_markbad(rt_mtd_t *mtd, uint32_t block); -int rt_mtd_block_isbad(rt_mtd_t *mtd, uint32_t block); - -rt_mtd_t* rt_mtd_get(const char *name); -int rt_mtd_register(rt_mtd_t *master, const struct mtd_part *parts, int np); - -#endif diff --git a/components/drivers/include/drivers/mtd_nand.h b/components/drivers/include/drivers/mtd_nand.h index 8afed000dd..f7675aede6 100644 --- a/components/drivers/include/drivers/mtd_nand.h +++ b/components/drivers/include/drivers/mtd_nand.h @@ -21,13 +21,13 @@ struct rt_mtd_nand_driver_ops; #define RT_MTD_NAND_DEVICE(device) ((struct rt_mtd_nand_device*)(device)) -#define RT_MTD_EOK 0 /* NO error */ -#define RT_MTD_EECC 1 /* ECC error */ -#define RT_MTD_EBUSY 2 /* hardware busy */ -#define RT_MTD_EIO 3 /* generic IO issue */ -#define RT_MTD_ENOMEM 4 /* out of memory */ -#define RT_MTD_ESRC 5 /* source issue */ -#define RT_MTD_EECC_CORRECT 6 /* ECC error but correct */ +#define RT_MTD_EOK 0 /* NO error */ +#define RT_MTD_EECC 101 /* ECC error */ +#define RT_MTD_EBUSY 102 /* hardware busy */ +#define RT_MTD_EIO 103 /* generic IO issue */ +#define RT_MTD_ENOMEM 104 /* out of memory */ +#define RT_MTD_ESRC 105 /* source issue */ +#define RT_MTD_EECC_CORRECT 106 /* ECC error but correct */ struct rt_mtd_nand_device { @@ -41,77 +41,97 @@ struct rt_mtd_nand_device rt_uint32_t pages_per_block; /* The number of page a block */ rt_uint16_t block_total; + /* Only be touched by driver */ rt_uint32_t block_start; /* The start of available block*/ rt_uint32_t block_end; /* The end of available block */ /* operations interface */ - const struct rt_mtd_nand_driver_ops* ops; + const struct rt_mtd_nand_driver_ops *ops; }; struct rt_mtd_nand_driver_ops { - rt_err_t (*read_id) (struct rt_mtd_nand_device* device); + rt_err_t (*read_id)(struct rt_mtd_nand_device *device); - rt_err_t (*read_page)(struct rt_mtd_nand_device* device, + rt_err_t (*read_page)(struct rt_mtd_nand_device *device, rt_off_t page, - rt_uint8_t* data, rt_uint32_t data_len, - rt_uint8_t * spare, rt_uint32_t spare_len); + rt_uint8_t *data, rt_uint32_t data_len, + rt_uint8_t *spare, rt_uint32_t spare_len); - rt_err_t (*write_page)(struct rt_mtd_nand_device * device, + rt_err_t (*write_page)(struct rt_mtd_nand_device *device, rt_off_t page, - const rt_uint8_t * data, rt_uint32_t data_len, - const rt_uint8_t * spare, rt_uint32_t spare_len); - rt_err_t (*move_page) (struct rt_mtd_nand_device *device, rt_off_t src_page, rt_off_t dst_page); + const rt_uint8_t *data, rt_uint32_t data_len, + const rt_uint8_t *spare, rt_uint32_t spare_len); + rt_err_t (*move_page)(struct rt_mtd_nand_device *device, rt_off_t src_page, rt_off_t dst_page); - rt_err_t (*erase_block)(struct rt_mtd_nand_device* device, rt_uint32_t block); - rt_err_t (*check_block)(struct rt_mtd_nand_device* device, rt_uint32_t block); - rt_err_t (*mark_badblock)(struct rt_mtd_nand_device* device, rt_uint32_t block); + rt_err_t (*erase_block)(struct rt_mtd_nand_device *device, rt_uint32_t block); + rt_err_t (*check_block)(struct rt_mtd_nand_device *device, rt_uint32_t block); + rt_err_t (*mark_badblock)(struct rt_mtd_nand_device *device, rt_uint32_t block); }; -rt_err_t rt_mtd_nand_register_device(const char* name, struct rt_mtd_nand_device* device); +rt_err_t rt_mtd_nand_register_device(const char *name, struct rt_mtd_nand_device *device); -rt_inline rt_uint32_t rt_mtd_nand_read_id(struct rt_mtd_nand_device* device) +rt_inline rt_uint32_t rt_mtd_nand_read_id(struct rt_mtd_nand_device *device) { + RT_ASSERT(device->ops->read_id); return device->ops->read_id(device); } rt_inline rt_err_t rt_mtd_nand_read( - struct rt_mtd_nand_device* device, + struct rt_mtd_nand_device *device, rt_off_t page, - rt_uint8_t* data, rt_uint32_t data_len, - rt_uint8_t * spare, rt_uint32_t spare_len) + rt_uint8_t *data, rt_uint32_t data_len, + rt_uint8_t *spare, rt_uint32_t spare_len) { + RT_ASSERT(device->ops->read_page); return device->ops->read_page(device, page, data, data_len, spare, spare_len); } rt_inline rt_err_t rt_mtd_nand_write( - struct rt_mtd_nand_device* device, + struct rt_mtd_nand_device *device, rt_off_t page, - const rt_uint8_t* data, rt_uint32_t data_len, - const rt_uint8_t * spare, rt_uint32_t spare_len) + const rt_uint8_t *data, rt_uint32_t data_len, + const rt_uint8_t *spare, rt_uint32_t spare_len) { + RT_ASSERT(device->ops->write_page); return device->ops->write_page(device, page, data, data_len, spare, spare_len); } -rt_inline rt_err_t rt_mtd_nand_move_page(struct rt_mtd_nand_device* device, - rt_off_t src_page, rt_off_t dst_page) +rt_inline rt_err_t rt_mtd_nand_move_page(struct rt_mtd_nand_device *device, + rt_off_t src_page, rt_off_t dst_page) { + RT_ASSERT(device->ops->move_page); return device->ops->move_page(device, src_page, dst_page); } -rt_inline rt_err_t rt_mtd_nand_erase_block(struct rt_mtd_nand_device* device, rt_uint32_t block) +rt_inline rt_err_t rt_mtd_nand_erase_block(struct rt_mtd_nand_device *device, rt_uint32_t block) { + RT_ASSERT(device->ops->erase_block); return device->ops->erase_block(device, block); } -rt_inline rt_err_t rt_mtd_nand_check_block(struct rt_mtd_nand_device* device, rt_uint32_t block) +rt_inline rt_err_t rt_mtd_nand_check_block(struct rt_mtd_nand_device *device, rt_uint32_t block) { - return device->ops->check_block(device, block); + if (device->ops->check_block) + { + return device->ops->check_block(device, block); + } + else + { + return -RT_ENOSYS; + } } -rt_inline rt_err_t rt_mtd_nand_mark_badblock(struct rt_mtd_nand_device* device, rt_uint32_t block) +rt_inline rt_err_t rt_mtd_nand_mark_badblock(struct rt_mtd_nand_device *device, rt_uint32_t block) { - return device->ops->mark_badblock(device, block); + if (device->ops->mark_badblock) + { + return device->ops->mark_badblock(device, block); + } + else + { + return -RT_ENOSYS; + } } #endif /* MTD_NAND_H_ */ diff --git a/components/drivers/include/drivers/mtdnand.h b/components/drivers/include/drivers/mtdnand.h deleted file mode 100644 index 2e836cb2fb..0000000000 --- a/components/drivers/include/drivers/mtdnand.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#ifndef _MTDNAND_H_ -#define _MTDNAND_H_ - -#include "mtd.h" - - /* Status bits */ -#define NAND_STATUS_FAIL 0x01 -#define NAND_STATUS_FAIL_N1 0x02 -#define NAND_STATUS_WP 0x80 - -typedef enum -{ - NAND_CMD_PAGE_RD, /* read data to chip's page buffer,do WaitBusy after this cmd in low driver */ - NAND_CMD_PAGE_WR0, /* write data to chip's page buffer */ - NAND_CMD_PAGE_WR1, /* do flash programe */ - NAND_CMD_BLK_ERASE, /* erase block */ - NAND_CMD_ECC_EN, /* enable gen HWECC */ - NAND_CMD_ECC_DIS /* disable gen HWECC */ -} nand_cmd_t; - -typedef enum -{ - NAND_ECCM_NONE, - NAND_ECCM_HW, -} nand_eccmode_t; - -struct nand_chip; -struct nand_ops; - -/** -* struct nand_buffers - buffer structure for read/write -* @ecccalc: buffer pointer for calculated ECC, size is oobsize. -* @ecccode: buffer pointer for ECC read from flash, size is oobsize. -* -*/ -struct nand_buffers -{ - uint8_t *ecccalc; - uint8_t *ecccode; -}; - -struct nand_ecc -{ - uint8_t mode; /* nand_eccmode_t */ - uint8_t bytes; /* gen ecc bytes per ecc step(usually 3) */ - uint16_t stepsize:12; /* min 256 */ - uint16_t _step:4; /* */ - - /* driver must set the two interface if HWECC */ - void (*calculate)(struct nand_chip *chip, const uint8_t *dat, uint8_t *ecc_code); - /* return max bit flips if can't correct,return -1 ECC is error(0 success) */ - int(*correct)(struct nand_chip *chip, uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc); - /* ignore if NONECC */ - const struct mtd_oob_region *layout; -}; - -typedef struct nand_chip -{ - rt_mtd_t parent; - - /* driver must init these */ - const struct nand_ops *ops; - struct nand_ecc ecc; - const struct mtd_oob_region *freelayout; - - /* driver do not touch */ - struct nand_buffers buffers; - uint8_t *oob_poi; - uint8_t *pagebuf; - uint32_t size; - uint16_t oobsize; - uint8_t pages_pb; - uint16_t page_size; - int(*read_page)(struct nand_chip *chip, uint8_t *buf, int oob_required, int page); - int(*write_page)(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page); -}rt_nand_t; - -struct nand_ops -{ - int(*cmdfunc)(rt_nand_t *nand, int cmd, int page, int offset); /* send nand operation cmd, return Status bits(0 success), - if nand is busy please wait in low driver */ - int(*read_buf)(rt_nand_t *nand, uint8_t *buf, int len); /* read data from nand chip's page buffer */ - int(*write_buf)(rt_nand_t *nand, const uint8_t *buf, int len);/* write data to nand chip's page buffer */ - int(*isbad)(rt_nand_t *nand, uint32_t blk); /* if NULL OOB[0] used as bad mark(not 0xff is bad) */ - int(*markbad)(rt_nand_t *nand, uint32_t blk); /* if NULL OOB[0] used as bad mark(set to 0x00) */ -}; - -int rt_mtd_nand_init(rt_nand_t *nand, int blk_size, int page_size, int oob_size); - -#endif /* MTD_NAND_H_ */ diff --git a/components/drivers/include/drivers/mtdnor.h b/components/drivers/include/drivers/mtdnor.h deleted file mode 100644 index ccb7466b4b..0000000000 --- a/components/drivers/include/drivers/mtdnor.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#ifndef __MTDNOR_H__ -#define __MTDNOR_H__ - -#include <drivers/mtd.h> - -struct nor_ops; - -typedef struct -{ - rt_mtd_t parent; - - const struct nor_ops *ops; /* operations interface */ -}rt_nor_t; - -struct nor_ops -{ - int (*erase)(rt_nor_t *nor, loff_t addr, size_t len); /* return success erased len or error code */ - int (*read)(rt_nor_t *nor, loff_t addr, uint8_t *buf, size_t len); /* return success data size or error code */ - int (*write)(rt_nor_t *nor, loff_t addr, const uint8_t *buf, size_t len); /* return success data size or error code */ -}; - -int rt_mtd_nor_init(rt_nor_t *nor, int blksize); - -#endif diff --git a/components/drivers/include/drivers/pm.h b/components/drivers/include/drivers/pm.h index e35b21cd48..dd5875aa1d 100644 --- a/components/drivers/include/drivers/pm.h +++ b/components/drivers/include/drivers/pm.h @@ -86,8 +86,8 @@ struct rt_pm; */ struct rt_pm_ops { - void (*sleep)(struct rt_pm *pm, uint8_t mode); - void (*run)(struct rt_pm *pm, uint8_t mode); + void (*sleep)(struct rt_pm *pm, rt_uint8_t mode); + void (*run)(struct rt_pm *pm, rt_uint8_t mode); void (*timer_start)(struct rt_pm *pm, rt_uint32_t timeout); void (*timer_stop)(struct rt_pm *pm); rt_tick_t (*timer_get_tick)(struct rt_pm *pm); @@ -95,9 +95,9 @@ struct rt_pm_ops struct rt_device_pm_ops { - int (*suspend)(const struct rt_device *device, uint8_t mode); - void (*resume)(const struct rt_device *device, uint8_t mode); - int (*frequency_change)(const struct rt_device *device, uint8_t mode); + int (*suspend)(const struct rt_device *device, rt_uint8_t mode); + void (*resume)(const struct rt_device *device, rt_uint8_t mode); + int (*frequency_change)(const struct rt_device *device, rt_uint8_t mode); }; struct rt_device_pm @@ -137,22 +137,22 @@ enum struct rt_pm_notify { - void (*notify)(uint8_t event, uint8_t mode, void *data); + void (*notify)(rt_uint8_t event, rt_uint8_t mode, void *data); void *data; }; -void rt_pm_request(uint8_t sleep_mode); -void rt_pm_release(uint8_t sleep_mode); -int rt_pm_run_enter(uint8_t run_mode); +void rt_pm_request(rt_uint8_t sleep_mode); +void rt_pm_release(rt_uint8_t sleep_mode); +int rt_pm_run_enter(rt_uint8_t run_mode); void rt_pm_device_register(struct rt_device *device, const struct rt_device_pm_ops *ops); void rt_pm_device_unregister(struct rt_device *device); -void rt_pm_notify_set(void (*notify)(uint8_t event, uint8_t mode, void *data), void *data); -void rt_pm_default_set(uint8_t sleep_mode); +void rt_pm_notify_set(void (*notify)(rt_uint8_t event, rt_uint8_t mode, void *data), void *data); +void rt_pm_default_set(rt_uint8_t sleep_mode); void rt_system_pm_init(const struct rt_pm_ops *ops, - uint8_t timer_mask, + rt_uint8_t timer_mask, void *user_data); #endif /* __PM_H__ */ diff --git a/components/drivers/include/drivers/pulse_encoder.h b/components/drivers/include/drivers/pulse_encoder.h new file mode 100644 index 0000000000..0c7df04cd6 --- /dev/null +++ b/components/drivers/include/drivers/pulse_encoder.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-08 balanceTWK the first version + */ + +#ifndef __PULSE_ENCODER_H__ +#define __PULSE_ENCODER_H__ + +#include <rtthread.h> +#include <rtdevice.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* pulse_encoder control command */ +#define PULSE_ENCODER_CMD_GET_TYPE (128 + 0) /* get a pulse_encoder type information */ +#define PULSE_ENCODER_CMD_ENABLE (128 + 1) /* enable pulse_encoder */ +#define PULSE_ENCODER_CMD_DISABLE (128 + 2) /* disable pulse_encoder */ +#define PULSE_ENCODER_CMD_CLEAR_COUNT (128 + 3) /* clear pulse_encoder count */ + +/* pulse_encoder type */ +enum rt_pulse_encoder_type +{ + UNKNOWN_PULSE_ENCODER_TYPE = 0x00, /* Unknown pulse_encoder type */ + SINGLE_PHASE_PULSE_ENCODER, /* single phase pulse_encoder */ + AB_PHASE_PULSE_ENCODER /* two phase pulse_encoder */ +}; + +struct rt_pulse_encoder_device; + +struct rt_pulse_encoder_ops +{ + rt_err_t (*init)(struct rt_pulse_encoder_device *pulse_encoder); + rt_int32_t (*get_count)(struct rt_pulse_encoder_device *pulse_encoder); + rt_err_t (*clear_count)(struct rt_pulse_encoder_device *pulse_encoder); + rt_err_t (*control)(struct rt_pulse_encoder_device *pulse_encoder, rt_uint32_t cmd, void *args); +}; + +struct rt_pulse_encoder_device +{ + struct rt_device parent; + const struct rt_pulse_encoder_ops *ops; + enum rt_pulse_encoder_type type; +}; + +rt_err_t rt_device_pulse_encoder_register(struct rt_pulse_encoder_device *pulse_encoder, const char *name, void *user_data); + +#ifdef __cplusplus +} +#endif + +#endif /* __PULSE_ENCODER_H__ */ diff --git a/components/drivers/include/drivers/rt_inputcapture.h b/components/drivers/include/drivers/rt_inputcapture.h new file mode 100644 index 0000000000..0cadf6444c --- /dev/null +++ b/components/drivers/include/drivers/rt_inputcapture.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-13 balanceTWK first version. + */ + +#ifndef __RT_INPUT_CAPTURE_H__ +#define __RT_INPUT_CAPTURE_H__ + +#include <rtthread.h> +#include <rtdevice.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* capture control command */ +#define INPUTCAPTURE_CMD_CLEAR_BUF (128 + 0) /* clear capture buf */ +#define INPUTCAPTURE_CMD_SET_WATERMARK (128 + 1) /* Set the callback threshold */ + +struct rt_inputcapture_data +{ + rt_uint32_t pulsewidth_us; + rt_bool_t is_high; +}; + +struct rt_inputcapture_device +{ + struct rt_device parent; + + const struct rt_inputcapture_ops *ops; + struct rt_ringbuffer *ringbuff; + rt_size_t watermark; +}; + +/** + * capture operators + */ +struct rt_inputcapture_ops +{ + rt_err_t (*init)(struct rt_inputcapture_device *inputcapture); + rt_err_t (*open)(struct rt_inputcapture_device *inputcapture); + rt_err_t (*close)(struct rt_inputcapture_device *inputcapture); + rt_err_t (*get_pulsewidth)(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us); +}; + +void rt_hw_capture_isr(struct rt_inputcapture_device *inputcapture, rt_bool_t level); + +rt_err_t rt_device_inputcapture_register(struct rt_inputcapture_device *inputcapture, + const char *name, + void *data); +#ifdef __cplusplus +} +#endif + +#endif /* __RT_INPUT_CAPTURE_H__ */ diff --git a/components/drivers/include/ipc/workqueue.h b/components/drivers/include/ipc/workqueue.h index 354a30c04e..23e256c420 100644 --- a/components/drivers/include/ipc/workqueue.h +++ b/components/drivers/include/ipc/workqueue.h @@ -43,13 +43,13 @@ struct rt_work void *work_data; rt_uint16_t flags; rt_uint16_t type; + struct rt_timer timer; + struct rt_workqueue *workqueue; }; struct rt_delayed_work { struct rt_work work; - struct rt_timer timer; - struct rt_workqueue *workqueue; }; #ifdef RT_USING_HEAP @@ -74,6 +74,7 @@ rt_inline void rt_work_init(struct rt_work *work, void (*work_func)(struct rt_wo rt_list_init(&(work->list)); work->work_func = work_func; work->work_data = work_data; + work->workqueue = RT_NULL; work->flags = 0; work->type = 0; } @@ -81,6 +82,7 @@ rt_inline void rt_work_init(struct rt_work *work, void (*work_func)(struct rt_wo 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 diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index d59b40cc47..623c085430 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -122,6 +122,18 @@ extern "C" { #include "drivers/mtdnand.h" #endif +#ifdef RT_USING_HWCRYPTO +#include "drivers/crypto.h" +#endif + +#ifdef RT_USING_PULSE_ENCODER +#include "drivers/pulse_encoder.h" +#endif + +#ifdef RT_USING_INPUT_CAPTURE +#include "drivers/rt_inputcapture.h" +#endif + #ifdef __cplusplus } #endif diff --git a/components/drivers/misc/SConscript b/components/drivers/misc/SConscript index c45ba524c5..8a9fdb5eb9 100644 --- a/components/drivers/misc/SConscript +++ b/components/drivers/misc/SConscript @@ -13,6 +13,12 @@ if GetDepend(['RT_USING_ADC']): if GetDepend(['RT_USING_PWM']): src = src + ['rt_drv_pwm.c'] + +if GetDepend(['RT_USING_PULSE_ENCODER']): + src = src + ['pulse_encoder.c'] + +if GetDepend(['RT_USING_INPUT_CAPTURE']): + src = src + ['rt_inputcapture.c'] if len(src): group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) diff --git a/components/drivers/misc/pulse_encoder.c b/components/drivers/misc/pulse_encoder.c new file mode 100644 index 0000000000..3145c24675 --- /dev/null +++ b/components/drivers/misc/pulse_encoder.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-08 balanceTWK the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> + +static rt_err_t rt_pulse_encoder_init(struct rt_device *dev) +{ + struct rt_pulse_encoder_device *pulse_encoder; + + pulse_encoder = (struct rt_pulse_encoder_device *)dev; + if (pulse_encoder->ops->init) + { + return pulse_encoder->ops->init(pulse_encoder); + } + else + { + return -RT_ENOSYS; + } +} + +static rt_err_t rt_pulse_encoder_open(struct rt_device *dev, rt_uint16_t oflag) +{ + struct rt_pulse_encoder_device *pulse_encoder; + + pulse_encoder = (struct rt_pulse_encoder_device *)dev; + if (pulse_encoder->ops->control) + { + return pulse_encoder->ops->control(pulse_encoder, PULSE_ENCODER_CMD_ENABLE, RT_NULL); + } + else + { + return -RT_ENOSYS; + } +} + +static rt_err_t rt_pulse_encoder_close(struct rt_device *dev) +{ + struct rt_pulse_encoder_device *pulse_encoder; + + pulse_encoder = (struct rt_pulse_encoder_device *)dev; + if (pulse_encoder->ops->control) + { + return pulse_encoder->ops->control(pulse_encoder, PULSE_ENCODER_CMD_DISABLE, RT_NULL); + } + else + { + return -RT_ENOSYS; + } +} + +static rt_size_t rt_pulse_encoder_read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + struct rt_pulse_encoder_device *pulse_encoder; + + pulse_encoder = (struct rt_pulse_encoder_device *)dev; + if (pulse_encoder->ops->get_count) + { + *(rt_int32_t *)buffer = pulse_encoder->ops->get_count(pulse_encoder); + } + return 1; +} + +static rt_err_t rt_pulse_encoder_control(struct rt_device *dev, int cmd, void *args) +{ + rt_err_t result; + struct rt_pulse_encoder_device *pulse_encoder; + + result = RT_EOK; + pulse_encoder = (struct rt_pulse_encoder_device *)dev; + switch (cmd) + { + case PULSE_ENCODER_CMD_CLEAR_COUNT: + result = pulse_encoder->ops->clear_count(pulse_encoder); + break; + case PULSE_ENCODER_CMD_GET_TYPE: + *(enum rt_pulse_encoder_type *)args = pulse_encoder->type; + break; + case PULSE_ENCODER_CMD_ENABLE: + case PULSE_ENCODER_CMD_DISABLE: + result = pulse_encoder->ops->control(pulse_encoder, cmd, args); + break; + default: + result = -RT_ENOSYS; + break; + } + + return result; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops pulse_encoder_ops = +{ + rt_pulse_encoder_init, + rt_pulse_encoder_open, + rt_pulse_encoder_close, + rt_pulse_encoder_read, + RT_NULL, + rt_pulse_encoder_control +}; +#endif + +rt_err_t rt_device_pulse_encoder_register(struct rt_pulse_encoder_device *pulse_encoder, const char *name, void *user_data) +{ + struct rt_device *device; + + RT_ASSERT(pulse_encoder != RT_NULL); + RT_ASSERT(pulse_encoder->ops != RT_NULL); + + device = &(pulse_encoder->parent); + + device->type = RT_Device_Class_Miscellaneous; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &pulse_encoder_ops; +#else + device->init = rt_pulse_encoder_init; + device->open = rt_pulse_encoder_open; + device->close = rt_pulse_encoder_close; + device->read = rt_pulse_encoder_read; + device->write = RT_NULL; + device->control = rt_pulse_encoder_control; +#endif + device->user_data = user_data; + + return rt_device_register(device, name, RT_DEVICE_FLAG_RDONLY | RT_DEVICE_FLAG_STANDALONE); +} diff --git a/components/drivers/misc/rt_drv_pwm.c b/components/drivers/misc/rt_drv_pwm.c index 2b7986b4d8..97d38d51b3 100644 --- a/components/drivers/misc/rt_drv_pwm.c +++ b/components/drivers/misc/rt_drv_pwm.c @@ -259,7 +259,7 @@ static int pwm_set(int argc, char **argv) _exit: return result; } -MSH_CMD_EXPORT(pwm_set, pwm_set 1 100 50); +MSH_CMD_EXPORT(pwm_set, pwm_set pwm1 1 100 50); #endif /* FINSH_USING_MSH */ #endif /* RT_USING_FINSH */ diff --git a/components/drivers/misc/rt_inputcapture.c b/components/drivers/misc/rt_inputcapture.c new file mode 100644 index 0000000000..d1886186d7 --- /dev/null +++ b/components/drivers/misc/rt_inputcapture.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-13 balanceTWK the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <rtdbg.h> + +static rt_err_t rt_inputcapture_init(struct rt_device *dev) +{ + rt_err_t ret; + struct rt_inputcapture_device *inputcapture; + + RT_ASSERT(dev != RT_NULL); + + ret = RT_EOK; + inputcapture = (struct rt_inputcapture_device *)dev; + inputcapture->watermark = RT_INPUT_CAPTURE_RB_SIZE / 2; + if (inputcapture->ops->init) + { + ret = inputcapture->ops->init(inputcapture); + } + + return ret; +} + +static rt_err_t rt_inputcapture_open(struct rt_device *dev, rt_uint16_t oflag) +{ + rt_err_t ret; + struct rt_inputcapture_device *inputcapture; + + RT_ASSERT(dev != RT_NULL); + + ret = RT_EOK; + inputcapture = (struct rt_inputcapture_device *)dev; + if (inputcapture->ringbuff == RT_NULL) + { + inputcapture->ringbuff = rt_ringbuffer_create(sizeof(struct rt_inputcapture_data) * RT_INPUT_CAPTURE_RB_SIZE); + } + if (inputcapture->ops->open) + { + ret = inputcapture->ops->open(inputcapture); + } + + return ret; +} + +static rt_err_t rt_inputcapture_close(struct rt_device *dev) +{ + rt_err_t ret; + struct rt_inputcapture_device *inputcapture; + + RT_ASSERT(dev != RT_NULL); + + ret = -RT_ERROR; + inputcapture = (struct rt_inputcapture_device *)dev; + + if (inputcapture->ops->close) + { + ret = inputcapture->ops->close(inputcapture); + } + + if (ret != RT_EOK) + { + return ret; + } + + if (inputcapture->ringbuff) + { + rt_ringbuffer_destroy(inputcapture->ringbuff); + inputcapture->ringbuff = RT_NULL; + } + return ret; +} + +static rt_size_t rt_inputcapture_read(struct rt_device *dev, + rt_off_t pos, + void *buffer, + rt_size_t size) +{ + rt_size_t receive_size; + struct rt_inputcapture_device *inputcapture; + + RT_ASSERT(dev != RT_NULL); + + inputcapture = (struct rt_inputcapture_device *)dev; + receive_size = rt_ringbuffer_get(inputcapture->ringbuff, (rt_uint8_t *)buffer, sizeof(struct rt_inputcapture_data) * size); + + return receive_size / sizeof(struct rt_inputcapture_data); +} + +static rt_err_t rt_inputcapture_control(struct rt_device *dev, int cmd, void *args) +{ + rt_err_t result; + struct rt_inputcapture_device *inputcapture; + + RT_ASSERT(dev != RT_NULL); + + result = RT_EOK; + inputcapture = (struct rt_inputcapture_device *)dev; + switch (cmd) + { + case INPUTCAPTURE_CMD_CLEAR_BUF: + if (inputcapture->ringbuff) + { + rt_ringbuffer_reset(inputcapture->ringbuff); + } + break; + case INPUTCAPTURE_CMD_SET_WATERMARK: + inputcapture->watermark = *(rt_size_t *)args; + break; + default: + result = -RT_ENOSYS; + break; + } + + return result; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops inputcapture_ops = +{ + rt_inputcapture_init, + rt_inputcapture_open, + rt_inputcapture_close, + rt_inputcapture_read, + RT_NULL, + rt_inputcapture_control +}; +#endif + +rt_err_t rt_device_inputcapture_register(struct rt_inputcapture_device *inputcapture, const char *name, void *user_data) +{ + struct rt_device *device; + + RT_ASSERT(inputcapture != RT_NULL); + RT_ASSERT(inputcapture->ops != RT_NULL); + RT_ASSERT(inputcapture->ops->get_pulsewidth != RT_NULL); + + device = &(inputcapture->parent); + + device->type = RT_Device_Class_Miscellaneous; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + inputcapture->ringbuff = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &inputcapture_ops; +#else + device->init = rt_inputcapture_init; + device->open = rt_inputcapture_open; + device->close = rt_inputcapture_close; + device->read = rt_inputcapture_read; + device->write = RT_NULL; + device->control = rt_inputcapture_control; +#endif + device->user_data = user_data; + + return rt_device_register(device, name, RT_DEVICE_FLAG_RDONLY | RT_DEVICE_FLAG_STANDALONE); +} + +/** + * This function is ISR for inputcapture interrupt. + * level: RT_TRUE denotes high level pulse, and RT_FALSE denotes low level pulse. + */ +void rt_hw_inputcapture_isr(struct rt_inputcapture_device *inputcapture, rt_bool_t level) +{ + struct rt_inputcapture_data data; + rt_size_t receive_size; + if (inputcapture->ops->get_pulsewidth(inputcapture, &data.pulsewidth_us) != RT_EOK) + { + return; + } + + data.is_high = level; + if (rt_ringbuffer_put(inputcapture->ringbuff, (rt_uint8_t *)&data, sizeof(struct rt_inputcapture_data)) == 0) + { + LOG_W("inputcapture ringbuffer doesn't have enough space."); + } + + receive_size = rt_ringbuffer_data_len(inputcapture->ringbuff) / sizeof(struct rt_inputcapture_data); + + if (receive_size >= inputcapture->watermark) + { + /* indicate to upper layer application */ + if (inputcapture->parent.rx_indicate != RT_NULL) + inputcapture->parent.rx_indicate(&inputcapture->parent, receive_size); + } +} diff --git a/components/drivers/mtd/SConscript b/components/drivers/mtd/SConscript index 462c38194c..6f86656187 100644 --- a/components/drivers/mtd/SConscript +++ b/components/drivers/mtd/SConscript @@ -1,5 +1,3 @@ -Import('RTT_ROOT') -Import('rtconfig') from building import * cwd = GetCurrentDir() @@ -9,17 +7,6 @@ depend = [] CPPPATH = [cwd + '/../include'] group = [] -if GetDepend(['RT_USING_MTD']): - src += ['mtd.c'] - depend += ['RT_USING_MTD'] - - if GetDepend(['MTD_USING_NOR']): - src += ['mtdnor.c'] - depend += ['MTD_USING_NOR'] - if GetDepend(['MTD_USING_NAND']): - src += ['mtdnand.c'] - depend += ['MTD_USING_NAND'] - if GetDepend(['RT_USING_MTD_NOR']): src += ['mtd_nor.c'] depend += ['RT_USING_MTD_NOR'] @@ -31,4 +18,4 @@ if GetDepend(['RT_USING_MTD_NAND']): if src: group = DefineGroup('DeviceDrivers', src, depend = depend, CPPPATH = CPPPATH) -Return('group')
\ No newline at end of file +Return('group') diff --git a/components/drivers/mtd/mtd.c b/components/drivers/mtd/mtd.c deleted file mode 100644 index 3e7b4f2b54..0000000000 --- a/components/drivers/mtd/mtd.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#include <drivers/mtd.h> - -static rt_mtd_t* mtd_part_alloc(rt_mtd_t *master, const struct mtd_part *part) -{ - rt_mtd_t *slave; - - slave = rt_malloc(sizeof(rt_mtd_t)); - if (slave == RT_NULL) - goto out; - - slave->master = master; - - *slave = *master; - slave->size = part->size; - slave->offset = part->offset; - -out: - - return slave; -} - -rt_mtd_t* rt_mtd_get(const char *name) -{ - rt_mtd_t *mtd; - - mtd = (rt_mtd_t *)rt_device_find(name); - if (mtd == RT_NULL) - return RT_NULL; - - if (mtd->parent.type != RT_Device_Class_MTD) - return RT_NULL; - - return mtd; -} - -/* - * Register MTD driver - * - * @parts partion description - * @np number of partitions - * @return number of unregistered partitions - * -*/ -int rt_mtd_register(rt_mtd_t *master, const struct mtd_part *parts, int np) -{ - int ret; - rt_mtd_t *slave; - - master->master = master; - master->parent.type = RT_Device_Class_MTD; - - if (np > 0) - { - master->offset = parts->offset; - master->size = parts->size; - - ret = rt_device_register((rt_device_t)master, parts->name, 0); - if (ret != 0) - goto _out; - - np --; - parts ++; - } - - while (np > 0) - { - slave = mtd_part_alloc(master, parts); - if (!slave) - break; - ret = rt_device_register((rt_device_t)slave, parts->name, 0); - if (ret) - break; - parts ++; - np --; - } - -_out: - return np; -} - -int rt_mtd_block_erase(rt_mtd_t *mtd, uint32_t block) -{ - uint32_t total_blks; - loff_t addr; - - total_blks = mtd->size/mtd->block_size; - if (block >= total_blks) - return -EINVAL; - addr = mtd->offset + mtd->block_size * block; - - return mtd->ops->erase(mtd->master, addr, mtd->block_size); -} - -int rt_mtd_block_isbad(rt_mtd_t *mtd, uint32_t block) -{ - uint32_t total_blks, offset_blk; - - if (!mtd->ops->isbad) - return 0; - - total_blks = mtd->size / mtd->block_size; - if (block >= total_blks) - return -EINVAL; - offset_blk = mtd->offset / mtd->block_size; - - return mtd->ops->isbad(mtd->master, block + offset_blk); -} - -int rt_mtd_block_markbad(rt_mtd_t *mtd, uint32_t block) -{ - uint32_t total_blks, offset_blk; - - if (!mtd->ops->markbad) - return -EOPNOTSUPP; - - total_blks = mtd->size / mtd->block_size; - if (block >= total_blks) - return -EINVAL; - offset_blk = mtd->offset / mtd->block_size; - - return mtd->ops->markbad(mtd->master, block + offset_blk); -} - -int rt_mtd_erase(rt_mtd_t *mtd, loff_t addr, size_t size) -{ - if (addr > mtd->size || (addr + size) > mtd->size) - return -EINVAL; - addr += mtd->offset; - - return mtd->ops->erase(mtd->master, addr, size); -} - -/* -* Read data only -* -* @from offset to read from -* @return success size or error code -*/ -int rt_mtd_read(rt_mtd_t *mtd, loff_t from, uint8_t *buf, size_t len) -{ - int ret; - struct mtd_io_desc desc = {0}; - - if (from < 0 || from >= (loff_t)mtd->size || len > mtd->size - from) - return -EINVAL; - if (!len) - return 0; - - desc.datbuf = buf; - desc.datlen = len; - ret = mtd->ops->read(mtd->master, from + mtd->offset, &desc); - if (ret) - return ret; - - return desc.datretlen; -} - -/** -* Write data only -* -* @to offset to write from -* @return success size or error code -*/ -int rt_mtd_write(rt_mtd_t *mtd, loff_t to, const uint8_t *buf, size_t len) -{ - int ret; - struct mtd_io_desc desc = {0}; - - if (to < 0 || to >= (loff_t)mtd->size || len > mtd->size - to) - return -EINVAL; - if (!mtd->ops->write) - return -EROFS; - if (!len) - return 0; - - desc.datbuf = (uint8_t*)buf; - desc.datlen = len; - ret = mtd->ops->write(mtd->master, to + mtd->offset, &desc); - if (ret) - return ret; - - return desc.datretlen; -} - -/** -* Read data and/or out-of-band -* -* @from offset to read from -* @desc sector operation description structure -* @return error code, 0 success -*/ -int rt_mtd_read_oob(rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *desc) -{ - desc->datretlen = 0; - desc->oobretlen = 0; - - if (from < 0 || from >= (loff_t)mtd->size) - return -EINVAL; - - if (desc->datbuf && (desc->datlen > (mtd->size - from))) - return -EINVAL; - - return mtd->ops->read(mtd->master, from + mtd->offset, desc); -} - -/** -* Write data and/or out-of-band -* -* @to offset to read from -* @desc sector operation description structure -* @return error code, 0 success -*/ -int rt_mtd_write_oob(rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *desc) -{ - desc->datretlen = 0; - desc->oobretlen = 0; - - if (to < 0 || to >= (loff_t)mtd->size) - return -EINVAL; - - if (desc->datbuf && (desc->datlen >(mtd->size - to))) - return -EINVAL; - - return mtd->ops->write(mtd->master, to + mtd->offset, desc); -} diff --git a/components/drivers/mtd/mtd_nand.c b/components/drivers/mtd/mtd_nand.c index 3e4582ceaf..ae5aa9c172 100644 --- a/components/drivers/mtd/mtd_nand.c +++ b/components/drivers/mtd/mtd_nand.c @@ -56,7 +56,7 @@ static rt_err_t _mtd_control(rt_device_t dev, int cmd, void *args) } #ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops mtd_nand_ops = +const static struct rt_device_ops mtd_nand_ops = { _mtd_init, _mtd_open, @@ -78,7 +78,7 @@ rt_err_t rt_mtd_nand_register_device(const char *name, /* set device class and generic device interface */ dev->type = RT_Device_Class_MTD; #ifdef RT_USING_DEVICE_OPS - dev->ops = &mtd_nand_ops; + dev->ops = &mtd_nand_ops; #else dev->init = _mtd_init; dev->open = _mtd_open; @@ -101,188 +101,262 @@ rt_err_t rt_mtd_nand_register_device(const char *name, static void mtd_dump_hex(const rt_uint8_t *ptr, rt_size_t buflen) { - unsigned char *buf = (unsigned char*)ptr; - int i, j; - for (i=0; i<buflen; i+=16) - { - rt_kprintf("%06x: ", i); - for (j=0; j<16; j++) - if (i+j < buflen) - rt_kprintf("%02x ", buf[i+j]); - else - rt_kprintf(" "); - rt_kprintf(" "); - for (j=0; j<16; j++) - if (i+j < buflen) - rt_kprintf("%c", __is_print(buf[i+j]) ? buf[i+j] : '.'); - rt_kprintf("\n"); - } + unsigned char *buf = (unsigned char *)ptr; + int i, j; + for (i = 0; i < buflen; i += 16) + { + rt_kprintf("%06x: ", i); + for (j = 0; j < 16; j++) + if (i + j < buflen) + rt_kprintf("%02x ", buf[i + j]); + else + rt_kprintf(" "); + rt_kprintf(" "); + for (j = 0; j < 16; j++) + if (i + j < buflen) + rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.'); + rt_kprintf("\n"); + } } -int mtd_nandid(const char* name) +int mtd_nandid(const char *name) { - struct rt_mtd_nand_device *nand; - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + struct rt_mtd_nand_device *nand; + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } - return rt_mtd_nand_read_id(nand); + return rt_mtd_nand_read_id(nand); } -FINSH_FUNCTION_EXPORT_ALIAS(mtd_nandid, nand_id, read ID - nandid(name)); -int mtd_nand_read(const char* name, int block, int page) +int mtd_nand_read(const char *name, int block, int page) { - rt_err_t result; - rt_uint8_t *page_ptr; - rt_uint8_t *oob_ptr; - struct rt_mtd_nand_device *nand; + rt_err_t result; + rt_uint8_t *page_ptr; + rt_uint8_t *oob_ptr; + struct rt_mtd_nand_device *nand; - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } - page_ptr = rt_malloc(nand->page_size + nand->oob_size); - if (page_ptr == RT_NULL) - { - rt_kprintf("out of memory!\n"); - return -RT_ENOMEM; - } + page_ptr = rt_malloc(nand->page_size + nand->oob_size); + if (page_ptr == RT_NULL) + { + rt_kprintf("out of memory!\n"); + return -RT_ENOMEM; + } - oob_ptr = page_ptr + nand->page_size; - rt_memset(page_ptr, 0xff, nand->page_size + nand->oob_size); + oob_ptr = page_ptr + nand->page_size; + rt_memset(page_ptr, 0xff, nand->page_size + nand->oob_size); - /* calculate the page number */ - page = block * nand->pages_per_block + page; - result = rt_mtd_nand_read(nand, page, page_ptr, nand->page_size, - oob_ptr, nand->oob_size); + /* calculate the page number */ + page = block * nand->pages_per_block + page; + result = rt_mtd_nand_read(nand, page, page_ptr, nand->page_size, + oob_ptr, nand->oob_size); - rt_kprintf("read page, rc=%d\n", result); - mtd_dump_hex(page_ptr, nand->page_size); - mtd_dump_hex(oob_ptr, nand->oob_size); + rt_kprintf("read page, rc=%d\n", result); + mtd_dump_hex(page_ptr, nand->page_size); + mtd_dump_hex(oob_ptr, nand->oob_size); - rt_free(page_ptr); - return 0; + rt_free(page_ptr); + return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_read, nand_read, read page in nand - nand_read(name, block, page)); -int mtd_nand_readoob(const char* name, int block, int page) +int mtd_nand_readoob(const char *name, int block, int page) { - struct rt_mtd_nand_device *nand; - rt_uint8_t *oob_ptr; + struct rt_mtd_nand_device *nand; + rt_uint8_t *oob_ptr; - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } - oob_ptr = rt_malloc(nand->oob_size); - if (oob_ptr == RT_NULL) - { - rt_kprintf("out of memory!\n"); - return -RT_ENOMEM; - } + oob_ptr = rt_malloc(nand->oob_size); + if (oob_ptr == RT_NULL) + { + rt_kprintf("out of memory!\n"); + return -RT_ENOMEM; + } - /* calculate the page number */ - page = block * nand->pages_per_block + page; - rt_mtd_nand_read(nand, page, RT_NULL, nand->page_size, - oob_ptr, nand->oob_size); - mtd_dump_hex(oob_ptr, nand->oob_size); + /* calculate the page number */ + page = block * nand->pages_per_block + page; + rt_mtd_nand_read(nand, page, RT_NULL, nand->page_size, + oob_ptr, nand->oob_size); + mtd_dump_hex(oob_ptr, nand->oob_size); - rt_free(oob_ptr); - return 0; + rt_free(oob_ptr); + return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_readoob, nand_readoob, read spare data in nand - nand_readoob(name, block, page)); -int mtd_nand_write(const char* name, int block, int page) +int mtd_nand_write(const char *name, int block, int page) { - rt_err_t result; - rt_uint8_t *page_ptr; - rt_uint8_t *oob_ptr; - rt_uint32_t index; - struct rt_mtd_nand_device *nand; + rt_err_t result; + rt_uint8_t *page_ptr; + rt_uint8_t *oob_ptr; + rt_uint32_t index; + struct rt_mtd_nand_device *nand; - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } - page_ptr = rt_malloc(nand->page_size + nand->oob_size); - if (page_ptr == RT_NULL) - { - rt_kprintf("out of memory!\n"); - return -RT_ENOMEM; - } + page_ptr = rt_malloc(nand->page_size + nand->oob_size); + if (page_ptr == RT_NULL) + { + rt_kprintf("out of memory!\n"); + return -RT_ENOMEM; + } - oob_ptr = page_ptr + nand->page_size; - /* prepare page data */ - for (index = 0; index < nand->page_size; index ++) - { - page_ptr[index] = index & 0xff; - } - /* prepare oob data */ - for (index = 0; index < nand->oob_size; index ++) - { - oob_ptr[index] = index & 0xff; - } + oob_ptr = page_ptr + nand->page_size; + /* prepare page data */ + for (index = 0; index < nand->page_size; index ++) + { + page_ptr[index] = index & 0xff; + } + /* prepare oob data */ + for (index = 0; index < nand->oob_size; index ++) + { + oob_ptr[index] = index & 0xff; + } - /* calculate the page number */ - page = block * nand->pages_per_block + page; - result = rt_mtd_nand_write(nand, page, page_ptr, nand->page_size, - oob_ptr, nand->oob_size); - if (result != RT_MTD_EOK) - { - rt_kprintf("write page failed!, rc=%d\n", result); - } + /* calculate the page number */ + page = block * nand->pages_per_block + page; + result = rt_mtd_nand_write(nand, page, page_ptr, nand->page_size, + oob_ptr, nand->oob_size); + if (result != RT_MTD_EOK) + { + rt_kprintf("write page failed!, rc=%d\n", result); + } - rt_free(page_ptr); - return 0; + rt_free(page_ptr); + return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_write, nand_write, write dump data to nand - nand_write(name, block, page)); -int mtd_nand_erase(const char* name, int block) +int mtd_nand_erase(const char *name, int block) { - struct rt_mtd_nand_device *nand; - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + struct rt_mtd_nand_device *nand; + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } - return rt_mtd_nand_erase_block(nand, block); + return rt_mtd_nand_erase_block(nand, block); } -FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_erase, nand_erase, nand_erase(name, block)); -int mtd_nand_erase_all(const char* name) +int mtd_nand_erase_all(const char *name) { - rt_uint32_t index = 0; - struct rt_mtd_nand_device *nand; - - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + rt_uint32_t index = 0; + struct rt_mtd_nand_device *nand; - for (index = 0; index < (nand->block_end - nand->block_start); index ++) - { - rt_mtd_nand_erase_block(nand, index); - } - - return 0; + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } + + for (index = 0; index < (nand->block_end - nand->block_start); index ++) + { + rt_mtd_nand_erase_block(nand, index); + } + + return 0; +} + +#ifdef FINSH_USING_MSH +static void mtd_nand(int argc, char **argv) +{ + /* If the number of arguments less than 2 */ + if (argc < 3) + { +help: + rt_kprintf("\n"); + rt_kprintf("mtd_nand [OPTION] [PARAM ...]\n"); + rt_kprintf(" id <name> Get nandid by given name\n"); + rt_kprintf(" read <name> <bn> <pn> Read data on page <pn> of block <bn> of device <name>\n"); + rt_kprintf(" readoob <name> <bn> <pn> Read oob on page <pn> of block <bn> of device <name>\n"); + rt_kprintf(" write <name> <bn> <pn> Run write test on page <pn> of block <bn> of device <name>\n"); + rt_kprintf(" erase <name> <bn> Erase on block <bn> of device <name>\n"); + rt_kprintf(" eraseall <name> Erase all block on device <name>\n"); + return ; + } + else if (!strcmp(argv[1], "id")) + { + mtd_nandid(argv[2]); + } + else if (!strcmp(argv[1], "read")) + { + if (argc < 5) + { + rt_kprintf("The input parameters are too few!\n"); + goto help; + } + mtd_nand_read(argv[2], atoi(argv[3]), atoi(argv[4])); + } + else if (!strcmp(argv[1], "readoob")) + { + if (argc < 5) + { + rt_kprintf("The input parameters are too few!\n"); + goto help; + } + mtd_nand_readoob(argv[2], atoi(argv[3]), atoi(argv[4])); + } + else if (!strcmp(argv[1], "write")) + { + if (argc < 5) + { + rt_kprintf("The input parameters are too few!\n"); + goto help; + } + mtd_nand_write(argv[2], atoi(argv[3]), atoi(argv[4])); + } + else if (!strcmp(argv[1], "erase")) + { + if (argc < 4) + { + rt_kprintf("The input parameters are too few!\n"); + goto help; + } + mtd_nand_erase(argv[2], atoi(argv[3])); + } + else if (!strcmp(argv[1], "eraseall")) + { + mtd_nand_erase_all(argv[2]); + } + else + { + rt_kprintf("Input parameters are not supported!\n"); + goto help; + } } +MSH_CMD_EXPORT(mtd_nand, MTD nand device test function); +#endif /* FINSH_USING_MSH */ + +#ifndef FINSH_USING_MSH_ONLY +FINSH_FUNCTION_EXPORT_ALIAS(mtd_nandid, nand_id, read ID - nandid(name)); +FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_read, nand_read, read page in nand - nand_read(name, block, page)); +FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_readoob, nand_readoob, read spare data in nand - nand_readoob(name, block, page)); +FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_write, nand_write, write dump data to nand - nand_write(name, block, page)); +FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_erase, nand_erase, nand_erase(name, block)); FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_erase_all, nand_erase_all, erase all of nand device - nand_erase_all(name, block)); -#endif +#endif /* FINSH_USING_MSH_ONLY */ -#endif +#endif /* defined(RT_MTD_NAND_DEBUG) && defined(RT_USING_FINSH) */ + +#endif /* RT_USING_MTD_NAND */ diff --git a/components/drivers/mtd/mtdnand.c b/components/drivers/mtd/mtdnand.c deleted file mode 100644 index 50012219fb..0000000000 --- a/components/drivers/mtd/mtdnand.c +++ /dev/null @@ -1,645 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-09-10 heyuanjie87 first version - */ - -#include <rtdevice.h> - -#define MTDTONAND(x) ((rt_nand_t*)(x)) -#define NOTALIGNED(x) ((x & (chip->page_size - 1)) != 0) -#ifndef min -#define min(a,b) (a>b? b:a) -#endif - -static uint8_t *nand_fill_oob(rt_nand_t *chip, uint8_t *oob, size_t len, struct mtd_io_desc *desc) -{ - rt_memset(chip->oob_poi, 0xff, chip->oobsize); - - switch (desc->mode) - { - case MTD_OPM_PLACE_OOB: - case MTD_OPM_RAW: - rt_memcpy(chip->oob_poi + desc->ooboffs, oob, len); - return oob + len; - - case MTD_OPM_AUTO_OOB: - { - const struct mtd_oob_region *free = chip->freelayout; - uint32_t boffs; - size_t bytes; - - bytes = min(len, free->length); - boffs = free->offset; - - rt_memcpy(chip->oob_poi + boffs, oob, bytes); - oob += bytes; - - return oob; - } - } - - return NULL; -} - -static uint8_t *nand_transfer_oob(rt_nand_t *chip, uint8_t *oob, struct mtd_io_desc *desc, size_t len) -{ - switch (desc->mode) - { - case MTD_OPM_PLACE_OOB: - case MTD_OPM_RAW: - rt_memcpy(oob, chip->oob_poi + desc->ooboffs, len); - return oob + len; - - case MTD_OPM_AUTO_OOB: - { - struct mtd_oob_region *free = (struct mtd_oob_region *)chip->freelayout; - uint32_t boffs = 0, roffs = desc->ooboffs; - size_t bytes = 0; - - for (; free->length && len; free++, len -= bytes) - { - /* Read request not from offset 0? */ - if (roffs) - { - if (roffs >= free->length) - { - roffs -= free->length; - continue; - } - boffs = free->offset + roffs; - bytes = min(len, (free->length - roffs)); - roffs = 0; - } - else - { - bytes = min(len, free->length); - boffs = free->offset; - } - - rt_memcpy(oob, chip->oob_poi + boffs, bytes); - oob += bytes; - } - - return oob; - } - } - - return NULL; -} - -static int nand_read_page_raw(rt_nand_t *chip, uint8_t *buf, int oob_required, int page) -{ - chip->ops->read_buf(chip, buf, chip->page_size); - - if (oob_required) - chip->ops->read_buf(chip, chip->oob_poi, chip->oobsize); - - return 0; -} - -static int nand_write_page_raw(rt_nand_t *chip, const uint8_t *buf, int oob_required, int page) -{ - chip->ops->write_buf(chip, buf, chip->page_size); - - if (oob_required) - chip->ops->write_buf(chip, chip->oob_poi, chip->oobsize); - - return 0; -} - -static int nand_write_page_hwecc(rt_nand_t *chip, const uint8_t *buf, int oob_required, int page) -{ - uint16_t i; - uint16_t stepsize = chip->ecc.stepsize; - uint16_t eccbytes = chip->ecc.bytes; - uint16_t eccsteps = chip->ecc._step; - uint16_t eccpos = chip->ecc.layout->offset; - uint8_t *ecc_calc = chip->buffers.ecccalc; - const uint8_t *p = buf; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += stepsize) - { - chip->ops->cmdfunc(chip, NAND_CMD_ECC_EN, 0, 0); - chip->ops->write_buf(chip, p, stepsize); - chip->ecc.calculate(chip, p, &ecc_calc[i]); - chip->ops->cmdfunc(chip, NAND_CMD_ECC_DIS, 0, 0); - } - - rt_memcpy(&chip->oob_poi[eccpos], ecc_calc, chip->ecc.layout->length); - - chip->ops->write_buf(chip, chip->oob_poi, chip->oobsize); - - return 0; -} - -static int nand_read_page_hwecc(rt_nand_t *chip, uint8_t *buf, int oob_required, int page) -{ - uint16_t i; - uint16_t eccsize = chip->ecc.stepsize; - uint16_t eccbytes = chip->ecc.bytes; - uint16_t eccsteps = chip->ecc._step; - uint16_t eccpos = chip->ecc.layout->offset; - uint8_t *p = buf; - uint8_t *ecc_calc = chip->buffers.ecccalc; - uint8_t *ecc_code = chip->buffers.ecccode; - int ret = 0; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) - { - chip->ops->cmdfunc(chip, NAND_CMD_ECC_EN, 0, 0); - chip->ops->read_buf(chip, p, eccsize); - chip->ecc.calculate(chip, p, &ecc_calc[i]); - chip->ops->cmdfunc(chip, NAND_CMD_ECC_DIS, 0, 0); - } - - chip->ops->read_buf(chip, chip->oob_poi, chip->oobsize); - rt_memcpy(ecc_code, &chip->oob_poi[eccpos], chip->ecc.layout->length); - - eccsteps = chip->ecc._step; - p = buf; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) - { - int stat; - - stat = chip->ecc.correct(chip, p, &ecc_code[i], &ecc_calc[i]); - if (stat != 0) - ret = -1; - } - - return ret; -} - -static int nand_write_page(rt_nand_t *chip, const uint8_t *buf, - int oob_required, int page, int raw) -{ - int status; - - chip->ops->cmdfunc(chip, NAND_CMD_PAGE_WR0, page, 0x00); - - if (raw) - { - nand_write_page_raw(chip, buf, oob_required, page); - } - else - { - chip->write_page(chip, buf, oob_required, page); - } - - status = chip->ops->cmdfunc(chip, NAND_CMD_PAGE_WR1, -1, -1); - - return status; -} - -static int nand_do_read_desc(rt_nand_t *chip, loff_t from, struct mtd_io_desc *desc) -{ - int page, bytes; - char oob_required; - char ecc_fail = 0; - int ret = 0; - uint32_t readlen = desc->datlen; - uint16_t oobreadlen = desc->ooblen; - uint16_t max_oobsize = desc->mode == MTD_OPM_AUTO_OOB ? - chip->freelayout->length : chip->oobsize; - - uint8_t *oob, *buf, *notalign = 0; - - /* Reject reads, which are not page aligned */ - if (NOTALIGNED(from)) - { - return -EINVAL; - } - - buf = desc->datbuf; - if (NOTALIGNED(desc->datlen) && !chip->pagebuf) - { - chip->pagebuf = rt_malloc(chip->page_size); - if (!chip->pagebuf) - return -ENOMEM; - } - - page = (int)(from / chip->page_size); - - oob = desc->oobbuf; - oob_required = oob ? 1 : 0; - - while (1) - { - bytes = min(chip->page_size, readlen); - - chip->ops->cmdfunc(chip, NAND_CMD_PAGE_RD, page, 0x00); - if (NOTALIGNED(bytes)) - { - notalign = buf; - buf = chip->pagebuf; - } - /* - * Now read the page into the buffer. Absent an error, - * the read methods return max bitflips per ecc step. - */ - if (desc->mode == MTD_OPM_RAW) - { - ret = nand_read_page_raw(chip, buf, oob_required, page); - } - else - { - ret = chip->read_page(chip, buf, oob_required, page); - } - - if (ret != 0) - { - ret = -EBADMSG; - break; - } - - if (oob) - { - int toread = min(oobreadlen, max_oobsize); - - if (toread) - { - oob = nand_transfer_oob(chip, oob, desc, toread); - oobreadlen -= toread; - } - } - - if (notalign) - { - rt_memcpy(notalign, buf, bytes); - } - - buf += bytes; - readlen -= bytes; - - if (!readlen) - break; - - page++; - } - - desc->datretlen = desc->datlen - (size_t)readlen; - if (oob) - desc->oobretlen = desc->ooblen - oobreadlen; - - return ret; -} - -/* - * write with ECC - * -*/ -static int nand_do_write_desc(rt_nand_t *chip, loff_t to, struct mtd_io_desc *desc) -{ - int page; - uint16_t writelen = desc->datlen; - uint16_t oob_required = desc->oobbuf ? 1 : 0; - uint16_t oobwritelen = desc->ooblen; - uint16_t oobmaxlen = desc->mode == MTD_OPM_AUTO_OOB ? - chip->freelayout->length : chip->oobsize; - - uint8_t *oob = desc->oobbuf; - uint8_t *buf = desc->datbuf; - int ret; - - if (!writelen) - return 0; - - /* Reject writes, which are not page aligned */ - if (NOTALIGNED(to)) - { - return -EINVAL; - } - - page = (int)(to / chip->page_size); - - /* Don't allow multipage oob writes with offset */ - if (oob && desc->ooboffs && (desc->ooboffs + desc->ooblen > oobmaxlen)) - { - ret = -EINVAL; - goto err_out; - } - - if (NOTALIGNED(desc->datlen) && !chip->pagebuf) - { - chip->pagebuf = rt_malloc(chip->page_size); - if (!chip->pagebuf) - return -ENOMEM; - } - - while (1) - { - uint16_t bytes = min(chip->page_size, writelen); - - if (oob) - { - size_t len = min(oobwritelen, oobmaxlen); - oob = nand_fill_oob(chip, oob, len, desc); - oobwritelen -= len; - } - else - { - /* We still need to erase leftover OOB data */ - rt_memset(chip->oob_poi, 0xff, chip->oobsize); - } - - if (NOTALIGNED(bytes)) - { - uint8_t *dbtmp = buf; - buf = chip->pagebuf; - rt_memset(&buf[bytes], 0xff, chip->page_size - bytes); - rt_memcpy(buf, dbtmp, bytes); - } - ret = nand_write_page(chip, buf, oob_required, page, (desc->mode == MTD_OPM_RAW)); - if (ret) - break; - - writelen -= bytes; - if (!writelen) - break; - - buf += bytes; - page++; - } - - desc->datretlen = desc->datlen - writelen; - if (oob) - desc->oobretlen = desc->ooblen; - -err_out: - - return ret; -} - -static int nand_read_oob_std(rt_nand_t *chip, int page) -{ - chip->ops->cmdfunc(chip, NAND_CMD_PAGE_RD, page, chip->page_size); - chip->ops->read_buf(chip, chip->oob_poi, chip->oobsize); - - return 0; -} - -/* - * read one page of OOB -*/ -static int nand_only_read_oob(rt_nand_t *chip, loff_t from, struct mtd_io_desc *desc) -{ - int page; - int readlen = desc->ooblen; - int len; - uint8_t *buf = desc->oobbuf; - int ret = 0; - - if (desc->mode == MTD_OPM_AUTO_OOB) - len = chip->freelayout->length; - else - len = chip->oobsize; - - if (desc->ooboffs >= len) //attempt to start read outside oob - { - return -EINVAL; - } - - page = (int)(from / chip->page_size); - - ret = nand_read_oob_std(chip, page); - if (ret == 0) - { - len = min(len, readlen); - buf = nand_transfer_oob(chip, buf, desc, len); - desc->oobretlen = len; - } - - return ret; -} - -static int nand_write_oob_std(rt_nand_t *chip, int page) -{ - int status; - - chip->ops->cmdfunc(chip, NAND_CMD_PAGE_WR0, page, chip->page_size); - chip->ops->write_buf(chip, chip->oob_poi, chip->oobsize); - /* Send command to program the OOB data */ - status = chip->ops->cmdfunc(chip, NAND_CMD_PAGE_WR1, -1, -1); - - return status & NAND_STATUS_FAIL ? -EIO : 0; -} - -static int nand_only_write_oob(rt_nand_t *chip, loff_t to, struct mtd_io_desc *desc) -{ - int page, ret, len; - - if (desc->mode == MTD_OPM_AUTO_OOB) - len = chip->freelayout->length; - else - len = chip->oobsize; - - /* Do not allow write past end of page */ - if ((desc->ooboffs + desc->ooblen) > len) - { - return -EINVAL; - } - - if (desc->ooblen == 0) - { - return -EINVAL; - } - - /* get page */ - page = (int)(to / chip->page_size); - - nand_fill_oob(chip, desc->oobbuf, desc->ooblen, desc); - - ret = nand_write_oob_std(chip, page); - if (ret == 0) - desc->oobretlen = len; - - return ret; -} - -static int nand_erase(rt_mtd_t *mtd, loff_t addr, size_t size) -{ - rt_nand_t *chip; - int status; - int page; - uint32_t blksize; - - chip = MTDTONAND(mtd); - blksize = mtd->block_size; - page = addr / chip->page_size; - - while (size >= blksize) - { - status = chip->ops->cmdfunc(chip, NAND_CMD_BLK_ERASE, page, 0); - if (status & NAND_STATUS_FAIL) - { - break; - } - size -= blksize; - page += chip->pages_pb; - } - - return size; -} - -static int nand_read(rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *desc) -{ - int ret = -ENOTSUP; - rt_nand_t *chip; - - chip = MTDTONAND(mtd); - - switch (desc->mode) - { - case MTD_OPM_PLACE_OOB: - case MTD_OPM_AUTO_OOB: - case MTD_OPM_RAW: - break; - - default: - goto out; - } - - if (!desc->datbuf || !desc->datlen) - ret = nand_only_read_oob(chip, from, desc); - else - ret = nand_do_read_desc(chip, from, desc); - -out: - - return ret; -} - -static int nand_write(rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *desc) -{ - int ret = -ENOTSUP; - rt_nand_t *chip; - - chip = MTDTONAND(mtd); - - switch (desc->mode) - { - case MTD_OPM_PLACE_OOB: - case MTD_OPM_AUTO_OOB: - case MTD_OPM_RAW: - break; - - default: - goto out; - } - - if (!desc->datbuf || !desc->datlen) - ret = nand_only_write_oob(chip, to, desc); - else - ret = nand_do_write_desc(chip, to, desc); - -out: - - return ret; -} - -static int nand_block_isbad(rt_mtd_t *mtd, uint32_t blk) -{ - int ret; - rt_nand_t *chip = MTDTONAND(mtd); - - if (chip->ops->isbad) - { - ret = chip->ops->isbad(chip, blk); - } - else - { - int page; - - page = blk * chip->pages_pb; - nand_read_oob_std(chip, page); - ret = chip->oob_poi[0] != 0xFF; - } - - return ret; -} - -static int nand_block_markbad(rt_mtd_t *mtd, uint32_t blk) -{ - int ret; - rt_nand_t *chip; - - chip = MTDTONAND(mtd); - - if (chip->ops->markbad) - { - ret = chip->ops->markbad(chip, blk); - } - else - { - int page; - - page = blk * chip->pages_pb; - rt_memset(chip->oob_poi, 0xff, chip->oobsize); - chip->oob_poi[0] = 0; - ret = nand_write_oob_std(chip, page); - } - - return ret; -} - -static const struct mtd_ops _ops = -{ - nand_erase, - nand_read, - nand_write, - nand_block_isbad, - nand_block_markbad, -}; - -int rt_mtd_nand_init(rt_nand_t *nand, int blk_size, int page_size, int oob_size) -{ - uint8_t *buf; - - buf = rt_malloc(oob_size * 3); - if (buf == RT_NULL) - return -ENOMEM; - - nand->oob_poi = buf; - buf += oob_size; - nand->buffers.ecccalc = buf; - buf += oob_size; - nand->buffers.ecccode = buf; - nand->pagebuf = 0; /* alloc when unaligen access */ - - nand->pages_pb = blk_size / page_size; - nand->ecc._step = page_size / nand->ecc.stepsize; - nand->page_size = page_size; - nand->oobsize = oob_size; - - nand->parent.type = MTD_TYPE_NAND; - nand->parent.ops = &_ops; - nand->parent.sector_size = page_size; - nand->parent.block_size = blk_size; - nand->parent.oob_size = oob_size; - - switch (nand->ecc.mode) - { - case NAND_ECCM_NONE: - { - nand->read_page = nand_read_page_raw; - nand->write_page = nand_write_page_raw; - }break; - case NAND_ECCM_HW: - { - nand->read_page = nand_read_page_hwecc; - nand->write_page = nand_write_page_hwecc; - }break; - default: - { - rt_free(buf); - return -1; - } - } - - return 0; -} diff --git a/components/drivers/mtd/mtdnor.c b/components/drivers/mtd/mtdnor.c deleted file mode 100644 index 481d26167e..0000000000 --- a/components/drivers/mtd/mtdnor.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#include <drivers/mtdnor.h> - -#ifdef MTD_USING_NOR -static int _nor_erase(rt_mtd_t *mtd, loff_t addr, size_t len) -{ - rt_nor_t *nor; - - nor = (rt_nor_t *)mtd; - return nor->ops->erase(nor, addr, len); -} - -static int _nor_read(rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *desc) -{ - rt_nor_t *nor; - int ret; - - nor = (rt_nor_t *)mtd; - ret = nor->ops->read(nor, from, desc->datbuf, desc->datlen); - if (ret > 0) - { - desc->datretlen = ret; - ret = 0; - } - - return ret; -} - -static int _nor_write(rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *desc) -{ - rt_nor_t *nor; - int ret; - - nor = (rt_nor_t *)mtd; - ret = nor->ops->write(nor, to, desc->datbuf, desc->datlen); - if (ret > 0) - { - desc->datretlen = ret; - ret = 0; - } - - return ret; -} - -static const struct mtd_ops _ops = -{ - _nor_erase, - _nor_read, - _nor_write, - 0, - 0 -}; - -int rt_mtd_nor_init(rt_nor_t *nor, int blksize) -{ - nor->parent.sector_size = 1; - nor->parent.block_size = blksize; - nor->parent.ops = &_ops; - nor->parent.type = MTD_TYPE_NOR; - nor->parent.oob_size = 0; - - return 0; -} -#endif diff --git a/components/drivers/pm/pm.c b/components/drivers/pm/pm.c index 3e9cf56c76..dd7cc2ae63 100644 --- a/components/drivers/pm/pm.c +++ b/components/drivers/pm/pm.c @@ -17,18 +17,18 @@ #ifdef RT_USING_PM static struct rt_pm _pm; -static uint8_t _pm_default_sleep = RT_PM_DEFAULT_SLEEP_MODE; +static rt_uint8_t _pm_default_sleep = RT_PM_DEFAULT_SLEEP_MODE; static struct rt_pm_notify _pm_notify; -static uint8_t _pm_init_flag = 0; +static rt_uint8_t _pm_init_flag = 0; #define RT_PM_TICKLESS_THRESH (2) -RT_WEAK uint32_t rt_pm_enter_critical(uint8_t sleep_mode) +RT_WEAK rt_uint32_t rt_pm_enter_critical(rt_uint8_t sleep_mode) { return rt_hw_interrupt_disable(); } -RT_WEAK void rt_pm_exit_critical(uint32_t ctx, uint8_t sleep_mode) +RT_WEAK void rt_pm_exit_critical(rt_uint32_t ctx, rt_uint8_t sleep_mode) { rt_hw_interrupt_enable(ctx); } @@ -36,7 +36,7 @@ RT_WEAK void rt_pm_exit_critical(uint32_t ctx, uint8_t sleep_mode) /** * This function will suspend all registered devices */ -static int _pm_device_suspend(uint8_t mode) +static int _pm_device_suspend(rt_uint8_t mode) { int index, ret = RT_EOK; @@ -56,7 +56,7 @@ static int _pm_device_suspend(uint8_t mode) /** * This function will resume all registered devices */ -static void _pm_device_resume(uint8_t mode) +static void _pm_device_resume(rt_uint8_t mode) { int index; @@ -72,7 +72,7 @@ static void _pm_device_resume(uint8_t mode) /** * This function will update the frequency of all registered devices */ -static void _pm_device_frequency_change(uint8_t mode) +static void _pm_device_frequency_change(rt_uint8_t mode) { rt_uint32_t index; @@ -106,10 +106,10 @@ static void _pm_frequency_scaling(struct rt_pm *pm) /** * This function selects the sleep mode according to the rt_pm_request/rt_pm_release count. */ -static uint8_t _pm_select_sleep_mode(struct rt_pm *pm) +static rt_uint8_t _pm_select_sleep_mode(struct rt_pm *pm) { int index; - uint8_t mode; + rt_uint8_t mode; mode = _pm_default_sleep; for (index = PM_SLEEP_MODE_NONE; index < PM_SLEEP_MODE_MAX; index ++) @@ -128,7 +128,7 @@ static uint8_t _pm_select_sleep_mode(struct rt_pm *pm) /** * This function changes the power sleep mode base on the result of selection */ -static void _pm_change_sleep_mode(struct rt_pm *pm, uint8_t mode) +static void _pm_change_sleep_mode(struct rt_pm *pm, rt_uint8_t mode) { rt_tick_t timeout_tick, delta_tick; rt_base_t level; @@ -214,7 +214,7 @@ static void _pm_change_sleep_mode(struct rt_pm *pm, uint8_t mode) */ void rt_system_power_manager(void) { - uint8_t mode; + rt_uint8_t mode; if (_pm_init_flag == 0) return; @@ -233,7 +233,7 @@ void rt_system_power_manager(void) * * @param parameter the parameter of run mode or sleep mode */ -void rt_pm_request(uint8_t mode) +void rt_pm_request(rt_uint8_t mode) { rt_base_t level; struct rt_pm *pm; @@ -258,7 +258,7 @@ void rt_pm_request(uint8_t mode) * @param parameter the parameter of run mode or sleep mode * */ -void rt_pm_release(uint8_t mode) +void rt_pm_release(rt_uint8_t mode) { rt_ubase_t level; struct rt_pm *pm; @@ -342,7 +342,7 @@ void rt_pm_device_unregister(struct rt_device *device) /** * This function set notification callback for application */ -void rt_pm_notify_set(void (*notify)(uint8_t event, uint8_t mode, void *data), void *data) +void rt_pm_notify_set(void (*notify)(rt_uint8_t event, rt_uint8_t mode, void *data), void *data) { _pm_notify.notify = notify; _pm_notify.data = data; @@ -351,7 +351,7 @@ void rt_pm_notify_set(void (*notify)(uint8_t event, uint8_t mode, void *data), v /** * This function set default sleep mode when no pm_request */ -void rt_pm_default_set(uint8_t sleep_mode) +void rt_pm_default_set(rt_uint8_t sleep_mode) { _pm_default_sleep = sleep_mode; } @@ -428,7 +428,7 @@ static rt_err_t _rt_pm_device_control(rt_device_t dev, return RT_EOK; } -int rt_pm_run_enter(uint8_t mode) +int rt_pm_run_enter(rt_uint8_t mode) { rt_base_t level; struct rt_pm *pm; @@ -458,6 +458,18 @@ int rt_pm_run_enter(uint8_t mode) return RT_EOK; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops pm_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + _rt_pm_device_read, + _rt_pm_device_write, + _rt_pm_device_control, +}; +#endif + /** * This function will initialize power management. * @@ -479,12 +491,16 @@ void rt_system_pm_init(const struct rt_pm_ops *ops, device->rx_indicate = RT_NULL; device->tx_complete = RT_NULL; +#ifdef RT_USING_DEVICE_OPS + device->ops = &pm_ops; +#else device->init = RT_NULL; device->open = RT_NULL; device->close = RT_NULL; device->read = _rt_pm_device_read; device->write = _rt_pm_device_write; device->control = _rt_pm_device_control; +#endif device->user_data = user_data; /* register PM device to the system */ diff --git a/components/drivers/sdio/block_dev.c b/components/drivers/sdio/block_dev.c index cac4fc5036..5db0f38c08 100644 --- a/components/drivers/sdio/block_dev.c +++ b/components/drivers/sdio/block_dev.c @@ -472,7 +472,7 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card) } #ifdef RT_USING_DFS_MNTTABLE - if (0) // if (blk_dev) + if (blk_dev) { LOG_I("try to mount file system!"); /* try to mount file system on this block device */ @@ -507,9 +507,10 @@ void rt_mmcsd_blk_remove(struct rt_mmcsd_card *card) const char * mounted_path = dfs_filesystem_get_mounted_path(&(blk_dev->dev)); if (mounted_path) { - dfs_unmount(mounted_path); + dfs_unmount(mounted_path); + LOG_D("unmount file system %s for device %s.\r\n", mounted_path, blk_dev->dev.parent.name); } - + rt_sem_delete(blk_dev->part.lock); rt_device_unregister(&blk_dev->dev); rt_list_remove(&blk_dev->list); rt_free(blk_dev); diff --git a/components/drivers/sdio/mmc.c b/components/drivers/sdio/mmc.c index 5c7ddcb258..7b1f7ee193 100644 --- a/components/drivers/sdio/mmc.c +++ b/components/drivers/sdio/mmc.c @@ -4,8 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 * * Change Logs: - * Date Author Notes - * 2015-06-15 hichard first version + * Date Author Notes + * 2015-06-15 hichard first version */ #include <drivers/mmcsd_core.h> @@ -182,6 +182,8 @@ static int mmc_get_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t **new_ext_csd) */ static int mmc_parse_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd) { + rt_uint64_t card_capacity = 0; + if(card == RT_NULL || ext_csd == RT_NULL) { LOG_E("emmc parse ext csd fail, invaild args"); @@ -191,9 +193,10 @@ static int mmc_parse_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd) card->flags |= CARD_FLAG_HIGHSPEED; card->hs_max_data_rate = 200000000; - card->card_capacity = *((rt_uint32_t *)&ext_csd[EXT_CSD_SEC_CNT]); - card->card_capacity *= card->card_blksize; - card->card_capacity >>= 10; /* unit:KB */ + card_capacity = *((rt_uint32_t *)&ext_csd[EXT_CSD_SEC_CNT]); + card_capacity *= card->card_blksize; + card_capacity >>= 10; /* unit:KB */ + card->card_capacity = card_capacity; LOG_I("emmc card capacity %d KB.", card->card_capacity); return 0; diff --git a/components/drivers/sdio/sdio.c b/components/drivers/sdio/sdio.c index f31f5b81a8..65bf87b895 100644 --- a/components/drivers/sdio/sdio.c +++ b/components/drivers/sdio/sdio.c @@ -709,6 +709,16 @@ static rt_int32_t sdio_initialize_function(struct rt_mmcsd_card *card, if (ret) goto err1; + /* + * product/manufacturer id is optional for function CIS, so + * copy it from the card structure as needed. + */ + if (func->product == 0) + { + func->manufacturer = card->cis.manufacturer; + func->product = card->cis.product; + } + card->sdio_function[func_num] = func; return 0; diff --git a/components/drivers/sensors/sensor.c b/components/drivers/sensors/sensor.c index e76ac51f12..91b256bd66 100644 --- a/components/drivers/sensors/sensor.c +++ b/components/drivers/sensors/sensor.c @@ -30,7 +30,7 @@ static char *const sensor_name_str[] = "hr_", /* Heart Rate */ "tvoc_", /* TVOC Level */ "noi_", /* Noise Loudness */ - "step_" /* Step sensor */ + "step_", /* Step sensor */ "forc_" /* Force sensor */ }; @@ -44,7 +44,7 @@ void rt_sensor_cb(rt_sensor_t sen) { return; } - + if (sen->irq_handle != RT_NULL) { sen->irq_handle(sen); @@ -69,7 +69,7 @@ void rt_sensor_cb(rt_sensor_t sen) /* ISR for sensor interrupt */ static void irq_callback(void *args) { - rt_sensor_t sensor = args; + rt_sensor_t sensor = (rt_sensor_t)args; rt_uint8_t i; if (sensor->module) @@ -116,30 +116,18 @@ static rt_err_t rt_sensor_irq_init(rt_sensor_t sensor) return 0; } -/* Sensor interrupt enable */ -static void rt_sensor_irq_enable(rt_sensor_t sensor) -{ - if (sensor->config.irq_pin.pin != RT_PIN_NONE) - { - rt_pin_irq_enable(sensor->config.irq_pin.pin, RT_TRUE); - } -} - -/* Sensor interrupt disable */ -static void rt_sensor_irq_disable(rt_sensor_t sensor) -{ - if (sensor->config.irq_pin.pin != RT_PIN_NONE) - { - rt_pin_irq_enable(sensor->config.irq_pin.pin, RT_FALSE); - } -} - /* RT-Thread Device Interface */ - -static rt_err_t rt_sensor_init(rt_device_t dev) +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; + + if (sensor->module) + { + /* take the module mutex */ + rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER); + } if (sensor->module != RT_NULL && sensor->info.fifo_max > 0 && sensor->data_buf == RT_NULL) { @@ -147,55 +135,46 @@ static rt_err_t rt_sensor_init(rt_device_t dev) sensor->data_buf = rt_malloc(sizeof(struct rt_sensor_data) * sensor->info.fifo_max); if (sensor->data_buf == RT_NULL) { - return -RT_ENOMEM; + res = -RT_ENOMEM; + goto __exit; } } - return RT_EOK; -} - -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); - - if (sensor->module) - { - /* take the module mutex */ - rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER); - } - if (oflag & RT_DEVICE_FLAG_RDONLY && dev->flag & RT_DEVICE_FLAG_RDONLY) { - /* If polling mode is supported, configure it to polling mode */ - if (sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_POLLING) == RT_EOK) + if (sensor->ops->control != RT_NULL) { - sensor->config.mode = RT_SENSOR_MODE_POLLING; + /* 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; } else if (oflag & RT_DEVICE_FLAG_INT_RX && dev->flag & RT_DEVICE_FLAG_INT_RX) { - /* If interrupt mode is supported, configure it to interrupt mode */ - if (sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_INT) == RT_EOK) + if (sensor->ops->control != RT_NULL) { - sensor->config.mode = RT_SENSOR_MODE_INT; - /* Initialization sensor interrupt */ - rt_sensor_irq_init(sensor); + /* 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; } else if (oflag & RT_DEVICE_FLAG_FIFO_RX && dev->flag & RT_DEVICE_FLAG_FIFO_RX) { - /* If fifo mode is supported, configure it to fifo mode */ - if (sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_FIFO) == RT_EOK) + if (sensor->ops->control != RT_NULL) { - sensor->config.mode = RT_SENSOR_MODE_FIFO; - /* Initialization sensor interrupt */ - rt_sensor_irq_init(sensor); + /* 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; } else { - return -RT_EINVAL; + res = -RT_EINVAL; + goto __exit; } /* Configure power mode to normal mode */ @@ -204,18 +183,21 @@ static rt_err_t rt_sensor_open(rt_device_t dev, rt_uint16_t oflag) sensor->config.power = RT_SENSOR_POWER_NORMAL; } +__exit: if (sensor->module) { /* release the module mutex */ rt_mutex_release(sensor->module->lock); } - return RT_EOK; + return res; } -static rt_err_t rt_sensor_close(rt_device_t dev) +static rt_err_t rt_sensor_close(rt_device_t dev) { rt_sensor_t sensor = (rt_sensor_t)dev; + int i; + RT_ASSERT(dev != RT_NULL); if (sensor->module) @@ -230,8 +212,31 @@ static rt_err_t rt_sensor_close(rt_device_t dev) } /* Sensor disable interrupt */ - rt_sensor_irq_disable(sensor); + if (sensor->config.irq_pin.pin != RT_PIN_NONE) + { + rt_pin_irq_enable(sensor->config.irq_pin.pin, RT_FALSE); + } + + if (sensor->module != RT_NULL && sensor->info.fifo_max > 0 && sensor->data_buf != RT_NULL) + { + for (i = 0; i < sensor->module->sen_num; i ++) + { + if (sensor->module->sen[i]->parent.ref_count > 0) + goto __exit; + } + /* Free memory for the sensor buffer */ + for (i = 0; i < sensor->module->sen_num; i ++) + { + if (sensor->module->sen[i]->data_buf != RT_NULL) + { + rt_free(sensor->module->sen[i]->data_buf); + sensor->module->sen[i]->data_buf = RT_NULL; + } + } + } + +__exit: if (sensor->module) { rt_mutex_release(sensor->module->lock); @@ -320,7 +325,7 @@ static rt_err_t rt_sensor_control(rt_device_t dev, int cmd, void *args) } break; case RT_SENSOR_CTRL_SET_ODR: - + /* Configuration data output rate */ result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_ODR, args); if (result == RT_EOK) @@ -329,27 +334,8 @@ static rt_err_t rt_sensor_control(rt_device_t dev, int cmd, void *args) LOG_D("set odr %d", sensor->config.odr); } break; - case RT_SENSOR_CTRL_SET_MODE: - - /* Configuration sensor work mode */ - result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, args); - if (result == RT_EOK) - { - sensor->config.mode = (rt_uint32_t)args & 0xFF; - LOG_D("set work mode code:", sensor->config.mode); - - if (sensor->config.mode == RT_SENSOR_MODE_POLLING) - { - rt_sensor_irq_disable(sensor); - } - else if (sensor->config.mode == RT_SENSOR_MODE_INT || sensor->config.mode == RT_SENSOR_MODE_FIFO) - { - rt_sensor_irq_enable(sensor); - } - } - break; case RT_SENSOR_CTRL_SET_POWER: - + /* Configuration sensor power mode */ result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_POWER, args); if (result == RT_EOK) @@ -359,7 +345,7 @@ 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); break; @@ -378,7 +364,7 @@ static rt_err_t rt_sensor_control(rt_device_t dev, int cmd, void *args) #ifdef RT_USING_DEVICE_OPS const static struct rt_device_ops rt_sensor_ops = { - rt_sensor_init, + RT_NULL, rt_sensor_open, rt_sensor_close, rt_sensor_read, @@ -403,7 +389,7 @@ int rt_hw_sensor_register(rt_sensor_t sensor, /* Add a type name for the sensor device */ sensor_name = sensor_name_str[sensor->info.type]; - device_name = rt_calloc(1, rt_strlen(sensor_name) + 1 + rt_strlen(name)); + device_name = (char *)rt_calloc(1, rt_strlen(sensor_name) + 1 + rt_strlen(name)); if (device_name == RT_NULL) { LOG_E("device_name calloc failed!"); @@ -429,7 +415,7 @@ int rt_hw_sensor_register(rt_sensor_t sensor, #ifdef RT_USING_DEVICE_OPS device->ops = &rt_sensor_ops; #else - device->init = rt_sensor_init; + device->init = RT_NULL; device->open = rt_sensor_open; device->close = rt_sensor_close; device->read = rt_sensor_read; @@ -444,10 +430,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) { + 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"); return RT_EOK; } diff --git a/components/drivers/sensors/sensor.h b/components/drivers/sensors/sensor.h index a9b6684457..9c6e5ecc55 100644 --- a/components/drivers/sensors/sensor.h +++ b/components/drivers/sensors/sensor.h @@ -55,6 +55,7 @@ extern "C" { #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 */ /* Sensor unit types */ diff --git a/components/drivers/sensors/sensor_cmd.c b/components/drivers/sensors/sensor_cmd.c index 6babf12db3..dd1aa1ef95 100644 --- a/components/drivers/sensors/sensor_cmd.c +++ b/components/drivers/sensors/sensor_cmd.c @@ -4,8 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 * * Change Logs: - * Date Author Notes - * 2019-01-31 flybreak first version + * Date Author Notes + * 2019-01-31 flybreak first version + * 2019-07-16 WillianChan Increase the output of sensor information */ #include "sensor.h" @@ -55,7 +56,7 @@ static void sensor_show_data(rt_size_t num, rt_sensor_t sensor, struct rt_sensor } } -rt_err_t rx_callback(rt_device_t dev, rt_size_t size) +static rt_err_t rx_callback(rt_device_t dev, rt_size_t size) { rt_sem_release(sensor_rx_sem); return 0; @@ -63,15 +64,15 @@ rt_err_t rx_callback(rt_device_t dev, rt_size_t size) static void sensor_fifo_rx_entry(void *parameter) { - rt_device_t dev = parameter; - rt_sensor_t sensor = parameter; + rt_device_t dev = (rt_device_t)parameter; + rt_sensor_t sensor = (rt_sensor_t)parameter; struct rt_sensor_data *data = RT_NULL; struct rt_sensor_info info; rt_size_t res, i; rt_device_control(dev, RT_SENSOR_CTRL_GET_INFO, &info); - data = rt_malloc(sizeof(struct rt_sensor_data) * info.fifo_max); + data = (struct rt_sensor_data *)rt_malloc(sizeof(struct rt_sensor_data) * info.fifo_max); if (data == RT_NULL) { LOG_E("Memory allocation failed!"); @@ -137,8 +138,8 @@ MSH_CMD_EXPORT(sensor_fifo, Sensor fifo mode test function); static void sensor_irq_rx_entry(void *parameter) { - rt_device_t dev = parameter; - rt_sensor_t sensor = parameter; + rt_device_t dev = (rt_device_t)parameter; + rt_sensor_t sensor = (rt_sensor_t)parameter; struct rt_sensor_data data; rt_size_t res, i = 0; @@ -268,13 +269,88 @@ static void sensor(int argc, char **argv) else if (!strcmp(argv[1], "info")) { struct rt_sensor_info info; + if (dev == RT_NULL) + { + LOG_W("Please probe sensor device first!"); + return ; + } rt_device_control(dev, RT_SENSOR_CTRL_GET_INFO, &info); - rt_kprintf("vendor :%d\n", info.vendor); - rt_kprintf("model :%s\n", info.model); - rt_kprintf("unit :%d\n", info.unit); + switch (info.vendor) + { + case RT_SENSOR_VENDOR_UNKNOWN: + rt_kprintf("vendor :unknown vendor\n"); + break; + case RT_SENSOR_VENDOR_STM: + rt_kprintf("vendor :STMicroelectronics\n"); + break; + case RT_SENSOR_VENDOR_BOSCH: + rt_kprintf("vendor :Bosch\n"); + break; + case RT_SENSOR_VENDOR_INVENSENSE: + rt_kprintf("vendor :Invensense\n"); + break; + case RT_SENSOR_VENDOR_SEMTECH: + rt_kprintf("vendor :Semtech\n"); + break; + case RT_SENSOR_VENDOR_GOERTEK: + rt_kprintf("vendor :Goertek\n"); + break; + case RT_SENSOR_VENDOR_MIRAMEMS: + rt_kprintf("vendor :MiraMEMS\n"); + break; + case RT_SENSOR_VENDOR_DALLAS: + rt_kprintf("vendor :Dallas\n"); + break; + } + rt_kprintf("model :%s\n", info.model); + switch (info.unit) + { + case RT_SENSOR_UNIT_NONE: + rt_kprintf("unit :none\n"); + break; + case RT_SENSOR_UNIT_MG: + rt_kprintf("unit :mG\n"); + break; + case RT_SENSOR_UNIT_MDPS: + rt_kprintf("unit :mdps\n"); + break; + case RT_SENSOR_UNIT_MGAUSS: + rt_kprintf("unit :mGauss\n"); + break; + case RT_SENSOR_UNIT_LUX: + rt_kprintf("unit :lux\n"); + break; + case RT_SENSOR_UNIT_CM: + rt_kprintf("unit :cm\n"); + break; + case RT_SENSOR_UNIT_PA: + rt_kprintf("unit :pa\n"); + break; + case RT_SENSOR_UNIT_PERMILLAGE: + rt_kprintf("unit :permillage\n"); + break; + case RT_SENSOR_UNIT_DCELSIUS: + rt_kprintf("unit :Celsius\n"); + break; + case RT_SENSOR_UNIT_HZ: + rt_kprintf("unit :HZ\n"); + break; + case RT_SENSOR_UNIT_ONE: + rt_kprintf("unit :1\n"); + break; + case RT_SENSOR_UNIT_BPM: + rt_kprintf("unit :bpm\n"); + break; + case RT_SENSOR_UNIT_MM: + rt_kprintf("unit :mm\n"); + break; + case RT_SENSOR_UNIT_MN: + rt_kprintf("unit :mN\n"); + break; + } rt_kprintf("range_max :%d\n", info.range_max); rt_kprintf("range_min :%d\n", info.range_min); - rt_kprintf("period_min:%d\n", info.period_min); + rt_kprintf("period_min:%dms\n", info.period_min); rt_kprintf("fifo_max :%d\n", info.fifo_max); } else if (!strcmp(argv[1], "read")) diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index c3e96fc77b..50dd7e188b 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -327,6 +327,18 @@ rt_inline int _serial_int_tx(struct rt_serial_device *serial, const rt_uint8_t * return size - length; } +static void _serial_check_buffer_size(void) +{ + static rt_bool_t already_output = RT_FALSE; + + if (already_output == RT_FALSE) + { + LOG_W("Warning: There is no enough buffer for saving data," + " please increase the RT_SERIAL_RB_BUFSZ option."); + already_output = RT_TRUE; + } +} + #if defined(RT_USING_POSIX) || defined(RT_SERIAL_USING_DMA) static rt_size_t _serial_fifo_calc_recved_len(struct rt_serial_device *serial) { @@ -428,12 +440,11 @@ static void rt_dma_recv_update_put_index(struct rt_serial_device *serial, rt_siz } } - if(rx_fifo->is_full == RT_TRUE) + if(rx_fifo->is_full == RT_TRUE) { - rx_fifo->get_index = rx_fifo->put_index; - } - - if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0; + _serial_check_buffer_size(); + rx_fifo->get_index = rx_fifo->put_index; + } } /* @@ -791,16 +802,16 @@ static rt_size_t rt_serial_read(struct rt_device *dev, if (dev->open_flag & RT_DEVICE_FLAG_INT_RX) { - return _serial_int_rx(serial, buffer, size); + return _serial_int_rx(serial, (rt_uint8_t *)buffer, size); } #ifdef RT_SERIAL_USING_DMA else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX) { - return _serial_dma_rx(serial, buffer, size); + return _serial_dma_rx(serial, (rt_uint8_t *)buffer, size); } #endif /* RT_SERIAL_USING_DMA */ - return _serial_poll_rx(serial, buffer, size); + return _serial_poll_rx(serial, (rt_uint8_t *)buffer, size); } static rt_size_t rt_serial_write(struct rt_device *dev, @@ -817,17 +828,17 @@ static rt_size_t rt_serial_write(struct rt_device *dev, if (dev->open_flag & RT_DEVICE_FLAG_INT_TX) { - return _serial_int_tx(serial, buffer, size); + return _serial_int_tx(serial, (const rt_uint8_t *)buffer, size); } #ifdef RT_SERIAL_USING_DMA else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX) { - return _serial_dma_tx(serial, buffer, size); + return _serial_dma_tx(serial, (const rt_uint8_t *)buffer, size); } #endif /* RT_SERIAL_USING_DMA */ else { - return _serial_poll_tx(serial, buffer, size); + return _serial_poll_tx(serial, (const rt_uint8_t *)buffer, size); } } @@ -1172,6 +1183,8 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event) rx_fifo->get_index += 1; rx_fifo->is_full = RT_TRUE; if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0; + + _serial_check_buffer_size(); } /* enable interrupt */ diff --git a/components/drivers/spi/SConscript b/components/drivers/spi/SConscript index b88671ebc9..e19f30861f 100644 --- a/components/drivers/spi/SConscript +++ b/components/drivers/spi/SConscript @@ -14,24 +14,9 @@ src_device = [] if GetDepend('RT_USING_SPI_WIFI'): src_device += ['spi_wifi_rw009.c'] -if GetDepend('RT_USING_W25QXX'): - src_device += ['spi_flash_w25qxx.c'] - -if GetDepend('RT_USING_W25QXX_MTD'): - src_device += ['spi_flash_w25qxx_mtd.c'] - if GetDepend('RT_USING_ENC28J60'): src_device += ['enc28j60.c'] -if GetDepend('RT_USING_AT45DBXX'): - src_device += ['spi_flash_at45dbxx.c'] - -if GetDepend('RT_USING_SST25VFXX'): - src_device += ['spi_flash_sst25vfxx.c'] - -if GetDepend('RT_USING_GD'): - src_device += ['spi_flash_gd.c'] - if GetDepend('RT_USING_SPI_MSD'): src_device += ['spi_msd.c'] diff --git a/components/drivers/spi/device_driver_list.txt b/components/drivers/spi/device_driver_list.txt index 2c9d6a16b8..939baa7531 100644 --- a/components/drivers/spi/device_driver_list.txt +++ b/components/drivers/spi/device_driver_list.txt @@ -5,11 +5,5 @@ http://www.rt-thread.com/ enc28j60.c/enc28j60.h http://www.microchip.com/ -spi_flash_at45dbxx.c/spi_flash_at45dbxx.h -http://www.atmel.com/ - -spi_flash_sst25vfxx.c/spi_flash_sst25vfxx.h -http://www.microchip.com/ - -spi_flash_w25qxx.c/spi_flash_w25qxx.h -http://www.winbond.com/ +spi_flash_sfud: Serial Flash Universal Driver +https://github.com/armink/SFUD
\ No newline at end of file diff --git a/components/drivers/spi/sfud/inc/sfud_cfg.h b/components/drivers/spi/sfud/inc/sfud_cfg.h index 051de6d577..3b7860062d 100644 --- a/components/drivers/spi/sfud/inc/sfud_cfg.h +++ b/components/drivers/spi/sfud/inc/sfud_cfg.h @@ -59,6 +59,6 @@ #define SFUD_USING_FLASH_INFO_TABLE #endif -#define SFUD_FLASH_DEVICE_TABLE {0} +#define SFUD_FLASH_DEVICE_TABLE {{0}} #endif /* _SFUD_CFG_H_ */ diff --git a/components/drivers/spi/sfud/inc/sfud_flash_def.h b/components/drivers/spi/sfud/inc/sfud_flash_def.h index 8922375557..13a0e702a8 100644 --- a/components/drivers/spi/sfud/inc/sfud_flash_def.h +++ b/components/drivers/spi/sfud/inc/sfud_flash_def.h @@ -124,6 +124,7 @@ typedef struct { {"AT45DB161E", SFUD_MF_ID_ATMEL, 0x26, 0x00, 2L*1024L*1024L, SFUD_WM_BYTE|SFUD_WM_DUAL_BUFFER, 512, 0x81}, \ {"W25Q40BV", SFUD_MF_ID_WINBOND, 0x40, 0x13, 512L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}, \ {"W25Q16BV", SFUD_MF_ID_WINBOND, 0x40, 0x15, 2L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}, \ + {"W25Q64DW", SFUD_MF_ID_WINBOND, 0x60, 0x17, 8L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}, \ {"W25Q128BV", SFUD_MF_ID_WINBOND, 0x40, 0x18, 16L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}, \ {"W25Q256FV", SFUD_MF_ID_WINBOND, 0x40, 0x19, 32L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}, \ {"SST25VF016B", SFUD_MF_ID_SST, 0x25, 0x41, 2L*1024L*1024L, SFUD_WM_BYTE|SFUD_WM_AAI, 4096, 0x20}, \ diff --git a/components/drivers/spi/spi_flash_at45dbxx.c b/components/drivers/spi/spi_flash_at45dbxx.c deleted file mode 100644 index 0a30f0a328..0000000000 --- a/components/drivers/spi/spi_flash_at45dbxx.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - */ - -#include <stdint.h> -#include "spi_flash_at45dbxx.h" - -#define FLASH_DEBUG -#define DMA_BUFFER_SIZE 512 - -#ifdef FLASH_DEBUG -#define FLASH_TRACE rt_kprintf -#else -#define FLASH_TRACE(...) -#endif /**< #ifdef FLASH_DEBUG */ - -/* JEDEC Manufacturer’s ID */ -#define MF_ID (0x1F) /* atmel */ -#define DENSITY_CODE_011D (0x02) /* AT45DB011D Density Code : 00010 = 1-Mbit */ -#define DENSITY_CODE_021D (0x03) /* AT45DB021D Density Code : 00011 = 2-Mbit */ -#define DENSITY_CODE_041D (0x04) /* AT45DB041D Density Code : 00100 = 4-Mbit */ -#define DENSITY_CODE_081D (0x05) /* AT45DB081D Density Code : 00101 = 8-Mbit */ -#define DENSITY_CODE_161D (0x06) /* AT45DB161D Density Code : 00110 = 16-Mbit */ -#define DENSITY_CODE_321D (0x07) /* AT45DB321D Density Code : 00111 = 32-Mbit */ -#define DENSITY_CODE_642D (0x08) /* AT45DB642D Density Code : 01000 = 64-Mbit */ - -struct JEDEC_ID -{ - uint8_t manufacturer_id; /* Manufacturer ID */ - uint8_t density_code:5; /* Density Code */ - uint8_t family_code:3; /* Family Code */ - uint8_t version_code:5; /* Product Version Code */ - uint8_t mlc_code:3; /* MLC Code */ - uint8_t byte_count; /* Byte Count */ -}; - -#define AT45DB_BUFFER_1_WRITE 0x84 -#define AT45DB_BUFFER_2_WRITE 0x87 -#define AT45DB_BUFFER_1_READ 0xD4 -#define AT45DB_BUFFER_2_READ 0xD6 -#define AT45DB_B1_TO_MM_PAGE_PROG_WITH_ERASE 0x83 -#define AT45DB_B2_TO_MM_PAGE_PROG_WITH_ERASE 0x86 -#define AT45DB_MM_PAGE_TO_B1_XFER 0x53 -#define AT45DB_MM_PAGE_TO_B2_XFER 0x55 -#define AT45DB_PAGE_ERASE 0x81 -#define AT45DB_SECTOR_ERASE 0x7C -#define AT45DB_READ_STATE_REGISTER 0xD7 -#define AT45DB_MM_PAGE_READ 0xD2 -#define AT45DB_MM_PAGE_PROG_THRU_BUFFER1 0x82 -#define AT45DB_CMD_JEDEC_ID 0x9F - -static struct spi_flash_at45dbxx spi_flash_at45dbxx; - -/*****************************************************************************/ -/*Status Register Format: */ -/* ------------------------------------------------------------------------- */ -/* | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 | */ -/* |--------|--------|--------|--------|--------|--------|--------|--------| */ -/* |RDY/BUSY| COMP | device density | X | X | */ -/* ------------------------------------------------------------------------- */ -/* 0:busy | | AT45DB041:0111 | protect|page size */ -/* 1:ready | | AT45DB161:1011 | */ -/* --------------------------------------------------------------------------*/ -/*****************************************************************************/ -static uint8_t AT45DB_StatusRegisterRead(void) -{ - return rt_spi_sendrecv8(spi_flash_at45dbxx.rt_spi_device, AT45DB_READ_STATE_REGISTER); -} - -static void wait_busy(void) -{ - uint16_t i = 0; - while (i++ < 10000) - { - if (AT45DB_StatusRegisterRead() & 0x80) - { - return; - } - } - FLASH_TRACE("\r\nSPI_FLASH timeout!!!\r\n"); -} - -/* RT-Thread Device Driver Interface */ -static rt_err_t AT45DB_flash_init(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t AT45DB_flash_open(rt_device_t dev, rt_uint16_t oflag) -{ - - return RT_EOK; -} - -static rt_err_t AT45DB_flash_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t AT45DB_flash_control(rt_device_t dev, int cmd, void *args) -{ - RT_ASSERT(dev != RT_NULL); - - if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) - { - struct rt_device_blk_geometry *geometry; - - geometry = (struct rt_device_blk_geometry *)args; - if (geometry == RT_NULL) return -RT_ERROR; - - geometry->bytes_per_sector = 512; - geometry->sector_count = 4096; - geometry->block_size = 4096; /* block erase: 4k */ - } - - return RT_EOK; -} - -static rt_size_t AT45DB_flash_read_page_256(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) -{ - uint32_t index, nr; - uint8_t * read_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[8]; - uint32_t i; - - for(i=0; i<sizeof(send_buffer); i++) - { - send_buffer[i] = 0; - } - - send_buffer[0] = AT45DB_MM_PAGE_READ; - send_buffer[1] = (uint8_t)(page >> 7); - send_buffer[2] = (uint8_t)(page << 1); - - rt_spi_send_then_recv(spi_flash_at45dbxx.rt_spi_device, send_buffer, 8, read_buffer, 256); - read_buffer += 256; - page++; - } - - return size; -} - -static rt_size_t AT45DB_flash_read_page_512(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) -{ - uint32_t index, nr; - uint8_t * read_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[8]; - uint32_t i; - - for(i=0; i<sizeof(send_buffer); i++) - { - send_buffer[i] = 0; - } - - send_buffer[0] = AT45DB_MM_PAGE_READ; - send_buffer[1] = (uint8_t)(page >> 6); - send_buffer[2] = (uint8_t)(page << 2); - - rt_spi_send_then_recv(spi_flash_at45dbxx.rt_spi_device, send_buffer, 8, read_buffer, 512); - read_buffer += 512; - page++; - } - - return size; -} - -static rt_size_t AT45DB_flash_read_page_1024(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) -{ - uint32_t index, nr; - uint8_t * read_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[8]; - uint32_t i; - - for(i=0; i<sizeof(send_buffer); i++) - { - send_buffer[i] = 0; - } - - send_buffer[0] = AT45DB_MM_PAGE_READ; - send_buffer[1] = (uint8_t)(page >> 5); - send_buffer[2] = (uint8_t)(page << 3); - - rt_spi_send_then_recv(spi_flash_at45dbxx.rt_spi_device, send_buffer, 8, read_buffer, 1024); - read_buffer += 1024; - page++; - } - - return size; -} - -static rt_size_t AT45DB_flash_write_page_256(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) -{ - rt_uint32_t index, nr; - const uint8_t * write_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[4]; - - send_buffer[0] = AT45DB_MM_PAGE_PROG_THRU_BUFFER1; - send_buffer[1] = (uint8_t) (page >> 7); - send_buffer[2] = (uint8_t) (page << 1); - send_buffer[3] = 0; - - rt_spi_send_then_send(spi_flash_at45dbxx.rt_spi_device, send_buffer, 4, write_buffer, 256); - - write_buffer += 256; - page++; - - wait_busy(); - } - - return size; -} - -static rt_size_t AT45DB_flash_write_page_512(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) -{ - rt_uint32_t index, nr; - const uint8_t * write_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[4]; - - send_buffer[0] = AT45DB_MM_PAGE_PROG_THRU_BUFFER1; - send_buffer[1] = (uint8_t) (page >> 6); - send_buffer[2] = (uint8_t) (page << 2); - send_buffer[3] = 0; - - rt_spi_send_then_send(spi_flash_at45dbxx.rt_spi_device, send_buffer, 4, write_buffer, 512); - - write_buffer += 512; - page++; - - wait_busy(); - } - - return size; -} - -static rt_size_t AT45DB_flash_write_page_1024(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) -{ - rt_uint32_t index, nr; - const uint8_t * write_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[4]; - - send_buffer[0] = AT45DB_MM_PAGE_PROG_THRU_BUFFER1; - send_buffer[1] = (uint8_t) (page >> 5); - send_buffer[2] = (uint8_t) (page << 3); - send_buffer[3] = 0; - - rt_spi_send_then_send(spi_flash_at45dbxx.rt_spi_device, send_buffer, 4, write_buffer, 1024); - - write_buffer += 1024; - page++; - - wait_busy(); - } - - return size; -} - -rt_err_t at45dbxx_init(const char * flash_device_name, const char * spi_device_name) -{ - struct rt_spi_device * rt_spi_device; - struct JEDEC_ID * JEDEC_ID; - - rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); - if(rt_spi_device == RT_NULL) - { - FLASH_TRACE("spi device %s not found!\r\n", spi_device_name); - return -RT_ENOSYS; - } - spi_flash_at45dbxx.rt_spi_device = rt_spi_device; - - /* config spi */ - { - struct rt_spi_configuration cfg; - cfg.data_width = 8; - cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible Modes 0 and 3 */ - cfg.max_hz = 66000000; /* Atmel RapidS Serial Interface: 66MHz Maximum Clock Frequency */ - rt_spi_configure(spi_flash_at45dbxx.rt_spi_device, &cfg); - } - - /* read JEDEC ID */ - { - uint8_t cmd; - uint8_t id_recv[6]; - JEDEC_ID = (struct JEDEC_ID *)id_recv; - - cmd = AT45DB_CMD_JEDEC_ID; - rt_spi_send_then_recv(spi_flash_at45dbxx.rt_spi_device, &cmd, 1, id_recv, 6); - - /**< 1FH = Atmel */ - /**< 001 = Atmel DataFlash */ - if(JEDEC_ID->manufacturer_id != 0x1F || JEDEC_ID->family_code != 0x01) - { - FLASH_TRACE("Manufacturer’s ID or Memory Type error!\r\n"); - FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]); - return -RT_ENOSYS; - } - - if(JEDEC_ID->density_code == DENSITY_CODE_011D) - { - /**< AT45DB011D Density Code : 00010 = 1-Mbit */ - FLASH_TRACE("AT45DB011D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 256; /* Page Erase (256 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 512; /* 1-Mbit / 8 / 256 = 512 */ - spi_flash_at45dbxx.geometry.block_size = 1024*2; /* Block Erase (2-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_021D) - { - /**< AT45DB021D Density Code : 00011 = 2-Mbit */ - FLASH_TRACE("AT45DB021D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 256; /* Page Erase (256 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 512*2; /* 2-Mbit / 8 / 256 = 1024 */ - spi_flash_at45dbxx.geometry.block_size = 1024*2; /* Block Erase (2-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_041D) - { - /**< AT45DB041D Density Code : 00100 = 4-Mbit */ - FLASH_TRACE("AT45DB041D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 256; /* Page Erase (256 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 512*4; /* 4-Mbit / 8 / 256 = 2048 */ - spi_flash_at45dbxx.geometry.block_size = 1024*2; /* Block Erase (2-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_081D) - { - /**< AT45DB081D Density Code : 00101 = 8-Mbit */ - FLASH_TRACE("AT45DB081D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 256; /* Page Erase (256 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 512*8; /* 8-Mbit / 8 / 256 = 4096 */ - spi_flash_at45dbxx.geometry.block_size = 1024*2; /* Block Erase (2-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_161D) - { - /**< AT45DB161D Density Code : 00110 = 16-Mbit */ - FLASH_TRACE("AT45DB161D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 512; /* Page Erase (512 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 256*16; /* 16-Mbit / 8 / 512 = 4096 */ - spi_flash_at45dbxx.geometry.block_size = 1024*4; /* Block Erase (4-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_321D) - { - /**< AT45DB321D Density Code : 00111 = 32-Mbit */ - FLASH_TRACE("AT45DB321D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 512; /* Page Erase (512 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 256*32; /* 32-Mbit / 8 / 512 = 8192 */ - spi_flash_at45dbxx.geometry.block_size = 1024*4; /* Block Erase (4-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_642D) - { - /**< AT45DB642D Density Code : 01000 = 64-Mbit */ - FLASH_TRACE("AT45DB642D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 1024; /* Page Erase (1 Kbyte) */ - spi_flash_at45dbxx.geometry.sector_count = 128*64; /* 64-Mbit / 8 / 1024 = 8192 */ - spi_flash_at45dbxx.geometry.block_size = 1024*8; /* Block Erase (8 Kbytes) */ - } - else - { - FLASH_TRACE("Memory Capacity error!\r\n"); - return -RT_ENOSYS; - } - } - - /* register device */ - spi_flash_at45dbxx.flash_device.type = RT_Device_Class_Block; - spi_flash_at45dbxx.flash_device.init = AT45DB_flash_init; - spi_flash_at45dbxx.flash_device.open = AT45DB_flash_open; - spi_flash_at45dbxx.flash_device.close = AT45DB_flash_close; - spi_flash_at45dbxx.flash_device.control = AT45DB_flash_control; - - if(JEDEC_ID->density_code == DENSITY_CODE_642D) - { - spi_flash_at45dbxx.flash_device.read = AT45DB_flash_read_page_1024; - spi_flash_at45dbxx.flash_device.write = AT45DB_flash_write_page_1024; - } - else if(JEDEC_ID->density_code == DENSITY_CODE_161D - || JEDEC_ID->density_code == DENSITY_CODE_321D ) - { - spi_flash_at45dbxx.flash_device.read = AT45DB_flash_read_page_512; - spi_flash_at45dbxx.flash_device.write = AT45DB_flash_write_page_512; - } - else - { - spi_flash_at45dbxx.flash_device.read = AT45DB_flash_read_page_256; - spi_flash_at45dbxx.flash_device.write = AT45DB_flash_write_page_256; - } - - /* no private */ - spi_flash_at45dbxx.flash_device.user_data = RT_NULL; - - rt_device_register(&spi_flash_at45dbxx.flash_device, flash_device_name, - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); - - return RT_EOK; -} diff --git a/components/drivers/spi/spi_flash_at45dbxx.h b/components/drivers/spi/spi_flash_at45dbxx.h deleted file mode 100644 index d1bc1a2aeb..0000000000 --- a/components/drivers/spi/spi_flash_at45dbxx.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - */ - -#ifndef SPI_FLASH_AT45DBXX_H_INCLUDED -#define SPI_FLASH_AT45DBXX_H_INCLUDED - -#include <rtthread.h> -#include <drivers/spi.h> - -struct spi_flash_at45dbxx -{ - struct rt_device flash_device; - struct rt_device_blk_geometry geometry; - struct rt_spi_device * rt_spi_device; -}; - -extern rt_err_t at45dbxx_init(const char * flash_device_name, const char * spi_device_name); - - -#endif // SPI_FLASH_AT45DBXX_H_INCLUDED diff --git a/components/drivers/spi/spi_flash_gd.c b/components/drivers/spi/spi_flash_gd.c deleted file mode 100644 index 3c52035372..0000000000 --- a/components/drivers/spi/spi_flash_gd.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2015-10-11 fullhan copy from winbond flash - */ - -#include <stdint.h> -#include <rtthread.h> -#include <rtdevice.h> - -#include "spi_flash.h" -#include "spi_flash_gd.h" - -#define FLASH_DEBUG - -#ifdef FLASH_DEBUG -#define FLASH_TRACE rt_kprintf -#else -#define FLASH_TRACE(...) -#endif /* #ifdef FLASH_DEBUG */ - -#define PAGE_SIZE 4096 - -/* JEDEC Manufacturer's ID */ -#define MF_ID (0xC8) -/* JEDEC Device ID: Memory type and Capacity */ -#define MTC_GD25Q128 (0x4018) - -/* command list */ -#define CMD_WRSR (0x01) /* Write Status Register */ -#define CMD_PP (0x02) /* Page Program */ -#define CMD_READ (0x03) /* Read Data */ -#define CMD_WRDI (0x04) /* Write Disable */ -#define CMD_RDSR1 (0x05) /* Read Status Register-1 */ -#define CMD_WREN (0x06) /* Write Enable */ -#define CMD_FAST_READ (0x0B) /* Fast Read */ -#define CMD_ERASE_4K (0x20) /* Sector Erase:4K */ -#define CMD_RDSR2 (0x35) /* Read Status Register-2 */ -#define CMD_ERASE_32K (0x52) /* 32KB Block Erase */ -#define CMD_JEDEC_ID (0x9F) /* Read JEDEC ID */ -#define CMD_ERASE_full (0xC7) /* Chip Erase */ -#define CMD_ERASE_64K (0xD8) /* 64KB Block Erase */ - -#define DUMMY (0xFF) - -static struct spi_flash_device spi_flash_device; - -static void flash_lock(struct spi_flash_device * flash_device) -{ - rt_mutex_take(&flash_device->lock, RT_WAITING_FOREVER); -} - -static void flash_unlock(struct spi_flash_device * flash_device) -{ - rt_mutex_release(&flash_device->lock); -} - -static uint8_t w25qxx_read_status(void) -{ - return rt_spi_sendrecv8(spi_flash_device.rt_spi_device, CMD_RDSR1); -} - -static void w25qxx_wait_busy(void) -{ - while( w25qxx_read_status() & (0x01)); -} - -/** \brief read [size] byte from [offset] to [buffer] - * - * \param offset uint32_t unit : byte - * \param buffer uint8_t* - * \param size uint32_t unit : byte - * \return uint32_t byte for read - * - */ -static uint32_t w25qxx_read(uint32_t offset, uint8_t * buffer, uint32_t size) -{ - uint8_t send_buffer[4]; - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_READ; - send_buffer[1] = (uint8_t)(offset>>16); - send_buffer[2] = (uint8_t)(offset>>8); - send_buffer[3] = (uint8_t)(offset); - - rt_spi_send_then_recv(spi_flash_device.rt_spi_device, - send_buffer, 4, - buffer, size); - - return size; -} - -/** \brief write N page on [page] - * - * \param page_addr uint32_t unit : byte (4096 * N,1 page = 4096byte) - * \param buffer const uint8_t* - * \return uint32_t - * - */ -static uint32_t w25qxx_page_write(uint32_t page_addr, const uint8_t* buffer) -{ - uint32_t index; - uint8_t send_buffer[4]; - - RT_ASSERT((page_addr&0xFF) == 0); /* page addr must align to 256byte. */ - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_ERASE_4K; - send_buffer[1] = (page_addr >> 16); - send_buffer[2] = (page_addr >> 8); - send_buffer[3] = (page_addr); - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 4); - - w25qxx_wait_busy(); // wait erase done. - - for(index=0; index < (PAGE_SIZE / 256); index++) - { - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_PP; - send_buffer[1] = (uint8_t)(page_addr >> 16); - send_buffer[2] = (uint8_t)(page_addr >> 8); - send_buffer[3] = (uint8_t)(page_addr); - - rt_spi_send_then_send(spi_flash_device.rt_spi_device, - send_buffer, - 4, - buffer, - 256); - - buffer += 256; - page_addr += 256; - w25qxx_wait_busy(); - } - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - return PAGE_SIZE; -} - -/* RT-Thread device interface */ -static rt_err_t w25qxx_flash_init(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t w25qxx_flash_open(rt_device_t dev, rt_uint16_t oflag) -{ - uint8_t send_buffer[3]; - - flash_lock((struct spi_flash_device *)dev); - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_WRSR; - send_buffer[1] = 0; - send_buffer[2] = 0; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 3); - - w25qxx_wait_busy(); - - flash_unlock((struct spi_flash_device *)dev); - - return RT_EOK; -} - -static rt_err_t w25qxx_flash_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t w25qxx_flash_control(rt_device_t dev, int cmd, void *args) -{ - RT_ASSERT(dev != RT_NULL); - - if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) - { - struct rt_device_blk_geometry *geometry; - - geometry = (struct rt_device_blk_geometry *)args; - if (geometry == RT_NULL) return -RT_ERROR; - - geometry->bytes_per_sector = spi_flash_device.geometry.bytes_per_sector; - geometry->sector_count = spi_flash_device.geometry.sector_count; - geometry->block_size = spi_flash_device.geometry.block_size; - } - - return RT_EOK; -} - -static rt_size_t w25qxx_flash_read(rt_device_t dev, - rt_off_t pos, - void* buffer, - rt_size_t size) -{ - flash_lock((struct spi_flash_device *)dev); - - w25qxx_read(pos*spi_flash_device.geometry.bytes_per_sector, - buffer, - size*spi_flash_device.geometry.bytes_per_sector); - - flash_unlock((struct spi_flash_device *)dev); - - return size; -} - -static rt_size_t w25qxx_flash_write(rt_device_t dev, - rt_off_t pos, - const void* buffer, - rt_size_t size) -{ - rt_size_t i = 0; - rt_size_t block = size; - const uint8_t * ptr = buffer; - - flash_lock((struct spi_flash_device *)dev); - - while(block--) - { - w25qxx_page_write((pos + i)*spi_flash_device.geometry.bytes_per_sector, - ptr); - ptr += PAGE_SIZE; - i++; - } - - flash_unlock((struct spi_flash_device *)dev); - - return size; -} - -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops gd_device_ops = -{ - w25qxx_flash_init, - w25qxx_flash_open, - w25qxx_flash_close, - w25qxx_flash_read, - w25qxx_flash_write, - w25qxx_flash_control -}; -#endif - -rt_err_t gd_init(const char * flash_device_name, const char * spi_device_name) -{ - struct rt_spi_device * rt_spi_device; - - /* initialize mutex */ - if (rt_mutex_init(&spi_flash_device.lock, spi_device_name, RT_IPC_FLAG_FIFO) != RT_EOK) - { - rt_kprintf("init sd lock mutex failed\n"); - return -RT_ENOSYS; - } - - rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); - if(rt_spi_device == RT_NULL) - { - FLASH_TRACE("spi device %s not found!\r\n", spi_device_name); - return -RT_ENOSYS; - } - spi_flash_device.rt_spi_device = rt_spi_device; - - /* config spi */ - { - struct rt_spi_configuration cfg; - cfg.data_width = 8; - cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */ - cfg.max_hz = 50 * 1000 * 1000; /* 50M */ - rt_spi_configure(spi_flash_device.rt_spi_device, &cfg); - } - - /* init flash */ - { - rt_uint8_t cmd; - rt_uint8_t id_recv[3]; - uint16_t memory_type_capacity; - - flash_lock(&spi_flash_device); - - cmd = 0xFF; /* reset SPI FLASH, cancel all cmd in processing. */ - rt_spi_send(spi_flash_device.rt_spi_device, &cmd, 1); - - cmd = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, &cmd, 1); - - /* read flash id */ - cmd = CMD_JEDEC_ID; - rt_spi_send_then_recv(spi_flash_device.rt_spi_device, &cmd, 1, id_recv, 3); - - flash_unlock(&spi_flash_device); - - if(id_recv[0] != MF_ID) - { - FLASH_TRACE("Manufacturers ID error!\r\n"); - FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]); - return -RT_ENOSYS; - } - - spi_flash_device.geometry.bytes_per_sector = 4096; - spi_flash_device.geometry.block_size = 4096; /* block erase: 4k */ - - /* get memory type and capacity */ - memory_type_capacity = id_recv[1]; - memory_type_capacity = (memory_type_capacity << 8) | id_recv[2]; - - if(memory_type_capacity == MTC_GD25Q128) - { - FLASH_TRACE("GD128 detection\r\n"); - spi_flash_device.geometry.sector_count = 4096; - } - else - { - FLASH_TRACE("Memory Capacity error!\r\n"); - return -RT_ENOSYS; - } - } - - /* register device */ - spi_flash_device.flash_device.type = RT_Device_Class_Block; -#ifdef RT_USING_DEVICE_OPS - spi_flash_device.flash_device.ops = &gd_device_ops; -#else - spi_flash_device.flash_device.init = w25qxx_flash_init; - spi_flash_device.flash_device.open = w25qxx_flash_open; - spi_flash_device.flash_device.close = w25qxx_flash_close; - spi_flash_device.flash_device.read = w25qxx_flash_read; - spi_flash_device.flash_device.write = w25qxx_flash_write; - spi_flash_device.flash_device.control = w25qxx_flash_control; -#endif - /* no private */ - spi_flash_device.flash_device.user_data = RT_NULL; - - rt_device_register(&spi_flash_device.flash_device, flash_device_name, - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); - - return RT_EOK; -} diff --git a/components/drivers/spi/spi_flash_gd.h b/components/drivers/spi/spi_flash_gd.h deleted file mode 100644 index 904d976ed0..0000000000 --- a/components/drivers/spi/spi_flash_gd.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2015-10-11 fullhan copy from winbond flash - */ - -#ifndef SPI_FLASH_GD_H_ -#define SPI_FLASH_GD_H_ - -#include <rtthread.h> - -extern rt_err_t gd_init(const char * flash_device_name, const char * spi_device_name); - -#endif /* SPI_FLASH_GD_H_ */ diff --git a/components/drivers/spi/spi_flash_sfud.c b/components/drivers/spi/spi_flash_sfud.c index 7fa7de6ad5..ce67ce9a72 100644 --- a/components/drivers/spi/spi_flash_sfud.c +++ b/components/drivers/spi/spi_flash_sfud.c @@ -22,12 +22,17 @@ #endif /* RT_DEBUG_SFUD */ #ifndef RT_SFUD_DEFAULT_SPI_CFG + +#ifndef RT_SFUD_SPI_MAX_HZ +#define RT_SFUD_SPI_MAX_HZ 50000000 +#endif + /* read the JEDEC SFDP command must run at 50 MHz or less */ #define RT_SFUD_DEFAULT_SPI_CFG \ { \ .mode = RT_SPI_MODE_0 | RT_SPI_MSB, \ .data_width = 8, \ - .max_hz = 50 * 1000 * 1000, \ + .max_hz = RT_SFUD_SPI_MAX_HZ, \ } #endif diff --git a/components/drivers/spi/spi_flash_sst25vfxx.c b/components/drivers/spi/spi_flash_sst25vfxx.c deleted file mode 100644 index bd618a8e9b..0000000000 --- a/components/drivers/spi/spi_flash_sst25vfxx.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - */ - -#include <stdint.h> -#include "spi_flash_sst25vfxx.h" - -#define FLASH_DEBUG - -#ifdef FLASH_DEBUG -#define FLASH_TRACE rt_kprintf -#else -#define FLASH_TRACE(...) -#endif /* #ifdef FLASH_DEBUG */ - -/* JEDEC Manufacturer’s ID */ -#define MF_ID (0xBF) -/* JEDEC Device ID : Memory Type */ -#define MT_ID (0x25) -/* JEDEC Device ID: Memory Capacity */ -#define MC_ID_SST25VF020B (0x8C) /* 2Mbit */ -#define MC_ID_SST25VF040B (0x8D) /* 4Mbit */ -#define MC_ID_SST25VF080B (0x8E) /* 8Mbit */ -#define MC_ID_SST25VF016B (0x41) /* 16Mbit */ -#define MC_ID_SST25VF032B (0x4A) /* 32Mbit */ -#define MC_ID_SST25VF064C (0x4B) /* 64Mbit */ - -/* command list */ -#define CMD_RDSR (0x05) -#define CMD_WRSR (0x01) -#define CMD_EWSR (0x50) -#define CMD_WRDI (0x04) -#define CMD_WREN (0x06) -#define CMD_READ (0x03) -#define CMD_FAST_READ (0x0B) -#define CMD_BP (0x02) -#define CMD_AAIP (0xAD) -#define CMD_ERASE_4K (0x20) -#define CMD_ERASE_32K (0x52) -#define CMD_ERASE_64K (0xD8) -#define CMD_ERASE_full (0xC7) -#define CMD_JEDEC_ID (0x9F) -#define CMD_EBSY (0x70) -#define CMD_DBSY (0x80) - -#define DUMMY (0xFF) - -static struct spi_flash_sst25vfxx spi_flash_sst25vfxx; - -static uint8_t sst25vfxx_read_status(struct spi_flash_sst25vfxx * spi_flash) -{ - return rt_spi_sendrecv8(spi_flash->rt_spi_device, CMD_RDSR); -} - -static void sst25vfxx_wait_busy(struct spi_flash_sst25vfxx * spi_flash) -{ - while( sst25vfxx_read_status(spi_flash) & (0x01)); -} - -/** \brief write N page on [page] - * - * \param page uint32_t unit : byte (4096 * N,1 page = 4096byte) - * \param buffer const uint8_t* - * \param size uint32_t unit : byte ( 4096*N ) - * \return uint32_t - * - */ -static uint32_t sst25vfxx_page_write(struct spi_flash_sst25vfxx * spi_flash, uint32_t page, const uint8_t * buffer, uint32_t size) -{ - uint32_t index; - uint32_t need_wirte = size; - uint8_t send_buffer[6]; - - page &= ~0xFFF; // page size = 4096byte - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_ERASE_4K; - send_buffer[1] = (page >> 16); - send_buffer[2] = (page >> 8); - send_buffer[3] = (page); - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 4); - - sst25vfxx_wait_busy(spi_flash); // wait erase done. - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_AAIP; - send_buffer[1] = (uint8_t)(page >> 16); - send_buffer[2] = (uint8_t)(page >> 8); - send_buffer[3] = (uint8_t)(page); - send_buffer[4] = *buffer++; - send_buffer[5] = *buffer++; - need_wirte -= 2; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 6); - - sst25vfxx_wait_busy(spi_flash); - - for(index=0; index < need_wirte/2; index++) - { - send_buffer[0] = CMD_AAIP; - send_buffer[1] = *buffer++; - send_buffer[2] = *buffer++; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 3); - sst25vfxx_wait_busy(spi_flash); - } - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - return size; -} - -/* RT-Thread device interface */ -static rt_err_t sst25vfxx_flash_init(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t sst25vfxx_flash_open(rt_device_t dev, rt_uint16_t oflag) -{ - rt_err_t result; - uint8_t send_buffer[2]; - struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev; - - /* lock spi flash */ - result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER); - if(result != RT_EOK) - { - return result; - } - - send_buffer[0] = CMD_DBSY; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_EWSR; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_WRSR; - send_buffer[1] = 0; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 2); - - /* release lock */ - rt_mutex_release(&(spi_flash->lock)); - - return RT_EOK; -} - -static rt_err_t sst25vfxx_flash_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t sst25vfxx_flash_control(rt_device_t dev, int cmd, void *args) -{ - struct spi_flash_sst25vfxx * spi_flash; - - spi_flash = (struct spi_flash_sst25vfxx *)dev; - - RT_ASSERT(dev != RT_NULL); - - if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) - { - struct rt_device_blk_geometry *geometry; - - geometry = (struct rt_device_blk_geometry *)args; - if (geometry == RT_NULL) return -RT_ERROR; - - geometry->bytes_per_sector = spi_flash->geometry.bytes_per_sector; - geometry->sector_count = spi_flash->geometry.sector_count; - geometry->block_size = spi_flash->geometry.block_size; - } - - return RT_EOK; -} - -static rt_size_t sst25vfxx_flash_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) -{ - rt_err_t result; - uint8_t send_buffer[4]; - struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev; - uint32_t offset = pos * spi_flash->geometry.bytes_per_sector; - - /* lock spi flash */ - result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER); - if(result != RT_EOK) - { - return 0; - } - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_READ; - send_buffer[1] = (uint8_t)(offset>>16); - send_buffer[2] = (uint8_t)(offset>>8); - send_buffer[3] = (uint8_t)(offset); - rt_spi_send_then_recv(spi_flash->rt_spi_device, send_buffer, 4, buffer, size * spi_flash->geometry.bytes_per_sector); - - /* release lock */ - rt_mutex_release(&(spi_flash->lock)); - - return size; -} - -static rt_size_t sst25vfxx_flash_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) -{ - uint32_t i; - rt_err_t result; - const uint8_t * write_buffer = buffer; - struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev; - - /* lock spi flash */ - result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER); - if(result != RT_EOK) - { - return 0; - } - - for(i=0; i<size; i++) - { - sst25vfxx_page_write(spi_flash, - (pos + i) * spi_flash->geometry.bytes_per_sector, - write_buffer, - spi_flash->geometry.bytes_per_sector); - write_buffer += spi_flash->geometry.bytes_per_sector; - } - - /* release lock */ - rt_mutex_release(&(spi_flash->lock)); - - return size; -} - -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops sst25vfxx_device_ops = -{ - sst25vfxx_flash_init, - sst25vfxx_flash_open, - sst25vfxx_flash_close, - sst25vfxx_flash_read, - sst25vfxx_flash_write, - sst25vfxx_flash_control -}; -#endif - -rt_err_t sst25vfxx_init(const char * flash_device_name, const char * spi_device_name) -{ - struct rt_spi_device * rt_spi_device; - struct spi_flash_sst25vfxx * spi_flash = &spi_flash_sst25vfxx; - - rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); - if(rt_spi_device == RT_NULL) - { - FLASH_TRACE("spi device %s not found!\r\n", spi_device_name); - return -RT_ENOSYS; - } - spi_flash->rt_spi_device = rt_spi_device; - - /* config spi */ - { - struct rt_spi_configuration cfg; - cfg.data_width = 8; - cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */ - cfg.max_hz = 50000000; /* 50M */ - rt_spi_configure(spi_flash->rt_spi_device, &cfg); - } - - /* init flash */ - { - rt_uint8_t cmd; - rt_uint8_t id_recv[3]; - - cmd = CMD_WRDI; - rt_spi_send(spi_flash->rt_spi_device, &cmd, 1); - - /* read flash id */ - cmd = CMD_JEDEC_ID; - rt_spi_send_then_recv(spi_flash->rt_spi_device, &cmd, 1, id_recv, 3); - - if(id_recv[0] != MF_ID || id_recv[1] != MT_ID) - { - FLASH_TRACE("Manufacturer’s ID or Memory Type error!\r\n"); - FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]); - return -RT_ENOSYS; - } - - spi_flash->geometry.bytes_per_sector = 4096; - spi_flash->geometry.block_size = 4096; /* block erase: 4k */ - - if(id_recv[2] == MC_ID_SST25VF020B) - { - FLASH_TRACE("SST25VF020B detection\r\n"); - spi_flash->geometry.sector_count = 64; - } - else if(id_recv[2] == MC_ID_SST25VF040B) - { - FLASH_TRACE("SST25VF040B detection\r\n"); - spi_flash->geometry.sector_count = 128; - } - else if(id_recv[2] == MC_ID_SST25VF080B) - { - FLASH_TRACE("SST25VF080B detection\r\n"); - spi_flash->geometry.sector_count = 256; - } - else if(id_recv[2] == MC_ID_SST25VF016B) - { - FLASH_TRACE("SST25VF016B detection\r\n"); - spi_flash->geometry.sector_count = 512; - } - else if(id_recv[2] == MC_ID_SST25VF032B) - { - FLASH_TRACE("SST25VF032B detection\r\n"); - spi_flash->geometry.sector_count = 1024; - } - else if(id_recv[2] == MC_ID_SST25VF064C) - { - FLASH_TRACE("SST25VF064C detection\r\n"); - spi_flash->geometry.sector_count = 2048; - } - else - { - FLASH_TRACE("Memory Capacity error!\r\n"); - return -RT_ENOSYS; - } - } - - /* initialize mutex lock */ - rt_mutex_init(&spi_flash->lock, flash_device_name, RT_IPC_FLAG_PRIO); - - /* register device */ - spi_flash->flash_device.type = RT_Device_Class_Block; -#ifdef RT_USING_DEVICE_OPS - spi_flash->flash_device.ops = &sst25vfxx_device_ops; -#else - spi_flash->flash_device.init = sst25vfxx_flash_init; - spi_flash->flash_device.open = sst25vfxx_flash_open; - spi_flash->flash_device.close = sst25vfxx_flash_close; - spi_flash->flash_device.read = sst25vfxx_flash_read; - spi_flash->flash_device.write = sst25vfxx_flash_write; - spi_flash->flash_device.control = sst25vfxx_flash_control; -#endif - /* no private */ - spi_flash->flash_device.user_data = RT_NULL; - - rt_device_register(&spi_flash->flash_device, flash_device_name, - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); - - return RT_EOK; -} diff --git a/components/drivers/spi/spi_flash_sst25vfxx.h b/components/drivers/spi/spi_flash_sst25vfxx.h deleted file mode 100644 index 7a7283f753..0000000000 --- a/components/drivers/spi/spi_flash_sst25vfxx.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - */ - -#ifndef SPI_FLASH_SST25VFXX_H_INCLUDED -#define SPI_FLASH_SST25VFXX_H_INCLUDED - -#include <rtthread.h> -#include <drivers/spi.h> - -struct spi_flash_sst25vfxx -{ - struct rt_device flash_device; - struct rt_device_blk_geometry geometry; - struct rt_spi_device * rt_spi_device; - struct rt_mutex lock; -}; - -extern rt_err_t sst25vfxx_init(const char * flash_device_name, const char * spi_device_name); - - -#endif // SPI_FLASH_SST25VFXX_H_INCLUDED diff --git a/components/drivers/spi/spi_flash_w25qxx.c b/components/drivers/spi/spi_flash_w25qxx.c deleted file mode 100644 index bba9c0b5cc..0000000000 --- a/components/drivers/spi/spi_flash_w25qxx.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - * 2012-05-06 aozima can page write. - * 2012-08-23 aozima add flash lock. - * 2012-08-24 aozima fixed write status register BUG. - */ - -#include <stdint.h> -#include <rtdevice.h> - -#include "spi_flash.h" -#include "spi_flash_w25qxx.h" - -#define FLASH_DEBUG - -#ifdef FLASH_DEBUG -#define FLASH_TRACE rt_kprintf -#else -#define FLASH_TRACE(...) -#endif /* #ifdef FLASH_DEBUG */ - -#define PAGE_SIZE 4096 - -/* JEDEC Manufacturer ID */ -#define MF_ID (0xEF) - -/* JEDEC Device ID: Memory type and Capacity */ -#define MTC_W25Q80_BV (0x4014) /* W25Q80BV */ -#define MTC_W25Q16_BV_CL_CV (0x4015) /* W25Q16BV W25Q16CL W25Q16CV */ -#define MTC_W25Q16_DW (0x6015) /* W25Q16DW */ -#define MTC_W25Q32_BV (0x4016) /* W25Q32BV */ -#define MTC_W25Q32_DW (0x6016) /* W25Q32DW */ -#define MTC_W25Q64_BV_CV (0x4017) /* W25Q64BV W25Q64CV */ -#define MTC_W25Q64_DW (0x4017) /* W25Q64DW */ -#define MTC_W25Q128_BV (0x4018) /* W25Q128BV */ -#define MTC_W25Q256_FV (TBD) /* W25Q256FV */ - -/* command list */ -#define CMD_WRSR (0x01) /* Write Status Register */ -#define CMD_PP (0x02) /* Page Program */ -#define CMD_READ (0x03) /* Read Data */ -#define CMD_WRDI (0x04) /* Write Disable */ -#define CMD_RDSR1 (0x05) /* Read Status Register-1 */ -#define CMD_WREN (0x06) /* Write Enable */ -#define CMD_FAST_READ (0x0B) /* Fast Read */ -#define CMD_ERASE_4K (0x20) /* Sector Erase:4K */ -#define CMD_RDSR2 (0x35) /* Read Status Register-2 */ -#define CMD_ERASE_32K (0x52) /* 32KB Block Erase */ -#define CMD_JEDEC_ID (0x9F) /* Read JEDEC ID */ -#define CMD_ERASE_full (0xC7) /* Chip Erase */ -#define CMD_ERASE_64K (0xD8) /* 64KB Block Erase */ - -#define DUMMY (0xFF) - -static struct spi_flash_device spi_flash_device; - -static void flash_lock(struct spi_flash_device * flash_device) -{ - rt_mutex_take(&flash_device->lock, RT_WAITING_FOREVER); -} - -static void flash_unlock(struct spi_flash_device * flash_device) -{ - rt_mutex_release(&flash_device->lock); -} - -static uint8_t w25qxx_read_status(void) -{ - return rt_spi_sendrecv8(spi_flash_device.rt_spi_device, CMD_RDSR1); -} - -static void w25qxx_wait_busy(void) -{ - while( w25qxx_read_status() & (0x01)); -} - -/** \brief read [size] byte from [offset] to [buffer] - * - * \param offset uint32_t unit : byte - * \param buffer uint8_t* - * \param size uint32_t unit : byte - * \return uint32_t byte for read - * - */ -static uint32_t w25qxx_read(uint32_t offset, uint8_t * buffer, uint32_t size) -{ - uint8_t send_buffer[4]; - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_READ; - send_buffer[1] = (uint8_t)(offset>>16); - send_buffer[2] = (uint8_t)(offset>>8); - send_buffer[3] = (uint8_t)(offset); - - rt_spi_send_then_recv(spi_flash_device.rt_spi_device, - send_buffer, 4, - buffer, size); - - return size; -} - -/** \brief write N page on [page] - * - * \param page_addr uint32_t unit : byte (4096 * N,1 page = 4096byte) - * \param buffer const uint8_t* - * \return uint32_t - * - */ -uint32_t w25qxx_page_write(uint32_t page_addr, const uint8_t* buffer) -{ - uint32_t index; - uint8_t send_buffer[4]; - - RT_ASSERT((page_addr&0xFF) == 0); /* page addr must align to 256byte. */ - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_ERASE_4K; - send_buffer[1] = (page_addr >> 16); - send_buffer[2] = (page_addr >> 8); - send_buffer[3] = (page_addr); - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 4); - - w25qxx_wait_busy(); // wait erase done. - - for(index=0; index < (PAGE_SIZE / 256); index++) - { - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_PP; - send_buffer[1] = (uint8_t)(page_addr >> 16); - send_buffer[2] = (uint8_t)(page_addr >> 8); - send_buffer[3] = (uint8_t)(page_addr); - - rt_spi_send_then_send(spi_flash_device.rt_spi_device, - send_buffer, - 4, - buffer, - 256); - - buffer += 256; - page_addr += 256; - w25qxx_wait_busy(); - } - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - return PAGE_SIZE; -} - -/* RT-Thread device interface */ -static rt_err_t w25qxx_flash_init(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t w25qxx_flash_open(rt_device_t dev, rt_uint16_t oflag) -{ - uint8_t send_buffer[3]; - - flash_lock((struct spi_flash_device *)dev); - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_WRSR; - send_buffer[1] = 0; - send_buffer[2] = 0; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 3); - - w25qxx_wait_busy(); - - flash_unlock((struct spi_flash_device *)dev); - - return RT_EOK; -} - -static rt_err_t w25qxx_flash_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t w25qxx_flash_control(rt_device_t dev, int cmd, void *args) -{ - RT_ASSERT(dev != RT_NULL); - - if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) - { - struct rt_device_blk_geometry *geometry; - - geometry = (struct rt_device_blk_geometry *)args; - if (geometry == RT_NULL) return -RT_ERROR; - - geometry->bytes_per_sector = spi_flash_device.geometry.bytes_per_sector; - geometry->sector_count = spi_flash_device.geometry.sector_count; - geometry->block_size = spi_flash_device.geometry.block_size; - } - - return RT_EOK; -} - -static rt_size_t w25qxx_flash_read(rt_device_t dev, - rt_off_t pos, - void* buffer, - rt_size_t size) -{ - flash_lock((struct spi_flash_device *)dev); - - w25qxx_read(pos*spi_flash_device.geometry.bytes_per_sector, - buffer, - size*spi_flash_device.geometry.bytes_per_sector); - - flash_unlock((struct spi_flash_device *)dev); - - return size; -} - -static rt_size_t w25qxx_flash_write(rt_device_t dev, - rt_off_t pos, - const void* buffer, - rt_size_t size) -{ - rt_size_t i = 0; - rt_size_t block = size; - const uint8_t * ptr = buffer; - - flash_lock((struct spi_flash_device *)dev); - - while(block--) - { - w25qxx_page_write((pos + i)*spi_flash_device.geometry.bytes_per_sector, - ptr); - ptr += PAGE_SIZE; - i++; - } - - flash_unlock((struct spi_flash_device *)dev); - - return size; -} - -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops w25qxx_device_ops = -{ - w25qxx_flash_init, - w25qxx_flash_open, - w25qxx_flash_close, - w25qxx_flash_read, - w25qxx_flash_write, - w25qxx_flash_control -}; -#endif - -rt_err_t w25qxx_init(const char * flash_device_name, const char * spi_device_name) -{ - struct rt_spi_device * rt_spi_device; - - /* initialize mutex */ - if (rt_mutex_init(&spi_flash_device.lock, spi_device_name, RT_IPC_FLAG_FIFO) != RT_EOK) - { - rt_kprintf("init sd lock mutex failed\n"); - return -RT_ENOSYS; - } - - rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); - if(rt_spi_device == RT_NULL) - { - FLASH_TRACE("spi device %s not found!\r\n", spi_device_name); - return -RT_ENOSYS; - } - spi_flash_device.rt_spi_device = rt_spi_device; - - /* config spi */ - { - struct rt_spi_configuration cfg; - cfg.data_width = 8; - cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */ - cfg.max_hz = 50 * 1000 * 1000; /* 50M */ - rt_spi_configure(spi_flash_device.rt_spi_device, &cfg); - } - - /* init flash */ - { - rt_uint8_t cmd; - rt_uint8_t id_recv[3]; - uint16_t memory_type_capacity; - - flash_lock(&spi_flash_device); - - cmd = 0xFF; /* reset SPI FLASH, cancel all cmd in processing. */ - rt_spi_send(spi_flash_device.rt_spi_device, &cmd, 1); - - cmd = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, &cmd, 1); - - /* read flash id */ - cmd = CMD_JEDEC_ID; - rt_spi_send_then_recv(spi_flash_device.rt_spi_device, &cmd, 1, id_recv, 3); - - flash_unlock(&spi_flash_device); - - if(id_recv[0] != MF_ID) - { - FLASH_TRACE("Manufacturers ID error!\r\n"); - FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]); - return -RT_ENOSYS; - } - - spi_flash_device.geometry.bytes_per_sector = 4096; - spi_flash_device.geometry.block_size = 4096; /* block erase: 4k */ - - /* get memory type and capacity */ - memory_type_capacity = id_recv[1]; - memory_type_capacity = (memory_type_capacity << 8) | id_recv[2]; - - if(memory_type_capacity == MTC_W25Q128_BV) - { - FLASH_TRACE("W25Q128BV detection\r\n"); - spi_flash_device.geometry.sector_count = 4096; - } - else if(memory_type_capacity == MTC_W25Q64_BV_CV) - { - FLASH_TRACE("W25Q64BV or W25Q64CV detection\r\n"); - spi_flash_device.geometry.sector_count = 2048; - } - else if(memory_type_capacity == MTC_W25Q64_DW) - { - FLASH_TRACE("W25Q64DW detection\r\n"); - spi_flash_device.geometry.sector_count = 2048; - } - else if(memory_type_capacity == MTC_W25Q32_BV) - { - FLASH_TRACE("W25Q32BV detection\r\n"); - spi_flash_device.geometry.sector_count = 1024; - } - else if(memory_type_capacity == MTC_W25Q32_DW) - { - FLASH_TRACE("W25Q32DW detection\r\n"); - spi_flash_device.geometry.sector_count = 1024; - } - else if(memory_type_capacity == MTC_W25Q16_BV_CL_CV) - { - FLASH_TRACE("W25Q16BV or W25Q16CL or W25Q16CV detection\r\n"); - spi_flash_device.geometry.sector_count = 512; - } - else if(memory_type_capacity == MTC_W25Q16_DW) - { - FLASH_TRACE("W25Q16DW detection\r\n"); - spi_flash_device.geometry.sector_count = 512; - } - else if(memory_type_capacity == MTC_W25Q80_BV) - { - FLASH_TRACE("W25Q80BV detection\r\n"); - spi_flash_device.geometry.sector_count = 256; - } - else - { - FLASH_TRACE("Memory Capacity error!\r\n"); - return -RT_ENOSYS; - } - } - - /* register device */ - spi_flash_device.flash_device.type = RT_Device_Class_Block; -#ifdef RT_USING_DEVICE_OPS - spi_flash_device.flash_device.ops = &w25qxx_device_ops; -#else - spi_flash_device.flash_device.init = w25qxx_flash_init; - spi_flash_device.flash_device.open = w25qxx_flash_open; - spi_flash_device.flash_device.close = w25qxx_flash_close; - spi_flash_device.flash_device.read = w25qxx_flash_read; - spi_flash_device.flash_device.write = w25qxx_flash_write; - spi_flash_device.flash_device.control = w25qxx_flash_control; -#endif - /* no private */ - spi_flash_device.flash_device.user_data = RT_NULL; - - rt_device_register(&spi_flash_device.flash_device, flash_device_name, - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); - - return RT_EOK; -} diff --git a/components/drivers/spi/spi_flash_w25qxx.h b/components/drivers/spi/spi_flash_w25qxx.h deleted file mode 100644 index 14837bc87c..0000000000 --- a/components/drivers/spi/spi_flash_w25qxx.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - * 2012-08-23 aozima add flash lock. - */ - -#ifndef SPI_FLASH_W25QXX_H_INCLUDED -#define SPI_FLASH_W25QXX_H_INCLUDED - -#include <rtthread.h> - -extern rt_err_t w25qxx_init(const char * flash_device_name, - const char * spi_device_name); - -#endif // SPI_FLASH_W25QXX_H_INCLUDED diff --git a/components/drivers/spi/spi_flash_w25qxx_mtd.c b/components/drivers/spi/spi_flash_w25qxx_mtd.c deleted file mode 100644 index 9f1ef802f6..0000000000 --- a/components/drivers/spi/spi_flash_w25qxx_mtd.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ -#include <rtthread.h> -#include <rtdevice.h> - -#include "spi_flash.h" -#include "spi_flash_w25qxx_mtd.h" - -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - -#define FLASH_DEBUG - -#ifdef FLASH_DEBUG -#define FLASH_TRACE printf -#else -#define FLASH_TRACE(...) -#endif /* #ifdef FLASH_DEBUG */ - -/* JEDEC Manufacturer’s ID */ -#define MF_ID (0xEF) -/* JEDEC Device ID: Memory type and Capacity */ -#define MTC_W25Q80_BV (0x4014) /* W25Q80BV */ -#define MTC_W25Q16_BV_CL_CV (0x4015) /* W25Q16BV W25Q16CL W25Q16CV */ -#define MTC_W25Q16_DW (0x6015) /* W25Q16DW */ -#define MTC_W25Q32_BV (0x4016) /* W25Q32BV */ -#define MTC_W25Q32_DW (0x6016) /* W25Q32DW */ -#define MTC_W25Q64_BV_CV (0x4017) /* W25Q64BV W25Q64CV */ -#define MTC_W25Q64_DW (0x4017) /* W25Q64DW */ -#define MTC_W25Q128_BV (0x4018) /* W25Q128BV */ -#define MTC_W25Q256_FV (TBD) /* W25Q256FV */ - -#define MTC_W25X80 (0x3014) - -/* command list */ -#define CMD_WRSR (0x01) /* Write Status Register */ -#define CMD_PP (0x02) /* Page Program */ -#define CMD_READ (0x03) /* Read Data */ -#define CMD_WRDI (0x04) /* Write Disable */ -#define CMD_RDSR1 (0x05) /* Read Status Register-1 */ -#define CMD_WREN (0x06) /* Write Enable */ -#define CMD_FAST_READ (0x0B) /* Fast Read */ -#define CMD_ERASE_4K (0x20) /* Sector Erase:4K */ -#define CMD_RDSR2 (0x35) /* Read Status Register-2 */ -#define CMD_ERASE_32K (0x52) /* 32KB Block Erase */ -#define CMD_JEDEC_ID (0x9F) /* Read JEDEC ID */ -#define CMD_ERASE_full (0xC7) /* Chip Erase */ -#define CMD_ERASE_64K (0xD8) /* 64KB Block Erase */ -#define CMD_MANU_ID (0x90) - -#define DUMMY (0xFF) - -#define FLASH_ERASE_CMD CMD_ERASE_4K -#define FLASH_BLOCK_SIZE 4096 -#define FLASH_PAGE_SIZE 256 - -static void w25qxx_lock(struct rt_mtd_nor_device *device) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - rt_mutex_take(&mtd->lock, RT_WAITING_FOREVER); -} - -static void w25qxx_unlock(struct rt_mtd_nor_device *device) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - rt_mutex_release(&mtd->lock); -} - -static rt_uint8_t w25qxx_read_status(struct rt_mtd_nor_device *device) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - return rt_spi_sendrecv8(mtd->rt_spi_device, CMD_RDSR1); -} - -static void w25qxx_wait_busy(struct rt_mtd_nor_device *device) -{ - while( w25qxx_read_status(device) & (0x01)); -} - -static rt_err_t w25qxx_read_id(struct rt_mtd_nor_device *device) -{ - rt_uint8_t cmd; - rt_uint8_t id_recv[3]; - - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - - w25qxx_lock(device); - - cmd = 0xFF; /* reset SPI FLASH, cancel all cmd in processing. */ - rt_spi_send(mtd->rt_spi_device, &cmd, 1); - - cmd = CMD_WRDI; - rt_spi_send(mtd->rt_spi_device, &cmd, 1); - - /* read flash id */ - cmd = CMD_JEDEC_ID; - rt_spi_send_then_recv(mtd->rt_spi_device, &cmd, 1, id_recv, 3); - - w25qxx_unlock(device); - - return (rt_uint32_t)(id_recv[0] << 16) | (id_recv[1] << 8) | id_recv[2]; -} - -static rt_size_t w25qxx_read(struct rt_mtd_nor_device *device, rt_off_t offset, rt_uint8_t *buffer, rt_size_t length) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - rt_uint8_t send_buffer[4]; - - if((offset + length) > device->block_end * FLASH_BLOCK_SIZE) - return 0; - - - w25qxx_lock(device); - - send_buffer[0] = CMD_WRDI; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_READ; - send_buffer[1] = (rt_uint8_t)(offset>>16); - send_buffer[2] = (rt_uint8_t)(offset>>8); - send_buffer[3] = (rt_uint8_t)(offset); - rt_spi_send_then_recv(mtd->rt_spi_device, - send_buffer, 4, - buffer, length); - - w25qxx_unlock(device); - return length; -} - -static rt_size_t w25qxx_write(struct rt_mtd_nor_device *device, rt_off_t offset, const rt_uint8_t *buffer, rt_size_t length) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - rt_uint8_t send_buffer[4]; - rt_uint8_t *write_ptr ; - rt_size_t write_size,write_total; - - if((offset + length) > device->block_end * FLASH_BLOCK_SIZE) - return 0; - - w25qxx_lock(device); - - send_buffer[0] = CMD_WREN; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - w25qxx_wait_busy(device); // wait erase done. - - write_size = 0; - write_total = 0; - write_ptr = (rt_uint8_t *)buffer; - while(write_total < length) - { - send_buffer[0] = CMD_WREN; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - - //write first page... - send_buffer[0] = CMD_PP; - send_buffer[1] = (rt_uint8_t)(offset >> 16); - send_buffer[2] = (rt_uint8_t)(offset >> 8); - send_buffer[3] = (rt_uint8_t)(offset); - - //address % FLASH_PAGE_SIZE + length - if(((offset & (FLASH_PAGE_SIZE - 1)) + (length - write_total)) > FLASH_PAGE_SIZE) - { - write_size = FLASH_PAGE_SIZE - (offset & (FLASH_PAGE_SIZE - 1)); - } - else - { - write_size = (length - write_total); - } - - rt_spi_send_then_send(mtd->rt_spi_device, - send_buffer, 4, - write_ptr + write_total, write_size); - w25qxx_wait_busy(device); - - - offset += write_size; - write_total += write_size; - } - - send_buffer[0] = CMD_WRDI; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - - w25qxx_unlock(device); - - return length; -} - -static rt_err_t w25qxx_erase_block(struct rt_mtd_nor_device *device, rt_off_t offset, rt_uint32_t length) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - rt_uint8_t send_buffer[4]; - rt_uint32_t erase_size = 0; - - //offset must be ALIGN_DOWN to BLOCKSIZE - if(offset != RT_ALIGN_DOWN(offset,FLASH_BLOCK_SIZE)) - return 0; - - if((offset + length) > device->block_end * FLASH_BLOCK_SIZE) - return 0; - - /* check length must align to block size */ - if(length % device->block_size != 0) - { - rt_kprintf("param length = %d ,error\n",length); - return 0; - } - - w25qxx_lock(device); - - send_buffer[0] = CMD_WREN; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - w25qxx_wait_busy(device); // wait erase done. - while (erase_size < length) - { - send_buffer[0] = CMD_ERASE_4K; - send_buffer[1] = (rt_uint8_t) (offset >> 16); - send_buffer[2] = (rt_uint8_t) (offset >> 8); - send_buffer[3] = (rt_uint8_t) (offset); - rt_spi_send(mtd->rt_spi_device, send_buffer, 4); - w25qxx_wait_busy(device); // wait erase done. - - erase_size += 4096; - offset += 4096; - } - send_buffer[0] = CMD_WRDI; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - - w25qxx_unlock(device); - return RT_EOK; -} - -const static struct rt_mtd_nor_driver_ops w25qxx_mtd_ops = -{ - w25qxx_read_id, - w25qxx_read, - w25qxx_write, - w25qxx_erase_block, -}; - -rt_err_t w25qxx_mtd_init(const char *mtd_name,const char * spi_device_name) -{ - rt_err_t result = RT_EOK; - rt_uint32_t id; - rt_uint8_t send_buffer[3]; - - struct rt_spi_device* rt_spi_device; - struct spi_flash_mtd* mtd = (struct spi_flash_mtd *)rt_malloc(sizeof(struct spi_flash_mtd)); - - RT_ASSERT(mtd != RT_NULL); - - /* initialize mutex */ - if (rt_mutex_init(&mtd->lock, mtd_name, RT_IPC_FLAG_FIFO) != RT_EOK) - { - FLASH_TRACE("init mtd lock mutex failed\n"); - result = -RT_ENOSYS; - - goto _error_exit; - } - - rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); - if(rt_spi_device == RT_NULL) - { - FLASH_TRACE("spi device %s not found!\r\n", spi_device_name); - result = -RT_ENOSYS; - - goto _error_exit; - } - mtd->rt_spi_device = rt_spi_device; - /* config spi */ - { - struct rt_spi_configuration cfg; - cfg.data_width = 8; - cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */ - cfg.max_hz = 20 * 1000 * 1000; /* 20 */ - rt_spi_configure(rt_spi_device, &cfg); - } - - /* Init Flash device */ - { - w25qxx_lock(&mtd->mtd_device); - - send_buffer[0] = CMD_WREN; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - w25qxx_wait_busy(&mtd->mtd_device); - - send_buffer[0] = CMD_WRSR; - send_buffer[1] = 0; - send_buffer[2] = 0; - rt_spi_send(mtd->rt_spi_device, send_buffer, 3); - w25qxx_wait_busy(&mtd->mtd_device); - - w25qxx_unlock(&mtd->mtd_device); - } - - id = w25qxx_read_id(&mtd->mtd_device); - - mtd->mtd_device.block_size = 4096; - mtd->mtd_device.block_start = 0; - switch(id & 0xFFFF) - { - case MTC_W25Q80_BV: /* W25Q80BV */ - mtd->mtd_device.block_end = 256; - break; - case MTC_W25Q16_BV_CL_CV: /* W25Q16BV W25Q16CL W25Q16CV */ - case MTC_W25Q16_DW: /* W25Q16DW */ - mtd->mtd_device.block_end = 512; - break; - case MTC_W25Q32_BV: /* W25Q32BV */ - case MTC_W25Q32_DW: /* W25Q32DW */ - mtd->mtd_device.block_end = 1024; - break; - case MTC_W25Q64_BV_CV: /* W25Q64BV W25Q64CV */ - mtd->mtd_device.block_end = 2048; - break; - case MTC_W25Q128_BV: /* W25Q128BV */ - mtd->mtd_device.block_end = 4086; - break; - } - mtd->mtd_device.ops = &w25qxx_mtd_ops; - rt_mtd_nor_register_device(mtd_name,&mtd->mtd_device); - - return RT_EOK; - -_error_exit: - if(mtd != RT_NULL) - rt_free(mtd); - return result; -} diff --git a/components/drivers/spi/spi_flash_w25qxx_mtd.h b/components/drivers/spi/spi_flash_w25qxx_mtd.h deleted file mode 100644 index 28f6828ffb..0000000000 --- a/components/drivers/spi/spi_flash_w25qxx_mtd.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - * 2012-08-23 aozima add flash lock. - * 2017-02-11 urey add mtd fucntion - */ - -#ifndef SPI_FLASH_W25QXX_H_INCLUDED -#define SPI_FLASH_W25QXX_H_INCLUDED - -#include <rtthread.h> - -extern rt_err_t w25qxx_mtd_init(const char *mtd_name,const char * spi_device_name); - -#endif // SPI_FLASH_W25QXX_H_INCLUDED diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c index 16fb82dbfb..b682c351ad 100644 --- a/components/drivers/src/pipe.c +++ b/components/drivers/src/pipe.c @@ -425,7 +425,7 @@ rt_pipe_t *rt_pipe_create(const char *name, int bufsz) rt_pipe_t *pipe; rt_device_t dev; - pipe = rt_malloc(sizeof(rt_pipe_t)); + pipe = (rt_pipe_t *)rt_malloc(sizeof(rt_pipe_t)); if (pipe == RT_NULL) return RT_NULL; rt_memset(pipe, 0, sizeof(rt_pipe_t)); diff --git a/components/drivers/src/ringblk_buf.c b/components/drivers/src/ringblk_buf.c index 74ced674fe..86e812cd4c 100644 --- a/components/drivers/src/ringblk_buf.c +++ b/components/drivers/src/ringblk_buf.c @@ -134,16 +134,16 @@ 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 = NULL; + rt_rbb_blk_t head, tail, new_rbb = NULL; RT_ASSERT(rbb); RT_ASSERT(blk_size < (1L << 24)); level = rt_hw_interrupt_disable(); - new = find_empty_blk_in_set(rbb); + new_rbb = find_empty_blk_in_set(rbb); - if (rt_slist_len(&rbb->blk_list) < rbb->blk_max_num && new) + if (rt_slist_len(&rbb->blk_list) < rbb->blk_max_num && new_rbb) { if (rt_slist_len(&rbb->blk_list) > 0) { @@ -163,22 +163,22 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size) if (empty1 >= blk_size) { - rt_slist_append(&rbb->blk_list, &new->list); - new->status = RT_RBB_BLK_INITED; - new->buf = tail->buf + tail->size; - new->size = blk_size; + rt_slist_append(&rbb->blk_list, &new_rbb->list); + new_rbb->status = RT_RBB_BLK_INITED; + new_rbb->buf = tail->buf + tail->size; + new_rbb->size = blk_size; } else if (empty2 >= blk_size) { - rt_slist_append(&rbb->blk_list, &new->list); - new->status = RT_RBB_BLK_INITED; - new->buf = rbb->buf; - new->size = blk_size; + rt_slist_append(&rbb->blk_list, &new_rbb->list); + new_rbb->status = RT_RBB_BLK_INITED; + new_rbb->buf = rbb->buf; + new_rbb->size = blk_size; } else { /* no space */ - new = NULL; + new_rbb = NULL; } } else @@ -194,35 +194,35 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size) if (empty1 >= blk_size) { - rt_slist_append(&rbb->blk_list, &new->list); - new->status = RT_RBB_BLK_INITED; - new->buf = tail->buf + tail->size; - new->size = blk_size; + rt_slist_append(&rbb->blk_list, &new_rbb->list); + new_rbb->status = RT_RBB_BLK_INITED; + new_rbb->buf = tail->buf + tail->size; + new_rbb->size = blk_size; } else { /* no space */ - new = NULL; + new_rbb = NULL; } } } else { /* the list is empty */ - rt_slist_append(&rbb->blk_list, &new->list); - new->status = RT_RBB_BLK_INITED; - new->buf = rbb->buf; - new->size = blk_size; + rt_slist_append(&rbb->blk_list, &new_rbb->list); + new_rbb->status = RT_RBB_BLK_INITED; + new_rbb->buf = rbb->buf; + new_rbb->size = blk_size; } } else { - new = NULL; + new_rbb = NULL; } rt_hw_interrupt_enable(level); - return new; + return new_rbb; } RTM_EXPORT(rt_rbb_blk_alloc); diff --git a/components/drivers/src/ringbuffer.c b/components/drivers/src/ringbuffer.c index 0acdbbd38c..c6a491a7cc 100644 --- a/components/drivers/src/ringbuffer.c +++ b/components/drivers/src/ringbuffer.c @@ -332,11 +332,11 @@ struct rt_ringbuffer* rt_ringbuffer_create(rt_uint16_t size) size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE); - rb = rt_malloc(sizeof(struct rt_ringbuffer)); + rb = (struct rt_ringbuffer *)rt_malloc(sizeof(struct rt_ringbuffer)); if (rb == RT_NULL) goto exit; - pool = rt_malloc(size); + pool = (rt_uint8_t *)rt_malloc(size); if (pool == RT_NULL) { rt_free(rb); diff --git a/components/drivers/src/workqueue.c b/components/drivers/src/workqueue.c index 7bf4bd81a7..2e0280df3a 100644 --- a/components/drivers/src/workqueue.c +++ b/components/drivers/src/workqueue.c @@ -71,6 +71,7 @@ static void _workqueue_thread_entry(void *parameter) rt_list_remove(&(work->list)); queue->work_current = work; work->flags &= ~RT_WORK_STATE_PENDING; + work->workqueue = RT_NULL; rt_hw_interrupt_enable(level); /* do work */ @@ -141,7 +142,7 @@ static rt_err_t _workqueue_cancel_work(struct rt_workqueue *queue, struct rt_wor return RT_EOK; } -static rt_err_t _workqueue_cancel_delayed_work(struct rt_delayed_work *work) +static rt_err_t _workqueue_cancel_delayed_work(struct rt_work *work) { rt_base_t level; int ret = RT_EOK; @@ -152,10 +153,10 @@ static rt_err_t _workqueue_cancel_delayed_work(struct rt_delayed_work *work) goto __exit; } - if (work->work.flags & RT_WORK_STATE_PENDING) + if (work->flags & RT_WORK_STATE_PENDING) { /* Remove from the queue if already submitted */ - ret = rt_workqueue_cancel_work(work->workqueue, &(work->work)); + ret = _workqueue_cancel_work(work->workqueue, work); if (ret) { goto __exit; @@ -163,12 +164,12 @@ static rt_err_t _workqueue_cancel_delayed_work(struct rt_delayed_work *work) } else { - if (work->work.flags & RT_WORK_STATE_SUBMITTING) + if (work->flags & RT_WORK_STATE_SUBMITTING) { level = rt_hw_interrupt_disable(); rt_timer_stop(&(work->timer)); rt_timer_detach(&(work->timer)); - work->work.flags &= ~RT_WORK_STATE_SUBMITTING; + work->flags &= ~RT_WORK_STATE_SUBMITTING; rt_hw_interrupt_enable(level); } } @@ -176,7 +177,7 @@ static rt_err_t _workqueue_cancel_delayed_work(struct rt_delayed_work *work) level = rt_hw_interrupt_disable(); /* Detach from workqueue */ work->workqueue = RT_NULL; - work->work.flags &= ~(RT_WORK_STATE_PENDING); + work->flags &= ~(RT_WORK_STATE_PENDING); rt_hw_interrupt_enable(level); __exit: @@ -184,11 +185,10 @@ __exit: } static rt_err_t _workqueue_submit_delayed_work(struct rt_workqueue *queue, - struct rt_delayed_work *work, rt_tick_t ticks) + struct rt_work *work, rt_tick_t ticks) { rt_base_t level; - int ret = RT_EOK; - + rt_err_t ret = RT_EOK; /* Work cannot be active in multiple queues */ if (work->workqueue && work->workqueue != queue) @@ -215,13 +215,13 @@ static rt_err_t _workqueue_submit_delayed_work(struct rt_workqueue *queue, if (!ticks) { /* Submit work if no ticks is 0 */ - _workqueue_submit_work(work->workqueue, &(work->work)); + ret = _workqueue_submit_work(work->workqueue, work); } else { level = rt_hw_interrupt_disable(); /* Add timeout */ - work->work.flags |= RT_WORK_STATE_SUBMITTING; + work->flags |= RT_WORK_STATE_SUBMITTING; rt_timer_init(&(work->timer), "work", _delayed_work_timeout_handler, work, ticks, RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER); rt_hw_interrupt_enable(level); @@ -234,16 +234,17 @@ __exit: static void _delayed_work_timeout_handler(void *parameter) { - struct rt_delayed_work *delayed_work; + struct rt_work *delayed_work; rt_base_t level; - delayed_work = (struct rt_delayed_work *)parameter; + delayed_work = (struct rt_work *)parameter; level = rt_hw_interrupt_disable(); rt_timer_stop(&(delayed_work->timer)); rt_timer_detach(&(delayed_work->timer)); - delayed_work->work.flags &= ~RT_WORK_STATE_SUBMITTING; + delayed_work->flags &= ~RT_WORK_STATE_SUBMITTING; + delayed_work->type &= ~RT_WORK_TYPE_DELAYED; rt_hw_interrupt_enable(level); - _workqueue_submit_work(delayed_work->workqueue, &(delayed_work->work)); + _workqueue_submit_work(delayed_work->workqueue, delayed_work); } struct rt_workqueue *rt_workqueue_create(const char *name, rt_uint16_t stack_size, rt_uint8_t priority) @@ -295,9 +296,14 @@ rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *wo RT_ASSERT(queue != RT_NULL); RT_ASSERT(work != RT_NULL); + if (time > 0) + { + work->type |= RT_WORK_TYPE_DELAYED; + } + if (work->type & RT_WORK_TYPE_DELAYED) { - return _workqueue_submit_delayed_work(queue, (struct rt_delayed_work *)work, time); + return _workqueue_submit_delayed_work(queue, work, time); } else { @@ -341,7 +347,7 @@ rt_err_t rt_workqueue_cancel_work(struct rt_workqueue *queue, struct rt_work *wo if (work->type & RT_WORK_TYPE_DELAYED) { - return _workqueue_cancel_delayed_work((struct rt_delayed_work *)work); + return _workqueue_cancel_delayed_work(work); } else { @@ -391,8 +397,7 @@ rt_err_t rt_workqueue_cancel_all_work(struct rt_workqueue *queue) 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); - work->work.type = RT_WORK_TYPE_DELAYED; + rt_work_init(&work->work, work_func, work_data); } #ifdef RT_USING_SYSTEM_WORKQUEUE @@ -408,8 +413,11 @@ rt_err_t rt_work_cancel(struct rt_work *work) return rt_workqueue_cancel_work(sys_workq, work); } -static int rt_work_sys_workqueue_init(void) +int rt_work_sys_workqueue_init(void) { + if (sys_workq != RT_NULL) + return 0; + sys_workq = rt_workqueue_create("sys_work", RT_SYSTEM_WORKQUEUE_STACKSIZE, RT_SYSTEM_WORKQUEUE_PRIORITY); diff --git a/components/drivers/touch/SConscript b/components/drivers/touch/SConscript new file mode 100644 index 0000000000..f370b2aba6 --- /dev/null +++ b/components/drivers/touch/SConscript @@ -0,0 +1,11 @@ +# SConscript for touch framework + +from building import * + +cwd = GetCurrentDir() +src = ['touch.c'] +CPPPATH = [cwd, cwd + '/../include'] + +group = DefineGroup('Touch', src, depend = ['RT_USING_TOUCH', 'RT_USING_DEVICE'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/touch/touch.c b/components/drivers/touch/touch.c new file mode 100644 index 0000000000..80ba6378bb --- /dev/null +++ b/components/drivers/touch/touch.c @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-05-20 tyustli the first version + */ + +#include "touch.h" +#include <string.h> + +#define DBG_TAG "touch" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +/* ISR for touch interrupt */ +static void irq_callback(void *args) +{ + rt_touch_t touch; + + touch = (rt_touch_t)args; + + if (touch->parent.rx_indicate == RT_NULL) + { + return; + } + + if (touch->irq_handle != RT_NULL) + { + touch->irq_handle(touch); + } + + touch->parent.rx_indicate(&touch->parent, 1); +} + +/* touch interrupt initialization function */ +static rt_err_t rt_touch_irq_init(rt_touch_t touch) +{ + if (touch->config.irq_pin.pin == RT_PIN_NONE) + { + return -RT_EINVAL; + } + + rt_pin_mode(touch->config.irq_pin.pin, touch->config.irq_pin.mode); + + if (touch->config.irq_pin.mode == PIN_MODE_INPUT_PULLDOWN) + { + rt_pin_attach_irq(touch->config.irq_pin.pin, PIN_IRQ_MODE_RISING, irq_callback, (void *)touch); + } + else if (touch->config.irq_pin.mode == PIN_MODE_INPUT_PULLUP) + { + rt_pin_attach_irq(touch->config.irq_pin.pin, PIN_IRQ_MODE_FALLING, irq_callback, (void *)touch); + } + else if (touch->config.irq_pin.mode == PIN_MODE_INPUT) + { + rt_pin_attach_irq(touch->config.irq_pin.pin, PIN_IRQ_MODE_RISING_FALLING, irq_callback, (void *)touch); + } + + rt_pin_irq_enable(touch->config.irq_pin.pin, PIN_IRQ_ENABLE); + + return RT_EOK; +} + +/* touch interrupt enable */ +static void rt_touch_irq_enable(rt_touch_t touch) +{ + if (touch->config.irq_pin.pin != RT_PIN_NONE) + { + rt_pin_irq_enable(touch->config.irq_pin.pin, RT_TRUE); + } +} + +/* touch interrupt disable */ +static void rt_touch_irq_disable(rt_touch_t touch) +{ + if (touch->config.irq_pin.pin != RT_PIN_NONE) + { + rt_pin_irq_enable(touch->config.irq_pin.pin, RT_FALSE); + } +} + +static rt_err_t rt_touch_open(rt_device_t dev, rt_uint16_t oflag) +{ + rt_touch_t touch; + RT_ASSERT(dev != RT_NULL); + touch = (rt_touch_t)dev; + + if (oflag & RT_DEVICE_FLAG_INT_RX && dev->flag & RT_DEVICE_FLAG_INT_RX) + { + /* Initialization touch interrupt */ + rt_touch_irq_init(touch); + } + + return RT_EOK; +} + +static rt_err_t rt_touch_close(rt_device_t dev) +{ + rt_touch_t touch; + RT_ASSERT(dev != RT_NULL); + touch = (rt_touch_t)dev; + + /* touch disable interrupt */ + rt_touch_irq_disable(touch); + + return RT_EOK; +} + +static rt_size_t rt_touch_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t len) +{ + rt_touch_t touch; + rt_size_t result = 0; + RT_ASSERT(dev != RT_NULL); + touch = (rt_touch_t)dev; + + if (buf == NULL || len == 0) + { + return 0; + } + + result = touch->ops->touch_readpoint(touch, buf, len); + + return result; +} + +static rt_err_t rt_touch_control(rt_device_t dev, int cmd, void *args) +{ + rt_touch_t touch; + rt_err_t result = RT_EOK; + RT_ASSERT(dev != RT_NULL); + touch = (rt_touch_t)dev; + + 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); + + if (result == RT_EOK) + { + rt_uint16_t mode; + mode = *(rt_uint16_t*)args; + if (mode == RT_DEVICE_FLAG_INT_RX) + { + rt_touch_irq_enable(touch); /* enable interrupt */ + } + } + + break; + case RT_TOUCH_CTRL_SET_X_RANGE: + result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_SET_X_RANGE, args); + + if (result == RT_EOK) + { + touch->info.range_x = *(rt_int32_t *)args; + LOG_D("set x coordinate range :%d\n", touch->info.range_x); + } + + break; + case RT_TOUCH_CTRL_SET_Y_RANGE: + result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_SET_Y_RANGE, args); + + if (result == RT_EOK) + { + touch->info.range_y = *(rt_uint32_t *)args; + LOG_D("set y coordinate range :%d \n", touch->info.range_x); + } + + break; + case RT_TOUCH_CTRL_DISABLE_INT: + rt_touch_irq_disable(touch); + break; + case RT_TOUCH_CTRL_ENABLE_INT: + rt_touch_irq_enable(touch); + break; + default: + return -RT_ERROR; + } + + return result; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops rt_touch_ops = +{ + RT_NULL, + rt_touch_open, + rt_touch_close, + rt_touch_read, + RT_NULL, + rt_touch_control +}; +#endif + +/* + * touch register + */ +int rt_hw_touch_register(rt_touch_t touch, + const char *name, + rt_uint32_t flag, + void *data) +{ + rt_int8_t result; + rt_device_t device; + RT_ASSERT(touch != RT_NULL); + + device = &touch->parent; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &rt_touch_ops; +#else + device->init = RT_NULL; + device->open = rt_touch_open; + device->close = rt_touch_close; + device->read = rt_touch_read; + device->write = RT_NULL; + device->control = rt_touch_control; +#endif + device->type = RT_Device_Class_Touch; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + device->user_data = data; + + result = rt_device_register(device, name, flag | RT_DEVICE_FLAG_STANDALONE); + + if (result != RT_EOK) + { + LOG_E("rt_touch register err code: %d", result); + return result; + } + + LOG_I("rt_touch init success"); + + return RT_EOK; +} diff --git a/components/drivers/touch/touch.h b/components/drivers/touch/touch.h new file mode 100644 index 0000000000..6b7288a5a0 --- /dev/null +++ b/components/drivers/touch/touch.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-05-20 tyustli the first version + */ + +#ifndef __TOUCH_H__ +#define __TOUCH_H__ + +#include <rtthread.h> +#include <rtdevice.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef RT_USING_RTC +#define rt_touch_get_ts() time(RT_NULL) /* API for the touch to get the timestamp */ +#else +#define rt_touch_get_ts() rt_tick_get() /* API for the touch to get the timestamp */ +#endif + +#define RT_PIN_NONE 0xFFFF /* RT PIN NONE */ + +/* Touch vendor types */ +#define RT_TOUCH_VENDOR_UNKNOWN (0) /* unknown */ +#define RT_TOUCH_VENDOR_GT (1) /* GTxx series */ +#define RT_TOUCH_VENDOR_FT (2) /* FTxx series */ + +/* Touch ic type*/ +#define RT_TOUCH_TYPE_NONE (0) /* touch ic none */ +#define RT_TOUCH_TYPE_CAPACITANCE (1) /* capacitance ic */ +#define RT_TOUCH_TYPE_RESISTANCE (2) /* resistance ic */ + +/* Touch control cmd types */ +#define RT_TOUCH_CTRL_GET_ID (0) /* Get device id */ +#define RT_TOUCH_CTRL_GET_INFO (1) /* Get touch info */ +#define RT_TOUCH_CTRL_SET_MODE (2) /* Set touch's work mode. ex. RT_TOUCH_MODE_POLLING,RT_TOUCH_MODE_INT */ +#define RT_TOUCH_CTRL_SET_X_RANGE (3) /* Set x coordinate range */ +#define RT_TOUCH_CTRL_SET_Y_RANGE (4) /* Set y coordinate range */ +#define RT_TOUCH_CTRL_SET_X_TO_Y (5) /* Set X Y coordinate exchange */ +#define RT_TOUCH_CTRL_DISABLE_INT (6) /* Disable interrupt */ +#define RT_TOUCH_CTRL_ENABLE_INT (7) /* Enable interrupt */ + +/* Touch event */ +#define RT_TOUCH_EVENT_NONE (0) /* Touch none */ +#define RT_TOUCH_EVENT_UP (1) /* Touch up event */ +#define RT_TOUCH_EVENT_DOWN (2) /* Touch down event */ +#define RT_TOUCH_EVENT_MOVE (3) /* Touch move event */ + +struct rt_touch_info +{ + rt_uint8_t type; /* The touch type */ + rt_uint8_t vendor; /* Vendor of touchs */ + rt_uint8_t point_num; /* Support point num */ + rt_int32_t range_x; /* X coordinate range */ + rt_int32_t range_y; /* Y coordinate range */ +}; + +struct rt_touch_config +{ + struct rt_device_pin_mode irq_pin; /* Interrupt pin, The purpose of this pin is to notification read data */ + char *dev_name; /* The name of the communication device */ + void *user_data; +}; + +typedef struct rt_touch_device *rt_touch_t; +struct rt_touch_device +{ + struct rt_device parent; /* The standard device */ + struct rt_touch_info info; /* The touch info data */ + struct rt_touch_config config; /* The touch config data */ + + const struct rt_touch_ops *ops; /* The touch ops */ + rt_err_t (*irq_handle)(rt_touch_t touch); /* Called when an interrupt is generated, registered by the driver */ +}; + +struct rt_touch_data +{ + rt_uint8_t event; /* The touch event of the data */ + rt_uint8_t track_id; /* Track id of point */ + rt_uint8_t width; /* Point of width */ + rt_uint16_t x_coordinate; /* Point of x coordinate */ + rt_uint16_t y_coordinate; /* Point of y coordinate */ + rt_tick_t timestamp; /* The timestamp when the data was received */ +}; + +struct rt_touch_ops +{ + rt_size_t (*touch_readpoint)(struct rt_touch_device *touch, void *buf, rt_size_t touch_num); + rt_err_t (*touch_control)(struct rt_touch_device *touch, int cmd, void *arg); +}; + +int rt_hw_touch_register(rt_touch_t touch, + const char *name, + rt_uint32_t flag, + void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* __TOUCH_H__ */ diff --git a/components/drivers/usb/usbdevice/SConscript b/components/drivers/usb/usbdevice/SConscript index be0b0c7b50..010b9837a4 100644 --- a/components/drivers/usb/usbdevice/SConscript +++ b/components/drivers/usb/usbdevice/SConscript @@ -24,6 +24,12 @@ if GetDepend('RT_USB_DEVICE_RNDIS'): if GetDepend('RT_USB_DEVICE_WINUSB'): src += Glob('class/winusb.c') + +if GetDepend('RT_USB_DEVICE_AUDIO_MIC'): + src += Glob('class/audio_mic.c') + +if GetDepend('RT_USB_DEVICE_AUDIO_SPEAKER'): + src += Glob('class/audio_speaker.c') CPPPATH = [cwd] diff --git a/components/drivers/usb/usbdevice/class/audio.h b/components/drivers/usb/usbdevice/class/audio.h new file mode 100644 index 0000000000..4bb8994b47 --- /dev/null +++ b/components/drivers/usb/usbdevice/class/audio.h @@ -0,0 +1,676 @@ +/* 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 new file mode 100644 index 0000000000..4ac85711ad --- /dev/null +++ b/components/drivers/usb/usbdevice/class/audio_mic.c @@ -0,0 +1,577 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-09-07 flybreak the first version + */ + +#include <rthw.h> +#include <rtthread.h> +#include <rtservice.h> +#include <rtdevice.h> + +#include "drivers/usb_device.h" +#include "audio.h" + +#define DBG_TAG "usbd.audio.mic" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +#define RECORD_SAMPLERATE 16000 +#define RECORD_CHANNEL 1 +#define RESOLUTION_BITS 16 + +#define RESOLUTION_BYTE (RESOLUTION_BITS / 8) +#define RECORD_PER_MS_SZ ((RECORD_SAMPLERATE * RECORD_CHANNEL * RESOLUTION_BYTE) / 1000) +#define RECORD_BUFFER_SZ (RECORD_PER_MS_SZ * 20) /* 20ms */ + +#if defined(RT_USBD_MIC_DEVICE_NAME) + #define MIC_DEVICE_NAME RT_USBD_MIC_DEVICE_NAME +#else + #define MIC_DEVICE_NAME "mic0" +#endif + +#define EVENT_RECORD_START (1 << 0) +#define EVENT_RECORD_STOP (1 << 1) +#define EVENT_RECORD_DATA (1 << 2) + +/* + * uac mic descriptor define + */ + +#define UAC_CS_INTERFACE 0x24 +#define UAC_CS_ENDPOINT 0x25 + +#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 +{ +#ifdef RT_USB_DEVICE_COMPOSITE + 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; +#if UAC_USE_FEATURE_UNIT + DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(UAC_CH_NUM) 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 uendpoint_descriptor ep_desc; + struct uac_iso_endpoint_descriptor as_ep_desc; +}; + +/* + * uac mic device type + */ + +struct uac_audio_mic +{ + rt_device_t dev; + rt_event_t event; + rt_uint8_t open_count; + + rt_uint8_t *buffer; + rt_uint32_t buffer_index; + + uep_t ep; +}; +static struct uac_audio_mic mic; + +ALIGN(4) +static struct udevice_descriptor dev_desc = +{ + USB_DESC_LENGTH_DEVICE, //bLength; + USB_DESC_TYPE_DEVICE, //type; + USB_BCD_VERSION, //bcdUSB; + USB_CLASS_DEVICE, //bDeviceClass; + 0x00, //bDeviceSubClass; + 0x00, //bDeviceProtocol; + UAC_MAX_PACKET_SIZE, //bMaxPacketSize0; + _VENDOR_ID, //idVendor; + _PRODUCT_ID, //idProduct; + USB_BCD_DEVICE, //bcdDevice; + USB_STRING_MANU_INDEX, //iManufacturer; + USB_STRING_PRODUCT_INDEX, //iProduct; + USB_STRING_SERIAL_INDEX, //iSerialNumber;Unused. + USB_DYNAMIC, //bNumConfigurations; +}; + +//FS and HS needed +ALIGN(4) +static struct usb_qualifier_descriptor dev_qualifier = +{ + sizeof(dev_qualifier), //bLength + USB_DESC_TYPE_DEVICEQUALIFIER, //bDescriptorType + 0x0200, //bcdUSB + USB_CLASS_AUDIO, //bDeviceClass + 0x00, //bDeviceSubClass + 0x00, //bDeviceProtocol + 64, //bMaxPacketSize0 + 0x01, //bNumConfigurations + 0, +}; + +ALIGN(4) +const static char *_ustring[] = +{ + "Language", + "RT-Thread Team.", + "Microphone", + "32021919830108", + "Configuration", + "Interface", +}; + +ALIGN(4) +static struct uac_ac_descriptor ac_desc = +{ +#ifdef RT_USB_DEVICE_COMPOSITE + /* Interface Association Descriptor */ + { + USB_DESC_LENGTH_IAD, + USB_DESC_TYPE_IAD, + USB_DYNAMIC, + 0x02, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, + }, +#endif + /* Interface Descriptor */ + { + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x00, + 0x00, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOCONTROL, + 0x00, + 0x00, + }, + /* Header Descriptor */ + { + UAC_DT_AC_HEADER_SIZE(UAC_INTR_NUM), + UAC_CS_INTERFACE, + UAC_HEADER, + 0x0100, /* Version: 1.00 */ + 0x001E, /* Total length: 30 */ + 0x01, /* Total number of interfaces: 1 */ + {0x01}, /* Interface number: 1 */ + }, + /* Input Terminal Descriptor */ + { + UAC_DT_INPUT_TERMINAL_SIZE, + UAC_CS_INTERFACE, + UAC_INPUT_TERMINAL, + 0x01, /* Terminal ID: 1 */ + 0x0201, /* Terminal Type: Microphone (0x0201) */ + 0x00, /* Assoc Terminal: 0 */ + 0x01, /* Number Channels: 1 */ + 0x0000, /* Channel Config: 0x0000 */ + 0x00, /* Channel Names: 0 */ + 0x00, /* Terminal: 0 */ + }, + /* Output Terminal Descriptor */ + { + UAC_DT_OUTPUT_TERMINAL_SIZE, + UAC_CS_INTERFACE, + UAC_OUTPUT_TERMINAL, + 0x02, /* Terminal ID: 2 */ + 0x0101, /* Terminal Type: USB Streaming (0x0101) */ + 0x00, /* Assoc Terminal: 0 */ + 0x01, /* Source ID: 1 */ + 0x00, /* Terminal: 0 */ + }, +#if UAC_USE_FEATURE_UNIT + /* Feature unit Descriptor */ + { + UAC_DT_FEATURE_UNIT_SIZE(UAC_CH_NUM), + UAC_CS_INTERFACE, + UAC_FEATURE_UNIT, + 0x02, + 0x0101, + 0x00, + 0x01, + }, +#endif +}; + +ALIGN(4) +static struct uinterface_descriptor as_desc0 = +{ + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x00, + 0x00, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, +}; + +ALIGN(4) +static struct uac_as_descriptor as_desc = +{ + /* Interface Descriptor */ + { + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x01, + 0x01, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, + }, + /* General AS Descriptor */ + { + UAC_DT_AS_HEADER_SIZE, + UAC_CS_INTERFACE, + UAC_AS_GENERAL, + 0x02, /* Terminal ID: 2 */ + 0x01, /* Interface delay in frames: 1 */ + UAC_FORMAT_TYPE_I_PCM, + }, + /* Format type i Descriptor */ + { + UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(UAC_FORMAT_NUM), + UAC_CS_INTERFACE, + UAC_FORMAT_TYPE, + UAC_FORMAT_TYPE_I, + UAC_CHANNEL_NUM, + 2, /* Subframe Size: 2 */ + RESOLUTION_BITS, + 0x01, /* Samples Frequence Type: 1 */ + {0}, /* Samples Frequence */ + }, + /* Endpoint Descriptor */ + { + USB_DESC_LENGTH_ENDPOINT, + USB_DESC_TYPE_ENDPOINT, + USB_DYNAMIC | USB_DIR_IN, + USB_EP_ATTR_ISOC, + UAC_EP_MAX_PACKET_SIZE, + 0x01, + }, + /* AS Endpoint Descriptor */ + { + UAC_ISO_ENDPOINT_DESC_SIZE, + UAC_CS_ENDPOINT, + UAC_MS_GENERAL, + }, +}; + +void mic_entry(void *parameter) +{ + struct rt_audio_caps caps = {0}; + rt_uint32_t e, index; + + mic.buffer = rt_malloc(RECORD_BUFFER_SZ); + if (mic.buffer == RT_NULL) + { + LOG_E("malloc failed"); + goto __exit; + } + + mic.dev = rt_device_find(MIC_DEVICE_NAME); + if (mic.dev == RT_NULL) + { + LOG_E("can't find device:%s", MIC_DEVICE_NAME); + goto __exit; + } + + while (1) + { + if (rt_event_recv(mic.event, EVENT_RECORD_START | EVENT_RECORD_STOP, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + 1000, &e) != RT_EOK) + { + continue; + } + if (mic.open_count == 0) + { + continue; + } + LOG_D("record start"); + + rt_device_open(mic.dev, RT_DEVICE_OFLAG_RDONLY); + + caps.main_type = AUDIO_TYPE_INPUT; + caps.sub_type = AUDIO_DSP_PARAM; + caps.udata.config.samplerate = RECORD_SAMPLERATE; + caps.udata.config.channels = RECORD_CHANNEL; + caps.udata.config.samplebits = RESOLUTION_BITS; + rt_device_control(mic.dev, AUDIO_CTL_CONFIGURE, &caps); + + while (1) + { + if (rt_event_recv(mic.event, EVENT_RECORD_DATA | EVENT_RECORD_STOP, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + 1000, &e) != RT_EOK) + { + if (mic.open_count > 0) + continue; + else + break; + } + if (e & EVENT_RECORD_DATA) + { + index = (mic.buffer_index >= RECORD_BUFFER_SZ / 2) ? 0 : (RECORD_BUFFER_SZ / 2); + rt_device_read(mic.dev, 0, mic.buffer + index, RECORD_BUFFER_SZ / 2); + } + else if (e & EVENT_RECORD_STOP) + { + break; + } + } + LOG_D("record stop"); + rt_device_close(mic.dev); + } + +__exit: + if (mic.buffer) + rt_free(mic.buffer); +} + +static rt_err_t _record_start(ufunction_t func) +{ + mic.ep->request.buffer = RT_NULL; + mic.ep->request.size = UAC_EP_MAX_PACKET_SIZE; + mic.ep->request.req_type = UIO_REQUEST_WRITE; + rt_usbd_io_request(func->device, mic.ep, &mic.ep->request); + + mic.open_count ++; + rt_event_send(mic.event, EVENT_RECORD_START); + return 0; +} + +static rt_err_t _record_stop(ufunction_t func) +{ + mic.open_count --; + rt_event_send(mic.event, EVENT_RECORD_STOP); + return 0; +} + +static rt_err_t _ep_data_in_handler(ufunction_t func, rt_size_t size) +{ + RT_ASSERT(func != RT_NULL); + LOG_D("_ep_data_in_handler"); + + mic.ep->request.buffer = mic.buffer + mic.buffer_index; + mic.ep->request.size = UAC_EP_MAX_PACKET_SIZE; + mic.ep->request.req_type = UIO_REQUEST_WRITE; + rt_usbd_io_request(func->device, mic.ep, &mic.ep->request); + + mic.buffer_index += UAC_EP_MAX_PACKET_SIZE; + if (mic.buffer_index >= RECORD_BUFFER_SZ) + { + mic.buffer_index = 0; + rt_event_send(mic.event, EVENT_RECORD_DATA); + } + else if (mic.buffer_index == RECORD_BUFFER_SZ / 2) + { + rt_event_send(mic.event, EVENT_RECORD_DATA); + } + + return RT_EOK; +} + +static rt_err_t _interface_as_handler(ufunction_t func, ureq_t setup) +{ + RT_ASSERT(func != RT_NULL); + RT_ASSERT(func->device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + LOG_D("_interface_as_handler"); + + if ((setup->request_type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD) + { + switch (setup->bRequest) + { + case USB_REQ_GET_INTERFACE: + break; + case USB_REQ_SET_INTERFACE: + LOG_D("set interface handler"); + if (setup->wValue == 1) + { + _record_start(func); + } + else if (setup->wValue == 0) + { + _record_stop(func); + } + break; + default: + LOG_D("unknown uac request 0x%x", setup->bRequest); + return -RT_ERROR; + } + } + + return RT_EOK; +} + +static rt_err_t _function_enable(ufunction_t func) +{ + RT_ASSERT(func != RT_NULL); + + LOG_D("uac function enable"); + + return RT_EOK; +} + +static rt_err_t _function_disable(ufunction_t func) +{ + RT_ASSERT(func != RT_NULL); + + LOG_D("uac function disable"); + _record_stop(func); + return RT_EOK; +} + +static struct ufunction_ops ops = +{ + _function_enable, + _function_disable, + RT_NULL, +}; +/** + * This function will configure uac descriptor. + * + * @param comm the communication interface number. + * @param data the data interface number. + * + * @return RT_EOK on successful. + */ +static rt_err_t _uac_descriptor_config(struct uac_ac_descriptor *ac, + rt_uint8_t cintf_nr, struct uac_as_descriptor *as, rt_uint8_t sintf_nr) +{ + ac->hdr_desc.baInterfaceNr[0] = sintf_nr; +#ifdef RT_USB_DEVICE_COMPOSITE + ac->iad_desc.bFirstInterface = cintf_nr; +#endif + + return RT_EOK; +} + +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; + return RT_EOK; +} + +/** + * This function will create a uac function instance. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +ufunction_t rt_usbd_function_uac_mic_create(udevice_t device) +{ + ufunction_t func; + uintf_t intf_ac, intf_as; + ualtsetting_t setting_as0; + ualtsetting_t setting_ac, setting_as; + struct uac_as_descriptor *as_desc_t; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + + /* set usb device string description */ + rt_usbd_device_set_string(device, _ustring); + + /* create a uac function */ + func = rt_usbd_function_new(device, &dev_desc, &ops); + //not support HS + //rt_usbd_device_set_qualifier(device, &dev_qualifier); + + /* create interface */ + intf_ac = rt_usbd_interface_new(device, RT_NULL); + intf_as = rt_usbd_interface_new(device, _interface_as_handler); + + /* create alternate setting */ + setting_ac = rt_usbd_altsetting_new(sizeof(struct uac_ac_descriptor)); + setting_as0 = rt_usbd_altsetting_new(sizeof(struct uinterface_descriptor)); + setting_as = rt_usbd_altsetting_new(sizeof(struct uac_as_descriptor)); + /* config desc in alternate setting */ + rt_usbd_altsetting_config_descriptor(setting_ac, &ac_desc, + (rt_off_t) & ((struct uac_ac_descriptor *)0)->intf_desc); + rt_usbd_altsetting_config_descriptor(setting_as0, &as_desc0, 0); + rt_usbd_altsetting_config_descriptor(setting_as, &as_desc, + (rt_off_t) & ((struct uac_as_descriptor *)0)->intf_desc); + /* configure the uac interface descriptor */ + _uac_descriptor_config(setting_ac->desc, intf_ac->intf_num, setting_as->desc, intf_as->intf_num); + _uac_samplerate_config(setting_as->desc, RECORD_SAMPLERATE); + + /* create endpoint */ + as_desc_t = (struct uac_as_descriptor *)setting_as->desc; + mic.ep = rt_usbd_endpoint_new(&as_desc_t->ep_desc, _ep_data_in_handler); + + /* add the endpoint to the alternate setting */ + rt_usbd_altsetting_add_endpoint(setting_as, mic.ep); + + /* add the alternate setting to the interface, then set default setting of the interface */ + rt_usbd_interface_add_altsetting(intf_ac, setting_ac); + rt_usbd_set_altsetting(intf_ac, 0); + rt_usbd_interface_add_altsetting(intf_as, setting_as0); + rt_usbd_interface_add_altsetting(intf_as, setting_as); + rt_usbd_set_altsetting(intf_as, 0); + + /* add the interface to the uac function */ + rt_usbd_function_add_interface(func, intf_ac); + rt_usbd_function_add_interface(func, intf_as); + + return func; +} + +int audio_mic_init(void) +{ + rt_thread_t mic_tid; + mic.event = rt_event_create("mic_event", RT_IPC_FLAG_FIFO); + + mic_tid = rt_thread_create("mic_thread", + mic_entry, RT_NULL, + 1024, + 5, 10); + + if (mic_tid != RT_NULL) + rt_thread_startup(mic_tid); + return RT_EOK; +} +INIT_COMPONENT_EXPORT(audio_mic_init); + +/* + * register uac class + */ +struct udclass uac_class = +{ + .rt_usbd_function_create = rt_usbd_function_uac_mic_create +}; + +int rt_usbd_uac_mic_class_register(void) +{ + rt_usbd_class_register(&uac_class); + return 0; +} +INIT_PREV_EXPORT(rt_usbd_uac_mic_class_register); diff --git a/components/drivers/usb/usbdevice/class/audio_speaker.c b/components/drivers/usb/usbdevice/class/audio_speaker.c new file mode 100644 index 0000000000..84c36d2053 --- /dev/null +++ b/components/drivers/usb/usbdevice/class/audio_speaker.c @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-09-19 flybreak the first version + */ + +#include <rthw.h> +#include <rtthread.h> +#include <rtservice.h> +#include <rtdevice.h> + +#include "drivers/usb_device.h" +#include "audio.h" + +#define DBG_TAG "usbd.audio.speaker" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +#define AUDIO_SAMPLERATE 16000 +#define AUDIO_CHANNEL 1 +#define RESOLUTION_BITS 16 + +#define RESOLUTION_BYTE (RESOLUTION_BITS / 8) +#define AUDIO_PER_MS_SZ ((AUDIO_SAMPLERATE * AUDIO_CHANNEL * RESOLUTION_BYTE) / 1000) +#define AUDIO_BUFFER_SZ (AUDIO_PER_MS_SZ * 20) /* 20ms */ + +#if defined(RT_USBD_SPEAKER_DEVICE_NAME) + #define SPEAKER_DEVICE_NAME RT_USBD_SPEAKER_DEVICE_NAME +#else + #define SPEAKER_DEVICE_NAME "sound0" +#endif + +#define EVENT_AUDIO_START (1 << 0) +#define EVENT_AUDIO_STOP (1 << 1) +#define EVENT_AUDIO_DATA (1 << 2) + +/* + * uac speaker descriptor define + */ + +#define UAC_CS_INTERFACE 0x24 +#define UAC_CS_ENDPOINT 0x25 + +#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 +{ +#ifdef RT_USB_DEVICE_COMPOSITE + 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; +#if UAC_USE_FEATURE_UNIT + DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(UAC_CH_NUM) 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 uendpoint_descriptor ep_desc; + struct uac_iso_endpoint_descriptor as_ep_desc; +}; + +/* + * uac speaker device type + */ + +struct uac_audio_speaker +{ + rt_device_t dev; + rt_event_t event; + rt_uint8_t open_count; + + rt_uint8_t *buffer; + rt_uint32_t buffer_index; + + uep_t ep; +}; +static struct uac_audio_speaker speaker; + +ALIGN(4) +static struct udevice_descriptor dev_desc = +{ + USB_DESC_LENGTH_DEVICE, //bLength; + USB_DESC_TYPE_DEVICE, //type; + USB_BCD_VERSION, //bcdUSB; + USB_CLASS_DEVICE, //bDeviceClass; + 0x00, //bDeviceSubClass; + 0x00, //bDeviceProtocol; + UAC_MAX_PACKET_SIZE, //bMaxPacketSize0; + _VENDOR_ID, //idVendor; + _PRODUCT_ID, //idProduct; + USB_BCD_DEVICE, //bcdDevice; + USB_STRING_MANU_INDEX, //iManufacturer; + USB_STRING_PRODUCT_INDEX, //iProduct; + USB_STRING_SERIAL_INDEX, //iSerialNumber;Unused. + USB_DYNAMIC, //bNumConfigurations; +}; + +//FS and HS needed +ALIGN(4) +static struct usb_qualifier_descriptor dev_qualifier = +{ + sizeof(dev_qualifier), //bLength + USB_DESC_TYPE_DEVICEQUALIFIER, //bDescriptorType + 0x0200, //bcdUSB + USB_CLASS_AUDIO, //bDeviceClass + 0x00, //bDeviceSubClass + 0x00, //bDeviceProtocol + 64, //bMaxPacketSize0 + 0x01, //bNumConfigurations + 0, +}; + +ALIGN(4) +const static char *_ustring[] = +{ + "Language", + "RT-Thread Team.", + "RT-Thread Speaker", + "32021919830108", + "Configuration", + "Interface", +}; + +ALIGN(4) +static struct uac_ac_descriptor ac_desc = +{ +#ifdef RT_USB_DEVICE_COMPOSITE + /* Interface Association Descriptor */ + { + USB_DESC_LENGTH_IAD, + USB_DESC_TYPE_IAD, + USB_DYNAMIC, + 0x02, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, + }, +#endif + /* Interface Descriptor */ + { + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x00, + 0x00, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOCONTROL, + 0x00, + 0x00, + }, + /* Header Descriptor */ + { + UAC_DT_AC_HEADER_SIZE(UAC_INTR_NUM), + UAC_CS_INTERFACE, + UAC_HEADER, + 0x0100, /* Version: 1.00 */ + 0x0027, /* Total length: 39 */ + 0x01, /* Total number of interfaces: 1 */ + {0x01}, /* Interface number: 1 */ + }, + /* Input Terminal Descriptor */ + { + UAC_DT_INPUT_TERMINAL_SIZE, + UAC_CS_INTERFACE, + UAC_INPUT_TERMINAL, + 0x01, /* Terminal ID: 1 */ + 0x0101, /* Terminal Type: USB Streaming (0x0101) */ + 0x00, /* Assoc Terminal: 0 */ + 0x01, /* Number Channels: 1 */ + 0x0000, /* Channel Config: 0x0000 */ + 0x00, /* Channel Names: 0 */ + 0x00, /* Terminal: 0 */ + }, + /* Output Terminal Descriptor */ + { + UAC_DT_OUTPUT_TERMINAL_SIZE, + UAC_CS_INTERFACE, + UAC_OUTPUT_TERMINAL, + 0x02, /* Terminal ID: 2 */ + 0x0302, /* Terminal Type: Headphones (0x0302) */ + 0x00, /* Assoc Terminal: 0 */ + 0x01, /* Source ID: 1 */ + 0x00, /* Terminal: 0 */ + }, +#if UAC_USE_FEATURE_UNIT + /* Feature unit Descriptor */ + { + UAC_DT_FEATURE_UNIT_SIZE(UAC_CH_NUM), + UAC_CS_INTERFACE, + UAC_FEATURE_UNIT, + 0x02, + 0x0101, + 0x00, + 0x01, + }, +#endif +}; + +ALIGN(4) +static struct uinterface_descriptor as_desc0 = +{ + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x00, + 0x00, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, +}; + +ALIGN(4) +static struct uac_as_descriptor as_desc = +{ + /* Interface Descriptor */ + { + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x01, + 0x01, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, + }, + /* General AS Descriptor */ + { + UAC_DT_AS_HEADER_SIZE, + UAC_CS_INTERFACE, + UAC_AS_GENERAL, + 0x01, /* Terminal ID: 1 */ + 0x01, /* Interface delay in frames: 1 */ + UAC_FORMAT_TYPE_I_PCM, + }, + /* Format type i Descriptor */ + { + UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(UAC_FORMAT_NUM), + UAC_CS_INTERFACE, + UAC_FORMAT_TYPE, + UAC_FORMAT_TYPE_I, + UAC_CHANNEL_NUM, + 2, /* Subframe Size: 2 */ + RESOLUTION_BITS, + 0x01, /* Samples Frequence Type: 1 */ + {0}, /* Samples Frequence */ + }, + /* Endpoint Descriptor */ + { + USB_DESC_LENGTH_ENDPOINT, + USB_DESC_TYPE_ENDPOINT, + USB_DYNAMIC | USB_DIR_OUT, + USB_EP_ATTR_ISOC, + UAC_EP_MAX_PACKET_SIZE, + 0x01, + }, + /* AS Endpoint Descriptor */ + { + UAC_ISO_ENDPOINT_DESC_SIZE, + UAC_CS_ENDPOINT, + UAC_MS_GENERAL, + }, +}; + +void speaker_entry(void *parameter) +{ + struct rt_audio_caps caps = {0}; + rt_uint32_t e, index; + + speaker.buffer = rt_malloc(AUDIO_BUFFER_SZ); + if (speaker.buffer == RT_NULL) + { + LOG_E("malloc failed"); + goto __exit; + } + + speaker.dev = rt_device_find(SPEAKER_DEVICE_NAME); + if (speaker.dev == RT_NULL) + { + LOG_E("can't find device:%s", SPEAKER_DEVICE_NAME); + goto __exit; + } + + while (1) + { + if (rt_event_recv(speaker.event, EVENT_AUDIO_START | EVENT_AUDIO_STOP, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + 1000, &e) != RT_EOK) + { + continue; + } + if (speaker.open_count == 0) + { + continue; + } + LOG_D("play start"); + + rt_device_open(speaker.dev, RT_DEVICE_OFLAG_WRONLY); + + caps.main_type = AUDIO_TYPE_OUTPUT; + caps.sub_type = AUDIO_DSP_PARAM; + caps.udata.config.samplerate = AUDIO_SAMPLERATE; + caps.udata.config.channels = AUDIO_CHANNEL; + caps.udata.config.samplebits = RESOLUTION_BITS; + rt_device_control(speaker.dev, AUDIO_CTL_CONFIGURE, &caps); + + while (1) + { + if (rt_event_recv(speaker.event, EVENT_AUDIO_DATA | EVENT_AUDIO_STOP, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + 1000, &e) != RT_EOK) + { + if (speaker.open_count > 0) + continue; + else + break; + } + if (e & EVENT_AUDIO_DATA) + { + index = (speaker.buffer_index >= AUDIO_BUFFER_SZ / 2) ? 0 : (AUDIO_BUFFER_SZ / 2); + rt_device_write(speaker.dev, 0, speaker.buffer + index, AUDIO_BUFFER_SZ / 2); + } + else if (e & EVENT_AUDIO_STOP) + { + break; + } + } + LOG_D("play stop"); + rt_device_close(speaker.dev); + } + +__exit: + if (speaker.buffer) + rt_free(speaker.buffer); +} + +static rt_err_t _audio_start(ufunction_t func) +{ + speaker.ep->request.buffer = speaker.buffer; + speaker.ep->request.size = UAC_EP_MAX_PACKET_SIZE; + speaker.ep->request.req_type = UIO_REQUEST_READ_FULL; + rt_usbd_io_request(func->device, speaker.ep, &speaker.ep->request); + + speaker.open_count ++; + rt_event_send(speaker.event, EVENT_AUDIO_START); + + return 0; +} + +static rt_err_t _audio_stop(ufunction_t func) +{ + speaker.open_count --; + rt_event_send(speaker.event, EVENT_AUDIO_STOP); + return 0; +} + +static rt_err_t _ep_data_handler(ufunction_t func, rt_size_t size) +{ + RT_ASSERT(func != RT_NULL); + LOG_D("_ep_data_handler"); + + speaker.ep->request.buffer = speaker.buffer + speaker.buffer_index; + speaker.ep->request.size = UAC_EP_MAX_PACKET_SIZE; + speaker.ep->request.req_type = UIO_REQUEST_READ_FULL; + rt_usbd_io_request(func->device, speaker.ep, &speaker.ep->request); + + speaker.buffer_index += UAC_EP_MAX_PACKET_SIZE; + if (speaker.buffer_index >= AUDIO_BUFFER_SZ) + { + speaker.buffer_index = 0; + rt_event_send(speaker.event, EVENT_AUDIO_DATA); + } + else if (speaker.buffer_index == AUDIO_BUFFER_SZ / 2) + { + rt_event_send(speaker.event, EVENT_AUDIO_DATA); + } + + return RT_EOK; +} + +static rt_err_t _interface_as_handler(ufunction_t func, ureq_t setup) +{ + RT_ASSERT(func != RT_NULL); + RT_ASSERT(func->device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + LOG_D("_interface_as_handler"); + + if ((setup->request_type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD) + { + switch (setup->bRequest) + { + case USB_REQ_GET_INTERFACE: + break; + case USB_REQ_SET_INTERFACE: + LOG_D("set interface handler"); + if (setup->wValue == 1) + { + _audio_start(func); + } + else if (setup->wValue == 0) + { + _audio_stop(func); + } + break; + default: + LOG_D("unknown uac request 0x%x", setup->bRequest); + return -RT_ERROR; + } + } + + return RT_EOK; +} + +static rt_err_t _function_enable(ufunction_t func) +{ + RT_ASSERT(func != RT_NULL); + + LOG_D("uac function enable"); + + return RT_EOK; +} + +static rt_err_t _function_disable(ufunction_t func) +{ + RT_ASSERT(func != RT_NULL); + + LOG_D("uac function disable"); + _audio_stop(func); + return RT_EOK; +} + +static struct ufunction_ops ops = +{ + _function_enable, + _function_disable, + RT_NULL, +}; +/** + * This function will configure uac descriptor. + * + * @param comm the communication interface number. + * @param data the data interface number. + * + * @return RT_EOK on successful. + */ +static rt_err_t _uac_descriptor_config(struct uac_ac_descriptor *ac, + rt_uint8_t cintf_nr, struct uac_as_descriptor *as, rt_uint8_t sintf_nr) +{ + ac->hdr_desc.baInterfaceNr[0] = sintf_nr; +#ifdef RT_USB_DEVICE_COMPOSITE + ac->iad_desc.bFirstInterface = cintf_nr; +#endif + + return RT_EOK; +} + +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; + return RT_EOK; +} + +/** + * This function will create a uac function instance. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +ufunction_t rt_usbd_function_uac_speaker_create(udevice_t device) +{ + ufunction_t func; + uintf_t intf_ac, intf_as; + ualtsetting_t setting_as0; + ualtsetting_t setting_ac, setting_as; + struct uac_as_descriptor *as_desc_t; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + + /* set usb device string description */ + rt_usbd_device_set_string(device, _ustring); + + /* create a uac function */ + func = rt_usbd_function_new(device, &dev_desc, &ops); + //not support HS + //rt_usbd_device_set_qualifier(device, &dev_qualifier); + + /* create interface */ + intf_ac = rt_usbd_interface_new(device, RT_NULL); + intf_as = rt_usbd_interface_new(device, _interface_as_handler); + + /* create alternate setting */ + setting_ac = rt_usbd_altsetting_new(sizeof(struct uac_ac_descriptor)); + setting_as0 = rt_usbd_altsetting_new(sizeof(struct uinterface_descriptor)); + setting_as = rt_usbd_altsetting_new(sizeof(struct uac_as_descriptor)); + /* config desc in alternate setting */ + rt_usbd_altsetting_config_descriptor(setting_ac, &ac_desc, + (rt_off_t) & ((struct uac_ac_descriptor *)0)->intf_desc); + rt_usbd_altsetting_config_descriptor(setting_as0, &as_desc0, 0); + rt_usbd_altsetting_config_descriptor(setting_as, &as_desc, + (rt_off_t) & ((struct uac_as_descriptor *)0)->intf_desc); + /* configure the uac interface descriptor */ + _uac_descriptor_config(setting_ac->desc, intf_ac->intf_num, setting_as->desc, intf_as->intf_num); + _uac_samplerate_config(setting_as->desc, AUDIO_SAMPLERATE); + + /* create endpoint */ + as_desc_t = (struct uac_as_descriptor *)setting_as->desc; + speaker.ep = rt_usbd_endpoint_new(&as_desc_t->ep_desc, _ep_data_handler); + + /* add the endpoint to the alternate setting */ + rt_usbd_altsetting_add_endpoint(setting_as, speaker.ep); + + /* add the alternate setting to the interface, then set default setting of the interface */ + rt_usbd_interface_add_altsetting(intf_ac, setting_ac); + rt_usbd_set_altsetting(intf_ac, 0); + rt_usbd_interface_add_altsetting(intf_as, setting_as0); + rt_usbd_interface_add_altsetting(intf_as, setting_as); + rt_usbd_set_altsetting(intf_as, 0); + + /* add the interface to the uac function */ + rt_usbd_function_add_interface(func, intf_ac); + rt_usbd_function_add_interface(func, intf_as); + + return func; +} + +int audio_speaker_init(void) +{ + rt_thread_t speaker_tid; + speaker.event = rt_event_create("speaker_event", RT_IPC_FLAG_FIFO); + + speaker_tid = rt_thread_create("speaker_thread", + speaker_entry, RT_NULL, + 1024, + 5, 10); + + if (speaker_tid != RT_NULL) + rt_thread_startup(speaker_tid); + return RT_EOK; +} +INIT_COMPONENT_EXPORT(audio_speaker_init); + +/* + * register uac class + */ +static struct udclass uac_speaker_class = +{ + .rt_usbd_function_create = rt_usbd_function_uac_speaker_create +}; + +int rt_usbd_uac_speaker_class_register(void) +{ + rt_usbd_class_register(&uac_speaker_class); + return 0; +} +INIT_PREV_EXPORT(rt_usbd_uac_speaker_class_register); diff --git a/components/drivers/usb/usbdevice/class/ecm.c b/components/drivers/usb/usbdevice/class/ecm.c index cda1a8bf1b..b98b5007f4 100644 --- a/components/drivers/usb/usbdevice/class/ecm.c +++ b/components/drivers/usb/usbdevice/class/ecm.c @@ -6,17 +6,16 @@ * Change Logs: * Date Author Notes * 2017-11-19 ZYH first version + * 2019-06-10 ZYH fix hotplug */ #include <rtdevice.h> +#ifdef RT_USB_DEVICE_ECM #include "cdc.h" - -#ifdef ECM_DEBUG -#define ECM_PRINTF rt_kprintf("[ECM] "); rt_kprintf -#else -#define ECM_PRINTF(...) -#endif /* ECM_DEBUG */ +#define DBG_LEVEL DBG_WARNING +#define DBG_SECTION_NAME "ECM" +#include <rtdbg.h> /* RT-Thread LWIP ethernet interface */ #include <netif/ethernetif.h> @@ -216,15 +215,21 @@ static rt_err_t _cdc_send_notifi(ufunction_t func,ucdc_notification_code_t notif return RT_EOK; } + static rt_err_t _ecm_set_eth_packet_filter(ufunction_t func, ureq_t setup) { rt_ecm_eth_t _ecm_eth = (rt_ecm_eth_t)func->user_data; dcd_ep0_send_status(func->device->dcd); - /* send link up. */ eth_device_linkchange(&_ecm_eth->parent, RT_TRUE); - _cdc_send_notifi(func,UCDC_NOTIFI_NETWORK_CONNECTION,1,0); + _cdc_send_notifi(func, UCDC_NOTIFI_NETWORK_CONNECTION, 1, 0); + +#ifdef LWIP_USING_DHCPD + extern void dhcpd_start(const char *netif_name); + dhcpd_start("u0"); +#endif + return RT_EOK; } /** @@ -243,10 +248,11 @@ static rt_err_t _interface_handler(ufunction_t func, ureq_t setup) switch(setup->bRequest) { case CDC_SET_ETH_PACKET_FILTER: + LOG_D("CDC_SET_ETH_PACKET_FILTER"); _ecm_set_eth_packet_filter(func, setup); break; default: - rt_kprintf("setup->bRequest:0x%02X",setup->bRequest); + LOG_E("Unknow setup->bRequest: 0x%02X", setup->bRequest); break; } return RT_EOK; @@ -402,22 +408,26 @@ rt_err_t rt_ecm_eth_tx(rt_device_t dev, struct pbuf* p) if(!ecm_eth_dev->parent.link_status) { - ECM_PRINTF("linkdown, drop pkg\r\n"); + LOG_D("linkdown, drop pkg"); return RT_EOK; } - // RT_ASSERT(p->tot_len < USB_ETH_MTU); if(p->tot_len > USB_ETH_MTU) { - ECM_PRINTF("RNDIS MTU is:%d, but the send packet size is %d\r\n", + LOG_W("ECM MTU is:%d, but the send packet size is %d", USB_ETH_MTU, p->tot_len); p->tot_len = USB_ETH_MTU; } - result = rt_sem_take(&ecm_eth_dev->tx_buffer_free, RT_WAITING_FOREVER); + + result = rt_sem_take(&device->tx_buffer_free, rt_tick_from_millisecond(1000)); if(result != RT_EOK) { + LOG_W("wait for buffer free timeout"); + /* if cost 1s to wait send done it said that connection is close . drop it */ + rt_sem_release(&device->tx_buffer_free); return result; } + pbuffer = (char *)&ecm_eth_dev->tx_buffer; for (q = p; q != NULL; q = q->next) { @@ -461,8 +471,13 @@ static rt_err_t _function_enable(ufunction_t func) { cdc_eps_t eps; rt_ecm_eth_t ecm_device = (rt_ecm_eth_t)func->user_data; + + LOG_D("plugged in"); + eps = (cdc_eps_t)&ecm_device->eps; eps->ep_out->buffer = ecm_device->rx_pool; + + /* reset eth rx tx */ ecm_device->rx_size = 0; ecm_device->rx_offset = 0; @@ -482,7 +497,14 @@ static rt_err_t _function_enable(ufunction_t func) */ static rt_err_t _function_disable(ufunction_t func) { + LOG_D("plugged out"); + eth_device_linkchange(&((rt_ecm_eth_t)func->user_data)->parent, RT_FALSE); + + /* reset eth rx tx */ + ((rt_ecm_eth_t)func->user_data)->rx_size = 0; + ((rt_ecm_eth_t)func->user_data)->rx_offset = 0; + return RT_EOK; } @@ -643,3 +665,5 @@ int rt_usbd_ecm_class_register(void) return 0; } INIT_PREV_EXPORT(rt_usbd_ecm_class_register); + +#endif /* RT_USB_DEVICE_ECM */ diff --git a/components/drivers/usb/usbdevice/class/hid.c b/components/drivers/usb/usbdevice/class/hid.c index aea6d802d1..a9b2e62d70 100644 --- a/components/drivers/usb/usbdevice/class/hid.c +++ b/components/drivers/usb/usbdevice/class/hid.c @@ -372,7 +372,7 @@ const static char* _ustring[] = "Interface", }; -static void dump_data(uint8_t *data, rt_size_t size) +static void dump_data(rt_uint8_t *data, rt_size_t size) { rt_size_t i; for (i = 0; i < size; i++) diff --git a/components/drivers/usb/usbdevice/class/rndis.c b/components/drivers/usb/usbdevice/class/rndis.c index 8996b728e6..93e0ba6ae2 100644 --- a/components/drivers/usb/usbdevice/class/rndis.c +++ b/components/drivers/usb/usbdevice/class/rndis.c @@ -13,21 +13,21 @@ * 2013-07-09 aozima support respone chain list. * 2013-07-18 aozima re-initial respone chain list when RNDIS restart. * 2017-11-25 ZYH fix it and add OS descriptor + * 2019-06-10 ZYH fix hot plug and delay linkup */ #include <rtdevice.h> +#ifdef RT_USB_DEVICE_RNDIS #include "cdc.h" #include "rndis.h" #include "ndis.h" -//#define RNDIS_DEBUG -//#define RNDIS_DELAY_LINK_UP +/* define RNDIS_DELAY_LINK_UP by menuconfig for delay linkup */ + +#define DBG_LEVEL DBG_WARNING +#define DBG_SECTION_NAME "RNDIS" +#include <rtdbg.h> -#ifdef RNDIS_DEBUG -#define RNDIS_PRINTF rt_kprintf("[RNDIS] "); rt_kprintf -#else -#define RNDIS_PRINTF(...) -#endif /* RNDIS_DEBUG */ /* RT-Thread LWIP ethernet interface */ #include <netif/ethernetif.h> @@ -314,7 +314,7 @@ static rt_err_t _rndis_init_response(ufunction_t func, rndis_init_msg_t msg) if( (response == RT_NULL) || (resp == RT_NULL) ) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); if(response != RT_NULL) rt_free(response); @@ -360,7 +360,7 @@ static rndis_query_cmplt_t _create_resp(rt_size_t size) if(resp == RT_NULL) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); return RT_NULL; } @@ -421,7 +421,7 @@ static rt_err_t _rndis_query_response(ufunction_t func,rndis_query_msg_t msg) case OID_GEN_LINK_SPEED: resp = _create_resp(4); if(resp == RT_NULL) break; - _set_resp(resp, func->device->dcd->device_is_hs ? (480UL * 1000 *1000) : (12UL * 1000 * 1000) / 100); + _set_resp(resp, (func->device->dcd->device_is_hs ? (480UL * 1000 *1000) : (12UL * 1000 * 1000)) / 100); break; case OID_GEN_MEDIA_CONNECT_STATUS: @@ -510,7 +510,7 @@ static rt_err_t _rndis_query_response(ufunction_t func,rndis_query_msg_t msg) break; default: - RNDIS_PRINTF("OID %X\n", msg->Oid); + LOG_W("Not support OID %X", msg->Oid); ret = -RT_ERROR; break; } @@ -518,7 +518,7 @@ static rt_err_t _rndis_query_response(ufunction_t func,rndis_query_msg_t msg) response = rt_malloc(sizeof(struct rt_rndis_response)); if( (response == RT_NULL) || (resp == RT_NULL) ) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); if(response != RT_NULL) rt_free(response); @@ -557,7 +557,7 @@ static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg) if( (response == RT_NULL) || (resp == RT_NULL) ) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); if(response != RT_NULL) rt_free(response); @@ -577,8 +577,10 @@ static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg) case OID_GEN_CURRENT_PACKET_FILTER: oid_packet_filter = *((rt_uint32_t *)((rt_uint8_t *)&(msg->RequestId) + \ msg->InformationBufferOffset)); + /* TODO: make complier happy */ oid_packet_filter = oid_packet_filter; - RNDIS_PRINTF("OID_GEN_CURRENT_PACKET_FILTER\r\n"); + + LOG_D("OID_GEN_CURRENT_PACKET_FILTER"); #ifdef RNDIS_DELAY_LINK_UP /* link up. */ @@ -592,6 +594,7 @@ static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg) break; default: + LOG_W("Unknow rndis set 0x%02X", msg->Oid); resp->Status = RNDIS_STATUS_FAILURE; return RT_EOK; } @@ -609,6 +612,56 @@ static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg) return RT_EOK; } +static rt_err_t _rndis_reset_response(ufunction_t func,rndis_set_msg_t msg) +{ + struct rndis_reset_cmplt * resp; + struct rt_rndis_response * response; + + response = rt_malloc(sizeof(struct rt_rndis_response)); + resp = rt_malloc(sizeof(struct rndis_reset_cmplt)); + + if( (response == RT_NULL) || (resp == RT_NULL) ) + { + LOG_E("%s,%d: no memory!", __func__, __LINE__); + + if(response != RT_NULL) + rt_free(response); + + if(resp != RT_NULL) + rt_free(resp); + + return -RT_ENOMEM; + } + + /* reset packet filter */ + + oid_packet_filter = 0x0000000; + + /* link down eth */ + + eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_FALSE); + + /* reset eth rx tx */ + ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE; + ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE; + + + resp->MessageType = REMOTE_NDIS_RESET_CMPLT; + resp->MessageLength = sizeof(struct rndis_reset_cmplt); + resp->Status = RNDIS_STATUS_SUCCESS; + resp->AddressingReset = 1; + + response->buffer = resp; + + { + rt_base_t level = rt_hw_interrupt_disable(); + rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list); + rt_hw_interrupt_enable(level); + } + + return RT_EOK; +} + static rt_err_t _rndis_keepalive_response(ufunction_t func,rndis_keepalive_msg_t msg) { rndis_keepalive_cmplt_t resp; @@ -619,7 +672,7 @@ static rt_err_t _rndis_keepalive_response(ufunction_t func,rndis_keepalive_msg_t if( (response == RT_NULL) || (resp == RT_NULL) ) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); if(response != RT_NULL) rt_free(response); @@ -652,34 +705,42 @@ static rt_err_t _rndis_msg_parser(ufunction_t func, rt_uint8_t *msg) switch (((rndis_gen_msg_t) msg)->MessageType) { case REMOTE_NDIS_INITIALIZE_MSG: + LOG_D("REMOTE_NDIS_INITIALIZE_MSG"); ret = _rndis_init_response(func, (rndis_init_msg_t) msg); break; case REMOTE_NDIS_HALT_MSG: - RNDIS_PRINTF("halt\n"); + LOG_D("REMOTE_NDIS_HALT_MSG"); /* link down. */ eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_FALSE); + + /* reset eth rx tx */ + ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE; + ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE; break; case REMOTE_NDIS_QUERY_MSG: + LOG_D("REMOTE_NDIS_QUERY_MSG"); ret = _rndis_query_response(func,(rndis_query_msg_t) msg); break; case REMOTE_NDIS_SET_MSG: + LOG_D("REMOTE_NDIS_SET_MSG"); ret = _rndis_set_response(func,(rndis_set_msg_t) msg); - RNDIS_PRINTF("set\n"); break; case REMOTE_NDIS_RESET_MSG: - RNDIS_PRINTF("reset\n"); + LOG_D("REMOTE_NDIS_RESET_MSG"); + ret = _rndis_reset_response(func,(rndis_set_msg_t) msg); break; case REMOTE_NDIS_KEEPALIVE_MSG: + LOG_D("REMOTE_NDIS_KEEPALIVE_MSG"); ret = _rndis_keepalive_response(func,(rndis_keepalive_msg_t) msg); break; default: - RNDIS_PRINTF("msg %X\n", ((rndis_gen_msg_t) msg)->MessageType); + LOG_W("not support RNDIS msg %X", ((rndis_gen_msg_t) msg)->MessageType); ret = -RT_ERROR; break; } @@ -718,7 +779,7 @@ static rt_err_t _rndis_get_encapsulated_response(ufunction_t func, ureq_t setup) if(rt_list_isempty(&((rt_rndis_eth_t)func->user_data)->response_list)) { - RNDIS_PRINTF("response_list is empty!\r\n"); + LOG_D("response_list is empty!"); ((rt_rndis_eth_t)func->user_data)->need_notify = RT_TRUE; return RT_EOK; } @@ -741,7 +802,7 @@ static rt_err_t _rndis_get_encapsulated_response(ufunction_t func, ureq_t setup) { rt_uint32_t * data; - RNDIS_PRINTF("auto append next response!\r\n"); + LOG_I("auto append next response!"); data = (rt_uint32_t *)((rt_rndis_eth_t)func->user_data)->eps.ep_cmd->buffer; data[0] = RESPONSE_AVAILABLE; data[1] = 0; @@ -758,55 +819,6 @@ static rt_err_t _rndis_get_encapsulated_response(ufunction_t func, ureq_t setup) return RT_EOK; } -#ifdef RNDIS_DELAY_LINK_UP -/** - * This function will set rndis connect status. - * - * @param device the usb device object. - * @param status the connect status. - * - * @return RT_EOK on successful. - */ -static rt_err_t _rndis_indicate_status_msg(ufunction_t func, rt_uint32_t status) -{ - rndis_indicate_status_msg_t resp; - struct rt_rndis_response * response; - - response = rt_malloc(sizeof(struct rt_rndis_response)); - resp = rt_malloc(sizeof(struct rndis_indicate_status_msg)); - - if( (response == RT_NULL) || (resp == RT_NULL) ) - { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); - - if(response != RT_NULL) - rt_free(response); - - if(resp != RT_NULL) - rt_free(resp); - - return -RT_ENOMEM; - } - - resp->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG; - resp->MessageLength = 20; /* sizeof(struct rndis_indicate_status_msg) */ - resp->Status = status; - resp->StatusBufferLength = 0; - resp->StatusBufferOffset = 0; - - response->buffer = resp; - { - rt_base_t level = rt_hw_interrupt_disable(); - rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list); - rt_hw_interrupt_enable(level); - } - - _rndis_response_available(func); - - return RT_EOK; -} -#endif /* RNDIS_DELAY_LINK_UP */ - /** * This function will handle rndis interface request. * @@ -831,7 +843,7 @@ static rt_err_t _interface_handler(ufunction_t func, ureq_t setup) break; default: - RNDIS_PRINTF("unkown setup->request!\r\n"); + LOG_W("unkown setup->request 0x%02X !", setup->bRequest); break; } @@ -933,6 +945,8 @@ static rt_err_t _function_enable(ufunction_t func) { cdc_eps_t eps; + LOG_I("plugged in"); + eps = (cdc_eps_t)&((rt_rndis_eth_t)func->user_data)->eps; eps->ep_in->buffer = ((rt_rndis_eth_t)func->user_data)->tx_pool; eps->ep_out->buffer = ((rt_rndis_eth_t)func->user_data)->rx_pool; @@ -945,6 +959,7 @@ static rt_err_t _function_enable(ufunction_t func) ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE; ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE; + // eth_device_ready(&(((rt_rndis_eth_t)func->user_data)->parent)); #ifdef RNDIS_DELAY_LINK_UP /* stop link up timer. */ @@ -981,7 +996,7 @@ static rt_err_t _function_enable(ufunction_t func) */ static rt_err_t _function_disable(ufunction_t func) { - RNDIS_PRINTF("plugged out\n"); + LOG_I("plugged out"); #ifdef RNDIS_DELAY_LINK_UP /* stop link up timer. */ @@ -996,7 +1011,7 @@ static rt_err_t _function_disable(ufunction_t func) while(!rt_list_isempty(&((rt_rndis_eth_t)func->user_data)->response_list)) { response = (struct rt_rndis_response *)((rt_rndis_eth_t)func->user_data)->response_list.next; - RNDIS_PRINTF("remove resp chain list!\r\n"); + LOG_D("remove resp chain list!"); rt_list_remove(&response->list); rt_free((void *)response->buffer); @@ -1007,8 +1022,14 @@ static rt_err_t _function_disable(ufunction_t func) rt_hw_interrupt_enable(level); } + /* link down. */ eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_FALSE); + + /* reset eth rx tx */ + ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE; + ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE; + return RT_EOK; } @@ -1141,22 +1162,25 @@ rt_err_t rt_rndis_eth_tx(rt_device_t dev, struct pbuf* p) if(!device->parent.link_status) { - RNDIS_PRINTF("linkdown, drop pkg\r\n"); + LOG_I("linkdown, drop pkg"); return RT_EOK; } - RT_ASSERT(p->tot_len < sizeof(device->tx_buffer)); + //RT_ASSERT(p->tot_len < sizeof(device->tx_buffer)); if(p->tot_len > sizeof(device->tx_buffer)) { - RNDIS_PRINTF("RNDIS MTU is:%d, but the send packet size is %d\r\n", + LOG_W("RNDIS MTU is:%d, but the send packet size is %d", sizeof(device->tx_buffer), p->tot_len); p->tot_len = sizeof(device->tx_buffer); } /* wait for buffer free. */ - result = rt_sem_take(&device->tx_buffer_free, RT_WAITING_FOREVER); + result = rt_sem_take(&device->tx_buffer_free, rt_tick_from_millisecond(1000)); if(result != RT_EOK) { + LOG_W("wait for buffer free timeout"); + /* if cost 1s to wait send done it said that connection is close . drop it */ + rt_sem_release(&device->tx_buffer_free); return result; } @@ -1215,11 +1239,59 @@ const static struct rt_device_ops rndis_device_ops = #endif /* RT_USING_LWIP */ #ifdef RNDIS_DELAY_LINK_UP + +/** + * This function will set rndis connect status. + * + * @param device the usb device object. + * @param status the connect status. + * + * @return RT_EOK on successful. + */ +static rt_err_t _rndis_indicate_status_msg(ufunction_t func, rt_uint32_t status) +{ + rndis_indicate_status_msg_t resp; + struct rt_rndis_response * response; + + response = rt_malloc(sizeof(struct rt_rndis_response)); + resp = rt_malloc(sizeof(struct rndis_indicate_status_msg)); + + if( (response == RT_NULL) || (resp == RT_NULL) ) + { + LOG_E("%s,%d: no memory!", __func__, __LINE__); + + if(response != RT_NULL) + rt_free(response); + + if(resp != RT_NULL) + rt_free(resp); + + return -RT_ENOMEM; + } + + resp->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG; + resp->MessageLength = 20; /* sizeof(struct rndis_indicate_status_msg) */ + resp->Status = status; + resp->StatusBufferLength = 0; + resp->StatusBufferOffset = 0; + + response->buffer = resp; + { + rt_base_t level = rt_hw_interrupt_disable(); + rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list); + rt_hw_interrupt_enable(level); + } + + _rndis_response_available(func); + + return RT_EOK; +} + /* the delay linkup timer handler. */ static void timer_timeout(void* parameter) { - RNDIS_PRINTF("delay link up!\r\n"); - _rndis_indicate_status_msg(((rt_rndis_eth_t)parameter)->parent.parent.user_data, + LOG_I("delay link up!"); + _rndis_indicate_status_msg(((rt_rndis_eth_t)parameter)->func, RNDIS_STATUS_MEDIA_CONNECT); eth_device_linkchange(&((rt_rndis_eth_t)parameter)->parent, RT_TRUE); } @@ -1319,7 +1391,7 @@ ufunction_t rt_usbd_function_rndis_create(udevice_t device) timer_timeout, _rndis, RT_TICK_PER_SECOND * 2, - RT_TIMER_FLAG_ONE_SHOT); + RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER); #endif /* RNDIS_DELAY_LINK_UP */ /* OUI 00-00-00, only for test. */ @@ -1372,4 +1444,6 @@ int rt_usbd_rndis_class_register(void) rt_usbd_class_register(&rndis_class); return 0; } -INIT_PREV_EXPORT(rt_usbd_rndis_class_register);
\ No newline at end of file +INIT_PREV_EXPORT(rt_usbd_rndis_class_register); + +#endif /* RT_USB_DEVICE_RNDIS */ diff --git a/components/drivers/usb/usbdevice/class/rndis.h b/components/drivers/usb/usbdevice/class/rndis.h index 000ea62baf..fcdd249984 100644 --- a/components/drivers/usb/usbdevice/class/rndis.h +++ b/components/drivers/usb/usbdevice/class/rndis.h @@ -180,6 +180,15 @@ struct rndis_reset_msg rt_uint32_t Reserved; }; +/* Remote NDIS Soft Reset Response */ +struct rndis_reset_cmplt +{ + rt_uint32_t MessageType; + rt_uint32_t MessageLength; + rt_uint32_t Status; + rt_uint32_t AddressingReset; +}; + /* Remote NDIS Indicate Status Message */ struct rndis_indicate_status_msg { diff --git a/components/drivers/usb/usbdevice/core/core.c b/components/drivers/usb/usbdevice/core/core.c index 4e3a3e9280..584556303f 100644 --- a/components/drivers/usb/usbdevice/core/core.c +++ b/components/drivers/usb/usbdevice/core/core.c @@ -237,7 +237,8 @@ static rt_err_t _get_interface(struct udevice* device, ureq_t setup) { rt_uint8_t value; uintf_t intf; - + ufunction_t func; + /* parameter check */ RT_ASSERT(device != RT_NULL); RT_ASSERT(setup != RT_NULL); @@ -251,12 +252,17 @@ static rt_err_t _get_interface(struct udevice* device, ureq_t setup) } /* find the specified interface and its alternate setting */ - intf = rt_usbd_find_interface(device, setup->wIndex & 0xFF, RT_NULL); + intf = rt_usbd_find_interface(device, setup->wIndex & 0xFF, &func); value = intf->curr_setting->intf_desc->bAlternateSetting; /* send the interface alternate setting to endpoint 0*/ rt_usbd_ep0_write(device, &value, 1); + if (intf->handler) + { + intf->handler(func, setup); + } + return RT_EOK; } @@ -270,6 +276,7 @@ static rt_err_t _get_interface(struct udevice* device, ureq_t setup) */ static rt_err_t _set_interface(struct udevice* device, ureq_t setup) { + ufunction_t func; uintf_t intf; uep_t ep; struct rt_list_node* i; @@ -288,7 +295,7 @@ static rt_err_t _set_interface(struct udevice* device, ureq_t setup) } /* find the specified interface */ - intf = rt_usbd_find_interface(device, setup->wIndex & 0xFF, RT_NULL); + intf = rt_usbd_find_interface(device, setup->wIndex & 0xFF, &func); /* set alternate setting to the interface */ rt_usbd_set_altsetting(intf, setup->wValue & 0xFF); @@ -303,6 +310,11 @@ static rt_err_t _set_interface(struct udevice* device, ureq_t setup) } dcd_ep0_send_status(device->dcd); + if (intf->handler) + { + intf->handler(func, setup); + } + return RT_EOK; } @@ -995,7 +1007,7 @@ udevice_t rt_usbd_device_new(void) RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_new\n")); /* allocate memory for the object */ - udevice = rt_malloc(sizeof(struct udevice)); + udevice = (udevice_t)rt_malloc(sizeof(struct udevice)); if(udevice == RT_NULL) { rt_kprintf("alloc memery failed\n"); @@ -1109,7 +1121,7 @@ uconfig_t rt_usbd_config_new(void) RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_new\n")); /* allocate memory for the object */ - cfg = rt_malloc(sizeof(struct uconfig)); + cfg = (uconfig_t)rt_malloc(sizeof(struct uconfig)); if(cfg == RT_NULL) { rt_kprintf("alloc memery failed\n"); @@ -1488,9 +1500,10 @@ uep_t rt_usbd_find_endpoint(udevice_t device, ufunction_t* pfunc, rt_uint8_t ep_ */ rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg) { - struct rt_list_node *i, *j, *k; + struct rt_list_node *i, *j, *k, *m; ufunction_t func; uintf_t intf; + ualtsetting_t altsetting; uep_t ep; RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_add_config\n")); @@ -1512,22 +1525,26 @@ rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg) intf = (uintf_t)rt_list_entry(j, struct uinterface, list); cfg->cfg_desc.bNumInterfaces++; - /* allocate address for every endpoint in the interface alternate setting */ - for(k=intf->curr_setting->ep_list.next; - k!=&intf->curr_setting->ep_list; k=k->next) + for(k=intf->setting_list.next; k!=&intf->setting_list;k=k->next) { - ep = (uep_t)rt_list_entry(k, struct uendpoint, list); - if(rt_usbd_ep_assign(device, ep) != RT_EOK) + altsetting = (ualtsetting_t)rt_list_entry(k, struct ualtsetting, list); + + /* allocate address for every endpoint in the interface alternate setting */ + for(m=altsetting->ep_list.next; m!=&altsetting->ep_list; m=m->next) { - rt_kprintf("endpoint assign error\n"); + ep = (uep_t)rt_list_entry(m, struct uendpoint, list); + if(rt_usbd_ep_assign(device, ep) != RT_EOK) + { + rt_kprintf("endpoint assign error\n"); + } } - } - /* construct complete configuration descriptor */ - rt_memcpy((void*)&cfg->cfg_desc.data[cfg->cfg_desc.wTotalLength - USB_DESC_LENGTH_CONFIG], - (void*)intf->curr_setting->desc, - intf->curr_setting->desc_size); - cfg->cfg_desc.wTotalLength += intf->curr_setting->desc_size; + /* construct complete configuration descriptor */ + rt_memcpy((void*)&cfg->cfg_desc.data[cfg->cfg_desc.wTotalLength - USB_DESC_LENGTH_CONFIG], + (void*)altsetting->desc, + altsetting->desc_size); + cfg->cfg_desc.wTotalLength += altsetting->desc_size; + } } } @@ -2053,7 +2070,7 @@ rt_size_t rt_usbd_ep0_write(udevice_t device, void *buffer, rt_size_t size) ep0 = &device->dcd->ep0; ep0->request.size = size; - ep0->request.buffer = buffer; + ep0->request.buffer = (rt_uint8_t *)buffer; ep0->request.remain_size = size; if(size >= ep0->id->maxpacket) { @@ -2079,7 +2096,7 @@ rt_size_t rt_usbd_ep0_read(udevice_t device, void *buffer, rt_size_t size, RT_ASSERT(buffer != RT_NULL); ep0 = &device->dcd->ep0; - ep0->request.buffer = buffer; + ep0->request.buffer = (rt_uint8_t *)buffer; ep0->request.remain_size = size; ep0->rx_indicate = rx_ind; if(size >= ep0->id->maxpacket) diff --git a/components/drivers/wlan/SConscript b/components/drivers/wlan/SConscript index 271ca66a80..f2a6bbdc82 100644 --- a/components/drivers/wlan/SConscript +++ b/components/drivers/wlan/SConscript @@ -1,8 +1,30 @@ from building import * cwd = GetCurrentDir() -src = Glob('*.c') CPPPATH = [cwd] + +src = Split(''' + wlan_dev.c + ''') + +if GetDepend(['RT_WLAN_MANAGE_ENABLE']): + src += ['wlan_mgnt.c'] + +if GetDepend(['RT_WLAN_MSH_CMD_ENABLE']): + src += ['wlan_cmd.c'] + +if GetDepend(['RT_WLAN_PROT_ENABLE']): + src += ['wlan_prot.c'] + +if GetDepend(['RT_WLAN_PROT_LWIP_ENABLE']): + src += ['wlan_lwip.c'] + +if GetDepend(['RT_WLAN_CFG_ENABLE']): + src += ['wlan_cfg.c'] + +if GetDepend(['RT_WLAN_WORK_THREAD_ENABLE']): + src += ['wlan_workqueue.c'] + group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_WIFI'], CPPPATH = CPPPATH) Return('group') diff --git a/components/drivers/wlan/wlan_cfg.c b/components/drivers/wlan/wlan_cfg.c index 126cee40f5..7fa9ecb2da 100644 --- a/components/drivers/wlan/wlan_cfg.c +++ b/components/drivers/wlan/wlan_cfg.c @@ -19,6 +19,8 @@ #endif /* RT_WLAN_CFG_DEBUG */ #include <rtdbg.h> +#ifdef RT_WLAN_CFG_ENABLE + #define WLAN_CFG_LOCK() (rt_mutex_take(&cfg_mutex, RT_WAITING_FOREVER)) #define WLAN_CFG_UNLOCK() (rt_mutex_release(&cfg_mutex)) @@ -462,3 +464,5 @@ void rt_wlan_cfg_dump(void) rt_kprintf("%3d \n", info->channel); } } + +#endif diff --git a/components/drivers/wlan/wlan_cmd.c b/components/drivers/wlan/wlan_cmd.c index b962b63947..fead6a8bf2 100644 --- a/components/drivers/wlan/wlan_cmd.c +++ b/components/drivers/wlan/wlan_cmd.c @@ -13,6 +13,8 @@ #include <wlan_cfg.h> #include <wlan_prot.h> +#if defined(RT_WLAN_MANAGE_ENABLE) && defined(RT_WLAN_MSH_CMD_ENABLE) + struct wifi_cmd_des { const char *cmd; @@ -75,7 +77,7 @@ static int wifi_help(int argc, char *argv[]) { rt_kprintf("wifi\n"); rt_kprintf("wifi help\n"); - rt_kprintf("wifi scan\n"); + rt_kprintf("wifi scan [SSID]\n"); rt_kprintf("wifi join [SSID] [PASSWORD]\n"); rt_kprintf("wifi ap SSID [PASSWORD]\n"); rt_kprintf("wifi disc\n"); @@ -143,12 +145,23 @@ static int wifi_status(int argc, char *argv[]) static int wifi_scan(int argc, char *argv[]) { struct rt_wlan_scan_result *scan_result = RT_NULL; + struct rt_wlan_info *info = RT_NULL; + struct rt_wlan_info filter; - if (argc > 2) + if (argc > 3) return -1; + if (argc == 3) + { + INVALID_INFO(&filter); + SSID_SET(&filter, argv[2]); + info = &filter; + } + + /* clean scan result */ + rt_wlan_scan_result_clean(); /* scan ap info */ - scan_result = rt_wlan_scan_sync(); + scan_result = rt_wlan_scan_with_info(info); if (scan_result) { int index, num; @@ -224,8 +237,10 @@ static int wifi_join(int argc, char *argv[]) const char *key = RT_NULL; struct rt_wlan_cfg_info cfg_info; + rt_memset(&cfg_info, 0, sizeof(cfg_info)); if (argc == 2) { +#ifdef RT_WLAN_CFG_ENABLE /* get info to connect */ if (rt_wlan_cfg_read_index(&cfg_info, 0) == 1) { @@ -234,8 +249,9 @@ static int wifi_join(int argc, char *argv[]) key = (char *)(&cfg_info.key.val[0]); } else +#endif { - rt_kprintf("not find info\n"); + rt_kprintf("not find connect info\n"); } } else if (argc == 3) @@ -387,8 +403,9 @@ static int wifi_debug_save_cfg(int argc, char *argv[]) rt_memcpy(&cfg_info.key.val[0], password, len); cfg_info.key.len = len; } - +#ifdef RT_WLAN_CFG_ENABLE rt_wlan_cfg_save(&cfg_info); +#endif return 0; } @@ -396,7 +413,9 @@ static int wifi_debug_dump_cfg(int argc, char *argv[]) { if (argc == 1) { +#ifdef RT_WLAN_CFG_ENABLE rt_wlan_cfg_dump(); +#endif } else { @@ -409,8 +428,10 @@ static int wifi_debug_clear_cfg(int argc, char *argv[]) { if (argc == 1) { +#ifdef RT_WLAN_CFG_ENABLE rt_wlan_cfg_delete_all(); rt_wlan_cfg_cache_save(); +#endif } else { @@ -447,6 +468,10 @@ static int wifi_debug_set_mode(int argc, char *argv[]) { mode = RT_WLAN_AP; } + else if (rt_strcmp("none", argv[1]) == 0) + { + mode = RT_WLAN_NONE; + } else return -1; @@ -564,3 +589,5 @@ static int wifi_msh(int argc, char *argv[]) #if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) FINSH_FUNCTION_EXPORT_ALIAS(wifi_msh, __cmd_wifi, wifi command.); #endif + +#endif diff --git a/components/drivers/wlan/wlan_dev.c b/components/drivers/wlan/wlan_dev.c index 82fa4e73e7..cbfd50a6c3 100644 --- a/components/drivers/wlan/wlan_dev.c +++ b/components/drivers/wlan/wlan_dev.c @@ -21,6 +21,8 @@ #endif /* RT_WLAN_DEV_DEBUG */ #include <rtdbg.h> +#if defined(RT_USING_WIFI) || defined(RT_USING_WLAN) + #ifndef RT_DEVICE #define RT_DEVICE(__device) ((rt_device_t)__device) #endif @@ -56,6 +58,17 @@ rt_err_t rt_wlan_dev_init(struct rt_wlan_device *device, rt_wlan_mode_t mode) return -RT_ERROR; } + if (mode == RT_WLAN_AP && device->flags & RT_WLAN_FLAG_STA_ONLY) + { + LOG_E("F:%s L:%d This wlan device can only be set to sta mode!", __FUNCTION__, __LINE__); + return -RT_ERROR; + } + else if (mode == RT_WLAN_STATION && device->flags & RT_WLAN_FLAG_AP_ONLY) + { + LOG_E("F:%s L:%d This wlan device can only be set to ap mode!", __FUNCTION__, __LINE__); + return -RT_ERROR; + } + result = rt_device_init(RT_DEVICE(device)); if (result != RT_EOK) { @@ -134,8 +147,8 @@ rt_err_t rt_wlan_dev_ap_start(struct rt_wlan_device *device, struct rt_wlan_info return -RT_ERROR; } - if ((password_len >= RT_WLAN_PASSWORD_MAX_LENGTH) || - (info->ssid.len >= RT_WLAN_SSID_MAX_LENGTH)) + if ((password_len > RT_WLAN_PASSWORD_MAX_LENGTH) || + (info->ssid.len > RT_WLAN_SSID_MAX_LENGTH)) { LOG_E("L:%d password or ssid is to long", __LINE__); return -RT_ERROR; @@ -515,15 +528,24 @@ rt_err_t rt_wlan_dev_scan(struct rt_wlan_device *device, struct rt_wlan_info *in if (info != RT_NULL) { - if (info->ssid.len >= RT_WLAN_SSID_MAX_LENGTH) + if (info->ssid.len > RT_WLAN_SSID_MAX_LENGTH) { LOG_E("L:%d ssid is to long", __LINE__); return -RT_EINVAL; } rt_memcpy(&scan_info.ssid, &info->ssid, sizeof(rt_wlan_ssid_t)); rt_memcpy(scan_info.bssid, info->bssid, RT_WLAN_BSSID_MAX_LENGTH); - scan_info.channel_min = -1; - scan_info.channel_max = -1; + if (info->channel > 0) + { + scan_info.channel_min = info->channel; + scan_info.channel_max = info->channel; + } + else + { + scan_info.channel_min = -1; + scan_info.channel_max = -1; + } + scan_info.passive = info->hidden ? RT_TRUE : RT_FALSE; p_scan_info = &scan_info; } result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_SCAN, p_scan_info); @@ -545,7 +567,11 @@ rt_err_t rt_wlan_dev_scan_stop(struct rt_wlan_device *device) rt_err_t rt_wlan_dev_report_data(struct rt_wlan_device *device, void *buff, int len) { +#ifdef RT_WLAN_PROT_ENABLE return rt_wlan_dev_transfer_prot(device, buff, len); +#else + return -RT_ERROR; +#endif } static rt_err_t _rt_wlan_dev_init(rt_device_t dev) @@ -768,14 +794,15 @@ rt_err_t rt_wlan_dev_register(struct rt_wlan_device *wlan, const char *name, con { rt_err_t err = RT_EOK; - if ((wlan == RT_NULL) || (name == RT_NULL) || (ops == RT_NULL)) + if ((wlan == RT_NULL) || (name == RT_NULL) || (ops == RT_NULL) || + (flag & RT_WLAN_FLAG_STA_ONLY && flag & RT_WLAN_FLAG_AP_ONLY)) { LOG_E("F:%s L:%d parameter Wrongful", __FUNCTION__, __LINE__); return RT_NULL; } rt_memset(wlan, 0, sizeof(struct rt_wlan_device)); - + #ifdef RT_USING_DEVICE_OPS wlan->device.ops = &wlan_ops; #else @@ -801,3 +828,5 @@ rt_err_t rt_wlan_dev_register(struct rt_wlan_device *wlan, const char *name, con return err; } + +#endif diff --git a/components/drivers/wlan/wlan_dev.h b/components/drivers/wlan/wlan_dev.h index a9300be9d7..43d6506d6f 100644 --- a/components/drivers/wlan/wlan_dev.h +++ b/components/drivers/wlan/wlan_dev.h @@ -381,6 +381,11 @@ typedef struct rt_wlan_key rt_wlan_key_t; (_info)->channel = -1; \ } while(0) +#define SSID_SET(_info, _ssid) do { \ + rt_strncpy((char *)(_info)->ssid.val, (_ssid), RT_WLAN_SSID_MAX_LENGTH); \ + (_info)->ssid.len = rt_strlen((char *)(_info)->ssid.val); \ + } while(0) + struct rt_wlan_info { /* security type */ @@ -442,6 +447,7 @@ struct rt_wlan_device rt_wlan_pormisc_callback_t pormisc_callback; const struct rt_wlan_dev_ops *ops; rt_uint32_t flags; + struct netdev *netdev; void *prot; void *user_data; }; @@ -470,6 +476,7 @@ struct rt_scan_info rt_uint8_t bssid[6]; rt_int16_t channel_min; rt_int16_t channel_max; + rt_bool_t passive; }; struct rt_wlan_dev_ops diff --git a/components/drivers/wlan/wlan_lwip.c b/components/drivers/wlan/wlan_lwip.c index 84b448c68f..3c4e4dd598 100644 --- a/components/drivers/wlan/wlan_lwip.c +++ b/components/drivers/wlan/wlan_lwip.c @@ -14,12 +14,17 @@ #include <wlan_prot.h> #include <wlan_workqueue.h> +#if defined(RT_WLAN_PROT_ENABLE) && defined(RT_WLAN_PROT_LWIP_ENABLE) + #ifdef RT_USING_LWIP #include <netif/ethernetif.h> #include <lwip/netifapi.h> #ifdef LWIP_USING_DHCPD #include <dhcp_server.h> #endif +#ifdef RT_USING_NETDEV +#include <netdev.h> +#endif #define DBG_TAG "WLAN.lwip" #ifdef RT_WLAN_LWIP_DEBUG @@ -33,6 +38,10 @@ #define IPADDR_STRLEN_MAX (32) #endif +#ifndef RT_WLAN_PROT_LWIP_NAME +#define RT_WLAN_PROT_LWIP_NAME ("lwip") +#endif + struct lwip_prot_des { struct rt_wlan_prot prot; @@ -47,12 +56,16 @@ static void netif_is_ready(struct rt_work *work, void *parameter) ip_addr_t ip_addr_zero = { 0 }; struct rt_wlan_device *wlan = parameter; struct lwip_prot_des *lwip_prot = (struct lwip_prot_des *)wlan->prot; - struct eth_device *eth_dev = &lwip_prot->eth; + struct eth_device *eth_dev; rt_base_t level; struct rt_wlan_buff buff; rt_uint32_t ip_addr[4]; char str[IPADDR_STRLEN_MAX]; + if (lwip_prot == RT_NULL) + return; + + eth_dev = &lwip_prot->eth; rt_timer_stop(&lwip_prot->timer); if (ip_addr_cmp(&(eth_dev->netif->ip_addr), &ip_addr_zero) != 0) { @@ -100,18 +113,26 @@ static void netif_is_ready(struct rt_work *work, void *parameter) LOG_I("Got IP address : %s", str); exit: level = rt_hw_interrupt_disable(); - rt_memset(work, 0, sizeof(struct rt_work)); + if (work) + { + rt_memset(work, 0, sizeof(struct rt_work)); + } rt_hw_interrupt_enable(level); } static void timer_callback(void *parameter) { +#ifdef RT_WLAN_WORK_THREAD_ENABLE struct rt_workqueue *workqueue; struct rt_wlan_device *wlan = parameter; struct lwip_prot_des *lwip_prot = (struct lwip_prot_des *)wlan->prot; - struct rt_work *work = &lwip_prot->work; + struct rt_work *work; rt_base_t level; + if (lwip_prot == RT_NULL) + return; + + work = &lwip_prot->work; workqueue = rt_wlan_get_workqueue(); if (workqueue != RT_NULL) { @@ -125,13 +146,22 @@ static void timer_callback(void *parameter) rt_hw_interrupt_enable(level); } } +#else + netif_is_ready(RT_NULL, parameter); +#endif + } static void netif_set_connected(void *parameter) { struct rt_wlan_device *wlan = parameter; struct lwip_prot_des *lwip_prot = wlan->prot; - struct eth_device *eth_dev = &lwip_prot->eth; + struct eth_device *eth_dev; + + if (lwip_prot == RT_NULL) + return; + + eth_dev = &lwip_prot->eth; if (lwip_prot->connected_flag) { @@ -151,14 +181,10 @@ static void netif_set_connected(void *parameter) netifapi_netif_common(eth_dev->netif, netif_set_link_up, NULL); #ifdef LWIP_USING_DHCPD { - char netif_name[8]; - int i; + char netif_name[RT_NAME_MAX]; rt_memset(netif_name, 0, sizeof(netif_name)); - for (i = 0; i < sizeof(eth_dev->netif->name); i++) - { - netif_name[i] = eth_dev->netif->name[i]; - } + rt_memcpy(netif_name, eth_dev->netif->name, sizeof(eth_dev->netif->name)); dhcpd_start(netif_name); } #endif @@ -166,24 +192,24 @@ static void netif_set_connected(void *parameter) } else { - if (wlan->mode == RT_WLAN_STATION) - { - LOG_D("F:%s L:%d dhcp stop run", __FUNCTION__, __LINE__); - netifapi_netif_common(eth_dev->netif, netif_set_link_down, NULL); + LOG_D("F:%s L:%d set linkdown", __FUNCTION__, __LINE__); + netifapi_netif_common(eth_dev->netif, netif_set_link_down, NULL); + rt_timer_stop(&lwip_prot->timer); #ifdef RT_LWIP_DHCP - { - ip_addr_t ip_addr = { 0 }; - dhcp_stop(eth_dev->netif); - netif_set_addr(eth_dev->netif, &ip_addr, &ip_addr, &ip_addr); - } -#endif - rt_timer_stop(&lwip_prot->timer); + { + ip_addr_t ip_addr = { 0 }; + dhcp_stop(eth_dev->netif); + netif_set_addr(eth_dev->netif, &ip_addr, &ip_addr, &ip_addr); } - else if (wlan->mode == RT_WLAN_AP) +#endif +#ifdef LWIP_USING_DHCPD { - LOG_D("F:%s L:%d dhcpd stop run", __FUNCTION__, __LINE__); - netifapi_netif_common(eth_dev->netif, netif_set_link_down, NULL); + char netif_name[RT_NAME_MAX]; + rt_memset(netif_name, 0, sizeof(netif_name)); + rt_memcpy(netif_name, lwip_prot->eth.netif->name, sizeof(lwip_prot->eth.netif->name)); + dhcpd_stop(netif_name); } +#endif } } @@ -192,6 +218,9 @@ static void rt_wlan_lwip_event_handle(struct rt_wlan_prot *port, struct rt_wlan_ struct lwip_prot_des *lwip_prot = (struct lwip_prot_des *)wlan->prot; rt_bool_t flag_old; + if (lwip_prot == RT_NULL) + return; + flag_old = lwip_prot->connected_flag; switch (event) @@ -238,8 +267,11 @@ static void rt_wlan_lwip_event_handle(struct rt_wlan_prot *port, struct rt_wlan_ } if (flag_old != lwip_prot->connected_flag) { +#ifdef RT_WLAN_WORK_THREAD_ENABLE rt_wlan_workqueue_dowork(netif_set_connected, wlan); - // netif_set_connected(wlan); +#else + netif_set_connected(wlan); +#endif } } @@ -385,7 +417,7 @@ const static struct rt_device_ops wlan_lwip_ops = static struct rt_wlan_prot *rt_wlan_lwip_protocol_register(struct rt_wlan_prot *prot, struct rt_wlan_device *wlan) { struct eth_device *eth = RT_NULL; - static rt_uint8_t id = 0; + rt_uint8_t id = 0; char eth_name[4], timer_name[16]; rt_device_t device = RT_NULL; struct lwip_prot_des *lwip_prot; @@ -452,22 +484,43 @@ static struct rt_wlan_prot *rt_wlan_lwip_protocol_register(struct rt_wlan_prot * return RT_NULL; } rt_memcpy(&lwip_prot->prot, prot, sizeof(struct rt_wlan_prot)); - if (wlan->mode == RT_WLAN_STATION) - { - rt_sprintf(timer_name, "timer_%s", eth_name); - rt_timer_init(&lwip_prot->timer, timer_name, timer_callback, wlan, rt_tick_from_millisecond(1000), - RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_ONE_SHOT); - } + rt_sprintf(timer_name, "timer_%s", eth_name); + rt_timer_init(&lwip_prot->timer, timer_name, timer_callback, wlan, rt_tick_from_millisecond(1000), + RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_ONE_SHOT); netif_set_up(eth->netif); LOG_I("eth device init ok name:%s", eth_name); - +#ifdef RT_USING_NETDEV + wlan->netdev = netdev_get_by_name(eth_name); +#endif return &lwip_prot->prot; } static void rt_wlan_lwip_protocol_unregister(struct rt_wlan_prot *prot, struct rt_wlan_device *wlan) { - /*TODO*/ + struct lwip_prot_des *lwip_prot = (struct lwip_prot_des *)prot; + LOG_D("F:%s L:%d is run wlan:0x%08x", __FUNCTION__, __LINE__, wlan); +#if !defined(RT_USING_LWIP141) + wlan->prot = RT_NULL; + if (lwip_prot == RT_NULL) + { + return; + } + +#ifdef LWIP_USING_DHCPD + { + char netif_name[RT_NAME_MAX]; + rt_memset(netif_name, 0, sizeof(netif_name)); + rt_memcpy(netif_name, lwip_prot->eth.netif->name, sizeof(lwip_prot->eth.netif->name)); + dhcpd_stop(netif_name); + } +#endif + eth_device_deinit(&lwip_prot->eth); + rt_device_close((rt_device_t)wlan); + rt_timer_detach(&lwip_prot->timer); + wlan->netdev = RT_NULL; + rt_free(lwip_prot); +#endif } static struct rt_wlan_prot_ops ops = @@ -483,7 +536,7 @@ int rt_wlan_lwip_init(void) rt_wlan_prot_event_t event; rt_memset(&prot, 0, sizeof(prot)); - rt_strncpy(&prot.name[0], RT_WLAN_PROT_LWIP, RT_WLAN_PROT_NAME_LEN); + rt_strncpy(&prot.name[0], RT_WLAN_PROT_LWIP_NAME, RT_WLAN_PROT_NAME_LEN); prot.ops = &ops; if (rt_wlan_prot_regisetr(&prot) != RT_EOK) @@ -502,3 +555,4 @@ int rt_wlan_lwip_init(void) INIT_PREV_EXPORT(rt_wlan_lwip_init); #endif +#endif diff --git a/components/drivers/wlan/wlan_mgnt.c b/components/drivers/wlan/wlan_mgnt.c index 91a77e43d0..cf2204c6b3 100644 --- a/components/drivers/wlan/wlan_mgnt.c +++ b/components/drivers/wlan/wlan_mgnt.c @@ -24,6 +24,8 @@ #endif /* RT_WLAN_MGNT_DEBUG */ #include <rtdbg.h> +#ifdef RT_WLAN_MANAGE_ENABLE + #ifndef RT_WLAN_DEVICE #define RT_WLAN_DEVICE(__device) ((struct rt_wlan_device *)__device) #endif @@ -48,13 +50,16 @@ #define COMPLETE_LOCK() (rt_mutex_take(&complete_mutex, RT_WAITING_FOREVER)) #define COMPLETE_UNLOCK() (rt_mutex_release(&complete_mutex)) +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE #define TIME_STOP() (rt_timer_stop(&reconnect_time)) #define TIME_START() (rt_timer_start(&reconnect_time)) - -#define DISCONNECT_RESPONSE_TICK (2000) +#else +#define TIME_STOP() +#define TIME_START() +#endif #if RT_WLAN_EBOX_NUM < 1 -#error "event box num Too little" +#error "event box num Too few" #endif struct rt_wlan_mgnt_des @@ -113,8 +118,11 @@ static struct rt_wlan_event_desc event_tab[RT_WLAN_EVT_MAX]; static struct rt_wlan_complete_des *complete_tab[5]; static struct rt_mutex complete_mutex; +static struct rt_wlan_info *scan_filter; +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE static struct rt_timer reconnect_time; +#endif rt_inline int _sta_is_null(void) { @@ -145,9 +153,97 @@ rt_inline rt_bool_t _is_do_connect(void) return RT_TRUE; } -static void rt_wlan_mgnt_work(void *parameter); +#ifdef RT_WLAN_WORK_THREAD_ENABLE + +static rt_bool_t rt_wlan_info_isequ(struct rt_wlan_info *info1, struct rt_wlan_info *info2) +{ + rt_bool_t is_equ = 1; + rt_uint8_t bssid_zero[RT_WLAN_BSSID_MAX_LENGTH] = { 0 }; + + if (is_equ && (info1->security != SECURITY_UNKNOWN) && (info2->security != SECURITY_UNKNOWN)) + { + is_equ &= info2->security == info1->security; + } + if (is_equ && ((info1->ssid.len > 0) && (info2->ssid.len > 0))) + { + is_equ &= info1->ssid.len == info2->ssid.len; + is_equ &= rt_memcmp(&info2->ssid.val[0], &info1->ssid.val[0], info1->ssid.len) == 0; + } + if (is_equ && (rt_memcmp(&info1->bssid[0], bssid_zero, RT_WLAN_BSSID_MAX_LENGTH)) && + (rt_memcmp(&info2->bssid[0], bssid_zero, RT_WLAN_BSSID_MAX_LENGTH))) + { + is_equ &= rt_memcmp(&info1->bssid[0], &info2->bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0; + } + if (is_equ && info1->datarate && info2->datarate) + { + is_equ &= info1->datarate == info2->datarate; + } + if (is_equ && (info1->channel >= 0) && (info2->channel >= 0)) + { + is_equ &= info1->channel == info2->channel; + } + if (is_equ && (info1->rssi < 0) && (info2->rssi < 0)) + { + is_equ &= info1->rssi == info2->rssi; + } + return is_equ; +} + +static void rt_wlan_mgnt_work(void *parameter) +{ + struct rt_wlan_msg *msg = parameter; + void *user_parameter; + rt_wlan_event_handler handler = RT_NULL; + struct rt_wlan_buff user_buff = { 0 }; + rt_base_t level; + + /* Get user callback */ + if (msg->event < RT_WLAN_EVT_MAX) + { + level = rt_hw_interrupt_disable(); + handler = event_tab[msg->event].handler; + user_parameter = event_tab[msg->event].parameter; + rt_hw_interrupt_enable(level); + } + + /* run user callback fun */ + if (handler) + { + user_buff.data = msg->buff; + user_buff.len = msg->len; + RT_WLAN_LOG_D("wlan work thread run user callback, event:%d", msg->event); + handler(msg->event, &user_buff, user_parameter); + } + + switch (msg->event) + { + case RT_WLAN_EVT_STA_CONNECTED: + { + struct rt_wlan_cfg_info cfg_info; + + rt_memset(&cfg_info, 0, sizeof(cfg_info)); + /* save config */ + if (rt_wlan_is_connected() == RT_TRUE) + { + rt_enter_critical(); + cfg_info.info = _sta_mgnt.info; + cfg_info.key = _sta_mgnt.key; + rt_exit_critical(); + RT_WLAN_LOG_D("run save config! ssid:%s len%d", _sta_mgnt.info.ssid.val, _sta_mgnt.info.ssid.len); +#ifdef RT_WLAN_CFG_ENABLE + rt_wlan_cfg_save(&cfg_info); +#endif + } + break; + } + default : + break; + } + + rt_free(msg); +} -static rt_err_t rt_wlan_send_msg(rt_wlan_dev_event_t event, void *buff, int len) +static rt_err_t rt_wlan_send_to_thread(rt_wlan_event_t event, void *buff, int len) { struct rt_wlan_msg *msg; @@ -164,7 +260,8 @@ static rt_err_t rt_wlan_send_msg(rt_wlan_dev_event_t event, void *buff, int len) msg->event = event; if (len != 0) { - msg->buff = ((char *)msg) + sizeof(struct rt_wlan_msg); + msg->buff = (void *)&msg[1]; + rt_memcpy(msg->buff, buff, len); msg->len = len; } @@ -177,14 +274,16 @@ static rt_err_t rt_wlan_send_msg(rt_wlan_dev_event_t event, void *buff, int len) } return RT_EOK; } +#endif static rt_err_t rt_wlan_scan_result_cache(struct rt_wlan_info *info, int timeout) { struct rt_wlan_info *ptable; rt_err_t err = RT_EOK; int i, insert = -1; + rt_base_t level; - if (_sta_is_null() || (info == RT_NULL)) return RT_EOK; + if (_sta_is_null() || (info == RT_NULL) || (info->ssid.len == 0)) return RT_EOK; RT_WLAN_LOG_D("ssid:%s len:%d mac:%02x:%02x:%02x:%02x:%02x:%02x", info->ssid.val, info->ssid.len, info->bssid[0], info->bssid[1], info->bssid[2], info->bssid[3], info->bssid[4], info->bssid[5]); @@ -193,6 +292,23 @@ static rt_err_t rt_wlan_scan_result_cache(struct rt_wlan_info *info, int timeout if (err != RT_EOK) return err; + /* scanning result filtering */ + level = rt_hw_interrupt_disable(); + if (scan_filter) + { + struct rt_wlan_info _tmp_info = *scan_filter; + rt_hw_interrupt_enable(level); + if (rt_wlan_info_isequ(&_tmp_info, info) != RT_TRUE) + { + rt_mutex_release(&scan_result_mutex); + return RT_EOK; + } + } + else + { + rt_hw_interrupt_enable(level); + } + /* de-duplicatio */ for (i = 0; i < scan_result.num; i++) { @@ -381,7 +497,7 @@ static rt_err_t rt_wlan_sta_info_del_all(int timeout) sta_info.node = RT_NULL; return err; } - +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE static void rt_wlan_auto_connect_run(struct rt_work *work, void *parameter) { static rt_uint32_t id = 0; @@ -413,12 +529,12 @@ static void rt_wlan_auto_connect_run(struct rt_work *work, void *parameter) if (id >= rt_wlan_cfg_get_num()) id = 0; - if ((cfg_info.key.len > 0) && (cfg_info.key.len < RT_WLAN_PASSWORD_MAX_LENGTH)) + if ((cfg_info.key.len > 0) && (cfg_info.key.len <= RT_WLAN_PASSWORD_MAX_LENGTH)) { cfg_info.key.val[cfg_info.key.len] = '\0'; password = (char *)(&cfg_info.key.val[0]); } - rt_wlan_connect_adv(&cfg_info.info, password); + rt_wlan_connect((char *)cfg_info.info.ssid.val, password); exit: rt_mutex_release(&mgnt_mutex); level = rt_hw_interrupt_disable(); @@ -449,41 +565,10 @@ static void rt_wlan_cyclic_check(void *parameter) } } } - -static void rt_wlan_mgnt_work(void *parameter) -{ - struct rt_wlan_msg *msg = parameter; - - switch (msg->event) - { - case RT_WLAN_DEV_EVT_CONNECT: - { - struct rt_wlan_cfg_info cfg_info; - - /* save config */ - if (rt_wlan_is_connected() == RT_TRUE) - { - rt_enter_critical(); - cfg_info.info = _sta_mgnt.info; - cfg_info.key = _sta_mgnt.key; - rt_exit_critical(); - RT_WLAN_LOG_D("run save config! ssid:%s len%d", _sta_mgnt.info.ssid.val, _sta_mgnt.info.ssid.len); - rt_wlan_cfg_save(&cfg_info); - } - break; - } - default : - break; - } - - rt_free(msg); -} +#endif static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_event_t event, struct rt_wlan_buff *buff, void *parameter) { - rt_base_t level; - void *user_parameter; - rt_wlan_event_handler handler = RT_NULL; rt_err_t err = RT_NULL; rt_wlan_event_t user_event = RT_WLAN_EVT_MAX; int i; @@ -503,7 +588,6 @@ static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_ev _sta_mgnt.state &= ~RT_WLAN_STATE_CONNECTING; user_event = RT_WLAN_EVT_STA_CONNECTED; TIME_STOP(); - rt_wlan_send_msg(event, RT_NULL, 0); user_buff.data = &_sta_mgnt.info; user_buff.len = sizeof(struct rt_wlan_info); RT_WLAN_LOG_I("wifi connect success ssid:%s", &_sta_mgnt.info.ssid.val[0]); @@ -518,7 +602,10 @@ static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_ev user_event = RT_WLAN_EVT_STA_CONNECTED_FAIL; user_buff.data = &_sta_mgnt.info; user_buff.len = sizeof(struct rt_wlan_info); - TIME_START(); + if (rt_wlan_get_autoreconnect_mode()) + { + TIME_START(); + } break; } case RT_WLAN_DEV_EVT_DISCONNECT: @@ -529,7 +616,10 @@ static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_ev user_event = RT_WLAN_EVT_STA_DISCONNECTED; user_buff.data = &_sta_mgnt.info; user_buff.len = sizeof(struct rt_wlan_info); - TIME_START(); + if (rt_wlan_get_autoreconnect_mode()) + { + TIME_START(); + } break; } case RT_WLAN_DEV_EVT_AP_START: @@ -622,20 +712,30 @@ static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_ev } } COMPLETE_UNLOCK(); - /* Get user callback */ - if (user_event < RT_WLAN_EVT_MAX) +#ifdef RT_WLAN_WORK_THREAD_ENABLE + rt_wlan_send_to_thread(user_event, RT_NULL, 0); +#else { - level = rt_hw_interrupt_disable(); - handler = event_tab[user_event].handler; - user_parameter = event_tab[user_event].parameter; - rt_hw_interrupt_enable(level); - } + void *user_parameter; + rt_wlan_event_handler handler = RT_NULL; + rt_base_t level; + /* Get user callback */ + if (user_event < RT_WLAN_EVT_MAX) + { + level = rt_hw_interrupt_disable(); + handler = event_tab[user_event].handler; + user_parameter = event_tab[user_event].parameter; + rt_hw_interrupt_enable(level); + } - /* run user callback fun */ - if (handler) - { - handler(user_event, &user_buff, user_parameter); + /* run user callback fun */ + if (handler) + { + RT_WLAN_LOG_D("unknown thread run user callback, event:%d", user_event); + handler(user_event, &user_buff, user_parameter); + } } +#endif } static struct rt_wlan_complete_des *rt_wlan_complete_create(const char *name) @@ -820,14 +920,30 @@ rt_err_t rt_wlan_set_mode(const char *dev_name, rt_wlan_mode_t mode) /* update dev event handle */ if (up_event_flag == 1) { - rt_wlan_dev_event_t event; - for (event = RT_WLAN_DEV_EVT_INIT_DONE; event < RT_WLAN_DEV_EVT_MAX; event++) + if (handler) { - if (handler) + if (mode == RT_WLAN_STATION) + { + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_CONNECT, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_CONNECT_FAIL, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_DISCONNECT, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_SCAN_REPORT, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_SCAN_DONE, handler, RT_NULL); + } + else if (mode == RT_WLAN_AP) { - rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), event, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_AP_START, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_AP_STOP, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_AP_ASSOCIATED, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_AP_DISASSOCIATED, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_AP_ASSOCIATE_FAILED, handler, RT_NULL); } - else + } + else + { + rt_wlan_dev_event_t event; + handler = rt_wlan_event_dispatch; + for (event = RT_WLAN_DEV_EVT_INIT_DONE; event < RT_WLAN_DEV_EVT_MAX; event++) { rt_wlan_dev_unregister_event_handler(RT_WLAN_DEVICE(device), event, handler); } @@ -836,8 +952,11 @@ rt_err_t rt_wlan_set_mode(const char *dev_name, rt_wlan_mode_t mode) MGNT_UNLOCK(); /* Mount protocol */ -#ifdef RT_WLAN_DEFAULT_PROT - rt_wlan_prot_attach(dev_name, RT_WLAN_DEFAULT_PROT); +#if defined(RT_WLAN_PROT_ENABLE) && defined(RT_WLAN_DEFAULT_PROT) + if (err == RT_EOK) + { + rt_wlan_prot_attach(dev_name, RT_WLAN_DEFAULT_PROT); + } #endif return err; } @@ -932,6 +1051,7 @@ rt_err_t rt_wlan_connect(const char *ssid, const char *password) struct rt_wlan_info info; struct rt_wlan_complete_des *complete; rt_uint32_t set = 0, recved = 0; + rt_uint32_t scan_retry = RT_WLAN_SCAN_RETRY_CNT; /* sta dev Can't be NULL */ if (_sta_is_null()) @@ -960,12 +1080,11 @@ rt_err_t rt_wlan_connect(const char *ssid, const char *password) /* get info from cache */ INVALID_INFO(&info); MGNT_LOCK(); - if (rt_wlan_find_best_by_cache(ssid, &info) != RT_TRUE) + while (scan_retry-- && rt_wlan_find_best_by_cache(ssid, &info) != RT_TRUE) { rt_wlan_scan_sync(); - rt_wlan_find_best_by_cache(ssid, &info); - rt_wlan_scan_result_clean(); } + rt_wlan_scan_result_clean(); if (info.ssid.len <= 0) { @@ -1216,10 +1335,13 @@ rt_err_t rt_wlan_get_info(struct rt_wlan_info *info) } RT_WLAN_LOG_D("%s is run", __FUNCTION__); - rt_enter_critical(); - *info = _sta_mgnt.info; - rt_exit_critical(); - return RT_EOK; + if (rt_wlan_is_connected() == RT_TRUE) + { + *info = _sta_mgnt.info; + info->rssi = rt_wlan_get_rssi(); + return RT_EOK; + } + return -RT_ERROR; } int rt_wlan_get_rssi(void) @@ -1268,6 +1390,7 @@ rt_err_t rt_wlan_start_ap(const char *ssid, const char *password) rt_memcpy(&info.ssid.val, ssid, ssid_len); info.ssid.len = ssid_len; info.channel = 6; + info.band = RT_802_11_BAND_2_4GHZ; /* Initializing events that need to wait */ MGNT_LOCK(); @@ -1427,8 +1550,12 @@ rt_err_t rt_wlan_ap_get_info(struct rt_wlan_info *info) } RT_WLAN_LOG_D("%s is run", __FUNCTION__); - *info = _ap_mgnt.info; - return RT_EOK; + if (rt_wlan_ap_is_active() == RT_TRUE) + { + *info = _ap_mgnt.info; + return RT_EOK; + } + return -RT_ERROR; } /* get sta number */ @@ -1555,27 +1682,35 @@ rt_country_code_t rt_wlan_ap_get_country(void) void rt_wlan_config_autoreconnect(rt_bool_t enable) { +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE RT_WLAN_LOG_D("%s is run enable:%d", __FUNCTION__, enable); MGNT_LOCK(); if (enable) { + TIME_START(); _sta_mgnt.flags |= RT_WLAN_STATE_AUTOEN; } else { + TIME_STOP(); _sta_mgnt.flags &= ~RT_WLAN_STATE_AUTOEN; } MGNT_UNLOCK(); +#endif } rt_bool_t rt_wlan_get_autoreconnect_mode(void) { +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE rt_bool_t enable = 0; enable = _sta_mgnt.flags & RT_WLAN_STATE_AUTOEN ? 1 : 0; RT_WLAN_LOG_D("%s is run enable:%d", __FUNCTION__, enable); return enable; +#else + return RT_FALSE; +#endif } /* Call the underlying scan function, which is asynchronous. @@ -1612,6 +1747,9 @@ struct rt_wlan_scan_result *rt_wlan_scan_with_info(struct rt_wlan_info *info) rt_err_t err = RT_EOK; struct rt_wlan_complete_des *complete; rt_uint32_t set = 0, recved = 0; + static struct rt_wlan_info scan_filter_info; + rt_base_t level; + struct rt_wlan_scan_result *result; if (_sta_is_null()) { @@ -1633,14 +1771,23 @@ struct rt_wlan_scan_result *rt_wlan_scan_with_info(struct rt_wlan_info *info) return &scan_result; } + /* add scan info filter */ + if (info) + { + scan_filter_info = *info; + level = rt_hw_interrupt_disable(); + scan_filter = &scan_filter_info; + rt_hw_interrupt_enable(level); + } + /* run scan */ err = rt_wlan_dev_scan(STA_DEVICE(), info); if (err != RT_EOK) { rt_wlan_complete_delete(complete); RT_WLAN_LOG_E("scan sync fail"); - MGNT_UNLOCK(); - return RT_NULL; + result = RT_NULL; + goto scan_exit; } /* Initializing events that need to wait */ @@ -1653,12 +1800,17 @@ struct rt_wlan_scan_result *rt_wlan_scan_with_info(struct rt_wlan_info *info) if (!(recved & set)) { RT_WLAN_LOG_E("scan wait timeout!"); - MGNT_UNLOCK(); - return &scan_result; + result = &scan_result; + goto scan_exit; } +scan_exit: MGNT_UNLOCK(); - return &scan_result; + level = rt_hw_interrupt_disable(); + scan_filter = RT_NULL; + rt_hw_interrupt_enable(level); + result = &scan_result; + return result; } int rt_wlan_scan_get_info_num(void) @@ -1709,8 +1861,7 @@ int rt_wlan_scan_find_cache(struct rt_wlan_info *info, struct rt_wlan_info *out_ { int i = 0, count = 0; struct rt_wlan_info *scan_info; - rt_bool_t is_equ = 1; - rt_uint8_t bssid_zero[RT_WLAN_BSSID_MAX_LENGTH] = { 0 }; + rt_bool_t is_equ; if ((out_info == RT_NULL) || (info == RT_NULL) || (num <= 0)) { @@ -1721,31 +1872,7 @@ int rt_wlan_scan_find_cache(struct rt_wlan_info *info, struct rt_wlan_info *out_ for (i = 0; (i < scan_result.num) && (count < num); i++) { scan_info = &scan_result.info[i]; - - if (is_equ && (info->security != SECURITY_UNKNOWN)) - { - is_equ &= info->security == scan_info->security; - } - if (is_equ && ((info->ssid.len > 0) && (info->ssid.len == scan_info->ssid.len))) - { - is_equ &= rt_memcmp(&info->ssid.val[0], &scan_info->ssid.val[0], scan_info->ssid.len) == 0; - } - if (is_equ && (rt_memcmp(&info->bssid[0], bssid_zero, RT_WLAN_BSSID_MAX_LENGTH))) - { - is_equ &= rt_memcmp(&info->bssid[0], &scan_info->bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0; - } - if (is_equ && info->datarate) - { - is_equ &= info->datarate == scan_info->datarate; - } - if (is_equ && (info->channel >= 0)) - { - is_equ &= info->channel == scan_info->channel; - } - if (is_equ && (info->rssi < 0)) - { - is_equ &= info->rssi == scan_info->rssi; - } + is_equ = rt_wlan_info_isequ(scan_info, info); /* Determine whether to find */ if (is_equ) { @@ -1840,8 +1967,6 @@ void rt_wlan_mgnt_unlock(void) int rt_wlan_prot_ready_event(struct rt_wlan_device *wlan, struct rt_wlan_buff *buff) { rt_base_t level; - void *user_parameter; - rt_wlan_event_handler handler = RT_NULL; if ((wlan == RT_NULL) || (_sta_mgnt.device != wlan) || (!(_sta_mgnt.state & RT_WLAN_STATE_CONNECT))) @@ -1854,13 +1979,24 @@ int rt_wlan_prot_ready_event(struct rt_wlan_device *wlan, struct rt_wlan_buff *b } level = rt_hw_interrupt_disable(); _sta_mgnt.state |= RT_WLAN_STATE_READY; - handler = event_tab[RT_WLAN_EVT_READY].handler; - user_parameter = event_tab[RT_WLAN_EVT_READY].parameter; rt_hw_interrupt_enable(level); - if (handler) +#ifdef RT_WLAN_WORK_THREAD_ENABLE + rt_wlan_send_to_thread(RT_WLAN_EVT_READY, buff->data, buff->len); +#else { - handler(RT_WLAN_EVT_READY, buff, user_parameter); + void *user_parameter; + rt_wlan_event_handler handler = RT_NULL; + + level = rt_hw_interrupt_disable(); + handler = event_tab[RT_WLAN_EVT_READY].handler; + user_parameter = event_tab[RT_WLAN_EVT_READY].parameter; + rt_hw_interrupt_enable(level); + if (handler) + { + handler(RT_WLAN_EVT_READY, buff, user_parameter); + } } +#endif return 0; } @@ -1879,10 +2015,15 @@ int rt_wlan_init(void) rt_mutex_init(&scan_result_mutex, "scan", RT_IPC_FLAG_FIFO); rt_mutex_init(&sta_info_mutex, "sta", RT_IPC_FLAG_FIFO); rt_mutex_init(&complete_mutex, "complete", RT_IPC_FLAG_FIFO); - rt_timer_init(&reconnect_time, "wifi_tim", rt_wlan_cyclic_check, RT_NULL, DISCONNECT_RESPONSE_TICK, RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER); - rt_timer_start(&reconnect_time); +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE + rt_timer_init(&reconnect_time, "wifi_tim", rt_wlan_cyclic_check, RT_NULL, + rt_tick_from_millisecond(AUTO_CONNECTION_PERIOD_MS), + RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER); +#endif _init_flag = 1; } return 0; } INIT_PREV_EXPORT(rt_wlan_init); + +#endif diff --git a/components/drivers/wlan/wlan_mgnt.h b/components/drivers/wlan/wlan_mgnt.h index f4d9e0cff9..df0827bb7b 100644 --- a/components/drivers/wlan/wlan_mgnt.h +++ b/components/drivers/wlan/wlan_mgnt.h @@ -37,6 +37,14 @@ extern "C" { #define RT_WLAN_EBOX_NUM (10) #endif +#ifndef RT_WLAN_SCAN_RETRY_CNT +#define RT_WLAN_SCAN_RETRY_CNT (3) +#endif + +#ifndef AUTO_CONNECTION_PERIOD_MS +#define AUTO_CONNECTION_PERIOD_MS (2000) +#endif + /*state fot station*/ #define RT_WLAN_STATE_CONNECT (1UL << 0) #define RT_WLAN_STATE_CONNECTING (1UL << 1) diff --git a/components/drivers/wlan/wlan_prot.c b/components/drivers/wlan/wlan_prot.c index 0402962e01..b1a1b5de99 100644 --- a/components/drivers/wlan/wlan_prot.c +++ b/components/drivers/wlan/wlan_prot.c @@ -21,6 +21,8 @@ #endif /* RT_WLAN_PROT_DEBUG */ #include <rtdbg.h> +#ifdef RT_WLAN_PROT_ENABLE + #if RT_WLAN_PROT_NAME_LEN < 4 #error "The name is too short" #endif @@ -160,7 +162,7 @@ rt_err_t rt_wlan_prot_attach_dev(struct rt_wlan_device *wlan, const char *prot_n { int i = 0; struct rt_wlan_prot *prot = wlan->prot; - rt_wlan_dev_event_t event; + rt_wlan_dev_event_handler handler = rt_wlan_prot_event_handle; if (wlan == RT_NULL) { @@ -180,7 +182,7 @@ rt_err_t rt_wlan_prot_attach_dev(struct rt_wlan_device *wlan, const char *prot_n rt_wlan_prot_detach_dev(wlan); #ifdef RT_WLAN_PROT_LWIP_PBUF_FORCE - if (rt_strcmp(RT_WLAN_PROT_LWIP, prot_name) != 0) + if (rt_strcmp(RT_WLAN_PROT_LWIP_NAME, prot_name) != 0) { return -RT_ERROR; } @@ -202,13 +204,12 @@ rt_err_t rt_wlan_prot_attach_dev(struct rt_wlan_device *wlan, const char *prot_n return -RT_ERROR; } - for (event = RT_WLAN_DEV_EVT_INIT_DONE; event < RT_WLAN_DEV_EVT_MAX; event ++) - { - if (rt_wlan_dev_register_event_handler(wlan, event, rt_wlan_prot_event_handle, RT_NULL) != RT_EOK) - { - LOG_E("prot register event filed:%d", event); - } - } + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_CONNECT, handler, RT_NULL); + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_DISCONNECT, handler, RT_NULL); + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_AP_START, handler, RT_NULL); + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_AP_STOP, handler, RT_NULL); + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_AP_ASSOCIATED, handler, RT_NULL); + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_AP_DISASSOCIATED, handler, RT_NULL); return RT_EOK; } @@ -360,3 +361,4 @@ void rt_wlan_prot_dump(void) } } } +#endif diff --git a/components/drivers/wlan/wlan_prot.h b/components/drivers/wlan/wlan_prot.h index 34c5bae7fd..2df979270f 100644 --- a/components/drivers/wlan/wlan_prot.h +++ b/components/drivers/wlan/wlan_prot.h @@ -25,8 +25,6 @@ extern "C" { #define RT_LWAN_ID_PREFIX (0x5054) -#define RT_WLAN_PROT_LWIP ("lwip") - typedef enum { RT_WLAN_PROT_EVT_INIT_DONE = 0, diff --git a/components/drivers/wlan/wlan_workqueue.c b/components/drivers/wlan/wlan_workqueue.c index ec21243d60..4cd98346d2 100644 --- a/components/drivers/wlan/wlan_workqueue.c +++ b/components/drivers/wlan/wlan_workqueue.c @@ -17,6 +17,8 @@ #define DBG_LVL DBG_INFO #include <rtdbg.h> +#ifdef RT_WLAN_WORK_THREAD_ENABLE + struct rt_wlan_work { struct rt_work work; @@ -95,3 +97,5 @@ int rt_wlan_workqueue_init(void) return 0; } INIT_PREV_EXPORT(rt_wlan_workqueue_init); + +#endif |
