Sony FeliCa reader/writer (RC-S620/S) library Copyright 2010 Sony Corporation, modified by SWITCHSCIENCE, modified by Suga

Dependents:   RFID_FeliCa_sample

Files at this revision

API Documentation at this revision

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_ */