mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-07-06 21:21:17 -07:00
Always enable fast response mode (was enabled for flasher only)
* ensure that CMD_ACK is used exclusively for the very last response of each PM3 operation. All Dbprintf() must be before. * always switch off field before exiting * append null packet for USB transfers % 64 bytes * reformatting and whitespace fixes
This commit is contained in:
parent
b8ed9975e5
commit
929b61c670
17 changed files with 501 additions and 474 deletions
13
armsrc/epa.c
13
armsrc/epa.c
|
@ -453,20 +453,17 @@ int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Perform the PACE protocol by replaying given APDUs
|
// Perform the PACE protocol by replaying given APDUs
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void EPA_PACE_Replay(UsbCommand *c)
|
void EPA_PACE_Replay(UsbCommand *c) {
|
||||||
{
|
|
||||||
uint32_t timings[sizeof(apdu_lengths_replay) / sizeof(apdu_lengths_replay[0])] = {0};
|
uint32_t timings[sizeof(apdu_lengths_replay) / sizeof(apdu_lengths_replay[0])] = {0};
|
||||||
|
|
||||||
// if an APDU has been passed, save it
|
// if an APDU has been passed, just save it
|
||||||
if (c->arg[0] != 0) {
|
if (c->arg[0] != 0) {
|
||||||
// make sure it's not too big
|
// make sure it's not too big
|
||||||
if(c->arg[2] > apdus_replay[c->arg[0] - 1].len)
|
if(c->arg[2] > apdus_replay[c->arg[0] - 1].len) {
|
||||||
{
|
|
||||||
cmd_send(CMD_ACK, 1, 0, 0, NULL, 0);
|
cmd_send(CMD_ACK, 1, 0, 0, NULL, 0);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1],
|
memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1], c->d.asBytes, c->arg[2]);
|
||||||
c->d.asBytes,
|
|
||||||
c->arg[2]);
|
|
||||||
// save/update APDU length
|
// save/update APDU length
|
||||||
if (c->arg[1] == 0) {
|
if (c->arg[1] == 0) {
|
||||||
apdu_lengths_replay[c->arg[0] - 1] = c->arg[2];
|
apdu_lengths_replay[c->arg[0] - 1] = c->arg[2];
|
||||||
|
|
|
@ -733,7 +733,6 @@ void ReaderIClass(uint8_t flags) {
|
||||||
if (selectIclassTag(resp, &eof_time)) {
|
if (selectIclassTag(resp, &eof_time)) {
|
||||||
result_status = FLAG_ICLASS_READER_CSN;
|
result_status = FLAG_ICLASS_READER_CSN;
|
||||||
memcpy(card_data, resp, 8);
|
memcpy(card_data, resp, 8);
|
||||||
}
|
|
||||||
|
|
||||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||||
|
|
||||||
|
@ -768,6 +767,7 @@ void ReaderIClass(uint8_t flags) {
|
||||||
Dbprintf("Failed to read AA block");
|
Dbprintf("Failed to read AA block");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cmd_send(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data));
|
cmd_send(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data));
|
||||||
|
|
||||||
|
@ -819,9 +819,9 @@ void iClass_ReadBlk(uint8_t blockno) {
|
||||||
|
|
||||||
uint8_t readblockdata[10];
|
uint8_t readblockdata[10];
|
||||||
bool isOK = iClass_ReadBlock(blockno, readblockdata);
|
bool isOK = iClass_ReadBlock(blockno, readblockdata);
|
||||||
cmd_send(CMD_ACK, isOK, 0, 0, readblockdata, 8);
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
|
cmd_send(CMD_ACK, isOK, 0, 0, readblockdata, 8);
|
||||||
|
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
}
|
}
|
||||||
|
@ -899,11 +899,10 @@ void iClass_WriteBlock(uint8_t blockNo, uint8_t *data) {
|
||||||
} else {
|
} else {
|
||||||
Dbprintf("Write block [%02x] failed", blockNo);
|
Dbprintf("Write block [%02x] failed", blockNo);
|
||||||
}
|
}
|
||||||
cmd_send(CMD_ACK, isOK, 0, 0, 0, 0);
|
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
|
|
||||||
|
cmd_send(CMD_ACK, isOK, 0, 0, 0, 0);
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -934,6 +933,5 @@ void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) {
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
|
|
||||||
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
|
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
|
||||||
|
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2048,7 +2048,7 @@ void ReaderIso14443a(UsbCommand *c) {
|
||||||
}
|
}
|
||||||
FpgaDisableTracing();
|
FpgaDisableTracing();
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
cmd_send(CMD_ACK,arg0,card->uidlen,0,buf,sizeof(iso14a_card_select_t));
|
cmd_send(CMD_NACK,arg0,card->uidlen,0,buf,sizeof(iso14a_card_select_t));
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,11 +111,12 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
|
if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
|
||||||
|
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);
|
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,9 +203,10 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_send(CMD_ACK,1,0,0,dataout,16);
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
|
|
||||||
|
cmd_send(CMD_ACK,1,0,0,dataout,16);
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,12 +268,13 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED");
|
if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED");
|
||||||
|
|
||||||
|
// Thats it...
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16*NumBlocksPerSector(sectorNo));
|
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16*NumBlocksPerSector(sectorNo));
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
// Thats it...
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,10 +365,11 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= MF_DBG_DEBUG) Dbprintf("Blocks read %d", countblocks);
|
if (MF_DBGLEVEL >= MF_DBG_DEBUG) Dbprintf("Blocks read %d", countblocks);
|
||||||
|
|
||||||
cmd_send(CMD_ACK, 1, countblocks*4, BigBuf_max_traceLen(), 0, 0);
|
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
|
|
||||||
|
cmd_send(CMD_ACK, 1, countblocks*4, BigBuf_max_traceLen(), 0, 0);
|
||||||
|
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
}
|
}
|
||||||
|
@ -431,13 +435,14 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||||
|
|
||||||
|
// Thats it...
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
|
|
||||||
// Thats it...
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,8 +480,9 @@ void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain)
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||||
|
|
||||||
cmd_send(CMD_ACK,1,0,0,0,0);
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
|
||||||
|
cmd_send(CMD_ACK,1,0,0,0,0);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
@ -544,8 +550,9 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||||
|
|
||||||
cmd_send(CMD_ACK,1,0,0,0,0);
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
|
||||||
|
cmd_send(CMD_ACK,1,0,0,0,0);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,8 +620,9 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
cmd_send(CMD_ACK,1,0,0,0,0);
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
|
||||||
|
cmd_send(CMD_ACK,1,0,0,0,0);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -743,16 +751,17 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
||||||
|
|
||||||
crypto1_destroy(pcs);
|
crypto1_destroy(pcs);
|
||||||
|
|
||||||
|
if (field_off) {
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
LEDsoff();
|
||||||
|
}
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf));
|
cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf));
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished");
|
if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished");
|
||||||
|
|
||||||
if (field_off) {
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -978,13 +987,14 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
||||||
memcpy(buf+16, &target_ks[1], 4);
|
memcpy(buf+16, &target_ks[1], 4);
|
||||||
memcpy(buf+20, &authentication_timeout, 4);
|
memcpy(buf+20, &authentication_timeout, 4);
|
||||||
|
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
|
||||||
|
if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf));
|
cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf));
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");
|
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1352,13 +1362,14 @@ void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset fpga
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
|
||||||
// send USB response
|
// send USB response
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
cmd_send(CMD_ACK,isOK,0,0,NULL,0);
|
cmd_send(CMD_ACK,isOK,0,0,NULL,0);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
// reset fpga
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -1490,15 +1501,16 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((workFlags & 0x10) || (!isOK)) {
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
}
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
cmd_send(CMD_ACK,isOK,0,0,uid,4);
|
cmd_send(CMD_ACK,isOK,0,0,uid,4);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
if ((workFlags & 0x10) || (!isOK)) {
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
|
void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
|
||||||
|
@ -1574,6 +1586,10 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((workFlags & 0x10) || (!isOK)) {
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
}
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
if (workFlags & 0x20) {
|
if (workFlags & 0x20) {
|
||||||
if (isOK)
|
if (isOK)
|
||||||
|
@ -1583,11 +1599,8 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
cmd_send(CMD_ACK,isOK,0,0,data,18);
|
cmd_send(CMD_ACK,isOK,0,0,data,18);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
if ((workFlags & 0x10) || (!isOK)) {
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void MifareCIdent(){
|
void MifareCIdent(){
|
||||||
|
|
||||||
|
@ -1622,11 +1635,12 @@ void MifareCIdent(){
|
||||||
// From iceman1001: removed the if, since some magic tags misbehavies and send an answer to it.
|
// From iceman1001: removed the if, since some magic tags misbehavies and send an answer to it.
|
||||||
mifare_classic_halt(NULL, 0);
|
mifare_classic_halt(NULL, 0);
|
||||||
|
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1657,6 +1671,7 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");
|
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");
|
||||||
|
|
||||||
cmd_send(CMD_ACK, 1, cuid, 0, dataout, sizeof(dataout));
|
cmd_send(CMD_ACK, 1, cuid, 0, dataout, sizeof(dataout));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1677,10 +1692,11 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED");
|
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED");
|
||||||
|
|
||||||
cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));
|
cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,7 +152,7 @@ bool intMfSniffSend() {
|
||||||
while (pckLen > 0) {
|
while (pckLen > 0) {
|
||||||
pckSize = MIN(USB_CMD_DATA_SIZE, pckLen);
|
pckSize = MIN(USB_CMD_DATA_SIZE, pckLen);
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
cmd_send(CMD_ACK, 1, BigBuf_get_traceLen(), pckSize, trace + BigBuf_get_traceLen() - pckLen, pckSize);
|
cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, 1, BigBuf_get_traceLen(), pckSize, trace + BigBuf_get_traceLen() - pckLen, pckSize);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
pckLen -= pckSize;
|
pckLen -= pckSize;
|
||||||
|
@ -160,7 +160,7 @@ bool intMfSniffSend() {
|
||||||
}
|
}
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
cmd_send(CMD_ACK,2,0,0,0,0);
|
cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K,2,0,0,0,0);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
|
|
@ -51,7 +51,7 @@ int Hf14443_4aGetCardData(iso14a_card_select_t * card) {
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
|
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
WaitForResponse(CMD_ACK,&resp);
|
WaitForResponse(CMD_NACK, &resp);
|
||||||
|
|
||||||
memcpy(card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
|
memcpy(card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
|
||||||
|
|
||||||
|
@ -156,13 +156,17 @@ int CmdHF14AReader(const char *Cmd) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdHF14AInfo(const char *Cmd)
|
|
||||||
{
|
int CmdHF14AInfo(const char *Cmd) {
|
||||||
|
|
||||||
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}};
|
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}};
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
|
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
WaitForResponse(CMD_ACK,&resp);
|
if (!WaitForResponseTimeout(CMD_NACK, &resp, 500)) {
|
||||||
|
if (Cmd[0] != 's') PrintAndLog("Error: No response from Proxmark.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
iso14a_card_select_t card;
|
iso14a_card_select_t card;
|
||||||
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
|
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
|
||||||
|
@ -217,7 +221,7 @@ int CmdHF14AInfo(const char *Cmd)
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
|
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
WaitForResponse(CMD_ACK,&resp);
|
WaitForResponse(CMD_NACK,&resp);
|
||||||
|
|
||||||
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
|
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
|
||||||
|
|
||||||
|
@ -462,7 +466,7 @@ int CmdHF14ACUIDs(const char *Cmd)
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
|
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
WaitForResponse(CMD_ACK,&resp);
|
WaitForResponse(CMD_NACK,&resp);
|
||||||
|
|
||||||
iso14a_card_select_t *card = (iso14a_card_select_t *) resp.d.asBytes;
|
iso14a_card_select_t *card = (iso14a_card_select_t *) resp.d.asBytes;
|
||||||
|
|
||||||
|
|
|
@ -333,7 +333,7 @@ int HFiClassReader(bool loop, bool verbose) {
|
||||||
|
|
||||||
while (!ukbhit()) {
|
while (!ukbhit()) {
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {
|
||||||
uint8_t readStatus = resp.arg[0] & 0xff;
|
uint8_t readStatus = resp.arg[0] & 0xff;
|
||||||
uint8_t *data = resp.d.asBytes;
|
uint8_t *data = resp.d.asBytes;
|
||||||
|
|
||||||
|
@ -368,7 +368,8 @@ int HFiClassReader(bool loop, bool verbose) {
|
||||||
|
|
||||||
if (tagFound && !loop) return 1;
|
if (tagFound && !loop) return 1;
|
||||||
} else {
|
} else {
|
||||||
if (verbose) PrintAndLog("Command execute timeout");
|
if (verbose) PrintAndLog("Error: No response from Proxmark.");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (!loop) break;
|
if (!loop) break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2672,7 +2672,7 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
}
|
}
|
||||||
|
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
if (WaitForResponseTimeoutW(CMD_ACK, &resp, 2000, false)) {
|
if (WaitForResponseTimeoutW(CMD_UNKNOWN, &resp, 2000, false)) {
|
||||||
res = resp.arg[0] & 0xff;
|
res = resp.arg[0] & 0xff;
|
||||||
uint16_t traceLen = resp.arg[1];
|
uint16_t traceLen = resp.arg[1];
|
||||||
len = resp.arg[2];
|
len = resp.arg[2];
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "comms.h"
|
#include "comms.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
@ -33,7 +34,6 @@ static bool offline;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool run; // If TRUE, continue running the uart_communication thread
|
bool run; // If TRUE, continue running the uart_communication thread
|
||||||
bool block_after_ACK; // if true, block after receiving an ACK package
|
|
||||||
} communication_arg_t;
|
} communication_arg_t;
|
||||||
|
|
||||||
static communication_arg_t conn;
|
static communication_arg_t conn;
|
||||||
|
@ -195,10 +195,12 @@ static bool receive_from_serial(serial_port sp, uint8_t *rx_buf, size_t len, siz
|
||||||
*received_len = 0;
|
*received_len = 0;
|
||||||
// we eventually need to call uart_receive several times if it times out in the middle of a transfer
|
// we eventually need to call uart_receive several times if it times out in the middle of a transfer
|
||||||
while (uart_receive(sp, rx_buf + *received_len, len - *received_len, &bytes_read) && bytes_read && *received_len < len) {
|
while (uart_receive(sp, rx_buf + *received_len, len - *received_len, &bytes_read) && bytes_read && *received_len < len) {
|
||||||
|
#ifdef COMMS_DEBUG
|
||||||
if (bytes_read != len - *received_len) {
|
if (bytes_read != len - *received_len) {
|
||||||
printf("uart_receive() returned true but not enough bytes could be received. received: %d, wanted to receive: %d, already received before: %d\n",
|
printf("uart_receive() returned true but not enough bytes could be received. received: %d, wanted to receive: %d, already received before: %d\n",
|
||||||
bytes_read, len - *received_len, *received_len);
|
bytes_read, len - *received_len, *received_len);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
*received_len += bytes_read;
|
*received_len += bytes_read;
|
||||||
bytes_read = 0;
|
bytes_read = 0;
|
||||||
}
|
}
|
||||||
|
@ -231,12 +233,12 @@ __attribute__((force_align_arg_pointer))
|
||||||
if (receive_from_serial(sp, prx, bytes_to_read, &rxlen)) {
|
if (receive_from_serial(sp, prx, bytes_to_read, &rxlen)) {
|
||||||
prx += rxlen;
|
prx += rxlen;
|
||||||
if (response->cmd & CMD_VARIABLE_SIZE_FLAG) { // new style response with variable size
|
if (response->cmd & CMD_VARIABLE_SIZE_FLAG) { // new style response with variable size
|
||||||
// printf("received new style response %04" PRIx16 ", datalen = %d, arg[0] = %08" PRIx32 ", arg[1] = %08" PRIx32 ", arg[2] = %08" PRIx32 "\n",
|
// PrintAndLog("received new style response %04" PRIx16 ", datalen = %d, arg[0] = %08" PRIx32 ", arg[1] = %08" PRIx32 ", arg[2] = %08" PRIx32 "\n",
|
||||||
// response->cmd, response->datalen, response->arg[0], response->arg[1], response->arg[2]);
|
// response->cmd, response->datalen, response->arg[0], response->arg[1], response->arg[2]);
|
||||||
bytes_to_read = response->datalen;
|
bytes_to_read = response->datalen;
|
||||||
if (receive_from_serial(sp, prx, bytes_to_read, &rxlen)) {
|
if (receive_from_serial(sp, prx, bytes_to_read, &rxlen)) {
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
resp.cmd = response->cmd & ~CMD_VARIABLE_SIZE_FLAG;
|
resp.cmd = response->cmd & ~CMD_VARIABLE_SIZE_FLAG; // remove the flag
|
||||||
resp.arg[0] = response->arg[0];
|
resp.arg[0] = response->arg[0];
|
||||||
resp.arg[1] = response->arg[1];
|
resp.arg[1] = response->arg[1];
|
||||||
resp.arg[2] = response->arg[2];
|
resp.arg[2] = response->arg[2];
|
||||||
|
@ -247,7 +249,7 @@ __attribute__((force_align_arg_pointer))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // old style response uses same data structure as commands. Fixed size.
|
} else { // old style response uses same data structure as commands. Fixed size.
|
||||||
// printf("received old style response %016" PRIx64 ", arg[0] = %016" PRIx64 "\n", command->cmd, command->arg[0]);
|
// PrintAndLog("received old style response %016" PRIx64 ", arg[0] = %016" PRIx64 "\n", command->cmd, command->arg[0]);
|
||||||
bytes_to_read = sizeof(UsbCommand) - bytes_to_read;
|
bytes_to_read = sizeof(UsbCommand) - bytes_to_read;
|
||||||
if (receive_from_serial(sp, prx, bytes_to_read, &rxlen)) {
|
if (receive_from_serial(sp, prx, bytes_to_read, &rxlen)) {
|
||||||
UsbCommandReceived(command);
|
UsbCommandReceived(command);
|
||||||
|
@ -259,24 +261,21 @@ __attribute__((force_align_arg_pointer))
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&txBufferMutex);
|
pthread_mutex_lock(&txBufferMutex);
|
||||||
|
// if we received an ACK the PM has done its job and waits for another command.
|
||||||
if (conn->block_after_ACK) {
|
// We therefore can wait here as well until a new command is to be transmitted.
|
||||||
// if we just received an ACK, wait here until a new command is to be transmitted
|
// The advantage is that the next command will be transmitted immediately without the need to wait for a receive timeout
|
||||||
if (ACK_received) {
|
if (ACK_received) {
|
||||||
while (!txBuffer_pending) {
|
while (!txBuffer_pending) {
|
||||||
pthread_cond_wait(&txBufferSig, &txBufferMutex);
|
pthread_cond_wait(&txBufferSig, &txBufferMutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (txBuffer_pending) {
|
if (txBuffer_pending) {
|
||||||
if (!uart_send(sp, (uint8_t*) &txBuffer, sizeof(UsbCommand))) {
|
if (!uart_send(sp, (uint8_t*) &txBuffer, sizeof(UsbCommand))) {
|
||||||
PrintAndLog("Sending bytes to proxmark failed");
|
PrintAndLog("Sending bytes to proxmark failed");
|
||||||
}
|
}
|
||||||
txBuffer_pending = false;
|
txBuffer_pending = false;
|
||||||
pthread_cond_signal(&txBufferSig); // tell main thread that txBuffer is empty
|
|
||||||
}
|
}
|
||||||
|
pthread_cond_signal(&txBufferSig); // tell main thread that txBuffer is empty
|
||||||
pthread_mutex_unlock(&txBufferMutex);
|
pthread_mutex_unlock(&txBufferMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,7 +372,7 @@ bool GetFromFpgaRAM(uint8_t *dest, int bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode) {
|
bool OpenProxmark(void *port, bool wait_for_port, int timeout) {
|
||||||
char *portname = (char *)port;
|
char *portname = (char *)port;
|
||||||
if (!wait_for_port) {
|
if (!wait_for_port) {
|
||||||
sp = uart_open(portname);
|
sp = uart_open(portname);
|
||||||
|
@ -405,7 +404,6 @@ bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode)
|
||||||
// start the USB communication thread
|
// start the USB communication thread
|
||||||
serial_port_name = portname;
|
serial_port_name = portname;
|
||||||
conn.run = true;
|
conn.run = true;
|
||||||
conn.block_after_ACK = flash_mode;
|
|
||||||
pthread_create(&USB_communication_thread, NULL, &uart_communication, &conn);
|
pthread_create(&USB_communication_thread, NULL, &uart_communication, &conn);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
extern void SetOffline(bool new_offline);
|
extern void SetOffline(bool new_offline);
|
||||||
extern bool IsOffline();
|
extern bool IsOffline();
|
||||||
extern bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode);
|
extern bool OpenProxmark(void *port, bool wait_for_port, int timeout);
|
||||||
extern void CloseProxmark(void);
|
extern void CloseProxmark(void);
|
||||||
extern void SendCommand(UsbCommand *c);
|
extern void SendCommand(UsbCommand *c);
|
||||||
extern void clearCommandBuffer();
|
extern void clearCommandBuffer();
|
||||||
|
|
|
@ -336,7 +336,7 @@ static int enter_bootloader(char *serial_port_name)
|
||||||
msleep(100);
|
msleep(100);
|
||||||
CloseProxmark();
|
CloseProxmark();
|
||||||
|
|
||||||
bool opened = OpenProxmark(serial_port_name, true, 120, true); // wait for 2 minutes
|
bool opened = OpenProxmark(serial_port_name, true, 120); // wait for 2 minutes
|
||||||
if (opened) {
|
if (opened) {
|
||||||
fprintf(stderr," Found.\n");
|
fprintf(stderr," Found.\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -83,7 +83,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
char* serial_port_name = argv[1];
|
char* serial_port_name = argv[1];
|
||||||
|
|
||||||
if (!OpenProxmark(serial_port_name, true, 120, true)) { // wait for 2 minutes
|
if (!OpenProxmark(serial_port_name, true, 120)) { // wait for 2 minutes
|
||||||
fprintf(stderr, "Could not find Proxmark on %s.\n\n", serial_port_name);
|
fprintf(stderr, "Could not find Proxmark on %s.\n\n", serial_port_name);
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1164,7 +1164,7 @@ int DetectClassicPrng(void){
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
if (!WaitForResponseTimeout(CMD_NACK, &resp, 2000)) {
|
||||||
PrintAndLog("PRNG UID: Reply timeout.");
|
PrintAndLog("PRNG UID: Reply timeout.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,7 +286,7 @@ int main(int argc, char* argv[]) {
|
||||||
set_my_executable_path();
|
set_my_executable_path();
|
||||||
|
|
||||||
// try to open USB connection to Proxmark
|
// try to open USB connection to Proxmark
|
||||||
usb_present = OpenProxmark(argv[1], waitCOMPort, 20, false);
|
usb_present = OpenProxmark(argv[1], waitCOMPort, 20);
|
||||||
|
|
||||||
#ifdef HAVE_GUI
|
#ifdef HAVE_GUI
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -309,8 +309,10 @@ int main(int argc, char* argv[]) {
|
||||||
main_loop(script_cmds_file, script_cmd, usb_present);
|
main_loop(script_cmds_file, script_cmd, usb_present);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Clean up the port
|
// Switch off field and clean up the port
|
||||||
if (usb_present) {
|
if (usb_present) {
|
||||||
|
UsbCommand c = {CMD_FPGA_MAJOR_MODE_OFF};
|
||||||
|
SendCommand(&c);
|
||||||
CloseProxmark();
|
CloseProxmark();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
496
common/usb_cdc.c
496
common/usb_cdc.c
|
@ -222,28 +222,26 @@ static const char* getStringDescriptor(uint8_t idx) {
|
||||||
|
|
||||||
|
|
||||||
// Bitmap for all status bits in CSR which must be written as 1 to cause no effect
|
// Bitmap for all status bits in CSR which must be written as 1 to cause no effect
|
||||||
#define REG_NO_EFFECT_1_ALL AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \
|
#define REG_NO_EFFECT_1_ALL (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 | AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP | AT91C_UDP_TXCOMP)
|
||||||
|AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP \
|
|
||||||
|AT91C_UDP_TXCOMP
|
|
||||||
|
|
||||||
|
|
||||||
// Clear flags in the UDP_CSR register
|
// Clear flags in the UDP_CSR register
|
||||||
#define UDP_CLEAR_EP_FLAGS(endpoint, flags) { \
|
#define UDP_CLEAR_EP_FLAGS(endpoint, flags) { \
|
||||||
volatile unsigned int reg; \
|
volatile unsigned int reg; \
|
||||||
reg = pUdp->UDP_CSR[(endpoint)]; \
|
reg = AT91C_BASE_UDP->UDP_CSR[(endpoint)]; \
|
||||||
reg |= REG_NO_EFFECT_1_ALL; \
|
reg |= REG_NO_EFFECT_1_ALL; \
|
||||||
reg &= ~(flags); \
|
reg &= ~(flags); \
|
||||||
pUdp->UDP_CSR[(endpoint)] = reg; \
|
AT91C_BASE_UDP->UDP_CSR[(endpoint)] = reg; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Set flags in the UDP_CSR register
|
// Set flags in the UDP_CSR register
|
||||||
#define UDP_SET_EP_FLAGS(endpoint, flags) { \
|
#define UDP_SET_EP_FLAGS(endpoint, flags) { \
|
||||||
volatile unsigned int reg; \
|
volatile unsigned int reg; \
|
||||||
reg = pUdp->UDP_CSR[(endpoint)]; \
|
reg = AT91C_BASE_UDP->UDP_CSR[(endpoint)]; \
|
||||||
reg |= REG_NO_EFFECT_1_ALL; \
|
reg |= REG_NO_EFFECT_1_ALL; \
|
||||||
reg |= (flags); \
|
reg |= (flags); \
|
||||||
pUdp->UDP_CSR[(endpoint)] = reg; \
|
AT91C_BASE_UDP->UDP_CSR[(endpoint)] = reg; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -283,19 +281,16 @@ typedef struct {
|
||||||
} AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING;
|
} AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING;
|
||||||
|
|
||||||
|
|
||||||
AT91S_CDC_LINE_CODING line = {
|
static AT91S_CDC_LINE_CODING line = {
|
||||||
115200, // baudrate
|
115200, // baudrate
|
||||||
0, // 1 Stop Bit
|
0, // 1 Stop Bit
|
||||||
0, // None Parity
|
0, // None Parity
|
||||||
8}; // 8 Data bits
|
8}; // 8 Data bits
|
||||||
|
|
||||||
|
|
||||||
static void AT91F_CDC_Enumerate();
|
static uint8_t btConfiguration = 0;
|
||||||
|
static uint8_t btConnection = 0;
|
||||||
AT91PS_UDP pUdp = AT91C_BASE_UDP;
|
static uint8_t btReceiveBank = AT91C_UDP_RX_DATA_BK0;
|
||||||
uint8_t btConfiguration = 0;
|
|
||||||
uint8_t btConnection = 0;
|
|
||||||
uint8_t btReceiveBank = AT91C_UDP_RX_DATA_BK0;
|
|
||||||
|
|
||||||
|
|
||||||
//*----------------------------------------------------------------------------
|
//*----------------------------------------------------------------------------
|
||||||
|
@ -307,8 +302,8 @@ void usb_disable() {
|
||||||
AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU;
|
AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU;
|
||||||
|
|
||||||
// Clear all lingering interrupts
|
// Clear all lingering interrupts
|
||||||
if (pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES) {
|
if (AT91C_BASE_UDP->UDP_ISR & AT91C_UDP_ENDBUSRES) {
|
||||||
pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;
|
AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,24 +341,233 @@ void usb_enable() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//*----------------------------------------------------------------------------
|
||||||
|
//* \fn AT91F_USB_SendZlp
|
||||||
|
//* \brief Send zero length packet through an endpoint
|
||||||
|
//*----------------------------------------------------------------------------
|
||||||
|
static void AT91F_USB_SendZlp(uint8_t endpoint) {
|
||||||
|
UDP_SET_EP_FLAGS(endpoint, AT91C_UDP_TXPKTRDY);
|
||||||
|
while (!(AT91C_BASE_UDP->UDP_CSR[endpoint] & AT91C_UDP_TXCOMP))
|
||||||
|
/* wait */;
|
||||||
|
UDP_CLEAR_EP_FLAGS(endpoint, AT91C_UDP_TXCOMP);
|
||||||
|
while (AT91C_BASE_UDP->UDP_CSR[endpoint] & AT91C_UDP_TXCOMP)
|
||||||
|
/* wait */;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//*----------------------------------------------------------------------------
|
||||||
|
//* \fn AT91F_USB_SendData
|
||||||
|
//* \brief Send Data through the control endpoint
|
||||||
|
//*----------------------------------------------------------------------------
|
||||||
|
static void AT91F_USB_SendData(const char *pData, uint32_t length) {
|
||||||
|
uint32_t cpt = 0;
|
||||||
|
AT91_REG csr;
|
||||||
|
|
||||||
|
do {
|
||||||
|
cpt = MIN(length, 8);
|
||||||
|
length -= cpt;
|
||||||
|
|
||||||
|
while (cpt--)
|
||||||
|
AT91C_BASE_UDP->UDP_FDR[0] = *pData++;
|
||||||
|
|
||||||
|
if (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
|
||||||
|
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
|
||||||
|
while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP)
|
||||||
|
/* wait */;
|
||||||
|
}
|
||||||
|
|
||||||
|
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);
|
||||||
|
do {
|
||||||
|
csr = AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL];
|
||||||
|
|
||||||
|
// Data IN stage has been stopped by a status OUT
|
||||||
|
if (csr & AT91C_UDP_RX_DATA_BK0) {
|
||||||
|
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (!(csr & AT91C_UDP_TXCOMP));
|
||||||
|
|
||||||
|
} while (length);
|
||||||
|
|
||||||
|
if (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
|
||||||
|
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
|
||||||
|
while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP)
|
||||||
|
/* wait */;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//*----------------------------------------------------------------------------
|
||||||
|
//* \fn AT91F_USB_SendStall
|
||||||
|
//* \brief Stall the control endpoint
|
||||||
|
//*----------------------------------------------------------------------------
|
||||||
|
static void AT91F_USB_SendStall(void) {
|
||||||
|
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL);
|
||||||
|
while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_ISOERROR))
|
||||||
|
/* wait */;
|
||||||
|
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR);
|
||||||
|
while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR))
|
||||||
|
/* wait */;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//*----------------------------------------------------------------------------
|
||||||
|
//* \fn AT91F_CDC_Enumerate
|
||||||
|
//* \brief This function is a callback invoked when a SETUP packet is received
|
||||||
|
//*----------------------------------------------------------------------------
|
||||||
|
static void AT91F_CDC_Enumerate() {
|
||||||
|
uint8_t bmRequestType, bRequest;
|
||||||
|
uint16_t wValue, wIndex, wLength, wStatus;
|
||||||
|
|
||||||
|
if (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP))
|
||||||
|
return;
|
||||||
|
|
||||||
|
bmRequestType = AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL];
|
||||||
|
bRequest = AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL];
|
||||||
|
wValue = (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
|
||||||
|
wValue |= (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] << 8);
|
||||||
|
wIndex = (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
|
||||||
|
wIndex |= (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] << 8);
|
||||||
|
wLength = (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
|
||||||
|
wLength |= (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] << 8);
|
||||||
|
|
||||||
|
if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host
|
||||||
|
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR);
|
||||||
|
while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR))
|
||||||
|
/* wait */;
|
||||||
|
}
|
||||||
|
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RXSETUP);
|
||||||
|
while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP)
|
||||||
|
/* wait */;
|
||||||
|
|
||||||
|
// Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1
|
||||||
|
switch ((bRequest << 8) | bmRequestType) {
|
||||||
|
case STD_GET_DESCRIPTOR:
|
||||||
|
if (wValue == 0x100) // Return Device Descriptor
|
||||||
|
AT91F_USB_SendData(devDescriptor, MIN(sizeof(devDescriptor), wLength));
|
||||||
|
else if (wValue == 0x200) // Return Configuration Descriptor
|
||||||
|
AT91F_USB_SendData(cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));
|
||||||
|
else if ((wValue & 0xF00) == 0x300) { // Return String Descriptor
|
||||||
|
const char *strDescriptor = getStringDescriptor(wValue & 0xff);
|
||||||
|
if (strDescriptor != NULL) {
|
||||||
|
AT91F_USB_SendData(strDescriptor, MIN(strDescriptor[0], wLength));
|
||||||
|
} else {
|
||||||
|
AT91F_USB_SendStall();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
AT91F_USB_SendStall();
|
||||||
|
break;
|
||||||
|
case STD_SET_ADDRESS:
|
||||||
|
AT91F_USB_SendZlp(AT91C_EP_CONTROL);
|
||||||
|
AT91C_BASE_UDP->UDP_FADDR = (AT91C_UDP_FEN | wValue);
|
||||||
|
AT91C_BASE_UDP->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;
|
||||||
|
break;
|
||||||
|
case STD_SET_CONFIGURATION:
|
||||||
|
btConfiguration = wValue;
|
||||||
|
AT91F_USB_SendZlp(AT91C_EP_CONTROL);
|
||||||
|
AT91C_BASE_UDP->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;
|
||||||
|
AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;
|
||||||
|
AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;
|
||||||
|
AT91C_BASE_UDP->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;
|
||||||
|
break;
|
||||||
|
case STD_GET_CONFIGURATION:
|
||||||
|
AT91F_USB_SendData((char *) &(btConfiguration), sizeof(btConfiguration));
|
||||||
|
break;
|
||||||
|
case STD_GET_STATUS_ZERO:
|
||||||
|
wStatus = 0; // Device is Bus powered, remote wakeup disabled
|
||||||
|
AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus));
|
||||||
|
break;
|
||||||
|
case STD_GET_STATUS_INTERFACE:
|
||||||
|
wStatus = 0; // reserved for future use
|
||||||
|
AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus));
|
||||||
|
break;
|
||||||
|
case STD_GET_STATUS_ENDPOINT:
|
||||||
|
wStatus = 0;
|
||||||
|
wIndex &= 0x0F;
|
||||||
|
if ((AT91C_BASE_UDP->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) {
|
||||||
|
wStatus = (AT91C_BASE_UDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
|
||||||
|
AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus));
|
||||||
|
} else if ((AT91C_BASE_UDP->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) {
|
||||||
|
wStatus = (AT91C_BASE_UDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
|
||||||
|
AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus));
|
||||||
|
} else
|
||||||
|
AT91F_USB_SendStall();
|
||||||
|
break;
|
||||||
|
case STD_SET_FEATURE_ZERO:
|
||||||
|
AT91F_USB_SendStall();
|
||||||
|
break;
|
||||||
|
case STD_SET_FEATURE_INTERFACE:
|
||||||
|
AT91F_USB_SendZlp(AT91C_EP_CONTROL);
|
||||||
|
break;
|
||||||
|
case STD_SET_FEATURE_ENDPOINT:
|
||||||
|
wIndex &= 0x0F;
|
||||||
|
if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
|
||||||
|
AT91C_BASE_UDP->UDP_CSR[wIndex] = 0;
|
||||||
|
AT91F_USB_SendZlp(AT91C_EP_CONTROL);
|
||||||
|
} else
|
||||||
|
AT91F_USB_SendStall();
|
||||||
|
break;
|
||||||
|
case STD_CLEAR_FEATURE_ZERO:
|
||||||
|
AT91F_USB_SendStall();
|
||||||
|
break;
|
||||||
|
case STD_CLEAR_FEATURE_INTERFACE:
|
||||||
|
AT91F_USB_SendZlp(AT91C_EP_CONTROL);
|
||||||
|
break;
|
||||||
|
case STD_CLEAR_FEATURE_ENDPOINT:
|
||||||
|
wIndex &= 0x0F;
|
||||||
|
if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
|
||||||
|
if (wIndex == AT91C_EP_OUT)
|
||||||
|
AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);
|
||||||
|
else if (wIndex == AT91C_EP_IN)
|
||||||
|
AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);
|
||||||
|
else if (wIndex == AT91C_EP_NOTIFY)
|
||||||
|
AT91C_BASE_UDP->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN);
|
||||||
|
AT91F_USB_SendZlp(AT91C_EP_CONTROL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
AT91F_USB_SendStall();
|
||||||
|
break;
|
||||||
|
|
||||||
|
// handle CDC class requests
|
||||||
|
case SET_LINE_CODING:
|
||||||
|
while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RX_DATA_BK0))
|
||||||
|
/* wait */;
|
||||||
|
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);
|
||||||
|
AT91F_USB_SendZlp(AT91C_EP_CONTROL);
|
||||||
|
break;
|
||||||
|
case GET_LINE_CODING:
|
||||||
|
AT91F_USB_SendData((char *) &line, MIN(sizeof(line), wLength));
|
||||||
|
break;
|
||||||
|
case SET_CONTROL_LINE_STATE:
|
||||||
|
btConnection = wValue;
|
||||||
|
AT91F_USB_SendZlp(AT91C_EP_CONTROL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
AT91F_USB_SendStall();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//*----------------------------------------------------------------------------
|
//*----------------------------------------------------------------------------
|
||||||
//* \fn usb_check
|
//* \fn usb_check
|
||||||
//* \brief Test if the device is configured and handle enumeration
|
//* \brief Test if the device is configured and handle enumeration
|
||||||
//*----------------------------------------------------------------------------
|
//*----------------------------------------------------------------------------
|
||||||
static bool usb_check() {
|
static bool usb_check() {
|
||||||
AT91_REG isr = pUdp->UDP_ISR;
|
AT91_REG isr = AT91C_BASE_UDP->UDP_ISR;
|
||||||
|
|
||||||
if (isr & AT91C_UDP_ENDBUSRES) {
|
if (isr & AT91C_UDP_ENDBUSRES) {
|
||||||
pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;
|
AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
|
||||||
// reset all endpoints
|
// reset all endpoints
|
||||||
pUdp->UDP_RSTEP = (unsigned int)-1;
|
AT91C_BASE_UDP->UDP_RSTEP = (unsigned int)-1;
|
||||||
pUdp->UDP_RSTEP = 0;
|
AT91C_BASE_UDP->UDP_RSTEP = 0;
|
||||||
// Enable the function
|
// Enable the function
|
||||||
pUdp->UDP_FADDR = AT91C_UDP_FEN;
|
AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
|
||||||
// Configure endpoint 0
|
// Configure endpoint 0
|
||||||
pUdp->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
|
AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
|
||||||
} else if (isr & AT91C_UDP_EPINT0) {
|
} else if (isr & AT91C_UDP_EPINT0) {
|
||||||
pUdp->UDP_ICR = AT91C_UDP_EPINT0;
|
AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_EPINT0;
|
||||||
AT91F_CDC_Enumerate();
|
AT91F_CDC_Enumerate();
|
||||||
}
|
}
|
||||||
return (btConfiguration) ? true : false;
|
return (btConfiguration) ? true : false;
|
||||||
|
@ -372,7 +576,7 @@ static bool usb_check() {
|
||||||
|
|
||||||
bool usb_poll() {
|
bool usb_poll() {
|
||||||
if (!usb_check()) return false;
|
if (!usb_check()) return false;
|
||||||
return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);
|
return (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -386,8 +590,8 @@ bool usb_poll() {
|
||||||
**/
|
**/
|
||||||
bool usb_poll_validate_length() {
|
bool usb_poll_validate_length() {
|
||||||
if (!usb_check()) return false;
|
if (!usb_check()) return false;
|
||||||
if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false;
|
if (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false;
|
||||||
return (pUdp->UDP_CSR[AT91C_EP_OUT] >> 16) > 0;
|
return (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] >> 16) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -403,11 +607,11 @@ static uint32_t usb_read(uint8_t* data, size_t len) {
|
||||||
while (len) {
|
while (len) {
|
||||||
if (!usb_check()) break;
|
if (!usb_check()) break;
|
||||||
|
|
||||||
if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) {
|
if ( AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] & bank ) {
|
||||||
packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, len);
|
packetSize = MIN(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] >> 16, len);
|
||||||
len -= packetSize;
|
len -= packetSize;
|
||||||
while (packetSize--)
|
while (packetSize--)
|
||||||
data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];
|
data[nbBytesRcv++] = AT91C_BASE_UDP->UDP_FDR[AT91C_EP_OUT];
|
||||||
UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank);
|
UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank);
|
||||||
if (bank == AT91C_UDP_RX_DATA_BK0) {
|
if (bank == AT91C_UDP_RX_DATA_BK0) {
|
||||||
bank = AT91C_UDP_RX_DATA_BK1;
|
bank = AT91C_UDP_RX_DATA_BK1;
|
||||||
|
@ -438,249 +642,47 @@ static uint32_t usb_write(const uint8_t* data, const size_t len) {
|
||||||
cpt = MIN(length, AT91C_EP_IN_SIZE);
|
cpt = MIN(length, AT91C_EP_IN_SIZE);
|
||||||
length -= cpt;
|
length -= cpt;
|
||||||
while (cpt--) {
|
while (cpt--) {
|
||||||
pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
|
AT91C_BASE_UDP->UDP_FDR[AT91C_EP_IN] = *data++;
|
||||||
}
|
}
|
||||||
UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
|
UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
|
||||||
|
while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY))
|
||||||
|
/* wait */;
|
||||||
|
|
||||||
while (length) {
|
while (length) {
|
||||||
// Fill the next bank
|
// Fill the next bank
|
||||||
cpt = MIN(length, AT91C_EP_IN_SIZE);
|
cpt = MIN(length, AT91C_EP_IN_SIZE);
|
||||||
length -= cpt;
|
length -= cpt;
|
||||||
while (cpt--) {
|
while (cpt--) {
|
||||||
pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
|
AT91C_BASE_UDP->UDP_FDR[AT91C_EP_IN] = *data++;
|
||||||
}
|
}
|
||||||
// Wait for the previous bank to be sent
|
// Wait for the previous bank to be sent
|
||||||
while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
|
while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
|
||||||
if (!usb_check()) return length;
|
if (!usb_check()) return length;
|
||||||
}
|
}
|
||||||
UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
|
|
||||||
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)
|
|
||||||
/* wait */;
|
|
||||||
UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
|
UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
|
||||||
|
while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY))
|
||||||
|
/* wait */;
|
||||||
|
UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
|
||||||
|
while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)
|
||||||
|
/* wait */;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for the end of transfer
|
// Wait for the end of transfer
|
||||||
while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
|
while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
|
||||||
if (!usb_check()) return length;
|
if (!usb_check()) return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
|
UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
|
||||||
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)
|
while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)
|
||||||
/* wait */;
|
/* wait */;
|
||||||
|
|
||||||
|
if (len % AT91C_EP_IN_SIZE == 0) { // need to send a zero length packet to complete the transfer
|
||||||
|
AT91F_USB_SendZlp(AT91C_EP_IN);
|
||||||
|
}
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//*----------------------------------------------------------------------------
|
|
||||||
//* \fn AT91F_USB_SendData
|
|
||||||
//* \brief Send Data through the control endpoint
|
|
||||||
//*----------------------------------------------------------------------------
|
|
||||||
static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) {
|
|
||||||
uint32_t cpt = 0;
|
|
||||||
AT91_REG csr;
|
|
||||||
|
|
||||||
do {
|
|
||||||
cpt = MIN(length, 8);
|
|
||||||
length -= cpt;
|
|
||||||
|
|
||||||
while (cpt--)
|
|
||||||
pUdp->UDP_FDR[0] = *pData++;
|
|
||||||
|
|
||||||
if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
|
|
||||||
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
|
|
||||||
while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP)
|
|
||||||
/* wait */;
|
|
||||||
}
|
|
||||||
|
|
||||||
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);
|
|
||||||
do {
|
|
||||||
csr = pUdp->UDP_CSR[AT91C_EP_CONTROL];
|
|
||||||
|
|
||||||
// Data IN stage has been stopped by a status OUT
|
|
||||||
if (csr & AT91C_UDP_RX_DATA_BK0) {
|
|
||||||
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} while (!(csr & AT91C_UDP_TXCOMP));
|
|
||||||
|
|
||||||
} while (length);
|
|
||||||
|
|
||||||
if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
|
|
||||||
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
|
|
||||||
while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP)
|
|
||||||
/* wait */;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//*----------------------------------------------------------------------------
|
|
||||||
//* \fn AT91F_USB_SendZlp
|
|
||||||
//* \brief Send zero length packet through the control endpoint
|
|
||||||
//*----------------------------------------------------------------------------
|
|
||||||
static void AT91F_USB_SendZlp(AT91PS_UDP pUdp) {
|
|
||||||
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);
|
|
||||||
while (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP))
|
|
||||||
/* wait */;
|
|
||||||
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
|
|
||||||
while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP)
|
|
||||||
/* wait */;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//*----------------------------------------------------------------------------
|
|
||||||
//* \fn AT91F_USB_SendStall
|
|
||||||
//* \brief Stall the control endpoint
|
|
||||||
//*----------------------------------------------------------------------------
|
|
||||||
static void AT91F_USB_SendStall(AT91PS_UDP pUdp) {
|
|
||||||
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL);
|
|
||||||
while (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_ISOERROR))
|
|
||||||
/* wait */;
|
|
||||||
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR);
|
|
||||||
while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR))
|
|
||||||
/* wait */;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//*----------------------------------------------------------------------------
|
|
||||||
//* \fn AT91F_CDC_Enumerate
|
|
||||||
//* \brief This function is a callback invoked when a SETUP packet is received
|
|
||||||
//*----------------------------------------------------------------------------
|
|
||||||
static void AT91F_CDC_Enumerate() {
|
|
||||||
uint8_t bmRequestType, bRequest;
|
|
||||||
uint16_t wValue, wIndex, wLength, wStatus;
|
|
||||||
|
|
||||||
if (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP))
|
|
||||||
return;
|
|
||||||
|
|
||||||
bmRequestType = pUdp->UDP_FDR[AT91C_EP_CONTROL];
|
|
||||||
bRequest = pUdp->UDP_FDR[AT91C_EP_CONTROL];
|
|
||||||
wValue = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
|
|
||||||
wValue |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
|
|
||||||
wIndex = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
|
|
||||||
wIndex |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
|
|
||||||
wLength = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
|
|
||||||
wLength |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
|
|
||||||
|
|
||||||
if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host
|
|
||||||
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR);
|
|
||||||
while (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR))
|
|
||||||
/* wait */;
|
|
||||||
}
|
|
||||||
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RXSETUP);
|
|
||||||
while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP)
|
|
||||||
/* wait */;
|
|
||||||
|
|
||||||
// Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1
|
|
||||||
switch ((bRequest << 8) | bmRequestType) {
|
|
||||||
case STD_GET_DESCRIPTOR:
|
|
||||||
if (wValue == 0x100) // Return Device Descriptor
|
|
||||||
AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength));
|
|
||||||
else if (wValue == 0x200) // Return Configuration Descriptor
|
|
||||||
AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));
|
|
||||||
else if ((wValue & 0xF00) == 0x300) { // Return String Descriptor
|
|
||||||
const char *strDescriptor = getStringDescriptor(wValue & 0xff);
|
|
||||||
if (strDescriptor != NULL) {
|
|
||||||
AT91F_USB_SendData(pUdp, strDescriptor, MIN(strDescriptor[0], wLength));
|
|
||||||
} else {
|
|
||||||
AT91F_USB_SendStall(pUdp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
AT91F_USB_SendStall(pUdp);
|
|
||||||
break;
|
|
||||||
case STD_SET_ADDRESS:
|
|
||||||
AT91F_USB_SendZlp(pUdp);
|
|
||||||
pUdp->UDP_FADDR = (AT91C_UDP_FEN | wValue);
|
|
||||||
pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;
|
|
||||||
break;
|
|
||||||
case STD_SET_CONFIGURATION:
|
|
||||||
btConfiguration = wValue;
|
|
||||||
AT91F_USB_SendZlp(pUdp);
|
|
||||||
pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;
|
|
||||||
pUdp->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;
|
|
||||||
pUdp->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;
|
|
||||||
pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;
|
|
||||||
break;
|
|
||||||
case STD_GET_CONFIGURATION:
|
|
||||||
AT91F_USB_SendData(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration));
|
|
||||||
break;
|
|
||||||
case STD_GET_STATUS_ZERO:
|
|
||||||
wStatus = 0; // Device is Bus powered, remote wakeup disabled
|
|
||||||
AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
|
|
||||||
break;
|
|
||||||
case STD_GET_STATUS_INTERFACE:
|
|
||||||
wStatus = 0; // reserved for future use
|
|
||||||
AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
|
|
||||||
break;
|
|
||||||
case STD_GET_STATUS_ENDPOINT:
|
|
||||||
wStatus = 0;
|
|
||||||
wIndex &= 0x0F;
|
|
||||||
if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) {
|
|
||||||
wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
|
|
||||||
AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
|
|
||||||
} else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) {
|
|
||||||
wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
|
|
||||||
AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
|
|
||||||
} else
|
|
||||||
AT91F_USB_SendStall(pUdp);
|
|
||||||
break;
|
|
||||||
case STD_SET_FEATURE_ZERO:
|
|
||||||
AT91F_USB_SendStall(pUdp);
|
|
||||||
break;
|
|
||||||
case STD_SET_FEATURE_INTERFACE:
|
|
||||||
AT91F_USB_SendZlp(pUdp);
|
|
||||||
break;
|
|
||||||
case STD_SET_FEATURE_ENDPOINT:
|
|
||||||
wIndex &= 0x0F;
|
|
||||||
if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
|
|
||||||
pUdp->UDP_CSR[wIndex] = 0;
|
|
||||||
AT91F_USB_SendZlp(pUdp);
|
|
||||||
} else
|
|
||||||
AT91F_USB_SendStall(pUdp);
|
|
||||||
break;
|
|
||||||
case STD_CLEAR_FEATURE_ZERO:
|
|
||||||
AT91F_USB_SendStall(pUdp);
|
|
||||||
break;
|
|
||||||
case STD_CLEAR_FEATURE_INTERFACE:
|
|
||||||
AT91F_USB_SendZlp(pUdp);
|
|
||||||
break;
|
|
||||||
case STD_CLEAR_FEATURE_ENDPOINT:
|
|
||||||
wIndex &= 0x0F;
|
|
||||||
if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
|
|
||||||
if (wIndex == AT91C_EP_OUT)
|
|
||||||
pUdp->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);
|
|
||||||
else if (wIndex == AT91C_EP_IN)
|
|
||||||
pUdp->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);
|
|
||||||
else if (wIndex == AT91C_EP_NOTIFY)
|
|
||||||
pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN);
|
|
||||||
AT91F_USB_SendZlp(pUdp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
AT91F_USB_SendStall(pUdp);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// handle CDC class requests
|
|
||||||
case SET_LINE_CODING:
|
|
||||||
while (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RX_DATA_BK0))
|
|
||||||
/* wait */;
|
|
||||||
UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);
|
|
||||||
AT91F_USB_SendZlp(pUdp);
|
|
||||||
break;
|
|
||||||
case GET_LINE_CODING:
|
|
||||||
AT91F_USB_SendData(pUdp, (char *) &line, MIN(sizeof(line), wLength));
|
|
||||||
break;
|
|
||||||
case SET_CONTROL_LINE_STATE:
|
|
||||||
btConnection = wValue;
|
|
||||||
AT91F_USB_SendZlp(pUdp);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
AT91F_USB_SendStall(pUdp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//***************************************************************************
|
//***************************************************************************
|
||||||
// Interface to the main program
|
// Interface to the main program
|
||||||
//***************************************************************************
|
//***************************************************************************
|
||||||
|
|
17
uart/uart.h
17
uart/uart.h
|
@ -29,13 +29,10 @@
|
||||||
* @file uart.h
|
* @file uart.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _PM3_UART_H_
|
#ifndef PM3_UART_H__
|
||||||
#define _PM3_UART_H_
|
#define PM3_UART_H__
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
@ -69,11 +66,11 @@ typedef void* serial_port;
|
||||||
*
|
*
|
||||||
* On errors, this method returns INVALID_SERIAL_PORT or CLAIMED_SERIAL_PORT.
|
* On errors, this method returns INVALID_SERIAL_PORT or CLAIMED_SERIAL_PORT.
|
||||||
*/
|
*/
|
||||||
serial_port uart_open(const char* pcPortName);
|
extern serial_port uart_open(const char* pcPortName);
|
||||||
|
|
||||||
/* Closes the given port.
|
/* Closes the given port.
|
||||||
*/
|
*/
|
||||||
void uart_close(const serial_port sp);
|
extern void uart_close(const serial_port sp);
|
||||||
|
|
||||||
/* Reads from the given serial port for up to 30ms.
|
/* Reads from the given serial port for up to 30ms.
|
||||||
* pbtRx: A pointer to a buffer for the returned data to be written to.
|
* pbtRx: A pointer to a buffer for the returned data to be written to.
|
||||||
|
@ -86,13 +83,13 @@ void uart_close(const serial_port sp);
|
||||||
* partial read may have completed into the buffer by the corresponding
|
* partial read may have completed into the buffer by the corresponding
|
||||||
* implementation, so pszRxLen should be checked to see if any data was written.
|
* implementation, so pszRxLen should be checked to see if any data was written.
|
||||||
*/
|
*/
|
||||||
bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen);
|
extern bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen);
|
||||||
|
|
||||||
/* Sends a buffer to a given serial port.
|
/* Sends a buffer to a given serial port.
|
||||||
* pbtTx: A pointer to a buffer containing the data to send.
|
* pbtTx: A pointer to a buffer containing the data to send.
|
||||||
* szTxLen: The amount of data to be sent.
|
* szTxLen: The amount of data to be sent.
|
||||||
*/
|
*/
|
||||||
bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t szTxLen);
|
extern bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t szTxLen);
|
||||||
|
|
||||||
/* Sets the current speed of the serial port, in baud.
|
/* Sets the current speed of the serial port, in baud.
|
||||||
*/
|
*/
|
||||||
|
@ -100,7 +97,7 @@ bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed);
|
||||||
|
|
||||||
/* Gets the current speed of the serial port, in baud.
|
/* Gets the current speed of the serial port, in baud.
|
||||||
*/
|
*/
|
||||||
uint32_t uart_get_speed(const serial_port sp);
|
extern uint32_t uart_get_speed(const serial_port sp);
|
||||||
|
|
||||||
#endif // _PM3_UART_H_
|
#endif // _PM3_UART_H_
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,11 @@
|
||||||
|
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
|
||||||
// The windows serial port implementation
|
// The windows serial port implementation
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -48,6 +53,7 @@ typedef struct {
|
||||||
COMMTIMEOUTS ct; // Serial port time-out configuration
|
COMMTIMEOUTS ct; // Serial port time-out configuration
|
||||||
} serial_port_windows;
|
} serial_port_windows;
|
||||||
|
|
||||||
|
|
||||||
void upcase(char *p) {
|
void upcase(char *p) {
|
||||||
while(*p != '\0') {
|
while(*p != '\0') {
|
||||||
if(*p >= 97 && *p <= 122) {
|
if(*p >= 97 && *p <= 122) {
|
||||||
|
@ -57,6 +63,13 @@ void upcase(char *p) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void uart_close(const serial_port sp) {
|
||||||
|
CloseHandle(((serial_port_windows*)sp)->hPort);
|
||||||
|
free(sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
serial_port uart_open(const char* pcPortName) {
|
serial_port uart_open(const char* pcPortName) {
|
||||||
char acPortName[255];
|
char acPortName[255];
|
||||||
serial_port_windows* sp = malloc(sizeof(serial_port_windows));
|
serial_port_windows* sp = malloc(sizeof(serial_port_windows));
|
||||||
|
@ -102,20 +115,18 @@ serial_port uart_open(const char* pcPortName) {
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_close(const serial_port sp) {
|
|
||||||
CloseHandle(((serial_port_windows*)sp)->hPort);
|
|
||||||
free(sp);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool uart_receive(const serial_port sp, uint8_t *pbtRx, size_t pszMaxRxLen, size_t *pszRxLen) {
|
bool uart_receive(const serial_port sp, uint8_t *pbtRx, size_t pszMaxRxLen, size_t *pszRxLen) {
|
||||||
return ReadFile(((serial_port_windows*)sp)->hPort, pbtRx, pszMaxRxLen, (LPDWORD)pszRxLen, NULL);
|
return ReadFile(((serial_port_windows*)sp)->hPort, pbtRx, pszMaxRxLen, (LPDWORD)pszRxLen, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t szTxLen) {
|
bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t szTxLen) {
|
||||||
DWORD dwTxLen = 0;
|
DWORD dwTxLen = 0;
|
||||||
return WriteFile(((serial_port_windows*)sp)->hPort, pbtTx, szTxLen, &dwTxLen, NULL);
|
return WriteFile(((serial_port_windows*)sp)->hPort, pbtTx, szTxLen, &dwTxLen, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) {
|
bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) {
|
||||||
serial_port_windows* spw;
|
serial_port_windows* spw;
|
||||||
spw = (serial_port_windows*)sp;
|
spw = (serial_port_windows*)sp;
|
||||||
|
@ -123,6 +134,7 @@ bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) {
|
||||||
return SetCommState(spw->hPort, &spw->dcb);
|
return SetCommState(spw->hPort, &spw->dcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t uart_get_speed(const serial_port sp) {
|
uint32_t uart_get_speed(const serial_port sp) {
|
||||||
const serial_port_windows* spw = (serial_port_windows*)sp;
|
const serial_port_windows* spw = (serial_port_windows*)sp;
|
||||||
if (!GetCommState(spw->hPort, (serial_port)&spw->dcb)) {
|
if (!GetCommState(spw->hPort, (serial_port)&spw->dcb)) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue