Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
qemu
提交
656acddb
Q
qemu
项目概览
openeuler
/
qemu
通知
10
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Q
qemu
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
656acddb
编写于
6月 27, 2011
作者:
A
Anthony Liguori
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'kraxel/usb.17' into staging
上级
c45d1fc1
a7fb71d1
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
191 addition
and
64 deletion
+191
-64
hw/usb-bus.c
hw/usb-bus.c
+21
-10
hw/usb-ccid.c
hw/usb-ccid.c
+1
-0
hw/usb-desc.c
hw/usb-desc.c
+14
-0
hw/usb-ehci.c
hw/usb-ehci.c
+23
-20
hw/usb-msd.c
hw/usb-msd.c
+14
-5
hw/usb-ohci.c
hw/usb-ohci.c
+14
-3
hw/usb.h
hw/usb.h
+4
-0
usb-bsd.c
usb-bsd.c
+2
-0
usb-linux.c
usb-linux.c
+98
-26
未找到文件。
hw/usb-bus.c
浏览文件 @
656acddb
...
...
@@ -75,7 +75,7 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
QLIST_INIT
(
&
dev
->
strings
);
rc
=
dev
->
info
->
init
(
dev
);
if
(
rc
==
0
&&
dev
->
auto_attach
)
usb_device_attach
(
dev
);
rc
=
usb_device_attach
(
dev
);
return
rc
;
}
...
...
@@ -121,7 +121,7 @@ USBDevice *usb_create(USBBus *bus, const char *name)
bus
=
usb_bus_find
(
-
1
);
if
(
!
bus
)
return
NULL
;
fprintf
(
stderr
,
"%s: no bus specified, using
\"
%s
\"
for
\"
%s
\"\n
"
,
error_report
(
"%s: no bus specified, using
\"
%s
\"
for
\"
%s
\"\n
"
,
__FUNCTION__
,
bus
->
qbus
.
name
,
name
);
}
#endif
...
...
@@ -171,15 +171,20 @@ void usb_unregister_port(USBBus *bus, USBPort *port)
bus
->
nfree
--
;
}
static
void
do_attach
(
USBDevice
*
dev
)
static
int
do_attach
(
USBDevice
*
dev
)
{
USBBus
*
bus
=
usb_bus_from_device
(
dev
);
USBPort
*
port
;
if
(
dev
->
attached
)
{
fprintf
(
stderr
,
"Warning
: tried to attach usb device %s twice
\n
"
,
error_report
(
"Error
: tried to attach usb device %s twice
\n
"
,
dev
->
product_desc
);
return
;
return
-
1
;
}
if
(
bus
->
nfree
==
0
)
{
error_report
(
"Error: tried to attach usb device %s to a bus with no free ports
\n
"
,
dev
->
product_desc
);
return
-
1
;
}
if
(
dev
->
port_path
)
{
QTAILQ_FOREACH
(
port
,
&
bus
->
free
,
next
)
{
...
...
@@ -188,13 +193,18 @@ static void do_attach(USBDevice *dev)
}
}
if
(
port
==
NULL
)
{
fprintf
(
stderr
,
"Warning
: usb port %s (bus %s) not found
\n
"
,
error_report
(
"Error
: usb port %s (bus %s) not found
\n
"
,
dev
->
port_path
,
bus
->
qbus
.
name
);
return
;
return
-
1
;
}
}
else
{
port
=
QTAILQ_FIRST
(
&
bus
->
free
);
}
if
(
!
(
port
->
speedmask
&
dev
->
speedmask
))
{
error_report
(
"Warning: speed mismatch trying to attach usb device %s to bus %s
\n
"
,
dev
->
product_desc
,
bus
->
qbus
.
name
);
return
-
1
;
}
dev
->
attached
++
;
QTAILQ_REMOVE
(
&
bus
->
free
,
port
,
next
);
...
...
@@ -204,6 +214,8 @@ static void do_attach(USBDevice *dev)
QTAILQ_INSERT_TAIL
(
&
bus
->
used
,
port
,
next
);
bus
->
nused
++
;
return
0
;
}
int
usb_device_attach
(
USBDevice
*
dev
)
...
...
@@ -215,8 +227,7 @@ int usb_device_attach(USBDevice *dev)
(unless a physical port location is specified). */
usb_create_simple
(
bus
,
"usb-hub"
);
}
do_attach
(
dev
);
return
0
;
return
do_attach
(
dev
);
}
int
usb_device_detach
(
USBDevice
*
dev
)
...
...
@@ -225,7 +236,7 @@ int usb_device_detach(USBDevice *dev)
USBPort
*
port
;
if
(
!
dev
->
attached
)
{
fprintf
(
stderr
,
"Warning
: tried to detach unattached usb device %s
\n
"
,
error_report
(
"Error
: tried to detach unattached usb device %s
\n
"
,
dev
->
product_desc
);
return
-
1
;
}
...
...
hw/usb-ccid.c
浏览文件 @
656acddb
...
...
@@ -1271,6 +1271,7 @@ static int ccid_initfn(USBDevice *dev)
s
->
migration_target_ip
=
0
;
s
->
migration_target_port
=
0
;
s
->
dev
.
speed
=
USB_SPEED_FULL
;
s
->
dev
.
speedmask
=
USB_SPEED_MASK_FULL
;
s
->
notify_slot_change
=
false
;
s
->
powered
=
true
;
s
->
pending_answers_num
=
0
;
...
...
hw/usb-desc.c
浏览文件 @
656acddb
...
...
@@ -242,7 +242,17 @@ static void usb_desc_setdefaults(USBDevice *dev)
void
usb_desc_init
(
USBDevice
*
dev
)
{
const
USBDesc
*
desc
=
dev
->
info
->
usb_desc
;
assert
(
desc
!=
NULL
);
dev
->
speed
=
USB_SPEED_FULL
;
dev
->
speedmask
=
0
;
if
(
desc
->
full
)
{
dev
->
speedmask
|=
USB_SPEED_MASK_FULL
;
}
if
(
desc
->
high
)
{
dev
->
speedmask
|=
USB_SPEED_MASK_HIGH
;
}
usb_desc_setdefaults
(
dev
);
}
...
...
@@ -375,6 +385,10 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
trace_usb_desc_other_speed_config
(
dev
->
addr
,
index
,
len
,
ret
);
break
;
case
USB_DT_DEBUG
:
/* ignore silently */
break
;
default:
fprintf
(
stderr
,
"%s: %d unknown type %d (len %zd)
\n
"
,
__FUNCTION__
,
dev
->
addr
,
type
,
len
);
...
...
hw/usb-ehci.c
浏览文件 @
656acddb
...
...
@@ -130,7 +130,7 @@
#define PORTSC_CONNECT (1 << 0) // Current Connect Status
#define FRAME_TIMER_FREQ 1000
#define FRAME_TIMER_
USEC (1
000000 / FRAME_TIMER_FREQ)
#define FRAME_TIMER_
NS (1000
000000 / FRAME_TIMER_FREQ)
#define NB_MAXINTRATE 8 // Max rate at which controller issues ints
#define NB_PORTS 4 // Number of downstream ports
...
...
@@ -348,7 +348,8 @@ struct EHCIQueue {
EHCIState
*
ehci
;
QTAILQ_ENTRY
(
EHCIQueue
)
next
;
bool
async_schedule
;
uint32_t
seen
,
ts
;
uint32_t
seen
;
uint64_t
ts
;
/* cached data from guest - needs to be flushed
* when guest removes an entry (doorbell, handshake sequence)
...
...
@@ -373,6 +374,11 @@ struct EHCIState {
target_phys_addr_t
mem_base
;
int
mem
;
int
num_ports
;
/* properties */
uint32_t
freq
;
uint32_t
maxframes
;
/*
* EHCI spec version 1.0 Section 2.3
* Host Controller Operational Registers
...
...
@@ -413,12 +419,11 @@ struct EHCIState {
uint8_t
ibuffer
[
BUFF_SIZE
];
int
isoch_pause
;
uint32_t
last_run_usec
;
uint32_t
frame_end_usec
;
uint64_t
last_run_ns
;
};
#define SET_LAST_RUN_CLOCK(s) \
(s)->last_run_
usec = qemu_get_clock_ns(vm_clock) / 1000
;
(s)->last_run_
ns = qemu_get_clock_ns(vm_clock)
;
/* nifty macros from Arnon's EHCI version */
#define get_field(data, field) \
...
...
@@ -685,10 +690,10 @@ static void ehci_queues_rip_unused(EHCIState *ehci)
QTAILQ_FOREACH_SAFE
(
q
,
&
ehci
->
queues
,
next
,
tmp
)
{
if
(
q
->
seen
)
{
q
->
seen
=
0
;
q
->
ts
=
ehci
->
last_run_
usec
;
q
->
ts
=
ehci
->
last_run_
ns
;
continue
;
}
if
(
ehci
->
last_run_
usec
<
q
->
ts
+
25
0000
)
{
if
(
ehci
->
last_run_
ns
<
q
->
ts
+
25000
0000
)
{
/* allow 0.25 sec idle */
continue
;
}
...
...
@@ -2040,23 +2045,16 @@ static void ehci_frame_timer(void *opaque)
{
EHCIState
*
ehci
=
opaque
;
int64_t
expire_time
,
t_now
;
int
usec
_elapsed
;
uint64_t
ns
_elapsed
;
int
frames
;
int
usec_now
;
int
i
;
int
skipped_frames
=
0
;
t_now
=
qemu_get_clock_ns
(
vm_clock
);
expire_time
=
t_now
+
(
get_ticks_per_sec
()
/
FRAME_TIMER_FREQ
);
if
(
expire_time
==
t_now
)
{
expire_time
++
;
}
expire_time
=
t_now
+
(
get_ticks_per_sec
()
/
ehci
->
freq
);
usec_now
=
t_now
/
1000
;
usec_elapsed
=
usec_now
-
ehci
->
last_run_usec
;
frames
=
usec_elapsed
/
FRAME_TIMER_USEC
;
ehci
->
frame_end_usec
=
usec_now
+
FRAME_TIMER_USEC
-
10
;
ns_elapsed
=
t_now
-
ehci
->
last_run_ns
;
frames
=
ns_elapsed
/
FRAME_TIMER_NS
;
for
(
i
=
0
;
i
<
frames
;
i
++
)
{
if
(
!
(
ehci
->
usbsts
&
USBSTS_HALT
))
{
...
...
@@ -2073,13 +2071,13 @@ static void ehci_frame_timer(void *opaque)
ehci
->
sofv
&=
0x000003ff
;
}
if
(
frames
-
i
>
10
)
{
if
(
frames
-
i
>
ehci
->
maxframes
)
{
skipped_frames
++
;
}
else
{
ehci_advance_periodic_state
(
ehci
);
}
ehci
->
last_run_
usec
+=
FRAME_TIMER_USEC
;
ehci
->
last_run_
ns
+=
FRAME_TIMER_NS
;
}
#if 0
...
...
@@ -2146,6 +2144,11 @@ static PCIDeviceInfo ehci_info = {
.
device_id
=
PCI_DEVICE_ID_INTEL_82801D
,
.
revision
=
0x10
,
.
class_id
=
PCI_CLASS_SERIAL_USB
,
.
qdev
.
props
=
(
Property
[])
{
DEFINE_PROP_UINT32
(
"freq"
,
EHCIState
,
freq
,
FRAME_TIMER_FREQ
),
DEFINE_PROP_UINT32
(
"maxframes"
,
EHCIState
,
maxframes
,
128
),
DEFINE_PROP_END_OF_LIST
(),
},
};
static
int
usb_ehci_initfn
(
PCIDevice
*
dev
)
...
...
hw/usb-msd.c
浏览文件 @
656acddb
...
...
@@ -51,6 +51,7 @@ typedef struct {
SCSIRequest
*
req
;
SCSIBus
bus
;
BlockConf
conf
;
char
*
serial
;
SCSIDevice
*
scsi_dev
;
uint32_t
removable
;
int
result
;
...
...
@@ -497,8 +498,9 @@ static void usb_msd_password_cb(void *opaque, int err)
MSDState
*
s
=
opaque
;
if
(
!
err
)
usb_device_attach
(
&
s
->
dev
);
else
err
=
usb_device_attach
(
&
s
->
dev
);
if
(
err
)
qdev_unplug
(
&
s
->
dev
.
qdev
);
}
...
...
@@ -531,9 +533,15 @@ static int usb_msd_initfn(USBDevice *dev)
bdrv_detach
(
bs
,
&
s
->
dev
.
qdev
);
s
->
conf
.
bs
=
NULL
;
dinfo
=
drive_get_by_blockdev
(
bs
);
if
(
dinfo
&&
dinfo
->
serial
)
{
usb_desc_set_string
(
dev
,
STR_SERIALNUMBER
,
dinfo
->
serial
);
if
(
!
s
->
serial
)
{
/* try to fall back to value set with legacy -drive serial=... */
dinfo
=
drive_get_by_blockdev
(
bs
);
if
(
*
dinfo
->
serial
)
{
s
->
serial
=
strdup
(
dinfo
->
serial
);
}
}
if
(
s
->
serial
)
{
usb_desc_set_string
(
dev
,
STR_SERIALNUMBER
,
s
->
serial
);
}
usb_desc_init
(
dev
);
...
...
@@ -632,6 +640,7 @@ static struct USBDeviceInfo msd_info = {
.
usbdevice_init
=
usb_msd_init
,
.
qdev
.
props
=
(
Property
[])
{
DEFINE_BLOCK_PROPERTIES
(
MSDState
,
conf
),
DEFINE_PROP_STRING
(
"serial"
,
MSDState
,
serial
),
DEFINE_PROP_BIT
(
"removable"
,
MSDState
,
removable
,
0
,
false
),
DEFINE_PROP_END_OF_LIST
(),
},
...
...
hw/usb-ohci.c
浏览文件 @
656acddb
...
...
@@ -373,14 +373,25 @@ static void ohci_wakeup(USBDevice *dev)
OHCIState
*
s
=
container_of
(
bus
,
OHCIState
,
bus
);
int
portnum
=
dev
->
port
->
index
;
OHCIPort
*
port
=
&
s
->
rhport
[
portnum
];
uint32_t
intr
=
0
;
if
(
port
->
ctrl
&
OHCI_PORT_PSS
)
{
DPRINTF
(
"usb-ohci: port %d: wakeup
\n
"
,
portnum
);
port
->
ctrl
|=
OHCI_PORT_PSSC
;
port
->
ctrl
&=
~
OHCI_PORT_PSS
;
if
((
s
->
ctl
&
OHCI_CTL_HCFS
)
==
OHCI_USB_SUSPEND
)
{
ohci_set_interrupt
(
s
,
OHCI_INTR_RD
);
}
intr
=
OHCI_INTR_RHSC
;
}
/* Note that the controller can be suspended even if this port is not */
if
((
s
->
ctl
&
OHCI_CTL_HCFS
)
==
OHCI_USB_SUSPEND
)
{
DPRINTF
(
"usb-ohci: remote-wakeup: SUSPEND->RESUME
\n
"
);
/* This is the one state transition the controller can do by itself */
s
->
ctl
&=
~
OHCI_CTL_HCFS
;
s
->
ctl
|=
OHCI_USB_RESUME
;
/* In suspend mode only ResumeDetected is possible, not RHSC:
* see the OHCI spec 5.1.2.3.
*/
intr
=
OHCI_INTR_RD
;
}
ohci_set_interrupt
(
s
,
intr
);
}
/* Reset the controller */
...
...
hw/usb.h
浏览文件 @
656acddb
...
...
@@ -130,6 +130,7 @@
#define USB_DT_ENDPOINT 0x05
#define USB_DT_DEVICE_QUALIFIER 0x06
#define USB_DT_OTHER_SPEED_CONFIG 0x07
#define USB_DT_DEBUG 0x0A
#define USB_DT_INTERFACE_ASSOC 0x0B
#define USB_ENDPOINT_XFER_CONTROL 0
...
...
@@ -168,7 +169,10 @@ struct USBDevice {
char
*
port_path
;
void
*
opaque
;
/* Actual connected speed */
int
speed
;
/* Supported speeds, not in info because it may be variable (hostdevs) */
int
speedmask
;
uint8_t
addr
;
char
product_desc
[
32
];
int
auto_attach
;
...
...
usb-bsd.c
浏览文件 @
656acddb
...
...
@@ -367,8 +367,10 @@ USBDevice *usb_host_device_open(const char *devname)
if
(
dev_info
.
udi_speed
==
1
)
{
dev
->
dev
.
speed
=
USB_SPEED_LOW
-
1
;
dev
->
dev
.
speedmask
=
USB_SPEED_MASK_LOW
;
}
else
{
dev
->
dev
.
speed
=
USB_SPEED_FULL
-
1
;
dev
->
dev
.
speedmask
=
USB_SPEED_MASK_FULL
;
}
if
(
strncmp
(
dev_info
.
udi_product
,
"product"
,
7
)
!=
0
)
{
...
...
usb-linux.c
浏览文件 @
656acddb
...
...
@@ -85,7 +85,6 @@ static int usb_fs_type;
/* endpoint association data */
#define ISO_FRAME_DESC_PER_URB 32
#define ISO_URB_COUNT 3
#define INVALID_EP_TYPE 255
/* devio.c limits single requests to 16k */
...
...
@@ -101,6 +100,7 @@ struct endp_data {
int
iso_urb_idx
;
int
iso_buffer_used
;
int
max_packet_size
;
int
inflight
;
};
struct
USBAutoFilter
{
...
...
@@ -120,6 +120,7 @@ typedef struct USBHostDevice {
int
configuration
;
int
ninterfaces
;
int
closing
;
uint32_t
iso_urb_count
;
Notifier
exit
;
struct
endp_data
endp_table
[
MAX_ENDPOINTS
];
...
...
@@ -142,74 +143,91 @@ static void usb_host_auto_check(void *unused);
static
int
usb_host_read_file
(
char
*
line
,
size_t
line_size
,
const
char
*
device_file
,
const
char
*
device_name
);
static
struct
endp_data
*
get_endp
(
USBHostDevice
*
s
,
int
ep
)
{
return
s
->
endp_table
+
ep
-
1
;
}
static
int
is_isoc
(
USBHostDevice
*
s
,
int
ep
)
{
return
s
->
endp_table
[
ep
-
1
].
type
==
USBDEVFS_URB_TYPE_ISO
;
return
get_endp
(
s
,
ep
)
->
type
==
USBDEVFS_URB_TYPE_ISO
;
}
static
int
is_valid
(
USBHostDevice
*
s
,
int
ep
)
{
return
s
->
endp_table
[
ep
-
1
].
type
!=
INVALID_EP_TYPE
;
return
get_endp
(
s
,
ep
)
->
type
!=
INVALID_EP_TYPE
;
}
static
int
is_halted
(
USBHostDevice
*
s
,
int
ep
)
{
return
s
->
endp_table
[
ep
-
1
].
halted
;
return
get_endp
(
s
,
ep
)
->
halted
;
}
static
void
clear_halt
(
USBHostDevice
*
s
,
int
ep
)
{
s
->
endp_table
[
ep
-
1
].
halted
=
0
;
get_endp
(
s
,
ep
)
->
halted
=
0
;
}
static
void
set_halt
(
USBHostDevice
*
s
,
int
ep
)
{
s
->
endp_table
[
ep
-
1
].
halted
=
1
;
get_endp
(
s
,
ep
)
->
halted
=
1
;
}
static
int
is_iso_started
(
USBHostDevice
*
s
,
int
ep
)
{
return
s
->
endp_table
[
ep
-
1
].
iso_started
;
return
get_endp
(
s
,
ep
)
->
iso_started
;
}
static
void
clear_iso_started
(
USBHostDevice
*
s
,
int
ep
)
{
s
->
endp_table
[
ep
-
1
].
iso_started
=
0
;
get_endp
(
s
,
ep
)
->
iso_started
=
0
;
}
static
void
set_iso_started
(
USBHostDevice
*
s
,
int
ep
)
{
s
->
endp_table
[
ep
-
1
].
iso_started
=
1
;
struct
endp_data
*
e
=
get_endp
(
s
,
ep
);
if
(
!
e
->
iso_started
)
{
e
->
iso_started
=
1
;
e
->
inflight
=
0
;
}
}
static
int
change_iso_inflight
(
USBHostDevice
*
s
,
int
ep
,
int
value
)
{
struct
endp_data
*
e
=
get_endp
(
s
,
ep
);
e
->
inflight
+=
value
;
return
e
->
inflight
;
}
static
void
set_iso_urb
(
USBHostDevice
*
s
,
int
ep
,
AsyncURB
*
iso_urb
)
{
s
->
endp_table
[
ep
-
1
].
iso_urb
=
iso_urb
;
get_endp
(
s
,
ep
)
->
iso_urb
=
iso_urb
;
}
static
AsyncURB
*
get_iso_urb
(
USBHostDevice
*
s
,
int
ep
)
{
return
s
->
endp_table
[
ep
-
1
].
iso_urb
;
return
get_endp
(
s
,
ep
)
->
iso_urb
;
}
static
void
set_iso_urb_idx
(
USBHostDevice
*
s
,
int
ep
,
int
i
)
{
s
->
endp_table
[
ep
-
1
].
iso_urb_idx
=
i
;
get_endp
(
s
,
ep
)
->
iso_urb_idx
=
i
;
}
static
int
get_iso_urb_idx
(
USBHostDevice
*
s
,
int
ep
)
{
return
s
->
endp_table
[
ep
-
1
].
iso_urb_idx
;
return
get_endp
(
s
,
ep
)
->
iso_urb_idx
;
}
static
void
set_iso_buffer_used
(
USBHostDevice
*
s
,
int
ep
,
int
i
)
{
s
->
endp_table
[
ep
-
1
].
iso_buffer_used
=
i
;
get_endp
(
s
,
ep
)
->
iso_buffer_used
=
i
;
}
static
int
get_iso_buffer_used
(
USBHostDevice
*
s
,
int
ep
)
{
return
s
->
endp_table
[
ep
-
1
].
iso_buffer_used
;
return
get_endp
(
s
,
ep
)
->
iso_buffer_used
;
}
static
void
set_max_packet_size
(
USBHostDevice
*
s
,
int
ep
,
uint8_t
*
descriptor
)
...
...
@@ -223,14 +241,12 @@ static void set_max_packet_size(USBHostDevice *s, int ep, uint8_t *descriptor)
case
2
:
microframes
=
3
;
break
;
default:
microframes
=
1
;
break
;
}
DPRINTF
(
"husb: max packet size: 0x%x -> %d x %d
\n
"
,
raw
,
microframes
,
size
);
s
->
endp_table
[
ep
-
1
].
max_packet_size
=
size
*
microframes
;
get_endp
(
s
,
ep
)
->
max_packet_size
=
size
*
microframes
;
}
static
int
get_max_packet_size
(
USBHostDevice
*
s
,
int
ep
)
{
return
s
->
endp_table
[
ep
-
1
].
max_packet_size
;
return
get_endp
(
s
,
ep
)
->
max_packet_size
;
}
/*
...
...
@@ -279,6 +295,7 @@ static void async_complete(void *opaque)
{
USBHostDevice
*
s
=
opaque
;
AsyncURB
*
aurb
;
int
urbs
=
0
;
while
(
1
)
{
USBPacket
*
p
;
...
...
@@ -286,6 +303,9 @@ static void async_complete(void *opaque)
int
r
=
ioctl
(
s
->
fd
,
USBDEVFS_REAPURBNDELAY
,
&
aurb
);
if
(
r
<
0
)
{
if
(
errno
==
EAGAIN
)
{
if
(
urbs
>
2
)
{
fprintf
(
stderr
,
"husb: %d iso urbs finished at once
\n
"
,
urbs
);
}
return
;
}
if
(
errno
==
ENODEV
&&
!
s
->
closing
)
{
...
...
@@ -303,10 +323,16 @@ static void async_complete(void *opaque)
/* If this is a buffered iso urb mark it as complete and don't do
anything else (it is handled further in usb_host_handle_iso_data) */
if
(
aurb
->
iso_frame_idx
==
-
1
)
{
int
inflight
;
if
(
aurb
->
urb
.
status
==
-
EPIPE
)
{
set_halt
(
s
,
aurb
->
urb
.
endpoint
&
0xf
);
}
aurb
->
iso_frame_idx
=
0
;
urbs
++
;
inflight
=
change_iso_inflight
(
s
,
aurb
->
urb
.
endpoint
&
0xf
,
-
1
);
if
(
inflight
==
0
&&
is_iso_started
(
s
,
aurb
->
urb
.
endpoint
&
0xf
))
{
fprintf
(
stderr
,
"husb: out of buffers for iso stream
\n
"
);
}
continue
;
}
...
...
@@ -502,8 +528,8 @@ static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, uint8_t ep, int in)
AsyncURB
*
aurb
;
int
i
,
j
,
len
=
get_max_packet_size
(
s
,
ep
);
aurb
=
qemu_mallocz
(
ISO_URB_COUNT
*
sizeof
(
*
aurb
));
for
(
i
=
0
;
i
<
ISO_URB_COUNT
;
i
++
)
{
aurb
=
qemu_mallocz
(
s
->
iso_urb_count
*
sizeof
(
*
aurb
));
for
(
i
=
0
;
i
<
s
->
iso_urb_count
;
i
++
)
{
aurb
[
i
].
urb
.
endpoint
=
ep
;
aurb
[
i
].
urb
.
buffer_length
=
ISO_FRAME_DESC_PER_URB
*
len
;
aurb
[
i
].
urb
.
buffer
=
qemu_malloc
(
aurb
[
i
].
urb
.
buffer_length
);
...
...
@@ -533,7 +559,7 @@ static void usb_host_stop_n_free_iso(USBHostDevice *s, uint8_t ep)
return
;
}
for
(
i
=
0
;
i
<
ISO_URB_COUNT
;
i
++
)
{
for
(
i
=
0
;
i
<
s
->
iso_urb_count
;
i
++
)
{
/* in flight? */
if
(
aurb
[
i
].
iso_frame_idx
==
-
1
)
{
ret
=
ioctl
(
s
->
fd
,
USBDEVFS_DISCARDURB
,
&
aurb
[
i
]);
...
...
@@ -551,7 +577,7 @@ static void usb_host_stop_n_free_iso(USBHostDevice *s, uint8_t ep)
async_complete
(
s
);
}
for
(
i
=
0
;
i
<
ISO_URB_COUNT
;
i
++
)
{
for
(
i
=
0
;
i
<
s
->
iso_urb_count
;
i
++
)
{
qemu_free
(
aurb
[
i
].
urb
.
buffer
);
}
...
...
@@ -636,7 +662,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
}
aurb
[
i
].
iso_frame_idx
++
;
if
(
aurb
[
i
].
iso_frame_idx
==
ISO_FRAME_DESC_PER_URB
)
{
i
=
(
i
+
1
)
%
ISO_URB_COUNT
;
i
=
(
i
+
1
)
%
s
->
iso_urb_count
;
set_iso_urb_idx
(
s
,
p
->
devep
,
i
);
}
}
else
{
...
...
@@ -649,7 +675,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
if
(
is_iso_started
(
s
,
p
->
devep
))
{
/* (Re)-submit all fully consumed / filled urbs */
for
(
i
=
0
;
i
<
ISO_URB_COUNT
;
i
++
)
{
for
(
i
=
0
;
i
<
s
->
iso_urb_count
;
i
++
)
{
if
(
aurb
[
i
].
iso_frame_idx
==
ISO_FRAME_DESC_PER_URB
)
{
ret
=
ioctl
(
s
->
fd
,
USBDEVFS_SUBMITURB
,
&
aurb
[
i
]);
if
(
ret
<
0
)
{
...
...
@@ -667,6 +693,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
break
;
}
aurb
[
i
].
iso_frame_idx
=
-
1
;
change_iso_inflight
(
s
,
p
->
devep
,
+
1
);
}
}
}
...
...
@@ -1061,6 +1088,42 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
return
0
;
}
/*
* Check if we can safely redirect a usb2 device to a usb1 virtual controller,
* this function assumes this is safe, if:
* 1) There are no isoc endpoints
* 2) There are no interrupt endpoints with a max_packet_size > 64
* Note bulk endpoints with a max_packet_size > 64 in theory also are not
* usb1 compatible, but in practice this seems to work fine.
*/
static
int
usb_linux_full_speed_compat
(
USBHostDevice
*
dev
)
{
int
i
,
packet_size
;
/*
* usb_linux_update_endp_table only registers info about ep in the current
* interface altsettings, so we need to parse the descriptors again.
*/
for
(
i
=
0
;
(
i
+
5
)
<
dev
->
descr_len
;
i
+=
dev
->
descr
[
i
])
{
if
(
dev
->
descr
[
i
+
1
]
==
USB_DT_ENDPOINT
)
{
switch
(
dev
->
descr
[
i
+
3
]
&
0x3
)
{
case
0x00
:
/* CONTROL */
break
;
case
0x01
:
/* ISO */
return
0
;
case
0x02
:
/* BULK */
break
;
case
0x03
:
/* INTERRUPT */
packet_size
=
dev
->
descr
[
i
+
4
]
+
(
dev
->
descr
[
i
+
5
]
<<
8
);
if
(
packet_size
>
64
)
return
0
;
break
;
}
}
}
return
1
;
}
static
int
usb_host_open
(
USBHostDevice
*
dev
,
int
bus_num
,
int
addr
,
char
*
port
,
const
char
*
prod_name
,
int
speed
)
{
...
...
@@ -1140,6 +1203,10 @@ static int usb_host_open(USBHostDevice *dev, int bus_num,
}
}
dev
->
dev
.
speed
=
speed
;
dev
->
dev
.
speedmask
=
(
1
<<
speed
);
if
(
dev
->
dev
.
speed
==
USB_SPEED_HIGH
&&
usb_linux_full_speed_compat
(
dev
))
{
dev
->
dev
.
speedmask
|=
USB_SPEED_MASK_FULL
;
}
printf
(
"husb: grabbed usb device %d.%d
\n
"
,
bus_num
,
addr
);
...
...
@@ -1151,10 +1218,14 @@ static int usb_host_open(USBHostDevice *dev, int bus_num,
prod_name
);
}
ret
=
usb_device_attach
(
&
dev
->
dev
);
if
(
ret
)
{
goto
fail
;
}
/* USB devio uses 'write' flag to check for async completions */
qemu_set_fd_handler
(
dev
->
fd
,
NULL
,
async_complete
,
dev
);
usb_device_attach
(
&
dev
->
dev
);
return
0
;
fail:
...
...
@@ -1230,6 +1301,7 @@ static struct USBDeviceInfo usb_host_dev_info = {
DEFINE_PROP_STRING
(
"hostport"
,
USBHostDevice
,
match
.
port
),
DEFINE_PROP_HEX32
(
"vendorid"
,
USBHostDevice
,
match
.
vendor_id
,
0
),
DEFINE_PROP_HEX32
(
"productid"
,
USBHostDevice
,
match
.
product_id
,
0
),
DEFINE_PROP_UINT32
(
"isobufs"
,
USBHostDevice
,
iso_urb_count
,
4
),
DEFINE_PROP_END_OF_LIST
(),
},
};
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录