Discussion:
Fix? usb_reset on Darwin
Fabio Utzig
2012-09-14 00:35:46 UTC
Permalink
Hi,

Today when trying to run mspdebug with and EZ430-F2013 dev board on a Mac I found an interesting problem. When mspdebug runs on this specific board, it first checks the number of configurations (bNumConfigurations) and if it has only 1, it will download a .hex file to the board I try to restart the board which should now have 2 configurations. When trying to switch to the second configuration it always gets in error and dies.

While debugging this I found that after downloading the FW on the board it does an usb_reset. On the Darwin backend the usb_reset turns into this call (libusb/os/darwin_usb.c:1215):

kresult = (*(dpriv->device))->ResetDevice (dpriv->device);

Checking Apple's documentation here:

https://developer.apple.com/library/mac/#documentation/IOKit/Reference/IOUSBDeviceInterface_reference/translated_content/IOUSBDeviceInterface.html

It states:

"It will not reenumerate the device, which means that the cached device descriptor values will not be updated after the reset. (If you want the IOUSBFamily to reload the cached values, use the call USBDeviceReEnumerate)."

So I add the new call to USBDeviceReEnumerate just after the call to ResetDevice and now it seems to be working fine.

I never used libusb before and I'm not very much into USB internals so I'm not really sure if this fix will not have side effects or if there's another way of fixing this without this modification. Anyway I'm sending a patch attached with the proposed fix.

Best Regards,
--
Fabio Utzig
Xiaofan Chen
2012-09-14 01:20:44 UTC
Permalink
Post by Fabio Utzig
While debugging this I found that after downloading the FW on the board it
does an usb_reset. On the Darwin backend the usb_reset turns into this call
kresult = (*(dpriv->device))->ResetDevice (dpriv->device);
https://developer.apple.com/library/mac/#documentation/IOKit/Reference/IOUSBDeviceInterface_reference/translated_content/IOUSBDeviceInterface.html
"It will not reenumerate the device, which means that the cached device
descriptor values will not be updated after the reset. (If you want the
IOUSBFamily to reload the cached values, use the call
USBDeviceReEnumerate)."
So I add the new call to USBDeviceReEnumerate just after the call to
ResetDevice and now it seems to be working fine.
I never used libusb before and I'm not very much into USB internals so I'm
not really sure if this fix will not have side effects or if there's another
way of fixing this without this modification. Anyway I'm sending a patch
attached with the proposed fix.
Please refer to this thread.
http://libusb.6.n5.nabble.com/PATCH-make-libusb-reset-force-re-enumeration-on-Mac-td4499375.html

Previous patch was basically rejected.

libusb_reset_device()
http://libusb.sourceforge.net/api-1.0/group__dev.html#ga7321bd8dc28e9a20b411bf18e6d0e9aa

This is different from libusb-0.1 documentation of usb_reset()
http://libusb.sourceforge.net/doc/function.usbreset.html
--
Xiaofan
Peter Stuge
2012-09-17 06:39:05 UTC
Permalink
Post by Xiaofan Chen
Previous patch was basically rejected.
This is less bad than it might sound. Hans email in the thread
Xiaofan linked to explains why; a device which shifts shape always
requires closing the handle and getting a new device list and/or
re-opening the device by vid/pid.


//Peter
Xiaofan Chen
2012-09-17 07:06:12 UTC
Permalink
Post by Peter Stuge
Post by Xiaofan Chen
Previous patch was basically rejected.
This is less bad than it might sound. Hans email in the thread
Xiaofan linked to explains why; a device which shifts shape always
requires closing the handle and getting a new device list and/or
re-opening the device by vid/pid.
I agree.

On the other hand, now libusb-compat's usb_reset() will have some
conflict with the old libusb-0.1 API document (which may not be
correct in the first place but it is no longer maintained). Maybe
something needs to be done on the libusb-compat documentation.

If we add Windows in the picture, it is even more complicated.
WinUSB does not support reset whereas libusb0.sys and libusbk.sys
can support it.

libusb_reset_device()
http://libusb.sourceforge.net/api-1.0/group__dev.html#ga7321bd8dc28e9a20b411bf18e6d0e9aa

This is different from libusb-0.1 documentation of usb_reset()
http://libusb.sourceforge.net/doc/function.usbreset.html

Name
usb_reset -- Resets a device
Description

int usb_reset(usb_dev_handle *dev);

usb_reset resets the specified device by sending a RESET
down the port it is connected to. Returns 0 on success
or < 0 on error.

Causes re-enumeration: After calling usb_reset, the device
will need to re-enumerate and thusly, requires you to find the
new device and open a new handle. The handle used to
call usb_reset will no longer work.
--
Xiaofan
Loading...