Add async_usb_write_XX()

This commit is contained in:
wh201906 2023-11-14 01:12:21 +08:00
commit e1dc17df1a
No known key found for this signature in database
2 changed files with 124 additions and 3 deletions

View file

@ -114,6 +114,7 @@ AT91SAM7S256 USB Device Port
#define SET_LINE_CODING 0x2021
#define SET_CONTROL_LINE_STATE 0x2221
static bool isAsyncRequestFinished = false;
static AT91PS_UDP pUdp = AT91C_BASE_UDP;
static uint8_t btConfiguration = 0;
static uint8_t btConnection = 0;
@ -638,6 +639,10 @@ bool usb_poll(void) {
return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);
}
inline uint16_t usb_available_length(void) {
return ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16);
}
/**
In github PR #129, some users appears to get a false positive from
usb_poll, which returns true, but the usb_read operation
@ -649,7 +654,7 @@ bool usb_poll(void) {
bool usb_poll_validate_length(void) {
if (!usb_check()) return false;
if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false;
return ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) > 0;
return ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) > 0;
}
/*
@ -671,7 +676,7 @@ uint32_t usb_read(uint8_t *data, size_t len) {
if (pUdp->UDP_CSR[AT91C_EP_OUT] & bank) {
packetSize = (pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16;
packetSize = ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16);
packetSize = MIN(packetSize, len);
len -= packetSize;
while (packetSize--)
@ -727,7 +732,7 @@ uint32_t usb_read_ng(uint8_t *data, size_t len) {
if ((pUdp->UDP_CSR[AT91C_EP_OUT] & bank)) {
uint32_t available = (pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16;
uint32_t available = ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16);
packetSize = MIN(available, len);
available -= packetSize;
len -= packetSize;
@ -821,6 +826,117 @@ int usb_write(const uint8_t *data, const size_t len) {
return PM3_SUCCESS;
}
/*
*----------------------------------------------------------------------------
* \fn async_usb_write_start
* \brief Start async write process
* \return PM3_EIO if USB is invalid, PM3_SUCCESS if it is ready for write
*
* This function checks if the USB is connected, and wait until the FIFO
* is ready to be filled.
*
* Warning: usb_write() should not be called between
* async_usb_write_start() and async_usb_write_stop().
*----------------------------------------------------------------------------
*/
int async_usb_write_start(void) {
if (!usb_check()) return PM3_EIO;
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) {
if (!usb_check()) return PM3_EIO;
}
isAsyncRequestFinished = false;
return PM3_SUCCESS;
}
/*
*----------------------------------------------------------------------------
* \fn async_usb_write_pushByte
* \brief Push one byte to the FIFO of IN endpoint (time-critical)
*
* This function simply push a byte to the FIFO of IN endpoint.
* The FIFO size is AT91C_EP_IN_SIZE. Make sure this function is not called
* over AT91C_EP_IN_SIZE times between each async_usb_write_requestWrite().
*----------------------------------------------------------------------------
*/
inline void async_usb_write_pushByte(uint8_t data) {
pUdp->UDP_FDR[AT91C_EP_IN] = data;
isAsyncRequestFinished = false;
}
/*
*----------------------------------------------------------------------------
* \fn async_usb_write_requestWrite
* \brief Request a write operation (time-critical)
* \return false if the last write request is not finished, true if success
*
* This function requests a write operation from FIFO to the USB bus,
* and switch the internal banks of FIFO. It doesn't wait for the end of
* transmission from FIFO to the USB bus.
*
* Note: This function doesn't check if the usb is valid, as it is
* time-critical.
*----------------------------------------------------------------------------
*/
inline bool async_usb_write_requestWrite(void) {
// check if last request is finished
if (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) {
return false;
}
// clear transmission completed flag
UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
// start of transmission
UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
// hack: no need to wait if UDP_CSR and UDP_FDR are not used immediately.
// while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY)) {};
isAsyncRequestFinished = true;
return true;
}
/*
*----------------------------------------------------------------------------
* \fn async_usb_write_stop
* \brief Stop async write process
* \return PM3_EIO if USB is invalid, PM3_SUCCESS if data is written
*
* This function makes sure the data left in the FIFO is written to the
* USB bus.
*
* Warning: usb_write() should not be called between
* async_usb_write_start() and async_usb_write_stop().
*----------------------------------------------------------------------------
*/
int async_usb_write_stop(void) {
// Wait for the end of transfer
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) {
if (!usb_check()) return PM3_EIO;
}
// clear transmission completed flag
UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
// FIFO is not empty, request a write in non-ping-pong mode
if (isAsyncRequestFinished == false) {
UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
if (!usb_check()) return PM3_EIO;
}
UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
}
return PM3_SUCCESS;
}
/*
*----------------------------------------------------------------------------
* \fn AT91F_USB_SendData

View file

@ -27,9 +27,14 @@ void usb_disable(void);
void usb_enable(void);
bool usb_check(void);
bool usb_poll(void);
uint16_t usb_available_length(void);
bool usb_poll_validate_length(void);
uint32_t usb_read(uint8_t *data, size_t len);
int usb_write(const uint8_t *data, const size_t len);
int async_usb_write_start(void);
void async_usb_write_pushByte(uint8_t data);
bool async_usb_write_requestWrite(void);
int async_usb_write_stop(void);
uint32_t usb_read_ng(uint8_t *data, size_t len);
void usb_update_serial(uint64_t newSerialNumber);