Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 36431
b: refs/heads/master
c: 088dc27
h: refs/heads/master
i:
  36429: daacbba
  36427: 11d5a90
  36423: 70a92e4
  36415: 5ab9b0c
v: v3
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Sep 27, 2006
1 parent ee7d654 commit 8ca1932
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3a3416b12f1fbd607bc137a57c924a628aa5485c
refs/heads/master: 088dc270e1da03744d977cbd9edd4311af142348
59 changes: 59 additions & 0 deletions trunk/drivers/usb/core/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -1493,6 +1493,65 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
return 0;
}

struct set_config_request {
struct usb_device *udev;
int config;
struct work_struct work;
};

/* Worker routine for usb_driver_set_configuration() */
static void driver_set_config_work(void *_req)
{
struct set_config_request *req = _req;

usb_lock_device(req->udev);
usb_set_configuration(req->udev, req->config);
usb_unlock_device(req->udev);
usb_put_dev(req->udev);
kfree(req);
}

/**
* usb_driver_set_configuration - Provide a way for drivers to change device configurations
* @udev: the device whose configuration is being updated
* @config: the configuration being chosen.
* Context: In process context, must be able to sleep
*
* Device interface drivers are not allowed to change device configurations.
* This is because changing configurations will destroy the interface the
* driver is bound to and create new ones; it would be like a floppy-disk
* driver telling the computer to replace the floppy-disk drive with a
* tape drive!
*
* Still, in certain specialized circumstances the need may arise. This
* routine gets around the normal restrictions by using a work thread to
* submit the change-config request.
*
* Returns 0 if the request was succesfully queued, error code otherwise.
* The caller has no way to know whether the queued request will eventually
* succeed.
*/
int usb_driver_set_configuration(struct usb_device *udev, int config)
{
struct set_config_request *req;

req = kmalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
req->udev = udev;
req->config = config;
INIT_WORK(&req->work, driver_set_config_work, req);

usb_get_dev(udev);
if (!schedule_work(&req->work)) {
usb_put_dev(udev);
kfree(req);
return -EINVAL;
}
return 0;
}
EXPORT_SYMBOL_GPL(usb_driver_set_configuration);

// synchronous request completion model
EXPORT_SYMBOL(usb_control_msg);
EXPORT_SYMBOL(usb_bulk_msg);
Expand Down
3 changes: 3 additions & 0 deletions trunk/include/linux/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,9 @@ extern int usb_clear_halt(struct usb_device *dev, int pipe);
extern int usb_reset_configuration(struct usb_device *dev);
extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);

/* this request isn't really synchronous, but it belongs with the others */
extern int usb_driver_set_configuration(struct usb_device *udev, int config);

/*
* timeouts, in milliseconds, used for sending/receiving control messages
* they typically complete within a few frames (msec) after they're issued
Expand Down

0 comments on commit 8ca1932

Please sign in to comment.