| 1 | //-----------------------------------------------------------------------------\r |
| 2 | // Utility functions used in many places, not specific to any piece of code.\r |
| 3 | // Jonathan Westhues, Sept 2005\r |
| 4 | //-----------------------------------------------------------------------------\r |
| 5 | #include <proxmark3.h>\r |
| 6 | #include "apps.h"\r |
| 7 | \r |
| 8 | void *memcpy(void *dest, const void *src, int len)\r |
| 9 | {\r |
| 10 | BYTE *d = dest;\r |
| 11 | const BYTE *s = src;\r |
| 12 | while((len--) > 0) {\r |
| 13 | *d = *s;\r |
| 14 | d++;\r |
| 15 | s++;\r |
| 16 | }\r |
| 17 | return dest;\r |
| 18 | }\r |
| 19 | \r |
| 20 | void *memset(void *dest, int c, int len)\r |
| 21 | {\r |
| 22 | BYTE *d = dest;\r |
| 23 | while((len--) > 0) {\r |
| 24 | *d = c;\r |
| 25 | d++;\r |
| 26 | }\r |
| 27 | return dest;\r |
| 28 | }\r |
| 29 | \r |
| 30 | int memcmp(const void *av, const void *bv, int len)\r |
| 31 | {\r |
| 32 | const BYTE *a = av;\r |
| 33 | const BYTE *b = bv;\r |
| 34 | \r |
| 35 | while((len--) > 0) {\r |
| 36 | if(*a != *b) {\r |
| 37 | return *a - *b;\r |
| 38 | }\r |
| 39 | a++;\r |
| 40 | b++;\r |
| 41 | }\r |
| 42 | return 0;\r |
| 43 | }\r |
| 44 | \r |
| 45 | int strlen(char *str)\r |
| 46 | {\r |
| 47 | int l = 0;\r |
| 48 | while(*str) {\r |
| 49 | l++;\r |
| 50 | str++;\r |
| 51 | }\r |
| 52 | return l;\r |
| 53 | }\r |
| 54 | \r |
| 55 | char* strncat(char *dest, const char *src, unsigned int n)\r |
| 56 | {\r |
| 57 | unsigned int dest_len = strlen(dest);\r |
| 58 | unsigned int i;\r |
| 59 | \r |
| 60 | for (i = 0 ; i < n && src[i] != '\0' ; i++)\r |
| 61 | dest[dest_len + i] = src[i];\r |
| 62 | dest[dest_len + i] = '\0';\r |
| 63 | \r |
| 64 | return dest;\r |
| 65 | }\r |
| 66 | \r |
| 67 | void num_to_bytes(uint64_t n, size_t len, byte_t* dest)\r |
| 68 | {\r |
| 69 | while (len--) {\r |
| 70 | dest[len] = (byte_t) n;\r |
| 71 | n >>= 8;\r |
| 72 | }\r |
| 73 | }\r |
| 74 | \r |
| 75 | uint64_t bytes_to_num(byte_t* src, size_t len)\r |
| 76 | {\r |
| 77 | uint64_t num = 0;\r |
| 78 | while (len--)\r |
| 79 | {\r |
| 80 | num = (num << 8) | (*src);\r |
| 81 | src++;\r |
| 82 | }\r |
| 83 | return num;\r |
| 84 | }\r |
| 85 | \r |
| 86 | void LEDsoff()\r |
| 87 | {\r |
| 88 | LED_A_OFF();\r |
| 89 | LED_B_OFF();\r |
| 90 | LED_C_OFF();\r |
| 91 | LED_D_OFF();\r |
| 92 | }\r |
| 93 | \r |
| 94 | // LEDs: R(C) O(A) G(B) -- R(D) [1, 2, 4 and 8]\r |
| 95 | void LED(int led, int ms)\r |
| 96 | {\r |
| 97 | if (led & LED_RED)\r |
| 98 | LED_C_ON();\r |
| 99 | if (led & LED_ORANGE)\r |
| 100 | LED_A_ON();\r |
| 101 | if (led & LED_GREEN)\r |
| 102 | LED_B_ON();\r |
| 103 | if (led & LED_RED2)\r |
| 104 | LED_D_ON();\r |
| 105 | \r |
| 106 | if (!ms)\r |
| 107 | return;\r |
| 108 | \r |
| 109 | SpinDelay(ms);\r |
| 110 | \r |
| 111 | if (led & LED_RED)\r |
| 112 | LED_C_OFF();\r |
| 113 | if (led & LED_ORANGE)\r |
| 114 | LED_A_OFF();\r |
| 115 | if (led & LED_GREEN)\r |
| 116 | LED_B_OFF();\r |
| 117 | if (led & LED_RED2)\r |
| 118 | LED_D_OFF();\r |
| 119 | }\r |
| 120 | \r |
| 121 | \r |
| 122 | // Determine if a button is double clicked, single clicked,\r |
| 123 | // not clicked, or held down (for ms || 1sec)\r |
| 124 | // In general, don't use this function unless you expect a\r |
| 125 | // double click, otherwise it will waste 500ms -- use BUTTON_HELD instead\r |
| 126 | int BUTTON_CLICKED(int ms)\r |
| 127 | {\r |
| 128 | // Up to 500ms in between clicks to mean a double click\r |
| 129 | int ticks = (48000 * (ms ? ms : 1000)) >> 10;\r |
| 130 | \r |
| 131 | // If we're not even pressed, forget about it!\r |
| 132 | if (!BUTTON_PRESS())\r |
| 133 | return BUTTON_NO_CLICK;\r |
| 134 | \r |
| 135 | // Borrow a PWM unit for my real-time clock\r |
| 136 | AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);\r |
| 137 | // 48 MHz / 1024 gives 46.875 kHz\r |
| 138 | AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10);\r |
| 139 | AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0;\r |
| 140 | AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff;\r |
| 141 | \r |
| 142 | WORD start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;\r |
| 143 | \r |
| 144 | int letoff = 0;\r |
| 145 | for(;;)\r |
| 146 | {\r |
| 147 | WORD now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;\r |
| 148 | \r |
| 149 | // We haven't let off the button yet\r |
| 150 | if (!letoff)\r |
| 151 | {\r |
| 152 | // We just let it off!\r |
| 153 | if (!BUTTON_PRESS())\r |
| 154 | {\r |
| 155 | letoff = 1;\r |
| 156 | \r |
| 157 | // reset our timer for 500ms\r |
| 158 | start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;\r |
| 159 | ticks = (48000 * (500)) >> 10;\r |
| 160 | }\r |
| 161 | \r |
| 162 | // Still haven't let it off\r |
| 163 | else\r |
| 164 | // Have we held down a full second?\r |
| 165 | if (now == (WORD)(start + ticks))\r |
| 166 | return BUTTON_HOLD;\r |
| 167 | }\r |
| 168 | \r |
| 169 | // We already let off, did we click again?\r |
| 170 | else\r |
| 171 | // Sweet, double click!\r |
| 172 | if (BUTTON_PRESS())\r |
| 173 | return BUTTON_DOUBLE_CLICK;\r |
| 174 | \r |
| 175 | // Have we ran out of time to double click?\r |
| 176 | else\r |
| 177 | if (now == (WORD)(start + ticks))\r |
| 178 | // At least we did a single click\r |
| 179 | return BUTTON_SINGLE_CLICK;\r |
| 180 | \r |
| 181 | WDT_HIT();\r |
| 182 | }\r |
| 183 | \r |
| 184 | // We should never get here\r |
| 185 | return BUTTON_ERROR;\r |
| 186 | }\r |
| 187 | \r |
| 188 | // Determine if a button is held down\r |
| 189 | int BUTTON_HELD(int ms)\r |
| 190 | {\r |
| 191 | // If button is held for one second\r |
| 192 | int ticks = (48000 * (ms ? ms : 1000)) >> 10;\r |
| 193 | \r |
| 194 | // If we're not even pressed, forget about it!\r |
| 195 | if (!BUTTON_PRESS())\r |
| 196 | return BUTTON_NO_CLICK;\r |
| 197 | \r |
| 198 | // Borrow a PWM unit for my real-time clock\r |
| 199 | AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);\r |
| 200 | // 48 MHz / 1024 gives 46.875 kHz\r |
| 201 | AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10);\r |
| 202 | AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0;\r |
| 203 | AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff;\r |
| 204 | \r |
| 205 | WORD start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;\r |
| 206 | \r |
| 207 | for(;;)\r |
| 208 | {\r |
| 209 | WORD now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;\r |
| 210 | \r |
| 211 | // As soon as our button let go, we didn't hold long enough\r |
| 212 | if (!BUTTON_PRESS())\r |
| 213 | return BUTTON_SINGLE_CLICK;\r |
| 214 | \r |
| 215 | // Have we waited the full second?\r |
| 216 | else\r |
| 217 | if (now == (WORD)(start + ticks))\r |
| 218 | return BUTTON_HOLD;\r |
| 219 | \r |
| 220 | WDT_HIT();\r |
| 221 | }\r |
| 222 | \r |
| 223 | // We should never get here\r |
| 224 | return BUTTON_ERROR;\r |
| 225 | }\r |
| 226 | \r |
| 227 | // attempt at high resolution microsecond timer\r |
| 228 | // beware: timer counts in 21.3uS increments (1024/48Mhz)\r |
| 229 | void SpinDelayUs(int us)\r |
| 230 | {\r |
| 231 | int ticks = (48*us) >> 10;\r |
| 232 | \r |
| 233 | // Borrow a PWM unit for my real-time clock\r |
| 234 | AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);\r |
| 235 | // 48 MHz / 1024 gives 46.875 kHz\r |
| 236 | AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10);\r |
| 237 | AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0;\r |
| 238 | AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff;\r |
| 239 | \r |
| 240 | WORD start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;\r |
| 241 | \r |
| 242 | for(;;) {\r |
| 243 | WORD now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;\r |
| 244 | if (now == (WORD)(start + ticks))\r |
| 245 | return;\r |
| 246 | \r |
| 247 | WDT_HIT();\r |
| 248 | }\r |
| 249 | }\r |
| 250 | \r |
| 251 | void SpinDelay(int ms)\r |
| 252 | {\r |
| 253 | // convert to uS and call microsecond delay function\r |
| 254 | SpinDelayUs(ms*1000);\r |
| 255 | }\r |
| 256 | \r |
| 257 | /* Similar to FpgaGatherVersion this formats stored version information\r |
| 258 | * into a string representation. It takes a pointer to the struct version_information,\r |
| 259 | * verifies the magic properties, then stores a formatted string, prefixed by\r |
| 260 | * prefix in dst.\r |
| 261 | */\r |
| 262 | void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information)\r |
| 263 | {\r |
| 264 | struct version_information *v = (struct version_information*)version_information;\r |
| 265 | dst[0] = 0;\r |
| 266 | strncat(dst, prefix, len);\r |
| 267 | if(v->magic != VERSION_INFORMATION_MAGIC) {\r |
| 268 | strncat(dst, "Missing/Invalid version information", len);\r |
| 269 | return;\r |
| 270 | }\r |
| 271 | if(v->versionversion != 1) {\r |
| 272 | strncat(dst, "Version information not understood", len);\r |
| 273 | return;\r |
| 274 | }\r |
| 275 | if(!v->present) {\r |
| 276 | strncat(dst, "Version information not available", len);\r |
| 277 | return;\r |
| 278 | }\r |
| 279 | \r |
| 280 | strncat(dst, v->svnversion, len);\r |
| 281 | if(v->clean == 0) {\r |
| 282 | strncat(dst, "-unclean", len);\r |
| 283 | } else if(v->clean == 2) {\r |
| 284 | strncat(dst, "-suspect", len);\r |
| 285 | }\r |
| 286 | \r |
| 287 | strncat(dst, " ", len);\r |
| 288 | strncat(dst, v->buildtime, len);\r |
| 289 | }\r |