mirror of
https://git.FreeBSD.org/ports.git
synced 2024-12-24 04:33:24 +00:00
- Add Lonnie's usb host support patches and a bunch of other fixes mostly from
cvs, including a workaround for the -nographic crash. PR: ports/94654 Submitted by: Juergen Lock <nox@jelal.kn-bremen.de> (maintainer)
This commit is contained in:
parent
c3dba571af
commit
b56ad1448d
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=157608
@ -7,7 +7,7 @@
|
||||
|
||||
PORTNAME= qemu
|
||||
PORTVERSION= 0.8.0
|
||||
PORTREVISION= 3
|
||||
PORTREVISION= 4
|
||||
CATEGORIES= emulators
|
||||
MASTER_SITES= http://www.qemu.org/:release \
|
||||
http://people.fruitsalad.org/nox/qemu/:snapshot \
|
||||
|
741
emulators/qemu-devel/files/patch-bsdusb.patch
Normal file
741
emulators/qemu-devel/files/patch-bsdusb.patch
Normal file
@ -0,0 +1,741 @@
|
||||
Index: qemu/configure
|
||||
@@ -122,6 +122,7 @@
|
||||
*)
|
||||
oss="yes"
|
||||
linux="yes"
|
||||
+usb="linux"
|
||||
if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
|
||||
kqemu="yes"
|
||||
fi
|
||||
@@ -131,6 +132,7 @@
|
||||
if [ "$bsd" = "yes" ] ; then
|
||||
if [ ! "$darwin" = "yes" ] ; then
|
||||
make="gmake"
|
||||
+ usb="bsd"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -656,6 +675,19 @@
|
||||
echo "#define _BSD 1" >> $config_h
|
||||
fi
|
||||
|
||||
+# USB host support
|
||||
+case "$usb" in
|
||||
+linux)
|
||||
+ echo "HOST_USB=linux" >> $conig_mak
|
||||
+;;
|
||||
+bsd)
|
||||
+ echo "HOST_USB=bsd" >> $config_mak
|
||||
+;;
|
||||
+*)
|
||||
+ echo "HOST_USB=stub" >> $config_mak
|
||||
+;;
|
||||
+esac
|
||||
+
|
||||
for target in $target_list; do
|
||||
|
||||
target_dir="$target"
|
||||
Index: qemu/Makefile.target
|
||||
@@ -303,7 +303,7 @@
|
||||
endif
|
||||
|
||||
# USB layer
|
||||
-VL_OBJS+= usb.o usb-uhci.o usb-linux.o usb-hid.o
|
||||
+VL_OBJS+= usb.o usb-uhci.o usb-$(HOST_USB).o usb-hid.o
|
||||
|
||||
ifeq ($(TARGET_BASE_ARCH), i386)
|
||||
# Hardware support
|
||||
Index: qemu/usb-stub.c
|
||||
@@ -0,0 +1,11 @@
|
||||
+#include "vl.h"
|
||||
+
|
||||
+void usb_host_info(void)
|
||||
+{
|
||||
+ term_printf("USB host devices not supported\n");
|
||||
+}
|
||||
+
|
||||
+USBDevice *usb_host_device_open(const char *devname)
|
||||
+{
|
||||
+ return NULL;
|
||||
+}
|
||||
Index: qemu/usb-bsd.c
|
||||
@@ -0,0 +1,592 @@
|
||||
+/*
|
||||
+ * BSD host USB redirector
|
||||
+ *
|
||||
+ * Copyright (c) 2005 Lonnie Mendez
|
||||
+ * Portions of code and concepts borrowed from
|
||||
+ * usb-linux.c and libusb's bsd.c and are copyright their respective owners.
|
||||
+ *
|
||||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
+ * of this software and associated documentation files (the "Software"), to deal
|
||||
+ * in the Software without restriction, including without limitation the rights
|
||||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
+ * copies of the Software, and to permit persons to whom the Software is
|
||||
+ * furnished to do so, subject to the following conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be included in
|
||||
+ * all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
+ * THE SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+#include "vl.h"
|
||||
+
|
||||
+/* usb.h declares these */
|
||||
+#undef USB_SPEED_HIGH
|
||||
+#undef USB_SPEED_FULL
|
||||
+#undef USB_SPEED_LOW
|
||||
+
|
||||
+#include <sys/ioctl.h>
|
||||
+#include <dev/usb/usb.h>
|
||||
+#include <signal.h>
|
||||
+
|
||||
+/* This value has maximum potential at 16.
|
||||
+ * You should also set hw.usb.debug to gain
|
||||
+ * more detailed view.
|
||||
+ */
|
||||
+//#define DEBUG
|
||||
+#define UGEN_DEBUG_LEVEL 0
|
||||
+
|
||||
+
|
||||
+typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id,
|
||||
+ int vendor_id, int product_id,
|
||||
+ const char *product_name, int speed);
|
||||
+static int usb_host_find_device(int *pbus_num, int *paddr,
|
||||
+ const char *devname);
|
||||
+
|
||||
+typedef struct USBHostDevice {
|
||||
+ USBDevice dev;
|
||||
+ int ep_fd[USB_MAX_ENDPOINTS];
|
||||
+ int devfd;
|
||||
+ char devpath[32];
|
||||
+} USBHostDevice;
|
||||
+
|
||||
+
|
||||
+static int ensure_ep_open(USBHostDevice *dev, int ep, int mode)
|
||||
+{
|
||||
+ char buf[32];
|
||||
+ int fd;
|
||||
+
|
||||
+ /* Get the address for this endpoint */
|
||||
+ ep = UE_GET_ADDR(ep);
|
||||
+
|
||||
+ if (dev->ep_fd[ep] < 0) {
|
||||
+#if __FreeBSD__
|
||||
+ snprintf(buf, sizeof(buf) - 1, "%s.%d", dev->devpath, ep);
|
||||
+#else
|
||||
+ snprintf(buf, sizeof(buf) - 1, "%s.%02d", dev->devpath, ep);
|
||||
+#endif
|
||||
+ /* Try to open it O_RDWR first for those devices which have in and out
|
||||
+ * endpoints with the same address (eg 0x02 and 0x82)
|
||||
+ */
|
||||
+ fd = open(buf, O_RDWR);
|
||||
+ if (fd < 0 && errno == ENXIO)
|
||||
+ fd = open(buf, mode);
|
||||
+ if (fd < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("ensure_ep_open: failed to open device endpoint %s: %s\n",
|
||||
+ buf, strerror(errno));
|
||||
+#endif
|
||||
+ }
|
||||
+ dev->ep_fd[ep] = fd;
|
||||
+ }
|
||||
+
|
||||
+ return dev->ep_fd[ep];
|
||||
+}
|
||||
+
|
||||
+static void ensure_eps_closed(USBHostDevice *dev)
|
||||
+{
|
||||
+ int epnum = 1;
|
||||
+
|
||||
+ if (!dev)
|
||||
+ return;
|
||||
+
|
||||
+ while (epnum < USB_MAX_ENDPOINTS) {
|
||||
+ if (dev->ep_fd[epnum] >= 0) {
|
||||
+ close(dev->ep_fd[epnum]);
|
||||
+ dev->ep_fd[epnum] = -1;
|
||||
+ }
|
||||
+ epnum++;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void usb_host_handle_reset(USBDevice *dev)
|
||||
+{
|
||||
+#if 0
|
||||
+ USBHostDevice *s = (USBHostDevice *)dev;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+/* XXX:
|
||||
+ * -check device states against transfer requests
|
||||
+ * and return appropriate response
|
||||
+ */
|
||||
+static int usb_host_handle_control(USBDevice *dev,
|
||||
+ int request,
|
||||
+ int value,
|
||||
+ int index,
|
||||
+ int length,
|
||||
+ uint8_t *data)
|
||||
+{
|
||||
+ USBHostDevice *s = (USBHostDevice *)dev;
|
||||
+ struct usb_ctl_request req;
|
||||
+ struct usb_alt_interface aiface;
|
||||
+ int ret, timeout = 50;
|
||||
+
|
||||
+ if ((request >> 8) == UT_WRITE_DEVICE &&
|
||||
+ (request & 0xff) == UR_SET_ADDRESS) {
|
||||
+
|
||||
+ /* specific SET_ADDRESS support */
|
||||
+ dev->addr = value;
|
||||
+ return 0;
|
||||
+ } else if ((request >> 8) == UT_WRITE_DEVICE &&
|
||||
+ (request & 0xff) == UR_SET_CONFIG) {
|
||||
+
|
||||
+ ensure_eps_closed(s); /* can't do this without all eps closed */
|
||||
+
|
||||
+ ret = ioctl(s->devfd, USB_SET_CONFIG, &value);
|
||||
+ if (ret < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("handle_control: failed to set configuration - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ return USB_RET_STALL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+ } else if ((request >> 8) == UT_WRITE_INTERFACE &&
|
||||
+ (request & 0xff) == UR_SET_INTERFACE) {
|
||||
+
|
||||
+ aiface.uai_interface_index = index;
|
||||
+ aiface.uai_alt_no = value;
|
||||
+
|
||||
+ ensure_eps_closed(s); /* can't do this without all eps closed */
|
||||
+ ret = ioctl(s->devfd, USB_SET_ALTINTERFACE, &aiface);
|
||||
+ if (ret < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("handle_control: failed to set alternate interface - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ return USB_RET_STALL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+ } else {
|
||||
+ req.ucr_request.bmRequestType = request >> 8;
|
||||
+ req.ucr_request.bRequest = request & 0xff;
|
||||
+ USETW(req.ucr_request.wValue, value);
|
||||
+ USETW(req.ucr_request.wIndex, index);
|
||||
+ USETW(req.ucr_request.wLength, length);
|
||||
+ req.ucr_data = data;
|
||||
+ req.ucr_flags = USBD_SHORT_XFER_OK;
|
||||
+
|
||||
+ ret = ioctl(s->devfd, USB_SET_TIMEOUT, &timeout);
|
||||
+#if (__NetBSD__ || __OpenBSD__)
|
||||
+ if (ret < 0 && errno != EINVAL) {
|
||||
+#else
|
||||
+ if (ret < 0) {
|
||||
+#endif
|
||||
+#ifdef DEBUG
|
||||
+ printf("handle_control: setting timeout failed - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ }
|
||||
+
|
||||
+ ret = ioctl(s->devfd, USB_DO_REQUEST, &req);
|
||||
+ /* ugen returns EIO for usbd_do_request_ no matter what
|
||||
+ * happens with the transfer */
|
||||
+ if (ret < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("handle_control: error after request - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ return USB_RET_NAK; // STALL
|
||||
+ } else {
|
||||
+ return req.ucr_actlen;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int usb_host_handle_data(USBDevice *dev, int pid,
|
||||
+ uint8_t devep,
|
||||
+ uint8_t *data, int len)
|
||||
+{
|
||||
+ USBHostDevice *s = (USBHostDevice *)dev;
|
||||
+ int ret, fd, mode;
|
||||
+ int one = 1, shortpacket = 0, timeout = 50;
|
||||
+ sigset_t new_mask, old_mask;
|
||||
+
|
||||
+ /* protect data transfers from SIGALRM signal */
|
||||
+ sigemptyset(&new_mask);
|
||||
+ sigaddset(&new_mask, SIGALRM);
|
||||
+ sigprocmask(SIG_BLOCK, &new_mask, &old_mask);
|
||||
+
|
||||
+ /* XXX: optimize and handle all data types by looking at the
|
||||
+ config descriptor */
|
||||
+ if (pid == USB_TOKEN_IN) {
|
||||
+ devep |= 0x80;
|
||||
+ mode = O_RDONLY;
|
||||
+ shortpacket = 1;
|
||||
+ } else {
|
||||
+ mode = O_WRONLY;
|
||||
+ }
|
||||
+
|
||||
+ fd = ensure_ep_open(s, devep, mode);
|
||||
+ if (fd < 0) {
|
||||
+ sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
||||
+ return USB_RET_NODEV;
|
||||
+ }
|
||||
+
|
||||
+ if (ioctl(fd, USB_SET_TIMEOUT, &timeout) < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("handle_data: failed to set timeout - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ }
|
||||
+
|
||||
+ if (shortpacket) {
|
||||
+ if (ioctl(fd, USB_SET_SHORT_XFER, &one) < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("handle_data: failed to set short xfer mode - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (pid == USB_TOKEN_IN)
|
||||
+ ret = read(fd, data, len);
|
||||
+ else
|
||||
+ ret = write(fd, data, len);
|
||||
+
|
||||
+ sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
||||
+
|
||||
+ if (ret < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("handle_data: error after %s data - %s\n",
|
||||
+ pid == USB_TOKEN_IN ? "reading" : "writing", strerror(errno));
|
||||
+#endif
|
||||
+ switch(errno) {
|
||||
+ case ETIMEDOUT:
|
||||
+ case EINTR:
|
||||
+ return USB_RET_NAK;
|
||||
+ default:
|
||||
+ return USB_RET_STALL;
|
||||
+ }
|
||||
+ } else {
|
||||
+ return ret;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+USBDevice *usb_host_device_open(const char *devname)
|
||||
+{
|
||||
+ struct usb_device_info bus_info, dev_info;
|
||||
+ USBHostDevice *dev;
|
||||
+ char ctlpath[PATH_MAX + 1];
|
||||
+ char buspath[PATH_MAX + 1];
|
||||
+ int bfd, dfd, bus, address, i;
|
||||
+ int ugendebug = UGEN_DEBUG_LEVEL;
|
||||
+
|
||||
+ if (usb_host_find_device(&bus, &address, devname) < 0)
|
||||
+ return NULL;
|
||||
+
|
||||
+ snprintf(buspath, PATH_MAX, "/dev/usb%d", bus);
|
||||
+
|
||||
+ bfd = open(buspath, O_RDWR);
|
||||
+ if (bfd < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("usb_host_device_open: failed to open usb bus - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ bus_info.udi_addr = address;
|
||||
+ if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("usb_host_device_open: failed to grab bus information - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+#if __FreeBSD__
|
||||
+ snprintf(ctlpath, PATH_MAX, "/dev/%s", bus_info.udi_devnames[0]);
|
||||
+#else
|
||||
+ snprintf(ctlpath, PATH_MAX, "/dev/%s.00", bus_info.udi_devnames[0]);
|
||||
+#endif
|
||||
+
|
||||
+ dfd = open(ctlpath, O_RDWR);
|
||||
+ if (dfd < 0) {
|
||||
+ dfd = open(ctlpath, O_RDONLY);
|
||||
+ if (dfd < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("usb_host_device_open: failed to open usb device %s - %s\n",
|
||||
+ ctlpath, strerror(errno));
|
||||
+#endif
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (dfd >= 0) {
|
||||
+ dev = qemu_mallocz(sizeof(USBHostDevice));
|
||||
+ if (!dev)
|
||||
+ goto fail;
|
||||
+ dev->devfd = dfd;
|
||||
+
|
||||
+ if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("usb_host_device_open: failed to grab device info - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ if (dev_info.udi_speed == 1)
|
||||
+ dev->dev.speed = USB_SPEED_LOW - 1;
|
||||
+ else
|
||||
+ dev->dev.speed = USB_SPEED_FULL - 1;
|
||||
+
|
||||
+ dev->dev.handle_packet = usb_generic_handle_packet;
|
||||
+
|
||||
+ dev->dev.handle_reset = usb_host_handle_reset;
|
||||
+ dev->dev.handle_control = usb_host_handle_control;
|
||||
+ dev->dev.handle_data = usb_host_handle_data;
|
||||
+
|
||||
+ strcpy(dev->devpath, "/dev/");
|
||||
+ strcat(dev->devpath, dev_info.udi_devnames[0]);
|
||||
+
|
||||
+ /* Mark the endpoints as not yet open */
|
||||
+ for (i = 0; i < USB_MAX_ENDPOINTS; i++)
|
||||
+ dev->ep_fd[i] = -1;
|
||||
+
|
||||
+ ioctl(dfd, USB_SETDEBUG, &ugendebug);
|
||||
+
|
||||
+ return (USBDevice *)dev;
|
||||
+ }
|
||||
+
|
||||
+fail:
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+void usb_host_device_close(USBDevice *opaque)
|
||||
+{
|
||||
+ USBHostDevice *s = (USBHostDevice *)opaque;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < USB_MAX_ENDPOINTS; i++)
|
||||
+ if (s->ep_fd[i] >= 0)
|
||||
+ close(s->ep_fd[i]);
|
||||
+
|
||||
+ if (s->devfd < 0)
|
||||
+ return;
|
||||
+
|
||||
+ close(s->devfd);
|
||||
+}
|
||||
+
|
||||
+static int usb_host_scan(void *opaque, USBScanFunc *func)
|
||||
+{
|
||||
+ struct usb_device_info bus_info;
|
||||
+ struct usb_device_info dev_info;
|
||||
+ uint16_t vendor_id, product_id, class_id, speed;
|
||||
+ int bfd, dfd, bus, address;
|
||||
+ char busbuf[20], devbuf[20], product_name[256];
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ for (bus = 0; bus < 10; bus++) {
|
||||
+
|
||||
+ snprintf(busbuf, sizeof(busbuf) - 1, "/dev/usb%d", bus);
|
||||
+ bfd = open(busbuf, O_RDWR);
|
||||
+ if (bfd < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ for (address = 1; address < 127; address++) {
|
||||
+
|
||||
+ bus_info.udi_addr = address;
|
||||
+ if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ /* only list devices that can be used by generic layer */
|
||||
+ if (strncmp(bus_info.udi_devnames[0], "ugen", 4) != 0)
|
||||
+ continue;
|
||||
+
|
||||
+#if __FreeBSD__
|
||||
+ snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s", bus_info.udi_devnames[0]);
|
||||
+#else
|
||||
+ snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s.00", bus_info.udi_devnames[0]);
|
||||
+#endif
|
||||
+
|
||||
+ dfd = open(devbuf, O_RDONLY);
|
||||
+ if (dfd < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("usb_host_scan: couldn't open device %s - %s\n", devbuf,
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0)
|
||||
+ printf("usb_host_scan: couldn't get device information for %s - %s\n",
|
||||
+ devbuf, strerror(errno));
|
||||
+
|
||||
+ // XXX: might need to fixup endianess of word values before copying over
|
||||
+
|
||||
+ vendor_id = dev_info.udi_vendorNo;
|
||||
+ product_id = dev_info.udi_productNo;
|
||||
+ class_id = dev_info.udi_class;
|
||||
+ speed = dev_info.udi_speed;
|
||||
+
|
||||
+ if (strncmp(dev_info.udi_product, "product", 7) != 0)
|
||||
+ strcpy(product_name, dev_info.udi_product);
|
||||
+ else
|
||||
+ product_name[0] = '\0';
|
||||
+
|
||||
+ ret = func(opaque, bus, address, class_id, vendor_id,
|
||||
+ product_id, product_name, speed);
|
||||
+
|
||||
+ close(dfd);
|
||||
+
|
||||
+ if (ret)
|
||||
+ goto the_end;
|
||||
+ }
|
||||
+
|
||||
+ close(bfd);
|
||||
+ }
|
||||
+
|
||||
+the_end:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+typedef struct FindDeviceState {
|
||||
+ int vendor_id;
|
||||
+ int product_id;
|
||||
+ int bus_num;
|
||||
+ int addr;
|
||||
+} FindDeviceState;
|
||||
+
|
||||
+static int usb_host_find_device_scan(void *opaque, int bus_num, int addr,
|
||||
+ int class_id,
|
||||
+ int vendor_id, int product_id,
|
||||
+ const char *product_name, int speed)
|
||||
+{
|
||||
+ FindDeviceState *s = opaque;
|
||||
+ if (vendor_id == s->vendor_id &&
|
||||
+ product_id == s->product_id) {
|
||||
+ s->bus_num = bus_num;
|
||||
+ s->addr = addr;
|
||||
+ return 1;
|
||||
+ } else {
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* the syntax is :
|
||||
+ 'bus.addr' (decimal numbers) or
|
||||
+ 'vendor_id:product_id' (hexa numbers) */
|
||||
+static int usb_host_find_device(int *pbus_num, int *paddr,
|
||||
+ const char *devname)
|
||||
+{
|
||||
+ const char *p;
|
||||
+ int ret;
|
||||
+ FindDeviceState fs;
|
||||
+
|
||||
+ p = strchr(devname, '.');
|
||||
+ if (p) {
|
||||
+ *pbus_num = strtoul(devname, NULL, 0);
|
||||
+ *paddr = strtoul(p + 1, NULL, 0);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ p = strchr(devname, ':');
|
||||
+ if (p) {
|
||||
+ fs.vendor_id = strtoul(devname, NULL, 16);
|
||||
+ fs.product_id = strtoul(p + 1, NULL, 16);
|
||||
+ ret = usb_host_scan(&fs, usb_host_find_device_scan);
|
||||
+ if (ret) {
|
||||
+ *pbus_num = fs.bus_num;
|
||||
+ *paddr = fs.addr;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+/**********************/
|
||||
+/* USB host device info */
|
||||
+
|
||||
+struct usb_class_info {
|
||||
+ int class;
|
||||
+ const char *class_name;
|
||||
+};
|
||||
+
|
||||
+static const struct usb_class_info usb_class_info[] = {
|
||||
+ { USB_CLASS_AUDIO, "Audio"},
|
||||
+ { USB_CLASS_COMM, "Communication"},
|
||||
+ { USB_CLASS_HID, "HID"},
|
||||
+ { USB_CLASS_HUB, "Hub" },
|
||||
+ { USB_CLASS_PHYSICAL, "Physical" },
|
||||
+ { USB_CLASS_PRINTER, "Printer" },
|
||||
+ { USB_CLASS_MASS_STORAGE, "Storage" },
|
||||
+ { USB_CLASS_CDC_DATA, "Data" },
|
||||
+ { USB_CLASS_APP_SPEC, "Application Specific" },
|
||||
+ { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
|
||||
+ { USB_CLASS_STILL_IMAGE, "Still Image" },
|
||||
+ { USB_CLASS_CSCID, "Smart Card" },
|
||||
+ { USB_CLASS_CONTENT_SEC, "Content Security" },
|
||||
+ { -1, NULL }
|
||||
+};
|
||||
+
|
||||
+static const char *usb_class_str(uint8_t class)
|
||||
+{
|
||||
+ const struct usb_class_info *p;
|
||||
+ for (p = usb_class_info; p->class != -1; p++) {
|
||||
+ if (p->class == class)
|
||||
+ break;
|
||||
+ }
|
||||
+ return p->class_name;
|
||||
+}
|
||||
+
|
||||
+void usb_info_device(int bus_num, int addr, int class_id,
|
||||
+ int vendor_id, int product_id,
|
||||
+ const char *product_name,
|
||||
+ int speed)
|
||||
+{
|
||||
+ const char *class_str, *speed_str;
|
||||
+
|
||||
+ switch(speed) {
|
||||
+ case USB_SPEED_LOW:
|
||||
+ speed_str = "1.5";
|
||||
+ break;
|
||||
+ case USB_SPEED_FULL:
|
||||
+ speed_str = "12";
|
||||
+ break;
|
||||
+ case USB_SPEED_HIGH:
|
||||
+ speed_str = "480";
|
||||
+ break;
|
||||
+ default:
|
||||
+ speed_str = "?";
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ term_printf(" Device %d.%d, speed %s Mb/s\n",
|
||||
+ bus_num, addr, speed_str);
|
||||
+ class_str = usb_class_str(class_id);
|
||||
+ if (class_str)
|
||||
+ term_printf(" %s:", class_str);
|
||||
+ else
|
||||
+ term_printf(" Class %02x:", class_id);
|
||||
+ term_printf(" USB device %04x:%04x", vendor_id, product_id);
|
||||
+ if (product_name[0] != '\0')
|
||||
+ term_printf(", %s", product_name);
|
||||
+ term_printf("\n");
|
||||
+}
|
||||
+
|
||||
+static int usb_host_info_device(void *opaque, int bus_num, int addr,
|
||||
+ int class_id,
|
||||
+ int vendor_id, int product_id,
|
||||
+ const char *product_name,
|
||||
+ int speed)
|
||||
+{
|
||||
+ usb_info_device(bus_num, addr, class_id, vendor_id, product_id,
|
||||
+ product_name, speed);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void usb_host_info(void)
|
||||
+{
|
||||
+ usb_host_scan(NULL, usb_host_info_device);
|
||||
+}
|
||||
Index: qemu/vl.c
|
||||
@@ -2820,10 +2822,12 @@
|
||||
dev = usb_host_device_open(p);
|
||||
if (!dev)
|
||||
return -1;
|
||||
+ dev->isproxied = 1;
|
||||
} else if (!strcmp(devname, "mouse")) {
|
||||
dev = usb_mouse_init();
|
||||
if (!dev)
|
||||
return -1;
|
||||
+ dev->isproxied = 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
@@ -2852,6 +2856,8 @@
|
||||
if (dev && dev->addr == addr)
|
||||
break;
|
||||
}
|
||||
+ if (dev && dev->isproxied)
|
||||
+ usb_host_device_close(dev);
|
||||
if (i == MAX_VM_USB_PORTS)
|
||||
return -1;
|
||||
usb_attach(vm_usb_ports[i], NULL);
|
||||
Index: qemu/hw/usb.h
|
||||
@@ -135,6 +146,8 @@
|
||||
int setup_state;
|
||||
int setup_len;
|
||||
int setup_index;
|
||||
+
|
||||
+ int isproxied;
|
||||
};
|
||||
|
||||
/* USB port on which a device can be connected */
|
||||
@@ -157,8 +170,9 @@
|
||||
/* usb-uhci.c */
|
||||
void usb_uhci_init(PCIBus *bus, USBPort **usb_ports);
|
||||
|
||||
-/* usb-linux.c */
|
||||
+/* host proxy functions */
|
||||
USBDevice *usb_host_device_open(const char *devname);
|
||||
+void usb_host_device_close(USBDevice *dev);
|
||||
void usb_host_info(void);
|
||||
|
||||
/* usb-hid.c */
|
||||
Index: qemu/usb-linux.c
|
||||
@@ -23,7 +23,6 @@
|
||||
*/
|
||||
#include "vl.h"
|
||||
|
||||
-#if defined(__linux__)
|
||||
#include <dirent.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/usbdevice_fs.h>
|
||||
@@ -255,6 +254,14 @@
|
||||
return q - buf;
|
||||
}
|
||||
|
||||
+void usb_host_device_close(USBDevice *opaque)
|
||||
+{
|
||||
+ USBHostDevice *s = (USBHostDevice *)opaque;
|
||||
+
|
||||
+ if (s->fd >= 0)
|
||||
+ close(s->fd);
|
||||
+}
|
||||
+
|
||||
static int usb_host_scan(void *opaque, USBScanFunc *func)
|
||||
{
|
||||
FILE *f;
|
||||
@@ -468,18 +475,3 @@
|
||||
{
|
||||
usb_host_scan(NULL, usb_host_info_device);
|
||||
}
|
||||
-
|
||||
-#else
|
||||
-
|
||||
-void usb_host_info(void)
|
||||
-{
|
||||
- term_printf("USB host devices not supported\n");
|
||||
-}
|
||||
-
|
||||
-/* XXX: modify configure to compile the right host driver */
|
||||
-USBDevice *usb_host_device_open(const char *devname)
|
||||
-{
|
||||
- return NULL;
|
||||
-}
|
||||
-
|
||||
-#endif
|
11
emulators/qemu-devel/files/patch-dyngen.h
Normal file
11
emulators/qemu-devel/files/patch-dyngen.h
Normal file
@ -0,0 +1,11 @@
|
||||
# 1.9
|
||||
Index: qemu/dyngen.h
|
||||
@@ -59,7 +59,7 @@
|
||||
{
|
||||
unsigned long p;
|
||||
|
||||
- p = start & ~(MIN_CACHE_LINE_SIZE - 1);
|
||||
+ start &= ~(MIN_CACHE_LINE_SIZE - 1);
|
||||
stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
|
||||
|
||||
for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
|
44
emulators/qemu-devel/files/patch-hw-ne2000.c
Normal file
44
emulators/qemu-devel/files/patch-hw-ne2000.c
Normal file
@ -0,0 +1,44 @@
|
||||
# 1.19
|
||||
Index: qemu/hw/ne2000.c
|
||||
@@ -648,6 +648,8 @@
|
||||
{
|
||||
NE2000State* s=(NE2000State*)opaque;
|
||||
|
||||
+ qemu_put_8s(f, &s->rxcr);
|
||||
+
|
||||
qemu_put_8s(f, &s->cmd);
|
||||
qemu_put_be32s(f, &s->start);
|
||||
qemu_put_be32s(f, &s->stop);
|
||||
@@ -672,8 +674,13 @@
|
||||
{
|
||||
NE2000State* s=(NE2000State*)opaque;
|
||||
|
||||
- if (version_id != 1)
|
||||
+ if (version_id == 2) {
|
||||
+ qemu_get_8s(f, &s->rxcr);
|
||||
+ } else if (version_id == 1) {
|
||||
+ s->rxcr = 0x0c;
|
||||
+ } else {
|
||||
return -EINVAL;
|
||||
+ }
|
||||
|
||||
qemu_get_8s(f, &s->cmd);
|
||||
qemu_get_be32s(f, &s->start);
|
||||
@@ -732,7 +739,7 @@
|
||||
s->macaddr[4],
|
||||
s->macaddr[5]);
|
||||
|
||||
- register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s);
|
||||
+ register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s);
|
||||
}
|
||||
|
||||
/***********************************************************/
|
||||
@@ -803,7 +810,7 @@
|
||||
s->macaddr[5]);
|
||||
|
||||
/* XXX: instance number ? */
|
||||
- register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s);
|
||||
+ register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s);
|
||||
register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load,
|
||||
&d->dev);
|
||||
}
|
28
emulators/qemu-devel/files/patch-hw-usb-uhci.c
Normal file
28
emulators/qemu-devel/files/patch-hw-usb-uhci.c
Normal file
@ -0,0 +1,28 @@
|
||||
# 1.6
|
||||
Index: qemu/hw/usb-uhci.c
|
||||
@@ -153,6 +153,7 @@
|
||||
switch(addr) {
|
||||
case 0x0c:
|
||||
val = s->sof_timing;
|
||||
+ break;
|
||||
default:
|
||||
val = 0xff;
|
||||
break;
|
||||
@@ -654,6 +655,7 @@
|
||||
pci_conf[0x0b] = 0x0c;
|
||||
pci_conf[0x0e] = 0x00; // header_type
|
||||
pci_conf[0x3d] = 4; // interrupt pin 3
|
||||
+ pci_conf[0x60] = 0x10; // release number
|
||||
|
||||
for(i = 0; i < NB_PORTS; i++) {
|
||||
port = &s->ports[i];
|
||||
@@ -666,6 +668,8 @@
|
||||
|
||||
uhci_reset(s);
|
||||
|
||||
- pci_register_io_region(&s->dev, 0, 0x20,
|
||||
+ /* Use region 4 for consistency with real hardware. BSD guests seem
|
||||
+ to rely on this. */
|
||||
+ pci_register_io_region(&s->dev, 4, 0x20,
|
||||
PCI_ADDRESS_SPACE_IO, uhci_map);
|
||||
}
|
11
emulators/qemu-devel/files/patch-hw-usb.c
Normal file
11
emulators/qemu-devel/files/patch-hw-usb.c
Normal file
@ -0,0 +1,11 @@
|
||||
# 1.4
|
||||
Index: qemu/hw/usb.c
|
||||
@@ -183,7 +183,7 @@
|
||||
|
||||
q = buf;
|
||||
len = strlen(str);
|
||||
- *q++ = 2 * len + 1;
|
||||
+ *q++ = 2 * len + 2;
|
||||
*q++ = 3;
|
||||
for(i = 0; i < len; i++) {
|
||||
*q++ = str[i];
|
29
emulators/qemu-devel/files/patch-sdl.c
Normal file
29
emulators/qemu-devel/files/patch-sdl.c
Normal file
@ -0,0 +1,29 @@
|
||||
# 1.24
|
||||
Index: qemu/sdl.c
|
||||
@@ -404,6 +404,7 @@
|
||||
mod_state = (ev->key.keysym.mod & gui_grab_code);
|
||||
if (!mod_state) {
|
||||
if (gui_key_modifier_pressed) {
|
||||
+ gui_key_modifier_pressed = 0;
|
||||
if (gui_keysym == 0) {
|
||||
/* exit/enter grab if pressing Ctrl-Alt */
|
||||
if (!gui_grab)
|
||||
@@ -415,7 +416,6 @@
|
||||
reset_keys();
|
||||
break;
|
||||
}
|
||||
- gui_key_modifier_pressed = 0;
|
||||
gui_keysym = 0;
|
||||
}
|
||||
}
|
||||
@@ -456,8 +456,8 @@
|
||||
}
|
||||
break;
|
||||
case SDL_ACTIVEEVENT:
|
||||
- if (gui_grab && (ev->active.gain & SDL_ACTIVEEVENTMASK) == 0 &&
|
||||
- !gui_fullscreen_initial_grab) {
|
||||
+ if (gui_grab && ev->active.state == SDL_APPINPUTFOCUS &&
|
||||
+ !ev->active.gain && !gui_fullscreen_initial_grab) {
|
||||
sdl_grab_end();
|
||||
}
|
||||
break;
|
18
emulators/qemu-devel/files/patch-slirp-socket.c
Normal file
18
emulators/qemu-devel/files/patch-slirp-socket.c
Normal file
@ -0,0 +1,18 @@
|
||||
# 1.6
|
||||
Index: qemu/slirp/socket.c
|
||||
@@ -573,6 +573,7 @@
|
||||
addr.sin_port = port;
|
||||
|
||||
if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||
|
||||
+ (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
|
||||
(bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
|
||||
(listen(s,1) < 0)) {
|
||||
int tmperrno = errno; /* Don't clobber the real reason we failed */
|
||||
@@ -587,7 +588,6 @@
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
- setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
|
||||
setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
|
||||
|
||||
getsockname(s,(struct sockaddr *)&addr,&addrlen);
|
29
emulators/qemu-devel/files/patch-target-i386-translate.c
Normal file
29
emulators/qemu-devel/files/patch-target-i386-translate.c
Normal file
@ -0,0 +1,29 @@
|
||||
# 1.53
|
||||
Index: qemu/target-i386/translate.c
|
||||
@@ -5803,14 +5803,24 @@
|
||||
op = (modrm >> 3) & 7;
|
||||
switch(op) {
|
||||
case 0: /* fxsave */
|
||||
- if (mod == 3 || !(s->cpuid_features & CPUID_FXSR))
|
||||
+ if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
|
||||
+ (s->flags & HF_EM_MASK))
|
||||
goto illegal_op;
|
||||
+ if (s->flags & HF_TS_MASK) {
|
||||
+ gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
|
||||
+ break;
|
||||
+ }
|
||||
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
|
||||
gen_op_fxsave_A0((s->dflag == 2));
|
||||
break;
|
||||
case 1: /* fxrstor */
|
||||
- if (mod == 3 || !(s->cpuid_features & CPUID_FXSR))
|
||||
+ if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
|
||||
+ (s->flags & HF_EM_MASK))
|
||||
goto illegal_op;
|
||||
+ if (s->flags & HF_TS_MASK) {
|
||||
+ gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
|
||||
+ break;
|
||||
+ }
|
||||
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
|
||||
gen_op_fxrstor_A0((s->dflag == 2));
|
||||
break;
|
10
emulators/qemu-devel/files/patch-usb-hchalt
Normal file
10
emulators/qemu-devel/files/patch-usb-hchalt
Normal file
@ -0,0 +1,10 @@
|
||||
Index: qemu/hw/usb-uhci.c
|
||||
@@ -527,6 +532,8 @@
|
||||
|
||||
if (!(s->cmd & UHCI_CMD_RS)) {
|
||||
qemu_del_timer(s->frame_timer);
|
||||
+ /* set hchalted bit in status - UHCI11D 2.1.2 */
|
||||
+ s->status |= UHCI_STS_HCHALTED;
|
||||
return;
|
||||
}
|
||||
frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
|
87
emulators/qemu-devel/files/patch-usb-hubfixups
Normal file
87
emulators/qemu-devel/files/patch-usb-hubfixups
Normal file
@ -0,0 +1,87 @@
|
||||
Index: qemu/hw/usb.c
|
||||
@@ -330,9 +330,9 @@
|
||||
0x0a, /* u16 wHubCharacteristics; */
|
||||
0x00, /* (per-port OC, no power switching) */
|
||||
0x01, /* u8 bPwrOn2pwrGood; 2ms */
|
||||
- 0x00, /* u8 bHubContrCurrent; 0 mA */
|
||||
- 0x00, /* u8 DeviceRemovable; *** 7 Ports max *** */
|
||||
- 0xff /* u8 PortPwrCtrlMask; *** 7 ports max *** */
|
||||
+ 0x00 /* u8 bHubContrCurrent; 0 mA */
|
||||
+
|
||||
+ /* DeviceRemovable and PortPwrCtrlMask patched in later */
|
||||
};
|
||||
|
||||
static void usb_hub_attach(USBPort *port1, USBDevice *dev)
|
||||
@@ -391,6 +391,12 @@
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
+ case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
|
||||
+ if (value == 0 && index != 0x81) { /* clear ep halt */
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ ret = 0;
|
||||
+ break;
|
||||
case DeviceOutRequest | USB_REQ_SET_FEATURE:
|
||||
if (value == USB_DEVICE_REMOTE_WAKEUP) {
|
||||
dev->remote_wakeup = 1;
|
||||
@@ -408,6 +414,11 @@
|
||||
case USB_DT_DEVICE:
|
||||
memcpy(data, qemu_hub_dev_descriptor,
|
||||
sizeof(qemu_hub_dev_descriptor));
|
||||
+
|
||||
+ /* status change endpoint size based on number
|
||||
+ * of ports */
|
||||
+ data[22] = (s->nb_ports + 1 + 7) / 8;
|
||||
+
|
||||
ret = sizeof(qemu_hub_dev_descriptor);
|
||||
break;
|
||||
case USB_DT_CONFIG:
|
||||
@@ -558,11 +569,29 @@
|
||||
}
|
||||
break;
|
||||
case GetHubDescriptor:
|
||||
- memcpy(data, qemu_hub_hub_descriptor,
|
||||
- sizeof(qemu_hub_hub_descriptor));
|
||||
- data[2] = s->nb_ports;
|
||||
- ret = sizeof(qemu_hub_hub_descriptor);
|
||||
- break;
|
||||
+ {
|
||||
+ unsigned int n, limit, var_hub_size = 0;
|
||||
+ memcpy(data, qemu_hub_hub_descriptor,
|
||||
+ sizeof(qemu_hub_hub_descriptor));
|
||||
+ data[2] = s->nb_ports;
|
||||
+
|
||||
+ /* fill DeviceRemovable bits */
|
||||
+ limit = ((s->nb_ports + 1 + 7) / 8) + 7;
|
||||
+ for (n = 7; n < limit; n++) {
|
||||
+ data[n] = 0x00;
|
||||
+ var_hub_size++;
|
||||
+ }
|
||||
+
|
||||
+ /* fill PortPwrCtrlMask bits */
|
||||
+ limit = limit + ((s->nb_ports + 7) / 8);
|
||||
+ for (;n < limit; n++) {
|
||||
+ data[n] = 0xff;
|
||||
+ var_hub_size++;
|
||||
+ }
|
||||
+
|
||||
+ ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size;
|
||||
+ break;
|
||||
+ }
|
||||
default:
|
||||
fail:
|
||||
ret = USB_RET_STALL;
|
||||
@@ -584,8 +613,11 @@
|
||||
unsigned int status;
|
||||
int i, n;
|
||||
n = (s->nb_ports + 1 + 7) / 8;
|
||||
- if (n > len)
|
||||
+ if (len == 1) { /* FreeBSD workaround */
|
||||
+ n = 1;
|
||||
+ } else if (n > len) {
|
||||
return USB_RET_BABBLE;
|
||||
+ }
|
||||
status = 0;
|
||||
for(i = 0; i < s->nb_ports; i++) {
|
||||
port = &s->ports[i];
|
9
emulators/qemu-devel/files/patch-vl.c-nographic
Normal file
9
emulators/qemu-devel/files/patch-vl.c-nographic
Normal file
@ -0,0 +1,9 @@
|
||||
Index: qemu/vl.c
|
||||
@@ -4668,6 +4668,7 @@
|
||||
case QEMU_OPTION_nographic:
|
||||
pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
|
||||
pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio");
|
||||
+ pstrcpy(parallel_devices[0], sizeof(parallel_devices[0]), "null");
|
||||
nographic = 1;
|
||||
break;
|
||||
case QEMU_OPTION_kernel:
|
@ -33,4 +33,16 @@ in this message: http://docs.freebsd.org/cgi/mid.cgi?200510131428.21211.jkim
|
||||
(not included in the port since the used VIA VT86C926 PCI ID does not
|
||||
really match the emulated nic exactly, it just `happens' to work with
|
||||
6.0-RC1's driver.)
|
||||
- if you want to use usb devices connected to the host in the guest
|
||||
(usb_add host:... monitor command) you need to make sure the host isn't
|
||||
claiming them, e.g. for umass devices (like memory sticks or external
|
||||
harddrives) make sure umass isn't in the kernel (you can then still load it
|
||||
as a kld when needed), also unless you are running qemu as root you then
|
||||
need to fix permissions for /dev/ugen* device nodes: if you are on 5.x or
|
||||
later (devfs) put a rule in /etc/devfs.rules, activate it in /etc/rc.conf
|
||||
and run /etc/rc.d/devfs restart. example devfs.rules:
|
||||
[ugen_ruleset=20]
|
||||
add path 'ugen*' mode 660 group operator
|
||||
corresponding rc.conf line:
|
||||
devfs_system_ruleset="ugen_ruleset"
|
||||
====
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
PORTNAME= qemu
|
||||
PORTVERSION= 0.8.0
|
||||
PORTREVISION= 3
|
||||
PORTREVISION= 4
|
||||
CATEGORIES= emulators
|
||||
MASTER_SITES= http://www.qemu.org/:release \
|
||||
http://people.fruitsalad.org/nox/qemu/:snapshot \
|
||||
|
741
emulators/qemu/files/patch-bsdusb.patch
Normal file
741
emulators/qemu/files/patch-bsdusb.patch
Normal file
@ -0,0 +1,741 @@
|
||||
Index: qemu/configure
|
||||
@@ -122,6 +122,7 @@
|
||||
*)
|
||||
oss="yes"
|
||||
linux="yes"
|
||||
+usb="linux"
|
||||
if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
|
||||
kqemu="yes"
|
||||
fi
|
||||
@@ -131,6 +132,7 @@
|
||||
if [ "$bsd" = "yes" ] ; then
|
||||
if [ ! "$darwin" = "yes" ] ; then
|
||||
make="gmake"
|
||||
+ usb="bsd"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -656,6 +675,19 @@
|
||||
echo "#define _BSD 1" >> $config_h
|
||||
fi
|
||||
|
||||
+# USB host support
|
||||
+case "$usb" in
|
||||
+linux)
|
||||
+ echo "HOST_USB=linux" >> $conig_mak
|
||||
+;;
|
||||
+bsd)
|
||||
+ echo "HOST_USB=bsd" >> $config_mak
|
||||
+;;
|
||||
+*)
|
||||
+ echo "HOST_USB=stub" >> $config_mak
|
||||
+;;
|
||||
+esac
|
||||
+
|
||||
for target in $target_list; do
|
||||
|
||||
target_dir="$target"
|
||||
Index: qemu/Makefile.target
|
||||
@@ -303,7 +303,7 @@
|
||||
endif
|
||||
|
||||
# USB layer
|
||||
-VL_OBJS+= usb.o usb-uhci.o usb-linux.o usb-hid.o
|
||||
+VL_OBJS+= usb.o usb-uhci.o usb-$(HOST_USB).o usb-hid.o
|
||||
|
||||
ifeq ($(TARGET_BASE_ARCH), i386)
|
||||
# Hardware support
|
||||
Index: qemu/usb-stub.c
|
||||
@@ -0,0 +1,11 @@
|
||||
+#include "vl.h"
|
||||
+
|
||||
+void usb_host_info(void)
|
||||
+{
|
||||
+ term_printf("USB host devices not supported\n");
|
||||
+}
|
||||
+
|
||||
+USBDevice *usb_host_device_open(const char *devname)
|
||||
+{
|
||||
+ return NULL;
|
||||
+}
|
||||
Index: qemu/usb-bsd.c
|
||||
@@ -0,0 +1,592 @@
|
||||
+/*
|
||||
+ * BSD host USB redirector
|
||||
+ *
|
||||
+ * Copyright (c) 2005 Lonnie Mendez
|
||||
+ * Portions of code and concepts borrowed from
|
||||
+ * usb-linux.c and libusb's bsd.c and are copyright their respective owners.
|
||||
+ *
|
||||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
+ * of this software and associated documentation files (the "Software"), to deal
|
||||
+ * in the Software without restriction, including without limitation the rights
|
||||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
+ * copies of the Software, and to permit persons to whom the Software is
|
||||
+ * furnished to do so, subject to the following conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be included in
|
||||
+ * all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
+ * THE SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+#include "vl.h"
|
||||
+
|
||||
+/* usb.h declares these */
|
||||
+#undef USB_SPEED_HIGH
|
||||
+#undef USB_SPEED_FULL
|
||||
+#undef USB_SPEED_LOW
|
||||
+
|
||||
+#include <sys/ioctl.h>
|
||||
+#include <dev/usb/usb.h>
|
||||
+#include <signal.h>
|
||||
+
|
||||
+/* This value has maximum potential at 16.
|
||||
+ * You should also set hw.usb.debug to gain
|
||||
+ * more detailed view.
|
||||
+ */
|
||||
+//#define DEBUG
|
||||
+#define UGEN_DEBUG_LEVEL 0
|
||||
+
|
||||
+
|
||||
+typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id,
|
||||
+ int vendor_id, int product_id,
|
||||
+ const char *product_name, int speed);
|
||||
+static int usb_host_find_device(int *pbus_num, int *paddr,
|
||||
+ const char *devname);
|
||||
+
|
||||
+typedef struct USBHostDevice {
|
||||
+ USBDevice dev;
|
||||
+ int ep_fd[USB_MAX_ENDPOINTS];
|
||||
+ int devfd;
|
||||
+ char devpath[32];
|
||||
+} USBHostDevice;
|
||||
+
|
||||
+
|
||||
+static int ensure_ep_open(USBHostDevice *dev, int ep, int mode)
|
||||
+{
|
||||
+ char buf[32];
|
||||
+ int fd;
|
||||
+
|
||||
+ /* Get the address for this endpoint */
|
||||
+ ep = UE_GET_ADDR(ep);
|
||||
+
|
||||
+ if (dev->ep_fd[ep] < 0) {
|
||||
+#if __FreeBSD__
|
||||
+ snprintf(buf, sizeof(buf) - 1, "%s.%d", dev->devpath, ep);
|
||||
+#else
|
||||
+ snprintf(buf, sizeof(buf) - 1, "%s.%02d", dev->devpath, ep);
|
||||
+#endif
|
||||
+ /* Try to open it O_RDWR first for those devices which have in and out
|
||||
+ * endpoints with the same address (eg 0x02 and 0x82)
|
||||
+ */
|
||||
+ fd = open(buf, O_RDWR);
|
||||
+ if (fd < 0 && errno == ENXIO)
|
||||
+ fd = open(buf, mode);
|
||||
+ if (fd < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("ensure_ep_open: failed to open device endpoint %s: %s\n",
|
||||
+ buf, strerror(errno));
|
||||
+#endif
|
||||
+ }
|
||||
+ dev->ep_fd[ep] = fd;
|
||||
+ }
|
||||
+
|
||||
+ return dev->ep_fd[ep];
|
||||
+}
|
||||
+
|
||||
+static void ensure_eps_closed(USBHostDevice *dev)
|
||||
+{
|
||||
+ int epnum = 1;
|
||||
+
|
||||
+ if (!dev)
|
||||
+ return;
|
||||
+
|
||||
+ while (epnum < USB_MAX_ENDPOINTS) {
|
||||
+ if (dev->ep_fd[epnum] >= 0) {
|
||||
+ close(dev->ep_fd[epnum]);
|
||||
+ dev->ep_fd[epnum] = -1;
|
||||
+ }
|
||||
+ epnum++;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void usb_host_handle_reset(USBDevice *dev)
|
||||
+{
|
||||
+#if 0
|
||||
+ USBHostDevice *s = (USBHostDevice *)dev;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+/* XXX:
|
||||
+ * -check device states against transfer requests
|
||||
+ * and return appropriate response
|
||||
+ */
|
||||
+static int usb_host_handle_control(USBDevice *dev,
|
||||
+ int request,
|
||||
+ int value,
|
||||
+ int index,
|
||||
+ int length,
|
||||
+ uint8_t *data)
|
||||
+{
|
||||
+ USBHostDevice *s = (USBHostDevice *)dev;
|
||||
+ struct usb_ctl_request req;
|
||||
+ struct usb_alt_interface aiface;
|
||||
+ int ret, timeout = 50;
|
||||
+
|
||||
+ if ((request >> 8) == UT_WRITE_DEVICE &&
|
||||
+ (request & 0xff) == UR_SET_ADDRESS) {
|
||||
+
|
||||
+ /* specific SET_ADDRESS support */
|
||||
+ dev->addr = value;
|
||||
+ return 0;
|
||||
+ } else if ((request >> 8) == UT_WRITE_DEVICE &&
|
||||
+ (request & 0xff) == UR_SET_CONFIG) {
|
||||
+
|
||||
+ ensure_eps_closed(s); /* can't do this without all eps closed */
|
||||
+
|
||||
+ ret = ioctl(s->devfd, USB_SET_CONFIG, &value);
|
||||
+ if (ret < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("handle_control: failed to set configuration - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ return USB_RET_STALL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+ } else if ((request >> 8) == UT_WRITE_INTERFACE &&
|
||||
+ (request & 0xff) == UR_SET_INTERFACE) {
|
||||
+
|
||||
+ aiface.uai_interface_index = index;
|
||||
+ aiface.uai_alt_no = value;
|
||||
+
|
||||
+ ensure_eps_closed(s); /* can't do this without all eps closed */
|
||||
+ ret = ioctl(s->devfd, USB_SET_ALTINTERFACE, &aiface);
|
||||
+ if (ret < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("handle_control: failed to set alternate interface - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ return USB_RET_STALL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+ } else {
|
||||
+ req.ucr_request.bmRequestType = request >> 8;
|
||||
+ req.ucr_request.bRequest = request & 0xff;
|
||||
+ USETW(req.ucr_request.wValue, value);
|
||||
+ USETW(req.ucr_request.wIndex, index);
|
||||
+ USETW(req.ucr_request.wLength, length);
|
||||
+ req.ucr_data = data;
|
||||
+ req.ucr_flags = USBD_SHORT_XFER_OK;
|
||||
+
|
||||
+ ret = ioctl(s->devfd, USB_SET_TIMEOUT, &timeout);
|
||||
+#if (__NetBSD__ || __OpenBSD__)
|
||||
+ if (ret < 0 && errno != EINVAL) {
|
||||
+#else
|
||||
+ if (ret < 0) {
|
||||
+#endif
|
||||
+#ifdef DEBUG
|
||||
+ printf("handle_control: setting timeout failed - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ }
|
||||
+
|
||||
+ ret = ioctl(s->devfd, USB_DO_REQUEST, &req);
|
||||
+ /* ugen returns EIO for usbd_do_request_ no matter what
|
||||
+ * happens with the transfer */
|
||||
+ if (ret < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("handle_control: error after request - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ return USB_RET_NAK; // STALL
|
||||
+ } else {
|
||||
+ return req.ucr_actlen;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int usb_host_handle_data(USBDevice *dev, int pid,
|
||||
+ uint8_t devep,
|
||||
+ uint8_t *data, int len)
|
||||
+{
|
||||
+ USBHostDevice *s = (USBHostDevice *)dev;
|
||||
+ int ret, fd, mode;
|
||||
+ int one = 1, shortpacket = 0, timeout = 50;
|
||||
+ sigset_t new_mask, old_mask;
|
||||
+
|
||||
+ /* protect data transfers from SIGALRM signal */
|
||||
+ sigemptyset(&new_mask);
|
||||
+ sigaddset(&new_mask, SIGALRM);
|
||||
+ sigprocmask(SIG_BLOCK, &new_mask, &old_mask);
|
||||
+
|
||||
+ /* XXX: optimize and handle all data types by looking at the
|
||||
+ config descriptor */
|
||||
+ if (pid == USB_TOKEN_IN) {
|
||||
+ devep |= 0x80;
|
||||
+ mode = O_RDONLY;
|
||||
+ shortpacket = 1;
|
||||
+ } else {
|
||||
+ mode = O_WRONLY;
|
||||
+ }
|
||||
+
|
||||
+ fd = ensure_ep_open(s, devep, mode);
|
||||
+ if (fd < 0) {
|
||||
+ sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
||||
+ return USB_RET_NODEV;
|
||||
+ }
|
||||
+
|
||||
+ if (ioctl(fd, USB_SET_TIMEOUT, &timeout) < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("handle_data: failed to set timeout - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ }
|
||||
+
|
||||
+ if (shortpacket) {
|
||||
+ if (ioctl(fd, USB_SET_SHORT_XFER, &one) < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("handle_data: failed to set short xfer mode - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (pid == USB_TOKEN_IN)
|
||||
+ ret = read(fd, data, len);
|
||||
+ else
|
||||
+ ret = write(fd, data, len);
|
||||
+
|
||||
+ sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
||||
+
|
||||
+ if (ret < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("handle_data: error after %s data - %s\n",
|
||||
+ pid == USB_TOKEN_IN ? "reading" : "writing", strerror(errno));
|
||||
+#endif
|
||||
+ switch(errno) {
|
||||
+ case ETIMEDOUT:
|
||||
+ case EINTR:
|
||||
+ return USB_RET_NAK;
|
||||
+ default:
|
||||
+ return USB_RET_STALL;
|
||||
+ }
|
||||
+ } else {
|
||||
+ return ret;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+USBDevice *usb_host_device_open(const char *devname)
|
||||
+{
|
||||
+ struct usb_device_info bus_info, dev_info;
|
||||
+ USBHostDevice *dev;
|
||||
+ char ctlpath[PATH_MAX + 1];
|
||||
+ char buspath[PATH_MAX + 1];
|
||||
+ int bfd, dfd, bus, address, i;
|
||||
+ int ugendebug = UGEN_DEBUG_LEVEL;
|
||||
+
|
||||
+ if (usb_host_find_device(&bus, &address, devname) < 0)
|
||||
+ return NULL;
|
||||
+
|
||||
+ snprintf(buspath, PATH_MAX, "/dev/usb%d", bus);
|
||||
+
|
||||
+ bfd = open(buspath, O_RDWR);
|
||||
+ if (bfd < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("usb_host_device_open: failed to open usb bus - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ bus_info.udi_addr = address;
|
||||
+ if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("usb_host_device_open: failed to grab bus information - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+#if __FreeBSD__
|
||||
+ snprintf(ctlpath, PATH_MAX, "/dev/%s", bus_info.udi_devnames[0]);
|
||||
+#else
|
||||
+ snprintf(ctlpath, PATH_MAX, "/dev/%s.00", bus_info.udi_devnames[0]);
|
||||
+#endif
|
||||
+
|
||||
+ dfd = open(ctlpath, O_RDWR);
|
||||
+ if (dfd < 0) {
|
||||
+ dfd = open(ctlpath, O_RDONLY);
|
||||
+ if (dfd < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("usb_host_device_open: failed to open usb device %s - %s\n",
|
||||
+ ctlpath, strerror(errno));
|
||||
+#endif
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (dfd >= 0) {
|
||||
+ dev = qemu_mallocz(sizeof(USBHostDevice));
|
||||
+ if (!dev)
|
||||
+ goto fail;
|
||||
+ dev->devfd = dfd;
|
||||
+
|
||||
+ if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("usb_host_device_open: failed to grab device info - %s\n",
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ if (dev_info.udi_speed == 1)
|
||||
+ dev->dev.speed = USB_SPEED_LOW - 1;
|
||||
+ else
|
||||
+ dev->dev.speed = USB_SPEED_FULL - 1;
|
||||
+
|
||||
+ dev->dev.handle_packet = usb_generic_handle_packet;
|
||||
+
|
||||
+ dev->dev.handle_reset = usb_host_handle_reset;
|
||||
+ dev->dev.handle_control = usb_host_handle_control;
|
||||
+ dev->dev.handle_data = usb_host_handle_data;
|
||||
+
|
||||
+ strcpy(dev->devpath, "/dev/");
|
||||
+ strcat(dev->devpath, dev_info.udi_devnames[0]);
|
||||
+
|
||||
+ /* Mark the endpoints as not yet open */
|
||||
+ for (i = 0; i < USB_MAX_ENDPOINTS; i++)
|
||||
+ dev->ep_fd[i] = -1;
|
||||
+
|
||||
+ ioctl(dfd, USB_SETDEBUG, &ugendebug);
|
||||
+
|
||||
+ return (USBDevice *)dev;
|
||||
+ }
|
||||
+
|
||||
+fail:
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+void usb_host_device_close(USBDevice *opaque)
|
||||
+{
|
||||
+ USBHostDevice *s = (USBHostDevice *)opaque;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < USB_MAX_ENDPOINTS; i++)
|
||||
+ if (s->ep_fd[i] >= 0)
|
||||
+ close(s->ep_fd[i]);
|
||||
+
|
||||
+ if (s->devfd < 0)
|
||||
+ return;
|
||||
+
|
||||
+ close(s->devfd);
|
||||
+}
|
||||
+
|
||||
+static int usb_host_scan(void *opaque, USBScanFunc *func)
|
||||
+{
|
||||
+ struct usb_device_info bus_info;
|
||||
+ struct usb_device_info dev_info;
|
||||
+ uint16_t vendor_id, product_id, class_id, speed;
|
||||
+ int bfd, dfd, bus, address;
|
||||
+ char busbuf[20], devbuf[20], product_name[256];
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ for (bus = 0; bus < 10; bus++) {
|
||||
+
|
||||
+ snprintf(busbuf, sizeof(busbuf) - 1, "/dev/usb%d", bus);
|
||||
+ bfd = open(busbuf, O_RDWR);
|
||||
+ if (bfd < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ for (address = 1; address < 127; address++) {
|
||||
+
|
||||
+ bus_info.udi_addr = address;
|
||||
+ if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ /* only list devices that can be used by generic layer */
|
||||
+ if (strncmp(bus_info.udi_devnames[0], "ugen", 4) != 0)
|
||||
+ continue;
|
||||
+
|
||||
+#if __FreeBSD__
|
||||
+ snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s", bus_info.udi_devnames[0]);
|
||||
+#else
|
||||
+ snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s.00", bus_info.udi_devnames[0]);
|
||||
+#endif
|
||||
+
|
||||
+ dfd = open(devbuf, O_RDONLY);
|
||||
+ if (dfd < 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("usb_host_scan: couldn't open device %s - %s\n", devbuf,
|
||||
+ strerror(errno));
|
||||
+#endif
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0)
|
||||
+ printf("usb_host_scan: couldn't get device information for %s - %s\n",
|
||||
+ devbuf, strerror(errno));
|
||||
+
|
||||
+ // XXX: might need to fixup endianess of word values before copying over
|
||||
+
|
||||
+ vendor_id = dev_info.udi_vendorNo;
|
||||
+ product_id = dev_info.udi_productNo;
|
||||
+ class_id = dev_info.udi_class;
|
||||
+ speed = dev_info.udi_speed;
|
||||
+
|
||||
+ if (strncmp(dev_info.udi_product, "product", 7) != 0)
|
||||
+ strcpy(product_name, dev_info.udi_product);
|
||||
+ else
|
||||
+ product_name[0] = '\0';
|
||||
+
|
||||
+ ret = func(opaque, bus, address, class_id, vendor_id,
|
||||
+ product_id, product_name, speed);
|
||||
+
|
||||
+ close(dfd);
|
||||
+
|
||||
+ if (ret)
|
||||
+ goto the_end;
|
||||
+ }
|
||||
+
|
||||
+ close(bfd);
|
||||
+ }
|
||||
+
|
||||
+the_end:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+typedef struct FindDeviceState {
|
||||
+ int vendor_id;
|
||||
+ int product_id;
|
||||
+ int bus_num;
|
||||
+ int addr;
|
||||
+} FindDeviceState;
|
||||
+
|
||||
+static int usb_host_find_device_scan(void *opaque, int bus_num, int addr,
|
||||
+ int class_id,
|
||||
+ int vendor_id, int product_id,
|
||||
+ const char *product_name, int speed)
|
||||
+{
|
||||
+ FindDeviceState *s = opaque;
|
||||
+ if (vendor_id == s->vendor_id &&
|
||||
+ product_id == s->product_id) {
|
||||
+ s->bus_num = bus_num;
|
||||
+ s->addr = addr;
|
||||
+ return 1;
|
||||
+ } else {
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* the syntax is :
|
||||
+ 'bus.addr' (decimal numbers) or
|
||||
+ 'vendor_id:product_id' (hexa numbers) */
|
||||
+static int usb_host_find_device(int *pbus_num, int *paddr,
|
||||
+ const char *devname)
|
||||
+{
|
||||
+ const char *p;
|
||||
+ int ret;
|
||||
+ FindDeviceState fs;
|
||||
+
|
||||
+ p = strchr(devname, '.');
|
||||
+ if (p) {
|
||||
+ *pbus_num = strtoul(devname, NULL, 0);
|
||||
+ *paddr = strtoul(p + 1, NULL, 0);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ p = strchr(devname, ':');
|
||||
+ if (p) {
|
||||
+ fs.vendor_id = strtoul(devname, NULL, 16);
|
||||
+ fs.product_id = strtoul(p + 1, NULL, 16);
|
||||
+ ret = usb_host_scan(&fs, usb_host_find_device_scan);
|
||||
+ if (ret) {
|
||||
+ *pbus_num = fs.bus_num;
|
||||
+ *paddr = fs.addr;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+/**********************/
|
||||
+/* USB host device info */
|
||||
+
|
||||
+struct usb_class_info {
|
||||
+ int class;
|
||||
+ const char *class_name;
|
||||
+};
|
||||
+
|
||||
+static const struct usb_class_info usb_class_info[] = {
|
||||
+ { USB_CLASS_AUDIO, "Audio"},
|
||||
+ { USB_CLASS_COMM, "Communication"},
|
||||
+ { USB_CLASS_HID, "HID"},
|
||||
+ { USB_CLASS_HUB, "Hub" },
|
||||
+ { USB_CLASS_PHYSICAL, "Physical" },
|
||||
+ { USB_CLASS_PRINTER, "Printer" },
|
||||
+ { USB_CLASS_MASS_STORAGE, "Storage" },
|
||||
+ { USB_CLASS_CDC_DATA, "Data" },
|
||||
+ { USB_CLASS_APP_SPEC, "Application Specific" },
|
||||
+ { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
|
||||
+ { USB_CLASS_STILL_IMAGE, "Still Image" },
|
||||
+ { USB_CLASS_CSCID, "Smart Card" },
|
||||
+ { USB_CLASS_CONTENT_SEC, "Content Security" },
|
||||
+ { -1, NULL }
|
||||
+};
|
||||
+
|
||||
+static const char *usb_class_str(uint8_t class)
|
||||
+{
|
||||
+ const struct usb_class_info *p;
|
||||
+ for (p = usb_class_info; p->class != -1; p++) {
|
||||
+ if (p->class == class)
|
||||
+ break;
|
||||
+ }
|
||||
+ return p->class_name;
|
||||
+}
|
||||
+
|
||||
+void usb_info_device(int bus_num, int addr, int class_id,
|
||||
+ int vendor_id, int product_id,
|
||||
+ const char *product_name,
|
||||
+ int speed)
|
||||
+{
|
||||
+ const char *class_str, *speed_str;
|
||||
+
|
||||
+ switch(speed) {
|
||||
+ case USB_SPEED_LOW:
|
||||
+ speed_str = "1.5";
|
||||
+ break;
|
||||
+ case USB_SPEED_FULL:
|
||||
+ speed_str = "12";
|
||||
+ break;
|
||||
+ case USB_SPEED_HIGH:
|
||||
+ speed_str = "480";
|
||||
+ break;
|
||||
+ default:
|
||||
+ speed_str = "?";
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ term_printf(" Device %d.%d, speed %s Mb/s\n",
|
||||
+ bus_num, addr, speed_str);
|
||||
+ class_str = usb_class_str(class_id);
|
||||
+ if (class_str)
|
||||
+ term_printf(" %s:", class_str);
|
||||
+ else
|
||||
+ term_printf(" Class %02x:", class_id);
|
||||
+ term_printf(" USB device %04x:%04x", vendor_id, product_id);
|
||||
+ if (product_name[0] != '\0')
|
||||
+ term_printf(", %s", product_name);
|
||||
+ term_printf("\n");
|
||||
+}
|
||||
+
|
||||
+static int usb_host_info_device(void *opaque, int bus_num, int addr,
|
||||
+ int class_id,
|
||||
+ int vendor_id, int product_id,
|
||||
+ const char *product_name,
|
||||
+ int speed)
|
||||
+{
|
||||
+ usb_info_device(bus_num, addr, class_id, vendor_id, product_id,
|
||||
+ product_name, speed);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void usb_host_info(void)
|
||||
+{
|
||||
+ usb_host_scan(NULL, usb_host_info_device);
|
||||
+}
|
||||
Index: qemu/vl.c
|
||||
@@ -2820,10 +2822,12 @@
|
||||
dev = usb_host_device_open(p);
|
||||
if (!dev)
|
||||
return -1;
|
||||
+ dev->isproxied = 1;
|
||||
} else if (!strcmp(devname, "mouse")) {
|
||||
dev = usb_mouse_init();
|
||||
if (!dev)
|
||||
return -1;
|
||||
+ dev->isproxied = 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
@@ -2852,6 +2856,8 @@
|
||||
if (dev && dev->addr == addr)
|
||||
break;
|
||||
}
|
||||
+ if (dev && dev->isproxied)
|
||||
+ usb_host_device_close(dev);
|
||||
if (i == MAX_VM_USB_PORTS)
|
||||
return -1;
|
||||
usb_attach(vm_usb_ports[i], NULL);
|
||||
Index: qemu/hw/usb.h
|
||||
@@ -135,6 +146,8 @@
|
||||
int setup_state;
|
||||
int setup_len;
|
||||
int setup_index;
|
||||
+
|
||||
+ int isproxied;
|
||||
};
|
||||
|
||||
/* USB port on which a device can be connected */
|
||||
@@ -157,8 +170,9 @@
|
||||
/* usb-uhci.c */
|
||||
void usb_uhci_init(PCIBus *bus, USBPort **usb_ports);
|
||||
|
||||
-/* usb-linux.c */
|
||||
+/* host proxy functions */
|
||||
USBDevice *usb_host_device_open(const char *devname);
|
||||
+void usb_host_device_close(USBDevice *dev);
|
||||
void usb_host_info(void);
|
||||
|
||||
/* usb-hid.c */
|
||||
Index: qemu/usb-linux.c
|
||||
@@ -23,7 +23,6 @@
|
||||
*/
|
||||
#include "vl.h"
|
||||
|
||||
-#if defined(__linux__)
|
||||
#include <dirent.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/usbdevice_fs.h>
|
||||
@@ -255,6 +254,14 @@
|
||||
return q - buf;
|
||||
}
|
||||
|
||||
+void usb_host_device_close(USBDevice *opaque)
|
||||
+{
|
||||
+ USBHostDevice *s = (USBHostDevice *)opaque;
|
||||
+
|
||||
+ if (s->fd >= 0)
|
||||
+ close(s->fd);
|
||||
+}
|
||||
+
|
||||
static int usb_host_scan(void *opaque, USBScanFunc *func)
|
||||
{
|
||||
FILE *f;
|
||||
@@ -468,18 +475,3 @@
|
||||
{
|
||||
usb_host_scan(NULL, usb_host_info_device);
|
||||
}
|
||||
-
|
||||
-#else
|
||||
-
|
||||
-void usb_host_info(void)
|
||||
-{
|
||||
- term_printf("USB host devices not supported\n");
|
||||
-}
|
||||
-
|
||||
-/* XXX: modify configure to compile the right host driver */
|
||||
-USBDevice *usb_host_device_open(const char *devname)
|
||||
-{
|
||||
- return NULL;
|
||||
-}
|
||||
-
|
||||
-#endif
|
11
emulators/qemu/files/patch-dyngen.h
Normal file
11
emulators/qemu/files/patch-dyngen.h
Normal file
@ -0,0 +1,11 @@
|
||||
# 1.9
|
||||
Index: qemu/dyngen.h
|
||||
@@ -59,7 +59,7 @@
|
||||
{
|
||||
unsigned long p;
|
||||
|
||||
- p = start & ~(MIN_CACHE_LINE_SIZE - 1);
|
||||
+ start &= ~(MIN_CACHE_LINE_SIZE - 1);
|
||||
stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
|
||||
|
||||
for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
|
44
emulators/qemu/files/patch-hw-ne2000.c
Normal file
44
emulators/qemu/files/patch-hw-ne2000.c
Normal file
@ -0,0 +1,44 @@
|
||||
# 1.19
|
||||
Index: qemu/hw/ne2000.c
|
||||
@@ -648,6 +648,8 @@
|
||||
{
|
||||
NE2000State* s=(NE2000State*)opaque;
|
||||
|
||||
+ qemu_put_8s(f, &s->rxcr);
|
||||
+
|
||||
qemu_put_8s(f, &s->cmd);
|
||||
qemu_put_be32s(f, &s->start);
|
||||
qemu_put_be32s(f, &s->stop);
|
||||
@@ -672,8 +674,13 @@
|
||||
{
|
||||
NE2000State* s=(NE2000State*)opaque;
|
||||
|
||||
- if (version_id != 1)
|
||||
+ if (version_id == 2) {
|
||||
+ qemu_get_8s(f, &s->rxcr);
|
||||
+ } else if (version_id == 1) {
|
||||
+ s->rxcr = 0x0c;
|
||||
+ } else {
|
||||
return -EINVAL;
|
||||
+ }
|
||||
|
||||
qemu_get_8s(f, &s->cmd);
|
||||
qemu_get_be32s(f, &s->start);
|
||||
@@ -732,7 +739,7 @@
|
||||
s->macaddr[4],
|
||||
s->macaddr[5]);
|
||||
|
||||
- register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s);
|
||||
+ register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s);
|
||||
}
|
||||
|
||||
/***********************************************************/
|
||||
@@ -803,7 +810,7 @@
|
||||
s->macaddr[5]);
|
||||
|
||||
/* XXX: instance number ? */
|
||||
- register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s);
|
||||
+ register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s);
|
||||
register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load,
|
||||
&d->dev);
|
||||
}
|
28
emulators/qemu/files/patch-hw-usb-uhci.c
Normal file
28
emulators/qemu/files/patch-hw-usb-uhci.c
Normal file
@ -0,0 +1,28 @@
|
||||
# 1.6
|
||||
Index: qemu/hw/usb-uhci.c
|
||||
@@ -153,6 +153,7 @@
|
||||
switch(addr) {
|
||||
case 0x0c:
|
||||
val = s->sof_timing;
|
||||
+ break;
|
||||
default:
|
||||
val = 0xff;
|
||||
break;
|
||||
@@ -654,6 +655,7 @@
|
||||
pci_conf[0x0b] = 0x0c;
|
||||
pci_conf[0x0e] = 0x00; // header_type
|
||||
pci_conf[0x3d] = 4; // interrupt pin 3
|
||||
+ pci_conf[0x60] = 0x10; // release number
|
||||
|
||||
for(i = 0; i < NB_PORTS; i++) {
|
||||
port = &s->ports[i];
|
||||
@@ -666,6 +668,8 @@
|
||||
|
||||
uhci_reset(s);
|
||||
|
||||
- pci_register_io_region(&s->dev, 0, 0x20,
|
||||
+ /* Use region 4 for consistency with real hardware. BSD guests seem
|
||||
+ to rely on this. */
|
||||
+ pci_register_io_region(&s->dev, 4, 0x20,
|
||||
PCI_ADDRESS_SPACE_IO, uhci_map);
|
||||
}
|
11
emulators/qemu/files/patch-hw-usb.c
Normal file
11
emulators/qemu/files/patch-hw-usb.c
Normal file
@ -0,0 +1,11 @@
|
||||
# 1.4
|
||||
Index: qemu/hw/usb.c
|
||||
@@ -183,7 +183,7 @@
|
||||
|
||||
q = buf;
|
||||
len = strlen(str);
|
||||
- *q++ = 2 * len + 1;
|
||||
+ *q++ = 2 * len + 2;
|
||||
*q++ = 3;
|
||||
for(i = 0; i < len; i++) {
|
||||
*q++ = str[i];
|
29
emulators/qemu/files/patch-sdl.c
Normal file
29
emulators/qemu/files/patch-sdl.c
Normal file
@ -0,0 +1,29 @@
|
||||
# 1.24
|
||||
Index: qemu/sdl.c
|
||||
@@ -404,6 +404,7 @@
|
||||
mod_state = (ev->key.keysym.mod & gui_grab_code);
|
||||
if (!mod_state) {
|
||||
if (gui_key_modifier_pressed) {
|
||||
+ gui_key_modifier_pressed = 0;
|
||||
if (gui_keysym == 0) {
|
||||
/* exit/enter grab if pressing Ctrl-Alt */
|
||||
if (!gui_grab)
|
||||
@@ -415,7 +416,6 @@
|
||||
reset_keys();
|
||||
break;
|
||||
}
|
||||
- gui_key_modifier_pressed = 0;
|
||||
gui_keysym = 0;
|
||||
}
|
||||
}
|
||||
@@ -456,8 +456,8 @@
|
||||
}
|
||||
break;
|
||||
case SDL_ACTIVEEVENT:
|
||||
- if (gui_grab && (ev->active.gain & SDL_ACTIVEEVENTMASK) == 0 &&
|
||||
- !gui_fullscreen_initial_grab) {
|
||||
+ if (gui_grab && ev->active.state == SDL_APPINPUTFOCUS &&
|
||||
+ !ev->active.gain && !gui_fullscreen_initial_grab) {
|
||||
sdl_grab_end();
|
||||
}
|
||||
break;
|
18
emulators/qemu/files/patch-slirp-socket.c
Normal file
18
emulators/qemu/files/patch-slirp-socket.c
Normal file
@ -0,0 +1,18 @@
|
||||
# 1.6
|
||||
Index: qemu/slirp/socket.c
|
||||
@@ -573,6 +573,7 @@
|
||||
addr.sin_port = port;
|
||||
|
||||
if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||
|
||||
+ (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
|
||||
(bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
|
||||
(listen(s,1) < 0)) {
|
||||
int tmperrno = errno; /* Don't clobber the real reason we failed */
|
||||
@@ -587,7 +588,6 @@
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
- setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
|
||||
setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
|
||||
|
||||
getsockname(s,(struct sockaddr *)&addr,&addrlen);
|
29
emulators/qemu/files/patch-target-i386-translate.c
Normal file
29
emulators/qemu/files/patch-target-i386-translate.c
Normal file
@ -0,0 +1,29 @@
|
||||
# 1.53
|
||||
Index: qemu/target-i386/translate.c
|
||||
@@ -5803,14 +5803,24 @@
|
||||
op = (modrm >> 3) & 7;
|
||||
switch(op) {
|
||||
case 0: /* fxsave */
|
||||
- if (mod == 3 || !(s->cpuid_features & CPUID_FXSR))
|
||||
+ if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
|
||||
+ (s->flags & HF_EM_MASK))
|
||||
goto illegal_op;
|
||||
+ if (s->flags & HF_TS_MASK) {
|
||||
+ gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
|
||||
+ break;
|
||||
+ }
|
||||
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
|
||||
gen_op_fxsave_A0((s->dflag == 2));
|
||||
break;
|
||||
case 1: /* fxrstor */
|
||||
- if (mod == 3 || !(s->cpuid_features & CPUID_FXSR))
|
||||
+ if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
|
||||
+ (s->flags & HF_EM_MASK))
|
||||
goto illegal_op;
|
||||
+ if (s->flags & HF_TS_MASK) {
|
||||
+ gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
|
||||
+ break;
|
||||
+ }
|
||||
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
|
||||
gen_op_fxrstor_A0((s->dflag == 2));
|
||||
break;
|
10
emulators/qemu/files/patch-usb-hchalt
Normal file
10
emulators/qemu/files/patch-usb-hchalt
Normal file
@ -0,0 +1,10 @@
|
||||
Index: qemu/hw/usb-uhci.c
|
||||
@@ -527,6 +532,8 @@
|
||||
|
||||
if (!(s->cmd & UHCI_CMD_RS)) {
|
||||
qemu_del_timer(s->frame_timer);
|
||||
+ /* set hchalted bit in status - UHCI11D 2.1.2 */
|
||||
+ s->status |= UHCI_STS_HCHALTED;
|
||||
return;
|
||||
}
|
||||
frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
|
87
emulators/qemu/files/patch-usb-hubfixups
Normal file
87
emulators/qemu/files/patch-usb-hubfixups
Normal file
@ -0,0 +1,87 @@
|
||||
Index: qemu/hw/usb.c
|
||||
@@ -330,9 +330,9 @@
|
||||
0x0a, /* u16 wHubCharacteristics; */
|
||||
0x00, /* (per-port OC, no power switching) */
|
||||
0x01, /* u8 bPwrOn2pwrGood; 2ms */
|
||||
- 0x00, /* u8 bHubContrCurrent; 0 mA */
|
||||
- 0x00, /* u8 DeviceRemovable; *** 7 Ports max *** */
|
||||
- 0xff /* u8 PortPwrCtrlMask; *** 7 ports max *** */
|
||||
+ 0x00 /* u8 bHubContrCurrent; 0 mA */
|
||||
+
|
||||
+ /* DeviceRemovable and PortPwrCtrlMask patched in later */
|
||||
};
|
||||
|
||||
static void usb_hub_attach(USBPort *port1, USBDevice *dev)
|
||||
@@ -391,6 +391,12 @@
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
+ case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
|
||||
+ if (value == 0 && index != 0x81) { /* clear ep halt */
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ ret = 0;
|
||||
+ break;
|
||||
case DeviceOutRequest | USB_REQ_SET_FEATURE:
|
||||
if (value == USB_DEVICE_REMOTE_WAKEUP) {
|
||||
dev->remote_wakeup = 1;
|
||||
@@ -408,6 +414,11 @@
|
||||
case USB_DT_DEVICE:
|
||||
memcpy(data, qemu_hub_dev_descriptor,
|
||||
sizeof(qemu_hub_dev_descriptor));
|
||||
+
|
||||
+ /* status change endpoint size based on number
|
||||
+ * of ports */
|
||||
+ data[22] = (s->nb_ports + 1 + 7) / 8;
|
||||
+
|
||||
ret = sizeof(qemu_hub_dev_descriptor);
|
||||
break;
|
||||
case USB_DT_CONFIG:
|
||||
@@ -558,11 +569,29 @@
|
||||
}
|
||||
break;
|
||||
case GetHubDescriptor:
|
||||
- memcpy(data, qemu_hub_hub_descriptor,
|
||||
- sizeof(qemu_hub_hub_descriptor));
|
||||
- data[2] = s->nb_ports;
|
||||
- ret = sizeof(qemu_hub_hub_descriptor);
|
||||
- break;
|
||||
+ {
|
||||
+ unsigned int n, limit, var_hub_size = 0;
|
||||
+ memcpy(data, qemu_hub_hub_descriptor,
|
||||
+ sizeof(qemu_hub_hub_descriptor));
|
||||
+ data[2] = s->nb_ports;
|
||||
+
|
||||
+ /* fill DeviceRemovable bits */
|
||||
+ limit = ((s->nb_ports + 1 + 7) / 8) + 7;
|
||||
+ for (n = 7; n < limit; n++) {
|
||||
+ data[n] = 0x00;
|
||||
+ var_hub_size++;
|
||||
+ }
|
||||
+
|
||||
+ /* fill PortPwrCtrlMask bits */
|
||||
+ limit = limit + ((s->nb_ports + 7) / 8);
|
||||
+ for (;n < limit; n++) {
|
||||
+ data[n] = 0xff;
|
||||
+ var_hub_size++;
|
||||
+ }
|
||||
+
|
||||
+ ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size;
|
||||
+ break;
|
||||
+ }
|
||||
default:
|
||||
fail:
|
||||
ret = USB_RET_STALL;
|
||||
@@ -584,8 +613,11 @@
|
||||
unsigned int status;
|
||||
int i, n;
|
||||
n = (s->nb_ports + 1 + 7) / 8;
|
||||
- if (n > len)
|
||||
+ if (len == 1) { /* FreeBSD workaround */
|
||||
+ n = 1;
|
||||
+ } else if (n > len) {
|
||||
return USB_RET_BABBLE;
|
||||
+ }
|
||||
status = 0;
|
||||
for(i = 0; i < s->nb_ports; i++) {
|
||||
port = &s->ports[i];
|
9
emulators/qemu/files/patch-vl.c-nographic
Normal file
9
emulators/qemu/files/patch-vl.c-nographic
Normal file
@ -0,0 +1,9 @@
|
||||
Index: qemu/vl.c
|
||||
@@ -4668,6 +4668,7 @@
|
||||
case QEMU_OPTION_nographic:
|
||||
pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
|
||||
pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio");
|
||||
+ pstrcpy(parallel_devices[0], sizeof(parallel_devices[0]), "null");
|
||||
nographic = 1;
|
||||
break;
|
||||
case QEMU_OPTION_kernel:
|
@ -33,4 +33,16 @@ in this message: http://docs.freebsd.org/cgi/mid.cgi?200510131428.21211.jkim
|
||||
(not included in the port since the used VIA VT86C926 PCI ID does not
|
||||
really match the emulated nic exactly, it just `happens' to work with
|
||||
6.0-RC1's driver.)
|
||||
- if you want to use usb devices connected to the host in the guest
|
||||
(usb_add host:... monitor command) you need to make sure the host isn't
|
||||
claiming them, e.g. for umass devices (like memory sticks or external
|
||||
harddrives) make sure umass isn't in the kernel (you can then still load it
|
||||
as a kld when needed), also unless you are running qemu as root you then
|
||||
need to fix permissions for /dev/ugen* device nodes: if you are on 5.x or
|
||||
later (devfs) put a rule in /etc/devfs.rules, activate it in /etc/rc.conf
|
||||
and run /etc/rc.d/devfs restart. example devfs.rules:
|
||||
[ugen_ruleset=20]
|
||||
add path 'ugen*' mode 660 group operator
|
||||
corresponding rc.conf line:
|
||||
devfs_system_ruleset="ugen_ruleset"
|
||||
====
|
||||
|
Loading…
Reference in New Issue
Block a user