Commit cda62fd6 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linuxusb.bkbits.net/linus-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents b9bfb312 944b9581
...@@ -1431,15 +1431,10 @@ static void hid_disconnect(struct usb_device *dev, void *ptr) ...@@ -1431,15 +1431,10 @@ static void hid_disconnect(struct usb_device *dev, void *ptr)
{ {
struct hid_device *hid = ptr; struct hid_device *hid = ptr;
dbg("cleanup called");
usb_unlink_urb(hid->urbin); usb_unlink_urb(hid->urbin);
usb_unlink_urb(hid->urbout); usb_unlink_urb(hid->urbout);
usb_unlink_urb(hid->urbctrl); usb_unlink_urb(hid->urbctrl);
usb_free_urb(hid->urbin);
usb_free_urb(hid->urbctrl);
if (hid->urbout)
usb_free_urb(hid->urbout);
if (hid->claimed & HID_CLAIMED_INPUT) if (hid->claimed & HID_CLAIMED_INPUT)
hidinput_disconnect(hid); hidinput_disconnect(hid);
...@@ -1447,6 +1442,12 @@ static void hid_disconnect(struct usb_device *dev, void *ptr) ...@@ -1447,6 +1442,12 @@ static void hid_disconnect(struct usb_device *dev, void *ptr)
if (hid->claimed & HID_CLAIMED_HIDDEV) if (hid->claimed & HID_CLAIMED_HIDDEV)
hiddev_disconnect(hid); hiddev_disconnect(hid);
#endif #endif
usb_free_urb(hid->urbin);
usb_free_urb(hid->urbctrl);
if (hid->urbout)
usb_free_urb(hid->urbout);
hid_free_device(hid); hid_free_device(hid);
} }
......
...@@ -2322,7 +2322,8 @@ int usb_clear_halt(struct usb_device *dev, int pipe) ...@@ -2322,7 +2322,8 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
int usb_set_interface(struct usb_device *dev, int interface, int alternate) int usb_set_interface(struct usb_device *dev, int interface, int alternate)
{ {
struct usb_interface *iface; struct usb_interface *iface;
int ret; struct usb_interface_descriptor *iface_as;
int i, ret;
iface = usb_ifnum_to_if(dev, interface); iface = usb_ifnum_to_if(dev, interface);
if (!iface) { if (!iface) {
...@@ -2344,8 +2345,30 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) ...@@ -2344,8 +2345,30 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
return ret; return ret;
iface->act_altsetting = alternate; iface->act_altsetting = alternate;
dev->toggle[0] = 0; /* 9.1.1.5 says to do this */
dev->toggle[1] = 0; /* 9.1.1.5: reset toggles for all endpoints affected by this iface-as
*
* Note:
* Despite EP0 is always present in all interfaces/AS, the list of
* endpoints from the descriptor does not contain EP0. Due to its
* omnipresence one might expect EP0 being considered "affected" by
* any SetInterface request and hence assume toggles need to be reset.
* However, EP0 toggles are re-synced for every individual transfer
* during the SETUP stage - hence EP0 toggles are "don't care" here.
*/
iface_as = &iface->altsetting[alternate];
for (i = 0; i < iface_as->bNumEndpoints; i++) {
u8 ep = iface_as->endpoint[i].bEndpointAddress;
usb_settoggle(dev, ep&USB_ENDPOINT_NUMBER_MASK, usb_endpoint_out(ep), 0);
}
/* usb_set_maxpacket() sets the maxpacket size for all EP in all
* interfaces but it shouldn't do any harm here: we have changed
* the AS for the requested interface only, hence for unaffected
* interfaces it's just re-application of still-valid values.
*/
usb_set_maxpacket(dev); usb_set_maxpacket(dev);
return 0; return 0;
} }
......
...@@ -1156,12 +1156,12 @@ const struct usb_device_id *usb_match_id(struct usb_device *dev, ...@@ -1156,12 +1156,12 @@ const struct usb_device_id *usb_match_id(struct usb_device *dev,
#define PIPE_DEVEP_MASK 0x0007ff00 #define PIPE_DEVEP_MASK 0x0007ff00
/* The D0/D1 toggle bits */ /* The D0/D1 toggle bits */
#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> ep) & 1) #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << ep)) #define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << (ep)))
#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << ep)) | ((bit) << ep)) #define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | ((bit) << (ep)))
/* Endpoint halt control/status */ /* Endpoint halt control/status */
#define usb_endpoint_out(ep_dir) (((ep_dir >> 7) & 1) ^ 1) #define usb_endpoint_out(ep_dir) ((((ep_dir) >> 7) & 1) ^ 1)
#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep))) #define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep))) #define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep)))
#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep))) #define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep)))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment