1765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang/*
2765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * Author: Jon Trulson <jtrulson@ics.com>
3765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * Copyright (c) 2015 Intel Corporation.
4765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang *
5765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * Permission is hereby granted, free of charge, to any person obtaining
6765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * a copy of this software and associated documentation files (the
7765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * "Software"), to deal in the Software without restriction, including
8765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * without limitation the rights to use, copy, modify, merge, publish,
9765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * distribute, sublicense, and/or sell copies of the Software, and to
10765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * permit persons to whom the Software is furnished to do so, subject to
11765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * the following conditions:
12765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang *
13765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * The above copyright notice and this permission notice shall be
14765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * included in all copies or substantial portions of the Software.
15765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang *
16765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang */
24765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
25765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang#include <stdexcept>
26765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
27765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang#include "sm130.h"
28765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
29765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangusing namespace upm;
30765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangusing namespace std;
31765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
32765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang// Uncomment the below to see packaet data sent and received from the SM130
33765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang// #define SM130_DEBUG
34765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
35765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangstatic const int defaultDelay = 1000; // ms for read
36765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
37765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangstatic const int maxLen = 64; // max number of bytes to read
38765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
39765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun ZhangSM130::SM130(int uart, int reset) :
40765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_uart(uart), m_gpioReset(reset)
41765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
42765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_tagType = TAG_NONE;
43765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_uidLen = 0;
44765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_uid.clear();
45765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
46765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  initClock();
47765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
48765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_gpioReset.dir(mraa::DIR_OUT);
49765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_gpioReset.write(0);
50765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
51765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
52765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun ZhangSM130::~SM130()
53765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
54765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
55765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
56765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangmraa::Result SM130::setBaudRate(int baud)
57765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
58765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_baud = baud;
59765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return m_uart.setBaudRate(baud);
60765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
61765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
62765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangstring SM130::sendCommand(CMD_T cmd, string data)
63765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
64765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  uint8_t cksum = 0;
65765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string command;
66765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
67765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // for uart, we need to add the sync bytes, 0xff, 0x00
68765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  command.push_back(0xff);
69765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  command.push_back(0x00);
70765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
71765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // compute the length - command + data
72765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  uint8_t len = 1; // command
73765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (!data.empty())
74765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    len += data.size();
75765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
76765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  command.push_back(len);
77765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
78765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  cksum += len;
79765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
80765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // now the command
81765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  command.push_back(cmd);
82765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  cksum += cmd;
83765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
84765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // now the data if any
85765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (!data.empty())
86765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
87765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      for (int i=0; i<data.size(); i++)
88765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        {
89765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          command.push_back(data[i]);
90765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          cksum += (uint8_t)data[i];
91765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        }
92765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
93765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
94765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // now add the checksum
95765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  command.push_back(cksum);
96765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
97765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang#ifdef SM130_DEBUG
98765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  cerr << "CMD: " << string2HexString(command) << endl;
99765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang#endif // SM130_DEBUG
100765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
101765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // send it
102765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_uart.writeStr(command);
103765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
104765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // if the command is SET_BAUD, then switch to the new baudrate here
105765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // before attempting to read the response (and hope it worked).
106765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (cmd == CMD_SET_BAUD)
107765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
108765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      usleep(100000); // 100ms
109765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      setBaudRate(m_baud);
110765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
111765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
112765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // now wait for a response
113765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (!m_uart.dataAvailable(defaultDelay))
114765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
115765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": timeout waiting for response" << endl;
116765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return "";
117765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
118765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
119765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = m_uart.readStr(maxLen);
120765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
121765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang#ifdef SM130_DEBUG
122765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  cerr << "RSP: " << string2HexString(resp) << endl;
123765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang#endif // SM130_DEBUG
124765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
125765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (!((uint8_t)resp[0] == 0xff && (uint8_t)resp[1] == 0x00))
126765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
127765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": invalid packet header" << endl;
128765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return "";
129765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
130765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
131765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // check size - 2 header bytes + len + cksum.
132765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.size() != ((uint8_t)resp[2] + 2 + 1 + 1))
133765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
134765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": invalid packet length, expected "
135765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang           << int((uint8_t)resp[2] + 2 + 1 + 1)
136765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang           << ", got " << resp.size() << endl;
137765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return "";
138765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
139765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
140765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // verify the cksum
141765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  cksum = 0;
142765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  for (int i=2; i<(resp.size() - 1); i++)
143765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    cksum += (uint8_t)resp[i];
144765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
145765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (cksum != (uint8_t)resp[resp.size() - 1])
146765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
147765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": invalid checksum, expected "
148765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang           << int(cksum) << ", got " << (uint8_t)resp[resp.size()-1] << endl;
149765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return "";
150765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
151765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
152765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // we could also verify that the command code returned was for the
153765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // command submitted...
154765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
155765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // now, remove the 2 header bytes and the checksum, leave the length
156765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // and command.
157765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  resp.erase(resp.size() - 1, 1); // cksum
158765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  resp.erase(0, 2);               // header bytes
159765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
160765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // return the rest
161765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return resp;
162765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
163765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
164765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangstring SM130::getFirmwareVersion()
165765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
166765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
167765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
168765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(CMD_VERSION, "");
169765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
170765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
171765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
172765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
173765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return "";
174765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
175765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
176765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // delete the len and cmd, return the rest
177765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  resp.erase(0, 2);
178765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return resp;
179765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
180765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
181765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangbool SM130::reset()
182765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
183765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
184765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
185765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(CMD_RESET, "");
186765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
187765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
188765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
189765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
190765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
191765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
192765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return true;
193765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
194765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
195765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangvoid SM130::hardwareReset()
196765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
197765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_gpioReset.write(1);
198765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  usleep(100000);
199765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_gpioReset.write(0);
200765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
201765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
202765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangbool SM130::select()
203765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
204765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
205765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
206765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_tagType = TAG_NONE;
207765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_uidLen = 0;
208765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_uid.clear();
209765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
210765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(CMD_SELECT_TAG, "");
211765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
212765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
213765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
214765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
215765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
216765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
217765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
218765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if ((uint8_t)resp[0] == 2)
219765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
220765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // then we got an error of some sort, store the error code, str
221765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // and bail.
222765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      m_lastErrorCode = resp[2];
223765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
224765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      switch (m_lastErrorCode)
225765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        {
226765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'N': m_lastErrorString = "No tag present";
227765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
228765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'U': m_lastErrorString = "Access failed, RF field is off";
229765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
230765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        default: m_lastErrorString = "Unknown error code";
231765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
232765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        }
233765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
234765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
235765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
236765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // if we are here, then store the uid info and tag type.
237765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_tagType = (TAG_TYPE_T)resp[2];
238765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
239765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if ((uint8_t)resp[0] == 6)
240765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    m_uidLen = 4;               // 4 byte uid
241765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  else
242765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    m_uidLen = 7;               // 7 byte
243765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
244765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  for (int i=0; i<m_uidLen; i++)
245765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    m_uid.push_back(resp[i+3]);
246765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
247765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return true;
248765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
249765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
250765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangbool SM130::authenticate(uint8_t block, KEY_TYPES_T keyType, string key)
251765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
252765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
253765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
254765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // A little sanity checking...
255765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (keyType == KEY_TYPE_A || keyType == KEY_TYPE_B)
256765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
257765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      if (key.empty())
258765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        throw std::invalid_argument(string(__FUNCTION__) +
259765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang                                    ": You must specify a key for type A or B");
260765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      if (key.size() != 6)
261765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        throw std::invalid_argument(string(__FUNCTION__) +
262765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang                                    ": Key size must be 6");
263765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
264765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false; // probably not reached :)
265765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
266765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  else
267765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
268765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // make sure the key is empty for any other key type
269765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      key.clear();
270765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
271765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
272765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string data;
273765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data.push_back(block);
274765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data.push_back(keyType);
275765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data += key;
276765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
277765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(CMD_AUTHENTICATE, data);
278765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
279765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
280765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
281765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
282765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
283765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
284765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
285765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // response len is always 2, 'L' means auth was successful
286765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp[2] != 'L')
287765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
288765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // then we got an error of some sort, store the error code, str
289765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // and bail.
290765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      m_lastErrorCode = resp[2];
291765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
292765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      switch (m_lastErrorCode)
293765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        {
294765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'N': m_lastErrorString = "No tag present, or login failed";
295765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
296765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'U': m_lastErrorString = "Login failed";
297765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
298765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'E': m_lastErrorString = "Invalid key format in EEPROM";
299765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
300765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        default: m_lastErrorString = "Unknown error code";
301765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
302765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        }
303765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
304765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
305765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
306765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return true;
307765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
308765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
309765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangstring SM130::readBlock16(uint8_t block)
310765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
311765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
312765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
313765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string data;
314765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
315765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data.push_back(block);
316765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
317765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(CMD_READ16, data);
318765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
319765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
320765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
321765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
322765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return "";
323765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
324765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
325765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if ((uint8_t)resp[0] == 2)
326765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
327765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // then we got an error of some sort, store the error code, str
328765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // and bail.
329765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      m_lastErrorCode = resp[2];
330765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
331765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      switch (m_lastErrorCode)
332765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        {
333765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'N': m_lastErrorString = "No tag present";
334765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
335765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'F': m_lastErrorString = "Read failed";
336765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
337765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        default: m_lastErrorString = "Unknown error code";
338765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
339765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        }
340765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
341765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return "";
342765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
343765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
344765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // trim off the len, cmd, and block # bytes and return the rest
345765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  resp.erase(0, 3);
346765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return resp;
347765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
348765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
349765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangint32_t SM130::readValueBlock(uint8_t block)
350765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
351765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
352765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
353765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string data;
354765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
355765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data.push_back(block);
356765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
357765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(CMD_READ_VALUE, data);
358765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
359765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
360765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
361765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
362765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return 0;
363765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
364765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
365765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if ((uint8_t)resp[0] == 2)
366765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
367765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // then we got an error of some sort, store the error code, str
368765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // and bail.
369765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      m_lastErrorCode = resp[2];
370765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
371765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      switch (m_lastErrorCode)
372765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        {
373765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'N': m_lastErrorString = "No tag present";
374765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
375765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'F': m_lastErrorString = "Read failed";
376765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
377765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'I': m_lastErrorString = "Invalid Value Block";
378765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
379765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        default: m_lastErrorString = "Unknown error code";
380765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
381765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        }
382765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
383765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return 0;
384765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
385765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
386765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  int32_t rv;
387765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  rv = ((uint8_t)resp[3] |
388765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        ((uint8_t)resp[4] << 8) |
389765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        ((uint8_t)resp[5] << 16) |
390765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        ((uint8_t)resp[6] << 24));
391765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
392765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return rv;
393765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
394765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
395765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangbool SM130::writeBlock16(uint8_t block, string contents)
396765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
397765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
398765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
399765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // A little sanity checking...
400765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (contents.size() != 16)
401765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
402765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      throw std::invalid_argument(string(__FUNCTION__) +
403765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang                                  ": You must supply 16 bytes for block content");
404765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
405765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
406765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
407765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
408765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string data;
409765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data.push_back(block);
410765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data += contents;
411765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
412765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(CMD_WRITE16, data);
413765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
414765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
415765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
416765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
417765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
418765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
419765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
420765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if ((uint8_t)resp[0] == 2)
421765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
422765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // then we got an error of some sort, store the error code, str
423765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // and bail.
424765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      m_lastErrorCode = resp[2];
425765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
426765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      switch (m_lastErrorCode)
427765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        {
428765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'F': m_lastErrorString = "Write failed";
429765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
430765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'N': m_lastErrorString = "No tag present";
431765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
432765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'U': m_lastErrorString = "Read after write failed";
433765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
434765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'X': m_lastErrorString = "Unable to read after write";
435765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
436765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        default: m_lastErrorString = "Unknown error code";
437765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
438765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        }
439765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
440765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
441765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
442765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return true;
443765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
444765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
445765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangbool SM130::writeValueBlock(uint8_t block, int32_t value)
446765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
447765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
448765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
449765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string data;
450765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data.push_back(block);
451765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // put the value in, LSB first
452765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data += (value & 0xff);
453765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data += ((value >> 8) & 0xff);
454765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data += ((value >> 16) & 0xff);
455765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data += ((value >> 24) & 0xff);
456765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
457765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(CMD_WRITE_VALUE, data);
458765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
459765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
460765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
461765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
462765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
463765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
464765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
465765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if ((uint8_t)resp[0] == 2)
466765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
467765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // then we got an error of some sort, store the error code, str
468765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // and bail.
469765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      m_lastErrorCode = resp[2];
470765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
471765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      switch (m_lastErrorCode)
472765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        {
473765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'F': m_lastErrorString = "Read failed during verification";
474765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
475765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'N': m_lastErrorString = "No tag present";
476765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
477765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'I': m_lastErrorString = "Invalid value block";
478765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
479765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        default: m_lastErrorString = "Unknown error code";
480765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
481765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        }
482765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
483765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
484765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
485765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return true;
486765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
487765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
488765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangbool SM130::writeBlock4(uint8_t block, string contents)
489765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
490765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
491765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
492765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // A little sanity checking...
493765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (contents.size() != 4)
494765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
495765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      throw std::invalid_argument(string(__FUNCTION__) +
496765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang                                  ": You must supply 4 bytes for block content");
497765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
498765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
499765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
500765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
501765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string data;
502765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data.push_back(block);
503765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data += contents;
504765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
505765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(CMD_WRITE4, data);
506765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
507765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
508765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
509765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
510765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
511765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
512765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
513765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if ((uint8_t)resp[0] == 2)
514765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
515765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // then we got an error of some sort, store the error code, str
516765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // and bail.
517765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      m_lastErrorCode = resp[2];
518765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
519765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      switch (m_lastErrorCode)
520765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        {
521765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'F': m_lastErrorString = "Write failed";
522765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
523765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'N': m_lastErrorString = "No tag present";
524765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
525765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'U': m_lastErrorString = "Read after write failed";
526765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
527765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'X': m_lastErrorString = "Unable to read after write";
528765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
529765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        default: m_lastErrorString = "Unknown error code";
530765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
531765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        }
532765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
533765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
534765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
535765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return true;
536765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
537765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
538765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangbool SM130::writeKey(uint8_t eepromSector, KEY_TYPES_T keyType, string key)
539765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
540765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
541765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
542765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // A little sanity checking...
543765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  eepromSector &= 0x0f; // Only 0x00-0x0f is valid
544765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
545765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (!(keyType == KEY_TYPE_A || keyType == KEY_TYPE_B))
546765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
547765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      throw std::invalid_argument(string(__FUNCTION__) +
548765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang                                  ": Key type must be A or B");
549765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
550765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
551765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
552765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
553765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (key.size() != 6)
554765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
555765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      throw std::invalid_argument(string(__FUNCTION__) +
556765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang                                  ": Key must be 6 bytes");
557765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
558765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
559765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
560765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
561765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string data;
562765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data.push_back(eepromSector);
563765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data += keyType;
564765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data += key;
565765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
566765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(CMD_WRITE_KEY, data);
567765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
568765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
569765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
570765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
571765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
572765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
573765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
574765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // reponse len is always 2
575765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if ((uint8_t)resp[2] != 'L')
576765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
577765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // then we got an error of some sort, store the error code, str
578765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // and bail.
579765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      m_lastErrorCode = resp[2];
580765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
581765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      switch (m_lastErrorCode)
582765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        {
583765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'N': m_lastErrorString = "Write master key failed";
584765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
585765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        default: m_lastErrorString = "Unknown error code";
586765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
587765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        }
588765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
589765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
590765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
591765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return true;
592765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
593765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
594765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangint32_t SM130::adjustValueBlock(uint8_t block, int32_t value, bool incr)
595765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
596765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
597765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
598765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string data;
599765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data.push_back(block);
600765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // put the value in, LSB first
601765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data += (value & 0xff);
602765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data += ((value >> 8) & 0xff);
603765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data += ((value >> 16) & 0xff);
604765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data += ((value >> 24) & 0xff);
605765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
606765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(((incr) ? CMD_INC_VALUE : CMD_DEC_VALUE), data);
607765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
608765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
609765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
610765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
611765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return 0;
612765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
613765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
614765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if ((uint8_t)resp[0] == 2)
615765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
616765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // then we got an error of some sort, store the error code, str
617765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // and bail.
618765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      m_lastErrorCode = resp[2];
619765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
620765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      switch (m_lastErrorCode)
621765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        {
622765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'F': m_lastErrorString = "Read failed during verification";
623765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
624765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'N': m_lastErrorString = "No tag present";
625765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
626765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'I': m_lastErrorString = "Invalid value block";
627765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
628765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        default: m_lastErrorString = "Unknown error code";
629765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
630765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        }
631765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return 0;
632765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
633765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
634765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // now unpack the new value, LSB first
635765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  int32_t rv;
636765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  rv = ((uint8_t)resp[3] |
637765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        ((uint8_t)resp[4] << 8) |
638765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        ((uint8_t)resp[5] << 16) |
639765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        ((uint8_t)resp[6] << 24));
640765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
641765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return rv;
642765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
643765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
644765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangbool SM130::setAntennaPower(bool on)
645765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
646765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
647765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
648765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(CMD_ANTENNA_POWER, "");
649765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
650765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
651765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
652765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
653765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
654765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
655765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
656765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return true;
657765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
658765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
659765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhanguint8_t SM130::readPorts()
660765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
661765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
662765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
663765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(CMD_READ_PORT, "");
664765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
665765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
666765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
667765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
668765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return 0;
669765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
670765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
671765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // only the first 2 bits are valid
672765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return (resp[2] & 3);
673765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
674765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
675765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangbool SM130::writePorts(uint8_t val)
676765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
677765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
678765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
679765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // only the first 2 bits are valid
680765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  val &= 3;
681765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
682765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string data;
683765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data.push_back(val);
684765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
685765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(CMD_WRITE_PORT, data);
686765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
687765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
688765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
689765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
690765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
691765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
692765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
693765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return true;
694765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
695765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
696765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangbool SM130::haltTag()
697765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
698765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
699765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
700765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(CMD_HALT_TAG, "");
701765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
702765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
703765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
704765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
705765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
706765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
707765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
708765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // reponse len is always 2
709765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if ((uint8_t)resp[2] != 'L')
710765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
711765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // then we got an error of some sort, store the error code, str
712765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      // and bail.
713765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      m_lastErrorCode = resp[2];
714765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
715765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      switch (m_lastErrorCode)
716765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        {
717765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        case 'U': m_lastErrorString = "Can not halt, RF field is off";
718765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
719765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        default: m_lastErrorString = "Unknown error code";
720765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          break;
721765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        }
722765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
723765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
724765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
725765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return true;
726765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
727765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
728765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangbool SM130::setSM130BaudRate(int baud)
729765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
730765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
731765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
732765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  uint8_t newBaud;
733765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
734765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  switch (baud)
735765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
736765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    case 9600: newBaud = 0x00;
737765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      break;
738765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    case 19200: newBaud = 0x01;
739765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      break;
740765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    case 38400: newBaud = 0x02;
741765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      break;
742765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    case 57600: newBaud = 0x03;
743765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      break;
744765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    case 115200: newBaud = 0x04;
745765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      break;
746765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    default:
747765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      throw std::invalid_argument(string(__FUNCTION__) +
748765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang                                  ": Invalid SM130 baud rate specified");
749765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
750765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
751765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // WARNING: this is a dangerous command
752765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  int oldBaud = m_baud;
753765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_baud = baud;
754765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
755765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string data;
756765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  data.push_back(newBaud);
757765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
758765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(CMD_SET_BAUD, data);
759765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
760765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
761765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
762765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
763765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": restoring old baud rate" << endl;
764765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
765765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      setBaudRate(oldBaud);
766765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
767765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
768765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
769765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // otherwise assume success, possibly incorrectly
770765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return true;
771765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
772765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
773765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangbool SM130::sleep()
774765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
775765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  clearError();
776765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
777765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string resp = sendCommand(CMD_SLEEP, "");
778765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
779765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (resp.empty())
780765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
781765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      cerr << __FUNCTION__ << ": failed" << endl;
782765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      return false;
783765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
784765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
785765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return true;
786765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
787765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
788765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangstring SM130::string2HexString(string input)
789765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
790765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  static const char* const lut = "0123456789abcdef";
791765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  size_t len = input.size();
792765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
793765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  string output;
794765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  output.reserve(3 * len);
795765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  for (size_t i = 0; i < len; ++i)
796765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
797765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      const unsigned char c = input[i];
798765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      output.push_back(lut[c >> 4]);
799765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      output.push_back(lut[c & 15]);
800765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      output.push_back(' ');
801765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
802765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
803765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return output;
804765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
805765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
806765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangvoid SM130::initClock()
807765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
808765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  gettimeofday(&m_startTime, NULL);
809765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
810765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
811765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhanguint32_t SM130::getMillis()
812765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
813765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  struct timeval elapsed, now;
814765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  uint32_t elapse;
815765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
816765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // get current time
817765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  gettimeofday(&now, NULL);
818765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
819765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // compute the delta since m_startTime
820765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if( (elapsed.tv_usec = now.tv_usec - m_startTime.tv_usec) < 0 )
821765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
822765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      elapsed.tv_usec += 1000000;
823765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      elapsed.tv_sec = now.tv_sec - m_startTime.tv_sec - 1;
824765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
825765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  else
826765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
827765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      elapsed.tv_sec = now.tv_sec - m_startTime.tv_sec;
828765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
829765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
830765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  elapse = (uint32_t)((elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000));
831765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
832765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // never return 0
833765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (elapse == 0)
834765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    elapse = 1;
835765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
836765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return elapse;
837765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
838765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
839765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangbool SM130::waitForTag(uint32_t timeout)
840765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
841765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  initClock();
842765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
843765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  do
844765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
845765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      if (select())
846765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        {
847765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          // success
848765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          return true;
849765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        }
850765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      else
851765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        {
852765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          // If there was an error, fail if it's anything other than a
853765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          // tag not present
854765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          if (getLastErrorCode() != 'N')
855765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang            return false;
856765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
857765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          // otherwise, sleep for 100ms and try again
858765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang          usleep(100000);
859765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        }
860765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    } while (getMillis() <= timeout);
861765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
862765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return false;
863765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
864765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
865765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangstring SM130::tag2String(TAG_TYPE_T tag)
866765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang{
867765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  switch (tag)
868765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    {
869765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    case TAG_MIFARE_ULTRALIGHT: return "MiFare Ultralight";
870765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    case TAG_MIFARE_1K:         return "MiFare 1K";
871765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    case TAG_MIFARE_4K:         return "MiFare 4K";
872765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    case TAG_UNKNOWN:           return "Unknown Tag Type";
873765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    default:                    return "Invalid Tag Type";
874765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
875765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
876765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
877765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
878765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
879