From: roel@libnfc.org <roel@libnfc.org@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Date: Wed, 27 Feb 2013 13:23:38 +0000 (+0000)
Subject: fixed USB GPIO bug reported by gregy, and fixed 'hf 14a reader' command
X-Git-Tag: v1.0.0~130^2~15
X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/79a73ab2d1a63fdf75d42774e160a9335d893416?ds=sidebyside

fixed USB GPIO bug reported by gregy, and fixed 'hf 14a reader' command
---

diff --git a/armsrc/apps.h b/armsrc/apps.h
index 94bc5b04..5543d585 100644
--- a/armsrc/apps.h
+++ b/armsrc/apps.h
@@ -183,7 +183,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd);
 
 // cmd.h
 bool cmd_receive(UsbCommand* cmd);
-bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, byte_t* data, size_t len);
+bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len);
 
 /// util.h
 
diff --git a/armsrc/cmd.c b/armsrc/cmd.c
index c414bc39..ff5c4f81 100644
--- a/armsrc/cmd.c
+++ b/armsrc/cmd.c
@@ -1,7 +1,7 @@
 /*
  * Proxmark send and receive commands
  *
- * Copyright (c) 2010, Roel Verdult
+ * Copyright (c) 2012, Roel Verdult
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -52,7 +52,7 @@ bool cmd_receive(UsbCommand* cmd) {
   return true;
 }
 
-bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, byte_t* data, size_t len) {
+bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len) {
   UsbCommand txcmd;
 
   // Compose the outgoing command frame
@@ -63,7 +63,7 @@ bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, byte_t*
 
   // Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE
   if (data && len) {
-    memcpy(txcmd.d.asBytes,data,MIN(len,USB_CMD_DATA_SIZE));
+    memcpy(txcmd.d.asBytes,(byte_t*)data,MIN(len,USB_CMD_DATA_SIZE));
 	  }
   
   // Send frame and make sure all bytes are transmitted
diff --git a/armsrc/cmd.h b/armsrc/cmd.h
index c10a534f..b330a219 100644
--- a/armsrc/cmd.h
+++ b/armsrc/cmd.h
@@ -38,7 +38,7 @@
 #include "usb_cdc.h"
 
 bool cmd_receive(UsbCommand* cmd);
-bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, byte_t* data, size_t len);
+bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len);
 
 #endif // _PROXMARK_CMD_H_
 
diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c
index d2ebb0c6..7c1db14b 100644
--- a/armsrc/iso14443a.c
+++ b/armsrc/iso14443a.c
@@ -1636,31 +1636,36 @@ int ReaderReceivePar(uint8_t* receivedAnswer, uint32_t * parptr)
 /* performs iso14443a anticolision procedure
  * fills the uid pointer unless NULL
  * fills resp_data unless NULL */
-int iso14443a_select_card(uint8_t * uid_ptr, iso14a_card_select_t * resp_data, uint32_t * cuid_ptr) {
+int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, uint32_t* cuid_ptr) {
 	uint8_t wupa[]       = { 0x52 };  // 0x26 - REQA  0x52 - WAKE-UP
 	uint8_t sel_all[]    = { 0x93,0x20 };
 	uint8_t sel_uid[]    = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
 	uint8_t rats[]       = { 0xE0,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0
-
 	uint8_t* resp = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);	// was 3560 - tied to other size changes
+  byte_t uid_resp[4];
+  size_t uid_resp_len;
 
 	uint8_t sak = 0x04; // cascade uid
 	int cascade_level = 0;
-
 	int len;
-	
-	// clear uid
-	memset(uid_ptr, 0, 12);
-
+	 
 	// Broadcast for a card, WUPA (0x52) will force response from all cards in the field
 	ReaderTransmitShort(wupa);
 	// Receive the ATQA
 	if(!ReaderReceive(resp)) return 0;
 //  Dbprintf("atqa: %02x %02x",resp[0],resp[1]);
   
-	if(resp_data)
-		memcpy(resp_data->atqa, resp, 2);
+	if(p_hi14a_card) {
+		memcpy(p_hi14a_card->atqa, resp, 2);
+    p_hi14a_card->uidlen = 0;
+    memset(p_hi14a_card->uid,0,10);
+  }
 	
+  // clear uid
+  if (uid_ptr) {
+    memset(uid_ptr,0,10);
+  }
+
 	// OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
 	// which case we need to make a cascade 2 request and select - this is a long UID
 	// While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
@@ -1672,12 +1677,16 @@ int iso14443a_select_card(uint8_t * uid_ptr, iso14a_card_select_t * resp_data, u
 		// SELECT_ALL
 		ReaderTransmit(sel_all,sizeof(sel_all));
 		if (!ReaderReceive(resp)) return 0;
-//    Dbprintf("uid: %02x %02x %02x %02x",resp[0],resp[1],resp[2],resp[3]);
-
-		if(uid_ptr) memcpy(uid_ptr + cascade_level*4, resp, 4);
-		
+    
+    // First backup the current uid 
+    memcpy(uid_resp,resp,4);
+    uid_resp_len = 4;
+    //    Dbprintf("uid: %02x %02x %02x %02x",uid_resp[0],uid_resp[1],uid_resp[2],uid_resp[3]);
+    
 		// calculate crypto UID
-		if(cuid_ptr) *cuid_ptr = bytes_to_num(resp, 4);
+		if(cuid_ptr) {
+      *cuid_ptr = bytes_to_num(uid_resp, 4);
+    }
 
 		// Construct SELECT UID command
 		memcpy(sel_uid+2,resp,5);
@@ -1687,34 +1696,47 @@ int iso14443a_select_card(uint8_t * uid_ptr, iso14a_card_select_t * resp_data, u
 		// Receive the SAK
 		if (!ReaderReceive(resp)) return 0;
 		sak = resp[0];
+
+    // Test if more parts of the uid are comming
+    if ((sak & 0x04) && uid_resp[0] == 0x88) {
+      // Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of:
+      // http://www.nxp.com/documents/application_note/AN10927.pdf
+      memcpy(uid_ptr, uid_ptr + 1, 3);
+      uid_resp_len = 3;
+    }
+    
+    if(uid_ptr) {
+      memcpy(uid_ptr + (cascade_level*3), uid_resp, uid_resp_len);
+    }
+    
+    if(p_hi14a_card) {
+      memcpy(p_hi14a_card->uid + (cascade_level*3), uid_resp, uid_resp_len);
+      p_hi14a_card->uidlen += uid_resp_len;
+    }
 	}
-	if(resp_data) {
-		resp_data->sak = sak;
-		resp_data->ats_len = 0;
-	}
-	//--  this byte not UID, it CT.  http://www.nxp.com/documents/application_note/AN10927.pdf  page 3
-	if (uid_ptr[0] == 0x88) {  
-		memcpy(uid_ptr, uid_ptr + 1, 7);
-		uid_ptr[7] = 0;
+
+	if(p_hi14a_card) {
+		p_hi14a_card->sak = sak;
+		p_hi14a_card->ats_len = 0;
 	}
 
-	if( (sak & 0x20) == 0)
+	if( (sak & 0x20) == 0) {
 		return 2; // non iso14443a compliant tag
+  }
 
 	// Request for answer to select
-	if(resp_data) {  // JCOP cards - if reader sent RATS then there is no MIFARE session at all!!!
+	if(p_hi14a_card) {  // JCOP cards - if reader sent RATS then there is no MIFARE session at all!!!
 		AppendCrc14443a(rats, 2);
 		ReaderTransmit(rats, sizeof(rats));
 		
 		if (!(len = ReaderReceive(resp))) return 0;
 		
-		memcpy(resp_data->ats, resp, sizeof(resp_data->ats));
-		resp_data->ats_len = len;
+		memcpy(p_hi14a_card->ats, resp, sizeof(p_hi14a_card->ats));
+		p_hi14a_card->ats_len = len;
 	}
 	
 	// reset the PCB block number
 	iso14_pcb_blocknum = 0;
-	
 	return 1;
 }
 
@@ -1774,18 +1796,20 @@ void ReaderIso14443a(UsbCommand * c)
 	iso14a_command_t param = c->arg[0];
 	uint8_t * cmd = c->d.asBytes;
 	size_t len = c->arg[1];
-  uint32_t arg0;
-  byte_t buf[48];
+  uint32_t arg0 = 0;
+  byte_t buf[USB_CMD_DATA_SIZE];
   
   iso14a_clear_trace();
   iso14a_set_tracing(true);
 
-	if(param & ISO14A_REQUEST_TRIGGER) iso14a_set_trigger(1);
+	if(param & ISO14A_REQUEST_TRIGGER) {
+    iso14a_set_trigger(1);
+  }
 
 	if(param & ISO14A_CONNECT) {
 		iso14443a_setup();
-		arg0 = iso14443a_select_card(buf, (iso14a_card_select_t *)(buf+12), NULL);
-		cmd_send(CMD_ACK,arg0,0,0,buf,48);
+		arg0 = iso14443a_select_card(NULL,(iso14a_card_select_t*)buf,NULL);
+		cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(iso14a_card_select_t));
 //    UsbSendPacket((void *)ack, sizeof(UsbCommand));
 	}
 
@@ -1799,7 +1823,7 @@ void ReaderIso14443a(UsbCommand * c)
 
 	if(param & ISO14A_APDU) {
 		arg0 = iso14_apdu(cmd, len, buf);
-		cmd_send(CMD_ACK,arg0,0,0,buf,48);
+		cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf));
 //		UsbSendPacket((void *)ack, sizeof(UsbCommand));
 	}
 
@@ -1811,13 +1835,16 @@ void ReaderIso14443a(UsbCommand * c)
 		ReaderTransmit(cmd,len);
 		arg0 = ReaderReceive(buf);
 //		UsbSendPacket((void *)ack, sizeof(UsbCommand));
-    cmd_send(CMD_ACK,arg0,0,0,buf,48);
+    cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf));
 	}
 
-	if(param & ISO14A_REQUEST_TRIGGER) iso14a_set_trigger(0);
+	if(param & ISO14A_REQUEST_TRIGGER) {
+    iso14a_set_trigger(0);
+  }
 
-	if(param & ISO14A_NO_DISCONNECT)
+	if(param & ISO14A_NO_DISCONNECT) {
 		return;
+  }
 
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 	LEDsoff();
diff --git a/armsrc/usb_cdc.c b/armsrc/usb_cdc.c
index b8aee5a4..fa1f849e 100644
--- a/armsrc/usb_cdc.c
+++ b/armsrc/usb_cdc.c
@@ -34,6 +34,7 @@
 
 #include "usb_cdc.h"
 #include "util.h"
+#include "config_gpio.h"
 
 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
@@ -217,12 +218,12 @@ byte_t btConnection    = 0;
 byte_t btReceiveBank   = AT91C_UDP_RX_DATA_BK0;
 
 //*----------------------------------------------------------------------------
-//* \fn    AT91F_USB_Disable
+//* \fn    usb_disable
 //* \brief This function deactivates the USB device
 //*----------------------------------------------------------------------------
 void usb_disable() {
-  // Disconnect and reconnect USB controller for 100ms
-  AT91C_BASE_PIOA->PIO_ODR = AT91C_PIO_PA24;
+  // Disconnect the USB device
+  AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU;
   SpinDelay(100);
   
   // Clear all lingering interrupts
@@ -232,7 +233,7 @@ void usb_disable() {
 }
 
 //*----------------------------------------------------------------------------
-//* \fn    AT91F_USB_Enable
+//* \fn    usb_enable
 //* \brief This function Activates the USB device
 //*----------------------------------------------------------------------------
 void usb_enable() {
@@ -246,25 +247,25 @@ void usb_enable() {
   
   // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO
   // Set in PIO mode and Configure in Output
-  AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA16; // Set in PIO mode
-	AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA16; // Configure as Output
+  AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode
+	AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output
   
-  // Clear for set the Pul up resistor
-	AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA16;
+  // Clear for set the Pullup resistor
+	AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU;
   
-  // Disconnect and USB device
+  // Disconnect and reconnect USB controller for 100ms
   usb_disable();
   
   // Wait for a short while
   SpinDelay(100);
 
   // Reconnect USB reconnect
-  AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA24;
-  AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA24;
+  AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU;
+  AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU;
 }
 
 //*----------------------------------------------------------------------------
-//* \fn    AT91F_UDP_IsConfigured
+//* \fn    usb_check
 //* \brief Test if the device is configured and handle enumeration
 //*----------------------------------------------------------------------------
 bool usb_check() {
@@ -295,7 +296,7 @@ bool usb_poll()
 }
 
 //*----------------------------------------------------------------------------
-//* \fn    AT91F_UDP_Read
+//* \fn    usb_read
 //* \brief Read available data from Endpoint OUT
 //*----------------------------------------------------------------------------
 uint32_t usb_read(byte_t* data, size_t len) {
@@ -328,7 +329,7 @@ uint32_t usb_read(byte_t* data, size_t len) {
 }
 
 //*----------------------------------------------------------------------------
-//* \fn    AT91F_CDC_Write
+//* \fn    usb_write
 //* \brief Send through endpoint 2
 //*----------------------------------------------------------------------------
 uint32_t usb_write(const byte_t* data, const size_t len) {
diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c
index a82c7e35..79273040 100644
--- a/client/cmdhf14a.c
+++ b/client/cmdhf14a.c
@@ -168,8 +168,8 @@ int CmdHF14AReader(const char *Cmd)
 	UsbCommand resp;
   WaitForResponse(CMD_ACK,&resp);
 	
-  uint8_t              * uid  = resp.d.asBytes;
-	iso14a_card_select_t * card = (iso14a_card_select_t *)(uid + 12);
+	iso14a_card_select_t *card = (iso14a_card_select_t *)resp.d.asBytes;
+  uint8_t              * uid = card->uid;
 
 	if(resp.arg[0] == 0) {
 		PrintAndLog("iso14443a card select failed");
@@ -177,24 +177,24 @@ int CmdHF14AReader(const char *Cmd)
 	}
 
 	PrintAndLog("ATQA : %02x %02x", card->atqa[0], card->atqa[1]);
-	PrintAndLog(" UID : %s", sprint_hex(uid, 12));
+	PrintAndLog(" UID : %s", sprint_hex(card->uid, card->uidlen));
 	PrintAndLog(" SAK : %02x [%d]", card->sak, resp.arg[0]);
 
 	switch (card->sak) {
-		case 0x00: PrintAndLog(" SAK : NXP MIFARE Ultralight | Ultralight C"); break;
-		case 0x04: PrintAndLog(" SAK : NXP MIFARE (various !DESFire !DESFire EV1)"); break;
-
-		case 0x08: PrintAndLog(" SAK : NXP MIFARE CLASSIC 1k | Plus 2k"); break;
-		case 0x09: PrintAndLog(" SAK : NXP MIFARE Mini 0.3k"); break;
-		case 0x10: PrintAndLog(" SAK : NXP MIFARE Plus 2k"); break;
-		case 0x11: PrintAndLog(" SAK : NXP MIFARE Plus 4k"); break;
-		case 0x18: PrintAndLog(" SAK : NXP MIFARE Classic 4k | Plus 4k"); break;
-		case 0x20: PrintAndLog(" SAK : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k | JCOP 31/41"); break;
-		case 0x24: PrintAndLog(" SAK : NXP MIFARE DESFire | DESFire EV1"); break;
-		case 0x28: PrintAndLog(" SAK : JCOP31 or JCOP41 v2.3.1"); break;
-		case 0x38: PrintAndLog(" SAK : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); break;
-		case 0x88: PrintAndLog(" SAK : Infineon MIFARE CLASSIC 1K"); break;
-		case 0x98: PrintAndLog(" SAK : Gemplus MPCOS"); break;
+		case 0x00: PrintAndLog("TYPE : NXP MIFARE Ultralight | Ultralight C"); break;
+		case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break;
+
+		case 0x08: PrintAndLog("TYPE : NXP MIFARE CLASSIC 1k | Plus 2k"); break;
+		case 0x09: PrintAndLog("TYPE : NXP MIFARE Mini 0.3k"); break;
+		case 0x10: PrintAndLog("TYPE : NXP MIFARE Plus 2k"); break;
+		case 0x11: PrintAndLog("TYPE : NXP MIFARE Plus 4k"); break;
+		case 0x18: PrintAndLog("TYPE : NXP MIFARE Classic 4k | Plus 4k"); break;
+		case 0x20: PrintAndLog("TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k | JCOP 31/41"); break;
+		case 0x24: PrintAndLog("TYPE : NXP MIFARE DESFire | DESFire EV1"); break;
+		case 0x28: PrintAndLog("TYPE : JCOP31 or JCOP41 v2.3.1"); break;
+		case 0x38: PrintAndLog("TYPE : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); break;
+		case 0x88: PrintAndLog("TYPE : Infineon MIFARE CLASSIC 1K"); break;
+		case 0x98: PrintAndLog("TYPE : Gemplus MPCOS"); break;
 		default: ;
 	}
 	if(resp.arg[0] == 1) {
@@ -314,9 +314,9 @@ int CmdHF14AReader(const char *Cmd)
 				}
 			}
 		}
-	}
-	else
-		PrintAndLog("proprietary non-iso14443a card found, RATS not supported");
+	} else {
+		PrintAndLog("proprietary non iso14443a-4 card found, RATS not supported");
+  }
 
 	return resp.arg[0];
 }
diff --git a/client/cmdmain.c b/client/cmdmain.c
index 2fdaabc1..62eef122 100644
--- a/client/cmdmain.c
+++ b/client/cmdmain.c
@@ -100,13 +100,15 @@ void CommandReceived(char *Cmd) {
 //-----------------------------------------------------------------------------
 void UsbCommandReceived(UsbCommand *UC)
 {
+  /*
   //  Debug
-  //  printf("UsbCommand length[len=%d]\n",sizeof(UsbCommand));
-  //  printf("  cmd[len=%d]: %x\n",sizeof(UC->cmd),UC->cmd);
-  //  printf(" arg0[len=%d]: %x\n",sizeof(UC->arg[0]),UC->arg[0]);
-  //  printf(" arg1[len=%d]: %x\n",sizeof(UC->arg[1]),UC->arg[1]);
-  //  printf(" arg2[len=%d]: %x\n",sizeof(UC->arg[2]),UC->arg[2]);
-  //  printf(" data[len=%d]: %02x%02x%02x...\n",sizeof(UC->d.asBytes),UC->d.asBytes[0],UC->d.asBytes[1],UC->d.asBytes[2]);
+  printf("UsbCommand length[len=%zd]\n",sizeof(UsbCommand));
+  printf("  cmd[len=%zd]: %llx\n",sizeof(UC->cmd),UC->cmd);
+  printf(" arg0[len=%zd]: %llx\n",sizeof(UC->arg[0]),UC->arg[0]);
+  printf(" arg1[len=%zd]: %llx\n",sizeof(UC->arg[1]),UC->arg[1]);
+  printf(" arg2[len=%zd]: %llx\n",sizeof(UC->arg[2]),UC->arg[2]);
+  printf(" data[len=%zd]: %02x%02x%02x...\n",sizeof(UC->d.asBytes),UC->d.asBytes[0],UC->d.asBytes[1],UC->d.asBytes[2]);
+  */
 
   //	printf("%s(%x) current cmd = %x\n", __FUNCTION__, c->cmd, current_command);
   // If we recognize a response, return to avoid further processing