Solved: OpenPCD hangs after running mifare-tool (or others) several times

Christian Vogel vogelchr at vogel.cx
Sun Feb 21 19:59:23 UTC 2010


Hi,

there are several bugreports in the archives concerning a loss of
USB connectivity (for the bulk endpoints) after running any of the
tools (e.g. librfid-tool) for a few times.

For me, running the librfid-utils looks like this (with heavy
serial-port debugging enabled on the OpenPCD in udp_irq, attached
to this email is the actual dump):

Plugging in:

	ENDBUSRES (Bus reset...)
	...
	EP0INT (Control) bmRequestType=0x80 ...
		(Exchanging descriptor etc...)
	...
	EP0INT (Control) SET_CONFIG ...

Now waiting for commands, running e.g. mifare tool...

	EP0INT (Control) SET_CONFIG ...
	EP1INT, EP2INT ...the actual commands exchanged...

Running mifare-tools a second time...

	EP0INT (Control) SET_CONFIG ...
	EP1INT, EP2INT ...the actual commands exchanged...
		(everything interestingly almost identical to
		 1st time)

Running mifare-tools a third time...

	EP0INT (Control) SET_CONFIG ...
	-------- nothing! ----------

So it seems that the udp_irq doesn't fire for EP1 anymore. I haven't
really found out where exactly it messes up the USB controller config
and why it's hanging after running the mifare-tool exactly two times
(this is 100% reproducible), but for me I have found a solution:

In the udp_ep0_handler function in pcd_enumerate.c (starts around
line #520) add reset_ep(1); up to reset_ep(3); to the code that
handles the SET_CONFIGURATION request on the config endpoint:

	case STD_SET_CONFIGURATION:
		DEBUGE("SET_CONFIG wValue=0x02x ",wValue);
		if (upcd.state != USB_STATE_ADDRESS &&
		    upcd.state != USB_STATE_CONFIGURED) {
		    	goto out_stall;
		}
		reset_ep(1);  /* <-------------           */
		reset_ep(2);  /* <------------- HERE!     */
		reset_ep(3);  /* <-------------           */
		if ((wValue & 0xff) == 0) {
			upcd.state = USB_STATE_ADDRESS;
			pUDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
			pUDP->UDP_CSR[1] = 0;
			pUDP->UDP_CSR[2] = 0;
			pUDP->UDP_CSR[3] = 0;
		} else if ((wValue & 0xff) <=
					dev_descriptor.bNumConfigurations)
{
			upcd.state = USB_STATE_CONFIGURED;
			pUDP->UDP_GLBSTATE = AT91C_UDP_CONFG;
			pUDP->UDP_CSR[1] = AT91C_UDP_EPEDS |
					   AT91C_UDP_EPTYPE_BULK_OUT;
			pUDP->UDP_CSR[2] = AT91C_UDP_EPEDS |
					   AT91C_UDP_EPTYPE_BULK_IN;
			pUDP->UDP_CSR[3] = AT91C_UDP_EPEDS |
					   AT91C_UDP_EPTYPE_INT_IN;
		} else {
			/* invalid configuration */
			goto out_stall;
			break;
		}

My configuration:
	Linux atrocity 2.6.32.8 #4 SMP PREEMPT Sat Feb 20 21:57:24 CET 2010 i686 GNU/Linux
	Cc: arm-none-eabi-gcc, gcc version 4.4.1 (Sourcery G++ Lite 2009q3-68)
	OpenPCD SVN Revision: 495 (diff see attachment)

Greetings,

	Chris

-------------- next part --------------
A non-text attachment was scrubbed...
Name: dbug_usb.txt.gz
Type: application/octet-stream
Size: 1042 bytes
Desc: not available
Url : http://lists.openpcd.org/pipermail/openpcd-devel/attachments/20100221/6bd3cfd8/attachment.obj 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPCD_fw_trunk.diff
Type: text/x-diff
Size: 3374 bytes
Desc: not available
Url : http://lists.openpcd.org/pipermail/openpcd-devel/attachments/20100221/6bd3cfd8/attachment.bin 


More information about the openpcd-devel mailing list