# Bugs in Maxim chip MAX3421E (used as USB Host)

The MAX3421E is an USB client/host chip from Maxim which can be controled by SPI.

Can anybody confirm that there are bugs in the chip or at least confirm that the chip does not always do what the documentation says?

I found several bugs / oddities / misdesigns and would like to know if I'am the only one experiencing this. USB programming is very complex and may be I did something wrong.

• have you had any luck with contacting Maxim about the issue? – jsotola May 3 '18 at 21:40
• Did you read my answer ? – Elmue May 4 '18 at 22:49

I'am working with this chip now since several months and finding out all the below stuff has costed me a lot of time because debugging is difficult in an embedded processor where I cannot easily attach a debugger.

As I could not find anything about these problems in internet I'am the first to post about this and I hope it will be useful for someone running into the same problems.

I found the following bugs / oddities / misdesigns which I posted to the Maxim support. But they told me that they do not work anymore on this chip and that they do not have plans to make a new version. Finally they did not respond to my bug reports so I still do not know if these are confirmed bugs or not.

They told me that there exist only 3 versions of the MAX3421E chip. The version can be read from register 18.

• Version 1 returned as 0x01
• Version 2 returned as 0x12
• Version 3 returned as 0x13 (= decimal 19. I have this version)

# Misdesign 1:

The Programming Guide says:

As the documentation says: The RemoteWakeUp signal is only detected if it is at least 10 ms long. But I have no device (keyboard, mouse) which sends such a long signal.

My mouse and keyboard send a remote wakeup of 5 ms which is NOT DETECTED by the MAX3421. This is a severe misdesign because the USB documentation says that a remote wakeup K condition may be between 1 and 15 ms.

# BUG 2:

The Programming Guide says:

I wait for the OSCOKIRQ beeing set by reading USBIRQ repeatedly and I wait forever. It is never set. NOTE: I do not use external hardware interrupt and I do not use OSCOKIE.

# BUG 3:

The Programming Guide says:

The SAMPLEBUS works correctly with one exception: If you have additionally set the HUBPRE bit in the MODE register the SAMPLEBUS will return a wrong result.

HUBPRE should not affect the SAMPLEBUS result.

# BUG 4:

The Programming Guide says:

This works fine. If I detect that the RCVDAVIRQ is set and I reset it then, there is no problem.

But if I write a code which resets the RCVDAVIRQ ALTHOUGH it was NOT set before, then the RECV FIFO will be toggled and further read operations will fail.

This is a wrong chip design. If I reset a flag which is already reset, this should have no effect at all.

# Misdesign 5:

I use the chip in Host Mode. It communicates with a Microsoft keyboard.

Before sending an OUT packet to the USB device I execute this code:

if ((ReadRegister(HIRQ) & SNDBAVIRQ) == 0)
{
TRACE("Send Buffer not available");
}


The Programming Guide says:

I cannot see any reason why the chip is designed like this? Why isn't it allowed to reset the SNDBAVIRQ flag and so to free the send FIFO? What is the reason behind this design?

Then I tried to write to the SNDBC register to free the send buffer as the manual says. But THIS DOES NOT WORK.

This can be proven with this code:

if ((ReadRegister(HIRQ) & SNDBAVIRQ) == 0)
{
TRACE("Send Buffer not available");

WriteRegister(SNDBC, 0);

if ((ReadRegister(HIRQ) & SNDBAVIRQ) == 0)
{
TRACE("Send Buffer STILL not available");
}
}


Here the chip does NOT behave as the documentation says. I tried also to write 1 instead of 0 to SNDBC without any success.

To really free the send FIFO I must also write the HXFR register to re-send the data. But this is no solution in my case because the devices STALLs the request again and the data is not send and the send buffer is still not freed.

How to reproduce this bug:

Connect a HID keyboard to the MAX3421

Set the configuration with SET_CONFIGURATION 1

My keyboard has a HID report which allows to set the LEDs in the keyboard with a SET_REPORT to Interface= 0, Type= Output, Length= 1:

EP 00 SETUP:  [8 byte] 21 09 00 02 00 00 01 00
EP 00 OUT:    [1 byte] 07
EP 00 IN:     [no data]


This command turns on all 3 LEDs (Caps Lock, Scroll Lock, Num Lock)

Find out which command you need to do the same on your keyboard

Now send a command which is not supported by most USB devices:

EP 00 SETUP:  [8 byte] 21 09 00 01 00 00 01 00
EP 00 OUT:    [1 byte] 07
-> STALL


As you see I replaced 02 (Output) with 01 (Input) which is not supported by my keyboard. The keyboard STALLs my request in the OUT phase of the control transfer and the send FIFO stays occupied.

Now produce this error a second time, so both send FIFOs will be occupied.

The next time you want send ANYTHING to the device you will get the "Send Buffer not available" message from above.

The problem is in the design of the MAX3421. The send buffer is ONLY freed when the last OUT transfer has been ACKed by the device. And if the device sends a NAK it can easily be resent as the documentation says. But for a STALL there is no solution how to free the send FIFO.

So how to solve this issue? Maxim does not allow me to reset the SNDBAVIRQ flag and writing SNDBC does not work neither, so I'am stuck. I cannot communicate with the device anymore because both send FIFOs are occupied now.

• Wrong Website. This should better go to maxim support, so they can fix their documentation. – Turbo J May 4 '18 at 3:41
• Did you read my answer ? – Elmue May 4 '18 at 22:49
• Re: bug2, if you're polling and not using an jnterrupt, how do you know you're not missing a fast event? – Scott Seidman Sep 27 '18 at 11:16
• Well, if you have read the documentation you know that the interrupts stay set until you reset them manually. It says: "The CPU clears the OSCOKIRQ bit by writing a 1 to it". All interrupts work the same way. And generally all interrupts work correctly, except this one. By the way: If I would use OSCOKIE and a hardware interrupt instead of polling, this would not change anything. When the hardware interrupt is signaled you must check all the interrupt flags that possibly may have triggered the interrupt. Note that there is only one interrupt line (the INT pin) to signal several interrupts. – Elmue Oct 1 '18 at 15:34