Site Tools


Hotfix release available: 2025-05-14b "Librarian". upgrade now! [56.2] (what's this?)
Hotfix release available: 2025-05-14a "Librarian". upgrade now! [56.1] (what's this?)
New release available: 2025-05-14 "Librarian". upgrade now! [56] (what's this?)
Hotfix release available: 2024-02-06b "Kaos". upgrade now! [55.2] (what's this?)
Hotfix release available: 2024-02-06a "Kaos". upgrade now! [55.1] (what's this?)
New release available: 2024-02-06 "Kaos". upgrade now! [55] (what's this?)
Hotfix release available: 2023-04-04b "Jack Jackrum". upgrade now! [54.2] (what's this?)
Hotfix release available: 2023-04-04a "Jack Jackrum". upgrade now! [54.1] (what's this?)
New release available: 2023-04-04 "Jack Jackrum". upgrade now! [54] (what's this?)
Hotfix release available: 2022-07-31b "Igor". upgrade now! [53.1] (what's this?)
Hotfix release available: 2022-07-31a "Igor". upgrade now! [53] (what's this?)
New release available: 2022-07-31 "Igor". upgrade now! [52.2] (what's this?)
New release candidate 2 available: rc2022-06-26 "Igor". upgrade now! [52.1] (what's this?)
New release candidate available: 2022-06-26 "Igor". upgrade now! [52] (what's this?)
Hotfix release available: 2020-07-29a "Hogfather". upgrade now! [51.4] (what's this?)
New release available: 2020-07-29 "Hogfather". upgrade now! [51.3] (what's this?)
New release candidate 3 available: 2020-06-09 "Hogfather". upgrade now! [51.2] (what's this?)
New release candidate 2 available: 2020-06-01 "Hogfather". upgrade now! [51.1] (what's this?)
New release candidate available: 2020-06-01 "Hogfather". upgrade now! [51] (what's this?)
Hotfix release available: 2018-04-22c "Greebo". upgrade now! [50.3] (what's this?)
Hotfix release available: 2018-04-22b "Greebo". upgrade now! [50.2] (what's this?)
Hotfix release available: 2018-04-22a "Greebo". upgrade now! [50.1] (what's this?)
New release available: 2018-04-22 "Greebo". upgrade now! [50] (what's this?)
Hotfix release available: 2017-02-19g "Frusterick Manners". upgrade now! [49.7] (what's this?)
Hotfix release available: 2017-02-19f "Frusterick Manners". upgrade now! [49.6] (what's this?)
Hotfix release available: 2017-02-19e "Frusterick Manners". upgrade now! [49.5] (what's this?)
Hotfix release available fixing CVE-2017-12979 and CVE-2017-12980: 2017-02-19d "Frusterick Manners". upgrade now! [49.4] (what's this?)
Hotfix release available fixing CVE-2017-12583: 2017-02-19c "Frusterick Manners". upgrade now! [49.3] (what's this?)
msr_test

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
msr_test [2017/09/12 21:25]
1.241.172.144 created
msr_test [2017/09/12 21:35] (current)
1.241.172.144
Line 127: Line 127:
   ​   ​
   #endif /* __MMD1100_H__ */   #endif /* __MMD1100_H__ */
 +
 +Driver Source File
 +
 +  #​include <​stdint.h>​ /​* types */
 +  #​include <​stdio.h>​ /​* printf */
 +  #​include <​string.h>​ /​* memcpy, strlen... */
 +  #​include <​termios.h>​ /​* struct termios */
 +  #​include <​unistd.h>​ /​* for open/close .. */
 +  #​include <​fcntl.h>​ /​* for O_RDWR */
 +  #​include <​sys/​ioctl.h>​ /​* for ioctl */
 +  #​include <​poll.h>​ /​* struct pollfd */
 +  #​include <​time.h>​ /​* 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;​
 +  }
 +
  
  
msr_test.1505219157.txt.gz · Last modified: 2017/09/12 21:25 by 1.241.172.144