diff options
| author | Bernard Xiong <[email protected]> | 2013-01-08 18:13:32 -0800 |
|---|---|---|
| committer | Bernard Xiong <[email protected]> | 2013-01-08 18:13:32 -0800 |
| commit | accace98e05eda28c116eb04502eb92d01b6ef1e (patch) | |
| tree | 4a425c96e0be3980779c8205c7c3fe2f1a144630 /components/drivers | |
| parent | 1fab41d48a490f6483582147500d43f4ca889a8e (diff) | |
| parent | 02b8e9366f362926799bfaecc0891830ba62f646 (diff) | |
Merge pull request #8 from mbbill/correct_crlf
Correct crlf
Diffstat (limited to 'components/drivers')
34 files changed, 7535 insertions, 7535 deletions
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 <rtdevice.h>
-
-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 <rtdevice.h> + +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 <rtdevice.h>
-
-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 <rtdevice.h> + +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 <rtthread.h>
-#include <drivers/mmcsd_host.h>
-
-#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 <rtthread.h> +#include <drivers/mmcsd_host.h> + +#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 <rtthread.h>
-#include <drivers/mmcsd_host.h>
-#include <drivers/mmcsd_card.h>
-#include <drivers/sdio_func_ids.h>
-
-#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 <rtthread.h> +#include <drivers/mmcsd_host.h> +#include <drivers/mmcsd_card.h> +#include <drivers/sdio_func_ids.h> + +#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 <rtthread.h>
-
-#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 <rtthread.h> + +#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 <rtthread.h>
-#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 <rtthread.h> +#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 <rtthread.h>
-#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 <rtthread.h> +#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 <drivers/mmcsd_core.h>
-#include <drivers/sdio.h>
-
-#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 <drivers/mmcsd_core.h> +#include <drivers/sdio.h> + +#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");
+ 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); +} - 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 <rtthread.h>
-#include <rtdevice.h>
-#include <rthw.h>
-#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 <rtthread.h> +#include <rtdevice.h> +#include <rthw.h> +#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 <rtthread.h>
-#include <rtservice.h>
-#include <rtdevice.h>
-#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 <rtthread.h> +#include <rtservice.h> +#include <rtdevice.h> +#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 <rtthread.h>
-
-#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 <rtthread.h> + +#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 <rtthread.h>
-#include <rtdevice.h>
-
-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; i<len; i++)
- {
- str_desc.String[i*2] = device->str[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 <rtthread.h> +#include <rtdevice.h> + +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; i<len; i++) + { + str_desc.String[i*2] = device->str[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 <rtthread.h>
-#include <rtdevice.h>
-#include <rtservice.h>
-
-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 <rtthread.h> +#include <rtdevice.h> +#include <rtservice.h> + +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 <rtthread.h>
-#include <drivers/usb_host.h>
-#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.h>
-
-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; i<ifinst->intf_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 <rtthread.h> +#include <drivers/usb_host.h> +#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.h> + +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; i<ifinst->intf_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 <rtthread.h>
-
-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 <rtthread.h> + +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 <rtthread.h>
-#include <drivers/usb_host.h>
-
-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; i<USB_MAX_DEVICE; i++)
- {
- /* to find an idle instance handle */
- if(uinst[i].status != UINST_STATUS_IDLE) continue;
-
- /* initialize the usb device instance */
- rt_memset(&uinst[i], 0, sizeof(struct uinstance));
-
- uinst[i].status = UINST_STATUS_BUSY;
- uinst[i].index = i + 1;
- uinst[i].address = 0;
- uinst[i].max_packet_size = 0x8;
-
- /* unlock scheduler */
- rt_exit_critical();
- return &uinst[i];
- }
-
- /* unlock scheduler */
- rt_exit_critical();
-
- return RT_NULL;
-}
-
-/**
- * This function will attatch an usb device instance to a host controller,
- * and do device enumunation process.
- *
- * @param hcd the host controller driver.
- * @param uinst the usb device instance.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_attatch_instance(uinst_t uinst)
-{
- int i = 0;
- rt_err_t ret = RT_EOK;
- struct uconfig_descriptor cfg_desc;
- udev_desc_t dev_desc;
- uintf_desc_t intf_desc;
- ucd_t drv;
-
- RT_ASSERT(uinst != RT_NULL);
-
- rt_memset(&cfg_desc, 0, sizeof(struct uconfig_descriptor));
- dev_desc = &uinst->dev_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; i<uinst->cfg_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; i<uinst->cfg_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 <rtthread.h> +#include <drivers/usb_host.h> + +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; i<USB_MAX_DEVICE; i++) + { + /* to find an idle instance handle */ + if(uinst[i].status != UINST_STATUS_IDLE) continue; + + /* initialize the usb device instance */ + rt_memset(&uinst[i], 0, sizeof(struct uinstance)); + + uinst[i].status = UINST_STATUS_BUSY; + uinst[i].index = i + 1; + uinst[i].address = 0; + uinst[i].max_packet_size = 0x8; + + /* unlock scheduler */ + rt_exit_critical(); + return &uinst[i]; + } + + /* unlock scheduler */ + rt_exit_critical(); + + return RT_NULL; +} + +/** + * This function will attatch an usb device instance to a host controller, + * and do device enumunation process. + * + * @param hcd the host controller driver. + * @param uinst the usb device instance. + * + * @return the error code, RT_EOK on successfully. + */ +rt_err_t rt_usb_attatch_instance(uinst_t uinst) +{ + int i = 0; + rt_err_t ret = RT_EOK; + struct uconfig_descriptor cfg_desc; + udev_desc_t dev_desc; + uintf_desc_t intf_desc; + ucd_t drv; + + RT_ASSERT(uinst != RT_NULL); + + rt_memset(&cfg_desc, 0, sizeof(struct uconfig_descriptor)); + dev_desc = &uinst->dev_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; i<uinst->cfg_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; i<uinst->cfg_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 <rtthread.h>
-#include <rtservice.h>
-#include <rtdevice.h>
-
-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 <rtthread.h> +#include <rtservice.h> +#include <rtdevice.h> + +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 <rtthread.h>
-#include <drivers/usb_host.h>
-
-#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; i<times; i++)
- {
- ret = rt_usb_hub_get_port_status(uhub, port, (rt_uint8_t*)&pstatus);
- if(ret != RT_EOK) return ret;
-
- if(!(pstatus & PORT_CCS))
- {
- connect = RT_FALSE;
- break;
- }
-
- rt_thread_delay(1);
- }
-
- if(connect) return RT_EOK;
- else return -RT_ERROR;
-}
-
-/**
- * This function will poll all the hub ports to detect port status, especially connect and
- * disconnect events.
- *
- * @param ifinst the interface instance.
- *
- * @return the error code, RT_EOK on successfully.
- */
-static rt_err_t rt_usb_hub_port_change(uhubinst_t uhub)
-{
- int i;
- rt_bool_t reconnect;
-
- /* parameter check */
- RT_ASSERT(uhub != RT_NULL);
-
- /* get usb device instance */
- for (i = 0; i < uhub->num_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; i<uhub->num_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 <rtthread.h> +#include <drivers/usb_host.h> + +#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; i<times; i++) + { + ret = rt_usb_hub_get_port_status(uhub, port, (rt_uint8_t*)&pstatus); + if(ret != RT_EOK) return ret; + + if(!(pstatus & PORT_CCS)) + { + connect = RT_FALSE; + break; + } + + rt_thread_delay(1); + } + + if(connect) return RT_EOK; + else return -RT_ERROR; +} + +/** + * This function will poll all the hub ports to detect port status, especially connect and + * disconnect events. + * + * @param ifinst the interface instance. + * + * @return the error code, RT_EOK on successfully. + */ +static rt_err_t rt_usb_hub_port_change(uhubinst_t uhub) +{ + int i; + rt_bool_t reconnect; + + /* parameter check */ + RT_ASSERT(uhub != RT_NULL); + + /* get usb device instance */ + for (i = 0; i < uhub->num_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; i<uhub->num_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 <rtthread.h>
-#include <drivers/usb_host.h>
-
-#if defined(RT_USB_HID_KEYBOARD) || defined(RT_USB_HID_MOUSE)
-#include <hid.h>
-#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 <rtthread.h> +#include <drivers/usb_host.h> + +#if defined(RT_USB_HID_KEYBOARD) || defined(RT_USB_HID_MOUSE) +#include <hid.h> +#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); +} + |
