From: pwpiwi Date: Thu, 23 Jan 2020 21:07:17 +0000 (+0100) Subject: Always enable fast response mode (was enabled for flasher only) X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/929b61c6701f8266c855a669d4c7827cbe0d8eb8 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 --- diff --git a/armsrc/epa.c b/armsrc/epa.c index ac907f6b..fe32e497 100644 --- a/armsrc/epa.c +++ b/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 //----------------------------------------------------------------------------- -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}; - // if an APDU has been passed, save it + // if an APDU has been passed, just save it if (c->arg[0] != 0) { // 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); + return; } - memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1], - c->d.asBytes, - c->arg[2]); + memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1], c->d.asBytes, c->arg[2]); // save/update APDU length if (c->arg[1] == 0) { apdu_lengths_replay[c->arg[0] - 1] = c->arg[2]; diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 1f814609..afe1a607 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -674,14 +674,14 @@ static bool selectIclassTag(uint8_t *card_data, uint32_t *eof_time) { // Send act_all ReaderTransmitIClass(act_all, 1, &start_time); // Card present? - if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_ACTALL, eof_time) < 0) return false;//Fail + if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_ACTALL, eof_time) < 0) return false; //Fail //Send Identify start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; ReaderTransmitIClass(identify, 1, &start_time); //We expect a 10-byte response here, 8 byte anticollision-CSN and 2 byte CRC uint8_t len = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time); - if (len != 10) return false;//Fail + if (len != 10) return false; //Fail //Copy the Anti-collision CSN to our select-packet memcpy(&select[1], resp, 8); @@ -690,7 +690,7 @@ static bool selectIclassTag(uint8_t *card_data, uint32_t *eof_time) { ReaderTransmitIClass(select, sizeof(select), &start_time); //We expect a 10-byte response here, 8 byte CSN and 2 byte CRC len = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time); - if (len != 10) return false;//Fail + if (len != 10) return false; //Fail //Success - we got CSN //Save CSN in response data @@ -733,42 +733,42 @@ void ReaderIClass(uint8_t flags) { if (selectIclassTag(resp, &eof_time)) { result_status = FLAG_ICLASS_READER_CSN; 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; - //Read block 1, config - if (flags & FLAG_ICLASS_READER_CONF) { - if (sendCmdGetResponseWithRetries(readConf, sizeof(readConf), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) { - result_status |= FLAG_ICLASS_READER_CONF; - memcpy(card_data+8, resp, 8); - } else { - Dbprintf("Failed to read config block"); + //Read block 1, config + if (flags & FLAG_ICLASS_READER_CONF) { + if (sendCmdGetResponseWithRetries(readConf, sizeof(readConf), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) { + result_status |= FLAG_ICLASS_READER_CONF; + memcpy(card_data+8, resp, 8); + } else { + Dbprintf("Failed to read config block"); + } + start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; } - start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; - } - //Read block 2, e-purse - if (flags & FLAG_ICLASS_READER_CC) { - if (sendCmdGetResponseWithRetries(readEpurse, sizeof(readEpurse), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) { - result_status |= FLAG_ICLASS_READER_CC; - memcpy(card_data + (8*2), resp, 8); - } else { - Dbprintf("Failed to read e-purse"); + //Read block 2, e-purse + if (flags & FLAG_ICLASS_READER_CC) { + if (sendCmdGetResponseWithRetries(readEpurse, sizeof(readEpurse), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) { + result_status |= FLAG_ICLASS_READER_CC; + memcpy(card_data + (8*2), resp, 8); + } else { + Dbprintf("Failed to read e-purse"); + } + start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; } - start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; - } - //Read block 5, AA - if (flags & FLAG_ICLASS_READER_AA) { - if (sendCmdGetResponseWithRetries(readAA, sizeof(readAA), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) { - result_status |= FLAG_ICLASS_READER_AA; - memcpy(card_data + (8*5), resp, 8); - } else { - Dbprintf("Failed to read AA block"); + //Read block 5, AA + if (flags & FLAG_ICLASS_READER_AA) { + if (sendCmdGetResponseWithRetries(readAA, sizeof(readAA), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) { + result_status |= FLAG_ICLASS_READER_AA; + memcpy(card_data + (8*5), resp, 8); + } else { + Dbprintf("Failed to read AA block"); + } } } - + cmd_send(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data)); LED_A_OFF(); @@ -819,9 +819,9 @@ void iClass_ReadBlk(uint8_t blockno) { uint8_t readblockdata[10]; bool isOK = iClass_ReadBlock(blockno, readblockdata); - cmd_send(CMD_ACK, isOK, 0, 0, readblockdata, 8); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); + cmd_send(CMD_ACK, isOK, 0, 0, readblockdata, 8); LED_A_OFF(); } @@ -899,11 +899,10 @@ void iClass_WriteBlock(uint8_t blockNo, uint8_t *data) { } else { Dbprintf("Write block [%02x] failed", blockNo); } - cmd_send(CMD_ACK, isOK, 0, 0, 0, 0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); + cmd_send(CMD_ACK, isOK, 0, 0, 0, 0); LED_A_OFF(); } @@ -934,6 +933,5 @@ void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) { LED_D_OFF(); cmd_send(CMD_ACK, 1, 0, 0, 0, 0); - LED_A_OFF(); } diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index a24e7a47..0de5ea6f 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2026,15 +2026,15 @@ void ReaderIso14443a(UsbCommand *c) { set_tracing(true); - if(param & ISO14A_CLEAR_TRACE) { + if (param & ISO14A_CLEAR_TRACE) { clear_trace(); } - if(param & ISO14A_REQUEST_TRIGGER) { + if (param & ISO14A_REQUEST_TRIGGER) { iso14a_set_trigger(true); } - if(param & ISO14A_CONNECT) { + if (param & ISO14A_CONNECT) { LED_A_ON(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); if(!(param & ISO14A_NO_SELECT)) { @@ -2048,16 +2048,16 @@ void ReaderIso14443a(UsbCommand *c) { } FpgaDisableTracing(); 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(); } } - if(param & ISO14A_SET_TIMEOUT) { + if (param & ISO14A_SET_TIMEOUT) { iso14a_set_timeout(timeout); } - if(param & ISO14A_APDU && !cantSELECT) { + if (param & ISO14A_APDU && !cantSELECT) { uint8_t res; arg0 = iso14_apdu(cmd, len, (param & ISO14A_SEND_CHAINING), buf, &res); FpgaDisableTracing(); @@ -2066,8 +2066,8 @@ void ReaderIso14443a(UsbCommand *c) { LED_B_OFF(); } - if(param & ISO14A_RAW && !cantSELECT) { - if(param & ISO14A_APPEND_CRC) { + if (param & ISO14A_RAW && !cantSELECT) { + if (param & ISO14A_APPEND_CRC) { if(param & ISO14A_TOPAZMODE) { AppendCrc14443b(cmd,len); } else { @@ -2076,8 +2076,8 @@ void ReaderIso14443a(UsbCommand *c) { len += 2; if (lenbits) lenbits += 16; } - if(lenbits>0) { // want to send a specific number of bits (e.g. short commands) - if(param & ISO14A_TOPAZMODE) { + if (lenbits > 0) { // want to send a specific number of bits (e.g. short commands) + if (param & ISO14A_TOPAZMODE) { int bits_to_send = lenbits; uint16_t i = 0; ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 7), NULL, NULL); // first byte is always short (7bits) and no parity @@ -2091,7 +2091,7 @@ void ReaderIso14443a(UsbCommand *c) { ReaderTransmitBitsPar(cmd, lenbits, par, NULL); // bytes are 8 bit with odd parity } } else { // want to send complete bytes only - if(param & ISO14A_TOPAZMODE) { + if (param & ISO14A_TOPAZMODE) { uint16_t i = 0; ReaderTransmitBitsPar(&cmd[i++], 7, NULL, NULL); // first byte: 7 bits, no paritiy while (i < len) { @@ -2105,15 +2105,15 @@ void ReaderIso14443a(UsbCommand *c) { FpgaDisableTracing(); LED_B_ON(); - cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf)); + cmd_send(CMD_ACK, arg0, 0, 0, buf, sizeof(buf)); LED_B_OFF(); } - if(param & ISO14A_REQUEST_TRIGGER) { + if (param & ISO14A_REQUEST_TRIGGER) { iso14a_set_trigger(false); } - if(param & ISO14A_NO_DISCONNECT) { + if (param & ISO14A_NO_DISCONNECT) { return; } diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index e30a5639..27b1cf19 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -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"); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_B_ON(); cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16); LED_B_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } @@ -202,9 +203,10 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) return; } - cmd_send(CMD_ACK,1,0,0,dataout,16); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); + + cmd_send(CMD_ACK,1,0,0,dataout,16); 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"); + // Thats it... + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_B_ON(); cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16*NumBlocksPerSector(sectorNo)); LED_B_OFF(); - // Thats it... - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); 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); - cmd_send(CMD_ACK, 1, countblocks*4, BigBuf_max_traceLen(), 0, 0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); + + cmd_send(CMD_ACK, 1, countblocks*4, BigBuf_max_traceLen(), 0, 0); + BigBuf_free(); 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"); + // Thats it... + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_B_ON(); cmd_send(CMD_ACK,isOK,0,0,0,0); LED_B_OFF(); - // Thats it... - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } @@ -475,8 +480,9 @@ void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain) if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); - cmd_send(CMD_ACK,1,0,0,0,0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + cmd_send(CMD_ACK,1,0,0,0,0); LEDsoff(); } */ @@ -544,8 +550,9 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); - cmd_send(CMD_ACK,1,0,0,0,0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + cmd_send(CMD_ACK,1,0,0,0,0); LEDsoff(); } @@ -613,8 +620,9 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){ return; }; - cmd_send(CMD_ACK,1,0,0,0,0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + cmd_send(CMD_ACK,1,0,0,0,0); LEDsoff(); } @@ -743,16 +751,17 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, crypto1_destroy(pcs); + if (field_off) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + } + LED_B_ON(); cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf)); LED_B_OFF(); 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+20, &authentication_timeout, 4); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED"); + LED_B_ON(); cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf)); LED_B_OFF(); - if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED"); - - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } @@ -1352,13 +1362,14 @@ void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ break; } + // reset fpga + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + // send USB response LED_B_ON(); cmd_send(CMD_ACK,isOK,0,0,NULL,0); LED_B_OFF(); - // reset fpga - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); return; @@ -1490,14 +1501,15 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai break; } + if ((workFlags & 0x10) || (!isOK)) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + } + LED_B_ON(); cmd_send(CMD_ACK,isOK,0,0,uid,4); LED_B_OFF(); - if ((workFlags & 0x10) || (!isOK)) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - } + LEDsoff(); } @@ -1574,6 +1586,10 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai break; } + if ((workFlags & 0x10) || (!isOK)) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + } + LED_B_ON(); if (workFlags & 0x20) { if (isOK) @@ -1583,10 +1599,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai cmd_send(CMD_ACK,isOK,0,0,data,18); LED_B_OFF(); - if ((workFlags & 0x10) || (!isOK)) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - } + LEDsoff(); } void MifareCIdent(){ @@ -1622,11 +1635,12 @@ void MifareCIdent(){ // From iceman1001: removed the if, since some magic tags misbehavies and send an answer to it. mifare_classic_halt(NULL, 0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_B_ON(); cmd_send(CMD_ACK,isOK,0,0,0,0); LED_B_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } @@ -1657,7 +1671,8 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){ } 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)); } void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){ @@ -1671,16 +1686,17 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){ isOK = mifare_desfire_des_auth2(cuid, key, dataout); - if( isOK) { + if (isOK) { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed"); OnError(4); return; } + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED"); cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout)); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff.c index b867c582..f3ee4a3f 100644 --- a/armsrc/mifaresniff.c +++ b/armsrc/mifaresniff.c @@ -152,7 +152,7 @@ bool intMfSniffSend() { while (pckLen > 0) { pckSize = MIN(USB_CMD_DATA_SIZE, pckLen); 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(); pckLen -= pckSize; @@ -160,7 +160,7 @@ bool intMfSniffSend() { } 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(); clear_trace(); diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index eba33947..58315582 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -46,28 +46,28 @@ int CmdHF14AList(const char *Cmd) return 0; } -int Hf14443_4aGetCardData(iso14a_card_select_t * card) { +int Hf14443_4aGetCardData(iso14a_card_select_t *card) { UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}}; SendCommand(&c); UsbCommand resp; - WaitForResponse(CMD_ACK,&resp); + WaitForResponse(CMD_NACK, &resp); memcpy(card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - if(select_status == 0) { + if (select_status == 0) { PrintAndLog("E->iso14443a card select failed"); return 1; } - if(select_status == 2) { + if (select_status == 2) { PrintAndLog("E->Card doesn't support iso14443-4 mode"); return 1; } - if(select_status == 3) { + if (select_status == 3) { PrintAndLog("E->Card doesn't support standard iso14443-3 anticollision"); PrintAndLog("\tATQA : %02x %02x", card->atqa[1], card->atqa[0]); return 1; @@ -156,20 +156,24 @@ int CmdHF14AReader(const char *Cmd) { 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}}; SendCommand(&c); 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; memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - if(select_status == 0) { + if (select_status == 0) { if (Cmd[0] != 's') PrintAndLog("iso14443a card select failed"); // disconnect c.arg[0] = 0; @@ -217,13 +221,13 @@ int CmdHF14AInfo(const char *Cmd) SendCommand(&c); UsbCommand resp; - WaitForResponse(CMD_ACK,&resp); + WaitForResponse(CMD_NACK,&resp); memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS - if(select_status == 0) { + if (select_status == 0) { //PrintAndLog("iso14443a card select failed"); // disconnect c.arg[0] = 0; @@ -272,7 +276,7 @@ int CmdHF14AInfo(const char *Cmd) // Double & triple sized UID, can be mapped to a manufacturer. // HACK: does this apply for Ultralight cards? - if ( card.uidlen > 4 ) { + if (card.uidlen > 4) { PrintAndLog("MANUFACTURER : %s", getManufacturerName(card.uid[0])); } @@ -430,7 +434,7 @@ int CmdHF14AInfo(const char *Cmd) (void)mfCIdentify(); if (isMifareClassic) { - switch(DetectClassicPrng()) { + switch (DetectClassicPrng()) { case 0: PrintAndLog("Prng detection: HARDENED (hardnested)"); break; @@ -462,7 +466,7 @@ int CmdHF14ACUIDs(const char *Cmd) SendCommand(&c); UsbCommand resp; - WaitForResponse(CMD_ACK,&resp); + WaitForResponse(CMD_NACK,&resp); iso14a_card_select_t *card = (iso14a_card_select_t *) resp.d.asBytes; diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 1400395a..93e46b67 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -333,7 +333,7 @@ int HFiClassReader(bool loop, bool verbose) { while (!ukbhit()) { SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { uint8_t readStatus = resp.arg[0] & 0xff; uint8_t *data = resp.d.asBytes; @@ -368,7 +368,8 @@ int HFiClassReader(bool loop, bool verbose) { if (tagFound && !loop) return 1; } else { - if (verbose) PrintAndLog("Command execute timeout"); + if (verbose) PrintAndLog("Error: No response from Proxmark."); + break; } if (!loop) break; } diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 93c3ea65..33790230 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2672,7 +2672,7 @@ int CmdHF14AMfSniff(const char *Cmd){ } UsbCommand resp; - if (WaitForResponseTimeoutW(CMD_ACK, &resp, 2000, false)) { + if (WaitForResponseTimeoutW(CMD_UNKNOWN, &resp, 2000, false)) { res = resp.arg[0] & 0xff; uint16_t traceLen = resp.arg[1]; len = resp.arg[2]; diff --git a/client/comms.c b/client/comms.c index d7f4265f..409eaba3 100644 --- a/client/comms.c +++ b/client/comms.c @@ -11,11 +11,12 @@ #include "comms.h" +#include #include #include #if defined(__linux__) && !defined(NO_UNLINK) -#include // for unlink() +#include // for unlink() #endif #include "uart.h" #include "ui.h" @@ -33,7 +34,6 @@ static bool offline; typedef struct { 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; static communication_arg_t conn; @@ -78,11 +78,11 @@ void SendCommand(UsbCommand *c) { if (offline) { PrintAndLog("Sending bytes to proxmark failed - offline"); return; - } + } pthread_mutex_lock(&txBufferMutex); /** - This causes hangups at times, when the pm3 unit is unresponsive or disconnected. The main console thread is alive, + This causes hangups at times, when the pm3 unit is unresponsive or disconnected. The main console thread is alive, but comm thread just spins here. Not good.../holiman **/ while (txBuffer_pending) { @@ -183,7 +183,7 @@ static void UsbCommandReceived(UsbCommand *UC) } break; default: - storeCommand(UC); + storeCommand(UC); break; } @@ -195,21 +195,23 @@ static bool receive_from_serial(serial_port sp, uint8_t *rx_buf, size_t len, siz *received_len = 0; // 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) { + #ifdef COMMS_DEBUG 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", bytes_read, len - *received_len, *received_len); } + #endif *received_len += bytes_read; bytes_read = 0; } return (*received_len == len); } - + static void #ifdef __has_attribute #if __has_attribute(force_align_arg_pointer) -__attribute__((force_align_arg_pointer)) +__attribute__((force_align_arg_pointer)) #endif #endif *uart_communication(void *targ) { @@ -231,12 +233,12 @@ __attribute__((force_align_arg_pointer)) if (receive_from_serial(sp, prx, bytes_to_read, &rxlen)) { prx += rxlen; 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]); bytes_to_read = response->datalen; if (receive_from_serial(sp, prx, bytes_to_read, &rxlen)) { 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[1] = response->arg[1]; resp.arg[2] = response->arg[2]; @@ -247,9 +249,9 @@ __attribute__((force_align_arg_pointer)) } } } 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; - if (receive_from_serial(sp, prx, bytes_to_read, &rxlen)) { + if (receive_from_serial(sp, prx, bytes_to_read, &rxlen)) { UsbCommandReceived(command); if (command->cmd == CMD_ACK) { ACK_received = true; @@ -257,26 +259,23 @@ __attribute__((force_align_arg_pointer)) } } } - - pthread_mutex_lock(&txBufferMutex); - if (conn->block_after_ACK) { - // if we just received an ACK, wait here until a new command is to be transmitted - if (ACK_received) { - while (!txBuffer_pending) { - pthread_cond_wait(&txBufferSig, &txBufferMutex); - } + pthread_mutex_lock(&txBufferMutex); + // if we received an ACK the PM has done its job and waits for another command. + // We therefore can wait here as well 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) { + while (!txBuffer_pending) { + pthread_cond_wait(&txBufferSig, &txBufferMutex); } } - - if(txBuffer_pending) { + if (txBuffer_pending) { if (!uart_send(sp, (uint8_t*) &txBuffer, sizeof(UsbCommand))) { PrintAndLog("Sending bytes to proxmark failed"); } 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); } @@ -309,7 +308,7 @@ bool GetFromBigBuf(uint8_t *dest, int bytes, int start_index, UsbCommand *respon uint64_t start_time = msclock(); UsbCommand resp; - if (response == NULL) { + if (response == NULL) { response = &resp; } @@ -339,7 +338,7 @@ bool GetFromBigBuf(uint8_t *dest, int bytes, int start_index, UsbCommand *respon return false; } - + bool GetFromFpgaRAM(uint8_t *dest, int bytes) { UsbCommand c = {CMD_HF_PLOT, {0, 0, 0}}; @@ -348,7 +347,7 @@ bool GetFromFpgaRAM(uint8_t *dest, int bytes) uint64_t start_time = msclock(); UsbCommand response; - + int bytes_completed = 0; bool show_warning = true; while(true) { @@ -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; if (!wait_for_port) { 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 serial_port_name = portname; conn.run = true; - conn.block_after_ACK = flash_mode; pthread_create(&USB_communication_thread, NULL, &uart_communication, &conn); return true; } @@ -477,7 +475,7 @@ bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeo // Wait until the command is received while (true) { - while(getCommand(response)) { + while (getCommand(response)) { if (cmd == CMD_UNKNOWN || response->cmd == cmd) { return true; } diff --git a/client/comms.h b/client/comms.h index c35c4f25..11df1d54 100644 --- a/client/comms.h +++ b/client/comms.h @@ -17,7 +17,7 @@ extern void SetOffline(bool new_offline); 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 SendCommand(UsbCommand *c); extern void clearCommandBuffer(); diff --git a/client/flash.c b/client/flash.c index 9a443cb8..67e371a2 100644 --- a/client/flash.c +++ b/client/flash.c @@ -336,7 +336,7 @@ static int enter_bootloader(char *serial_port_name) msleep(100); 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) { fprintf(stderr," Found.\n"); return 0; diff --git a/client/flasher.c b/client/flasher.c index 7691fb3f..d7fa0b5e 100644 --- a/client/flasher.c +++ b/client/flasher.c @@ -83,7 +83,7 @@ int main(int argc, char **argv) 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); return -1; } else { diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 7b710710..bc53e1fe 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -1164,7 +1164,7 @@ int DetectClassicPrng(void){ clearCommandBuffer(); SendCommand(&c); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (!WaitForResponseTimeout(CMD_NACK, &resp, 2000)) { PrintAndLog("PRNG UID: Reply timeout."); return -1; } diff --git a/client/proxmark3.c b/client/proxmark3.c index 6b1e2393..fb17d13d 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -286,7 +286,7 @@ int main(int argc, char* argv[]) { set_my_executable_path(); // 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 _WIN32 @@ -309,8 +309,10 @@ int main(int argc, char* argv[]) { main_loop(script_cmds_file, script_cmd, usb_present); #endif - // Clean up the port + // Switch off field and clean up the port if (usb_present) { + UsbCommand c = {CMD_FPGA_MAJOR_MODE_OFF}; + SendCommand(&c); CloseProxmark(); } diff --git a/common/usb_cdc.c b/common/usb_cdc.c index fa26ea7d..acd16b4e 100644 --- a/common/usb_cdc.c +++ b/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 -#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 +#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) // Clear flags in the UDP_CSR register #define UDP_CLEAR_EP_FLAGS(endpoint, flags) { \ volatile unsigned int reg; \ - reg = pUdp->UDP_CSR[(endpoint)]; \ + reg = AT91C_BASE_UDP->UDP_CSR[(endpoint)]; \ reg |= REG_NO_EFFECT_1_ALL; \ reg &= ~(flags); \ - pUdp->UDP_CSR[(endpoint)] = reg; \ + AT91C_BASE_UDP->UDP_CSR[(endpoint)] = reg; \ } // Set flags in the UDP_CSR register #define UDP_SET_EP_FLAGS(endpoint, flags) { \ volatile unsigned int reg; \ - reg = pUdp->UDP_CSR[(endpoint)]; \ + reg = AT91C_BASE_UDP->UDP_CSR[(endpoint)]; \ reg |= REG_NO_EFFECT_1_ALL; \ 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 line = { +static AT91S_CDC_LINE_CODING line = { 115200, // baudrate 0, // 1 Stop Bit 0, // None Parity 8}; // 8 Data bits -static void AT91F_CDC_Enumerate(); - -AT91PS_UDP pUdp = AT91C_BASE_UDP; -uint8_t btConfiguration = 0; -uint8_t btConnection = 0; -uint8_t btReceiveBank = AT91C_UDP_RX_DATA_BK0; +static uint8_t btConfiguration = 0; +static uint8_t btConnection = 0; +static uint8_t btReceiveBank = AT91C_UDP_RX_DATA_BK0; //*---------------------------------------------------------------------------- @@ -307,8 +302,8 @@ void usb_disable() { AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU; // Clear all lingering interrupts - if (pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES) { - pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES; + if (AT91C_BASE_UDP->UDP_ISR & AT91C_UDP_ENDBUSRES) { + AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES; } } @@ -347,128 +342,16 @@ void usb_enable() { //*---------------------------------------------------------------------------- -//* \fn usb_check -//* \brief Test if the device is configured and handle enumeration -//*---------------------------------------------------------------------------- -static bool usb_check() { - AT91_REG isr = pUdp->UDP_ISR; - - if (isr & AT91C_UDP_ENDBUSRES) { - pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES; - // reset all endpoints - pUdp->UDP_RSTEP = (unsigned int)-1; - pUdp->UDP_RSTEP = 0; - // Enable the function - pUdp->UDP_FADDR = AT91C_UDP_FEN; - // Configure endpoint 0 - pUdp->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL); - } else if (isr & AT91C_UDP_EPINT0) { - pUdp->UDP_ICR = AT91C_UDP_EPINT0; - AT91F_CDC_Enumerate(); - } - return (btConfiguration) ? true : false; -} - - -bool usb_poll() { - if (!usb_check()) return false; - return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank); -} - - -/** - In github PR #129, some users appears to get a false positive from - usb_poll, which returns true, but the usb_read operation - still returns 0. - This check is basically the same as above, but also checks - that the length available to read is non-zero, thus hopefully fixes the - bug. -**/ -bool usb_poll_validate_length() { - if (!usb_check()) return false; - if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false; - return (pUdp->UDP_CSR[AT91C_EP_OUT] >> 16) > 0; -} - - -//*---------------------------------------------------------------------------- -//* \fn usb_read -//* \brief Read available data from Endpoint OUT -//*---------------------------------------------------------------------------- -static uint32_t usb_read(uint8_t* data, size_t len) { - uint8_t bank = btReceiveBank; - uint32_t packetSize, nbBytesRcv = 0; - uint32_t time_out = 0; - - while (len) { - if (!usb_check()) break; - - if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) { - packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, len); - len -= packetSize; - while (packetSize--) - data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT]; - UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank); - if (bank == AT91C_UDP_RX_DATA_BK0) { - bank = AT91C_UDP_RX_DATA_BK1; - } else { - bank = AT91C_UDP_RX_DATA_BK0; - } - } - if (time_out++ == 0x1fff) break; - } - - btReceiveBank = bank; - return nbBytesRcv; -} - - -//*---------------------------------------------------------------------------- -//* \fn usb_write -//* \brief Send through endpoint 2 +//* \fn AT91F_USB_SendZlp +//* \brief Send zero length packet through an endpoint //*---------------------------------------------------------------------------- -static uint32_t usb_write(const uint8_t* data, const size_t len) { - size_t length = len; - uint32_t cpt = 0; - - if (!length) return 0; - if (!usb_check()) return 0; - - // Send the first packet - cpt = MIN(length, AT91C_EP_IN_SIZE); - length -= cpt; - while (cpt--) { - pUdp->UDP_FDR[AT91C_EP_IN] = *data++; - } - UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); - - while (length) { - // Fill the next bank - cpt = MIN(length, AT91C_EP_IN_SIZE); - length -= cpt; - while (cpt--) { - pUdp->UDP_FDR[AT91C_EP_IN] = *data++; - } - // Wait for the previous bank to be sent - while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { - 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); - } - - // Wait for the end of transfer - while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { - 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) +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 */; - - return length; } @@ -476,7 +359,7 @@ static uint32_t usb_write(const uint8_t* data, const size_t len) { //* \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) { +static void AT91F_USB_SendData(const char *pData, uint32_t length) { uint32_t cpt = 0; AT91_REG csr; @@ -485,17 +368,17 @@ static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t leng length -= cpt; while (cpt--) - pUdp->UDP_FDR[0] = *pData++; + AT91C_BASE_UDP->UDP_FDR[0] = *pData++; - if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) { + if (AT91C_BASE_UDP->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) + 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 = pUdp->UDP_CSR[AT91C_EP_CONTROL]; + 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) { @@ -506,38 +389,24 @@ static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t leng } while (length); - if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) { + if (AT91C_BASE_UDP->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) + while (AT91C_BASE_UDP->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) { +static void AT91F_USB_SendStall(void) { UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL); - while (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_ISOERROR)) + 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 (pUdp->UDP_CSR[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 */; } @@ -550,137 +419,270 @@ 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)) + if (!(AT91C_BASE_UDP->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); + 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 (!(pUdp->UDP_CSR[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 (pUdp->UDP_CSR[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(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength)); + AT91F_USB_SendData(devDescriptor, MIN(sizeof(devDescriptor), wLength)); else if (wValue == 0x200) // Return Configuration Descriptor - AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength)); + 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(pUdp, strDescriptor, MIN(strDescriptor[0], wLength)); + AT91F_USB_SendData(strDescriptor, MIN(strDescriptor[0], wLength)); } else { - AT91F_USB_SendStall(pUdp); + AT91F_USB_SendStall(); } } else - AT91F_USB_SendStall(pUdp); + AT91F_USB_SendStall(); break; case STD_SET_ADDRESS: - AT91F_USB_SendZlp(pUdp); - pUdp->UDP_FADDR = (AT91C_UDP_FEN | wValue); - pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0; + 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(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; + 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(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration)); + 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(pUdp, (char *) &wStatus, sizeof(wStatus)); + AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus)); break; case STD_GET_STATUS_INTERFACE: wStatus = 0; // reserved for future use - AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); + AT91F_USB_SendData((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)); + 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(pUdp); + AT91F_USB_SendStall(); break; case STD_SET_FEATURE_ZERO: - AT91F_USB_SendStall(pUdp); + AT91F_USB_SendStall(); break; case STD_SET_FEATURE_INTERFACE: - AT91F_USB_SendZlp(pUdp); + 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)) { - pUdp->UDP_CSR[wIndex] = 0; - AT91F_USB_SendZlp(pUdp); + AT91C_BASE_UDP->UDP_CSR[wIndex] = 0; + AT91F_USB_SendZlp(AT91C_EP_CONTROL); } else - AT91F_USB_SendStall(pUdp); + AT91F_USB_SendStall(); break; case STD_CLEAR_FEATURE_ZERO: - AT91F_USB_SendStall(pUdp); + AT91F_USB_SendStall(); break; case STD_CLEAR_FEATURE_INTERFACE: - AT91F_USB_SendZlp(pUdp); + 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) - pUdp->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT); + AT91C_BASE_UDP->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); + AT91C_BASE_UDP->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); + 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(pUdp); + AT91F_USB_SendStall(); break; // handle CDC class requests case SET_LINE_CODING: - while (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RX_DATA_BK0)) + 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(pUdp); + AT91F_USB_SendZlp(AT91C_EP_CONTROL); break; case GET_LINE_CODING: - AT91F_USB_SendData(pUdp, (char *) &line, MIN(sizeof(line), wLength)); + AT91F_USB_SendData((char *) &line, MIN(sizeof(line), wLength)); break; case SET_CONTROL_LINE_STATE: btConnection = wValue; - AT91F_USB_SendZlp(pUdp); + AT91F_USB_SendZlp(AT91C_EP_CONTROL); break; default: - AT91F_USB_SendStall(pUdp); + AT91F_USB_SendStall(); break; } } +//*---------------------------------------------------------------------------- +//* \fn usb_check +//* \brief Test if the device is configured and handle enumeration +//*---------------------------------------------------------------------------- +static bool usb_check() { + AT91_REG isr = AT91C_BASE_UDP->UDP_ISR; + + if (isr & AT91C_UDP_ENDBUSRES) { + AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES; + // reset all endpoints + AT91C_BASE_UDP->UDP_RSTEP = (unsigned int)-1; + AT91C_BASE_UDP->UDP_RSTEP = 0; + // Enable the function + AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN; + // Configure endpoint 0 + AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL); + } else if (isr & AT91C_UDP_EPINT0) { + AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_EPINT0; + AT91F_CDC_Enumerate(); + } + return (btConfiguration) ? true : false; +} + + +bool usb_poll() { + if (!usb_check()) return false; + return (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] & btReceiveBank); +} + + +/** + In github PR #129, some users appears to get a false positive from + usb_poll, which returns true, but the usb_read operation + still returns 0. + This check is basically the same as above, but also checks + that the length available to read is non-zero, thus hopefully fixes the + bug. +**/ +bool usb_poll_validate_length() { + if (!usb_check()) return false; + if (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false; + return (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] >> 16) > 0; +} + + +//*---------------------------------------------------------------------------- +//* \fn usb_read +//* \brief Read available data from Endpoint OUT +//*---------------------------------------------------------------------------- +static uint32_t usb_read(uint8_t* data, size_t len) { + uint8_t bank = btReceiveBank; + uint32_t packetSize, nbBytesRcv = 0; + uint32_t time_out = 0; + + while (len) { + if (!usb_check()) break; + + if ( AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] & bank ) { + packetSize = MIN(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] >> 16, len); + len -= packetSize; + while (packetSize--) + data[nbBytesRcv++] = AT91C_BASE_UDP->UDP_FDR[AT91C_EP_OUT]; + UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank); + if (bank == AT91C_UDP_RX_DATA_BK0) { + bank = AT91C_UDP_RX_DATA_BK1; + } else { + bank = AT91C_UDP_RX_DATA_BK0; + } + } + if (time_out++ == 0x1fff) break; + } + + btReceiveBank = bank; + return nbBytesRcv; +} + + +//*---------------------------------------------------------------------------- +//* \fn usb_write +//* \brief Send through endpoint 2 +//*---------------------------------------------------------------------------- +static uint32_t usb_write(const uint8_t* data, const size_t len) { + size_t length = len; + uint32_t cpt = 0; + + if (!length) return 0; + if (!usb_check()) return 0; + + // Send the first packet + cpt = MIN(length, AT91C_EP_IN_SIZE); + length -= cpt; + while (cpt--) { + AT91C_BASE_UDP->UDP_FDR[AT91C_EP_IN] = *data++; + } + 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) { + // Fill the next bank + cpt = MIN(length, AT91C_EP_IN_SIZE); + length -= cpt; + while (cpt--) { + AT91C_BASE_UDP->UDP_FDR[AT91C_EP_IN] = *data++; + } + // Wait for the previous bank to be sent + while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { + if (!usb_check()) return length; + } + 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 + while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { + if (!usb_check()) return length; + } + UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); + while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) + /* 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; +} + + //*************************************************************************** // Interface to the main program //*************************************************************************** @@ -752,7 +754,7 @@ bool cmd_send_old(uint16_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, voi txcmd.d.asBytes[i] = ((uint8_t*)data)[i]; } } - + // Send frame and make sure all bytes are transmitted if (usb_write((uint8_t*)&txcmd, sizeof(UsbCommand)) != 0) return false; diff --git a/uart/uart.h b/uart/uart.h index 3b563be2..ce00bc0b 100644 --- a/uart/uart.h +++ b/uart/uart.h @@ -29,24 +29,21 @@ * @file uart.h */ -#ifndef _PM3_UART_H_ -#define _PM3_UART_H_ +#ifndef PM3_UART_H__ +#define PM3_UART_H__ -#include -#include #include - #include #include /* Used to substitute for an example serial port path on each platform. */ #ifdef _WIN32 -#define SERIAL_PORT_H "com3" +#define SERIAL_PORT_H "com3" #elif __APPLE__ -#define SERIAL_PORT_H "/dev/tty.usbmodem*" +#define SERIAL_PORT_H "/dev/tty.usbmodem*" #else -#define SERIAL_PORT_H "/dev/ttyACM0" +#define SERIAL_PORT_H "/dev/ttyACM0" #endif /* serial_port is declared as a void*, which you should cast to whatever type @@ -69,11 +66,11 @@ typedef void* 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. */ -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. * pbtRx: A pointer to a buffer for the returned data to be written to. @@ -84,15 +81,15 @@ void uart_close(const serial_port sp); * * Returns FALSE if there was an error reading from the device. Note that a * 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. * pbtTx: A pointer to a buffer containing the data to send. * 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. */ @@ -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. */ -uint32_t uart_get_speed(const serial_port sp); +extern uint32_t uart_get_speed(const serial_port sp); #endif // _PM3_UART_H_ diff --git a/uart/uart_win32.c b/uart/uart_win32.c index b15e8786..0e4227de 100644 --- a/uart/uart_win32.c +++ b/uart/uart_win32.c @@ -38,97 +38,109 @@ #include "uart.h" +#include +#include +#include + + // The windows serial port implementation #ifdef _WIN32 #include typedef struct { - HANDLE hPort; // Serial port handle - DCB dcb; // Device control settings - COMMTIMEOUTS ct; // Serial port time-out configuration + HANDLE hPort; // Serial port handle + DCB dcb; // Device control settings + COMMTIMEOUTS ct; // Serial port time-out configuration } serial_port_windows; + void upcase(char *p) { - while(*p != '\0') { - if(*p >= 97 && *p <= 122) { - *p -= 32; - } - ++p; - } + while(*p != '\0') { + if(*p >= 97 && *p <= 122) { + *p -= 32; + } + ++p; + } } -serial_port uart_open(const char* pcPortName) { - char acPortName[255]; - serial_port_windows* sp = malloc(sizeof(serial_port_windows)); - - // Copy the input "com?" to "\\.\COM?" format - sprintf(acPortName,"\\\\.\\%s",pcPortName); - upcase(acPortName); - - // Try to open the serial port - sp->hPort = CreateFileA(acPortName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); - if (sp->hPort == INVALID_HANDLE_VALUE) { - uart_close(sp); - return INVALID_SERIAL_PORT; - } - - // Prepare the device control - memset(&sp->dcb, 0, sizeof(DCB)); - sp->dcb.DCBlength = sizeof(DCB); - if(!BuildCommDCBA("baud=9600 data=8 parity=N stop=1",&sp->dcb)) { - uart_close(sp); - return INVALID_SERIAL_PORT; - } - - // Update the active serial port - if(!SetCommState(sp->hPort,&sp->dcb)) { - uart_close(sp); - return INVALID_SERIAL_PORT; - } - - sp->ct.ReadIntervalTimeout = 0; - sp->ct.ReadTotalTimeoutMultiplier = 0; - sp->ct.ReadTotalTimeoutConstant = 30; - sp->ct.WriteTotalTimeoutMultiplier = 0; - sp->ct.WriteTotalTimeoutConstant = 30; - - if(!SetCommTimeouts(sp->hPort,&sp->ct)) { - uart_close(sp); - return INVALID_SERIAL_PORT; - } - - PurgeComm(sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR); - - return sp; -} void uart_close(const serial_port sp) { - CloseHandle(((serial_port_windows*)sp)->hPort); - free(sp); + CloseHandle(((serial_port_windows*)sp)->hPort); + free(sp); } + +serial_port uart_open(const char* pcPortName) { + char acPortName[255]; + serial_port_windows* sp = malloc(sizeof(serial_port_windows)); + + // Copy the input "com?" to "\\.\COM?" format + sprintf(acPortName,"\\\\.\\%s",pcPortName); + upcase(acPortName); + + // Try to open the serial port + sp->hPort = CreateFileA(acPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + if (sp->hPort == INVALID_HANDLE_VALUE) { + uart_close(sp); + return INVALID_SERIAL_PORT; + } + + // Prepare the device control + memset(&sp->dcb, 0, sizeof(DCB)); + sp->dcb.DCBlength = sizeof(DCB); + if (!BuildCommDCBA("baud=9600 data=8 parity=N stop=1",&sp->dcb)) { + uart_close(sp); + return INVALID_SERIAL_PORT; + } + + // Update the active serial port + if (!SetCommState(sp->hPort,&sp->dcb)) { + uart_close(sp); + return INVALID_SERIAL_PORT; + } + + sp->ct.ReadIntervalTimeout = 0; + sp->ct.ReadTotalTimeoutMultiplier = 0; + sp->ct.ReadTotalTimeoutConstant = 30; + sp->ct.WriteTotalTimeoutMultiplier = 0; + sp->ct.WriteTotalTimeoutConstant = 30; + + if (!SetCommTimeouts(sp->hPort, &sp->ct)) { + uart_close(sp); + return INVALID_SERIAL_PORT; + } + + PurgeComm(sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR); + + return sp; +} + + 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) { - DWORD dwTxLen = 0; - return WriteFile(((serial_port_windows*)sp)->hPort, pbtTx, szTxLen, &dwTxLen, NULL); + DWORD dwTxLen = 0; + return WriteFile(((serial_port_windows*)sp)->hPort, pbtTx, szTxLen, &dwTxLen, NULL); } + bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) { - serial_port_windows* spw; - spw = (serial_port_windows*)sp; - spw->dcb.BaudRate = uiPortSpeed; - return SetCommState(spw->hPort, &spw->dcb); + serial_port_windows* spw; + spw = (serial_port_windows*)sp; + spw->dcb.BaudRate = uiPortSpeed; + return SetCommState(spw->hPort, &spw->dcb); } + uint32_t uart_get_speed(const serial_port sp) { - const serial_port_windows* spw = (serial_port_windows*)sp; - if (!GetCommState(spw->hPort, (serial_port)&spw->dcb)) { - return spw->dcb.BaudRate; - } - return 0; + const serial_port_windows* spw = (serial_port_windows*)sp; + if (!GetCommState(spw->hPort, (serial_port)&spw->dcb)) { + return spw->dcb.BaudRate; + } + return 0; } #endif