大理水控初始版本
diff --git a/supwisdom/sp_card.c b/supwisdom/sp_card.c
new file mode 100644
index 0000000..5c6796a
--- /dev/null
+++ b/supwisdom/sp_card.c
@@ -0,0 +1,98 @@
+#include "../nec_apdu.h"
+#include "sp_des.h"
+#include "sp_constant.h"
+#include "sp_util.h"
+#include "sp_card.h"
+
+static uint8* prcv_buff = NULL;
+static uint8 rcv_len = 0;
+
+uint16 sp_select_sfi(uint8 sfi[2])
+{
+  uint16 ret;
+  uint8  cmd_buff[10];
+
+  cmd_buff[0] = 0x00; //CLA
+  cmd_buff[1] = 0xA4; //INS
+  cmd_buff[2] = 0x00; //P1
+  cmd_buff[3] = 0x00; //P2
+  cmd_buff[4] = 0x02; //Lc
+  memcpy(cmd_buff + 5, sfi, 2);
+
+  ret = card_cpu_exchange(cmd_buff, 2 + 5, 0, &prcv_buff, &rcv_len);
+  if(ret != RETCODE_OK)
+  {
+    return ret;
+  }
+  return 0;
+}
+
+uint16 sp_select_adf(void)
+{
+  uint16 ret;
+  uint8  cmd_buff[] = {"\x00\xA4\x04\x00\x0F\xD1\x56\x00\x00\x01\xBD\xF0\xCA\xCB\xB4\xEF\xD6\xA7\xB8\xB6"};
+  ret = card_cpu_exchange(cmd_buff, sizeof(cmd_buff) - 1, 0, &prcv_buff, &rcv_len);
+  if(ret != RETCODE_OK)
+  {
+    return ret;
+  }
+  return 0;
+}
+
+uint8 sp_card_request(sp_card_t* cardpcd)
+{
+
+  uint8 sak;
+  uint8 snr[8];
+
+  if(!card_request(&sak, snr))
+  {
+    if((sak & 0x20))
+    {
+      if(!card_cpu_mode())
+      {
+        Delay_ms(200);
+		if(sp_select_sfi("\x3f\x00") == 0)
+        {
+          sp_select_adf();
+          cardpcd->cardphyid[0] = snr[3];
+          cardpcd->cardphyid[1] = snr[2];
+          cardpcd->cardphyid[2] = snr[1];
+          cardpcd->cardphyid[3] = snr[0];
+          cardpcd->cardtype = TAG_TYPE_CPU;
+          return 0;
+        }
+      }
+    }
+    else
+    {
+      cardpcd->cardtype = TAG_TYPE_UNKONWN;
+	  return 1;
+    }
+  }
+  return 1;
+}
+
+int8 sp_check_cpu_exist(void)
+{
+  return card_cpu_exist();
+}
+
+static uint16 sp_cpu_read(sp_card_t* card)
+{
+  uint16 ret = 0;
+  MEMCLEAR(card->citizen_cardno, sizeof(card->citizen_cardno));
+  MEMCPY(card->expiredate, "\x20\x22\x08\x02", 4);
+  return ret;
+}
+
+uint16 sp_card_read(sp_card_t* card)
+{
+  switch(card->cardtype)
+  {
+  case TAG_TYPE_CPU:
+    return sp_cpu_read(card);
+  default:
+    return 1;
+  }
+}