View | Details | Raw Unified | Return to bug 94654
Collapse All | Expand All

(-)Makefile (-1 / +1 lines)
Lines 7-13 Link Here
7
7
8
PORTNAME=	qemu
8
PORTNAME=	qemu
9
PORTVERSION=	0.8.0
9
PORTVERSION=	0.8.0
10
PORTREVISION=	3
10
PORTREVISION=	4
11
CATEGORIES=	emulators
11
CATEGORIES=	emulators
12
MASTER_SITES=	http://www.qemu.org/:release \
12
MASTER_SITES=	http://www.qemu.org/:release \
13
		http://people.fruitsalad.org/nox/qemu/:snapshot \
13
		http://people.fruitsalad.org/nox/qemu/:snapshot \
(-)pkg-message (+12 lines)
Lines 33-36 Link Here
33
(not included in the port since the used VIA VT86C926 PCI ID does not
33
(not included in the port since the used VIA VT86C926 PCI ID does not
34
really match the emulated nic exactly, it just `happens' to work with
34
really match the emulated nic exactly, it just `happens' to work with
35
6.0-RC1's driver.)
35
6.0-RC1's driver.)
36
- if you want to use usb devices connected to the host in the guest
37
(usb_add host:... monitor command) you need to make sure the host isn't
38
claiming them, e.g. for umass devices (like memory sticks or external
39
harddrives) make sure umass isn't in the kernel (you can then still load it
40
as a kld when needed), also unless you are running qemu as root you then
41
need to fix permissions for /dev/ugen* device nodes: if you are on 5.x or
42
later (devfs) put a rule in /etc/devfs.rules, activate it in /etc/rc.conf
43
and run /etc/rc.d/devfs restart.  example devfs.rules:
44
	[ugen_ruleset=20]
45
	add path 'ugen*' mode 660 group operator
46
corresponding rc.conf line:
47
	devfs_system_ruleset="ugen_ruleset"
36
====
48
====
(-)files/patch-bsdusb.patch (+741 lines)
Line 0 Link Here
1
Index: qemu/configure
2
@@ -122,6 +122,7 @@
3
 *)
4
 oss="yes"
5
 linux="yes"
6
+usb="linux"
7
 if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
8
     kqemu="yes"
9
 fi
10
@@ -131,6 +132,7 @@
11
 if [ "$bsd" = "yes" ] ; then
12
   if [ ! "$darwin" = "yes" ] ; then
13
     make="gmake"
14
+    usb="bsd"
15
   fi
16
 fi
17
 
18
@@ -656,6 +675,19 @@
19
   echo "#define _BSD 1" >> $config_h
20
 fi
21
 
22
+# USB host support
23
+case "$usb" in
24
+linux)
25
+  echo "HOST_USB=linux" >> $conig_mak
26
+;;
27
+bsd)
28
+  echo "HOST_USB=bsd" >> $config_mak
29
+;;
30
+*)
31
+  echo "HOST_USB=stub" >> $config_mak
32
+;;
33
+esac
34
+
35
 for target in $target_list; do
36
 
37
 target_dir="$target"
38
Index: qemu/Makefile.target
39
@@ -303,7 +303,7 @@
40
 endif
41
 
42
 # USB layer
43
-VL_OBJS+= usb.o usb-uhci.o usb-linux.o usb-hid.o
44
+VL_OBJS+= usb.o usb-uhci.o usb-$(HOST_USB).o usb-hid.o
45
 
46
 ifeq ($(TARGET_BASE_ARCH), i386)
47
 # Hardware support
48
Index: qemu/usb-stub.c
49
@@ -0,0 +1,11 @@
50
+#include "vl.h"
51
+
52
+void usb_host_info(void)
53
+{
54
+    term_printf("USB host devices not supported\n");
55
+}
56
+
57
+USBDevice *usb_host_device_open(const char *devname)
58
+{
59
+    return NULL;
60
+}
61
Index: qemu/usb-bsd.c
62
@@ -0,0 +1,592 @@
63
+/*
64
+ * BSD host USB redirector
65
+ *
66
+ * Copyright (c) 2005 Lonnie Mendez
67
+ * Portions of code and concepts borrowed from
68
+ * usb-linux.c and libusb's bsd.c and are copyright their respective owners.
69
+ *
70
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
71
+ * of this software and associated documentation files (the "Software"), to deal
72
+ * in the Software without restriction, including without limitation the rights
73
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
74
+ * copies of the Software, and to permit persons to whom the Software is
75
+ * furnished to do so, subject to the following conditions:
76
+ *
77
+ * The above copyright notice and this permission notice shall be included in
78
+ * all copies or substantial portions of the Software.
79
+ *
80
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
81
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
82
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
83
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
84
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
85
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
86
+ * THE SOFTWARE.
87
+ */
88
+
89
+#include "vl.h"
90
+
91
+/* usb.h declares these */
92
+#undef USB_SPEED_HIGH
93
+#undef USB_SPEED_FULL
94
+#undef USB_SPEED_LOW
95
+
96
+#include <sys/ioctl.h>
97
+#include <dev/usb/usb.h>
98
+#include <signal.h>
99
+
100
+/* This value has maximum potential at 16.
101
+ * You should also set hw.usb.debug to gain
102
+ * more detailed view.
103
+ */
104
+//#define DEBUG
105
+#define UGEN_DEBUG_LEVEL 0
106
+
107
+
108
+typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id,
109
+                        int vendor_id, int product_id,
110
+                        const char *product_name, int speed);
111
+static int usb_host_find_device(int *pbus_num, int *paddr,
112
+                                const char *devname);
113
+
114
+typedef struct USBHostDevice {
115
+    USBDevice dev;
116
+    int ep_fd[USB_MAX_ENDPOINTS];
117
+    int devfd;
118
+    char devpath[32];
119
+} USBHostDevice;
120
+
121
+
122
+static int ensure_ep_open(USBHostDevice *dev, int ep, int mode)
123
+{
124
+    char buf[32];
125
+    int fd;
126
+
127
+    /* Get the address for this endpoint */
128
+    ep = UE_GET_ADDR(ep);
129
+
130
+    if (dev->ep_fd[ep] < 0) {
131
+#if __FreeBSD__
132
+        snprintf(buf, sizeof(buf) - 1, "%s.%d", dev->devpath, ep);
133
+#else
134
+        snprintf(buf, sizeof(buf) - 1, "%s.%02d", dev->devpath, ep);
135
+#endif
136
+        /* Try to open it O_RDWR first for those devices which have in and out
137
+         * endpoints with the same address (eg 0x02 and 0x82)
138
+         */
139
+        fd = open(buf, O_RDWR);
140
+        if (fd < 0 && errno == ENXIO)
141
+            fd = open(buf, mode);
142
+        if (fd < 0) {
143
+#ifdef DEBUG
144
+            printf("ensure_ep_open: failed to open device endpoint %s: %s\n",
145
+                   buf, strerror(errno));
146
+#endif
147
+        }
148
+        dev->ep_fd[ep] = fd;
149
+    }
150
+
151
+    return dev->ep_fd[ep];
152
+}
153
+
154
+static void ensure_eps_closed(USBHostDevice *dev)
155
+{
156
+    int epnum = 1;
157
+
158
+    if (!dev)
159
+        return;
160
+
161
+    while (epnum < USB_MAX_ENDPOINTS) {
162
+        if (dev->ep_fd[epnum] >= 0) {
163
+            close(dev->ep_fd[epnum]);
164
+            dev->ep_fd[epnum] = -1;
165
+        }
166
+        epnum++;
167
+    }
168
+}
169
+
170
+static void usb_host_handle_reset(USBDevice *dev)
171
+{
172
+#if 0
173
+    USBHostDevice *s = (USBHostDevice *)dev;
174
+#endif
175
+}
176
+
177
+/* XXX:
178
+ * -check device states against transfer requests
179
+ *  and return appropriate response
180
+ */
181
+static int usb_host_handle_control(USBDevice *dev,
182
+                                   int request,
183
+                                   int value,
184
+                                   int index,
185
+                                   int length,
186
+                                   uint8_t *data)
187
+{
188
+    USBHostDevice *s = (USBHostDevice *)dev;
189
+    struct usb_ctl_request req;
190
+    struct usb_alt_interface aiface;
191
+    int ret, timeout = 50;
192
+
193
+    if ((request >> 8) == UT_WRITE_DEVICE &&
194
+        (request & 0xff) == UR_SET_ADDRESS) {
195
+
196
+        /* specific SET_ADDRESS support */
197
+        dev->addr = value;
198
+        return 0;
199
+    } else if ((request >> 8) == UT_WRITE_DEVICE &&
200
+               (request & 0xff) == UR_SET_CONFIG) {
201
+
202
+        ensure_eps_closed(s); /* can't do this without all eps closed */
203
+
204
+        ret = ioctl(s->devfd, USB_SET_CONFIG, &value);
205
+        if (ret < 0) {
206
+#ifdef DEBUG
207
+            printf("handle_control: failed to set configuration - %s\n",
208
+                   strerror(errno));
209
+#endif
210
+            return USB_RET_STALL;
211
+        }
212
+
213
+        return 0;
214
+    } else if ((request >> 8) == UT_WRITE_INTERFACE &&
215
+               (request & 0xff) == UR_SET_INTERFACE) {
216
+
217
+        aiface.uai_interface_index = index;
218
+        aiface.uai_alt_no = value;
219
+
220
+        ensure_eps_closed(s); /* can't do this without all eps closed */
221
+        ret = ioctl(s->devfd, USB_SET_ALTINTERFACE, &aiface);
222
+        if (ret < 0) {
223
+#ifdef DEBUG
224
+            printf("handle_control: failed to set alternate interface - %s\n",
225
+                   strerror(errno));
226
+#endif
227
+            return USB_RET_STALL;
228
+        }
229
+
230
+        return 0;
231
+    } else {
232
+        req.ucr_request.bmRequestType = request >> 8;
233
+        req.ucr_request.bRequest = request & 0xff;
234
+        USETW(req.ucr_request.wValue, value);
235
+        USETW(req.ucr_request.wIndex, index);
236
+        USETW(req.ucr_request.wLength, length);
237
+        req.ucr_data = data;
238
+        req.ucr_flags = USBD_SHORT_XFER_OK;
239
+
240
+        ret = ioctl(s->devfd, USB_SET_TIMEOUT, &timeout);
241
+#if (__NetBSD__ || __OpenBSD__)
242
+        if (ret < 0 && errno != EINVAL) {
243
+#else
244
+        if (ret < 0) {
245
+#endif
246
+#ifdef DEBUG
247
+            printf("handle_control: setting timeout failed - %s\n",
248
+                   strerror(errno));
249
+#endif
250
+        }
251
+
252
+        ret = ioctl(s->devfd, USB_DO_REQUEST, &req);
253
+        /* ugen returns EIO for usbd_do_request_ no matter what
254
+         * happens with the transfer */
255
+        if (ret < 0) {
256
+#ifdef DEBUG
257
+            printf("handle_control: error after request - %s\n",
258
+                   strerror(errno));
259
+#endif
260
+            return USB_RET_NAK; // STALL
261
+        } else {
262
+            return req.ucr_actlen;
263
+        }
264
+    }
265
+}
266
+
267
+static int usb_host_handle_data(USBDevice *dev, int pid,
268
+                                uint8_t devep,
269
+                                uint8_t *data, int len)
270
+{
271
+    USBHostDevice *s = (USBHostDevice *)dev;
272
+    int ret, fd, mode;
273
+    int one = 1, shortpacket = 0, timeout = 50;
274
+    sigset_t new_mask, old_mask;
275
+
276
+    /* protect data transfers from SIGALRM signal */
277
+    sigemptyset(&new_mask);
278
+    sigaddset(&new_mask, SIGALRM);
279
+    sigprocmask(SIG_BLOCK, &new_mask, &old_mask);
280
+
281
+    /* XXX: optimize and handle all data types by looking at the
282
+       config descriptor */
283
+    if (pid == USB_TOKEN_IN) {
284
+        devep |= 0x80;
285
+        mode = O_RDONLY;
286
+        shortpacket = 1;
287
+    } else {
288
+        mode = O_WRONLY;
289
+    }
290
+
291
+    fd = ensure_ep_open(s, devep, mode);
292
+    if (fd < 0) {
293
+        sigprocmask(SIG_SETMASK, &old_mask, NULL);
294
+        return USB_RET_NODEV;
295
+    }
296
+
297
+    if (ioctl(fd, USB_SET_TIMEOUT, &timeout) < 0) {
298
+#ifdef DEBUG
299
+        printf("handle_data: failed to set timeout - %s\n",
300
+               strerror(errno));
301
+#endif
302
+    }
303
+
304
+    if (shortpacket) {
305
+        if (ioctl(fd, USB_SET_SHORT_XFER, &one) < 0) {
306
+#ifdef DEBUG
307
+            printf("handle_data: failed to set short xfer mode - %s\n",
308
+                   strerror(errno));
309
+#endif
310
+            sigprocmask(SIG_SETMASK, &old_mask, NULL);
311
+        }
312
+    }
313
+
314
+    if (pid == USB_TOKEN_IN)
315
+        ret = read(fd, data, len);
316
+    else
317
+        ret = write(fd, data, len);
318
+
319
+    sigprocmask(SIG_SETMASK, &old_mask, NULL);
320
+
321
+    if (ret < 0) {
322
+#ifdef DEBUG
323
+        printf("handle_data: error after %s data - %s\n",
324
+               pid == USB_TOKEN_IN ? "reading" : "writing", strerror(errno));
325
+#endif
326
+        switch(errno) {
327
+        case ETIMEDOUT:
328
+        case EINTR:
329
+            return USB_RET_NAK;
330
+        default:
331
+            return USB_RET_STALL;
332
+        }
333
+    } else {
334
+        return ret;
335
+    }
336
+}
337
+
338
+USBDevice *usb_host_device_open(const char *devname)
339
+{
340
+    struct usb_device_info bus_info, dev_info;
341
+    USBHostDevice *dev;
342
+    char ctlpath[PATH_MAX + 1];
343
+    char buspath[PATH_MAX + 1];
344
+    int bfd, dfd, bus, address, i;
345
+    int ugendebug = UGEN_DEBUG_LEVEL;
346
+
347
+    if (usb_host_find_device(&bus, &address, devname) < 0)
348
+        return NULL;
349
+
350
+    snprintf(buspath, PATH_MAX, "/dev/usb%d", bus);
351
+
352
+    bfd = open(buspath, O_RDWR);
353
+    if (bfd < 0) {
354
+#ifdef DEBUG
355
+        printf("usb_host_device_open: failed to open usb bus - %s\n",
356
+               strerror(errno));
357
+#endif
358
+        return NULL;
359
+    }
360
+
361
+    bus_info.udi_addr = address;
362
+    if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0) {
363
+#ifdef DEBUG
364
+        printf("usb_host_device_open: failed to grab bus information - %s\n",
365
+               strerror(errno));
366
+#endif
367
+        return NULL;
368
+    }
369
+
370
+#if __FreeBSD__
371
+    snprintf(ctlpath, PATH_MAX, "/dev/%s", bus_info.udi_devnames[0]);
372
+#else
373
+    snprintf(ctlpath, PATH_MAX, "/dev/%s.00", bus_info.udi_devnames[0]);
374
+#endif
375
+
376
+    dfd  = open(ctlpath, O_RDWR);
377
+    if (dfd < 0) {
378
+        dfd = open(ctlpath, O_RDONLY);
379
+        if (dfd < 0) {
380
+#ifdef DEBUG
381
+            printf("usb_host_device_open: failed to open usb device %s - %s\n",
382
+                   ctlpath, strerror(errno));
383
+#endif
384
+        }
385
+    }
386
+
387
+    if (dfd >= 0) {
388
+        dev = qemu_mallocz(sizeof(USBHostDevice));
389
+        if (!dev)
390
+            goto fail;
391
+        dev->devfd = dfd;
392
+
393
+        if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) {
394
+#ifdef DEBUG
395
+            printf("usb_host_device_open: failed to grab device info - %s\n",
396
+                   strerror(errno));
397
+#endif
398
+            goto fail;
399
+        }
400
+
401
+        if (dev_info.udi_speed == 1)
402
+            dev->dev.speed = USB_SPEED_LOW - 1;
403
+        else
404
+            dev->dev.speed = USB_SPEED_FULL - 1;
405
+
406
+        dev->dev.handle_packet = usb_generic_handle_packet;
407
+
408
+        dev->dev.handle_reset = usb_host_handle_reset;
409
+        dev->dev.handle_control = usb_host_handle_control;
410
+        dev->dev.handle_data = usb_host_handle_data;
411
+
412
+        strcpy(dev->devpath, "/dev/");
413
+	strcat(dev->devpath, dev_info.udi_devnames[0]);
414
+
415
+        /* Mark the endpoints as not yet open */
416
+        for (i = 0; i < USB_MAX_ENDPOINTS; i++)
417
+           dev->ep_fd[i] = -1;
418
+
419
+        ioctl(dfd, USB_SETDEBUG, &ugendebug);
420
+
421
+        return (USBDevice *)dev;
422
+    }
423
+
424
+fail:
425
+    return NULL;
426
+}
427
+
428
+void usb_host_device_close(USBDevice *opaque)
429
+{
430
+    USBHostDevice *s = (USBHostDevice *)opaque;
431
+    int i;
432
+
433
+    for (i = 0; i < USB_MAX_ENDPOINTS; i++)
434
+        if (s->ep_fd[i] >= 0)
435
+            close(s->ep_fd[i]);
436
+
437
+    if (s->devfd < 0)
438
+        return;
439
+
440
+    close(s->devfd);
441
+}
442
+
443
+static int usb_host_scan(void *opaque, USBScanFunc *func)
444
+{
445
+    struct usb_device_info bus_info;
446
+    struct usb_device_info dev_info;
447
+    uint16_t vendor_id, product_id, class_id, speed;
448
+    int bfd, dfd, bus, address;
449
+    char busbuf[20], devbuf[20], product_name[256];
450
+    int ret = 0;
451
+
452
+    for (bus = 0; bus < 10; bus++) {
453
+
454
+        snprintf(busbuf, sizeof(busbuf) - 1, "/dev/usb%d", bus);
455
+        bfd = open(busbuf, O_RDWR);
456
+        if (bfd < 0)
457
+	    continue;
458
+
459
+        for (address = 1; address < 127; address++) {
460
+
461
+            bus_info.udi_addr = address;
462
+            if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0)
463
+                continue;
464
+
465
+            /* only list devices that can be used by generic layer */
466
+            if (strncmp(bus_info.udi_devnames[0], "ugen", 4) != 0)
467
+                continue;
468
+
469
+#if __FreeBSD__
470
+            snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s", bus_info.udi_devnames[0]);
471
+#else
472
+            snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s.00", bus_info.udi_devnames[0]);
473
+#endif
474
+
475
+            dfd = open(devbuf, O_RDONLY);
476
+            if (dfd < 0) {
477
+#ifdef DEBUG
478
+                printf("usb_host_scan: couldn't open device %s - %s\n", devbuf,
479
+                       strerror(errno));
480
+#endif
481
+                continue;
482
+            }
483
+
484
+            if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0)
485
+                printf("usb_host_scan: couldn't get device information for %s - %s\n",
486
+                       devbuf, strerror(errno));
487
+
488
+            // XXX: might need to fixup endianess of word values before copying over
489
+
490
+            vendor_id = dev_info.udi_vendorNo;
491
+            product_id = dev_info.udi_productNo;
492
+            class_id = dev_info.udi_class;
493
+            speed = dev_info.udi_speed;
494
+
495
+            if (strncmp(dev_info.udi_product, "product", 7) != 0)
496
+                strcpy(product_name, dev_info.udi_product);
497
+            else
498
+                product_name[0] = '\0';
499
+
500
+            ret = func(opaque, bus, address, class_id, vendor_id,
501
+                       product_id, product_name, speed);
502
+
503
+            close(dfd);
504
+
505
+            if (ret)
506
+                goto the_end;
507
+        }
508
+
509
+        close(bfd);
510
+    }
511
+
512
+the_end:
513
+    return ret;
514
+}
515
+
516
+typedef struct FindDeviceState {
517
+    int vendor_id;
518
+    int product_id;
519
+    int bus_num;
520
+    int addr;
521
+} FindDeviceState;
522
+
523
+static int usb_host_find_device_scan(void *opaque, int bus_num, int addr,
524
+                                     int class_id,
525
+                                     int vendor_id, int product_id,
526
+                                     const char *product_name, int speed)
527
+{
528
+    FindDeviceState *s = opaque;
529
+    if (vendor_id == s->vendor_id &&
530
+        product_id == s->product_id) {
531
+        s->bus_num = bus_num;
532
+        s->addr = addr;
533
+        return 1;
534
+     } else {
535
+        return 0;
536
+     }
537
+}
538
+
539
+
540
+/* the syntax is :
541
+   'bus.addr' (decimal numbers) or
542
+   'vendor_id:product_id' (hexa numbers) */
543
+static int usb_host_find_device(int *pbus_num, int *paddr,
544
+                                const char *devname)
545
+{
546
+    const char *p;
547
+    int ret;
548
+    FindDeviceState fs;
549
+
550
+    p = strchr(devname, '.');
551
+    if (p) {
552
+        *pbus_num = strtoul(devname, NULL, 0);
553
+        *paddr = strtoul(p + 1, NULL, 0);
554
+        return 0;
555
+    }
556
+    p = strchr(devname, ':');
557
+    if (p) {
558
+        fs.vendor_id = strtoul(devname, NULL, 16);
559
+        fs.product_id = strtoul(p + 1, NULL, 16);
560
+        ret = usb_host_scan(&fs, usb_host_find_device_scan);
561
+        if (ret) {
562
+            *pbus_num = fs.bus_num;
563
+            *paddr = fs.addr;
564
+            return 0;
565
+        }
566
+     }
567
+     return -1;
568
+}
569
+
570
+/**********************/
571
+/* USB host device info */
572
+
573
+struct usb_class_info {
574
+    int class;
575
+    const char *class_name;
576
+};
577
+
578
+static const struct usb_class_info usb_class_info[] = {
579
+    { USB_CLASS_AUDIO, "Audio"},
580
+    { USB_CLASS_COMM, "Communication"},
581
+    { USB_CLASS_HID, "HID"},
582
+    { USB_CLASS_HUB, "Hub" },
583
+    { USB_CLASS_PHYSICAL, "Physical" },
584
+    { USB_CLASS_PRINTER, "Printer" },
585
+    { USB_CLASS_MASS_STORAGE, "Storage" },
586
+    { USB_CLASS_CDC_DATA, "Data" },
587
+    { USB_CLASS_APP_SPEC, "Application Specific" },
588
+    { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
589
+    { USB_CLASS_STILL_IMAGE, "Still Image" },
590
+    { USB_CLASS_CSCID, "Smart Card" },
591
+    { USB_CLASS_CONTENT_SEC, "Content Security" },
592
+    { -1, NULL }
593
+};
594
+
595
+static const char *usb_class_str(uint8_t class)
596
+{
597
+    const struct usb_class_info *p;
598
+    for (p = usb_class_info; p->class != -1; p++) {
599
+        if (p->class == class)
600
+            break;
601
+    }
602
+    return p->class_name;
603
+}
604
+
605
+void usb_info_device(int bus_num, int addr, int class_id,
606
+                     int vendor_id, int product_id,
607
+                     const char *product_name,
608
+                     int speed)
609
+{
610
+    const char *class_str, *speed_str;
611
+
612
+    switch(speed) {
613
+    case USB_SPEED_LOW:
614
+        speed_str = "1.5";
615
+        break;
616
+    case USB_SPEED_FULL:
617
+        speed_str = "12";
618
+        break;
619
+    case USB_SPEED_HIGH:
620
+        speed_str = "480";
621
+        break;
622
+    default:
623
+        speed_str = "?";
624
+        break;
625
+    }
626
+
627
+    term_printf("  Device %d.%d, speed %s Mb/s\n",
628
+                bus_num, addr, speed_str);
629
+    class_str = usb_class_str(class_id);
630
+    if (class_str)
631
+        term_printf("    %s:", class_str);
632
+    else
633
+        term_printf("    Class %02x:", class_id);
634
+    term_printf(" USB device %04x:%04x", vendor_id, product_id);
635
+    if (product_name[0] != '\0')
636
+        term_printf(", %s", product_name);
637
+    term_printf("\n");
638
+}
639
+
640
+static int usb_host_info_device(void *opaque, int bus_num, int addr,
641
+                                int class_id,
642
+                                int vendor_id, int product_id,
643
+                                const char *product_name,
644
+                                int speed)
645
+{
646
+    usb_info_device(bus_num, addr, class_id, vendor_id, product_id,
647
+                    product_name, speed);
648
+    return 0;
649
+}
650
+
651
+void usb_host_info(void)
652
+{
653
+    usb_host_scan(NULL, usb_host_info_device);
654
+}
655
Index: qemu/vl.c
656
@@ -2820,10 +2822,12 @@
657
         dev = usb_host_device_open(p);
658
         if (!dev)
659
             return -1;
660
+        dev->isproxied = 1;
661
     } else if (!strcmp(devname, "mouse")) {
662
         dev = usb_mouse_init();
663
         if (!dev)
664
             return -1;
665
+        dev->isproxied = 0;
666
     } else {
667
         return -1;
668
     }
669
@@ -2852,6 +2856,8 @@
670
         if (dev && dev->addr == addr)
671
             break;
672
     }
673
+    if (dev && dev->isproxied)
674
+        usb_host_device_close(dev);
675
     if (i == MAX_VM_USB_PORTS)
676
         return -1;
677
     usb_attach(vm_usb_ports[i], NULL);
678
Index: qemu/hw/usb.h
679
@@ -135,6 +146,8 @@
680
     int setup_state;
681
     int setup_len;
682
     int setup_index;
683
+
684
+    int isproxied;
685
 };
686
 
687
 /* USB port on which a device can be connected */
688
@@ -157,8 +170,9 @@
689
 /* usb-uhci.c */
690
 void usb_uhci_init(PCIBus *bus, USBPort **usb_ports);
691
 
692
-/* usb-linux.c */
693
+/* host proxy functions */
694
 USBDevice *usb_host_device_open(const char *devname);
695
+void usb_host_device_close(USBDevice *dev);
696
 void usb_host_info(void);
697
 
698
 /* usb-hid.c */
699
Index: qemu/usb-linux.c
700
@@ -23,7 +23,6 @@
701
  */
702
 #include "vl.h"
703
 
704
-#if defined(__linux__)
705
 #include <dirent.h>
706
 #include <sys/ioctl.h>
707
 #include <linux/usbdevice_fs.h>
708
@@ -255,6 +254,14 @@
709
     return q - buf;
710
 }
711
 
712
+void usb_host_device_close(USBDevice *opaque)
713
+{
714
+    USBHostDevice *s = (USBHostDevice *)opaque;
715
+
716
+    if (s->fd >= 0)
717
+       close(s->fd);
718
+}
719
+
720
 static int usb_host_scan(void *opaque, USBScanFunc *func)
721
 {
722
     FILE *f;
723
@@ -468,18 +475,3 @@
724
 {
725
     usb_host_scan(NULL, usb_host_info_device);
726
 }
727
-
728
-#else
729
-
730
-void usb_host_info(void)
731
-{
732
-    term_printf("USB host devices not supported\n");
733
-}
734
-
735
-/* XXX: modify configure to compile the right host driver */
736
-USBDevice *usb_host_device_open(const char *devname)
737
-{
738
-    return NULL;
739
-}
740
-
741
-#endif
(-)files/patch-dyngen.h (+11 lines)
Line 0 Link Here
1
# 1.9
2
Index: qemu/dyngen.h
3
@@ -59,7 +59,7 @@
4
 {
5
     unsigned long p;
6
 
7
-    p = start & ~(MIN_CACHE_LINE_SIZE - 1);
8
+    start &= ~(MIN_CACHE_LINE_SIZE - 1);
9
     stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
10
     
11
     for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
(-)files/patch-hw-ne2000.c (+44 lines)
Line 0 Link Here
1
# 1.19
2
Index: qemu/hw/ne2000.c
3
@@ -648,6 +648,8 @@
4
 {
5
 	NE2000State* s=(NE2000State*)opaque;
6
 
7
+        qemu_put_8s(f, &s->rxcr);
8
+
9
 	qemu_put_8s(f, &s->cmd);
10
 	qemu_put_be32s(f, &s->start);
11
 	qemu_put_be32s(f, &s->stop);
12
@@ -672,8 +674,13 @@
13
 {
14
 	NE2000State* s=(NE2000State*)opaque;
15
 
16
-	if (version_id != 1)
17
+        if (version_id == 2) {
18
+            qemu_get_8s(f, &s->rxcr);
19
+        } else if (version_id == 1) {
20
+            s->rxcr = 0x0c;
21
+        } else {
22
             return -EINVAL;
23
+        }
24
 
25
 	qemu_get_8s(f, &s->cmd);
26
 	qemu_get_be32s(f, &s->start);
27
@@ -732,7 +739,7 @@
28
              s->macaddr[4],
29
              s->macaddr[5]);
30
              
31
-    register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s);
32
+    register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s);
33
 }
34
 
35
 /***********************************************************/
36
@@ -803,7 +810,7 @@
37
              s->macaddr[5]);
38
              
39
     /* XXX: instance number ? */
40
-    register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s);
41
+    register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s);
42
     register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load, 
43
                     &d->dev);
44
 }
(-)files/patch-hw-usb-uhci.c (+28 lines)
Line 0 Link Here
1
# 1.6
2
Index: qemu/hw/usb-uhci.c
3
@@ -153,6 +153,7 @@
4
     switch(addr) {
5
     case 0x0c:
6
         val = s->sof_timing;
7
+        break;
8
     default:
9
         val = 0xff;
10
         break;
11
@@ -654,6 +655,7 @@
12
     pci_conf[0x0b] = 0x0c;
13
     pci_conf[0x0e] = 0x00; // header_type
14
     pci_conf[0x3d] = 4; // interrupt pin 3
15
+    pci_conf[0x60] = 0x10; // release number
16
     
17
     for(i = 0; i < NB_PORTS; i++) {
18
         port = &s->ports[i];
19
@@ -666,6 +668,8 @@
20
 
21
     uhci_reset(s);
22
 
23
-    pci_register_io_region(&s->dev, 0, 0x20, 
24
+    /* Use region 4 for consistency with real hardware.  BSD guests seem
25
+       to rely on this.  */
26
+    pci_register_io_region(&s->dev, 4, 0x20, 
27
                            PCI_ADDRESS_SPACE_IO, uhci_map);
28
 }
(-)files/patch-hw-usb.c (+11 lines)
Line 0 Link Here
1
# 1.4
2
Index: qemu/hw/usb.c
3
@@ -183,7 +183,7 @@
4
 
5
     q = buf;
6
     len = strlen(str);
7
-    *q++ = 2 * len + 1;
8
+    *q++ = 2 * len + 2;
9
     *q++ = 3;
10
     for(i = 0; i < len; i++) {
11
         *q++ = str[i];
(-)files/patch-sdl.c (+29 lines)
Line 0 Link Here
1
# 1.24
2
Index: qemu/sdl.c
3
@@ -404,6 +404,7 @@
4
                 mod_state = (ev->key.keysym.mod & gui_grab_code);
5
                 if (!mod_state) {
6
                     if (gui_key_modifier_pressed) {
7
+                        gui_key_modifier_pressed = 0;
8
                         if (gui_keysym == 0) {
9
                             /* exit/enter grab if pressing Ctrl-Alt */
10
                             if (!gui_grab)
11
@@ -415,7 +416,6 @@
12
                             reset_keys();
13
                             break;
14
                         }
15
-                        gui_key_modifier_pressed = 0;
16
                         gui_keysym = 0;
17
                     }
18
                 }
19
@@ -456,8 +456,8 @@
20
             }
21
             break;
22
         case SDL_ACTIVEEVENT:
23
-            if (gui_grab && (ev->active.gain & SDL_ACTIVEEVENTMASK) == 0 &&
24
-                !gui_fullscreen_initial_grab) {
25
+            if (gui_grab && ev->active.state == SDL_APPINPUTFOCUS &&
26
+                !ev->active.gain && !gui_fullscreen_initial_grab) {
27
                 sdl_grab_end();
28
             }
29
             break;
(-)files/patch-slirp-socket.c (+18 lines)
Line 0 Link Here
1
# 1.6
2
Index: qemu/slirp/socket.c
3
@@ -573,6 +573,7 @@
4
 	addr.sin_port = port;
5
 	
6
 	if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||
7
+	    (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
8
 	    (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
9
 	    (listen(s,1) < 0)) {
10
 		int tmperrno = errno; /* Don't clobber the real reason we failed */
11
@@ -587,7 +588,6 @@
12
 #endif
13
 		return NULL;
14
 	}
15
-	setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
16
 	setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
17
 	
18
 	getsockname(s,(struct sockaddr *)&addr,&addrlen);
(-)files/patch-target-i386-translate.c (+29 lines)
Line 0 Link Here
1
# 1.53
2
Index: qemu/target-i386/translate.c
3
@@ -5803,14 +5803,24 @@
4
         op = (modrm >> 3) & 7;
5
         switch(op) {
6
         case 0: /* fxsave */
7
-            if (mod == 3 || !(s->cpuid_features & CPUID_FXSR))
8
+            if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) || 
9
+                (s->flags & HF_EM_MASK))
10
                 goto illegal_op;
11
+            if (s->flags & HF_TS_MASK) {
12
+                gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
13
+                break;
14
+            }
15
             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
16
             gen_op_fxsave_A0((s->dflag == 2));
17
             break;
18
         case 1: /* fxrstor */
19
-            if (mod == 3 || !(s->cpuid_features & CPUID_FXSR))
20
+            if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) || 
21
+                (s->flags & HF_EM_MASK))
22
                 goto illegal_op;
23
+            if (s->flags & HF_TS_MASK) {
24
+                gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
25
+                break;
26
+            }
27
             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
28
             gen_op_fxrstor_A0((s->dflag == 2));
29
             break;
(-)files/patch-usb-hchalt (+10 lines)
Line 0 Link Here
1
Index: qemu/hw/usb-uhci.c
2
@@ -527,6 +532,8 @@
3
 
4
     if (!(s->cmd & UHCI_CMD_RS)) {
5
         qemu_del_timer(s->frame_timer);
6
+        /* set hchalted bit in status - UHCI11D 2.1.2 */
7
+        s->status |= UHCI_STS_HCHALTED;
8
         return;
9
     }
10
     frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
(-)files/patch-usb-hubfixups (+87 lines)
Line 0 Link Here
1
Index: qemu/hw/usb.c
2
@@ -330,9 +330,9 @@
3
 	0x0a,			/* u16  wHubCharacteristics; */
4
 	0x00,			/*   (per-port OC, no power switching) */
5
 	0x01,			/*  u8  bPwrOn2pwrGood; 2ms */
6
-	0x00,			/*  u8  bHubContrCurrent; 0 mA */
7
-	0x00,			/*  u8  DeviceRemovable; *** 7 Ports max *** */
8
-	0xff			/*  u8  PortPwrCtrlMask; *** 7 ports max *** */
9
+	0x00			/*  u8  bHubContrCurrent; 0 mA */
10
+
11
+        /* DeviceRemovable and PortPwrCtrlMask patched in later */
12
 };
13
 
14
 static void usb_hub_attach(USBPort *port1, USBDevice *dev)
15
@@ -391,6 +391,12 @@
16
         }
17
         ret = 0;
18
         break;
19
+    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
20
+        if (value == 0 && index != 0x81) { /* clear ep halt */
21
+            goto fail;
22
+        }
23
+        ret = 0;
24
+        break;
25
     case DeviceOutRequest | USB_REQ_SET_FEATURE:
26
         if (value == USB_DEVICE_REMOTE_WAKEUP) {
27
             dev->remote_wakeup = 1;
28
@@ -408,6 +414,11 @@
29
         case USB_DT_DEVICE:
30
             memcpy(data, qemu_hub_dev_descriptor, 
31
                    sizeof(qemu_hub_dev_descriptor));
32
+
33
+            /* status change endpoint size based on number
34
+             * of ports */
35
+            data[22] = (s->nb_ports + 1 + 7) / 8;
36
+
37
             ret = sizeof(qemu_hub_dev_descriptor);
38
             break;
39
         case USB_DT_CONFIG:
40
@@ -558,11 +569,29 @@
41
         }
42
         break;
43
     case GetHubDescriptor:
44
-        memcpy(data, qemu_hub_hub_descriptor, 
45
-               sizeof(qemu_hub_hub_descriptor));
46
-        data[2] = s->nb_ports;
47
-        ret = sizeof(qemu_hub_hub_descriptor);
48
-        break;
49
+        {
50
+            unsigned int n, limit, var_hub_size = 0;
51
+            memcpy(data, qemu_hub_hub_descriptor, 
52
+                   sizeof(qemu_hub_hub_descriptor));
53
+            data[2] = s->nb_ports;
54
+
55
+            /* fill DeviceRemovable bits */
56
+            limit = ((s->nb_ports + 1 + 7) / 8) + 7;
57
+            for (n = 7; n < limit; n++) {
58
+                data[n] = 0x00;
59
+                var_hub_size++;
60
+            }
61
+
62
+            /* fill PortPwrCtrlMask bits */
63
+            limit = limit + ((s->nb_ports + 7) / 8);
64
+            for (;n < limit; n++) {
65
+                data[n] = 0xff;
66
+                var_hub_size++;
67
+            }
68
+
69
+            ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size;
70
+            break;
71
+        }
72
     default:
73
     fail:
74
         ret = USB_RET_STALL;
75
@@ -584,8 +613,11 @@
76
             unsigned int status;
77
             int i, n;
78
             n = (s->nb_ports + 1 + 7) / 8;
79
-            if (n > len)
80
+            if (len == 1) { /* FreeBSD workaround */
81
+                n = 1;
82
+            } else if (n > len) {
83
                 return USB_RET_BABBLE;
84
+            }
85
             status = 0;
86
             for(i = 0; i < s->nb_ports; i++) {
87
                 port = &s->ports[i];
(-)files/patch-vl.c-nographic (+9 lines)
Line 0 Link Here
1
Index: qemu/vl.c
2
@@ -4668,6 +4668,7 @@
3
             case QEMU_OPTION_nographic:
4
                 pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
5
                 pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio");
6
+                pstrcpy(parallel_devices[0], sizeof(parallel_devices[0]), "null");
7
                 nographic = 1;
8
                 break;
9
             case QEMU_OPTION_kernel:

Return to bug 94654