fix little endian vs big endian in the macros... again... but this time correct
[RRG-proxmark3.git] / client / src / cmdlfcotag.c
blob8f4e844a75610550555c061ae0973c2487fd1e54
1 //-----------------------------------------------------------------------------
2 // Iceman
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //-----------------------------------------------------------------------------
8 // Low frequency COTAG commands
9 //-----------------------------------------------------------------------------
10 #include "cmdlfcotag.h" // COTAG function declarations
11 #include <string.h>
12 #include <stdio.h>
13 #include "cmdparser.h" // command_t
14 #include "comms.h"
15 #include "lfdemod.h"
16 #include "cmddata.h" // getSamples
17 #include "ui.h" // PrintAndLog
18 #include "ctype.h" // tolower
19 #include "cliparser.h"
21 static int CmdHelp(const char *Cmd);
23 // COTAG demod should be able to use GraphBuffer,
24 // when data load samples
25 int demodCOTAG(bool verbose) {
26 (void) verbose; // unused so far
28 uint8_t bits[COTAG_BITS] = {0};
29 size_t bitlen = COTAG_BITS;
30 memcpy(bits, DemodBuffer, COTAG_BITS);
32 uint8_t alignPos = 0;
33 uint16_t err = manrawdecode(bits, &bitlen, 1, &alignPos);
34 if (err > 50) {
35 PrintAndLogEx(DEBUG, "DEBUG: Error - COTAG too many errors: %d", err);
36 return PM3_ESOFT;
39 setDemodBuff(bits, bitlen, 0);
41 //got a good demod
42 uint16_t cn = bytebits_to_byteLSBF(bits + 1, 16);
43 uint32_t fc = bytebits_to_byteLSBF(bits + 1 + 16, 8);
45 uint32_t raw1 = bytebits_to_byteLSBF(bits, 32);
46 uint32_t raw2 = bytebits_to_byteLSBF(bits + 32, 32);
47 uint32_t raw3 = bytebits_to_byteLSBF(bits + 64, 32);
48 uint32_t raw4 = bytebits_to_byteLSBF(bits + 96, 32);
51 fc 161: 1010 0001 -> LSB 1000 0101
52 cn 33593 1000 0011 0011 1001 -> LSB 1001 1100 1100 0001
53 cccc cccc cccc cccc ffffffff
54 0 1001 1100 1100 0001 1000 0101 0000 0000 100001010000000001111011100000011010000010000000000000000000000000000000000000000000000000000000100111001100000110000101000
55 1001 1100 1100 0001 10000101
57 PrintAndLogEx(SUCCESS, "COTAG Found: FC %u, CN: %u Raw: %08X%08X%08X%08X", fc, cn, raw1, raw2, raw3, raw4);
58 return PM3_SUCCESS;
61 static int CmdCOTAGDemod(const char *Cmd) {
62 CLIParserContext *ctx;
63 CLIParserInit(&ctx, "lf cotag demod",
64 "Try to find COTAG preamble, if found decode / descramble data",
65 "lf cotag demod"
68 void *argtable[] = {
69 arg_param_begin,
70 arg_param_end
72 CLIExecWithReturn(ctx, Cmd, argtable, true);
73 CLIParserFree(ctx);
74 return demodCOTAG(true);
77 // When reading a COTAG.
78 // 0 = HIGH/LOW signal - maxlength bigbuff
79 // 1 = translation for HI/LO into bytes with manchester 0,1 - length 300
80 // 2 = raw signal - maxlength bigbuff
81 static int CmdCOTAGReader(const char *Cmd) {
83 CLIParserContext *ctx;
84 CLIParserInit(&ctx, "lf cotag reader",
85 "read a COTAG tag, the current support for COTAG is limited. ",
86 "lf cotag reader -2"
89 void *argtable[] = {
90 arg_param_begin,
91 arg_lit0("1", NULL, "HIGH/LOW signal; maxlength bigbuff"),
92 arg_lit0("2", NULL, "translation of HIGH/LOW into bytes with manchester 0,1"),
93 arg_lit0("3", NULL, "raw signal; maxlength bigbuff"),
94 arg_param_end
97 CLIExecWithReturn(ctx, Cmd, argtable, false);
98 bool mode0 = arg_get_lit(ctx, 1);
99 bool mode1 = arg_get_lit(ctx, 2);
100 bool mode2 = arg_get_lit(ctx, 3);
101 CLIParserFree(ctx);
103 if ((mode0 + mode1 + mode2) > 1) {
104 PrintAndLogEx(ERR, "You can only use one option at a time");
105 return PM3_EINVARG;
107 uint8_t mode = 0xFF;
108 if (mode0)
109 mode = 0;
110 if (mode1)
111 mode = 1;
112 if (mode2)
113 mode = 2;
115 struct p {
116 uint8_t mode;
117 } PACKED payload;
118 payload.mode = mode;
120 PacketResponseNG resp;
121 clearCommandBuffer();
122 SendCommandNG(CMD_LF_COTAG_READ, (uint8_t *)&payload, sizeof(payload));
124 uint8_t timeout = 3;
125 int res = PM3_SUCCESS;
126 while (!WaitForResponseTimeout(CMD_LF_COTAG_READ, &resp, 1000)) {
127 timeout--;
128 PrintAndLogEx(NORMAL, "." NOLF);
129 if (timeout == 0) {
130 PrintAndLogEx(NORMAL, "");
131 PrintAndLogEx(WARNING, "command execution time out");
132 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
133 res = PM3_ETIMEOUT;
137 if (res != PM3_SUCCESS) {
138 return res;
141 if (timeout != 3)
142 PrintAndLogEx(NORMAL, "");
144 switch (payload.mode) {
145 case 0:
146 case 2: {
147 CmdPlot("");
148 CmdGrid("384");
149 getSamples(0, false);
150 break;
152 case 1: {
153 memcpy(DemodBuffer, resp.data.asBytes, resp.length);
154 DemodBufferLen = resp.length;
155 return demodCOTAG(true);
158 return PM3_SUCCESS;
161 static command_t CommandTable[] = {
162 {"help", CmdHelp, AlwaysAvailable, "This help"},
163 {"demod", CmdCOTAGDemod, AlwaysAvailable, "demodulate an COTAG tag"},
164 {"reader", CmdCOTAGReader, IfPm3Lf, "attempt to read and extract tag data"},
165 {NULL, NULL, NULL, NULL}
167 static int CmdHelp(const char *Cmd) {
168 (void)Cmd; // Cmd is not used so far
169 CmdsHelp(CommandTable);
170 return PM3_SUCCESS;
173 int CmdLFCOTAG(const char *Cmd) {
174 clearCommandBuffer();
175 return CmdsParse(CommandTable, Cmd);
178 int readCOTAGUid(void) {
179 return (CmdCOTAGReader("-2") == PM3_SUCCESS);