/* * Copyright (c) 2019 Clementine Computing LLC. * * This file is part of PopuFare. * * PopuFare is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * PopuFare is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with PopuFare. If not, see . * */ #include #include #include #include "../common/common_defs.h" typedef struct rfid_decode_pattern_struct { unsigned int bits; unsigned int shift; unsigned long long mask; unsigned long long match; unsigned int site_shift; unsigned long long site_mask; unsigned int id_shift; unsigned long long id_mask; } rfid_decode_pattern; static rfid_decode_pattern rfid_pattern_buffer[NUM_RFID_PATTERNS] = {{0}}; static int rfid_pattern_used = -1; int rfid_pattern_loaded() { return rfid_pattern_used; } int load_rfid_decode_patterns(char *filename) { char line[LINE_BUFFER_SIZE]; int i, retval; FILE *f; char *c; if(!filename) { fprintf(stderr, "Cannot open RFID Pattern Match file %s", "(null)"); rfid_pattern_used = -1; return -1; } i = 0; f = fopen(filename, "rb"); if(!f) { fprintf(stderr, "Cannot open RFID Pattern Match file %s", filename); rfid_pattern_used = -1; return -1; } while(i < NUM_RFID_PATTERNS) { fgets(line, LINE_BUFFER_SIZE, f); if(feof(f)) { break; } c = line; //skip any blank lines, or comment lines starting with a # as their first non-whitespace character while( (*c == ' ') || (*c == '\t') || (*c == '\r') || (*c == '\n') ) c++; if( (*c == '#') || (*c == '\0') ) continue; retval = sscanf(c, "%x %x %llx %llx %x %llx %x %llx", &rfid_pattern_buffer[i].bits, &rfid_pattern_buffer[i].shift, &rfid_pattern_buffer[i].mask, &rfid_pattern_buffer[i].match, &rfid_pattern_buffer[i].site_shift, &rfid_pattern_buffer[i].site_mask, &rfid_pattern_buffer[i].id_shift, &rfid_pattern_buffer[i].id_mask ); if(retval == 8) { i++; } else { memset(&rfid_pattern_buffer[i], 0, sizeof(rfid_decode_pattern)); fprintf(stderr, "Cannot parse RFID Pattern Match line \"%s\"\n", line); } } fclose(f); if(i >= NUM_RFID_PATTERNS) { fprintf(stderr, "RFID Pattern Match file %s contains more than %d records!", filename, NUM_RFID_PATTERNS); rfid_pattern_used = -1; return -1; } memset(&rfid_pattern_buffer[i], 0, sizeof(rfid_decode_pattern)); rfid_pattern_used = i; return i; } int decode_rfid_string(char *raw_rfid, unsigned long long *site, unsigned long long *id, unsigned int *bits) { unsigned long long raw; unsigned int nbits; char *rest; int i; if(!raw_rfid) { fprintf(stderr, "NULL RFID String!\n"); return -1; } if(rfid_pattern_used < 1) { fprintf(stderr, "rfid_pattern_used < 1!\n"); } nbits = strtol(raw_rfid, &rest, 16); if(*rest++ != '|') { fprintf(stderr, "Malformed RFID String!\n"); return -1; } raw = strtoll(rest, NULL, 16); for(i = 0; i < rfid_pattern_used; i++) { //If this RFID string has the right number of bits AND matches our shift-and-mask criteria if( (nbits == rfid_pattern_buffer[i].bits) && (((raw >> rfid_pattern_buffer[i].shift) & rfid_pattern_buffer[i].mask) == rfid_pattern_buffer[i].match) ) { if(bits) { *bits = nbits; } if(site) { *site = (raw >> rfid_pattern_buffer[i].site_shift) & rfid_pattern_buffer[i].site_mask; } if(id) { *id = (raw >> rfid_pattern_buffer[i].id_shift) & rfid_pattern_buffer[i].id_mask; } return 0; } } return -1; }