diff options
Diffstat (limited to 'cphidgetrfid.c')
-rw-r--r-- | cphidgetrfid.c | 2904 |
1 files changed, 1263 insertions, 1641 deletions
diff --git a/cphidgetrfid.c b/cphidgetrfid.c index 718653d..3d177ba 100644 --- a/cphidgetrfid.c +++ b/cphidgetrfid.c @@ -7,72 +7,12 @@ // === Internal Functions === // CThread_func_return_t tagTimerThreadFunction(CThread_func_arg_t userPtr); - static int analyze_data(CPhidgetRFIDHandle phid); +static int tagEvent_fromEM4100Data(CPhidgetRFIDHandle phid, unsigned char *data); +#ifdef RFID_HITAGS_SUPPORT static int analyze_data_AC(CPhidgetRFIDHandle phid); -static int sendRAWData(CPhidgetRFIDHandle phid, unsigned char *data, int bitlength); -static int advancedTagEventForOldReaders(CPhidgetRFIDHandle phid, unsigned char *data); - -//Hitag S Commands static int HitagS_UID_REQUEST(CPhidgetRFIDHandle phid); -static int HitagS_AC_SEQUENCE(CPhidgetRFIDHandle phid, CPhidgetRFID_HitagACHandle ac); - -#define ABS(x) ((x) < 0 ? -(x) : (x)) -#define pdiff(a, b) ( ABS((a) - (b)) / (double)( ((a) + (b)) / 2.0 ) ) - -int CPhidgetRFID_Tag_areEqual(void *arg1, void *arg2) -{ - CPhidgetRFID_TagHandle tag1 = (CPhidgetRFID_TagHandle)arg1; - CPhidgetRFID_TagHandle tag2 = (CPhidgetRFID_TagHandle)arg2; - - if(!tag1 || !tag2) - return PFALSE; - - if(!strcmp(tag1->tagString, tag2->tagString) - && tag1->tagInfo.tagType == tag2->tagInfo.tagType - && tag1->tagInfo.bitRate == tag2->tagInfo.bitRate - && tag1->tagInfo.encoding == tag2->tagInfo.encoding) - return PTRUE; - else - return PFALSE; -} - -void CPhidgetRFID_Tag_free(void *arg) -{ - CPhidgetRFID_TagHandle tag = (CPhidgetRFID_TagHandle)arg; - - if(!tag) - return; - - free(tag); tag = NULL; - return; -} - -int CPhidgetRFID_HitagAC_areEqual(void *arg1, void *arg2) -{ - CPhidgetRFID_HitagACHandle ac1 = (CPhidgetRFID_HitagACHandle)arg1; - CPhidgetRFID_HitagACHandle ac2 = (CPhidgetRFID_HitagACHandle)arg2; - - if(!ac1 || !ac2) - return PFALSE; - - if(!memcmp(ac1->uid, ac2->uid, 4) - && ac1->colPos == ac2->colPos) - return PTRUE; - else - return PFALSE; -} - -void CPhidgetRFID_HitagAC_free(void *arg) -{ - CPhidgetRFID_HitagACHandle ac = (CPhidgetRFID_HitagACHandle)arg; - - if(!ac) - return; - - free(ac); ac = NULL; - return; -} +#endif //clearVars - sets all device variables to unknown state CPHIDGETCLEARVARS(RFID) @@ -81,11 +21,7 @@ CPHIDGETCLEARVARS(RFID) phid->antennaEchoState = PUNI_BOOL; phid->ledEchoState = PUNI_BOOL; phid->tagPresent = PUNI_BOOL; - phid->fullStateEcho = PUNK_BOOL; - phid->ledState = PUNK_BOOL; - phid->antennaState = PUNK_BOOL; phid->lastTagValid = PUNI_BOOL; - for (i = 0; i<RFID_MAXOUTPUTS; i++) { phid->outputEchoState[i] = PUNI_BOOL; @@ -98,47 +34,36 @@ CPHIDGETCLEARVARS(RFID) // used during attach initialization - on every attach CPHIDGETINIT(RFID) int i = 0; - unsigned char buffer[8] = { 0 }; int result; TESTPTR(phid); + //make sure the tagTimerThread isn't running + if (phid->tagTimerThread.thread_status == PTRUE) + { + phid->tagTimerThread.thread_status = PFALSE; + CThread_join(&phid->tagTimerThread); + } + phid->tagTimerThread.thread_status = PFALSE; + //Make sure no old writes are still pending phid->outputPacketLen = 0; //setup anything device specific - switch(phid->phid.deviceIDSpec) + switch(phid->phid.deviceUID) { - case PHIDID_RFID: - if (phid->phid.deviceVersion < 200) - { - phid->fullStateEcho = PFALSE; - phid->antennaEchoState = PTRUE; - } - else - return EPHIDGET_BADVERSION; + case PHIDUID_RFID_OLD: + case PHIDUID_RFID: + phid->fullStateEcho = PFALSE; + phid->antennaEchoState = PTRUE; break; - case PHIDID_RFID_2OUTPUT: //2-output RFID - if ((phid->phid.deviceVersion >= 200) && (phid->phid.deviceVersion < 201)) - { - phid->antennaEchoState = PUNK_BOOL; - phid->fullStateEcho = PFALSE; - } - else if ((phid->phid.deviceVersion >= 201) && (phid->phid.deviceVersion < 300)) - { - phid->antennaEchoState = PUNK_BOOL; - phid->fullStateEcho = PTRUE; - } - else - return EPHIDGET_BADVERSION; + case PHIDUID_RFID_2OUTPUT_NO_ECHO: + phid->fullStateEcho = PFALSE; + phid->antennaEchoState = PUNK_BOOL; break; - case PHIDID_RFID_2OUTPUT_ADVANCED: //2-output RFID (Advanced) - if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200)) - { - phid->antennaEchoState = PUNK_BOOL; - phid->fullStateEcho = PTRUE; - } - else - return EPHIDGET_BADVERSION; + case PHIDUID_RFID_2OUTPUT: + case PHIDUID_RFID_2OUTPUT_READ_WRITE: + phid->fullStateEcho = PTRUE; + phid->antennaEchoState = PUNK_BOOL; break; default: return EPHIDGET_UNEXPECTED; @@ -149,68 +74,66 @@ CPHIDGETINIT(RFID) { phid->outputEchoState[i] = PUNK_BOOL; } + phid->ledEchoState = PUNK_BOOL; phid->tagPresent = PUNK_BOOL; - ZEROMEM(phid->lastTag, 10); + ZEROMEM(&phid->lastTag, sizeof(CPhidgetRFID_Tag)); + ZEROMEM(&phid->pendingTag, sizeof(CPhidgetRFID_Tag)); phid->tagEventPending = PFALSE; + phid->lastTagValid = PFALSE; - phid->frequencyEcho = PUNK_INT; phid->pregapClocksEcho = PUNK_INT; - phid->postgapClocksEcho = PUNK_INT; + phid->prepulseClocksEcho = PUNK_INT; phid->zeroClocksEcho = PUNK_INT; phid->oneClocksEcho = PUNK_INT; phid->spaceClocksEcho = PUNK_INT; + phid->postgapClocksEcho = PUNK_INT; + phid->eofpulseClocksEcho = PUNK_INT; + phid->listenDuringEOFEcho = PUNK_BOOL; + phid->_4097ConfEcho = PUNK_INT; phid->dataReadPtr = 0; phid->dataWritePtr = 0; - phid->dataReadACPtr = 0; - phid->userReadPtr = 0; phid->manReadPtr = 0; - phid->manEventReadPtr = 0; phid->manWritePtr = 0; phid->biphaseReadPtr = 0; phid->biphaseWritePtr = 0; - - phid->ACCodingOK = PFALSE; - - phid->tagAdvancedCount = PUNK_INT; - phid->polling = PTRUE; + phid->shortClocks = phid->longClocks = 0; - CThread_mutex_lock(&phid->tagthreadlock); - if(phid->tagAdvancedList) - CList_emptyList((CListHandle *)&phid->tagAdvancedList, PTRUE, CPhidgetRFID_Tag_free); - phid->tagAdvancedList = NULL; - CThread_mutex_unlock(&phid->tagthreadlock); - phid->lastTagAdvanced.tagString[0] = '\0'; - - phid->one = phid->two = phid->oneCount = phid->twoCount = 0; + phid->manLockedIn = PFALSE; + phid->biphaseLockedIn = PFALSE; + phid->manShortChange = PFALSE; + phid->biphaseShortChange = PFALSE; - phid->manLockedIn = 0; - phid->biphaseLockedIn = 0; - phid->manShortChange = 0; - phid->biphaseShortChange = 0; + CThread_reset_event(&phid->tagAvailableEvent); - //This needs to always have a valid time -#ifdef _WINDOWS - GetSystemTime(&phid->lastDataTime); -#else - gettimeofday(&phid->lastDataTime,NULL); +#ifdef RFID_HITAGS_SUPPORT + phid->dataReadACPtr = 0; + phid->ACCodingOK = PFALSE; + phid->polling = PFALSE; + setTimeNow(&phid->lastDataTime); + setTimeNow(&phid->hitagReqTime); +#endif + +#ifdef RFID_RAWDATA_API_SUPPORT + phid->userReadPtr = 0; + phid->manEventReadPtr = 0; + phid->lastManEventLong = PFALSE; #endif //send out any initial pre-read packets - switch(phid->phid.deviceIDSpec) { - case PHIDID_RFID: - if (phid->phid.deviceVersion <= 103) - { - ZEROMEM(buffer,8); - LOG(PHIDGET_LOG_INFO,"Sending workaround startup packet"); - if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK) - return result; - } + switch(phid->phid.deviceUID) { + case PHIDUID_RFID_OLD: + { + unsigned char buffer[8] = { 0 }; + ZEROMEM(buffer,8); + LOG(PHIDGET_LOG_INFO,"Sending workaround startup packet"); + if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK) + return result; break; - case PHIDID_RFID_2OUTPUT: + } default: break; } @@ -229,13 +152,35 @@ CPHIDGETINIT(RFID) CPhidget_read((CPhidgetHandle)phid); } + switch(phid->phid.deviceUID) + { + case PHIDUID_RFID_2OUTPUT_READ_WRITE: + //Did we get some data? Wait for a tag + if(phid->dataWritePtr != 0) + { + int readtries = 30; //This should be enough data to guarantee detection of a tag. + while(readtries-- > 0) + { + CPhidget_read((CPhidgetHandle)phid); + if(phid->tagPresent != PUNK_BOOL) + break; + } + } + break; + default: + break; + } + //if the antenna is on, and tagPresent is unknown, then it is false if(phid->antennaEchoState == PTRUE && phid->tagPresent == PUNK_BOOL) phid->tagPresent = PFALSE; - //if the antenna is on, and tagCount is unknown, then it is false - if(phid->antennaEchoState == PTRUE && phid->tagAdvancedCount == PUNK_INT) - phid->tagAdvancedCount = 0; + //So that we can get the tag in the attach handler + if(phid->tagPresent == PTRUE) + { + phid->lastTag = phid->pendingTag; + phid->lastTagValid = PTRUE; + } //recover what we can - if anything isn't filled out, it's PUNK anyways for (i = 0; i<phid->phid.attr.rfid.numOutputs; i++) @@ -250,263 +195,216 @@ CPHIDGETINIT(RFID) phid->zeroClocks = phid->zeroClocksEcho; phid->oneClocks = phid->oneClocksEcho; phid->spaceClocks = phid->spaceClocksEcho; + phid->eofpulseClocks = phid->eofpulseClocksEcho; + phid->prepulseClocks = phid->prepulseClocksEcho; + phid->listenDuringEOF = phid->listenDuringEOFEcho; phid->_4097Conf = phid->_4097ConfEcho; - //make sure the tagTimerThread isn't running - if (phid->tagTimerThread.thread_status == PTRUE) - { - phid->tagTimerThread.thread_status = PFALSE; - CThread_join(&phid->tagTimerThread); - } - return EPHIDGET_OK; } //dataInput - parses device packets CPHIDGETDATA(RFID) int i = 0, j = 0; - unsigned char newTag = PFALSE, newOutputs = PFALSE; - unsigned char tagData[5]; + unsigned char newStateData = PFALSE; unsigned char outputs[RFID_MAXOUTPUTS]; - unsigned char lastOutputs[RFID_MAXOUTPUTS]; - unsigned char antennaState = 0, ledState = 0; - unsigned char gotData = PFALSE; + unsigned char antennaState, ledState; if (length<0) return EPHIDGET_INVALIDARG; TESTPTR(phid); TESTPTR(buffer); - ZEROMEM(tagData, sizeof(tagData)); - ZEROMEM(outputs, sizeof(outputs)); - ZEROMEM(lastOutputs, sizeof(lastOutputs)); - //Parse device packets - store data locally - switch(phid->phid.deviceIDSpec) + switch(phid->phid.deviceUID) { - case PHIDID_RFID: - if (phid->phid.deviceVersion < 200) - { - gotData = PTRUE; - CThread_mutex_lock(&phid->tagthreadlock); - setTimeNow(&phid->lastTagTime); - advancedTagEventForOldReaders(phid, buffer+1); - if(!memcmp(phid->lastTag, buffer+1, 5) && phid->tagPresent == PTRUE) - newTag = PFALSE; - else if(!memcmp("\0\0\0\0\0", buffer+1, 5)) - newTag = PFALSE; - else - { - memcpy(tagData, buffer+1, 5); - newTag = PTRUE; - } - CThread_mutex_unlock(&phid->tagthreadlock); - } - else - return EPHIDGET_UNEXPECTED; + case PHIDUID_RFID_OLD: + case PHIDUID_RFID: + // Enything other then all 0's means a tag is detected + if(memcmp("\0\0\0\0\0", buffer+1, 5)) + tagEvent_fromEM4100Data(phid, buffer+1); break; - case PHIDID_RFID_2OUTPUT: - if ((phid->phid.deviceVersion >= 200) && (phid->phid.deviceVersion < 300)) - { - switch(buffer[0]) - { - case RFID_PACKET_TAG: - gotData = PTRUE; - CThread_mutex_lock(&phid->tagthreadlock); - setTimeNow(&phid->lastTagTime); - advancedTagEventForOldReaders(phid, buffer+1); - if(!memcmp(phid->lastTag, buffer+1, 5) && phid->tagPresent == PTRUE) - newTag = PFALSE; - else if(!memcmp("\0\0\0\0\0", buffer+1, 5)) - newTag = PFALSE; - else - { - memcpy(tagData, buffer+1, 5); - newTag = PTRUE; - } - CThread_mutex_unlock(&phid->tagthreadlock); - break; - case RFID_PACKET_OUTPUT_ECHO: - if(phid->fullStateEcho) - { - newOutputs = PTRUE; - - for (i = 0, j = 0x01; i < phid->phid.attr.rfid.numOutputs; i++, j<<=1) - { - if (buffer[1] & j) - outputs[i] = PTRUE; - else - outputs[i] = PFALSE; - } - - if(buffer[1] & RFID_LED_FLAG) - ledState = PTRUE; - else - ledState = PFALSE; - - if(buffer[1] & RFID_ANTENNA_FLAG) - antennaState = PTRUE; - else - antennaState = PFALSE; - } - break; - default: - return EPHIDGET_UNEXPECTED; - } - } - else - return EPHIDGET_UNEXPECTED; - break; - // RFID with decoding in software and write support - case PHIDID_RFID_2OUTPUT_ADVANCED: - if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200)) + case PHIDUID_RFID_2OUTPUT_NO_ECHO: + case PHIDUID_RFID_2OUTPUT: + switch(buffer[0]) { - int dataLength = 0; - int data[RFID_MAX_DATA_PER_PACKET]; - switch(buffer[0] & 0x40) - { - case RFID_READ_DATA_IN_PACKET: - gotData = PTRUE; - phid->frequencyEcho = buffer[1] * 1000; - - //move RFID data into local storage - dataLength = buffer[0]; - for(i = 0; i < dataLength; i++) - { - data[i] = buffer[i+2]; - phid->dataBuffer[phid->dataWritePtr] = buffer[i+2]; - - phid->dataWritePtr++; - phid->dataWritePtr &= RFID_DATA_ARRAY_MASK; - - //if we run into data that hasn't been read... too bad, we overwrite it and adjust the read pointer - if(phid->dataWritePtr == phid->dataReadPtr) - { - phid->dataReadPtr++; - phid->dataReadPtr &= RFID_DATA_ARRAY_MASK; - } - if(phid->dataWritePtr == phid->dataReadACPtr) - { - phid->dataReadACPtr++; - phid->dataReadACPtr &= RFID_DATA_ARRAY_MASK; - } - } - - break; - case RFID_ECHO_IN_PACKET: - newOutputs = PTRUE; - phid->frequencyEcho = buffer[1] * 1000; - - //LOG(PHIDGET_LOG_DEBUG, "Frequency: %d", phid->frequencyEcho); - - phid->pregapClocksEcho = buffer[2]; - phid->postgapClocksEcho = buffer[3]; - phid->zeroClocksEcho = buffer[4]; - phid->oneClocksEcho = buffer[5]; - phid->spaceClocksEcho = buffer[6]; + case RFID_PACKET_TAG: + // Enything other then all 0's means a tag is detected + if(memcmp("\0\0\0\0\0", buffer+1, 5)) + tagEvent_fromEM4100Data(phid, buffer+1); + break; + case RFID_PACKET_OUTPUT_ECHO: + if(phid->fullStateEcho) + { + newStateData = PTRUE; for (i = 0, j = 0x01; i < phid->phid.attr.rfid.numOutputs; i++, j<<=1) { - if (buffer[7] & j) + if (buffer[1] & j) outputs[i] = PTRUE; else outputs[i] = PFALSE; } - if(buffer[7] & RFID_LED_FLAG) + if(buffer[1] & RFID_LED_FLAG) ledState = PTRUE; else ledState = PFALSE; - if(buffer[7] & RFID_ANTENNA_FLAG) + if(buffer[1] & RFID_ANTENNA_FLAG) antennaState = PTRUE; else antennaState = PFALSE; + } + break; + default: + return EPHIDGET_UNEXPECTED; + } + break; + + // RFID with decoding in software and write support + case PHIDUID_RFID_2OUTPUT_READ_WRITE: + { + int dataLength = 0; + int dataOffset = 1; + int data[RFID_MAX_DATA_PER_PACKET]; + switch(buffer[0] & 0x40) + { + case RFID_ECHO_IN_PACKET: + dataOffset = 11; + newStateData = PTRUE; + + //Don't bother - we don't use it. + //phid->frequencyEcho = buffer[1] * 1000; + + phid->pregapClocksEcho = buffer[2]; + phid->prepulseClocksEcho = buffer[7]; + phid->zeroClocksEcho = buffer[4]; + phid->oneClocksEcho = buffer[5]; + phid->spaceClocksEcho = buffer[6]; + phid->postgapClocksEcho = buffer[3]; + phid->eofpulseClocksEcho = buffer[8]; + + for (i = 0, j = 0x01; i < phid->phid.attr.rfid.numOutputs; i++, j<<=1) + { + if (buffer[9] & j) + outputs[i] = PTRUE; + else + outputs[i] = PFALSE; + } - phid->_4097ConfEcho = buffer[8]; + if(buffer[9] & RFID_LED_FLAG) + ledState = PTRUE; + else + ledState = PFALSE; - //space in data - if(buffer[9]) - { - //Manchester event with space - unsigned char manEventData[1]; - manEventData[0] = PUNK_BOOL; + if(buffer[9] & RFID_ANTENNA_FLAG) + antennaState = PTRUE; + else + antennaState = PFALSE; + + if(buffer[9] & RFID_LISTEN_DURING_EOF_FLAG) + phid->listenDuringEOFEcho = PTRUE; + else + phid->listenDuringEOFEcho = PFALSE; - FIRE(ManchesterData, manEventData, 1); + phid->_4097ConfEcho = buffer[10]; - //Add a space in the buffer - only if it's not already a space + //NOTE: Fall Through + case RFID_READ_DATA_IN_PACKET: + + //move RFID data into local storage + dataLength = buffer[0] & 0x3F; + for(i = 0; i < dataLength; i++) + { + data[i] = buffer[i+dataOffset] << 1; + if((data[i] & 0xFE) == 0xFE) + { + data[i] = PUNK_INT; phid->dataBuffer[phid->dataWritePtr] = PUNK_INT; - phid->dataWritePtr++; - phid->dataWritePtr &= RFID_DATA_ARRAY_MASK; - - //if we run into data that hasn't been read... too bad, we overwrite it and adjust the read pointer - if(phid->dataWritePtr == phid->dataReadPtr) - { - phid->dataReadPtr++; - phid->dataReadPtr &= RFID_DATA_ARRAY_MASK; - } - if(phid->dataWritePtr == phid->dataReadACPtr) - { - phid->dataReadACPtr++; - phid->dataReadACPtr &= RFID_DATA_ARRAY_MASK; - } - dataLength = 1; - data[0] = PUNK_INT; } else - gotData = PTRUE; + { + // convert to data lengths that we expect to deal with internally + int polarity = data[i] & 0x100; + int clocks = data[i] & 0xff; + + if(clocks >= 10 && clocks <= 22) + phid->dataBuffer[phid->dataWritePtr] = polarity | 16; + else if(clocks >= 26 && clocks <= 40) + phid->dataBuffer[phid->dataWritePtr] = polarity | 32; + else if(clocks >= 42 && clocks <= 54) + phid->dataBuffer[phid->dataWritePtr] = polarity | 48; + else if(clocks >= 56 && clocks <= 72) + phid->dataBuffer[phid->dataWritePtr] = polarity | 64; + else if(clocks >= 120 && clocks <= 136) + phid->dataBuffer[phid->dataWritePtr] = polarity | 128; + else + phid->dataBuffer[phid->dataWritePtr] = PUNK_INT; + } - break; - default: - return EPHIDGET_UNEXPECTED; - } + phid->dataWritePtr++; + phid->dataWritePtr &= RFID_DATA_ARRAY_MASK; - if(dataLength) - { - //send out raw data event - FIRE(RawData, data, dataLength); + //if we run into data that hasn't been read... too bad, we overwrite it and adjust the read pointer + if(phid->dataWritePtr == phid->dataReadPtr) + { + phid->dataReadPtr++; + phid->dataReadPtr &= RFID_DATA_ARRAY_MASK; + } +#ifdef RFID_HITAGS_SUPPORT + if(phid->dataWritePtr == phid->dataReadACPtr) + { + phid->dataReadACPtr++; + phid->dataReadACPtr &= RFID_DATA_ARRAY_MASK; + } +#endif + } - //analyze data - analyze_data(phid); - if(phid->ACCodingOK) - analyze_data_AC(phid); - else - phid->dataReadACPtr = phid->dataWritePtr; - } + break; + default: + return EPHIDGET_UNEXPECTED; + } + + if(dataLength) + { + +#ifdef RFID_RAWDATA_API_SUPPORT + FIRE(RawData, data, dataLength); +#endif + + //analyze data + analyze_data(phid); + +#ifdef RFID_HITAGS_SUPPORT + setTimeNow(&phid->lastDataTime); + if(phid->ACCodingOK) + analyze_data_AC(phid); + else + phid->dataReadACPtr = phid->dataWritePtr; +#endif } - else - return EPHIDGET_UNEXPECTED; break; + } default: return EPHIDGET_UNEXPECTED; } - if(gotData) - setTimeNow(&phid->lastDataTime); - //Make sure values are within defined range, and store to structure - if(newOutputs) + if(newStateData) { + unsigned char lastOutputs[RFID_MAXOUTPUTS]; + for (i = 0; i < phid->phid.attr.rfid.numOutputs; i++) { lastOutputs[i] = phid->outputEchoState[i]; phid->outputEchoState[i] = outputs[i]; } + phid->ledEchoState = ledState; phid->antennaEchoState = antennaState; - } - CThread_mutex_lock(&phid->tagthreadlock); - if(newTag && !phid->tagEventPending) - { - memcpy(phid->pendingTag, tagData, 5); - phid->tagEventPending = PTRUE; - CThread_set_event(&phid->tagAvailableEvent); - } - CThread_mutex_unlock(&phid->tagthreadlock); - //Events - if(newOutputs) - { + //Events for (i = 0; i < phid->phid.attr.rfid.numOutputs; i++) { if(lastOutputs[i] != phid->outputEchoState[i]) @@ -529,13 +427,24 @@ CPHIDGETINITEVENTS(RFID) } } - //Initial tag events are sent from the tagTimerThread + //Initial non-remote tag events are sent from the tagTimerThread //Don't start the tag thread if this is a networked Phidget CThread_mutex_lock(&phid->phid.lock); if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_ATTACHED_FLAG)) { - if(!CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG)) + //For remote - if there is a tag present, send the tag event here + if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG)) + { + CThread_mutex_unlock(&phid->phid.lock); + if(phid->tagPresent == PTRUE && phid->lastTagValid == PTRUE) + { + if(phid->lastTag.protocol == PHIDGET_RFID_PROTOCOL_EM4100) + FIRE(Tag, phid->lastTag.tagData); + FIRE(Tag2, phid->lastTag.tagString, phid->lastTag.protocol); + } + } + else { CThread_mutex_unlock(&phid->phid.lock); //Start the tagTimerThread - do it here because we are about to start the read thread, and that will keep it active @@ -546,13 +455,6 @@ CPHIDGETINITEVENTS(RFID) return EPHIDGET_UNEXPECTED; } } - //For remote - if there is a tag present, send the tag event here - else - { - CThread_mutex_unlock(&phid->phid.lock); - if(phid->tagPresent == PTRUE) - FIRE(Tag, phid->lastTag); - } } else { @@ -584,8 +486,6 @@ int CPhidgetRFID_free(CPhidgetHandle phidG) CPhidgetRFIDHandle phid = (CPhidgetRFIDHandle)phidG; CThread_mutex_destroy(&phid->tagthreadlock); CThread_destroy_event(&phid->tagAvailableEvent); - CThread_destroy_event(&phid->respEvent); - CThread_destroy_event(&phid->respEvent2); return EPHIDGET_OK; } @@ -601,75 +501,91 @@ CMAKEPACKET(RFID) TESTPTRS(phid, buffer); - switch(phid->phid.deviceIDSpec) + switch(phid->phid.deviceUID) { - case PHIDID_RFID_2OUTPUT: //4-output RFID - if ((phid->phid.deviceVersion >= 200) && (phid->phid.deviceVersion < 300)) + case PHIDUID_RFID_2OUTPUT_NO_ECHO: + case PHIDUID_RFID_2OUTPUT: + //have to make sure that everything to be sent has some sort of default value if the user hasn't set a value + for (i = 0; i < phid->phid.attr.rfid.numOutputs; i++) { - //have to make sure that everything to be sent has some sort of default value if the user hasn't set a value - for (i = 0; i < phid->phid.attr.rfid.numOutputs; i++) - { - if (phid->outputState[i] == PUNK_BOOL) - phid->outputState[i] = PFALSE; - } - if(phid->antennaState == PUNK_BOOL) - phid->antennaState = PFALSE; - if(phid->ledState == PUNK_BOOL) - phid->ledState = PFALSE; + if (phid->outputState[i] == PUNK_BOOL) + phid->outputState[i] = PFALSE; + } + if(phid->antennaState == PUNK_BOOL) + phid->antennaState = PFALSE; + if(phid->ledState == PUNK_BOOL) + phid->ledState = PFALSE; - //construct the packet - for (i = 0, j = 1; i < phid->phid.attr.rfid.numOutputs; i++, j<<=1) - { - if (phid->outputState[i]) - buffer[0] |= j; - } - if(phid->ledState == PTRUE) - buffer[0] |= RFID_LED_FLAG; - if(phid->antennaState == PTRUE) - buffer[0] |= RFID_ANTENNA_FLAG; + //construct the packet + for (i = 0, j = 1; i < phid->phid.attr.rfid.numOutputs; i++, j<<=1) + { + if (phid->outputState[i]) + buffer[0] |= j; } - else - return EPHIDGET_UNEXPECTED; + if(phid->ledState == PTRUE) + buffer[0] |= RFID_LED_FLAG; + if(phid->antennaState == PTRUE) + buffer[0] |= RFID_ANTENNA_FLAG; break; - case PHIDID_RFID_2OUTPUT_ADVANCED: //4-output RFID Advanced - if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200)) + case PHIDUID_RFID_2OUTPUT_READ_WRITE: + //have to make sure that everything to be sent has some sort of default value if the user hasn't set a value + for (i = 0; i < phid->phid.attr.rfid.numOutputs; i++) { - //have to make sure that everything to be sent has some sort of default value if the user hasn't set a value - for (i = 0; i < phid->phid.attr.rfid.numOutputs; i++) - { - if (phid->outputState[i] == PUNK_BOOL) - phid->outputState[i] = PFALSE; - } - if(phid->antennaState == PUNK_BOOL) - phid->antennaState = PFALSE; - if(phid->ledState == PUNK_BOOL) - phid->ledState = PFALSE; - - //construct the packet - for (i = 0, j = 1; i < phid->phid.attr.rfid.numOutputs; i++, j<<=1) - { - if (phid->outputState[i]) - buffer[7] |= j; - } - if(phid->ledState == PTRUE) - buffer[7] |= RFID_LED_FLAG; - if(phid->antennaState == PTRUE) - buffer[7] |= RFID_ANTENNA_FLAG; - - //TODO: make sure these are actually all valid - buffer[0] = RFID_CONTROL_OUT_PACKET; - buffer[1] = phid->pregapClocks; - buffer[2] = phid->postgapClocks; - buffer[3] = phid->zeroClocks; - buffer[4] = phid->oneClocks; - buffer[5] = phid->spaceClocks; - buffer[6] = phid->_4097Conf; + if (phid->outputState[i] == PUNK_BOOL) + phid->outputState[i] = PFALSE; } + if(phid->antennaState == PUNK_BOOL) + phid->antennaState = PFALSE; + if(phid->ledState == PUNK_BOOL) + phid->ledState = PFALSE; + + // Default write timing to T5577 + if(phid->pregapClocks == PUNK_INT) + phid->pregapClocks = RFID_T5577_StartGap; + if(phid->prepulseClocks == PUNK_INT) + phid->prepulseClocks = RFID_T5577_PrePulse; + if(phid->zeroClocks == PUNK_INT) + phid->zeroClocks = RFID_T5577_Zero; + if(phid->oneClocks == PUNK_INT) + phid->oneClocks = RFID_T5577_One; + if(phid->spaceClocks == PUNK_INT) + phid->spaceClocks = RFID_T5577_WriteGap; + if(phid->postgapClocks == PUNK_INT) + phid->postgapClocks = RFID_T5577_EndGap; + if(phid->eofpulseClocks == PUNK_INT) + phid->eofpulseClocks = RFID_T5577_EOF; + if(phid->listenDuringEOF == PUNK_BOOL) + phid->listenDuringEOF = PFALSE; + + //construct the packet + for (i = 0, j = 1; i < phid->phid.attr.rfid.numOutputs; i++, j<<=1) + { + if (phid->outputState[i]) + buffer[0] |= j; + } + if(phid->ledState == PTRUE) + buffer[0] |= RFID_LED_FLAG; + if(phid->antennaState == PTRUE) + buffer[0] |= RFID_ANTENNA_FLAG; + + if(phid->antennaState == PTRUE) + phid->_4097Conf = RFID_4097_DefaultON; else - return EPHIDGET_UNEXPECTED; + phid->_4097Conf = RFID_4097_PowerDown; + + buffer[0] |= RFID_CONTROL_OUT_PACKET; + buffer[1] = (phid->pregapClocks-1) & 0x3F; + buffer[1] |= ((phid->postgapClocks-1) << 2) & 0xC0; + buffer[2] = (phid->postgapClocks-1) & 0x0F; + buffer[2] |= ((phid->spaceClocks-1) << 2) & 0xF0; + buffer[3] = (phid->spaceClocks-1) & 0x03; + buffer[3] |= ((phid->zeroClocks-1) << 1) & 0xFC; + buffer[4] = (phid->zeroClocks-1) & 0x01; + buffer[4] |= ((phid->oneClocks-1) << 1) & 0xFE; + buffer[5] = phid->prepulseClocks; + buffer[6] = phid->eofpulseClocks; + buffer[7] = phid->_4097Conf; break; - case PHIDID_RFID: - return EPHIDGET_UNSUPPORTED; //this version does not have outputs default: return EPHIDGET_UNEXPECTED; } @@ -681,15 +597,11 @@ CMAKEPACKET(RFID) CThread_func_return_t tagTimerThreadFunction(CThread_func_arg_t userPtr) { CPhidgetRFIDHandle phid = (CPhidgetRFIDHandle)userPtr; - CPhidgetRFID_TagList *trav = 0, *tagLostList = 0, *tagFoundList = 0; if(!phid) return (CThread_func_return_t)EPHIDGET_INVALIDARG; LOG(PHIDGET_LOG_INFO,"tagTimerThread running"); - //Set this before creation - //phid->tagTimerThread.thread_status = PTRUE; - while (CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_ATTACHED_FLAG) && phid->tagTimerThread.thread_status == PTRUE) { //sleeps for up to 50ms, but can be signalled externally to return immediately @@ -697,120 +609,71 @@ CThread_func_return_t tagTimerThreadFunction(CThread_func_arg_t userPtr) CThread_reset_event(&phid->tagAvailableEvent); //Tag events - //Old-style + CThread_mutex_lock(&phid->tagthreadlock); if(phid->tagEventPending) { - phid->tagPresent = PTRUE; - FIRE(Tag, phid->pendingTag); - CThread_mutex_lock(&phid->tagthreadlock); - setTimeNow(&phid->lastTagTime); - - //so they can access the last tag from this tag event - memcpy(phid->lastTag, phid->pendingTag, 5); - phid->tagEventPending = PFALSE; CThread_mutex_unlock(&phid->tagthreadlock); - } - //New-style - CThread_mutex_lock(&phid->tagthreadlock); - for (trav=phid->tagAdvancedList; trav; trav = trav->next) - { - if(trav->tag->tagEventPending == PTRUE) - CList_addToList((CListHandle *)&tagFoundList, trav->tag, CPhidgetRFID_Tag_areEqual); - } - for (trav=tagFoundList; trav; trav = trav->next) - { - if(phid->tagAdvancedCount == PUNK_INT) - phid->tagAdvancedCount = 0; - phid->tagAdvancedCount++; + if(phid->pendingTag.protocol == PHIDGET_RFID_PROTOCOL_EM4100) + FIRE(Tag, phid->pendingTag.tagData); + FIRE(Tag2, phid->pendingTag.tagString, phid->pendingTag.protocol); - CThread_mutex_unlock(&phid->tagthreadlock); - FIRE(TagAdvanced, trav->tag->tagString, &trav->tag->tagInfo); + //Fill in lastTag after the event so that LAST tag (not current tag) is avialable in the event CThread_mutex_lock(&phid->tagthreadlock); - setTimeNow(&trav->tag->lastTagTime); - - //so they can access the last tag from this tag event - memcpy(&phid->lastTagAdvanced, trav->tag, sizeof(CPhidgetRFID_Tag)); - trav->tag->tagEventPending = PFALSE; + phid->lastTag = phid->pendingTag; + phid->lastTagValid = PTRUE; + phid->tagEventPending = PFALSE; } - CList_emptyList((CListHandle *)&tagFoundList, PFALSE, NULL); CThread_mutex_unlock(&phid->tagthreadlock); //TAG Lost events - //Old-style + CThread_mutex_lock(&phid->tagthreadlock); if(phid->tagPresent != PFALSE) { /* check for tag lost */ - - CThread_mutex_lock(&phid->tagthreadlock); +#ifdef RFID_HITAGS_SUPPORT + if((timeSince(&phid->lastTagTime) > 0.2 && phid->lastTag.protocol != PHIDGET_RFID_PROTOCOL_HITAGS_UID) + || (timeSince(&phid->lastTagTime) > 0.5 && phid->lastTag.protocol == PHIDGET_RFID_PROTOCOL_HITAGS_UID)) +#else if(timeSince(&phid->lastTagTime) > 0.2) +#endif { if (phid->tagPresent == PTRUE) { phid->tagPresent = PFALSE; CThread_mutex_unlock(&phid->tagthreadlock); - FIRE(TagLost, phid->lastTag); + + if(phid->pendingTag.protocol == PHIDGET_RFID_PROTOCOL_EM4100) + FIRE(TagLost, phid->lastTag.tagData); + FIRE(TagLost2, phid->lastTag.tagString, phid->lastTag.protocol); + CThread_mutex_lock(&phid->tagthreadlock); } else if(phid->antennaEchoState == PTRUE) //could be PUNK_BOOL - don't send event, just set to PFALSE (but only if the antenna is on) phid->tagPresent = PFALSE; } - CThread_mutex_unlock(&phid->tagthreadlock); - } - //New-style - if(phid->tagAdvancedCount != 0) - { - if(phid->tagAdvancedCount != PUNK_INT) - { - CThread_mutex_lock(&phid->tagthreadlock); - for (trav=phid->tagAdvancedList; trav; trav = trav->next) - { - if((timeSince(&trav->tag->lastTagTime) > 0.2 && trav->tag->tagInfo.tagType != PHIDGET_RFID_TAG_HITAGS) - || (timeSince(&trav->tag->lastTagTime) > 0.5 && trav->tag->tagInfo.tagType == PHIDGET_RFID_TAG_HITAGS)) - CList_addToList((CListHandle *)&tagLostList, trav->tag, CPhidgetRFID_Tag_areEqual); - } - for (trav=tagLostList; trav; trav = trav->next) - { - CList_removeFromList((CListHandle *)&phid->tagAdvancedList, trav->tag, CPhidgetRFID_Tag_areEqual, PFALSE, NULL); - phid->tagAdvancedCount--; - CThread_mutex_unlock(&phid->tagthreadlock); - FIRE(TagLostAdvanced, trav->tag->tagString, &trav->tag->tagInfo); - CThread_mutex_lock(&phid->tagthreadlock); - } - CList_emptyList((CListHandle *)&tagLostList, PTRUE, CPhidgetRFID_Tag_free); - CThread_mutex_unlock(&phid->tagthreadlock); - } - else if(phid->antennaEchoState == PTRUE) - phid->tagAdvancedCount = 0; } + CThread_mutex_unlock(&phid->tagthreadlock); +#ifdef RFID_HITAGS_SUPPORT //Actively look for tags if we haven't gotten data for a while (Hitag) + CThread_mutex_lock(&phid->tagthreadlock); if(phid->antennaEchoState == PTRUE && phid->polling == PTRUE) { - switch(phid->phid.deviceIDSpec) + switch(phid->phid.deviceUID) { - case PHIDID_RFID_2OUTPUT_ADVANCED: //2-output RFID Advanced - if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200)) + case PHIDUID_RFID_2OUTPUT_READ_WRITE: + if(timeSince(&phid->hitagReqTime) > 0.1 && timeSince(&phid->lastDataTime) > 0.1) //100ms { - CThread_mutex_lock(&phid->tagthreadlock); - if(timeSince(&phid->hitagReqTime) > 0.1) //100ms - { - if(timeSince(&phid->lastDataTime) > 0.1) //100ms - { - HitagS_UID_REQUEST(phid); - } - } - CThread_mutex_unlock(&phid->tagthreadlock); + HitagS_UID_REQUEST(phid); } - else - return (CThread_func_return_t)EPHIDGET_UNEXPECTED; break; + //Cannot send data - case PHIDID_RFID_2OUTPUT: - case PHIDID_RFID: - break; default: - return (CThread_func_return_t)EPHIDGET_UNEXPECTED; + break; } } + CThread_mutex_unlock(&phid->tagthreadlock); +#endif } LOG(PHIDGET_LOG_INFO,"tagTimerThread exiting normally"); @@ -818,6 +681,67 @@ CThread_func_return_t tagTimerThreadFunction(CThread_func_arg_t userPtr) return (CThread_func_return_t)EPHIDGET_OK; } +static int tagEvent(CPhidgetRFIDHandle phid, CPhidgetRFID_TagHandle tagPtr) +{ +again: + CThread_mutex_lock(&phid->tagthreadlock); + + //update time + setTimeNow(&phid->lastTagTime); + + //See if there is a current tag, and if it matches this tag + if(phid->tagPresent != PTRUE || + (phid->lastTagValid && strcmp(phid->lastTag.tagString, tagPtr->tagString) && phid->lastTag.protocol == tagPtr->protocol)) + { + //Wait for tagEventPending to be false if it's true + if(phid->tagEventPending == PTRUE) + { + CThread_mutex_unlock(&phid->tagthreadlock); + SLEEP(10); + goto again; + } + + phid->pendingTag = *tagPtr; + phid->tagEventPending = PTRUE; + CThread_set_event(&phid->tagAvailableEvent); + } + + phid->tagPresent = PTRUE; + + CThread_mutex_unlock(&phid->tagthreadlock); + + return EPHIDGET_OK; +} + +static int tagEvent_fromEM4100Data(CPhidgetRFIDHandle phid, unsigned char *data) +{ + CPhidgetRFID_Tag tag; + ZEROMEM(&tag, sizeof(CPhidgetRFID_Tag)); + snprintf(tag.tagString, RFID_MAX_TAG_STRING_LEN, "%02x%02x%02x%02x%02x",data[0],data[1],data[2],data[3],data[4]); + tag.protocol = PHIDGET_RFID_PROTOCOL_EM4100; + memcpy(tag.tagData, data, 5); + return tagEvent(phid, &tag); +} + +static int waitForTag(CPhidgetRFIDHandle phid, char *tagString, int timeout) +{ + //Wait for this tag to show up + while(timeout > 0) + { + CThread_mutex_lock(&phid->tagthreadlock); + if(!strncmp(phid->pendingTag.tagString, tagString, RFID_MAX_TAG_STRING_LEN)) + { + CThread_mutex_unlock(&phid->tagthreadlock); + return EPHIDGET_OK; + } + CThread_mutex_unlock(&phid->tagthreadlock); + SLEEP(50); + timeout-=50; + } + + return EPHIDGET_TIMEOUT; +} + static int sendRAWData(CPhidgetRFIDHandle phid, unsigned char *data, int bitlength) { unsigned char buffer[10]; @@ -857,229 +781,210 @@ static int sendRAWData(CPhidgetRFIDHandle phid, unsigned char *data, int bitleng return EPHIDGET_OK; } -static void resetHitagACBuffer(CPhidgetRFIDHandle phid) +static void resetValuesFromSpace(CPhidgetRFIDHandle phid) { - phid->dataReadACPtr = phid->dataWritePtr; - phid->ACCodingOK = PTRUE; -} + phid->shortClocks = phid->longClocks = 0; + phid->manLockedIn = 0; + phid->manReadPtr = 0; + phid->manWritePtr = 0; + phid->biphaseReadPtr = 0; + phid->biphaseWritePtr = 0; + phid->manShortChange = 0; + phid->biphaseShortChange = 0; + phid->biphaseLockedIn = 0; -//Hitag CRC -#define CRC_PRESET 0xFF -#define CRC_POLYNOM 0x1D -static void calc_crc_hitag(unsigned char * crc, - unsigned char data, - unsigned char Bitcount) -{ - *crc ^= data; //crc = crc (exor) data - do - { - if( *crc & 0x80 ) // if (MSB-CRC == 1) - { - *crc<<=1; // CRC = CRC Bit-shift left - *crc ^= CRC_POLYNOM; // CRC = CRC (exor) CRC_POLYNOM - } - else - *crc<<=1; // CRC = CRC Bit-shift left - } while(--Bitcount); -} -static unsigned char hitagCRC8(unsigned char *data, int dataBits) -{ - unsigned char crc; - int i; - int dataLength = dataBits / 8; - if(dataBits%8 != 0) - dataLength++; - crc = CRC_PRESET; /* initialize crc algorithm */ +#ifdef RFID_RAWDATA_API_SUPPORT + phid->manEventReadPtr = 0; - for(i=0; i<dataLength; i++) + //Manchester event with space + if(phid->lastManEventLong == PFALSE) { - calc_crc_hitag(&crc, data[i], ((dataBits > 8) ? 8 : dataBits)); - dataBits -= 8; + unsigned char manEventData[1]; + phid->lastManEventLong = PTRUE; + manEventData[0] = PUNK_BOOL; + FIRE(ManchesterData, manEventData, 1); } - - return crc; +#endif } -static int HitagS_WRITE(CPhidgetRFIDHandle phid, int page, unsigned char *data, unsigned char blockWrite) +//ISO11785 CRC +static void CRC_16_CCITT_update(unsigned short *crc, unsigned char x) { - int res; - unsigned char buf[] = {0,0,0}; - unsigned char crc; - - buf[0] = (blockWrite ? 0x90 : 0x80) | page >> 4; - buf[1] = page << 4; - crc = hitagCRC8(buf, 12); - buf[1] |= crc >> 4; - buf[2] = crc << 4; - - //make sure it's been at least 50ms since last hitag request - CThread_mutex_lock(&phid->tagthreadlock); - while(timeSince(&phid->hitagReqTime) < 0.01) //50ms - SLEEP(10); - - phid->hitagState = RFID_HITAG_STATE_WRITE; - phid->hitagOffset = page; - - phid->manShortChange=0; - phid->manLockedIn = 1; - phid->manReadPtr = phid->manWritePtr; - - //Send a Hitag S Command - res = CPhidgetRFID_writeRaw(phid, buf, 20, 7, 7, 7, 13, 21); - - //Don't send it again for at least 100ms - setTimeNow(&phid->hitagReqTime); - CThread_mutex_unlock(&phid->tagthreadlock); - - //Wait for ACK - - //Send page data - - return res; + unsigned short crc_new = (unsigned char)((*crc) >> 8) | ((*crc) << 8); + crc_new ^= x; + crc_new ^= (unsigned char)(crc_new & 0xff) >> 4; + crc_new ^= crc_new << 12; + crc_new ^= (crc_new & 0xff) << 5; + (*crc) = crc_new; } -static int HitagS_READ(CPhidgetRFIDHandle phid, int page, unsigned char blockRead) +//Reverse all bits +static __uint64 +reverse(__uint64 x) { - int res; - unsigned char buf[] = {0,0,0}; - unsigned char crc; - - buf[0] = (blockRead ? 0xD0 : 0xC0) | page >> 4; - buf[1] = page << 4; - crc = hitagCRC8(buf, 12); - buf[1] |= crc >> 4; - buf[2] = crc << 4; - - //make sure it's been at least 50ms since last hitag request - CThread_mutex_lock(&phid->tagthreadlock); - while(timeSince(&phid->hitagReqTime) < 0.01) //50ms - SLEEP(10); - - phid->hitagState = RFID_HITAG_STATE_READ; - phid->hitagOffset = page; - - phid->manShortChange=0; - phid->manLockedIn = 1; - phid->manReadPtr = phid->manWritePtr; - - //Send a Hitag S Command - res = CPhidgetRFID_writeRaw(phid, buf, 20, 7, 7, 7, 13, 21); - - //Don't send it again for at least 100ms - setTimeNow(&phid->hitagReqTime); - CThread_mutex_unlock(&phid->tagthreadlock); - - return res; + x = (((x & 0xaaaaaaaaaaaaaaaaLL) >> 1) | ((x & 0x5555555555555555LL) << 1)); + x = (((x & 0xccccccccccccccccLL) >> 2) | ((x & 0x3333333333333333LL) << 2)); + x = (((x & 0xf0f0f0f0f0f0f0f0LL) >> 4) | ((x & 0x0f0f0f0f0f0f0f0fLL) << 4)); + x = (((x & 0xff00ff00ff00ff00LL) >> 8) | ((x & 0x00ff00ff00ff00ffLL) << 8)); + x = (((x & 0xffff0000ffff0000LL) >> 16) | ((x & 0x0000ffff0000ffffLL) << 16)); + return((x >> 32) | (x << 32)); } -static int HitagS_SELECT(CPhidgetRFIDHandle phid, unsigned char *UID) +/* Takes the tagString in 10-digit hex, and produces data for programming. + * blockData are 32-bit blocks. + * blockDataLen will be 2 when we return, as EM4100 takes 64-bits. + */ +static int encodeEM4100(char *tagString, unsigned int *blockData, int *blockDataLen) { - int res; - unsigned char buf[] = {0,0,0,0,0,0}; - unsigned char crc; - int k,i; - - if(!UID) - return EPHIDGET_INVALIDARG; - if(strlen((char *)UID)!=8) + __int64 tagData, mask; + __uint64 encodedTagData = 0; + int i,j,row,col; + TESTPTRS(tagString, blockData) + TESTPTR(blockDataLen) + if(*blockDataLen < 2) return EPHIDGET_INVALIDARG; + if(strlen(tagString) != 10 ) + if(!(strlen(tagString) == 12 && tagString[0] == '0' && tagString[1] == 'x')) + return EPHIDGET_INVALIDARG; - for(i=0,k=5;i<32;i++,k++) + tagData = strtoll(tagString, NULL, 16); + + //9 leading 1's + encodedTagData = 0xFF80000000000000LL; + //Data + for(i=0, mask=0x0078000000000000LL, j=15; i<10; i++, j--, mask>>=5) { - buf[k/8] |= ((hexval(UID[i/4]) >> (3-(i%4))) & 0x01) << (7-(k%8)); + encodedTagData |= ((tagData << j) & mask); } - crc = hitagCRC8(buf, 37); - for(i=0;i<8;i++,k++) + //Parity + for(i=0, row=1, col=1; i<40; i++, col++) { - buf[k/8] |= (crc >> (7-(i%8))) << (7-(k%8)); + if(col>4) { col=1; row++; } + + //column parity + encodedTagData ^= ((tagData & 0x1) << col); + //row parity + encodedTagData ^= ((tagData & 0x1) << (row*5)); + + tagData>>=1; } - //make sure it's been at least 50ms since last hitag request - CThread_mutex_lock(&phid->tagthreadlock); - while(timeSince(&phid->hitagReqTime) < 0.05) //50ms - SLEEP(10); - - phid->hitagState = RFID_HITAG_STATE_SELECT; - - phid->manShortChange=0; - phid->manLockedIn = 1; - phid->manReadPtr = phid->manWritePtr; - - //Send a Hitag S AC Sequence Command - res = CPhidgetRFID_writeRaw(phid, buf, k, 7, 7, 7, 13, 21); - - //Don't send it again for at least 100ms - setTimeNow(&phid->hitagReqTime); - CThread_mutex_unlock(&phid->tagthreadlock); + blockData[0] = (int)(encodedTagData >> 32); + blockData[1] = (int)encodedTagData; + *blockDataLen = 2; - return res; + return EPHIDGET_OK; } -static int HitagS_UID_REQUEST(CPhidgetRFIDHandle phid) + +/* Takes the tagString in 15-digit decimal, and produces data for programming. + * blockData are 32-bit blocks. + * blockDataLen will be 4 when we return, as FDX-B takes 128-bits. + */ +static int encodeISO11785_FDX_B(char *tagString, unsigned int *blockData, int *blockDataLen) { - int res; - //Send a Hitag S UID Request Command - unsigned char buf[] = { 0xC0 }; + __uint64 tagData, encodedTagData[2] = {0,0}, mask, uniqueID; + unsigned short crc = 0x0000; + unsigned long countryCode; + char countryCodeStr[4]; + int i,j; + TESTPTRS(tagString, blockData) + TESTPTR(blockDataLen) + if(*blockDataLen < 4) + return EPHIDGET_INVALIDARG; + if(strlen(tagString) != 15 ) + return EPHIDGET_INVALIDARG; - //make sure it's been at least 50ms since last hitag request - CThread_mutex_lock(&phid->tagthreadlock); - while(timeSince(&phid->hitagReqTime) < 0.05) //50ms - SLEEP(10); + //Get uniqueID + uniqueID = (__uint64)strtoll(tagString+3, NULL, 10); + //must be 38-bit or less + if(uniqueID > 0x3FFFFFFFFFLL) + return EPHIDGET_INVALIDARG; - phid->hitagState = RFID_HITAG_STATE_UID_REQUEST; + //Get Country Code + memcpy(countryCodeStr, tagString, 3); + countryCodeStr[3] = '\0'; + countryCode = strtoul(countryCodeStr, NULL, 10); + + //Create ISO11784 64-bit data + tagData = (((__uint64)countryCode) << 38) | uniqueID; + //Add the animal bit + tagData |= 0x8000000000000000LL; + //Reverse because order is LSB 1st. + tagData = reverse(tagData); + //Calculate CRC + for(i=0,j=7*8;i<8;i++,j-=8) + CRC_16_CCITT_update(&crc, (unsigned char)((tagData>>j) & 0xFF)); + + //Put it into the FDX-B Format + + //Header and control bits + encodedTagData[0] = 0x0020100804020100LL; + encodedTagData[1] = 0x8040201008040201LL; + //Data + for(i=0, mask = 0x001FE00000000000LL, j=11; i<6; i++, mask >>= 9, j++) + encodedTagData[0] |= ((tagData >> j) & mask); + for(i=0, mask = 0x7F80000000000000LL, j=47; i<2; i++, mask >>= 9, j--) + encodedTagData[1] |= ((tagData << j) & mask); + //CRC + encodedTagData[1] |= ((((__uint64)crc) << 29) & 0x00001FE000000000LL); + encodedTagData[1] |= ((((__uint64)crc) << 28) & 0x0000000FF0000000LL); + + blockData[0] = (int)(encodedTagData[0] >> 32); + blockData[1] = (int)encodedTagData[0]; + blockData[2] = (int)(encodedTagData[1] >> 32); + blockData[3] = (int)encodedTagData[1]; + *blockDataLen = 4; - //Empty AC List - if(phid->hitagACList) - CList_emptyList((CListHandle *)&phid->hitagACList, PTRUE, CPhidgetRFID_HitagAC_free); - phid->hitagACList = NULL; + return EPHIDGET_OK; +} - resetHitagACBuffer(phid); - res = CPhidgetRFID_writeRaw(phid, buf, 5, 7, 7, 7, 13, 21); +/* Takes the tagString in ASCII up to 24 characters, and produces data for programming. + * blockData are 32-bit blocks. + * blockDataLen will be 7 when we return, as PHIDGETS_TAG takes 224-bits. + */ +static int encodePHIDGETS_TAG(char *tagString, unsigned int *blockData, int *blockDataLen) +{ + char tagData[24]; + int len, i, j; + unsigned short crc; + TESTPTRS(tagString, blockData) + TESTPTR(blockDataLen) + if(*blockDataLen < 7) + return EPHIDGET_INVALIDARG; + if(strlen(tagString) > 24 ) + return EPHIDGET_INVALIDARG; - //Don't send it again for at least 100ms - setTimeNow(&phid->hitagReqTime); - CThread_mutex_unlock(&phid->tagthreadlock); + //copy of string. + len = strlen(tagString); + ZEROMEM(tagData, 24); + memcpy(tagData, tagString, len); - return res; -} -static int HitagS_AC_SEQUENCE(CPhidgetRFIDHandle phid, CPhidgetRFID_HitagACHandle ac) -{ - int res; - unsigned char buf[] = {0,0,0,0,0,0}; - unsigned char crc; - int k,i; + //Calculate CRC + crc=0; + for(i=0;i<24;i++) + CRC_16_CCITT_update(&crc, (unsigned char)tagData[i]); - buf[0] = (ac->colPos) << 3; - for(i=0,k=5;i<ac->colPos;i++,k++) + //Header, control bits and CRC + blockData[0] = 0x00040201; + blockData[0] |= (((unsigned int)crc) << 2 & 0x0003FC00); + blockData[0] |= (((unsigned int)crc) << 1 & 0x000001FE); + //Control bits + for(i=1;i<7;i++) + blockData[i] = 0x01010101; + //Data + for(i=0,j=184;i<24;i++,j-=8) { - buf[k/8] |= (ac->uid[i/8] >> (7-(i%8))) << (7-(k%8)); + int block = i/4+1; + int shift = (j%32)+1; + blockData[block] |= (tagData[i] << shift); } - crc = hitagCRC8(buf, ac->colPos+5); - for(i=0;i<8;i++,k++) - { - buf[k/8] |= (crc >> (7-(i%8))) << (7-(k%8)); - } - - //make sure it's been at least 50ms since last hitag request - CThread_mutex_lock(&phid->tagthreadlock); - while(timeSince(&phid->hitagReqTime) < 0.05) //50ms - SLEEP(10); - - memcpy(&phid->lastHitagAC, ac, sizeof(CPhidgetRFID_HitagAC)); - //Send a Hitag S AC Sequence Command - phid->hitagState = RFID_HITAG_STATE_AC_SEQUENCE; - - resetHitagACBuffer(phid); - res = CPhidgetRFID_writeRaw(phid, buf, k, 7, 7, 7, 13, 21); - - //Don't send it again for at least 100ms - setTimeNow(&phid->hitagReqTime); - CThread_mutex_unlock(&phid->tagthreadlock); + *blockDataLen = 7; - return res; + return EPHIDGET_OK; } -static int decodeEM4102(CPhidgetRFIDHandle phid, unsigned char *data, int *startPtr, int *endPtr, CPhidgetRFID_TagHandle tag) +static int decodeEM4100(CPhidgetRFIDHandle phid, unsigned char *data, int *startPtr, int *endPtr, CPhidgetRFID_TagHandle tag) { int i, foundStart, k, j; int myReadPtr = *startPtr; @@ -1116,7 +1021,7 @@ start: } //Got here? - We found the start pattern - //Now decode the EM4102 data + //Now decode the EM4100 data for(i=0;i<64;i++) { em4103data[i] = data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK]; @@ -1157,22 +1062,11 @@ start: j++; //skip row parity bit } - //Old style Tag event for EM4102 - CThread_mutex_lock(&phid->tagthreadlock); - setTimeNow(&phid->lastTagTime); - if((memcmp(phid->lastTag, decodedData, 5) || phid->tagPresent == PFALSE) - && memcmp("\0\0\0\0\0", decodedData, 5) - && !phid->tagEventPending) - { - memcpy(phid->pendingTag, decodedData, 5); - phid->tagEventPending = PTRUE; - CThread_set_event(&phid->tagAvailableEvent); - } - CThread_mutex_unlock(&phid->tagthreadlock); - //Update the tag struct for the advanced tag event - snprintf(tag->tagString, 255, "%02x%02x%02x%02x%02x",decodedData[0],decodedData[1],decodedData[2],decodedData[3],decodedData[4]); - tag->tagInfo.tagType = PHIDGET_RFID_TAG_EM4102; + //Update the tag struct for the tag2 event + snprintf(tag->tagString, RFID_MAX_TAG_STRING_LEN, "%02x%02x%02x%02x%02x",decodedData[0],decodedData[1],decodedData[2],decodedData[3],decodedData[4]); + tag->protocol = PHIDGET_RFID_PROTOCOL_EM4100; + memcpy(tag->tagData, decodedData, 5); //update master read pointer (*startPtr)+=64; @@ -1185,19 +1079,7 @@ tryagain: goto start; } -//ISO11785 CRC -void -CRC_16_CCITT_update(unsigned short *crc, unsigned char x) -{ - unsigned short crc_new = (unsigned char)((*crc) >> 8) | ((*crc) << 8); - crc_new ^= x; - crc_new ^= (unsigned char)(crc_new & 0xff) >> 4; - crc_new ^= crc_new << 12; - crc_new ^= (crc_new & 0xff) << 5; - (*crc) = crc_new; -} - -static int decodeISO11785(CPhidgetRFIDHandle phid, unsigned char *data, int *startPtr, int *endPtr, CPhidgetRFID_TagHandle tag) +static int decodeISO11785_FDX_B(CPhidgetRFIDHandle phid, unsigned char *data, int *startPtr, int *endPtr, CPhidgetRFID_TagHandle tag) { int i, foundStart, k; int myReadPtr = *startPtr; @@ -1305,8 +1187,8 @@ start: (((__uint64)iso11785dataReversed[6]) << 8) + ((__uint64)iso11785dataReversed[7])) & 0x3FFFFFFFFFll;// 38 bit - bits 27-63 - snprintf(tag->tagString, 255, "%03d%012lld",countryCode, UID); - tag->tagInfo.tagType = PHIDGET_RFID_TAG_ISO11784; + snprintf(tag->tagString, RFID_MAX_TAG_STRING_LEN, "%03d%012lld",countryCode, UID); + tag->protocol = PHIDGET_RFID_PROTOCOL_ISO11785_FDX_B; } //update master read pointer @@ -1320,271 +1202,119 @@ tryagain: goto start; } -static int decodeHitagUID(CPhidgetRFIDHandle phid, unsigned char *data, int bytesInQueue, CPhidgetRFID_TagHandle tag, int *collisionPos) -{ - int i, k; - int myReadPtr = 0; - unsigned int HitagUID; - int sofBits = 3; - int expectedBytes = 0; - - if(phid->hitagState == RFID_HITAG_STATE_UID_REQUEST) - expectedBytes = 35; - else if(phid->hitagState == RFID_HITAG_STATE_AC_SEQUENCE) - expectedBytes = 35 - phid->lastHitagAC.colPos; - - *collisionPos = -1; - - //UID is 32 bits, plus SOF == '111' - if(bytesInQueue != expectedBytes) - return EPHIDGET_NOTFOUND; - - //verify SOF - for(i=0;i<sofBits;i++) - { - if(data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] != 1) - return EPHIDGET_NOTFOUND; - } - - //advance past SOF - myReadPtr += sofBits; - myReadPtr &= RFID_DATA_ARRAY_MASK; - - HitagUID = 0; - - //if AC Sequence, read in bits from last AC - for(k=0;k<(32-(expectedBytes-sofBits));k++) - { - HitagUID |= (phid->lastHitagAC.uid[k/8] >> (7-(k%8))) << (31-k); - } - - for(i=0;i<(expectedBytes-sofBits);k++,i++) - { - //check for a collision - if(data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] == PUNK_BOOL) - { - *collisionPos = k; - return EPHIDGET_NOTFOUND; - } - HitagUID |= data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] << (31-k); - } - - //We're good! - snprintf(tag->tagString, 255, "%08x",HitagUID); - tag->tagInfo.tagType = PHIDGET_RFID_TAG_HITAGS; - - return EPHIDGET_OK; -} - -static int decodeHitagACKResponse(CPhidgetRFIDHandle phid, unsigned char *data, int *startPtr, int *endPtr) +static int decodePHIDGETS_TAG(CPhidgetRFIDHandle phid, unsigned char *data, int *startPtr, int *endPtr, CPhidgetRFID_TagHandle tag) { + int i, foundStart, k; int myReadPtr = *startPtr; + char tagData[24]; int bytesInQueue; - int i; - int sofBits = 5; //SOF is really 6-bit but we only see it as 5-bit - int expectedBytes = 7; - + unsigned short crcCalc = 0x0000, crcRead = 0x0000; + //Look for the starting pattern of 13 zeroes and 1 one +start: bytesInQueue = *endPtr - myReadPtr; if(myReadPtr > *endPtr) bytesInQueue += RFID_DATA_ARRAY_SIZE; - //printf("maybe(read).. %d\n", bytesInQueue); - //print_buffer(data, *startPtr, *endPtr); - - if(bytesInQueue != expectedBytes) - return EPHIDGET_NOTFOUND; - - //verify SOF - for(i=0;i<sofBits;i++) + while(myReadPtr != *endPtr) { - if(data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] != 1) + //full sequence is 224 bits + if(bytesInQueue < 224) + return EPHIDGET_NOTFOUND; + foundStart = 1; + + for(i=0;i<13;i++) { - phid->respStatus = EPHIDGET_NOTFOUND; - goto done; + if(data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] != 0) + { + foundStart = 0; + break; + } } - } - - //Data should be '01' - if(data[(myReadPtr + 5) & RFID_DATA_ARRAY_MASK] != 0 - || data[(myReadPtr + 6) & RFID_DATA_ARRAY_MASK] != 1) - { - phid->respStatus = EPHIDGET_NOTFOUND; - goto done; - } - - phid->respStatus = EPHIDGET_OK; -done: - CThread_set_event(&phid->respEvent); - return phid->respStatus; -} - -static int decodeHitagReadResponse(CPhidgetRFIDHandle phid, unsigned char *data, int *startPtr, int *endPtr) -{ - int myReadPtr = *startPtr; - int bytesInQueue; - unsigned char buf[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - int i,k; - int sofBits = 5; //SOF is really 6-bit but we only see it as 5-bit - int expectedBytes = 141; - unsigned char crcExpected = 0, crcFound = 0; - CPhidgetRFID_TagHandle tag = phid->respData; - - bytesInQueue = *endPtr - myReadPtr; - if(myReadPtr > *endPtr) - bytesInQueue += RFID_DATA_ARRAY_SIZE; - - //printf("maybe(read).. %d\n", bytesInQueue); - //print_buffer(data, *startPtr, *endPtr); - - if(bytesInQueue != expectedBytes) - return EPHIDGET_NOTFOUND; - - //verify SOF - for(i=0;i<sofBits;i++) - { - if(data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] != 1) + if(data[(myReadPtr + 13) & RFID_DATA_ARRAY_MASK] != 1) { - phid->respStatus = EPHIDGET_NOTFOUND; - goto done; + foundStart = 0; } - } - - //advance past SOF - myReadPtr += sofBits; - myReadPtr &= RFID_DATA_ARRAY_MASK; + if(foundStart) + break; - for(k=0;k<128;k++) - { - buf[k/8] |= data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] << (7-(k%8)); - } - for(i=0;i<8;k++,i++) - { - crcFound |= data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] << (7-i); - } - crcExpected = hitagCRC8(buf, 128); + myReadPtr++; + myReadPtr &= RFID_DATA_ARRAY_MASK; - if(crcFound != crcExpected) - { - LOG(PHIDGET_LOG_WARNING, "Hitag Read response has bad CRC (%02x, %02x)",crcFound, crcExpected); - phid->respStatus = EPHIDGET_NOTFOUND; - goto done; + bytesInQueue--; } - //We're good! transfer Read data - memcpy(tag->tagData + phid->hitagOffset * 4, buf, 16); - tag->tagDataValid = PTRUE; - - //update timer - setTimeNow(&tag->lastTagTime); - - phid->respStatus = EPHIDGET_OK; -done: - CThread_set_event(&phid->respEvent); - return phid->respStatus; -} - -static int decodeHitagSelectResponse(CPhidgetRFIDHandle phid, unsigned char *data, int *startPtr, int *endPtr) -{ - int myReadPtr = *startPtr; - int bytesInQueue; - unsigned char buf[] = {0,0,0,0}; - int i,k; - int sofBits = 5; //SOF is really 6-bit but we only see it as 5-bit - int expectedBytes = 45; - unsigned char crcExpected = 0, crcFound = 0; - CPhidgetRFID_TagHandle tag = phid->respData; - - bytesInQueue = *endPtr - myReadPtr; - if(myReadPtr > *endPtr) - bytesInQueue += RFID_DATA_ARRAY_SIZE; - - //printf("maybe.. %d\n", bytesInQueue); - //print_buffer(data, *startPtr, *endPtr); + //advance past header + myReadPtr += 14; + myReadPtr &= RFID_DATA_ARRAY_MASK; - if(bytesInQueue != expectedBytes) - return EPHIDGET_NOTFOUND; + //Got here? - We found the start pattern - //verify SOF - for(i=0;i<sofBits;i++) + //Pull out the CRC + for(k=0,i=0;i<16;i++,k++) { - if(data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] != 1) + if(i>0 && i%8 == 0) { - phid->respStatus = EPHIDGET_NOTFOUND; - goto done; + if(data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] != 1) goto tryagain; + k++; } - } - - //advance past SOF - myReadPtr += sofBits; - myReadPtr &= RFID_DATA_ARRAY_MASK; + crcRead |= data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] << (15-i); + } + if(data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] != 1) goto tryagain; + k++; - for(k=0;k<32;k++) - { - buf[k/8] |= data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] << (7-(k%8)); - } - for(i=0;i<8;k++,i++) + //Now decode the PHIDGETS_TAG data + //every block of 7 is followed by a '1' + memset(tagData, 0, 24); + for(i=0;i<192;i++,k++) { - crcFound |= data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] << (7-i); + //Check for control bit + if((i+1)%8 == 0) + { + if(data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] != 1) + goto tryagain; + } + //pull out data + else + { + tagData[i/8] |= data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] << (6-(i%8)); + } } - crcExpected = hitagCRC8(buf, 32); - if(crcFound != crcExpected) - { - LOG(PHIDGET_LOG_WARNING, "Hitag Select response has bad CRC (%02x, %02x)",crcFound, crcExpected); - phid->respStatus = EPHIDGET_NOTFOUND; - goto done; - } + //Calculate CRC + crcCalc = 0; + for(i=0;i<24;i++) + CRC_16_CCITT_update(&crcCalc, (unsigned char)tagData[i]); - //We're good! fill in structure - //Memory size - switch(buf[0] & 0x03) + if(crcCalc != crcRead) { - case 0x00: - tag->tagOptions.memSize = 32; - break; - case 0x01: - tag->tagOptions.memSize = 256; - break; - case 0x02: - tag->tagOptions.memSize = 2048; - break; - case 0x03: - default: - phid->respStatus = EPHIDGET_UNEXPECTED; - goto done; + //FAIL + goto tryagain; } - //AUT bit - if(buf[1] & 0x80) - tag->tagOptions.encrypted = PTRUE; - else - tag->tagOptions.encrypted = PFALSE; - //LCON bit - if(buf[1] & 0x02) - tag->tagOptions.writable = PFALSE; - else - tag->tagOptions.writable = PTRUE; - tag->tagOptionsValid = PTRUE; + //We're good! + memcpy(tag->tagString, tagData, 24); + tag->tagString[24] = '\0'; + tag->protocol = PHIDGET_RFID_PROTOCOL_PHIDGETS; - //update timer - setTimeNow(&tag->lastTagTime); + //update master read pointer + (*startPtr) += 224; + (*startPtr) &= RFID_DATA_ARRAY_MASK; + return EPHIDGET_OK; - phid->respStatus = EPHIDGET_OK; -done: - CThread_set_event(&phid->respEvent); - return phid->respStatus; +tryagain: + myReadPtr++; + myReadPtr &= RFID_DATA_ARRAY_MASK; + goto start; } -static int add_biphase_data(CPhidgetRFIDHandle phid, int readToPtr, int shortClocks, int longClocks) +static int add_biphase_data(CPhidgetRFIDHandle phid, int readToPtr) { int myReadPtr = phid->dataReadPtr; while(myReadPtr != readToPtr) { - int clocks = phid->dataBuffer[myReadPtr] & 0x7F; - //int polarity = (phid->dataBuffer[myReadPtr] & 0x80) ? 1 : 0; + int clocks = phid->dataBuffer[myReadPtr] & 0xFF; - //1 - if (pdiff(clocks, longClocks) < 0.3) { + if (clocks == phid->longClocks) { phid->biphaseBuffer[phid->biphaseWritePtr] = 1; @@ -1600,7 +1330,7 @@ static int add_biphase_data(CPhidgetRFIDHandle phid, int readToPtr, int shortClo phid->biphaseLockedIn = 1; phid->biphaseShortChange = 0; } - else if (pdiff(clocks, shortClocks) < 0.3) { + else if (clocks == phid->shortClocks) { if (phid->biphaseLockedIn && phid->biphaseShortChange) { phid->biphaseBuffer[phid->biphaseWritePtr] = 0; @@ -1632,15 +1362,26 @@ static int add_biphase_data(CPhidgetRFIDHandle phid, int readToPtr, int shortClo return EPHIDGET_OK; } -static int add_manchester_data(CPhidgetRFIDHandle phid, int readToPtr, int shortClocks, int longClocks) +static int add_manchester_data(CPhidgetRFIDHandle phid, int readToPtr) { int myReadPtr = phid->dataReadPtr; while(myReadPtr != readToPtr) { - int clocks = phid->dataBuffer[myReadPtr] & 0x7F; - int polarity = (phid->dataBuffer[myReadPtr] & 0x80) ? 1 : 0; + int clocks = phid->dataBuffer[myReadPtr] & 0xFF; + int polarity = (phid->dataBuffer[myReadPtr] & 0x100) ? 1 : 0; - if (pdiff(clocks, longClocks) < 0.3) { + if (clocks == phid->longClocks) + { + //We're out of sync - re-sync + if(phid->manShortChange) + { + phid->manReadPtr = phid->manWritePtr; + phid->manReadPtr &= RFID_DATA_ARRAY_MASK; +#ifdef RFID_RAWDATA_API_SUPPORT + phid->manEventReadPtr = phid->manWritePtr; + phid->manEventReadPtr &= RFID_DATA_ARRAY_MASK; +#endif + } if (polarity) phid->manBuffer[phid->manWritePtr] = 1; @@ -1650,59 +1391,427 @@ static int add_manchester_data(CPhidgetRFIDHandle phid, int readToPtr, int short phid->manWritePtr++; phid->manWritePtr &= RFID_DATA_ARRAY_MASK; + //TODO: is there a danger of these actually happening?? if(phid->manWritePtr == phid->manReadPtr) { phid->manReadPtr++; phid->manReadPtr &= RFID_DATA_ARRAY_MASK; } +#ifdef RFID_RAWDATA_API_SUPPORT if(phid->manWritePtr == phid->manEventReadPtr) { phid->manEventReadPtr++; phid->manEventReadPtr &= RFID_DATA_ARRAY_MASK; } +#endif phid->manLockedIn = 1; phid->manShortChange = 0; - } - else if (pdiff(clocks, shortClocks) < 0.3) { - if (phid->manLockedIn && phid->manShortChange) { - if (polarity) - phid->manBuffer[phid->manWritePtr] = 1; - else - phid->manBuffer[phid->manWritePtr] = 0; - - phid->manWritePtr++; - phid->manWritePtr &= RFID_DATA_ARRAY_MASK; - - if(phid->manWritePtr == phid->manReadPtr) + } + // Short clocks + else + { + if(!phid->manLockedIn) + { + if(polarity) { - phid->manReadPtr++; - phid->manReadPtr &= RFID_DATA_ARRAY_MASK; + phid->manShortChange=1; + phid->manLockedIn = 1; } - - if(phid->manWritePtr == phid->manEventReadPtr) + } + else + { + if(phid->manShortChange) { - phid->manEventReadPtr++; - phid->manEventReadPtr &= RFID_DATA_ARRAY_MASK; - } + if (polarity) + phid->manBuffer[phid->manWritePtr] = 1; + else + phid->manBuffer[phid->manWritePtr] = 0; + + phid->manWritePtr++; + phid->manWritePtr &= RFID_DATA_ARRAY_MASK; + + if(phid->manWritePtr == phid->manReadPtr) + { + phid->manReadPtr++; + phid->manReadPtr &= RFID_DATA_ARRAY_MASK; + } + +#ifdef RFID_RAWDATA_API_SUPPORT + if(phid->manWritePtr == phid->manEventReadPtr) + { + phid->manEventReadPtr++; + phid->manEventReadPtr &= RFID_DATA_ARRAY_MASK; + } +#endif - phid->manShortChange=0; + phid->manShortChange=0; + } + else + phid->manShortChange=1; } - else - phid->manShortChange=1; } - else { - phid->manLockedIn = 0; - //invalid - phid->manReadPtr = phid->manEventReadPtr = phid->manWritePtr; - //This is not Manchester encoded data - return EPHIDGET_NOTFOUND; + + myReadPtr++; + myReadPtr &= RFID_DATA_ARRAY_MASK; + } + return EPHIDGET_OK; +} + +//Analyses streaming data in Manchester or Biphase coding +static int analyze_data(CPhidgetRFIDHandle phid) +{ + int bytesToRead = 0, bytesRead = 0; + int temp, clocks; + int myReadPtr; + CPhidgetRFID_Tag tag; + + //read till we have real data +start: + while(phid->dataReadPtr != phid->dataWritePtr) + { + if(phid->dataBuffer[phid->dataReadPtr] == PUNK_INT) + { + //LOG(PHIDGET_LOG_DEBUG, "LONG"); + phid->dataReadPtr++; + phid->dataReadPtr &= RFID_DATA_ARRAY_MASK; + resetValuesFromSpace(phid); + } + else + break; + } + + //Make sure we have enough data to do something useful with.. + bytesToRead = phid->dataWritePtr - phid->dataReadPtr; + if(phid->dataReadPtr > phid->dataWritePtr) + bytesToRead += RFID_DATA_ARRAY_SIZE; + + //then read till we have a space or run out of data - figure out data rate + bytesRead = 0; + myReadPtr = phid->dataReadPtr; + while(myReadPtr != phid->dataWritePtr) + { + if(phid->dataBuffer[myReadPtr] == PUNK_INT) + break; + + clocks = (phid->dataBuffer[myReadPtr] & 0xFF); + + if(!phid->shortClocks) + { + phid->shortClocks = clocks; + } + else if(clocks != phid->shortClocks) + { + if(!phid->longClocks) + { + if(phid->shortClocks * 2 == clocks || phid->shortClocks / 2 == clocks) + phid->longClocks = clocks; + else + //found a values that doesn't work - error + goto update_readPtr_restart; + } + else if(clocks != phid->longClocks) + //found a values that doesn't work - error + goto update_readPtr_restart; } myReadPtr++; myReadPtr &= RFID_DATA_ARRAY_MASK; + bytesRead++; + } + + //We haven't seen a one and a two!! + if(phid->shortClocks == 0 || phid->longClocks == 0) + { + //got a gap? move on to more data + if(bytesRead != bytesToRead) + goto check_done; + + //otherwise, wait for more data + return EPHIDGET_OK; + } + + //Order them by size + if(phid->longClocks < phid->shortClocks) + { + temp = phid->longClocks; + phid->longClocks = phid->shortClocks; + phid->shortClocks = temp; + } + + ZEROMEM(&tag, sizeof(CPhidgetRFID_Tag)); + + //Shift data into Manchester and Biphase decoders, update read ptr + if(!add_manchester_data(phid, myReadPtr)) + { +#ifdef RFID_RAWDATA_API_SUPPORT + unsigned char manEventData[RFID_DATA_ARRAY_SIZE]; + int manEventDataWritePtr = 0; +#endif + + if(!decodeEM4100(phid, phid->manBuffer, &phid->manReadPtr, &phid->manWritePtr, &tag)) + tagEvent(phid, &tag); + +#ifdef RFID_RAWDATA_API_SUPPORT + //Manchester data event + while(phid->manEventReadPtr != phid->manWritePtr) + { + manEventData[manEventDataWritePtr++] = phid->manBuffer[phid->manEventReadPtr]; + phid->manEventReadPtr++; + phid->manEventReadPtr&=RFID_DATA_ARRAY_MASK; + } + if(manEventDataWritePtr) + { + phid->lastManEventLong = PFALSE; + FIRE(ManchesterData, manEventData, manEventDataWritePtr); + } + } + //Manchester event with space + else if(phid->lastManEventLong == PFALSE) + { + unsigned char manEventData[1]; + phid->lastManEventLong = PTRUE; + manEventData[0] = PUNK_BOOL; + FIRE(ManchesterData, manEventData, 1); +#endif + } + + if(!add_biphase_data(phid, myReadPtr)) + { + if(!decodePHIDGETS_TAG(phid, phid->biphaseBuffer, &phid->biphaseReadPtr, &phid->biphaseWritePtr, &tag)) + tagEvent(phid, &tag); + if(!decodeISO11785_FDX_B(phid, phid->biphaseBuffer, &phid->biphaseReadPtr, &phid->biphaseWritePtr, &tag)) + tagEvent(phid, &tag); + } + +check_done: + //update read pointer + phid->dataReadPtr = myReadPtr; + + //If there is more data, loop around + if(phid->dataReadPtr != phid->dataWritePtr) + goto start; + + return EPHIDGET_OK; + + //ran into a bad pulse length or a gap - reset stuff +update_readPtr_restart: + phid->dataReadPtr++; + phid->dataReadPtr &= RFID_DATA_ARRAY_MASK; + resetValuesFromSpace(phid); + + goto start; +} + +static int T5577_WriteBlock(CPhidgetRFIDHandle phid, int page, int block, unsigned int data, int lockpage) +{ + int res = EPHIDGET_OK; + unsigned char byteData[5]; + + byteData[0] = ((0x02 | (page & 0x01)) << 6); //OpCode + byteData[0] |= ((lockpage ? 0x01 : 0x00) << 5); //Lock + byteData[0] |= ((data >> 27) & 0x1F); //Data 31:27 + byteData[1] = ((data >> 19) & 0xFF); //Data 26:19 + byteData[2] = ((data >> 11) & 0xFF); //Data 18:11 + byteData[3] = ((data >> 3) & 0xFF); //Data 10:3 + byteData[4] = ((data << 5) & 0xE0); //Data 2:0 + byteData[4] |= ((block & 0x07) << 2); //Block (0-7) + + res = CPhidgetRFID_writeRaw(phid, byteData, 38, + RFID_T5577_StartGap, + RFID_T5577_WriteGap, + RFID_T5577_EndGap, + RFID_T5577_Zero, + RFID_T5577_One, + RFID_T5577_PrePulse, + RFID_T5577_EOF, + PFALSE); + + return res; +} + +static int T5577_Reset(CPhidgetRFIDHandle phid) +{ + int res = EPHIDGET_OK; + unsigned char byteData[1]; + + byteData[0] = 0x00; //OpCode + + res = CPhidgetRFID_writeRaw(phid, byteData, 2, + RFID_T5577_StartGap, + RFID_T5577_WriteGap, + RFID_T5577_EndGap, + RFID_T5577_Zero, + RFID_T5577_One, + RFID_T5577_PrePulse, + RFID_T5577_EOF, + PFALSE); + + return res; +} + +/* Programs a T5577 using the specified protocol and data + * data: Tag string. + * lock: lock the T5577 so it cannot be reprogrammed. + */ +static int T5577_WriteTag(CPhidgetRFIDHandle phid, CPhidgetRFID_Protocol protocol, char *tagString, int lock) +{ + int ret = EPHIDGET_OK, i; + unsigned int data[7]; + int dataLen = 7; + unsigned int configBlock; + + switch(protocol) + { + case PHIDGET_RFID_PROTOCOL_EM4100: + if((ret = encodeEM4100(tagString, data, &dataLen)) != EPHIDGET_OK) + return ret; + configBlock = 0x00148040; // RF/63, manchester, Maxblock = 2 + break; + case PHIDGET_RFID_PROTOCOL_ISO11785_FDX_B: + if((ret = encodeISO11785_FDX_B(tagString, data, &dataLen)) != EPHIDGET_OK) + return ret; + configBlock = 0x603F8080; // RF/32, differential bi-phase, Maxblock = 4 + break; + case PHIDGET_RFID_PROTOCOL_PHIDGETS: + if((ret = encodePHIDGETS_TAG(tagString, data, &dataLen)) != EPHIDGET_OK) + return ret; + configBlock = 0x603F80E0; // RF/32, differential bi-phase, Maxblock = 7 + break; + default: + return EPHIDGET_INVALIDARG; + } + + //Write Data + for(i=0;i<dataLen;i++) + { + if((ret = T5577_WriteBlock(phid, 0, i+1, data[i], lock)) != EPHIDGET_OK) + return ret; + SLEEP(50); //some time beetween writes! + } + //Write config + if((ret = T5577_WriteBlock(phid, 0, 0, configBlock, lock)) != EPHIDGET_OK) + return ret; + + SLEEP(50); //some time beetween writes! + //Reset Chip + if((ret = T5577_Reset(phid)) != EPHIDGET_OK) + return ret; + + return ret; +} + +#ifdef RFID_HITAGS_SUPPORT +#define ABS(x) ((x) < 0 ? -(x) : (x)) +#define pdiff(a, b) ( ABS((a) - (b)) / (double)( ((a) + (b)) / 2.0 ) ) + +static void resetHitagACBuffer(CPhidgetRFIDHandle phid) +{ + phid->dataReadACPtr = phid->dataWritePtr; + phid->ACCodingOK = PTRUE; +} + +//Hitag CRC +#define CRC_PRESET 0xFF +#define CRC_POLYNOM 0x1D +static void calc_crc_hitag(unsigned char * crc, + unsigned char data, + unsigned char Bitcount) +{ + *crc ^= data; //crc = crc (exor) data + do + { + if( *crc & 0x80 ) // if (MSB-CRC == 1) + { + *crc<<=1; // CRC = CRC Bit-shift left + *crc ^= CRC_POLYNOM; // CRC = CRC (exor) CRC_POLYNOM + } + else + *crc<<=1; // CRC = CRC Bit-shift left + } while(--Bitcount); +} +static unsigned char hitagCRC8(unsigned char *data, int dataBits) +{ + unsigned char crc; + int i; + int dataLength = dataBits / 8; + if(dataBits%8 != 0) + dataLength++; + crc = CRC_PRESET; /* initialize crc algorithm */ + + for(i=0; i<dataLength; i++) + { + calc_crc_hitag(&crc, data[i], ((dataBits > 8) ? 8 : dataBits)); + dataBits -= 8; + } + + return crc; +} + +static int HitagS_UID_REQUEST(CPhidgetRFIDHandle phid) +{ + int res; + //Send a Hitag S UID Request Command + unsigned char buf[] = { 0xC0 }; + + //make sure it's been at least 50ms since last hitag request + while(timeSince(&phid->hitagReqTime) < 0.05) //50ms + SLEEP(10); + + resetHitagACBuffer(phid); + res = CPhidgetRFID_writeRaw(phid, buf, 5, 7, 7, 7, 13, 21, 0, 64, PTRUE); + + //Don't send it again for at least 100ms + setTimeNow(&phid->hitagReqTime); + + return res; +} + +static int decodeHitagUID(CPhidgetRFIDHandle phid, unsigned char *data, int bytesInQueue, CPhidgetRFID_TagHandle tag, int *collisionPos) +{ + int i, k; + int myReadPtr = 0; + unsigned int HitagUID; + int sofBits = 3; + int expectedBytes = 0; + + expectedBytes = 35; + + *collisionPos = -1; + + //UID is 32 bits, plus SOF == '111' + if(bytesInQueue != expectedBytes) + return EPHIDGET_NOTFOUND; + + //verify SOF + for(i=0;i<sofBits;i++) + { + if(data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] != 1) + return EPHIDGET_NOTFOUND; + } + + //advance past SOF + myReadPtr += sofBits; + myReadPtr &= RFID_DATA_ARRAY_MASK; + + HitagUID = 0; + + for(i=0,k=0;i<(expectedBytes-sofBits);k++,i++) + { + //check for a collision + if(data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] == PUNK_BOOL) + { + *collisionPos = k; + return EPHIDGET_NOTFOUND; + } + HitagUID |= data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] << (31-k); } + + //We're good! + snprintf(tag->tagString, RFID_MAX_TAG_STRING_LEN, "%08x",HitagUID); + tag->protocol = PHIDGET_RFID_PROTOCOL_HITAGS_UID; + return EPHIDGET_OK; } @@ -1721,20 +1830,17 @@ static int decodeACdata(CPhidgetRFIDHandle phid, unsigned char *acBuffer, int *a int acWritePtr = 0; unsigned char acBitLocation = 0; - if(phid->hitagState == RFID_HITAG_STATE_UID_REQUEST) - lastIndex = 34; - else if(phid->hitagState == RFID_HITAG_STATE_AC_SEQUENCE) - lastIndex = 34 - phid->lastHitagAC.colPos; + lastIndex = 34; if(*acBufferSize < lastIndex+1) goto fail; //if the first pulse is low, we need to add a high pulse before it - if(!(phid->dataBuffer[phid->dataReadACPtr] & 0x80)) + if(!(phid->dataBuffer[phid->dataReadACPtr] & 0x100)) { myReadPtr--; myReadPtr &= RFID_DATA_ARRAY_MASK; - phid->dataBuffer[myReadPtr] = (shortClocks/2) | 0x80; + phid->dataBuffer[myReadPtr] = (shortClocks/2) | 0x100; } bytesToRead = readToPtr - myReadPtr; @@ -1748,10 +1854,10 @@ static int decodeACdata(CPhidgetRFIDHandle phid, unsigned char *acBuffer, int *a for(i=0;i<bytesToRead;i+=2) { - clocks1 = phid->dataBuffer[myReadPtr] & 0x7F; - polarity1 = (phid->dataBuffer[myReadPtr] & 0x80) ? 1 : 0; - clocks2 = phid->dataBuffer[(myReadPtr+1) & RFID_DATA_ARRAY_MASK] & 0x7F; - polarity2 = (phid->dataBuffer[(myReadPtr+1) & RFID_DATA_ARRAY_MASK] & 0x80) ? 1 : 0; + clocks1 = phid->dataBuffer[myReadPtr] & 0xFF; + polarity1 = (phid->dataBuffer[myReadPtr] & 0x100) ? 1 : 0; + clocks2 = phid->dataBuffer[(myReadPtr+1) & RFID_DATA_ARRAY_MASK] & 0xFF; + polarity2 = (phid->dataBuffer[(myReadPtr+1) & RFID_DATA_ARRAY_MASK] & 0x100) ? 1 : 0; clocks = clocks1 + clocks2; @@ -1759,7 +1865,7 @@ static int decodeACdata(CPhidgetRFIDHandle phid, unsigned char *acBuffer, int *a goto fail; //the first pulse can be long - if (pdiff(clocks, shortClocks) < 0.2 || acWritePtr == 0) + if (clocks == shortClocks || acWritePtr == 0) { if(acBitLocation == 1) { @@ -1769,7 +1875,7 @@ static int decodeACdata(CPhidgetRFIDHandle phid, unsigned char *acBuffer, int *a } acBitLocation ^= 1; } - else if(pdiff(clocks, longClocks) < 0.2) + else if(clocks == longClocks) { if(acBitLocation == 1) { @@ -1807,13 +1913,13 @@ static int decodeACdata(CPhidgetRFIDHandle phid, unsigned char *acBuffer, int *a //last low pulse won't be seen because we idle low if(acWritePtr == lastIndex && myReadPtr == ((readToPtr-1) & RFID_DATA_ARRAY_MASK)) { - clocks = phid->dataBuffer[myReadPtr] & 0x7F; - polarity1 = (phid->dataBuffer[myReadPtr] & 0x80) ? 1 : 0; + clocks = phid->dataBuffer[myReadPtr] & 0xFF; + polarity1 = (phid->dataBuffer[myReadPtr] & 0x100) ? 1 : 0; if(polarity1 != 1) goto fail; - if(pdiff(clocks, shortClocks/2) < 0.4) + if(clocks == shortClocks/2) { if(acBitLocation==1) { @@ -1824,7 +1930,7 @@ static int decodeACdata(CPhidgetRFIDHandle phid, unsigned char *acBuffer, int *a else acBitLocation ^= 1; } - else if(pdiff(clocks, longClocks/2) < 0.3) + else if(clocks == shortClocks) { if(acBitLocation==1) goto fail; @@ -1832,7 +1938,7 @@ static int decodeACdata(CPhidgetRFIDHandle phid, unsigned char *acBuffer, int *a acBuffer[acWritePtr] = PFALSE; acWritePtr++; } - else if(pdiff(clocks, (longClocks/4)*3) < 0.25) + else if(clocks, shortClocks * 1.5) { if(acBitLocation==1) goto fail; @@ -1858,257 +1964,6 @@ fail: return EPHIDGET_NOTFOUND; } -//NOTE: tag is a local variable, we need to make a copy of it before adding it to lists, etc. -static int advanced_tag_event(CPhidgetRFIDHandle phid, CPhidgetRFID_TagHandle tagPtr, int lock) -{ - CPhidgetRFID_TagHandle tag; - //Add to the tag list here, remove from the tag list in the tagTimerThreadFunction - if(lock) - CThread_mutex_lock(&phid->tagthreadlock); - if(CList_findInList((CListHandle)phid->tagAdvancedList, tagPtr, CPhidgetRFID_Tag_areEqual, (void**)&tag) == EPHIDGET_NOTFOUND) - { - //make a copy - tag = (CPhidgetRFID_TagHandle)malloc(sizeof(*tag)); - memcpy(tag, tagPtr, sizeof(*tag)); - tag->tagEventPending = PTRUE; - CThread_set_event(&phid->tagAvailableEvent); - CList_addToList((CListHandle *)&phid->tagAdvancedList, tag, CPhidgetRFID_Tag_areEqual); - } - - setTimeNow(&tag->lastTagTime); - if(lock) - CThread_mutex_unlock(&phid->tagthreadlock); - - return EPHIDGET_OK; -} - -//Analyses streaming data in Manchester or Biphase coding -static int analyze_data(CPhidgetRFIDHandle phid) -{ - int bytesToRead = 0, bytesRead = 0; - int temp, one, two; - int myReadPtr; - CPhidgetRFID_Tag tag; - - //read till we have real data -start: - while(phid->dataReadPtr != phid->dataWritePtr) - { - if(phid->dataBuffer[phid->dataReadPtr] == PUNK_INT) - { - phid->dataReadPtr++; - phid->dataReadPtr &= RFID_DATA_ARRAY_MASK; - phid->atGap = PTRUE; - - phid->one = phid->two = phid->oneCount = phid->twoCount = 0; - } - else - break; - } - myReadPtr = phid->dataReadPtr; - - //Make sure we have enough data to do something useful with.. - bytesToRead = phid->dataWritePtr - phid->dataReadPtr; - if(phid->dataReadPtr > phid->dataWritePtr) - bytesToRead += RFID_DATA_ARRAY_SIZE; - - if(bytesToRead < 32 && phid->atGap) - return EPHIDGET_OK; - - //then read till we have a space or run out of data - figure out data rate - one = two = 0; - bytesRead = 0; - while(myReadPtr != phid->dataWritePtr) - { - if(phid->dataBuffer[myReadPtr] == PUNK_INT) - break; - - if(phid->one == 0) - { - phid->one = phid->dataBuffer[myReadPtr] & 0x7F; - phid->oneCount++; - } - else - { - temp = round((double)((double)phid->one / (double)phid->oneCount)); - if(pdiff(temp, phid->dataBuffer[myReadPtr] & 0x7F) < 0.3) - { - phid->one += phid->dataBuffer[myReadPtr] & 0x7F; - phid->oneCount++; - } - else - { - if(phid->two == 0) - { - temp = round((double)((double)phid->one / (double)phid->oneCount)); - if(pdiff(temp * 2, phid->dataBuffer[myReadPtr] & 0x7F) < 0.3 - || pdiff(temp / 2, phid->dataBuffer[myReadPtr] & 0x7F) < 0.3) - { - phid->two = phid->dataBuffer[myReadPtr] & 0x7F; - phid->twoCount++; - } - else - { - goto update_readPtr_restart; - } - } - else - { - temp = round((double)((double)phid->two / (double)phid->twoCount)); - if(pdiff(temp, phid->dataBuffer[myReadPtr] & 0x7F) < 0.3) - { - phid->two += phid->dataBuffer[myReadPtr] & 0x7F; - phid->twoCount++; - } - else - { - goto update_readPtr_restart; - } - } - } - } - - myReadPtr++; - myReadPtr &= RFID_DATA_ARRAY_MASK; - bytesRead++; - } - - if(bytesRead < bytesToRead) - { - goto update_readPtr_restart; - } - - //don't let the one and two counters get too big - if(phid->oneCount >= RFID_DATA_ARRAY_SIZE) - { - phid->one = round((double)((double)phid->one / 2.0)); - phid->oneCount = phid->oneCount / 2; - } - if(phid->twoCount >= RFID_DATA_ARRAY_SIZE) - { - phid->two = round((double)((double)phid->two / 2.0)); - phid->twoCount = phid->twoCount / 2; - } - - if(phid->one) - one = round((double)((double)phid->one / (double)phid->oneCount)); - if(phid->two) - two = round((double)((double)phid->two / (double)phid->twoCount)); - - //Order them by size - if(two < one) - { - temp = two; - two = one; - one = temp; - } - - //printf("One: %3d Two: %3d Bytes: %4d\n",one, two, bytesToRead); - - ZEROMEM(&tag, sizeof(CPhidgetRFID_Tag)); - //Normalize the data rate we supply to the user to be a power of 2 - //TODO: are there any tags which use a bitrate that's not a power of two? - //Yes - Q5 can have an arbitrary data rate - temp=1; - tag.tagInfo.bitRate = two; - while(temp<two) - { - temp*=2; - if(pdiff(temp, two) < 0.3) - { - tag.tagInfo.bitRate = temp; - break; - } - } - if(tag.tagInfo.bitRate == 128) - printf("hmm\n"); //TODO: are we actually going to do something about this? - - //Shift data into Manchester and Biphase decoders, update read ptr - if(phid->hitagState == RFID_HITAG_STATE_SELECT - || phid->hitagState == RFID_HITAG_STATE_READ - || phid->hitagState == RFID_HITAG_STATE_WRITE) - { - if(phid->manReadPtr == phid->manWritePtr) - { - //may have to advance one to make things work - if(phid->dataBuffer[phid->dataReadPtr] & 0x80 && pdiff(phid->dataBuffer[phid->dataReadPtr] & 0x7F, 16) < 0.3) - phid->dataReadPtr = ((phid->dataReadPtr + 1) & RFID_DATA_ARRAY_MASK); - } - } - if(!add_manchester_data(phid, myReadPtr, one, two)) - { - unsigned char manEventData[RFID_DATA_ARRAY_SIZE]; - int manEventDataWritePtr = 0; - - tag.tagInfo.encoding = PHIDGET_RFID_ENCODING_MANCHESTER; - - //Manchester data event - while(phid->manEventReadPtr != phid->manWritePtr) - { - manEventData[manEventDataWritePtr++] = phid->manBuffer[phid->manEventReadPtr]; - phid->manEventReadPtr++; - phid->manEventReadPtr&=RFID_DATA_ARRAY_MASK; - } - if(manEventDataWritePtr) - FIRE(ManchesterData, manEventData, manEventDataWritePtr); - - if(phid->hitagState == RFID_HITAG_STATE_SELECT) - { - //try to decode a Hitag SELECT response - decodeHitagSelectResponse(phid, phid->manBuffer, &phid->manReadPtr, &phid->manWritePtr); - } - if(phid->hitagState == RFID_HITAG_STATE_READ) - { - //try to decode a Hitag READ response - decodeHitagReadResponse(phid, phid->manBuffer, &phid->manReadPtr, &phid->manWritePtr); - } - if(phid->hitagState == RFID_HITAG_STATE_WRITE) - { - //try to decode a Hitag WRITE response - decodeHitagACKResponse(phid, phid->manBuffer, &phid->manReadPtr, &phid->manWritePtr); - } - if(!decodeEM4102(phid, phid->manBuffer, &phid->manReadPtr, &phid->manWritePtr, &tag)) - advanced_tag_event(phid, &tag, PTRUE); - if(!decodeISO11785(phid, phid->manBuffer, &phid->manReadPtr, &phid->manWritePtr, &tag)) - advanced_tag_event(phid, &tag, PTRUE); - } - else - { - //Manchester event with space - unsigned char manEventData[1]; - manEventData[0] = PUNK_BOOL; - phid->manEventReadPtr = phid->manWritePtr; - - FIRE(ManchesterData, manEventData, 1); - } - if(!add_biphase_data(phid, myReadPtr, one, two)) - { - tag.tagInfo.encoding = PHIDGET_RFID_ENCODING_BIPHASE; - if(!decodeEM4102(phid, phid->biphaseBuffer, &phid->biphaseReadPtr, &phid->biphaseWritePtr, &tag)) - advanced_tag_event(phid, &tag, PTRUE); - if(!decodeISO11785(phid, phid->biphaseBuffer, &phid->biphaseReadPtr, &phid->biphaseWritePtr, &tag)) - advanced_tag_event(phid, &tag, PTRUE); - } - - //update read pointer - phid->dataReadPtr = myReadPtr; - phid->atGap = PFALSE; - - return EPHIDGET_OK; - - //ran into a bad pulse length or a gap - reset stuff -update_readPtr_restart: - phid->one = phid->two = phid->oneCount = phid->twoCount = 0; - phid->dataReadPtr = myReadPtr; - phid->atGap = PTRUE; - phid->manReadPtr = 0; - phid->manEventReadPtr = 0; - phid->manWritePtr = 0; - phid->biphaseReadPtr = 0; - phid->biphaseWritePtr = 0; - goto start; -} - //Analyses data for Hitag AC coding static int analyze_data_AC(CPhidgetRFIDHandle phid) { @@ -2164,44 +2019,9 @@ static int analyze_data_AC(CPhidgetRFIDHandle phid) phid->ACCodingOK = PFALSE; - //printf("%d ",phid->acWritePtr); - tag.tagInfo.encoding = PHIDGET_RFID_ENCODING_AC; - tag.tagInfo.bitRate = 64; if(!decodeHitagUID(phid, acBuffer, acBufferSize, &tag, &collision)) { - advanced_tag_event(phid, &tag, PTRUE); - //TODO: select tag? - //printf("Got Hitag Tag: %s\n",tag.tagString); - - //Any pending AC commands? - if(phid->hitagACList) - { - CPhidgetRFID_HitagACHandle ac = phid->hitagACList[0].hitagAC; - HitagS_AC_SEQUENCE(phid, ac); - CList_removeFromList((CListHandle *)&phid->hitagACList, ac, CPhidgetRFID_HitagAC_areEqual, PTRUE, CPhidgetRFID_HitagAC_free); - } - } - else if(collision != -1) - { - int k; - CPhidgetRFID_HitagACHandle ac = (CPhidgetRFID_HitagACHandle)malloc(sizeof(CPhidgetRFID_HitagAC)); - ZEROMEM(ac, sizeof(CPhidgetRFID_HitagAC)); - //printf("Got Hitag Collision: %d\n",collision); - - for(k=0;k<collision;k++) - { - ac->uid[k/8] |= acBuffer[k+3] << (7-(k%8)); - } - //choose 1 for the collision position - ac->uid[k/8] |= 1 << (7-(k%8)); - - ac->colPos = collision+1; - - HitagS_AC_SEQUENCE(phid, ac); - - //add AC with 0 to queue - ac->uid[k/8] &= ~(1 << (7-(k%8))); - CList_addToList((CListHandle *)&phid->hitagACList, ac, CPhidgetRFID_HitagAC_areEqual); + tagEvent(phid, &tag); } } @@ -2210,18 +2030,7 @@ static int analyze_data_AC(CPhidgetRFIDHandle phid) return EPHIDGET_OK; } - -static int advancedTagEventForOldReaders(CPhidgetRFIDHandle phid, unsigned char *data) -{ - CPhidgetRFID_Tag tag; - ZEROMEM(&tag, sizeof(CPhidgetRFID_Tag)); - tag.tagInfo.bitRate = 64; - tag.tagInfo.encoding = PHIDGET_RFID_ENCODING_MANCHESTER; - snprintf(tag.tagString, 255, "%02x%02x%02x%02x%02x",data[0],data[1],data[2],data[3],data[4]); - tag.tagInfo.tagType = PHIDGET_RFID_TAG_EM4102; - return advanced_tag_event(phid, &tag, PFALSE); -} - +#endif // === Exported Functions === // @@ -2229,8 +2038,6 @@ static int advancedTagEventForOldReaders(CPhidgetRFIDHandle phid, unsigned char CCREATE_EXTRA(RFID, PHIDCLASS_RFID) CThread_mutex_init(&phid->tagthreadlock); CThread_create_event(&phid->tagAvailableEvent); - CThread_create_event(&phid->respEvent); - CThread_create_event(&phid->respEvent2); phid->phid.fptrClose = CPhidgetRFID_close; phid->phid.fptrFree = CPhidgetRFID_free; return EPHIDGET_OK; @@ -2238,12 +2045,17 @@ CCREATE_EXTRA(RFID, PHIDCLASS_RFID) //event setup functions CFHANDLE(RFID, OutputChange, int, int) -CFHANDLE(RFID, Tag, unsigned char *) -CFHANDLE(RFID, TagLost, unsigned char *) +CFHANDLE(RFID, Tag2, char *tagString, CPhidgetRFID_Protocol protocol) +CFHANDLE(RFID, TagLost2, char *tagString, CPhidgetRFID_Protocol protocol) +#ifdef RFID_RAWDATA_API_SUPPORT CFHANDLE(RFID, ManchesterData, unsigned char *data, int dataLength) CFHANDLE(RFID, RawData, int *data, int dataLength) -CFHANDLE(RFID, TagAdvanced, char *tagString, CPhidgetRFID_TagInfoHandle tagInfo) -CFHANDLE(RFID, TagLostAdvanced, char *tagString, CPhidgetRFID_TagInfoHandle tagInfo) +#else +PHIDGET21_API int CCONV CPhidgetRFID_set_OnManchesterData_Handler(CPhidgetRFIDHandle phidA, int (CCONV *fptr)(CPhidgetRFIDHandle, void *userPtr, unsigned char *data, int dataLength), void *userPtr) +{return EPHIDGET_UNSUPPORTED;} +PHIDGET21_API int CCONV CPhidgetRFID_set_OnRawData_Handler(CPhidgetRFIDHandle phidA, int (CCONV *fptr)(CPhidgetRFIDHandle, void *userPtr, int *data, int dataLength), void *userPtr) +{return EPHIDGET_UNSUPPORTED;} +#endif CGET(RFID,OutputCount,int) TESTPTRS(phid,pVal) @@ -2258,9 +2070,9 @@ CGETINDEX(RFID,OutputState,int) TESTDEVICETYPE(PHIDCLASS_RFID) TESTATTACHED TESTINDEX(phid.attr.rfid.numOutputs) - TESTMASGN(outputState[Index], PUNK_BOOL) + TESTMASGN(outputEchoState[Index], PUNK_BOOL) - MASGN(outputState[Index]) + MASGN(outputEchoState[Index]) } CSETINDEX(RFID,OutputState,int) TESTPTR(phid) @@ -2302,9 +2114,11 @@ CSET(RFID,AntennaOn,int) TESTDEVICETYPE(PHIDCLASS_RFID) TESTATTACHED - switch(phid->phid.deviceIDSpec) + switch(phid->phid.deviceUID) { - case PHIDID_RFID_2OUTPUT: + case PHIDUID_RFID_2OUTPUT_NO_ECHO: + case PHIDUID_RFID_2OUTPUT: + case PHIDUID_RFID_2OUTPUT_READ_WRITE: TESTRANGE(PFALSE, PTRUE) if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG)) @@ -2313,41 +2127,11 @@ CSET(RFID,AntennaOn,int) { SENDPACKET(RFID, antennaState); //echo back state if the device doesn't - if (!(phid->fullStateEcho)) + if (phid->fullStateEcho == PFALSE) phid->antennaEchoState = newVal; } return EPHIDGET_OK; - case PHIDID_RFID_2OUTPUT_ADVANCED: - if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG)) - ADDNETWORKKEY(AntennaOn, "%d", antennaState); - else - { - unsigned char *buffer; - int ret = 0; - if(!(buffer = malloc(phid->phid.outputReportByteLength))) return EPHIDGET_NOMEMORY; - ZEROMEM(buffer, phid->phid.outputReportByteLength); - CThread_mutex_lock(&phid->phid.writelock); - - phid->antennaState = newVal; - if(newVal) - { - //phid->_4097Conf = RFID_4097_AmpDemod | RFID_4097_Active | RFID_4097_DataOut | RFID_4097_IntPLL | RFID_4097_FastStart | RFID_4097_Gain960; - phid->_4097Conf = RFID_4097_AmpDemod | RFID_4097_Active | RFID_4097_DataOut | RFID_4097_IntPLL | RFID_4097_FastStart | RFID_4097_Gain120; - } - else - { - phid->_4097Conf = RFID_4097_PowerDown; - } - if((ret = CPhidgetRFID_makePacket(phid, buffer))) goto done2; - if((ret = CPhidgetRFID_sendpacket(phid, buffer))) goto done2; - done2: - CThread_mutex_unlock(&phid->phid.writelock); - free(buffer); - if(ret) return ret; - } - return EPHIDGET_OK; - case PHIDID_RFID: default: return EPHIDGET_UNSUPPORTED; } @@ -2358,13 +2142,13 @@ CGET(RFID,LEDOn,int) TESTDEVICETYPE(PHIDCLASS_RFID) TESTATTACHED - switch(phid->phid.deviceIDSpec) + switch(phid->phid.deviceUID) { - case PHIDID_RFID_2OUTPUT: - case PHIDID_RFID_2OUTPUT_ADVANCED: + case PHIDUID_RFID_2OUTPUT_NO_ECHO: + case PHIDUID_RFID_2OUTPUT: + case PHIDUID_RFID_2OUTPUT_READ_WRITE: TESTMASGN(ledEchoState, PUNK_BOOL) MASGN(ledEchoState) - case PHIDID_RFID: default: return EPHIDGET_UNSUPPORTED; } @@ -2374,10 +2158,11 @@ CSET(RFID,LEDOn,int) TESTDEVICETYPE(PHIDCLASS_RFID) TESTATTACHED - switch(phid->phid.deviceIDSpec) + switch(phid->phid.deviceUID) { - case PHIDID_RFID_2OUTPUT: - case PHIDID_RFID_2OUTPUT_ADVANCED: + case PHIDUID_RFID_2OUTPUT_NO_ECHO: + case PHIDUID_RFID_2OUTPUT: + case PHIDUID_RFID_2OUTPUT_READ_WRITE: TESTRANGE(PFALSE, PTRUE) if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG)) @@ -2390,7 +2175,6 @@ CSET(RFID,LEDOn,int) phid->ledEchoState = newVal; } return EPHIDGET_OK; - case PHIDID_RFID: default: return EPHIDGET_UNSUPPORTED; } @@ -2401,29 +2185,42 @@ CSET(RFID,PollingOn,int) TESTDEVICETYPE(PHIDCLASS_RFID) TESTATTACHED - switch(phid->phid.deviceIDSpec) +#ifdef RFID_HITAGS_SUPPORT + switch(phid->phid.deviceUID) { - case PHIDID_RFID_2OUTPUT_ADVANCED: - phid->polling = newVal; - return EPHIDGET_OK; - case PHIDID_RFID_2OUTPUT: - case PHIDID_RFID: + case PHIDUID_RFID_2OUTPUT_READ_WRITE: + if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG)) + return EPHIDGET_UNSUPPORTED; //TODO? maybe just don't enable over webservice. + else + { + phid->polling = newVal; + return EPHIDGET_OK; + } default: return EPHIDGET_UNSUPPORTED; } +#else + return EPHIDGET_UNSUPPORTED; +#endif } -CGET(RFID, LastTag, unsigned char) - TESTPTRS(phid,pVal) + +PHIDGET21_API int CCONV CPhidgetRFID_getLastTag2(CPhidgetRFIDHandle phid, char **tagString, CPhidgetRFID_Protocol *protocol) +{ + TESTPTRS(phid,tagString) + TESTPTR(protocol) TESTDEVICETYPE(PHIDCLASS_RFID) TESTATTACHED - //if it's all 0's - it's not yet available - if(!memcmp("\0\0\0\0\0", phid->lastTag, 5)) - return EPHIDGET_UNKNOWNVAL; - - memcpy(pVal, phid->lastTag, 5); - - return EPHIDGET_OK; + CThread_mutex_lock(&phid->tagthreadlock); + if(phid->lastTagValid == PTRUE) + { + *tagString = phid->lastTag.tagString; + *protocol = phid->lastTag.protocol; + CThread_mutex_unlock(&phid->tagthreadlock); + return EPHIDGET_OK; + } + CThread_mutex_unlock(&phid->tagthreadlock); + return EPHIDGET_UNKNOWNVAL; } CGET(RFID, TagStatus, int) @@ -2431,361 +2228,186 @@ CGET(RFID, TagStatus, int) TESTDEVICETYPE(PHIDCLASS_RFID) TESTATTACHED - if(phid->tagPresent == PUNK_BOOL && phid->tagAdvancedCount == PUNK_INT) - { - *pVal = PUNK_BOOL; - return EPHIDGET_UNKNOWNVAL; - } + *pVal = phid->tagPresent; - if(phid->tagPresent == PTRUE || (phid->tagAdvancedCount > 0 && phid->tagAdvancedCount != PUNK_INT)) - *pVal = PTRUE; - else - *pVal = PFALSE; + if(*pVal == PUNK_BOOL) + return EPHIDGET_UNKNOWNVAL; return EPHIDGET_OK; } -PHIDGET21_API int CCONV CPhidgetRFID_writeRaw(CPhidgetRFIDHandle phid, unsigned char *data, int bitlength, int pregap, int space, int postgap, int zero, int one) +PHIDGET21_API int CCONV CPhidgetRFID_writeRaw(CPhidgetRFIDHandle phid, unsigned char *data, int bitlength, + int pregap, int space, int postgap, int zero, int one, int prepulse, int eof, int listenDuringEOF) { int retval; TESTPTR(phid) TESTDEVICETYPE(PHIDCLASS_RFID) TESTATTACHED - if(pregap < (2) || pregap > (255)) return EPHIDGET_INVALIDARG; - if(space < (2) || space > (255)) return EPHIDGET_INVALIDARG; - if(postgap < (2) || postgap > (255)) return EPHIDGET_INVALIDARG; - if(zero < (5) || zero > (255)) return EPHIDGET_INVALIDARG; - if(one < (5) || one > (255)) return EPHIDGET_INVALIDARG; - if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG)) - ;//ADDNETWORKKEYINDEXED(Acceleration, "%lE", motorAcceleration); //TODO - else + switch(phid->phid.deviceUID) { - unsigned char *buffer; - int ret = 0; - if(!(buffer = malloc(phid->phid.outputReportByteLength))) return EPHIDGET_NOMEMORY; - ZEROMEM(buffer, phid->phid.outputReportByteLength); - CThread_mutex_lock(&phid->phid.writelock); - - phid->pregapClocks = pregap; - phid->postgapClocks = postgap; - phid->spaceClocks = space; - phid->zeroClocks = zero; - phid->oneClocks = one; + case PHIDUID_RFID_2OUTPUT_READ_WRITE: + //limit spaces to 64 clocks + if(pregap < (2) || pregap > (64)) return EPHIDGET_INVALIDARG; + if(space < (2) || space > (64)) return EPHIDGET_INVALIDARG; + if(postgap < (2) || postgap > (64)) return EPHIDGET_INVALIDARG; + //pulses can be up to 256 clocks + if(zero < (4) || zero > (128)) return EPHIDGET_INVALIDARG; + if(one < (4) || one > (128)) return EPHIDGET_INVALIDARG; + if(prepulse < (0) || prepulse > (255)) return EPHIDGET_INVALIDARG; + if(eof < (0) || eof > (255)) return EPHIDGET_INVALIDARG; + if(listenDuringEOF < (PFALSE) || listenDuringEOF > (PTRUE)) return EPHIDGET_INVALIDARG; - //Send timing - if((ret = CPhidgetRFID_makePacket(phid, buffer))) goto done2; - if((ret = CPhidgetRFID_sendpacket(phid, buffer))) goto done2; - - //send data - if((retval = sendRAWData(phid, data, bitlength))) goto done2; - - done2: - CThread_mutex_unlock(&phid->phid.writelock); - free(buffer); - if(ret) return ret; - } + if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG)) + return EPHIDGET_UNSUPPORTED;//TODO + else + { + unsigned char *buffer; + int ret = 0; + if(!(buffer = malloc(phid->phid.outputReportByteLength))) return EPHIDGET_NOMEMORY; + ZEROMEM(buffer, phid->phid.outputReportByteLength); + CThread_mutex_lock(&phid->phid.writelock); - return EPHIDGET_OK; -} + phid->pregapClocks = pregap; + phid->postgapClocks = postgap; + phid->spaceClocks = space; + phid->zeroClocks = zero; + phid->oneClocks = one; + phid->prepulseClocks = prepulse; + phid->eofpulseClocks = eof; + phid->listenDuringEOF = listenDuringEOF; -PHIDGET21_API int CCONV CPhidgetRFID_getRawData(CPhidgetRFIDHandle phid, int *data, int *dataLength) -{ - int i; - TESTPTR(phid) - TESTDEVICETYPE(PHIDCLASS_RFID) - TESTATTACHED + //Send timing + if((ret = CPhidgetRFID_makePacket(phid, buffer))) goto done2; + if((ret = CPhidgetRFID_sendpacket(phid, buffer))) goto done2; - //make sure length is even so we only send out data with starting space and ending pulse - if((*dataLength % 2) == 1) - (*dataLength)--; + //send data + if((retval = sendRAWData(phid, data, bitlength))) goto done2; - for(i=0;i<*dataLength;i++) - { - if(phid->userReadPtr == phid->dataWritePtr) - break; + done2: + CThread_mutex_unlock(&phid->phid.writelock); + free(buffer); + if(ret) return ret; + } - data[i] = phid->dataBuffer[phid->userReadPtr]; - phid->userReadPtr = (phid->userReadPtr + 1) & RFID_DATA_ARRAY_MASK; - } + return EPHIDGET_OK; - //make sure i is even so that we don't end with a pulse - if((i % 2) == 1) - { - //negate the pulse if we added it - i--; - phid->userReadPtr = (phid->userReadPtr - 1) & RFID_DATA_ARRAY_MASK; + default: + return EPHIDGET_UNSUPPORTED; } - - *dataLength = i; - - return EPHIDGET_OK; } -PHIDGET21_API int CCONV CPhidgetRFID_getTagOptions(CPhidgetRFIDHandle phid, char *tagString, CPhidgetRFID_TagOptionsHandle options) +PHIDGET21_API int CCONV CPhidgetRFID_getRawData(CPhidgetRFIDHandle phid, int *data, int *dataLength) { - int ret = EPHIDGET_OK, wait_return = 0; - CPhidgetRFID_TagList *trav = 0; - CPhidgetRFID_TagHandle tag = 0; - TESTPTRS(phid,tagString) - TESTPTR(options) + TESTPTR(phid) TESTDEVICETYPE(PHIDCLASS_RFID) TESTATTACHED - //1st find it in the list - not there? can't get options. - CThread_mutex_lock(&phid->tagthreadlock); - for (trav=phid->tagAdvancedList; trav; trav = trav->next) - { - if(!strcmp(trav->tag->tagString, tagString)) - tag = trav->tag; - } - if(!tag) - { - CThread_mutex_unlock(&phid->tagthreadlock); - return EPHIDGET_NOTFOUND; - } - - //Do we need to poll for the options? yes for Hitag - if(!tag->tagOptionsValid) +#ifdef RFID_RAWDATA_API_SUPPORT + switch(phid->phid.deviceUID) { - switch(tag->tagInfo.tagType) + case PHIDUID_RFID_2OUTPUT_READ_WRITE: { - case PHIDGET_RFID_TAG_HITAGS: - CThread_mutex_unlock(&phid->tagthreadlock); - - phid->respData = tag; - CThread_reset_event(&phid->respEvent); - HitagS_SELECT(phid, (unsigned char *)tagString); - - wait_return = CThread_wait_on_event(&phid->respEvent, 500); - switch (wait_return) { - case WAIT_TIMEOUT: - ret = EPHIDGET_TIMEOUT; - break; - case WAIT_OBJECT_0: - ret = phid->respStatus; - break; - default: - ret = EPHIDGET_UNEXPECTED; - break; - } - - CThread_reset_event(&phid->respEvent); - - CThread_mutex_lock(&phid->tagthreadlock); - break; - case PHIDGET_RFID_TAG_ISO11784: - break; - case PHIDGET_RFID_TAG_EM4102: - break; - default: - CThread_mutex_unlock(&phid->tagthreadlock); - return EPHIDGET_UNEXPECTED; - } - } - //copy over options - memcpy(options, &tag->tagOptions, sizeof(CPhidgetRFID_TagOptions)); - - CThread_mutex_unlock(&phid->tagthreadlock); - return ret; -} - -PHIDGET21_API int CCONV CPhidgetRFID_read(CPhidgetRFIDHandle phid, char *tagString, unsigned char *data, int *dataLength, char *password) -{ - int ret = EPHIDGET_OK, wait_return = 0, i; - CPhidgetRFID_TagList *trav = 0; - CPhidgetRFID_TagHandle tag = 0; - CPhidgetRFID_TagOptions options; - TESTPTRS(phid,tagString) - TESTPTR(data) - TESTDEVICETYPE(PHIDCLASS_RFID) - TESTATTACHED - - //1st find it in the list - not there? can't get options. - CThread_mutex_lock(&phid->tagthreadlock); - for (trav=phid->tagAdvancedList; trav; trav = trav->next) - { - if(!strcmp(trav->tag->tagString, tagString)) - tag = trav->tag; - } - if(!tag) - { - CThread_mutex_unlock(&phid->tagthreadlock); - return EPHIDGET_NOTFOUND; - } + int i; + //make sure length is even so we only send out data with starting space and ending pulse + if((*dataLength % 2) == 1) + (*dataLength)--; - switch(tag->tagInfo.tagType) - { - case PHIDGET_RFID_TAG_HITAGS: - if(tag->tagOptions.memSize == 32) + for(i=0;i<*dataLength;i++) { - ret = EPHIDGET_UNSUPPORTED; - break; - } - //Do we need to select the tag first? - if(!tag->tagOptionsValid) - { - CThread_mutex_unlock(&phid->tagthreadlock); - if((ret = CPhidgetRFID_getTagOptions(phid, tagString, &options))) - return ret; - CThread_mutex_lock(&phid->tagthreadlock); + if(phid->userReadPtr == phid->dataWritePtr) + break; + + data[i] = phid->dataBuffer[phid->userReadPtr]; + phid->userReadPtr = (phid->userReadPtr + 1) & RFID_DATA_ARRAY_MASK; } - //Now do the reads - if(!tag->tagDataValid) + //make sure i is even so that we don't end with a pulse + if((i % 2) == 1) { - CThread_mutex_unlock(&phid->tagthreadlock); - phid->respData = tag; - CThread_reset_event(&phid->respEvent); - //reading blocks - 4 pages/block, 32 bits/page - for(i=0;i<tag->tagOptions.memSize/32;i+=4) - { - HitagS_READ(phid, i, PTRUE); - - wait_return = CThread_wait_on_event(&phid->respEvent, 1000); - switch (wait_return) { - case WAIT_TIMEOUT: - return EPHIDGET_TIMEOUT; - case WAIT_OBJECT_0: - if((ret = phid->respStatus)) - return ret; - break; - default: - return EPHIDGET_UNEXPECTED; - } + //negate the pulse if we added it + i--; + phid->userReadPtr = (phid->userReadPtr - 1) & RFID_DATA_ARRAY_MASK; + } - CThread_reset_event(&phid->respEvent); - } + *dataLength = i; - CThread_mutex_lock(&phid->tagthreadlock); - } - //copy over data - ignore 1st 8 bytes, it's UID and configuration - //TODO: if Authentication is turned on, we lose even more space - if(*dataLength > tag->tagOptions.memSize/8 - 8) - *dataLength = tag->tagOptions.memSize/8 - 8; - memcpy(data, tag->tagData + 8, *dataLength); + return EPHIDGET_OK; + } - break; - case PHIDGET_RFID_TAG_ISO11784: - ret = EPHIDGET_UNSUPPORTED; - break; - case PHIDGET_RFID_TAG_EM4102: - ret = EPHIDGET_UNSUPPORTED; - break; default: - ret = EPHIDGET_UNEXPECTED; - break; + return EPHIDGET_UNSUPPORTED; } - - CThread_mutex_unlock(&phid->tagthreadlock); - return ret; +#else + return EPHIDGET_UNSUPPORTED; +#endif } -PHIDGET21_API int CCONV CPhidgetRFID_write(CPhidgetRFIDHandle phid, char *tagString, unsigned char *data, int dataLength, int offset, char *password) +PHIDGET21_API int CCONV CPhidgetRFID_write(CPhidgetRFIDHandle phid, char *tagString, CPhidgetRFID_Protocol protocol, int lock) { - int ret = EPHIDGET_OK, wait_return = 0, i, writePage, writeSize; - CPhidgetRFID_TagList *trav = 0; - CPhidgetRFID_TagHandle tag = 0; - CPhidgetRFID_TagOptions options; - unsigned char readData[256]; - int readDataSize = 256; - TESTPTRS(phid,tagString) - TESTPTR(data) + int ret = EPHIDGET_OK; + char newVal[50]; + TESTPTRS(phid,tagString) TESTDEVICETYPE(PHIDCLASS_RFID) TESTATTACHED - //1st find it in the list - not there? can't get options. - CThread_mutex_lock(&phid->tagthreadlock); - for (trav=phid->tagAdvancedList; trav; trav = trav->next) - { - if(!strcmp(trav->tag->tagString, tagString)) - tag = trav->tag; - } - if(!tag) - { - CThread_mutex_unlock(&phid->tagthreadlock); - return EPHIDGET_NOTFOUND; - } - - switch(tag->tagInfo.tagType) + switch(phid->phid.deviceUID) { - case PHIDGET_RFID_TAG_HITAGS: + case PHIDUID_RFID_2OUTPUT_READ_WRITE: + if(protocol < (PHIDGET_RFID_PROTOCOL_EM4100) || protocol > (PHIDGET_RFID_PROTOCOL_PHIDGETS)) + return EPHIDGET_INVALIDARG; + if(lock < (PFALSE) || lock > (PTRUE)) + return EPHIDGET_INVALIDARG; - if(tag->tagOptions.memSize == 32) + if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG)) { - ret = EPHIDGET_UNSUPPORTED; - break; + sprintf(newVal, "%d/%d/%s", protocol, lock, tagString); + ADDNETWORKKEY(WriteTag, "%s", remoteWrite); } - //Do we need to select the tag first? - if(!tag->tagOptionsValid) + else { + CThread_mutex_lock(&phid->tagthreadlock); + ret = T5577_WriteTag(phid, protocol, tagString, lock); CThread_mutex_unlock(&phid->tagthreadlock); - if((ret = CPhidgetRFID_getTagOptions(phid, tagString, &options))) + if(ret != EPHIDGET_OK) return ret; - CThread_mutex_lock(&phid->tagthreadlock); - } - - if(offset+dataLength > (tag->tagOptions.memSize/8)-8) - return EPHIDGET_INVALIDARG; - - //Need to read in the tag first - CThread_mutex_unlock(&phid->tagthreadlock); - if((ret = CPhidgetRFID_read(phid, tagString, readData, &readDataSize, password))) - return ret; - CThread_mutex_lock(&phid->tagthreadlock); - - //Now do the writes - CThread_mutex_unlock(&phid->tagthreadlock); - phid->respData = tag; - CThread_reset_event(&phid->respEvent); - - //need to start the write on a page border - //these are in pages (4 bytes) - writePage = offset/4; - writeSize = dataLength/4 + (dataLength%4 ? 1 : 0) + offset%4; - - //replace what the user wants to write - memcpy(readData+offset, data, dataLength); - - for(i=writePage;i<writePage+writeSize;i+=(i%4 ? i%4 : 4)) - { - HitagS_WRITE(phid, i, readData+i, PTRUE); - - wait_return = CThread_wait_on_event(&phid->respEvent, 500); - switch (wait_return) { - case WAIT_TIMEOUT: - return EPHIDGET_TIMEOUT; - case WAIT_OBJECT_0: - if((ret = phid->respStatus)) - return ret; - break; - default: - return EPHIDGET_UNEXPECTED; - } - - CThread_reset_event(&phid->respEvent); + return waitForTag(phid, tagString, 500); } - CThread_mutex_lock(&phid->tagthreadlock); - - break; - case PHIDGET_RFID_TAG_ISO11784: - ret = EPHIDGET_UNSUPPORTED; - break; - case PHIDGET_RFID_TAG_EM4102: - ret = EPHIDGET_UNSUPPORTED; break; + default: - ret = EPHIDGET_UNEXPECTED; - break; + return EPHIDGET_UNSUPPORTED; } - CThread_mutex_unlock(&phid->tagthreadlock); - return ret; + return EPHIDGET_OK; } // === Deprecated Functions === // +CFHANDLE(RFID, Tag, unsigned char *) +CFHANDLE(RFID, TagLost, unsigned char *) CGET(RFID,NumOutputs,int) return CPhidgetRFID_getOutputCount(phid, pVal); } +CGET(RFID, LastTag, unsigned char) + int ret = EPHIDGET_OK; + TESTPTRS(phid,pVal) + TESTDEVICETYPE(PHIDCLASS_RFID) + TESTATTACHED + + //This function only work if the last tag was EM4100 + CThread_mutex_lock(&phid->tagthreadlock); + if(phid->lastTagValid) + { + if(phid->lastTag.protocol == PHIDGET_RFID_PROTOCOL_EM4100) + memcpy(pVal, phid->lastTag.tagData, 5); + else + ret = EPHIDGET_UNSUPPORTED; //unsupported for the protocol of the last tag + } + else + ret = EPHIDGET_UNKNOWNVAL; + CThread_mutex_unlock(&phid->tagthreadlock); + + return ret; +} |