+int param_gethex_ex(const char *line, int paramnum, uint8_t * data, int *hexcnt)
+{
+ int bg, en, temp, i;
+
+ //if (hexcnt % 2)
+ // return 1;
+
+ if (param_getptr(line, &bg, &en, paramnum)) return 1;
+
+ *hexcnt = en - bg + 1;
+ if (*hexcnt % 2) //error if not complete hex bytes
+ return 1;
+
+ for(i = 0; i < *hexcnt; i += 2) {
+ if (!(isxdigit((unsigned char)line[bg + i]) && isxdigit((unsigned char)line[bg + i + 1])) ) return 1;
+
+ sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp);
+ data[i / 2] = temp & 0xff;
+ }
+
+ return 0;
+}
+
+int param_gethex_to_eol(const char *line, int paramnum, uint8_t * data, int maxdatalen, int *datalen) {
+ int bg, en;
+ uint32_t temp;
+ char buf[5] = {0};
+
+ if (param_getptr(line, &bg, &en, paramnum)) return 1;
+
+ *datalen = 0;
+
+ int indx = bg;
+ while (line[indx]) {
+ if (line[indx] == '\t' || line[indx] == ' ') {
+ indx++;
+ continue;
+ }
+
+ if (isxdigit((unsigned char)line[indx])) {
+ buf[strlen(buf) + 1] = 0x00;
+ buf[strlen(buf)] = line[indx];
+ } else {
+ // if we have symbols other than spaces and hex
+ return 1;
+ }
+
+ if (*datalen >= maxdatalen) {
+ // if we dont have space in buffer and have symbols to translate
+ return 2;
+ }
+
+ if (strlen(buf) >= 2) {
+ sscanf(buf, "%x", &temp);
+ data[*datalen] = (uint8_t)(temp & 0xff);
+ *buf = 0;
+ (*datalen)++;
+ }
+
+ indx++;
+ }
+
+ if (strlen(buf) > 0)
+ //error when not completed hex bytes
+ return 3;
+
+ return 0;
+}
+
+int param_getstr(const char *line, int paramnum, char * str, size_t buffersize)
+{
+ int bg, en;
+
+ if (param_getptr(line, &bg, &en, paramnum)) {
+ return 0;
+ }
+
+ // Prevent out of bounds errors
+ if (en - bg + 1 >= buffersize) {
+ printf("out of bounds error: want %d bytes have %zd bytes\n", en - bg + 1 + 1, buffersize);
+ return 0;
+ }
+
+ memcpy(str, line + bg, en - bg + 1);
+ str[en - bg + 1] = 0;
+
+ return en - bg + 1;
+}
+
+/*
+The following methods comes from Rfidler sourcecode.
+https://github.com/ApertureLabsLtd/RFIDler/blob/master/firmware/Pic32/RFIDler.X/src/
+*/
+
+// convert hex to sequence of 0/1 bit values
+// returns number of bits converted
+int hextobinarray(char *target, char *source)
+{
+ int length, i, count= 0;
+ char* start = source;
+ char x;
+
+ length = strlen(source);
+ // process 4 bits (1 hex digit) at a time
+ while(length--)
+ {
+ x= *(source++);
+ // capitalize
+ if (x >= 'a' && x <= 'f')
+ x -= 32;
+ // convert to numeric value
+ if (x >= '0' && x <= '9')
+ x -= '0';
+ else if (x >= 'A' && x <= 'F')
+ x -= 'A' - 10;
+ else {
+ printf("Discovered unknown character %c %d at idx %tu of %s\n", x, x, source - start, start);
+ return 0;
+ }
+ // output
+ for(i= 0 ; i < 4 ; ++i, ++count)
+ *(target++)= (x >> (3 - i)) & 1;
+ }
+
+ return count;
+}
+
+// convert binary array of 0x00/0x01 values to hex (safe to do in place as target will always be shorter than source)
+// return number of bits converted
+int binarraytohex(char *target,char *source, int length)
+{
+ unsigned char i, x;
+ int j = length;
+
+ if(j % 4)
+ return 0;
+
+ while(j)
+ {
+ for(i= x= 0 ; i < 4 ; ++i)
+ x += ( source[i] << (3 - i));
+ sprintf(target,"%X", (unsigned int)x);
+ ++target;
+ source += 4;
+ j -= 4;
+ }
+ return length;
+}
+
+// return parity bit required to match type
+uint8_t GetParity( uint8_t *bits, uint8_t type, int length)
+{
+ int x;
+
+ for(x= 0 ; length > 0 ; --length)
+ x += bits[length - 1];
+ x %= 2;
+
+ return x ^ type;
+}
+
+// add HID parity to binary array: EVEN prefix for 1st half of ID, ODD suffix for 2nd half
+void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length)
+{
+ *(target++)= GetParity(source, EVEN, length / 2);
+ memcpy(target, source, length);
+ target += length;
+ *(target)= GetParity(source + length / 2, ODD, length / 2);
+}
+
+// xor two arrays together for len items. The dst array contains the new xored values.
+void xor(unsigned char *dst, unsigned char *src, size_t len) {
+ for( ; len > 0; len--,dst++,src++)
+ *dst ^= *src;
+}
+
+// RotateLeft - Ultralight, Desfire, works on byte level
+// 00-01-02 >> 01-02-00
+void rol(uint8_t *data, const size_t len){
+ uint8_t first = data[0];
+ for (size_t i = 0; i < len-1; i++) {
+ data[i] = data[i+1];
+ }
+ data[len-1] = first;
+}
+
+
+// Replace unprintable characters with a dot in char buffer
+void clean_ascii(unsigned char *buf, size_t len) {
+ for (size_t i = 0; i < len; i++) {
+ if (!isprint(buf[i]))
+ buf[i] = '.';
+ }
+}
+
+// replace \r \n to \0
+void strcleanrn(char *buf, size_t len) {
+ strcreplace(buf, len, '\n', '\0');
+ strcreplace(buf, len, '\r', '\0');
+}
+
+// replace char in buffer
+void strcreplace(char *buf, size_t len, char from, char to) {
+ for (size_t i = 0; i < len; i++) {
+ if (buf[i] == from)
+ buf[i] = to;
+ }
+}
+
+char *strmcopy(char *buf) {
+ char * str = NULL;
+ if ((str = (char*) malloc(strlen(buf) + 1)) != NULL) {
+ memset(str, 0, strlen(buf) + 1);
+ strcpy(str, buf);
+ }
+ return str;
+}
+
+
+// determine number of logical CPU cores (use for multithreaded functions)
+extern int num_CPUs(void)
+{
+#if defined(_WIN32)
+ #include <sysinfoapi.h>
+ SYSTEM_INFO sysinfo;
+ GetSystemInfo(&sysinfo);
+ return sysinfo.dwNumberOfProcessors;
+#elif defined(__linux__) || defined(__APPLE__)
+ #include <unistd.h>
+ return sysconf(_SC_NPROCESSORS_ONLN);
+#else
+ return 1;
+#endif
+}
+