Merge pull request #2616 from jmichelp/fix14b
[RRG-proxmark3.git] / armsrc / util.c
blob0df89352d2b594f79f62b7e185cc60aa9d77975d
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Jonathan Westhues, Sept 2005
3 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 //
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // See LICENSE.txt for the text of the license.
16 //-----------------------------------------------------------------------------
17 // Utility functions used in many places, not specific to any piece of code.
18 //-----------------------------------------------------------------------------
19 #include "util.h"
21 #include "proxmark3_arm.h"
22 #include "ticks.h"
23 #include "commonutil.h"
24 #include "dbprint.h"
25 #include "string.h"
26 #include "usb_cdc.h"
27 #include "usart.h"
29 size_t nbytes(size_t nbits) {
30 return (nbits >> 3) + ((nbits % 8) > 0);
33 //convert hex digit to integer
34 uint8_t hex2int(char x) {
35 switch (x) {
36 case '0':
37 return 0;
38 case '1':
39 return 1;
40 case '2':
41 return 2;
42 case '3':
43 return 3;
44 case '4':
45 return 4;
46 case '5':
47 return 5;
48 case '6':
49 return 6;
50 case '7':
51 return 7;
52 case '8':
53 return 8;
54 case '9':
55 return 9;
56 case 'a':
57 case 'A':
58 return 10;
59 case 'b':
60 case 'B':
61 return 11;
62 case 'c':
63 case 'C':
64 return 12;
65 case 'd':
66 case 'D':
67 return 13;
68 case 'e':
69 case 'E':
70 return 14;
71 case 'f':
72 case 'F':
73 return 15;
74 default:
75 return 0;
80 The following methods comes from Rfidler sourcecode.
81 https://github.com/ApertureLabsLtd/RFIDler/blob/master/firmware/Pic32/RFIDler.X/src/
83 // convert hex to sequence of 0/1 bit values
84 // returns number of bits converted
85 int hex2binarray(char *target, const char *source) {
86 return hex2binarray_n(target, source, strlen(source));
89 int hex2binarray_n(char *target, const char *source, int sourcelen) {
90 int count = 0;
92 // process 4 bits (1 hex digit) at a time
93 while (sourcelen--) {
95 char x = *(source++);
97 *(target++) = (x >> 7) & 1;
98 *(target++) = (x >> 6) & 1;
99 *(target++) = (x >> 5) & 1;
100 *(target++) = (x >> 4) & 1;
101 *(target++) = (x >> 3) & 1;
102 *(target++) = (x >> 2) & 1;
103 *(target++) = (x >> 1) & 1;
104 *(target++) = (x & 1);
106 count += 8;
108 return count;
111 int binarray2hex(const uint8_t *bs, int bs_len, uint8_t *hex) {
113 int count = 0;
114 int byte_index = 0;
116 // Clear output buffer
117 memset(hex, 0, bs_len >> 3);
119 for (int i = 0; i < bs_len; i++) {
121 // Set the appropriate bit in hex
122 if (bs[i] == 1) {
123 hex[byte_index] |= (1 << (7 - (count % 8)));
126 count++;
128 // Move to the next byte if 8 bits have been filled
129 if (count % 8 == 0) {
130 byte_index++;
134 return count;
138 void LEDsoff(void) {
139 LED_A_OFF();
140 LED_B_OFF();
141 LED_C_OFF();
142 LED_D_OFF();
145 //ICEMAN: LED went from 1,2,3,4 -> 1,2,4,8
146 void LED(int led, int ms) {
147 if (led & LED_A) // Proxmark3 historical mapping: LED_ORANGE
148 LED_A_ON();
149 if (led & LED_B) // Proxmark3 historical mapping: LED_GREEN
150 LED_B_ON();
151 if (led & LED_C) // Proxmark3 historical mapping: LED_RED
152 LED_C_ON();
153 if (led & LED_D) // Proxmark3 historical mapping: LED_RED2
154 LED_D_ON();
156 if (!ms)
157 return;
159 SpinDelay(ms);
161 if (led & LED_A)
162 LED_A_OFF();
163 if (led & LED_B)
164 LED_B_OFF();
165 if (led & LED_C)
166 LED_C_OFF();
167 if (led & LED_D)
168 LED_D_OFF();
171 void SpinOff(uint32_t pause) {
172 LED_A_OFF();
173 LED_B_OFF();
174 LED_C_OFF();
175 LED_D_OFF();
176 SpinDelay(pause);
179 // Blinks..
180 // A = 1, B = 2, C = 4, D = 8
181 void SpinErr(uint8_t led, uint32_t speed, uint8_t times) {
182 SpinOff(speed);
183 NTIME(times) {
185 if (led & LED_A) // Proxmark3 historical mapping: LED_ORANGE
186 LED_A_INV();
187 if (led & LED_B) // Proxmark3 historical mapping: LED_GREEN
188 LED_B_INV();
189 if (led & LED_C) // Proxmark3 historical mapping: LED_RED
190 LED_C_INV();
191 if (led & LED_D) // Proxmark3 historical mapping: LED_RED2
192 LED_D_INV();
194 SpinDelay(speed);
196 LED_A_OFF();
197 LED_B_OFF();
198 LED_C_OFF();
199 LED_D_OFF();
202 void SpinDown(uint32_t speed) {
203 SpinOff(speed);
204 LED_D_ON();
205 SpinDelay(speed);
206 LED_D_OFF();
207 LED_C_ON();
208 SpinDelay(speed);
209 LED_C_OFF();
210 LED_B_ON();
211 SpinDelay(speed);
212 LED_B_OFF();
213 LED_A_ON();
214 SpinDelay(speed);
215 LED_A_OFF();
218 void SpinUp(uint32_t speed) {
219 SpinOff(speed);
220 LED_A_ON();
221 SpinDelay(speed);
222 LED_A_OFF();
223 LED_B_ON();
224 SpinDelay(speed);
225 LED_B_OFF();
226 LED_C_ON();
227 SpinDelay(speed);
228 LED_C_OFF();
229 LED_D_ON();
230 SpinDelay(speed);
231 LED_D_OFF();
235 // Determine if a button is double clicked, single clicked,
236 // not clicked, or held down (for ms || 1sec)
237 // In general, don't use this function unless you expect a
238 // double click, otherwise it will waste 500ms -- use BUTTON_HELD instead
239 int BUTTON_CLICKED(int ms) {
240 // Up to 500ms in between clicks to mean a double click
241 // timer counts in 21.3us increments (1024/48MHz)
242 // WARNING: timer can't measure more than 1.39s (21.3us * 0xffff)
243 if (ms > 1390) {
244 if (g_dbglevel >= DBG_ERROR) Dbprintf(_RED_("Error, BUTTON_CLICKED called with %i > 1390"), ms);
245 ms = 1390;
247 int ticks = ((MCK / 1000) * (ms ? ms : 1000)) >> 10;
249 // If we're not even pressed, forget about it!
250 if (BUTTON_PRESS() == false)
251 return BUTTON_NO_CLICK;
253 // Borrow a PWM unit for my real-time clock
254 AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
255 // 48 MHz / 1024 gives 46.875 kHz
256 AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10);
257 AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0;
258 AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff;
260 uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
262 int letoff = 0;
263 for (;;) {
264 uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
266 // We haven't let off the button yet
267 if (!letoff) {
268 // We just let it off!
269 if (BUTTON_PRESS() == false) {
270 letoff = 1;
272 // reset our timer for 500ms
273 start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
274 ticks = ((MCK / 1000) * (500)) >> 10;
277 // Still haven't let it off
278 else
279 // Have we held down a full second?
280 if (now == (uint16_t)(start + ticks))
281 return BUTTON_HOLD;
284 // We already let off, did we click again?
285 else
286 // Sweet, double click!
287 if (BUTTON_PRESS())
288 return BUTTON_DOUBLE_CLICK;
290 // Have we ran out of time to double click?
291 else if (now == (uint16_t)(start + ticks))
292 // At least we did a single click
293 return BUTTON_SINGLE_CLICK;
295 WDT_HIT();
298 // We should never get here
299 return BUTTON_ERROR;
302 // Determine if a button is held down
303 int BUTTON_HELD(int ms) {
304 // timer counts in 21.3us increments (1024/48MHz)
305 // WARNING: timer can't measure more than 1.39s (21.3us * 0xffff)
306 if (ms > 1390) {
307 if (g_dbglevel >= DBG_ERROR) Dbprintf(_RED_("Error, BUTTON_HELD called with %i > 1390"), ms);
308 ms = 1390;
310 // If button is held for one second
311 int ticks = (48000 * (ms ? ms : 1000)) >> 10;
313 // If we're not even pressed, forget about it!
314 if (BUTTON_PRESS() == false) {
315 return BUTTON_NO_CLICK;
318 // Borrow a PWM unit for my real-time clock
319 AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
320 // 48 MHz / 1024 gives 46.875 kHz
321 AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10);
322 AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0;
323 AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff;
325 uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
327 for (;;) {
328 uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
330 // As soon as our button let go, we didn't hold long enough
331 if (BUTTON_PRESS() == false) {
332 return BUTTON_SINGLE_CLICK;
335 // Have we waited the full second?
336 else if (now == (uint16_t)(start + ticks)) {
337 return BUTTON_HOLD;
340 WDT_HIT();
343 // We should never get here
344 return BUTTON_ERROR;
347 // This function returns false if no data is available or
348 // the USB connection is invalid.
349 bool data_available(void) {
350 #ifdef WITH_FPC_USART_HOST
351 return usb_poll_validate_length() || (usart_rxdata_available() > 0);
352 #else
353 return usb_poll_validate_length();
354 #endif
357 // This function doesn't check if the USB connection is valid.
358 // In most of the cases, you should use data_available() unless
359 // the timing is critical.
360 bool data_available_fast(void) {
361 #ifdef WITH_FPC_USART_HOST
362 return usb_available_length() || (usart_rxdata_available() > 0);
363 #else
364 return usb_available_length();
365 #endif
368 uint32_t flash_size_from_cidr(uint32_t cidr) {
369 uint8_t nvpsiz = (cidr & 0xF00) >> 8;
370 switch (nvpsiz) {
371 case 0:
372 return 0;
373 case 1:
374 return 8 * 1024;
375 case 2:
376 return 16 * 1024;
377 case 3:
378 return 32 * 1024;
379 case 5:
380 return 64 * 1024;
381 case 7:
382 return 128 * 1024;
383 case 9:
384 return 256 * 1024;
385 case 10:
386 return 512 * 1024;
387 case 12:
388 return 1024 * 1024;
389 case 14:
390 default: // for 'reserved' values, guess 2MB
391 return 2048 * 1024;
395 uint32_t get_flash_size(void) {
396 return flash_size_from_cidr(*AT91C_DBGU_CIDR);
399 // Combined function to convert an unsigned int to an array of hex values corresponding to the last three bits of k1
400 void convertToHexArray(uint32_t num, uint8_t *partialkey) {
401 char binaryStr[25]; // 24 bits for binary representation + 1 for null terminator
402 binaryStr[24] = '\0'; // Null-terminate the string
404 // Convert the number to binary string
405 for (int i = 23; i >= 0; i--) {
406 binaryStr[i] = (num % 2) ? '1' : '0';
407 num /= 2;
410 // Split the binary string into groups of 3 and convert to hex
411 for (int i = 0; i < 8 ; i++) {
412 char group[4] = {'0', '0', '0', '\0'}; // Ensure group is initialized correctly
413 memcpy(group, binaryStr + i * 3, 3); // Use memcpy to copy exactly 3 characters
414 group[3] = '\0'; // Null-terminate the group string
415 partialkey[i] = (uint8_t)strtoul(group, NULL, 2);