Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Chance Z
rt-thread
提交
8fd0a7f9
R
rt-thread
项目概览
Chance Z
/
rt-thread
与 Fork 源项目一致
Fork自
RT-Thread / rt-thread
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rt-thread
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
8fd0a7f9
编写于
2月 16, 2014
作者:
qiuyiuestc
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Update USB Device Stack to support more device controllers;
Pass USB CV test verification; Code cleanup;
上级
db02f562
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
2172 addition
and
1034 deletion
+2172
-1034
components/drivers/include/drivers/usb_common.h
components/drivers/include/drivers/usb_common.h
+48
-15
components/drivers/include/drivers/usb_device.h
components/drivers/include/drivers/usb_device.h
+205
-112
components/drivers/usb/usbdevice/SConscript
components/drivers/usb/usbdevice/SConscript
+0
-3
components/drivers/usb/usbdevice/class/cdc_vcom.c
components/drivers/usb/usbdevice/class/cdc_vcom.c
+301
-256
components/drivers/usb/usbdevice/class/mstorage.c
components/drivers/usb/usbdevice/class/mstorage.c
+755
-300
components/drivers/usb/usbdevice/class/mstorage.h
components/drivers/usb/usbdevice/class/mstorage.h
+0
-7
components/drivers/usb/usbdevice/core/core.c
components/drivers/usb/usbdevice/core/core.c
+831
-311
components/drivers/usb/usbdevice/core/usbdevice.c
components/drivers/usb/usbdevice/core/usbdevice.c
+32
-30
未找到文件。
components/drivers/include/drivers/usb_common.h
浏览文件 @
8fd0a7f9
...
...
@@ -20,6 +20,7 @@
* Change Logs:
* Date Author Notes
* 2012-10-01 Yi Qiu first version
* 2013-04-26 aozima add DEVICEQUALIFIER support.
*/
#ifndef __USB_COMMON_H__
...
...
@@ -148,13 +149,22 @@ extern "C" {
#define USB_EPNO_MASK 0x7f
#define USB_DIR_OUT 0x00
#define USB_DIR_IN 0x80
#define USB_DIR_INOUT 0x40
#define USB_DIR_MASK 0x80
#define ID_UNASSIGNED 0
#define ID_ASSIGNED 1
#define RH_GET_PORT_STATUS 0
#define RH_SET_PORT_STATUS 1
#define RH_CLEAR_PORT_FEATURE 2
#define RH_SET_PORT_FEATURE 3
#define USB_BUS_POWERED 0
#define USB_SELF_POWERED 1
#define USB_REMOTE_WAKEUP 1
#define USB_EP_HALT 0
/*
* Port feature numbers
*/
...
...
@@ -205,6 +215,7 @@ extern "C" {
#define USB_EP_ATTR(attr) (attr & USB_EP_ATTR_TYPE_MASK)
#define USB_EP_DESC_NUM(addr) (addr & USB_EP_DESC_NUM_MASK)
#define USB_EP_DIR(addr) ((addr & USB_DIR_MASK)>>7)
#define uswap_32(x) \
((((x) & 0xff000000) >> 24) | \
...
...
@@ -239,7 +250,7 @@ struct usb_descriptor
};
typedef
struct
usb_descriptor
*
udesc_t
;
struct
udevice_descriptor
struct
udevice_descriptor
{
rt_uint8_t
bLength
;
rt_uint8_t
type
;
...
...
@@ -258,7 +269,7 @@ struct udevice_descriptor
};
typedef
struct
udevice_descriptor
*
udev_desc_t
;
struct
uconfig_descriptor
struct
uconfig_descriptor
{
rt_uint8_t
bLength
;
rt_uint8_t
type
;
...
...
@@ -272,7 +283,7 @@ struct uconfig_descriptor
};
typedef
struct
uconfig_descriptor
*
ucfg_desc_t
;
struct
uinterface_descriptor
struct
uinterface_descriptor
{
rt_uint8_t
bLength
;
rt_uint8_t
type
;
...
...
@@ -287,7 +298,7 @@ struct uinterface_descriptor
typedef
struct
uinterface_descriptor
*
uintf_desc_t
;
/* Interface Association Descriptor (IAD) */
struct
uiad_descriptor
struct
uiad_descriptor
{
rt_uint8_t
bLength
;
rt_uint8_t
bDescriptorType
;
...
...
@@ -300,7 +311,7 @@ struct uiad_descriptor
};
typedef
struct
uiad_descriptor
*
uiad_desc_t
;
struct
uendpoint_descriptor
struct
uendpoint_descriptor
{
rt_uint8_t
bLength
;
rt_uint8_t
type
;
...
...
@@ -311,7 +322,7 @@ struct uendpoint_descriptor
};
typedef
struct
uendpoint_descriptor
*
uep_desc_t
;
struct
ustring_descriptor
struct
ustring_descriptor
{
rt_uint8_t
bLength
;
rt_uint8_t
type
;
...
...
@@ -319,19 +330,34 @@ struct ustring_descriptor
};
typedef
struct
ustring_descriptor
*
ustr_desc_t
;
struct
uhub_descriptor
struct
uhub_descriptor
{
rt_uint8_t
length
;
rt_uint8_t
type
;
rt_uint8_t
num_ports
;
rt_uint16_t
characteristics
;
rt_uint16_t
characteristics
;
rt_uint8_t
pwron_to_good
;
/* power on to power good */
rt_uint8_t
current
;
rt_uint8_t
current
;
rt_uint8_t
removable
[
8
];
rt_uint8_t
pwr_ctl
[
8
];
};
typedef
struct
uhub_descriptor
*
uhub_desc_t
;
/* USB_DESC_TYPE_DEVICEQUALIFIER: Device Qualifier descriptor */
struct
usb_qualifier_descriptor
{
rt_uint8_t
bLength
;
rt_uint8_t
bDescriptorType
;
rt_uint16_t
bcdUSB
;
// TODO: big-endian.
rt_uint8_t
bDeviceClass
;
rt_uint8_t
bDeviceSubClass
;
rt_uint8_t
bDeviceProtocol
;
rt_uint8_t
bMaxPacketSize0
;
rt_uint8_t
bNumConfigurations
;
rt_uint8_t
bRESERVED
;
}
__attribute__
((
packed
));
struct
uhid_descriptor
{
rt_uint8_t
bLength
;
...
...
@@ -352,15 +378,17 @@ struct ureqest
rt_uint8_t
request_type
;
rt_uint8_t
request
;
rt_uint16_t
value
;
rt_uint16_t
index
;
rt_uint16_t
index
;
rt_uint16_t
length
;
};
typedef
struct
ureqest
*
ureq_t
;
#ifndef MIN
#define MIN(a, b) (a < b ? a : b)
#define MAX(a, b) (a > b ? a : b)
#endif
/*
/*
* the define related to mass storage
*/
#define USBREQ_GET_MAX_LUN 0xfe
...
...
@@ -368,6 +396,11 @@ typedef struct ureqest* ureq_t;
#define SIZEOF_CSW 0x0d
#define SIZEOF_CBW 0x1f
#define SIZEOF_INQUIRY_CMD 0x24
#define SIZEOF_MODE_SENSE_6 0x4
#define SIZEOF_READ_CAPACITIES 0xc
#define SIZEOF_READ_CAPACITY 0x8
#define SIZEOF_REQUEST_SENSE 0x12
#define CBWFLAGS_DIR_M 0x80
#define CBWFLAGS_DIR_IN 0x80
...
...
@@ -376,7 +409,7 @@ typedef struct ureqest* ureq_t;
#define SCSI_TEST_UNIT_READY 0x00
#define SCSI_REQUEST_SENSE 0x03
#define SCSI_INQUIRY_CMD 0x12
#define SCSI_ALLOW_
MEDIUM_REMOVAL
0x1e
#define SCSI_ALLOW_
REMOVAL
0x1e
#define SCSI_MODE_SENSE_6 0x1a
#define SCSI_START_STOP 0x1b
#define SCSI_READ_CAPACITIES 0x23
...
...
@@ -389,7 +422,7 @@ typedef struct ureqest* ureq_t;
#define CSW_SIGNATURE 0x53425355
#define CBW_TAG_VALUE 0x12345678
struct
ustorage_cbw
struct
ustorage_cbw
{
rt_uint32_t
signature
;
rt_uint32_t
tag
;
...
...
@@ -401,11 +434,11 @@ struct ustorage_cbw
};
typedef
struct
ustorage_cbw
*
ustorage_cbw_t
;
struct
ustorage_csw
struct
ustorage_csw
{
rt_uint32_t
signature
;
rt_uint32_t
tag
;
rt_
u
int32_t
data_reside
;
rt_int32_t
data_reside
;
rt_uint8_t
status
;
};
typedef
struct
ustorage_csw
*
ustorage_csw_t
;
...
...
components/drivers/include/drivers/usb_device.h
浏览文件 @
8fd0a7f9
...
...
@@ -20,7 +20,8 @@
* Change Logs:
* Date Author Notes
* 2012-10-01 Yi Qiu first version
* 2012-12-12 heyuanjie87 change endpoint and class handler
* 2012-12-12 heyuanjie87 change endpoint and function handler
* 2013-04-26 aozima add DEVICEQUALIFIER support.
*/
#ifndef __USB_DEVICE_H__
...
...
@@ -31,59 +32,115 @@
/* Vendor ID */
#ifdef USB_VENDOR_ID
#define _VENDOR_ID USB_VENDOR_ID
#define _VENDOR_ID
USB_VENDOR_ID
#else
#define _VENDOR_ID 0x0EFF
#define _VENDOR_ID
0x0EFF
#endif
/* Product ID */
#ifdef USB_PRODUCT_ID
#define _PRODUCT_ID USB_PRODUCT_ID
#define _PRODUCT_ID
USB_PRODUCT_ID
#else
#define _PRODUCT_ID 0x0001
#define _PRODUCT_ID
0x0001
#endif
#define USB_BCD_DEVICE 0x0200
/* USB Specification Release Number in Binary-Coded Decimal */
#define USB_BCD_VERSION 0x0200
/* USB 2.0 */
struct
uclass
;
#define USB_BCD_DEVICE 0x0200
/* USB Specification Release Number in Binary-Coded Decimal */
#define USB_BCD_VERSION 0x0200
/* USB 2.0 */
#define EP0_IN_ADDR 0x80
#define EP0_OUT_ADDR 0x00
#define EP_HANDLER(ep, func, size) RT_ASSERT(ep != RT_NULL); ep->handler(func, size)
#define EP_ADDRESS(ep) ep->ep_desc->bEndpointAddress
#define EP_MAXPACKET(ep) ep->ep_desc->wMaxPacketSize
#define FUNC_ENABLE(func) do{ \
if(func->ops->enable != RT_NULL && \
func->enabled == RT_FALSE) \
{ \
if(func->ops->enable(func) == RT_EOK) \
func->enabled = RT_TRUE; \
} \
}while(0)
#define FUNC_DISABLE(func) do{ \
if(func->ops->disable != RT_NULL && \
func->enabled == RT_TRUE) \
{ \
func->enabled = RT_FALSE; \
func->ops->disable(func); \
} \
}while(0)
struct
ufunction
;
struct
udevice
;
struct
uendpoint
;
typedef
enum
{
/* request to read full count */
UIO_REQUEST_READ_FULL
,
/* request to read any count */
UIO_REQUEST_READ_BEST
,
/* request to write full count */
UIO_REQUEST_WRITE
,
}
UIO_REQUEST_TYPE
;
struct
udcd_ops
{
rt_err_t
(
*
set_address
)(
rt_uint8_t
value
);
rt_err_t
(
*
clear_feature
)(
rt_uint16_t
value
,
rt_uint16_t
index
);
rt_err_t
(
*
set_feature
)(
rt_uint16_t
value
,
rt_uint16_t
index
);
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
);
rt_err_t
(
*
send_status
)(
void
);
rt_err_t
(
*
set_address
)(
rt_uint8_t
address
);
rt_err_t
(
*
set_config
)(
rt_uint8_t
address
);
rt_err_t
(
*
ep_set_stall
)(
rt_uint8_t
address
);
rt_err_t
(
*
ep_clear_stall
)(
rt_uint8_t
address
);
rt_err_t
(
*
ep_enable
)(
struct
uendpoint
*
ep
);
rt_err_t
(
*
ep_disable
)(
struct
uendpoint
*
ep
);
rt_size_t
(
*
ep_read_prepare
)(
rt_uint8_t
address
,
void
*
buffer
,
rt_size_t
size
);
rt_size_t
(
*
ep_read
)(
rt_uint8_t
address
,
void
*
buffer
);
rt_size_t
(
*
ep_write
)(
rt_uint8_t
address
,
void
*
buffer
,
rt_size_t
size
);
rt_err_t
(
*
ep0_send_status
)(
void
);
rt_err_t
(
*
suspend
)(
void
);
rt_err_t
(
*
wakeup
)(
void
);
};
struct
udc
d
struct
ep_i
d
{
struct
rt_device
parent
;
struct
udcd_ops
*
ops
;
struct
rt_completion
completion
;
rt_uint8_t
addr
;
rt_uint8_t
type
;
rt_uint8_t
dir
;
rt_uint8_t
maxpacket
;
rt_uint8_t
status
;
};
typedef
struct
udcd
*
udcd_t
;
typedef
rt_err_t
(
*
udep_handler_t
)(
struct
u
device
*
device
,
struct
uclass
*
cls
,
rt_size_t
size
);
typedef
rt_err_t
(
*
udep_handler_t
)(
struct
u
function
*
func
,
rt_size_t
size
);
struct
u
endpoin
t
struct
u
io_reques
t
{
rt_list_t
list
;
UIO_REQUEST_TYPE
req_type
;
rt_uint8_t
*
buffer
;
rt_size_t
size
;
rt_size_t
remain_size
;
};
typedef
struct
uio_request
*
uio_request_t
;
struct
uendpoint
{
rt_list_t
list
;
uep_desc_t
ep_desc
;
rt_list_t
request_list
;
struct
uio_request
request
;
rt_uint8_t
*
buffer
;
rt_bool_t
stalled
;
struct
ep_id
*
id
;
udep_handler_t
handler
;
rt_
bool_t
is_stall
;
rt_
err_t
(
*
rx_indicate
)(
struct
udevice
*
dev
,
rt_size_t
size
)
;
};
typedef
struct
uendpoint
*
uep_t
;
struct
udcd
{
struct
rt_device
parent
;
const
struct
udcd_ops
*
ops
;
struct
uendpoint
ep0
;
struct
ep_id
*
ep_pool
;
};
typedef
struct
udcd
*
udcd_t
;
struct
ualtsetting
{
rt_list_t
list
;
...
...
@@ -94,7 +151,7 @@ struct ualtsetting
};
typedef
struct
ualtsetting
*
ualtsetting_t
;
typedef
rt_err_t
(
*
uintf_handler_t
)(
struct
u
device
*
device
,
struct
uclass
*
cls
,
ureq_t
setup
);
typedef
rt_err_t
(
*
uintf_handler_t
)(
struct
u
function
*
func
,
ureq_t
setup
);
struct
uinterface
{
...
...
@@ -106,32 +163,32 @@ struct uinterface
};
typedef
struct
uinterface
*
uintf_t
;
struct
u
class
_ops
struct
u
function
_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
u
device
*
device
,
struct
uclass
*
cls
);
rt_err_t
(
*
enable
)(
struct
ufunction
*
func
);
rt_err_t
(
*
disable
)(
struct
ufunction
*
func
);
rt_err_t
(
*
sof_handler
)(
struct
u
function
*
func
);
};
typedef
struct
u
class_ops
*
uclass
_ops_t
;
typedef
struct
u
function_ops
*
ufunction
_ops_t
;
struct
u
class
struct
u
function
{
rt_list_t
list
;
uclass_ops_t
ops
;
void
*
eps
;
ufunction_ops_t
ops
;
struct
udevice
*
device
;
udev_desc_t
dev_desc
;
void
*
user_data
;
rt_bool_t
enabled
;
rt_list_t
intf_list
;
};
typedef
struct
u
class
*
uclass
_t
;
typedef
struct
u
function
*
ufunction
_t
;
struct
uconfig
{
rt_list_t
list
;
struct
uconfig_descriptor
cfg_desc
;
rt_list_t
cls
_list
;
rt_list_t
func
_list
;
};
typedef
struct
uconfig
*
uconfig_t
;
...
...
@@ -139,6 +196,8 @@ struct udevice
{
rt_list_t
list
;
struct
udevice_descriptor
dev_desc
;
struct
usb_qualifier_descriptor
*
dev_qualifier
;
const
char
**
str
;
udevice_state_t
state
;
...
...
@@ -154,8 +213,11 @@ enum udev_msg_type
{
USB_MSG_SETUP_NOTIFY
,
USB_MSG_DATA_NOTIFY
,
USB_MSG_EP0_OUT
,
USB_MSG_EP_CLEAR_FEATURE
,
USB_MSG_SOF
,
USB_MSG_RESET
,
USB_MSG_PLUG_IN
,
/* we don't need to add a "PLUG_IN" event because after the cable is
* plugged in(before any SETUP) the classed have nothing to do. If the host
* is ready, it will send RESET and we will have USB_MSG_RESET. So, a RESET
...
...
@@ -164,153 +226,184 @@ enum udev_msg_type
};
typedef
enum
udev_msg_type
udev_msg_type
;
struct
ep_msg
{
rt_size_t
size
;
rt_uint8_t
ep_addr
;
};
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
;
struct
ep_msg
ep_msg
;
struct
ureqest
setup
;
}
content
;
};
typedef
struct
udev_msg
*
udev_msg_t
;
udevice_t
rt_usbd_device_create
(
void
);
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
);
udevice_t
rt_usbd_device_new
(
void
);
uconfig_t
rt_usbd_config_new
(
void
);
ufunction_t
rt_usbd_function_new
(
udevice_t
device
,
udev_desc_t
dev_desc
,
ufunction_ops_t
ops
);
uintf_t
rt_usbd_interface_new
(
udevice_t
device
,
uintf_handler_t
handler
);
uep_t
rt_usbd_endpoint_new
(
uep_desc_t
ep_desc
,
udep_handler_t
handler
);
ualtsetting_t
rt_usbd_altsetting_new
(
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_usb_device_init
(
void
);
rt_err_t
rt_usbd_event_signal
(
struct
udev_msg
*
msg
);
rt_err_t
rt_usbd_device_set_controller
(
udevice_t
device
,
udcd_t
dcd
);
rt_err_t
rt_usbd_device_set_descriptor
(
udevice_t
device
,
udev_desc_t
dev_desc
);
rt_err_t
rt_usbd_device_set_string
(
udevice_t
device
,
const
char
**
ustring
);
rt_err_t
rt_usbd_device_set_qualifier
(
udevice_t
device
,
struct
usb_qualifier_descriptor
*
qualifier
);
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_config_add_
function
(
uconfig_t
cfg
,
ufunction_t
func
);
rt_err_t
rt_usbd_
function_add_interface
(
ufunction_t
func
,
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_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
);
u
class_t
rt_usbd_class
_mstorage_create
(
udevice_t
device
);
u
class_t
rt_usbd_class
_cdc_create
(
udevice_t
device
);
u
class_t
rt_usbd_class
_rndis_create
(
udevice_t
device
);
u
class_t
rt_usbd_class
_dap_create
(
udevice_t
device
);
uintf_t
rt_usbd_find_interface
(
udevice_t
device
,
rt_uint8_t
value
,
ufunction_t
*
pfunc
);
uep_t
rt_usbd_find_endpoint
(
udevice_t
device
,
ufunction_t
*
pfunc
,
rt_uint8_t
ep_addr
);
rt_size_t
rt_usbd_io_request
(
udevice_t
device
,
uep_t
ep
,
uio_request_t
req
);
rt_size_t
rt_usbd_ep0_write
(
udevice_t
device
,
void
*
buffer
,
rt_size_t
size
);
rt_size_t
rt_usbd_ep0_read
(
udevice_t
device
,
void
*
buffer
,
rt_size_t
size
,
rt_err_t
(
*
rx_ind
)(
udevice_t
device
,
rt_size_t
size
)
);
u
function_t
rt_usbd_function
_mstorage_create
(
udevice_t
device
);
u
function_t
rt_usbd_function
_cdc_create
(
udevice_t
device
);
u
function_t
rt_usbd_function
_rndis_create
(
udevice_t
device
);
u
function_t
rt_usbd_function
_dap_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
);
rt_err_t
rt_usbd_
function_set_iad
(
ufunction_t
func
,
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_uint16_t
value
,
rt_uint16_t
index
)
rt_err_t
rt_usbd_set_feature
(
udevice_t
device
,
rt_uint16_t
value
,
rt_uint16_t
index
);
rt_err_t
rt_usbd_clear_feature
(
udevice_t
device
,
rt_uint16_t
value
,
rt_uint16_t
index
);
rt_err_t
rt_usbd_ep_set_stall
(
udevice_t
device
,
uep_t
ep
);
rt_err_t
rt_usbd_ep_clear_stall
(
udevice_t
device
,
uep_t
ep
);
rt_err_t
rt_usbd_ep0_set_stall
(
udevice_t
device
);
rt_err_t
rt_usbd_ep0_clear_stall
(
udevice_t
device
);
rt_err_t
rt_usbd_ep0_setup_handler
(
udcd_t
dcd
,
struct
ureqest
*
setup
);
rt_err_t
rt_usbd_ep0_in_handler
(
udcd_t
dcd
);
rt_err_t
rt_usbd_ep0_out_handler
(
udcd_t
dcd
,
rt_size_t
size
);
rt_err_t
rt_usbd_ep_in_handler
(
udcd_t
dcd
,
rt_uint8_t
address
);
rt_err_t
rt_usbd_ep_out_handler
(
udcd_t
dcd
,
rt_uint8_t
address
,
rt_size_t
size
);
rt_err_t
rt_usbd_reset_handler
(
udcd_t
dcd
);
rt_err_t
rt_usbd_connect_handler
(
udcd_t
dcd
);
rt_err_t
rt_usbd_disconnect_handler
(
udcd_t
dcd
);
rt_err_t
rt_usbd_sof_handler
(
udcd_t
dcd
);
rt_inline
rt_err_t
dcd_set_address
(
udcd_t
dcd
,
rt_uint8_t
address
)
{
RT_ASSERT
(
dcd
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
->
set_address
!=
RT_NULL
);
return
dcd
->
ops
->
clear_feature
(
value
,
index
);
return
dcd
->
ops
->
set_address
(
address
);
}
rt_inline
rt_err_t
dcd_set_feature
(
udcd_t
dcd
,
rt_uint8_t
value
,
rt_uint16_t
index
)
rt_inline
rt_err_t
dcd_set_config
(
udcd_t
dcd
,
rt_uint8_t
address
)
{
RT_ASSERT
(
dcd
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
->
set_config
!=
RT_NULL
);
return
dcd
->
ops
->
set_
feature
(
value
,
index
);
return
dcd
->
ops
->
set_
config
(
address
);
}
rt_inline
rt_err_t
dcd_ep_
stall
(
udcd_t
dcd
,
uep_t
ep
)
rt_inline
rt_err_t
dcd_ep_
enable
(
udcd_t
dcd
,
uep_t
ep
)
{
RT_ASSERT
(
dcd
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
->
ep_enable
!=
RT_NULL
);
return
dcd
->
ops
->
ep_
stall
(
ep
);
return
dcd
->
ops
->
ep_
enable
(
ep
);
}
rt_inline
rt_
uint8_t
dcd_ep_alloc
(
udcd_t
dcd
,
uep_t
ep
)
rt_inline
rt_
err_t
dcd_ep_disable
(
udcd_t
dcd
,
uep_t
ep
)
{
RT_ASSERT
(
dcd
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
->
ep_disable
!=
RT_NULL
);
return
dcd
->
ops
->
ep_
alloc
(
ep
);
return
dcd
->
ops
->
ep_
disable
(
ep
);
}
rt_inline
rt_err_t
dcd_ep_free
(
udcd_t
dcd
,
uep_t
ep
)
rt_inline
rt_size_t
dcd_ep_read_prepare
(
udcd_t
dcd
,
rt_uint8_t
address
,
void
*
buffer
,
rt_size_t
size
)
{
RT_ASSERT
(
dcd
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
!=
RT_NULL
);
return
dcd
->
ops
->
ep_free
(
ep
);
if
(
dcd
->
ops
->
ep_read_prepare
!=
RT_NULL
)
{
return
dcd
->
ops
->
ep_read_prepare
(
address
,
buffer
,
size
);
}
else
{
return
0
;
}
}
rt_inline
rt_
err_t
dcd_ep_run
(
udcd_t
dcd
,
uep_t
ep
)
rt_inline
rt_
size_t
dcd_ep_read
(
udcd_t
dcd
,
rt_uint8_t
address
,
void
*
buffer
)
{
RT_ASSERT
(
dcd
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
!=
RT_NULL
);
return
dcd
->
ops
->
ep_run
(
ep
);
if
(
dcd
->
ops
->
ep_read
!=
RT_NULL
)
{
return
dcd
->
ops
->
ep_read
(
address
,
buffer
);
}
else
{
return
0
;
}
}
rt_inline
rt_err_t
dcd_ep_stop
(
udcd_t
dcd
,
uep_t
ep
)
rt_inline
rt_size_t
dcd_ep_write
(
udcd_t
dcd
,
rt_uint8_t
address
,
void
*
buffer
,
rt_size_t
size
)
{
RT_ASSERT
(
dcd
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
->
ep_write
!=
RT_NULL
);
return
dcd
->
ops
->
ep_
stop
(
ep
);
return
dcd
->
ops
->
ep_
write
(
address
,
buffer
,
size
);
}
rt_inline
rt_err_t
dcd_ep_read
(
udcd_t
dcd
,
uep_t
ep
,
void
*
buffer
,
rt_size_t
size
)
rt_inline
rt_err_t
dcd_ep0_send_status
(
udcd_t
dcd
)
{
RT_ASSERT
(
dcd
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
->
ep0_send_status
!=
RT_NULL
);
return
dcd
->
ops
->
ep
_read
(
ep
,
buffer
,
size
);
return
dcd
->
ops
->
ep
0_send_status
(
);
}
rt_inline
rt_size_t
dcd_ep_write
(
udcd_t
dcd
,
uep_t
ep
,
void
*
buffer
,
rt_size_t
size
)
{
rt_inline
rt_err_t
dcd_ep_set_stall
(
udcd_t
dcd
,
rt_uint8_t
address
)
{
RT_ASSERT
(
dcd
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
->
ep_set_stall
!=
RT_NULL
);
return
dcd
->
ops
->
ep_
write
(
ep
,
buffer
,
size
);
return
dcd
->
ops
->
ep_
set_stall
(
address
);
}
rt_inline
rt_err_t
dcd_
send_status
(
udcd_t
dcd
)
rt_inline
rt_err_t
dcd_
ep_clear_stall
(
udcd_t
dcd
,
rt_uint8_t
address
)
{
RT_ASSERT
(
dcd
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
!=
RT_NULL
);
RT_ASSERT
(
dcd
->
ops
->
ep_clear_stall
!=
RT_NULL
);
return
dcd
->
ops
->
send_status
(
);
return
dcd
->
ops
->
ep_clear_stall
(
address
);
}
#endif
components/drivers/usb/usbdevice/SConscript
浏览文件 @
8fd0a7f9
...
...
@@ -13,9 +13,6 @@ if GetDepend('RT_USB_DEVICE_CDC'):
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
)
...
...
components/drivers/usb/usbdevice/class/cdc_vcom.c
浏览文件 @
8fd0a7f9
...
...
@@ -20,34 +20,56 @@
* Change Logs:
* Date Author Notes
* 2012-10-02 Yi Qiu first version
* 2012-12-12 heyuanjie87 change endpoints and class handler
* 2012-12-12 heyuanjie87 change endpoints and function handler
* 2013-06-25 heyuanjie87 remove SOF mechinism
* 2013-07-20 Yi Qiu do more test
*/
#include <rtthread.h>
#include <rtservice.h>
#include <rtdevice.h>
#include <rthw.h>
#include "cdc.h"
#ifdef RT_USB_DEVICE_CDC
#define TX_TIMEOUT 100
#define CDC_RX_BUFSIZE 2048
#define CDC_TX_BUFSIZE 2048
static
rt_uint8_t
rx_rbp
[
CDC_RX_BUFSIZE
];
static
rt_uint8_t
tx_rbp
[
CDC_TX_BUFSIZE
];
static
struct
rt_ringbuffer
rx_ringbuffer
;
static
struct
rt_ringbuffer
tx_ringbuffer
;
static
struct
serial_ringbuffer
vcom_int_rx
;
#define CDC_MAX_PACKET_SIZE 64
#define VCOM_DEVICE "vcom"
static
struct
rt_serial_device
vcom_serial
;
#define CDC_MaxPacketSize 64
ALIGN
(
RT_ALIGN_SIZE
)
static
rt_uint8_t
rx_buf
[
CDC_RX_BUFSIZE
];
ALIGN
(
RT_ALIGN_SIZE
)
static
rt_uint8_t
tx_buf
[
CDC_TX_BUFSIZE
];
static
rt_uint8_t
vcom_thread_stack
[
512
];
static
struct
rt_thread
vcom_thread
;
#define VCOM_MQ_MSG_SZ 16
#define VCOM_MQ_MAX_MSG 4
/* internal of the message queue: every message is associated with a pointer,
* so in order to recveive VCOM_MQ_MAX_MSG messages, we have to allocate more
* than VCOM_MQ_MSG_SZ*VCOM_MQ_MAX_MSG memery. */
static
rt_uint8_t
vcom_tx_thread_mq_pool
[(
VCOM_MQ_MSG_SZ
+
sizeof
(
void
*
))
*
VCOM_MQ_MAX_MSG
];
static
struct
rt_messagequeue
vcom_tx_thread_mq
;
static
struct
ucdc_line_coding
line_coding
;
struct
vcom
{
struct
rt_serial_device
serial
;
uep_t
ep_out
;
uep_t
ep_in
;
uep_t
ep_cmd
;
rt_bool_t
connected
;
rt_bool_t
in_sending
;
struct
rt_completion
wait
;
rt_uint8_t
rx_rbp
[
CDC_RX_BUFSIZE
];
struct
rt_ringbuffer
rx_ringbuffer
;
struct
serial_ringbuffer
vcom_int_rx
;
};
volatile
static
rt_bool_t
vcom_connected
=
RT_FALSE
;
volatile
static
rt_bool_t
vcom_in_sending
=
RT_FALSE
;
struct
vcom_tx_msg
{
struct
rt_serial_device
*
serial
;
const
char
*
buf
;
rt_size_t
size
;
};
static
struct
udevice_descriptor
dev_desc
=
{
...
...
@@ -57,7 +79,7 @@ static struct udevice_descriptor dev_desc =
USB_CLASS_CDC
,
//bDeviceClass;
0x00
,
//bDeviceSubClass;
0x00
,
//bDeviceProtocol;
CDC_M
axPacketSize
,
//bMaxPacketSize0;
CDC_M
AX_PACKET_SIZE
,
//bMaxPacketSize0;
_VENDOR_ID
,
//idVendor;
_PRODUCT_ID
,
//idProduct;
USB_BCD_DEVICE
,
//bcdDevice;
...
...
@@ -67,6 +89,18 @@ static struct udevice_descriptor dev_desc =
USB_DYNAMIC
,
//bNumConfigurations;
};
static
struct
usb_qualifier_descriptor
dev_qualifier
=
{
sizeof
(
dev_qualifier
),
USB_DESC_TYPE_DEVICEQUALIFIER
,
0x0200
,
USB_CLASS_CDC
,
0x00
,
64
,
0x01
,
0
,
};
/* communcation interface descriptor */
const
static
struct
ucdc_comm_descriptor
_comm_desc
=
{
...
...
@@ -85,19 +119,19 @@ const static struct ucdc_comm_descriptor _comm_desc =
USB_DESC_LENGTH_INTERFACE
,
USB_DESC_TYPE_INTERFACE
,
USB_DYNAMIC
,
0x00
,
0x00
,
0x01
,
USB_CDC_CLASS_COMM
,
USB_CDC_SUBCLASS_ACM
,
USB_CDC_PROTOCOL_V25TER
,
0x00
,
/* Header Functional Descriptor */
0x05
,
/* Header Functional Descriptor */
0x05
,
USB_CDC_CS_INTERFACE
,
USB_CDC_SCS_HEADER
,
0x0110
,
/* Call Management Functional Descriptor */
0x05
,
/* Call Management Functional Descriptor */
0x05
,
USB_CDC_CS_INTERFACE
,
USB_CDC_SCS_CALL_MGMT
,
0x00
,
...
...
@@ -107,13 +141,13 @@ const static struct ucdc_comm_descriptor _comm_desc =
USB_CDC_CS_INTERFACE
,
USB_CDC_SCS_ACM
,
0x02
,
/* Union Functional Descriptor */
/* Union Functional Descriptor */
0x05
,
USB_CDC_CS_INTERFACE
,
USB_CDC_SCS_UNION
,
USB_DYNAMIC
,
USB_DYNAMIC
,
/* Endpoint Descriptor */
/* Endpoint Descriptor */
USB_DESC_LENGTH_ENDPOINT
,
USB_DESC_TYPE_ENDPOINT
,
USB_DYNAMIC
|
USB_DIR_IN
,
...
...
@@ -130,23 +164,23 @@ const static struct ucdc_data_descriptor _data_desc =
USB_DESC_TYPE_INTERFACE
,
USB_DYNAMIC
,
0x00
,
0x02
,
0x02
,
USB_CDC_CLASS_DATA
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
/* endpoint, bulk out */
USB_DESC_LENGTH_ENDPOINT
,
USB_DESC_LENGTH_ENDPOINT
,
USB_DESC_TYPE_ENDPOINT
,
USB_DYNAMIC
|
USB_DIR_OUT
,
USB_EP_ATTR_BULK
,
USB_EP_ATTR_BULK
,
USB_CDC_BUFSIZE
,
0x00
,
0x00
,
/* endpoint, bulk in */
USB_DESC_LENGTH_ENDPOINT
,
USB_DESC_TYPE_ENDPOINT
,
USB_DYNAMIC
|
USB_DIR_IN
,
USB_EP_ATTR_BULK
,
USB_EP_ATTR_BULK
,
USB_CDC_BUFSIZE
,
0x00
,
};
...
...
@@ -156,18 +190,24 @@ const static char* _ustring[] =
"Language"
,
"RT-Thread Team."
,
"RTT Virtual Serial"
,
"
1.1.0
"
,
"
32021919830108
"
,
"Configuration"
,
"Interface"
,
};
static
void
rt_usb_vcom_init
(
struct
ufunction
*
func
);
static
void
_vcom_reset_state
(
void
)
static
void
_vcom_reset_state
(
ufunction_t
func
)
{
int
lvl
=
rt_hw_interrupt_disable
();
tx_ringbuffer
.
read_mirror
=
tx_ringbuffer
.
read_index
=
0
;
tx_ringbuffer
.
write_mirror
=
tx_ringbuffer
.
write_index
=
0
;
vcom_connected
=
RT_FALSE
;
vcom_in_sending
=
RT_FALSE
;
struct
vcom
*
data
;
int
lvl
;
RT_ASSERT
(
func
!=
RT_NULL
)
data
=
(
struct
vcom
*
)
func
->
user_data
;
lvl
=
rt_hw_interrupt_disable
();
data
->
connected
=
RT_FALSE
;
data
->
in_sending
=
RT_FALSE
;
/*rt_kprintf("reset USB serial\n", cnt);*/
rt_hw_interrupt_enable
(
lvl
);
}
...
...
@@ -175,95 +215,73 @@ static void _vcom_reset_state(void)
/**
* This function will handle cdc bulk in endpoint request.
*
* @param
device the usb device
object.
* @param
func the usb function
object.
* @param size request size.
*
* @return RT_EOK.
*/
static
rt_err_t
_ep_in_handler
(
u
device_t
device
,
uclass_t
cls
,
rt_size_t
size
)
static
rt_err_t
_ep_in_handler
(
u
function_t
func
,
rt_size_t
size
)
{
rt_uint32_t
level
;
rt_uint32_t
remain
;
cdc_eps_t
eps
;
struct
vcom
*
data
;
eps
=
(
cdc_eps_t
)
cls
->
eps
;
level
=
rt_hw_interrupt_disable
();
remain
=
rt_ringbuffer_data_len
(
&
tx_ringbuffer
);
if
(
remain
!=
0
)
{
/* although vcom_in_sending is set in SOF handler in the very
* beginning, we have to guarantee the state is right when start
* sending. There is at least one extreme case where we have finished the
* last IN transaction but the vcom_in_sending is RT_FALSE.
*
* Ok, what the extreme case is: pour data into vcom in loop. Open
* terminal on the PC, you will see the data. Then close it. So the
* data will be sent to the PC in the back. When the buffer of the PC
* driver is full. It will not send IN packet to the board and you will
* have no chance to clear vcom_in_sending in this function. The data
* will fill into the ringbuffer until it is full, and we will reset
* the state machine and clear vcom_in_sending. When you open the
* terminal on the PC again. The IN packet will appear on the line and
* we will, eventually, reach here with vcom_in_sending is clear.
*/
vcom_in_sending
=
RT_TRUE
;
rt_ringbuffer_get
(
&
tx_ringbuffer
,
eps
->
ep_in
->
buffer
,
remain
);
rt_hw_interrupt_enable
(
level
);
/* send data to host */
dcd_ep_write
(
device
->
dcd
,
eps
->
ep_in
,
eps
->
ep_in
->
buffer
,
remain
);
RT_ASSERT
(
func
!=
RT_NULL
);
return
RT_EOK
;
}
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_ep_in_handler %d
\n
"
,
size
));
if
(
size
!=
0
&&
(
size
%
CDC_MaxPacketSize
)
==
0
)
data
=
(
struct
vcom
*
)
func
->
user_data
;
if
((
size
!=
0
)
&&
(
size
%
CDC_MAX_PACKET_SIZE
==
0
)
)
{
/* don't have data right now. Send a zero-length-packet to
* terminate the transaction.
*
* FIXME: actually, this might not be the right place to send zlp.
* Only the rt_device_write could know how much data is sending. */
vcom_in_sending
=
RT_TRUE
;
rt_hw_interrupt_enable
(
level
);
dcd_ep_write
(
device
->
dcd
,
eps
->
ep_in
,
RT_NULL
,
0
);
return
RT_EOK
;
}
else
{
vcom_in_sending
=
RT_FALSE
;
rt_hw_interrupt_enable
(
level
);
data
->
in_sending
=
RT_TRUE
;
data
->
ep_in
->
request
.
buffer
=
RT_NULL
;
data
->
ep_in
->
request
.
size
=
0
;
data
->
ep_in
->
request
.
req_type
=
UIO_REQUEST_WRITE
;
rt_usbd_io_request
(
func
->
device
,
data
->
ep_in
,
&
data
->
ep_in
->
request
);
return
RT_EOK
;
}
rt_completion_done
(
&
data
->
wait
);
return
RT_EOK
;
}
/**
* This function will handle cdc bulk out endpoint request.
*
* @param
device the usb device
object.
* @param
func the usb function
object.
* @param size request size.
*
* @return RT_EOK.
*/
static
rt_err_t
_ep_out_handler
(
u
device_t
device
,
uclass_t
cls
,
rt_size_t
size
)
static
rt_err_t
_ep_out_handler
(
u
function_t
func
,
rt_size_t
size
)
{
rt_uint32_t
level
;
cdc_eps_t
eps
;
struct
vcom
*
data
;
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
func
!=
RT_NULL
);
eps
=
(
cdc_eps_t
)
cls
->
eps
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_ep_out_handler %d
\n
"
,
size
));
data
=
(
struct
vcom
*
)
func
->
user_data
;
/* receive data from USB VCOM */
level
=
rt_hw_interrupt_disable
();
rt_ringbuffer_put
(
&
rx_ringbuffer
,
eps
->
ep_out
->
buffer
,
size
);
rt_ringbuffer_put
(
&
data
->
rx_ringbuffer
,
data
->
ep_out
->
buffer
,
size
);
rt_hw_interrupt_enable
(
level
);
/* notify receive data */
rt_hw_serial_isr
(
&
vcom_
serial
);
rt_hw_serial_isr
(
&
data
->
serial
);
dcd_ep_read
(
device
->
dcd
,
eps
->
ep_out
,
eps
->
ep_out
->
buffer
,
eps
->
ep_out
->
ep_desc
->
wMaxPacketSize
);
data
->
ep_out
->
request
.
buffer
=
data
->
ep_out
->
buffer
;
data
->
ep_out
->
request
.
size
=
EP_MAXPACKET
(
data
->
ep_out
);
data
->
ep_out
->
request
.
req_type
=
UIO_REQUEST_READ_BEST
;
rt_usbd_io_request
(
func
->
device
,
data
->
ep_out
,
&
data
->
ep_out
->
request
);
return
RT_EOK
;
}
...
...
@@ -276,9 +294,9 @@ static rt_err_t _ep_out_handler(udevice_t device, uclass_t cls, rt_size_t size)
*
* @return RT_EOK.
*/
static
rt_err_t
_ep_cmd_handler
(
u
device_t
device
,
uclass_t
cls
,
rt_size_t
size
)
static
rt_err_t
_ep_cmd_handler
(
u
function_t
func
,
rt_size_t
size
)
{
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
func
!=
RT_NULL
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_ep_cmd_handler
\n
"
));
...
...
@@ -301,14 +319,25 @@ static rt_err_t _cdc_get_line_coding(udevice_t device, ureq_t setup)
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
setup
!=
RT_NULL
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_cdc_get_line_coding
\n
"
));
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
);
rt_usbd_ep0_write
(
device
,
(
void
*
)
&
data
,
size
);
return
RT_EOK
;
}
static
rt_err_t
_cdc_set_line_coding_callback
(
udevice_t
device
,
rt_size_t
size
)
{
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_cdc_set_line_coding_callback
\n
"
));
dcd_ep0_send_status
(
device
->
dcd
);
return
RT_EOK
;
}
...
...
@@ -322,21 +351,13 @@ static rt_err_t _cdc_get_line_coding(udevice_t device, ureq_t setup)
*/
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
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_cdc_set_line_coding
\n
"
)
);
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
"
);
}
rt_usbd_ep0_read
(
device
,
(
void
*
)
&
line_coding
,
sizeof
(
struct
ucdc_line_coding
),
_cdc_set_line_coding_callback
);
return
RT_EOK
;
}
...
...
@@ -349,11 +370,16 @@ static rt_err_t _cdc_set_line_coding(udevice_t device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
static
rt_err_t
_interface_handler
(
u
device_t
device
,
uclass_t
cls
,
ureq_t
setup
)
static
rt_err_t
_interface_handler
(
u
function_t
func
,
ureq_t
setup
)
{
RT_ASSERT
(
device
!=
RT_NULL
);
struct
vcom
*
data
;
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
func
->
device
!=
RT_NULL
);
RT_ASSERT
(
setup
!=
RT_NULL
);
data
=
(
struct
vcom
*
)
func
->
user_data
;
switch
(
setup
->
request
)
{
case
CDC_SEND_ENCAPSULATED_COMMAND
:
...
...
@@ -367,14 +393,14 @@ static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup)
case
CDC_CLEAR_COMM_FEATURE
:
break
;
case
CDC_SET_LINE_CODING
:
_cdc_set_line_coding
(
device
,
setup
);
vcom_connected
=
RT_TRUE
;
_cdc_set_line_coding
(
func
->
device
,
setup
);
data
->
connected
=
RT_TRUE
;
break
;
case
CDC_GET_LINE_CODING
:
_cdc_get_line_coding
(
device
,
setup
);
_cdc_get_line_coding
(
func
->
device
,
setup
);
break
;
case
CDC_SET_CONTROL_LINE_STATE
:
dcd_
send_status
(
device
->
dcd
);
dcd_
ep0_send_status
(
func
->
device
->
dcd
);
break
;
case
CDC_SEND_BREAK
:
break
;
...
...
@@ -387,92 +413,66 @@ static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup)
}
/**
* This function will run cdc
class
, it will be called on handle set configuration request.
* This function will run cdc
function
, it will be called on handle set configuration request.
*
* @param
device the usb device
object.
* @param
func the usb function
object.
*
* @return RT_EOK on successful.
*/
static
rt_err_t
_
class_run
(
udevice_t
device
,
uclass_t
cls
)
static
rt_err_t
_
function_enable
(
ufunction_t
func
)
{
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
;
struct
vcom
*
data
;
eps
->
ep_in
->
buffer
=
tx_buf
;
eps
->
ep_out
->
buffer
=
rx_buf
;
RT_ASSERT
(
func
!=
RT_NULL
);
_vcom_reset_state
(
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"cdc function enable
\n
"
)
);
dcd_ep_read
(
device
->
dcd
,
eps
->
ep_out
,
eps
->
ep_out
->
buffer
,
eps
->
ep_out
->
ep_desc
->
wMaxPacketSize
);
_vcom_reset_state
(
func
);
data
=
(
struct
vcom
*
)
func
->
user_data
;
data
->
ep_out
->
buffer
=
rt_malloc
(
CDC_RX_BUFSIZE
);
data
->
ep_out
->
request
.
buffer
=
data
->
ep_out
->
buffer
;
data
->
ep_out
->
request
.
size
=
EP_MAXPACKET
(
data
->
ep_out
);
data
->
ep_out
->
request
.
req_type
=
UIO_REQUEST_READ_BEST
;
rt_usbd_io_request
(
func
->
device
,
data
->
ep_out
,
&
data
->
ep_out
->
request
);
return
RT_EOK
;
}
/**
* This function will stop cdc
class
, it will be called on handle set configuration request.
* This function will stop cdc
function
, it will be called on handle set configuration request.
*
* @param
device the usb device
object.
* @param
func the usb function
object.
*
* @return RT_EOK on successful.
*/
static
rt_err_t
_
class_stop
(
udevice_t
device
,
uclass_t
cls
)
static
rt_err_t
_
function_disable
(
ufunction_t
func
)
{
RT_ASSERT
(
device
!=
RT_NULL
)
;
struct
vcom
*
data
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"cdc class stop
\n
"
));
_vcom_reset_state
();
return
RT_EOK
;
}
RT_ASSERT
(
func
!=
RT_NULL
);
/**
* 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
;
cdc_eps_t
eps
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"cdc function disable
\n
"
));
if
(
vcom_connected
!=
RT_TRUE
)
return
-
RT_ERROR
;
_vcom_reset_state
(
func
);
if
(
vcom_in_sending
)
data
=
(
struct
vcom
*
)
func
->
user_data
;
if
(
data
->
ep_out
->
buffer
!=
RT_NULL
)
{
return
RT_EOK
;
rt_free
(
data
->
ep_out
->
buffer
);
data
->
ep_out
->
buffer
=
RT_NULL
;
}
eps
=
(
cdc_eps_t
)
cls
->
eps
;
size
=
rt_ringbuffer_data_len
(
&
tx_ringbuffer
);
if
(
size
==
0
)
return
-
RT_EFULL
;
level
=
rt_hw_interrupt_disable
();
rt_ringbuffer_get
(
&
tx_ringbuffer
,
eps
->
ep_in
->
buffer
,
size
);
rt_hw_interrupt_enable
(
level
);
/* send data to host */
vcom_in_sending
=
RT_TRUE
;
dcd_ep_write
(
device
->
dcd
,
eps
->
ep_in
,
eps
->
ep_in
->
buffer
,
size
);
return
RT_EOK
;
}
static
struct
u
class
_ops
ops
=
static
struct
u
function
_ops
ops
=
{
_
class_run
,
_
class_stop
,
_class_sof_handler
,
_
function_enable
,
_
function_disable
,
RT_NULL
,
};
/**
...
...
@@ -483,7 +483,8 @@ static struct uclass_ops ops =
*
* @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
)
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
;
...
...
@@ -496,16 +497,16 @@ static rt_err_t _cdc_descriptor_config(ucdc_comm_desc_t comm, rt_uint8_t cintf_n
}
/**
* This function will create a cdc
class
instance.
* This function will create a cdc
function
instance.
*
* @param device the usb device object.
*
* @return RT_EOK on successful.
*/
u
class_t
rt_usbd_class
_cdc_create
(
udevice_t
device
)
u
function_t
rt_usbd_function
_cdc_create
(
udevice_t
device
)
{
u
class_t
cd
c
;
cdc_eps_t
eps
;
u
function_t
fun
c
;
struct
vcom
*
data
;
uintf_t
intf_comm
,
intf_data
;
ualtsetting_t
comm_setting
,
data_setting
;
ucdc_data_desc_t
data_desc
;
...
...
@@ -516,19 +517,26 @@ uclass_t rt_usbd_class_cdc_create(udevice_t device)
/* set usb device string description */
rt_usbd_device_set_string
(
device
,
_ustring
);
/* 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 function */
func
=
rt_usbd_function_new
(
device
,
&
dev_desc
,
&
ops
);
rt_usbd_device_set_qualifier
(
device
,
&
dev_qualifier
);
/* allocate memory for cdc vcom data */
data
=
(
struct
vcom
*
)
rt_malloc
(
sizeof
(
struct
vcom
));
rt_memset
(
data
,
0
,
sizeof
(
struct
vcom
));
func
->
user_data
=
(
void
*
)
data
;
/* initilize vcom */
rt_usb_vcom_init
(
func
);
/* 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
);
intf_comm
=
rt_usbd_interface_
new
(
device
,
_interface_handler
);
intf_data
=
rt_usbd_interface_
new
(
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
));
comm_setting
=
rt_usbd_altsetting_
new
(
sizeof
(
struct
ucdc_comm_descriptor
));
data_setting
=
rt_usbd_altsetting_
new
(
sizeof
(
struct
ucdc_data_descriptor
));
/* config desc in alternate setting */
rt_usbd_altsetting_config_descriptor
(
comm_setting
,
&
_comm_desc
,
...
...
@@ -537,39 +545,39 @@ uclass_t rt_usbd_class_cdc_create(udevice_t device)
/* 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
);
data
->
ep_cmd
=
rt_usbd_endpoint_new
(
&
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
);
rt_usbd_altsetting_add_endpoint
(
comm_setting
,
data
->
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
(
cd
c
,
intf_comm
);
/* add the communication interface to the cdc
function
*/
rt_usbd_
function_add_interface
(
fun
c
,
intf_comm
);
return
cdc
;
/* create a bulk in and a bulk endpoint */
data_desc
=
(
ucdc_data_desc_t
)
data_setting
->
desc
;
data
->
ep_out
=
rt_usbd_endpoint_new
(
&
data_desc
->
ep_out_desc
,
_ep_out_handler
);
data
->
ep_in
=
rt_usbd_endpoint_new
(
&
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
,
data
->
ep_in
);
rt_usbd_altsetting_add_endpoint
(
data_setting
,
data
->
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 function */
rt_usbd_function_add_interface
(
func
,
intf_data
);
return
func
;
}
/**
...
...
@@ -597,80 +605,106 @@ static rt_err_t _vcom_control(struct rt_serial_device *serial,
return
RT_EOK
;
}
static
int
_vcom_
putc
(
struct
rt_serial_device
*
serial
,
char
c
)
static
int
_vcom_
getc
(
struct
rt_serial_device
*
serial
)
{
int
result
;
rt_uint8_t
ch
;
rt_uint32_t
level
;
int
cnt
;
struct
ufunction
*
func
;
struct
vcom
*
data
;
func
=
(
struct
ufunction
*
)
serial
->
parent
.
user_data
;
data
=
(
struct
vcom
*
)
func
->
user_data
;
if
(
vcom_connected
!=
RT_TRUE
)
{
return
0
;
}
/* if the buffer is full, there is a chance that the host would pull some
* data out soon. But we cannot rely on that and if we wait to long, just
* return. */
for
(
cnt
=
500
;
rt_ringbuffer_space_len
(
&
tx_ringbuffer
)
==
0
&&
cnt
;
cnt
--
)
{
/*rt_kprintf("wait for %d\n", cnt);*/
if
(
vcom_connected
!=
RT_TRUE
)
return
0
;
}
if
(
cnt
==
0
)
{
/* OK, we believe that the connection is lost. So don't send any more
* data and act as the USB cable is not plugged in. Reset the VCOM
* state machine */
_vcom_reset_state
();
return
0
;
}
result
=
-
1
;
level
=
rt_hw_interrupt_disable
();
if
(
rt_ringbuffer_space_len
(
&
tx_ringbuffer
))
if
(
rt_ringbuffer_getchar
(
&
data
->
rx_ringbuffer
,
&
ch
)
!=
0
)
{
r
t_ringbuffer_putchar
(
&
tx_ringbuffer
,
c
)
;
r
esult
=
ch
;
}
rt_hw_interrupt_enable
(
level
);
return
1
;
return
result
;
}
static
int
_vcom_getc
(
struct
rt_serial_device
*
serial
)
static
rt_size_t
_vcom_tx
(
struct
rt_serial_device
*
serial
,
const
char
*
buf
,
rt_size_t
size
)
{
int
result
;
rt_uint8_t
ch
;
rt_uint32_t
level
;
struct
vcom_tx_msg
msg
;
result
=
-
1
;
RT_ASSERT
(
serial
!=
RT_NULL
);
RT_ASSERT
(
buf
!=
RT_NULL
);
level
=
rt_hw_interrupt_disable
();
if
(
rt_ringbuffer_data_len
(
&
rx_ringbuffer
))
msg
.
buf
=
buf
;
msg
.
serial
=
serial
;
msg
.
size
=
size
;
if
(
rt_mq_send
(
&
vcom_tx_thread_mq
,
(
void
*
)
&
msg
,
sizeof
(
struct
vcom_tx_msg
))
!=
RT_EOK
)
{
rt_
ringbuffer_getchar
(
&
rx_ringbuffer
,
&
ch
);
re
sult
=
ch
;
rt_
kprintf
(
"vcom send msg fail
\n
"
);
re
turn
0
;
}
rt_hw_interrupt_enable
(
level
);
return
result
;
return
size
;
}
static
const
struct
rt_uart_ops
usb_vcom_ops
=
{
_vcom_configure
,
_vcom_control
,
_vcom_putc
,
RT_NULL
,
_vcom_getc
,
RT_NULL
,
//_vcom_tx,
};
void
rt_usb_vcom_init
(
void
)
/* Vcom Tx Thread */
static
void
vcom_tx_thread_entry
(
void
*
parameter
)
{
struct
serial_configure
config
;
struct
vcom_tx_msg
msg
;
while
(
1
)
{
if
(
rt_mq_recv
(
&
vcom_tx_thread_mq
,
(
void
*
)
&
msg
,
sizeof
(
struct
vcom_tx_msg
),
RT_WAITING_FOREVER
)
==
RT_EOK
)
{
struct
ufunction
*
func
;
struct
vcom
*
data
;
func
=
(
struct
ufunction
*
)
msg
.
serial
->
parent
.
user_data
;
data
=
(
struct
vcom
*
)
func
->
user_data
;
if
(
!
data
->
connected
)
{
continue
;
}
rt_completion_init
(
&
data
->
wait
);
data
->
ep_in
->
request
.
buffer
=
(
void
*
)
msg
.
buf
;
data
->
ep_in
->
request
.
size
=
msg
.
size
;
data
->
ep_in
->
request
.
req_type
=
UIO_REQUEST_WRITE
;
rt_usbd_io_request
(
func
->
device
,
data
->
ep_in
,
&
data
->
ep_in
->
request
);
if
(
rt_completion_wait
(
&
data
->
wait
,
TX_TIMEOUT
)
!=
RT_EOK
)
{
rt_kprintf
(
"vcom tx timeout
\n
"
);
}
}
}
}
static
void
rt_usb_vcom_init
(
struct
ufunction
*
func
)
{
rt_err_t
result
=
RT_EOK
;
struct
serial_configure
config
;
struct
vcom
*
data
=
(
struct
vcom
*
)
func
->
user_data
;
/* initialize ring buffer */
rt_ringbuffer_init
(
&
rx_ringbuffer
,
rx_rbp
,
CDC_RX_BUFSIZE
);
rt_ringbuffer_init
(
&
tx_ringbuffer
,
tx_rbp
,
CDC_TX_BUFSIZE
);
rt_ringbuffer_init
(
&
data
->
rx_ringbuffer
,
data
->
rx_rbp
,
CDC_RX_BUFSIZE
);
config
.
baud_rate
=
BAUD_RATE_115200
;
config
.
bit_order
=
BIT_ORDER_LSB
;
...
...
@@ -679,14 +713,25 @@ void rt_usb_vcom_init(void)
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
;
data
->
serial
.
ops
=
&
usb_vcom_ops
;
data
->
serial
.
int_rx
=
&
data
->
vcom_int_rx
;
data
->
serial
.
config
=
config
;
/* register vcom device */
rt_hw_serial_register
(
&
vcom_serial
,
"vcom"
,
RT_DEVICE_FLAG_RDWR
|
RT_DEVICE_FLAG_INT_RX
,
RT_NULL
);
rt_hw_serial_register
(
&
data
->
serial
,
VCOM_DEVICE
,
RT_DEVICE_FLAG_RDWR
|
RT_DEVICE_FLAG_INT_RX
|
RT_DEVICE_FLAG_INT_TX
,
func
);
/* create an vcom message queue */
rt_mq_init
(
&
vcom_tx_thread_mq
,
"vcomq"
,
vcom_tx_thread_mq_pool
,
VCOM_MQ_MSG_SZ
,
sizeof
(
vcom_tx_thread_mq_pool
),
RT_IPC_FLAG_FIFO
);
/* init usb device thread */
rt_thread_init
(
&
vcom_thread
,
"vcom"
,
vcom_tx_thread_entry
,
RT_NULL
,
vcom_thread_stack
,
512
,
8
,
20
);
result
=
rt_thread_startup
(
&
vcom_thread
);
RT_ASSERT
(
result
==
RT_EOK
);
}
#endif
components/drivers/usb/usbdevice/class/mstorage.c
浏览文件 @
8fd0a7f9
...
...
@@ -21,7 +21,8 @@
* 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
* 2012-12-09 Heyuanjie87 change function and endpoint handler
* 2013-07-25 Yi Qiu update for USB CV test
*/
#include <rtthread.h>
...
...
@@ -31,19 +32,55 @@
#ifdef RT_USB_DEVICE_MSTORAGE
#define STATUS_CBW 0x00
#define STATUS_CSW 0x01
#define STATUS_RECEIVE 0x02
#define STATUS_SEND 0x03
enum
STAT
{
STAT_CBW
,
STAT_CMD
,
STAT_CSW
,
STAT_RECEIVE
,
STAT_SEND
,
};
typedef
enum
{
FIXED
,
COUNT
,
BLOCK_COUNT
,
}
CB_SIZE_TYPE
;
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
rt_uint32_t
_removed
=
0
;
typedef
enum
{
DIR_IN
,
DIR_OUT
,
DIR_NONE
,
}
CB_DIR
;
typedef
rt_size_t
(
*
cbw_handler
)(
ufunction_t
func
,
ustorage_cbw_t
cbw
);
struct
scsi_cmd
{
rt_uint16_t
cmd
;
cbw_handler
handler
;
rt_size_t
cmd_len
;
CB_SIZE_TYPE
type
;
rt_size_t
data_size
;
CB_DIR
dir
;
};
struct
mstorage
{
struct
ustorage_csw
csw_response
;
uep_t
ep_in
;
uep_t
ep_out
;
int
status
;
rt_uint32_t
cb_data_size
;
rt_device_t
disk
;
rt_uint32_t
block
;
rt_int32_t
count
;
rt_int32_t
size
;
struct
scsi_cmd
*
processing
;
struct
rt_device_blk_geometry
geometry
;
};
static
struct
udevice_descriptor
dev_desc
=
{
...
...
@@ -63,6 +100,18 @@ static struct udevice_descriptor dev_desc =
USB_DYNAMIC
,
//bNumConfigurations;
};
static
struct
usb_qualifier_descriptor
dev_qualifier
=
{
sizeof
(
dev_qualifier
),
USB_DESC_TYPE_DEVICEQUALIFIER
,
0x0200
,
USB_CLASS_MASS_STORAGE
,
0x00
,
64
,
0x01
,
0
,
};
const
static
struct
umass_descriptor
_mass_desc
=
{
USB_DESC_LENGTH_INTERFACE
,
//bLength;
...
...
@@ -95,270 +144,489 @@ const static char* _ustring[] =
"Language"
,
"RT-Thread Team."
,
"RTT Mass Storage"
,
"
1.1.0
"
,
"
320219198301
"
,
"Configuration"
,
"Interface"
,
};
static
rt_size_t
_test_unit_ready
(
ufunction_t
func
,
ustorage_cbw_t
cbw
);
static
rt_size_t
_request_sense
(
ufunction_t
func
,
ustorage_cbw_t
cbw
);
static
rt_size_t
_inquiry_cmd
(
ufunction_t
func
,
ustorage_cbw_t
cbw
);
static
rt_size_t
_allow_removal
(
ufunction_t
func
,
ustorage_cbw_t
cbw
);
static
rt_size_t
_start_stop
(
ufunction_t
func
,
ustorage_cbw_t
cbw
);
static
rt_size_t
_mode_sense_6
(
ufunction_t
func
,
ustorage_cbw_t
cbw
);
static
rt_size_t
_read_capacities
(
ufunction_t
func
,
ustorage_cbw_t
cbw
);
static
rt_size_t
_read_capacity
(
ufunction_t
func
,
ustorage_cbw_t
cbw
);
static
rt_size_t
_read_10
(
ufunction_t
func
,
ustorage_cbw_t
cbw
);
static
rt_size_t
_write_10
(
ufunction_t
func
,
ustorage_cbw_t
cbw
);
static
rt_size_t
_verify_10
(
ufunction_t
func
,
ustorage_cbw_t
cbw
);
static
struct
scsi_cmd
cmd_data
[]
=
{
{
SCSI_TEST_UNIT_READY
,
_test_unit_ready
,
6
,
FIXED
,
0
,
DIR_NONE
},
{
SCSI_REQUEST_SENSE
,
_request_sense
,
6
,
COUNT
,
0
,
DIR_IN
},
{
SCSI_INQUIRY_CMD
,
_inquiry_cmd
,
6
,
COUNT
,
0
,
DIR_IN
},
{
SCSI_ALLOW_REMOVAL
,
_allow_removal
,
6
,
FIXED
,
0
,
DIR_NONE
},
{
SCSI_MODE_SENSE_6
,
_mode_sense_6
,
6
,
COUNT
,
0
,
DIR_IN
},
{
SCSI_START_STOP
,
_start_stop
,
6
,
FIXED
,
0
,
DIR_NONE
},
{
SCSI_READ_CAPACITIES
,
_read_capacities
,
10
,
COUNT
,
0
,
DIR_NONE
},
{
SCSI_READ_CAPACITY
,
_read_capacity
,
10
,
FIXED
,
8
,
DIR_IN
},
{
SCSI_READ_10
,
_read_10
,
10
,
BLOCK_COUNT
,
0
,
DIR_IN
},
{
SCSI_WRITE_10
,
_write_10
,
10
,
BLOCK_COUNT
,
0
,
DIR_OUT
},
{
SCSI_VERIFY_10
,
_verify_10
,
10
,
FIXED
,
0
,
DIR_NONE
},
};
static
void
_send_status
(
ufunction_t
func
)
{
struct
mstorage
*
data
;
RT_ASSERT
(
func
!=
RT_NULL
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_send_status
\n
"
));
data
=
(
struct
mstorage
*
)
func
->
user_data
;
data
->
ep_in
->
request
.
buffer
=
(
rt_uint8_t
*
)
&
data
->
csw_response
;
data
->
ep_in
->
request
.
size
=
SIZEOF_CSW
;
data
->
ep_in
->
request
.
req_type
=
UIO_REQUEST_WRITE
;
rt_usbd_io_request
(
func
->
device
,
data
->
ep_in
,
&
data
->
ep_in
->
request
);
data
->
status
=
STAT_CSW
;
}
static
rt_size_t
_test_unit_ready
(
ufunction_t
func
,
ustorage_cbw_t
cbw
)
{
struct
mstorage
*
data
;
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
func
->
device
!=
RT_NULL
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_test_unit_ready
\n
"
));
data
=
(
struct
mstorage
*
)
func
->
user_data
;
data
->
csw_response
.
status
=
0
;
return
0
;
}
static
rt_size_t
_allow_removal
(
ufunction_t
func
,
ustorage_cbw_t
cbw
)
{
struct
mstorage
*
data
;
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
func
->
device
!=
RT_NULL
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_allow_removal
\n
"
));
data
=
(
struct
mstorage
*
)
func
->
user_data
;
data
->
csw_response
.
status
=
0
;
return
0
;
}
/**
* This function will
allocate an usb device instance from system
.
* This function will
handle inquiry command request
.
*
* @param
parent the hub instance to which the new allocated device attached.
* @param
port the hub port
.
* @param
func the usb function object.
* @param
cbw the command block wrapper
.
*
* @return
the allocate instance on successful, or RT_NULL on failure
.
* @return
RT_EOK on successful
.
*/
static
rt_err_t
_inquiry_cmd
(
udevice_t
device
,
uep_t
ep_in
)
static
rt_size_t
_inquiry_cmd
(
ufunction_t
func
,
ustorage_cbw_t
cbw
)
{
rt_uint8_t
data
[
36
];
struct
mstorage
*
data
;
rt_uint8_t
*
buf
;
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
func
->
device
!=
RT_NULL
);
RT_ASSERT
(
cbw
!=
RT_NULL
);
*
(
rt_uint32_t
*
)
&
data
[
0
]
=
0x0
|
(
0x80
<<
8
);
*
(
rt_uint32_t
*
)
&
data
[
4
]
=
31
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_inquiry_cmd
\n
"
));
rt_memset
(
&
data
[
8
],
0x20
,
28
);
rt_memcpy
(
&
data
[
8
],
"RTT"
,
3
);
rt_memcpy
(
&
data
[
16
],
"USB Disk"
,
8
);
data
=
(
struct
mstorage
*
)
func
->
user_data
;
buf
=
data
->
ep_in
->
buffer
;
dcd_ep_write
(
device
->
dcd
,
ep_in
,
(
rt_uint8_t
*
)
&
data
,
36
);
*
(
rt_uint32_t
*
)
&
buf
[
0
]
=
0x0
|
(
0x80
<<
8
);
*
(
rt_uint32_t
*
)
&
buf
[
4
]
=
31
;
return
RT_EOK
;
rt_memset
(
&
buf
[
8
],
0x20
,
28
);
rt_memcpy
(
&
buf
[
8
],
"RTT"
,
3
);
rt_memcpy
(
&
buf
[
16
],
"USB Disk"
,
8
);
data
->
cb_data_size
=
MIN
(
data
->
cb_data_size
,
SIZEOF_INQUIRY_CMD
);
data
->
ep_in
->
request
.
buffer
=
buf
;
data
->
ep_in
->
request
.
size
=
data
->
cb_data_size
;
data
->
ep_in
->
request
.
req_type
=
UIO_REQUEST_WRITE
;
rt_usbd_io_request
(
func
->
device
,
data
->
ep_in
,
&
data
->
ep_in
->
request
);
data
->
status
=
STAT_CMD
;
return
data
->
cb_data_size
;
}
/**
* This function will handle sense request.
*
* @param device the usb device object.
* @param func the usb function object.
* @param cbw the command block wrapper.
*
* @return RT_EOK on successful.
*/
static
rt_
err_t
_request_sense
(
udevice_t
device
,
uep_t
ep_in
)
static
rt_
size_t
_request_sense
(
ufunction_t
func
,
ustorage_cbw_t
cbw
)
{
struct
request_sense_data
data
;
data
.
ErrorCode
=
0x70
;
data
.
Valid
=
0
;
data
.
SenseKey
=
2
;
//TODO
data
.
Information
[
0
]
=
0
;
data
.
Information
[
1
]
=
0
;
data
.
Information
[
2
]
=
0
;
data
.
Information
[
3
]
=
0
;
data
.
AdditionalSenseLength
=
0x0a
;
data
.
AdditionalSenseCode
=
0x3a
;
//TODO
data
.
AdditionalSenseCodeQualifier
=
0
;
struct
mstorage
*
data
;
struct
request_sense_data
*
buf
;
dcd_ep_write
(
device
->
dcd
,
ep_in
,
(
rt_uint8_t
*
)
&
data
,
sizeof
(
struct
request_sense_data
));
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
func
->
device
!=
RT_NULL
);
RT_ASSERT
(
cbw
!=
RT_NULL
);
return
RT_EOK
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_request_sense
\n
"
));
data
=
(
struct
mstorage
*
)
func
->
user_data
;
buf
=
(
struct
request_sense_data
*
)
data
->
ep_in
->
buffer
;
buf
->
ErrorCode
=
0x70
;
buf
->
Valid
=
0
;
buf
->
SenseKey
=
2
;
buf
->
Information
[
0
]
=
0
;
buf
->
Information
[
1
]
=
0
;
buf
->
Information
[
2
]
=
0
;
buf
->
Information
[
3
]
=
0
;
buf
->
AdditionalSenseLength
=
0x0a
;
buf
->
AdditionalSenseCode
=
0x3a
;
buf
->
AdditionalSenseCodeQualifier
=
0
;
data
->
cb_data_size
=
MIN
(
data
->
cb_data_size
,
SIZEOF_REQUEST_SENSE
);
data
->
ep_in
->
request
.
buffer
=
(
rt_uint8_t
*
)
data
->
ep_in
->
buffer
;
data
->
ep_in
->
request
.
size
=
data
->
cb_data_size
;
data
->
ep_in
->
request
.
req_type
=
UIO_REQUEST_WRITE
;
rt_usbd_io_request
(
func
->
device
,
data
->
ep_in
,
&
data
->
ep_in
->
request
);
data
->
status
=
STAT_CMD
;
return
data
->
cb_data_size
;
}
/**
* This function will handle mode_sense_6 request.
*
* @param device the usb device object.
* @param func the usb function object.
* @param cbw the command block wrapper.
*
* @return RT_EOK on successful.
*/
static
rt_
err_t
_mode_sense_6
(
udevice_t
device
,
uep_t
ep_in
)
static
rt_
size_t
_mode_sense_6
(
ufunction_t
func
,
ustorage_cbw_t
cbw
)
{
rt_uint8_t
data
[
4
];
struct
mstorage
*
data
;
rt_uint8_t
*
buf
;
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
func
->
device
!=
RT_NULL
);
RT_ASSERT
(
cbw
!=
RT_NULL
);
data
[
0
]
=
3
;
data
[
1
]
=
0
;
data
[
2
]
=
0
;
data
[
3
]
=
0
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_mode_sense_6
\n
"
));
dcd_ep_write
(
device
->
dcd
,
ep_in
,
(
rt_uint8_t
*
)
&
data
,
4
);
data
=
(
struct
mstorage
*
)
func
->
user_data
;
buf
=
data
->
ep_in
->
buffer
;
buf
[
0
]
=
3
;
buf
[
1
]
=
0
;
buf
[
2
]
=
0
;
buf
[
3
]
=
0
;
return
RT_EOK
;
data
->
cb_data_size
=
MIN
(
data
->
cb_data_size
,
SIZEOF_MODE_SENSE_6
);
data
->
ep_in
->
request
.
buffer
=
buf
;
data
->
ep_in
->
request
.
size
=
data
->
cb_data_size
;
data
->
ep_in
->
request
.
req_type
=
UIO_REQUEST_WRITE
;
rt_usbd_io_request
(
func
->
device
,
data
->
ep_in
,
&
data
->
ep_in
->
request
);
data
->
status
=
STAT_CMD
;
return
data
->
cb_data_size
;
}
/**
* This function will handle read_capacities request.
*
* @param device the usb device object.
* @param func the usb function object.
* @param cbw the command block wrapper.
*
* @return RT_EOK on successful.
*/
static
rt_
err_t
_read_capacities
(
udevice_t
device
,
uep_t
ep_in
)
static
rt_
size_t
_read_capacities
(
ufunction_t
func
,
ustorage_cbw_t
cbw
)
{
rt_uint8_t
data
[
12
];
struct
mstorage
*
data
;
rt_uint8_t
*
buf
;
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
);
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
func
->
device
!=
RT_NULL
);
RT_ASSERT
(
cbw
!=
RT_NULL
);
return
RT_EOK
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_read_capacities
\n
"
));
data
=
(
struct
mstorage
*
)
func
->
user_data
;
buf
=
data
->
ep_in
->
buffer
;
sector_count
=
data
->
geometry
.
sector_count
;
sector_size
=
data
->
geometry
.
bytes_per_sector
;
*
(
rt_uint32_t
*
)
&
buf
[
0
]
=
0x08000000
;
buf
[
4
]
=
sector_count
>>
24
;
buf
[
5
]
=
0xff
&
(
sector_count
>>
16
);
buf
[
6
]
=
0xff
&
(
sector_count
>>
8
);
buf
[
7
]
=
0xff
&
(
sector_count
);
buf
[
8
]
=
0x02
;
buf
[
9
]
=
0xff
&
(
sector_size
>>
16
);
buf
[
10
]
=
0xff
&
(
sector_size
>>
8
);
buf
[
11
]
=
0xff
&
sector_size
;
data
->
cb_data_size
=
MIN
(
data
->
cb_data_size
,
SIZEOF_READ_CAPACITIES
);
data
->
ep_in
->
request
.
buffer
=
buf
;
data
->
ep_in
->
request
.
size
=
data
->
cb_data_size
;
data
->
ep_in
->
request
.
req_type
=
UIO_REQUEST_WRITE
;
rt_usbd_io_request
(
func
->
device
,
data
->
ep_in
,
&
data
->
ep_in
->
request
);
data
->
status
=
STAT_CMD
;
return
data
->
cb_data_size
;
}
/**
* This function will handle read_capacity request.
*
* @param device the usb device object.
* @param func the usb function object.
* @param cbw the command block wapper.
*
* @return RT_EOK on successful.
*/
static
rt_
err_t
_read_capacity
(
udevice_t
device
,
uep_t
ep_in
)
static
rt_
size_t
_read_capacity
(
ufunction_t
func
,
ustorage_cbw_t
cbw
)
{
rt_uint8_t
data
[
8
];
rt_uint32_t
sector_count
,
sector_size
;
struct
mstorage
*
data
;
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
;
rt_uint8_t
*
buf
;
rt_uint32_t
sector_count
,
sector_size
;
dcd_ep_write
(
device
->
dcd
,
ep_in
,
(
rt_uint8_t
*
)
&
data
,
8
);
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
func
->
device
!=
RT_NULL
);
RT_ASSERT
(
cbw
!=
RT_NULL
);
return
RT_EOK
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_read_capacity
\n
"
));
data
=
(
struct
mstorage
*
)
func
->
user_data
;
buf
=
data
->
ep_in
->
buffer
;
sector_count
=
data
->
geometry
.
sector_count
;
sector_size
=
data
->
geometry
.
bytes_per_sector
;
buf
[
0
]
=
sector_count
>>
24
;
buf
[
1
]
=
0xff
&
(
sector_count
>>
16
);
buf
[
2
]
=
0xff
&
(
sector_count
>>
8
);
buf
[
3
]
=
0xff
&
(
sector_count
);
buf
[
4
]
=
0x0
;
buf
[
5
]
=
0xff
&
(
sector_size
>>
16
);
buf
[
6
]
=
0xff
&
(
sector_size
>>
8
);
buf
[
7
]
=
0xff
&
sector_size
;
data
->
cb_data_size
=
MIN
(
data
->
cb_data_size
,
SIZEOF_READ_CAPACITY
);
data
->
ep_in
->
request
.
buffer
=
buf
;
data
->
ep_in
->
request
.
size
=
data
->
cb_data_size
;
data
->
ep_in
->
request
.
req_type
=
UIO_REQUEST_WRITE
;
rt_usbd_io_request
(
func
->
device
,
data
->
ep_in
,
&
data
->
ep_in
->
request
);
data
->
status
=
STAT_CMD
;
return
data
->
cb_data_size
;
}
/**
* This function will handle read_10 request.
*
* @param
device the usb device
object.
* @param
func the usb function
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
)
static
rt_
size_t
_read_10
(
ufunction_t
func
,
ustorage_cbw_t
cbw
)
{
RT_ASSERT
(
device
!=
RT_NULL
);
struct
mstorage
*
data
;
rt_size_t
size
;
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
func
->
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
;
data
=
(
struct
mstorage
*
)
func
->
user_data
;
data
->
block
=
cbw
->
cb
[
2
]
<<
24
|
cbw
->
cb
[
3
]
<<
16
|
cbw
->
cb
[
4
]
<<
8
|
cbw
->
cb
[
5
]
<<
0
;
data
->
count
=
cbw
->
cb
[
7
]
<<
8
|
cbw
->
cb
[
8
]
<<
0
;
_count
=
cbw
->
cb
[
7
]
<<
8
|
cbw
->
cb
[
8
]
<<
0
;
RT_ASSERT
(
data
->
count
<
data
->
geometry
.
sector_count
)
;
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
data
->
csw_response
.
data_reside
=
data
->
cb_data_size
;
size
=
rt_device_read
(
data
->
disk
,
data
->
block
,
data
->
ep_in
->
buffer
,
1
);
if
(
size
==
0
)
{
status
=
STATUS_CSW
;
rt_kprintf
(
"read data error
\n
"
)
;
}
return
RT_EOK
;
data
->
ep_in
->
request
.
buffer
=
data
->
ep_in
->
buffer
;
data
->
ep_in
->
request
.
size
=
data
->
geometry
.
bytes_per_sector
;
data
->
ep_in
->
request
.
req_type
=
UIO_REQUEST_WRITE
;
rt_usbd_io_request
(
func
->
device
,
data
->
ep_in
,
&
data
->
ep_in
->
request
);
data
->
status
=
STAT_SEND
;
return
data
->
geometry
.
bytes_per_sector
;
}
/**
* This function will handle write_10 request.
*
* @param
device the usb device
object.
* @param
func the usb function
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
)
static
rt_
size_t
_write_10
(
ufunction_t
func
,
ustorage_cbw_t
cbw
)
{
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
;
struct
mstorage
*
data
;
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
);
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
func
->
device
!=
RT_NULL
);
RT_ASSERT
(
cbw
!=
RT_NULL
);
return
RT_EOK
;
data
=
(
struct
mstorage
*
)
func
->
user_data
;
data
->
block
=
cbw
->
cb
[
2
]
<<
24
|
cbw
->
cb
[
3
]
<<
16
|
cbw
->
cb
[
4
]
<<
8
|
cbw
->
cb
[
5
]
<<
0
;
data
->
count
=
cbw
->
cb
[
7
]
<<
8
|
cbw
->
cb
[
8
];
data
->
csw_response
.
data_reside
=
cbw
->
xfer_len
;
data
->
size
=
data
->
count
*
data
->
geometry
.
bytes_per_sector
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_write_10 count 0x%x block 0x%x 0x%x
\n
"
,
data
->
count
,
data
->
block
,
data
->
geometry
.
sector_count
));
data
->
csw_response
.
data_reside
=
data
->
cb_data_size
;
data
->
ep_out
->
request
.
buffer
=
data
->
ep_out
->
buffer
;
data
->
ep_out
->
request
.
size
=
data
->
geometry
.
bytes_per_sector
;
data
->
ep_out
->
request
.
req_type
=
UIO_REQUEST_READ_FULL
;
rt_usbd_io_request
(
func
->
device
,
data
->
ep_out
,
&
data
->
ep_out
->
request
);
data
->
status
=
STAT_RECEIVE
;
return
data
->
geometry
.
bytes_per_sector
;
}
/**
* This function will handle verify_10 request.
*
* @param
device the usb device
object.
* @param
func the usb function
object.
*
* @return RT_EOK on successful.
*/
static
rt_
err_t
_verify_10
(
udevice_t
device
)
static
rt_
size_t
_verify_10
(
ufunction_t
func
,
ustorage_cbw_t
cbw
)
{
return
RT_EOK
;
}
struct
mstorage
*
data
;
static
void
_send_status
(
udevice_t
device
,
mass_eps_t
eps
,
ustorage_csw_t
csw
)
{
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
;
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
func
->
device
!=
RT_NULL
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_verify_10
\n
"
));
data
=
(
struct
mstorage
*
)
func
->
user_data
;
data
->
csw_response
.
status
=
0
;
return
0
;
}
static
void
_start_stop
(
ustorage_cbw_t
cbw
)
static
rt_size_t
_start_stop
(
ufunction_t
func
,
ustorage_cbw_t
cbw
)
{
//TODO
_removed
=
1
;
struct
mstorage
*
data
;
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
func
->
device
!=
RT_NULL
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_start_stop
\n
"
));
data
=
(
struct
mstorage
*
)
func
->
user_data
;
data
->
csw_response
.
status
=
0
;
return
0
;
}
/**
* 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
)
static
rt_err_t
_ep_in_handler
(
ufunction_t
func
,
rt_size_t
size
)
{
mass_eps_t
eps
;
RT_ASSERT
(
device
!=
RT_NULL
);
struct
mstorage
*
data
;
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
func
->
device
!=
RT_NULL
);
eps
=
cls
->
eps
;
if
(
status
==
STATUS_CSW
)
{
_send_status
(
device
,
eps
,
&
csw
);
}
else
if
(
status
==
STATUS_SEND
)
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_ep_in_handler
\n
"
));
data
=
(
struct
mstorage
*
)
func
->
user_data
;
switch
(
data
->
status
)
{
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
)
case
STAT_CSW
:
if
(
data
->
ep_in
->
request
.
size
!=
SIZEOF_CSW
)
{
_block
++
;
status
=
STATUS_SEND
;
rt_kprintf
(
"Size of csw command error
\n
"
)
;
rt_usbd_ep_set_stall
(
func
->
device
,
data
->
ep_in
);
}
else
{
status
=
STATUS_CSW
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"return to cbw status
\n
"
));
data
->
ep_out
->
request
.
buffer
=
data
->
ep_out
->
buffer
;
data
->
ep_out
->
request
.
size
=
SIZEOF_CBW
;
data
->
ep_out
->
request
.
req_type
=
UIO_REQUEST_READ_FULL
;
rt_usbd_io_request
(
func
->
device
,
data
->
ep_out
,
&
data
->
ep_out
->
request
);
data
->
status
=
STAT_CBW
;
}
}
break
;
case
STAT_CMD
:
if
(
data
->
csw_response
.
data_reside
==
0xFF
)
{
data
->
csw_response
.
data_reside
=
0
;
}
else
{
data
->
csw_response
.
data_reside
-=
data
->
ep_in
->
request
.
size
;
if
(
data
->
csw_response
.
data_reside
!=
0
)
{
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"data_reside %d, request %d
\n
"
,
data
->
csw_response
.
data_reside
,
data
->
ep_in
->
request
.
size
));
if
(
data
->
processing
->
dir
==
DIR_OUT
)
{
rt_usbd_ep_set_stall
(
func
->
device
,
data
->
ep_out
);
}
else
{
rt_usbd_ep_set_stall
(
func
->
device
,
data
->
ep_in
);
}
data
->
csw_response
.
data_reside
=
0
;
}
}
_send_status
(
func
);
break
;
case
STAT_SEND
:
data
->
csw_response
.
data_reside
-=
data
->
ep_in
->
request
.
size
;
data
->
count
--
;
data
->
block
++
;
if
(
data
->
count
>
0
&&
data
->
csw_response
.
data_reside
>
0
)
{
if
(
rt_device_read
(
data
->
disk
,
data
->
block
,
data
->
ep_in
->
buffer
,
1
)
==
0
)
{
rt_kprintf
(
"disk read error
\n
"
);
rt_usbd_ep_set_stall
(
func
->
device
,
data
->
ep_in
);
return
-
RT_ERROR
;
}
data
->
ep_in
->
request
.
buffer
=
data
->
ep_in
->
buffer
;
data
->
ep_in
->
request
.
size
=
data
->
geometry
.
bytes_per_sector
;
data
->
ep_in
->
request
.
req_type
=
UIO_REQUEST_WRITE
;
rt_usbd_io_request
(
func
->
device
,
data
->
ep_in
,
&
data
->
ep_in
->
request
);
}
else
{
_send_status
(
func
);
}
break
;
}
return
RT_EOK
;
return
RT_EOK
;
}
#ifdef MASS_CBW_DUMP
...
...
@@ -376,134 +644,283 @@ static void cbw_dump(struct ustorage_cbw* cbw)
}
#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
)
static
struct
scsi_cmd
*
_find_cbw_command
(
rt_uint16_t
cmd
)
{
mass_eps_t
eps
;
RT_ASSERT
(
device
!=
RT_NULL
);
int
i
;
eps
=
(
mass_eps_t
)
cls
->
eps
;
if
(
status
==
STATUS_CBW
)
for
(
i
=
0
;
i
<
sizeof
(
cmd_data
)
/
sizeof
(
struct
scsi_cmd
);
i
++
)
{
struct
ustorage_cbw
*
cbw
;
if
(
cmd_data
[
i
].
cmd
==
cmd
)
return
&
cmd_data
[
i
];
}
/* dump cbw information */
cbw
=
(
struct
ustorage_cbw
*
)
eps
->
ep_out
->
buffer
;
return
RT_NULL
;
}
if
(
cbw
->
signature
==
CBW_SIGNATURE
)
{
csw
.
signature
=
CSW_SIGNATURE
;
csw
.
tag
=
cbw
->
tag
;
csw
.
data_reside
=
0
;
csw
.
status
=
0
;
}
else
return
-
RT_ERROR
;
static
void
_cb_len_calc
(
ufunction_t
func
,
struct
scsi_cmd
*
cmd
,
ustorage_cbw_t
cbw
)
{
struct
mstorage
*
data
;
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
cmd
!=
RT_NULL
);
RT_ASSERT
(
cbw
!=
RT_NULL
);
switch
(
cbw
->
cb
[
0
])
data
=
(
struct
mstorage
*
)
func
->
user_data
;
if
(
cmd
->
cmd_len
==
6
)
{
switch
(
cmd
->
type
)
{
case
SCSI_TEST_UNIT_READY
:
csw
.
status
=
_removed
;
_send_status
(
device
,
eps
,
&
csw
);
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
;
case
COUNT
:
data
->
cb_data_size
=
cbw
->
cb
[
4
];
break
;
case
SCSI_ALLOW_MEDIUM_REMOVAL
:
_send_status
(
device
,
eps
,
&
csw
)
;
case
BLOCK_COUNT
:
data
->
cb_data_size
=
cbw
->
cb
[
4
]
*
data
->
geometry
.
bytes_per_sector
;
break
;
case
SCSI_READ_CAPACITIES
:
_read_capacities
(
device
,
eps
->
ep_in
);
status
=
STATUS_CSW
;
case
FIXED
:
data
->
cb_data_size
=
cmd
->
data_size
;
break
;
case
SCSI_READ_CAPACITY
:
_read_capacity
(
device
,
eps
->
ep_in
);
status
=
STATUS_CSW
;
default:
break
;
case
SCSI_READ_10
:
_read_10
(
device
,
cbw
,
eps
->
ep_in
);
}
}
else
if
(
cmd
->
cmd_len
==
10
)
{
switch
(
cmd
->
type
)
{
case
COUNT
:
data
->
cb_data_size
=
cbw
->
cb
[
7
]
<<
8
|
cbw
->
cb
[
8
];
break
;
case
SCSI_WRITE_10
:
_write_10
(
device
,
cbw
,
eps
->
ep_out
);
status
=
STATUS_RECEIVE
;
case
BLOCK_COUNT
:
data
->
cb_data_size
=
(
cbw
->
cb
[
7
]
<<
8
|
cbw
->
cb
[
8
])
*
data
->
geometry
.
bytes_per_sector
;
break
;
case
SCSI_VERIFY_10
:
_verify_10
(
device
)
;
case
FIXED
:
data
->
cb_data_size
=
cmd
->
data_size
;
break
;
case
SCSI_START_STOP
:
_start_stop
(
cbw
);
_send_status
(
device
,
eps
,
&
csw
);
default:
break
;
}
}
else
if
(
status
==
STATUS_RECEIVE
)
else
{
rt_kprintf
(
"cmd_len error %d
\n
"
,
cmd
->
cmd_len
);
}
}
static
rt_bool_t
_cbw_verify
(
ufunction_t
func
,
struct
scsi_cmd
*
cmd
,
ustorage_cbw_t
cbw
)
{
struct
mstorage
*
data
;
RT_ASSERT
(
cmd
!=
RT_NULL
);
RT_ASSERT
(
cbw
!=
RT_NULL
);
RT_ASSERT
(
func
!=
RT_NULL
);
data
=
(
struct
mstorage
*
)
func
->
user_data
;
if
(
cmd
->
cmd_len
!=
cbw
->
cb_len
)
{
rt_kprintf
(
"cb_len error
\n
"
);
cmd
->
cmd_len
=
cbw
->
cb_len
;
}
if
(
cbw
->
xfer_len
>
0
&&
data
->
cb_data_size
==
0
)
{
rt_kprintf
(
"xfer_len > 0 && data_size == 0
\n
"
);
return
RT_FALSE
;
}
if
(
cbw
->
xfer_len
==
0
&&
data
->
cb_data_size
>
0
)
{
rt_kprintf
(
"xfer_len == 0 && data_size > 0"
);
return
RT_FALSE
;
}
if
((
cbw
->
dflags
&
USB_DIR_IN
)
&&
cmd
->
dir
==
DIR_OUT
||
!
(
cbw
->
dflags
&
USB_DIR_IN
)
&&
cmd
->
dir
==
DIR_IN
)
{
rt_kprintf
(
"dir error
\n
"
);
return
RT_FALSE
;
}
if
(
cbw
->
xfer_len
>
data
->
cb_data_size
)
{
rt_kprintf
(
"xfer_len > data_size
\n
"
);
return
RT_FALSE
;
}
if
(
cbw
->
xfer_len
<
data
->
cb_data_size
)
{
rt_kprintf
(
"xfer_len < data_size
\n
"
);
data
->
cb_data_size
=
cbw
->
xfer_len
;
data
->
csw_response
.
status
=
1
;
}
return
RT_TRUE
;
}
static
rt_size_t
_cbw_handler
(
ufunction_t
func
,
struct
scsi_cmd
*
cmd
,
ustorage_cbw_t
cbw
)
{
struct
mstorage
*
data
;
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
cbw
!=
RT_NULL
);
RT_ASSERT
(
cmd
->
handler
!=
RT_NULL
);
data
=
(
struct
mstorage
*
)
func
->
user_data
;
data
->
processing
=
cmd
;
return
cmd
->
handler
(
func
,
cbw
);
}
/**
* This function will handle mass storage bulk out endpoint request.
*
* @param func the usb function object.
* @param size request size.
*
* @return RT_EOK.
*/
static
rt_err_t
_ep_out_handler
(
ufunction_t
func
,
rt_size_t
size
)
{
struct
mstorage
*
data
;
struct
scsi_cmd
*
cmd
;
rt_size_t
len
;
struct
ustorage_cbw
*
cbw
;
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
func
->
device
!=
RT_NULL
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_ep_out_handler %d
\n
"
,
size
));
data
=
(
struct
mstorage
*
)
func
->
user_data
;
cbw
=
(
struct
ustorage_cbw
*
)
data
->
ep_out
->
buffer
;
if
(
data
->
status
==
STAT_CBW
)
{
/* dump cbw information */
if
(
cbw
->
signature
!=
CBW_SIGNATURE
||
size
!=
SIZEOF_CBW
)
{
goto
exit
;
}
data
->
csw_response
.
signature
=
CSW_SIGNATURE
;
data
->
csw_response
.
tag
=
cbw
->
tag
;
data
->
csw_response
.
data_reside
=
cbw
->
xfer_len
;
data
->
csw_response
.
status
=
0
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"ep_out reside %d
\n
"
,
data
->
csw_response
.
data_reside
));
cmd
=
_find_cbw_command
(
cbw
->
cb
[
0
]);
if
(
cmd
==
RT_NULL
)
{
rt_kprintf
(
"can't find cbw command
\n
"
);
goto
exit
;
}
_cb_len_calc
(
func
,
cmd
,
cbw
);
if
(
!
_cbw_verify
(
func
,
cmd
,
cbw
))
{
goto
exit
;
}
len
=
_cbw_handler
(
func
,
cmd
,
cbw
);
if
(
len
==
0
)
{
_send_status
(
func
);
}
return
RT_EOK
;
}
else
if
(
data
->
status
==
STAT_RECEIVE
)
{
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"write size 0x%x block 0x%x oount 0x%x
\n
"
,
size
,
_block
,
_size
));
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"
\n
write size %d block 0x%x oount 0x%x
\n
"
,
size
,
data
->
block
,
data
->
size
));
data
->
size
-=
size
;
data
->
csw_response
.
data_reside
-=
size
;
_size
-=
size
;
csw
.
data_reside
-=
size
;
rt_device_write
(
data
->
disk
,
data
->
block
,
data
->
ep_out
->
buffer
,
1
);
rt_device_write
(
disk
,
_block
,
eps
->
ep_in
->
buffer
,
1
);
_block
++
;
if
(
_size
==
0
)
if
(
data
->
csw_response
.
data_reside
!=
0
)
{
_send_status
(
device
,
eps
,
&
csw
);
data
->
ep_out
->
request
.
buffer
=
data
->
ep_out
->
buffer
;
data
->
ep_out
->
request
.
size
=
data
->
geometry
.
bytes_per_sector
;
data
->
ep_out
->
request
.
req_type
=
UIO_REQUEST_READ_FULL
;
rt_usbd_io_request
(
func
->
device
,
data
->
ep_out
,
&
data
->
ep_out
->
request
);
data
->
block
++
;
}
else
{
dcd_ep_read
(
device
->
dcd
,
eps
->
ep_out
,
eps
->
ep_out
->
buffer
,
geometry
.
bytes_per_sector
);
_send_status
(
func
);
}
return
RT_EOK
;
}
else
exit:
if
(
data
->
csw_response
.
data_reside
)
{
rt_kprintf
(
"none cbw status
\n
"
);
if
(
cbw
->
dflags
&
USB_DIR_IN
)
{
rt_usbd_ep_set_stall
(
func
->
device
,
data
->
ep_in
);
}
else
{
rt_usbd_ep_set_stall
(
func
->
device
,
data
->
ep_in
);
rt_usbd_ep_set_stall
(
func
->
device
,
data
->
ep_out
);
}
}
return
RT_EOK
;
data
->
csw_response
.
status
=
1
;
_send_status
(
func
);
return
-
RT_ERROR
;
}
/**
* This function will handle mass storage interface request.
*
* @param
device the usb device
object.
* @param
func the usb function
object.
* @param setup the setup request.
*
* @return RT_EOK on successful.
*/
static
rt_err_t
_interface_handler
(
u
device_t
device
,
uclass_t
cls
,
ureq_t
setup
)
static
rt_err_t
_interface_handler
(
u
function_t
func
,
ureq_t
setup
)
{
rt_uint8_t
lun
=
0
;
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
func
->
device
!=
RT_NULL
);
RT_ASSERT
(
setup
!=
RT_NULL
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_interface_handler
\n
"
));
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"
mstorage
_interface_handler
\n
"
));
switch
(
setup
->
request
)
{
case
USBREQ_GET_MAX_LUN
:
dcd_ep_write
(
device
->
dcd
,
0
,
&
lun
,
1
);
case
USBREQ_GET_MAX_LUN
:
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"USBREQ_GET_MAX_LUN
\n
"
));
if
(
setup
->
value
||
setup
->
length
!=
1
)
{
rt_usbd_ep0_set_stall
(
func
->
device
);
}
else
{
rt_usbd_ep0_write
(
func
->
device
,
&
lun
,
1
);
}
break
;
case
USBREQ_MASS_STORAGE_RESET
:
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"USBREQ_MASS_STORAGE_RESET
\n
"
));
if
(
setup
->
value
||
setup
->
length
!=
0
)
{
rt_usbd_ep0_set_stall
(
func
->
device
);
}
else
{
rt_usbd_ep0_write
(
func
->
device
,
RT_NULL
,
0
);
}
break
;
default:
rt_kprintf
(
"unknown interface request
\n
"
);
...
...
@@ -514,81 +931,114 @@ static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup)
}
/**
* This function will run mass storage
class
, it will be called on handle set configuration request.
* This function will run mass storage
function
, it will be called on handle set configuration request.
*
* @param
device the usb device
object.
* @param
func the usb function
object.
*
* @return RT_EOK on successful.
*/
static
rt_err_t
_
class_run
(
udevice_t
device
,
uclass_t
cls
)
static
rt_err_t
_
function_enable
(
ufunction_t
func
)
{
mass_eps_t
eps
;
rt_uint8_t
*
buffer
;
RT_ASSERT
(
device
!=
RT_NULL
);
struct
mstorage
*
data
;
RT_ASSERT
(
func
!=
RT_NULL
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"
mass storage run
\n
"
));
eps
=
(
mass_eps_t
)
cls
->
eps
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"
Mass storage function enabled
\n
"
));
data
=
(
struct
mstorage
*
)
func
->
user_data
;
disk
=
rt_device_find
(
RT_USB_MSTORAGE_DISK_NAME
);
if
(
disk
==
RT_NULL
)
d
ata
->
d
isk
=
rt_device_find
(
RT_USB_MSTORAGE_DISK_NAME
);
if
(
d
ata
->
d
isk
==
RT_NULL
)
{
rt_kprintf
(
"no disk named %s
\n
"
,
RT_USB_MSTORAGE_DISK_NAME
);
rt_kprintf
(
"no d
ata->d
isk 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
)
if
(
rt_device_open
(
data
->
disk
,
RT_DEVICE_OFLAG_RDWR
)
!=
RT_EOK
)
{
rt_kprintf
(
"disk open error
\n
"
);
return
-
RT_ERROR
;
}
if
(
rt_device_control
(
data
->
disk
,
RT_DEVICE_CTRL_BLK_GETGEOME
,
(
void
*
)
&
data
->
geometry
)
!=
RT_EOK
)
{
rt_kprintf
(
"get disk info error
\n
"
);
return
-
RT_ERROR
;
}
data
->
ep_in
->
buffer
=
(
rt_uint8_t
*
)
rt_malloc
(
data
->
geometry
.
bytes_per_sector
);
if
(
data
->
ep_in
->
buffer
==
RT_NULL
)
{
rt_kprintf
(
"no memory
\n
"
);
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
);
}
data
->
ep_out
->
buffer
=
(
rt_uint8_t
*
)
rt_malloc
(
data
->
geometry
.
bytes_per_sector
);
if
(
data
->
ep_out
->
buffer
==
RT_NULL
)
{
rt_free
(
data
->
ep_in
->
buffer
);
rt_kprintf
(
"no memory
\n
"
);
return
-
RT_ENOMEM
;
}
/* prepare to read CBW request */
data
->
ep_out
->
request
.
buffer
=
data
->
ep_out
->
buffer
;
data
->
ep_out
->
request
.
size
=
SIZEOF_CBW
;
data
->
ep_out
->
request
.
req_type
=
UIO_REQUEST_READ_FULL
;
rt_usbd_io_request
(
func
->
device
,
data
->
ep_out
,
&
data
->
ep_out
->
request
);
return
RT_EOK
;
}
/**
* This function will stop mass storage
class
, it will be called on handle set configuration request.
* This function will stop mass storage
function
, 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
)
static
rt_err_t
_
function_disable
(
ufunction_t
func
)
{
mass_eps_t
eps
;
RT_ASSERT
(
device
!=
RT_NULL
);
struct
mstorage
*
data
;
RT_ASSERT
(
func
!=
RT_NULL
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"Mass storage function disabled
\n
"
));
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
;
data
=
(
struct
mstorage
*
)
func
->
user_data
;
if
(
data
->
ep_in
->
buffer
!=
RT_NULL
)
{
rt_free
(
data
->
ep_in
->
buffer
);
data
->
ep_in
->
buffer
=
RT_NULL
;
}
if
(
data
->
ep_out
->
buffer
!=
RT_NULL
)
{
rt_free
(
data
->
ep_out
->
buffer
);
data
->
ep_out
->
buffer
=
RT_NULL
;
}
data
->
status
=
STAT_CBW
;
return
RT_EOK
;
}
static
struct
u
class
_ops
ops
=
static
struct
u
function
_ops
ops
=
{
_
class_run
,
_
class_stop
,
_
function_enable
,
_
function_disable
,
RT_NULL
,
};
/**
* This function will create a mass storage
class
instance.
* This function will create a mass storage
function
instance.
*
* @param device the usb device object.
*
* @return RT_EOK on successful.
*/
u
class_t
rt_usbd_class
_mstorage_create
(
udevice_t
device
)
u
function_t
rt_usbd_function
_mstorage_create
(
udevice_t
device
)
{
uintf_t
intf
;
mass_eps_t
eps
;
u
class_t
mstorage
;
struct
mstorage
*
data
;
u
function_t
func
;
ualtsetting_t
setting
;
umass_desc_t
mass_desc
;
...
...
@@ -597,37 +1047,42 @@ uclass_t rt_usbd_class_mstorage_create(udevice_t device)
/* set usb device string description */
rt_usbd_device_set_string
(
device
,
_ustring
);
/* 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
));
/* create a mass storage function */
func
=
rt_usbd_function_new
(
device
,
&
dev_desc
,
&
ops
);
device
->
dev_qualifier
=
&
dev_qualifier
;
/* allocate memory for mass storage function data */
data
=
(
struct
mstorage
*
)
rt_malloc
(
sizeof
(
struct
mstorage
));
rt_memset
(
data
,
0
,
sizeof
(
struct
mstorage
));
func
->
user_data
=
(
void
*
)
data
;
/* create an interface object */
intf
=
rt_usbd_interface_new
(
device
,
_interface_handler
);
/* create an alternate setting object */
setting
=
rt_usbd_altsetting_new
(
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
);
data
->
ep_in
=
rt_usbd_endpoint_new
(
&
mass_desc
->
ep_in_desc
,
_ep_in_handler
);
data
->
ep_out
=
rt_usbd_endpoint_new
(
&
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
);
rt_usbd_altsetting_add_endpoint
(
setting
,
data
->
ep_out
);
rt_usbd_altsetting_add_endpoint
(
setting
,
data
->
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
);
/* add the interface to the mass storage
function
*/
rt_usbd_
function_add_interface
(
func
,
intf
);
return
mstorage
;
return
func
;
}
#endif
...
...
components/drivers/usb/usbdevice/class/mstorage.h
浏览文件 @
8fd0a7f9
...
...
@@ -59,13 +59,6 @@ struct request_sense_data
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
components/drivers/usb/usbdevice/core/core.c
浏览文件 @
8fd0a7f9
...
...
@@ -20,8 +20,10 @@
* Change Logs:
* Date Author Notes
* 2012-10-01 Yi Qiu first version
* 2012-12-12 heyuanjie87 change endpoint and
class
handler
* 2012-12-12 heyuanjie87 change endpoint and
function
handler
* 2012-12-30 heyuanjie87 change inferface handler
* 2013-04-26 aozima add DEVICEQUALIFIER support.
* 2013-07-25 Yi Qiu update for USB CV test
*/
#include <rtthread.h>
...
...
@@ -29,6 +31,11 @@
static
rt_list_t
device_list
;
static
rt_size_t
rt_usbd_ep_write
(
udevice_t
device
,
uep_t
ep
,
void
*
buffer
,
rt_size_t
size
);
static
rt_size_t
rt_usbd_ep_read_prepare
(
udevice_t
device
,
uep_t
ep
,
void
*
buffer
,
rt_size_t
size
);
static
rt_err_t
rt_usbd_ep_assign
(
udevice_t
device
,
uep_t
ep
);
static
rt_err_t
rt_usbd_ep_unassign
(
udevice_t
device
,
uep_t
ep
);
/**
* This function will handle get_device_descriptor request.
*
...
...
@@ -37,7 +44,7 @@ static rt_list_t device_list;
*
* @return RT_EOK on successful.
*/
static
rt_err_t
_get_device_descriptor
(
struct
udevice
*
device
,
ureq_t
setup
)
static
rt_err_t
_get_device_descriptor
(
struct
udevice
*
device
,
ureq_t
setup
)
{
rt_size_t
size
;
...
...
@@ -52,7 +59,8 @@ static rt_err_t _get_device_descriptor(struct udevice *device, ureq_t setup)
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
);
rt_usbd_ep0_write
(
device
,
(
rt_uint8_t
*
)
&
device
->
dev_desc
,
size
);
return
RT_EOK
;
}
...
...
@@ -65,7 +73,7 @@ static rt_err_t _get_device_descriptor(struct udevice *device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
static
rt_err_t
_get_config_descriptor
(
struct
udevice
*
device
,
ureq_t
setup
)
static
rt_err_t
_get_config_descriptor
(
struct
udevice
*
device
,
ureq_t
setup
)
{
rt_size_t
size
;
ucfg_desc_t
cfg_desc
;
...
...
@@ -81,7 +89,7 @@ static rt_err_t _get_config_descriptor(struct udevice *device, ureq_t setup)
cfg_desc
->
wTotalLength
:
setup
->
length
;
/* send configuration descriptor to endpoint 0 */
dcd_ep_write
(
device
->
dcd
,
0
,
(
rt_uint8_t
*
)
cfg_desc
,
size
);
rt_usbd_ep0_write
(
device
,
(
rt_uint8_t
*
)
cfg_desc
,
size
);
return
RT_EOK
;
}
...
...
@@ -94,7 +102,7 @@ static rt_err_t _get_config_descriptor(struct udevice *device, ureq_t setup)
*
* @return RT_EOK on successful, -RT_ERROR on invalid request.
*/
static
rt_err_t
_get_string_descriptor
(
struct
udevice
*
device
,
ureq_t
setup
)
static
rt_err_t
_get_string_descriptor
(
struct
udevice
*
device
,
ureq_t
setup
)
{
struct
ustring_descriptor
str_desc
;
rt_uint8_t
index
,
i
;
...
...
@@ -109,14 +117,13 @@ static rt_err_t _get_string_descriptor(struct udevice *device, ureq_t setup)
str_desc
.
type
=
USB_DESC_TYPE_STRING
;
index
=
setup
->
value
&
0xFF
;
if
(
index
>
USB_STRING_INTERFACE_INDEX
)
if
(
index
>
USB_STRING_INTERFACE_INDEX
)
{
rt_kprintf
(
"unknown string index
\n
"
);
dcd_ep_stall
(
device
->
dcd
,
0
);
rt_usbd_ep0_set_stall
(
device
);
return
-
RT_ERROR
;
}
if
(
index
==
0
)
if
(
index
==
0
)
{
str_desc
.
bLength
=
4
;
str_desc
.
String
[
0
]
=
0x09
;
...
...
@@ -127,7 +134,7 @@ static rt_err_t _get_string_descriptor(struct udevice *device, ureq_t setup)
len
=
rt_strlen
(
device
->
str
[
index
]);
str_desc
.
bLength
=
len
*
2
+
2
;
for
(
i
=
0
;
i
<
len
;
i
++
)
for
(
i
=
0
;
i
<
len
;
i
++
)
{
str_desc
.
String
[
i
*
2
]
=
device
->
str
[
index
][
i
];
str_desc
.
String
[
i
*
2
+
1
]
=
0
;
...
...
@@ -140,7 +147,29 @@ static rt_err_t _get_string_descriptor(struct udevice *device, ureq_t setup)
len
=
setup
->
length
;
/* send string descriptor to endpoint 0 */
dcd_ep_write
(
device
->
dcd
,
0
,
(
rt_uint8_t
*
)
&
str_desc
,
len
);
rt_usbd_ep0_write
(
device
,
(
rt_uint8_t
*
)
&
str_desc
,
len
);
return
RT_EOK
;
}
static
rt_err_t
_get_qualifier_descriptor
(
struct
udevice
*
device
,
ureq_t
setup
)
{
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_get_qualifier_descriptor
\n
"
));
/* parameter check */
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
setup
!=
RT_NULL
);
if
(
device
->
dev_qualifier
)
{
/* send device qualifier descriptor to endpoint 0 */
rt_usbd_ep0_write
(
device
,
(
rt_uint8_t
*
)
device
->
dev_qualifier
,
sizeof
(
struct
usb_qualifier_descriptor
));
}
else
{
rt_usbd_ep0_set_stall
(
device
);
}
return
RT_EOK
;
}
...
...
@@ -153,15 +182,15 @@ static rt_err_t _get_string_descriptor(struct udevice *device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
static
rt_err_t
_get_descriptor
(
struct
udevice
*
device
,
ureq_t
setup
)
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
)
if
(
setup
->
request_type
==
USB_REQ_TYPE_DIR_IN
)
{
switch
(
setup
->
value
>>
8
)
switch
(
setup
->
value
>>
8
)
{
case
USB_DESC_TYPE_DEVICE
:
_get_device_descriptor
(
device
,
setup
);
...
...
@@ -173,18 +202,18 @@ static rt_err_t _get_descriptor(struct udevice *device, ureq_t setup)
_get_string_descriptor
(
device
,
setup
);
break
;
case
USB_DESC_TYPE_DEVICEQUALIFIER
:
dcd_ep_stall
(
device
->
dcd
,
0
);
_get_qualifier_descriptor
(
device
,
setup
);
break
;
default:
rt_kprintf
(
"unsupported descriptor request
\n
"
);
dcd_ep_stall
(
device
->
dcd
,
0
);
rt_usbd_ep0_set_stall
(
device
);
break
;
}
}
else
{
rt_kprintf
(
"request direction error
\n
"
);
dcd_ep_stall
(
device
->
dcd
,
0
);
rt_usbd_ep0_set_stall
(
device
);
}
return
RT_EOK
;
...
...
@@ -198,7 +227,7 @@ static rt_err_t _get_descriptor(struct udevice *device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
static
rt_err_t
_get_interface
(
struct
udevice
*
device
,
ureq_t
setup
)
static
rt_err_t
_get_interface
(
struct
udevice
*
device
,
ureq_t
setup
)
{
rt_uint8_t
value
;
uintf_t
intf
;
...
...
@@ -211,8 +240,7 @@ static rt_err_t _get_interface(struct udevice *device, ureq_t setup)
if
(
device
->
state
!=
USB_STATE_CONFIGURED
)
{
dcd_ep_stall
(
device
->
dcd
,
0
);
rt_usbd_ep0_set_stall
(
device
);
return
-
RT_ERROR
;
}
...
...
@@ -221,7 +249,7 @@ static rt_err_t _get_interface(struct udevice *device, ureq_t setup)
value
=
intf
->
curr_setting
->
intf_desc
->
bAlternateSetting
;
/* send the interface alternate setting to endpoint 0*/
dcd_ep_write
(
device
->
dcd
,
0
,
&
value
,
1
);
rt_usbd_ep0_write
(
device
,
&
value
,
1
);
return
RT_EOK
;
}
...
...
@@ -234,11 +262,11 @@ static rt_err_t _get_interface(struct udevice *device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
static
rt_err_t
_set_interface
(
struct
udevice
*
device
,
ureq_t
setup
)
static
rt_err_t
_set_interface
(
struct
udevice
*
device
,
ureq_t
setup
)
{
uintf_t
intf
;
uep_t
ep
;
struct
rt_list_node
*
i
;
struct
rt_list_node
*
i
;
ualtsetting_t
setting
;
/* parameter check */
...
...
@@ -249,11 +277,10 @@ static rt_err_t _set_interface(struct udevice *device, ureq_t setup)
if
(
device
->
state
!=
USB_STATE_CONFIGURED
)
{
dcd_ep_stall
(
device
->
dcd
,
0
);
rt_usbd_ep0_set_stall
(
device
);
return
-
RT_ERROR
;
}
/* find the specified interface */
intf
=
rt_usbd_find_interface
(
device
,
setup
->
index
&
0xFF
,
RT_NULL
);
...
...
@@ -262,13 +289,13 @@ static rt_err_t _set_interface(struct udevice *device, ureq_t setup)
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
)
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
);
dcd_ep_
disable
(
device
->
dcd
,
ep
);
dcd_ep_
enable
(
device
->
dcd
,
ep
);
}
dcd_send_status
(
device
->
dcd
);
dcd_
ep0_
send_status
(
device
->
dcd
);
return
RT_EOK
;
}
...
...
@@ -281,7 +308,7 @@ static rt_err_t _set_interface(struct udevice *device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
static
rt_err_t
_get_config
(
struct
udevice
*
device
,
ureq_t
setup
)
static
rt_err_t
_get_config
(
struct
udevice
*
device
,
ureq_t
setup
)
{
rt_uint8_t
value
;
...
...
@@ -291,7 +318,7 @@ static rt_err_t _get_config(struct udevice *device, ureq_t setup)
RT_ASSERT
(
device
->
curr_cfg
!=
RT_NULL
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_get_config
\n
"
));
if
(
device
->
state
==
USB_STATE_CONFIGURED
)
{
/* get current configuration */
...
...
@@ -302,7 +329,7 @@ static rt_err_t _get_config(struct udevice *device, ureq_t setup)
value
=
0
;
}
/* write the current configuration to endpoint 0 */
dcd_ep_write
(
device
->
dcd
,
0
,
&
value
,
1
);
rt_usbd_ep0_write
(
device
,
&
value
,
1
);
return
RT_EOK
;
}
...
...
@@ -315,7 +342,7 @@ static rt_err_t _get_config(struct udevice *device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
static
rt_err_t
_set_config
(
struct
udevice
*
device
,
ureq_t
setup
)
static
rt_err_t
_set_config
(
struct
udevice
*
device
,
ureq_t
setup
)
{
struct
rt_list_node
*
i
,
*
j
,
*
k
;
uconfig_t
cfg
;
...
...
@@ -331,8 +358,7 @@ static rt_err_t _set_config(struct udevice *device, ureq_t setup)
if
(
setup
->
value
>
device
->
dev_desc
.
bNumConfigurations
)
{
dcd_ep_stall
(
device
->
dcd
,
0
);
rt_usbd_ep0_set_stall
(
device
);
return
-
RT_ERROR
;
}
...
...
@@ -348,33 +374,32 @@ static rt_err_t _set_config(struct udevice *device, ureq_t setup)
rt_usbd_set_config
(
device
,
setup
->
value
);
cfg
=
device
->
curr_cfg
;
for
(
i
=
cfg
->
cls_list
.
next
;
i
!=&
cfg
->
cls
_list
;
i
=
i
->
next
)
for
(
i
=
cfg
->
func_list
.
next
;
i
!=&
cfg
->
func
_list
;
i
=
i
->
next
)
{
/* run all
class
es and their endpoints in the configuration */
u
class_t
cls
=
(
uclass_t
)
rt_list_entry
(
i
,
struct
uclass
,
list
);
for
(
j
=
cls
->
intf_list
.
next
;
j
!=&
cls
->
intf_list
;
j
=
j
->
next
)
/* run all
function
es and their endpoints in the configuration */
u
function_t
func
=
(
ufunction_t
)
rt_list_entry
(
i
,
struct
ufunction
,
list
);
for
(
j
=
func
->
intf_list
.
next
;
j
!=&
func
->
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
)
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
);
/* first
disable then enable an
endpoint */
dcd_ep_
disable
(
device
->
dcd
,
ep
);
dcd_ep_
enable
(
device
->
dcd
,
ep
);
}
}
/* after running all endpoints, then run class */
if
(
cls
->
ops
->
run
!=
RT_NULL
)
cls
->
ops
->
run
(
device
,
cls
);
/* after enabled endpoints, then enable function */
FUNC_ENABLE
(
func
);
}
device
->
state
=
USB_STATE_CONFIGURED
;
_exit:
/* issue status stage */
dcd_send_status
(
device
->
dcd
);
dcd_
ep0_
send_status
(
device
->
dcd
);
return
RT_EOK
;
}
...
...
@@ -387,38 +412,38 @@ _exit:
*
* @return RT_EOK on successful.
*/
static
rt_err_t
_set_address
(
struct
udevice
*
device
,
ureq_t
setup
)
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
"
));
/* issue status stage */
dcd_ep0_send_status
(
device
->
dcd
);
/* set address in device control driver */
dcd_set_address
(
device
->
dcd
,
setup
->
value
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_set_address
\n
"
));
device
->
state
=
USB_STATE_ADDRESS
;
/* issue status stage */
dcd_send_status
(
device
->
dcd
);
return
RT_EOK
;
}
/**
* This function will handle standard request to
* interface that defined in
class
-specifics
* This function will handle standard request to
* interface that defined in
function
-specifics
*
* @param device the usb device object.
* @param setup the setup request.
*
* @return RT_EOK on successful.
* @return RT_EOK on successful.
*/
static
rt_err_t
_request_interface
(
struct
udevice
*
device
,
ureq_t
setup
)
static
rt_err_t
_request_interface
(
struct
udevice
*
device
,
ureq_t
setup
)
{
uintf_t
intf
;
u
class_t
cls
;
u
function_t
func
;
rt_err_t
ret
;
/* parameter check */
...
...
@@ -427,16 +452,16 @@ static rt_err_t _request_interface(struct udevice *device, ureq_t setup)
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"_request_interface
\n
"
));
intf
=
rt_usbd_find_interface
(
device
,
setup
->
index
&
0xFF
,
&
cls
);
intf
=
rt_usbd_find_interface
(
device
,
setup
->
index
&
0xFF
,
&
func
);
if
(
intf
!=
RT_NULL
)
{
ret
=
intf
->
handler
(
device
,
cls
,
setup
);
ret
=
intf
->
handler
(
func
,
setup
);
}
else
{
ret
=
-
RT_ERROR
;
}
return
ret
;
}
...
...
@@ -448,7 +473,7 @@ static rt_err_t _request_interface(struct udevice *device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
static
rt_err_t
_standard_request
(
struct
udevice
*
device
,
ureq_t
setup
)
static
rt_err_t
_standard_request
(
struct
udevice
*
device
,
ureq_t
setup
)
{
udcd_t
dcd
;
rt_uint16_t
value
=
0
;
...
...
@@ -459,20 +484,20 @@ static rt_err_t _standard_request(struct udevice *device, ureq_t setup)
dcd
=
device
->
dcd
;
switch
(
setup
->
request_type
&
USB_REQ_TYPE_RECIPIENT_MASK
)
switch
(
setup
->
request_type
&
USB_REQ_TYPE_RECIPIENT_MASK
)
{
case
USB_REQ_TYPE_DEVICE
:
switch
(
setup
->
request
)
switch
(
setup
->
request
)
{
case
USB_REQ_GET_STATUS
:
dcd_ep_write
(
device
->
dcd
,
0
,
&
value
,
2
);
rt_usbd_ep0_write
(
device
,
&
value
,
2
);
break
;
case
USB_REQ_CLEAR_FEATURE
:
dcd_clear_feature
(
dcd
,
setup
->
value
,
setup
->
index
);
dcd_send_status
(
dcd
);
rt_usbd_clear_feature
(
device
,
setup
->
value
,
setup
->
index
);
dcd_
ep0_
send_status
(
dcd
);
break
;
case
USB_REQ_SET_FEATURE
:
dcd_set_feature
(
dcd
,
setup
->
value
,
setup
->
index
);
rt_usbd_set_feature
(
device
,
setup
->
value
,
setup
->
index
);
break
;
case
USB_REQ_SET_ADDRESS
:
_set_address
(
device
,
setup
);
...
...
@@ -481,7 +506,7 @@ static rt_err_t _standard_request(struct udevice *device, ureq_t setup)
_get_descriptor
(
device
,
setup
);
break
;
case
USB_REQ_SET_DESCRIPTOR
:
dcd_ep_stall
(
dcd
,
0
);
rt_usbd_ep0_set_stall
(
device
);
break
;
case
USB_REQ_GET_CONFIGURATION
:
_get_config
(
device
,
setup
);
...
...
@@ -491,12 +516,12 @@ static rt_err_t _standard_request(struct udevice *device, ureq_t setup)
break
;
default:
rt_kprintf
(
"unknown device request
\n
"
);
dcd_ep_stall
(
device
->
dcd
,
0
);
rt_usbd_ep0_set_stall
(
device
);
break
;
}
break
;
case
USB_REQ_TYPE_INTERFACE
:
switch
(
setup
->
request
)
switch
(
setup
->
request
)
{
case
USB_REQ_GET_INTERFACE
:
_get_interface
(
device
,
setup
);
...
...
@@ -508,8 +533,7 @@ static rt_err_t _standard_request(struct udevice *device, ureq_t setup)
if
(
_request_interface
(
device
,
setup
)
!=
RT_EOK
)
{
rt_kprintf
(
"unknown interface request
\n
"
);
dcd_ep_stall
(
device
->
dcd
,
0
);
rt_usbd_ep0_set_stall
(
device
);
return
-
RT_ERROR
;
}
else
...
...
@@ -517,53 +541,69 @@ static rt_err_t _standard_request(struct udevice *device, ureq_t setup)
}
break
;
case
USB_REQ_TYPE_ENDPOINT
:
switch
(
setup
->
request
)
switch
(
setup
->
request
)
{
case
USB_REQ_GET_STATUS
:
{
/* TODO */
uep_t
ep
;
ep
=
rt_usbd_find_endpoint
(
device
,
RT_NULL
,
setup
->
index
);
value
=
ep
->
is_stall
;
dcd_ep_write
(
dcd
,
0
,
&
value
,
2
);
value
=
ep
->
stalled
;
rt_usbd_ep0_write
(
device
,
&
value
,
2
);
}
break
;
case
USB_REQ_CLEAR_FEATURE
:
{
uep_t
ep
;
uio_request_t
req
;
struct
rt_list_node
*
node
;
ep
=
rt_usbd_find_endpoint
(
device
,
RT_NULL
,
setup
->
index
);
ep
->
is_stall
=
0
;
dcd_clear_feature
(
dcd
,
setup
->
value
,
setup
->
index
);
dcd_send_status
(
dcd
);
if
(
USB_EP_HALT
==
setup
->
value
&&
ep
->
stalled
==
RT_TRUE
)
{
rt_usbd_clear_feature
(
device
,
setup
->
value
,
setup
->
index
);
dcd_ep0_send_status
(
dcd
);
ep
->
stalled
=
RT_FALSE
;
for
(
node
=
ep
->
request_list
.
next
;
node
!=
&
ep
->
request_list
;
node
=
node
->
next
)
{
req
=
(
uio_request_t
)
rt_list_entry
(
node
,
struct
uio_request
,
list
);
rt_usbd_io_request
(
device
,
ep
,
req
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"fired a request
\n
"
));
}
rt_list_init
(
&
ep
->
request_list
);
}
}
break
;
case
USB_REQ_SET_FEATURE
:
{
uep_t
ep
;
ep
=
rt_usbd_find_endpoint
(
device
,
RT_NULL
,
setup
->
index
);
ep
->
is_stall
=
1
;
dcd_set_feature
(
dcd
,
setup
->
value
,
setup
->
index
);
dcd_send_status
(
dcd
);
if
(
USB_EP_HALT
==
setup
->
value
)
{
ep
=
rt_usbd_find_endpoint
(
device
,
RT_NULL
,
setup
->
index
);
ep
->
stalled
=
RT_TRUE
;
rt_usbd_set_feature
(
device
,
setup
->
value
,
setup
->
index
);
dcd_ep0_send_status
(
dcd
);
}
}
break
;
case
USB_REQ_SYNCH_FRAME
:
break
;
default:
rt_kprintf
(
"unknown endpoint request
\n
"
);
dcd_ep_stall
(
device
->
dcd
,
0
);
rt_usbd_ep0_set_stall
(
device
);
break
;
}
break
;
case
USB_REQ_TYPE_OTHER
:
rt_kprintf
(
"unknown other type request
\n
"
);
dcd_ep_stall
(
device
->
dcd
,
0
);
rt_usbd_ep0_set_stall
(
device
);
break
;
default:
rt_kprintf
(
"unknown type request
\n
"
);
dcd_ep_stall
(
device
->
dcd
,
0
);
rt_usbd_ep0_set_stall
(
device
);
break
;
}
...
...
@@ -571,47 +611,68 @@ static rt_err_t _standard_request(struct udevice *device, ureq_t setup)
}
/**
* This function will handle
class
request.
* This function will handle
function
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
)
static
rt_err_t
_
function
_request
(
udevice_t
device
,
ureq_t
setup
)
{
uintf_t
intf
;
u
class_t
cls
;
u
function_t
func
;
/* parameter check */
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
setup
!=
RT_NULL
);
/* verify request value */
if
(
setup
->
index
>
device
->
curr_cfg
->
cfg_desc
.
bNumInterfaces
)
if
(
setup
->
index
>
device
->
curr_cfg
->
cfg_desc
.
bNumInterfaces
)
{
dcd_ep_stall
(
device
->
dcd
,
0
);
rt_usbd_ep0_set_stall
(
device
);
return
-
RT_ERROR
;
}
switch
(
setup
->
request_type
&
USB_REQ_TYPE_RECIPIENT_MASK
)
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
);
intf
=
rt_usbd_find_interface
(
device
,
setup
->
index
&
0xFF
,
&
func
);
if
(
intf
==
RT_NULL
)
{
rt_kprintf
(
"unkwown interface request
\n
"
);
rt_usbd_ep0_set_stall
(
device
);
}
else
{
intf
->
handler
(
func
,
setup
);
}
break
;
case
USB_REQ_TYPE_ENDPOINT
:
break
;
default:
rt_kprintf
(
"unknown
class
request type
\n
"
);
dcd_ep_stall
(
device
->
dcd
,
0
);
rt_kprintf
(
"unknown
function
request type
\n
"
);
rt_usbd_ep0_set_stall
(
device
);
break
;
}
return
RT_EOK
;
}
static
rt_err_t
_dump_setup_packet
(
ureq_t
setup
)
{
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"[
\n
"
));
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"setup_request 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
"
));
return
RT_EOK
;
}
/**
* This function will handle setup request.
*
...
...
@@ -626,29 +687,22 @@ static rt_err_t _setup_request(udevice_t device, ureq_t setup)
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
"
));
_dump_setup_packet
(
setup
);
switch
((
setup
->
request_type
&
USB_REQ_TYPE_MASK
))
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
);
_
function
_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
);
rt_usbd_ep0_set_stall
(
device
);
return
-
RT_ERROR
;
}
...
...
@@ -656,104 +710,207 @@ static rt_err_t _setup_request(udevice_t device, ureq_t setup)
}
/**
* This function will
notity sof event to all of class
.
* This function will
hanle data notify event
.
*
* @param device the usb device object.
* @param device the usb device object.
* @param ep_msg the endpoint message.
*
* @return RT_EOK.
*/
rt_err_t
_sof_notify
(
udevice_t
device
)
static
rt_err_t
_data_notify
(
udevice_t
device
,
struct
ep_msg
*
ep_msg
)
{
struct
rt_list_node
*
i
;
uclass_t
cls
;
uep_t
ep
;
ufunction_t
func
;
rt_size_t
size
=
0
;
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
ep_msg
!=
RT_NULL
);
if
(
device
->
state
!=
USB_STATE_CONFIGURED
)
{
return
-
RT_ERROR
;
}
ep
=
rt_usbd_find_endpoint
(
device
,
&
func
,
ep_msg
->
ep_addr
);
if
(
ep
==
RT_NULL
)
{
rt_kprintf
(
"invalid endpoint
\n
"
);
return
-
RT_ERROR
;
}
if
(
EP_ADDRESS
(
ep
)
&
USB_DIR_IN
)
{
if
(
ep
->
request
.
remain_size
>=
EP_MAXPACKET
(
ep
))
{
dcd_ep_write
(
device
->
dcd
,
EP_ADDRESS
(
ep
),
ep
->
request
.
buffer
,
EP_MAXPACKET
(
ep
));
ep
->
request
.
remain_size
-=
EP_MAXPACKET
(
ep
);
ep
->
request
.
buffer
+=
EP_MAXPACKET
(
ep
);
}
else
if
(
ep
->
request
.
remain_size
>
0
)
{
dcd_ep_write
(
device
->
dcd
,
EP_ADDRESS
(
ep
),
ep
->
request
.
buffer
,
ep
->
request
.
remain_size
);
ep
->
request
.
remain_size
=
0
;
}
else
{
EP_HANDLER
(
ep
,
func
,
size
);
}
}
else
{
size
=
ep_msg
->
size
;
if
(
ep
->
request
.
remain_size
==
0
)
{
return
RT_EOK
;
}
if
(
size
==
0
)
{
size
=
dcd_ep_read
(
device
->
dcd
,
EP_ADDRESS
(
ep
),
ep
->
request
.
buffer
);
}
ep
->
request
.
remain_size
-=
size
;
ep
->
request
.
buffer
+=
size
;
if
(
ep
->
request
.
req_type
==
UIO_REQUEST_READ_BEST
)
{
EP_HANDLER
(
ep
,
func
,
size
);
}
else
if
(
ep
->
request
.
remain_size
==
0
)
{
EP_HANDLER
(
ep
,
func
,
ep
->
request
.
size
);
}
}
return
RT_EOK
;
}
static
rt_err_t
_ep0_out_notify
(
udevice_t
device
,
struct
ep_msg
*
ep_msg
)
{
uep_t
ep0
;
rt_size_t
size
;
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
ep_msg
!=
RT_NULL
);
RT_ASSERT
(
device
->
dcd
!=
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
)
ep0
=
&
device
->
dcd
->
ep0
;
size
=
ep_msg
->
size
;
if
(
ep0
->
request
.
remain_size
==
0
)
{
return
RT_EOK
;
}
if
(
size
==
0
)
{
size
=
dcd_ep_read
(
device
->
dcd
,
EP0_OUT_ADDR
,
ep0
->
request
.
buffer
);
if
(
size
==
0
)
{
return
RT_EOK
;
}
}
ep0
->
request
.
remain_size
-=
size
;
ep0
->
request
.
buffer
+=
size
;
if
(
ep0
->
request
.
remain_size
==
0
)
{
cls
=
(
uclass_t
)
rt_list_entry
(
i
,
struct
uclass
,
list
);
if
(
cls
->
ops
->
sof_handler
!=
RT_NULL
)
cls
->
ops
->
sof_handler
(
device
,
cls
);
/* invoke callback */
if
(
ep0
->
rx_indicate
!=
RT_NULL
)
{
ep0
->
rx_indicate
(
device
,
size
);
}
}
return
RT_EOK
;
}
/**
* This function will
stop all class
.
* This function will
notity sof event to all of function
.
*
* @param device the usb device object.
*
* @return RT_EOK.
*/
rt_err_t
_stop
_notify
(
udevice_t
device
)
static
rt_err_t
_sof
_notify
(
udevice_t
device
)
{
struct
rt_list_node
*
i
;
u
class_t
cls
;
u
function_t
func
;
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
)
/* to notity every function that sof event comes */
for
(
i
=
device
->
curr_cfg
->
func_list
.
next
;
i
!=&
device
->
curr_cfg
->
func_list
;
i
=
i
->
next
)
{
cls
=
(
uclass_t
)
rt_list_entry
(
i
,
struct
uclass
,
list
);
if
(
cls
->
ops
->
stop
!=
RT_NULL
)
cls
->
ops
->
stop
(
device
,
cls
);
func
=
(
ufunction_t
)
rt_list_entry
(
i
,
struct
ufunction
,
list
);
if
(
func
->
ops
->
sof_handler
!=
RT_NULL
)
func
->
ops
->
sof_handler
(
func
);
}
return
RT_EOK
;
}
/**
* This function will
run all clas
s.
* This function will
disable all USB function
s.
*
* @param device the usb device object.
*
* @return RT_EOK.
*/
rt_err_t
_run
_notify
(
udevice_t
device
)
static
rt_err_t
_stop
_notify
(
udevice_t
device
)
{
struct
rt_list_node
*
i
;
u
class_t
cls
;
u
function_t
func
;
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
;
/* to notity every
function
*/
for
(
i
=
device
->
curr_cfg
->
func
_list
.
next
;
i
!=
&
device
->
curr_cfg
->
func
_list
;
i
=
i
->
next
)
{
cls
=
(
uclass_t
)
rt_list_entry
(
i
,
struct
uclass
,
list
);
if
(
cls
->
ops
->
run
!=
RT_NULL
)
cls
->
ops
->
run
(
device
,
cls
);
func
=
(
ufunction_t
)
rt_list_entry
(
i
,
struct
ufunction
,
list
);
FUNC_DISABLE
(
func
);
}
return
RT_EOK
;
}
/**
* This function will reset all class.
*
* @param device the usb device object.
*
* @return RT_EOK.
*/
rt_err_t
_reset_notify
(
udevice_t
device
)
static
rt_size_t
rt_usbd_ep_write
(
udevice_t
device
,
uep_t
ep
,
void
*
buffer
,
rt_size_t
size
)
{
struct
rt_list_node
*
i
;
uclass_t
cls
;
rt_uint16_t
maxpacket
;
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
device
->
dcd
!=
RT_NULL
);
RT_ASSERT
(
ep
!=
RT_NULL
);
RT_ASSERT
(
device
!=
RT_NULL
);
maxpacket
=
EP_MAXPACKET
(
ep
);
if
(
ep
->
request
.
remain_size
>=
maxpacket
)
{
dcd_ep_write
(
device
->
dcd
,
EP_ADDRESS
(
ep
),
ep
->
request
.
buffer
,
maxpacket
);
ep
->
request
.
remain_size
-=
maxpacket
;
ep
->
request
.
buffer
+=
maxpacket
;
}
else
{
dcd_ep_write
(
device
->
dcd
,
EP_ADDRESS
(
ep
),
ep
->
request
.
buffer
,
ep
->
request
.
remain_size
);
ep
->
request
.
remain_size
=
0
;
}
_stop_notify
(
device
)
;
_run_notify
(
device
);
return
size
;
}
return
RT_EOK
;
static
rt_size_t
rt_usbd_ep_read_prepare
(
udevice_t
device
,
uep_t
ep
,
void
*
buffer
,
rt_size_t
size
)
{
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
device
->
dcd
!=
RT_NULL
);
RT_ASSERT
(
ep
!=
RT_NULL
);
RT_ASSERT
(
buffer
!=
RT_NULL
);
RT_ASSERT
(
ep
->
ep_desc
!=
RT_NULL
);
return
dcd_ep_read_prepare
(
device
->
dcd
,
EP_ADDRESS
(
ep
),
buffer
,
size
);
}
/**
...
...
@@ -763,18 +920,17 @@ rt_err_t _reset_notify(udevice_t device)
*
* @return an usb device object on success, RT_NULL on fail.
*/
udevice_t
rt_usbd_device_
create
(
void
)
udevice_t
rt_usbd_device_
new
(
void
)
{
udevice_t
udevice
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_device_
create
\n
"
));
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_device_
new
\n
"
));
/* allocate memory for the object */
udevice
=
rt_malloc
(
sizeof
(
struct
udevice
));
if
(
udevice
==
RT_NULL
)
if
(
udevice
==
RT_NULL
)
{
rt_kprintf
(
"alloc memery failed
\n
"
);
return
RT_NULL
;
}
rt_memset
(
udevice
,
0
,
sizeof
(
struct
udevice
));
...
...
@@ -783,7 +939,7 @@ udevice_t rt_usbd_device_create(void)
rt_list_init
(
&
udevice
->
cfg_list
);
/* insert the device object to device list */
rt_list_insert_
after
(
&
device_list
,
&
udevice
->
list
);
rt_list_insert_
before
(
&
device_list
,
&
udevice
->
list
);
return
udevice
;
}
...
...
@@ -791,7 +947,7 @@ udevice_t rt_usbd_device_create(void)
/**
* This function will set usb device string description.
*
* @param device the usb device object.
* @param device the usb device object.
* @param ustring pointer to string pointer array.
*
* @return RT_EOK.
...
...
@@ -808,6 +964,17 @@ rt_err_t rt_usbd_device_set_string(udevice_t device, const char** ustring)
return
RT_EOK
;
}
rt_err_t
rt_usbd_device_set_qualifier
(
udevice_t
device
,
struct
usb_qualifier_descriptor
*
qualifier
)
{
/* parameter check */
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
qualifier
!=
RT_NULL
);
device
->
dev_qualifier
=
qualifier
;
return
RT_EOK
;
}
/**
* This function will set an usb controller driver to a device.
*
...
...
@@ -855,31 +1022,30 @@ rt_err_t rt_usbd_device_set_descriptor(udevice_t device, udev_desc_t dev_desc)
*
* @return an usb configuration object.
*/
uconfig_t
rt_usbd_config_
create
(
void
)
uconfig_t
rt_usbd_config_
new
(
void
)
{
uconfig_t
cfg
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_config_
create
\n
"
));
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_config_
new
\n
"
));
/* allocate memory for the object */
cfg
=
rt_malloc
(
sizeof
(
struct
uconfig
));
if
(
cfg
==
RT_NULL
)
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
.
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
;
cfg
->
cfg_desc
.
MaxPower
=
0x32
;
/* to initialize
class
object list */
rt_list_init
(
&
cfg
->
cls
_list
);
/* to initialize
function
object list */
rt_list_init
(
&
cfg
->
func
_list
);
return
cfg
;
}
...
...
@@ -892,21 +1058,20 @@ uconfig_t rt_usbd_config_create(void)
*
* @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
rt_usbd_interface_
new
(
udevice_t
device
,
uintf_handler_t
handler
)
{
uintf_t
intf
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_interface_
create
\n
"
));
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_interface_
new
\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
)
if
(
intf
==
RT_NULL
)
{
rt_kprintf
(
"alloc memery failed
\n
"
);
return
RT_NULL
;
}
intf
->
intf_num
=
device
->
nr_intf
;
...
...
@@ -928,21 +1093,20 @@ uintf_t rt_usbd_interface_create(udevice_t device, uintf_handler_t handler)
*
* @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
rt_usbd_altsetting_
new
(
rt_size_t
desc_size
)
{
ualtsetting_t
setting
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_altsetting_
create
\n
"
));
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_altsetting_
new
\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
)
if
(
setting
==
RT_NULL
)
{
rt_kprintf
(
"alloc memery failed
\n
"
);
return
RT_NULL
;
}
/* allocate memory for the desc */
...
...
@@ -951,7 +1115,6 @@ ualtsetting_t rt_usbd_altsetting_create(rt_size_t desc_size)
{
rt_kprintf
(
"alloc desc memery failed
\n
"
);
rt_free
(
setting
);
return
RT_NULL
;
}
...
...
@@ -973,56 +1136,53 @@ ualtsetting_t rt_usbd_altsetting_create(rt_size_t desc_size)
*
* @return RT_EOK.
*/
rt_err_t
rt_usbd_altsetting_config_descriptor
(
ualtsetting_t
setting
,
const
void
*
desc
,
rt_off_t
intf_pos
)
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
);
setting
->
intf_desc
=
(
uintf_desc_t
)((
char
*
)
setting
->
desc
+
intf_pos
);
return
RT_EOK
;
}
/**
* This function will create an usb
class
object.
* This function will create an usb
function
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.
* @return an usb
function
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
)
ufunction_t
rt_usbd_function_new
(
udevice_t
device
,
udev_desc_t
dev_desc
,
ufunction_ops_t
ops
)
{
u
class_t
cls
;
u
function_t
func
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_
class_create
\n
"
));
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_
function_new
\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
)
func
=
(
ufunction_t
)
rt_malloc
(
sizeof
(
struct
ufunction
));
if
(
func
==
RT_NULL
)
{
rt_kprintf
(
"alloc memery failed
\n
"
);
return
RT_NULL
;
}
cls
->
dev_desc
=
dev_desc
;
cls
->
ops
=
ops
;
cls
->
device
=
device
;
func
->
dev_desc
=
dev_desc
;
func
->
ops
=
ops
;
func
->
device
=
device
;
func
->
enabled
=
RT_FALSE
;
/* to initialize interface list */
rt_list_init
(
&
cls
->
intf_list
);
rt_list_init
(
&
func
->
intf_list
);
return
cls
;
return
func
;
}
/**
...
...
@@ -1033,26 +1193,27 @@ uclass_t rt_usbd_class_create(udevice_t device,
*
* @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
rt_usbd_endpoint_
new
(
uep_desc_t
ep_desc
,
udep_handler_t
handler
)
{
uep_t
ep
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_endpoint_
create
\n
"
));
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_endpoint_
new
\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
)
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
;
ep
->
stalled
=
RT_FALSE
;
rt_list_init
(
&
ep
->
request_list
);
return
ep
;
}
...
...
@@ -1066,7 +1227,7 @@ uep_t rt_usbd_endpoint_create(uep_desc_t ep_desc, udep_handler_t handler)
*/
udevice_t
rt_usbd_find_device
(
udcd_t
dcd
)
{
struct
rt_list_node
*
node
;
struct
rt_list_node
*
node
;
udevice_t
device
;
/* parameter check */
...
...
@@ -1076,12 +1237,10 @@ udevice_t rt_usbd_find_device(udcd_t dcd)
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
;
if
(
device
->
dcd
==
dcd
)
return
device
;
}
rt_kprintf
(
"can't find device
\n
"
);
return
RT_NULL
;
}
...
...
@@ -1095,7 +1254,7 @@ udevice_t rt_usbd_find_device(udcd_t dcd)
*/
uconfig_t
rt_usbd_find_config
(
udevice_t
device
,
rt_uint8_t
value
)
{
struct
rt_list_node
*
node
;
struct
rt_list_node
*
node
;
uconfig_t
cfg
=
RT_NULL
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_find_config
\n
"
));
...
...
@@ -1105,17 +1264,16 @@ uconfig_t rt_usbd_find_config(udevice_t device, rt_uint8_t value)
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
)
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
)
if
(
cfg
->
cfg_desc
.
bConfigurationValue
==
value
)
{
return
cfg
;
}
}
rt_kprintf
(
"can't find configuration %d
\n
"
,
value
);
return
RT_NULL
;
}
...
...
@@ -1127,12 +1285,10 @@ uconfig_t rt_usbd_find_config(udevice_t device, rt_uint8_t value)
*
* @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
)
uintf_t
rt_usbd_find_interface
(
udevice_t
device
,
rt_uint8_t
value
,
ufunction_t
*
pfunc
)
{
struct
rt_list_node
*
i
,
*
j
;
u
class_t
cls
;
u
function_t
func
;
uintf_t
intf
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_find_interface
\n
"
));
...
...
@@ -1142,26 +1298,23 @@ uintf_t rt_usbd_find_interface(udevice_t device,
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
)
for
(
i
=
device
->
curr_cfg
->
func_list
.
next
;
i
!=&
device
->
curr_cfg
->
func_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
)
func
=
(
ufunction_t
)
rt_list_entry
(
i
,
struct
ufunction
,
list
);
for
(
j
=
func
->
intf_list
.
next
;
j
!=&
func
->
intf_list
;
j
=
j
->
next
)
{
intf
=
(
uintf_t
)
rt_list_entry
(
j
,
struct
uinterface
,
list
);
if
(
intf
->
intf_num
==
value
)
if
(
intf
->
intf_num
==
value
)
{
if
(
pcls
!=
RT_NULL
)
*
pcls
=
cls
;
if
(
pfunc
!=
RT_NULL
)
*
pfunc
=
func
;
return
intf
;
}
}
}
rt_kprintf
(
"can't find interface %d
\n
"
,
value
);
return
RT_NULL
;
}
...
...
@@ -1183,23 +1336,22 @@ ualtsetting_t rt_usbd_find_altsetting(uintf_t intf, rt_uint8_t value)
/* parameter check */
RT_ASSERT
(
intf
!=
RT_NULL
);
if
(
intf
->
curr_setting
!=
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
)
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
)
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
)
if
(
setting
->
intf_desc
->
bAlternateSetting
==
value
)
return
setting
;
}
rt_kprintf
(
"can't find alternate setting %d
\n
"
,
value
);
return
RT_NULL
;
}
...
...
@@ -1211,37 +1363,32 @@ ualtsetting_t rt_usbd_find_altsetting(uintf_t intf, rt_uint8_t value)
*
* @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
rt_usbd_find_endpoint
(
udevice_t
device
,
ufunction_t
*
pfunc
,
rt_uint8_t
ep_addr
)
{
uep_t
ep
;
struct
rt_list_node
*
i
,
*
j
,
*
k
;
u
class_t
cls
;
u
function_t
func
;
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
)
for
(
i
=
device
->
curr_cfg
->
func_list
.
next
;
i
!=&
device
->
curr_cfg
->
func_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
)
func
=
(
ufunction_t
)
rt_list_entry
(
i
,
struct
ufunction
,
list
);
for
(
j
=
func
->
intf_list
.
next
;
j
!=&
func
->
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
)
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
(
EP_ADDRESS
(
ep
)
==
ep_addr
)
{
if
(
pcls
!=
RT_NULL
)
*
pcls
=
cls
;
if
(
pfunc
!=
RT_NULL
)
*
pfunc
=
func
;
return
ep
;
}
}
...
...
@@ -1249,7 +1396,6 @@ uep_t rt_usbd_find_endpoint(udevice_t device,
}
rt_kprintf
(
"can't find endpoint 0x%x
\n
"
,
ep_addr
);
return
RT_NULL
;
}
...
...
@@ -1264,7 +1410,7 @@ uep_t rt_usbd_find_endpoint(udevice_t device,
rt_err_t
rt_usbd_device_add_config
(
udevice_t
device
,
uconfig_t
cfg
)
{
struct
rt_list_node
*
i
,
*
j
,
*
k
;
u
class_t
cls
;
u
function_t
func
;
uintf_t
intf
;
uep_t
ep
;
...
...
@@ -1278,79 +1424,81 @@ rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg)
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
)
for
(
i
=
cfg
->
func_list
.
next
;
i
!=&
cfg
->
func
_list
;
i
=
i
->
next
)
{
cls
=
(
uclass_t
)
rt_list_entry
(
i
,
struct
uclass
,
list
);
func
=
(
ufunction_t
)
rt_list_entry
(
i
,
struct
ufunction
,
list
);
for
(
j
=
cls
->
intf_list
.
next
;
j
!=&
cls
->
intf_list
;
j
=
j
->
next
)
for
(
j
=
func
->
intf_list
.
next
;
j
!=&
func
->
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
)
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
);
if
(
rt_usbd_ep_assign
(
device
,
ep
)
!=
RT_EOK
)
{
rt_kprintf
(
"endpoint assign error
\n
"
);
}
}
/* construct complete configuration descriptor */
rt_memcpy
((
void
*
)
&
cfg
->
cfg_desc
.
data
[
cfg
->
cfg_desc
.
wTotalLength
-
USB_DESC_LENGTH_CONFIG
],
(
void
*
)
intf
->
curr_setting
->
desc
,
intf
->
curr_setting
->
desc_size
);
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
);
rt_list_insert_
before
(
&
device
->
cfg_list
,
&
cfg
->
list
);
return
RT_EOK
;
}
/**
* This function will add a
class
to a configuration.
* This function will add a
function
to a configuration.
*
* @param cfg the configuration object.
* @param
cls the class
object.
* @param
func the function
object.
*
* @return RT_EOK.
*/
rt_err_t
rt_usbd_config_add_
class
(
uconfig_t
cfg
,
uclass_t
cls
)
rt_err_t
rt_usbd_config_add_
function
(
uconfig_t
cfg
,
ufunction_t
func
)
{
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_config_add_
class
\n
"
));
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_config_add_
function
\n
"
));
/* parameter check */
RT_ASSERT
(
cfg
!=
RT_NULL
);
RT_ASSERT
(
cls
!=
RT_NULL
);
RT_ASSERT
(
func
!=
RT_NULL
);
/* insert the
class
to the list */
rt_list_insert_
after
(
&
cfg
->
cls_list
,
&
cls
->
list
);
/* insert the
function
to the list */
rt_list_insert_
before
(
&
cfg
->
func_list
,
&
func
->
list
);
return
RT_EOK
;
}
/**
* This function will add an interface to a
class
.
* This function will add an interface to a
function
.
*
* @param
cls the class
object.
* @param
func the function
object.
* @param intf the interface object.
*
* @return RT_EOK.
*/
rt_err_t
rt_usbd_
class_add_interface
(
uclass_t
cls
,
uintf_t
intf
)
rt_err_t
rt_usbd_
function_add_interface
(
ufunction_t
func
,
uintf_t
intf
)
{
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_
class
_add_interface
\n
"
));
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"rt_usbd_
function
_add_interface
\n
"
));
/* parameter check */
RT_ASSERT
(
cls
!=
RT_NULL
);
RT_ASSERT
(
func
!=
RT_NULL
);
RT_ASSERT
(
intf
!=
RT_NULL
);
/* insert the interface to the list */
rt_list_insert_
after
(
&
cls
->
intf_list
,
&
intf
->
list
);
rt_list_insert_
before
(
&
func
->
intf_list
,
&
intf
->
list
);
return
RT_EOK
;
}
...
...
@@ -1374,7 +1522,7 @@ rt_err_t rt_usbd_interface_add_altsetting(uintf_t intf, ualtsetting_t setting)
setting
->
intf_desc
->
bInterfaceNumber
=
intf
->
intf_num
;
/* insert the alternate setting to the list */
rt_list_insert_
after
(
&
intf
->
setting_list
,
&
setting
->
list
);
rt_list_insert_
before
(
&
intf
->
setting_list
,
&
setting
->
list
);
return
RT_EOK
;
}
...
...
@@ -1396,7 +1544,7 @@ rt_err_t rt_usbd_altsetting_add_endpoint(ualtsetting_t setting, uep_t ep)
RT_ASSERT
(
ep
!=
RT_NULL
);
/* insert the endpoint to the list */
rt_list_insert_
after
(
&
setting
->
ep_list
,
&
ep
->
list
);
rt_list_insert_
before
(
&
setting
->
ep_list
,
&
ep
->
list
);
return
RT_EOK
;
}
...
...
@@ -1451,9 +1599,387 @@ rt_err_t rt_usbd_set_config(udevice_t device, rt_uint8_t value)
/* set as current configuration */
device
->
curr_cfg
=
cfg
;
dcd_set_config
(
device
->
dcd
,
value
);
return
RT_TRUE
;
}
/**
* This function will request an IO transaction.
*
* @param device the usb device object.
* @param ep the endpoint object.
* @param req IO request.
*
* @return RT_EOK.
*/
rt_size_t
rt_usbd_io_request
(
udevice_t
device
,
uep_t
ep
,
uio_request_t
req
)
{
rt_size_t
size
=
0
;
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
req
!=
RT_NULL
);
if
(
ep
->
stalled
==
RT_FALSE
)
{
switch
(
req
->
req_type
)
{
case
UIO_REQUEST_READ_BEST
:
case
UIO_REQUEST_READ_FULL
:
ep
->
request
.
remain_size
=
ep
->
request
.
size
;
size
=
rt_usbd_ep_read_prepare
(
device
,
ep
,
req
->
buffer
,
req
->
size
);
break
;
case
UIO_REQUEST_WRITE
:
ep
->
request
.
remain_size
=
ep
->
request
.
size
;
size
=
rt_usbd_ep_write
(
device
,
ep
,
req
->
buffer
,
req
->
size
);
break
;
default:
rt_kprintf
(
"unknown request type
\n
"
);
break
;
}
}
else
{
rt_list_insert_before
(
&
ep
->
request_list
,
&
req
->
list
);
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"suspend a request
\n
"
));
}
return
size
;
}
/**
* This function will set feature for an usb device.
*
* @param device the usb device object.
* @param value the configuration number.
*
* @return RT_EOK.
*/
rt_err_t
rt_usbd_set_feature
(
udevice_t
device
,
rt_uint16_t
value
,
rt_uint16_t
index
)
{
RT_ASSERT
(
device
!=
RT_NULL
);
if
(
value
==
USB_FEATURE_DEV_REMOTE_WAKEUP
)
{
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"set feature remote wakeup
\n
"
));
}
else
if
(
value
==
USB_FEATURE_ENDPOINT_HALT
)
{
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"set feature stall
\n
"
));
dcd_ep_set_stall
(
device
->
dcd
,
(
rt_uint32_t
)(
index
&
0xFF
));
}
return
RT_EOK
;
}
/**
* This function will clear feature for an usb device.
*
* @param device the usb device object.
* @param value the configuration number.
*
* @return RT_EOK.
*/
rt_err_t
rt_usbd_clear_feature
(
udevice_t
device
,
rt_uint16_t
value
,
rt_uint16_t
index
)
{
RT_ASSERT
(
device
!=
RT_NULL
);
if
(
value
==
USB_FEATURE_DEV_REMOTE_WAKEUP
)
{
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"clear feature remote wakeup
\n
"
));
}
else
if
(
value
==
USB_FEATURE_ENDPOINT_HALT
)
{
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"clear feature stall
\n
"
));
dcd_ep_clear_stall
(
device
->
dcd
,
(
rt_uint32_t
)(
index
&
0xFF
));
}
return
RT_EOK
;
}
rt_err_t
rt_usbd_ep0_set_stall
(
udevice_t
device
)
{
RT_ASSERT
(
device
!=
RT_NULL
);
return
dcd_ep_set_stall
(
device
->
dcd
,
0
);
}
rt_err_t
rt_usbd_ep0_clear_stall
(
udevice_t
device
)
{
RT_ASSERT
(
device
!=
RT_NULL
);
return
dcd_ep_clear_stall
(
device
->
dcd
,
0
);
}
rt_err_t
rt_usbd_ep_set_stall
(
udevice_t
device
,
uep_t
ep
)
{
rt_err_t
ret
;
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
ep
!=
RT_NULL
);
RT_ASSERT
(
ep
->
ep_desc
!=
RT_NULL
);
ret
=
dcd_ep_set_stall
(
device
->
dcd
,
EP_ADDRESS
(
ep
));
if
(
ret
==
RT_EOK
)
{
ep
->
stalled
=
RT_TRUE
;
}
return
ret
;
}
rt_err_t
rt_usbd_ep_clear_stall
(
udevice_t
device
,
uep_t
ep
)
{
rt_err_t
ret
;
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
ep
!=
RT_NULL
);
RT_ASSERT
(
ep
->
ep_desc
!=
RT_NULL
);
ret
=
dcd_ep_clear_stall
(
device
->
dcd
,
EP_ADDRESS
(
ep
));
if
(
ret
==
RT_EOK
)
{
ep
->
stalled
=
RT_FALSE
;
}
return
ret
;
}
static
rt_err_t
rt_usbd_ep_assign
(
udevice_t
device
,
uep_t
ep
)
{
int
i
=
0
;
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
device
->
dcd
!=
RT_NULL
);
RT_ASSERT
(
device
->
dcd
->
ep_pool
!=
RT_NULL
);
RT_ASSERT
(
ep
!=
RT_NULL
);
RT_ASSERT
(
ep
->
ep_desc
!=
RT_NULL
);
while
(
device
->
dcd
->
ep_pool
[
i
].
addr
!=
0xFF
)
{
if
(
device
->
dcd
->
ep_pool
[
i
].
status
==
ID_UNASSIGNED
&&
ep
->
ep_desc
->
bmAttributes
==
device
->
dcd
->
ep_pool
[
i
].
type
)
{
EP_ADDRESS
(
ep
)
|=
device
->
dcd
->
ep_pool
[
i
].
addr
;
ep
->
id
=
&
device
->
dcd
->
ep_pool
[
i
];
device
->
dcd
->
ep_pool
[
i
].
status
=
ID_ASSIGNED
;
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"assigned %d
\n
"
,
device
->
dcd
->
ep_pool
[
i
].
addr
));
return
RT_EOK
;
}
i
++
;
}
return
-
RT_ERROR
;
}
static
rt_err_t
rt_usbd_ep_unassign
(
udevice_t
device
,
uep_t
ep
)
{
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
device
->
dcd
!=
RT_NULL
);
RT_ASSERT
(
device
->
dcd
->
ep_pool
!=
RT_NULL
);
RT_ASSERT
(
ep
!=
RT_NULL
);
RT_ASSERT
(
ep
->
ep_desc
!=
RT_NULL
);
ep
->
id
->
status
=
ID_UNASSIGNED
;
return
RT_EOK
;
}
rt_err_t
rt_usbd_ep0_setup_handler
(
udcd_t
dcd
,
struct
ureqest
*
setup
)
{
struct
udev_msg
msg
;
rt_size_t
size
;
RT_ASSERT
(
dcd
!=
RT_NULL
);
if
(
setup
==
RT_NULL
)
{
size
=
dcd_ep_read
(
dcd
,
EP0_OUT_ADDR
,
(
void
*
)
&
msg
.
content
.
setup
);
if
(
size
!=
sizeof
(
struct
ureqest
))
{
rt_kprintf
(
"read setup packet error
\n
"
);
return
-
RT_ERROR
;
}
}
else
{
rt_memcpy
((
void
*
)
&
msg
.
content
.
setup
,
(
void
*
)
setup
,
sizeof
(
struct
ureqest
));
}
msg
.
type
=
USB_MSG_SETUP_NOTIFY
;
msg
.
dcd
=
dcd
;
rt_usbd_event_signal
(
&
msg
);
return
RT_EOK
;
}
rt_err_t
rt_usbd_ep0_in_handler
(
udcd_t
dcd
)
{
RT_ASSERT
(
dcd
!=
RT_NULL
);
if
(
dcd
->
ep0
.
request
.
remain_size
>=
dcd
->
ep0
.
id
->
maxpacket
)
{
dcd_ep_write
(
dcd
,
EP0_IN_ADDR
,
dcd
->
ep0
.
request
.
buffer
,
dcd
->
ep0
.
id
->
maxpacket
);
dcd
->
ep0
.
request
.
remain_size
-=
dcd
->
ep0
.
id
->
maxpacket
;
}
else
if
(
dcd
->
ep0
.
request
.
remain_size
>
0
)
{
dcd_ep_write
(
dcd
,
EP0_IN_ADDR
,
dcd
->
ep0
.
request
.
buffer
,
dcd
->
ep0
.
request
.
remain_size
);
dcd
->
ep0
.
request
.
remain_size
=
0
;
}
else
{
dcd_ep_write
(
dcd
,
EP0_IN_ADDR
,
RT_NULL
,
0
);
}
return
RT_EOK
;
}
rt_err_t
rt_usbd_ep0_out_handler
(
udcd_t
dcd
,
rt_size_t
size
)
{
struct
udev_msg
msg
;
RT_ASSERT
(
dcd
!=
RT_NULL
);
msg
.
type
=
USB_MSG_EP0_OUT
;
msg
.
dcd
=
dcd
;
msg
.
content
.
ep_msg
.
size
=
size
;
rt_usbd_event_signal
(
&
msg
);
return
RT_EOK
;
}
rt_err_t
rt_usbd_ep_in_handler
(
udcd_t
dcd
,
rt_uint8_t
address
)
{
struct
udev_msg
msg
;
RT_ASSERT
(
dcd
!=
RT_NULL
);
msg
.
type
=
USB_MSG_DATA_NOTIFY
;
msg
.
dcd
=
dcd
;
msg
.
content
.
ep_msg
.
ep_addr
=
address
;
msg
.
content
.
ep_msg
.
size
=
0
;
rt_usbd_event_signal
(
&
msg
);
return
RT_EOK
;
}
rt_err_t
rt_usbd_ep_out_handler
(
udcd_t
dcd
,
rt_uint8_t
address
,
rt_size_t
size
)
{
struct
udev_msg
msg
;
RT_ASSERT
(
dcd
!=
RT_NULL
);
msg
.
type
=
USB_MSG_DATA_NOTIFY
;
msg
.
dcd
=
dcd
;
msg
.
content
.
ep_msg
.
ep_addr
=
address
;
msg
.
content
.
ep_msg
.
size
=
size
;
rt_usbd_event_signal
(
&
msg
);
return
RT_EOK
;
}
rt_err_t
rt_usbd_reset_handler
(
udcd_t
dcd
)
{
struct
udev_msg
msg
;
RT_ASSERT
(
dcd
!=
RT_NULL
);
msg
.
type
=
USB_MSG_RESET
;
msg
.
dcd
=
dcd
;
rt_usbd_event_signal
(
&
msg
);
return
RT_EOK
;
}
rt_err_t
rt_usbd_connect_handler
(
udcd_t
dcd
)
{
struct
udev_msg
msg
;
RT_ASSERT
(
dcd
!=
RT_NULL
);
msg
.
type
=
USB_MSG_PLUG_IN
;
msg
.
dcd
=
dcd
;
rt_usbd_event_signal
(
&
msg
);
return
RT_EOK
;
}
rt_err_t
rt_usbd_disconnect_handler
(
udcd_t
dcd
)
{
struct
udev_msg
msg
;
RT_ASSERT
(
dcd
!=
RT_NULL
);
msg
.
type
=
USB_MSG_PLUG_OUT
;
msg
.
dcd
=
dcd
;
rt_usbd_event_signal
(
&
msg
);
return
RT_EOK
;
}
rt_err_t
rt_usbd_sof_handler
(
udcd_t
dcd
)
{
struct
udev_msg
msg
;
RT_ASSERT
(
dcd
!=
RT_NULL
);
msg
.
type
=
USB_MSG_SOF
;
msg
.
dcd
=
dcd
;
rt_usbd_event_signal
(
&
msg
);
return
RT_EOK
;
}
rt_size_t
rt_usbd_ep0_write
(
udevice_t
device
,
void
*
buffer
,
rt_size_t
size
)
{
uep_t
ep0
;
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
device
->
dcd
!=
RT_NULL
);
RT_ASSERT
(
buffer
!=
RT_NULL
);
RT_ASSERT
(
size
>
0
);
ep0
=
&
device
->
dcd
->
ep0
;
ep0
->
request
.
size
=
size
;
ep0
->
request
.
buffer
=
buffer
;
ep0
->
request
.
remain_size
=
size
;
if
(
ep0
->
request
.
remain_size
>=
ep0
->
id
->
maxpacket
)
{
dcd_ep_write
(
device
->
dcd
,
EP0_IN_ADDR
,
ep0
->
request
.
buffer
,
ep0
->
id
->
maxpacket
);
ep0
->
request
.
remain_size
-=
ep0
->
id
->
maxpacket
;
ep0
->
request
.
buffer
+=
ep0
->
id
->
maxpacket
;
}
else
{
dcd_ep_write
(
device
->
dcd
,
EP0_IN_ADDR
,
ep0
->
request
.
buffer
,
ep0
->
request
.
remain_size
);
ep0
->
request
.
remain_size
=
0
;
}
return
size
;
}
rt_size_t
rt_usbd_ep0_read
(
udevice_t
device
,
void
*
buffer
,
rt_size_t
size
,
rt_err_t
(
*
rx_ind
)(
udevice_t
device
,
rt_size_t
size
))
{
uep_t
ep0
;
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
device
->
dcd
!=
RT_NULL
);
RT_ASSERT
(
buffer
!=
RT_NULL
);
ep0
=
&
device
->
dcd
->
ep0
;
ep0
->
request
.
size
=
size
;
ep0
->
request
.
buffer
=
buffer
;
ep0
->
request
.
remain_size
=
size
;
ep0
->
rx_indicate
=
rx_ind
;
dcd_ep_read_prepare
(
device
->
dcd
,
EP0_OUT_ADDR
,
buffer
,
size
);
return
size
;
}
static
struct
rt_messagequeue
usb_mq
;
/**
...
...
@@ -1464,26 +1990,27 @@ static struct rt_messagequeue usb_mq;
*
* @return none.
*/
static
void
rt_usbd_thread_entry
(
void
*
parameter
)
static
void
rt_usbd_thread_entry
(
void
*
parameter
)
{
while
(
1
)
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
)
if
(
rt_mq_recv
(
&
usb_mq
,
&
msg
,
sizeof
(
struct
udev_msg
),
RT_WAITING_FOREVER
)
!=
RT_EOK
)
continue
;
device
=
rt_usbd_find_device
(
msg
.
dcd
);
if
(
device
==
RT_NULL
)
if
(
device
==
RT_NULL
)
{
rt_kprintf
(
"invalid usb device
\n
"
);
continue
;
}
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"message type %d
\n
"
,
msg
.
type
));
switch
(
msg
.
type
)
{
case
USB_MSG_SOF
:
...
...
@@ -1492,26 +2019,28 @@ static void rt_usbd_thread_entry(void *parameter)
case
USB_MSG_DATA_NOTIFY
:
/* some buggy drivers will have USB_MSG_DATA_NOTIFY before the core
* got configured. */
if
(
device
->
state
!=
USB_STATE_CONFIGURED
)
break
;
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
"
);
_data_notify
(
device
,
&
msg
.
content
.
ep_msg
);
break
;
case
USB_MSG_SETUP_NOTIFY
:
_setup_request
(
device
,
(
ureq_t
)
msg
.
content
.
setup_msg
.
packet
);
_setup_request
(
device
,
&
msg
.
content
.
setup
);
break
;
case
USB_MSG_EP0_OUT
:
_ep0_out_notify
(
device
,
&
msg
.
content
.
ep_msg
);
break
;
case
USB_MSG_RESET
:
case
USB_MSG_RESET
:
RT_DEBUG_LOG
(
RT_DEBUG_USB
,
(
"reset %d
\n
"
,
device
->
state
));
if
(
device
->
state
==
USB_STATE_ADDRESS
)
_reset_notify
(
device
);
_stop_notify
(
device
);
break
;
case
USB_MSG_PLUG_IN
:
device
->
state
=
USB_STATE_ATTACHED
;
break
;
case
USB_MSG_PLUG_OUT
:
device
->
state
=
USB_STATE_NOTATTACHED
;
_stop_notify
(
device
);
break
;
default:
rt_kprintf
(
"unknown msg type
\n
"
);
rt_kprintf
(
"unknown msg type
%d
\n
"
,
msg
.
type
);
break
;
}
}
...
...
@@ -1525,12 +2054,12 @@ static void rt_usbd_thread_entry(void *parameter)
*
* @return the error code, RT_EOK on successfully.
*/
rt_err_t
rt_usbd_
post_event
(
struct
udev_msg
*
msg
,
rt_size_t
size
)
rt_err_t
rt_usbd_
event_signal
(
struct
udev_msg
*
msg
)
{
RT_ASSERT
(
msg
!=
RT_NULL
);
/* send message to usb message queue */
return
rt_mq_send
(
&
usb_mq
,
(
void
*
)
msg
,
size
);
return
rt_mq_send
(
&
usb_mq
,
(
void
*
)
msg
,
sizeof
(
struct
udev_msg
)
);
}
...
...
@@ -1548,30 +2077,21 @@ static rt_uint8_t usb_mq_pool[(USBD_MQ_MSG_SZ+sizeof(void*))*USBD_MQ_MAX_MSG];
* This function will initialize usb device thread.
*
* @return none.
*
*/
rt_err_t
rt_usbd_core_init
(
void
)
{
rt_list_init
(
&
device_list
);
/* create an usb message queue */
rt_mq_init
(
&
usb_mq
,
"usbd"
,
usb_mq_pool
,
USBD_MQ_MSG_SZ
,
sizeof
(
usb_mq_pool
),
RT_IPC_FLAG_FIFO
);
rt_mq_init
(
&
usb_mq
,
"usbd"
,
usb_mq_pool
,
USBD_MQ_MSG_SZ
,
sizeof
(
usb_mq_pool
),
RT_IPC_FLAG_FIFO
);
/* init usb device thread */
rt_thread_init
(
&
usb_thread
,
"usbd"
,
rt_usbd_thread_entry
,
RT_NULL
,
usb_thread_stack
,
RT_USBD_THREAD_STACK_SZ
,
RT_USBD_THREAD_PRIO
,
20
);
rt_thread_init
(
&
usb_thread
,
"usbd"
,
rt_usbd_thread_entry
,
RT_NULL
,
usb_thread_stack
,
RT_USBD_THREAD_STACK_SZ
,
RT_USBD_THREAD_PRIO
,
20
);
/* rt_thread_init should always be OK, so start the thread without further
* checking. */
return
rt_thread_startup
(
&
usb_thread
);
}
components/drivers/usb/usbdevice/core/usbdevice.c
浏览文件 @
8fd0a7f9
...
...
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*
* Change Logs:
* Date Author Notes
* 2012-10-02 Yi Qiu first version
...
...
@@ -28,13 +28,15 @@
#ifdef RT_USING_USB_DEVICE
#define USB_DEVICE_CONTROLLER_NAME "usbd"
#ifdef RT_USB_DEVICE_COMPOSITE
const
static
char
*
ustring
[]
=
{
"Language"
,
"RT-Thread Team."
,
"RTT Composite Device"
,
"
1.1.0
"
,
"
320219198301
"
,
"Configuration"
,
"Interface"
,
};
...
...
@@ -60,54 +62,54 @@ static struct udevice_descriptor compsit_desc =
};
#endif
rt_err_t
rt_usb_device_init
(
const
char
*
udc_name
)
rt_err_t
rt_usb_device_init
(
void
)
{
rt_device_t
udc
;
udevice_t
udevice
;
uconfig_t
cfg
;
uclass_t
cls
;
ufunction_t
func
;
/* create and startup usb device thread */
rt_usbd_core_init
();
RT_ASSERT
(
udc_name
!=
RT_NULL
);
/* create a device object */
udevice
=
rt_usbd_device_new
();
udc
=
rt_device_find
(
udc_name
);
udc
=
rt_device_find
(
USB_DEVICE_CONTROLLER_NAME
);
if
(
udc
==
RT_NULL
)
{
rt_kprintf
(
"can't find usb device controller %s
\n
"
,
udc_name
);
rt_kprintf
(
"can't find usb device controller %s
\n
"
,
USB_DEVICE_CONTROLLER_NAME
);
return
-
RT_ERROR
;
}
/* create and startup usb device thread */
rt_usbd_core_init
();
/* create a device object */
udevice
=
rt_usbd_device_create
();
/* 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
();
cfg
=
rt_usbd_config_
new
();
#ifdef RT_USB_DEVICE_MSTORAGE
/* create a mass storage
class
object */
cls
=
rt_usbd_class
_mstorage_create
(
udevice
);
/* create a mass storage
function
object */
func
=
rt_usbd_function
_mstorage_create
(
udevice
);
/* add the
class
to the configuration */
rt_usbd_config_add_
class
(
cfg
,
cls
);
/* add the
function
to the configuration */
rt_usbd_config_add_
function
(
cfg
,
func
);
#endif
#ifdef RT_USB_DEVICE_CDC
/* create a cdc
class
object */
cls
=
rt_usbd_class
_cdc_create
(
udevice
);
/* create a cdc
function
object */
func
=
rt_usbd_function
_cdc_create
(
udevice
);
/* add the
class
to the configuration */
rt_usbd_config_add_
class
(
cfg
,
cls
);
/* add the
function
to the configuration */
rt_usbd_config_add_
function
(
cfg
,
func
);
#endif
#ifdef RT_USB_DEVICE_RNDIS
/* create a rndis
class
object */
cls
=
rt_usbd_class
_rndis_create
(
udevice
);
/* create a rndis
function
object */
func
=
rt_usbd_function
_rndis_create
(
udevice
);
/* add the
class
to the configuration */
rt_usbd_config_add_
class
(
cfg
,
cls
);
/* add the
function
to the configuration */
rt_usbd_config_add_
function
(
cfg
,
func
);
#endif
/* set device descriptor to the device */
...
...
@@ -115,18 +117,18 @@ rt_err_t rt_usb_device_init(const char* udc_name)
rt_usbd_device_set_descriptor
(
udevice
,
&
compsit_desc
);
rt_usbd_device_set_string
(
udevice
,
ustring
);
#else
rt_usbd_device_set_descriptor
(
udevice
,
cls
->
dev_desc
);
rt_usbd_device_set_descriptor
(
udevice
,
func
->
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
);
/* set default configuration to 1 */
rt_usbd_set_config
(
udevice
,
1
);
return
RT_EOK
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录