Author Topic: RF card encoder with RS232 interface ( CP210x USB to UART bridge sil com lab)  (Read 19222 times)

hiramlight

  • Member
  • ***
  • Posts: 4
Hello,

I developed an Hotel Room management system (VB>NET). Up to now I was using dllImports to integrate electronic key door system , but this time I would like to connect directly to encoder interface.
the encoder use a USB to UART driver ( I get the latest drivers from sil lab ) and it work good ( OS
 is win 7) , Also this is my first time working on serialCom .

I build a test application to connect to the com port but I am not sure that I am even connecting to the encoder.

I use the Advanced serial Monitor port to comapre , what my test RS 232 code is sending (TX) and what my other test app ( using the  manufacture dll through dllImport) is sending .
The dllImport test app is adding some charaters in the string who just dont make sens to me .
the doc coming with the encoder aspecify this data structure:

Data Format
Data format: 1 start bit, 1 end bit, 8 data bits, no verification; The communication rate is from 2400bps to 19200bps.
Control Character
STX (0x02): Tag the beginning of the data.
ETX (0x03): Tag the end of the data.

Information Format
Information format: <STX>ddssff[data]<ETX>cc
When the receiving end gets the information complying with the above format, it will respond with “ACK” if the calculated verification is same as the received verification. Otherwise, it will respond with “NAK”.

Information Field   Description
dd   Destination address, target (client) address
ss   Source address which tags the information source
ff   Command or answer code
[data]   Data region (optional)

Check character:   2-byte;
Algorithm: Use 0x00 as the seed to do XOR with all the data after STX. The result of each XOR will be used as the new seed for the next XOR. The final 1-byte result will be transformed into a 2-byte hexadecimal ASCII code.
Example:
STX   0x30   0x39   0x52   ETX   C1   C2

First calculation:             0x00 XOR 0x30 = 0x30
Second calculation:          0x30 XOR 0x39 = 0x09
Third calculation:            0x09 XOR 0x52 = 0x5B
Forth calculation:            0x5B XOR 0x03 = 0x58
Verification code of the first byte (C1):        0x5 ->ASCII 5 = 0x35
Verification code of the second byte (C2):     0x8 ->ASCII 8 = 0x38

and my test is : <STX>0103E<ETX>CC

//////
Card Verification/Guest Card Reading Command
Command code: (E).
This command is used to read the information in guest card and search the card’s information in the database. If the search is successful, relative information (R, N, D and O) will be fed back. Example as follows:
PMS: <STX>0103E<ETX>CC
AIS: <ACK>
AIS: <STX>03010<RS>R101<RS>NDuck<RS>D200212201200<RS>O200212302100<ETX>CC
PMS: <ACK>
/////////////

this is what the serial port monitore show:

<20110405141219.100 SYS>
COM port is opened
<20110405141219.100 SYS>
Purge the serial port: RXCLEAR, TXCLEAR
<20110405141219.100 SYS>
Baud rate 9600
<20110405141219.100 SYS>
RTS off
<20110405141219.100 SYS>
DTR off
<20110405141219.100 SYS>
Data bits=8, Stop bits=1, Parity=None
<20110405141219.100 SYS>
Set chars: Eof=0x00, Error=0x00, Break=0x00, Event=0x00, Xon=0x11, Xoff=0x13
<20110405141219.100 SYS>
Handflow: ControlHandShake=(), FlowReplace=(), XonLimit=2048, XoffLimit=512
<20110405141219.100 SYS>
In/out queue size 512/512
<20110405141219.100 SYS>
Set timeouts: ReadInterval=100, ReadTotalTimeoutMultiplier=2000, ReadTotalTimeoutConstant=2000, WriteTotalTimeoutMultiplier=0, WriteTotalTimeoutConstant=0
<20110405141219.100 SYS>
Purge the serial port: RXCLEAR, TXCLEAR
<20110405141219.100 TX>
<STX>103E<ETX>74
<20110405141231.163 SYS>
COM port is closed

and this is the dllimport test show , sending the same query:


IOCTL_SERIAL_SET_DTR: Set DTR

000031: I/O Request (UP), 29.03.2011 16:47:51.075 +0.0
IOCTL_SERIAL_SET_DTR: Set DTR

000032: I/O Request (DOWN), 29.03.2011 16:47:51.075 +0.0
IOCTL_SERIAL_SET_LINE_CONTROL: Set line control
  WordLength=8
  StopBits=1 stop bit
  Parity=No parity
000033: I/O Request (UP), 29.03.2011 16:47:51.090 +0.015
IOCTL_SERIAL_SET_LINE_CONTROL: Set line control

000034: I/O Request (DOWN), 29.03.2011 16:47:51.090 +0.0
IOCTL_SERIAL_SET_CHARS: Set special characters
  EofChar=0x0
  ErrorChar=0x0
  BreakChar=0x0
  EventChar=0x0
  XonChar=0x11
  XoffChar=0x13
000035: I/O Request (UP), 29.03.2011 16:47:51.090 +0.0
IOCTL_SERIAL_SET_CHARS: Set special characters

000036: I/O Request (DOWN), 29.03.2011 16:47:51.090 +0.0
IOCTL_SERIAL_SET_HANDFLOW: Set handshake information
  ControlHandShake=1
  FlowReplace=0
  XonLimit=28672
  XoffLimit=7168

000037: I/O Request (UP), 29.03.2011 16:47:51.090 +0.0
IOCTL_SERIAL_SET_HANDFLOW: Set handshake information

000040: I/O Request (DOWN), 29.03.2011 16:47:51.090 +0.0
IOCTL_SERIAL_SET_TIMEOUTS: Set timeouts
  ReadIntervalTimeout=4294967295  >>> when I try to put this value I get an error in my 232 class
  ReadTotalTimeoutMultiplier=0
  ReadTotalTimeoutConstant=0
  WriteTotalTimeoutMultiplier=0
  WriteTotalTimeoutConstant=5000

000041: I/O Request (UP), 29.03.2011 16:47:51.090 +0.0
IOCTL_SERIAL_SET_TIMEOUTS: Set timeouts

000042: I/O Request (DOWN), 29.03.2011 16:47:51.090 +0.0
IOCTL_SERIAL_PURGE: Purge requests
  Purge mask=TXABORT: Read requests, RXABORT: Receive buffer, TXCLEAR: Write requests, RXCLEAR: Write buffer

000043: I/O Request (UP), 29.03.2011 16:47:51.090 +0.0
IOCTL_SERIAL_PURGE: Purge requests

000044: Write Request (DOWN), 29.03.2011 16:47:51.090 +0.0
Buffer size: 0x16 bytes
 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 7E   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~
 FF 00 DF 0B 17 7E                                 ÿ.ß..~


000049: Read Request (UP), 29.03.2011 16:47:51.121 +0.0
Buffer size: 0x1 bytes
Status: 0x00000000
 7E                                                ~

000053: Read Request (UP), 29.03.2011 16:47:51.121 +0.0
Buffer size: 0x1 bytes
Status: 0x00000000
 00                                                .

000057: Read Request (UP), 29.03.2011 16:47:51.121 +0.0
Buffer size: 0x1 bytes
Status: 0x00000000
 00                                                .


etc.....
There is many additional characteres who dont make sens to me the  why all  the ""FF""  and also the translation show 7E                                 ÿ.ß..~... what does that mean ...? when my rs232 code show this as hex value:

WriteTotalTimeoutConstant=100 103E74COM port is close

when compare with a serial monitor

( using dllimport and the encodoer dll)
00000129   24.03.2011 19:52:25.419   +0.0   IRP_MJ_DEVICECONTROL: IOCTL_SERIAL_SET_TIMEOUTS   UP   0x00000000      
00000130   24.03.2011 19:52:25.419   +0.0   IRP_MJ_WRITE   DOWN   0x00000000   7e ff 03 80 31 85 02 00 63 5b e0 7e    ~...1...c[.~


(using my ES232 test app)
00000049   24.03.2011 20:20:36.259   +0.006   IRP_MJ_DEVICECONTROL: IOCTL_SERIAL_PURGE   UP   0x00000000      
00000050   24.03.2011 20:20:48.354   +12.094   IRP_MJ_WRITE   DOWN   0x00000000   3c 45 54 58 3e 31 3c 45 4e 51 3e 3c 4e 55 4c 3e    <ETX>1<ENQ><NUL>


with the mfct dll the bytes translate to those funny characters ""~...1...c[.~""  when I run the same command in my test app the bytes show in char that we can read ""<ETX>1<ENQ><NUL>""  so am I  doing something wrong in the  convert function

this is my first posting on this board so I hope that I didn't exceed the lenght and I will be happy to attached any piece of code or doc that I have and who are needed to resolve this .
Sincerely,


alan
« Last Edit: April 05, 2011, 06:55:53 am by hiramlight »

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Let me see if I understand.

In both cases, the RF encoder connects to a PC via a SiLabs USB/serial-port adapter?

The original system used a DLL and its API to access the encoder, and now you want to do so directly by reading and writing to the USB virtual serial port?

So you're trying to reverse engineer the protocols by monitoring the traffic?

"dllimport test" is a test application provided by the vendor?

The "serial port monitor" data shows the traffic when you run "dllimport test"?

The port is closed after the purge request?

Jan

hiramlight

  • Member
  • ***
  • Posts: 4
Hello Jan ,

I am not trying to reverse engineering anything, encoder come usually with their own software ... limited in scope and sometime not so stable like orbita for exemple ... their software are memory leak and after a while just lock the system .


In The application that I built  , rooms and floors are in graphical display, ledger and accounting areinclude as well as a trnsparent online booking system , but since hotels are using different key card encoder system  ( like orbita, mifare 2 of the most used ) I was using the their api ( C++ build dll) . RMS being a .net app using dllimport was by the only way I could integret their API .

I got a document from Mifare showing the dta structutre if i wanted to use rs232 to directly talk to the encoder , I tought that if I could do that it would be more stable and since most encoder use the same format and  only data that you are passing is different  it would make for a better more stable app. also I could then work with any encoder ... with some company it is very difficult to get doc or API.

I attached the rs 232 doc and the Api from Orbita .

I monitore the traffic from my test app using dllImport because I build the test app ( using rs232 call) by following the doc from Mifare and dont get the result that I expect it .. so like I put in my first post .. I try to understand what did I do wrong .

====================

In both cases, the RF encoder connects to a PC via a SiLabs USB/serial-port adapter?  > Correct

The original system used a DLL and its API to access the encoder, and now you want to do so directly by reading and writing to the USB virtual serial port?  > correct


So you're trying to reverse engineer the protocols by monitoring the traffic? > not to sure what you meant by reverse eng .. but no I followed the doc that I  got from the encoder cpy  ( attached to this post)


"dllimport test" is a test application provided by the vendor?  > nope I build it ib VB.NET using the dll and doc provider by vendor

for ex:
3. Read Card Number, if success, return 0

int     (*GetCardNumber)(int ComNumber,int* CardNumber) ;
Explain:
ComNumber, the comport to connect the encoder.
CardNumber, Card number will be return from the parameter “CardNumber”. 



become in my test app:

    <DllImport("akey/HUNERF.DLL", EntryPoint:="GetCardNumber")> _
         Public Shared Function GetCardNumber(ByVal comport As Integer, ByRef CardNumber As IntPtr) As IntPtr
    End Function

The "serial port monitor" data shows the traffic when you run "dllimport test"?  >> it show both , the first sample show traffic from my test app using the RS 232 test app and end:
<20110405141219.100 TX>
<STX>103E<ETX>74
<20110405141231.163 SYS>
COM port is closed



the second when using the second test app and  dll import :
000044: Write Request (DOWN), 29.03.2011 16:47:51.090 +0.0
Buffer size: 0x16 bytes
 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 7E   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~
 FF 00 DF 0B 17 7E                                 ÿ.ß..~

 and like I put in my post what really baffle me is the difference :

what those meant ...?? ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~
 FF 00 DF 0B 17 7E                                 ÿ.ß..~

I known thos are the byte values FF 00 DF 0B 17 7E, but this ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~   or ÿ.ß..~ , when following the rs232 doc my string look like this: 100 103E74COM



I got 2 encoder I can trest with a Mifare and an Orbita and got the same problem with both .. I can send you some traffic from the orbit a next if you like ... but look preety much the same .

I though that the function that I build to go from ASCII char to byte and XOR the dta was correct ...but maybe not

wha
  
Alan  


[attachment deleted by admin]
« Last Edit: April 06, 2011, 02:21:34 am by hiramlight »

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
In your Write Request, it looks like you're sending 16 bytes: 15 FFh followed by one 7Eh. Assuming that's not what you intended to send, I would start by looking at how you declare and store data in the buffer.

Jan

hiramlight

  • Member
  • ***
  • Posts: 4
Hello Jan ,

I use an RS 232 class from a sample app that I found on the internet ( please find attached)

then I call a funcion to convert the ASCII command to byte :

I declare CMD as global variable forthe test
and idxsent as in integer


/*
    Target : Points to a byte Array big enough to hold the command
    CMD    : Points to a character Array with the command NULL terminated
    Return : length of the Target Command to send to the remote Device
*/

I wanted CMD to "point" to a string ie :  Dim enComd As String = "0103E"
Note: My call is expecting a pointer to the string, not the actual string.  
In the case of the CMD, this could just be the string as its not changed.
In the case of Target it needs to point to the target as it gets updated.


  Dim comhold As New rs232 'class that handles the com port connections
  Dim hexconv As hexconv = New hexconv  ' class that handle convertion to bytes and XON
  Dim myTestByte(X) As Byte
  CMD = "103E"
  idxsent = hexconv.FormatCommand_MifareByte(myTestByte, Encoder)

===============================

   Public Function FormatCommand_Mifare(ByVal Target() As Byte, ByVal ENC As Integer) As Integer

        ' Encoder= 2

        'Mifare string

        'common char & byte
        Dim STX As Byte = &H2
        Dim ECT As Byte = &H3
        Dim ENQ As Byte = &H5
        Dim ACK As Byte = &H6
        Dim NAK As Byte = &H15
        Dim RS As Byte = &H1E
        Dim Idx As Integer = 0
        Dim [Loop] As Integer
        Dim CC As New Byte()

      
        ' Move STX into array
        Target(Idx) = STX
        Idx += 1


        ' Move "user" command into array
        For [Loop] = 0 To CMD.Length - 1
            Target(Idx) = CByte(AscW(CMD([Loop])))
            Idx += 1
        Next [Loop]


        ' Move ECT into array
        Target(Idx) = ECT
        Idx += 1


        ' Calc CC : XOR all bytes (seed with 0) execpt the first byte
        CC = 0
        [Loop] = 1
        Do While [Loop] < Idx
            CC = CC Xor Target([Loop])
            [Loop] += 1
        Loop

        ' Get CC high nibble and convert to hex/ascii
        If (CC >> 4) > 9 Then
            Target(Idx) = CByte(AscW("A"c) + (CC >> 4))
            Idx += 1
        Else
            Target(Idx) = CByte(AscW("0"c) + (CC >> 4))
            Idx += 1
        End If

        ' Get CC low nibble and convert to hex/ascii
        If (CC And &HF) > 9 Then
            Target(Idx) = CByte(AscW("A"c) + (CC And &HF))
            Idx += 1
        Else
            Target(Idx) = CByte(AscW("0"c) + (CC And &HF))
            Idx += 1
        End If

        Return Idx

    End Function

==================================

then call the write command

            comhold.Write(myTestByte)
            txtRX.Text = comhold.Read(idxsent).ToString


////

but to come back to your question , this example :

000044: Write Request (DOWN), 29.03.2011 16:47:51.090 +0.0
Buffer size: 0x16 bytes
 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 7E   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~
 FF 00 DF 0B 17 7E                                 ÿ.ß..~

000049: Read Request (UP), 29.03.2011 16:47:51.121 +0.0
Buffer size: 0x1 bytes
Status: 0x00000000
 7E        


is coming from the test app using dllimport and it is working well, this what I would like to achive using my RS232 class test app

Read Request (UP) meant we are reading a reply from the encoder, since we have a total of 6 request read.. correct ..?I didn't put them all for the sake of lenght ..

here I send a different string <ETX>1<ENQ><NUL> instead <STX>0103E<ETX> but it doesn't really matter what string that I send the formatting seem off.

From the DLL Import test
/////////
00000033   24.03.2011 19:52:19.471   +0.0   IRP_MJ_DEVICECONTROL: IOCTL_SERIAL_SET_TIMEOUTS   UP   0x00000000      
00000034   24.03.2011 19:52:19.471   +0.0   IRP_MJ_WRITE   DOWN   0x00000000   7e ff 03 80 31 05 00 67 32 7e    ~...1..g2~
00000037   24.03.2011 19:52:19.605   +0.133   IRP_MJ_READ   UP   0x00000000   7e    ~
00000039   24.03.2011 19:52:19.606   +0.001   IRP_MJ_READ   UP   0x00000000   ff    .
00000041   24.03.2011 19:52:19.607   +0.001   IRP_MJ_READ   UP   0x00000000   03    .
00000043   24.03.2011 19:52:19.608   +0.001   IRP_MJ_READ   UP   0x00000000   80


/////////////////////////////

from the rs232 class test app
/////////
00000048   24.03.2011 20:20:36.253   +57.433   IRP_MJ_DEVICECONTROL: IOCTL_SERIAL_PURGE   DOWN   0x00000000   0c 00 00 00    ....
00000049   24.03.2011 20:20:36.259   +0.006   IRP_MJ_DEVICECONTROL: IOCTL_SERIAL_PURGE   UP   0x00000000      
00000050   24.03.2011 20:20:48.354   +12.094   IRP_MJ_WRITE   DOWN   0x00000000   3c 45 54 58 3e 31 3c 45 4e 51 3e 3c 4e 55 4c 3e    <ETX>1<ENQ><NUL>

then the port closed no IRP_MJ_READ   UP so no reply from the encoder.

////////

Also I come accross "Any Serial Port". Did you ever use that application ..? can it be an  option for me to look at ...?

Thank's for taking the time to help...

Alan


[attachment deleted by admin]
« Last Edit: April 07, 2011, 12:34:15 am by hiramlight »

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
If you have working code in your dllimport example, why are you trying to do it in a different way? It's possible you've explained this already, but please refresh my memory.

Jan


hiramlight

  • Member
  • ***
  • Posts: 4
Hello Jan,

I am working with 2 encoder an orbita and a Mifare, I only got the dll instruction for Orbita ( with the dll) so I was able to build a com module using dllImport... No such luck with the Mifare and I look around to other cpy who sale the same encoder type , but most are chinese and i didn't get any reply ... I think just interested in selling harware and in any cases the 2 cpy that I find selling the same type of encoder didn't even bother to reply to my emails as mention it above .... the only doc I got is RS232 spec that I load in my previous email.

I am not formating my command string correctly, when I resolve this .. I think it be light at the end of the tunnel ...

thank's

Alan

PS: Apology for the tardy reply, had to go On Site for a week and didn't see that you replied until I came back .... somehow I miss the email from LVR
« Last Edit: April 19, 2011, 01:07:44 am by hiramlight »