forked from atlas44/sam-fusee-launcher
-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
noemu
committed
Jul 13, 2018
1 parent
90cc327
commit 6ebdd12
Showing
4 changed files
with
258 additions
and
309 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
#include <Arduino.h> | ||
#include <Usb.h> | ||
|
||
#define INTERMEZZO_SIZE 92 | ||
const byte intermezzo[INTERMEZZO_SIZE] = | ||
{ | ||
0x44, 0x00, 0x9F, 0xE5, 0x01, 0x11, 0xA0, 0xE3, 0x40, 0x20, 0x9F, 0xE5, 0x00, 0x20, 0x42, 0xE0, | ||
0x08, 0x00, 0x00, 0xEB, 0x01, 0x01, 0xA0, 0xE3, 0x10, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0xA0, 0xE1, | ||
0x2C, 0x00, 0x9F, 0xE5, 0x2C, 0x10, 0x9F, 0xE5, 0x02, 0x28, 0xA0, 0xE3, 0x01, 0x00, 0x00, 0xEB, | ||
0x20, 0x00, 0x9F, 0xE5, 0x10, 0xFF, 0x2F, 0xE1, 0x04, 0x30, 0x90, 0xE4, 0x04, 0x30, 0x81, 0xE4, | ||
0x04, 0x20, 0x52, 0xE2, 0xFB, 0xFF, 0xFF, 0x1A, 0x1E, 0xFF, 0x2F, 0xE1, 0x20, 0xF0, 0x01, 0x40, | ||
0x5C, 0xF0, 0x01, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, 0x40, | ||
}; | ||
|
||
#define PACKET_CHUNK_SIZE 0x1000 | ||
|
||
|
||
USBHost usb; | ||
EpInfo epInfo[3]; | ||
|
||
byte usbWriteBuffer[PACKET_CHUNK_SIZE] = {0}; | ||
uint32_t usbWriteBufferUsed = 0; | ||
uint32_t packetsWritten = 0; | ||
|
||
bool foundTegra = false; | ||
byte tegraDeviceAddress = -1; | ||
|
||
unsigned long lastCheckTime = 0; | ||
|
||
// From what I can tell, usb.outTransfer is completely broken for transfers larger than 64 bytes (even if maxPktSize is | ||
// adjusted for that endpoint). This is a minimal and simplified reimplementation specific to our use cases that fixes | ||
// that bug and is based on the code of USBHost::outTransfer, USBHost::SetPipeAddress and USBHost::OutTransfer. | ||
void usbOutTransferChunk(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data) | ||
{ | ||
EpInfo* epInfo = usb.getEpInfoEntry(addr, ep); | ||
|
||
usb_pipe_table[epInfo->epAddr].HostDescBank[0].CTRL_PIPE.bit.PDADDR = addr; | ||
|
||
if (epInfo->bmSndToggle) | ||
USB->HOST.HostPipe[epInfo->epAddr].PSTATUSSET.reg = USB_HOST_PSTATUSSET_DTGL; | ||
else | ||
USB->HOST.HostPipe[epInfo->epAddr].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_DTGL; | ||
|
||
UHD_Pipe_Write(epInfo->epAddr, PACKET_CHUNK_SIZE, data); | ||
uint32_t rcode = usb.dispatchPkt(tokOUT, epInfo->epAddr, 15); | ||
if (rcode) | ||
{ | ||
if (rcode == USB_ERROR_DATATOGGLE) | ||
{ | ||
epInfo->bmSndToggle = USB_HOST_DTGL(epInfo->epAddr); | ||
if (epInfo->bmSndToggle) | ||
USB->HOST.HostPipe[epInfo->epAddr].PSTATUSSET.reg = USB_HOST_PSTATUSSET_DTGL; | ||
else | ||
USB->HOST.HostPipe[epInfo->epAddr].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_DTGL; | ||
} | ||
else | ||
{ | ||
//setLedColor("red"); //add error code and stop execution | ||
return; | ||
} | ||
} | ||
epInfo->bmSndToggle = USB_HOST_DTGL(epInfo->epAddr); | ||
} | ||
|
||
void usbFlushBuffer() | ||
{ | ||
usbOutTransferChunk(tegraDeviceAddress, 0x01, PACKET_CHUNK_SIZE, usbWriteBuffer); | ||
|
||
memset(usbWriteBuffer, 0, PACKET_CHUNK_SIZE); | ||
usbWriteBufferUsed = 0; | ||
packetsWritten++; | ||
} | ||
|
||
// This accepts arbitrary sized USB writes and will automatically chunk them into writes of size 0x1000 and increment | ||
// packetsWritten every time a chunk is written out. | ||
void usbBufferedWrite(const byte *data, uint32_t length) | ||
{ | ||
while (usbWriteBufferUsed + length >= PACKET_CHUNK_SIZE) | ||
{ | ||
uint32_t bytesToWrite = min(PACKET_CHUNK_SIZE - usbWriteBufferUsed, length); | ||
memcpy(usbWriteBuffer + usbWriteBufferUsed, data, bytesToWrite); | ||
usbWriteBufferUsed += bytesToWrite; | ||
usbFlushBuffer(); | ||
data += bytesToWrite; | ||
length -= bytesToWrite; | ||
} | ||
|
||
if (length > 0) | ||
{ | ||
memcpy(usbWriteBuffer + usbWriteBufferUsed, data, length); | ||
usbWriteBufferUsed += length; | ||
} | ||
} | ||
|
||
void usbBufferedWriteU32(uint32_t data) | ||
{ | ||
usbBufferedWrite((byte *)&data, 4); | ||
} | ||
|
||
void readTegraDeviceID(byte *deviceID) | ||
{ | ||
byte readLength = 16; | ||
UHD_Pipe_Alloc(tegraDeviceAddress, 0x01, USB_HOST_PTYPE_BULK, USB_EP_DIR_IN, 0x40, 0, USB_HOST_NB_BK_1); | ||
|
||
if (usb.inTransfer(tegraDeviceAddress, 0x01, &readLength, deviceID)) | ||
return; //false; //add breakpoint | ||
} | ||
|
||
void sendPayload(const byte *payload, uint32_t payloadLength) | ||
{ | ||
byte zeros[0x1000] = {0}; | ||
|
||
usbBufferedWriteU32(0x30298); | ||
usbBufferedWrite(zeros, 680 - 4); | ||
|
||
for (uint32_t i = 0; i < 0x3C00; i++) | ||
usbBufferedWriteU32(0x4001F000); | ||
|
||
usbBufferedWrite(intermezzo, INTERMEZZO_SIZE); | ||
usbBufferedWrite(zeros, 0xFA4); | ||
usbBufferedWrite(payload, payloadLength); | ||
usbFlushBuffer(); | ||
|
||
if (packetsWritten % 2 != 1) | ||
{ | ||
usbFlushBuffer(); | ||
} | ||
} | ||
|
||
void findTegraDevice(UsbDeviceDefinition *pdev) | ||
{ | ||
uint32_t address = pdev->address.devAddress; | ||
USB_DEVICE_DESCRIPTOR deviceDescriptor; | ||
if (usb.getDevDescr(address, 0, 0x12, (uint8_t *)&deviceDescriptor)) | ||
{ | ||
return; //false; //add breakpoint | ||
} | ||
|
||
if (deviceDescriptor.idVendor == 0x0955 && deviceDescriptor.idProduct == 0x7321) | ||
{ | ||
tegraDeviceAddress = address; | ||
foundTegra = true; | ||
} | ||
} | ||
|
||
boolean searchTegraDevice() | ||
{ | ||
usb.Task(); | ||
usb.ForEachUsbDevice(&findTegraDevice); | ||
return foundTegra; | ||
} | ||
|
||
int usbInit() | ||
{ | ||
return usb.Init(); | ||
} | ||
|
||
void setupTegraDevice() | ||
{ | ||
epInfo[0].epAddr = 0; | ||
epInfo[0].maxPktSize = 0x40; | ||
epInfo[0].epAttribs = USB_TRANSFER_TYPE_CONTROL; | ||
epInfo[0].bmNakPower = USB_NAK_MAX_POWER; | ||
epInfo[0].bmSndToggle = 0; | ||
epInfo[0].bmRcvToggle = 0; | ||
|
||
epInfo[1].epAddr = 0x01; | ||
epInfo[1].maxPktSize = 0x40; | ||
epInfo[1].epAttribs = USB_TRANSFER_TYPE_BULK; | ||
epInfo[1].bmNakPower = USB_NAK_MAX_POWER; | ||
epInfo[1].bmSndToggle = 0; | ||
epInfo[1].bmRcvToggle = 0; | ||
|
||
usb.setEpInfoEntry(tegraDeviceAddress, 2, epInfo); | ||
usb.setConf(tegraDeviceAddress, 0, 0); | ||
usb.Task(); | ||
|
||
UHD_Pipe_Alloc(tegraDeviceAddress, 0x01, USB_HOST_PTYPE_BULK, USB_EP_DIR_IN, 0x40, 0, USB_HOST_NB_BK_1); | ||
|
||
byte deviceID[16] = {0}; | ||
readTegraDeviceID(deviceID); | ||
|
||
UHD_Pipe_Alloc(tegraDeviceAddress, 0x01, USB_HOST_PTYPE_BULK, USB_EP_DIR_OUT, 0x40, 0, USB_HOST_NB_BK_1); | ||
packetsWritten = 0; | ||
} | ||
|
||
void launchPayload() | ||
{ | ||
usb.ctrlReq(tegraDeviceAddress, 0, USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE, | ||
0x00, 0x00, 0x00, 0x00, 0x7000, 0x7000, usbWriteBuffer, NULL); | ||
} | ||
|
Oops, something went wrong.