Sony FeliCa reader/writer (RC-S620/S) library Copyright 2010 Sony Corporation, modified by SWITCHSCIENCE, modified by Suga
Dependents: RFID_FeliCa_sample
Revision 0:ccb5446a6b93, committed 2012-05-10
- Comitter:
- okini3939
- Date:
- Thu May 10 06:13:54 2012 +0000
- Commit message:
Changed in this revision
RCS620S.cpp | Show annotated file Show diff for this revision Revisions of this file |
RCS620S.h | Show annotated file Show diff for this revision Revisions of this file |
diff -r 000000000000 -r ccb5446a6b93 RCS620S.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RCS620S.cpp Thu May 10 06:13:54 2012 +0000 @@ -0,0 +1,367 @@ +/* + * RC-S620/S sample library for Arduino + * + * Copyright 2010 Sony Corporation + * + * Rewrite for mbed + * + * modified by SWITCHSCIENCE + * https://github.com/SWITCHSCIENCE/mbed-FeliCa + * + * modified by Suga + */ + +/** @file + * @brief Sony FeliCa reader/writer (RC-S620/S) library for mbed + */ + +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include "RCS620S.h" +#include "mbed.h" + +/* -------------------------------- + * Constant + * -------------------------------- */ + +#define RCS620S_DEFAULT_TIMEOUT 1000 + +/* -------------------------------- + * Variable + * -------------------------------- */ + +/* -------------------------------- + * Prototype Declaration + * -------------------------------- */ + +/* -------------------------------- + * Macro + * -------------------------------- */ + +/* -------------------------------- + * Function + * -------------------------------- */ + +/* ------------------------ + * public + * ------------------------ */ + +RCS620S::RCS620S(PinName p_tx, PinName p_rx) : serial(p_tx, p_rx) +{ + serial.baud(115200); + this->timeout = RCS620S_DEFAULT_TIMEOUT; +} + +int RCS620S::initDevice(void) +{ + int ret; + uint8_t response[RCS620S_MAX_RW_RESPONSE_LEN]; + uint16_t responseLen; + + /* RFConfiguration (various timings) */ + ret = rwCommand((const uint8_t*)"\xd4\x32\x02\x00\x00\x00", 6, + response, &responseLen); + if (!ret || (responseLen != 2) || + (memcmp(response, "\xd5\x33", 2) != 0)) { + return 0; + } + + /* RFConfiguration (max retries) */ + ret = rwCommand((const uint8_t*)"\xd4\x32\x05\x00\x00\x00", 6, + response, &responseLen); + if (!ret || (responseLen != 2) || + (memcmp(response, "\xd5\x33", 2) != 0)) { + return 0; + } + + /* RFConfiguration (additional wait time = 24ms) */ + ret = rwCommand((const uint8_t*)"\xd4\x32\x81\xb7", 4, + response, &responseLen); + if (!ret || (responseLen != 2) || + (memcmp(response, "\xd5\x33", 2) != 0)) { + return 0; + } + + return 1; +} + +int RCS620S::polling(uint16_t systemCode) +{ + int ret; + uint8_t buf[9]; + uint8_t response[RCS620S_MAX_RW_RESPONSE_LEN]; + uint16_t responseLen; + + /* InListPassiveTarget */ + memcpy(buf, "\xd4\x4a\x01\x01\x00\xff\xff\x00\x00", 9); + buf[5] = (uint8_t)((systemCode >> 8) & 0xff); + buf[6] = (uint8_t)((systemCode >> 0) & 0xff); + + ret = rwCommand(buf, 9, response, &responseLen); + if (!ret || (responseLen != 22) || + (memcmp(response, "\xd5\x4b\x01\x01\x12\x01", 6) != 0)) { + return 0; + } + + memcpy(this->idm, response + 6, 8); + memcpy(this->pmm, response + 14, 8); + + return 1; +} + +int RCS620S::cardCommand( + const uint8_t* command, + uint8_t commandLen, + uint8_t response[RCS620S_MAX_CARD_RESPONSE_LEN], + uint8_t* responseLen) +{ + int ret; + uint16_t commandTimeout; + uint8_t buf[RCS620S_MAX_RW_RESPONSE_LEN]; + uint16_t len; + + if (this->timeout >= (0x10000 / 2)) { + commandTimeout = 0xffff; + } else { + commandTimeout = (uint16_t)(this->timeout * 2); + } + + /* CommunicateThruEX */ + buf[0] = 0xd4; + buf[1] = 0xa0; + buf[2] = (uint8_t)((commandTimeout >> 0) & 0xff); + buf[3] = (uint8_t)((commandTimeout >> 8) & 0xff); + buf[4] = (uint8_t)(commandLen + 1); + memcpy(buf + 5, command, commandLen); + + ret = rwCommand(buf, 5 + commandLen, buf, &len); + if (!ret || (len < 4) || + (buf[0] != 0xd5) || (buf[1] != 0xa1) || (buf[2] != 0x00) || + (len != (3 + buf[3]))) { + return 0; + } + + *responseLen = (uint8_t)(buf[3] - 1); + memcpy(response, buf + 4, *responseLen); + + return 1; +} + +int RCS620S::rfOff(void) +{ + int ret; + uint8_t response[RCS620S_MAX_RW_RESPONSE_LEN]; + uint16_t responseLen; + + /* RFConfiguration (RF field) */ + ret = rwCommand((const uint8_t*)"\xd4\x32\x01\x00", 4, + response, &responseLen); + if (!ret || (responseLen != 2) || + (memcmp(response, "\xd5\x33", 2) != 0)) { + return 0; + } + + return 1; +} + +int RCS620S::push( + const uint8_t* data, + uint8_t dataLen) +{ + int ret; + uint8_t buf[RCS620S_MAX_CARD_RESPONSE_LEN]; + uint8_t responseLen; + + if (dataLen > 224) { + return 0; + } + + /* Push */ + buf[0] = 0xb0; + memcpy(buf + 1, this->idm, 8); + buf[9] = dataLen; + memcpy(buf + 10, data, dataLen); + + ret = cardCommand(buf, 10 + dataLen, buf, &responseLen); + if (!ret || (responseLen != 10) || (buf[0] != 0xb1) || + (memcmp(buf + 1, this->idm, 8) != 0) || (buf[9] != dataLen)) { + return 0; + } + + buf[0] = 0xa4; + memcpy(buf + 1, this->idm, 8); + buf[9] = 0x00; + + ret = cardCommand(buf, 10, buf, &responseLen); + if (!ret || (responseLen != 10) || (buf[0] != 0xa5) || + (memcmp(buf + 1, this->idm, 8) != 0) || (buf[9] != 0x00)) { + return 0; + } + + wait(1); + return 1; +} + +/* ------------------------ + * private + * ------------------------ */ + +int RCS620S::rwCommand( + const uint8_t* command, + uint16_t commandLen, + uint8_t response[RCS620S_MAX_RW_RESPONSE_LEN], + uint16_t* responseLen) +{ + int ret; + uint8_t buf[9]; + + flushSerial(); + + uint8_t dcs = calcDCS(command, commandLen); + + /* transmit the command */ + buf[0] = 0x00; + buf[1] = 0x00; + buf[2] = 0xff; + if (commandLen <= 255) { + /* normal frame */ + buf[3] = commandLen; + buf[4] = (uint8_t)-buf[3]; + writeSerial(buf, 5); + } else { + /* extended frame */ + buf[3] = 0xff; + buf[4] = 0xff; + buf[5] = (uint8_t)((commandLen >> 8) & 0xff); + buf[6] = (uint8_t)((commandLen >> 0) & 0xff); + buf[7] = (uint8_t)-(buf[5] + buf[6]); + writeSerial(buf, 8); + } + writeSerial(command, commandLen); + buf[0] = dcs; + buf[1] = 0x00; + writeSerial(buf, 2); + + /* receive an ACK */ + ret = readSerial(buf, 6); + if (!ret || (memcmp(buf, "\x00\x00\xff\x00\xff\x00", 6) != 0)) { + cancel(); + return 0; + } + + /* receive a response */ + ret = readSerial(buf, 5); + if (!ret) { + cancel(); + return 0; + } else if (memcmp(buf, "\x00\x00\xff", 3) != 0) { + return 0; + } + if ((buf[3] == 0xff) && (buf[4] == 0xff)) { + ret = readSerial(buf + 5, 3); + if (!ret || (((buf[5] + buf[6] + buf[7]) & 0xff) != 0)) { + return 0; + } + *responseLen = (((uint16_t)buf[5] << 8) | + ((uint16_t)buf[6] << 0)); + } else { + if (((buf[3] + buf[4]) & 0xff) != 0) { + return 0; + } + *responseLen = buf[3]; + } + if (*responseLen > RCS620S_MAX_RW_RESPONSE_LEN) { + return 0; + } + + ret = readSerial(response, *responseLen); + if (!ret) { + cancel(); + return 0; + } + + dcs = calcDCS(response, *responseLen); + + ret = readSerial(buf, 2); + if (!ret || (buf[0] != dcs) || (buf[1] != 0x00)) { + cancel(); + return 0; + } + + return 1; +} + +void RCS620S::cancel(void) +{ + /* transmit an ACK */ + writeSerial((const uint8_t*)"\x00\x00\xff\x00\xff\x00", 6); + wait(1); + flushSerial(); +} + +uint8_t RCS620S::calcDCS( + const uint8_t* data, + uint16_t len) +{ + uint8_t sum = 0; + + for (uint16_t i = 0; i < len; i++) { + sum += data[i]; + } + + return (uint8_t)-(sum & 0xff); +} + +void RCS620S::writeSerial( + const uint8_t* data, + uint16_t len) +{ +// Serial.write(data, len); + uint16_t nwrite = 0; + + while (nwrite < len) { + serial.putc( *(data + nwrite) ); + nwrite++; + } +} + + +int RCS620S::readSerial( + uint8_t* data, + uint16_t len) +{ + uint16_t nread = 0; + time_t t0 = time(NULL); + + while (nread < len) { + if ((checkTimeout(t0))) { + return 0; + } + + if (serial.readable() > 0) { + data[nread] = serial.getc(); + nread++; + } + } + + return 1; +} + + +void RCS620S::flushSerial(void) +{ + while( serial.readable() ); +} + + +int RCS620S::checkTimeout(time_t t0) +{ + time_t t = time(NULL); + + if ((t - t0) >= this->timeout) { + return 1; + } + + return 0; +}
diff -r 000000000000 -r ccb5446a6b93 RCS620S.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RCS620S.h Thu May 10 06:13:54 2012 +0000 @@ -0,0 +1,83 @@ +/* + * RC-S620/S sample library for Arduino + * + * Copyright 2010 Sony Corporation + * + * Rewrite for mbed + * + * modified by SWITCHSCIENCE + * https://github.com/SWITCHSCIENCE/mbed-FeliCa + * + * modified by Suga + */ + +/** @file + * @brief Sony FeliCa reader/writer (RC-S620/S) library for mbed + */ + +#include "mbed.h" +#include <inttypes.h> + +#ifndef RCS620S_H_ +#define RCS620S_H_ + +/* -------------------------------- + * Constant + * -------------------------------- */ + +#define RCS620S_MAX_CARD_RESPONSE_LEN 254 +#define RCS620S_MAX_RW_RESPONSE_LEN 265 + +/* -------------------------------- + * Class Declaration + * -------------------------------- */ + +class RCS620S +{ +public: + RCS620S(PinName p_tx, PinName p_rx); + + int initDevice(void); + int polling(uint16_t systemCode = 0xffff); + int cardCommand( + const uint8_t* command, + uint8_t commandLen, + uint8_t response[RCS620S_MAX_CARD_RESPONSE_LEN], + uint8_t* responseLen); + int rfOff(void); + + int push( + const uint8_t* data, + uint8_t dataLen); + +private: + int rwCommand( + const uint8_t* command, + uint16_t commandLen, + uint8_t response[RCS620S_MAX_RW_RESPONSE_LEN], + uint16_t* responseLen); + void cancel(void); + uint8_t calcDCS( + const uint8_t* data, + uint16_t len); + + void writeSerial( + const uint8_t* data, + uint16_t len); + int readSerial( + uint8_t* data, + uint16_t len); + void flushSerial(void); + + int checkTimeout(time_t t0); + +public: + time_t timeout; + uint8_t idm[8]; + uint8_t pmm[8]; + +private: + Serial serial; +}; + +#endif /* !RCS620S_H_ */