-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathREADME.linux.patches
120 lines (108 loc) · 5.12 KB
/
README.linux.patches
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
The patches below (extracted from kernel version 2.6.24.3)
do bulk->int change and let the kernel recognize low-speed
midi devices, the old 2.6.22.1-rt9 kernel said:
"unknown device speed".
If you're using a new kernel >=2.6.23 there is no need for
this patch. But I use the older 2.6.22.1-rt9 kernel because
it works much better with my laptop and jack, with newer ones
I get xruns constantly.
The patch consists of two parts:
one for /usr/src/linux/drivers/usb/core/config.c:
--- config.c 2007-07-10 20:56:30.000000000 +0200
+++ config.c.2.6.24.3 2008-01-24 23:58:37.000000000 +0100
@@ -124,6 +130,21 @@
endpoint->desc.bInterval = n;
}
+ /* Some buggy low-speed devices have Bulk endpoints, which is
+ * explicitly forbidden by the USB spec. In an attempt to make
+ * them usable, we will try treating them as Interrupt endpoints.
+ */
+ if (to_usb_device(ddev)->speed == USB_SPEED_LOW &&
+ usb_endpoint_xfer_bulk(d)) {
+ dev_warn(ddev, "config %d interface %d altsetting %d "
+ "endpoint 0x%X is Bulk; changing to Interrupt\n",
+ cfgno, inum, asnum, d->bEndpointAddress);
+ endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT;
+ endpoint->desc.bInterval = 1;
+ if (le16_to_cpu(endpoint->desc.wMaxPacketSize) > 8)
+ endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
+ }
+
/* Skip over any Class Specific or Vendor Specific descriptors;
* find the next endpoint or interface descriptor */
endpoint->extra = buffer;
the second one for /usr/src/linux/sound/usb/usbaudio.c and .../usbmidi.c:
Code:
--- usbaudio.c 2007-07-10 20:56:30.000000000 +0200
+++ usbaudio.c.2.6.24.3 2008-01-24 23:58:37.000000000 +0100
@@ -3381,7 +3390,8 @@
*rchip = NULL;
- if (snd_usb_get_speed(dev) != USB_SPEED_FULL &&
+ if (snd_usb_get_speed(dev) != USB_SPEED_LOW &&
+ snd_usb_get_speed(dev) != USB_SPEED_FULL &&
snd_usb_get_speed(dev) != USB_SPEED_HIGH) {
snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev));
return -ENXIO;
@@ -3455,7 +3465,9 @@
usb_make_path(dev, card->longname + len, sizeof(card->longname) - len);
strlcat(card->longname,
- snd_usb_get_speed(dev) == USB_SPEED_FULL ? ", full speed" : ", high speed",
+ snd_usb_get_speed(dev) == USB_SPEED_LOW ? ", low speed" :
+ snd_usb_get_speed(dev) == USB_SPEED_FULL ? ", full speed" :
+ ", high speed",
sizeof(card->longname));
snd_usb_audio_create_proc(chip);
--- linux-2.6.22.1-rt9/sound/usb/usbmidi.c 2007-07-10 20:56:30.000000000 +0200
+++ linux-2.6.24.3-rt3/sound/usb/usbmidi.c 2008-01-24 23:58:37.000000000 +0100
@@ -963,8 +983,10 @@
snd_usbmidi_out_endpoint_delete(ep);
return -ENOMEM;
}
- /* we never use interrupt output pipes */
- pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep);
+ if (ep_info->out_interval)
+ pipe = usb_sndintpipe(umidi->chip->dev, ep_info->out_ep);
+ else
+ pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep);
if (umidi->chip->usb_id == USB_ID(0x0a92, 0x1020)) /* ESI M4U */
/* FIXME: we need more URBs to get reasonable bandwidth here: */
ep->max_transfer = 4;
@@ -976,8 +998,14 @@
snd_usbmidi_out_endpoint_delete(ep);
return -ENOMEM;
}
- usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer,
- ep->max_transfer, snd_usbmidi_out_urb_complete, ep);
+ if (ep_info->out_interval)
+ usb_fill_int_urb(ep->urb, umidi->chip->dev, pipe, buffer,
+ ep->max_transfer, snd_usbmidi_out_urb_complete,
+ ep, ep_info->out_interval);
+ else
+ usb_fill_bulk_urb(ep->urb, umidi->chip->dev,
+ pipe, buffer, ep->max_transfer,
+ snd_usbmidi_out_urb_complete, ep);
ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
spin_lock_init(&ep->buffer_lock);
@@ -1323,6 +1351,13 @@
endpoints[epidx].out_ep = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
endpoints[epidx].out_interval = ep->bInterval;
+ else if (snd_usb_get_speed(umidi->chip->dev) == USB_SPEED_LOW)
+ /*
+ * Low speed bulk transfers don't exist, so
+ * force interrupt transfers for devices like
+ * ESI MIDI Mate that try to use them anyway.
+ */
+ endpoints[epidx].out_interval = 1;
endpoints[epidx].out_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n",
ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
@@ -1336,6 +1371,8 @@
endpoints[epidx].in_ep = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
endpoints[epidx].in_interval = ep->bInterval;
+ else if (snd_usb_get_speed(umidi->chip->dev) == USB_SPEED_LOW)
+ endpoints[epidx].in_interval = 1;
endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n",
ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);