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 _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel