├── D23V3A0600.pdf ├── layoutstd.pdf ├── magtek-app.pdf ├── magtek-io.pdf ├── magtek6516.pdf ├── README.md └── swipy.pde /D23V3A0600.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Custom-Magstripe-Swiper/HEAD/D23V3A0600.pdf -------------------------------------------------------------------------------- /layoutstd.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Custom-Magstripe-Swiper/HEAD/layoutstd.pdf -------------------------------------------------------------------------------- /magtek-app.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Custom-Magstripe-Swiper/HEAD/magtek-app.pdf -------------------------------------------------------------------------------- /magtek-io.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Custom-Magstripe-Swiper/HEAD/magtek-io.pdf -------------------------------------------------------------------------------- /magtek6516.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Custom-Magstripe-Swiper/HEAD/magtek6516.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Custom-Magstripe-Swiper 2 | Merges a microcontroller (Teensy w/Arduino) with a magstripe swiper 3 | 4 | ## This repository has been archived 5 | 6 | The files in this repository accompanied an [Adafruit Learning System](https://learn.adafruit.com) tutorial 7 | and were moved to [https://github.com/adafruit/Adafruit_Learning_System_Guides/tree/master/Custom_Magstripe_Swiper](https://github.com/adafruit/Adafruit_Learning_System_Guides/tree/master/Custom_Magstripe_Swiper) 8 | 9 | Tutorial: Low Level Magstripe Reader [https://learn.adafruit.com/low-level-magstripe-reader/code-snippets](https://learn.adafruit.com/low-level-magstripe-reader/code-snippets) 10 | 11 | See the tutorial for details. 12 | 13 | All code MIT License, please attribute to Adafruit 14 | 15 | Please consider buying your parts at [Adafruit.com](https://www.adafruit.com) to support open source code 16 | -------------------------------------------------------------------------------- /swipy.pde: -------------------------------------------------------------------------------- 1 | #define PIEZO 3 2 | #define CLOCK2 10 3 | #define DATA2 9 4 | #define CARD2 23 5 | 6 | #define TRACK1_LEN 79 7 | #define BUFF 30 8 | uint8_t track1[TRACK1_LEN+BUFF]; 9 | uint8_t scratch[TRACK1_LEN+BUFF]; 10 | 11 | #define RIGHT 1 12 | #define LEFT 0 13 | 14 | #define BYTELENGTH 7 // 6 + 1 parity 15 | 16 | //#define _SERIAL 1 17 | #define _KEYBOARD 1 18 | 19 | void beep(uint8_t pin, long freq, long dur) { 20 | long d = 500000/ freq; 21 | 22 | for (long i=0; i< freq * dur / 2000; i++) { 23 | digitalWrite(pin, HIGH); 24 | delayMicroseconds(d); 25 | digitalWrite(pin, LOW); 26 | delayMicroseconds(d); 27 | } 28 | } 29 | 30 | 31 | void setup() 32 | { 33 | #ifdef _SERIAL 34 | Serial.begin(9600); // USB is always 12 Mbit/sec 35 | #endif 36 | 37 | pinMode(5, OUTPUT); 38 | pinMode(PIEZO, OUTPUT); 39 | digitalWrite(5, LOW); 40 | 41 | beep(PIEZO, 4000, 200); 42 | } 43 | 44 | //http://stripesnoop.sourceforge.net/devel/magtek-app.pdf 45 | 46 | void loop() 47 | { 48 | while (digitalRead(CARD2)); 49 | uint8_t zeros = 0; 50 | 51 | // card was swiped! 52 | // check clocked in data 53 | for (uint8_t t1 = 0; t1 < TRACK1_LEN; t1++) { 54 | track1[t1] = 0; 55 | for (uint8_t b=0; b < BYTELENGTH; b++) { 56 | 57 | // wait while clock is high 58 | while (digitalRead(CLOCK2) && !digitalRead(CARD2)); 59 | // we sample on the falling edge! 60 | uint8_t x = digitalRead(DATA2); 61 | if (!x) { 62 | // data is LSB and inverted! 63 | track1[t1] |= _BV(b); 64 | } 65 | // heep hanging out while its low 66 | while (!digitalRead(CLOCK2) && !digitalRead(CARD2)); 67 | 68 | } 69 | 70 | if ((t1 == 0) && (track1[t1] == 0)) { 71 | // get rid of leading 0's 72 | zeros++; 73 | t1--; 74 | continue; 75 | } 76 | 77 | if (zeros < 4) { 78 | t1--; 79 | continue; 80 | } 81 | if ((t1 == 1) && (track1[t1] == 0)) { 82 | t1 = -1; 83 | zeros = 1; 84 | continue; 85 | } 86 | } 87 | 88 | // shift left until we have no more starting zero bits! 89 | while ((track1[0] & 0x1) == 0 ) { 90 | shifttrack(track1, scratch, LEFT); 91 | } 92 | 93 | if (!verifycard(track1)) { 94 | // Serial.println("flippy?"); 95 | 96 | // didnt pass verification, perhaps we can try flipping it around? 97 | for (uint8_t i = 0; i < TRACK1_LEN+BUFF; i++) 98 | scratch[i] = 0; // clear out the scratch 99 | 100 | for (uint8_t i = 0; i < TRACK1_LEN+BUFF; i++) { 101 | // for each bit starting with the MSB of the LAST 'byte' to the LSB of the first byte 102 | for (int8_t j=0; j < 7; j++) { 103 | if (track1[TRACK1_LEN+BUFF-1-i] & _BV(6-j)) 104 | scratch[i] |= _BV(j); 105 | } 106 | } 107 | 108 | for (uint8_t i = 0; i < TRACK1_LEN+BUFF; i++) { 109 | track1[i] = scratch[i]; 110 | } 111 | 112 | // get rid of leading zero bits and possible single bit flips 113 | while (((track1[0] & 0x1) == 0) || track1[1] == 0) 114 | shifttrack(track1, scratch, LEFT); 115 | } 116 | 117 | if (verifycard(track1)) { 118 | 119 | #ifdef _SERIAL 120 | Serial.println("Swiped!"); 121 | for (uint8_t i = 0; i < TRACK1_LEN; i++) { 122 | Serial.print(track1[i], HEX); 123 | Serial.print(" "); 124 | } 125 | Serial.println(); 126 | for (uint8_t i = 0; i < TRACK1_LEN; i++) { 127 | #if ARDUINO >= 100 128 | Serial.write((track1[i] & 0x3F)+0x20); 129 | #else 130 | Serial.print((track1[i] & 0x3F)+0x20, BYTE); 131 | #endif 132 | Serial.print(" "); 133 | } 134 | Serial.println(); 135 | for (uint8_t i = 0; i < 6; i++) { 136 | for (uint8_t j = 0; j < 7; j++) { 137 | if (track1[i] & _BV(j)) { 138 | Serial.print('1'); 139 | } else { 140 | Serial.print('0'); 141 | } 142 | } 143 | } 144 | Serial.println(); 145 | #endif 146 | 147 | // FIND PAN 148 | uint8_t i=2; 149 | while ((track1[i] & 0x3F) != 0x3E) { 150 | #if ARDUINO >= 100 151 | #ifdef _SERIAL 152 | Serial.write((track1[i] & 0x3F)+0x20); 153 | #endif 154 | #ifdef _KEYBOARD 155 | Keyboard.write((track1[i] & 0x3F)+0x20); 156 | #endif 157 | #else 158 | #ifdef _SERIAL 159 | Serial.print((track1[i] & 0x3F)+0x20, BYTE); 160 | #endif 161 | #ifdef _KEYBOARD 162 | Keyboard.print((track1[i] & 0x3F)+0x20, BYTE); 163 | #endif 164 | #endif 165 | i++; 166 | } 167 | i++; 168 | char fname[26], lname[26]; 169 | 170 | // LAST NAME 171 | uint8_t j=0; 172 | while ((track1[i] & 0x3F) != 0xF) { 173 | #ifdef _SERIAL 174 | #if ARDUINO >= 100 175 | Serial.write((track1[i] & 0x3F)+0x20); 176 | #else 177 | Serial.print((track1[i] & 0x3F)+0x20, BYTE); 178 | #endif 179 | #endif 180 | lname[j++] = (track1[i] & 0x3F)+0x20; 181 | i++; 182 | } 183 | lname[j] = 0; 184 | i++; 185 | j=0; 186 | // FIRST NAME 187 | while ((track1[i] & 0x3F) != 0x3E) { 188 | #ifdef _SERIAL 189 | #if ARDUINO >= 100 190 | Serial.write((track1[i] & 0x3F)+0x20); 191 | #else 192 | Serial.print((track1[i] & 0x3F)+0x20, BYTE); 193 | #endif 194 | #endif 195 | 196 | fname[j++] = (track1[i] & 0x3F)+0x20; 197 | 198 | i++; 199 | } 200 | fname[j] = 0; 201 | i++; 202 | char y1, y2, m1, m2; 203 | y1 = (track1[i++] & 0x3F)+0x20; 204 | y2 = (track1[i++] & 0x3F)+0x20; 205 | m1 = (track1[i++] & 0x3F)+0x20; 206 | m2 = (track1[i++] & 0x3F)+0x20; 207 | 208 | #ifdef _KEYBOARD 209 | Keyboard.print('\t'); 210 | #if ARDUINO >= 100 211 | Keyboard.write(m1); 212 | Keyboard.write(m2); 213 | Keyboard.write(y1); 214 | Keyboard.write(y2); 215 | #else 216 | Keyboard.print(m1, BYTE); 217 | Keyboard.print(m2, BYTE); 218 | Keyboard.print(y1, BYTE); 219 | Keyboard.print(y2, BYTE); 220 | #endif 221 | 222 | Keyboard.print('\t'); // tab to amount 223 | Keyboard.print('\t'); // tab to invoice 224 | Keyboard.print('\t'); // tab to description 225 | Keyboard.print("HOPE conference kits from Adafruit.com"); 226 | Keyboard.print('\t'); // tab to customer ID 227 | Keyboard.print('\t'); // tab to first name 228 | Keyboard.print(fname); 229 | Keyboard.print('\t'); // tab to last name 230 | Keyboard.print(lname); 231 | 232 | for (uint8_t i=0; i<5; i++) { 233 | Keyboard.set_modifier(MODIFIERKEY_SHIFT); 234 | Keyboard.set_key1(KEY_TAB); 235 | Keyboard.send_now(); 236 | Keyboard.set_modifier(0); 237 | Keyboard.set_key1(0); 238 | Keyboard.send_now(); 239 | } 240 | 241 | #endif 242 | 243 | beep(PIEZO, 4000, 200); 244 | } else { 245 | beep(PIEZO, 1000, 200); 246 | 247 | #ifdef _SERIAL 248 | Serial.println("Failed!"); 249 | for (uint8_t i = 0; i < TRACK1_LEN; i++) { 250 | Serial.print(track1[i], HEX); 251 | Serial.print(" "); 252 | } 253 | Serial.println(); 254 | for (uint8_t i = 0; i < 6; i++) { 255 | for (uint8_t j = 0; j < 7; j++) { 256 | if (track1[i] & _BV(j)) { 257 | Serial.print('1'); 258 | } else { 259 | Serial.print('0'); 260 | } 261 | } 262 | } 263 | } 264 | Serial.println(); 265 | #endif 266 | 267 | //Serial.println(zeros, DEC); 268 | 269 | for (uint8_t i = 0; i < TRACK1_LEN+BUFF; i++) { 270 | track1[i] = scratch[i] = 0; 271 | } 272 | 273 | while (! digitalRead(CARD2)); 274 | return; 275 | } 276 | 277 | uint8_t verifycard(byte track[]) { 278 | uint8_t parityok = 1; 279 | 280 | // calculate parity for each byte 281 | for (uint8_t i = 0; i < TRACK1_LEN; i++) { 282 | uint8_t p = 1; 283 | for (uint8_t j = 0; j < 6; j++) { 284 | if (track1[i] & _BV(j)) 285 | p++; 286 | } 287 | p %= 2; 288 | if (p != track1[i] >> 6) { 289 | //Serial.print("Bad parity on "); 290 | //Serial.println(track1[i], HEX); 291 | parityok = 0; 292 | } 293 | if (track1[i] == 0x1F) break; 294 | } 295 | 296 | if ((track1[0] == 0x45) && (track1[1] == 0x62) && parityok) { 297 | return 1; 298 | } 299 | return 0; 300 | } 301 | 302 | // We use this to s 303 | void shifttrack(byte track[], byte shiftbuffer[], uint8_t dir) { 304 | if (dir == RIGHT) { 305 | // shift right 306 | uint8_t x =0; 307 | 308 | for (uint8_t i = 0; i < TRACK1_LEN+BUFF; i++) { 309 | shiftbuffer[i] = ((track[i] << 1) | x) & 0x3F; 310 | x = (track[i]>>6) & 0x1; // snag the parity bit 311 | } 312 | } else { 313 | // left 314 | uint8_t x =0; 315 | 316 | for (uint8_t i = 0; i < TRACK1_LEN+BUFF; i++) { 317 | x = track[i+1] & 0x1; // snag the bit 318 | shiftbuffer[i] = ((track[i] >> 1) | (x << 6)); 319 | 320 | } 321 | } 322 | 323 | for (uint8_t i = 0; i < TRACK1_LEN+BUFF; i++) { 324 | track[i] = shiftbuffer[i]; 325 | } 326 | } 327 | --------------------------------------------------------------------------------