===== MSR Test Application ===== [[MSR 정보]] Driver Header file #ifndef __MMD1100_H__ #define __MMD1100_H__ #include /* types */ #define DEVICE_MMD1100 "/dev/ttyS5" #define MMD1100_DEFAULT_BAUDRATE 9600 //#define MMD1100_DEFAULT_BAUDRATE 19200 //#define MMD1100_DEFAULT_BAUDRATE 38400 //#define MMD1100_DEFAULT_BAUDRATE 57600 //#define MMD1100_DEFAULT_BAUDRATE 115200 #define MMD1100_TIMEOUT_BETWEEN_SERIAL_INPUT_DATA 20 /*20 msec*/ typedef enum { MMD1100_COMMAND_GET_VERSION = 0, MMD1100_COMMAND_LOAD_USER_PARAMETERS, MMD1100_COMMAND_UART_CALIBRATION, MMD1100_COMMAND_OTP_WRITE, MMD1100_COMMAND_GET_STATUS, MMD1100_COMMAND_READ_DATA_RETRY, MMD1100_COMMAND_SOFTWARE_RESET } MMD1100_Command_t; typedef struct { /* */ uint8_t ErrorCodeForTrack1; uint8_t ErrorCodeForTrack2; uint8_t ErrorCodeForTrack3; /* */ uint8_t LengthOfTrack1; uint8_t LengthOfTrack2; uint8_t LengthOfTrack3; /* ISO7813 */ uint8_t pTrack1[79 * 2]; uint8_t pTrack2[40 * 2]; uint8_t pTrack3[107 * 2]; /* */ uint8_t LengthOfRaw1; uint8_t LengthOfRaw2; uint8_t LengthOfRaw3; uint8_t pRaw1[79 * 2]; uint8_t pRaw2[40 * 2]; uint8_t pRaw3[107 * 2]; } MSRTrack_t; typedef struct { MMD1100_Command_t Command; uint8_t ErrorCode; uint8_t pData[100]; } MMD1100Response_t; /* open serial device for cummunication with MMD1100 return: -1: Fail to operation -2: Input Paramters Error 0: OK */ extern int mmd1100_open(int *pDeviceFileDescriptor); /* close serial device for end of cummunication with MMD1100 return: -1: Fail to operation 0: OK */ extern int mmd1100_close(void); /* serial buffer flush for cummunication with MMD1100 */ extern void mmd1100_serial_flush(void); /* get serial device file descriptor for cummunication with MMD1100 return: -1: Fail to operation -2: Input Paramters Error 0: OK */ extern int mmd1100_get_device_file_descriptor(int *pDeviceFileDescriptor); /* receive return: -1: Fail to operation -2: Input Parameter Error -4: Timeout or Not Ready 0: OK */ extern int mmd1100_receive(MSRTrack_t *pMSRTrack, MMD1100Response_t *pResponse, uint32_t *pIsNotTrack, uint32_t ResponseTimeout); /* -1: invalid parameter 0 : OK */ extern int mmd1100_make_packet(uint8_t *pPacket, uint32_t *pMakedPacketByteLength, MMD1100_Command_t Command, uint8_t pArguments[4]); /* -1: invalid parameter -2: send error 0 : Not open + : Send length */ extern int mmd1100_send(uint8_t *pPacket, uint8_t PacketByteLength); #endif /* __MMD1100_H__ */ Driver Source File #include /* types */ #include /* printf */ #include /* memcpy, strlen... */ #include /* struct termios */ #include /* for open/close .. */ #include /* for O_RDWR */ #include /* for ioctl */ #include /* struct pollfd */ #include /* struct timespec */ #include "CRC_LRC.h" /* lrc_xor() */ #include "MemoryControl.h" /* memory_pick_up_bit() */ #include "MMD1100.h" /* */ #define MMD1100_DEBUG(fmt, args ...) printf("DEBUG:%s(%d): " fmt, __FUNCTION__,__LINE__, ## args) #define MMD1100_ERROR(fmt, args ...) printf("ERROR:%s(%d): " fmt, __FUNCTION__,__LINE__, ## args) #define MMD1100_INFO(fmt, args ...) printf("INFOs:%s(%d): " fmt, __FUNCTION__,__LINE__, ## args) #define MMD1100_BYTE_SIZE_OF_BUFFER_FOR_SERIAL 512 #define MMD1100_BYTE_SIZE_OF_BUFFER_FOR_PACKET 1024 #define MMD1100_PACKET_POSITION_STX 0 #define MMD1100_PACKET_POSITION_CLASS 1 #define MMD1100_PACKET_POSITION_FUNCTION 2 #define MMD1100_PACKET_POSITION_LENGTH 3 #define MMD1100_PACKET_POSITION_STATUS 4 #define MMD1100_PACKET_POSITION_DATA_START 5 #define MMD1100_PACKET_POSITION_TRACK_ID 2 #define MMD1100_DEFINE_STX 0x02 #define MMD1100_DEFINE_ETX 0x03 #define MMD1100_DEFINE_TRACK_DATA 0x33 #define MMD1100_DEFINE_TRACK_ID_1 0x25 //#define MMD1100_DEFINE_TRACK_ID_2 0x3F //#define MMD1100_DEFINE_TRACK_ID_3 0x5E #define MMD1100_DEFINE_TRACK_ID_2 0x5E /*Bug Fix*/ #define MMD1100_DEFINE_TRACK_ID_3 0x3F /*Bug Fix*/ #define MMD1100_DEFINE_ACK 0x06 #define MMD1100_DEFINE_NAK 0x15 #define MMD1100_COMMAND_CLASS_GET_VERSION 0x10 #define MMD1100_COMMAND_CLASS_LOAD_USER_PARAMETERS 0x12 #define MMD1100_COMMAND_CLASS_UART_CALIBRATION 0x13 #define MMD1100_COMMAND_CLASS_OTP_WRITE 0x15 #define MMD1100_COMMAND_CLASS_GET_STATUS 0x16 #define MMD1100_COMMAND_CLASS_READ_DATA_RETRY 0x17 #define MMD1100_COMMAND_CLASS_SOFTWARE_RESET 0x18 #define MMD1100_COMMAND_FUNCTION_GET_VERSION 0x31 #define MMD1100_COMMAND_FUNCTION_LOAD_USER_PARAMETERS 0x31 #define MMD1100_COMMAND_FUNCTION_UART_CALIBRATION 0x31 #define MMD1100_COMMAND_FUNCTION_OTP_WRITE 0x33 #define MMD1100_COMMAND_FUNCTION_GET_STATUS 0x31 #define MMD1100_COMMAND_FUNCTION_READ_DATA_RETRY 0x31 #define MMD1100_COMMAND_FUNCTION_SOFTWARE_RESET 0x31 #define MMD1100_COMMAND_LENGTH_GET_VERSION 0x00 #define MMD1100_COMMAND_LENGTH_LOAD_USER_PARAMETERS 0x04 #define MMD1100_COMMAND_LENGTH_UART_CALIBRATION 0x05 #define MMD1100_COMMAND_LENGTH_OTP_WRITE 0x00 #define MMD1100_COMMAND_LENGTH_GET_STATUS 0x00 #define MMD1100_COMMAND_LENGTH_READ_DATA_RETRY 0x00 #define MMD1100_COMMAND_LENGTH_SOFTWARE_RESET 0x00 #define MMD1100_RESPONSE_ACK_LENGTH_GET_VERSION 0x10 #define MMD1100_RESPONSE_ACK_LENGTH_LOAD_USER_PARAMETERS 0x04 #define MMD1100_RESPONSE_ACK_LENGTH_UART_CALIBRATION 0x01 #define MMD1100_RESPONSE_ACK_LENGTH_OTP_WRITE 0x01 #define MMD1100_RESPONSE_ACK_LENGTH_GET_STATUS 0x06 #define MMD1100_RESPONSE_NAK_LENGTH 0x01 typedef enum { MMD1100_PACKET_CHECK_STATE_STX = 0, MMD1100_PACKET_CHECK_STATE_MODE_CLASS, MMD1100_PACKET_CHECK_STATE_TRACK_ID, MMD1100_PACKET_CHECK_STATE_TRACK_LENGTH, MMD1100_PACKET_CHECK_STATE_TRACK_STATE, MMD1100_PACKET_CHECK_STATE_TRACK_DATA, MMD1100_PACKET_CHECK_STATE_FUNCTION, MMD1100_PACKET_CHECK_STATE_LENGTH, MMD1100_PACKET_CHECK_STATE_STATUS, MMD1100_PACKET_CHECK_STATE_DATA, MMD1100_PACKET_CHECK_STATE_ETX, MMD1100_PACKET_CHECK_STATE_BCC } MMD1100PacketCheckState_t; typedef struct { /* Device File Descriptor */ int Device; struct termios BackupTerminalInfo; /* Serial Receive Buffer */ uint8_t pBufferForSerial[MMD1100_BYTE_SIZE_OF_BUFFER_FOR_SERIAL]; uint32_t HeadPointerForSerial; uint32_t TailPointerForSerial; /* Received Packet Buffer */ uint8_t pBufferForPacket[MMD1100_BYTE_SIZE_OF_BUFFER_FOR_PACKET]; uint32_t PacketOffset; MMD1100PacketCheckState_t PacketCheckState; uint32_t DataLengthInPacket; uint32_t PacketLength; } MMD1100context_t; static MMD1100context_t MMD1100context = { /* Device File Descriptor */ .Device = -1, /* struct termios BackupTerminalInfo*/ /* Serial Receive Buffer */ .pBufferForSerial = {0}, .HeadPointerForSerial = 0, .TailPointerForSerial = 0, /* Received Packet Buffer */ .pBufferForPacket = {0}, .PacketOffset = 0, .PacketCheckState = MMD1100_PACKET_CHECK_STATE_STX, .DataLengthInPacket = 0, .PacketLength = 0 }; /* 5 bit (Data + Parity) ANSI/ISO BCD Data Format convert to 8 bit ASCII */ static const uint8_t pDataFormatTableForISO_BCD[] = { /* 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 */ ' ', '1', '2', ' ', '4', ' ', ' ', '7', /* 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F */ '8', ' ', ' ', ';', ' ', '=', '>', ' ', /* 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 */ '0', ' ', ' ', '3', ' ', '5', '6', ' ', /* 0x18 0x19 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F */ ' ', '9', ':', ' ', '<', ' ', ' ', '?' }; /* 7 bit (Data + Parity) ANSI/ISO ALPHA Data Format convert to 8 bit ASCII */ static const uint8_t pDataFormatTableForISO_ALPHA[] = { /* 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 */ 0x00, '!', '"', 0x00, '$', 0x00, 0x00, '\'', /* 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F */ '(', 0x00, 0x00, '+', 0x00, '-', '.', 0x00, /* 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 */ '0', 0x00, 0x00, '3', 0x00, '5', '6', 0x00, /* 0x18 0x19 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F */ 0x00, '9', ':', 0x00, '<', 0x00, 0x00, '?', /* 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 */ '@', 0x00, 0x00, 'C', 0x00, 'E', 'F', 0x00, /* 0x28 0x29 0x2A 0x2B 0x2C 0x2D 0x2E 0x2F */ 0x00, 'I', 'J', 0x00, 'L', 0x00, 0x00, 'O', /* 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 */ 0x00, 'Q', 'R', 0x00, 'T', 0x00, 0x00, 'W', /* 0x38 0x39 0x3A 0x3B 0x3C 0x3D 0x3E 0x3F */ 'X', 0x00, 0x00, '[', 0x00, 'D', '^', 0x00, /* 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 */ ' ', 0x00, 0x00, '#', 0x00, '%', '&', 0x00, /* 0x48 0x49 0x4A 0x4B 0x4C 0x4D 0x4E 0x4F */ 0x00, ')', '*', 0x00, ',', 0x00, 0x00, '/', /* 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 */ 0x00, '1', '2', 0x00, '4', 0x00, 0x00, '7', /* 0x58 0x59 0x5A 0x5B 0x5C 0x5D 0x5E 0x5F */ '8', 0x00, 0x00, 0x00, 0x00, '=', '>', 0x00, /* 0x60 0x61 0x62 0x63 0x64 0x65 0x66 0x67 */ 0x00, 'A', 'B', 0x00, 'D', 0x00, 0x00, 'G', /* 0x68 0x69 0x6A 0x6B 0x6C 0x6D 0x6E 0x6F */ 'H', 0x00, 0x00, 'K', 0x00, 'M', 'N', 0x00, /* 0x70 0x71 0x72 0x73 0x74 0x75 0x76 0x77 */ 'P', 0x00, 0x00, 'S', 0x00, 'U', 'V', 0x00, /* 0x78 0x79 0x7A 0x7B 0x7C 0x7D 0x7E 0x7F */ 0x00, 'Y', 'Z', 0x00, '\\', 0x00, 0x00, '_' }; static int mmd100_convert_rawdata_to_bcd( uint8_t *pTarget, uint8_t *pSource, uint32_t ByteLengthOfSource, int StartFromLast) { uint32_t TotalBitInMemory; uint32_t BitPositionInMemory; uint32_t BitPositionInBCD; int ByteLengthOfConvertedBCD; int FirstHighBitPosition; int IsERROR; uint8_t BCD; if ( ( pTarget == (uint8_t *)0) || ( pSource == (uint8_t *)0 ) ) { return -1; } FirstHighBitPosition = -1; TotalBitInMemory = ByteLengthOfSource * 8; BCD = 0; IsERROR = 0; for ( BitPositionInMemory = 0; BitPositionInMemory < TotalBitInMemory; BitPositionInMemory++) { BCD >>= 1; if ( memory_pick_up_bit( (void *)pSource, TotalBitInMemory, BitPositionInMemory, StartFromLast) == 1 ) { if ( FirstHighBitPosition == -1 ) { FirstHighBitPosition = BitPositionInMemory; } BCD |= 0x10; } else { BCD &= 0xEF; } BCD &= 0x1F; if ( BCD == 0x0B/* ';' = SS */ ) { if (FirstHighBitPosition + 4 != BitPositionInMemory) { IsERROR = 1; /* SS error */ } /* get sync */ break; } } BitPositionInMemory++; /* skip parity bit for sync char */ if(BitPositionInMemory >= TotalBitInMemory) { return -2; /* Not find SS */ } ByteLengthOfConvertedBCD = 0; pTarget[ByteLengthOfConvertedBCD++] = pDataFormatTableForISO_BCD[0x0B]; /* ';' = SS */ /* gather data */ BitPositionInBCD=0; BCD = 0; for ( ; BitPositionInMemory < TotalBitInMemory; BitPositionInMemory++) { BCD |= (memory_pick_up_bit( (void *)pSource, TotalBitInMemory, BitPositionInMemory, StartFromLast) << BitPositionInBCD); BitPositionInBCD ++; if ( BitPositionInBCD == 5 ) { pTarget[ByteLengthOfConvertedBCD++] = pDataFormatTableForISO_BCD[BCD]; BitPositionInBCD=0; BCD = 0; } } return ByteLengthOfConvertedBCD; } static void mmd1100_packet_flush_buffer(void); /* open serial device for cummunication with MMD1100 return: -1: Fail to operation -2: Input Paramters Error 0: OK */ int mmd1100_open(int *pDeviceFileDescriptor) { struct termios TerminalInfo; if ( pDeviceFileDescriptor == (int *)0 ) { return -2; } if ( MMD1100context.Device < 0 ) { /* Initial Serial Receive Buffer */ MMD1100context.HeadPointerForSerial = 0; MMD1100context.TailPointerForSerial = 0; /* Initial Received Packet Buffer */ mmd1100_packet_flush_buffer(); /* 화일을 연다. */ MMD1100context.Device = open( DEVICE_MMD1100, (O_RDWR | O_NOCTTY) ); if ( MMD1100context.Device < 0 ) { /* 화일 열기 실패 */ MMD1100_ERROR( "failed to open %s\n", DEVICE_MMD1100 ); MMD1100context.Device = -1; *pDeviceFileDescriptor = MMD1100context.Device; return -1; } /* 현재 설정을 BackupTerminalInfo에 저장 */ tcgetattr( MMD1100context.Device, &MMD1100context.BackupTerminalInfo ); memset( &TerminalInfo, 0, sizeof(TerminalInfo) ); switch( MMD1100_DEFAULT_BAUDRATE ) { case 19200: TerminalInfo.c_cflag = B19200 | CS8 | CSTOPB | CLOCAL | CREAD ; break; case 38400: TerminalInfo.c_cflag = B38400 | CS8 | CSTOPB | CLOCAL | CREAD ; break; case 57600: TerminalInfo.c_cflag = B57600 | CS8 | CSTOPB | CLOCAL | CREAD ; break; case 115200: TerminalInfo.c_cflag = B115200 | CS8 | CSTOPB | CLOCAL | CREAD ; break; case 9600: default: TerminalInfo.c_cflag = B9600 | CS8 | CSTOPB | CLOCAL | CREAD ; break; } TerminalInfo.c_iflag = 0; /* IGNPAR? */ TerminalInfo.c_oflag = 0; //set input mode (non-canonical, no echo,.....) TerminalInfo.c_lflag = 0; TerminalInfo.c_cc[VTIME] = 30; /* time-out 값으로 사용된다. time-out 값은 TIME*0.1초 이다. */ TerminalInfo.c_cc[VMIN] = 0; /* MIN은 read가 리턴되기 위한 최소한의 문자 개수 */ tcflush(MMD1100context.Device, TCIFLUSH); tcsetattr(MMD1100context.Device, TCSANOW, &TerminalInfo); // raw mode fcntl(MMD1100context.Device, F_SETFL, O_NONBLOCK); } else { MMD1100_DEBUG("%s already opened\n", DEVICE_MMD1100); } *pDeviceFileDescriptor = MMD1100context.Device; return 0; } /* close serial device for end of cummunication with MMD1100 return: -1: Fail to operation 0: OK */ int mmd1100_close(void) { if ( MMD1100context.Device < 0 ) { MMD1100_ERROR("%s already closed\n", DEVICE_MMD1100); return -1; } /* 이전 상태로 되돌린다. */ tcsetattr( MMD1100context.Device, TCSANOW, &MMD1100context.BackupTerminalInfo ); close(MMD1100context.Device); MMD1100context.Device = -1; return 0; } /* get serial device file descriptor for cummunication with MMD1100 return: -1: Fail to operation -2: Input Paramters Error 0: OK */ int mmd1100_get_device_file_descriptor(int *pDeviceFileDescriptor) { if ( pDeviceFileDescriptor == (int *)0 ) { return -2; } if ( MMD1100context.Device != -1 ) { *pDeviceFileDescriptor = MMD1100context.Device; return 0; } MMD1100_ERROR("%s is closed\n", DEVICE_MMD1100); return -1; } /* serial buffer flush for cummunication with MMD1100 */ void mmd1100_serial_flush(void) { struct pollfd PollFileDescriptor; int Result; uint8_t ReceivedByte; if ( MMD1100context.Device != -1 ) { memset( &PollFileDescriptor, 0, sizeof(struct pollfd) ); while(1) { PollFileDescriptor.fd = MMD1100context.Device; PollFileDescriptor.events = POLLIN; PollFileDescriptor.revents = 0; Result = poll( &PollFileDescriptor, 1, 2 ); // 2 msec if ( (Result == 1) && ((PollFileDescriptor.revents & POLLIN) != 0) ) { read(MMD1100context.Device, &ReceivedByte, 1); } else { break; } } } else { MMD1100_ERROR("%s is closed\n", DEVICE_MMD1100); } MMD1100context.HeadPointerForSerial = 0; MMD1100context.TailPointerForSerial = 0; } /* send data(n byte) to MMD1100 through serial device */ static void mmd1100_serial_transmit_data(uint8_t *pData, uint32_t ByteLengthOfData) { int Result; uint8_t Byte; while(ByteLengthOfData--) { Byte = *pData++; do { Result = write(MMD1100context.Device, &Byte, 1); } while( Result != 1 ); } } /* polling serial device to save input data from MMD1100 */ static void mmd1100_serial_polling(void) { struct pollfd PollFileDescriptor; uint32_t Temp; int Result; uint8_t ReceivedByte; memset( &PollFileDescriptor, 0, sizeof(struct pollfd) ); PollFileDescriptor.fd = MMD1100context.Device; PollFileDescriptor.events = POLLIN; PollFileDescriptor.revents = 0; Result = poll( (struct pollfd *)&PollFileDescriptor, 1, 20); // 20 msec if ( (Result == 1) && ((PollFileDescriptor.revents & POLLIN) != 0) ) { if ( read(MMD1100context.Device, &ReceivedByte, 1) == 1 ) { MMD1100context.pBufferForSerial[MMD1100context.HeadPointerForSerial] = ReceivedByte; Temp = (MMD1100context.HeadPointerForSerial + 1) % MMD1100_BYTE_SIZE_OF_BUFFER_FOR_SERIAL; if ( Temp != MMD1100context.TailPointerForSerial ) { MMD1100context.HeadPointerForSerial = Temp; } } } } /* check serial buffer to find received data from MMD1100 return: 0: Data is not received 1: Data received */ static int mmd1100_serial_check_buffer(void) { // check lowlevel serial data, if we have no data if ( MMD1100context.HeadPointerForSerial == MMD1100context.TailPointerForSerial ) { mmd1100_serial_polling(); } if ( MMD1100context.HeadPointerForSerial != MMD1100context.TailPointerForSerial ) { return 1; } return 0; } /* get data from serial buffer return: -1: Fail to operation -2: Input Paramters Error 0: OK */ static int mmd1100_serial_get_data_from_buffer(uint8_t *pData) { if ( pData == (uint8_t *)0 ) { return -2; } if ( MMD1100context.TailPointerForSerial == MMD1100context.HeadPointerForSerial) { return -1; } *pData = MMD1100context.pBufferForSerial[MMD1100context.TailPointerForSerial]; MMD1100context.TailPointerForSerial++; MMD1100context.TailPointerForSerial %= MMD1100_BYTE_SIZE_OF_BUFFER_FOR_SERIAL; return 0; } /* flush received packet buffer */ static void mmd1100_packet_flush_buffer(void) { MMD1100context.PacketOffset = 0; MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STX; } /* -1: invalid 0 : OK */ static int mmd1100_check_response(uint8_t Class, uint8_t Function, uint8_t Length, uint8_t Status) { switch (Class) { case MMD1100_COMMAND_CLASS_GET_VERSION: if ( Function == MMD1100_COMMAND_FUNCTION_GET_VERSION ) { if ( ( ( Status == MMD1100_DEFINE_ACK ) && ( Length == MMD1100_RESPONSE_ACK_LENGTH_GET_VERSION ) ) || ( ( Status == MMD1100_DEFINE_NAK ) && ( Length == MMD1100_RESPONSE_NAK_LENGTH ) ) ) { return 0; } } break; case MMD1100_COMMAND_CLASS_LOAD_USER_PARAMETERS: if ( Function == MMD1100_COMMAND_FUNCTION_LOAD_USER_PARAMETERS ) { if ( ( ( Status == MMD1100_DEFINE_ACK ) && ( Length == MMD1100_RESPONSE_ACK_LENGTH_LOAD_USER_PARAMETERS ) ) || ( ( Status == MMD1100_DEFINE_NAK ) && ( Length == MMD1100_RESPONSE_NAK_LENGTH ) ) ) { return 0; } } break; case MMD1100_COMMAND_CLASS_UART_CALIBRATION: if ( Function == MMD1100_COMMAND_FUNCTION_UART_CALIBRATION ) { if ( ( ( Status == MMD1100_DEFINE_ACK ) && ( Length == MMD1100_RESPONSE_ACK_LENGTH_UART_CALIBRATION ) ) || ( ( Status == MMD1100_DEFINE_NAK ) && ( Length == MMD1100_RESPONSE_NAK_LENGTH ) ) ) { return 0; } } break; case MMD1100_COMMAND_CLASS_OTP_WRITE: if ( Function == MMD1100_COMMAND_FUNCTION_OTP_WRITE ) { if ( ( ( Status == MMD1100_DEFINE_ACK ) && ( Length == MMD1100_RESPONSE_ACK_LENGTH_OTP_WRITE ) ) || ( ( Status == MMD1100_DEFINE_NAK ) && ( Length == MMD1100_RESPONSE_NAK_LENGTH ) ) ) { return 0; } } break; case MMD1100_COMMAND_CLASS_GET_STATUS: if ( Function == MMD1100_COMMAND_FUNCTION_GET_STATUS ) { if ( ( ( Status == MMD1100_DEFINE_ACK ) && ( Length == MMD1100_RESPONSE_ACK_LENGTH_GET_STATUS ) ) || ( ( Status == MMD1100_DEFINE_NAK ) && ( Length == MMD1100_RESPONSE_NAK_LENGTH ) ) ) { return 0; } } break; case MMD1100_COMMAND_CLASS_READ_DATA_RETRY: if ( Function == MMD1100_COMMAND_FUNCTION_READ_DATA_RETRY ) { if ( ( Status == MMD1100_DEFINE_NAK ) && ( Length == MMD1100_RESPONSE_NAK_LENGTH ) ) { return 0; } } break; case MMD1100_COMMAND_CLASS_SOFTWARE_RESET: if ( Function == MMD1100_COMMAND_FUNCTION_SOFTWARE_RESET ) { if ( ( Status == MMD1100_DEFINE_NAK ) && ( Length == MMD1100_RESPONSE_NAK_LENGTH ) ) { return 0; } } break; default: break; } return -1; } /* make response packet form serial buffer return: 2: Notify Packet 1: Need Time Wait -1: Fail to operation -2: Packet LRC Error -3: Packet Data is too Big -4: Timeout or Not Ready 0: OK */ static int mmd1100_packet_make_response_from_serial_buffer(void) { struct timespec CurrentTime; struct timespec GetTimeToLastData; uint8_t Data; while( mmd1100_serial_check_buffer() == 1 ) { /* Serial buffer has data */ mmd1100_serial_get_data_from_buffer( &Data ); clock_gettime( CLOCK_REALTIME, &GetTimeToLastData ); /* Push Data to Packet Buffer */ MMD1100context.pBufferForPacket[MMD1100context.PacketOffset] = Data; /* printf("0x%02X ", Data); */ if ( MMD1100context.PacketOffset < MMD1100_BYTE_SIZE_OF_BUFFER_FOR_PACKET ) { MMD1100context.PacketOffset++; } switch( MMD1100context.PacketCheckState ) { case MMD1100_PACKET_CHECK_STATE_STX: if ( Data == MMD1100_DEFINE_STX ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_MODE_CLASS; } else { mmd1100_packet_flush_buffer(); // invaild command sequence MMD1100_DEBUG( "invalid received Data : 0x%02X\n", Data ); return -1; } break; case MMD1100_PACKET_CHECK_STATE_MODE_CLASS: MMD1100context.PacketLength = 0; if ( Data == MMD1100_DEFINE_TRACK_DATA ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_TRACK_ID; } else { switch ( Data ) { case MMD1100_COMMAND_CLASS_GET_VERSION: case MMD1100_COMMAND_CLASS_LOAD_USER_PARAMETERS: case MMD1100_COMMAND_CLASS_UART_CALIBRATION: case MMD1100_COMMAND_CLASS_OTP_WRITE: case MMD1100_COMMAND_CLASS_GET_STATUS: case MMD1100_COMMAND_CLASS_READ_DATA_RETRY: case MMD1100_COMMAND_CLASS_SOFTWARE_RESET: MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_FUNCTION; break; default: mmd1100_packet_flush_buffer(); // invaild command sequence MMD1100_DEBUG( "invalid received Data : 0x%02X\n", Data ); return -1; break; } } break; case MMD1100_PACKET_CHECK_STATE_TRACK_ID: if ( ( Data == MMD1100_DEFINE_TRACK_ID_1 ) || ( Data == MMD1100_DEFINE_TRACK_ID_2 ) || ( Data == MMD1100_DEFINE_TRACK_ID_3 ) ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_TRACK_LENGTH; } else if ( Data == MMD1100_DEFINE_ETX ) { MMD1100context.PacketLength += 3; MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_BCC; } else { mmd1100_packet_flush_buffer(); // invaild command sequence MMD1100_DEBUG("invalid received Data : 0x%02X\n", Data); return -1; } break; case MMD1100_PACKET_CHECK_STATE_TRACK_LENGTH: MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_TRACK_STATE; MMD1100context.DataLengthInPacket = Data; break; case MMD1100_PACKET_CHECK_STATE_TRACK_STATE: if ( ( Data == MMD1100_DEFINE_ACK ) || ( Data == MMD1100_DEFINE_NAK ) ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_TRACK_DATA; MMD1100context.PacketLength += (MMD1100context.DataLengthInPacket + 3); } else { mmd1100_packet_flush_buffer(); // invaild command sequence MMD1100_DEBUG("invalid received Data : 0x%02X\n", Data); return -1; } break; case MMD1100_PACKET_CHECK_STATE_TRACK_DATA: MMD1100context.DataLengthInPacket--; if ( MMD1100context.DataLengthInPacket == 0 ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_TRACK_ID; } break; case MMD1100_PACKET_CHECK_STATE_FUNCTION: switch ( MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_CLASS] ) { case MMD1100_COMMAND_CLASS_GET_VERSION: if ( Data == MMD1100_COMMAND_FUNCTION_GET_VERSION ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_LENGTH; } break; case MMD1100_COMMAND_CLASS_LOAD_USER_PARAMETERS: if ( Data == MMD1100_COMMAND_FUNCTION_LOAD_USER_PARAMETERS ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_LENGTH; } break; case MMD1100_COMMAND_CLASS_UART_CALIBRATION: if ( Data == MMD1100_COMMAND_FUNCTION_UART_CALIBRATION ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_LENGTH; } break; case MMD1100_COMMAND_CLASS_OTP_WRITE: if ( Data == MMD1100_COMMAND_FUNCTION_OTP_WRITE ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_LENGTH; } break; case MMD1100_COMMAND_CLASS_GET_STATUS: if ( Data == MMD1100_COMMAND_FUNCTION_GET_STATUS ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_LENGTH; } break; case MMD1100_COMMAND_CLASS_READ_DATA_RETRY: if ( Data == MMD1100_COMMAND_FUNCTION_READ_DATA_RETRY ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_LENGTH; } break; case MMD1100_COMMAND_CLASS_SOFTWARE_RESET: if ( Data == MMD1100_COMMAND_FUNCTION_SOFTWARE_RESET ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_LENGTH; } break; default: break; } if ( MMD1100context.PacketCheckState != MMD1100_PACKET_CHECK_STATE_LENGTH ) { mmd1100_packet_flush_buffer(); // invaild command sequence MMD1100_DEBUG("invalid received Data : 0x%02X\n", Data); return -1; } break; case MMD1100_PACKET_CHECK_STATE_LENGTH: switch ( MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_CLASS] ) { case MMD1100_COMMAND_CLASS_GET_VERSION: if ( ( Data == MMD1100_RESPONSE_ACK_LENGTH_GET_VERSION ) || ( Data == MMD1100_RESPONSE_NAK_LENGTH ) ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STATUS; } break; case MMD1100_COMMAND_CLASS_LOAD_USER_PARAMETERS: if ( ( Data == MMD1100_RESPONSE_ACK_LENGTH_LOAD_USER_PARAMETERS ) || ( Data == MMD1100_RESPONSE_NAK_LENGTH ) ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STATUS; } break; case MMD1100_COMMAND_CLASS_UART_CALIBRATION: if ( ( Data == MMD1100_RESPONSE_ACK_LENGTH_UART_CALIBRATION ) || ( Data == MMD1100_RESPONSE_NAK_LENGTH ) ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STATUS; } break; case MMD1100_COMMAND_CLASS_OTP_WRITE: if ( ( Data == MMD1100_RESPONSE_ACK_LENGTH_OTP_WRITE ) || ( Data == MMD1100_RESPONSE_NAK_LENGTH ) ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STATUS; } break; case MMD1100_COMMAND_CLASS_GET_STATUS: if ( ( Data == MMD1100_RESPONSE_ACK_LENGTH_GET_STATUS ) || ( Data == MMD1100_RESPONSE_NAK_LENGTH ) ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STATUS; } break; case MMD1100_COMMAND_CLASS_READ_DATA_RETRY: if ( Data == MMD1100_RESPONSE_NAK_LENGTH ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STATUS; } break; case MMD1100_COMMAND_CLASS_SOFTWARE_RESET: if ( Data == MMD1100_RESPONSE_NAK_LENGTH ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STATUS; } break; default: break; } if ( MMD1100context.PacketCheckState != MMD1100_PACKET_CHECK_STATE_STATUS ) { mmd1100_packet_flush_buffer(); // invaild command sequence MMD1100_DEBUG("invalid received Data : 0x%02X\n", Data); return -1; } break; case MMD1100_PACKET_CHECK_STATE_STATUS: if ( mmd1100_check_response(MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_CLASS]/*Class*/, MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_FUNCTION]/*Function*/, MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_LENGTH]/*Length*/, Data/*Status*/) == 0 ) { MMD1100context.DataLengthInPacket = MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_LENGTH]; MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_DATA; } else { mmd1100_packet_flush_buffer(); // invaild command sequence MMD1100_DEBUG("invalid received Data : 0x%02X\n", Data); return -1; } break; case MMD1100_PACKET_CHECK_STATE_DATA: MMD1100context.DataLengthInPacket--; if ( MMD1100context.DataLengthInPacket == 0 ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_ETX; } break; case MMD1100_PACKET_CHECK_STATE_ETX: if ( Data == MMD1100_DEFINE_ETX ) { MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_BCC; MMD1100context.PacketLength = 6 + MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_LENGTH]; } else { mmd1100_packet_flush_buffer(); // invaild command sequence MMD1100_INFO("invalid received Data : 0x%02X\n", Data); return -1; } break; case MMD1100_PACKET_CHECK_STATE_BCC: mmd1100_packet_flush_buffer(); MMD1100_DEBUG("received lenght : %d\n", MMD1100context.PacketLength); if ( Data == lrc_xor(MMD1100context.pBufferForPacket, MMD1100context.PacketLength) ) { MMD1100_INFO("BCC : OK\n"); return 0; } else { MMD1100_ERROR("BCC : Fail\n"); return -2; } break; } } // check inter-character timeout if ( MMD1100context.PacketCheckState != MMD1100_PACKET_CHECK_STATE_STX ) { clock_gettime(CLOCK_REALTIME, &CurrentTime); if ( (CurrentTime.tv_nsec - GetTimeToLastData.tv_nsec) > (MMD1100_TIMEOUT_BETWEEN_SERIAL_INPUT_DATA * 1000)/**/ ) { mmd1100_packet_flush_buffer(); // return -4; /* Time out */ } } return -4; /* Not Ready */ } /* receive return: -1: Fail to operation -2: Input Parameter Error -4: Timeout or Not Ready 0: OK */ int mmd1100_receive(MSRTrack_t *pMSRTrack, MMD1100Response_t *pResponse, uint32_t *pIsNotTrack, uint32_t ResponseMilisecondTimeout) { struct timespec Start; struct timespec Current; uint32_t Position; int Result; if ( pIsNotTrack == (uint32_t *)0 ) { return -2; } clock_gettime(CLOCK_REALTIME, &Start); while(1) { Result = mmd1100_packet_make_response_from_serial_buffer(); if ( Result == -4 ) /* Not ready or time-out */ { clock_gettime(CLOCK_REALTIME, &Current); if ( (Current.tv_nsec - Start.tv_nsec) > (ResponseMilisecondTimeout * 1000) ) { // MMD1100_DEBUG("time-out :start - %d nsec, cur = %d nsec, timeout = %d nsec \n", Start, Current, (ResponseMilisecondTimeout * 1000) ); return -4; } continue; } if ( Result != 0 ) { MMD1100_DEBUG("response_check() return - %d\n", Result); return -1; } break; } if( MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_CLASS] == MMD1100_DEFINE_TRACK_DATA) { /* Track Data */ *pIsNotTrack = 0; if ( pMSRTrack == (MSRTrack_t *)0 ) { return -2; } memset( pMSRTrack, 0, sizeof(MSRTrack_t) ); { Position = MMD1100_PACKET_POSITION_TRACK_ID; while ( MMD1100context.pBufferForPacket[Position] != MMD1100_DEFINE_ETX ) { int i; if ( MMD1100context.pBufferForPacket[Position] == MMD1100_DEFINE_TRACK_ID_1 ) { if ( MMD1100context.pBufferForPacket[Position + 2] == MMD1100_DEFINE_NAK) { pMSRTrack->ErrorCodeForTrack1 = MMD1100context.pBufferForPacket[Position + 3]; pMSRTrack->LengthOfTrack1 = 0; } else { int temp; pMSRTrack->ErrorCodeForTrack1 = 0; pMSRTrack->LengthOfTrack1 = 0; pMSRTrack->LengthOfRaw1 = MMD1100context.pBufferForPacket[Position + 1]; memcpy( pMSRTrack->pRaw1, &MMD1100context.pBufferForPacket[Position + 3], pMSRTrack->LengthOfRaw1 ); temp = mmd100_convert_rawdata_to_bcd( pMSRTrack->pTrack1, &MMD1100context.pBufferForPacket[Position + 3], MMD1100context.pBufferForPacket[Position + 1], 1); if (temp > 0) { pMSRTrack->LengthOfTrack1 = temp; } } } if ( MMD1100context.pBufferForPacket[Position] == MMD1100_DEFINE_TRACK_ID_2 ) { if ( MMD1100context.pBufferForPacket[Position + 2] == MMD1100_DEFINE_NAK) { pMSRTrack->ErrorCodeForTrack2 = MMD1100context.pBufferForPacket[Position + 3]; pMSRTrack->LengthOfTrack2 = 0; } else { int temp; pMSRTrack->ErrorCodeForTrack2 = 0; pMSRTrack->LengthOfTrack2 = 0; pMSRTrack->LengthOfRaw2 = MMD1100context.pBufferForPacket[Position + 1]; memcpy( pMSRTrack->pRaw2, &MMD1100context.pBufferForPacket[Position + 3], pMSRTrack->LengthOfRaw2 ); temp = mmd100_convert_rawdata_to_bcd( pMSRTrack->pTrack2, &MMD1100context.pBufferForPacket[Position + 3], MMD1100context.pBufferForPacket[Position + 1], 1); if (temp > 0) { pMSRTrack->LengthOfTrack2 = temp; } else { MMD1100_ERROR( " mmd100_convert_rawdata_to_bcd() = -%d", -temp); } } } if ( MMD1100context.pBufferForPacket[Position] == MMD1100_DEFINE_TRACK_ID_3 ) { if ( MMD1100context.pBufferForPacket[Position + 2] == MMD1100_DEFINE_NAK) { pMSRTrack->ErrorCodeForTrack3 = MMD1100context.pBufferForPacket[Position + 3]; pMSRTrack->LengthOfTrack3 = 0; } else { int temp; pMSRTrack->ErrorCodeForTrack3 = 0; pMSRTrack->LengthOfTrack3 = 0; pMSRTrack->LengthOfRaw3 = MMD1100context.pBufferForPacket[Position + 1]; memcpy( pMSRTrack->pRaw3, &MMD1100context.pBufferForPacket[Position + 3], pMSRTrack->LengthOfRaw3 ); temp = mmd100_convert_rawdata_to_bcd( pMSRTrack->pTrack3, &MMD1100context.pBufferForPacket[Position + 3], MMD1100context.pBufferForPacket[Position + 1], 1); if (temp > 0) { pMSRTrack->LengthOfTrack3 = temp; } else { MMD1100_ERROR( " mmd100_convert_rawdata_to_bcd() = -%d", -temp); } } } Position += (3 + MMD1100context.pBufferForPacket[Position + 1]); } } } else /* Response */ { *pIsNotTrack = 1; if ( pResponse == (MMD1100Response_t *)0 ) { return -2; } memset( pResponse, 0, sizeof(MMD1100Response_t) ); switch ( MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_CLASS] ) { case MMD1100_COMMAND_CLASS_GET_VERSION: pResponse->Command = MMD1100_COMMAND_GET_VERSION; break; case MMD1100_COMMAND_CLASS_LOAD_USER_PARAMETERS: pResponse->Command = MMD1100_COMMAND_LOAD_USER_PARAMETERS; break; case MMD1100_COMMAND_CLASS_UART_CALIBRATION: pResponse->Command = MMD1100_COMMAND_UART_CALIBRATION; break; case MMD1100_COMMAND_CLASS_OTP_WRITE: pResponse->Command = MMD1100_COMMAND_OTP_WRITE; break; case MMD1100_COMMAND_CLASS_GET_STATUS: pResponse->Command = MMD1100_COMMAND_GET_STATUS; break; case MMD1100_COMMAND_CLASS_READ_DATA_RETRY: pResponse->Command = MMD1100_COMMAND_READ_DATA_RETRY; break; case MMD1100_COMMAND_CLASS_SOFTWARE_RESET: pResponse->Command = MMD1100_COMMAND_SOFTWARE_RESET; break; } if ( MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_STATUS] == MMD1100_DEFINE_NAK ) { pResponse->ErrorCode = MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_DATA_START]; } else /* ( MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_STATUS] == MMD1100_DEFINE_ACK ) */ { pResponse->ErrorCode = 0; memcpy( pResponse->pData, &MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_DATA_START], MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_LENGTH] ); } } return 0; } /* -1: invalid parameter 0 : OK */ int mmd1100_make_packet(uint8_t *pPacket, uint32_t *pMakedPacketByteLength, MMD1100_Command_t Command, uint8_t pArguments[4]) { if((pPacket == (uint8_t *)0) || (pMakedPacketByteLength == (uint32_t *)0)) { return -1; } pPacket[0] = MMD1100_DEFINE_STX; /* STX */ switch(Command) { case MMD1100_COMMAND_GET_VERSION: pPacket[1] = MMD1100_COMMAND_CLASS_GET_VERSION; /* Class */ pPacket[2] = MMD1100_COMMAND_FUNCTION_GET_VERSION; /* Function */ pPacket[3] = MMD1100_COMMAND_LENGTH_GET_VERSION; /* Length */ pPacket[4] = MMD1100_DEFINE_ETX; /* ETX */ *pMakedPacketByteLength = 6; pPacket[5] = lrc_xor(pPacket, (*pMakedPacketByteLength - 1)); /* BCC */ break; case MMD1100_COMMAND_LOAD_USER_PARAMETERS: if(pArguments == (uint8_t *)0) { return -1; } pPacket[1] = MMD1100_COMMAND_CLASS_LOAD_USER_PARAMETERS; /* Class */ pPacket[2] = MMD1100_COMMAND_FUNCTION_LOAD_USER_PARAMETERS; /* Function */ pPacket[3] = MMD1100_COMMAND_LENGTH_LOAD_USER_PARAMETERS; /* Length */ pPacket[4] = pArguments[0]; /* Tx Mode 1 Byte */ pPacket[5] = pArguments[1]; /* Reserved 1 Byte */ pPacket[6] = pArguments[2]; /* All Track Error 1 Byte */ pPacket[7] = pArguments[3]; /* Reserved 1 Byte */ pPacket[8] = MMD1100_DEFINE_ETX; /* ETX */ *pMakedPacketByteLength = 10; pPacket[9] = lrc_xor(pPacket, (*pMakedPacketByteLength - 1)); /* BCC */ break; case MMD1100_COMMAND_UART_CALIBRATION: pPacket[1] = MMD1100_COMMAND_CLASS_UART_CALIBRATION; /* Class */ pPacket[2] = MMD1100_COMMAND_FUNCTION_UART_CALIBRATION; /* Function */ pPacket[3] = MMD1100_COMMAND_LENGTH_UART_CALIBRATION; /* Length */ pPacket[4] = 0xAA; /* */ pPacket[5] = 0xAA; /* */ pPacket[6] = 0xAA; /* */ pPacket[7] = 0xAA; /* */ pPacket[8] = 0xAA; /* */ pPacket[9] = MMD1100_DEFINE_ETX; /* ETX */ *pMakedPacketByteLength = 11; pPacket[10] = lrc_xor(pPacket, (*pMakedPacketByteLength - 1)); /* BCC */ break; case MMD1100_COMMAND_OTP_WRITE: pPacket[1] = MMD1100_COMMAND_CLASS_OTP_WRITE; /* Class */ pPacket[2] = MMD1100_COMMAND_FUNCTION_OTP_WRITE; /* Function */ pPacket[3] = MMD1100_COMMAND_LENGTH_OTP_WRITE; /* Length */ pPacket[4] = MMD1100_DEFINE_ETX; /* ETX */ *pMakedPacketByteLength = 6; pPacket[5] = lrc_xor(pPacket, (*pMakedPacketByteLength - 1)); /* BCC */ break; case MMD1100_COMMAND_GET_STATUS: pPacket[1] = MMD1100_COMMAND_CLASS_GET_STATUS; /* Class */ pPacket[2] = MMD1100_COMMAND_FUNCTION_GET_STATUS; /* Function */ pPacket[3] = MMD1100_COMMAND_LENGTH_GET_STATUS; /* Length */ pPacket[4] = MMD1100_DEFINE_ETX; /* ETX */ *pMakedPacketByteLength = 6; pPacket[5] = lrc_xor(pPacket, (*pMakedPacketByteLength - 1) ); /* BCC */ break; case MMD1100_COMMAND_READ_DATA_RETRY: pPacket[1] = MMD1100_COMMAND_CLASS_READ_DATA_RETRY; /* Class */ pPacket[2] = MMD1100_COMMAND_FUNCTION_READ_DATA_RETRY; /* Function */ pPacket[3] = MMD1100_COMMAND_LENGTH_READ_DATA_RETRY; /* Length */ pPacket[4] = MMD1100_DEFINE_ETX; /* ETX */ *pMakedPacketByteLength = 6; pPacket[5] = lrc_xor(pPacket, (*pMakedPacketByteLength - 1) ); /* BCC */ break; case MMD1100_COMMAND_SOFTWARE_RESET: pPacket[1] = MMD1100_COMMAND_CLASS_SOFTWARE_RESET; /* Class */ pPacket[2] = MMD1100_COMMAND_FUNCTION_SOFTWARE_RESET; /* Function */ pPacket[3] = MMD1100_COMMAND_LENGTH_SOFTWARE_RESET; /* Length */ pPacket[4] = MMD1100_DEFINE_ETX; /* ETX */ *pMakedPacketByteLength = 6; pPacket[5] = lrc_xor(pPacket, (*pMakedPacketByteLength - 1) ); /* BCC */ break; default: return -1; break; } return 0; } /* -1: invalid parameter -2: send error 0 : Not open + : Send length */ int mmd1100_send(uint8_t *pPacket, uint8_t PacketByteLength) { uint32_t Index; if ( ( pPacket == (uint8_t *)0 ) || ( PacketByteLength == 0 ) ) { return -1; } if ( MMD1100context.Device == -1 ) { return 0; } mmd1100_serial_flush(); for ( Index = 0; Index < PacketByteLength; Index ++ ) { if ( write( MMD1100context.Device, &pPacket[Index], 1 ) != 1 ) { MMD1100_ERROR( "failed to send packet to MSR controller(MMD1100) %s\n", DEVICE_MMD1100 ); return -2; } } tcdrain( MMD1100context.Device ); return Index; } Test App Source int DeviceFileDescriptorForMSR; MSRTrack_t MSRTrack; MMD1100Response_t MSRResponse; uint32_t IsNotTrack; uint8_t pVersion[1024]; int ConvertLength; .... if ( mmd1100_open( &DeviceFileDescriptorForMSR ) != 0 ) { printf("Fail to mmd1100_open\n"); } else { printf("OK to mmd1100_open\n"); } .... while( ?? ) { .... if ( mmd1100_receive( &MSRTrack, &MSRResponse, &IsNotTrack, 10000/*10ms ResponseTimeout*/) == 0 ) { printf("MSR IN\n"); if ( IsNotTrack == 1 ) { switch ( MSRResponse.Command ) { case MMD1100_COMMAND_GET_VERSION: if ( MSRResponse.ErrorCode == 0 ) { printf(" MMD1100_COMMAND_GET_VERSION : %s\n", MSRResponse.pData ); } else { printf(" MMD1100_COMMAND_GET_VERSION : Error = 0x%02X\n", MSRResponse.ErrorCode ); } break; case MMD1100_COMMAND_LOAD_USER_PARAMETERS: break; case MMD1100_COMMAND_UART_CALIBRATION: break; case MMD1100_COMMAND_OTP_WRITE: break; case MMD1100_COMMAND_GET_STATUS: break; case MMD1100_COMMAND_READ_DATA_RETRY: break; case MMD1100_COMMAND_SOFTWARE_RESET: break; default: break; } } else { int i; if ( MSRTrack.ErrorCodeForTrack1 == 0 ) { printf( " Track 1 : " ); for ( i = 0; i < MSRTrack.LengthOfTrack1; i++ ) { printf( "%c", MSRTrack.pTrack1[i] ); } printf( "\n" ); if ( ( (MSRTrack.LengthOfTrack1 * 8) % 7 ) == 0 ) { printf( " Length OK \n" ); } } else { printf(" Track 1 : ErrorCode = 0x%02X\n", MSRTrack.ErrorCodeForTrack1 ); } if ( MSRTrack.ErrorCodeForTrack2 == 0 ) { printf( " Track 2 Raw Data : (Length = %d)\n ", MSRTrack.LengthOfRaw2 ); for ( i = 0; i < MSRTrack.LengthOfRaw2; i++ ) { printf( "%02X ", MSRTrack.pRaw2[i] ); } printf( "\n" ); printf( " Track 2 : (Length = %d)\n ", MSRTrack.LengthOfTrack2 ); for ( i = 0; i < MSRTrack.LengthOfTrack2; i++ ) { printf( "%c", MSRTrack.pTrack2[i] ); } printf( "\n" ); } else { printf(" Track 2 : ErrorCode = 0x%02X\n", MSRTrack.ErrorCodeForTrack2 ); } if ( MSRTrack.ErrorCodeForTrack3 == 0 ) { printf( " Track 3 Raw Data : (Length = %d)\n ", MSRTrack.LengthOfRaw3 ); for ( i = 0; i < MSRTrack.LengthOfRaw3; i++ ) { printf( "%02X ", MSRTrack.pRaw3[i] ); } printf( "\n" ); printf( " Track 3 : (Length = %d)\n ", MSRTrack.LengthOfTrack3 ); for ( i = 0; i < MSRTrack.LengthOfTrack3; i++ ) { printf( "%c", MSRTrack.pTrack3[i] ); } printf( "\n" ); } else { printf(" Track 3 : ErrorCode = 0x%02X\n", MSRTrack.ErrorCodeForTrack3 ); } } } .... } Result ... MSR IN Track 1 : ErrorCode = 0x55 Track 2 Raw Data : (Length = 31) 00 00 00 F0 7F 08 21 84 19 C8 14 8D 40 88 10 09 13 DA D9 08 27 61 92 16 02 22 2D 13 0D 00 00 Track 2 : (Length = 45) ;4364200649047469=19042211468940900000?? Track 3 Raw Data : (Length = 88) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90 1F 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 A0 01 00 00 00 00 00 20 Track 3 : (Length = 129) ;00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000?4 필요 라이브러리 소스 int memory_pick_up_bit( void *pMemory, uint32_t TotalBitInMemory, uint32_t BitPositionInMemory, int StartFromLast) { uint8_t * pByte; if ( pMemory == (void *)0 ) { return -1; } pByte = (uint8_t *)pMemory; if (StartFromLast == 0) { if ( ( pByte[BitPositionInMemory >> 3] & (0x01 << ( BitPositionInMemory & 0x07 ) ) ) != 0 ) { return 1; } else { return 0; } } else { BitPositionInMemory = TotalBitInMemory - BitPositionInMemory; if ( ( pByte[BitPositionInMemory >> 3] & (0x01 << ( BitPositionInMemory & 0x07 ) ) ) != 0 ) { return 1; } else { return 0; } } } uint8_t lrc_xor(uint8_t *pData, uint32_t ByteLength) { uint8_t LRC = 0; while(ByteLength--) LRC ^= *pData++; return LRC; }