/*
* 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;
}