Arduino Due Peripheral with Xbox One Controller

Hi all,

I've been working on trying to port some code from the USB Host Shield Library to the USBHost library
in order to let me use my Xbox One Controller with the Due.

I downloaded the shield code from:

Followed the guide as posted here:
http://forum.arduino.cc/index.php?topic=283058.0

I know his method works because I was successful in using a Xbox 360 Controller with this.
I compared the original USB Host Shield Library with the modded one in WinMerge and made the same changes to the Xbox One code but I still get NAKs.

After enabling the debugging print statements in the XBOXONE.cpp and Usb.cpp, the output is shown here:

Xbox One Controller Disconnected
 + USB_ATTACHED_SUBSTATE_SETTLE
 + USB_ATTACHED_SUBSTATE_RESET_DEVICE
 + USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE
 + USB_ATTACHED_SUBSTATE_WAIT_SOF
 + USB_STATE_CONFIGURING

XBOXONE InitctrlReq
 nak_limit Before 2848409796 bmNakPower16 nak_limit After 65535     => SetAddress deviceEP=0 configued as hostPIPE=0 sending to address=0
     => dispatchPkt token=0 pipe=0 nak_limit=65535
    => ctrlData IN
nak_limit FFFF
     => dispatchPkt token=256 pipe=0 nak_limit=65535
     => dispatchPkt token=512 pipe=0 nak_limit=65535
   => USBHost::setAddr
    => ctrlReq
 nak_limit Before 0 bmNakPower0 nak_limit After 0 => SetAddress deviceEP=0 configued as hostPIPE=0 sending to address=0
     => dispatchPkt token=0 pipe=0 nak_limit=0
     => dispatchPkt token=256 pipe=0 nak_limit=0

Addr: 1    => ctrlReq
 nak_limit Before 532847 bmNakPower16 nak_limit After 65535     => SetAddress deviceEP=0 configued as hostPIPE=0 sending to address=1
     => dispatchPkt token=0 pipe=0 nak_limit=65535
     => dispatchPkt token=256 pipe=0 nak_limit=65535

Xbox One Controller Connected
 nak_limit Before 0 bmNakPower1 nak_limit After 1     => SetAddress deviceEP=1 configued as hostPIPE=0 sending to address=1
     => dispatchPkt token=512 pipe=0 nak_limit=1

XboxCommand, Return: 0 nak_limit Before 0 bmNakPower1 nak_limit After 1Address deviceEP=1 configued as hostPIPE=0 sending to address=1
     => dispatchPkt token=512 pipe=0 nak_limit=1

XboxCommand, Return: 0t::Configuring : found device class!
 + USB_STATE_RUNNING
 nak_limit Before 0 bmNakPower1 nak_limit After 1=> SetAddress deviceEP=1 configued as hostPIPE=0 sending to address=1
rcode 0nak_limit 1
    => dispatchPkt token=256 pipe=0 nak_limit=1
rcode: 1

Xbox One Poll Failed, error code: 1 nak_limit Before 0 bmNakPower1 nak_limit After 1    => SetAddress deviceEP=1 configued as hostPIPE=0 sending to address=1
rcode 0nak_limit 1
    => dispatchPkt token=256 pipe=0 nak_limit=1
rcode: 1

Xbox One Poll Failed, error code: 1 nak_limit Before 0 bmNakPower1 nak_limit After 1=> SetAddress deviceEP=1 configued as hostPIPE=0 sending to address=1
rcode 0nak_limit 1
     => dispatchPkt token=256 pipe=0 nak_limit=1
rcode: 1

I added my own print statements to and followed through the usb.cpp code to find that the nak_limit gets set to 1 and causes a problem here.
A NAK will always be returned if the nak_limit is 1 and so that should be the problem.

 // Is NAK received?
 if (Is_uhd_nak_received(hostPipeNum))
 {
 uhd_ack_nak_received(hostPipeNum);
 nak_count++;

 if (nak_limit && (nak_count == nak_limit))
 {
 // Return NAK
 return 1;
 }
 }

nak_limit gets to 1 in the setPipeAddress function from this piece of code here:

nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER ) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
nak_limit--;

The problem is that bmNakPower gets set to 1 somehow and that's where I get lost.

I think the key is in how this piece of code works in the address.h

struct EpInfo
{
 uint32_t deviceEpNum; // Device endpoint number
 uint32_t hostPipeNum; // Host corresponding pipe number
 uint32_t maxPktSize; // Maximum packet size

 union
 {
 uint8_t epAttribs;

 struct
 {
 uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise
 uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise
 uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value
 };
 };
};

I believe epAttribs, bmSndToggle, bmRcvToggle and bmNakPower are linked to the same space of memory as per the union and one of them gets set to 1 causing bmNakPower to be 1.

Attached are my WIP files for the USBHost library and my test code.

If anyone has done this before or could lead me in the right direction please let me know!

Thanks,

Owen

XBOXONEDUE.cpp (13.5 KB)

XBOXONEDUE.h (5.88 KB)

Usb.cpp (23.4 KB)

Usb.h (8.84 KB)

Rover_v1.0.ino (3.41 KB)

I am receiving similar problems, with the same library, but with a Logitech extreme 3d pro joystick.