From b4de7cce57305033e86c3b187271683b609ddb26 Mon Sep 17 00:00:00 2001 From: "Ming, Bai" Date: Tue, 8 Jan 2013 22:40:58 +0800 Subject: Re-normalizing the repo --- components/drivers/SConscript | 28 +- components/drivers/i2c/SConscript | 36 +- components/drivers/include/drivers/mtd_nand.h | 238 +- components/drivers/include/drivers/mtd_nor.h | 142 +- components/drivers/include/drivers/sd.h | 64 +- components/drivers/include/drivers/sdio.h | 398 +-- components/drivers/include/drivers/sdio_func_ids.h | 88 +- components/drivers/include/drivers/serial.h | 24 +- components/drivers/include/drivers/usb_common.h | 756 +++--- components/drivers/include/drivers/usb_device.h | 534 ++-- components/drivers/include/drivers/usb_host.h | 552 ++-- components/drivers/include/rtdevice.h | 6 +- components/drivers/mtd/SConscript | 44 +- components/drivers/rtc/SConscript | 38 +- components/drivers/sdio/SConscript | 34 +- components/drivers/sdio/sdio.c | 2662 ++++++++++---------- components/drivers/serial/SConscript | 16 +- components/drivers/spi/SConscript | 16 +- components/drivers/src/SConscript | 16 +- components/drivers/usb/SConscript | 28 +- components/drivers/usb/usbdevice/SConscript | 46 +- components/drivers/usb/usbdevice/class/cdc.h | 348 +-- components/drivers/usb/usbdevice/class/cdc_vcom.c | 1182 ++++----- components/drivers/usb/usbdevice/class/mstorage.c | 1196 ++++----- components/drivers/usb/usbdevice/class/mstorage.h | 132 +- components/drivers/usb/usbdevice/core/core.c | 2642 +++++++++---------- components/drivers/usb/usbdevice/core/usbdevice.c | 234 +- components/drivers/usb/usbhost/SConscript | 68 +- components/drivers/usb/usbhost/class/adk.c | 814 +++--- components/drivers/usb/usbhost/class/adk.h | 94 +- components/drivers/usb/usbhost/core/core.c | 938 +++---- components/drivers/usb/usbhost/core/driver.c | 288 +-- components/drivers/usb/usbhost/core/hub.c | 1222 ++++----- components/drivers/usb/usbhost/core/usbhost.c | 148 +- 34 files changed, 7536 insertions(+), 7536 deletions(-) (limited to 'components/drivers') diff --git a/components/drivers/SConscript b/components/drivers/SConscript index 1cb7618499..744d8d7821 100644 --- a/components/drivers/SConscript +++ b/components/drivers/SConscript @@ -1,14 +1,14 @@ -# for module compiling -import os -from building import * - -cwd = GetCurrentDir() -objs = [] -list = os.listdir(cwd) - -for d in list: - path = os.path.join(cwd, d) - if os.path.isfile(os.path.join(path, 'SConscript')): - objs = objs + SConscript(os.path.join(d, 'SConscript')) - -Return('objs') +# for module compiling +import os +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/components/drivers/i2c/SConscript b/components/drivers/i2c/SConscript index 0607250da4..5e85a645a7 100644 --- a/components/drivers/i2c/SConscript +++ b/components/drivers/i2c/SConscript @@ -1,18 +1,18 @@ -Import('RTT_ROOT') -from building import * - -cwd = GetCurrentDir() -src = Split(""" -i2c_core.c -i2c_dev.c -""") - -if GetDepend('RT_USING_I2C_BITOPS'): - src = src + ['i2c-bit-ops.c'] - -# The set of source files associated with this SConscript file. -path = [cwd + '/../include'] - -group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_I2C'], CPPPATH = path) - -Return('group') +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +src = Split(""" +i2c_core.c +i2c_dev.c +""") + +if GetDepend('RT_USING_I2C_BITOPS'): + src = src + ['i2c-bit-ops.c'] + +# The set of source files associated with this SConscript file. +path = [cwd + '/../include'] + +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_I2C'], CPPPATH = path) + +Return('group') diff --git a/components/drivers/include/drivers/mtd_nand.h b/components/drivers/include/drivers/mtd_nand.h index 4ea2a92d40..45c3016e5c 100644 --- a/components/drivers/include/drivers/mtd_nand.h +++ b/components/drivers/include/drivers/mtd_nand.h @@ -1,119 +1,119 @@ -/* - * File : mtd_nand.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2011-12-05 Bernard the first version - * 2011-04-02 prife add mark_badblock and check_block - */ - -/* - * COPYRIGHT (C) 2012, Shanghai Real Thread - */ - -#ifndef __MTD_NAND_H__ -#define __MTD_NAND_H__ - -#include - -struct rt_mtd_nand_driver_ops; -#define RT_MTD_NAND_DEVICE(device) ((struct rt_mtd_nand_device*)(device)) - -#define RT_MTD_EOK 0 -#define RT_MTD_EECC 1 -#define RT_MTD_EBUSY 2 -#define RT_MTD_EIO 3 -#define RT_MTD_ENOMEM 4 - -struct rt_mtd_nand_device -{ - struct rt_device parent; - - rt_uint16_t page_size; /* The Page size in the flash */ - rt_uint16_t oob_size; /* Out of bank size */ - rt_uint16_t oob_free; /* the free area in oob that flash driver not use */ - rt_uint16_t plane_num; /* the number of plane in the NAND Flash */ - - rt_uint32_t pages_per_block; /* The number of page a block */ - rt_uint16_t block_total; - - 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; -}; - -struct rt_mtd_nand_driver_ops -{ - rt_err_t (*read_id) (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_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); - - 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_inline rt_uint32_t rt_mtd_nand_read_id(struct rt_mtd_nand_device* device) -{ - return device->ops->read_id(device); -} - -rt_inline rt_err_t rt_mtd_nand_read( - 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) -{ - 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, - rt_off_t page, - const rt_uint8_t* data, rt_uint32_t data_len, - const rt_uint8_t * spare, rt_uint32_t spare_len) -{ - 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) -{ - 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) -{ - 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) -{ - return device->ops->check_block(device, 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); -} - -#endif /* MTD_NAND_H_ */ +/* + * File : mtd_nand.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2011-12-05 Bernard the first version + * 2011-04-02 prife add mark_badblock and check_block + */ + +/* + * COPYRIGHT (C) 2012, Shanghai Real Thread + */ + +#ifndef __MTD_NAND_H__ +#define __MTD_NAND_H__ + +#include + +struct rt_mtd_nand_driver_ops; +#define RT_MTD_NAND_DEVICE(device) ((struct rt_mtd_nand_device*)(device)) + +#define RT_MTD_EOK 0 +#define RT_MTD_EECC 1 +#define RT_MTD_EBUSY 2 +#define RT_MTD_EIO 3 +#define RT_MTD_ENOMEM 4 + +struct rt_mtd_nand_device +{ + struct rt_device parent; + + rt_uint16_t page_size; /* The Page size in the flash */ + rt_uint16_t oob_size; /* Out of bank size */ + rt_uint16_t oob_free; /* the free area in oob that flash driver not use */ + rt_uint16_t plane_num; /* the number of plane in the NAND Flash */ + + rt_uint32_t pages_per_block; /* The number of page a block */ + rt_uint16_t block_total; + + 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; +}; + +struct rt_mtd_nand_driver_ops +{ + rt_err_t (*read_id) (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_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); + + 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_inline rt_uint32_t rt_mtd_nand_read_id(struct rt_mtd_nand_device* device) +{ + return device->ops->read_id(device); +} + +rt_inline rt_err_t rt_mtd_nand_read( + 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) +{ + 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, + rt_off_t page, + const rt_uint8_t* data, rt_uint32_t data_len, + const rt_uint8_t * spare, rt_uint32_t spare_len) +{ + 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) +{ + 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) +{ + 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) +{ + return device->ops->check_block(device, 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); +} + +#endif /* MTD_NAND_H_ */ diff --git a/components/drivers/include/drivers/mtd_nor.h b/components/drivers/include/drivers/mtd_nor.h index 044993b16f..9797b167de 100644 --- a/components/drivers/include/drivers/mtd_nor.h +++ b/components/drivers/include/drivers/mtd_nor.h @@ -1,71 +1,71 @@ -/* - * File : mtd_nor.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2012, Shanghai Real-Thread Technology Co., Ltd - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2012-5-30 Bernard the first version - */ - -#ifndef __MTD_NOR_H__ -#define __MTD_NOR_H__ - -#include - -struct rt_mtd_nor_driver_ops; -#define RT_MTD_NOR_DEVICE(device) ((struct rt_mtd_nor_device*)(device)) - -struct rt_mtd_nor_device -{ - struct rt_device parent; - - rt_uint32_t block_size; /* The Block size in the flash */ - 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_nor_driver_ops* ops; -}; - -struct rt_mtd_nor_driver_ops -{ - rt_err_t (*read_id) (struct rt_mtd_nor_device* device); - - rt_size_t (*read) (struct rt_mtd_nor_device* device, rt_off_t offset, rt_uint8_t* data, rt_uint32_t length); - rt_size_t (*write) (struct rt_mtd_nor_device* device, rt_off_t offset, const rt_uint8_t* data, rt_uint32_t length); - - rt_err_t (*erase_block)(struct rt_mtd_nor_device* device, rt_off_t offset, rt_uint32_t length); -}; - -rt_err_t rt_mtd_nor_register_device(const char* name, struct rt_mtd_nor_device* device); - -rt_inline rt_uint32_t rt_mtd_nor_read_id(struct rt_mtd_nor_device* device) -{ - return device->ops->read_id(device); -} - -rt_inline rt_size_t rt_mtd_nor_read( - struct rt_mtd_nor_device* device, - rt_off_t offset, rt_uint8_t* data, rt_uint32_t length) -{ - return device->ops->read(device, offset, data, length); -} - -rt_inline rt_size_t rt_mtd_nor_write( - struct rt_mtd_nor_device* device, - rt_off_t offset, const rt_uint8_t* data, rt_uint32_t length) -{ - return device->ops->write(device, offset, data, length); -} - -rt_inline rt_err_t rt_mtd_nor_erase_block(struct rt_mtd_nor_device* device, rt_off_t offset, rt_size_t length) -{ - return device->ops->erase_block(device, offset, length); -} - -#endif +/* + * File : mtd_nor.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2012, Shanghai Real-Thread Technology Co., Ltd + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2012-5-30 Bernard the first version + */ + +#ifndef __MTD_NOR_H__ +#define __MTD_NOR_H__ + +#include + +struct rt_mtd_nor_driver_ops; +#define RT_MTD_NOR_DEVICE(device) ((struct rt_mtd_nor_device*)(device)) + +struct rt_mtd_nor_device +{ + struct rt_device parent; + + rt_uint32_t block_size; /* The Block size in the flash */ + 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_nor_driver_ops* ops; +}; + +struct rt_mtd_nor_driver_ops +{ + rt_err_t (*read_id) (struct rt_mtd_nor_device* device); + + rt_size_t (*read) (struct rt_mtd_nor_device* device, rt_off_t offset, rt_uint8_t* data, rt_uint32_t length); + rt_size_t (*write) (struct rt_mtd_nor_device* device, rt_off_t offset, const rt_uint8_t* data, rt_uint32_t length); + + rt_err_t (*erase_block)(struct rt_mtd_nor_device* device, rt_off_t offset, rt_uint32_t length); +}; + +rt_err_t rt_mtd_nor_register_device(const char* name, struct rt_mtd_nor_device* device); + +rt_inline rt_uint32_t rt_mtd_nor_read_id(struct rt_mtd_nor_device* device) +{ + return device->ops->read_id(device); +} + +rt_inline rt_size_t rt_mtd_nor_read( + struct rt_mtd_nor_device* device, + rt_off_t offset, rt_uint8_t* data, rt_uint32_t length) +{ + return device->ops->read(device, offset, data, length); +} + +rt_inline rt_size_t rt_mtd_nor_write( + struct rt_mtd_nor_device* device, + rt_off_t offset, const rt_uint8_t* data, rt_uint32_t length) +{ + return device->ops->write(device, offset, data, length); +} + +rt_inline rt_err_t rt_mtd_nor_erase_block(struct rt_mtd_nor_device* device, rt_off_t offset, rt_size_t length) +{ + return device->ops->erase_block(device, offset, length); +} + +#endif diff --git a/components/drivers/include/drivers/sd.h b/components/drivers/include/drivers/sd.h index b2491d7528..a2a330d6dd 100644 --- a/components/drivers/include/drivers/sd.h +++ b/components/drivers/include/drivers/sd.h @@ -1,32 +1,32 @@ -#ifndef __SD_H__ -#define __SD_H__ -/* - * File : sd.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2011-07-25 weety first version - */ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -rt_err_t mmcsd_send_if_cond(struct rt_mmcsd_host *host, rt_uint32_t ocr); -rt_err_t mmcsd_send_app_op_cond(struct rt_mmcsd_host *host, rt_uint32_t ocr, rt_uint32_t *rocr); -rt_int32_t init_sd(struct rt_mmcsd_host *host, rt_uint32_t ocr); - -#ifdef __cplusplus -} -#endif - -#endif +#ifndef __SD_H__ +#define __SD_H__ +/* + * File : sd.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2011-07-25 weety first version + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +rt_err_t mmcsd_send_if_cond(struct rt_mmcsd_host *host, rt_uint32_t ocr); +rt_err_t mmcsd_send_app_op_cond(struct rt_mmcsd_host *host, rt_uint32_t ocr, rt_uint32_t *rocr); +rt_int32_t init_sd(struct rt_mmcsd_host *host, rt_uint32_t ocr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/include/drivers/sdio.h b/components/drivers/include/drivers/sdio.h index 5a0272bdb3..d61bcfa392 100644 --- a/components/drivers/include/drivers/sdio.h +++ b/components/drivers/include/drivers/sdio.h @@ -1,199 +1,199 @@ -/* - * File : sdio.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2012-01-15 weety first version - */ - - -#ifndef __SDIO_H__ -#define __SDIO_H__ - - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Card Common Control Registers (CCCR) - */ - -#define SDIO_REG_CCCR_CCCR_REV 0x00 - -#define SDIO_CCCR_REV_1_00 0 /* CCCR/FBR Version 1.00 */ -#define SDIO_CCCR_REV_1_10 1 /* CCCR/FBR Version 1.10 */ -#define SDIO_CCCR_REV_1_20 2 /* CCCR/FBR Version 1.20 */ - -#define SDIO_SDIO_REV_1_00 0 /* SDIO Spec Version 1.00 */ -#define SDIO_SDIO_REV_1_10 1 /* SDIO Spec Version 1.10 */ -#define SDIO_SDIO_REV_1_20 2 /* SDIO Spec Version 1.20 */ -#define SDIO_SDIO_REV_2_00 3 /* SDIO Spec Version 2.00 */ - -#define SDIO_REG_CCCR_SD_REV 0x01 - -#define SDIO_SD_REV_1_01 0 /* SD Physical Spec Version 1.01 */ -#define SDIO_SD_REV_1_10 1 /* SD Physical Spec Version 1.10 */ -#define SDIO_SD_REV_2_00 2 /* SD Physical Spec Version 2.00 */ - -#define SDIO_REG_CCCR_IO_EN 0x02 -#define SDIO_REG_CCCR_IO_RDY 0x03 - -#define SDIO_REG_CCCR_INT_EN 0x04 /* Function/Master Interrupt Enable */ -#define SDIO_REG_CCCR_INT_PEND 0x05 /* Function Interrupt Pending */ - -#define SDIO_REG_CCCR_IO_ABORT 0x06 /* function abort/card reset */ - -#define SDIO_REG_CCCR_BUS_IF 0x07 /* bus interface controls */ - -#define SDIO_BUS_WIDTH_1BIT 0x00 -#define SDIO_BUS_WIDTH_4BIT 0x02 -#define SDIO_BUS_ECSI 0x20 /* Enable continuous SPI interrupt */ -#define SDIO_BUS_SCSI 0x40 /* Support continuous SPI interrupt */ - -#define SDIO_BUS_ASYNC_INT 0x20 - -#define SDIO_BUS_CD_DISABLE 0x80 /* disable pull-up on DAT3 (pin 1) */ - -#define SDIO_REG_CCCR_CARD_CAPS 0x08 - -#define SDIO_CCCR_CAP_SDC 0x01 /* can do CMD52 while data transfer */ -#define SDIO_CCCR_CAP_SMB 0x02 /* can do multi-block xfers (CMD53) */ -#define SDIO_CCCR_CAP_SRW 0x04 /* supports read-wait protocol */ -#define SDIO_CCCR_CAP_SBS 0x08 /* supports suspend/resume */ -#define SDIO_CCCR_CAP_S4MI 0x10 /* interrupt during 4-bit CMD53 */ -#define SDIO_CCCR_CAP_E4MI 0x20 /* enable ints during 4-bit CMD53 */ -#define SDIO_CCCR_CAP_LSC 0x40 /* low speed card */ -#define SDIO_CCCR_CAP_4BLS 0x80 /* 4 bit low speed card */ - -#define SDIO_REG_CCCR_CIS_PTR 0x09 /* common CIS pointer (3 bytes) */ - -/* Following 4 regs are valid only if SBS is set */ -#define SDIO_REG_CCCR_BUS_SUSPEND 0x0c -#define SDIO_REG_CCCR_FUNC_SEL 0x0d -#define SDIO_REG_CCCR_EXEC_FLAG 0x0e -#define SDIO_REG_CCCR_READY_FLAG 0x0f - -#define SDIO_REG_CCCR_FN0_BLKSIZE 0x10 /* 2bytes, 0x10~0x11 */ - -#define SDIO_REG_CCCR_POWER_CTRL 0x12 - -#define SDIO_POWER_SMPC 0x01 /* Supports Master Power Control */ -#define SDIO_POWER_EMPC 0x02 /* Enable Master Power Control */ - -#define SDIO_REG_CCCR_SPEED 0x13 - -#define SDIO_SPEED_SHS 0x01 /* Supports High-Speed mode */ -#define SDIO_SPEED_EHS 0x02 /* Enable High-Speed mode */ - -/* - * Function Basic Registers (FBR) - */ - -#define SDIO_REG_FBR_BASE(f) ((f) * 0x100) /* base of function f's FBRs */ - -#define SDIO_REG_FBR_STD_FUNC_IF 0x00 - -#define SDIO_FBR_SUPPORTS_CSA 0x40 /* supports Code Storage Area */ -#define SDIO_FBR_ENABLE_CSA 0x80 /* enable Code Storage Area */ - -#define SDIO_REG_FBR_STD_IF_EXT 0x01 - -#define SDIO_REG_FBR_POWER 0x02 - -#define SDIO_FBR_POWER_SPS 0x01 /* Supports Power Selection */ -#define SDIO_FBR_POWER_EPS 0x02 /* Enable (low) Power Selection */ - -#define SDIO_REG_FBR_CIS 0x09 /* CIS pointer (3 bytes) */ - - -#define SDIO_REG_FBR_CSA 0x0C /* CSA pointer (3 bytes) */ - -#define SDIO_REG_FBR_CSA_DATA 0x0F - -#define SDIO_REG_FBR_BLKSIZE 0x10 /* block size (2 bytes) */ - - -/* SDIO CIS Tuple code */ -#define CISTPL_NULL 0x00 -#define CISTPL_CHECKSUM 0x10 -#define CISTPL_VERS_1 0x15 -#define CISTPL_ALTSTR 0x16 -#define CISTPL_MANFID 0x20 -#define CISTPL_FUNCID 0x21 -#define CISTPL_FUNCE 0x22 -#define CISTPL_SDIO_STD 0x91 -#define CISTPL_SDIO_EXT 0x92 -#define CISTPL_END 0xff - -/* SDIO device id */ -#define SDIO_ANY_FUNC_ID 0xff -#define SDIO_ANY_MAN_ID 0xffff -#define SDIO_ANY_PROD_ID 0xffff - -struct rt_sdio_device_id { - rt_uint8_t func_code; - rt_uint16_t manufacturer; - rt_uint16_t product; -}; - -struct rt_sdio_driver { - char *name; - rt_int32_t (*probe)(struct rt_mmcsd_card *card); - rt_int32_t (*remove)(struct rt_mmcsd_card *card); - struct rt_sdio_device_id *id; -}; - - - -rt_int32_t sdio_io_send_op_cond(struct rt_mmcsd_host *host, rt_uint32_t ocr, rt_uint32_t -*cmd5_resp); -rt_int32_t sdio_io_rw_direct(struct rt_mmcsd_card *card, rt_int32_t rw, rt_uint32_t fn, - rt_uint32_t reg_addr, rt_uint8_t *pdata, rt_uint8_t raw); -rt_int32_t sdio_io_rw_extended(struct rt_mmcsd_card *card, rt_int32_t rw, rt_uint32_t fn, - rt_uint32_t addr, rt_int32_t op_code, rt_uint8_t *buf, rt_uint32_t blocks, rt_uint32_t blksize); -rt_uint8_t sdio_io_readb(struct rt_sdio_function *func, - rt_uint32_t reg, rt_int32_t *err); -rt_int32_t sdio_io_writeb(struct rt_sdio_function *func, - rt_uint32_t reg, rt_uint8_t data); -rt_uint16_t sdio_io_readw(struct rt_sdio_function *func, rt_uint32_t addr, rt_int32_t *err); -rt_int32_t sdio_io_writew(struct rt_sdio_function *func, rt_uint16_t data, rt_uint32_t addr); -rt_uint32_t sdio_io_readl(struct rt_sdio_function *func, rt_uint32_t addr, rt_int32_t *err); -rt_int32_t sdio_io_writel(struct rt_sdio_function *func, rt_uint32_t data, rt_uint32_t addr); -rt_int32_t sdio_io_read_multi_fifo_b(struct rt_sdio_function *func, - rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t len); -rt_int32_t sdio_io_write_multi_fifo_b(struct rt_sdio_function *func, - rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t len); -rt_int32_t sdio_io_read_multi_incr_b(struct rt_sdio_function *func, - rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t len); -rt_int32_t sdio_io_write_multi_incr_b(struct rt_sdio_function *func, - rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t len); -rt_int32_t init_sdio(struct rt_mmcsd_host *host, rt_uint32_t ocr); -rt_int32_t sdio_attach_irq(struct rt_sdio_function *func, rt_sdio_irq_handler_t *handler); -rt_int32_t sdio_detach_irq(struct rt_sdio_function *func); -void sdio_irq_wakeup(struct rt_mmcsd_host *host); -rt_int32_t sdio_enable_func(struct rt_sdio_function *func); -rt_int32_t sdio_disable_func(struct rt_sdio_function *func); -rt_int32_t sdio_set_block_size(struct rt_sdio_function *func, rt_uint32_t blksize); -rt_int32_t sdio_register_driver(struct rt_sdio_driver *driver); -rt_int32_t sdio_unregister_driver(struct rt_sdio_driver *driver); -void rt_sdio_init(void); - - -#ifdef __cplusplus -} -#endif - -#endif - +/* + * File : sdio.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2012-01-15 weety first version + */ + + +#ifndef __SDIO_H__ +#define __SDIO_H__ + + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Card Common Control Registers (CCCR) + */ + +#define SDIO_REG_CCCR_CCCR_REV 0x00 + +#define SDIO_CCCR_REV_1_00 0 /* CCCR/FBR Version 1.00 */ +#define SDIO_CCCR_REV_1_10 1 /* CCCR/FBR Version 1.10 */ +#define SDIO_CCCR_REV_1_20 2 /* CCCR/FBR Version 1.20 */ + +#define SDIO_SDIO_REV_1_00 0 /* SDIO Spec Version 1.00 */ +#define SDIO_SDIO_REV_1_10 1 /* SDIO Spec Version 1.10 */ +#define SDIO_SDIO_REV_1_20 2 /* SDIO Spec Version 1.20 */ +#define SDIO_SDIO_REV_2_00 3 /* SDIO Spec Version 2.00 */ + +#define SDIO_REG_CCCR_SD_REV 0x01 + +#define SDIO_SD_REV_1_01 0 /* SD Physical Spec Version 1.01 */ +#define SDIO_SD_REV_1_10 1 /* SD Physical Spec Version 1.10 */ +#define SDIO_SD_REV_2_00 2 /* SD Physical Spec Version 2.00 */ + +#define SDIO_REG_CCCR_IO_EN 0x02 +#define SDIO_REG_CCCR_IO_RDY 0x03 + +#define SDIO_REG_CCCR_INT_EN 0x04 /* Function/Master Interrupt Enable */ +#define SDIO_REG_CCCR_INT_PEND 0x05 /* Function Interrupt Pending */ + +#define SDIO_REG_CCCR_IO_ABORT 0x06 /* function abort/card reset */ + +#define SDIO_REG_CCCR_BUS_IF 0x07 /* bus interface controls */ + +#define SDIO_BUS_WIDTH_1BIT 0x00 +#define SDIO_BUS_WIDTH_4BIT 0x02 +#define SDIO_BUS_ECSI 0x20 /* Enable continuous SPI interrupt */ +#define SDIO_BUS_SCSI 0x40 /* Support continuous SPI interrupt */ + +#define SDIO_BUS_ASYNC_INT 0x20 + +#define SDIO_BUS_CD_DISABLE 0x80 /* disable pull-up on DAT3 (pin 1) */ + +#define SDIO_REG_CCCR_CARD_CAPS 0x08 + +#define SDIO_CCCR_CAP_SDC 0x01 /* can do CMD52 while data transfer */ +#define SDIO_CCCR_CAP_SMB 0x02 /* can do multi-block xfers (CMD53) */ +#define SDIO_CCCR_CAP_SRW 0x04 /* supports read-wait protocol */ +#define SDIO_CCCR_CAP_SBS 0x08 /* supports suspend/resume */ +#define SDIO_CCCR_CAP_S4MI 0x10 /* interrupt during 4-bit CMD53 */ +#define SDIO_CCCR_CAP_E4MI 0x20 /* enable ints during 4-bit CMD53 */ +#define SDIO_CCCR_CAP_LSC 0x40 /* low speed card */ +#define SDIO_CCCR_CAP_4BLS 0x80 /* 4 bit low speed card */ + +#define SDIO_REG_CCCR_CIS_PTR 0x09 /* common CIS pointer (3 bytes) */ + +/* Following 4 regs are valid only if SBS is set */ +#define SDIO_REG_CCCR_BUS_SUSPEND 0x0c +#define SDIO_REG_CCCR_FUNC_SEL 0x0d +#define SDIO_REG_CCCR_EXEC_FLAG 0x0e +#define SDIO_REG_CCCR_READY_FLAG 0x0f + +#define SDIO_REG_CCCR_FN0_BLKSIZE 0x10 /* 2bytes, 0x10~0x11 */ + +#define SDIO_REG_CCCR_POWER_CTRL 0x12 + +#define SDIO_POWER_SMPC 0x01 /* Supports Master Power Control */ +#define SDIO_POWER_EMPC 0x02 /* Enable Master Power Control */ + +#define SDIO_REG_CCCR_SPEED 0x13 + +#define SDIO_SPEED_SHS 0x01 /* Supports High-Speed mode */ +#define SDIO_SPEED_EHS 0x02 /* Enable High-Speed mode */ + +/* + * Function Basic Registers (FBR) + */ + +#define SDIO_REG_FBR_BASE(f) ((f) * 0x100) /* base of function f's FBRs */ + +#define SDIO_REG_FBR_STD_FUNC_IF 0x00 + +#define SDIO_FBR_SUPPORTS_CSA 0x40 /* supports Code Storage Area */ +#define SDIO_FBR_ENABLE_CSA 0x80 /* enable Code Storage Area */ + +#define SDIO_REG_FBR_STD_IF_EXT 0x01 + +#define SDIO_REG_FBR_POWER 0x02 + +#define SDIO_FBR_POWER_SPS 0x01 /* Supports Power Selection */ +#define SDIO_FBR_POWER_EPS 0x02 /* Enable (low) Power Selection */ + +#define SDIO_REG_FBR_CIS 0x09 /* CIS pointer (3 bytes) */ + + +#define SDIO_REG_FBR_CSA 0x0C /* CSA pointer (3 bytes) */ + +#define SDIO_REG_FBR_CSA_DATA 0x0F + +#define SDIO_REG_FBR_BLKSIZE 0x10 /* block size (2 bytes) */ + + +/* SDIO CIS Tuple code */ +#define CISTPL_NULL 0x00 +#define CISTPL_CHECKSUM 0x10 +#define CISTPL_VERS_1 0x15 +#define CISTPL_ALTSTR 0x16 +#define CISTPL_MANFID 0x20 +#define CISTPL_FUNCID 0x21 +#define CISTPL_FUNCE 0x22 +#define CISTPL_SDIO_STD 0x91 +#define CISTPL_SDIO_EXT 0x92 +#define CISTPL_END 0xff + +/* SDIO device id */ +#define SDIO_ANY_FUNC_ID 0xff +#define SDIO_ANY_MAN_ID 0xffff +#define SDIO_ANY_PROD_ID 0xffff + +struct rt_sdio_device_id { + rt_uint8_t func_code; + rt_uint16_t manufacturer; + rt_uint16_t product; +}; + +struct rt_sdio_driver { + char *name; + rt_int32_t (*probe)(struct rt_mmcsd_card *card); + rt_int32_t (*remove)(struct rt_mmcsd_card *card); + struct rt_sdio_device_id *id; +}; + + + +rt_int32_t sdio_io_send_op_cond(struct rt_mmcsd_host *host, rt_uint32_t ocr, rt_uint32_t +*cmd5_resp); +rt_int32_t sdio_io_rw_direct(struct rt_mmcsd_card *card, rt_int32_t rw, rt_uint32_t fn, + rt_uint32_t reg_addr, rt_uint8_t *pdata, rt_uint8_t raw); +rt_int32_t sdio_io_rw_extended(struct rt_mmcsd_card *card, rt_int32_t rw, rt_uint32_t fn, + rt_uint32_t addr, rt_int32_t op_code, rt_uint8_t *buf, rt_uint32_t blocks, rt_uint32_t blksize); +rt_uint8_t sdio_io_readb(struct rt_sdio_function *func, + rt_uint32_t reg, rt_int32_t *err); +rt_int32_t sdio_io_writeb(struct rt_sdio_function *func, + rt_uint32_t reg, rt_uint8_t data); +rt_uint16_t sdio_io_readw(struct rt_sdio_function *func, rt_uint32_t addr, rt_int32_t *err); +rt_int32_t sdio_io_writew(struct rt_sdio_function *func, rt_uint16_t data, rt_uint32_t addr); +rt_uint32_t sdio_io_readl(struct rt_sdio_function *func, rt_uint32_t addr, rt_int32_t *err); +rt_int32_t sdio_io_writel(struct rt_sdio_function *func, rt_uint32_t data, rt_uint32_t addr); +rt_int32_t sdio_io_read_multi_fifo_b(struct rt_sdio_function *func, + rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t len); +rt_int32_t sdio_io_write_multi_fifo_b(struct rt_sdio_function *func, + rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t len); +rt_int32_t sdio_io_read_multi_incr_b(struct rt_sdio_function *func, + rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t len); +rt_int32_t sdio_io_write_multi_incr_b(struct rt_sdio_function *func, + rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t len); +rt_int32_t init_sdio(struct rt_mmcsd_host *host, rt_uint32_t ocr); +rt_int32_t sdio_attach_irq(struct rt_sdio_function *func, rt_sdio_irq_handler_t *handler); +rt_int32_t sdio_detach_irq(struct rt_sdio_function *func); +void sdio_irq_wakeup(struct rt_mmcsd_host *host); +rt_int32_t sdio_enable_func(struct rt_sdio_function *func); +rt_int32_t sdio_disable_func(struct rt_sdio_function *func); +rt_int32_t sdio_set_block_size(struct rt_sdio_function *func, rt_uint32_t blksize); +rt_int32_t sdio_register_driver(struct rt_sdio_driver *driver); +rt_int32_t sdio_unregister_driver(struct rt_sdio_driver *driver); +void rt_sdio_init(void); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/components/drivers/include/drivers/sdio_func_ids.h b/components/drivers/include/drivers/sdio_func_ids.h index 4c25622463..1885533544 100644 --- a/components/drivers/include/drivers/sdio_func_ids.h +++ b/components/drivers/include/drivers/sdio_func_ids.h @@ -1,44 +1,44 @@ -/* - * File : sdio_func_ids.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2012-02-26 weety first version - */ - -#ifndef __SDIO_FUNC_IDS_H__ -#define __SDIO_FUNC_IDS_H__ - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Standard SDIO Function Interfaces */ - -#define SDIO_FUNC_CODE_NONE 0x00 /* Not a SDIO standard interface */ -#define SDIO_FUNC_CODE_UART 0x01 /* SDIO Standard UART */ -#define SDIO_FUNC_CODE_BT_A 0x02 /* SDIO Type-A for Bluetooth standard interface */ -#define SDIO_FUNC_CODE_BT_B 0x03 /* SDIO Type-B for Bluetooth standard interface */ -#define SDIO_FUNC_CODE_GPS 0x04 /* SDIO GPS standard interface */ -#define SDIO_FUNC_CODE_CAMERA 0x05 /* SDIO Camera standard interface */ -#define SDIO_FUNC_CODE_PHS 0x06 /* SDIO PHS standard interface */ -#define SDIO_FUNC_CODE_WLAN 0x07 /* SDIO WLAN interface */ -#define SDIO_FUNC_CODE_ATA 0x08 /* Embedded SDIO-ATA standard interface */ - -/* manufacturer id, product io */ - -#define SDIO_MANUFACTURER_ID_MARVELL 0x02df -#define SDIO_PRODUCT_ID_MARVELL_88W8686 0x9103 - -#ifdef __cplusplus -} -#endif - -#endif +/* + * File : sdio_func_ids.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2012-02-26 weety first version + */ + +#ifndef __SDIO_FUNC_IDS_H__ +#define __SDIO_FUNC_IDS_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Standard SDIO Function Interfaces */ + +#define SDIO_FUNC_CODE_NONE 0x00 /* Not a SDIO standard interface */ +#define SDIO_FUNC_CODE_UART 0x01 /* SDIO Standard UART */ +#define SDIO_FUNC_CODE_BT_A 0x02 /* SDIO Type-A for Bluetooth standard interface */ +#define SDIO_FUNC_CODE_BT_B 0x03 /* SDIO Type-B for Bluetooth standard interface */ +#define SDIO_FUNC_CODE_GPS 0x04 /* SDIO GPS standard interface */ +#define SDIO_FUNC_CODE_CAMERA 0x05 /* SDIO Camera standard interface */ +#define SDIO_FUNC_CODE_PHS 0x06 /* SDIO PHS standard interface */ +#define SDIO_FUNC_CODE_WLAN 0x07 /* SDIO WLAN interface */ +#define SDIO_FUNC_CODE_ATA 0x08 /* Embedded SDIO-ATA standard interface */ + +/* manufacturer id, product io */ + +#define SDIO_MANUFACTURER_ID_MARVELL 0x02df +#define SDIO_PRODUCT_ID_MARVELL_88W8686 0x9103 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/include/drivers/serial.h b/components/drivers/include/drivers/serial.h index af467c494e..b10dbe57d6 100644 --- a/components/drivers/include/drivers/serial.h +++ b/components/drivers/include/drivers/serial.h @@ -57,21 +57,21 @@ #define RT_SERIAL_ERR_OVERRUN 0x01 #define RT_SERIAL_ERR_FRAMING 0x02 -#define RT_SERIAL_ERR_PARITY 0x03 +#define RT_SERIAL_ERR_PARITY 0x03 #define RT_SERIAL_TX_DATAQUEUE_SIZE 40 #define RT_SERIAL_TX_DATAQUEUE_LWM 30 - -/* Default config for serial_configure structure */ -#define RT_SERIAL_CONFIG_DEFAULT \ -{ \ - BAUD_RATE_115200, /* 115200 bits/s */ \ - DATA_BITS_8, /* 8 databits */ \ - STOP_BITS_1, /* 1 stopbit */ \ - PARITY_NONE, /* No parity */ \ - BIT_ORDER_LSB, /* LSB first sent */ \ - NRZ_NORMAL, /* Normal mode */ \ - 0 \ + +/* Default config for serial_configure structure */ +#define RT_SERIAL_CONFIG_DEFAULT \ +{ \ + BAUD_RATE_115200, /* 115200 bits/s */ \ + DATA_BITS_8, /* 8 databits */ \ + STOP_BITS_1, /* 1 stopbit */ \ + PARITY_NONE, /* No parity */ \ + BIT_ORDER_LSB, /* LSB first sent */ \ + NRZ_NORMAL, /* Normal mode */ \ + 0 \ } struct serial_ringbuffer diff --git a/components/drivers/include/drivers/usb_common.h b/components/drivers/include/drivers/usb_common.h index 19c75b5f17..503d3edbae 100644 --- a/components/drivers/include/drivers/usb_common.h +++ b/components/drivers/include/drivers/usb_common.h @@ -1,378 +1,378 @@ -/* - * File : usb_common.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2012, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2012-10-01 Yi Qiu first version - */ - -#ifndef __RT_USB_COMMON_H__ -#define __RT_USB_COMMON_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#define RT_DEBUG_USB 0x00 -#define USB_DYNAMIC 0x00 - -#define USB_CLASS_DEVICE 0x00 -#define USB_CLASS_AUDIO 0x01 -#define USB_CLASS_CDC 0x02 -#define USB_CLASS_HID 0x03 -#define USB_CLASS_PHYSICAL 0x05 -#define USB_CLASS_IMAGE 0x06 -#define USB_CLASS_PRINTER 0x07 -#define USB_CLASS_MASS_STORAGE 0x08 -#define USB_CLASS_HUB 0x09 -#define USB_CLASS_CDC_DATA 0x0a -#define USB_CLASS_SMART_CARD 0x0b -#define USB_CLASS_SECURITY 0x0d -#define USB_CLASS_VIDEO 0x0e -#define USB_CLASS_HEALTHCARE 0x0f -#define USB_CLASS_DIAG_DEVICE 0xdc -#define USB_CLASS_WIRELESS 0xe0 -#define USB_CLASS_MISC 0xef -#define USB_CLASS_APP_SPECIFIC 0xfe -#define USB_CLASS_VEND_SPECIFIC 0xff - -#define USB_DESC_TYPE_DEVICE 0x01 -#define USB_DESC_TYPE_CONFIGURATION 0x02 -#define USB_DESC_TYPE_STRING 0x03 -#define USB_DESC_TYPE_INTERFACE 0x04 -#define USB_DESC_TYPE_ENDPOINT 0x05 -#define USB_DESC_TYPE_DEVICEQUALIFIER 0x06 -#define USB_DESC_TYPE_OTHERSPEED 0x07 -#define USB_DESC_TYPE_IAD 0x0b -#define USB_DESC_TYPE_HID 0x21 -#define USB_DESC_TYPE_REPORT 0x22 -#define USB_DESC_TYPE_PHYSICAL 0x23 -#define USB_DESC_TYPE_HUB 0x29 - -#define USB_DESC_LENGTH_DEVICE 0x12 -#define USB_DESC_LENGTH_CONFIG 0x9 -#define USB_DESC_LENGTH_IAD 0x8 -#define USB_DESC_LENGTH_STRING 0x4 -#define USB_DESC_LENGTH_INTERFACE 0x9 -#define USB_DESC_LENGTH_ENDPOINT 0x7 - -#define USB_REQ_TYPE_STANDARD 0x00 -#define USB_REQ_TYPE_CLASS 0x20 -#define USB_REQ_TYPE_VENDOR 0x40 -#define USB_REQ_TYPE_MASK 0x60 - -#define USB_REQ_TYPE_DIR_OUT 0x00 -#define USB_REQ_TYPE_DIR_IN 0x80 - -#define USB_REQ_TYPE_DEVICE 0x00 -#define USB_REQ_TYPE_INTERFACE 0x01 -#define USB_REQ_TYPE_ENDPOINT 0x02 -#define USB_REQ_TYPE_OTHER 0x03 -#define USB_REQ_TYPE_RECIPIENT_MASK 0x1f - -#define USB_FEATURE_ENDPOINT_HALT 0x00 -#define USB_FEATURE_DEV_REMOTE_WAKEUP 0x01 -#define USB_FEATURE_TEST_MODE 0x02 - -#define USB_REQ_GET_STATUS 0x00 -#define USB_REQ_CLEAR_FEATURE 0x01 -#define USB_REQ_SET_FEATURE 0x03 -#define USB_REQ_SET_ADDRESS 0x05 -#define USB_REQ_GET_DESCRIPTOR 0x06 -#define USB_REQ_SET_DESCRIPTOR 0x07 -#define USB_REQ_GET_CONFIGURATION 0x08 -#define USB_REQ_SET_CONFIGURATION 0x09 -#define USB_REQ_GET_INTERFACE 0x0A -#define USB_REQ_SET_INTERFACE 0x0B -#define USB_REQ_SYNCH_FRAME 0x0C -#define USB_REQ_SET_ENCRYPTION 0x0D -#define USB_REQ_GET_ENCRYPTION 0x0E -#define USB_REQ_RPIPE_ABORT 0x0E -#define USB_REQ_SET_HANDSHAKE 0x0F -#define USB_REQ_RPIPE_RESET 0x0F -#define USB_REQ_GET_HANDSHAKE 0x10 -#define USB_REQ_SET_CONNECTION 0x11 -#define USB_REQ_SET_SECURITY_DATA 0x12 -#define USB_REQ_GET_SECURITY_DATA 0x13 -#define USB_REQ_SET_WUSB_DATA 0x14 -#define USB_REQ_LOOPBACK_DATA_WRITE 0x15 -#define USB_REQ_LOOPBACK_DATA_READ 0x16 -#define USB_REQ_SET_INTERFACE_DS 0x17 - -#define USB_STRING_LANGID_INDEX 0x00 -#define USB_STRING_MANU_INDEX 0x01 -#define USB_STRING_PRODUCT_INDEX 0x02 -#define USB_STRING_SERIAL_INDEX 0x03 -#define USB_STRING_CONFIG_INDEX 0x04 -#define USB_STRING_INTERFACE_INDEX 0x05 - -#define USB_PID_OUT 0x01 -#define USB_PID_ACK 0x02 -#define USB_PID_DATA0 0x03 -#define USB_PID_SOF 0x05 -#define USB_PID_IN 0x09 -#define USB_PID_NACK 0x0A -#define USB_PID_DATA1 0x0B -#define USB_PID_PRE 0x0C -#define USB_PID_SETUP 0x0D -#define USB_PID_STALL 0x0E - -#define USB_EP_DESC_OUT 0x00 -#define USB_EP_DESC_IN 0x80 -#define USB_EP_DESC_NUM_MASK 0x0f - -#define USB_EP_ATTR_CONTROL 0x00 -#define USB_EP_ATTR_ISOC 0x01 -#define USB_EP_ATTR_BULK 0x02 -#define USB_EP_ATTR_INT 0x03 -#define USB_EP_ATTR_TYPE_MASK 0x03 - -#define USB_EPNO_MASK 0x7f -#define USB_DIR_OUT 0x00 -#define USB_DIR_IN 0x80 -#define USB_DIR_MASK 0x80 - -#define RH_GET_PORT_STATUS 0 -#define RH_SET_PORT_STATUS 1 -#define RH_CLEAR_PORT_FEATURE 2 -#define RH_SET_PORT_FEATURE 3 - -/* - * Port feature numbers - */ -#define PORT_FEAT_CONNECTION 0 -#define PORT_FEAT_ENABLE 1 -#define PORT_FEAT_SUSPEND 2 -#define PORT_FEAT_OVER_CURRENT 3 -#define PORT_FEAT_RESET 4 -#define PORT_FEAT_POWER 8 -#define PORT_FEAT_LOWSPEED 9 -#define PORT_FEAT_HIGHSPEED 10 -#define PORT_FEAT_C_CONNECTION 16 -#define PORT_FEAT_C_ENABLE 17 -#define PORT_FEAT_C_SUSPEND 18 -#define PORT_FEAT_C_OVER_CURRENT 19 -#define PORT_FEAT_C_RESET 20 - -/* - The HcRhPortStatus[1:NDP] register is used to control and report port events on a per-port - basis. NumberDownstreamPorts represents the number of HcRhPortStatus registers that are - implemented in hardware. The lower word is used to reflect the port status, whereas the upper - word reflects the status change bits. Some status bits are implemented with special write behavior - (see below). If a transaction (token through handshake) is in progress when a write to change - port status occurs, the resulting port status change must be postponed until the transaction - completes. Reserved bits should always be written '0'. -*/ -#define PORT_CCS 0x00000001UL /* R:CurrentConnectStatus - W:ClearPortEnable */ -#define PORT_PES 0x00000002UL /* R:PortEnableStatus - W:SetPortEnable */ -#define PORT_PSS 0x00000004UL /* R:PortSuspendStatus - W:SetPortSuspend */ -#define PORT_POCI 0x00000008UL /* R:PortOverCurrentIndicator - W:ClearSuspendStatus */ -#define PORT_PRS 0x00000010UL /* R:PortResetStatus - W: SetPortReset */ -#define PORT_PPS 0x00000100UL /* R:PortPowerStatus - W: SetPortPower */ -#define PORT_LSDA 0x00000200UL /* R:LowSpeedDeviceAttached - W:ClearPortPower */ -#define PORT_CCSC 0x00010000UL -#define PORT_PESC 0x00020000UL -#define PORT_PSSC 0x00040000UL -#define PORT_POCIC 0x00080000UL -#define PORT_PRSC 0x00100000UL - -/* - *Hub Status & Hub Change bit masks - */ -#define HUB_STATUS_LOCAL_POWER 0x0001 -#define HUB_STATUS_OVERCURRENT 0x0002 - -#define HUB_CHANGE_LOCAL_POWER 0x0001 -#define HUB_CHANGE_OVERCURRENT 0x0002 - -#define USB_EP_ATTR(attr) (attr & USB_EP_ATTR_TYPE_MASK) -#define USB_EP_DESC_NUM(addr) (addr & USB_EP_DESC_NUM_MASK) - -#define uswap_32(x) \ - ((((x) & 0xff000000) >> 24) | \ - (((x) & 0x00ff0000) >> 8) | \ - (((x) & 0x0000ff00) << 8) | \ - (((x) & 0x000000ff) << 24)) - -#define uswap_8(x) \ - (((rt_uint16_t)(*((rt_uint8_t *)(x)))) + \ - (((rt_uint16_t)(*(((rt_uint8_t *)(x)) + 1))) << 8)) - -typedef void (*func_callback)(void *context); - -#pragma pack(1) - -struct usb_descriptor -{ - rt_uint8_t bLength; - rt_uint8_t type; -}; -typedef struct usb_descriptor* udesc_t; - -struct udevice_descriptor -{ - rt_uint8_t bLength; - rt_uint8_t type; - rt_uint16_t bcdUSB; - rt_uint8_t bDeviceClass; - rt_uint8_t bDeviceSubClass; - rt_uint8_t bDeviceProtocol; - rt_uint8_t bMaxPacketSize0; - rt_uint16_t idVendor; - rt_uint16_t idProduct; - rt_uint16_t bcdDevice; - rt_uint8_t iManufacturer; - rt_uint8_t iProduct; - rt_uint8_t iSerialNumber; - rt_uint8_t bNumConfigurations; -}; -typedef struct udevice_descriptor* udev_desc_t; - -struct uconfig_descriptor -{ - rt_uint8_t bLength; - rt_uint8_t type; - rt_uint16_t wTotalLength; - rt_uint8_t bNumInterfaces; - rt_uint8_t bConfigurationValue; - rt_uint8_t iConfiguration; - rt_uint8_t bmAttributes; - rt_uint8_t MaxPower; - rt_uint8_t data[256]; -}; -typedef struct uconfig_descriptor* ucfg_desc_t; - -struct uinterface_descriptor -{ - rt_uint8_t bLength; - rt_uint8_t type; - rt_uint8_t bInterfaceNumber; - rt_uint8_t bAlternateSetting; - rt_uint8_t bNumEndpoints; - rt_uint8_t bInterfaceClass; - rt_uint8_t bInterfaceSubClass; - rt_uint8_t bInterfaceProtocol; - rt_uint8_t iInterface; -}; -typedef struct uinterface_descriptor* uintf_desc_t; - -/* Interface Association Descriptor (IAD) */ -struct uiad_descriptor -{ - rt_uint8_t bLength; - rt_uint8_t bDescriptorType; - rt_uint8_t bFirstInterface; - rt_uint8_t bInterfaceCount; - rt_uint8_t bFunctionClass; - rt_uint8_t bFunctionSubClass; - rt_uint8_t bFunctionProtocol; - rt_uint8_t iFunction; -}; -typedef struct uiad_descriptor* uiad_desc_t; - -struct uendpoint_descriptor -{ - rt_uint8_t bLength; - rt_uint8_t type; - rt_uint8_t bEndpointAddress; - rt_uint8_t bmAttributes; - rt_uint16_t wMaxPacketSize; - rt_uint8_t bInterval; -}; -typedef struct uendpoint_descriptor* uep_desc_t; - -struct ustring_descriptor -{ - rt_uint8_t bLength; - rt_uint8_t type; - rt_uint8_t String[64]; -}; -typedef struct ustring_descriptor* ustr_desc_t; - -struct uhub_descriptor -{ - rt_uint8_t length; - rt_uint8_t type; - rt_uint8_t num_ports; - rt_uint16_t characteristics; - rt_uint8_t pwron_to_good; /* power on to power good */ - rt_uint8_t current; - rt_uint8_t removable[8]; - rt_uint8_t pwr_ctl[8]; -}; -typedef struct uhub_descriptor* uhub_desc_t; - -struct ureqest -{ - rt_uint8_t request_type; - rt_uint8_t request; - rt_uint16_t value; - rt_uint16_t index; - rt_uint16_t length; -}; -typedef struct ureqest* ureq_t; - -struct ustorage_cbw -{ - rt_uint32_t signature; - rt_uint32_t tag; - rt_uint32_t xfer_len; - rt_uint8_t dflags; - rt_uint8_t lun; - rt_uint8_t cb_len; - rt_uint8_t cb[16]; -}; -typedef struct ustorage_cbw* ustorage_cbw_t; - -struct ustorage_csw -{ - rt_uint32_t signature; - rt_uint32_t tag; - rt_uint32_t data_reside; - rt_uint8_t status; -}; -typedef struct ustorage_csw* ustorage_csw_t; - -#define SIZEOF_CSW 0x0d -#define SIZEOF_CBW 0x1f - -#define CBWFLAGS_DIR_M 0x80 -#define CBWFLAGS_DIR_IN 0x80 -#define CBWFLAGS_DIR_OUT 0x00 - -#define SCSI_TEST_UNIT_READY 0x00 -#define SCSI_REQUEST_SENSE 0x03 -#define SCSI_INQUIRY_CMD 0x12 -#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1e -#define SCSI_MODE_SENSE_6 0x1a -#define SCSI_READ_CAPACITIES 0x23 -#define SCSI_READ_CAPACITY 0x25 -#define SCSI_READ_10 0x28 -#define SCSI_WRITE_10 0x2a -#define SCSI_VERIFY_10 0x2f - -#define CBW_SIGNATURE 0x43425355 -#define CSW_SIGNATURE 0x53425355 -#define CBW_TAG_VALUE 0x12345678 - -#define USBREQ_GET_MAX_LUN 0xfe -#define USBREQ_MASS_STORAGE_RESET 0xff - -#define MIN(a, b) (a < b ? a : b) -#define MAX(a, b) (a > b ? a : b) - -#pragma pack() - -#ifdef __cplusplus -} -#endif - -#endif +/* + * File : usb_common.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2012, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2012-10-01 Yi Qiu first version + */ + +#ifndef __RT_USB_COMMON_H__ +#define __RT_USB_COMMON_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define RT_DEBUG_USB 0x00 +#define USB_DYNAMIC 0x00 + +#define USB_CLASS_DEVICE 0x00 +#define USB_CLASS_AUDIO 0x01 +#define USB_CLASS_CDC 0x02 +#define USB_CLASS_HID 0x03 +#define USB_CLASS_PHYSICAL 0x05 +#define USB_CLASS_IMAGE 0x06 +#define USB_CLASS_PRINTER 0x07 +#define USB_CLASS_MASS_STORAGE 0x08 +#define USB_CLASS_HUB 0x09 +#define USB_CLASS_CDC_DATA 0x0a +#define USB_CLASS_SMART_CARD 0x0b +#define USB_CLASS_SECURITY 0x0d +#define USB_CLASS_VIDEO 0x0e +#define USB_CLASS_HEALTHCARE 0x0f +#define USB_CLASS_DIAG_DEVICE 0xdc +#define USB_CLASS_WIRELESS 0xe0 +#define USB_CLASS_MISC 0xef +#define USB_CLASS_APP_SPECIFIC 0xfe +#define USB_CLASS_VEND_SPECIFIC 0xff + +#define USB_DESC_TYPE_DEVICE 0x01 +#define USB_DESC_TYPE_CONFIGURATION 0x02 +#define USB_DESC_TYPE_STRING 0x03 +#define USB_DESC_TYPE_INTERFACE 0x04 +#define USB_DESC_TYPE_ENDPOINT 0x05 +#define USB_DESC_TYPE_DEVICEQUALIFIER 0x06 +#define USB_DESC_TYPE_OTHERSPEED 0x07 +#define USB_DESC_TYPE_IAD 0x0b +#define USB_DESC_TYPE_HID 0x21 +#define USB_DESC_TYPE_REPORT 0x22 +#define USB_DESC_TYPE_PHYSICAL 0x23 +#define USB_DESC_TYPE_HUB 0x29 + +#define USB_DESC_LENGTH_DEVICE 0x12 +#define USB_DESC_LENGTH_CONFIG 0x9 +#define USB_DESC_LENGTH_IAD 0x8 +#define USB_DESC_LENGTH_STRING 0x4 +#define USB_DESC_LENGTH_INTERFACE 0x9 +#define USB_DESC_LENGTH_ENDPOINT 0x7 + +#define USB_REQ_TYPE_STANDARD 0x00 +#define USB_REQ_TYPE_CLASS 0x20 +#define USB_REQ_TYPE_VENDOR 0x40 +#define USB_REQ_TYPE_MASK 0x60 + +#define USB_REQ_TYPE_DIR_OUT 0x00 +#define USB_REQ_TYPE_DIR_IN 0x80 + +#define USB_REQ_TYPE_DEVICE 0x00 +#define USB_REQ_TYPE_INTERFACE 0x01 +#define USB_REQ_TYPE_ENDPOINT 0x02 +#define USB_REQ_TYPE_OTHER 0x03 +#define USB_REQ_TYPE_RECIPIENT_MASK 0x1f + +#define USB_FEATURE_ENDPOINT_HALT 0x00 +#define USB_FEATURE_DEV_REMOTE_WAKEUP 0x01 +#define USB_FEATURE_TEST_MODE 0x02 + +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C +#define USB_REQ_SET_ENCRYPTION 0x0D +#define USB_REQ_GET_ENCRYPTION 0x0E +#define USB_REQ_RPIPE_ABORT 0x0E +#define USB_REQ_SET_HANDSHAKE 0x0F +#define USB_REQ_RPIPE_RESET 0x0F +#define USB_REQ_GET_HANDSHAKE 0x10 +#define USB_REQ_SET_CONNECTION 0x11 +#define USB_REQ_SET_SECURITY_DATA 0x12 +#define USB_REQ_GET_SECURITY_DATA 0x13 +#define USB_REQ_SET_WUSB_DATA 0x14 +#define USB_REQ_LOOPBACK_DATA_WRITE 0x15 +#define USB_REQ_LOOPBACK_DATA_READ 0x16 +#define USB_REQ_SET_INTERFACE_DS 0x17 + +#define USB_STRING_LANGID_INDEX 0x00 +#define USB_STRING_MANU_INDEX 0x01 +#define USB_STRING_PRODUCT_INDEX 0x02 +#define USB_STRING_SERIAL_INDEX 0x03 +#define USB_STRING_CONFIG_INDEX 0x04 +#define USB_STRING_INTERFACE_INDEX 0x05 + +#define USB_PID_OUT 0x01 +#define USB_PID_ACK 0x02 +#define USB_PID_DATA0 0x03 +#define USB_PID_SOF 0x05 +#define USB_PID_IN 0x09 +#define USB_PID_NACK 0x0A +#define USB_PID_DATA1 0x0B +#define USB_PID_PRE 0x0C +#define USB_PID_SETUP 0x0D +#define USB_PID_STALL 0x0E + +#define USB_EP_DESC_OUT 0x00 +#define USB_EP_DESC_IN 0x80 +#define USB_EP_DESC_NUM_MASK 0x0f + +#define USB_EP_ATTR_CONTROL 0x00 +#define USB_EP_ATTR_ISOC 0x01 +#define USB_EP_ATTR_BULK 0x02 +#define USB_EP_ATTR_INT 0x03 +#define USB_EP_ATTR_TYPE_MASK 0x03 + +#define USB_EPNO_MASK 0x7f +#define USB_DIR_OUT 0x00 +#define USB_DIR_IN 0x80 +#define USB_DIR_MASK 0x80 + +#define RH_GET_PORT_STATUS 0 +#define RH_SET_PORT_STATUS 1 +#define RH_CLEAR_PORT_FEATURE 2 +#define RH_SET_PORT_FEATURE 3 + +/* + * Port feature numbers + */ +#define PORT_FEAT_CONNECTION 0 +#define PORT_FEAT_ENABLE 1 +#define PORT_FEAT_SUSPEND 2 +#define PORT_FEAT_OVER_CURRENT 3 +#define PORT_FEAT_RESET 4 +#define PORT_FEAT_POWER 8 +#define PORT_FEAT_LOWSPEED 9 +#define PORT_FEAT_HIGHSPEED 10 +#define PORT_FEAT_C_CONNECTION 16 +#define PORT_FEAT_C_ENABLE 17 +#define PORT_FEAT_C_SUSPEND 18 +#define PORT_FEAT_C_OVER_CURRENT 19 +#define PORT_FEAT_C_RESET 20 + +/* + The HcRhPortStatus[1:NDP] register is used to control and report port events on a per-port + basis. NumberDownstreamPorts represents the number of HcRhPortStatus registers that are + implemented in hardware. The lower word is used to reflect the port status, whereas the upper + word reflects the status change bits. Some status bits are implemented with special write behavior + (see below). If a transaction (token through handshake) is in progress when a write to change + port status occurs, the resulting port status change must be postponed until the transaction + completes. Reserved bits should always be written '0'. +*/ +#define PORT_CCS 0x00000001UL /* R:CurrentConnectStatus - W:ClearPortEnable */ +#define PORT_PES 0x00000002UL /* R:PortEnableStatus - W:SetPortEnable */ +#define PORT_PSS 0x00000004UL /* R:PortSuspendStatus - W:SetPortSuspend */ +#define PORT_POCI 0x00000008UL /* R:PortOverCurrentIndicator - W:ClearSuspendStatus */ +#define PORT_PRS 0x00000010UL /* R:PortResetStatus - W: SetPortReset */ +#define PORT_PPS 0x00000100UL /* R:PortPowerStatus - W: SetPortPower */ +#define PORT_LSDA 0x00000200UL /* R:LowSpeedDeviceAttached - W:ClearPortPower */ +#define PORT_CCSC 0x00010000UL +#define PORT_PESC 0x00020000UL +#define PORT_PSSC 0x00040000UL +#define PORT_POCIC 0x00080000UL +#define PORT_PRSC 0x00100000UL + +/* + *Hub Status & Hub Change bit masks + */ +#define HUB_STATUS_LOCAL_POWER 0x0001 +#define HUB_STATUS_OVERCURRENT 0x0002 + +#define HUB_CHANGE_LOCAL_POWER 0x0001 +#define HUB_CHANGE_OVERCURRENT 0x0002 + +#define USB_EP_ATTR(attr) (attr & USB_EP_ATTR_TYPE_MASK) +#define USB_EP_DESC_NUM(addr) (addr & USB_EP_DESC_NUM_MASK) + +#define uswap_32(x) \ + ((((x) & 0xff000000) >> 24) | \ + (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | \ + (((x) & 0x000000ff) << 24)) + +#define uswap_8(x) \ + (((rt_uint16_t)(*((rt_uint8_t *)(x)))) + \ + (((rt_uint16_t)(*(((rt_uint8_t *)(x)) + 1))) << 8)) + +typedef void (*func_callback)(void *context); + +#pragma pack(1) + +struct usb_descriptor +{ + rt_uint8_t bLength; + rt_uint8_t type; +}; +typedef struct usb_descriptor* udesc_t; + +struct udevice_descriptor +{ + rt_uint8_t bLength; + rt_uint8_t type; + rt_uint16_t bcdUSB; + rt_uint8_t bDeviceClass; + rt_uint8_t bDeviceSubClass; + rt_uint8_t bDeviceProtocol; + rt_uint8_t bMaxPacketSize0; + rt_uint16_t idVendor; + rt_uint16_t idProduct; + rt_uint16_t bcdDevice; + rt_uint8_t iManufacturer; + rt_uint8_t iProduct; + rt_uint8_t iSerialNumber; + rt_uint8_t bNumConfigurations; +}; +typedef struct udevice_descriptor* udev_desc_t; + +struct uconfig_descriptor +{ + rt_uint8_t bLength; + rt_uint8_t type; + rt_uint16_t wTotalLength; + rt_uint8_t bNumInterfaces; + rt_uint8_t bConfigurationValue; + rt_uint8_t iConfiguration; + rt_uint8_t bmAttributes; + rt_uint8_t MaxPower; + rt_uint8_t data[256]; +}; +typedef struct uconfig_descriptor* ucfg_desc_t; + +struct uinterface_descriptor +{ + rt_uint8_t bLength; + rt_uint8_t type; + rt_uint8_t bInterfaceNumber; + rt_uint8_t bAlternateSetting; + rt_uint8_t bNumEndpoints; + rt_uint8_t bInterfaceClass; + rt_uint8_t bInterfaceSubClass; + rt_uint8_t bInterfaceProtocol; + rt_uint8_t iInterface; +}; +typedef struct uinterface_descriptor* uintf_desc_t; + +/* Interface Association Descriptor (IAD) */ +struct uiad_descriptor +{ + rt_uint8_t bLength; + rt_uint8_t bDescriptorType; + rt_uint8_t bFirstInterface; + rt_uint8_t bInterfaceCount; + rt_uint8_t bFunctionClass; + rt_uint8_t bFunctionSubClass; + rt_uint8_t bFunctionProtocol; + rt_uint8_t iFunction; +}; +typedef struct uiad_descriptor* uiad_desc_t; + +struct uendpoint_descriptor +{ + rt_uint8_t bLength; + rt_uint8_t type; + rt_uint8_t bEndpointAddress; + rt_uint8_t bmAttributes; + rt_uint16_t wMaxPacketSize; + rt_uint8_t bInterval; +}; +typedef struct uendpoint_descriptor* uep_desc_t; + +struct ustring_descriptor +{ + rt_uint8_t bLength; + rt_uint8_t type; + rt_uint8_t String[64]; +}; +typedef struct ustring_descriptor* ustr_desc_t; + +struct uhub_descriptor +{ + rt_uint8_t length; + rt_uint8_t type; + rt_uint8_t num_ports; + rt_uint16_t characteristics; + rt_uint8_t pwron_to_good; /* power on to power good */ + rt_uint8_t current; + rt_uint8_t removable[8]; + rt_uint8_t pwr_ctl[8]; +}; +typedef struct uhub_descriptor* uhub_desc_t; + +struct ureqest +{ + rt_uint8_t request_type; + rt_uint8_t request; + rt_uint16_t value; + rt_uint16_t index; + rt_uint16_t length; +}; +typedef struct ureqest* ureq_t; + +struct ustorage_cbw +{ + rt_uint32_t signature; + rt_uint32_t tag; + rt_uint32_t xfer_len; + rt_uint8_t dflags; + rt_uint8_t lun; + rt_uint8_t cb_len; + rt_uint8_t cb[16]; +}; +typedef struct ustorage_cbw* ustorage_cbw_t; + +struct ustorage_csw +{ + rt_uint32_t signature; + rt_uint32_t tag; + rt_uint32_t data_reside; + rt_uint8_t status; +}; +typedef struct ustorage_csw* ustorage_csw_t; + +#define SIZEOF_CSW 0x0d +#define SIZEOF_CBW 0x1f + +#define CBWFLAGS_DIR_M 0x80 +#define CBWFLAGS_DIR_IN 0x80 +#define CBWFLAGS_DIR_OUT 0x00 + +#define SCSI_TEST_UNIT_READY 0x00 +#define SCSI_REQUEST_SENSE 0x03 +#define SCSI_INQUIRY_CMD 0x12 +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1e +#define SCSI_MODE_SENSE_6 0x1a +#define SCSI_READ_CAPACITIES 0x23 +#define SCSI_READ_CAPACITY 0x25 +#define SCSI_READ_10 0x28 +#define SCSI_WRITE_10 0x2a +#define SCSI_VERIFY_10 0x2f + +#define CBW_SIGNATURE 0x43425355 +#define CSW_SIGNATURE 0x53425355 +#define CBW_TAG_VALUE 0x12345678 + +#define USBREQ_GET_MAX_LUN 0xfe +#define USBREQ_MASS_STORAGE_RESET 0xff + +#define MIN(a, b) (a < b ? a : b) +#define MAX(a, b) (a > b ? a : b) + +#pragma pack() + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/include/drivers/usb_device.h b/components/drivers/include/drivers/usb_device.h index 360f8ed4aa..b969eb6864 100644 --- a/components/drivers/include/drivers/usb_device.h +++ b/components/drivers/include/drivers/usb_device.h @@ -1,267 +1,267 @@ -/* - * File : usb_device.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2012, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2012-10-01 Yi Qiu first version - * 2012-12-12 heyuanjie87 change endpoint and class handler - */ - -#ifndef __USB_DEVICE_H__ -#define __USB_DEVICE_H__ - -#include -#include "usb_common.h" - -#define CONTROL_SEND_STATUS 0x00 -#define CONTROL_RECEIVE_STATUS 0x01 - -#define USB_VENDOR_ID 0x0483 /* Vendor ID */ -#define USB_BCD_DEVICE 0x0200 /* USB Specification Release Number in Binary-Coded Decimal */ -#define USB_BCD_VERSION 0x0200 /* USB 2.0 */ - -struct uclass; -struct udevice; -struct uendpoint; - -struct udcd_ops -{ - rt_err_t (*set_address)(rt_uint8_t value); - rt_err_t (*clear_feature)(rt_uint8_t value); - rt_err_t (*set_feature)(rt_uint8_t value); - rt_err_t (*ep_alloc)(struct uendpoint* ep); - rt_err_t (*ep_free)(struct uendpoint* ep); - rt_err_t (*ep_stall)(struct uendpoint* ep); - rt_err_t (*ep_run)(struct uendpoint* ep); - rt_err_t (*ep_stop)(struct uendpoint* ep); - rt_err_t (*ep_read)(struct uendpoint* ep, void *buffer, rt_size_t size); - rt_size_t (*ep_write)(struct uendpoint* ep, void *buffer, rt_size_t size); -}; - -struct udcd -{ - struct rt_device parent; - struct udcd_ops* ops; - struct rt_completion completion; -}; -typedef struct udcd* udcd_t; - -typedef rt_err_t (*udep_handler_t)(struct udevice* device, struct uclass* cls, rt_size_t size); - -struct uendpoint -{ - rt_list_t list; - rt_uint8_t* buffer; - uep_desc_t ep_desc; - udep_handler_t handler; - rt_bool_t is_stall; -}; -typedef struct uendpoint* uep_t; - -struct ualtsetting -{ - rt_list_t list; - uintf_desc_t intf_desc; - void* desc; - rt_size_t desc_size; - rt_list_t ep_list; -}; -typedef struct ualtsetting* ualtsetting_t; - -typedef rt_err_t (*uintf_handler_t)(struct udevice* device, struct uclass* cls, ureq_t setup); - -struct uinterface -{ - rt_list_t list; - rt_uint8_t intf_num; - ualtsetting_t curr_setting; - rt_list_t setting_list; - uintf_handler_t handler; -}; -typedef struct uinterface* uintf_t; - -struct uclass_ops -{ - rt_err_t (*run)(struct udevice* device, struct uclass* cls); - rt_err_t (*stop)(struct udevice* device, struct uclass* cls); - rt_err_t (*sof_handler)(struct udevice* device, struct uclass* cls); -}; -typedef struct uclass_ops* uclass_ops_t; - -struct uclass -{ - rt_list_t list; - uclass_ops_t ops; - void* eps; - struct udevice* device; - udev_desc_t dev_desc; - void* user_data; - - rt_list_t intf_list; -}; -typedef struct uclass* uclass_t; - -struct uconfig -{ - rt_list_t list; - struct uconfig_descriptor cfg_desc; - rt_list_t cls_list; -}; -typedef struct uconfig* uconfig_t; - -struct udevice -{ - rt_list_t list; - struct udevice_descriptor dev_desc; - const char** str; - - rt_list_t cfg_list; - uconfig_t curr_cfg; - rt_uint8_t nr_intf; - - udcd_t dcd; -}; -typedef struct udevice* udevice_t; - -enum udev_msg_type -{ - USB_MSG_SETUP_NOTIFY, - USB_MSG_DATA_NOTIFY, - USB_MSG_SOF, -}; -typedef enum udev_msg_type udev_msg_type; - -struct udev_msg -{ - udev_msg_type type; - udcd_t dcd; - union - { - struct - { - rt_size_t size; - rt_uint8_t ep_addr; - } ep_msg; - struct - { - rt_uint32_t* packet; - } setup_msg; - } content; -}; -typedef struct udev_msg* udev_msg_t; - -udevice_t rt_usbd_device_create(const char** str); -uconfig_t rt_usbd_config_create(void); -uclass_t rt_usbd_class_create(udevice_t device, udev_desc_t dev_desc, - uclass_ops_t ops); -uintf_t rt_usbd_interface_create(udevice_t device, uintf_handler_t handler); -uep_t rt_usbd_endpoint_create(uep_desc_t ep_desc, udep_handler_t handler); -ualtsetting_t rt_usbd_altsetting_create(rt_size_t desc_size); - -rt_err_t rt_usbd_core_init(void); -rt_err_t rt_usb_device_init(const char* udc_name); -rt_err_t rt_usbd_post_event(struct udev_msg* msg, rt_size_t size); -rt_err_t rt_usbd_free_device(udevice_t device); -rt_err_t rt_usbd_device_set_controller(udevice_t device, udcd_t dcd); -rt_err_t rt_usbd_device_set_descriptor(udevice_t device, udev_desc_t dev_desc); -rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg); -rt_err_t rt_usbd_config_add_class(uconfig_t cfg, uclass_t cls); -rt_err_t rt_usbd_class_add_interface(uclass_t cls, uintf_t intf); -rt_err_t rt_usbd_interface_add_altsetting(uintf_t intf, ualtsetting_t setting); -rt_err_t rt_usbd_altsetting_add_endpoint(ualtsetting_t setting, uep_t ep); -rt_err_t rt_usbd_altsetting_config_descriptor(ualtsetting_t setting, const void* desc, rt_off_t intf_pos); -rt_err_t rt_usbd_set_config(udevice_t device, rt_uint8_t value); -rt_err_t rt_usbd_set_altsetting(uintf_t intf, rt_uint8_t value); - -udevice_t rt_usbd_find_device(udcd_t dcd); -uconfig_t rt_usbd_find_config(udevice_t device, rt_uint8_t value); -uintf_t rt_usbd_find_interface(udevice_t device, rt_uint8_t value, uclass_t *pcls); -uep_t rt_usbd_find_endpoint(udevice_t device, uclass_t* pcls, rt_uint8_t ep_addr); - -uclass_t rt_usbd_class_mstorage_create(udevice_t device); -uclass_t rt_usbd_class_cdc_create(udevice_t device); -uclass_t rt_usbd_class_rndis_create(udevice_t device); - -#ifdef RT_USB_DEVICE_COMPOSITE -rt_err_t rt_usbd_class_set_iad(uclass_t cls, uiad_desc_t iad_desc); -#endif - -rt_inline rt_err_t dcd_set_address(udcd_t dcd, rt_uint8_t value) -{ - RT_ASSERT(dcd != RT_NULL); - - return dcd->ops->set_address(value); -} - -rt_inline rt_err_t dcd_clear_feature(udcd_t dcd, rt_uint8_t value) -{ - RT_ASSERT(dcd != RT_NULL); - - return dcd->ops->clear_feature(value); -} - -rt_inline rt_err_t dcd_set_feature(udcd_t dcd, rt_uint8_t value) -{ - RT_ASSERT(dcd != RT_NULL); - - return dcd->ops->set_feature(value); -} - -rt_inline rt_err_t dcd_ep_stall(udcd_t dcd, uep_t ep) -{ - RT_ASSERT(dcd != RT_NULL); - - return dcd->ops->ep_stall(ep); -} - -rt_inline rt_uint8_t dcd_ep_alloc(udcd_t dcd, uep_t ep) -{ - RT_ASSERT(dcd != RT_NULL); - - return dcd->ops->ep_alloc(ep); -} - -rt_inline rt_err_t dcd_ep_free(udcd_t dcd, uep_t ep) -{ - RT_ASSERT(dcd != RT_NULL); - - return dcd->ops->ep_free(ep); -} - -rt_inline rt_err_t dcd_ep_run(udcd_t dcd, uep_t ep) -{ - RT_ASSERT(dcd != RT_NULL); - - return dcd->ops->ep_run(ep); -} - -rt_inline rt_err_t dcd_ep_stop(udcd_t dcd, uep_t ep) -{ - RT_ASSERT(dcd != RT_NULL); - - return dcd->ops->ep_stop(ep); -} - -rt_inline rt_err_t dcd_ep_read(udcd_t dcd, uep_t ep, void *buffer, - rt_size_t size) -{ - RT_ASSERT(dcd != RT_NULL); - - return dcd->ops->ep_read(ep, buffer, size); -} - -rt_inline rt_size_t dcd_ep_write(udcd_t dcd, uep_t ep, void *buffer, - rt_size_t size) -{ - RT_ASSERT(dcd != RT_NULL); - - return dcd->ops->ep_write(ep, buffer, size); -} - -#endif +/* + * File : usb_device.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2012, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2012-10-01 Yi Qiu first version + * 2012-12-12 heyuanjie87 change endpoint and class handler + */ + +#ifndef __USB_DEVICE_H__ +#define __USB_DEVICE_H__ + +#include +#include "usb_common.h" + +#define CONTROL_SEND_STATUS 0x00 +#define CONTROL_RECEIVE_STATUS 0x01 + +#define USB_VENDOR_ID 0x0483 /* Vendor ID */ +#define USB_BCD_DEVICE 0x0200 /* USB Specification Release Number in Binary-Coded Decimal */ +#define USB_BCD_VERSION 0x0200 /* USB 2.0 */ + +struct uclass; +struct udevice; +struct uendpoint; + +struct udcd_ops +{ + rt_err_t (*set_address)(rt_uint8_t value); + rt_err_t (*clear_feature)(rt_uint8_t value); + rt_err_t (*set_feature)(rt_uint8_t value); + rt_err_t (*ep_alloc)(struct uendpoint* ep); + rt_err_t (*ep_free)(struct uendpoint* ep); + rt_err_t (*ep_stall)(struct uendpoint* ep); + rt_err_t (*ep_run)(struct uendpoint* ep); + rt_err_t (*ep_stop)(struct uendpoint* ep); + rt_err_t (*ep_read)(struct uendpoint* ep, void *buffer, rt_size_t size); + rt_size_t (*ep_write)(struct uendpoint* ep, void *buffer, rt_size_t size); +}; + +struct udcd +{ + struct rt_device parent; + struct udcd_ops* ops; + struct rt_completion completion; +}; +typedef struct udcd* udcd_t; + +typedef rt_err_t (*udep_handler_t)(struct udevice* device, struct uclass* cls, rt_size_t size); + +struct uendpoint +{ + rt_list_t list; + rt_uint8_t* buffer; + uep_desc_t ep_desc; + udep_handler_t handler; + rt_bool_t is_stall; +}; +typedef struct uendpoint* uep_t; + +struct ualtsetting +{ + rt_list_t list; + uintf_desc_t intf_desc; + void* desc; + rt_size_t desc_size; + rt_list_t ep_list; +}; +typedef struct ualtsetting* ualtsetting_t; + +typedef rt_err_t (*uintf_handler_t)(struct udevice* device, struct uclass* cls, ureq_t setup); + +struct uinterface +{ + rt_list_t list; + rt_uint8_t intf_num; + ualtsetting_t curr_setting; + rt_list_t setting_list; + uintf_handler_t handler; +}; +typedef struct uinterface* uintf_t; + +struct uclass_ops +{ + rt_err_t (*run)(struct udevice* device, struct uclass* cls); + rt_err_t (*stop)(struct udevice* device, struct uclass* cls); + rt_err_t (*sof_handler)(struct udevice* device, struct uclass* cls); +}; +typedef struct uclass_ops* uclass_ops_t; + +struct uclass +{ + rt_list_t list; + uclass_ops_t ops; + void* eps; + struct udevice* device; + udev_desc_t dev_desc; + void* user_data; + + rt_list_t intf_list; +}; +typedef struct uclass* uclass_t; + +struct uconfig +{ + rt_list_t list; + struct uconfig_descriptor cfg_desc; + rt_list_t cls_list; +}; +typedef struct uconfig* uconfig_t; + +struct udevice +{ + rt_list_t list; + struct udevice_descriptor dev_desc; + const char** str; + + rt_list_t cfg_list; + uconfig_t curr_cfg; + rt_uint8_t nr_intf; + + udcd_t dcd; +}; +typedef struct udevice* udevice_t; + +enum udev_msg_type +{ + USB_MSG_SETUP_NOTIFY, + USB_MSG_DATA_NOTIFY, + USB_MSG_SOF, +}; +typedef enum udev_msg_type udev_msg_type; + +struct udev_msg +{ + udev_msg_type type; + udcd_t dcd; + union + { + struct + { + rt_size_t size; + rt_uint8_t ep_addr; + } ep_msg; + struct + { + rt_uint32_t* packet; + } setup_msg; + } content; +}; +typedef struct udev_msg* udev_msg_t; + +udevice_t rt_usbd_device_create(const char** str); +uconfig_t rt_usbd_config_create(void); +uclass_t rt_usbd_class_create(udevice_t device, udev_desc_t dev_desc, + uclass_ops_t ops); +uintf_t rt_usbd_interface_create(udevice_t device, uintf_handler_t handler); +uep_t rt_usbd_endpoint_create(uep_desc_t ep_desc, udep_handler_t handler); +ualtsetting_t rt_usbd_altsetting_create(rt_size_t desc_size); + +rt_err_t rt_usbd_core_init(void); +rt_err_t rt_usb_device_init(const char* udc_name); +rt_err_t rt_usbd_post_event(struct udev_msg* msg, rt_size_t size); +rt_err_t rt_usbd_free_device(udevice_t device); +rt_err_t rt_usbd_device_set_controller(udevice_t device, udcd_t dcd); +rt_err_t rt_usbd_device_set_descriptor(udevice_t device, udev_desc_t dev_desc); +rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg); +rt_err_t rt_usbd_config_add_class(uconfig_t cfg, uclass_t cls); +rt_err_t rt_usbd_class_add_interface(uclass_t cls, uintf_t intf); +rt_err_t rt_usbd_interface_add_altsetting(uintf_t intf, ualtsetting_t setting); +rt_err_t rt_usbd_altsetting_add_endpoint(ualtsetting_t setting, uep_t ep); +rt_err_t rt_usbd_altsetting_config_descriptor(ualtsetting_t setting, const void* desc, rt_off_t intf_pos); +rt_err_t rt_usbd_set_config(udevice_t device, rt_uint8_t value); +rt_err_t rt_usbd_set_altsetting(uintf_t intf, rt_uint8_t value); + +udevice_t rt_usbd_find_device(udcd_t dcd); +uconfig_t rt_usbd_find_config(udevice_t device, rt_uint8_t value); +uintf_t rt_usbd_find_interface(udevice_t device, rt_uint8_t value, uclass_t *pcls); +uep_t rt_usbd_find_endpoint(udevice_t device, uclass_t* pcls, rt_uint8_t ep_addr); + +uclass_t rt_usbd_class_mstorage_create(udevice_t device); +uclass_t rt_usbd_class_cdc_create(udevice_t device); +uclass_t rt_usbd_class_rndis_create(udevice_t device); + +#ifdef RT_USB_DEVICE_COMPOSITE +rt_err_t rt_usbd_class_set_iad(uclass_t cls, uiad_desc_t iad_desc); +#endif + +rt_inline rt_err_t dcd_set_address(udcd_t dcd, rt_uint8_t value) +{ + RT_ASSERT(dcd != RT_NULL); + + return dcd->ops->set_address(value); +} + +rt_inline rt_err_t dcd_clear_feature(udcd_t dcd, rt_uint8_t value) +{ + RT_ASSERT(dcd != RT_NULL); + + return dcd->ops->clear_feature(value); +} + +rt_inline rt_err_t dcd_set_feature(udcd_t dcd, rt_uint8_t value) +{ + RT_ASSERT(dcd != RT_NULL); + + return dcd->ops->set_feature(value); +} + +rt_inline rt_err_t dcd_ep_stall(udcd_t dcd, uep_t ep) +{ + RT_ASSERT(dcd != RT_NULL); + + return dcd->ops->ep_stall(ep); +} + +rt_inline rt_uint8_t dcd_ep_alloc(udcd_t dcd, uep_t ep) +{ + RT_ASSERT(dcd != RT_NULL); + + return dcd->ops->ep_alloc(ep); +} + +rt_inline rt_err_t dcd_ep_free(udcd_t dcd, uep_t ep) +{ + RT_ASSERT(dcd != RT_NULL); + + return dcd->ops->ep_free(ep); +} + +rt_inline rt_err_t dcd_ep_run(udcd_t dcd, uep_t ep) +{ + RT_ASSERT(dcd != RT_NULL); + + return dcd->ops->ep_run(ep); +} + +rt_inline rt_err_t dcd_ep_stop(udcd_t dcd, uep_t ep) +{ + RT_ASSERT(dcd != RT_NULL); + + return dcd->ops->ep_stop(ep); +} + +rt_inline rt_err_t dcd_ep_read(udcd_t dcd, uep_t ep, void *buffer, + rt_size_t size) +{ + RT_ASSERT(dcd != RT_NULL); + + return dcd->ops->ep_read(ep, buffer, size); +} + +rt_inline rt_size_t dcd_ep_write(udcd_t dcd, uep_t ep, void *buffer, + rt_size_t size) +{ + RT_ASSERT(dcd != RT_NULL); + + return dcd->ops->ep_write(ep, buffer, size); +} + +#endif diff --git a/components/drivers/include/drivers/usb_host.h b/components/drivers/include/drivers/usb_host.h index 026dcdac08..8803d5236b 100644 --- a/components/drivers/include/drivers/usb_host.h +++ b/components/drivers/include/drivers/usb_host.h @@ -1,276 +1,276 @@ -/* - * File : usb_host.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2011, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2011-3-12 Yi Qiu first version - */ - -#ifndef __RT_USB_HOST_H__ -#define __RT_USB_HOST_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "usb_common.h" - -#define USB_MAX_DEVICE 0x20 -#define USB_MAX_INTERFACE 0x08 -#define USB_HUB_PORT_NUM 0x04 -#define SIZEOF_USB_REQUEST 0x08 - -#define UINST_STATUS_IDLE 0x00 -#define UINST_STATUS_BUSY 0x01 -#define UINST_STATUS_ERROR 0x02 - -#define UPIPE_STATUS_OK 0x00 -#define UPIPE_STATUS_STALL 0x01 -#define UPIPE_STATUS_ERROR 0x02 - -struct uhcd; -struct uifinst; -struct uhubinst; - -struct uclass_driver -{ - rt_list_t list; - int class_code; - int subclass_code; - - rt_err_t (*run)(void* arg); - rt_err_t (*stop)(void* arg); - - void* user_data; -}; -typedef struct uclass_driver* ucd_t; - -struct uprotocal -{ - rt_list_t list; - int pro_id; - - rt_err_t (*init)(void* arg); - rt_err_t (*callback)(void* arg); -}; -typedef struct uprotocal* uprotocal_t; - -struct uinstance -{ - struct udevice_descriptor dev_desc; - ucfg_desc_t cfg_desc; - struct uhcd *hcd; - - rt_uint8_t status; - rt_uint8_t type; - rt_uint8_t index; - rt_uint8_t address; - rt_uint8_t speed; - rt_uint8_t max_packet_size; - rt_uint8_t port; - - struct uhubinst* parent; - struct uifinst* ifinst[USB_MAX_INTERFACE]; -}; -typedef struct uinstance* uinst_t; - -struct uifinst -{ - uinst_t uinst; - uintf_desc_t intf_desc; - - ucd_t drv; - void *user_data; -}; -typedef struct uifinst* uifinst_t; - -struct upipe -{ - rt_uint32_t status; - struct uendpoint_descriptor ep; - uifinst_t ifinst; - func_callback callback; - void* user_data; -}; -typedef struct upipe* upipe_t; - -struct uhubinst -{ - struct uhub_descriptor hub_desc; - rt_uint8_t num_ports; - rt_uint32_t port_status[USB_HUB_PORT_NUM]; - struct uinstance* child[USB_HUB_PORT_NUM]; - - rt_bool_t is_roothub; - upipe_t pipe_in; - rt_uint8_t buffer[8]; - struct uinstance* self; - struct uhcd *hcd; -}; -typedef struct uhubinst* uhubinst_t; - -struct uhcd_ops -{ - int (*ctl_xfer)(uinst_t inst, ureq_t setup, void* buffer, int nbytes, - int timeout); - int (*bulk_xfer)(upipe_t pipe, void* buffer, int nbytes, int timeout); - int (*int_xfer)(upipe_t pipe, void* buffer, int nbytes, int timeout); - int (*iso_xfer)(upipe_t pipe, void* buffer, int nbytes, int timeout); - - rt_err_t (*alloc_pipe)(struct upipe** pipe, uifinst_t ifinst, uep_desc_t ep, - func_callback callback); - rt_err_t (*free_pipe)(upipe_t pipe); - rt_err_t (*hub_ctrl)(rt_uint16_t port, rt_uint8_t cmd, void *args); -}; - -struct uhcd -{ - struct rt_device parent; - struct uhcd_ops* ops; -}; -typedef struct uhcd* uhcd_t; - -enum uhost_msg_type -{ - USB_MSG_CONNECT_CHANGE, - USB_MSG_CALLBACK, -}; -typedef enum uhost_msg_type uhost_msg_type; - -struct uhost_msg -{ - uhost_msg_type type; - union - { - struct uhubinst* uhub; - struct - { - func_callback function; - void *context; - }cb; - }content; -}; -typedef struct uhost_msg* uhost_msg_t; - -/* usb host system interface */ -void rt_usb_host_init(void); -void rt_usb_hub_thread(void); - -/* usb host core interface */ -uinst_t rt_usb_alloc_instance(void); -rt_err_t rt_usb_attatch_instance(uinst_t uinst); -rt_err_t rt_usb_detach_instance(uinst_t uinst); -rt_err_t rt_usb_get_descriptor(uinst_t uinst, rt_uint8_t type, void* buffer, - int nbytes); -rt_err_t rt_usb_set_configure(uinst_t uinst, int config); -rt_err_t rt_usb_set_address(uinst_t uinst); -rt_err_t rt_usb_set_interface(uinst_t uinst, int intf); -rt_err_t rt_usb_clear_feature(uinst_t uinst, int endpoint, int feature); -rt_err_t rt_usb_get_interface_descriptor(ucfg_desc_t cfg_desc, int num, - uintf_desc_t* intf_desc); -rt_err_t rt_usb_get_endpoint_descriptor(uintf_desc_t intf_desc, int num, - uep_desc_t* ep_desc); - -/* usb class driver interface */ -rt_err_t rt_usb_class_driver_init(void); -rt_err_t rt_usb_class_driver_register(ucd_t drv); -rt_err_t rt_usb_class_driver_unregister(ucd_t drv); -rt_err_t rt_usb_class_driver_run(ucd_t drv, void* args); -rt_err_t rt_usb_class_driver_stop(ucd_t drv, void* args); -ucd_t rt_usb_class_driver_find(int class_code, int subclass_code); - -/* usb class driver implement */ -ucd_t rt_usb_class_driver_hid(void); -ucd_t rt_usb_class_driver_hub(void); -ucd_t rt_usb_class_driver_storage(void); -ucd_t rt_usb_class_driver_adk(void); - -/* usb hid protocal implement */ -uprotocal_t rt_usb_hid_protocal_kbd(void); -uprotocal_t rt_usb_hid_protocal_mouse(void); - -/* usb adk class driver interface */ -rt_err_t rt_usb_adk_set_string(const char* manufacturer, const char* model, - const char* description, const char* version, const char* uri, - const char* serial); - -/* usb hub interface */ -rt_err_t rt_usb_hub_get_descriptor(uinst_t uinst, rt_uint8_t *buffer, - rt_size_t size); -rt_err_t rt_usb_hub_get_status(uinst_t uinst, rt_uint8_t* buffer); -rt_err_t rt_usb_hub_get_port_status(uhubinst_t uhub, rt_uint16_t port, - rt_uint8_t* buffer); -rt_err_t rt_usb_hub_clear_port_feature(uhubinst_t uhub, rt_uint16_t port, - rt_uint16_t feature); -rt_err_t rt_usb_hub_set_port_feature(uhubinst_t uhub, rt_uint16_t port, - rt_uint16_t feature); -rt_err_t rt_usb_hub_reset_port(uhubinst_t uhub, rt_uint16_t port); -rt_err_t rt_usb_post_event(struct uhost_msg* msg, rt_size_t size); - -/* usb host controller driver interface */ -rt_inline rt_err_t rt_usb_hcd_alloc_pipe(uhcd_t hcd, upipe_t* pipe, - uifinst_t ifinst, uep_desc_t ep, func_callback callback) -{ - if(ifinst == RT_NULL) return -RT_EIO; - - return hcd->ops->alloc_pipe(pipe, ifinst, ep, callback); -} - -rt_inline rt_err_t rt_usb_hcd_free_pipe(uhcd_t hcd, upipe_t pipe) -{ - RT_ASSERT(pipe != RT_NULL); - - return hcd->ops->free_pipe(pipe); -} - -rt_inline int rt_usb_hcd_bulk_xfer(uhcd_t hcd, upipe_t pipe, void* buffer, - int nbytes, int timeout) -{ - if(pipe == RT_NULL) return -1; - if(pipe->ifinst == RT_NULL) return -1; - if(pipe->ifinst->uinst == RT_NULL) return -1; - if(pipe->ifinst->uinst->status == UINST_STATUS_IDLE) - return -1; - - return hcd->ops->bulk_xfer(pipe, buffer, nbytes, timeout); -} - -rt_inline int rt_usb_hcd_control_xfer(uhcd_t hcd, uinst_t uinst, ureq_t setup, - void* buffer, int nbytes, int timeout) -{ - if(uinst->status == UINST_STATUS_IDLE) return -1; - - return hcd->ops->ctl_xfer(uinst, setup, buffer, nbytes, timeout); -} - -rt_inline int rt_usb_hcd_int_xfer(uhcd_t hcd, upipe_t pipe, void* buffer, - int nbytes, int timeout) -{ - if(pipe == RT_NULL) return -1; - if(pipe->ifinst == RT_NULL) return -1; - if(pipe->ifinst->uinst == RT_NULL) return -1; - if(pipe->ifinst->uinst->status == UINST_STATUS_IDLE) - return -1; - - return hcd->ops->int_xfer(pipe, buffer, nbytes, timeout); -} - -rt_inline rt_err_t rt_usb_hcd_hub_control(uhcd_t hcd, rt_uint16_t port, - rt_uint8_t cmd, void *args) -{ - return hcd->ops->hub_ctrl(port, cmd, args); -} - -#ifdef __cplusplus -} -#endif - -#endif - +/* + * File : usb_host.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2011, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2011-3-12 Yi Qiu first version + */ + +#ifndef __RT_USB_HOST_H__ +#define __RT_USB_HOST_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "usb_common.h" + +#define USB_MAX_DEVICE 0x20 +#define USB_MAX_INTERFACE 0x08 +#define USB_HUB_PORT_NUM 0x04 +#define SIZEOF_USB_REQUEST 0x08 + +#define UINST_STATUS_IDLE 0x00 +#define UINST_STATUS_BUSY 0x01 +#define UINST_STATUS_ERROR 0x02 + +#define UPIPE_STATUS_OK 0x00 +#define UPIPE_STATUS_STALL 0x01 +#define UPIPE_STATUS_ERROR 0x02 + +struct uhcd; +struct uifinst; +struct uhubinst; + +struct uclass_driver +{ + rt_list_t list; + int class_code; + int subclass_code; + + rt_err_t (*run)(void* arg); + rt_err_t (*stop)(void* arg); + + void* user_data; +}; +typedef struct uclass_driver* ucd_t; + +struct uprotocal +{ + rt_list_t list; + int pro_id; + + rt_err_t (*init)(void* arg); + rt_err_t (*callback)(void* arg); +}; +typedef struct uprotocal* uprotocal_t; + +struct uinstance +{ + struct udevice_descriptor dev_desc; + ucfg_desc_t cfg_desc; + struct uhcd *hcd; + + rt_uint8_t status; + rt_uint8_t type; + rt_uint8_t index; + rt_uint8_t address; + rt_uint8_t speed; + rt_uint8_t max_packet_size; + rt_uint8_t port; + + struct uhubinst* parent; + struct uifinst* ifinst[USB_MAX_INTERFACE]; +}; +typedef struct uinstance* uinst_t; + +struct uifinst +{ + uinst_t uinst; + uintf_desc_t intf_desc; + + ucd_t drv; + void *user_data; +}; +typedef struct uifinst* uifinst_t; + +struct upipe +{ + rt_uint32_t status; + struct uendpoint_descriptor ep; + uifinst_t ifinst; + func_callback callback; + void* user_data; +}; +typedef struct upipe* upipe_t; + +struct uhubinst +{ + struct uhub_descriptor hub_desc; + rt_uint8_t num_ports; + rt_uint32_t port_status[USB_HUB_PORT_NUM]; + struct uinstance* child[USB_HUB_PORT_NUM]; + + rt_bool_t is_roothub; + upipe_t pipe_in; + rt_uint8_t buffer[8]; + struct uinstance* self; + struct uhcd *hcd; +}; +typedef struct uhubinst* uhubinst_t; + +struct uhcd_ops +{ + int (*ctl_xfer)(uinst_t inst, ureq_t setup, void* buffer, int nbytes, + int timeout); + int (*bulk_xfer)(upipe_t pipe, void* buffer, int nbytes, int timeout); + int (*int_xfer)(upipe_t pipe, void* buffer, int nbytes, int timeout); + int (*iso_xfer)(upipe_t pipe, void* buffer, int nbytes, int timeout); + + rt_err_t (*alloc_pipe)(struct upipe** pipe, uifinst_t ifinst, uep_desc_t ep, + func_callback callback); + rt_err_t (*free_pipe)(upipe_t pipe); + rt_err_t (*hub_ctrl)(rt_uint16_t port, rt_uint8_t cmd, void *args); +}; + +struct uhcd +{ + struct rt_device parent; + struct uhcd_ops* ops; +}; +typedef struct uhcd* uhcd_t; + +enum uhost_msg_type +{ + USB_MSG_CONNECT_CHANGE, + USB_MSG_CALLBACK, +}; +typedef enum uhost_msg_type uhost_msg_type; + +struct uhost_msg +{ + uhost_msg_type type; + union + { + struct uhubinst* uhub; + struct + { + func_callback function; + void *context; + }cb; + }content; +}; +typedef struct uhost_msg* uhost_msg_t; + +/* usb host system interface */ +void rt_usb_host_init(void); +void rt_usb_hub_thread(void); + +/* usb host core interface */ +uinst_t rt_usb_alloc_instance(void); +rt_err_t rt_usb_attatch_instance(uinst_t uinst); +rt_err_t rt_usb_detach_instance(uinst_t uinst); +rt_err_t rt_usb_get_descriptor(uinst_t uinst, rt_uint8_t type, void* buffer, + int nbytes); +rt_err_t rt_usb_set_configure(uinst_t uinst, int config); +rt_err_t rt_usb_set_address(uinst_t uinst); +rt_err_t rt_usb_set_interface(uinst_t uinst, int intf); +rt_err_t rt_usb_clear_feature(uinst_t uinst, int endpoint, int feature); +rt_err_t rt_usb_get_interface_descriptor(ucfg_desc_t cfg_desc, int num, + uintf_desc_t* intf_desc); +rt_err_t rt_usb_get_endpoint_descriptor(uintf_desc_t intf_desc, int num, + uep_desc_t* ep_desc); + +/* usb class driver interface */ +rt_err_t rt_usb_class_driver_init(void); +rt_err_t rt_usb_class_driver_register(ucd_t drv); +rt_err_t rt_usb_class_driver_unregister(ucd_t drv); +rt_err_t rt_usb_class_driver_run(ucd_t drv, void* args); +rt_err_t rt_usb_class_driver_stop(ucd_t drv, void* args); +ucd_t rt_usb_class_driver_find(int class_code, int subclass_code); + +/* usb class driver implement */ +ucd_t rt_usb_class_driver_hid(void); +ucd_t rt_usb_class_driver_hub(void); +ucd_t rt_usb_class_driver_storage(void); +ucd_t rt_usb_class_driver_adk(void); + +/* usb hid protocal implement */ +uprotocal_t rt_usb_hid_protocal_kbd(void); +uprotocal_t rt_usb_hid_protocal_mouse(void); + +/* usb adk class driver interface */ +rt_err_t rt_usb_adk_set_string(const char* manufacturer, const char* model, + const char* description, const char* version, const char* uri, + const char* serial); + +/* usb hub interface */ +rt_err_t rt_usb_hub_get_descriptor(uinst_t uinst, rt_uint8_t *buffer, + rt_size_t size); +rt_err_t rt_usb_hub_get_status(uinst_t uinst, rt_uint8_t* buffer); +rt_err_t rt_usb_hub_get_port_status(uhubinst_t uhub, rt_uint16_t port, + rt_uint8_t* buffer); +rt_err_t rt_usb_hub_clear_port_feature(uhubinst_t uhub, rt_uint16_t port, + rt_uint16_t feature); +rt_err_t rt_usb_hub_set_port_feature(uhubinst_t uhub, rt_uint16_t port, + rt_uint16_t feature); +rt_err_t rt_usb_hub_reset_port(uhubinst_t uhub, rt_uint16_t port); +rt_err_t rt_usb_post_event(struct uhost_msg* msg, rt_size_t size); + +/* usb host controller driver interface */ +rt_inline rt_err_t rt_usb_hcd_alloc_pipe(uhcd_t hcd, upipe_t* pipe, + uifinst_t ifinst, uep_desc_t ep, func_callback callback) +{ + if(ifinst == RT_NULL) return -RT_EIO; + + return hcd->ops->alloc_pipe(pipe, ifinst, ep, callback); +} + +rt_inline rt_err_t rt_usb_hcd_free_pipe(uhcd_t hcd, upipe_t pipe) +{ + RT_ASSERT(pipe != RT_NULL); + + return hcd->ops->free_pipe(pipe); +} + +rt_inline int rt_usb_hcd_bulk_xfer(uhcd_t hcd, upipe_t pipe, void* buffer, + int nbytes, int timeout) +{ + if(pipe == RT_NULL) return -1; + if(pipe->ifinst == RT_NULL) return -1; + if(pipe->ifinst->uinst == RT_NULL) return -1; + if(pipe->ifinst->uinst->status == UINST_STATUS_IDLE) + return -1; + + return hcd->ops->bulk_xfer(pipe, buffer, nbytes, timeout); +} + +rt_inline int rt_usb_hcd_control_xfer(uhcd_t hcd, uinst_t uinst, ureq_t setup, + void* buffer, int nbytes, int timeout) +{ + if(uinst->status == UINST_STATUS_IDLE) return -1; + + return hcd->ops->ctl_xfer(uinst, setup, buffer, nbytes, timeout); +} + +rt_inline int rt_usb_hcd_int_xfer(uhcd_t hcd, upipe_t pipe, void* buffer, + int nbytes, int timeout) +{ + if(pipe == RT_NULL) return -1; + if(pipe->ifinst == RT_NULL) return -1; + if(pipe->ifinst->uinst == RT_NULL) return -1; + if(pipe->ifinst->uinst->status == UINST_STATUS_IDLE) + return -1; + + return hcd->ops->int_xfer(pipe, buffer, nbytes, timeout); +} + +rt_inline rt_err_t rt_usb_hcd_hub_control(uhcd_t hcd, rt_uint16_t port, + rt_uint8_t cmd, void *args) +{ + return hcd->ops->hub_ctrl(port, cmd, args); +} + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index 77e43f495d..f3400953ff 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -138,9 +138,9 @@ rt_err_t rt_data_queue_peak(struct rt_data_queue *queue, void rt_data_queue_reset(struct rt_data_queue *queue); #ifdef RT_USING_RTC -#include "drivers/rtc.h" -#ifdef RT_USING_ALARM -#include "drivers/alarm.h" +#include "drivers/rtc.h" +#ifdef RT_USING_ALARM +#include "drivers/alarm.h" #endif #endif /* RT_USING_RTC */ diff --git a/components/drivers/mtd/SConscript b/components/drivers/mtd/SConscript index 614f7a48ff..b9aac09b4b 100644 --- a/components/drivers/mtd/SConscript +++ b/components/drivers/mtd/SConscript @@ -1,22 +1,22 @@ -Import('RTT_ROOT') -Import('rtconfig') -from building import * - -cwd = GetCurrentDir() -src = [] - -mtd_nor = ['mtd_nor.c'] - -mtd_nand = ['mtd_nand.c'] - -CPPPATH = [cwd + '/../include'] -group = [] - -if GetDepend(['RT_USING_MTD_NOR']): - src = src + mtd_nor - group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_MTD_NOR'], CPPPATH = CPPPATH) -if GetDepend(['RT_USING_MTD_NAND']): - src = src + mtd_nand - group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_MTD_NAND'], CPPPATH = CPPPATH) - -Return('group') +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() +src = [] + +mtd_nor = ['mtd_nor.c'] + +mtd_nand = ['mtd_nand.c'] + +CPPPATH = [cwd + '/../include'] +group = [] + +if GetDepend(['RT_USING_MTD_NOR']): + src = src + mtd_nor + group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_MTD_NOR'], CPPPATH = CPPPATH) +if GetDepend(['RT_USING_MTD_NAND']): + src = src + mtd_nand + group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_MTD_NAND'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/rtc/SConscript b/components/drivers/rtc/SConscript index 65552a7765..9191ffec97 100644 --- a/components/drivers/rtc/SConscript +++ b/components/drivers/rtc/SConscript @@ -1,20 +1,20 @@ -from building import * - -cwd = GetCurrentDir() -src = [] - -rtc = ['rtc.c'] - -rtc_alarm = ['alarm.c'] - -CPPPATH = [cwd + '/../include'] -group = [] - -if GetDepend(['RT_USING_RTC']): - src = src + rtc - if GetDepend(['RT_USING_ALARM']): - src = src + rtc_alarm - -group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_RTC'], CPPPATH = CPPPATH) - +from building import * + +cwd = GetCurrentDir() +src = [] + +rtc = ['rtc.c'] + +rtc_alarm = ['alarm.c'] + +CPPPATH = [cwd + '/../include'] +group = [] + +if GetDepend(['RT_USING_RTC']): + src = src + rtc + if GetDepend(['RT_USING_ALARM']): + src = src + rtc_alarm + +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_RTC'], CPPPATH = CPPPATH) + Return('group') \ No newline at end of file diff --git a/components/drivers/sdio/SConscript b/components/drivers/sdio/SConscript index 83477d00d4..d2c8aa4e58 100644 --- a/components/drivers/sdio/SConscript +++ b/components/drivers/sdio/SConscript @@ -1,17 +1,17 @@ -Import('RTT_ROOT') -from building import * - -cwd = GetCurrentDir() -src = Split(""" -block_dev.c -mmcsd_core.c -sd.c -sdio.c -""") - -# The set of source files associated with this SConscript file. -path = [cwd + '/../include'] - -group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SDIO'], CPPPATH = path) - -Return('group') +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +src = Split(""" +block_dev.c +mmcsd_core.c +sd.c +sdio.c +""") + +# The set of source files associated with this SConscript file. +path = [cwd + '/../include'] + +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SDIO'], CPPPATH = path) + +Return('group') diff --git a/components/drivers/sdio/sdio.c b/components/drivers/sdio/sdio.c index 18f4f85163..1b472c5c56 100644 --- a/components/drivers/sdio/sdio.c +++ b/components/drivers/sdio/sdio.c @@ -1,1344 +1,1344 @@ -/* - * File : sdio.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2012-01-13 weety first version - */ - -#include -#include - -#ifndef RT_SDIO_STACK_SIZE -#define RT_SDIO_STACK_SIZE 512 -#endif -#ifndef RT_SDIO_THREAD_PREORITY -#define RT_SDIO_THREAD_PREORITY 0x40 -#endif - -static rt_list_t sdio_cards; -static rt_list_t sdio_drivers; - -struct sdio_card { - struct rt_mmcsd_card *card; - rt_list_t list; -}; - -struct sdio_driver { - struct rt_sdio_driver *drv; - rt_list_t list; -}; - -#define MIN(a, b) (a < b ? a : b) - -static const rt_uint8_t speed_value[16] = - { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 }; - -static const rt_uint32_t speed_unit[8] = - { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 }; - -rt_inline rt_int32_t sdio_match_card(struct rt_mmcsd_card *card, - const struct rt_sdio_device_id *id); - - -rt_int32_t sdio_io_send_op_cond(struct rt_mmcsd_host *host, rt_uint32_t ocr, rt_uint32_t -*cmd5_resp) -{ - struct rt_mmcsd_cmd cmd; - rt_int32_t i, err = 0; - - RT_ASSERT(host != RT_NULL); - - rt_memset(&cmd, 0, sizeof(struct rt_mmcsd_cmd)); - - cmd.cmd_code = SD_IO_SEND_OP_COND; - cmd.arg = ocr; - cmd.flags = RESP_SPI_R4 | RESP_R4 | CMD_BCR; - - for (i = 100; i; i--) - { - err = mmcsd_send_cmd(host, &cmd, 0); - if (err) - break; - - /* if we're just probing, do a single pass */ - if (ocr == 0) - break; - - /* otherwise wait until reset completes */ - if (controller_is_spi(host)) - { - /* - * Both R1_SPI_IDLE and MMC_CARD_BUSY indicate - * an initialized card under SPI, but some cards - * (Marvell's) only behave when looking at this - * one. - */ - if (cmd.resp[1] & CARD_BUSY) - break; - } - else - { - if (cmd.resp[0] & CARD_BUSY) - break; - } - - err = -RT_ETIMEOUT; - - mmcsd_delay_ms(10); - } - - if (cmd5_resp) - *cmd5_resp = cmd.resp[controller_is_spi(host) ? 1 : 0]; - - return err; -} - - -rt_int32_t sdio_io_rw_direct(struct rt_mmcsd_card *card, rt_int32_t rw, rt_uint32_t fn, - rt_uint32_t reg_addr, rt_uint8_t *pdata, rt_uint8_t raw) -{ - struct rt_mmcsd_cmd cmd; - rt_int32_t err; - - RT_ASSERT(card != RT_NULL); - RT_ASSERT(fn <= SDIO_MAX_FUNCTIONS); - - if (reg_addr & ~SDIO_ARG_CMD53_REG_MASK) - return -RT_ERROR; - - rt_memset(&cmd, 0, sizeof(struct rt_mmcsd_cmd)); - - cmd.cmd_code = SD_IO_RW_DIRECT; - cmd.arg = rw ? SDIO_ARG_CMD52_WRITE : SDIO_ARG_CMD52_READ; - cmd.arg |= fn << SDIO_ARG_CMD52_FUNC_SHIFT; - cmd.arg |= raw ? SDIO_ARG_CMD52_RAW_FLAG : 0x00000000; - cmd.arg |= reg_addr << SDIO_ARG_CMD52_REG_SHIFT; - cmd.arg |= *pdata; - cmd.flags = RESP_SPI_R5 | RESP_R5 | CMD_AC; - - err = mmcsd_send_cmd(card->host, &cmd, 0); - if (err) - return err; - - if (!controller_is_spi(card->host)) - { - if (cmd.resp[0] & R5_ERROR) - return -RT_EIO; - if (cmd.resp[0] & R5_FUNCTION_NUMBER) - return -RT_ERROR; - if (cmd.resp[0] & R5_OUT_OF_RANGE) - return -RT_ERROR; - } - - if (!rw || raw) - { - if (controller_is_spi(card->host)) - *pdata = (cmd.resp[0] >> 8) & 0xFF; - else - *pdata = cmd.resp[0] & 0xFF; - } - - return 0; -} - -rt_int32_t sdio_io_rw_extended(struct rt_mmcsd_card *card, rt_int32_t rw, rt_uint32_t fn, - rt_uint32_t addr, rt_int32_t op_code, rt_uint8_t *buf, rt_uint32_t blocks, rt_uint32_t blksize) -{ - struct rt_mmcsd_req req; - struct rt_mmcsd_cmd cmd; - struct rt_mmcsd_data data; - - RT_ASSERT(card != RT_NULL); - RT_ASSERT(fn <= SDIO_MAX_FUNCTIONS); - RT_ASSERT(blocks != 1 || blksize <= 512); - RT_ASSERT(blocks != 0); - RT_ASSERT(blksize != 0); - - if (addr & ~SDIO_ARG_CMD53_REG_MASK) - return -RT_ERROR; - - rt_memset(&req, 0, sizeof(struct rt_mmcsd_req)); - rt_memset(&cmd, 0, sizeof(struct rt_mmcsd_cmd)); - rt_memset(&data, 0, sizeof(struct rt_mmcsd_data)); - - req.cmd = &cmd; - req.data = &data; - - cmd.cmd_code = SD_IO_RW_EXTENDED; - cmd.arg = rw ? SDIO_ARG_CMD53_WRITE : SDIO_ARG_CMD53_READ; - cmd.arg |= fn << SDIO_ARG_CMD53_FUNC_SHIFT; - cmd.arg |= op_code ? SDIO_ARG_CMD53_INCREMENT : 0x00000000; - cmd.arg |= addr << SDIO_ARG_CMD53_REG_SHIFT; - if (blocks == 1 && blksize <= 512) - cmd.arg |= (blksize == 512) ? 0 : blksize; /* byte mode */ - else - cmd.arg |= SDIO_ARG_CMD53_BLOCK_MODE | blocks; /* block mode */ - cmd.flags = RESP_SPI_R5 | RESP_R5 | CMD_ADTC; - - data.blksize = blksize; - data.blks = blocks; - data.flags = rw ? DATA_DIR_WRITE : DATA_DIR_READ; - data.buf = (rt_uint32_t *)buf; - - mmcsd_set_data_timeout(&data, card); - - mmcsd_send_request(card->host, &req); - - if (cmd.err) - return cmd.err; - if (data.err) - return data.err; - - if (!controller_is_spi(card->host)) - { - if (cmd.resp[0] & R5_ERROR) - return -RT_EIO; - if (cmd.resp[0] & R5_FUNCTION_NUMBER) - return -RT_ERROR; - if (cmd.resp[0] & R5_OUT_OF_RANGE) - return -RT_ERROR; - } - - return 0; -} - -rt_inline rt_uint32_t sdio_max_block_size(struct rt_sdio_function *func) -{ - rt_uint32_t size = MIN(func->card->host->max_seg_size, - func->card->host->max_blk_size); - size = MIN(size, func->max_blk_size); - return MIN(size, 512u); /* maximum size for byte mode */ -} - -static rt_int32_t sdio_io_rw_extended_block(struct rt_sdio_function *func, rt_int32_t rw, - rt_uint32_t addr, rt_int32_t op_code, rt_uint8_t *buf, rt_uint32_t len) -{ - rt_int32_t ret; - rt_uint32_t left_size; - rt_uint32_t max_blks, blks; - - left_size = len; - - /* Do the bulk of the transfer using block mode (if supported). */ - if (func->card->cccr.multi_block && (len > sdio_max_block_size(func))) { - max_blks = MIN(func->card->host->max_blk_count, - func->card->host->max_seg_size / func->cur_blk_size); - max_blks = MIN(max_blks, 511u); - - while (left_size > func->cur_blk_size) { - - blks = left_size / func->cur_blk_size; - if (blks > max_blks) - blks = max_blks; - len = blks * func->cur_blk_size; - - ret = sdio_io_rw_extended(func->card, rw, func->num, - addr, op_code, buf, blks, func->cur_blk_size); - if (ret) - return ret; - - left_size -= len; - buf += len; - if (op_code) - addr += len; - } - } - - while (left_size > 0) { - len = MIN(left_size, sdio_max_block_size(func)); - - ret = sdio_io_rw_extended(func->card, rw, func->num, - addr, op_code, buf, 1, len); - if (ret) - return ret; - - left_size -= len; - buf += len; - if (op_code) - addr += len; - } - - return 0; -} - - -rt_uint8_t sdio_io_readb(struct rt_sdio_function *func, - rt_uint32_t reg, rt_int32_t *err) -{ - rt_uint8_t data; - rt_int32_t ret; - - ret = sdio_io_rw_direct(func->card, 0, func->num, reg, &data, 0); - - if (err) - { - *err = ret; - } - - return data; -} - -rt_int32_t sdio_io_writeb(struct rt_sdio_function *func, - rt_uint32_t reg, rt_uint8_t data) -{ - return sdio_io_rw_direct(func->card, 1, func->num, reg, &data, 0); -} - -rt_uint16_t sdio_io_readw(struct rt_sdio_function *func, rt_uint32_t addr, rt_int32_t *err) -{ - rt_int32_t ret; - rt_uint32_t dmabuf; - - if (err) - *err = 0; - - ret = sdio_io_rw_extended_block(func, 0, addr, 1, (rt_uint8_t *)&dmabuf, 2); - if (ret) - { - if (err) - *err = ret; - } - - return (rt_uint16_t)dmabuf; -} - -rt_int32_t sdio_io_writew(struct rt_sdio_function *func, rt_uint16_t data, rt_uint32_t addr) -{ - rt_uint32_t dmabuf = data; - - return sdio_io_rw_extended_block(func, 1, addr, 1, (rt_uint8_t *)&dmabuf, 2); -} - -rt_uint32_t sdio_io_readl(struct rt_sdio_function *func, rt_uint32_t addr, rt_int32_t *err) -{ - rt_int32_t ret; - rt_uint32_t dmabuf; - - if (err) - *err = 0; - - ret = sdio_io_rw_extended_block(func, 0, addr, 1, (rt_uint8_t *)&dmabuf, 4); - if (ret) - { - if (err) - *err = ret; - } - - return dmabuf; -} - -rt_int32_t sdio_io_writel(struct rt_sdio_function *func, rt_uint32_t data, rt_uint32_t addr) -{ - rt_uint32_t dmabuf = data; - - return sdio_io_rw_extended_block(func, 1, addr, 1, (rt_uint8_t *)&dmabuf, 4); -} - -rt_int32_t sdio_io_read_multi_fifo_b(struct rt_sdio_function *func, - rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t len) -{ - return sdio_io_rw_extended_block(func, 0, addr, 0, buf, len); -} - -rt_int32_t sdio_io_write_multi_fifo_b(struct rt_sdio_function *func, - rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t len) -{ - return sdio_io_rw_extended_block(func, 1, addr, 0, buf, len); -} - -rt_int32_t sdio_io_read_multi_incr_b(struct rt_sdio_function *func, - rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t len) -{ - return sdio_io_rw_extended_block(func, 0, addr, 1, buf, len); -} - -rt_int32_t sdio_io_write_multi_incr_b(struct rt_sdio_function *func, - rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t len) -{ - return sdio_io_rw_extended_block(func, 1, addr, 1, buf, len); -} - -static rt_int32_t sdio_read_cccr(struct rt_mmcsd_card *card) -{ - rt_int32_t ret; - rt_int32_t cccr_version; - rt_uint8_t data; - - rt_memset(&card->cccr, 0, sizeof(struct rt_sdio_cccr)); - - data = sdio_io_readb(card->sdio_function[0], SDIO_REG_CCCR_CCCR_REV, &ret); - if (ret) - goto out; - - cccr_version = data & 0x0f; - - if (cccr_version > SDIO_CCCR_REV_1_20) - { - rt_kprintf("unrecognised CCCR structure version %d\n", cccr_version); - return -RT_ERROR; - } - - card->cccr.sdio_version = (data & 0xf0) >> 4; - - data = sdio_io_readb(card->sdio_function[0], SDIO_REG_CCCR_CARD_CAPS, &ret); - if (ret) - goto out; - - if (data & SDIO_CCCR_CAP_SMB) - card->cccr.multi_block = 1; - if (data & SDIO_CCCR_CAP_LSC) - card->cccr.low_speed = 1; - if (data & SDIO_CCCR_CAP_4BLS) - card->cccr.low_speed_4 = 1; - if (data & SDIO_CCCR_CAP_4BLS) - card->cccr.bus_width = 1; - - if (cccr_version >= SDIO_CCCR_REV_1_10) - { - data = sdio_io_readb(card->sdio_function[0], SDIO_REG_CCCR_POWER_CTRL, &ret); - if (ret) - goto out; - - if (data & SDIO_POWER_SMPC) - card->cccr.power_ctrl = 1; - } - - if (cccr_version >= SDIO_CCCR_REV_1_20) - { - data = sdio_io_readb(card->sdio_function[0], SDIO_REG_CCCR_SPEED, &ret); - if (ret) - goto out; - - if (data & SDIO_SPEED_SHS) - card->cccr.high_speed = 1; - } - -out: - return ret; -} - -static rt_int32_t cistpl_funce_func0(struct rt_mmcsd_card *card, - const rt_uint8_t *buf, rt_uint32_t size) -{ - if (size < 0x04 || buf[0] != 0) - return -RT_ERROR; - - /* TPLFE_FN0_BLK_SIZE */ - card->cis.func0_blk_size = buf[1] | (buf[2] << 8); - - /* TPLFE_MAX_TRAN_SPEED */ - card->cis.max_tran_speed = speed_value[(buf[3] >> 3) & 15] * - speed_unit[buf[3] & 7]; - - return 0; -} - -static rt_int32_t cistpl_funce_func(struct rt_sdio_function *func, - const rt_uint8_t *buf, rt_uint32_t size) -{ - rt_uint32_t version; - rt_uint32_t min_size; - - version = func->card->cccr.sdio_version; - min_size = (version == SDIO_SDIO_REV_1_00) ? 28 : 42; - - if (size < min_size || buf[0] != 1) - return -RT_ERROR; - - /* TPLFE_MAX_BLK_SIZE */ - func->max_blk_size = buf[12] | (buf[13] << 8); - - /* TPLFE_ENABLE_TIMEOUT_VAL, present in ver 1.1 and above */ - if (version > SDIO_SDIO_REV_1_00) - func->enable_timeout_val = (buf[28] | (buf[29] << 8)) * 10; - else - func->enable_timeout_val = 1000; /* 1000ms */ - - return 0; -} - -static rt_int32_t sdio_read_cis(struct rt_sdio_function *func) -{ - rt_int32_t ret; - struct rt_sdio_function_tuple *curr, **prev; - rt_uint32_t i, cisptr = 0; - rt_uint8_t data; - rt_uint8_t tpl_code, tpl_link; - - struct rt_mmcsd_card *card = func->card; - struct rt_sdio_function *func0 = card->sdio_function[0]; - - RT_ASSERT(func0 != RT_NULL); - - for (i = 0; i < 3; i++) - { - data = sdio_io_readb(func0, - SDIO_REG_FBR_BASE(func->num) + SDIO_REG_FBR_CIS + i, &ret); - if (ret) - return ret; - cisptr |= data << (i * 8); - } - - prev = &func->tuples; - - do { - tpl_code = sdio_io_readb(func0, cisptr++, &ret); - if (ret) - break; - tpl_link = sdio_io_readb(func0, cisptr++, &ret); - if (ret) - break; - - if ((tpl_code == CISTPL_END) || (tpl_link == 0xff)) - break; - - if (tpl_code == CISTPL_NULL) - continue; - - - curr = rt_malloc(sizeof(struct rt_sdio_function_tuple) + tpl_link); - if (!curr) - return -RT_ENOMEM; - curr->data = (rt_uint8_t *)curr + sizeof(struct rt_sdio_function_tuple); - - for (i = 0; i < tpl_link; i++) - { - curr->data[i] = sdio_io_readb(func0, cisptr + i, &ret); - if (ret) - break; - } - if (ret) - { - rt_free(curr); - break; - } - - switch (tpl_code) - { - case CISTPL_MANFID: - if (tpl_link < 4) - { - rt_kprintf("bad CISTPL_MANFID length\n"); - break; - } - if (func->num != 0) - { - func->manufacturer = curr->data[0]; - func->manufacturer |= curr->data[1] << 8; - func->product = curr->data[2]; - func->product |= curr->data[3] << 8; - } - else - { - card->cis.manufacturer = curr->data[0]; - card->cis.manufacturer |= curr->data[1] << 8; - card->cis.product = curr->data[2]; - card->cis.product |= curr->data[3] << 8; - } - break; - case CISTPL_FUNCE: - if (func->num != 0) - ret = cistpl_funce_func(func, curr->data, tpl_link); - else - ret = cistpl_funce_func0(card, curr->data, tpl_link); - - if (ret) - { - rt_kprintf("bad CISTPL_FUNCE size %u " - "type %u\n", tpl_link, curr->data[0]); - } - - break; - case CISTPL_VERS_1: - if (tpl_link < 2) - { - rt_kprintf("CISTPL_VERS_1 too short\n"); - } - break; - default: - /* this tuple is unknown to the core */ - curr->next = RT_NULL; - curr->code = tpl_code; - curr->size = tpl_link; - *prev = curr; - prev = &curr->next; - rt_kprintf( "function %d, CIS tuple code %#x, length %d\n", - func->num, tpl_code, tpl_link); - break; - } - - cisptr += tpl_link; - } while (1); - - /* - * Link in all unknown tuples found in the common CIS so that - * drivers don't have to go digging in two places. - */ - if (func->num != 0) - *prev = func0->tuples; - - return ret; -} - - -void sdio_free_cis(struct rt_sdio_function *func) -{ - struct rt_sdio_function_tuple *tuple, *tmp; - struct rt_mmcsd_card *card = func->card; - - tuple = func->tuples; - - while (tuple && ((tuple != card->sdio_function[0]->tuples) || (!func->num))) - { - tmp = tuple; - tuple = tuple->next; - rt_free(tmp); - } - - func->tuples = RT_NULL; -} - - - -static rt_int32_t sdio_read_fbr(struct rt_sdio_function *func) -{ - rt_int32_t ret; - rt_uint8_t data; - struct rt_sdio_function *func0 = func->card->sdio_function[0]; - - data = sdio_io_readb(func0, - SDIO_REG_FBR_BASE(func->num) + SDIO_REG_FBR_STD_FUNC_IF, &ret); - if (ret) - goto err; - - data &= 0x0f; - - if (data == 0x0f) - { - data = sdio_io_readb(func0, - SDIO_REG_FBR_BASE(func->num) + SDIO_REG_FBR_STD_IF_EXT, &ret); - if (ret) - goto err; - } - - func->func_code = data; - -err: - return ret; -} - - -static rt_int32_t sdio_initialize_function(struct rt_mmcsd_card *card, rt_uint32_t func_num) -{ - rt_int32_t ret; - struct rt_sdio_function *func; - - RT_ASSERT(func_num <= SDIO_MAX_FUNCTIONS); - - func = rt_malloc(sizeof(struct rt_sdio_function)); - if (!func) - { - rt_kprintf("malloc rt_sdio_function failed\n"); - ret = -RT_ENOMEM; - goto err; - } - rt_memset(func, 0, sizeof(struct rt_sdio_function)); - - func->card = card; - func->num = func_num; - - ret = sdio_read_fbr(func); - if (ret) - goto err1; - - ret = sdio_read_cis(func); - if (ret) - goto err1; - - card->sdio_function[func_num] = func; - - return 0; - -err1: - sdio_free_cis(func); - rt_free(func); - card->sdio_function[func_num] = RT_NULL; -err: - return ret; -} - - -static rt_int32_t sdio_set_highspeed(struct rt_mmcsd_card *card) -{ - rt_int32_t ret; - rt_uint8_t speed; - - if (!(card->host->flags & MMCSD_SUP_HIGHSPEED)) - return 0; - - if (!card->cccr.high_speed) - return 0; - - speed = sdio_io_readb(card->sdio_function[0], SDIO_REG_CCCR_SPEED, &ret); - if (ret) - return ret; - - speed |= SDIO_SPEED_EHS; - - ret = sdio_io_writeb(card->sdio_function[0], SDIO_REG_CCCR_SPEED, speed); - if (ret) - return ret; - - card->flags |= CARD_FLAG_HIGHSPEED; - - return 0; -} - -static rt_int32_t sdio_set_bus_wide(struct rt_mmcsd_card *card) -{ - rt_int32_t ret; - rt_uint8_t busif; - - if (!(card->host->flags & MMCSD_BUSWIDTH_4)) - return 0; - - if (card->cccr.low_speed && !card->cccr.bus_width) - return 0; - - busif = sdio_io_readb(card->sdio_function[0], SDIO_REG_CCCR_BUS_IF, &ret); - if (ret) - return ret; - - busif |= SDIO_BUS_WIDTH_4BIT; - - ret = sdio_io_writeb(card->sdio_function[0], SDIO_REG_CCCR_BUS_IF, busif); - if (ret) - return ret; - - mmcsd_set_bus_width(card->host, MMCSD_BUS_WIDTH_4); - - return 0; -} - - -static rt_int32_t sdio_register_card(struct rt_mmcsd_card *card) -{ - struct sdio_card *sc; - struct sdio_driver *sd; - rt_list_t *l; - - sc = rt_malloc(sizeof(struct sdio_card)); - if (sc == RT_NULL) - { - rt_kprintf("malloc sdio card failed\n"); - return -RT_ENOMEM; - } - - sc->card = card; - rt_list_insert_after(&sdio_cards, &sc->list); - - if (rt_list_isempty(&sdio_drivers)) - { - goto out; - } - - for (l = (&sdio_drivers)->next; l != &sdio_drivers; l = l->next) - { - sd = (struct sdio_driver *)rt_list_entry(l, struct sdio_driver, list); - if (sdio_match_card(card, sd->drv->id)) - { - sd->drv->probe(card); - } - } - -out: - return 0; -} - - -static rt_int32_t sdio_init_card(struct rt_mmcsd_host *host, rt_uint32_t ocr) -{ - rt_int32_t err = 0; - rt_int32_t i, function_num; - rt_uint32_t cmd5_resp; - struct rt_mmcsd_card *card; - - err = sdio_io_send_op_cond(host, ocr, &cmd5_resp); - if (err) - goto err; - - if (controller_is_spi(host)) - { - err = mmcsd_spi_use_crc(host, host->spi_use_crc); - if (err) - goto err; - } - - function_num = (cmd5_resp & 0x70000000) >> 28; - - card = rt_malloc(sizeof(struct rt_mmcsd_card)); +/* + * File : sdio.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2012-01-13 weety first version + */ + +#include +#include + +#ifndef RT_SDIO_STACK_SIZE +#define RT_SDIO_STACK_SIZE 512 +#endif +#ifndef RT_SDIO_THREAD_PREORITY +#define RT_SDIO_THREAD_PREORITY 0x40 +#endif + +static rt_list_t sdio_cards; +static rt_list_t sdio_drivers; + +struct sdio_card { + struct rt_mmcsd_card *card; + rt_list_t list; +}; + +struct sdio_driver { + struct rt_sdio_driver *drv; + rt_list_t list; +}; + +#define MIN(a, b) (a < b ? a : b) + +static const rt_uint8_t speed_value[16] = + { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 }; + +static const rt_uint32_t speed_unit[8] = + { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 }; + +rt_inline rt_int32_t sdio_match_card(struct rt_mmcsd_card *card, + const struct rt_sdio_device_id *id); + + +rt_int32_t sdio_io_send_op_cond(struct rt_mmcsd_host *host, rt_uint32_t ocr, rt_uint32_t +*cmd5_resp) +{ + struct rt_mmcsd_cmd cmd; + rt_int32_t i, err = 0; + + RT_ASSERT(host != RT_NULL); + + rt_memset(&cmd, 0, sizeof(struct rt_mmcsd_cmd)); + + cmd.cmd_code = SD_IO_SEND_OP_COND; + cmd.arg = ocr; + cmd.flags = RESP_SPI_R4 | RESP_R4 | CMD_BCR; + + for (i = 100; i; i--) + { + err = mmcsd_send_cmd(host, &cmd, 0); + if (err) + break; + + /* if we're just probing, do a single pass */ + if (ocr == 0) + break; + + /* otherwise wait until reset completes */ + if (controller_is_spi(host)) + { + /* + * Both R1_SPI_IDLE and MMC_CARD_BUSY indicate + * an initialized card under SPI, but some cards + * (Marvell's) only behave when looking at this + * one. + */ + if (cmd.resp[1] & CARD_BUSY) + break; + } + else + { + if (cmd.resp[0] & CARD_BUSY) + break; + } + + err = -RT_ETIMEOUT; + + mmcsd_delay_ms(10); + } + + if (cmd5_resp) + *cmd5_resp = cmd.resp[controller_is_spi(host) ? 1 : 0]; + + return err; +} + + +rt_int32_t sdio_io_rw_direct(struct rt_mmcsd_card *card, rt_int32_t rw, rt_uint32_t fn, + rt_uint32_t reg_addr, rt_uint8_t *pdata, rt_uint8_t raw) +{ + struct rt_mmcsd_cmd cmd; + rt_int32_t err; + + RT_ASSERT(card != RT_NULL); + RT_ASSERT(fn <= SDIO_MAX_FUNCTIONS); + + if (reg_addr & ~SDIO_ARG_CMD53_REG_MASK) + return -RT_ERROR; + + rt_memset(&cmd, 0, sizeof(struct rt_mmcsd_cmd)); + + cmd.cmd_code = SD_IO_RW_DIRECT; + cmd.arg = rw ? SDIO_ARG_CMD52_WRITE : SDIO_ARG_CMD52_READ; + cmd.arg |= fn << SDIO_ARG_CMD52_FUNC_SHIFT; + cmd.arg |= raw ? SDIO_ARG_CMD52_RAW_FLAG : 0x00000000; + cmd.arg |= reg_addr << SDIO_ARG_CMD52_REG_SHIFT; + cmd.arg |= *pdata; + cmd.flags = RESP_SPI_R5 | RESP_R5 | CMD_AC; + + err = mmcsd_send_cmd(card->host, &cmd, 0); + if (err) + return err; + + if (!controller_is_spi(card->host)) + { + if (cmd.resp[0] & R5_ERROR) + return -RT_EIO; + if (cmd.resp[0] & R5_FUNCTION_NUMBER) + return -RT_ERROR; + if (cmd.resp[0] & R5_OUT_OF_RANGE) + return -RT_ERROR; + } + + if (!rw || raw) + { + if (controller_is_spi(card->host)) + *pdata = (cmd.resp[0] >> 8) & 0xFF; + else + *pdata = cmd.resp[0] & 0xFF; + } + + return 0; +} + +rt_int32_t sdio_io_rw_extended(struct rt_mmcsd_card *card, rt_int32_t rw, rt_uint32_t fn, + rt_uint32_t addr, rt_int32_t op_code, rt_uint8_t *buf, rt_uint32_t blocks, rt_uint32_t blksize) +{ + struct rt_mmcsd_req req; + struct rt_mmcsd_cmd cmd; + struct rt_mmcsd_data data; + + RT_ASSERT(card != RT_NULL); + RT_ASSERT(fn <= SDIO_MAX_FUNCTIONS); + RT_ASSERT(blocks != 1 || blksize <= 512); + RT_ASSERT(blocks != 0); + RT_ASSERT(blksize != 0); + + if (addr & ~SDIO_ARG_CMD53_REG_MASK) + return -RT_ERROR; + + rt_memset(&req, 0, sizeof(struct rt_mmcsd_req)); + rt_memset(&cmd, 0, sizeof(struct rt_mmcsd_cmd)); + rt_memset(&data, 0, sizeof(struct rt_mmcsd_data)); + + req.cmd = &cmd; + req.data = &data; + + cmd.cmd_code = SD_IO_RW_EXTENDED; + cmd.arg = rw ? SDIO_ARG_CMD53_WRITE : SDIO_ARG_CMD53_READ; + cmd.arg |= fn << SDIO_ARG_CMD53_FUNC_SHIFT; + cmd.arg |= op_code ? SDIO_ARG_CMD53_INCREMENT : 0x00000000; + cmd.arg |= addr << SDIO_ARG_CMD53_REG_SHIFT; + if (blocks == 1 && blksize <= 512) + cmd.arg |= (blksize == 512) ? 0 : blksize; /* byte mode */ + else + cmd.arg |= SDIO_ARG_CMD53_BLOCK_MODE | blocks; /* block mode */ + cmd.flags = RESP_SPI_R5 | RESP_R5 | CMD_ADTC; + + data.blksize = blksize; + data.blks = blocks; + data.flags = rw ? DATA_DIR_WRITE : DATA_DIR_READ; + data.buf = (rt_uint32_t *)buf; + + mmcsd_set_data_timeout(&data, card); + + mmcsd_send_request(card->host, &req); + + if (cmd.err) + return cmd.err; + if (data.err) + return data.err; + + if (!controller_is_spi(card->host)) + { + if (cmd.resp[0] & R5_ERROR) + return -RT_EIO; + if (cmd.resp[0] & R5_FUNCTION_NUMBER) + return -RT_ERROR; + if (cmd.resp[0] & R5_OUT_OF_RANGE) + return -RT_ERROR; + } + + return 0; +} + +rt_inline rt_uint32_t sdio_max_block_size(struct rt_sdio_function *func) +{ + rt_uint32_t size = MIN(func->card->host->max_seg_size, + func->card->host->max_blk_size); + size = MIN(size, func->max_blk_size); + return MIN(size, 512u); /* maximum size for byte mode */ +} + +static rt_int32_t sdio_io_rw_extended_block(struct rt_sdio_function *func, rt_int32_t rw, + rt_uint32_t addr, rt_int32_t op_code, rt_uint8_t *buf, rt_uint32_t len) +{ + rt_int32_t ret; + rt_uint32_t left_size; + rt_uint32_t max_blks, blks; + + left_size = len; + + /* Do the bulk of the transfer using block mode (if supported). */ + if (func->card->cccr.multi_block && (len > sdio_max_block_size(func))) { + max_blks = MIN(func->card->host->max_blk_count, + func->card->host->max_seg_size / func->cur_blk_size); + max_blks = MIN(max_blks, 511u); + + while (left_size > func->cur_blk_size) { + + blks = left_size / func->cur_blk_size; + if (blks > max_blks) + blks = max_blks; + len = blks * func->cur_blk_size; + + ret = sdio_io_rw_extended(func->card, rw, func->num, + addr, op_code, buf, blks, func->cur_blk_size); + if (ret) + return ret; + + left_size -= len; + buf += len; + if (op_code) + addr += len; + } + } + + while (left_size > 0) { + len = MIN(left_size, sdio_max_block_size(func)); + + ret = sdio_io_rw_extended(func->card, rw, func->num, + addr, op_code, buf, 1, len); + if (ret) + return ret; + + left_size -= len; + buf += len; + if (op_code) + addr += len; + } + + return 0; +} + + +rt_uint8_t sdio_io_readb(struct rt_sdio_function *func, + rt_uint32_t reg, rt_int32_t *err) +{ + rt_uint8_t data; + rt_int32_t ret; + + ret = sdio_io_rw_direct(func->card, 0, func->num, reg, &data, 0); + + if (err) + { + *err = ret; + } + + return data; +} + +rt_int32_t sdio_io_writeb(struct rt_sdio_function *func, + rt_uint32_t reg, rt_uint8_t data) +{ + return sdio_io_rw_direct(func->card, 1, func->num, reg, &data, 0); +} + +rt_uint16_t sdio_io_readw(struct rt_sdio_function *func, rt_uint32_t addr, rt_int32_t *err) +{ + rt_int32_t ret; + rt_uint32_t dmabuf; + + if (err) + *err = 0; + + ret = sdio_io_rw_extended_block(func, 0, addr, 1, (rt_uint8_t *)&dmabuf, 2); + if (ret) + { + if (err) + *err = ret; + } + + return (rt_uint16_t)dmabuf; +} + +rt_int32_t sdio_io_writew(struct rt_sdio_function *func, rt_uint16_t data, rt_uint32_t addr) +{ + rt_uint32_t dmabuf = data; + + return sdio_io_rw_extended_block(func, 1, addr, 1, (rt_uint8_t *)&dmabuf, 2); +} + +rt_uint32_t sdio_io_readl(struct rt_sdio_function *func, rt_uint32_t addr, rt_int32_t *err) +{ + rt_int32_t ret; + rt_uint32_t dmabuf; + + if (err) + *err = 0; + + ret = sdio_io_rw_extended_block(func, 0, addr, 1, (rt_uint8_t *)&dmabuf, 4); + if (ret) + { + if (err) + *err = ret; + } + + return dmabuf; +} + +rt_int32_t sdio_io_writel(struct rt_sdio_function *func, rt_uint32_t data, rt_uint32_t addr) +{ + rt_uint32_t dmabuf = data; + + return sdio_io_rw_extended_block(func, 1, addr, 1, (rt_uint8_t *)&dmabuf, 4); +} + +rt_int32_t sdio_io_read_multi_fifo_b(struct rt_sdio_function *func, + rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t len) +{ + return sdio_io_rw_extended_block(func, 0, addr, 0, buf, len); +} + +rt_int32_t sdio_io_write_multi_fifo_b(struct rt_sdio_function *func, + rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t len) +{ + return sdio_io_rw_extended_block(func, 1, addr, 0, buf, len); +} + +rt_int32_t sdio_io_read_multi_incr_b(struct rt_sdio_function *func, + rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t len) +{ + return sdio_io_rw_extended_block(func, 0, addr, 1, buf, len); +} + +rt_int32_t sdio_io_write_multi_incr_b(struct rt_sdio_function *func, + rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t len) +{ + return sdio_io_rw_extended_block(func, 1, addr, 1, buf, len); +} + +static rt_int32_t sdio_read_cccr(struct rt_mmcsd_card *card) +{ + rt_int32_t ret; + rt_int32_t cccr_version; + rt_uint8_t data; + + rt_memset(&card->cccr, 0, sizeof(struct rt_sdio_cccr)); + + data = sdio_io_readb(card->sdio_function[0], SDIO_REG_CCCR_CCCR_REV, &ret); + if (ret) + goto out; + + cccr_version = data & 0x0f; + + if (cccr_version > SDIO_CCCR_REV_1_20) + { + rt_kprintf("unrecognised CCCR structure version %d\n", cccr_version); + return -RT_ERROR; + } + + card->cccr.sdio_version = (data & 0xf0) >> 4; + + data = sdio_io_readb(card->sdio_function[0], SDIO_REG_CCCR_CARD_CAPS, &ret); + if (ret) + goto out; + + if (data & SDIO_CCCR_CAP_SMB) + card->cccr.multi_block = 1; + if (data & SDIO_CCCR_CAP_LSC) + card->cccr.low_speed = 1; + if (data & SDIO_CCCR_CAP_4BLS) + card->cccr.low_speed_4 = 1; + if (data & SDIO_CCCR_CAP_4BLS) + card->cccr.bus_width = 1; + + if (cccr_version >= SDIO_CCCR_REV_1_10) + { + data = sdio_io_readb(card->sdio_function[0], SDIO_REG_CCCR_POWER_CTRL, &ret); + if (ret) + goto out; + + if (data & SDIO_POWER_SMPC) + card->cccr.power_ctrl = 1; + } + + if (cccr_version >= SDIO_CCCR_REV_1_20) + { + data = sdio_io_readb(card->sdio_function[0], SDIO_REG_CCCR_SPEED, &ret); + if (ret) + goto out; + + if (data & SDIO_SPEED_SHS) + card->cccr.high_speed = 1; + } + +out: + return ret; +} + +static rt_int32_t cistpl_funce_func0(struct rt_mmcsd_card *card, + const rt_uint8_t *buf, rt_uint32_t size) +{ + if (size < 0x04 || buf[0] != 0) + return -RT_ERROR; + + /* TPLFE_FN0_BLK_SIZE */ + card->cis.func0_blk_size = buf[1] | (buf[2] << 8); + + /* TPLFE_MAX_TRAN_SPEED */ + card->cis.max_tran_speed = speed_value[(buf[3] >> 3) & 15] * + speed_unit[buf[3] & 7]; + + return 0; +} + +static rt_int32_t cistpl_funce_func(struct rt_sdio_function *func, + const rt_uint8_t *buf, rt_uint32_t size) +{ + rt_uint32_t version; + rt_uint32_t min_size; + + version = func->card->cccr.sdio_version; + min_size = (version == SDIO_SDIO_REV_1_00) ? 28 : 42; + + if (size < min_size || buf[0] != 1) + return -RT_ERROR; + + /* TPLFE_MAX_BLK_SIZE */ + func->max_blk_size = buf[12] | (buf[13] << 8); + + /* TPLFE_ENABLE_TIMEOUT_VAL, present in ver 1.1 and above */ + if (version > SDIO_SDIO_REV_1_00) + func->enable_timeout_val = (buf[28] | (buf[29] << 8)) * 10; + else + func->enable_timeout_val = 1000; /* 1000ms */ + + return 0; +} + +static rt_int32_t sdio_read_cis(struct rt_sdio_function *func) +{ + rt_int32_t ret; + struct rt_sdio_function_tuple *curr, **prev; + rt_uint32_t i, cisptr = 0; + rt_uint8_t data; + rt_uint8_t tpl_code, tpl_link; + + struct rt_mmcsd_card *card = func->card; + struct rt_sdio_function *func0 = card->sdio_function[0]; + + RT_ASSERT(func0 != RT_NULL); + + for (i = 0; i < 3; i++) + { + data = sdio_io_readb(func0, + SDIO_REG_FBR_BASE(func->num) + SDIO_REG_FBR_CIS + i, &ret); + if (ret) + return ret; + cisptr |= data << (i * 8); + } + + prev = &func->tuples; + + do { + tpl_code = sdio_io_readb(func0, cisptr++, &ret); + if (ret) + break; + tpl_link = sdio_io_readb(func0, cisptr++, &ret); + if (ret) + break; + + if ((tpl_code == CISTPL_END) || (tpl_link == 0xff)) + break; + + if (tpl_code == CISTPL_NULL) + continue; + + + curr = rt_malloc(sizeof(struct rt_sdio_function_tuple) + tpl_link); + if (!curr) + return -RT_ENOMEM; + curr->data = (rt_uint8_t *)curr + sizeof(struct rt_sdio_function_tuple); + + for (i = 0; i < tpl_link; i++) + { + curr->data[i] = sdio_io_readb(func0, cisptr + i, &ret); + if (ret) + break; + } + if (ret) + { + rt_free(curr); + break; + } + + switch (tpl_code) + { + case CISTPL_MANFID: + if (tpl_link < 4) + { + rt_kprintf("bad CISTPL_MANFID length\n"); + break; + } + if (func->num != 0) + { + func->manufacturer = curr->data[0]; + func->manufacturer |= curr->data[1] << 8; + func->product = curr->data[2]; + func->product |= curr->data[3] << 8; + } + else + { + card->cis.manufacturer = curr->data[0]; + card->cis.manufacturer |= curr->data[1] << 8; + card->cis.product = curr->data[2]; + card->cis.product |= curr->data[3] << 8; + } + break; + case CISTPL_FUNCE: + if (func->num != 0) + ret = cistpl_funce_func(func, curr->data, tpl_link); + else + ret = cistpl_funce_func0(card, curr->data, tpl_link); + + if (ret) + { + rt_kprintf("bad CISTPL_FUNCE size %u " + "type %u\n", tpl_link, curr->data[0]); + } + + break; + case CISTPL_VERS_1: + if (tpl_link < 2) + { + rt_kprintf("CISTPL_VERS_1 too short\n"); + } + break; + default: + /* this tuple is unknown to the core */ + curr->next = RT_NULL; + curr->code = tpl_code; + curr->size = tpl_link; + *prev = curr; + prev = &curr->next; + rt_kprintf( "function %d, CIS tuple code %#x, length %d\n", + func->num, tpl_code, tpl_link); + break; + } + + cisptr += tpl_link; + } while (1); + + /* + * Link in all unknown tuples found in the common CIS so that + * drivers don't have to go digging in two places. + */ + if (func->num != 0) + *prev = func0->tuples; + + return ret; +} + + +void sdio_free_cis(struct rt_sdio_function *func) +{ + struct rt_sdio_function_tuple *tuple, *tmp; + struct rt_mmcsd_card *card = func->card; + + tuple = func->tuples; + + while (tuple && ((tuple != card->sdio_function[0]->tuples) || (!func->num))) + { + tmp = tuple; + tuple = tuple->next; + rt_free(tmp); + } + + func->tuples = RT_NULL; +} + + + +static rt_int32_t sdio_read_fbr(struct rt_sdio_function *func) +{ + rt_int32_t ret; + rt_uint8_t data; + struct rt_sdio_function *func0 = func->card->sdio_function[0]; + + data = sdio_io_readb(func0, + SDIO_REG_FBR_BASE(func->num) + SDIO_REG_FBR_STD_FUNC_IF, &ret); + if (ret) + goto err; + + data &= 0x0f; + + if (data == 0x0f) + { + data = sdio_io_readb(func0, + SDIO_REG_FBR_BASE(func->num) + SDIO_REG_FBR_STD_IF_EXT, &ret); + if (ret) + goto err; + } + + func->func_code = data; + +err: + return ret; +} + + +static rt_int32_t sdio_initialize_function(struct rt_mmcsd_card *card, rt_uint32_t func_num) +{ + rt_int32_t ret; + struct rt_sdio_function *func; + + RT_ASSERT(func_num <= SDIO_MAX_FUNCTIONS); + + func = rt_malloc(sizeof(struct rt_sdio_function)); + if (!func) + { + rt_kprintf("malloc rt_sdio_function failed\n"); + ret = -RT_ENOMEM; + goto err; + } + rt_memset(func, 0, sizeof(struct rt_sdio_function)); + + func->card = card; + func->num = func_num; + + ret = sdio_read_fbr(func); + if (ret) + goto err1; + + ret = sdio_read_cis(func); + if (ret) + goto err1; + + card->sdio_function[func_num] = func; + + return 0; + +err1: + sdio_free_cis(func); + rt_free(func); + card->sdio_function[func_num] = RT_NULL; +err: + return ret; +} + + +static rt_int32_t sdio_set_highspeed(struct rt_mmcsd_card *card) +{ + rt_int32_t ret; + rt_uint8_t speed; + + if (!(card->host->flags & MMCSD_SUP_HIGHSPEED)) + return 0; + + if (!card->cccr.high_speed) + return 0; + + speed = sdio_io_readb(card->sdio_function[0], SDIO_REG_CCCR_SPEED, &ret); + if (ret) + return ret; + + speed |= SDIO_SPEED_EHS; + + ret = sdio_io_writeb(card->sdio_function[0], SDIO_REG_CCCR_SPEED, speed); + if (ret) + return ret; + + card->flags |= CARD_FLAG_HIGHSPEED; + + return 0; +} + +static rt_int32_t sdio_set_bus_wide(struct rt_mmcsd_card *card) +{ + rt_int32_t ret; + rt_uint8_t busif; + + if (!(card->host->flags & MMCSD_BUSWIDTH_4)) + return 0; + + if (card->cccr.low_speed && !card->cccr.bus_width) + return 0; + + busif = sdio_io_readb(card->sdio_function[0], SDIO_REG_CCCR_BUS_IF, &ret); + if (ret) + return ret; + + busif |= SDIO_BUS_WIDTH_4BIT; + + ret = sdio_io_writeb(card->sdio_function[0], SDIO_REG_CCCR_BUS_IF, busif); + if (ret) + return ret; + + mmcsd_set_bus_width(card->host, MMCSD_BUS_WIDTH_4); + + return 0; +} + + +static rt_int32_t sdio_register_card(struct rt_mmcsd_card *card) +{ + struct sdio_card *sc; + struct sdio_driver *sd; + rt_list_t *l; + + sc = rt_malloc(sizeof(struct sdio_card)); + if (sc == RT_NULL) + { + rt_kprintf("malloc sdio card failed\n"); + return -RT_ENOMEM; + } + + sc->card = card; + rt_list_insert_after(&sdio_cards, &sc->list); + + if (rt_list_isempty(&sdio_drivers)) + { + goto out; + } + + for (l = (&sdio_drivers)->next; l != &sdio_drivers; l = l->next) + { + sd = (struct sdio_driver *)rt_list_entry(l, struct sdio_driver, list); + if (sdio_match_card(card, sd->drv->id)) + { + sd->drv->probe(card); + } + } + +out: + return 0; +} + + +static rt_int32_t sdio_init_card(struct rt_mmcsd_host *host, rt_uint32_t ocr) +{ + rt_int32_t err = 0; + rt_int32_t i, function_num; + rt_uint32_t cmd5_resp; + struct rt_mmcsd_card *card; + + err = sdio_io_send_op_cond(host, ocr, &cmd5_resp); + if (err) + goto err; + + if (controller_is_spi(host)) + { + err = mmcsd_spi_use_crc(host, host->spi_use_crc); + if (err) + goto err; + } + + function_num = (cmd5_resp & 0x70000000) >> 28; + + card = rt_malloc(sizeof(struct rt_mmcsd_card)); if (!card) { rt_kprintf("malloc card failed\n"); err = -RT_ENOMEM; goto err; } - rt_memset(card, 0, sizeof(struct rt_mmcsd_card)); - - card->card_type = CARD_TYPE_SDIO; - card->sdio_function_num = function_num; - card->host = host; - host->card = card; - - card->sdio_function[0] = rt_malloc(sizeof(struct rt_sdio_function)); - if (!card->sdio_function[0]) - { - rt_kprintf("malloc sdio_func0 failed\n"); - err = -RT_ENOMEM; - goto err1; - } - rt_memset(card->sdio_function[0], 0, sizeof(struct rt_sdio_function)); - card->sdio_function[0]->card = card; - card->sdio_function[0]->num = 0; - - if (!controller_is_spi(host)) - { - err = mmcsd_get_card_addr(host, &card->rca); - if (err) - goto err2; - - mmcsd_set_bus_mode(host, MMCSD_BUSMODE_PUSHPULL); - } - - if (!controller_is_spi(host)) - { - err = mmcsd_select_card(card); - if (err) - goto err2; - } - - err = sdio_read_cccr(card); - if (err) - goto err2; - - err = sdio_read_cis(card->sdio_function[0]); - if (err) - goto err2; - - err = sdio_set_highspeed(card); - if (err) - goto err2; - - if (card->flags & CARD_FLAG_HIGHSPEED) - { - mmcsd_set_clock(host, 50000000); - } - else - { - mmcsd_set_clock(host, card->cis.max_tran_speed); - } - - err = sdio_set_bus_wide(card); - if (err) - goto err2; - - for (i = 1; i < function_num + 1; i++) - { - err = sdio_initialize_function(card, i); - if (err) - goto err3; - } - - - /* register sdio card */ - err = sdio_register_card(card); - if (err) - { - goto err3; - } - - return 0; - -err3: - if (host->card) - { - for (i = 1; i < host->card->sdio_function_num + 1; i++) - { - if (host->card->sdio_function[i]) - { - sdio_free_cis(host->card->sdio_function[i]); - rt_free(host->card->sdio_function[i]); - host->card->sdio_function[i] = RT_NULL; - rt_free(host->card); - host->card = RT_NULL; - - } - } - } -err2: - if (host->card && host->card->sdio_function[0]) - { - sdio_free_cis(host->card->sdio_function[0]); - rt_free(host->card->sdio_function[0]); - host->card->sdio_function[0] = RT_NULL; - } -err1: - if (host->card) - { - rt_free(host->card); - } -err: - rt_kprintf("error %d while initialising SDIO card\n", err); - - return err; -} - - - -rt_int32_t init_sdio(struct rt_mmcsd_host *host, rt_uint32_t ocr) -{ - rt_int32_t err; - rt_uint32_t current_ocr; - - RT_ASSERT(host != RT_NULL); - - if (ocr & 0x7F) - { - rt_kprintf("Card ocr below the defined voltage rang.\n"); - ocr &= ~0x7F; - } - - if (ocr & VDD_165_195) - { - rt_kprintf("Can't support the low voltage SDIO card.\n"); - ocr &= ~VDD_165_195; - } - - current_ocr = mmcsd_select_voltage(host, ocr); - - if (!current_ocr) - { - err = -RT_ERROR; - goto err; - } - - err = sdio_init_card(host, current_ocr); + rt_memset(card, 0, sizeof(struct rt_mmcsd_card)); + + card->card_type = CARD_TYPE_SDIO; + card->sdio_function_num = function_num; + card->host = host; + host->card = card; + + card->sdio_function[0] = rt_malloc(sizeof(struct rt_sdio_function)); + if (!card->sdio_function[0]) + { + rt_kprintf("malloc sdio_func0 failed\n"); + err = -RT_ENOMEM; + goto err1; + } + rt_memset(card->sdio_function[0], 0, sizeof(struct rt_sdio_function)); + card->sdio_function[0]->card = card; + card->sdio_function[0]->num = 0; + + if (!controller_is_spi(host)) + { + err = mmcsd_get_card_addr(host, &card->rca); + if (err) + goto err2; + + mmcsd_set_bus_mode(host, MMCSD_BUSMODE_PUSHPULL); + } + + if (!controller_is_spi(host)) + { + err = mmcsd_select_card(card); + if (err) + goto err2; + } + + err = sdio_read_cccr(card); + if (err) + goto err2; + + err = sdio_read_cis(card->sdio_function[0]); + if (err) + goto err2; + + err = sdio_set_highspeed(card); + if (err) + goto err2; + + if (card->flags & CARD_FLAG_HIGHSPEED) + { + mmcsd_set_clock(host, 50000000); + } + else + { + mmcsd_set_clock(host, card->cis.max_tran_speed); + } + + err = sdio_set_bus_wide(card); + if (err) + goto err2; + + for (i = 1; i < function_num + 1; i++) + { + err = sdio_initialize_function(card, i); + if (err) + goto err3; + } + + + /* register sdio card */ + err = sdio_register_card(card); + if (err) + { + goto err3; + } + + return 0; + +err3: + if (host->card) + { + for (i = 1; i < host->card->sdio_function_num + 1; i++) + { + if (host->card->sdio_function[i]) + { + sdio_free_cis(host->card->sdio_function[i]); + rt_free(host->card->sdio_function[i]); + host->card->sdio_function[i] = RT_NULL; + rt_free(host->card); + host->card = RT_NULL; + + } + } + } +err2: + if (host->card && host->card->sdio_function[0]) + { + sdio_free_cis(host->card->sdio_function[0]); + rt_free(host->card->sdio_function[0]); + host->card->sdio_function[0] = RT_NULL; + } +err1: + if (host->card) + { + rt_free(host->card); + } +err: + rt_kprintf("error %d while initialising SDIO card\n", err); + + return err; +} + + + +rt_int32_t init_sdio(struct rt_mmcsd_host *host, rt_uint32_t ocr) +{ + rt_int32_t err; + rt_uint32_t current_ocr; + + RT_ASSERT(host != RT_NULL); + + if (ocr & 0x7F) + { + rt_kprintf("Card ocr below the defined voltage rang.\n"); + ocr &= ~0x7F; + } + + if (ocr & VDD_165_195) + { + rt_kprintf("Can't support the low voltage SDIO card.\n"); + ocr &= ~VDD_165_195; + } + + current_ocr = mmcsd_select_voltage(host, ocr); + + if (!current_ocr) + { + err = -RT_ERROR; + goto err; + } + + err = sdio_init_card(host, current_ocr); if (err) - goto remove_card; - + goto remove_card; + return 0; -remove_card: +remove_card: rt_free(host->card); host->card = RT_NULL; err: - rt_kprintf("init SDIO card failed\n"); - - return err; - - - -} - - -static void sdio_irq_thread(void *param) -{ - rt_int32_t i, ret; - rt_uint8_t pending; - struct rt_mmcsd_card *card; - struct rt_mmcsd_host *host = (struct rt_mmcsd_host *)param; - RT_ASSERT(host != RT_NULL); - card = host->card; - RT_ASSERT(card != RT_NULL); - - while (1) - { - if (rt_sem_take(host->sdio_irq_sem, RT_WAITING_FOREVER) == RT_EOK) - { - mmcsd_host_lock(host); - pending = sdio_io_readb(host->card->sdio_function[0], - SDIO_REG_CCCR_INT_PEND, &ret); - if (ret) - { - mmcsd_dbg("error %d reading SDIO_REG_CCCR_INT_PEND\n", ret); - goto out; - } - - for (i = 1; i <= 7; i++) - { - if (pending & (1 << i)) - { - struct rt_sdio_function *func = card->sdio_function[i]; - if (!func) - { - mmcsd_dbg("pending IRQ for " - "non-existant function %d\n", func->num); - goto out; - } - else if (func->irq_handler) - { - func->irq_handler(func); - } - else - { - mmcsd_dbg("pending IRQ with no register handler\n"); - goto out; - } - } - } - - out: - mmcsd_host_unlock(host); - if (host->flags & MMCSD_SUP_SDIO_IRQ) - host->ops->enable_sdio_irq(host, 1); - continue; - } - } -} - -static rt_int32_t sdio_irq_thread_create(struct rt_mmcsd_card *card) -{ - struct rt_mmcsd_host *host = card->host; - - /* init semaphore and create sdio irq processing thread */ - if (!host->sdio_irq_num) - { - host->sdio_irq_num++; - host->sdio_irq_sem = rt_sem_create("sdio_irq", 0, RT_IPC_FLAG_FIFO); - RT_ASSERT(host->sdio_irq_sem != RT_NULL); - - host->sdio_irq_thread = rt_thread_create("sdio_irq", sdio_irq_thread, host, - RT_SDIO_STACK_SIZE, RT_SDIO_THREAD_PREORITY, 20); - if (host->sdio_irq_thread != RT_NULL) - { - rt_thread_startup(host->sdio_irq_thread); - } - } - - return 0; -} - -static rt_int32_t sdio_irq_thread_delete(struct rt_mmcsd_card *card) -{ - struct rt_mmcsd_host *host = card->host; - - RT_ASSERT(host->sdio_irq_num > 0); - - host->sdio_irq_num--; - if (!host->sdio_irq_num) - { - if (host->flags & MMCSD_SUP_SDIO_IRQ) - host->ops->enable_sdio_irq(host, 0); - rt_sem_delete(host->sdio_irq_sem); - host->sdio_irq_sem = RT_NULL; - rt_thread_delete(host->sdio_irq_thread); - host->sdio_irq_thread = RT_NULL; - } - - return 0; -} - - -rt_int32_t sdio_attach_irq(struct rt_sdio_function *func, rt_sdio_irq_handler_t *handler) -{ - rt_int32_t ret; - rt_uint8_t reg; - struct rt_sdio_function *func0; - - RT_ASSERT(func != RT_NULL); - RT_ASSERT(func->card != RT_NULL); - - func0 = func->card->sdio_function[0]; - - mmcsd_dbg("SDIO: enabling IRQ for function %d\n", func->num); - - if (func->irq_handler) - { - mmcsd_dbg("SDIO: IRQ for already in use.\n"); - return -RT_EBUSY; - } - - reg = sdio_io_readb(func0, SDIO_REG_CCCR_INT_EN, &ret); - if (ret) - return ret; - - reg |= 1 << func->num; - - reg |= 1; /* Master interrupt enable */ - - ret = sdio_io_writeb(func0, SDIO_REG_CCCR_INT_EN, reg); - if (ret) - return ret; - - func->irq_handler = handler; - - ret = sdio_irq_thread_create(func->card); - if (ret) - func->irq_handler = RT_NULL; - - return ret; -} - -rt_int32_t sdio_detach_irq(struct rt_sdio_function *func) -{ - rt_int32_t ret; - rt_uint8_t reg; - struct rt_sdio_function *func0; - - RT_ASSERT(func != RT_NULL); - RT_ASSERT(func->card != RT_NULL); - - func0 = func->card->sdio_function[0]; - - mmcsd_dbg("SDIO: disabling IRQ for function %d\n", func->num); - - if (func->irq_handler) - { - func->irq_handler = RT_NULL; - sdio_irq_thread_delete(func->card); - } - - reg = sdio_io_readb(func0, SDIO_REG_CCCR_INT_EN, &ret); - if (ret) - return ret; - - reg &= ~(1 << func->num); - - /* Disable master interrupt with the last function interrupt */ - if (!(reg & 0xFE)) - reg = 0; - - ret = sdio_io_writeb(func0, SDIO_REG_CCCR_INT_EN, reg); - if (ret) - return ret; - - return 0; -} - -void sdio_irq_wakeup(struct rt_mmcsd_host *host) -{ - host->ops->enable_sdio_irq(host, 0); - rt_sem_release(host->sdio_irq_sem); -} - - -rt_int32_t sdio_enable_func(struct rt_sdio_function *func) -{ - rt_int32_t ret; - rt_uint8_t reg; - rt_uint32_t timeout; - struct rt_sdio_function *func0; - - RT_ASSERT(func != RT_NULL); - RT_ASSERT(func->card != RT_NULL); - - func0 = func->card->sdio_function[0]; - - mmcsd_dbg("SDIO: enabling function %d\n", func->num); - - reg = sdio_io_readb(func0, SDIO_REG_CCCR_IO_EN, &ret); - if (ret) - goto err; - - reg |= 1 << func->num; - - ret = sdio_io_writeb(func0, SDIO_REG_CCCR_IO_EN, reg); - if (ret) - goto err; - - timeout = rt_tick_get() + func->enable_timeout_val * 1000 / RT_TICK_PER_SECOND; - - while (1) - { - reg = sdio_io_readb(func0, SDIO_REG_CCCR_IO_RDY, &ret); - if (ret) - goto err; - if (reg & (1 << func->num)) - break; - ret = -RT_ETIMEOUT; - if (rt_tick_get() > timeout) - goto err; - } - - mmcsd_dbg("SDIO: enabled function successfull\n"); - - return 0; - -err: - mmcsd_dbg("SDIO: failed to enable function %d\n", func->num); - return ret; -} - - -rt_int32_t sdio_disable_func(struct rt_sdio_function *func) -{ - rt_int32_t ret; - rt_uint8_t reg; - struct rt_sdio_function *func0; - - RT_ASSERT(func != RT_NULL); - RT_ASSERT(func->card != RT_NULL); - - func0 = func->card->sdio_function[0]; - - mmcsd_dbg("SDIO: disabling function %d\n", func->num); - - reg = sdio_io_readb(func0, SDIO_REG_CCCR_IO_EN, &ret); - if (ret) - goto err; - - reg &= ~(1 << func->num); - - ret = sdio_io_writeb(func0, SDIO_REG_CCCR_IO_EN, reg); - if (ret) - goto err; - - mmcsd_dbg("SDIO: disabled function successfull\n"); - - return 0; - -err: - mmcsd_dbg("SDIO: failed to disable function %d\n", func->num); - return -RT_EIO; -} - -rt_int32_t sdio_set_block_size(struct rt_sdio_function *func, rt_uint32_t blksize) -{ - rt_int32_t ret; - struct rt_sdio_function *func0 = func->card->sdio_function[0]; - - if (blksize > func->card->host->max_blk_size) - return -RT_ERROR; - - if (blksize == 0) - { - blksize = MIN(func->max_blk_size, func->card->host->max_blk_size); - blksize = MIN(blksize, 512u); - } - - ret = sdio_io_writeb(func0, SDIO_REG_FBR_BASE(func->num) + SDIO_REG_FBR_BLKSIZE, - blksize & 0xff); - if (ret) - return ret; - ret = sdio_io_writeb(func0, SDIO_REG_FBR_BASE(func->num) + SDIO_REG_FBR_BLKSIZE + 1, - (blksize >> 8) & 0xff); - if (ret) - return ret; - func->cur_blk_size = blksize; - - return 0; -} - - -rt_inline rt_int32_t sdio_match_card(struct rt_mmcsd_card *card, - const struct rt_sdio_device_id *id) -{ - if ((id->manufacturer != SDIO_ANY_MAN_ID) && - (id->manufacturer != card->cis.manufacturer)) - return 0; - if ((id->product != SDIO_ANY_PROD_ID) && - (id->product != card->cis.product)) - return 0; - - return 1; -} - -static struct rt_mmcsd_card *sdio_match_driver(struct rt_sdio_device_id *id) -{ - rt_list_t *l; - struct sdio_card *sc; - struct rt_mmcsd_card *card; - - for (l = (&sdio_cards)->next; l != &sdio_cards; l = l->next) - { - sc = (struct sdio_card *)rt_list_entry(l, struct sdio_card, list); - card = sc->card; - - if (sdio_match_card(card, id)) - { - return card; - } - } - - return RT_NULL; -} - -rt_int32_t sdio_register_driver(struct rt_sdio_driver *driver) -{ - struct sdio_driver *sd; - struct rt_mmcsd_card *card; - - sd = rt_malloc(sizeof(struct sdio_driver)); - if (sd == RT_NULL) - { - rt_kprintf("malloc sdio driver failed\n"); - return -RT_ENOMEM; - } - - rt_list_insert_after(&sdio_drivers, &sd->list); - - if (!rt_list_isempty(&sdio_cards)) - { - card = sdio_match_driver(driver->id); - if (card != RT_NULL) - { - driver->probe(card); - } - } - - return 0; -} - -rt_int32_t sdio_unregister_driver(struct rt_sdio_driver *driver) -{ - rt_list_t *l; - struct sdio_driver *sd = RT_NULL; - struct rt_mmcsd_card *card; - - - rt_list_insert_after(&sdio_drivers, &sd->list); - - for (l = (&sdio_drivers)->next; l != &sdio_drivers; l = l->next) - { - sd = (struct sdio_driver *)rt_list_entry(l, struct sdio_driver, list); - if (sd->drv != driver) - { - sd = RT_NULL; - } - } - - if (sd == RT_NULL) - { - rt_kprintf("SDIO driver %s not register\n", driver->name); - return -RT_ERROR; - } - - if (!rt_list_isempty(&sdio_cards)) - { - card = sdio_match_driver(driver->id); - if (card != RT_NULL) - { - driver->remove(card); - rt_list_remove(&sd->list); - rt_free(sd); - } - } - - return 0; -} - - -void rt_sdio_init(void) -{ - rt_list_init(&sdio_cards); - rt_list_init(&sdio_drivers); -} - + rt_kprintf("init SDIO card failed\n"); + + return err; + + + +} + + +static void sdio_irq_thread(void *param) +{ + rt_int32_t i, ret; + rt_uint8_t pending; + struct rt_mmcsd_card *card; + struct rt_mmcsd_host *host = (struct rt_mmcsd_host *)param; + RT_ASSERT(host != RT_NULL); + card = host->card; + RT_ASSERT(card != RT_NULL); + + while (1) + { + if (rt_sem_take(host->sdio_irq_sem, RT_WAITING_FOREVER) == RT_EOK) + { + mmcsd_host_lock(host); + pending = sdio_io_readb(host->card->sdio_function[0], + SDIO_REG_CCCR_INT_PEND, &ret); + if (ret) + { + mmcsd_dbg("error %d reading SDIO_REG_CCCR_INT_PEND\n", ret); + goto out; + } + + for (i = 1; i <= 7; i++) + { + if (pending & (1 << i)) + { + struct rt_sdio_function *func = card->sdio_function[i]; + if (!func) + { + mmcsd_dbg("pending IRQ for " + "non-existant function %d\n", func->num); + goto out; + } + else if (func->irq_handler) + { + func->irq_handler(func); + } + else + { + mmcsd_dbg("pending IRQ with no register handler\n"); + goto out; + } + } + } + + out: + mmcsd_host_unlock(host); + if (host->flags & MMCSD_SUP_SDIO_IRQ) + host->ops->enable_sdio_irq(host, 1); + continue; + } + } +} + +static rt_int32_t sdio_irq_thread_create(struct rt_mmcsd_card *card) +{ + struct rt_mmcsd_host *host = card->host; + + /* init semaphore and create sdio irq processing thread */ + if (!host->sdio_irq_num) + { + host->sdio_irq_num++; + host->sdio_irq_sem = rt_sem_create("sdio_irq", 0, RT_IPC_FLAG_FIFO); + RT_ASSERT(host->sdio_irq_sem != RT_NULL); + + host->sdio_irq_thread = rt_thread_create("sdio_irq", sdio_irq_thread, host, + RT_SDIO_STACK_SIZE, RT_SDIO_THREAD_PREORITY, 20); + if (host->sdio_irq_thread != RT_NULL) + { + rt_thread_startup(host->sdio_irq_thread); + } + } + + return 0; +} + +static rt_int32_t sdio_irq_thread_delete(struct rt_mmcsd_card *card) +{ + struct rt_mmcsd_host *host = card->host; + + RT_ASSERT(host->sdio_irq_num > 0); + + host->sdio_irq_num--; + if (!host->sdio_irq_num) + { + if (host->flags & MMCSD_SUP_SDIO_IRQ) + host->ops->enable_sdio_irq(host, 0); + rt_sem_delete(host->sdio_irq_sem); + host->sdio_irq_sem = RT_NULL; + rt_thread_delete(host->sdio_irq_thread); + host->sdio_irq_thread = RT_NULL; + } + + return 0; +} + + +rt_int32_t sdio_attach_irq(struct rt_sdio_function *func, rt_sdio_irq_handler_t *handler) +{ + rt_int32_t ret; + rt_uint8_t reg; + struct rt_sdio_function *func0; + + RT_ASSERT(func != RT_NULL); + RT_ASSERT(func->card != RT_NULL); + + func0 = func->card->sdio_function[0]; + + mmcsd_dbg("SDIO: enabling IRQ for function %d\n", func->num); + + if (func->irq_handler) + { + mmcsd_dbg("SDIO: IRQ for already in use.\n"); + return -RT_EBUSY; + } + + reg = sdio_io_readb(func0, SDIO_REG_CCCR_INT_EN, &ret); + if (ret) + return ret; + + reg |= 1 << func->num; + + reg |= 1; /* Master interrupt enable */ + + ret = sdio_io_writeb(func0, SDIO_REG_CCCR_INT_EN, reg); + if (ret) + return ret; + + func->irq_handler = handler; + + ret = sdio_irq_thread_create(func->card); + if (ret) + func->irq_handler = RT_NULL; + + return ret; +} + +rt_int32_t sdio_detach_irq(struct rt_sdio_function *func) +{ + rt_int32_t ret; + rt_uint8_t reg; + struct rt_sdio_function *func0; + + RT_ASSERT(func != RT_NULL); + RT_ASSERT(func->card != RT_NULL); + + func0 = func->card->sdio_function[0]; + + mmcsd_dbg("SDIO: disabling IRQ for function %d\n", func->num); + + if (func->irq_handler) + { + func->irq_handler = RT_NULL; + sdio_irq_thread_delete(func->card); + } + + reg = sdio_io_readb(func0, SDIO_REG_CCCR_INT_EN, &ret); + if (ret) + return ret; + + reg &= ~(1 << func->num); + + /* Disable master interrupt with the last function interrupt */ + if (!(reg & 0xFE)) + reg = 0; + + ret = sdio_io_writeb(func0, SDIO_REG_CCCR_INT_EN, reg); + if (ret) + return ret; + + return 0; +} + +void sdio_irq_wakeup(struct rt_mmcsd_host *host) +{ + host->ops->enable_sdio_irq(host, 0); + rt_sem_release(host->sdio_irq_sem); +} + + +rt_int32_t sdio_enable_func(struct rt_sdio_function *func) +{ + rt_int32_t ret; + rt_uint8_t reg; + rt_uint32_t timeout; + struct rt_sdio_function *func0; + + RT_ASSERT(func != RT_NULL); + RT_ASSERT(func->card != RT_NULL); + + func0 = func->card->sdio_function[0]; + + mmcsd_dbg("SDIO: enabling function %d\n", func->num); + + reg = sdio_io_readb(func0, SDIO_REG_CCCR_IO_EN, &ret); + if (ret) + goto err; + + reg |= 1 << func->num; + + ret = sdio_io_writeb(func0, SDIO_REG_CCCR_IO_EN, reg); + if (ret) + goto err; + + timeout = rt_tick_get() + func->enable_timeout_val * 1000 / RT_TICK_PER_SECOND; + + while (1) + { + reg = sdio_io_readb(func0, SDIO_REG_CCCR_IO_RDY, &ret); + if (ret) + goto err; + if (reg & (1 << func->num)) + break; + ret = -RT_ETIMEOUT; + if (rt_tick_get() > timeout) + goto err; + } + + mmcsd_dbg("SDIO: enabled function successfull\n"); + + return 0; + +err: + mmcsd_dbg("SDIO: failed to enable function %d\n", func->num); + return ret; +} + + +rt_int32_t sdio_disable_func(struct rt_sdio_function *func) +{ + rt_int32_t ret; + rt_uint8_t reg; + struct rt_sdio_function *func0; + + RT_ASSERT(func != RT_NULL); + RT_ASSERT(func->card != RT_NULL); + + func0 = func->card->sdio_function[0]; + + mmcsd_dbg("SDIO: disabling function %d\n", func->num); + + reg = sdio_io_readb(func0, SDIO_REG_CCCR_IO_EN, &ret); + if (ret) + goto err; + + reg &= ~(1 << func->num); + + ret = sdio_io_writeb(func0, SDIO_REG_CCCR_IO_EN, reg); + if (ret) + goto err; + + mmcsd_dbg("SDIO: disabled function successfull\n"); + + return 0; + +err: + mmcsd_dbg("SDIO: failed to disable function %d\n", func->num); + return -RT_EIO; +} + +rt_int32_t sdio_set_block_size(struct rt_sdio_function *func, rt_uint32_t blksize) +{ + rt_int32_t ret; + struct rt_sdio_function *func0 = func->card->sdio_function[0]; + + if (blksize > func->card->host->max_blk_size) + return -RT_ERROR; + + if (blksize == 0) + { + blksize = MIN(func->max_blk_size, func->card->host->max_blk_size); + blksize = MIN(blksize, 512u); + } + + ret = sdio_io_writeb(func0, SDIO_REG_FBR_BASE(func->num) + SDIO_REG_FBR_BLKSIZE, + blksize & 0xff); + if (ret) + return ret; + ret = sdio_io_writeb(func0, SDIO_REG_FBR_BASE(func->num) + SDIO_REG_FBR_BLKSIZE + 1, + (blksize >> 8) & 0xff); + if (ret) + return ret; + func->cur_blk_size = blksize; + + return 0; +} + + +rt_inline rt_int32_t sdio_match_card(struct rt_mmcsd_card *card, + const struct rt_sdio_device_id *id) +{ + if ((id->manufacturer != SDIO_ANY_MAN_ID) && + (id->manufacturer != card->cis.manufacturer)) + return 0; + if ((id->product != SDIO_ANY_PROD_ID) && + (id->product != card->cis.product)) + return 0; + + return 1; +} + +static struct rt_mmcsd_card *sdio_match_driver(struct rt_sdio_device_id *id) +{ + rt_list_t *l; + struct sdio_card *sc; + struct rt_mmcsd_card *card; + + for (l = (&sdio_cards)->next; l != &sdio_cards; l = l->next) + { + sc = (struct sdio_card *)rt_list_entry(l, struct sdio_card, list); + card = sc->card; + + if (sdio_match_card(card, id)) + { + return card; + } + } + + return RT_NULL; +} + +rt_int32_t sdio_register_driver(struct rt_sdio_driver *driver) +{ + struct sdio_driver *sd; + struct rt_mmcsd_card *card; + + sd = rt_malloc(sizeof(struct sdio_driver)); + if (sd == RT_NULL) + { + rt_kprintf("malloc sdio driver failed\n"); + return -RT_ENOMEM; + } + + rt_list_insert_after(&sdio_drivers, &sd->list); + + if (!rt_list_isempty(&sdio_cards)) + { + card = sdio_match_driver(driver->id); + if (card != RT_NULL) + { + driver->probe(card); + } + } + + return 0; +} + +rt_int32_t sdio_unregister_driver(struct rt_sdio_driver *driver) +{ + rt_list_t *l; + struct sdio_driver *sd = RT_NULL; + struct rt_mmcsd_card *card; + + + rt_list_insert_after(&sdio_drivers, &sd->list); + + for (l = (&sdio_drivers)->next; l != &sdio_drivers; l = l->next) + { + sd = (struct sdio_driver *)rt_list_entry(l, struct sdio_driver, list); + if (sd->drv != driver) + { + sd = RT_NULL; + } + } + + if (sd == RT_NULL) + { + rt_kprintf("SDIO driver %s not register\n", driver->name); + return -RT_ERROR; + } + + if (!rt_list_isempty(&sdio_cards)) + { + card = sdio_match_driver(driver->id); + if (card != RT_NULL) + { + driver->remove(card); + rt_list_remove(&sd->list); + rt_free(sd); + } + } + + return 0; +} + + +void rt_sdio_init(void) +{ + rt_list_init(&sdio_cards); + rt_list_init(&sdio_drivers); +} + diff --git a/components/drivers/serial/SConscript b/components/drivers/serial/SConscript index 5e66156c82..a6eb115919 100644 --- a/components/drivers/serial/SConscript +++ b/components/drivers/serial/SConscript @@ -1,8 +1,8 @@ -from building import * - -cwd = GetCurrentDir() -src = Glob('*.c') -CPPPATH = [cwd + '/../include'] -group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SERIAL'], CPPPATH = CPPPATH) - -Return('group') +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd + '/../include'] +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SERIAL'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/spi/SConscript b/components/drivers/spi/SConscript index 666545250a..f114ef7a41 100644 --- a/components/drivers/spi/SConscript +++ b/components/drivers/spi/SConscript @@ -1,8 +1,8 @@ -from building import * - -cwd = GetCurrentDir() -src = Glob('*.c') -CPPPATH = [cwd + '/../include'] -group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SPI'], CPPPATH = CPPPATH) - -Return('group') +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd + '/../include'] +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SPI'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/src/SConscript b/components/drivers/src/SConscript index 00608451aa..a9bb775427 100644 --- a/components/drivers/src/SConscript +++ b/components/drivers/src/SConscript @@ -1,8 +1,8 @@ -from building import * - -cwd = GetCurrentDir() -src = Glob('*.c') -CPPPATH = [cwd + '/../include'] -group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_DEVICE_IPC'], CPPPATH = CPPPATH) - -Return('group') +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd + '/../include'] +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_DEVICE_IPC'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/usb/SConscript b/components/drivers/usb/SConscript index 1cb7618499..744d8d7821 100644 --- a/components/drivers/usb/SConscript +++ b/components/drivers/usb/SConscript @@ -1,14 +1,14 @@ -# for module compiling -import os -from building import * - -cwd = GetCurrentDir() -objs = [] -list = os.listdir(cwd) - -for d in list: - path = os.path.join(cwd, d) - if os.path.isfile(os.path.join(path, 'SConscript')): - objs = objs + SConscript(os.path.join(d, 'SConscript')) - -Return('objs') +# for module compiling +import os +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/components/drivers/usb/usbdevice/SConscript b/components/drivers/usb/usbdevice/SConscript index afaac2e89f..d46ec3db59 100644 --- a/components/drivers/usb/usbdevice/SConscript +++ b/components/drivers/usb/usbdevice/SConscript @@ -1,23 +1,23 @@ -Import('RTT_ROOT') -from building import * - -cwd = GetCurrentDir() -src = Split(""" -core/core.c -core/usbdevice.c -""") - -if GetDepend('RT_USB_DEVICE_CDC'): - src += Glob('class/cdc_vcom.c') - -if GetDepend('RT_USB_DEVICE_MSTORAGE'): - src += Glob('class/mstorage.c') - -if GetDepend('RT_USB_DEVICE_RNDIS'): - src += Glob('class/rndis.c') - -CPPPATH = [cwd] - -group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_USB_DEVICE'], CPPPATH = CPPPATH) - -Return('group') +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +src = Split(""" +core/core.c +core/usbdevice.c +""") + +if GetDepend('RT_USB_DEVICE_CDC'): + src += Glob('class/cdc_vcom.c') + +if GetDepend('RT_USB_DEVICE_MSTORAGE'): + src += Glob('class/mstorage.c') + +if GetDepend('RT_USB_DEVICE_RNDIS'): + src += Glob('class/rndis.c') + +CPPPATH = [cwd] + +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_USB_DEVICE'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/usb/usbdevice/class/cdc.h b/components/drivers/usb/usbdevice/class/cdc.h index 859148ae43..ff938fd452 100644 --- a/components/drivers/usb/usbdevice/class/cdc.h +++ b/components/drivers/usb/usbdevice/class/cdc.h @@ -1,174 +1,174 @@ -/* - * File : cdc.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2012, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2012-10-03 Yi Qiu first version - * 2012-12-12 heyuanjie87 add CDC endpoints collection - */ - -#ifndef __CDC_H__ -#define __CDC_H__ - -#define USB_CDC_PRODUCT_ID 0x5740 /* Product ID */ -#define USB_CDC_BUFSIZE 0x40 - -#define USB_CDC_CLASS_COMM 0x02 -#define USB_CDC_CLASS_DATA 0x0A - -#define USB_CDC_SUBCLASS_DLCM 0x01 -#define USB_CDC_SUBCLASS_ACM 0x02 -#define USB_CDC_SUBCLASS_TCM 0x03 -#define USB_CDC_SUBCLASS_MCCM 0x04 -#define USB_CDC_SUBCLASS_CCM 0x05 -#define USB_CDC_SUBCLASS_ETH 0x06 -#define USB_CDC_SUBCLASS_ATM 0x07 - -#define USB_CDC_PROTOCOL_V25TER 0x01 - -#define USB_CDC_PROTOCOL_I430 0x30 -#define USB_CDC_PROTOCOL_HDLC 0x31 -#define USB_CDC_PROTOCOL_TRANS 0x32 -#define USB_CDC_PROTOCOL_Q921M 0x50 -#define USB_CDC_PROTOCOL_Q921 0x51 -#define USB_CDC_PROTOCOL_Q921TM 0x52 -#define USB_CDC_PROTOCOL_V42BIS 0x90 -#define USB_CDC_PROTOCOL_Q931 0x91 -#define USB_CDC_PROTOCOL_V120 0x92 -#define USB_CDC_PROTOCOL_CAPI20 0x93 -#define USB_CDC_PROTOCOL_HOST 0xFD -#define USB_CDC_PROTOCOL_PUFD 0xFE -#define USB_CDC_PROTOCOL_VENDOR 0xFF - -#define USB_CDC_CS_INTERFACE 0x24 -#define USB_CDC_CS_ENDPOINT 0x25 - -#define USB_CDC_SCS_HEADER 0x00 -#define USB_CDC_SCS_CALL_MGMT 0x01 -#define USB_CDC_SCS_ACM 0x02 -#define USB_CDC_SCS_UNION 0x06 - -#define CDC_SEND_ENCAPSULATED_COMMAND 0x00 -#define CDC_GET_ENCAPSULATED_RESPONSE 0x01 -#define CDC_SET_COMM_FEATURE 0x02 -#define CDC_GET_COMM_FEATURE 0x03 -#define CDC_CLEAR_COMM_FEATURE 0x04 -#define CDC_SET_AUX_LINE_STATE 0x10 -#define CDC_SET_HOOK_STATE 0x11 -#define CDC_PULSE_SETUP 0x12 -#define CDC_SEND_PULSE 0x13 -#define CDC_SET_PULSE_TIME 0x14 -#define CDC_RING_AUX_JACK 0x15 -#define CDC_SET_LINE_CODING 0x20 -#define CDC_GET_LINE_CODING 0x21 -#define CDC_SET_CONTROL_LINE_STATE 0x22 -#define CDC_SEND_BREAK 0x23 -#define CDC_SET_RINGER_PARMS 0x30 -#define CDC_GET_RINGER_PARMS 0x31 -#define CDC_SET_OPERATION_PARMS 0x32 -#define CDC_GET_OPERATION_PARMS 0x33 -#define CDC_SET_LINE_PARMS 0x34 -#define CDC_GET_LINE_PARMS 0x35 -#define CDC_DIAL_DIGITS 0x36 -#define CDC_SET_UNIT_PARAMETER 0x37 -#define CDC_GET_UNIT_PARAMETER 0x38 -#define CDC_CLEAR_UNIT_PARAMETER 0x39 -#define CDC_GET_PROFILE 0x3A -#define CDC_SET_ETH_MULTICAST_FILTERS 0x40 -#define CDC_SET_ETH_POWER_MGMT_FILT 0x41 -#define CDC_GET_ETH_POWER_MGMT_FILT 0x42 -#define CDC_SET_ETH_PACKET_FILTER 0x43 -#define CDC_GET_ETH_STATISTIC 0x44 -#define CDC_SET_ATM_DATA_FORMAT 0x50 -#define CDC_GET_ATM_DEVICE_STATISTICS 0x51 -#define CDC_SET_ATM_DEFAULT_VC 0x52 -#define CDC_GET_ATM_VC_STATISTICS 0x53 - -#pragma pack(1) - -struct ucdc_header_descriptor -{ - rt_uint8_t length; - rt_uint8_t type; - rt_uint8_t subtype; - rt_uint16_t bcd; -}; -typedef struct ucdc_header_descriptor* ucdc_hdr_desc_t; - -struct ucdc_acm_descriptor -{ - rt_uint8_t length; - rt_uint8_t type; - rt_uint8_t subtype; - rt_uint8_t capabilties; -}; -typedef struct ucdc_acm_descriptor* ucdc_acm_desc_t; - -struct ucdc_call_mgmt_descriptor -{ - rt_uint8_t length; - rt_uint8_t type; - rt_uint8_t subtype; - rt_uint8_t capabilties; - rt_uint8_t data_interface; -}; -typedef struct ucdc_call_mgmt_descriptor* ucdc_call_mgmt_desc_t; - -struct ucdc_union_descriptor -{ - rt_uint8_t length; - rt_uint8_t type; - rt_uint8_t subtype; - rt_uint8_t master_interface; - rt_uint8_t slave_interface0; -}; -typedef struct ucdc_union_descriptor* ucdc_union_desc_t; - -struct ucdc_comm_descriptor -{ -#ifdef RT_USB_DEVICE_COMPOSITE - struct uiad_descriptor iad_desc; -#endif - struct uinterface_descriptor intf_desc; - struct ucdc_header_descriptor hdr_desc; - struct ucdc_call_mgmt_descriptor call_mgmt_desc; - struct ucdc_acm_descriptor acm_desc; - struct ucdc_union_descriptor union_desc; - struct uendpoint_descriptor ep_desc; -}; -typedef struct ucdc_comm_descriptor* ucdc_comm_desc_t; - -struct ucdc_data_descriptor -{ - struct uinterface_descriptor intf_desc; - struct uendpoint_descriptor ep_out_desc; - struct uendpoint_descriptor ep_in_desc; -}; -typedef struct ucdc_data_descriptor* ucdc_data_desc_t; - -struct ucdc_line_coding -{ - rt_uint32_t dwDTERate; - rt_uint8_t bCharFormat; - rt_uint8_t bParityType; - rt_uint8_t bDataBits; -}; -typedef struct ucdc_line_coding* ucdc_line_coding_t; - -struct cdc_eps -{ - uep_t ep_out; - uep_t ep_in; - uep_t ep_cmd; -}; -typedef struct cdc_eps* cdc_eps_t; - -#pragma pack() - -#endif +/* + * File : cdc.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2012, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2012-10-03 Yi Qiu first version + * 2012-12-12 heyuanjie87 add CDC endpoints collection + */ + +#ifndef __CDC_H__ +#define __CDC_H__ + +#define USB_CDC_PRODUCT_ID 0x5740 /* Product ID */ +#define USB_CDC_BUFSIZE 0x40 + +#define USB_CDC_CLASS_COMM 0x02 +#define USB_CDC_CLASS_DATA 0x0A + +#define USB_CDC_SUBCLASS_DLCM 0x01 +#define USB_CDC_SUBCLASS_ACM 0x02 +#define USB_CDC_SUBCLASS_TCM 0x03 +#define USB_CDC_SUBCLASS_MCCM 0x04 +#define USB_CDC_SUBCLASS_CCM 0x05 +#define USB_CDC_SUBCLASS_ETH 0x06 +#define USB_CDC_SUBCLASS_ATM 0x07 + +#define USB_CDC_PROTOCOL_V25TER 0x01 + +#define USB_CDC_PROTOCOL_I430 0x30 +#define USB_CDC_PROTOCOL_HDLC 0x31 +#define USB_CDC_PROTOCOL_TRANS 0x32 +#define USB_CDC_PROTOCOL_Q921M 0x50 +#define USB_CDC_PROTOCOL_Q921 0x51 +#define USB_CDC_PROTOCOL_Q921TM 0x52 +#define USB_CDC_PROTOCOL_V42BIS 0x90 +#define USB_CDC_PROTOCOL_Q931 0x91 +#define USB_CDC_PROTOCOL_V120 0x92 +#define USB_CDC_PROTOCOL_CAPI20 0x93 +#define USB_CDC_PROTOCOL_HOST 0xFD +#define USB_CDC_PROTOCOL_PUFD 0xFE +#define USB_CDC_PROTOCOL_VENDOR 0xFF + +#define USB_CDC_CS_INTERFACE 0x24 +#define USB_CDC_CS_ENDPOINT 0x25 + +#define USB_CDC_SCS_HEADER 0x00 +#define USB_CDC_SCS_CALL_MGMT 0x01 +#define USB_CDC_SCS_ACM 0x02 +#define USB_CDC_SCS_UNION 0x06 + +#define CDC_SEND_ENCAPSULATED_COMMAND 0x00 +#define CDC_GET_ENCAPSULATED_RESPONSE 0x01 +#define CDC_SET_COMM_FEATURE 0x02 +#define CDC_GET_COMM_FEATURE 0x03 +#define CDC_CLEAR_COMM_FEATURE 0x04 +#define CDC_SET_AUX_LINE_STATE 0x10 +#define CDC_SET_HOOK_STATE 0x11 +#define CDC_PULSE_SETUP 0x12 +#define CDC_SEND_PULSE 0x13 +#define CDC_SET_PULSE_TIME 0x14 +#define CDC_RING_AUX_JACK 0x15 +#define CDC_SET_LINE_CODING 0x20 +#define CDC_GET_LINE_CODING 0x21 +#define CDC_SET_CONTROL_LINE_STATE 0x22 +#define CDC_SEND_BREAK 0x23 +#define CDC_SET_RINGER_PARMS 0x30 +#define CDC_GET_RINGER_PARMS 0x31 +#define CDC_SET_OPERATION_PARMS 0x32 +#define CDC_GET_OPERATION_PARMS 0x33 +#define CDC_SET_LINE_PARMS 0x34 +#define CDC_GET_LINE_PARMS 0x35 +#define CDC_DIAL_DIGITS 0x36 +#define CDC_SET_UNIT_PARAMETER 0x37 +#define CDC_GET_UNIT_PARAMETER 0x38 +#define CDC_CLEAR_UNIT_PARAMETER 0x39 +#define CDC_GET_PROFILE 0x3A +#define CDC_SET_ETH_MULTICAST_FILTERS 0x40 +#define CDC_SET_ETH_POWER_MGMT_FILT 0x41 +#define CDC_GET_ETH_POWER_MGMT_FILT 0x42 +#define CDC_SET_ETH_PACKET_FILTER 0x43 +#define CDC_GET_ETH_STATISTIC 0x44 +#define CDC_SET_ATM_DATA_FORMAT 0x50 +#define CDC_GET_ATM_DEVICE_STATISTICS 0x51 +#define CDC_SET_ATM_DEFAULT_VC 0x52 +#define CDC_GET_ATM_VC_STATISTICS 0x53 + +#pragma pack(1) + +struct ucdc_header_descriptor +{ + rt_uint8_t length; + rt_uint8_t type; + rt_uint8_t subtype; + rt_uint16_t bcd; +}; +typedef struct ucdc_header_descriptor* ucdc_hdr_desc_t; + +struct ucdc_acm_descriptor +{ + rt_uint8_t length; + rt_uint8_t type; + rt_uint8_t subtype; + rt_uint8_t capabilties; +}; +typedef struct ucdc_acm_descriptor* ucdc_acm_desc_t; + +struct ucdc_call_mgmt_descriptor +{ + rt_uint8_t length; + rt_uint8_t type; + rt_uint8_t subtype; + rt_uint8_t capabilties; + rt_uint8_t data_interface; +}; +typedef struct ucdc_call_mgmt_descriptor* ucdc_call_mgmt_desc_t; + +struct ucdc_union_descriptor +{ + rt_uint8_t length; + rt_uint8_t type; + rt_uint8_t subtype; + rt_uint8_t master_interface; + rt_uint8_t slave_interface0; +}; +typedef struct ucdc_union_descriptor* ucdc_union_desc_t; + +struct ucdc_comm_descriptor +{ +#ifdef RT_USB_DEVICE_COMPOSITE + struct uiad_descriptor iad_desc; +#endif + struct uinterface_descriptor intf_desc; + struct ucdc_header_descriptor hdr_desc; + struct ucdc_call_mgmt_descriptor call_mgmt_desc; + struct ucdc_acm_descriptor acm_desc; + struct ucdc_union_descriptor union_desc; + struct uendpoint_descriptor ep_desc; +}; +typedef struct ucdc_comm_descriptor* ucdc_comm_desc_t; + +struct ucdc_data_descriptor +{ + struct uinterface_descriptor intf_desc; + struct uendpoint_descriptor ep_out_desc; + struct uendpoint_descriptor ep_in_desc; +}; +typedef struct ucdc_data_descriptor* ucdc_data_desc_t; + +struct ucdc_line_coding +{ + rt_uint32_t dwDTERate; + rt_uint8_t bCharFormat; + rt_uint8_t bParityType; + rt_uint8_t bDataBits; +}; +typedef struct ucdc_line_coding* ucdc_line_coding_t; + +struct cdc_eps +{ + uep_t ep_out; + uep_t ep_in; + uep_t ep_cmd; +}; +typedef struct cdc_eps* cdc_eps_t; + +#pragma pack() + +#endif diff --git a/components/drivers/usb/usbdevice/class/cdc_vcom.c b/components/drivers/usb/usbdevice/class/cdc_vcom.c index ac558c9e32..addbb66c8e 100644 --- a/components/drivers/usb/usbdevice/class/cdc_vcom.c +++ b/components/drivers/usb/usbdevice/class/cdc_vcom.c @@ -1,591 +1,591 @@ -/* - * File : cdc_vcom.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2012, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2012-10-02 Yi Qiu first version - * 2012-12-12 heyuanjie87 change endpoints and class handler - */ - -#include -#include -#include -#include "cdc.h" - -#ifdef RT_USB_DEVICE_CDC - -#define CDC_RX_BUFSIZE 64 -#define CDC_TX_BUFSIZE 2048 -static rt_uint8_t rx_pool[CDC_RX_BUFSIZE]; -static rt_uint8_t tx_pool[CDC_TX_BUFSIZE]; -static struct rt_ringbuffer rx_ringbuffer; -static struct rt_ringbuffer tx_ringbuffer; -static struct rt_serial_device vcom_serial; -static struct serial_ringbuffer vcom_int_rx; -static rt_bool_t vcom_connected = RT_FALSE; - -static struct udevice_descriptor dev_desc = -{ - USB_DESC_LENGTH_DEVICE, //bLength; - USB_DESC_TYPE_DEVICE, //type; - USB_BCD_VERSION, //bcdUSB; - USB_CLASS_CDC, //bDeviceClass; - 0x00, //bDeviceSubClass; - 0x00, //bDeviceProtocol; - 0x40, //bMaxPacketSize0; - USB_VENDOR_ID, //idVendor; - USB_CDC_PRODUCT_ID, //idProduct; - USB_BCD_DEVICE, //bcdDevice; - USB_STRING_MANU_INDEX, //iManufacturer; - USB_STRING_PRODUCT_INDEX, //iProduct; - USB_STRING_SERIAL_INDEX, //iSerialNumber; - USB_DYNAMIC, //bNumConfigurations; -}; - -/* communcation interface descriptor */ -const static struct ucdc_comm_descriptor _comm_desc = -{ -#ifdef RT_USB_DEVICE_COMPOSITE - /* Interface Association Descriptor */ - USB_DESC_LENGTH_IAD, - USB_DESC_TYPE_IAD, - USB_DYNAMIC, - 0x02, - USB_CDC_CLASS_COMM, - USB_CDC_SUBCLASS_ACM, - USB_CDC_PROTOCOL_V25TER, - 0x00, -#endif - /* Interface Descriptor */ - USB_DESC_LENGTH_INTERFACE, - USB_DESC_TYPE_INTERFACE, - USB_DYNAMIC, - 0x00, - 0x01, - USB_CDC_CLASS_COMM, - USB_CDC_SUBCLASS_ACM, - USB_CDC_PROTOCOL_V25TER, - 0x00, - /* Header Functional Descriptor */ - 0x05, - USB_CDC_CS_INTERFACE, - USB_CDC_SCS_HEADER, - 0x0110, - /* Call Management Functional Descriptor */ - 0x05, - USB_CDC_CS_INTERFACE, - USB_CDC_SCS_CALL_MGMT, - 0x00, - USB_DYNAMIC, - /* Abstract Control Management Functional Descriptor */ - 0x04, - USB_CDC_CS_INTERFACE, - USB_CDC_SCS_ACM, - 0x02, - /* Union Functional Descriptor */ - 0x05, - USB_CDC_CS_INTERFACE, - USB_CDC_SCS_UNION, - USB_DYNAMIC, - USB_DYNAMIC, - /* Endpoint Descriptor */ - USB_DESC_LENGTH_ENDPOINT, - USB_DESC_TYPE_ENDPOINT, - USB_DYNAMIC | USB_DIR_IN, - USB_EP_ATTR_INT, - 0x08, - 0xFF, -}; - -/* data interface descriptor */ -const static struct ucdc_data_descriptor _data_desc = -{ - /* interface descriptor */ - USB_DESC_LENGTH_INTERFACE, - USB_DESC_TYPE_INTERFACE, - USB_DYNAMIC, - 0x00, - 0x02, - USB_CDC_CLASS_DATA, - 0x00, - 0x00, - 0x00, - /* endpoint, bulk out */ - USB_DESC_LENGTH_ENDPOINT, - USB_DESC_TYPE_ENDPOINT, - USB_DYNAMIC | USB_DIR_OUT, - USB_EP_ATTR_BULK, - USB_CDC_BUFSIZE, - 0x00, - /* endpoint, bulk in */ - USB_DESC_LENGTH_ENDPOINT, - USB_DESC_TYPE_ENDPOINT, - USB_DYNAMIC | USB_DIR_IN, - USB_EP_ATTR_BULK, - USB_CDC_BUFSIZE, - 0x00, -}; - -/** - * This function will handle cdc bulk in endpoint request. - * - * @param device the usb device object. - * @param size request size. - * - * @return RT_EOK. - */ -static rt_err_t _ep_in_handler(udevice_t device, uclass_t cls, rt_size_t size) -{ - rt_uint32_t level; - rt_size_t length; - cdc_eps_t eps; - rt_size_t mps; - - eps = (cdc_eps_t)cls->eps; - mps = eps->ep_in->ep_desc->wMaxPacketSize; - size = RT_RINGBUFFER_SIZE(&tx_ringbuffer); - if(size == 0) return RT_EOK; - - length = size > mps ? mps : size; - - level = rt_hw_interrupt_disable(); - rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, length); - rt_hw_interrupt_enable(level); - - /* send data to host */ - dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, length); - - return RT_EOK; -} - -/** - * This function will handle cdc bulk out endpoint request. - * - * @param device the usb device object. - * @param size request size. - * - * @return RT_EOK. - */ -static rt_err_t _ep_out_handler(udevice_t device, uclass_t cls, rt_size_t size) -{ - rt_uint32_t level; - cdc_eps_t eps; - - RT_ASSERT(device != RT_NULL); - - eps = (cdc_eps_t)cls->eps; - /* receive data from USB VCOM */ - level = rt_hw_interrupt_disable(); - rt_ringbuffer_put(&rx_ringbuffer, eps->ep_out->buffer, size); - rt_hw_interrupt_enable(level); - - /* notify receive data */ - rt_hw_serial_isr(&vcom_serial); - - dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, - eps->ep_out->ep_desc->wMaxPacketSize); - - return RT_EOK; -} - -/** - * This function will handle cdc interrupt in endpoint request. - * - * @param device the usb device object. - * @param size request size. - * - * @return RT_EOK. - */ -static rt_err_t _ep_cmd_handler(udevice_t device, uclass_t cls, rt_size_t size) -{ - RT_ASSERT(device != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_cmd_handler\n")); - - return RT_EOK; -} - -/** - * This function will handle cdc_get_line_coding request. - * - * @param device the usb device object. - * @param setup the setup request. - * - * @return RT_EOK on successful. - */ -static rt_err_t _cdc_get_line_coding(udevice_t device, ureq_t setup) -{ - struct ucdc_line_coding data; - rt_uint16_t size; - - RT_ASSERT(device != RT_NULL); - RT_ASSERT(setup != RT_NULL); - - data.dwDTERate = 115200; - data.bCharFormat = 0; - data.bDataBits = 8; - data.bParityType = 0; - size = setup->length > 7 ? 7 : setup->length; - - dcd_ep_write(device->dcd, 0, (void*)&data, size); - - return RT_EOK; -} - -/** - * This function will handle cdc_set_line_coding request. - * - * @param device the usb device object. - * @param setup the setup request. - * - * @return RT_EOK on successful. - */ -static rt_err_t _cdc_set_line_coding(udevice_t device, ureq_t setup) -{ - struct ucdc_line_coding data; - rt_err_t ret; - - RT_ASSERT(device != RT_NULL); - RT_ASSERT(setup != RT_NULL); - - rt_completion_init(&device->dcd->completion); - - dcd_ep_read(device->dcd, 0, (void*)&data, setup->length); - - ret = rt_completion_wait(&device->dcd->completion, 100); - if(ret != RT_EOK) - { - rt_kprintf("_cdc_set_line_coding timeout\n"); - } - - return RT_EOK; -} - -/** - * This function will handle cdc interface request. - * - * @param device the usb device object. - * @param setup the setup request. - * - * @return RT_EOK on successful. - */ -static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup) -{ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(setup != RT_NULL); - - switch(setup->request) - { - case CDC_SEND_ENCAPSULATED_COMMAND: - break; - case CDC_GET_ENCAPSULATED_RESPONSE: - break; - case CDC_SET_COMM_FEATURE: - break; - case CDC_GET_COMM_FEATURE: - break; - case CDC_CLEAR_COMM_FEATURE: - break; - case CDC_SET_LINE_CODING: - _cdc_set_line_coding(device, setup); - vcom_connected = RT_TRUE; - break; - case CDC_GET_LINE_CODING: - _cdc_get_line_coding(device, setup); - break; - case CDC_SET_CONTROL_LINE_STATE: - rt_device_control((rt_device_t)device->dcd, CONTROL_SEND_STATUS, RT_NULL); - break; - case CDC_SEND_BREAK: - break; - default: - rt_kprintf("unknown cdc request\n",setup->request_type); - return -RT_ERROR; - } - - return RT_EOK; -} - -/** - * This function will run cdc class, it will be called on handle set configuration request. - * - * @param device the usb device object. - * - * @return RT_EOK on successful. - */ -static rt_err_t _class_run(udevice_t device, uclass_t cls) -{ - cdc_eps_t eps; - RT_ASSERT(device != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc class run\n")); - eps = (cdc_eps_t)cls->eps; - - eps->ep_in->buffer=tx_pool; - eps->ep_out->buffer=rx_pool; - - dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, - eps->ep_out->ep_desc->wMaxPacketSize); - - return RT_EOK; -} - -/** - * This function will stop cdc class, it will be called on handle set configuration request. - * - * @param device the usb device object. - * - * @return RT_EOK on successful. - */ -static rt_err_t _class_stop(udevice_t device, uclass_t cls) -{ - RT_ASSERT(device != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc class stop\n")); - - return RT_EOK; -} - -/** - * This function will handle system sof event. - * - * @param device the usb device object. - * - * @return RT_EOK on successful. - */ -static rt_err_t _class_sof_handler(udevice_t device, uclass_t cls) -{ - rt_uint32_t level; - rt_size_t size; - static rt_uint32_t frame_count = 0; - cdc_eps_t eps; - - if(vcom_connected != RT_TRUE) return -RT_ERROR; - - eps = (cdc_eps_t)cls->eps; - if (frame_count ++ == 5) - { - rt_size_t mps = eps->ep_in->ep_desc->wMaxPacketSize; - - /* reset the frame counter */ - frame_count = 0; - - size = RT_RINGBUFFER_SIZE(&tx_ringbuffer); - if(size == 0) return -RT_EFULL; - - size = size > mps ? mps : size; - - level = rt_hw_interrupt_disable(); - rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, size); - rt_hw_interrupt_enable(level); - - /* send data to host */ - dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, size); - } - - return RT_EOK; -} - -static struct uclass_ops ops = -{ - _class_run, - _class_stop, - _class_sof_handler, -}; - -/** - * This function will configure cdc descriptor. - * - * @param comm the communication interface number. - * @param data the data interface number. - * - * @return RT_EOK on successful. - */ -static rt_err_t _cdc_descriptor_config(ucdc_comm_desc_t comm, rt_uint8_t cintf_nr, ucdc_data_desc_t data, rt_uint8_t dintf_nr) -{ - comm->call_mgmt_desc.data_interface = dintf_nr; - comm->union_desc.master_interface = cintf_nr; - comm->union_desc.slave_interface0 = dintf_nr; -#ifdef RT_USB_DEVICE_COMPOSITE - comm->iad_desc.bFirstInterface = cintf_nr; -#endif - - return RT_EOK; -} - -/** - * This function will create a cdc class instance. - * - * @param device the usb device object. - * - * @return RT_EOK on successful. - */ -uclass_t rt_usbd_class_cdc_create(udevice_t device) -{ - uclass_t cdc; - cdc_eps_t eps; - uintf_t intf_comm, intf_data; - ualtsetting_t comm_setting, data_setting; - ucdc_data_desc_t data_desc; - ucdc_comm_desc_t comm_desc; - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - - /* create a cdc class */ - cdc = rt_usbd_class_create(device, &dev_desc, &ops); - /* create a cdc class endpoints collection */ - eps = rt_malloc(sizeof(struct cdc_eps)); - cdc->eps = (void*)eps; - - /* create a cdc communication interface and a cdc data interface */ - intf_comm = rt_usbd_interface_create(device, _interface_handler); - intf_data = rt_usbd_interface_create(device, _interface_handler); - - /* create a communication alternate setting and a data alternate setting */ - comm_setting = rt_usbd_altsetting_create(sizeof(struct ucdc_comm_descriptor)); - data_setting = rt_usbd_altsetting_create(sizeof(struct ucdc_data_descriptor)); - - /* config desc in alternate setting */ - rt_usbd_altsetting_config_descriptor(comm_setting, &_comm_desc, - (rt_off_t)&((ucdc_comm_desc_t)0)->intf_desc); - rt_usbd_altsetting_config_descriptor(data_setting, &_data_desc, 0); - /* configure the cdc interface descriptor */ - _cdc_descriptor_config(comm_setting->desc, intf_comm->intf_num, data_setting->desc, intf_data->intf_num); - - /* create a bulk in and a bulk endpoint */ - data_desc = (ucdc_data_desc_t)data_setting->desc; - eps->ep_out = rt_usbd_endpoint_create(&data_desc->ep_out_desc, _ep_out_handler); - eps->ep_in = rt_usbd_endpoint_create(&data_desc->ep_in_desc, _ep_in_handler); - - /* add the bulk out and bulk in endpoints to the data alternate setting */ - rt_usbd_altsetting_add_endpoint(data_setting, eps->ep_in); - rt_usbd_altsetting_add_endpoint(data_setting, eps->ep_out); - - /* add the data alternate setting to the data interface - then set default setting of the interface */ - rt_usbd_interface_add_altsetting(intf_data, data_setting); - rt_usbd_set_altsetting(intf_data, 0); - - /* add the cdc data interface to cdc class */ - rt_usbd_class_add_interface(cdc, intf_data); - - /* create a command endpoint */ - comm_desc = (ucdc_comm_desc_t)comm_setting->desc; - eps->ep_cmd = rt_usbd_endpoint_create(&comm_desc->ep_desc, _ep_cmd_handler); - - /* add the command endpoint to the cdc communication interface */ - rt_usbd_altsetting_add_endpoint(comm_setting, eps->ep_cmd); - - /* add the communication alternate setting to the communication interface, - then set default setting of the interface */ - rt_usbd_interface_add_altsetting(intf_comm, comm_setting); - rt_usbd_set_altsetting(intf_comm, 0); - - /* add the communication interface to the cdc class */ - rt_usbd_class_add_interface(cdc, intf_comm); - - return cdc; -} - -/** -* UART device in RT-Thread -*/ -static rt_err_t _vcom_configure(struct rt_serial_device *serial, - struct serial_configure *cfg) -{ - return RT_EOK; -} - -static rt_err_t _vcom_control(struct rt_serial_device *serial, - int cmd, void *arg) -{ - switch (cmd) - { - case RT_DEVICE_CTRL_CLR_INT: - /* disable rx irq */ - break; - case RT_DEVICE_CTRL_SET_INT: - /* enable rx irq */ - break; - } - - return RT_EOK; -} - -static int _vcom_putc(struct rt_serial_device *serial, char c) -{ - rt_uint32_t level; - - if (vcom_connected != RT_TRUE) return 0; - - level = rt_hw_interrupt_disable(); - if (RT_RINGBUFFER_EMPTY(&tx_ringbuffer)) - { - rt_ringbuffer_putchar(&tx_ringbuffer, c); - } - rt_hw_interrupt_enable(level); - - return 1; -} - -static int _vcom_getc(struct rt_serial_device *serial) -{ - int result; - rt_uint8_t ch; - rt_uint32_t level; - - result = -1; - - level = rt_hw_interrupt_disable(); - if (RT_RINGBUFFER_SIZE(&rx_ringbuffer)) - { - rt_ringbuffer_getchar(&rx_ringbuffer, &ch); - result = ch; - } - rt_hw_interrupt_enable(level); - - return result; -} - -static const struct rt_uart_ops usb_vcom_ops = -{ - _vcom_configure, - _vcom_control, - _vcom_putc, - _vcom_getc, -}; - -void rt_usb_vcom_init(void) -{ - struct serial_configure config; - - /* initialize ring buffer */ - rt_ringbuffer_init(&rx_ringbuffer, rx_pool, CDC_RX_BUFSIZE); - rt_ringbuffer_init(&tx_ringbuffer, tx_pool, CDC_TX_BUFSIZE); - - config.baud_rate = BAUD_RATE_115200; - config.bit_order = BIT_ORDER_LSB; - config.data_bits = DATA_BITS_8; - config.parity = PARITY_NONE; - config.stop_bits = STOP_BITS_1; - config.invert = NRZ_NORMAL; - - vcom_serial.ops = &usb_vcom_ops; - vcom_serial.int_rx = &vcom_int_rx; - vcom_serial.config = config; - - /* register vcom device */ - rt_hw_serial_register(&vcom_serial, "vcom", - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM, - RT_NULL); -} - -#endif - +/* + * File : cdc_vcom.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2012, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2012-10-02 Yi Qiu first version + * 2012-12-12 heyuanjie87 change endpoints and class handler + */ + +#include +#include +#include +#include "cdc.h" + +#ifdef RT_USB_DEVICE_CDC + +#define CDC_RX_BUFSIZE 64 +#define CDC_TX_BUFSIZE 2048 +static rt_uint8_t rx_pool[CDC_RX_BUFSIZE]; +static rt_uint8_t tx_pool[CDC_TX_BUFSIZE]; +static struct rt_ringbuffer rx_ringbuffer; +static struct rt_ringbuffer tx_ringbuffer; +static struct rt_serial_device vcom_serial; +static struct serial_ringbuffer vcom_int_rx; +static rt_bool_t vcom_connected = RT_FALSE; + +static struct udevice_descriptor dev_desc = +{ + USB_DESC_LENGTH_DEVICE, //bLength; + USB_DESC_TYPE_DEVICE, //type; + USB_BCD_VERSION, //bcdUSB; + USB_CLASS_CDC, //bDeviceClass; + 0x00, //bDeviceSubClass; + 0x00, //bDeviceProtocol; + 0x40, //bMaxPacketSize0; + USB_VENDOR_ID, //idVendor; + USB_CDC_PRODUCT_ID, //idProduct; + USB_BCD_DEVICE, //bcdDevice; + USB_STRING_MANU_INDEX, //iManufacturer; + USB_STRING_PRODUCT_INDEX, //iProduct; + USB_STRING_SERIAL_INDEX, //iSerialNumber; + USB_DYNAMIC, //bNumConfigurations; +}; + +/* communcation interface descriptor */ +const static struct ucdc_comm_descriptor _comm_desc = +{ +#ifdef RT_USB_DEVICE_COMPOSITE + /* Interface Association Descriptor */ + USB_DESC_LENGTH_IAD, + USB_DESC_TYPE_IAD, + USB_DYNAMIC, + 0x02, + USB_CDC_CLASS_COMM, + USB_CDC_SUBCLASS_ACM, + USB_CDC_PROTOCOL_V25TER, + 0x00, +#endif + /* Interface Descriptor */ + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x00, + 0x01, + USB_CDC_CLASS_COMM, + USB_CDC_SUBCLASS_ACM, + USB_CDC_PROTOCOL_V25TER, + 0x00, + /* Header Functional Descriptor */ + 0x05, + USB_CDC_CS_INTERFACE, + USB_CDC_SCS_HEADER, + 0x0110, + /* Call Management Functional Descriptor */ + 0x05, + USB_CDC_CS_INTERFACE, + USB_CDC_SCS_CALL_MGMT, + 0x00, + USB_DYNAMIC, + /* Abstract Control Management Functional Descriptor */ + 0x04, + USB_CDC_CS_INTERFACE, + USB_CDC_SCS_ACM, + 0x02, + /* Union Functional Descriptor */ + 0x05, + USB_CDC_CS_INTERFACE, + USB_CDC_SCS_UNION, + USB_DYNAMIC, + USB_DYNAMIC, + /* Endpoint Descriptor */ + USB_DESC_LENGTH_ENDPOINT, + USB_DESC_TYPE_ENDPOINT, + USB_DYNAMIC | USB_DIR_IN, + USB_EP_ATTR_INT, + 0x08, + 0xFF, +}; + +/* data interface descriptor */ +const static struct ucdc_data_descriptor _data_desc = +{ + /* interface descriptor */ + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x00, + 0x02, + USB_CDC_CLASS_DATA, + 0x00, + 0x00, + 0x00, + /* endpoint, bulk out */ + USB_DESC_LENGTH_ENDPOINT, + USB_DESC_TYPE_ENDPOINT, + USB_DYNAMIC | USB_DIR_OUT, + USB_EP_ATTR_BULK, + USB_CDC_BUFSIZE, + 0x00, + /* endpoint, bulk in */ + USB_DESC_LENGTH_ENDPOINT, + USB_DESC_TYPE_ENDPOINT, + USB_DYNAMIC | USB_DIR_IN, + USB_EP_ATTR_BULK, + USB_CDC_BUFSIZE, + 0x00, +}; + +/** + * This function will handle cdc bulk in endpoint request. + * + * @param device the usb device object. + * @param size request size. + * + * @return RT_EOK. + */ +static rt_err_t _ep_in_handler(udevice_t device, uclass_t cls, rt_size_t size) +{ + rt_uint32_t level; + rt_size_t length; + cdc_eps_t eps; + rt_size_t mps; + + eps = (cdc_eps_t)cls->eps; + mps = eps->ep_in->ep_desc->wMaxPacketSize; + size = RT_RINGBUFFER_SIZE(&tx_ringbuffer); + if(size == 0) return RT_EOK; + + length = size > mps ? mps : size; + + level = rt_hw_interrupt_disable(); + rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, length); + rt_hw_interrupt_enable(level); + + /* send data to host */ + dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, length); + + return RT_EOK; +} + +/** + * This function will handle cdc bulk out endpoint request. + * + * @param device the usb device object. + * @param size request size. + * + * @return RT_EOK. + */ +static rt_err_t _ep_out_handler(udevice_t device, uclass_t cls, rt_size_t size) +{ + rt_uint32_t level; + cdc_eps_t eps; + + RT_ASSERT(device != RT_NULL); + + eps = (cdc_eps_t)cls->eps; + /* receive data from USB VCOM */ + level = rt_hw_interrupt_disable(); + rt_ringbuffer_put(&rx_ringbuffer, eps->ep_out->buffer, size); + rt_hw_interrupt_enable(level); + + /* notify receive data */ + rt_hw_serial_isr(&vcom_serial); + + dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, + eps->ep_out->ep_desc->wMaxPacketSize); + + return RT_EOK; +} + +/** + * This function will handle cdc interrupt in endpoint request. + * + * @param device the usb device object. + * @param size request size. + * + * @return RT_EOK. + */ +static rt_err_t _ep_cmd_handler(udevice_t device, uclass_t cls, rt_size_t size) +{ + RT_ASSERT(device != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_cmd_handler\n")); + + return RT_EOK; +} + +/** + * This function will handle cdc_get_line_coding request. + * + * @param device the usb device object. + * @param setup the setup request. + * + * @return RT_EOK on successful. + */ +static rt_err_t _cdc_get_line_coding(udevice_t device, ureq_t setup) +{ + struct ucdc_line_coding data; + rt_uint16_t size; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + data.dwDTERate = 115200; + data.bCharFormat = 0; + data.bDataBits = 8; + data.bParityType = 0; + size = setup->length > 7 ? 7 : setup->length; + + dcd_ep_write(device->dcd, 0, (void*)&data, size); + + return RT_EOK; +} + +/** + * This function will handle cdc_set_line_coding request. + * + * @param device the usb device object. + * @param setup the setup request. + * + * @return RT_EOK on successful. + */ +static rt_err_t _cdc_set_line_coding(udevice_t device, ureq_t setup) +{ + struct ucdc_line_coding data; + rt_err_t ret; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + rt_completion_init(&device->dcd->completion); + + dcd_ep_read(device->dcd, 0, (void*)&data, setup->length); + + ret = rt_completion_wait(&device->dcd->completion, 100); + if(ret != RT_EOK) + { + rt_kprintf("_cdc_set_line_coding timeout\n"); + } + + return RT_EOK; +} + +/** + * This function will handle cdc interface request. + * + * @param device the usb device object. + * @param setup the setup request. + * + * @return RT_EOK on successful. + */ +static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup) +{ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + switch(setup->request) + { + case CDC_SEND_ENCAPSULATED_COMMAND: + break; + case CDC_GET_ENCAPSULATED_RESPONSE: + break; + case CDC_SET_COMM_FEATURE: + break; + case CDC_GET_COMM_FEATURE: + break; + case CDC_CLEAR_COMM_FEATURE: + break; + case CDC_SET_LINE_CODING: + _cdc_set_line_coding(device, setup); + vcom_connected = RT_TRUE; + break; + case CDC_GET_LINE_CODING: + _cdc_get_line_coding(device, setup); + break; + case CDC_SET_CONTROL_LINE_STATE: + rt_device_control((rt_device_t)device->dcd, CONTROL_SEND_STATUS, RT_NULL); + break; + case CDC_SEND_BREAK: + break; + default: + rt_kprintf("unknown cdc request\n",setup->request_type); + return -RT_ERROR; + } + + return RT_EOK; +} + +/** + * This function will run cdc class, it will be called on handle set configuration request. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +static rt_err_t _class_run(udevice_t device, uclass_t cls) +{ + cdc_eps_t eps; + RT_ASSERT(device != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc class run\n")); + eps = (cdc_eps_t)cls->eps; + + eps->ep_in->buffer=tx_pool; + eps->ep_out->buffer=rx_pool; + + dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, + eps->ep_out->ep_desc->wMaxPacketSize); + + return RT_EOK; +} + +/** + * This function will stop cdc class, it will be called on handle set configuration request. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +static rt_err_t _class_stop(udevice_t device, uclass_t cls) +{ + RT_ASSERT(device != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc class stop\n")); + + return RT_EOK; +} + +/** + * This function will handle system sof event. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +static rt_err_t _class_sof_handler(udevice_t device, uclass_t cls) +{ + rt_uint32_t level; + rt_size_t size; + static rt_uint32_t frame_count = 0; + cdc_eps_t eps; + + if(vcom_connected != RT_TRUE) return -RT_ERROR; + + eps = (cdc_eps_t)cls->eps; + if (frame_count ++ == 5) + { + rt_size_t mps = eps->ep_in->ep_desc->wMaxPacketSize; + + /* reset the frame counter */ + frame_count = 0; + + size = RT_RINGBUFFER_SIZE(&tx_ringbuffer); + if(size == 0) return -RT_EFULL; + + size = size > mps ? mps : size; + + level = rt_hw_interrupt_disable(); + rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, size); + rt_hw_interrupt_enable(level); + + /* send data to host */ + dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, size); + } + + return RT_EOK; +} + +static struct uclass_ops ops = +{ + _class_run, + _class_stop, + _class_sof_handler, +}; + +/** + * This function will configure cdc descriptor. + * + * @param comm the communication interface number. + * @param data the data interface number. + * + * @return RT_EOK on successful. + */ +static rt_err_t _cdc_descriptor_config(ucdc_comm_desc_t comm, rt_uint8_t cintf_nr, ucdc_data_desc_t data, rt_uint8_t dintf_nr) +{ + comm->call_mgmt_desc.data_interface = dintf_nr; + comm->union_desc.master_interface = cintf_nr; + comm->union_desc.slave_interface0 = dintf_nr; +#ifdef RT_USB_DEVICE_COMPOSITE + comm->iad_desc.bFirstInterface = cintf_nr; +#endif + + return RT_EOK; +} + +/** + * This function will create a cdc class instance. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +uclass_t rt_usbd_class_cdc_create(udevice_t device) +{ + uclass_t cdc; + cdc_eps_t eps; + uintf_t intf_comm, intf_data; + ualtsetting_t comm_setting, data_setting; + ucdc_data_desc_t data_desc; + ucdc_comm_desc_t comm_desc; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + + /* create a cdc class */ + cdc = rt_usbd_class_create(device, &dev_desc, &ops); + /* create a cdc class endpoints collection */ + eps = rt_malloc(sizeof(struct cdc_eps)); + cdc->eps = (void*)eps; + + /* create a cdc communication interface and a cdc data interface */ + intf_comm = rt_usbd_interface_create(device, _interface_handler); + intf_data = rt_usbd_interface_create(device, _interface_handler); + + /* create a communication alternate setting and a data alternate setting */ + comm_setting = rt_usbd_altsetting_create(sizeof(struct ucdc_comm_descriptor)); + data_setting = rt_usbd_altsetting_create(sizeof(struct ucdc_data_descriptor)); + + /* config desc in alternate setting */ + rt_usbd_altsetting_config_descriptor(comm_setting, &_comm_desc, + (rt_off_t)&((ucdc_comm_desc_t)0)->intf_desc); + rt_usbd_altsetting_config_descriptor(data_setting, &_data_desc, 0); + /* configure the cdc interface descriptor */ + _cdc_descriptor_config(comm_setting->desc, intf_comm->intf_num, data_setting->desc, intf_data->intf_num); + + /* create a bulk in and a bulk endpoint */ + data_desc = (ucdc_data_desc_t)data_setting->desc; + eps->ep_out = rt_usbd_endpoint_create(&data_desc->ep_out_desc, _ep_out_handler); + eps->ep_in = rt_usbd_endpoint_create(&data_desc->ep_in_desc, _ep_in_handler); + + /* add the bulk out and bulk in endpoints to the data alternate setting */ + rt_usbd_altsetting_add_endpoint(data_setting, eps->ep_in); + rt_usbd_altsetting_add_endpoint(data_setting, eps->ep_out); + + /* add the data alternate setting to the data interface + then set default setting of the interface */ + rt_usbd_interface_add_altsetting(intf_data, data_setting); + rt_usbd_set_altsetting(intf_data, 0); + + /* add the cdc data interface to cdc class */ + rt_usbd_class_add_interface(cdc, intf_data); + + /* create a command endpoint */ + comm_desc = (ucdc_comm_desc_t)comm_setting->desc; + eps->ep_cmd = rt_usbd_endpoint_create(&comm_desc->ep_desc, _ep_cmd_handler); + + /* add the command endpoint to the cdc communication interface */ + rt_usbd_altsetting_add_endpoint(comm_setting, eps->ep_cmd); + + /* add the communication alternate setting to the communication interface, + then set default setting of the interface */ + rt_usbd_interface_add_altsetting(intf_comm, comm_setting); + rt_usbd_set_altsetting(intf_comm, 0); + + /* add the communication interface to the cdc class */ + rt_usbd_class_add_interface(cdc, intf_comm); + + return cdc; +} + +/** +* UART device in RT-Thread +*/ +static rt_err_t _vcom_configure(struct rt_serial_device *serial, + struct serial_configure *cfg) +{ + return RT_EOK; +} + +static rt_err_t _vcom_control(struct rt_serial_device *serial, + int cmd, void *arg) +{ + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + /* disable rx irq */ + break; + case RT_DEVICE_CTRL_SET_INT: + /* enable rx irq */ + break; + } + + return RT_EOK; +} + +static int _vcom_putc(struct rt_serial_device *serial, char c) +{ + rt_uint32_t level; + + if (vcom_connected != RT_TRUE) return 0; + + level = rt_hw_interrupt_disable(); + if (RT_RINGBUFFER_EMPTY(&tx_ringbuffer)) + { + rt_ringbuffer_putchar(&tx_ringbuffer, c); + } + rt_hw_interrupt_enable(level); + + return 1; +} + +static int _vcom_getc(struct rt_serial_device *serial) +{ + int result; + rt_uint8_t ch; + rt_uint32_t level; + + result = -1; + + level = rt_hw_interrupt_disable(); + if (RT_RINGBUFFER_SIZE(&rx_ringbuffer)) + { + rt_ringbuffer_getchar(&rx_ringbuffer, &ch); + result = ch; + } + rt_hw_interrupt_enable(level); + + return result; +} + +static const struct rt_uart_ops usb_vcom_ops = +{ + _vcom_configure, + _vcom_control, + _vcom_putc, + _vcom_getc, +}; + +void rt_usb_vcom_init(void) +{ + struct serial_configure config; + + /* initialize ring buffer */ + rt_ringbuffer_init(&rx_ringbuffer, rx_pool, CDC_RX_BUFSIZE); + rt_ringbuffer_init(&tx_ringbuffer, tx_pool, CDC_TX_BUFSIZE); + + config.baud_rate = BAUD_RATE_115200; + config.bit_order = BIT_ORDER_LSB; + config.data_bits = DATA_BITS_8; + config.parity = PARITY_NONE; + config.stop_bits = STOP_BITS_1; + config.invert = NRZ_NORMAL; + + vcom_serial.ops = &usb_vcom_ops; + vcom_serial.int_rx = &vcom_int_rx; + vcom_serial.config = config; + + /* register vcom device */ + rt_hw_serial_register(&vcom_serial, "vcom", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM, + RT_NULL); +} + +#endif + diff --git a/components/drivers/usb/usbdevice/class/mstorage.c b/components/drivers/usb/usbdevice/class/mstorage.c index 000bad5b62..389c2ea479 100644 --- a/components/drivers/usb/usbdevice/class/mstorage.c +++ b/components/drivers/usb/usbdevice/class/mstorage.c @@ -1,598 +1,598 @@ -/* - * File : mstorage.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2012, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2012-10-01 Yi Qiu first version - * 2012-11-25 Heyuanjie87 reduce the memory consumption - * 2012-12-09 Heyuanjie87 change class and endpoint handler - */ - -#include -#include -#include -#include "mstorage.h" - -#ifdef RT_USB_DEVICE_MSTORAGE - -#define STATUS_CBW 0x00 -#define STATUS_CSW 0x01 -#define STATUS_RECEIVE 0x02 -#define STATUS_SEND 0x03 - -static int status = STATUS_CBW; -ALIGN(RT_ALIGN_SIZE) -static struct ustorage_csw csw; -static rt_device_t disk; -static rt_uint32_t _block; -static rt_uint32_t _count, _size; -static struct rt_device_blk_geometry geometry; - -static struct udevice_descriptor dev_desc = -{ - USB_DESC_LENGTH_DEVICE, //bLength; - USB_DESC_TYPE_DEVICE, //type; - USB_BCD_VERSION, //bcdUSB; - USB_CLASS_MASS_STORAGE, //bDeviceClass; - 0x00, //bDeviceSubClass; - 0x00, //bDeviceProtocol; - 0x40, //bMaxPacketSize0; - USB_VENDOR_ID, //idVendor; - USB_MASS_STORAGE_PRODUCT_ID,//idProduct; - USB_BCD_DEVICE, //bcdDevice; - USB_STRING_MANU_INDEX, //iManufacturer; - USB_STRING_PRODUCT_INDEX, //iProduct; - USB_STRING_SERIAL_INDEX, //iSerialNumber; - USB_DYNAMIC, //bNumConfigurations; -}; - -const static struct umass_descriptor _mass_desc = -{ - USB_DESC_LENGTH_INTERFACE, //bLength; - USB_DESC_TYPE_INTERFACE, //type; - USB_DYNAMIC, //bInterfaceNumber; - 0x00, //bAlternateSetting; - 0x02, //bNumEndpoints - USB_CLASS_MASS_STORAGE, //bInterfaceClass; - 0x06, //bInterfaceSubClass; - 0x50, //bInterfaceProtocol; - 0x00, //iInterface; - - USB_DESC_LENGTH_ENDPOINT, //bLength; - USB_DESC_TYPE_ENDPOINT, //type; - USB_DYNAMIC | USB_DIR_OUT, //bEndpointAddress; - USB_EP_ATTR_BULK, //bmAttributes; - 0x40, //wMaxPacketSize; - 0x00, //bInterval; - - USB_DESC_LENGTH_ENDPOINT, //bLength; - USB_DESC_TYPE_ENDPOINT, //type; - USB_DYNAMIC | USB_DIR_IN, //bEndpointAddress; - USB_EP_ATTR_BULK, //bmAttributes; - 0x40, //wMaxPacketSize; - 0x00, //bInterval; -}; - -/** - * This function will allocate an usb device instance from system. - * - * @param parent the hub instance to which the new allocated device attached. - * @param port the hub port. - * - * @return the allocate instance on successful, or RT_NULL on failure. - */ -static rt_err_t _inquiry_cmd(udevice_t device, uep_t ep_in) -{ - rt_uint8_t data[36]; - - *(rt_uint32_t*)&data[0] = 0x0 | (0x80 << 8); - *(rt_uint32_t*)&data[4] = 31; - - rt_memset(&data[8], 0x20, 28); - rt_memcpy(&data[8], "RTT", 3); - rt_memcpy(&data[16], "USB Disk", 8); - - dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 36); - - return RT_EOK; -} - -/** - * This function will handle sense request. - * - * @param device the usb device object. - * - * @return RT_EOK on successful. - */ -static rt_err_t _request_sense(udevice_t device, uep_t ep_in) -{ - struct request_sense_data data; - - data.ErrorCode = 0x70; - data.Valid = 0; - data.SenseKey = 5; - data.Information[0] = 0; - data.Information[1] = 0; - data.Information[2] = 0; - data.Information[3] = 0; - data.AdditionalSenseLength = 0x0b; - data.AdditionalSenseCode = 0x20; - data.AdditionalSenseCodeQualifier =0; - - dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, sizeof(struct request_sense_data)); - - return RT_EOK; -} - -/** - * This function will handle mode_sense_6 request. - * - * @param device the usb device object. - * - * @return RT_EOK on successful. - */ -static rt_err_t _mode_sense_6(udevice_t device, uep_t ep_in) -{ - rt_uint8_t data[4]; - - data[0]=3; - data[1]=0; - data[2]=0; - data[3]=0; - - dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 4); - - return RT_EOK; -} - -/** - * This function will handle read_capacities request. - * - * @param device the usb device object. - * - * @return RT_EOK on successful. - */ -static rt_err_t _read_capacities(udevice_t device, uep_t ep_in) -{ - rt_uint8_t data[12]; - rt_uint32_t sector_count, sector_size; - - RT_ASSERT(device != RT_NULL); - - sector_count = geometry.sector_count; - sector_size = geometry.bytes_per_sector; - - *(rt_uint32_t*)&data[0] = 0x08000000; - data[4] = sector_count >> 24; - data[5] = 0xff & (sector_count >> 16); - data[6] = 0xff & (sector_count >> 8); - data[7] = 0xff & (sector_count); - data[8] = 0x02; - data[9] = 0xff & (sector_size >> 16); - data[10] = 0xff & (sector_size >> 8); - data[11] = 0xff & sector_size; - - dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 12); - - return RT_EOK; -} - -/** - * This function will handle read_capacity request. - * - * @param device the usb device object. - * - * @return RT_EOK on successful. - */ -static rt_err_t _read_capacity(udevice_t device, uep_t ep_in) -{ - rt_uint8_t data[8]; - rt_uint32_t sector_count, sector_size; - - RT_ASSERT(device != RT_NULL); - - sector_count = geometry.sector_count; - sector_size = geometry.bytes_per_sector; - - data[0] = sector_count >> 24; - data[1] = 0xff & (sector_count >> 16); - data[2] = 0xff & (sector_count >> 8); - data[3] = 0xff & (sector_count); - data[4] = 0x0; - data[5] = 0xff & (sector_size >> 16); - data[6] = 0xff & (sector_size >> 8); - data[7] = 0xff & sector_size; - - dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 8); - - return RT_EOK; -} - -/** - * This function will handle read_10 request. - * - * @param device the usb device object. - * @param cbw the command block wrapper. - * - * @return RT_EOK on successful. - */ -static rt_err_t _read_10(udevice_t device, ustorage_cbw_t cbw, uep_t ep_in) -{ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(cbw != RT_NULL); - - _block = cbw->cb[2]<<24 | cbw->cb[3]<<16 | cbw->cb[4]<<8 | - cbw->cb[5]<<0 ; - - _count = cbw->cb[7]<<8 | cbw->cb[8]<<0 ; - - RT_ASSERT(_count < geometry.sector_count); - - rt_device_read(disk, _block, ep_in->buffer, 1); - dcd_ep_write(device->dcd, ep_in, ep_in->buffer, geometry.bytes_per_sector); - _count --; - if (_count) - { - _block ++; - status = STATUS_SEND; - } - else - { - status = STATUS_CSW; - } - - return RT_EOK; -} - -/** - * This function will handle write_10 request. - * - * @param device the usb device object. - * @param cbw the command block wrapper. - * - * @return RT_EOK on successful. - */ -static rt_err_t _write_10(udevice_t device, ustorage_cbw_t cbw, uep_t ep_out) -{ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(cbw != RT_NULL); - - _block = cbw->cb[2]<<24 | cbw->cb[3]<<16 | cbw->cb[4]<<8 | - cbw->cb[5]<<0 ; - _count = cbw->cb[7]<<8 | cbw->cb[8]<<0; - csw.data_reside = cbw->xfer_len; - _size = _count * geometry.bytes_per_sector; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("_write_10 count 0x%x 0x%x\n", - _count, geometry.sector_count)); - - dcd_ep_read(device->dcd, ep_out, ep_out->buffer, geometry.bytes_per_sector); - - return RT_EOK; -} - -/** - * This function will handle verify_10 request. - * - * @param device the usb device object. - * - * @return RT_EOK on successful. - */ -static rt_err_t _verify_10(udevice_t device) -{ - return RT_EOK; -} - -/** - * This function will handle mass storage bulk in endpoint request. - * - * @param device the usb device object. - * @param size request size. - * - * @return RT_EOK. - */ -static rt_err_t _ep_in_handler(udevice_t device, uclass_t cls, rt_size_t size) -{ - mass_eps_t eps; - RT_ASSERT(device != RT_NULL); - - eps = cls->eps; - if(status == STATUS_CSW) - { - dcd_ep_write(device->dcd, eps->ep_in, (rt_uint8_t*)&csw, SIZEOF_CSW); - status = STATUS_CBW; - dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, SIZEOF_CBW); - } - if(status == STATUS_SEND) - { - rt_device_read(disk, _block, eps->ep_in->buffer, 1); - dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, - geometry.bytes_per_sector); - _count --; - if (_count) - { - _block ++; - status = STATUS_SEND; - } - else - { - status = STATUS_CSW; - } - } - - return RT_EOK; -} - -#ifdef MASS_CBW_DUMP -static void cbw_dump(struct ustorage_cbw* cbw) -{ - RT_ASSERT(cbw != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("signature 0x%x\n", cbw->signature)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("tag 0x%x\n", cbw->tag)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("xfer_len 0x%x\n", cbw->xfer_len)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("dflags 0x%x\n", cbw->dflags)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("lun 0x%x\n", cbw->lun)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("cb_len 0x%x\n", cbw->cb_len)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("cb[0] 0x%x\n", cbw->cb[0])); -} -#endif - -/** - * This function will handle mass storage bulk out endpoint request. - * - * @param device the usb device object. - * @param size request size. - * - * @return RT_EOK. - */ -static rt_err_t _ep_out_handler(udevice_t device, uclass_t cls, rt_size_t size) -{ - mass_eps_t eps; - RT_ASSERT(device != RT_NULL); - - eps = (mass_eps_t)cls->eps; - if(status == STATUS_CBW) - { - struct ustorage_cbw* cbw; - - /* dump cbw information */ - cbw = (struct ustorage_cbw*)eps->ep_out->buffer; - - if(cbw->signature == CBW_SIGNATURE) - { - csw.signature = CSW_SIGNATURE; - csw.tag = cbw->tag; - csw.data_reside = 0; - csw.status = 0; - } - else - return -RT_ERROR; - - switch(cbw->cb[0]) - { - case SCSI_TEST_UNIT_READY: - dcd_ep_write(device->dcd, eps->ep_in, (rt_uint8_t*)&csw, SIZEOF_CSW); - dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, SIZEOF_CBW); - break; - case SCSI_REQUEST_SENSE: - _request_sense(device, eps->ep_in); - status = STATUS_CSW; - break; - case SCSI_INQUIRY_CMD: - _inquiry_cmd(device, eps->ep_in); - status = STATUS_CSW; - break; - case SCSI_MODE_SENSE_6: - _mode_sense_6(device, eps->ep_in); - status = STATUS_CSW; - break; - case SCSI_ALLOW_MEDIUM_REMOVAL: - dcd_ep_write(device->dcd, eps->ep_in, (rt_uint8_t*)&csw, SIZEOF_CSW); - dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, SIZEOF_CBW); - break; - case SCSI_READ_CAPACITIES: - _read_capacities(device, eps->ep_in); - status = STATUS_CSW; - break; - case SCSI_READ_CAPACITY: - _read_capacity(device, eps->ep_in); - status = STATUS_CSW; - break; - case SCSI_READ_10: - _read_10(device, cbw, eps->ep_in); - break; - case SCSI_WRITE_10: - _write_10(device, cbw, eps->ep_out); - status = STATUS_RECEIVE; - break; - case SCSI_VERIFY_10: - _verify_10(device); - break; - } - } - else if(status == STATUS_RECEIVE) - { - RT_DEBUG_LOG(RT_DEBUG_USB, ("write size 0x%x block 0x%x oount 0x%x\n", - size, _block, _size)); - - _size -= size; - csw.data_reside -= size; - - rt_device_write(disk, _block, eps->ep_in->buffer, 1); - _block ++; - if(_size == 0) - { - dcd_ep_write(device->dcd, eps->ep_in, (rt_uint8_t*)&csw, SIZEOF_CSW); - dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, SIZEOF_CBW); - status = STATUS_CBW; - } - else - { - dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, - geometry.bytes_per_sector); - } - } - else - { - rt_kprintf("none cbw status\n"); - } - - return RT_EOK; -} - - -/** - * This function will handle mass storage interface request. - * - * @param device the usb device object. - * @param setup the setup request. - * - * @return RT_EOK on successful. - */ -static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup) -{ - rt_uint8_t lun = 0; - - RT_ASSERT(device != RT_NULL); - RT_ASSERT(setup != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("_interface_handler\n")); - - switch(setup->request) - { - case USBREQ_GET_MAX_LUN: - dcd_ep_write(device->dcd, 0, &lun, 1); - break; - case USBREQ_MASS_STORAGE_RESET: - break; - default: - rt_kprintf("unknown interface request\n"); - break; - } - - return RT_EOK; -} - -/** - * This function will run mass storage class, it will be called on handle set configuration request. - * - * @param device the usb device object. - * - * @return RT_EOK on successful. - */ -static rt_err_t _class_run(udevice_t device, uclass_t cls) -{ - mass_eps_t eps; - rt_uint8_t *buffer; - RT_ASSERT(device != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("mass storage run\n")); - eps = (mass_eps_t)cls->eps; - - disk = rt_device_find(RT_USB_MSTORAGE_DISK_NAME); - if(disk == RT_NULL) - { - rt_kprintf("no disk named %s\n", RT_USB_MSTORAGE_DISK_NAME); - return -RT_ERROR; - } - if(rt_device_control(disk, RT_DEVICE_CTRL_BLK_GETGEOME, (void*)&geometry) != RT_EOK) - return -RT_ERROR; - - buffer = (rt_uint8_t*)rt_malloc(geometry.bytes_per_sector); - if(buffer == RT_NULL) - return -RT_ENOMEM; - eps->ep_out->buffer = buffer; - eps->ep_in->buffer = buffer; - - dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, SIZEOF_CBW); - - return RT_EOK; -} - -/** - * This function will stop mass storage class, it will be called on handle set configuration request. - * - * @param device the usb device object. - * - * @return RT_EOK on successful. - */ -static rt_err_t _class_stop(udevice_t device, uclass_t cls) -{ - mass_eps_t eps; - RT_ASSERT(device != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("mass storage stop\n")); - eps = (mass_eps_t)cls->eps; - rt_free(eps->ep_in->buffer); - eps->ep_out->buffer = RT_NULL; - eps->ep_in->buffer = RT_NULL; - - return RT_EOK; -} - -static struct uclass_ops ops = -{ - _class_run, - _class_stop, - RT_NULL, -}; - -/** - * This function will create a mass storage class instance. - * - * @param device the usb device object. - * - * @return RT_EOK on successful. - */ -uclass_t rt_usbd_class_mstorage_create(udevice_t device) -{ - uintf_t intf; - mass_eps_t eps; - uclass_t mstorage; - ualtsetting_t setting; - umass_desc_t mass_desc; - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - - /* create a mass storage class */ - mstorage = rt_usbd_class_create(device, &dev_desc, &ops); - /* create a mass storage endpoints collection */ - eps = (mass_eps_t)rt_malloc(sizeof(struct mass_eps)); - mstorage->eps = (void*)eps; - - /* create an interface */ - intf = rt_usbd_interface_create(device, _interface_handler); - - /* create an alternate setting */ - setting = rt_usbd_altsetting_create(sizeof(struct umass_descriptor)); - /* config desc in alternate setting */ - rt_usbd_altsetting_config_descriptor(setting, &_mass_desc, 0); - - /* create a bulk out and a bulk in endpoint */ - mass_desc = (umass_desc_t)setting->desc; - eps->ep_in = rt_usbd_endpoint_create(&mass_desc->ep_in_desc, _ep_in_handler); - eps->ep_out = rt_usbd_endpoint_create(&mass_desc->ep_out_desc, _ep_out_handler); - - /* add the bulk out and bulk in endpoint to the alternate setting */ - rt_usbd_altsetting_add_endpoint(setting, eps->ep_out); - rt_usbd_altsetting_add_endpoint(setting, eps->ep_in); - - /* add the alternate setting to the interface, then set default setting */ - rt_usbd_interface_add_altsetting(intf, setting); - rt_usbd_set_altsetting(intf, 0); - - /* add the interface to the mass storage class */ - rt_usbd_class_add_interface(mstorage, intf); - - return mstorage; -} - -#endif +/* + * File : mstorage.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2012, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2012-10-01 Yi Qiu first version + * 2012-11-25 Heyuanjie87 reduce the memory consumption + * 2012-12-09 Heyuanjie87 change class and endpoint handler + */ + +#include +#include +#include +#include "mstorage.h" + +#ifdef RT_USB_DEVICE_MSTORAGE + +#define STATUS_CBW 0x00 +#define STATUS_CSW 0x01 +#define STATUS_RECEIVE 0x02 +#define STATUS_SEND 0x03 + +static int status = STATUS_CBW; +ALIGN(RT_ALIGN_SIZE) +static struct ustorage_csw csw; +static rt_device_t disk; +static rt_uint32_t _block; +static rt_uint32_t _count, _size; +static struct rt_device_blk_geometry geometry; + +static struct udevice_descriptor dev_desc = +{ + USB_DESC_LENGTH_DEVICE, //bLength; + USB_DESC_TYPE_DEVICE, //type; + USB_BCD_VERSION, //bcdUSB; + USB_CLASS_MASS_STORAGE, //bDeviceClass; + 0x00, //bDeviceSubClass; + 0x00, //bDeviceProtocol; + 0x40, //bMaxPacketSize0; + USB_VENDOR_ID, //idVendor; + USB_MASS_STORAGE_PRODUCT_ID,//idProduct; + USB_BCD_DEVICE, //bcdDevice; + USB_STRING_MANU_INDEX, //iManufacturer; + USB_STRING_PRODUCT_INDEX, //iProduct; + USB_STRING_SERIAL_INDEX, //iSerialNumber; + USB_DYNAMIC, //bNumConfigurations; +}; + +const static struct umass_descriptor _mass_desc = +{ + USB_DESC_LENGTH_INTERFACE, //bLength; + USB_DESC_TYPE_INTERFACE, //type; + USB_DYNAMIC, //bInterfaceNumber; + 0x00, //bAlternateSetting; + 0x02, //bNumEndpoints + USB_CLASS_MASS_STORAGE, //bInterfaceClass; + 0x06, //bInterfaceSubClass; + 0x50, //bInterfaceProtocol; + 0x00, //iInterface; + + USB_DESC_LENGTH_ENDPOINT, //bLength; + USB_DESC_TYPE_ENDPOINT, //type; + USB_DYNAMIC | USB_DIR_OUT, //bEndpointAddress; + USB_EP_ATTR_BULK, //bmAttributes; + 0x40, //wMaxPacketSize; + 0x00, //bInterval; + + USB_DESC_LENGTH_ENDPOINT, //bLength; + USB_DESC_TYPE_ENDPOINT, //type; + USB_DYNAMIC | USB_DIR_IN, //bEndpointAddress; + USB_EP_ATTR_BULK, //bmAttributes; + 0x40, //wMaxPacketSize; + 0x00, //bInterval; +}; + +/** + * This function will allocate an usb device instance from system. + * + * @param parent the hub instance to which the new allocated device attached. + * @param port the hub port. + * + * @return the allocate instance on successful, or RT_NULL on failure. + */ +static rt_err_t _inquiry_cmd(udevice_t device, uep_t ep_in) +{ + rt_uint8_t data[36]; + + *(rt_uint32_t*)&data[0] = 0x0 | (0x80 << 8); + *(rt_uint32_t*)&data[4] = 31; + + rt_memset(&data[8], 0x20, 28); + rt_memcpy(&data[8], "RTT", 3); + rt_memcpy(&data[16], "USB Disk", 8); + + dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 36); + + return RT_EOK; +} + +/** + * This function will handle sense request. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +static rt_err_t _request_sense(udevice_t device, uep_t ep_in) +{ + struct request_sense_data data; + + data.ErrorCode = 0x70; + data.Valid = 0; + data.SenseKey = 5; + data.Information[0] = 0; + data.Information[1] = 0; + data.Information[2] = 0; + data.Information[3] = 0; + data.AdditionalSenseLength = 0x0b; + data.AdditionalSenseCode = 0x20; + data.AdditionalSenseCodeQualifier =0; + + dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, sizeof(struct request_sense_data)); + + return RT_EOK; +} + +/** + * This function will handle mode_sense_6 request. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +static rt_err_t _mode_sense_6(udevice_t device, uep_t ep_in) +{ + rt_uint8_t data[4]; + + data[0]=3; + data[1]=0; + data[2]=0; + data[3]=0; + + dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 4); + + return RT_EOK; +} + +/** + * This function will handle read_capacities request. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +static rt_err_t _read_capacities(udevice_t device, uep_t ep_in) +{ + rt_uint8_t data[12]; + rt_uint32_t sector_count, sector_size; + + RT_ASSERT(device != RT_NULL); + + sector_count = geometry.sector_count; + sector_size = geometry.bytes_per_sector; + + *(rt_uint32_t*)&data[0] = 0x08000000; + data[4] = sector_count >> 24; + data[5] = 0xff & (sector_count >> 16); + data[6] = 0xff & (sector_count >> 8); + data[7] = 0xff & (sector_count); + data[8] = 0x02; + data[9] = 0xff & (sector_size >> 16); + data[10] = 0xff & (sector_size >> 8); + data[11] = 0xff & sector_size; + + dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 12); + + return RT_EOK; +} + +/** + * This function will handle read_capacity request. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +static rt_err_t _read_capacity(udevice_t device, uep_t ep_in) +{ + rt_uint8_t data[8]; + rt_uint32_t sector_count, sector_size; + + RT_ASSERT(device != RT_NULL); + + sector_count = geometry.sector_count; + sector_size = geometry.bytes_per_sector; + + data[0] = sector_count >> 24; + data[1] = 0xff & (sector_count >> 16); + data[2] = 0xff & (sector_count >> 8); + data[3] = 0xff & (sector_count); + data[4] = 0x0; + data[5] = 0xff & (sector_size >> 16); + data[6] = 0xff & (sector_size >> 8); + data[7] = 0xff & sector_size; + + dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 8); + + return RT_EOK; +} + +/** + * This function will handle read_10 request. + * + * @param device the usb device object. + * @param cbw the command block wrapper. + * + * @return RT_EOK on successful. + */ +static rt_err_t _read_10(udevice_t device, ustorage_cbw_t cbw, uep_t ep_in) +{ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(cbw != RT_NULL); + + _block = cbw->cb[2]<<24 | cbw->cb[3]<<16 | cbw->cb[4]<<8 | + cbw->cb[5]<<0 ; + + _count = cbw->cb[7]<<8 | cbw->cb[8]<<0 ; + + RT_ASSERT(_count < geometry.sector_count); + + rt_device_read(disk, _block, ep_in->buffer, 1); + dcd_ep_write(device->dcd, ep_in, ep_in->buffer, geometry.bytes_per_sector); + _count --; + if (_count) + { + _block ++; + status = STATUS_SEND; + } + else + { + status = STATUS_CSW; + } + + return RT_EOK; +} + +/** + * This function will handle write_10 request. + * + * @param device the usb device object. + * @param cbw the command block wrapper. + * + * @return RT_EOK on successful. + */ +static rt_err_t _write_10(udevice_t device, ustorage_cbw_t cbw, uep_t ep_out) +{ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(cbw != RT_NULL); + + _block = cbw->cb[2]<<24 | cbw->cb[3]<<16 | cbw->cb[4]<<8 | + cbw->cb[5]<<0 ; + _count = cbw->cb[7]<<8 | cbw->cb[8]<<0; + csw.data_reside = cbw->xfer_len; + _size = _count * geometry.bytes_per_sector; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("_write_10 count 0x%x 0x%x\n", + _count, geometry.sector_count)); + + dcd_ep_read(device->dcd, ep_out, ep_out->buffer, geometry.bytes_per_sector); + + return RT_EOK; +} + +/** + * This function will handle verify_10 request. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +static rt_err_t _verify_10(udevice_t device) +{ + return RT_EOK; +} + +/** + * This function will handle mass storage bulk in endpoint request. + * + * @param device the usb device object. + * @param size request size. + * + * @return RT_EOK. + */ +static rt_err_t _ep_in_handler(udevice_t device, uclass_t cls, rt_size_t size) +{ + mass_eps_t eps; + RT_ASSERT(device != RT_NULL); + + eps = cls->eps; + if(status == STATUS_CSW) + { + dcd_ep_write(device->dcd, eps->ep_in, (rt_uint8_t*)&csw, SIZEOF_CSW); + status = STATUS_CBW; + dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, SIZEOF_CBW); + } + if(status == STATUS_SEND) + { + rt_device_read(disk, _block, eps->ep_in->buffer, 1); + dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, + geometry.bytes_per_sector); + _count --; + if (_count) + { + _block ++; + status = STATUS_SEND; + } + else + { + status = STATUS_CSW; + } + } + + return RT_EOK; +} + +#ifdef MASS_CBW_DUMP +static void cbw_dump(struct ustorage_cbw* cbw) +{ + RT_ASSERT(cbw != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("signature 0x%x\n", cbw->signature)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("tag 0x%x\n", cbw->tag)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("xfer_len 0x%x\n", cbw->xfer_len)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("dflags 0x%x\n", cbw->dflags)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("lun 0x%x\n", cbw->lun)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("cb_len 0x%x\n", cbw->cb_len)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("cb[0] 0x%x\n", cbw->cb[0])); +} +#endif + +/** + * This function will handle mass storage bulk out endpoint request. + * + * @param device the usb device object. + * @param size request size. + * + * @return RT_EOK. + */ +static rt_err_t _ep_out_handler(udevice_t device, uclass_t cls, rt_size_t size) +{ + mass_eps_t eps; + RT_ASSERT(device != RT_NULL); + + eps = (mass_eps_t)cls->eps; + if(status == STATUS_CBW) + { + struct ustorage_cbw* cbw; + + /* dump cbw information */ + cbw = (struct ustorage_cbw*)eps->ep_out->buffer; + + if(cbw->signature == CBW_SIGNATURE) + { + csw.signature = CSW_SIGNATURE; + csw.tag = cbw->tag; + csw.data_reside = 0; + csw.status = 0; + } + else + return -RT_ERROR; + + switch(cbw->cb[0]) + { + case SCSI_TEST_UNIT_READY: + dcd_ep_write(device->dcd, eps->ep_in, (rt_uint8_t*)&csw, SIZEOF_CSW); + dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, SIZEOF_CBW); + break; + case SCSI_REQUEST_SENSE: + _request_sense(device, eps->ep_in); + status = STATUS_CSW; + break; + case SCSI_INQUIRY_CMD: + _inquiry_cmd(device, eps->ep_in); + status = STATUS_CSW; + break; + case SCSI_MODE_SENSE_6: + _mode_sense_6(device, eps->ep_in); + status = STATUS_CSW; + break; + case SCSI_ALLOW_MEDIUM_REMOVAL: + dcd_ep_write(device->dcd, eps->ep_in, (rt_uint8_t*)&csw, SIZEOF_CSW); + dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, SIZEOF_CBW); + break; + case SCSI_READ_CAPACITIES: + _read_capacities(device, eps->ep_in); + status = STATUS_CSW; + break; + case SCSI_READ_CAPACITY: + _read_capacity(device, eps->ep_in); + status = STATUS_CSW; + break; + case SCSI_READ_10: + _read_10(device, cbw, eps->ep_in); + break; + case SCSI_WRITE_10: + _write_10(device, cbw, eps->ep_out); + status = STATUS_RECEIVE; + break; + case SCSI_VERIFY_10: + _verify_10(device); + break; + } + } + else if(status == STATUS_RECEIVE) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("write size 0x%x block 0x%x oount 0x%x\n", + size, _block, _size)); + + _size -= size; + csw.data_reside -= size; + + rt_device_write(disk, _block, eps->ep_in->buffer, 1); + _block ++; + if(_size == 0) + { + dcd_ep_write(device->dcd, eps->ep_in, (rt_uint8_t*)&csw, SIZEOF_CSW); + dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, SIZEOF_CBW); + status = STATUS_CBW; + } + else + { + dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, + geometry.bytes_per_sector); + } + } + else + { + rt_kprintf("none cbw status\n"); + } + + return RT_EOK; +} + + +/** + * This function will handle mass storage interface request. + * + * @param device the usb device object. + * @param setup the setup request. + * + * @return RT_EOK on successful. + */ +static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup) +{ + rt_uint8_t lun = 0; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("_interface_handler\n")); + + switch(setup->request) + { + case USBREQ_GET_MAX_LUN: + dcd_ep_write(device->dcd, 0, &lun, 1); + break; + case USBREQ_MASS_STORAGE_RESET: + break; + default: + rt_kprintf("unknown interface request\n"); + break; + } + + return RT_EOK; +} + +/** + * This function will run mass storage class, it will be called on handle set configuration request. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +static rt_err_t _class_run(udevice_t device, uclass_t cls) +{ + mass_eps_t eps; + rt_uint8_t *buffer; + RT_ASSERT(device != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("mass storage run\n")); + eps = (mass_eps_t)cls->eps; + + disk = rt_device_find(RT_USB_MSTORAGE_DISK_NAME); + if(disk == RT_NULL) + { + rt_kprintf("no disk named %s\n", RT_USB_MSTORAGE_DISK_NAME); + return -RT_ERROR; + } + if(rt_device_control(disk, RT_DEVICE_CTRL_BLK_GETGEOME, (void*)&geometry) != RT_EOK) + return -RT_ERROR; + + buffer = (rt_uint8_t*)rt_malloc(geometry.bytes_per_sector); + if(buffer == RT_NULL) + return -RT_ENOMEM; + eps->ep_out->buffer = buffer; + eps->ep_in->buffer = buffer; + + dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, SIZEOF_CBW); + + return RT_EOK; +} + +/** + * This function will stop mass storage class, it will be called on handle set configuration request. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +static rt_err_t _class_stop(udevice_t device, uclass_t cls) +{ + mass_eps_t eps; + RT_ASSERT(device != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("mass storage stop\n")); + eps = (mass_eps_t)cls->eps; + rt_free(eps->ep_in->buffer); + eps->ep_out->buffer = RT_NULL; + eps->ep_in->buffer = RT_NULL; + + return RT_EOK; +} + +static struct uclass_ops ops = +{ + _class_run, + _class_stop, + RT_NULL, +}; + +/** + * This function will create a mass storage class instance. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +uclass_t rt_usbd_class_mstorage_create(udevice_t device) +{ + uintf_t intf; + mass_eps_t eps; + uclass_t mstorage; + ualtsetting_t setting; + umass_desc_t mass_desc; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + + /* create a mass storage class */ + mstorage = rt_usbd_class_create(device, &dev_desc, &ops); + /* create a mass storage endpoints collection */ + eps = (mass_eps_t)rt_malloc(sizeof(struct mass_eps)); + mstorage->eps = (void*)eps; + + /* create an interface */ + intf = rt_usbd_interface_create(device, _interface_handler); + + /* create an alternate setting */ + setting = rt_usbd_altsetting_create(sizeof(struct umass_descriptor)); + /* config desc in alternate setting */ + rt_usbd_altsetting_config_descriptor(setting, &_mass_desc, 0); + + /* create a bulk out and a bulk in endpoint */ + mass_desc = (umass_desc_t)setting->desc; + eps->ep_in = rt_usbd_endpoint_create(&mass_desc->ep_in_desc, _ep_in_handler); + eps->ep_out = rt_usbd_endpoint_create(&mass_desc->ep_out_desc, _ep_out_handler); + + /* add the bulk out and bulk in endpoint to the alternate setting */ + rt_usbd_altsetting_add_endpoint(setting, eps->ep_out); + rt_usbd_altsetting_add_endpoint(setting, eps->ep_in); + + /* add the alternate setting to the interface, then set default setting */ + rt_usbd_interface_add_altsetting(intf, setting); + rt_usbd_set_altsetting(intf, 0); + + /* add the interface to the mass storage class */ + rt_usbd_class_add_interface(mstorage, intf); + + return mstorage; +} + +#endif diff --git a/components/drivers/usb/usbdevice/class/mstorage.h b/components/drivers/usb/usbdevice/class/mstorage.h index b25b8b0a4b..740d9e6568 100644 --- a/components/drivers/usb/usbdevice/class/mstorage.h +++ b/components/drivers/usb/usbdevice/class/mstorage.h @@ -1,66 +1,66 @@ -/* - * File : mstorage.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2012, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2012-10-01 Yi Qiu first version - * 2012-12-12 heyuanjie87 add MASS endpoints collection - */ - -#ifndef __MSTORAGE_H__ -#define __MSTORAGE_H__ - -#include - -#define USBREQ_GET_MAX_LUN 0xfe -#define USBREQ_MASS_STORAGE_RESET 0xff - -#define USB_MASS_STORAGE_PRODUCT_ID 0x1000 /* Product ID */ - -#pragma pack(1) - -struct umass_descriptor -{ - struct uinterface_descriptor intf_desc; - struct uendpoint_descriptor ep_out_desc; - struct uendpoint_descriptor ep_in_desc; -}; -typedef struct umass_descriptor* umass_desc_t; - -struct capacity_data -{ - rt_uint8_t LastLogicalBlockAddress[4]; - rt_uint8_t BlockLengthInBytes[4]; -}; - -struct request_sense_data -{ - rt_uint8_t ErrorCode:7; - rt_uint8_t Valid:1; - rt_uint8_t Reserved1; - rt_uint8_t SenseKey:4; - rt_uint8_t Reserved2:4; - rt_uint8_t Information[4]; - rt_uint8_t AdditionalSenseLength; - rt_uint8_t Reserved3[4]; - rt_uint8_t AdditionalSenseCode; - rt_uint8_t AdditionalSenseCodeQualifier; - rt_uint8_t Reserved4[4]; -}request_sense_data_t; - -struct mass_eps -{ - uep_t ep_in; - uep_t ep_out; -}; -typedef struct mass_eps* mass_eps_t; - -#pragma pack() - -#endif +/* + * File : mstorage.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2012, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2012-10-01 Yi Qiu first version + * 2012-12-12 heyuanjie87 add MASS endpoints collection + */ + +#ifndef __MSTORAGE_H__ +#define __MSTORAGE_H__ + +#include + +#define USBREQ_GET_MAX_LUN 0xfe +#define USBREQ_MASS_STORAGE_RESET 0xff + +#define USB_MASS_STORAGE_PRODUCT_ID 0x1000 /* Product ID */ + +#pragma pack(1) + +struct umass_descriptor +{ + struct uinterface_descriptor intf_desc; + struct uendpoint_descriptor ep_out_desc; + struct uendpoint_descriptor ep_in_desc; +}; +typedef struct umass_descriptor* umass_desc_t; + +struct capacity_data +{ + rt_uint8_t LastLogicalBlockAddress[4]; + rt_uint8_t BlockLengthInBytes[4]; +}; + +struct request_sense_data +{ + rt_uint8_t ErrorCode:7; + rt_uint8_t Valid:1; + rt_uint8_t Reserved1; + rt_uint8_t SenseKey:4; + rt_uint8_t Reserved2:4; + rt_uint8_t Information[4]; + rt_uint8_t AdditionalSenseLength; + rt_uint8_t Reserved3[4]; + rt_uint8_t AdditionalSenseCode; + rt_uint8_t AdditionalSenseCodeQualifier; + rt_uint8_t Reserved4[4]; +}request_sense_data_t; + +struct mass_eps +{ + uep_t ep_in; + uep_t ep_out; +}; +typedef struct mass_eps* mass_eps_t; + +#pragma pack() + +#endif diff --git a/components/drivers/usb/usbdevice/core/core.c b/components/drivers/usb/usbdevice/core/core.c index 192cbe70bf..a4d729cb65 100644 --- a/components/drivers/usb/usbdevice/core/core.c +++ b/components/drivers/usb/usbdevice/core/core.c @@ -1,1321 +1,1321 @@ -/* - * File : core.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2012, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2012-10-01 Yi Qiu first version - * 2012-12-12 heyuanjie87 change endpoint and class handler - * 2012-12-30 heyuanjie87 change inferface handler - */ - -#include -#include - -static rt_list_t device_list; - -/** - * This function will handle get_device_descriptor request. - * - * @param device the usb device object. - * @param setup the setup request. - * - * @return RT_EOK on successful. - */ -static rt_err_t _get_device_descriptor(struct udevice* device, ureq_t setup) -{ - rt_size_t size; - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(setup != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_device_descriptor\n")); - - /* device descriptor length should less than USB_DESC_LENGTH_DEVICE*/ - size = (setup->length > USB_DESC_LENGTH_DEVICE) ? - USB_DESC_LENGTH_DEVICE : setup->length; - - /* send device descriptor to endpoint 0 */ - dcd_ep_write(device->dcd, 0, (rt_uint8_t*)&device->dev_desc, - size); - - return RT_EOK; -} - -/** - * This function will handle get_config_descriptor request. - * - * @param device the usb device object. - * @param setup the setup request. - * - * @return RT_EOK on successful. - */ -static rt_err_t _get_config_descriptor(struct udevice* device, ureq_t setup) -{ - rt_size_t size; - ucfg_desc_t cfg_desc; - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(setup != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_config_descriptor\n")); - - cfg_desc = &device->curr_cfg->cfg_desc; - size = (setup->length > cfg_desc->wTotalLength) ? - cfg_desc->wTotalLength : setup->length; - - /* send configuration descriptor to endpoint 0 */ - dcd_ep_write(device->dcd, 0, (rt_uint8_t*)cfg_desc, size); - - return RT_EOK; -} - -/** - * This function will handle get_string_descriptor request. - * - * @param device the usb device object. - * @param setup the setup request. - * - * @return RT_EOK on successful, -RT_ERROR on invalid request. - */ -static rt_err_t _get_string_descriptor(struct udevice* device, ureq_t setup) -{ - struct ustring_descriptor str_desc; - rt_uint8_t index, i; - rt_uint32_t len; - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(setup != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_string_descriptor\n")); - - str_desc.type = USB_DESC_TYPE_STRING; - index = setup->value & 0xFF; - - if(index > USB_STRING_INTERFACE_INDEX) - { - rt_kprintf("unknown string index\n"); - dcd_ep_stall(device->dcd, 0); - return -RT_ERROR; - } - if(index == 0) - { - str_desc.bLength = 4; - str_desc.String[0] = 0x09; - str_desc.String[1] = 0x04; - } - else - { - len = rt_strlen(device->str[index]); - str_desc.bLength = len*2 + 2; - - for(i=0; istr[index][i]; - str_desc.String[i*2 + 1] = 0; - } - } - - if(setup->length == 0xFF) - len = str_desc.bLength; - else - len = setup->length; - - /* send string descriptor to endpoint 0 */ - dcd_ep_write(device->dcd, 0, (rt_uint8_t*)&str_desc, len); - - return RT_EOK; -} - -/** - * This function will handle get_descriptor request. - * - * @param device the usb device object. - * @param setup the setup request. - * - * @return RT_EOK on successful. - */ -static rt_err_t _get_descriptor(struct udevice* device, ureq_t setup) -{ - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(setup != RT_NULL); - - if(setup->request_type == USB_REQ_TYPE_DIR_IN) - { - switch(setup->value >> 8) - { - case USB_DESC_TYPE_DEVICE: - _get_device_descriptor(device, setup); - break; - case USB_DESC_TYPE_CONFIGURATION: - _get_config_descriptor(device, setup); - break; - case USB_DESC_TYPE_STRING: - _get_string_descriptor(device, setup); - break; - case USB_DESC_TYPE_DEVICEQUALIFIER: - dcd_ep_stall(device->dcd, 0); - break; - default: - rt_kprintf("unsupported descriptor request\n"); - dcd_ep_stall(device->dcd, 0); - break; - } - } - else - { - rt_kprintf("request direction error\n"); - dcd_ep_stall(device->dcd, 0); - } - - return RT_EOK; -} - -/** - * This function will handle get_interface request. - * - * @param device the usb device object. - * @param setup the setup request. - * - * @return RT_EOK on successful. - */ -static rt_err_t _get_interface(struct udevice* device, ureq_t setup) -{ - rt_uint8_t value; - uintf_t intf; - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(setup != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_interface\n")); - - /* find the specified interface and its alternate setting */ - intf = rt_usbd_find_interface(device, setup->index & 0xFF, RT_NULL); - value = intf->curr_setting->intf_desc->bAlternateSetting; - - /* send the interface alternate setting to endpoint 0*/ - dcd_ep_write(device->dcd, 0, &value, 1); - - return RT_EOK; -} - -/** - * This function will handle set_interface request. - * - * @param device the usb device object. - * @param setup the setup request. - * - * @return RT_EOK on successful. - */ -static rt_err_t _set_interface(struct udevice* device, ureq_t setup) -{ - uintf_t intf; - uep_t ep; - struct rt_list_node* i; - ualtsetting_t setting; - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(setup != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("_set_interface\n")); - - /* find the specified interface */ - intf = rt_usbd_find_interface(device, setup->index & 0xFF, RT_NULL); - - /* set alternate setting to the interface */ - rt_usbd_set_altsetting(intf, setup->value & 0xFF); - setting = intf->curr_setting; - - /* start all endpoints of the interface alternate setting */ - for(i=setting->ep_list.next; i != &setting->ep_list; i=i->next) - { - ep = (uep_t)rt_list_entry(i, struct uendpoint, list); - dcd_ep_stop(device->dcd, ep); - dcd_ep_run(device->dcd, ep); - } - - return RT_EOK; -} - -/** - * This function will handle get_config request. - * - * @param device the usb device object. - * @param setup the setup request. - * - * @return RT_EOK on successful. - */ -static rt_err_t _get_config(struct udevice* device, ureq_t setup) -{ - rt_uint8_t value; - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(setup != RT_NULL); - RT_ASSERT(device->curr_cfg != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_config\n")); - - /* get current configuration */ - value = device->curr_cfg->cfg_desc.bConfigurationValue; - - /* write the current configuration to endpoint 0 */ - dcd_ep_write(device->dcd, 0, &value, 1); - - return RT_EOK; -} - -/** - * This function will handle set_config request. - * - * @param device the usb device object. - * @param setup the setup request. - * - * @return RT_EOK on successful. - */ -static rt_err_t _set_config(struct udevice* device, ureq_t setup) -{ - struct rt_list_node *i, *j, *k; - uconfig_t cfg; - uintf_t intf; - ualtsetting_t setting; - uep_t ep; - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(setup != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("_set_config\n")); - - /* set current configuration */ - rt_usbd_set_config(device, setup->value); - cfg = device->curr_cfg; - - for (i=cfg->cls_list.next; i!=&cfg->cls_list; i=i->next) - { - /* run all classes and their endpoints in the configuration */ - uclass_t cls = (uclass_t)rt_list_entry(i, struct uclass, list); - for(j=cls->intf_list.next; j!=&cls->intf_list; j=j->next) - { - intf = (uintf_t)rt_list_entry(j, struct uinterface, list); - setting = intf->curr_setting; - for(k=setting->ep_list.next; k != &setting->ep_list; k=k->next) - { - ep = (uep_t)rt_list_entry(k, struct uendpoint, list); - - /* first stop then start endpoint */ - dcd_ep_stop(device->dcd, ep); - dcd_ep_run(device->dcd, ep); - } - } - /* after running all endpoints, then run class */ - if(cls->ops->run != RT_NULL) - cls->ops->run(device, cls); - } - - /* issue status stage */ - rt_device_control((rt_device_t)device->dcd, CONTROL_SEND_STATUS, RT_NULL); - - return RT_EOK; -} - -/** - * This function will handle set_address request. - * - * @param device the usb device object. - * @param setup the setup request. - * - * @return RT_EOK on successful. - */ -static rt_err_t _set_address(struct udevice* device, ureq_t setup) -{ - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(setup != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("_set_address\n")); - - /* set address in device control driver */ - dcd_set_address(device->dcd, setup->value); - - /* issue status stage */ - rt_device_control((rt_device_t)device->dcd, CONTROL_SEND_STATUS, RT_NULL); - - return RT_EOK; -} - -/** - * This function will handle standard request. - * - * @param device the usb device object. - * @param setup the setup request. - * - * @return RT_EOK on successful. - */ -static rt_err_t _standard_request(struct udevice* device, ureq_t setup) -{ - udcd_t dcd; - rt_uint16_t value = 0; - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(setup != RT_NULL); - - dcd = device->dcd; - - switch(setup->request_type & USB_REQ_TYPE_RECIPIENT_MASK) - { - case USB_REQ_TYPE_DEVICE: - switch(setup->request) - { - case USB_REQ_GET_STATUS: - dcd_ep_write(device->dcd, 0, &value, 2); - break; - case USB_REQ_CLEAR_FEATURE: - dcd_clear_feature(dcd, setup->value); - break; - case USB_REQ_SET_FEATURE: - dcd_set_feature(dcd, setup->value); - break; - case USB_REQ_SET_ADDRESS: - _set_address(device, setup); - break; - case USB_REQ_GET_DESCRIPTOR: - _get_descriptor(device, setup); - break; - case USB_REQ_SET_DESCRIPTOR: - dcd_ep_stall(dcd, 0); - break; - case USB_REQ_GET_CONFIGURATION: - _get_config(device, setup); - break; - case USB_REQ_SET_CONFIGURATION: - _set_config(device, setup); - break; - default: - rt_kprintf("unknown device request\n"); - dcd_ep_stall(device->dcd, 0); - break; - } - break; - case USB_REQ_TYPE_INTERFACE: - switch(setup->request) - { - case USB_REQ_GET_INTERFACE: - _get_interface(device, setup); - break; - case USB_REQ_SET_INTERFACE: - _set_interface(device, setup); - break; - default: - rt_kprintf("unknown interface request\n"); - dcd_ep_stall(device->dcd, 0); - break; - } - break; - case USB_REQ_TYPE_ENDPOINT: - switch(setup->request) - { - case USB_REQ_GET_STATUS: - /* TODO */ - dcd_ep_write(dcd, 0, &value, 2); - break; - case USB_REQ_CLEAR_FEATURE: - dcd_clear_feature(dcd, setup->value); - break; - case USB_REQ_SET_FEATURE: - dcd_set_feature(dcd, setup->value); - break; - case USB_REQ_SYNCH_FRAME: - break; - default: - rt_kprintf("unknown endpoint request\n"); - dcd_ep_stall(device->dcd, 0); - break; - } - break; - case USB_REQ_TYPE_OTHER: - rt_kprintf("unknown other type request\n"); - dcd_ep_stall(device->dcd, 0); - break; - default: - rt_kprintf("unknown type request\n"); - dcd_ep_stall(device->dcd, 0); - break; - } - - return RT_EOK; -} - -/** - * This function will handle class request. - * - * @param device the usb device object. - * @param setup the setup request. - * - * @return RT_EOK on successful, -RT_ERROR on invalid request. - */ -static rt_err_t _class_request(udevice_t device, ureq_t setup) -{ - uintf_t intf; - uclass_t cls; - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(setup != RT_NULL); - - /* verify request value */ - if(setup->index > device->curr_cfg->cfg_desc.bNumInterfaces) - { - dcd_ep_stall(device->dcd, 0); - return -RT_ERROR; - } - - switch(setup->request_type & USB_REQ_TYPE_RECIPIENT_MASK) - { - case USB_REQ_TYPE_INTERFACE: - intf = rt_usbd_find_interface(device, setup->index & 0xFF, &cls); - intf->handler(device, cls, setup); - break; - case USB_REQ_TYPE_ENDPOINT: - break; - default: - rt_kprintf("unknown class request type\n"); - dcd_ep_stall(device->dcd, 0); - break; - } - - return RT_EOK; -} - -/** - * This function will handle setup request. - * - * @param device the usb device object. - * @param setup the setup request. - * - * @return RT_EOK on successful, -RT_ERROR on invalid request. - */ -static rt_err_t _setup_request(udevice_t device, ureq_t setup) -{ - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(setup != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("[\n")); - RT_DEBUG_LOG(RT_DEBUG_USB, ("setup_request_handler 0x%x\n", - setup->request_type)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("value 0x%x\n", setup->value)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("length 0x%x\n", setup->length)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("index 0x%x\n", setup->index)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("request 0x%x\n", setup->request)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("]\n")); - - switch((setup->request_type & USB_REQ_TYPE_MASK)) - { - case USB_REQ_TYPE_STANDARD: - _standard_request(device, setup); - break; - case USB_REQ_TYPE_CLASS: - _class_request(device, setup); - break; - case USB_REQ_TYPE_VENDOR: - rt_kprintf("vendor type request\n"); - break; - default: - rt_kprintf("unknown setup request type\n"); - dcd_ep_stall(device->dcd, 0); - return -RT_ERROR; - } - - return RT_EOK; -} - -/** - * This function will notity sof event to all of class. - * - * @param device the usb device object. - * - * @return RT_EOK. - */ -rt_err_t _sof_notify(udevice_t device) -{ - struct rt_list_node *i; - uclass_t cls; - - RT_ASSERT(device != RT_NULL); - - /* to notity every class that sof event comes */ - for (i=device->curr_cfg->cls_list.next; - i!=&device->curr_cfg->cls_list; i=i->next) - { - cls = (uclass_t)rt_list_entry(i, struct uclass, list); - if(cls->ops->sof_handler != RT_NULL) - cls->ops->sof_handler(device, cls); - } - - return RT_EOK; -} - -/** - * This function will create an usb device object. - * - * @param ustring the usb string array to contain string descriptor. - * - * @return an usb device object on success, RT_NULL on fail. - */ -udevice_t rt_usbd_device_create(const char** ustring) -{ - udevice_t udevice; - - /* parameter check */ - RT_ASSERT(ustring != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_create\n")); - - /* allocate memory for the object */ - udevice = rt_malloc(sizeof(struct udevice)); - if(udevice == RT_NULL) - { - rt_kprintf("alloc memery failed\n"); - return RT_NULL; - } - rt_memset(udevice, 0, sizeof(struct udevice)); - - /* set string descriptor array to the device object */ - udevice->str = ustring; - - /* to initialize configuration list */ - rt_list_init(&udevice->cfg_list); - - /* insert the device object to device list */ - rt_list_insert_after(&device_list, &udevice->list); - - return udevice; -} - -/** - * This function will set an usb controller driver to a device. - * - * @param device the usb device object. - * @param dcd the usb device controller driver. - * - * @return RT_EOK on successful. - */ -rt_err_t rt_usbd_device_set_controller(udevice_t device, udcd_t dcd) -{ - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(dcd != RT_NULL); - - /* set usb device controller driver to the device */ - device->dcd = dcd; - - return RT_EOK; -} - -/** - * This function will set an usb device descriptor to a device. - * - * @param device the usb device object. - * @param dev_desc the usb device descriptor. - * - * @return RT_EOK on successful. - */ -rt_err_t rt_usbd_device_set_descriptor(udevice_t device, udev_desc_t dev_desc) -{ - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(dev_desc != RT_NULL); - - /* copy the usb device descriptor to the device */ - rt_memcpy((void *)&device->dev_desc, (void *)dev_desc, USB_DESC_LENGTH_DEVICE); - - return RT_EOK; -} - -/** - * This function will create an usb configuration object. - * - * @param none. - * - * @return an usb configuration object. - */ -uconfig_t rt_usbd_config_create(void) -{ - uconfig_t cfg; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_create\n")); - - /* allocate memory for the object */ - cfg = rt_malloc(sizeof(struct uconfig)); - if(cfg == RT_NULL) - { - rt_kprintf("alloc memery failed\n"); - return RT_NULL; - } - rt_memset(cfg, 0, sizeof(struct uconfig)); - - /* set default value */ - cfg->cfg_desc.bLength = USB_DESC_LENGTH_CONFIG; - cfg->cfg_desc.type = USB_DESC_TYPE_CONFIGURATION; - cfg->cfg_desc.wTotalLength = USB_DESC_LENGTH_CONFIG; - cfg->cfg_desc.bmAttributes = 0xC0; - cfg->cfg_desc.MaxPower = 0x32; - - /* to initialize class object list */ - rt_list_init(&cfg->cls_list); - - return cfg; -} - -/** - * This function will create an usb interface object. - * - * @param device the usb device object. - * @handler the callback handler of object - * - * @return an usb interface object on success, RT_NULL on fail. - */ -uintf_t rt_usbd_interface_create(udevice_t device, uintf_handler_t handler) -{ - uintf_t intf; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_interface_create\n")); - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - - /* allocate memory for the object */ - intf = (uintf_t)rt_malloc(sizeof(struct uinterface)); - if(intf == RT_NULL) - { - rt_kprintf("alloc memery failed\n"); - return RT_NULL; - } - intf->intf_num = device->nr_intf; - device->nr_intf++; - intf->handler = handler; - intf->curr_setting = RT_NULL; - - /* to initialize the alternate setting object list */ - rt_list_init(&intf->setting_list); - - return intf; -} - -/** - * This function will create an usb alternate setting object. - * - * @param intf_desc the interface descriptor. - * @desc_size the size of the interface descriptor. - * - * @return an usb alternate setting object on success, RT_NULL on fail. - */ -ualtsetting_t rt_usbd_altsetting_create(rt_size_t desc_size) -{ - ualtsetting_t setting; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_altsetting_create\n")); - - /* parameter check */ - RT_ASSERT(desc_size > 0); - - /* allocate memory for the object */ - setting = (ualtsetting_t)rt_malloc(sizeof(struct ualtsetting)); - if(setting == RT_NULL) - { - rt_kprintf("alloc memery failed\n"); - return RT_NULL; - } - /* allocate memory for the desc */ - setting->desc = rt_malloc(desc_size); - if (setting->desc == RT_NULL) - { - rt_kprintf("alloc desc memery failed\n"); - rt_free(setting); - return RT_NULL; - } - - setting->desc_size = desc_size; - setting->intf_desc = RT_NULL; - - /* to initialize endpoint list */ - rt_list_init(&setting->ep_list); - - return setting; -} - -/** - * This function will config an desc in alternate setting object. - * - * @param setting the altsetting to be config. - * @param desc use it to init desc in setting. - * @param intf_pos the offset of interface descriptor in desc. - * - * @return RT_EOK. - */ -rt_err_t rt_usbd_altsetting_config_descriptor(ualtsetting_t setting, const void* desc, rt_off_t intf_pos) -{ - RT_ASSERT(setting != RT_NULL); - RT_ASSERT(setting->desc !=RT_NULL); - - rt_memcpy(setting->desc, desc, setting->desc_size); - setting->intf_desc = (uintf_desc_t)((char*)setting->desc + intf_pos); - - return RT_EOK; -} - -/** - * This function will create an usb class object. - * - * @param device the usb device object. - * @param dev_desc the device descriptor. - * @param ops the operation set. - * - * @return an usb class object on success, RT_NULL on fail. - */ -uclass_t rt_usbd_class_create(udevice_t device, udev_desc_t dev_desc, - uclass_ops_t ops) -{ - uclass_t cls; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_class_create\n")); - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(dev_desc != RT_NULL); - - /* allocate memory for the object */ - cls = (uclass_t)rt_malloc(sizeof(struct uclass)); - if(cls == RT_NULL) - { - rt_kprintf("alloc memery failed\n"); - return RT_NULL; - } - cls->dev_desc = dev_desc; - cls->ops = ops; - cls->device = device; - - /* to initialize interface list */ - rt_list_init(&cls->intf_list); - - return cls; -} - -/** - * This function will create an usb endpoint object. - * - * @param ep_desc the endpoint descriptor. - * @handler the callback handler of object - * - * @return an usb endpoint object on success, RT_NULL on fail. - */ -uep_t rt_usbd_endpoint_create(uep_desc_t ep_desc, udep_handler_t handler) -{ - uep_t ep; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_endpoint_create\n")); - - /* parameter check */ - RT_ASSERT(ep_desc != RT_NULL); - - /* allocate memory for the object */ - ep = (uep_t)rt_malloc(sizeof(struct uendpoint)); - if(ep == RT_NULL) - { - rt_kprintf("alloc memery failed\n"); - return RT_NULL; - } - ep->ep_desc = ep_desc; - ep->handler = handler; - ep->buffer = RT_NULL; - - return ep; -} - -/** - * This function will find an usb device object. - * - * @dcd usd device controller driver. - * - * @return an usb device object on found or RT_NULL on not found. - */ -udevice_t rt_usbd_find_device(udcd_t dcd) -{ - struct rt_list_node* node; - udevice_t device; - - /* parameter check */ - RT_ASSERT(dcd != RT_NULL); - - /* search a device in the the device list */ - for (node = device_list.next; node != &device_list; node = node->next) - { - device = (udevice_t)rt_list_entry(node, struct udevice, list); - if(device->dcd == dcd) return device; - } - - rt_kprintf("can't find device\n"); - return RT_NULL; -} - -/** - * This function will find an usb configuration object. - * - * @param device the usb device object. - * @param value the configuration number. - * - * @return an usb configuration object on found or RT_NULL on not found. - */ -uconfig_t rt_usbd_find_config(udevice_t device, rt_uint8_t value) -{ - struct rt_list_node* node; - uconfig_t cfg = RT_NULL; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_config\n")); - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(value <= device->dev_desc.bNumConfigurations); - - /* search a configration in the the device */ - for (node = device->cfg_list.next; node != &device->cfg_list; node = node->next) - { - cfg = (uconfig_t)rt_list_entry(node, struct udevice, list); - if(cfg->cfg_desc.bConfigurationValue == value) return cfg; - } - - rt_kprintf("can't find configuration %d\n", value); - return RT_NULL; -} - -/** - * This function will find an usb interface object. - * - * @param device the usb device object. - * @param value the interface number. - * - * @return an usb configuration object on found or RT_NULL on not found. - */ -uintf_t rt_usbd_find_interface(udevice_t device, rt_uint8_t value, uclass_t *pcls) -{ - struct rt_list_node *i, *j; - uclass_t cls; - uintf_t intf; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_interface\n")); - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(value < device->nr_intf); - - /* search an interface in the current configuration */ - for (i=device->curr_cfg->cls_list.next; - i!=&device->curr_cfg->cls_list; i=i->next) - { - cls = (uclass_t)rt_list_entry(i, struct uclass, list); - for(j=cls->intf_list.next; j!=&cls->intf_list; j=j->next) - { - intf = (uintf_t)rt_list_entry(j, struct uinterface, list); - if(intf->intf_num == value) - { - if (pcls != RT_NULL) - *pcls = cls; - return intf; - } - } - } - - rt_kprintf("can't find interface %d\n", value); - return RT_NULL; -} - -/** - * This function will find an usb interface alternate setting object. - * - * @param device the usb device object. - * @param value the alternate setting number. - * - * @return an usb interface alternate setting object on found or RT_NULL on not found. - */ -ualtsetting_t rt_usbd_find_altsetting(uintf_t intf, rt_uint8_t value) -{ - struct rt_list_node *i; - ualtsetting_t setting; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_altsetting\n")); - - /* parameter check */ - RT_ASSERT(intf != RT_NULL); - - if(intf->curr_setting != RT_NULL) - { - /* if the value equal to the current alternate setting, then do not search */ - if(intf->curr_setting->intf_desc->bAlternateSetting == value) - return intf->curr_setting; - } - - /* search a setting in the alternate setting list */ - for(i=intf->setting_list.next; i!=&intf->setting_list; i=i->next) - { - setting =(ualtsetting_t)rt_list_entry(i, struct ualtsetting, list); - if(setting->intf_desc->bAlternateSetting == value) - return setting; - } - - rt_kprintf("can't find alternate setting %d\n", value); - return RT_NULL; -} - -/** - * This function will find an usb endpoint object. - * - * @param device the usb device object. - * @param ep_addr endpoint address. - * - * @return an usb endpoint object on found or RT_NULL on not found. - */ -uep_t rt_usbd_find_endpoint(udevice_t device, uclass_t* pcls, rt_uint8_t ep_addr) -{ - uep_t ep; - struct rt_list_node *i, *j, *k; - uclass_t cls; - uintf_t intf; - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - - /* search a endpoint in the current configuration */ - for (i=device->curr_cfg->cls_list.next; - i!=&device->curr_cfg->cls_list; i=i->next) - { - cls = (uclass_t)rt_list_entry(i, struct uclass, list); - for(j=cls->intf_list.next; j!=&cls->intf_list; j=j->next) - { - intf = (uintf_t)rt_list_entry(j, struct uinterface, list); - for(k=intf->curr_setting->ep_list.next; - k!=&intf->curr_setting->ep_list; k=k->next) - { - ep = (uep_t)rt_list_entry(k, struct uendpoint, list); - if(ep->ep_desc->bEndpointAddress == ep_addr) - { - if (pcls != RT_NULL) - *pcls = cls; - return ep; - } - } - } - } - - rt_kprintf("can't find endpoint 0x%x\n", ep_addr); - return RT_NULL; -} - -/** - * This function will add a configuration to an usb device. - * - * @param device the usb device object. - * @param cfg the configuration object. - * - * @return RT_EOK. - */ -rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg) -{ - struct rt_list_node *i, *j, *k; - uclass_t cls; - uintf_t intf; - uep_t ep; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_add_config\n")); - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(cfg != RT_NULL); - - /* set configuration number to the configuration descriptor */ - cfg->cfg_desc.bConfigurationValue = device->dev_desc.bNumConfigurations + 1; - device->dev_desc.bNumConfigurations++; - - for (i=cfg->cls_list.next; i!=&cfg->cls_list; i=i->next) - { - cls = (uclass_t)rt_list_entry(i, struct uclass, list); - - for(j=cls->intf_list.next; j!=&cls->intf_list; j=j->next) - { - 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) - { - ep = (uep_t)rt_list_entry(k, struct uendpoint, list); - dcd_ep_alloc(device->dcd, ep); - } - - /* 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; - } - } - - /* insert the configuration to the list */ - rt_list_insert_after(&device->cfg_list, &cfg->list); - - return RT_EOK; -} - -/** - * This function will add a class to a configuration. - * - * @param cfg the configuration object. - * @param cls the class object. - * - * @return RT_EOK. - */ -rt_err_t rt_usbd_config_add_class(uconfig_t cfg, uclass_t cls) -{ - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_add_class\n")); - - /* parameter check */ - RT_ASSERT(cfg != RT_NULL); - RT_ASSERT(cls != RT_NULL); - - /* insert the class to the list */ - rt_list_insert_after(&cfg->cls_list, &cls->list); - - return RT_EOK; -} - -/** - * This function will add an interface to a class. - * - * @param cls the class object. - * @param intf the interface object. - * - * @return RT_EOK. - */ -rt_err_t rt_usbd_class_add_interface(uclass_t cls, uintf_t intf) -{ - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_class_add_interface\n")); - - /* parameter check */ - RT_ASSERT(cls != RT_NULL); - RT_ASSERT(intf != RT_NULL); - - /* insert the interface to the list */ - rt_list_insert_after(&cls->intf_list, &intf->list); - - return RT_EOK; -} - -/** - * This function will add an alternate setting to an interface. - * - * @param intf the interface object. - * @param setting the alternate setting object. - * - * @return RT_EOK. - */ -rt_err_t rt_usbd_interface_add_altsetting(uintf_t intf, ualtsetting_t setting) -{ - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_interface_add_altsetting\n")); - - /* parameter check */ - RT_ASSERT(intf != RT_NULL); - RT_ASSERT(setting != RT_NULL); - - setting->intf_desc->bInterfaceNumber = intf->intf_num; - - /* insert the alternate setting to the list */ - rt_list_insert_after(&intf->setting_list, &setting->list); - - return RT_EOK; -} - -/** - * This function will add an endpoint to an alternate setting. - * - * @param setting the alternate setting object. - * @param ep the endpoint object. - * - * @return RT_EOK. - */ -rt_err_t rt_usbd_altsetting_add_endpoint(ualtsetting_t setting, uep_t ep) -{ - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_altsetting_add_endpoint\n")); - - /* parameter check */ - RT_ASSERT(setting != RT_NULL); - RT_ASSERT(ep != RT_NULL); - - /* insert the endpoint to the list */ - rt_list_insert_after(&setting->ep_list, &ep->list); - - return RT_EOK; -} - -/** - * This function will set an alternate setting for an interface. - * - * @param intf_desc the interface descriptor. - * @param value the alternate setting number. - * - * @return RT_EOK. - */ -rt_err_t rt_usbd_set_altsetting(uintf_t intf, rt_uint8_t value) -{ - ualtsetting_t setting; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_set_altsetting\n")); - - /* parameter check */ - RT_ASSERT(intf != RT_NULL); - RT_ASSERT(setting != RT_NULL); - - /* find an alternate setting */ - setting = rt_usbd_find_altsetting(intf, value); - - /* set as current alternate setting */ - intf->curr_setting = setting; - - return RT_EOK; -} - -/** - * This function will set a configuration for an usb device. - * - * @param device the usb device object. - * @param value the configuration number. - * - * @return RT_EOK. - */ -rt_err_t rt_usbd_set_config(udevice_t device, rt_uint8_t value) -{ - uconfig_t cfg; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_set_config\n")); - - /* parameter check */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(value <= device->dev_desc.bNumConfigurations); - - /* find a configuration */ - cfg = rt_usbd_find_config(device, value); - - /* set as current configuration */ - device->curr_cfg = cfg; - - return RT_TRUE; -} - -static struct rt_messagequeue *usb_mq; - -/** - * This function is the main entry of usb device thread, it is in charge of - * processing all messages received from the usb message buffer. - * - * @param parameter the parameter of the usb device thread. - * - * @return none. - */ -static void rt_usbd_thread_entry(void* parameter) -{ - while(1) - { - struct udev_msg msg; - udevice_t device; - uclass_t cls; - uep_t ep; - - /* receive message */ - if(rt_mq_recv(usb_mq, &msg, sizeof(struct udev_msg), RT_WAITING_FOREVER) - != RT_EOK ) continue; - - switch (msg.type) - { - case USB_MSG_SETUP_NOTIFY: - device = rt_usbd_find_device(msg.dcd); - if(device != RT_NULL) - _setup_request(device, (ureq_t)msg.content.setup_msg.packet); - else - rt_kprintf("invalid usb device\n"); - break; - case USB_MSG_DATA_NOTIFY: - ep = rt_usbd_find_endpoint(device, &cls, msg.content.ep_msg.ep_addr); - if(ep != RT_NULL) - ep->handler(device, cls, msg.content.ep_msg.size); - else - rt_kprintf("invalid endpoint\n"); - break; - case USB_MSG_SOF: - device = rt_usbd_find_device(msg.dcd); - if(device != RT_NULL) - _sof_notify(device); - else - rt_kprintf("invalid usb device\n"); - break; - default: - break; - } - } -} - -/** - * This function will post an message to usb message queue, - * - * @param msg the message to be posted - * @param size the size of the message . - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usbd_post_event(struct udev_msg* msg, rt_size_t size) -{ - RT_ASSERT(msg != RT_NULL); - - /* send message to usb message queue */ - return rt_mq_send(usb_mq, (void*)msg, size); -} - -/** - * This function will initialize usb device thread. - * - * @return none. - * - */ -rt_err_t rt_usbd_core_init(void) -{ - rt_thread_t thread; - - rt_list_init(&device_list); - - /* create an usb message queue */ - usb_mq = rt_mq_create("usbd", 32, 16, RT_IPC_FLAG_FIFO); - - /* create usb device thread */ - thread = rt_thread_create("usbd", rt_usbd_thread_entry, RT_NULL, - 2048, 8, 20); - if(thread != RT_NULL) - { - /* startup usb device thread */ - rt_thread_startup(thread); - } - - return RT_EOK; -} - +/* + * File : core.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2012, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2012-10-01 Yi Qiu first version + * 2012-12-12 heyuanjie87 change endpoint and class handler + * 2012-12-30 heyuanjie87 change inferface handler + */ + +#include +#include + +static rt_list_t device_list; + +/** + * This function will handle get_device_descriptor request. + * + * @param device the usb device object. + * @param setup the setup request. + * + * @return RT_EOK on successful. + */ +static rt_err_t _get_device_descriptor(struct udevice* device, ureq_t setup) +{ + rt_size_t size; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_device_descriptor\n")); + + /* device descriptor length should less than USB_DESC_LENGTH_DEVICE*/ + size = (setup->length > USB_DESC_LENGTH_DEVICE) ? + USB_DESC_LENGTH_DEVICE : setup->length; + + /* send device descriptor to endpoint 0 */ + dcd_ep_write(device->dcd, 0, (rt_uint8_t*)&device->dev_desc, + size); + + return RT_EOK; +} + +/** + * This function will handle get_config_descriptor request. + * + * @param device the usb device object. + * @param setup the setup request. + * + * @return RT_EOK on successful. + */ +static rt_err_t _get_config_descriptor(struct udevice* device, ureq_t setup) +{ + rt_size_t size; + ucfg_desc_t cfg_desc; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_config_descriptor\n")); + + cfg_desc = &device->curr_cfg->cfg_desc; + size = (setup->length > cfg_desc->wTotalLength) ? + cfg_desc->wTotalLength : setup->length; + + /* send configuration descriptor to endpoint 0 */ + dcd_ep_write(device->dcd, 0, (rt_uint8_t*)cfg_desc, size); + + return RT_EOK; +} + +/** + * This function will handle get_string_descriptor request. + * + * @param device the usb device object. + * @param setup the setup request. + * + * @return RT_EOK on successful, -RT_ERROR on invalid request. + */ +static rt_err_t _get_string_descriptor(struct udevice* device, ureq_t setup) +{ + struct ustring_descriptor str_desc; + rt_uint8_t index, i; + rt_uint32_t len; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_string_descriptor\n")); + + str_desc.type = USB_DESC_TYPE_STRING; + index = setup->value & 0xFF; + + if(index > USB_STRING_INTERFACE_INDEX) + { + rt_kprintf("unknown string index\n"); + dcd_ep_stall(device->dcd, 0); + return -RT_ERROR; + } + if(index == 0) + { + str_desc.bLength = 4; + str_desc.String[0] = 0x09; + str_desc.String[1] = 0x04; + } + else + { + len = rt_strlen(device->str[index]); + str_desc.bLength = len*2 + 2; + + for(i=0; istr[index][i]; + str_desc.String[i*2 + 1] = 0; + } + } + + if(setup->length == 0xFF) + len = str_desc.bLength; + else + len = setup->length; + + /* send string descriptor to endpoint 0 */ + dcd_ep_write(device->dcd, 0, (rt_uint8_t*)&str_desc, len); + + return RT_EOK; +} + +/** + * This function will handle get_descriptor request. + * + * @param device the usb device object. + * @param setup the setup request. + * + * @return RT_EOK on successful. + */ +static rt_err_t _get_descriptor(struct udevice* device, ureq_t setup) +{ + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + if(setup->request_type == USB_REQ_TYPE_DIR_IN) + { + switch(setup->value >> 8) + { + case USB_DESC_TYPE_DEVICE: + _get_device_descriptor(device, setup); + break; + case USB_DESC_TYPE_CONFIGURATION: + _get_config_descriptor(device, setup); + break; + case USB_DESC_TYPE_STRING: + _get_string_descriptor(device, setup); + break; + case USB_DESC_TYPE_DEVICEQUALIFIER: + dcd_ep_stall(device->dcd, 0); + break; + default: + rt_kprintf("unsupported descriptor request\n"); + dcd_ep_stall(device->dcd, 0); + break; + } + } + else + { + rt_kprintf("request direction error\n"); + dcd_ep_stall(device->dcd, 0); + } + + return RT_EOK; +} + +/** + * This function will handle get_interface request. + * + * @param device the usb device object. + * @param setup the setup request. + * + * @return RT_EOK on successful. + */ +static rt_err_t _get_interface(struct udevice* device, ureq_t setup) +{ + rt_uint8_t value; + uintf_t intf; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_interface\n")); + + /* find the specified interface and its alternate setting */ + intf = rt_usbd_find_interface(device, setup->index & 0xFF, RT_NULL); + value = intf->curr_setting->intf_desc->bAlternateSetting; + + /* send the interface alternate setting to endpoint 0*/ + dcd_ep_write(device->dcd, 0, &value, 1); + + return RT_EOK; +} + +/** + * This function will handle set_interface request. + * + * @param device the usb device object. + * @param setup the setup request. + * + * @return RT_EOK on successful. + */ +static rt_err_t _set_interface(struct udevice* device, ureq_t setup) +{ + uintf_t intf; + uep_t ep; + struct rt_list_node* i; + ualtsetting_t setting; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("_set_interface\n")); + + /* find the specified interface */ + intf = rt_usbd_find_interface(device, setup->index & 0xFF, RT_NULL); + + /* set alternate setting to the interface */ + rt_usbd_set_altsetting(intf, setup->value & 0xFF); + setting = intf->curr_setting; + + /* start all endpoints of the interface alternate setting */ + for(i=setting->ep_list.next; i != &setting->ep_list; i=i->next) + { + ep = (uep_t)rt_list_entry(i, struct uendpoint, list); + dcd_ep_stop(device->dcd, ep); + dcd_ep_run(device->dcd, ep); + } + + return RT_EOK; +} + +/** + * This function will handle get_config request. + * + * @param device the usb device object. + * @param setup the setup request. + * + * @return RT_EOK on successful. + */ +static rt_err_t _get_config(struct udevice* device, ureq_t setup) +{ + rt_uint8_t value; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + RT_ASSERT(device->curr_cfg != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_config\n")); + + /* get current configuration */ + value = device->curr_cfg->cfg_desc.bConfigurationValue; + + /* write the current configuration to endpoint 0 */ + dcd_ep_write(device->dcd, 0, &value, 1); + + return RT_EOK; +} + +/** + * This function will handle set_config request. + * + * @param device the usb device object. + * @param setup the setup request. + * + * @return RT_EOK on successful. + */ +static rt_err_t _set_config(struct udevice* device, ureq_t setup) +{ + struct rt_list_node *i, *j, *k; + uconfig_t cfg; + uintf_t intf; + ualtsetting_t setting; + uep_t ep; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("_set_config\n")); + + /* set current configuration */ + rt_usbd_set_config(device, setup->value); + cfg = device->curr_cfg; + + for (i=cfg->cls_list.next; i!=&cfg->cls_list; i=i->next) + { + /* run all classes and their endpoints in the configuration */ + uclass_t cls = (uclass_t)rt_list_entry(i, struct uclass, list); + for(j=cls->intf_list.next; j!=&cls->intf_list; j=j->next) + { + intf = (uintf_t)rt_list_entry(j, struct uinterface, list); + setting = intf->curr_setting; + for(k=setting->ep_list.next; k != &setting->ep_list; k=k->next) + { + ep = (uep_t)rt_list_entry(k, struct uendpoint, list); + + /* first stop then start endpoint */ + dcd_ep_stop(device->dcd, ep); + dcd_ep_run(device->dcd, ep); + } + } + /* after running all endpoints, then run class */ + if(cls->ops->run != RT_NULL) + cls->ops->run(device, cls); + } + + /* issue status stage */ + rt_device_control((rt_device_t)device->dcd, CONTROL_SEND_STATUS, RT_NULL); + + return RT_EOK; +} + +/** + * This function will handle set_address request. + * + * @param device the usb device object. + * @param setup the setup request. + * + * @return RT_EOK on successful. + */ +static rt_err_t _set_address(struct udevice* device, ureq_t setup) +{ + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("_set_address\n")); + + /* set address in device control driver */ + dcd_set_address(device->dcd, setup->value); + + /* issue status stage */ + rt_device_control((rt_device_t)device->dcd, CONTROL_SEND_STATUS, RT_NULL); + + return RT_EOK; +} + +/** + * This function will handle standard request. + * + * @param device the usb device object. + * @param setup the setup request. + * + * @return RT_EOK on successful. + */ +static rt_err_t _standard_request(struct udevice* device, ureq_t setup) +{ + udcd_t dcd; + rt_uint16_t value = 0; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + dcd = device->dcd; + + switch(setup->request_type & USB_REQ_TYPE_RECIPIENT_MASK) + { + case USB_REQ_TYPE_DEVICE: + switch(setup->request) + { + case USB_REQ_GET_STATUS: + dcd_ep_write(device->dcd, 0, &value, 2); + break; + case USB_REQ_CLEAR_FEATURE: + dcd_clear_feature(dcd, setup->value); + break; + case USB_REQ_SET_FEATURE: + dcd_set_feature(dcd, setup->value); + break; + case USB_REQ_SET_ADDRESS: + _set_address(device, setup); + break; + case USB_REQ_GET_DESCRIPTOR: + _get_descriptor(device, setup); + break; + case USB_REQ_SET_DESCRIPTOR: + dcd_ep_stall(dcd, 0); + break; + case USB_REQ_GET_CONFIGURATION: + _get_config(device, setup); + break; + case USB_REQ_SET_CONFIGURATION: + _set_config(device, setup); + break; + default: + rt_kprintf("unknown device request\n"); + dcd_ep_stall(device->dcd, 0); + break; + } + break; + case USB_REQ_TYPE_INTERFACE: + switch(setup->request) + { + case USB_REQ_GET_INTERFACE: + _get_interface(device, setup); + break; + case USB_REQ_SET_INTERFACE: + _set_interface(device, setup); + break; + default: + rt_kprintf("unknown interface request\n"); + dcd_ep_stall(device->dcd, 0); + break; + } + break; + case USB_REQ_TYPE_ENDPOINT: + switch(setup->request) + { + case USB_REQ_GET_STATUS: + /* TODO */ + dcd_ep_write(dcd, 0, &value, 2); + break; + case USB_REQ_CLEAR_FEATURE: + dcd_clear_feature(dcd, setup->value); + break; + case USB_REQ_SET_FEATURE: + dcd_set_feature(dcd, setup->value); + break; + case USB_REQ_SYNCH_FRAME: + break; + default: + rt_kprintf("unknown endpoint request\n"); + dcd_ep_stall(device->dcd, 0); + break; + } + break; + case USB_REQ_TYPE_OTHER: + rt_kprintf("unknown other type request\n"); + dcd_ep_stall(device->dcd, 0); + break; + default: + rt_kprintf("unknown type request\n"); + dcd_ep_stall(device->dcd, 0); + break; + } + + return RT_EOK; +} + +/** + * This function will handle class request. + * + * @param device the usb device object. + * @param setup the setup request. + * + * @return RT_EOK on successful, -RT_ERROR on invalid request. + */ +static rt_err_t _class_request(udevice_t device, ureq_t setup) +{ + uintf_t intf; + uclass_t cls; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + /* verify request value */ + if(setup->index > device->curr_cfg->cfg_desc.bNumInterfaces) + { + dcd_ep_stall(device->dcd, 0); + return -RT_ERROR; + } + + switch(setup->request_type & USB_REQ_TYPE_RECIPIENT_MASK) + { + case USB_REQ_TYPE_INTERFACE: + intf = rt_usbd_find_interface(device, setup->index & 0xFF, &cls); + intf->handler(device, cls, setup); + break; + case USB_REQ_TYPE_ENDPOINT: + break; + default: + rt_kprintf("unknown class request type\n"); + dcd_ep_stall(device->dcd, 0); + break; + } + + return RT_EOK; +} + +/** + * This function will handle setup request. + * + * @param device the usb device object. + * @param setup the setup request. + * + * @return RT_EOK on successful, -RT_ERROR on invalid request. + */ +static rt_err_t _setup_request(udevice_t device, ureq_t setup) +{ + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("[\n")); + RT_DEBUG_LOG(RT_DEBUG_USB, ("setup_request_handler 0x%x\n", + setup->request_type)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("value 0x%x\n", setup->value)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("length 0x%x\n", setup->length)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("index 0x%x\n", setup->index)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("request 0x%x\n", setup->request)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("]\n")); + + switch((setup->request_type & USB_REQ_TYPE_MASK)) + { + case USB_REQ_TYPE_STANDARD: + _standard_request(device, setup); + break; + case USB_REQ_TYPE_CLASS: + _class_request(device, setup); + break; + case USB_REQ_TYPE_VENDOR: + rt_kprintf("vendor type request\n"); + break; + default: + rt_kprintf("unknown setup request type\n"); + dcd_ep_stall(device->dcd, 0); + return -RT_ERROR; + } + + return RT_EOK; +} + +/** + * This function will notity sof event to all of class. + * + * @param device the usb device object. + * + * @return RT_EOK. + */ +rt_err_t _sof_notify(udevice_t device) +{ + struct rt_list_node *i; + uclass_t cls; + + RT_ASSERT(device != RT_NULL); + + /* to notity every class that sof event comes */ + for (i=device->curr_cfg->cls_list.next; + i!=&device->curr_cfg->cls_list; i=i->next) + { + cls = (uclass_t)rt_list_entry(i, struct uclass, list); + if(cls->ops->sof_handler != RT_NULL) + cls->ops->sof_handler(device, cls); + } + + return RT_EOK; +} + +/** + * This function will create an usb device object. + * + * @param ustring the usb string array to contain string descriptor. + * + * @return an usb device object on success, RT_NULL on fail. + */ +udevice_t rt_usbd_device_create(const char** ustring) +{ + udevice_t udevice; + + /* parameter check */ + RT_ASSERT(ustring != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_create\n")); + + /* allocate memory for the object */ + udevice = rt_malloc(sizeof(struct udevice)); + if(udevice == RT_NULL) + { + rt_kprintf("alloc memery failed\n"); + return RT_NULL; + } + rt_memset(udevice, 0, sizeof(struct udevice)); + + /* set string descriptor array to the device object */ + udevice->str = ustring; + + /* to initialize configuration list */ + rt_list_init(&udevice->cfg_list); + + /* insert the device object to device list */ + rt_list_insert_after(&device_list, &udevice->list); + + return udevice; +} + +/** + * This function will set an usb controller driver to a device. + * + * @param device the usb device object. + * @param dcd the usb device controller driver. + * + * @return RT_EOK on successful. + */ +rt_err_t rt_usbd_device_set_controller(udevice_t device, udcd_t dcd) +{ + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(dcd != RT_NULL); + + /* set usb device controller driver to the device */ + device->dcd = dcd; + + return RT_EOK; +} + +/** + * This function will set an usb device descriptor to a device. + * + * @param device the usb device object. + * @param dev_desc the usb device descriptor. + * + * @return RT_EOK on successful. + */ +rt_err_t rt_usbd_device_set_descriptor(udevice_t device, udev_desc_t dev_desc) +{ + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(dev_desc != RT_NULL); + + /* copy the usb device descriptor to the device */ + rt_memcpy((void *)&device->dev_desc, (void *)dev_desc, USB_DESC_LENGTH_DEVICE); + + return RT_EOK; +} + +/** + * This function will create an usb configuration object. + * + * @param none. + * + * @return an usb configuration object. + */ +uconfig_t rt_usbd_config_create(void) +{ + uconfig_t cfg; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_create\n")); + + /* allocate memory for the object */ + cfg = rt_malloc(sizeof(struct uconfig)); + if(cfg == RT_NULL) + { + rt_kprintf("alloc memery failed\n"); + return RT_NULL; + } + rt_memset(cfg, 0, sizeof(struct uconfig)); + + /* set default value */ + cfg->cfg_desc.bLength = USB_DESC_LENGTH_CONFIG; + cfg->cfg_desc.type = USB_DESC_TYPE_CONFIGURATION; + cfg->cfg_desc.wTotalLength = USB_DESC_LENGTH_CONFIG; + cfg->cfg_desc.bmAttributes = 0xC0; + cfg->cfg_desc.MaxPower = 0x32; + + /* to initialize class object list */ + rt_list_init(&cfg->cls_list); + + return cfg; +} + +/** + * This function will create an usb interface object. + * + * @param device the usb device object. + * @handler the callback handler of object + * + * @return an usb interface object on success, RT_NULL on fail. + */ +uintf_t rt_usbd_interface_create(udevice_t device, uintf_handler_t handler) +{ + uintf_t intf; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_interface_create\n")); + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + + /* allocate memory for the object */ + intf = (uintf_t)rt_malloc(sizeof(struct uinterface)); + if(intf == RT_NULL) + { + rt_kprintf("alloc memery failed\n"); + return RT_NULL; + } + intf->intf_num = device->nr_intf; + device->nr_intf++; + intf->handler = handler; + intf->curr_setting = RT_NULL; + + /* to initialize the alternate setting object list */ + rt_list_init(&intf->setting_list); + + return intf; +} + +/** + * This function will create an usb alternate setting object. + * + * @param intf_desc the interface descriptor. + * @desc_size the size of the interface descriptor. + * + * @return an usb alternate setting object on success, RT_NULL on fail. + */ +ualtsetting_t rt_usbd_altsetting_create(rt_size_t desc_size) +{ + ualtsetting_t setting; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_altsetting_create\n")); + + /* parameter check */ + RT_ASSERT(desc_size > 0); + + /* allocate memory for the object */ + setting = (ualtsetting_t)rt_malloc(sizeof(struct ualtsetting)); + if(setting == RT_NULL) + { + rt_kprintf("alloc memery failed\n"); + return RT_NULL; + } + /* allocate memory for the desc */ + setting->desc = rt_malloc(desc_size); + if (setting->desc == RT_NULL) + { + rt_kprintf("alloc desc memery failed\n"); + rt_free(setting); + return RT_NULL; + } + + setting->desc_size = desc_size; + setting->intf_desc = RT_NULL; + + /* to initialize endpoint list */ + rt_list_init(&setting->ep_list); + + return setting; +} + +/** + * This function will config an desc in alternate setting object. + * + * @param setting the altsetting to be config. + * @param desc use it to init desc in setting. + * @param intf_pos the offset of interface descriptor in desc. + * + * @return RT_EOK. + */ +rt_err_t rt_usbd_altsetting_config_descriptor(ualtsetting_t setting, const void* desc, rt_off_t intf_pos) +{ + RT_ASSERT(setting != RT_NULL); + RT_ASSERT(setting->desc !=RT_NULL); + + rt_memcpy(setting->desc, desc, setting->desc_size); + setting->intf_desc = (uintf_desc_t)((char*)setting->desc + intf_pos); + + return RT_EOK; +} + +/** + * This function will create an usb class object. + * + * @param device the usb device object. + * @param dev_desc the device descriptor. + * @param ops the operation set. + * + * @return an usb class object on success, RT_NULL on fail. + */ +uclass_t rt_usbd_class_create(udevice_t device, udev_desc_t dev_desc, + uclass_ops_t ops) +{ + uclass_t cls; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_class_create\n")); + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(dev_desc != RT_NULL); + + /* allocate memory for the object */ + cls = (uclass_t)rt_malloc(sizeof(struct uclass)); + if(cls == RT_NULL) + { + rt_kprintf("alloc memery failed\n"); + return RT_NULL; + } + cls->dev_desc = dev_desc; + cls->ops = ops; + cls->device = device; + + /* to initialize interface list */ + rt_list_init(&cls->intf_list); + + return cls; +} + +/** + * This function will create an usb endpoint object. + * + * @param ep_desc the endpoint descriptor. + * @handler the callback handler of object + * + * @return an usb endpoint object on success, RT_NULL on fail. + */ +uep_t rt_usbd_endpoint_create(uep_desc_t ep_desc, udep_handler_t handler) +{ + uep_t ep; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_endpoint_create\n")); + + /* parameter check */ + RT_ASSERT(ep_desc != RT_NULL); + + /* allocate memory for the object */ + ep = (uep_t)rt_malloc(sizeof(struct uendpoint)); + if(ep == RT_NULL) + { + rt_kprintf("alloc memery failed\n"); + return RT_NULL; + } + ep->ep_desc = ep_desc; + ep->handler = handler; + ep->buffer = RT_NULL; + + return ep; +} + +/** + * This function will find an usb device object. + * + * @dcd usd device controller driver. + * + * @return an usb device object on found or RT_NULL on not found. + */ +udevice_t rt_usbd_find_device(udcd_t dcd) +{ + struct rt_list_node* node; + udevice_t device; + + /* parameter check */ + RT_ASSERT(dcd != RT_NULL); + + /* search a device in the the device list */ + for (node = device_list.next; node != &device_list; node = node->next) + { + device = (udevice_t)rt_list_entry(node, struct udevice, list); + if(device->dcd == dcd) return device; + } + + rt_kprintf("can't find device\n"); + return RT_NULL; +} + +/** + * This function will find an usb configuration object. + * + * @param device the usb device object. + * @param value the configuration number. + * + * @return an usb configuration object on found or RT_NULL on not found. + */ +uconfig_t rt_usbd_find_config(udevice_t device, rt_uint8_t value) +{ + struct rt_list_node* node; + uconfig_t cfg = RT_NULL; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_config\n")); + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(value <= device->dev_desc.bNumConfigurations); + + /* search a configration in the the device */ + for (node = device->cfg_list.next; node != &device->cfg_list; node = node->next) + { + cfg = (uconfig_t)rt_list_entry(node, struct udevice, list); + if(cfg->cfg_desc.bConfigurationValue == value) return cfg; + } + + rt_kprintf("can't find configuration %d\n", value); + return RT_NULL; +} + +/** + * This function will find an usb interface object. + * + * @param device the usb device object. + * @param value the interface number. + * + * @return an usb configuration object on found or RT_NULL on not found. + */ +uintf_t rt_usbd_find_interface(udevice_t device, rt_uint8_t value, uclass_t *pcls) +{ + struct rt_list_node *i, *j; + uclass_t cls; + uintf_t intf; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_interface\n")); + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(value < device->nr_intf); + + /* search an interface in the current configuration */ + for (i=device->curr_cfg->cls_list.next; + i!=&device->curr_cfg->cls_list; i=i->next) + { + cls = (uclass_t)rt_list_entry(i, struct uclass, list); + for(j=cls->intf_list.next; j!=&cls->intf_list; j=j->next) + { + intf = (uintf_t)rt_list_entry(j, struct uinterface, list); + if(intf->intf_num == value) + { + if (pcls != RT_NULL) + *pcls = cls; + return intf; + } + } + } + + rt_kprintf("can't find interface %d\n", value); + return RT_NULL; +} + +/** + * This function will find an usb interface alternate setting object. + * + * @param device the usb device object. + * @param value the alternate setting number. + * + * @return an usb interface alternate setting object on found or RT_NULL on not found. + */ +ualtsetting_t rt_usbd_find_altsetting(uintf_t intf, rt_uint8_t value) +{ + struct rt_list_node *i; + ualtsetting_t setting; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_altsetting\n")); + + /* parameter check */ + RT_ASSERT(intf != RT_NULL); + + if(intf->curr_setting != RT_NULL) + { + /* if the value equal to the current alternate setting, then do not search */ + if(intf->curr_setting->intf_desc->bAlternateSetting == value) + return intf->curr_setting; + } + + /* search a setting in the alternate setting list */ + for(i=intf->setting_list.next; i!=&intf->setting_list; i=i->next) + { + setting =(ualtsetting_t)rt_list_entry(i, struct ualtsetting, list); + if(setting->intf_desc->bAlternateSetting == value) + return setting; + } + + rt_kprintf("can't find alternate setting %d\n", value); + return RT_NULL; +} + +/** + * This function will find an usb endpoint object. + * + * @param device the usb device object. + * @param ep_addr endpoint address. + * + * @return an usb endpoint object on found or RT_NULL on not found. + */ +uep_t rt_usbd_find_endpoint(udevice_t device, uclass_t* pcls, rt_uint8_t ep_addr) +{ + uep_t ep; + struct rt_list_node *i, *j, *k; + uclass_t cls; + uintf_t intf; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + + /* search a endpoint in the current configuration */ + for (i=device->curr_cfg->cls_list.next; + i!=&device->curr_cfg->cls_list; i=i->next) + { + cls = (uclass_t)rt_list_entry(i, struct uclass, list); + for(j=cls->intf_list.next; j!=&cls->intf_list; j=j->next) + { + intf = (uintf_t)rt_list_entry(j, struct uinterface, list); + for(k=intf->curr_setting->ep_list.next; + k!=&intf->curr_setting->ep_list; k=k->next) + { + ep = (uep_t)rt_list_entry(k, struct uendpoint, list); + if(ep->ep_desc->bEndpointAddress == ep_addr) + { + if (pcls != RT_NULL) + *pcls = cls; + return ep; + } + } + } + } + + rt_kprintf("can't find endpoint 0x%x\n", ep_addr); + return RT_NULL; +} + +/** + * This function will add a configuration to an usb device. + * + * @param device the usb device object. + * @param cfg the configuration object. + * + * @return RT_EOK. + */ +rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg) +{ + struct rt_list_node *i, *j, *k; + uclass_t cls; + uintf_t intf; + uep_t ep; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_add_config\n")); + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(cfg != RT_NULL); + + /* set configuration number to the configuration descriptor */ + cfg->cfg_desc.bConfigurationValue = device->dev_desc.bNumConfigurations + 1; + device->dev_desc.bNumConfigurations++; + + for (i=cfg->cls_list.next; i!=&cfg->cls_list; i=i->next) + { + cls = (uclass_t)rt_list_entry(i, struct uclass, list); + + for(j=cls->intf_list.next; j!=&cls->intf_list; j=j->next) + { + 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) + { + ep = (uep_t)rt_list_entry(k, struct uendpoint, list); + dcd_ep_alloc(device->dcd, ep); + } + + /* 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; + } + } + + /* insert the configuration to the list */ + rt_list_insert_after(&device->cfg_list, &cfg->list); + + return RT_EOK; +} + +/** + * This function will add a class to a configuration. + * + * @param cfg the configuration object. + * @param cls the class object. + * + * @return RT_EOK. + */ +rt_err_t rt_usbd_config_add_class(uconfig_t cfg, uclass_t cls) +{ + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_add_class\n")); + + /* parameter check */ + RT_ASSERT(cfg != RT_NULL); + RT_ASSERT(cls != RT_NULL); + + /* insert the class to the list */ + rt_list_insert_after(&cfg->cls_list, &cls->list); + + return RT_EOK; +} + +/** + * This function will add an interface to a class. + * + * @param cls the class object. + * @param intf the interface object. + * + * @return RT_EOK. + */ +rt_err_t rt_usbd_class_add_interface(uclass_t cls, uintf_t intf) +{ + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_class_add_interface\n")); + + /* parameter check */ + RT_ASSERT(cls != RT_NULL); + RT_ASSERT(intf != RT_NULL); + + /* insert the interface to the list */ + rt_list_insert_after(&cls->intf_list, &intf->list); + + return RT_EOK; +} + +/** + * This function will add an alternate setting to an interface. + * + * @param intf the interface object. + * @param setting the alternate setting object. + * + * @return RT_EOK. + */ +rt_err_t rt_usbd_interface_add_altsetting(uintf_t intf, ualtsetting_t setting) +{ + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_interface_add_altsetting\n")); + + /* parameter check */ + RT_ASSERT(intf != RT_NULL); + RT_ASSERT(setting != RT_NULL); + + setting->intf_desc->bInterfaceNumber = intf->intf_num; + + /* insert the alternate setting to the list */ + rt_list_insert_after(&intf->setting_list, &setting->list); + + return RT_EOK; +} + +/** + * This function will add an endpoint to an alternate setting. + * + * @param setting the alternate setting object. + * @param ep the endpoint object. + * + * @return RT_EOK. + */ +rt_err_t rt_usbd_altsetting_add_endpoint(ualtsetting_t setting, uep_t ep) +{ + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_altsetting_add_endpoint\n")); + + /* parameter check */ + RT_ASSERT(setting != RT_NULL); + RT_ASSERT(ep != RT_NULL); + + /* insert the endpoint to the list */ + rt_list_insert_after(&setting->ep_list, &ep->list); + + return RT_EOK; +} + +/** + * This function will set an alternate setting for an interface. + * + * @param intf_desc the interface descriptor. + * @param value the alternate setting number. + * + * @return RT_EOK. + */ +rt_err_t rt_usbd_set_altsetting(uintf_t intf, rt_uint8_t value) +{ + ualtsetting_t setting; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_set_altsetting\n")); + + /* parameter check */ + RT_ASSERT(intf != RT_NULL); + RT_ASSERT(setting != RT_NULL); + + /* find an alternate setting */ + setting = rt_usbd_find_altsetting(intf, value); + + /* set as current alternate setting */ + intf->curr_setting = setting; + + return RT_EOK; +} + +/** + * This function will set a configuration for an usb device. + * + * @param device the usb device object. + * @param value the configuration number. + * + * @return RT_EOK. + */ +rt_err_t rt_usbd_set_config(udevice_t device, rt_uint8_t value) +{ + uconfig_t cfg; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_set_config\n")); + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(value <= device->dev_desc.bNumConfigurations); + + /* find a configuration */ + cfg = rt_usbd_find_config(device, value); + + /* set as current configuration */ + device->curr_cfg = cfg; + + return RT_TRUE; +} + +static struct rt_messagequeue *usb_mq; + +/** + * This function is the main entry of usb device thread, it is in charge of + * processing all messages received from the usb message buffer. + * + * @param parameter the parameter of the usb device thread. + * + * @return none. + */ +static void rt_usbd_thread_entry(void* parameter) +{ + while(1) + { + struct udev_msg msg; + udevice_t device; + uclass_t cls; + uep_t ep; + + /* receive message */ + if(rt_mq_recv(usb_mq, &msg, sizeof(struct udev_msg), RT_WAITING_FOREVER) + != RT_EOK ) continue; + + switch (msg.type) + { + case USB_MSG_SETUP_NOTIFY: + device = rt_usbd_find_device(msg.dcd); + if(device != RT_NULL) + _setup_request(device, (ureq_t)msg.content.setup_msg.packet); + else + rt_kprintf("invalid usb device\n"); + break; + case USB_MSG_DATA_NOTIFY: + ep = rt_usbd_find_endpoint(device, &cls, msg.content.ep_msg.ep_addr); + if(ep != RT_NULL) + ep->handler(device, cls, msg.content.ep_msg.size); + else + rt_kprintf("invalid endpoint\n"); + break; + case USB_MSG_SOF: + device = rt_usbd_find_device(msg.dcd); + if(device != RT_NULL) + _sof_notify(device); + else + rt_kprintf("invalid usb device\n"); + break; + default: + break; + } + } +} + +/** + * This function will post an message to usb message queue, + * + * @param msg the message to be posted + * @param size the size of the message . + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usbd_post_event(struct udev_msg* msg, rt_size_t size) +{ + RT_ASSERT(msg != RT_NULL); + + /* send message to usb message queue */ + return rt_mq_send(usb_mq, (void*)msg, size); +} + +/** + * This function will initialize usb device thread. + * + * @return none. + * + */ +rt_err_t rt_usbd_core_init(void) +{ + rt_thread_t thread; + + rt_list_init(&device_list); + + /* create an usb message queue */ + usb_mq = rt_mq_create("usbd", 32, 16, RT_IPC_FLAG_FIFO); + + /* create usb device thread */ + thread = rt_thread_create("usbd", rt_usbd_thread_entry, RT_NULL, + 2048, 8, 20); + if(thread != RT_NULL) + { + /* startup usb device thread */ + rt_thread_startup(thread); + } + + return RT_EOK; +} + diff --git a/components/drivers/usb/usbdevice/core/usbdevice.c b/components/drivers/usb/usbdevice/core/usbdevice.c index 42e8664738..328fd6c686 100644 --- a/components/drivers/usb/usbdevice/core/usbdevice.c +++ b/components/drivers/usb/usbdevice/core/usbdevice.c @@ -1,117 +1,117 @@ -/* - * File : usbdevice.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2012, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2012-10-02 Yi Qiu first version - */ - -#include -#include -#include - -const static char* ustring[] = -{ - "Language", - "RT-Thread Team.", - "RT-Thread Device", - "1.1.0", - "Configuration", - "Interface", -}; - -#ifdef RT_USB_DEVICE_COMPOSITE -static struct udevice_descriptor compsit_desc = -{ - USB_DESC_LENGTH_DEVICE, //bLength; - USB_DESC_TYPE_DEVICE, //type; - USB_BCD_VERSION, //bcdUSB; - USB_CLASS_MISC, //bDeviceClass; - 0x02, //bDeviceSubClass; - 0x01, //bDeviceProtocol; - 0x40, //bMaxPacketSize0; - USB_VENDOR_ID, //idVendor; - 0xbacf, //idProduct; - USB_BCD_DEVICE, //bcdDevice; - USB_STRING_MANU_INDEX, //iManufacturer; - USB_STRING_PRODUCT_INDEX, //iProduct; - USB_STRING_SERIAL_INDEX, //iSerialNumber; - USB_DYNAMIC, //bNumConfigurations; -}; -#endif - -rt_err_t rt_usb_device_init(const char* udc_name) -{ - rt_device_t udc; - udevice_t udevice; - uconfig_t cfg; - uclass_t cls; - - RT_ASSERT(udc_name != RT_NULL); - - udc = rt_device_find(udc_name); - if(udc == RT_NULL) - { - rt_kprintf("can't find usb device controller %s\n", udc_name); - return -RT_ERROR; - } - - /* create and startup usb device thread */ - rt_usbd_core_init(); - - /* create a device object */ - udevice = rt_usbd_device_create(ustring); - - /* set usb controller driver to the device */ - rt_usbd_device_set_controller(udevice, (udcd_t)udc); - - /* create a configuration object */ - cfg = rt_usbd_config_create(); - -#ifdef RT_USB_DEVICE_MSTORAGE - /* create a mass storage class object */ - cls = rt_usbd_class_mstorage_create(udevice); - - /* add the class to the configuration */ - rt_usbd_config_add_class(cfg, cls); -#endif -#ifdef RT_USB_DEVICE_CDC - /* create a cdc class object */ - cls = rt_usbd_class_cdc_create(udevice); - - /* add the class to the configuration */ - rt_usbd_config_add_class(cfg, cls); -#endif -#ifdef RT_USB_DEVICE_RNDIS - /* create a rndis class object */ - cls = rt_usbd_class_rndis_create(udevice); - - /* add the class to the configuration */ - rt_usbd_config_add_class(cfg, cls); -#endif - - /* set device descriptor to the device */ -#ifdef RT_USB_DEVICE_COMPOSITE - rt_usbd_device_set_descriptor(udevice, &compsit_desc); -#else - rt_usbd_device_set_descriptor(udevice, cls->dev_desc); -#endif - - /* add the configuration to the device */ - rt_usbd_device_add_config(udevice, cfg); - - /* set default configuration to 1 */ - rt_usbd_set_config(udevice, 1); - - /* initialize usb device controller */ - rt_device_init(udc); - - return RT_EOK; -} - +/* + * File : usbdevice.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2012, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2012-10-02 Yi Qiu first version + */ + +#include +#include +#include + +const static char* ustring[] = +{ + "Language", + "RT-Thread Team.", + "RT-Thread Device", + "1.1.0", + "Configuration", + "Interface", +}; + +#ifdef RT_USB_DEVICE_COMPOSITE +static struct udevice_descriptor compsit_desc = +{ + USB_DESC_LENGTH_DEVICE, //bLength; + USB_DESC_TYPE_DEVICE, //type; + USB_BCD_VERSION, //bcdUSB; + USB_CLASS_MISC, //bDeviceClass; + 0x02, //bDeviceSubClass; + 0x01, //bDeviceProtocol; + 0x40, //bMaxPacketSize0; + USB_VENDOR_ID, //idVendor; + 0xbacf, //idProduct; + USB_BCD_DEVICE, //bcdDevice; + USB_STRING_MANU_INDEX, //iManufacturer; + USB_STRING_PRODUCT_INDEX, //iProduct; + USB_STRING_SERIAL_INDEX, //iSerialNumber; + USB_DYNAMIC, //bNumConfigurations; +}; +#endif + +rt_err_t rt_usb_device_init(const char* udc_name) +{ + rt_device_t udc; + udevice_t udevice; + uconfig_t cfg; + uclass_t cls; + + RT_ASSERT(udc_name != RT_NULL); + + udc = rt_device_find(udc_name); + if(udc == RT_NULL) + { + rt_kprintf("can't find usb device controller %s\n", udc_name); + return -RT_ERROR; + } + + /* create and startup usb device thread */ + rt_usbd_core_init(); + + /* create a device object */ + udevice = rt_usbd_device_create(ustring); + + /* set usb controller driver to the device */ + rt_usbd_device_set_controller(udevice, (udcd_t)udc); + + /* create a configuration object */ + cfg = rt_usbd_config_create(); + +#ifdef RT_USB_DEVICE_MSTORAGE + /* create a mass storage class object */ + cls = rt_usbd_class_mstorage_create(udevice); + + /* add the class to the configuration */ + rt_usbd_config_add_class(cfg, cls); +#endif +#ifdef RT_USB_DEVICE_CDC + /* create a cdc class object */ + cls = rt_usbd_class_cdc_create(udevice); + + /* add the class to the configuration */ + rt_usbd_config_add_class(cfg, cls); +#endif +#ifdef RT_USB_DEVICE_RNDIS + /* create a rndis class object */ + cls = rt_usbd_class_rndis_create(udevice); + + /* add the class to the configuration */ + rt_usbd_config_add_class(cfg, cls); +#endif + + /* set device descriptor to the device */ +#ifdef RT_USB_DEVICE_COMPOSITE + rt_usbd_device_set_descriptor(udevice, &compsit_desc); +#else + rt_usbd_device_set_descriptor(udevice, cls->dev_desc); +#endif + + /* add the configuration to the device */ + rt_usbd_device_add_config(udevice, cfg); + + /* set default configuration to 1 */ + rt_usbd_set_config(udevice, 1); + + /* initialize usb device controller */ + rt_device_init(udc); + + return RT_EOK; +} + diff --git a/components/drivers/usb/usbhost/SConscript b/components/drivers/usb/usbhost/SConscript index 8da2dc4fb9..02e09f75df 100644 --- a/components/drivers/usb/usbhost/SConscript +++ b/components/drivers/usb/usbhost/SConscript @@ -1,34 +1,34 @@ -Import('RTT_ROOT') -from building import * - -cwd = GetCurrentDir() -src = Split(""" -core/core.c -core/driver.c -core/usbhost.c -core/hub.c -""") - -if GetDepend('RT_USB_CLASS_ADK'): - src += Glob('class/adk.c') - src += Glob('udev/adkapp.c') - -if GetDepend('RT_USB_CLASS_MASS_STORAGE'): - src += Glob('class/mass.c') - src += Glob('udev/udisk.c') - -if GetDepend('RT_USB_CLASS_HID'): - src += Glob('class/hid.c') - -if GetDepend('RT_USB_HID_MOUSE'): - src += Glob('udev/umouse.c') - -if GetDepend('RT_USB_HID_KEYBOARD'): - src += Glob('udev/ukbd.c') - -CPPPATH = [cwd, cwd + '/class', cwd + '/core', \ - cwd + '/include', cwd + '../../../include'] - -group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_USB_HOST'], CPPPATH = CPPPATH) - -Return('group') +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +src = Split(""" +core/core.c +core/driver.c +core/usbhost.c +core/hub.c +""") + +if GetDepend('RT_USB_CLASS_ADK'): + src += Glob('class/adk.c') + src += Glob('udev/adkapp.c') + +if GetDepend('RT_USB_CLASS_MASS_STORAGE'): + src += Glob('class/mass.c') + src += Glob('udev/udisk.c') + +if GetDepend('RT_USB_CLASS_HID'): + src += Glob('class/hid.c') + +if GetDepend('RT_USB_HID_MOUSE'): + src += Glob('udev/umouse.c') + +if GetDepend('RT_USB_HID_KEYBOARD'): + src += Glob('udev/ukbd.c') + +CPPPATH = [cwd, cwd + '/class', cwd + '/core', \ + cwd + '/include', cwd + '../../../include'] + +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_USB_HOST'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/usb/usbhost/class/adk.c b/components/drivers/usb/usbhost/class/adk.c index 0f1d409793..ff9bef92dd 100644 --- a/components/drivers/usb/usbhost/class/adk.c +++ b/components/drivers/usb/usbhost/class/adk.c @@ -1,407 +1,407 @@ -/* - * File : adk.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2011, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2011-12-12 Yi Qiu first version - */ - -#include -#include -#include "adk.h" - -#ifdef RT_USB_CLASS_ADK - -static struct uclass_driver adk_driver; -static const char* _adk_manufacturer = RT_NULL; -static const char* _adk_model = RT_NULL; -static const char* _adk_description = RT_NULL; -static const char* _adk_version = RT_NULL; -static const char* _adk_uri = RT_NULL; -static const char* _adk_serial = RT_NULL; - -rt_err_t rt_usb_adk_set_string(const char* manufacturer, const char* model, - const char* description, const char* _version, const char* uri, - const char* serial) -{ - _adk_manufacturer = manufacturer; - _adk_model = model; - _adk_description = description; - _adk_version = _version; - _adk_uri = uri; - _adk_serial = serial; - - return RT_EOK; -} - -#ifdef RT_USING_MODULE -#include - -RTM_EXPORT(rt_usb_adk_set_string); -#endif - -/** - * This function will do USB_REQ_GET_PROTOCOL request to set idle period to the usb adk device - * - * @param ifinst the interface instance. - * @duration the idle period of requesting data. - * @report_id the report id - * - * @return the error code, RT_EOK on successfully. -*/ -static rt_err_t rt_usb_adk_get_protocol(uifinst_t ifinst, rt_uint16_t *protocol) -{ - struct ureqest setup; - uinst_t uinst; - int timeout = 100; - - /* parameter check */ - RT_ASSERT(ifinst != RT_NULL); - RT_ASSERT(ifinst->uinst != RT_NULL); - - uinst = ifinst->uinst; - - setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_VENDOR | - USB_REQ_TYPE_DEVICE; - setup.request = USB_REQ_GET_PROTOCOL; - setup.index = 0; - setup.length = 2; - setup.value = 0; - - if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, (void*)protocol, 2, - timeout) == 0) return RT_EOK; - else return -RT_FALSE; -} - -/** - * This function will do USB_REQ_SEND_STRING request to set idle period to the usb adk device - * - * @param ifinst the interface instance. - * @duration the idle period of requesting data. - * @report_id the report id - * - * @return the error code, RT_EOK on successfully. -*/ -static rt_err_t rt_usb_adk_send_string(uifinst_t ifinst, rt_uint16_t index, - const char* str) -{ - struct ureqest setup; - uinst_t uinst; - int timeout = 100; - - /* parameter check */ - RT_ASSERT(ifinst != RT_NULL); - RT_ASSERT(ifinst->uinst != RT_NULL); - - uinst = ifinst->uinst; - - setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_VENDOR | - USB_REQ_TYPE_DEVICE; - setup.request = USB_REQ_SEND_STRING; - setup.index = index; - setup.length = rt_strlen(str) + 1; - setup.value = 0; - - if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, (void*)str, - rt_strlen(str) + 1, timeout) == 0) return RT_EOK; - else return -RT_FALSE; -} - -/** - * This function will do USB_REQ_START request to set idle period to the usb adk device - * - * @param ifinst the interface instance. - * @duration the idle period of requesting data. - * @report_id the report id - * - * @return the error code, RT_EOK on successfully. -*/ -static rt_err_t rt_usb_adk_start(uifinst_t ifinst) -{ - struct ureqest setup; - uinst_t uinst; - int timeout = 100; - - /* parameter check */ - RT_ASSERT(ifinst != RT_NULL); - RT_ASSERT(ifinst->uinst != RT_NULL); - - uinst = ifinst->uinst; - - setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_VENDOR | - USB_REQ_TYPE_DEVICE; - setup.request = USB_REQ_START; - setup.index = 0; - setup.length = 0; - setup.value = 0; - - if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0, - timeout) == 0) return RT_EOK; - else return -RT_FALSE; -} - -/** - * This function will read data from usb adk device - * - * @param ifinst the interface instance. - * - * @return the error code, RT_EOK on successfully. -*/ -static rt_size_t rt_usb_adk_read(rt_device_t device, rt_off_t pos, void* buffer, - rt_size_t size) -{ - uadkinst_t adkinst; - rt_size_t length; - uifinst_t ifinst; - - /* check parameter */ - RT_ASSERT(device != RT_NULL); - RT_ASSERT(buffer != RT_NULL); - - ifinst = (uifinst_t)device->user_data; - adkinst = (uadkinst_t)ifinst->user_data; - - length = rt_usb_hcd_bulk_xfer(ifinst->uinst->hcd, adkinst->pipe_in, - buffer, size, 300); - - return length; - -} - -/** - * This function will write data to usb adk device - * - * @param ifinst the interface instance. - * - * @return the error code, RT_EOK on successfully. -*/ -static rt_size_t rt_usb_adk_write (rt_device_t device, rt_off_t pos, const void* buffer, - rt_size_t size) -{ - uadkinst_t adkinst; - rt_size_t length; - uifinst_t ifinst; - - RT_ASSERT(buffer != RT_NULL); - - ifinst = (uifinst_t)device->user_data; - adkinst = (uadkinst_t)ifinst->user_data; - - length = rt_usb_hcd_bulk_xfer(ifinst->uinst->hcd, adkinst->pipe_out, - (void*)buffer, size, 300); - - return length; -} - -/** - * This function will run adk class driver when usb device is detected and identified - * as a adk class device, it will continue the enumulate process. - * - * @param arg the argument. - * - * @return the error code, RT_EOK on successfully. - */ -static rt_err_t rt_usb_adk_run(void* arg) -{ - int i = 0; - uadkinst_t adkinst; - uifinst_t ifinst = (uifinst_t)arg; - udev_desc_t dev_desc; - rt_uint16_t protocol; - rt_err_t ret; - - /* parameter check */ - if(ifinst == RT_NULL) - { - rt_kprintf("the interface is not available\n"); - return -RT_EIO; - } - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_adk_run\n")); - - dev_desc = &ifinst->uinst->dev_desc; - if(dev_desc->idVendor == USB_ACCESSORY_VENDOR_ID && - (dev_desc->idProduct == USB_ACCESSORY_PRODUCT_ID || - dev_desc->idProduct == USB_ACCESSORY_ADB_PRODUCT_ID)) - { - if(ifinst->intf_desc->bInterfaceSubClass != 0xFF) return -RT_ERROR; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("found android accessory device\n")); - } - else - { - RT_DEBUG_LOG(RT_DEBUG_USB, ("switch device\n")); - - if((ret = rt_usb_adk_get_protocol(ifinst, &protocol)) != RT_EOK) - { - rt_kprintf("rt_usb_adk_get_protocol failed\n"); - return ret; - } - - if(protocol != 1) - { - rt_kprintf("read protocol failed\n"); - return -RT_ERROR; - } - - rt_usb_adk_send_string(ifinst, - ACCESSORY_STRING_MANUFACTURER, _adk_manufacturer); - rt_usb_adk_send_string(ifinst, - ACCESSORY_STRING_MODEL, _adk_model); - rt_usb_adk_send_string(ifinst, - ACCESSORY_STRING_DESCRIPTION, _adk_description); - rt_usb_adk_send_string(ifinst, - ACCESSORY_STRING_VERSION, _adk_version); - rt_usb_adk_send_string(ifinst, - ACCESSORY_STRING_URI, _adk_uri); - rt_usb_adk_send_string(ifinst, - ACCESSORY_STRING_SERIAL, _adk_serial); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("manufacturer %s\n", _adk_manufacturer)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("model %s\n", _adk_model)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("description %s\n", _adk_description)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("version %s\n", _adk_version)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("uri %s\n", _adk_uri)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("serial %s\n", _adk_serial)); - - if((ret = rt_usb_adk_start(ifinst)) != RT_EOK) - { - rt_kprintf("rt_usb_adk_start failed\n"); - return ret; - } - - return RT_EOK; - } - - adkinst = rt_malloc(sizeof(struct uadkinst)); - RT_ASSERT(adkinst != RT_NULL); - - /* initilize the data structure */ - rt_memset(adkinst, 0, sizeof(struct uadkinst)); - ifinst->user_data = (void*)adkinst; - - for(i=0; iintf_desc->bNumEndpoints; i++) - { - uep_desc_t ep_desc; - - /* get endpoint descriptor from interface descriptor */ - rt_usb_get_endpoint_descriptor(ifinst->intf_desc, i, &ep_desc); - if(ep_desc == RT_NULL) - { - rt_kprintf("rt_usb_get_endpoint_descriptor error\n"); - return -RT_ERROR; - } - - /* the endpoint type of adk class should be BULK */ - if((ep_desc->bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK) - continue; - - /* allocate pipes according to the endpoint type */ - if(ep_desc->bEndpointAddress & USB_DIR_IN) - { - /* allocate an in pipe for the adk instance */ - ret = rt_usb_hcd_alloc_pipe(ifinst->uinst->hcd, &adkinst->pipe_in, - ifinst, ep_desc, RT_NULL); - if(ret != RT_EOK) return ret; - } - else - { - /* allocate an output pipe for the adk instance */ - ret = rt_usb_hcd_alloc_pipe(ifinst->uinst->hcd, &adkinst->pipe_out, - ifinst, ep_desc, RT_NULL); - if(ret != RT_EOK) return ret; - } - } - - /* check pipes infomation */ - if(adkinst->pipe_in == RT_NULL || adkinst->pipe_out == RT_NULL) - { - rt_kprintf("pipe error, unsupported device\n"); - return -RT_ERROR; - } - - /* set configuration */ - ret = rt_usb_set_configure(ifinst->uinst, 1); - if(ret != RT_EOK) return ret; - - /* register adk device */ - adkinst->device.type = RT_Device_Class_Char; - adkinst->device.init = RT_NULL; - adkinst->device.open = RT_NULL; - adkinst->device.close = RT_NULL; - adkinst->device.read = rt_usb_adk_read; - adkinst->device.write = rt_usb_adk_write; - adkinst->device.control = RT_NULL; - adkinst->device.user_data = (void*)ifinst; - - rt_device_register(&adkinst->device, "adkdev", RT_DEVICE_FLAG_RDWR); - - return RT_EOK; -} - -/** - * This function will be invoked when usb device plug out is detected and it would clean - * and release all hub class related resources. - * - * @param arg the argument. - * - * @return the error code, RT_EOK on successfully. - */ -static rt_err_t rt_usb_adk_stop(void* arg) -{ - uadkinst_t adkinst; - uifinst_t ifinst = (uifinst_t)arg; - - RT_ASSERT(ifinst != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_adk_stop\n")); - - adkinst = (uadkinst_t)ifinst->user_data; - if(adkinst == RT_NULL) - { - rt_free(ifinst); - return RT_EOK; - } - - if(adkinst->pipe_in != RT_NULL) - rt_usb_hcd_free_pipe(ifinst->uinst->hcd, adkinst->pipe_in); - - if(adkinst->pipe_out != RT_NULL) - rt_usb_hcd_free_pipe(ifinst->uinst->hcd, adkinst->pipe_out); - - /* unregister adk device */ - rt_device_unregister(&adkinst->device); - - /* free adk instance */ - if(adkinst != RT_NULL) rt_free(adkinst); - - /* free interface instance */ - rt_free(ifinst); - - return RT_EOK; -} - -/** - * This function will register adk class driver to the usb class driver manager. - * and it should be invoked in the usb system initialization. - * - * @return the error code, RT_EOK on successfully. - */ -ucd_t rt_usb_class_driver_adk(void) -{ - adk_driver.class_code = USB_CLASS_ADK; - - adk_driver.run = rt_usb_adk_run; - adk_driver.stop = rt_usb_adk_stop; - - return &adk_driver; -} - -#endif - +/* + * File : adk.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2011, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2011-12-12 Yi Qiu first version + */ + +#include +#include +#include "adk.h" + +#ifdef RT_USB_CLASS_ADK + +static struct uclass_driver adk_driver; +static const char* _adk_manufacturer = RT_NULL; +static const char* _adk_model = RT_NULL; +static const char* _adk_description = RT_NULL; +static const char* _adk_version = RT_NULL; +static const char* _adk_uri = RT_NULL; +static const char* _adk_serial = RT_NULL; + +rt_err_t rt_usb_adk_set_string(const char* manufacturer, const char* model, + const char* description, const char* _version, const char* uri, + const char* serial) +{ + _adk_manufacturer = manufacturer; + _adk_model = model; + _adk_description = description; + _adk_version = _version; + _adk_uri = uri; + _adk_serial = serial; + + return RT_EOK; +} + +#ifdef RT_USING_MODULE +#include + +RTM_EXPORT(rt_usb_adk_set_string); +#endif + +/** + * This function will do USB_REQ_GET_PROTOCOL request to set idle period to the usb adk device + * + * @param ifinst the interface instance. + * @duration the idle period of requesting data. + * @report_id the report id + * + * @return the error code, RT_EOK on successfully. +*/ +static rt_err_t rt_usb_adk_get_protocol(uifinst_t ifinst, rt_uint16_t *protocol) +{ + struct ureqest setup; + uinst_t uinst; + int timeout = 100; + + /* parameter check */ + RT_ASSERT(ifinst != RT_NULL); + RT_ASSERT(ifinst->uinst != RT_NULL); + + uinst = ifinst->uinst; + + setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_VENDOR | + USB_REQ_TYPE_DEVICE; + setup.request = USB_REQ_GET_PROTOCOL; + setup.index = 0; + setup.length = 2; + setup.value = 0; + + if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, (void*)protocol, 2, + timeout) == 0) return RT_EOK; + else return -RT_FALSE; +} + +/** + * This function will do USB_REQ_SEND_STRING request to set idle period to the usb adk device + * + * @param ifinst the interface instance. + * @duration the idle period of requesting data. + * @report_id the report id + * + * @return the error code, RT_EOK on successfully. +*/ +static rt_err_t rt_usb_adk_send_string(uifinst_t ifinst, rt_uint16_t index, + const char* str) +{ + struct ureqest setup; + uinst_t uinst; + int timeout = 100; + + /* parameter check */ + RT_ASSERT(ifinst != RT_NULL); + RT_ASSERT(ifinst->uinst != RT_NULL); + + uinst = ifinst->uinst; + + setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_VENDOR | + USB_REQ_TYPE_DEVICE; + setup.request = USB_REQ_SEND_STRING; + setup.index = index; + setup.length = rt_strlen(str) + 1; + setup.value = 0; + + if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, (void*)str, + rt_strlen(str) + 1, timeout) == 0) return RT_EOK; + else return -RT_FALSE; +} + +/** + * This function will do USB_REQ_START request to set idle period to the usb adk device + * + * @param ifinst the interface instance. + * @duration the idle period of requesting data. + * @report_id the report id + * + * @return the error code, RT_EOK on successfully. +*/ +static rt_err_t rt_usb_adk_start(uifinst_t ifinst) +{ + struct ureqest setup; + uinst_t uinst; + int timeout = 100; + + /* parameter check */ + RT_ASSERT(ifinst != RT_NULL); + RT_ASSERT(ifinst->uinst != RT_NULL); + + uinst = ifinst->uinst; + + setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_VENDOR | + USB_REQ_TYPE_DEVICE; + setup.request = USB_REQ_START; + setup.index = 0; + setup.length = 0; + setup.value = 0; + + if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0, + timeout) == 0) return RT_EOK; + else return -RT_FALSE; +} + +/** + * This function will read data from usb adk device + * + * @param ifinst the interface instance. + * + * @return the error code, RT_EOK on successfully. +*/ +static rt_size_t rt_usb_adk_read(rt_device_t device, rt_off_t pos, void* buffer, + rt_size_t size) +{ + uadkinst_t adkinst; + rt_size_t length; + uifinst_t ifinst; + + /* check parameter */ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(buffer != RT_NULL); + + ifinst = (uifinst_t)device->user_data; + adkinst = (uadkinst_t)ifinst->user_data; + + length = rt_usb_hcd_bulk_xfer(ifinst->uinst->hcd, adkinst->pipe_in, + buffer, size, 300); + + return length; + +} + +/** + * This function will write data to usb adk device + * + * @param ifinst the interface instance. + * + * @return the error code, RT_EOK on successfully. +*/ +static rt_size_t rt_usb_adk_write (rt_device_t device, rt_off_t pos, const void* buffer, + rt_size_t size) +{ + uadkinst_t adkinst; + rt_size_t length; + uifinst_t ifinst; + + RT_ASSERT(buffer != RT_NULL); + + ifinst = (uifinst_t)device->user_data; + adkinst = (uadkinst_t)ifinst->user_data; + + length = rt_usb_hcd_bulk_xfer(ifinst->uinst->hcd, adkinst->pipe_out, + (void*)buffer, size, 300); + + return length; +} + +/** + * This function will run adk class driver when usb device is detected and identified + * as a adk class device, it will continue the enumulate process. + * + * @param arg the argument. + * + * @return the error code, RT_EOK on successfully. + */ +static rt_err_t rt_usb_adk_run(void* arg) +{ + int i = 0; + uadkinst_t adkinst; + uifinst_t ifinst = (uifinst_t)arg; + udev_desc_t dev_desc; + rt_uint16_t protocol; + rt_err_t ret; + + /* parameter check */ + if(ifinst == RT_NULL) + { + rt_kprintf("the interface is not available\n"); + return -RT_EIO; + } + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_adk_run\n")); + + dev_desc = &ifinst->uinst->dev_desc; + if(dev_desc->idVendor == USB_ACCESSORY_VENDOR_ID && + (dev_desc->idProduct == USB_ACCESSORY_PRODUCT_ID || + dev_desc->idProduct == USB_ACCESSORY_ADB_PRODUCT_ID)) + { + if(ifinst->intf_desc->bInterfaceSubClass != 0xFF) return -RT_ERROR; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("found android accessory device\n")); + } + else + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("switch device\n")); + + if((ret = rt_usb_adk_get_protocol(ifinst, &protocol)) != RT_EOK) + { + rt_kprintf("rt_usb_adk_get_protocol failed\n"); + return ret; + } + + if(protocol != 1) + { + rt_kprintf("read protocol failed\n"); + return -RT_ERROR; + } + + rt_usb_adk_send_string(ifinst, + ACCESSORY_STRING_MANUFACTURER, _adk_manufacturer); + rt_usb_adk_send_string(ifinst, + ACCESSORY_STRING_MODEL, _adk_model); + rt_usb_adk_send_string(ifinst, + ACCESSORY_STRING_DESCRIPTION, _adk_description); + rt_usb_adk_send_string(ifinst, + ACCESSORY_STRING_VERSION, _adk_version); + rt_usb_adk_send_string(ifinst, + ACCESSORY_STRING_URI, _adk_uri); + rt_usb_adk_send_string(ifinst, + ACCESSORY_STRING_SERIAL, _adk_serial); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("manufacturer %s\n", _adk_manufacturer)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("model %s\n", _adk_model)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("description %s\n", _adk_description)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("version %s\n", _adk_version)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("uri %s\n", _adk_uri)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("serial %s\n", _adk_serial)); + + if((ret = rt_usb_adk_start(ifinst)) != RT_EOK) + { + rt_kprintf("rt_usb_adk_start failed\n"); + return ret; + } + + return RT_EOK; + } + + adkinst = rt_malloc(sizeof(struct uadkinst)); + RT_ASSERT(adkinst != RT_NULL); + + /* initilize the data structure */ + rt_memset(adkinst, 0, sizeof(struct uadkinst)); + ifinst->user_data = (void*)adkinst; + + for(i=0; iintf_desc->bNumEndpoints; i++) + { + uep_desc_t ep_desc; + + /* get endpoint descriptor from interface descriptor */ + rt_usb_get_endpoint_descriptor(ifinst->intf_desc, i, &ep_desc); + if(ep_desc == RT_NULL) + { + rt_kprintf("rt_usb_get_endpoint_descriptor error\n"); + return -RT_ERROR; + } + + /* the endpoint type of adk class should be BULK */ + if((ep_desc->bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK) + continue; + + /* allocate pipes according to the endpoint type */ + if(ep_desc->bEndpointAddress & USB_DIR_IN) + { + /* allocate an in pipe for the adk instance */ + ret = rt_usb_hcd_alloc_pipe(ifinst->uinst->hcd, &adkinst->pipe_in, + ifinst, ep_desc, RT_NULL); + if(ret != RT_EOK) return ret; + } + else + { + /* allocate an output pipe for the adk instance */ + ret = rt_usb_hcd_alloc_pipe(ifinst->uinst->hcd, &adkinst->pipe_out, + ifinst, ep_desc, RT_NULL); + if(ret != RT_EOK) return ret; + } + } + + /* check pipes infomation */ + if(adkinst->pipe_in == RT_NULL || adkinst->pipe_out == RT_NULL) + { + rt_kprintf("pipe error, unsupported device\n"); + return -RT_ERROR; + } + + /* set configuration */ + ret = rt_usb_set_configure(ifinst->uinst, 1); + if(ret != RT_EOK) return ret; + + /* register adk device */ + adkinst->device.type = RT_Device_Class_Char; + adkinst->device.init = RT_NULL; + adkinst->device.open = RT_NULL; + adkinst->device.close = RT_NULL; + adkinst->device.read = rt_usb_adk_read; + adkinst->device.write = rt_usb_adk_write; + adkinst->device.control = RT_NULL; + adkinst->device.user_data = (void*)ifinst; + + rt_device_register(&adkinst->device, "adkdev", RT_DEVICE_FLAG_RDWR); + + return RT_EOK; +} + +/** + * This function will be invoked when usb device plug out is detected and it would clean + * and release all hub class related resources. + * + * @param arg the argument. + * + * @return the error code, RT_EOK on successfully. + */ +static rt_err_t rt_usb_adk_stop(void* arg) +{ + uadkinst_t adkinst; + uifinst_t ifinst = (uifinst_t)arg; + + RT_ASSERT(ifinst != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_adk_stop\n")); + + adkinst = (uadkinst_t)ifinst->user_data; + if(adkinst == RT_NULL) + { + rt_free(ifinst); + return RT_EOK; + } + + if(adkinst->pipe_in != RT_NULL) + rt_usb_hcd_free_pipe(ifinst->uinst->hcd, adkinst->pipe_in); + + if(adkinst->pipe_out != RT_NULL) + rt_usb_hcd_free_pipe(ifinst->uinst->hcd, adkinst->pipe_out); + + /* unregister adk device */ + rt_device_unregister(&adkinst->device); + + /* free adk instance */ + if(adkinst != RT_NULL) rt_free(adkinst); + + /* free interface instance */ + rt_free(ifinst); + + return RT_EOK; +} + +/** + * This function will register adk class driver to the usb class driver manager. + * and it should be invoked in the usb system initialization. + * + * @return the error code, RT_EOK on successfully. + */ +ucd_t rt_usb_class_driver_adk(void) +{ + adk_driver.class_code = USB_CLASS_ADK; + + adk_driver.run = rt_usb_adk_run; + adk_driver.stop = rt_usb_adk_stop; + + return &adk_driver; +} + +#endif + diff --git a/components/drivers/usb/usbhost/class/adk.h b/components/drivers/usb/usbhost/class/adk.h index dd7606fbec..ef18ab2714 100644 --- a/components/drivers/usb/usbhost/class/adk.h +++ b/components/drivers/usb/usbhost/class/adk.h @@ -1,47 +1,47 @@ -/* - * File : adk.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2011, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2011-12-12 Yi Qiu first version - */ - -#ifndef __HID_H__ -#define __HID_H__ - -#include - -struct uadkinst -{ - upipe_t pipe_in; - upipe_t pipe_out; - - struct rt_device device; -}; -typedef struct uadkinst* uadkinst_t; - -#define USB_ACCESSORY_VENDOR_ID 0x18D1 -#define USB_ACCESSORY_PRODUCT_ID 0x2D00 -#define USB_ACCESSORY_ADB_PRODUCT_ID 0x2D01 - -#define ACCESSORY_STRING_MANUFACTURER 0 -#define ACCESSORY_STRING_MODEL 1 -#define ACCESSORY_STRING_DESCRIPTION 2 -#define ACCESSORY_STRING_VERSION 3 -#define ACCESSORY_STRING_URI 4 -#define ACCESSORY_STRING_SERIAL 5 - -#define USB_REQ_GET_PROTOCOL 51 -#define USB_REQ_SEND_STRING 52 -#define USB_REQ_START 53 - -#define USB_CLASS_ADK 0xff - -#endif - +/* + * File : adk.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2011, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2011-12-12 Yi Qiu first version + */ + +#ifndef __HID_H__ +#define __HID_H__ + +#include + +struct uadkinst +{ + upipe_t pipe_in; + upipe_t pipe_out; + + struct rt_device device; +}; +typedef struct uadkinst* uadkinst_t; + +#define USB_ACCESSORY_VENDOR_ID 0x18D1 +#define USB_ACCESSORY_PRODUCT_ID 0x2D00 +#define USB_ACCESSORY_ADB_PRODUCT_ID 0x2D01 + +#define ACCESSORY_STRING_MANUFACTURER 0 +#define ACCESSORY_STRING_MODEL 1 +#define ACCESSORY_STRING_DESCRIPTION 2 +#define ACCESSORY_STRING_VERSION 3 +#define ACCESSORY_STRING_URI 4 +#define ACCESSORY_STRING_SERIAL 5 + +#define USB_REQ_GET_PROTOCOL 51 +#define USB_REQ_SEND_STRING 52 +#define USB_REQ_START 53 + +#define USB_CLASS_ADK 0xff + +#endif + diff --git a/components/drivers/usb/usbhost/core/core.c b/components/drivers/usb/usbhost/core/core.c index 956f283b95..d689f7a249 100644 --- a/components/drivers/usb/usbhost/core/core.c +++ b/components/drivers/usb/usbhost/core/core.c @@ -1,469 +1,469 @@ -/* - * File : core.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2011, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2011-12-12 Yi Qiu first version - */ - -#include -#include - -static struct uinstance uinst[USB_MAX_DEVICE]; - -/** - * This function will allocate an usb device instance from system. - * - * @param parent the hub instance to which the new allocated device attached. - * @param port the hub port. - * - * @return the allocate instance on successful, or RT_NULL on failure. - */ -uinst_t rt_usb_alloc_instance(void) -{ - int i; - - /* lock scheduler */ - rt_enter_critical(); - - for(i=0; idev_desc; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("start enumnation\n")); - - /* get device descriptor head */ - ret = rt_usb_get_descriptor(uinst, USB_DESC_TYPE_DEVICE, (void*)dev_desc, 8); - if(ret != RT_EOK) - { - rt_kprintf("get device descriptor head failed\n"); - return ret; - } - - /* set device address */ - ret = rt_usb_set_address(uinst); - if(ret != RT_EOK) - { - rt_kprintf("set device address failed\n"); - return ret; - } - - /* set device max packet size */ - uinst->max_packet_size = uinst->dev_desc.bMaxPacketSize0; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("get device descriptor length %d\n", - dev_desc->bLength)); - - /* get full device descriptor again */ - ret = rt_usb_get_descriptor - (uinst, USB_DESC_TYPE_DEVICE, (void*)dev_desc, dev_desc->bLength); - if(ret != RT_EOK) - { - rt_kprintf("get full device descriptor failed\n"); - return ret; - } - - RT_DEBUG_LOG(RT_DEBUG_USB, ("Vendor ID 0x%x\n", dev_desc->idVendor)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("Product ID 0x%x\n", dev_desc->idProduct)); - - /* get configuration descriptor head */ - ret = rt_usb_get_descriptor(uinst, USB_DESC_TYPE_CONFIGURATION, &cfg_desc, - sizeof(struct uconfig_descriptor)); - if(ret != RT_EOK) - { - rt_kprintf("get configuration descriptor head failed\n"); - return ret; - } - - /* alloc memory for configuration descriptor */ - uinst->cfg_desc = (ucfg_desc_t)rt_malloc(cfg_desc.wTotalLength); - rt_memset(uinst->cfg_desc, 0, cfg_desc.wTotalLength); - - /* get full configuration descriptor */ - ret = rt_usb_get_descriptor(uinst, USB_DESC_TYPE_CONFIGURATION, - uinst->cfg_desc, cfg_desc.wTotalLength); - if(ret != RT_EOK) - { - rt_kprintf("get full configuration descriptor failed\n"); - return ret; - } - - /* set configuration */ - ret = rt_usb_set_configure(uinst, 1); - if(ret != RT_EOK) return ret; - - for(i=0; icfg_desc->bNumInterfaces; i++) - { - /* get interface descriptor through configuration descriptor */ - ret = rt_usb_get_interface_descriptor(uinst->cfg_desc, i, &intf_desc); - if(ret != RT_EOK) - { - rt_kprintf("rt_usb_get_interface_descriptor error\n"); - return -RT_ERROR; - } - - RT_DEBUG_LOG(RT_DEBUG_USB, ("interface class 0x%x, subclass 0x%x\n", - intf_desc->bInterfaceClass, - intf_desc->bInterfaceSubClass)); - - /* find driver by class code found in interface descriptor */ - drv = rt_usb_class_driver_find(intf_desc->bInterfaceClass, - intf_desc->bInterfaceSubClass); - - if(drv != RT_NULL) - { - /* allocate memory for interface uinst */ - uinst->ifinst[i] = - (uifinst_t)rt_malloc(sizeof(struct uifinst)); - - uinst->ifinst[i]->drv = drv; - uinst->ifinst[i]->uinst = uinst; - uinst->ifinst[i]->intf_desc = intf_desc; - uinst->ifinst[i]->user_data = RT_NULL; - - /* open usb class driver */ - ret = rt_usb_class_driver_run(drv, (void*)uinst->ifinst[i]); - if(ret != RT_EOK) - { - rt_kprintf("interface %d run class driver error\n", i); - } - } - else - { - rt_kprintf("find usb device driver failed\n"); - continue; - } - } - - return RT_EOK; -} - -/** - * This function will detach an usb device instance from its host controller, - * and release all resource. - * - * @param uinst the usb device instance. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_detach_instance(uinst_t uinst) -{ - int i = 0; - - if(uinst == RT_NULL) - { - rt_kprintf("no usb instance to detach\n"); - return -RT_ERROR; - } - - /* free configration descriptor */ - if(uinst->cfg_desc) rt_free(uinst->cfg_desc); - - for(i=0; icfg_desc->bNumInterfaces; i++) - { - if(uinst->ifinst[i] == RT_NULL) continue; - if(uinst->ifinst[i]->drv == RT_NULL) continue; - - RT_ASSERT(uinst->ifinst[i]->uinst == uinst); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("free interface instance %d\n", i)); - rt_usb_class_driver_stop(uinst->ifinst[i]->drv, (void*)uinst->ifinst[i]); - } - - rt_memset(uinst, 0, sizeof(struct uinstance)); - - return RT_EOK; -} - -/** - * This function will do USB_REQ_GET_DESCRIPTO' request for the usb device instance, - * - * @param uinst the usb device instance. - * @param type the type of descriptor request. - * @param buffer the data buffer to save requested data - * @param nbytes the size of buffer - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_get_descriptor(uinst_t uinst, rt_uint8_t type, void* buffer, - int nbytes) -{ - struct ureqest setup; - int timeout = 100; - - RT_ASSERT(uinst != RT_NULL); - - setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_STANDARD | - USB_REQ_TYPE_DEVICE; - setup.request = USB_REQ_GET_DESCRIPTOR; - setup.index = 0; - setup.length = nbytes; - setup.value = type << 8; - - if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, buffer, nbytes, - timeout) != nbytes) return -RT_EIO; - else return RT_EOK; -} - -/** - * This function will set an address to the usb device. - * - * @param uinst the usb device instance. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_set_address(uinst_t uinst) -{ - struct ureqest setup; - int timeout = 100; - - RT_ASSERT(uinst != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_set_address\n")); - - setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD | - USB_REQ_TYPE_DEVICE; - setup.request = USB_REQ_SET_ADDRESS; - setup.index = 0; - setup.length = 0; - setup.value = uinst->index; - - if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0, - timeout) != 0) return -RT_EIO; - - rt_thread_delay(50); - - uinst->address = uinst->index; - - return RT_EOK; -} - -/** - * This function will set a configuration to the usb device. - * - * @param uinst the usb device instance. - * @param config the configuration number. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_set_configure(uinst_t uinst, int config) -{ - struct ureqest setup; - int timeout = 100; - - /* check parameter */ - RT_ASSERT(uinst != RT_NULL); - - setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD | - USB_REQ_TYPE_DEVICE; - setup.request = USB_REQ_SET_CONFIGURATION; - setup.index = 0; - setup.length = 0; - setup.value = config; - - if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0, - timeout) != 0) return -RT_EIO; - - return RT_EOK; -} - -/** - * This function will set an interface to the usb device. - * - * @param uinst the usb device instance. - * @param intf the interface number. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_set_interface(uinst_t uinst, int intf) -{ - struct ureqest setup; - int timeout = 100; - - /* check parameter */ - RT_ASSERT(uinst != RT_NULL); - - setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD | - USB_REQ_TYPE_INTERFACE; - setup.request = USB_REQ_SET_INTERFACE; - setup.index = 0; - setup.length = 0; - setup.value = intf; - - if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0, - timeout) != 0) return -RT_EIO; - - return RT_EOK; -} - -/** - * This function will clear feature for the endpoint of the usb device. - * - * @param uinst the usb device instance. - * @param endpoint the endpoint number of the usb device. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_clear_feature(uinst_t uinst, int endpoint, int feature) -{ - struct ureqest setup; - int timeout = 100; - - /* check parameter */ - RT_ASSERT(uinst != RT_NULL); - - setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD | - USB_REQ_TYPE_ENDPOINT; - setup.request = USB_REQ_CLEAR_FEATURE; - setup.index = endpoint; - setup.length = 0; - setup.value = feature; - - if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0, - timeout) != 0) return -RT_EIO; - - return RT_EOK; -} - -/** - * This function will get an interface descriptor from the configuration descriptor. - * - * @param cfg_desc the point of configuration descriptor structure. - * @param num the number of interface descriptor. - * @intf_desc the point of interface descriptor point. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_get_interface_descriptor(ucfg_desc_t cfg_desc, int num, - uintf_desc_t* intf_desc) -{ - rt_uint32_t ptr, depth = 0; - udesc_t desc; - - /* check parameter */ - RT_ASSERT(cfg_desc != RT_NULL); - - ptr = (rt_uint32_t)cfg_desc + cfg_desc->bLength; - while(ptr < (rt_uint32_t)cfg_desc + cfg_desc->wTotalLength) - { - if(depth++ > 0x20) - { - *intf_desc = RT_NULL; - return -RT_EIO; - } - desc = (udesc_t)ptr; - if(desc->type == USB_DESC_TYPE_INTERFACE) - { - if(((uintf_desc_t)desc)->bInterfaceNumber == num) - { - *intf_desc = (uintf_desc_t)desc; - - RT_DEBUG_LOG(RT_DEBUG_USB, - ("rt_usb_get_interface_descriptor: %d\n", num)); - return RT_EOK; - } - } - ptr = (rt_uint32_t)desc + desc->bLength; - } - - rt_kprintf("rt_usb_get_interface_descriptor %d failed\n", num); - return -RT_EIO; -} - -/** - * This function will get an endpoint descriptor from the interface descriptor. - * - * @param intf_desc the point of interface descriptor structure. - * @param num the number of endpoint descriptor. - * @param ep_desc the point of endpoint descriptor point. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_get_endpoint_descriptor(uintf_desc_t intf_desc, int num, - uep_desc_t* ep_desc) -{ - int count = 0, depth = 0; - rt_uint32_t ptr; - udesc_t desc; - - /* check parameter */ - RT_ASSERT(intf_desc != RT_NULL); - RT_ASSERT(num < intf_desc->bNumEndpoints); - - ptr = (rt_uint32_t)intf_desc + intf_desc->bLength; - while(count < intf_desc->bNumEndpoints) - { - if(depth++ > 0x20) - { - *ep_desc = RT_NULL; - return -RT_EIO; - } - desc = (udesc_t)ptr; - if(desc->type == USB_DESC_TYPE_ENDPOINT) - { - if(num == count) - { - *ep_desc = (uep_desc_t)desc; - - RT_DEBUG_LOG(RT_DEBUG_USB, - ("rt_usb_get_endpoint_descriptor: %d\n", num)); - return RT_EOK; - } - else count++; - } - ptr = (rt_uint32_t)desc + desc->bLength; - } - - rt_kprintf("rt_usb_get_endpoint_descriptor %d failed\n", num); - return -RT_EIO; -} - +/* + * File : core.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2011, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2011-12-12 Yi Qiu first version + */ + +#include +#include + +static struct uinstance uinst[USB_MAX_DEVICE]; + +/** + * This function will allocate an usb device instance from system. + * + * @param parent the hub instance to which the new allocated device attached. + * @param port the hub port. + * + * @return the allocate instance on successful, or RT_NULL on failure. + */ +uinst_t rt_usb_alloc_instance(void) +{ + int i; + + /* lock scheduler */ + rt_enter_critical(); + + for(i=0; idev_desc; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("start enumnation\n")); + + /* get device descriptor head */ + ret = rt_usb_get_descriptor(uinst, USB_DESC_TYPE_DEVICE, (void*)dev_desc, 8); + if(ret != RT_EOK) + { + rt_kprintf("get device descriptor head failed\n"); + return ret; + } + + /* set device address */ + ret = rt_usb_set_address(uinst); + if(ret != RT_EOK) + { + rt_kprintf("set device address failed\n"); + return ret; + } + + /* set device max packet size */ + uinst->max_packet_size = uinst->dev_desc.bMaxPacketSize0; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("get device descriptor length %d\n", + dev_desc->bLength)); + + /* get full device descriptor again */ + ret = rt_usb_get_descriptor + (uinst, USB_DESC_TYPE_DEVICE, (void*)dev_desc, dev_desc->bLength); + if(ret != RT_EOK) + { + rt_kprintf("get full device descriptor failed\n"); + return ret; + } + + RT_DEBUG_LOG(RT_DEBUG_USB, ("Vendor ID 0x%x\n", dev_desc->idVendor)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("Product ID 0x%x\n", dev_desc->idProduct)); + + /* get configuration descriptor head */ + ret = rt_usb_get_descriptor(uinst, USB_DESC_TYPE_CONFIGURATION, &cfg_desc, + sizeof(struct uconfig_descriptor)); + if(ret != RT_EOK) + { + rt_kprintf("get configuration descriptor head failed\n"); + return ret; + } + + /* alloc memory for configuration descriptor */ + uinst->cfg_desc = (ucfg_desc_t)rt_malloc(cfg_desc.wTotalLength); + rt_memset(uinst->cfg_desc, 0, cfg_desc.wTotalLength); + + /* get full configuration descriptor */ + ret = rt_usb_get_descriptor(uinst, USB_DESC_TYPE_CONFIGURATION, + uinst->cfg_desc, cfg_desc.wTotalLength); + if(ret != RT_EOK) + { + rt_kprintf("get full configuration descriptor failed\n"); + return ret; + } + + /* set configuration */ + ret = rt_usb_set_configure(uinst, 1); + if(ret != RT_EOK) return ret; + + for(i=0; icfg_desc->bNumInterfaces; i++) + { + /* get interface descriptor through configuration descriptor */ + ret = rt_usb_get_interface_descriptor(uinst->cfg_desc, i, &intf_desc); + if(ret != RT_EOK) + { + rt_kprintf("rt_usb_get_interface_descriptor error\n"); + return -RT_ERROR; + } + + RT_DEBUG_LOG(RT_DEBUG_USB, ("interface class 0x%x, subclass 0x%x\n", + intf_desc->bInterfaceClass, + intf_desc->bInterfaceSubClass)); + + /* find driver by class code found in interface descriptor */ + drv = rt_usb_class_driver_find(intf_desc->bInterfaceClass, + intf_desc->bInterfaceSubClass); + + if(drv != RT_NULL) + { + /* allocate memory for interface uinst */ + uinst->ifinst[i] = + (uifinst_t)rt_malloc(sizeof(struct uifinst)); + + uinst->ifinst[i]->drv = drv; + uinst->ifinst[i]->uinst = uinst; + uinst->ifinst[i]->intf_desc = intf_desc; + uinst->ifinst[i]->user_data = RT_NULL; + + /* open usb class driver */ + ret = rt_usb_class_driver_run(drv, (void*)uinst->ifinst[i]); + if(ret != RT_EOK) + { + rt_kprintf("interface %d run class driver error\n", i); + } + } + else + { + rt_kprintf("find usb device driver failed\n"); + continue; + } + } + + return RT_EOK; +} + +/** + * This function will detach an usb device instance from its host controller, + * and release all resource. + * + * @param uinst the usb device instance. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_detach_instance(uinst_t uinst) +{ + int i = 0; + + if(uinst == RT_NULL) + { + rt_kprintf("no usb instance to detach\n"); + return -RT_ERROR; + } + + /* free configration descriptor */ + if(uinst->cfg_desc) rt_free(uinst->cfg_desc); + + for(i=0; icfg_desc->bNumInterfaces; i++) + { + if(uinst->ifinst[i] == RT_NULL) continue; + if(uinst->ifinst[i]->drv == RT_NULL) continue; + + RT_ASSERT(uinst->ifinst[i]->uinst == uinst); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("free interface instance %d\n", i)); + rt_usb_class_driver_stop(uinst->ifinst[i]->drv, (void*)uinst->ifinst[i]); + } + + rt_memset(uinst, 0, sizeof(struct uinstance)); + + return RT_EOK; +} + +/** + * This function will do USB_REQ_GET_DESCRIPTO' request for the usb device instance, + * + * @param uinst the usb device instance. + * @param type the type of descriptor request. + * @param buffer the data buffer to save requested data + * @param nbytes the size of buffer + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_get_descriptor(uinst_t uinst, rt_uint8_t type, void* buffer, + int nbytes) +{ + struct ureqest setup; + int timeout = 100; + + RT_ASSERT(uinst != RT_NULL); + + setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_STANDARD | + USB_REQ_TYPE_DEVICE; + setup.request = USB_REQ_GET_DESCRIPTOR; + setup.index = 0; + setup.length = nbytes; + setup.value = type << 8; + + if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, buffer, nbytes, + timeout) != nbytes) return -RT_EIO; + else return RT_EOK; +} + +/** + * This function will set an address to the usb device. + * + * @param uinst the usb device instance. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_set_address(uinst_t uinst) +{ + struct ureqest setup; + int timeout = 100; + + RT_ASSERT(uinst != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_set_address\n")); + + setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD | + USB_REQ_TYPE_DEVICE; + setup.request = USB_REQ_SET_ADDRESS; + setup.index = 0; + setup.length = 0; + setup.value = uinst->index; + + if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0, + timeout) != 0) return -RT_EIO; + + rt_thread_delay(50); + + uinst->address = uinst->index; + + return RT_EOK; +} + +/** + * This function will set a configuration to the usb device. + * + * @param uinst the usb device instance. + * @param config the configuration number. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_set_configure(uinst_t uinst, int config) +{ + struct ureqest setup; + int timeout = 100; + + /* check parameter */ + RT_ASSERT(uinst != RT_NULL); + + setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD | + USB_REQ_TYPE_DEVICE; + setup.request = USB_REQ_SET_CONFIGURATION; + setup.index = 0; + setup.length = 0; + setup.value = config; + + if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0, + timeout) != 0) return -RT_EIO; + + return RT_EOK; +} + +/** + * This function will set an interface to the usb device. + * + * @param uinst the usb device instance. + * @param intf the interface number. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_set_interface(uinst_t uinst, int intf) +{ + struct ureqest setup; + int timeout = 100; + + /* check parameter */ + RT_ASSERT(uinst != RT_NULL); + + setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD | + USB_REQ_TYPE_INTERFACE; + setup.request = USB_REQ_SET_INTERFACE; + setup.index = 0; + setup.length = 0; + setup.value = intf; + + if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0, + timeout) != 0) return -RT_EIO; + + return RT_EOK; +} + +/** + * This function will clear feature for the endpoint of the usb device. + * + * @param uinst the usb device instance. + * @param endpoint the endpoint number of the usb device. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_clear_feature(uinst_t uinst, int endpoint, int feature) +{ + struct ureqest setup; + int timeout = 100; + + /* check parameter */ + RT_ASSERT(uinst != RT_NULL); + + setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD | + USB_REQ_TYPE_ENDPOINT; + setup.request = USB_REQ_CLEAR_FEATURE; + setup.index = endpoint; + setup.length = 0; + setup.value = feature; + + if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0, + timeout) != 0) return -RT_EIO; + + return RT_EOK; +} + +/** + * This function will get an interface descriptor from the configuration descriptor. + * + * @param cfg_desc the point of configuration descriptor structure. + * @param num the number of interface descriptor. + * @intf_desc the point of interface descriptor point. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_get_interface_descriptor(ucfg_desc_t cfg_desc, int num, + uintf_desc_t* intf_desc) +{ + rt_uint32_t ptr, depth = 0; + udesc_t desc; + + /* check parameter */ + RT_ASSERT(cfg_desc != RT_NULL); + + ptr = (rt_uint32_t)cfg_desc + cfg_desc->bLength; + while(ptr < (rt_uint32_t)cfg_desc + cfg_desc->wTotalLength) + { + if(depth++ > 0x20) + { + *intf_desc = RT_NULL; + return -RT_EIO; + } + desc = (udesc_t)ptr; + if(desc->type == USB_DESC_TYPE_INTERFACE) + { + if(((uintf_desc_t)desc)->bInterfaceNumber == num) + { + *intf_desc = (uintf_desc_t)desc; + + RT_DEBUG_LOG(RT_DEBUG_USB, + ("rt_usb_get_interface_descriptor: %d\n", num)); + return RT_EOK; + } + } + ptr = (rt_uint32_t)desc + desc->bLength; + } + + rt_kprintf("rt_usb_get_interface_descriptor %d failed\n", num); + return -RT_EIO; +} + +/** + * This function will get an endpoint descriptor from the interface descriptor. + * + * @param intf_desc the point of interface descriptor structure. + * @param num the number of endpoint descriptor. + * @param ep_desc the point of endpoint descriptor point. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_get_endpoint_descriptor(uintf_desc_t intf_desc, int num, + uep_desc_t* ep_desc) +{ + int count = 0, depth = 0; + rt_uint32_t ptr; + udesc_t desc; + + /* check parameter */ + RT_ASSERT(intf_desc != RT_NULL); + RT_ASSERT(num < intf_desc->bNumEndpoints); + + ptr = (rt_uint32_t)intf_desc + intf_desc->bLength; + while(count < intf_desc->bNumEndpoints) + { + if(depth++ > 0x20) + { + *ep_desc = RT_NULL; + return -RT_EIO; + } + desc = (udesc_t)ptr; + if(desc->type == USB_DESC_TYPE_ENDPOINT) + { + if(num == count) + { + *ep_desc = (uep_desc_t)desc; + + RT_DEBUG_LOG(RT_DEBUG_USB, + ("rt_usb_get_endpoint_descriptor: %d\n", num)); + return RT_EOK; + } + else count++; + } + ptr = (rt_uint32_t)desc + desc->bLength; + } + + rt_kprintf("rt_usb_get_endpoint_descriptor %d failed\n", num); + return -RT_EIO; +} + diff --git a/components/drivers/usb/usbhost/core/driver.c b/components/drivers/usb/usbhost/core/driver.c index 44307ddb22..7aeb4cef58 100644 --- a/components/drivers/usb/usbhost/core/driver.c +++ b/components/drivers/usb/usbhost/core/driver.c @@ -1,144 +1,144 @@ -/* - * File : driver.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2011, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2011-03-12 Yi Qiu first version - */ - -#include -#include -#include - -static rt_list_t _driver_list; - -/** - * This function will initilize the usb class driver related data structure, - * and it should be invoked in the usb system initialization. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_class_driver_init(void) -{ - rt_list_init(&_driver_list); - - return RT_EOK; -} - -/** - * This function will register an usb class driver to the class driver manager. - * - * @param drv the pointer of the usb class driver. - * - * @return the error code, RT_EOK on successfully. - */ - -rt_err_t rt_usb_class_driver_register(ucd_t drv) -{ - if (drv == RT_NULL) return -RT_ERROR; - - /* insert class driver into driver list */ - rt_list_insert_after(&_driver_list, &(drv->list)); - - return RT_EOK; -} - -/** - * This function will removes a previously registed usb class driver. - * - * @param drv the pointer of the usb class driver structure. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_class_driver_unregister(ucd_t drv) -{ - RT_ASSERT(drv != RT_NULL); - - /* remove class driver from driver list */ - rt_list_remove(&(drv->list)); - - return RT_EOK; -} - -/** - * This function will run an usb class driver. - * - * @param drv the pointer of usb class driver. - * @param args the parameter of run function. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_class_driver_run(ucd_t drv, void* args) -{ - RT_ASSERT(drv != RT_NULL); - - if(drv->run != RT_NULL) - drv->run(args); - - return RT_EOK; -} - -/** - * This function will stop a usb class driver. - * - * @param drv the pointer of usb class driver structure. - * @param args the argument of the stop function. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_class_driver_stop(ucd_t drv, void* args) -{ - RT_ASSERT(drv != RT_NULL); - - if(drv->stop != RT_NULL) - drv->stop(args); - - return RT_EOK; -} - - -/** - * This function finds a usb class driver by specified class code and subclass code. - * - * @param class_code the usb class driver's class code. - * @param subclass_code the usb class driver's sub class code. - * - * @return the registered usb class driver on successful, or RT_NULL on failure. - */ -ucd_t rt_usb_class_driver_find(int class_code, int subclass_code) -{ - struct rt_list_node *node; - - /* enter critical */ - if (rt_thread_self() != RT_NULL) - rt_enter_critical(); - - /* try to find driver object */ - for (node = _driver_list.next; node != &_driver_list; node = node->next) - { - ucd_t drv = - (ucd_t)rt_list_entry(node, struct uclass_driver, list); - if (drv->class_code == class_code) - { - /* leave critical */ - if (rt_thread_self() != RT_NULL) - rt_exit_critical(); - - return drv; - } - } - - /* leave critical */ - if (rt_thread_self() != RT_NULL) - rt_exit_critical(); - - /* not found */ - return RT_NULL; -} - +/* + * File : driver.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2011, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2011-03-12 Yi Qiu first version + */ + +#include +#include +#include + +static rt_list_t _driver_list; + +/** + * This function will initilize the usb class driver related data structure, + * and it should be invoked in the usb system initialization. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_class_driver_init(void) +{ + rt_list_init(&_driver_list); + + return RT_EOK; +} + +/** + * This function will register an usb class driver to the class driver manager. + * + * @param drv the pointer of the usb class driver. + * + * @return the error code, RT_EOK on successfully. + */ + +rt_err_t rt_usb_class_driver_register(ucd_t drv) +{ + if (drv == RT_NULL) return -RT_ERROR; + + /* insert class driver into driver list */ + rt_list_insert_after(&_driver_list, &(drv->list)); + + return RT_EOK; +} + +/** + * This function will removes a previously registed usb class driver. + * + * @param drv the pointer of the usb class driver structure. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_class_driver_unregister(ucd_t drv) +{ + RT_ASSERT(drv != RT_NULL); + + /* remove class driver from driver list */ + rt_list_remove(&(drv->list)); + + return RT_EOK; +} + +/** + * This function will run an usb class driver. + * + * @param drv the pointer of usb class driver. + * @param args the parameter of run function. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_class_driver_run(ucd_t drv, void* args) +{ + RT_ASSERT(drv != RT_NULL); + + if(drv->run != RT_NULL) + drv->run(args); + + return RT_EOK; +} + +/** + * This function will stop a usb class driver. + * + * @param drv the pointer of usb class driver structure. + * @param args the argument of the stop function. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_class_driver_stop(ucd_t drv, void* args) +{ + RT_ASSERT(drv != RT_NULL); + + if(drv->stop != RT_NULL) + drv->stop(args); + + return RT_EOK; +} + + +/** + * This function finds a usb class driver by specified class code and subclass code. + * + * @param class_code the usb class driver's class code. + * @param subclass_code the usb class driver's sub class code. + * + * @return the registered usb class driver on successful, or RT_NULL on failure. + */ +ucd_t rt_usb_class_driver_find(int class_code, int subclass_code) +{ + struct rt_list_node *node; + + /* enter critical */ + if (rt_thread_self() != RT_NULL) + rt_enter_critical(); + + /* try to find driver object */ + for (node = _driver_list.next; node != &_driver_list; node = node->next) + { + ucd_t drv = + (ucd_t)rt_list_entry(node, struct uclass_driver, list); + if (drv->class_code == class_code) + { + /* leave critical */ + if (rt_thread_self() != RT_NULL) + rt_exit_critical(); + + return drv; + } + } + + /* leave critical */ + if (rt_thread_self() != RT_NULL) + rt_exit_critical(); + + /* not found */ + return RT_NULL; +} + diff --git a/components/drivers/usb/usbhost/core/hub.c b/components/drivers/usb/usbhost/core/hub.c index 892094fe4a..05016cb6f7 100644 --- a/components/drivers/usb/usbhost/core/hub.c +++ b/components/drivers/usb/usbhost/core/hub.c @@ -1,611 +1,611 @@ -/* - * File : hub.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2011, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2011-12-12 Yi Qiu first version - */ - -#include -#include - -#define USB_THREAD_STACK_SIZE 2048 - -static struct rt_messagequeue *usb_mq; -static struct uclass_driver hub_driver; - -/** - * This function will do USB_REQ_GET_DESCRIPTOR request for the device instance - * to get usb hub descriptor. - * - * @param ifinst the interface instance. - * @buffer the data buffer to save usb hub descriptor. - * @param nbytes the size of buffer - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_hub_get_descriptor(uinst_t uinst, rt_uint8_t *buffer, - rt_size_t nbytes) -{ - struct ureqest setup; - int timeout = 100; - - /* parameter check */ - RT_ASSERT(uinst != RT_NULL); - - setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS | - USB_REQ_TYPE_DEVICE; - setup.request = USB_REQ_GET_DESCRIPTOR; - setup.index = 0; - setup.length = nbytes; - setup.value = USB_DESC_TYPE_HUB << 8; - - if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, buffer, nbytes, - timeout) == nbytes) return RT_EOK; - else return -RT_FALSE; -} - -/** - * This function will do USB_REQ_GET_STATUS request for the device instance - * to get usb hub status. - * - * @param ifinst the interface instance. - * @buffer the data buffer to save usb hub status. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_hub_get_status(uinst_t uinst, rt_uint8_t* buffer) -{ - struct ureqest setup; - int timeout = 100; - int length = 4; - - /* parameter check */ - RT_ASSERT(uinst != RT_NULL); - - setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS | - USB_REQ_TYPE_DEVICE; - setup.request = USB_REQ_GET_STATUS; - setup.index = 0; - setup.length = length; - setup.value = 0; - - if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, buffer, length, - timeout) == length) return RT_EOK; - else return -RT_FALSE; -} - -/** - * This function will do USB_REQ_GET_STATUS request for the device instance - * to get hub port status. - * - * @param ifinst the interface instance. - * @port the hub port to get status. - * @buffer the data buffer to save usb hub status. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_hub_get_port_status(uhubinst_t uhub, rt_uint16_t port, - rt_uint8_t* buffer) -{ - struct ureqest setup; - int timeout = 100; - int length = 4; - - /* parameter check */ - RT_ASSERT(uhub != RT_NULL); - - /* get roothub port status */ - if(uhub->is_roothub) - { - rt_usb_hcd_hub_control(uhub->hcd, port, RH_GET_PORT_STATUS, - (void*)buffer); - return RT_EOK; - } - - setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS | - USB_REQ_TYPE_OTHER; - setup.request = USB_REQ_GET_STATUS; - setup.index = port; - setup.length = 4; - setup.value = 0; - - if(rt_usb_hcd_control_xfer(uhub->hcd, uhub->self, &setup, buffer, - length, timeout) == timeout) return RT_EOK; - else return -RT_FALSE; -} - -/** - * This function will do USB_REQ_CLEAR_FEATURE request for the device instance - * to clear feature of the hub port. - * - * @param ifinst the interface instance. - * @port the hub port. - * @feature feature to be cleared. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_hub_clear_port_feature(uhubinst_t uhub, rt_uint16_t port, - rt_uint16_t feature) -{ - struct ureqest setup; - int timeout = 100; - - /* parameter check */ - RT_ASSERT(uhub != RT_NULL); - - /* clear roothub feature */ - if(uhub->is_roothub) - { - rt_usb_hcd_hub_control(uhub->hcd, port, RH_CLEAR_PORT_FEATURE, - (void*)feature); - return RT_EOK; - } - - setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_CLASS | - USB_REQ_TYPE_OTHER; - setup.request = USB_REQ_CLEAR_FEATURE; - setup.index = port; - setup.length = 0; - setup.value = feature; - - if(rt_usb_hcd_control_xfer(uhub->hcd, uhub->self, &setup, RT_NULL, 0, - timeout) == 0) return RT_EOK; - else return -RT_FALSE; -} - -/** - * This function will do USB_REQ_SET_FEATURE request for the device instance - * to set feature of the hub port. - * - * @param ifinst the interface instance. - * @port the hub port. - * @feature feature to be set. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_hub_set_port_feature(uhubinst_t uhub, rt_uint16_t port, - rt_uint16_t feature) -{ - struct ureqest setup; - int timeout = 100; - - /* parameter check */ - RT_ASSERT(uhub != RT_NULL); - - /* clear roothub feature */ - if(uhub->is_roothub) - { - rt_usb_hcd_hub_control(uhub->hcd, port, RH_SET_PORT_FEATURE, - (void*)feature); - return RT_EOK; - } - - setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_CLASS | - USB_REQ_TYPE_OTHER; - setup.request = USB_REQ_SET_FEATURE; - setup.index = port; - setup.length = 0; - setup.value = feature; - - if(rt_usb_hcd_control_xfer(uhub->hcd, uhub->self, &setup, RT_NULL, 0, - timeout) == 0) return RT_EOK; - else return -RT_FALSE; -} - -/** - * This function will rest hub port, it is invoked when sub device attached to the hub port. - * - * @param ifinst the interface instance. - * @param port the hub port. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_hub_reset_port(uhubinst_t uhub, rt_uint16_t port) -{ - rt_err_t ret; - rt_uint32_t pstatus; - - /* parameter check */ - RT_ASSERT(uhub != RT_NULL); - - rt_thread_delay(50); - - /* reset hub port */ - ret = rt_usb_hub_set_port_feature(uhub, port, PORT_FEAT_RESET); - if(ret != RT_EOK) return ret; - - while(1) - { - ret = rt_usb_hub_get_port_status(uhub, port, (rt_uint8_t*)&pstatus); - if(!(pstatus & PORT_PRS)) break; - } - - /* clear port reset feature */ - ret = rt_usb_hub_clear_port_feature(uhub, port, PORT_FEAT_C_RESET); - if(ret != RT_EOK) return ret; - - rt_thread_delay(50); - - return RT_EOK; -} - -/** - * This function will do debouce, it is invoked when sub device attached to the hub port. - * - * @param uinst the usb instance. - * @param port the hub port. - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_hub_port_debounce(uhubinst_t uhub, rt_uint16_t port) -{ - rt_err_t ret; - int i = 0, times = 20; - rt_uint32_t pstatus; - rt_bool_t connect = RT_TRUE; - - /* parameter check */ - RT_ASSERT(uhub != RT_NULL); - - for(i=0; inum_ports; i++) - { - rt_err_t ret; - uinst_t uinst; - rt_uint32_t pstatus = 0; - - reconnect = RT_FALSE; - - /* get hub port status */ - ret = rt_usb_hub_get_port_status(uhub, i + 1, (rt_uint8_t*)&pstatus); - if(ret != RT_EOK) continue; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("port_status 0x%x\n", pstatus)); - - /* check port status change */ - if ((pstatus & PORT_CCSC)) - { - /* clear port status change feature */ - rt_usb_hub_clear_port_feature(uhub, i + 1, PORT_FEAT_C_CONNECTION); - reconnect = RT_TRUE; - } - - if(pstatus & PORT_PESC) - { - rt_usb_hub_clear_port_feature(uhub, i + 1, PORT_FEAT_C_ENABLE); - reconnect = RT_TRUE; - } - - if(reconnect) - { - if(uhub->child[i]->status != UINST_STATUS_IDLE) - rt_usb_detach_instance(uhub->child[i]); - - ret = rt_usb_hub_port_debounce(uhub, i + 1); - if(ret != RT_EOK) continue; - - /* allocate an usb instance for new connected device */ - uinst = rt_usb_alloc_instance(); - if(uinst == RT_NULL) break; - - /* set usb device speed */ - uinst->speed = (pstatus & PORT_LSDA) ? 1 : 0; - uinst->parent = uhub; - uinst->hcd = uhub->hcd; - uhub->child[i] = uinst; - - /* reset usb roothub port */ - rt_usb_hub_reset_port(uhub, i + 1); - - /* attatch the usb instance to the hcd */ - rt_usb_attatch_instance(uinst); - } - } - - return RT_EOK; -} - -/** - * This function is the callback function of hub's int endpoint, it is invoked when data comes. - * - * @param context the context of the callback function. - * - * @return none. - */ -static void rt_usb_hub_irq(void* context) -{ - upipe_t pipe; - uifinst_t ifinst; - uhubinst_t uhub; - int timeout = 100; - - RT_ASSERT(context != RT_NULL); - - pipe = (upipe_t)context; - ifinst = pipe->ifinst; - uhub = (uhubinst_t)ifinst->user_data; - - if(pipe->status != UPIPE_STATUS_OK) - { - rt_kprintf("hub irq error\n"); - return; - } - - rt_usb_hub_port_change(uhub); - - rt_kprintf("hub int xfer...\n"); - - /* parameter check */ - RT_ASSERT(pipe->ifinst->uinst->hcd != RT_NULL); - - rt_usb_hcd_int_xfer(ifinst->uinst->hcd, pipe, uhub->buffer, - pipe->ep.wMaxPacketSize, timeout); -} - -/** - * This function will run usb hub class driver when usb hub is detected and identified - * as a hub class device, it will continue to do the enumulate process. - * - * @param arg the argument. - * - * @return the error code, RT_EOK on successfully. - */ -static rt_err_t rt_usb_hub_run(void *arg) -{ - int i = 0; - rt_err_t ret = RT_EOK; - uep_desc_t ep_desc; - uhubinst_t uhub; - uinst_t uinst; - uifinst_t ifinst = (uifinst_t)arg; - int timeout = 300; - - /* paremeter check */ - RT_ASSERT(ifinst != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_hub_run\n")); - - /* get usb device instance */ - uinst = ifinst->uinst; - - /* create a hub instance */ - uhub = rt_malloc(sizeof(struct uhubinst)); - rt_memset(uhub, 0, sizeof(struct uhubinst)); - - /* make interface instance's user data point to hub instance */ - ifinst->user_data = (void*)uhub; - - /* get hub descriptor head */ - ret = rt_usb_hub_get_descriptor(uinst, (rt_uint8_t*)&uhub->hub_desc, 8); - if(ret != RT_EOK) - { - rt_kprintf("get hub descriptor failed\n"); - return -RT_ERROR; - } - - /* get full hub descriptor */ - ret = rt_usb_hub_get_descriptor(uinst, (rt_uint8_t*)&uhub->hub_desc, - uhub->hub_desc.length); - if(ret != RT_EOK) - { - rt_kprintf("get hub descriptor again failed\n"); - return -RT_ERROR; - } - - /* get hub ports number */ - uhub->num_ports = uhub->hub_desc.num_ports; - uhub->hcd = uinst->hcd; - uhub->self = uinst; - - /* reset all hub ports */ - for (i = 0; i < uhub->num_ports; i++) - { - rt_usb_hub_set_port_feature(uhub, i + 1, PORT_FEAT_POWER); - rt_thread_delay(uhub->hub_desc.pwron_to_good - * 2 * RT_TICK_PER_SECOND / 1000 ); - } - - if(ifinst->intf_desc->bNumEndpoints != 1) - return -RT_ERROR; - - /* get endpoint descriptor from interface descriptor */ - rt_usb_get_endpoint_descriptor(ifinst->intf_desc, 0, &ep_desc); - if(ep_desc == RT_NULL) - { - rt_kprintf("rt_usb_get_endpoint_descriptor error\n"); - return -RT_ERROR; - } - - /* the endpoint type of hub class should be interrupt */ - if( USB_EP_ATTR(ep_desc->bmAttributes) == USB_EP_ATTR_INT) - { - /* the endpoint direction of hub class should be in */ - if(ep_desc->bEndpointAddress & USB_DIR_IN) - { - /* allocate a pipe according to the endpoint type */ - rt_usb_hcd_alloc_pipe(uinst->hcd, &uhub->pipe_in, ifinst, - ep_desc, rt_usb_hub_irq); - } - else return -RT_ERROR; - } - - /* parameter check */ - RT_ASSERT(uinst->hcd != RT_NULL); - - rt_usb_hcd_int_xfer(uinst->hcd, uhub->pipe_in, uhub->buffer, - uhub->pipe_in->ep.wMaxPacketSize, timeout); - - return RT_EOK; -} - -/** - * This function will be invoked when usb hub plug out is detected and it would clean - * and release all hub class related resources. - * - * @param arg the argument. - * - * @return the error code, RT_EOK on successfully. - */ -static rt_err_t rt_usb_hub_stop(void* arg) -{ - int i; - uhubinst_t uhub; - uinst_t uinst; - uifinst_t ifinst = (uifinst_t)arg; - - /* paremeter check */ - RT_ASSERT(ifinst != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_hub_stop\n")); - - uinst = ifinst->uinst; - uhub = (uhubinst_t)ifinst->user_data; - - if(uhub->pipe_in != RT_NULL) - rt_usb_hcd_free_pipe(uinst->hcd, uhub->pipe_in); - - for(i=0; inum_ports; i++) - { - if(uhub->child[i] != RT_NULL) - rt_usb_detach_instance(uhub->child[i]); - } - - if(uhub != RT_NULL) rt_free(uhub); - if(ifinst != RT_NULL) rt_free(ifinst); - - return RT_EOK; -} - -/** - * This function will register hub class driver to the usb class driver manager. - * and it should be invoked in the usb system initialization. - * - * @return the error code, RT_EOK on successfully. - */ -ucd_t rt_usb_class_driver_hub(void) -{ - hub_driver.class_code = USB_CLASS_HUB; - - hub_driver.run = rt_usb_hub_run; - hub_driver.stop = rt_usb_hub_stop; - - return &hub_driver; -} - -/** - * This function is the main entry of usb hub thread, it is in charge of - * processing all messages received from the usb message buffer. - * - * @param parameter the parameter of the usb host thread. - * - * @return none. - */ -static void rt_usb_hub_thread_entry(void* parameter) -{ - while(1) - { - struct uhost_msg msg; - - /* receive message */ - if(rt_mq_recv(usb_mq, &msg, sizeof(struct uhost_msg), RT_WAITING_FOREVER) - != RT_EOK ) continue; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("msg type %d\n", msg.type)); - - switch (msg.type) - { - case USB_MSG_CONNECT_CHANGE: - rt_usb_hub_port_change(msg.content.uhub); - break; - case USB_MSG_CALLBACK: - /* invoke callback */ - msg.content.cb.function(msg.content.cb.context); - break; - default: - break; - } - } -} - -/** - * This function will post an message to the usb message queue, - * - * @param msg the message to be posted - * @param size the size of the message . - * - * @return the error code, RT_EOK on successfully. - */ -rt_err_t rt_usb_post_event(struct uhost_msg* msg, rt_size_t size) -{ - RT_ASSERT(msg != RT_NULL); - - /* send message to usb message queue */ - rt_mq_send(usb_mq, (void*)msg, size); - - return RT_EOK; -} - -/** - * This function will initialize usb hub thread. - * - * @return none. - * - */ -void rt_usb_hub_thread(void) -{ - rt_thread_t thread; - - /* create usb message queue */ - usb_mq = rt_mq_create("usbh", 32, 16, RT_IPC_FLAG_FIFO); - - /* create usb hub thread */ - thread = rt_thread_create("usbh", rt_usb_hub_thread_entry, RT_NULL, - USB_THREAD_STACK_SIZE, 8, 20); - if(thread != RT_NULL) - { - /* startup usb host thread */ - rt_thread_startup(thread); - } -} - +/* + * File : hub.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2011, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2011-12-12 Yi Qiu first version + */ + +#include +#include + +#define USB_THREAD_STACK_SIZE 2048 + +static struct rt_messagequeue *usb_mq; +static struct uclass_driver hub_driver; + +/** + * This function will do USB_REQ_GET_DESCRIPTOR request for the device instance + * to get usb hub descriptor. + * + * @param ifinst the interface instance. + * @buffer the data buffer to save usb hub descriptor. + * @param nbytes the size of buffer + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_hub_get_descriptor(uinst_t uinst, rt_uint8_t *buffer, + rt_size_t nbytes) +{ + struct ureqest setup; + int timeout = 100; + + /* parameter check */ + RT_ASSERT(uinst != RT_NULL); + + setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS | + USB_REQ_TYPE_DEVICE; + setup.request = USB_REQ_GET_DESCRIPTOR; + setup.index = 0; + setup.length = nbytes; + setup.value = USB_DESC_TYPE_HUB << 8; + + if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, buffer, nbytes, + timeout) == nbytes) return RT_EOK; + else return -RT_FALSE; +} + +/** + * This function will do USB_REQ_GET_STATUS request for the device instance + * to get usb hub status. + * + * @param ifinst the interface instance. + * @buffer the data buffer to save usb hub status. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_hub_get_status(uinst_t uinst, rt_uint8_t* buffer) +{ + struct ureqest setup; + int timeout = 100; + int length = 4; + + /* parameter check */ + RT_ASSERT(uinst != RT_NULL); + + setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS | + USB_REQ_TYPE_DEVICE; + setup.request = USB_REQ_GET_STATUS; + setup.index = 0; + setup.length = length; + setup.value = 0; + + if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, buffer, length, + timeout) == length) return RT_EOK; + else return -RT_FALSE; +} + +/** + * This function will do USB_REQ_GET_STATUS request for the device instance + * to get hub port status. + * + * @param ifinst the interface instance. + * @port the hub port to get status. + * @buffer the data buffer to save usb hub status. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_hub_get_port_status(uhubinst_t uhub, rt_uint16_t port, + rt_uint8_t* buffer) +{ + struct ureqest setup; + int timeout = 100; + int length = 4; + + /* parameter check */ + RT_ASSERT(uhub != RT_NULL); + + /* get roothub port status */ + if(uhub->is_roothub) + { + rt_usb_hcd_hub_control(uhub->hcd, port, RH_GET_PORT_STATUS, + (void*)buffer); + return RT_EOK; + } + + setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS | + USB_REQ_TYPE_OTHER; + setup.request = USB_REQ_GET_STATUS; + setup.index = port; + setup.length = 4; + setup.value = 0; + + if(rt_usb_hcd_control_xfer(uhub->hcd, uhub->self, &setup, buffer, + length, timeout) == timeout) return RT_EOK; + else return -RT_FALSE; +} + +/** + * This function will do USB_REQ_CLEAR_FEATURE request for the device instance + * to clear feature of the hub port. + * + * @param ifinst the interface instance. + * @port the hub port. + * @feature feature to be cleared. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_hub_clear_port_feature(uhubinst_t uhub, rt_uint16_t port, + rt_uint16_t feature) +{ + struct ureqest setup; + int timeout = 100; + + /* parameter check */ + RT_ASSERT(uhub != RT_NULL); + + /* clear roothub feature */ + if(uhub->is_roothub) + { + rt_usb_hcd_hub_control(uhub->hcd, port, RH_CLEAR_PORT_FEATURE, + (void*)feature); + return RT_EOK; + } + + setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_CLASS | + USB_REQ_TYPE_OTHER; + setup.request = USB_REQ_CLEAR_FEATURE; + setup.index = port; + setup.length = 0; + setup.value = feature; + + if(rt_usb_hcd_control_xfer(uhub->hcd, uhub->self, &setup, RT_NULL, 0, + timeout) == 0) return RT_EOK; + else return -RT_FALSE; +} + +/** + * This function will do USB_REQ_SET_FEATURE request for the device instance + * to set feature of the hub port. + * + * @param ifinst the interface instance. + * @port the hub port. + * @feature feature to be set. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_hub_set_port_feature(uhubinst_t uhub, rt_uint16_t port, + rt_uint16_t feature) +{ + struct ureqest setup; + int timeout = 100; + + /* parameter check */ + RT_ASSERT(uhub != RT_NULL); + + /* clear roothub feature */ + if(uhub->is_roothub) + { + rt_usb_hcd_hub_control(uhub->hcd, port, RH_SET_PORT_FEATURE, + (void*)feature); + return RT_EOK; + } + + setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_CLASS | + USB_REQ_TYPE_OTHER; + setup.request = USB_REQ_SET_FEATURE; + setup.index = port; + setup.length = 0; + setup.value = feature; + + if(rt_usb_hcd_control_xfer(uhub->hcd, uhub->self, &setup, RT_NULL, 0, + timeout) == 0) return RT_EOK; + else return -RT_FALSE; +} + +/** + * This function will rest hub port, it is invoked when sub device attached to the hub port. + * + * @param ifinst the interface instance. + * @param port the hub port. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_hub_reset_port(uhubinst_t uhub, rt_uint16_t port) +{ + rt_err_t ret; + rt_uint32_t pstatus; + + /* parameter check */ + RT_ASSERT(uhub != RT_NULL); + + rt_thread_delay(50); + + /* reset hub port */ + ret = rt_usb_hub_set_port_feature(uhub, port, PORT_FEAT_RESET); + if(ret != RT_EOK) return ret; + + while(1) + { + ret = rt_usb_hub_get_port_status(uhub, port, (rt_uint8_t*)&pstatus); + if(!(pstatus & PORT_PRS)) break; + } + + /* clear port reset feature */ + ret = rt_usb_hub_clear_port_feature(uhub, port, PORT_FEAT_C_RESET); + if(ret != RT_EOK) return ret; + + rt_thread_delay(50); + + return RT_EOK; +} + +/** + * This function will do debouce, it is invoked when sub device attached to the hub port. + * + * @param uinst the usb instance. + * @param port the hub port. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_hub_port_debounce(uhubinst_t uhub, rt_uint16_t port) +{ + rt_err_t ret; + int i = 0, times = 20; + rt_uint32_t pstatus; + rt_bool_t connect = RT_TRUE; + + /* parameter check */ + RT_ASSERT(uhub != RT_NULL); + + for(i=0; inum_ports; i++) + { + rt_err_t ret; + uinst_t uinst; + rt_uint32_t pstatus = 0; + + reconnect = RT_FALSE; + + /* get hub port status */ + ret = rt_usb_hub_get_port_status(uhub, i + 1, (rt_uint8_t*)&pstatus); + if(ret != RT_EOK) continue; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("port_status 0x%x\n", pstatus)); + + /* check port status change */ + if ((pstatus & PORT_CCSC)) + { + /* clear port status change feature */ + rt_usb_hub_clear_port_feature(uhub, i + 1, PORT_FEAT_C_CONNECTION); + reconnect = RT_TRUE; + } + + if(pstatus & PORT_PESC) + { + rt_usb_hub_clear_port_feature(uhub, i + 1, PORT_FEAT_C_ENABLE); + reconnect = RT_TRUE; + } + + if(reconnect) + { + if(uhub->child[i]->status != UINST_STATUS_IDLE) + rt_usb_detach_instance(uhub->child[i]); + + ret = rt_usb_hub_port_debounce(uhub, i + 1); + if(ret != RT_EOK) continue; + + /* allocate an usb instance for new connected device */ + uinst = rt_usb_alloc_instance(); + if(uinst == RT_NULL) break; + + /* set usb device speed */ + uinst->speed = (pstatus & PORT_LSDA) ? 1 : 0; + uinst->parent = uhub; + uinst->hcd = uhub->hcd; + uhub->child[i] = uinst; + + /* reset usb roothub port */ + rt_usb_hub_reset_port(uhub, i + 1); + + /* attatch the usb instance to the hcd */ + rt_usb_attatch_instance(uinst); + } + } + + return RT_EOK; +} + +/** + * This function is the callback function of hub's int endpoint, it is invoked when data comes. + * + * @param context the context of the callback function. + * + * @return none. + */ +static void rt_usb_hub_irq(void* context) +{ + upipe_t pipe; + uifinst_t ifinst; + uhubinst_t uhub; + int timeout = 100; + + RT_ASSERT(context != RT_NULL); + + pipe = (upipe_t)context; + ifinst = pipe->ifinst; + uhub = (uhubinst_t)ifinst->user_data; + + if(pipe->status != UPIPE_STATUS_OK) + { + rt_kprintf("hub irq error\n"); + return; + } + + rt_usb_hub_port_change(uhub); + + rt_kprintf("hub int xfer...\n"); + + /* parameter check */ + RT_ASSERT(pipe->ifinst->uinst->hcd != RT_NULL); + + rt_usb_hcd_int_xfer(ifinst->uinst->hcd, pipe, uhub->buffer, + pipe->ep.wMaxPacketSize, timeout); +} + +/** + * This function will run usb hub class driver when usb hub is detected and identified + * as a hub class device, it will continue to do the enumulate process. + * + * @param arg the argument. + * + * @return the error code, RT_EOK on successfully. + */ +static rt_err_t rt_usb_hub_run(void *arg) +{ + int i = 0; + rt_err_t ret = RT_EOK; + uep_desc_t ep_desc; + uhubinst_t uhub; + uinst_t uinst; + uifinst_t ifinst = (uifinst_t)arg; + int timeout = 300; + + /* paremeter check */ + RT_ASSERT(ifinst != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_hub_run\n")); + + /* get usb device instance */ + uinst = ifinst->uinst; + + /* create a hub instance */ + uhub = rt_malloc(sizeof(struct uhubinst)); + rt_memset(uhub, 0, sizeof(struct uhubinst)); + + /* make interface instance's user data point to hub instance */ + ifinst->user_data = (void*)uhub; + + /* get hub descriptor head */ + ret = rt_usb_hub_get_descriptor(uinst, (rt_uint8_t*)&uhub->hub_desc, 8); + if(ret != RT_EOK) + { + rt_kprintf("get hub descriptor failed\n"); + return -RT_ERROR; + } + + /* get full hub descriptor */ + ret = rt_usb_hub_get_descriptor(uinst, (rt_uint8_t*)&uhub->hub_desc, + uhub->hub_desc.length); + if(ret != RT_EOK) + { + rt_kprintf("get hub descriptor again failed\n"); + return -RT_ERROR; + } + + /* get hub ports number */ + uhub->num_ports = uhub->hub_desc.num_ports; + uhub->hcd = uinst->hcd; + uhub->self = uinst; + + /* reset all hub ports */ + for (i = 0; i < uhub->num_ports; i++) + { + rt_usb_hub_set_port_feature(uhub, i + 1, PORT_FEAT_POWER); + rt_thread_delay(uhub->hub_desc.pwron_to_good + * 2 * RT_TICK_PER_SECOND / 1000 ); + } + + if(ifinst->intf_desc->bNumEndpoints != 1) + return -RT_ERROR; + + /* get endpoint descriptor from interface descriptor */ + rt_usb_get_endpoint_descriptor(ifinst->intf_desc, 0, &ep_desc); + if(ep_desc == RT_NULL) + { + rt_kprintf("rt_usb_get_endpoint_descriptor error\n"); + return -RT_ERROR; + } + + /* the endpoint type of hub class should be interrupt */ + if( USB_EP_ATTR(ep_desc->bmAttributes) == USB_EP_ATTR_INT) + { + /* the endpoint direction of hub class should be in */ + if(ep_desc->bEndpointAddress & USB_DIR_IN) + { + /* allocate a pipe according to the endpoint type */ + rt_usb_hcd_alloc_pipe(uinst->hcd, &uhub->pipe_in, ifinst, + ep_desc, rt_usb_hub_irq); + } + else return -RT_ERROR; + } + + /* parameter check */ + RT_ASSERT(uinst->hcd != RT_NULL); + + rt_usb_hcd_int_xfer(uinst->hcd, uhub->pipe_in, uhub->buffer, + uhub->pipe_in->ep.wMaxPacketSize, timeout); + + return RT_EOK; +} + +/** + * This function will be invoked when usb hub plug out is detected and it would clean + * and release all hub class related resources. + * + * @param arg the argument. + * + * @return the error code, RT_EOK on successfully. + */ +static rt_err_t rt_usb_hub_stop(void* arg) +{ + int i; + uhubinst_t uhub; + uinst_t uinst; + uifinst_t ifinst = (uifinst_t)arg; + + /* paremeter check */ + RT_ASSERT(ifinst != RT_NULL); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_hub_stop\n")); + + uinst = ifinst->uinst; + uhub = (uhubinst_t)ifinst->user_data; + + if(uhub->pipe_in != RT_NULL) + rt_usb_hcd_free_pipe(uinst->hcd, uhub->pipe_in); + + for(i=0; inum_ports; i++) + { + if(uhub->child[i] != RT_NULL) + rt_usb_detach_instance(uhub->child[i]); + } + + if(uhub != RT_NULL) rt_free(uhub); + if(ifinst != RT_NULL) rt_free(ifinst); + + return RT_EOK; +} + +/** + * This function will register hub class driver to the usb class driver manager. + * and it should be invoked in the usb system initialization. + * + * @return the error code, RT_EOK on successfully. + */ +ucd_t rt_usb_class_driver_hub(void) +{ + hub_driver.class_code = USB_CLASS_HUB; + + hub_driver.run = rt_usb_hub_run; + hub_driver.stop = rt_usb_hub_stop; + + return &hub_driver; +} + +/** + * This function is the main entry of usb hub thread, it is in charge of + * processing all messages received from the usb message buffer. + * + * @param parameter the parameter of the usb host thread. + * + * @return none. + */ +static void rt_usb_hub_thread_entry(void* parameter) +{ + while(1) + { + struct uhost_msg msg; + + /* receive message */ + if(rt_mq_recv(usb_mq, &msg, sizeof(struct uhost_msg), RT_WAITING_FOREVER) + != RT_EOK ) continue; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("msg type %d\n", msg.type)); + + switch (msg.type) + { + case USB_MSG_CONNECT_CHANGE: + rt_usb_hub_port_change(msg.content.uhub); + break; + case USB_MSG_CALLBACK: + /* invoke callback */ + msg.content.cb.function(msg.content.cb.context); + break; + default: + break; + } + } +} + +/** + * This function will post an message to the usb message queue, + * + * @param msg the message to be posted + * @param size the size of the message . + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_post_event(struct uhost_msg* msg, rt_size_t size) +{ + RT_ASSERT(msg != RT_NULL); + + /* send message to usb message queue */ + rt_mq_send(usb_mq, (void*)msg, size); + + return RT_EOK; +} + +/** + * This function will initialize usb hub thread. + * + * @return none. + * + */ +void rt_usb_hub_thread(void) +{ + rt_thread_t thread; + + /* create usb message queue */ + usb_mq = rt_mq_create("usbh", 32, 16, RT_IPC_FLAG_FIFO); + + /* create usb hub thread */ + thread = rt_thread_create("usbh", rt_usb_hub_thread_entry, RT_NULL, + USB_THREAD_STACK_SIZE, 8, 20); + if(thread != RT_NULL) + { + /* startup usb host thread */ + rt_thread_startup(thread); + } +} + diff --git a/components/drivers/usb/usbhost/core/usbhost.c b/components/drivers/usb/usbhost/core/usbhost.c index 0b5bd9a0d1..572da8bd67 100644 --- a/components/drivers/usb/usbhost/core/usbhost.c +++ b/components/drivers/usb/usbhost/core/usbhost.c @@ -1,74 +1,74 @@ -/* - * File : usbhost.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2011, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2011-12-12 Yi Qiu first version - */ -#include -#include - -#if defined(RT_USB_HID_KEYBOARD) || defined(RT_USB_HID_MOUSE) -#include -#endif - -/** - * This function will initialize the usb host stack, all the usb class driver and - * host controller driver are also be initialized here. - * - * @return none. - */ -void rt_usb_host_init(void) -{ - ucd_t drv; -#ifdef RT_USB_CLASS_HID - uprotocal_t protocal; -#endif - - /* initialize usb hub thread */ - rt_usb_hub_thread(); - - /* initialize class driver */ - rt_usb_class_driver_init(); - -#ifdef RT_USB_CLASS_MASS_STORAGE - /* register mass storage class driver */ - drv = rt_usb_class_driver_storage(); - rt_usb_class_driver_register(drv); -#endif - -#ifdef RT_USB_CLASS_HID - /* register hid class driver */ - drv = rt_usb_class_driver_hid(); - rt_usb_class_driver_register(drv); - -#ifdef RT_USB_HID_KEYBOARD - /* register hid keyboard protocal */ - protocal = rt_usb_hid_protocal_kbd(); - rt_usb_hid_protocal_register(protocal); -#endif - -#ifdef RT_USB_HID_MOUSE - /* register hid mouse protocal */ - protocal = rt_usb_hid_protocal_mouse(); - rt_usb_hid_protocal_register(protocal); -#endif -#endif - -#ifdef RT_USB_CLASS_ADK - /* register adk class driver */ - drv = rt_usb_class_driver_adk(); - rt_usb_class_driver_register(drv); -#endif - - /* register hub class driver */ - drv = rt_usb_class_driver_hub(); - rt_usb_class_driver_register(drv); -} - +/* + * File : usbhost.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2011, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2011-12-12 Yi Qiu first version + */ +#include +#include + +#if defined(RT_USB_HID_KEYBOARD) || defined(RT_USB_HID_MOUSE) +#include +#endif + +/** + * This function will initialize the usb host stack, all the usb class driver and + * host controller driver are also be initialized here. + * + * @return none. + */ +void rt_usb_host_init(void) +{ + ucd_t drv; +#ifdef RT_USB_CLASS_HID + uprotocal_t protocal; +#endif + + /* initialize usb hub thread */ + rt_usb_hub_thread(); + + /* initialize class driver */ + rt_usb_class_driver_init(); + +#ifdef RT_USB_CLASS_MASS_STORAGE + /* register mass storage class driver */ + drv = rt_usb_class_driver_storage(); + rt_usb_class_driver_register(drv); +#endif + +#ifdef RT_USB_CLASS_HID + /* register hid class driver */ + drv = rt_usb_class_driver_hid(); + rt_usb_class_driver_register(drv); + +#ifdef RT_USB_HID_KEYBOARD + /* register hid keyboard protocal */ + protocal = rt_usb_hid_protocal_kbd(); + rt_usb_hid_protocal_register(protocal); +#endif + +#ifdef RT_USB_HID_MOUSE + /* register hid mouse protocal */ + protocal = rt_usb_hid_protocal_mouse(); + rt_usb_hid_protocal_register(protocal); +#endif +#endif + +#ifdef RT_USB_CLASS_ADK + /* register adk class driver */ + drv = rt_usb_class_driver_adk(); + rt_usb_class_driver_register(drv); +#endif + + /* register hub class driver */ + drv = rt_usb_class_driver_hub(); + rt_usb_class_driver_register(drv); +} + -- cgit v1.3.1