Am Donnerstag, 25. Januar 2007 16:54 schrieb Oleg Verych:
> On Thu, Jan 25, 2007 at 04:17:03PM +0100, Oliver Neukum wrote:
> []
> > >
> > > It is relatively new. As comment states, it doesn't guarantee
> > > anything, caller hangs in air...
> >
> > Yes, unfortunately this is true. However, as I understand it, you are
> > helpless if you are called with the wrong configuration. So you don't really
> > lose anything.
> > If you wish to, you can return 0 from probe() and you'll be disconnected
> > from the device by the change of configuration.
>
> Well, any kind of crutch may be used, still it's crutch.
If you insist, here's a version with feedback. Be careful of deadlocks.
> > The alternative is a deep change to the API for one odd type of device.
> > Do you absolutely need an error return?
>
> AFAIK, this is standard USB firmware update logic. Greg even
> co-authored a standard for this.
>
> As for me, driver must have full control of plugged device until it
> unplugged. USB ID games make this impossible at first glance. But i don't
> know about problems to have some kind of history of device acting
> during plug-unplug period.
Drivers are attachable and detachable through sysfs in all cases.
Regards
Oliver
----
--- a/drivers/usb/core/message.c 2007-01-15 11:37:39.000000000
+0100
+++ b/drivers/usb/core/message.c 2007-01-25 16:32:17.000000000 +0100
@@ -1496,6 +1496,8 @@
struct set_config_request {
struct usb_device *udev;
+ struct completion *completion;
+ int *status;
int config;
struct work_struct work;
};
@@ -1503,13 +1505,18 @@
/* Worker routine for usb_driver_set_configuration() */
static void driver_set_config_work(struct work_struct *work)
{
+ int rv;
struct set_config_request *req =
container_of(work, struct set_config_request, work);
usb_lock_device(req->udev);
- usb_set_configuration(req->udev, req->config);
+ rv = usb_set_configuration(req->udev, req->config);
usb_unlock_device(req->udev);
usb_put_dev(req->udev);
+ if (req->status)
+ *req->status = rv;
+ if (req->completion)
+ complete(req->completion);
kfree(req);
}
@@ -1533,15 +1540,9 @@
* 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;
+static int do_driver_setconf(struct usb_device *udev, struct
set_config_request *req)
+{
INIT_WORK(&req->work, driver_set_config_work);
usb_get_dev(udev);
@@ -1552,8 +1553,40 @@
}
return 0;
}
+
+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;
+
+ return do_driver_setconf(udev, req);
+}
EXPORT_SYMBOL_GPL(usb_driver_set_configuration);
+int usb_driver_set_configuration_complete
+(struct usb_device *udev, int config, struct completion *cpl, int *status)
+{
+ struct set_config_request *req;
+
+ req = kmalloc(sizeof(*req), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ req->udev = udev;
+ req->config = config;
+ req->completion = cpl;
+ req->status = status;
+
+ return do_driver_setconf(udev, req);
+}
+
+EXPORT_SYMBOL_GPL(usb_driver_set_configuration_complete);
+
// synchronous request completion model
EXPORT_SYMBOL(usb_control_msg);
EXPORT_SYMBOL(usb_bulk_msg);
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel