mirror of
https://git.proxmox.com/git/qemu
synced 2025-06-28 21:32:44 +00:00
Merge remote-tracking branch 'kraxel/usb.89' into staging
# By Gerd Hoffmann (2) and Miroslav Rezanina (2) # Via Gerd Hoffmann * kraxel/usb.89: ehci: save device pointer in EHCIState Remove dev-bluetooth.c dependency from vl.c Preparation for usb-bt-dongle conditional build usb: sanity check setup_index+setup_len in post_load Message-id: 1378806073-25197-1-git-send-email-kraxel@redhat.com Signed-off-by: Anthony Liguori <anthony@codemonkey.ws>
This commit is contained in:
commit
a640f07c0d
23
hw/bt/core.c
23
hw/bt/core.c
@ -119,3 +119,26 @@ void bt_device_done(struct bt_device_s *dev)
|
|||||||
|
|
||||||
*p = dev->next;
|
*p = dev->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct bt_vlan_s {
|
||||||
|
struct bt_scatternet_s net;
|
||||||
|
int id;
|
||||||
|
struct bt_vlan_s *next;
|
||||||
|
} *first_bt_vlan;
|
||||||
|
|
||||||
|
/* find or alloc a new bluetooth "VLAN" */
|
||||||
|
struct bt_scatternet_s *qemu_find_bt_vlan(int id)
|
||||||
|
{
|
||||||
|
struct bt_vlan_s **pvlan, *vlan;
|
||||||
|
for (vlan = first_bt_vlan; vlan != NULL; vlan = vlan->next) {
|
||||||
|
if (vlan->id == id)
|
||||||
|
return &vlan->net;
|
||||||
|
}
|
||||||
|
vlan = g_malloc0(sizeof(struct bt_vlan_s));
|
||||||
|
vlan->id = id;
|
||||||
|
pvlan = &first_bt_vlan;
|
||||||
|
while (*pvlan != NULL)
|
||||||
|
pvlan = &(*pvlan)->next;
|
||||||
|
*pvlan = vlan;
|
||||||
|
return &vlan->net;
|
||||||
|
}
|
||||||
|
48
hw/bt/hci.c
48
hw/bt/hci.c
@ -429,6 +429,24 @@ static const uint8_t bt_event_reserved_mask[8] = {
|
|||||||
0xff, 0x9f, 0xfb, 0xff, 0x07, 0x18, 0x00, 0x00,
|
0xff, 0x9f, 0xfb, 0xff, 0x07, 0x18, 0x00, 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static int null_hci_addr_set(struct HCIInfo *hci, const uint8_t *bd_addr)
|
||||||
|
{
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct HCIInfo null_hci = {
|
||||||
|
.cmd_send = null_hci_send,
|
||||||
|
.sco_send = null_hci_send,
|
||||||
|
.acl_send = null_hci_send,
|
||||||
|
.bdaddr_set = null_hci_addr_set,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static inline uint8_t *bt_hci_event_start(struct bt_hci_s *hci,
|
static inline uint8_t *bt_hci_event_start(struct bt_hci_s *hci,
|
||||||
int evt, int len)
|
int evt, int len)
|
||||||
{
|
{
|
||||||
@ -2176,6 +2194,36 @@ struct HCIInfo *bt_new_hci(struct bt_scatternet_s *net)
|
|||||||
return &s->info;
|
return &s->info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct HCIInfo *hci_init(const char *str)
|
||||||
|
{
|
||||||
|
char *endp;
|
||||||
|
struct bt_scatternet_s *vlan = 0;
|
||||||
|
|
||||||
|
if (!strcmp(str, "null"))
|
||||||
|
/* null */
|
||||||
|
return &null_hci;
|
||||||
|
else if (!strncmp(str, "host", 4) && (str[4] == '\0' || str[4] == ':'))
|
||||||
|
/* host[:hciN] */
|
||||||
|
return bt_host_hci(str[4] ? str + 5 : "hci0");
|
||||||
|
else if (!strncmp(str, "hci", 3)) {
|
||||||
|
/* hci[,vlan=n] */
|
||||||
|
if (str[3]) {
|
||||||
|
if (!strncmp(str + 3, ",vlan=", 6)) {
|
||||||
|
vlan = qemu_find_bt_vlan(strtol(str + 9, &endp, 0));
|
||||||
|
if (*endp)
|
||||||
|
vlan = 0;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
vlan = qemu_find_bt_vlan(0);
|
||||||
|
if (vlan)
|
||||||
|
return bt_new_hci(vlan);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "qemu: Unknown bluetooth HCI `%s'.\n", str);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void bt_hci_done(struct HCIInfo *info)
|
static void bt_hci_done(struct HCIInfo *info)
|
||||||
{
|
{
|
||||||
struct bt_hci_s *hci = hci_from_info(info);
|
struct bt_hci_s *hci = hci_from_info(info);
|
||||||
|
@ -18,9 +18,6 @@ common-obj-$(CONFIG_USB_STORAGE_UAS) += dev-uas.o
|
|||||||
common-obj-$(CONFIG_USB_AUDIO) += dev-audio.o
|
common-obj-$(CONFIG_USB_AUDIO) += dev-audio.o
|
||||||
common-obj-$(CONFIG_USB_SERIAL) += dev-serial.o
|
common-obj-$(CONFIG_USB_SERIAL) += dev-serial.o
|
||||||
common-obj-$(CONFIG_USB_NETWORK) += dev-network.o
|
common-obj-$(CONFIG_USB_NETWORK) += dev-network.o
|
||||||
|
|
||||||
# FIXME: make configurable too
|
|
||||||
CONFIG_USB_BLUETOOTH := y
|
|
||||||
common-obj-$(CONFIG_USB_BLUETOOTH) += dev-bluetooth.o
|
common-obj-$(CONFIG_USB_BLUETOOTH) += dev-bluetooth.o
|
||||||
|
|
||||||
ifeq ($(CONFIG_USB_SMARTCARD),y)
|
ifeq ($(CONFIG_USB_SMARTCARD),y)
|
||||||
|
@ -47,6 +47,10 @@ static int usb_device_post_load(void *opaque, int version_id)
|
|||||||
} else {
|
} else {
|
||||||
dev->attached = 1;
|
dev->attached = 1;
|
||||||
}
|
}
|
||||||
|
if (dev->setup_index >= sizeof(dev->data_buf) ||
|
||||||
|
dev->setup_len >= sizeof(dev->data_buf)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,10 +511,17 @@ static int usb_bt_initfn(USBDevice *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
USBDevice *usb_bt_init(USBBus *bus, HCIInfo *hci)
|
static USBDevice *usb_bt_init(USBBus *bus, const char *cmdline)
|
||||||
{
|
{
|
||||||
USBDevice *dev;
|
USBDevice *dev;
|
||||||
struct USBBtState *s;
|
struct USBBtState *s;
|
||||||
|
HCIInfo *hci;
|
||||||
|
|
||||||
|
if (*cmdline) {
|
||||||
|
hci = hci_init(cmdline);
|
||||||
|
} else {
|
||||||
|
hci = bt_new_hci(qemu_find_bt_vlan(0));
|
||||||
|
}
|
||||||
|
|
||||||
if (!hci)
|
if (!hci)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -566,6 +573,7 @@ static const TypeInfo bt_info = {
|
|||||||
static void usb_bt_register_types(void)
|
static void usb_bt_register_types(void)
|
||||||
{
|
{
|
||||||
type_register_static(&bt_info);
|
type_register_static(&bt_info);
|
||||||
|
usb_legacy_register("usb-bt-dongle", "bt", usb_bt_init);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_init(usb_bt_register_types)
|
type_init(usb_bt_register_types)
|
||||||
|
@ -1241,13 +1241,11 @@ static int ehci_init_transfer(EHCIPacket *p)
|
|||||||
{
|
{
|
||||||
uint32_t cpage, offset, bytes, plen;
|
uint32_t cpage, offset, bytes, plen;
|
||||||
dma_addr_t page;
|
dma_addr_t page;
|
||||||
USBBus *bus = &p->queue->ehci->bus;
|
|
||||||
BusState *qbus = BUS(bus);
|
|
||||||
|
|
||||||
cpage = get_field(p->qtd.token, QTD_TOKEN_CPAGE);
|
cpage = get_field(p->qtd.token, QTD_TOKEN_CPAGE);
|
||||||
bytes = get_field(p->qtd.token, QTD_TOKEN_TBYTES);
|
bytes = get_field(p->qtd.token, QTD_TOKEN_TBYTES);
|
||||||
offset = p->qtd.bufptr[0] & ~QTD_BUFPTR_MASK;
|
offset = p->qtd.bufptr[0] & ~QTD_BUFPTR_MASK;
|
||||||
qemu_sglist_init(&p->sgl, qbus->parent, 5, p->queue->ehci->as);
|
qemu_sglist_init(&p->sgl, p->queue->ehci->device, 5, p->queue->ehci->as);
|
||||||
|
|
||||||
while (bytes > 0) {
|
while (bytes > 0) {
|
||||||
if (cpage > 4) {
|
if (cpage > 4) {
|
||||||
@ -1486,7 +1484,7 @@ static int ehci_process_itd(EHCIState *ehci,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_sglist_init(&ehci->isgl, DEVICE(ehci), 2, ehci->as);
|
qemu_sglist_init(&ehci->isgl, ehci->device, 2, ehci->as);
|
||||||
if (off + len > 4096) {
|
if (off + len > 4096) {
|
||||||
/* transfer crosses page border */
|
/* transfer crosses page border */
|
||||||
uint32_t len2 = off + len - 4096;
|
uint32_t len2 = off + len - 4096;
|
||||||
@ -2529,6 +2527,7 @@ void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp)
|
|||||||
|
|
||||||
s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ehci_frame_timer, s);
|
s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ehci_frame_timer, s);
|
||||||
s->async_bh = qemu_bh_new(ehci_frame_timer, s);
|
s->async_bh = qemu_bh_new(ehci_frame_timer, s);
|
||||||
|
s->device = dev;
|
||||||
|
|
||||||
qemu_register_reset(ehci_reset, s);
|
qemu_register_reset(ehci_reset, s);
|
||||||
qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s);
|
qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s);
|
||||||
|
@ -255,6 +255,7 @@ typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead;
|
|||||||
|
|
||||||
struct EHCIState {
|
struct EHCIState {
|
||||||
USBBus bus;
|
USBBus bus;
|
||||||
|
DeviceState *device;
|
||||||
qemu_irq irq;
|
qemu_irq irq;
|
||||||
MemoryRegion mem;
|
MemoryRegion mem;
|
||||||
AddressSpace *as;
|
AddressSpace *as;
|
||||||
|
@ -108,12 +108,15 @@ struct bt_device_s {
|
|||||||
uint16_t clkoff; /* Note: Always little-endian */
|
uint16_t clkoff; /* Note: Always little-endian */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern struct HCIInfo null_hci;
|
||||||
/* bt.c */
|
/* bt.c */
|
||||||
void bt_device_init(struct bt_device_s *dev, struct bt_scatternet_s *net);
|
void bt_device_init(struct bt_device_s *dev, struct bt_scatternet_s *net);
|
||||||
void bt_device_done(struct bt_device_s *dev);
|
void bt_device_done(struct bt_device_s *dev);
|
||||||
|
struct bt_scatternet_s *qemu_find_bt_vlan(int id);
|
||||||
|
|
||||||
/* bt-hci.c */
|
/* bt-hci.c */
|
||||||
struct HCIInfo *bt_new_hci(struct bt_scatternet_s *net);
|
struct HCIInfo *bt_new_hci(struct bt_scatternet_s *net);
|
||||||
|
struct HCIInfo *hci_init(const char *str);
|
||||||
|
|
||||||
/* bt-vhci.c */
|
/* bt-vhci.c */
|
||||||
void bt_vhci_init(struct HCIInfo *info);
|
void bt_vhci_init(struct HCIInfo *info);
|
||||||
|
@ -442,9 +442,6 @@ int set_usb_string(uint8_t *buf, const char *str);
|
|||||||
USBDevice *usb_host_device_open(USBBus *bus, const char *devname);
|
USBDevice *usb_host_device_open(USBBus *bus, const char *devname);
|
||||||
void usb_host_info(Monitor *mon, const QDict *qdict);
|
void usb_host_info(Monitor *mon, const QDict *qdict);
|
||||||
|
|
||||||
/* usb-bt.c */
|
|
||||||
USBDevice *usb_bt_init(USBBus *bus, HCIInfo *hci);
|
|
||||||
|
|
||||||
/* usb ports of the VM */
|
/* usb ports of the VM */
|
||||||
|
|
||||||
#define VM_USB_HUB_SIZE 8
|
#define VM_USB_HUB_SIZE 8
|
||||||
|
82
vl.c
82
vl.c
@ -843,45 +843,6 @@ static int nb_hcis;
|
|||||||
static int cur_hci;
|
static int cur_hci;
|
||||||
static struct HCIInfo *hci_table[MAX_NICS];
|
static struct HCIInfo *hci_table[MAX_NICS];
|
||||||
|
|
||||||
static struct bt_vlan_s {
|
|
||||||
struct bt_scatternet_s net;
|
|
||||||
int id;
|
|
||||||
struct bt_vlan_s *next;
|
|
||||||
} *first_bt_vlan;
|
|
||||||
|
|
||||||
/* find or alloc a new bluetooth "VLAN" */
|
|
||||||
static struct bt_scatternet_s *qemu_find_bt_vlan(int id)
|
|
||||||
{
|
|
||||||
struct bt_vlan_s **pvlan, *vlan;
|
|
||||||
for (vlan = first_bt_vlan; vlan != NULL; vlan = vlan->next) {
|
|
||||||
if (vlan->id == id)
|
|
||||||
return &vlan->net;
|
|
||||||
}
|
|
||||||
vlan = g_malloc0(sizeof(struct bt_vlan_s));
|
|
||||||
vlan->id = id;
|
|
||||||
pvlan = &first_bt_vlan;
|
|
||||||
while (*pvlan != NULL)
|
|
||||||
pvlan = &(*pvlan)->next;
|
|
||||||
*pvlan = vlan;
|
|
||||||
return &vlan->net;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static int null_hci_addr_set(struct HCIInfo *hci, const uint8_t *bd_addr)
|
|
||||||
{
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct HCIInfo null_hci = {
|
|
||||||
.cmd_send = null_hci_send,
|
|
||||||
.sco_send = null_hci_send,
|
|
||||||
.acl_send = null_hci_send,
|
|
||||||
.bdaddr_set = null_hci_addr_set,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct HCIInfo *qemu_next_hci(void)
|
struct HCIInfo *qemu_next_hci(void)
|
||||||
{
|
{
|
||||||
if (cur_hci == nb_hcis)
|
if (cur_hci == nb_hcis)
|
||||||
@ -890,36 +851,6 @@ struct HCIInfo *qemu_next_hci(void)
|
|||||||
return hci_table[cur_hci++];
|
return hci_table[cur_hci++];
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct HCIInfo *hci_init(const char *str)
|
|
||||||
{
|
|
||||||
char *endp;
|
|
||||||
struct bt_scatternet_s *vlan = 0;
|
|
||||||
|
|
||||||
if (!strcmp(str, "null"))
|
|
||||||
/* null */
|
|
||||||
return &null_hci;
|
|
||||||
else if (!strncmp(str, "host", 4) && (str[4] == '\0' || str[4] == ':'))
|
|
||||||
/* host[:hciN] */
|
|
||||||
return bt_host_hci(str[4] ? str + 5 : "hci0");
|
|
||||||
else if (!strncmp(str, "hci", 3)) {
|
|
||||||
/* hci[,vlan=n] */
|
|
||||||
if (str[3]) {
|
|
||||||
if (!strncmp(str + 3, ",vlan=", 6)) {
|
|
||||||
vlan = qemu_find_bt_vlan(strtol(str + 9, &endp, 0));
|
|
||||||
if (*endp)
|
|
||||||
vlan = 0;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
vlan = qemu_find_bt_vlan(0);
|
|
||||||
if (vlan)
|
|
||||||
return bt_new_hci(vlan);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "qemu: Unknown bluetooth HCI `%s'.\n", str);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bt_hci_parse(const char *str)
|
static int bt_hci_parse(const char *str)
|
||||||
{
|
{
|
||||||
struct HCIInfo *hci;
|
struct HCIInfo *hci;
|
||||||
@ -1526,8 +1457,10 @@ static void configure_msg(QemuOpts *opts)
|
|||||||
|
|
||||||
static int usb_device_add(const char *devname)
|
static int usb_device_add(const char *devname)
|
||||||
{
|
{
|
||||||
const char *p;
|
|
||||||
USBDevice *dev = NULL;
|
USBDevice *dev = NULL;
|
||||||
|
#ifndef CONFIG_LINUX
|
||||||
|
const char *p;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!usb_enabled(false)) {
|
if (!usb_enabled(false)) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -1543,15 +1476,8 @@ static int usb_device_add(const char *devname)
|
|||||||
/* only the linux version is qdev-ified, usb-bsd still needs this */
|
/* only the linux version is qdev-ified, usb-bsd still needs this */
|
||||||
if (strstart(devname, "host:", &p)) {
|
if (strstart(devname, "host:", &p)) {
|
||||||
dev = usb_host_device_open(usb_bus_find(-1), p);
|
dev = usb_host_device_open(usb_bus_find(-1), p);
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (!strcmp(devname, "bt") || strstart(devname, "bt:", &p)) {
|
|
||||||
dev = usb_bt_init(usb_bus_find(-1),
|
|
||||||
devname[2] ? hci_init(p)
|
|
||||||
: bt_new_hci(qemu_find_bt_vlan(0)));
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user