+ CmdsParse(CommandTable15, Cmd);
+ return 0;
+}
+
+int CmdHF15Help(const char *Cmd)
+{
+ CmdsHelp(CommandTable15);
+ return 0;
+}
+
+
+// "HF 15 Cmd" Interface
+// Allows direct communication with the tag on command level
+
+int CmdHF15CmdInquiry(const char *Cmd)
+{
+ UsbCommand *r;
+ uint8_t *recv;
+ UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
+ uint8_t *req=c.d.asBytes;
+ int reqlen=0;
+
+ req[0]= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
+ ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1;
+ req[1]=ISO15_CMD_INVENTORY;
+ req[2]=0; // mask length
+ reqlen=AddCrc(req,3);
+ c.arg[0]=reqlen;
+
+ SendCommand(&c);
+
+ r=WaitForResponseTimeout(CMD_ACK,1000);
+
+ if (r!=NULL) {
+ if (r->arg[0]>=12) {
+ recv = r->d.asBytes;
+ PrintAndLog("UID=%s",sprintUID(NULL,&recv[2]));
+ PrintAndLog("Tag Info: %s",getTagInfo(&recv[2]));
+ } else {
+ PrintAndLog("Response to short, just %i bytes. No tag?\n",r->arg[0]);
+ }
+ } else {
+ PrintAndLog("timeout.");
+ }
+ return 0;
+}
+
+
+// Turns debugging on(1)/off(0)
+int CmdHF15CmdDebug( const char *cmd) {
+ int debug=atoi(cmd);
+ if (strlen(cmd)<1) {
+ PrintAndLog("Usage: hf 15 cmd debug <0/1>");
+ PrintAndLog(" 0..no debugging output 1..turn debugging on");
+ return 0;
+ }
+
+ UsbCommand c = {CMD_ISO_15693_DEBUG, {debug, 0, 0}};
+ SendCommand(&c);
+ return 0;
+}
+
+
+int CmdHF15CmdRaw (const char *cmd) {
+ UsbCommand *r;
+ uint8_t *recv;
+ UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
+ int reply=1;
+ int fast=1;
+ int crc=0;
+ char buf[5]="";
+ int i=0;
+ uint8_t data[100];
+ unsigned int datalen=0, temp;
+ char *hexout;
+
+
+ if (strlen(cmd)<3) {
+ PrintAndLog("Usage: hf 15 cmd raw [-r] [-2] [-c] <0A 0B 0C ... hex>");
+ PrintAndLog(" -r do not read response");
+ PrintAndLog(" -2 use slower '1 out of 256' mode");
+ PrintAndLog(" -c calculate and append CRC");
+ PrintAndLog(" Tip: turn on debugging for verbose output");
+ return 0;
+ }
+
+ // strip
+ while (*cmd==' ' || *cmd=='\t') cmd++;
+
+ while (cmd[i]!='\0') {
+ if (cmd[i]==' ' || cmd[i]=='\t') { i++; continue; }
+ if (cmd[i]=='-') {
+ switch (cmd[i+1]) {
+ case 'r':
+ case 'R':
+ reply=0;
+ break;
+ case '2':
+ fast=0;
+ break;
+ case 'c':
+ case 'C':
+ crc=1;
+ break;
+ default:
+ PrintAndLog("Invalid option");
+ return 0;
+ }
+ i+=2;
+ continue;
+ }
+ if ((cmd[i]>='0' && cmd[i]<='9') ||
+ (cmd[i]>='a' && cmd[i]<='f') ||
+ (cmd[i]>='A' && cmd[i]<='F') ) {
+ buf[strlen(buf)+1]=0;
+ buf[strlen(buf)]=cmd[i];
+ i++;
+
+ if (strlen(buf)>=2) {
+ sscanf(buf,"%x",&temp);
+ data[datalen]=(uint8_t)(temp & 0xff);
+ datalen++;
+ *buf=0;
+ }
+ continue;
+ }
+ PrintAndLog("Invalid char on input");
+ return 0;
+ }
+ if (crc) datalen=AddCrc(data,datalen);
+
+ c.arg[0]=datalen;
+ c.arg[1]=fast;
+ c.arg[2]=reply;
+ memcpy(c.d.asBytes,data,datalen);
+
+ SendCommand(&c);
+
+ if (reply) {
+ r=WaitForResponseTimeout(CMD_ACK,1000);
+
+ if (r!=NULL) {
+ recv = r->d.asBytes;
+ PrintAndLog("received %i octets",r->arg[0]);
+ hexout = (char *)malloc(r->arg[0] * 3 + 1);
+ if (hexout != NULL) {
+ for (int i = 0; i < r->arg[0]; i++) { // data in hex
+ sprintf(&hexout[i * 3], "%02hX ", recv[i]);
+ }
+ PrintAndLog("%s", hexout);
+ free(hexout);
+ }
+ } else {
+ PrintAndLog("timeout while waiting for reply.");
+ }
+
+ } // if reply
+ return 0;
+}
+
+
+int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd[], int iso15cmdlen) {
+ int temp;
+ uint8_t *req=c->d.asBytes, uid[8];
+ uint32_t reqlen=0;
+
+ // strip
+ while (**cmd==' ' || **cmd=='\t') (*cmd)++;
+
+ if (strstr(*cmd,"-2")==*cmd) {
+ c->arg[1]=0; // use 1of256
+ (*cmd)+=2;
+ }
+
+ // strip
+ while (**cmd==' ' || **cmd=='\t') (*cmd)++;
+
+ if (strstr(*cmd,"-o")==*cmd) {
+ req[reqlen]=ISO15_REQ_OPTION;
+ (*cmd)+=2;
+ }
+
+ // strip
+ while (**cmd==' ' || **cmd=='\t') (*cmd)++;
+
+ switch (**cmd) {
+ case 0:
+ PrintAndLog("missing addr");
+ return 0;
+ break;
+ case 's':
+ case 'S':
+ // you must have selected the tag earlier
+ req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
+ ISO15_REQ_NONINVENTORY | ISO15_REQ_SELECT;
+ memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen);
+ reqlen+=iso15cmdlen;
+ break;
+ case 'u':
+ case 'U':
+ // unaddressed mode may not be supported by all vendors
+ req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
+ ISO15_REQ_NONINVENTORY;
+ memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen);
+ reqlen+=iso15cmdlen;
+ break;
+ case '*':
+ req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
+ ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS;
+ memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen);
+ reqlen+=iso15cmdlen;
+ if (!getUID(uid)) {
+ PrintAndLog("No Tag found");
+ return 0;
+ }
+ memcpy(req+reqlen,uid,8);
+ PrintAndLog("Detected UID %s",sprintUID(NULL,uid));
+ reqlen+=8;
+ break;
+ default:
+ req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
+ ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS;
+ memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen);
+ reqlen+=iso15cmdlen;
+
+/* sscanf(cmd,"%hX%hX%hX%hX%hX%hX%hX%hX",
+ (short unsigned int *)&uid[7],(short unsigned int *)&uid[6],
+ (short unsigned int *)&uid[5],(short unsigned int *)&uid[4],
+ (short unsigned int *)&uid[3],(short unsigned int *)&uid[2],
+ (short unsigned int *)&uid[1],(short unsigned int *)&uid[0]); */
+ for (int i=0;i<8 && (*cmd)[i*2] && (*cmd)[i*2+1];i++) { // parse UID
+ sscanf((char[]){(*cmd)[i*2],(*cmd)[i*2+1],0},"%X",&temp);
+ uid[7-i]=temp&0xff;
+ }
+
+ PrintAndLog("Using UID %s",sprintUID(NULL,uid));
+ memcpy(&req[reqlen],&uid[0],8);
+ reqlen+=8;
+ }
+ // skip to next space
+ while (**cmd!=' ' && **cmd!='\t') (*cmd)++;
+ // skip over the space
+ while (**cmd==' ' || **cmd=='\t') (*cmd)++;
+
+ c->arg[0]=reqlen;
+ return 1;
+}
+
+
+
+/**
+ * Commandline handling: HF15 CMD SYSINFO
+ * get system information from tag/VICC
+ */
+int CmdHF15CmdSysinfo(const char *Cmd) {
+ UsbCommand *r;
+ uint8_t *recv;
+ UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
+ uint8_t *req=c.d.asBytes;
+ int reqlen=0;
+ char cmdbuf[100];
+ char *cmd=cmdbuf;
+ char output[2048]="";
+ int i;
+
+ strncpy(cmd,Cmd,99);
+
+ // usage:
+ if (strlen(cmd)<1) {
+ PrintAndLog("Usage: hf 15 cmd sysinfo [options] <uid|s|*>");
+ PrintAndLog(" options:");
+ PrintAndLog(" -2 use slower '1 out of 256' mode");
+ PrintAndLog(" uid (either): ");
+ PrintAndLog(" <8B hex> full UID eg E011223344556677");
+ PrintAndLog(" s selected tag");
+ PrintAndLog(" u unaddressed mode");
+ PrintAndLog(" * scan for tag");
+ PrintAndLog(" start#: page number to start 0-255");
+ PrintAndLog(" count#: number of pages");
+ return 0;
+ }
+
+ prepareHF15Cmd(&cmd, &c,(uint8_t[]){ISO15_CMD_SYSINFO},1);
+ reqlen=c.arg[0];
+
+ reqlen=AddCrc(req,reqlen);
+ c.arg[0]=reqlen;
+
+ SendCommand(&c);
+
+ r=WaitForResponseTimeout(CMD_ACK,1000);
+
+ if (r!=NULL && r->arg[0]>2) {
+ recv = r->d.asBytes;
+ if (ISO15_CRC_CHECK==Crc(recv,r->arg[0])) {
+ if (!(recv[0] & ISO15_RES_ERROR)) {
+ *output=0; // reset outputstring
+ for ( i=1; i<r->arg[0]-2; i++) {
+ sprintf(output+strlen(output),"%02hX ",recv[i]);
+ }
+ strcat(output,"\n\r");
+ strcat(output,"UID = ");
+ strcat(output,sprintUID(NULL,recv+2));
+ strcat(output,"\n\r");
+ strcat(output,getTagInfo(recv+2)); //ABC
+ strcat(output,"\n\r");
+ i=10;
+ if (recv[1] & 0x01)
+ sprintf(output+strlen(output),"DSFID supported, set to %02hX\n\r",recv[i++]);
+ else
+ strcat(output,"DSFID not supported\n\r");
+ if (recv[1] & 0x02)
+ sprintf(output+strlen(output),"AFI supported, set to %03hX\n\r",recv[i++]);
+ else
+ strcat(output,"AFI not supported\n\r");
+ if (recv[1] & 0x04) {
+ strcat(output,"Tag provides info on memory layout (vendor dependent)\n\r");
+ sprintf(output+strlen(output)," %i (or %i) bytes/page x %i pages \n\r",
+ (recv[i+1]&0x1F)+1, (recv[i+1]&0x1F), recv[i]+1);
+ i+=2;
+ } else
+ strcat(output,"Tag does not provide information on memory layout\n\r");
+ if (recv[1] & 0x08) sprintf(output+strlen(output),"IC reference given: %02hX\n\r",recv[i++]);
+ else strcat(output,"IC reference not given\n\r");
+
+
+ PrintAndLog("%s",output);
+ } else {
+ PrintAndLog("Tag returned Error %i: %s",recv[0],TagErrorStr(recv[0]));
+ }
+ } else {
+ PrintAndLog("CRC failed");
+ }
+ } else {
+ PrintAndLog("timeout: no answer");
+ }
+
+ return 0;
+}
+
+
+
+int CmdHF15CmdRead(const char *Cmd) {
+ UsbCommand *r;
+ uint8_t *recv;
+ UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
+ uint8_t *req=c.d.asBytes;
+ int reqlen=0, pagenum;
+ char cmdbuf[100];
+ char *cmd=cmdbuf;
+ char output[100]="";
+
+ strncpy(cmd,Cmd,99);
+
+ // usage:
+ if (strlen(cmd)<3) {
+ PrintAndLog("Usage: hf 15 cmd read [options] <uid|s|*> <page#>");
+ PrintAndLog(" options:");
+ PrintAndLog(" -2 use slower '1 out of 256' mode");
+ PrintAndLog(" uid (either): ");
+ PrintAndLog(" <8B hex> full UID eg E011223344556677");
+ PrintAndLog(" s selected tag");
+ PrintAndLog(" u unaddressed mode");
+ PrintAndLog(" * scan for tag");
+ PrintAndLog(" page#: page number 0-255");
+ return 0;
+ }
+
+ prepareHF15Cmd(&cmd, &c,(uint8_t[]){ISO15_CMD_READ},1);
+ reqlen=c.arg[0];
+
+ pagenum=strtol(cmd,NULL,0);
+ /*if (pagenum<0) {
+ PrintAndLog("invalid pagenum");
+ return 0;
+ } */
+
+ req[reqlen++]=(uint8_t)pagenum;
+
+ reqlen=AddCrc(req,reqlen);
+
+ c.arg[0]=reqlen;
+
+ SendCommand(&c);
+
+ r=WaitForResponseTimeout(CMD_ACK,1000);
+
+ if (r!=NULL && r->arg[0]>2) {
+ recv = r->d.asBytes;
+ if (ISO15_CRC_CHECK==Crc(recv,r->arg[0])) {
+ if (!(recv[0] & ISO15_RES_ERROR)) {
+ *output=0; // reset outputstring
+ //sprintf(output, "Block %2i ",blocknum);
+ for ( int i=1; i<r->arg[0]-2; i++) {
+ sprintf(output+strlen(output),"%02hX ",recv[i]);
+ }
+ strcat(output," ");
+ for ( int i=1; i<r->arg[0]-2; i++) {
+ sprintf(output+strlen(output),"%c",recv[i]>31 && recv[i]<127?recv[i]:'.');
+ }
+ PrintAndLog("%s",output);
+ } else {
+ PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1]));
+ }
+ } else {
+ PrintAndLog("CRC failed");
+ }
+ } else {
+ PrintAndLog("no answer");
+ }
+
+ return 0;