--- qemu-0.13.0/block/vvfat.c.orig 2010-10-15 22:56:09.000000000 +0200 +++ qemu-0.13.0/block/vvfat.c 2010-11-08 15:08:55.634689200 +0100 @@ -816,7 +816,13 @@ static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num) { - return (sector_num-s->faked_sectors)/s->sectors_per_cluster; + uint32_t ret; + + if (sector_num < s->faked_sectors) + ret = 0; + else + ret = (sector_num-s->faked_sectors)/s->sectors_per_cluster; + return ret; } static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num) --- qemu-0.13.0/configure.orig 2010-10-15 22:56:09.000000000 +0200 +++ qemu-0.13.0/configure 2010-11-09 18:06:57.086639800 +0100 @@ -333,13 +333,15 @@ CYGWIN*) mingw32="yes" QEMU_CFLAGS="-mno-cygwin $QEMU_CFLAGS" - audio_possible_drivers="winwave sdl" + audio_possible_drivers="winwave dsound sdl fmod" audio_drv_list="winwave" + usb="generic" ;; MINGW32*) mingw32="yes" audio_possible_drivers="winwave dsound sdl fmod" audio_drv_list="winwave" + usb="generic" ;; GNU/kFreeBSD) bsd="yes" @@ -2436,6 +2438,8 @@ fi # USB host support +LIBUSB_LIBS="" +LIBUSB_CFLAGS="" case "$usb" in linux) echo "HOST_USB=linux" >> $config_host_mak @@ -2443,10 +2447,34 @@ bsd) echo "HOST_USB=bsd" >> $config_host_mak ;; +generic) + if `libusb-config --libs 1>&2 2> /dev/null`; then + LIBUSB_LIBS=`libusb-config --libs 2> /dev/null` + LIBUSB_CFLAGS=`libusb-config --cflags 2> /dev/null` + else + LIBUSB_LIBS=-lusb + fi + + # libusb probe + cat > $TMPC << EOF +#include +int main( void ) { usb_set_debug(0); return 0; } +EOF + + if ! $cc -o $TMPE $TMPC $LIBUSB_LIBS $LIBUSB_CFLAGS $LDFLAGS 2> /dev/null ; then + usb="stub" + echo "HOST_USB=stub" >> $config_host_mak + LIBUSB_LIBS="" + LIBUSB_CFLAGS="" + else + echo "HOST_USB=libusb" >> $config_host_mak + fi +;; *) echo "HOST_USB=stub" >> $config_host_mak ;; esac +echo "LIBUSB_LIBS=$LIBUSB_LIBS" >> $config_host_mak echo "TOOLS=$tools" >> $config_host_mak echo "ROMS=$roms" >> $config_host_mak --- qemu-0.13.0/Makefile.target.orig 2010-10-15 22:56:09.000000000 +0200 +++ qemu-0.13.0/Makefile.target 2010-11-08 15:08:55.650314200 +0100 @@ -186,6 +186,10 @@ # USB layer obj-$(CONFIG_USB_OHCI) += usb-ohci.o +ifeq ($(HOST_USB), libusb) +LIBS += $(LIBUSB_LIBS) +endif + # PCI network cards obj-y += rtl8139.o obj-y += e1000.o --- qemu-0.13.0/osdep.c.orig 2010-10-15 22:56:09.000000000 +0200 +++ qemu-0.13.0/osdep.c 2010-11-08 15:08:55.650314200 +0100 @@ -137,9 +137,10 @@ fd = qemu_open(filename, O_RDWR | O_CREAT, 0600); if (fd == -1) return -1; - +#ifndef __CYGWIN__ if (lockf(fd, F_TLOCK, 0) == -1) return -1; +#endif len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid()); if (write(fd, buffer, len) != len) --- qemu-0.13.0/qemu-char.c.orig 2010-11-08 15:42:27.869064200 +0100 +++ qemu-0.13.0/qemu-char.c 2010-11-08 17:47:47.119394200 +0100 @@ -506,6 +506,12 @@ return len1 - len; } +static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out) +{ + /* NOT AVAILABLE */ + return NULL; +} + #else static int unix_write(int fd, const uint8_t *buf, int len1) @@ -532,6 +538,7 @@ { return unix_write(fd, buf, len1); } + #endif /* !_WIN32 */ #ifndef _WIN32 --- qemu-0.13.0/qemu_socket.h.orig 2010-10-15 22:56:09.000000000 +0200 +++ qemu-0.13.0/qemu_socket.h 2010-11-08 15:08:55.650314200 +0100 @@ -12,6 +12,7 @@ #define EWOULDBLOCK WSAEWOULDBLOCK #define EINTR WSAEINTR #define EINPROGRESS WSAEINPROGRESS +#define EADDRNOTAVAIL WSAEADDRNOTAVAIL int inet_aton(const char *cp, struct in_addr *ia); --- qemu-0.13.0/ui/sdl.c.orig 2010-10-15 22:56:09.000000000 +0200 +++ qemu-0.13.0/ui/sdl.c 2010-11-08 15:08:55.665939200 +0100 @@ -829,9 +829,11 @@ if (no_frame) gui_noframe = 1; +#ifndef WIN32 if (!full_screen) { setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0); } +#endif flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE; if (SDL_Init (flags)) { --- qemu-0.13.0/ui/vnc-enc-tight.c.orig 2010-10-15 22:56:09.000000000 +0200 +++ qemu-0.13.0/ui/vnc-enc-tight.c 2010-11-08 15:08:55.665939200 +0100 @@ -44,6 +44,8 @@ #include "vnc-enc-tight.h" #include "vnc-palette.h" +typedef unsigned int uint; + /* Compression level stuff. The following array contains various encoder parameters for each of 10 compression levels (0..9). Last three parameters correspond to JPEG quality levels (0..9). */ --- qemu-0.13.0/usb-libusb.c.orig 2010-11-08 15:08:55.681564200 +0100 +++ qemu-0.13.0/usb-libusb.c 2010-11-08 15:08:55.681564200 +0100 @@ -0,0 +1,552 @@ +/* + * Generic libusb host USB redirector + * + * Copyright (c) 2006 Lonnie Mendez + * Code adapted from and modified from usb-linux.c + * + * 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 "qemu-common.h" +#include "hw/usb.h" +#include "monitor.h" + +#include +#if !defined(ETIMEDOUT) && defined(_WIN32) +#define ETIMEDOUT 116 +#endif + + +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, struct usb_device **device); +static void usb_info_device(int bus_num, int addr, int class_id, + int vendor_id, int product_id, + const char *product_name, + int speed); + +//#define DEBUG +/* should be adjustable for interrupt endpoints */ +#define TRANS_TIMEOUT 50 + +typedef struct USBHostDevice { + USBDevice dev; + int num_interfaces; + struct usb_dev_handle *udev; +} USBHostDevice; +static USBHostDevice *hostdev_find(int bus_num, int addr); +static void usb_host_handle_reset(USBDevice *dev) +{ +#ifdef DEBUG + printf("usb_host_handle_reset called\n"); +#endif + +#if 0 + USBHostDevice *s = (USBHostDevice *)dev; + /* USBDEVFS_RESET, but not the first time as it has already be + * done by the host OS - usb_reset() - must reopen handle + */ + usb_reset(s->udev); +#endif +} + +static int usb_host_handle_control(USBDevice *dev, + int request, + int value, + int index, + int length, + uint8_t *data) +{ + USBHostDevice *s = (USBHostDevice *)dev; + int ret; + + if (request == (DeviceOutRequest | USB_REQ_SET_ADDRESS)) { + /* specific SET_ADDRESS support */ + dev->addr = value; + return 0; + } else { + ret = usb_control_msg(s->udev, request >> 8, request & 0xff, value, index, + data, length, TRANS_TIMEOUT); + if (ret < 0) { +#ifdef DEBUG + printf("handle_control: ret is %d - %s\n", ret, usb_strerror()); +#endif + // TODO: figure out how usb_clear_halt()/etc fit in for different host OS + switch(ret) { + case -ETIMEDOUT: + return USB_RET_NAK; + case -EIO: + default: + return USB_RET_STALL; + } + } else { + return ret; + } + } +} + +static int usb_host_handle_data(USBDevice *dev, USBPacket *p) +{ + USBHostDevice *s = (USBHostDevice *)dev; + int ret = 0; +#ifdef DEBUG + int i; +#endif + uint8_t devep = p->devep; + int pid = p->pid; + uint8_t *data = p->data; + int len = p->len; + + /* XXX: optimize and handle all data types by looking at the + config descriptor */ + if (pid == USB_TOKEN_IN) + devep |= 0x80; + +#ifdef DEBUG + if (pid != USB_TOKEN_IN) { + printf("writing(%d bytes - to ep %x):\n", len, devep); + for (i = 0; i < len; i++) + printf("%x ", data[i]); + printf("\n"); + } +#endif + + /* most libusb backends channel interrupt packets to a bulk transfer + * handler, with the exception of bsd.c */ + switch(pid) { + case USB_TOKEN_IN: + ret = usb_bulk_read(s->udev, devep, data, len, TRANS_TIMEOUT); + break; + case USB_TOKEN_OUT: + ret = usb_bulk_write(s->udev, devep, data, len, TRANS_TIMEOUT); + break; + } + +#ifdef DEBUG + if (pid == USB_TOKEN_IN) { + printf("reading(%d bytes - from ep %x):\n", ret, devep); + for (i = 0; i < ret; i++) + printf("%x ", data[i]); + printf("\n"); + } +#endif + + if (ret < 0) { +#ifdef DEBUG + printf("handle_data: ret is %d - %s\n", ret, usb_strerror()); +#endif + // TODO: figure out how usb_clear_halt()/etc fit in for different host OS + switch(ret) { + case -ETIMEDOUT: + return USB_RET_NAK; + case -EIO: /* stall condition on win32 - same for mac os x? */ + usb_clear_halt(s->udev, devep); + case -EPIPE: + default: + return USB_RET_STALL; + } + } else { + return ret; + } +} + +static void usb_host_handle_destroy(USBDevice *dev) +{ + USBHostDevice *s = (USBHostDevice *)dev; + int i; + + if (!s) + return; + + for (i = 0; i < s->num_interfaces; i++) + usb_release_interface(s->udev, i); + usb_close(s->udev); + s->udev = NULL; + qemu_free(s); +} + +/* XXX: exclude high speed devices or implement EHCI */ +USBDevice *usb_host_device_open(const char *devname) +{ + USBHostDevice *dev; + USBDeviceInfo *inf; + struct usb_dev_handle *udev = NULL; + struct usb_device *device = NULL; + struct usb_config_descriptor config_desc; + int config_descr_len, nb_interfaces; + int bus_num, addr, interface, ret; + char product_name[32] ; + + if ((ret = usb_host_find_device(&bus_num, &addr, devname, &device)) < 0) + return NULL; + + if (!device) + return NULL; + + udev = usb_open(device); + + if (!udev) { +#ifdef DEBUG + printf("couldn't open usb device at %d.%d\n", bus_num, addr); +#endif + return NULL; + } + + /* read the 1st config descriptor */ + config_descr_len = usb_get_descriptor(udev, 2, 0, &config_desc, sizeof(config_desc)); + if (config_descr_len <= 0) { + printf("read config_desc: %s", usb_strerror()); + goto fail; + } + + if (config_descr_len > sizeof(config_desc)) { + printf("config_desc size mismatch\n"); + goto fail; + } + + nb_interfaces = config_desc.bNumInterfaces; + usb_set_configuration(udev, config_desc.bConfigurationValue); + + for (interface = 0; interface < nb_interfaces; interface++) { + /* might as well */ +#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP + usb_detach_kernel_driver_np(udev, interface); +#endif + + ret = usb_claim_interface(udev, interface); + + if (ret < 0) { + printf("usb_claim_interface: %s", usb_strerror()); + fail: + if (udev) + usb_close(udev); + return NULL; + } + } + +#ifdef DEBUG + printf("host USB device %d.%d grabbed\n", bus_num, addr); +#endif + + dev = qemu_mallocz(sizeof(USBHostDevice)); + if (!dev) + goto fail; + + /* not accurate - might be better off reporting only low/full */ + switch (device->descriptor.bcdUSB) { + case 0x0110: + dev->dev.speed = USB_SPEED_FULL; + break; + case 0x0200: + dev->dev.speed = USB_SPEED_HIGH; + break; + case 0x0100: + dev->dev.speed = USB_SPEED_LOW; + break; + default: + dev->dev.speed = USB_SPEED_FULL; + } + + dev->udev = udev; + dev->num_interfaces = nb_interfaces; + + + inf = qemu_mallocz(sizeof(USBDeviceInfo)); + if (!dev) + goto fail; + dev->dev.info = inf; + + inf->handle_packet = usb_generic_handle_packet; + + inf->handle_reset = usb_host_handle_reset; + inf->handle_control = usb_host_handle_control; + inf->handle_data = usb_host_handle_data; + inf->handle_destroy = usb_host_handle_destroy; + + /* get product string if available */ + usb_get_string_simple(udev, device->descriptor.iProduct, + product_name, sizeof(product_name)); + + inf->usbdevice_name = qemu_mallocz(64); /* FIXME */ + if (!inf->usbdevice_name) + goto fail; + + if (product_name[0] == '\0') + snprintf(inf->usbdevice_name, sizeof(inf->usbdevice_name), + "host:%s", devname); + else + pstrcpy(inf->usbdevice_name, sizeof(inf->usbdevice_name), + product_name); + + return (USBDevice *)dev; +} + +int usb_host_device_close(const char *devname) +{ + USBHostDevice *dev; + struct usb_device *device = NULL; + int bus_num, addr, ret; + + if ((ret = usb_host_find_device(&bus_num, &addr, devname, &device)) < 0) + return -1; + + if (!device) + return -1; + dev = hostdev_find(bus_num, addr); + if (dev) { + usb_device_delete_addr(0, dev->dev.addr); + return 0; + } + + return -1; +} +static USBHostDevice *hostdev_find(int bus_num, int addr) +{ + return NULL; +} + +static int usb_host_scan(void *opaque, struct usb_device **device, + USBScanFunc *func) +{ + struct usb_bus *busses, *bus; + struct usb_dev_handle *udev; + struct usb_device *dev; + uint16_t vendor_id, product_id, class_id, speed; + char product_name[256]; + int ret = 0; + +#ifdef DEBUG + usb_set_debug(255); +#else + usb_set_debug(0); +#endif + + usb_init(); + usb_find_busses(); + usb_find_devices(); + + busses = usb_get_busses(); + + for (bus = busses; bus; bus = bus->next) { + for (dev = bus->devices; dev; dev = dev->next) { + vendor_id = dev->descriptor.idVendor; + product_id = dev->descriptor.idProduct; + + /* only find devices - not root hubs */ + if (vendor_id == 0x0000 && product_id == 0x0000) + continue; + + udev = usb_open(dev); + if (!udev) + continue; + + class_id = dev->descriptor.bDeviceClass; + + /* not accurate - might be better off reporting only low/full */ + switch (dev->descriptor.bcdUSB) { + case 0x0110: + speed = USB_SPEED_FULL; + break; + case 0x0200: + speed = USB_SPEED_HIGH; + break; + case 0x0100: + speed = USB_SPEED_LOW; + break; + default: + speed = USB_SPEED_FULL; + } + + ret = usb_get_string_simple(udev, dev->descriptor.iProduct, + product_name, sizeof(product_name)); + if (ret < 0) + product_name[0] = '\0'; + + ret = func(opaque, bus->location, dev->devnum, class_id, vendor_id, + product_id, product_name, speed); + + usb_close(udev); + + if (ret) { + *device = dev; + goto the_end; + } + } + } + +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 (s->vendor_id == -1 && + s->product_id == -1 && + bus_num == s->bus_num && + addr == s->addr) { + s->vendor_id = vendor_id; + s->product_id = product_id; + return 1; + } else 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, struct usb_device **device) +{ + const char *p; + int ret; + FindDeviceState fs; + + p = strchr(devname, '.'); + if (p) { + fs.vendor_id = -1; + fs.product_id = -1; + fs.bus_num = strtoul(devname, NULL, 0); + fs.addr = strtoul(p + 1, NULL, 0); + ret = usb_host_scan(&fs, device, usb_host_find_device_scan); + if (ret) { + *pbus_num = fs.bus_num; + *paddr = fs.addr; + 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, device, 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; + Monitor *mon = cur_mon; + + 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; + } + + monitor_printf(mon," Device %d.%d, speed %s Mb/s\n", + bus_num, addr, speed_str); + class_str = usb_class_str(class_id); + if (class_str) + monitor_printf(mon," %s:", class_str); + else + monitor_printf(mon," Class %02x:", class_id); + monitor_printf(mon," USB device %04x:%04x", vendor_id, product_id); + if (product_name[0] != '\0') + monitor_printf(mon,", %s", product_name); + monitor_printf(mon,"\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(Monitor *mon) +{ + usb_host_scan(NULL, NULL, usb_host_info_device); +}