TL;DR(要約)
- 目的は、簡易的な入退館システムとして、NFCタグのIDmを読み取りたい。
- ここでは、Windowsで、開発言語として.NET、リーダとして「PaSoRi RC-S380」を利用し、NFCタグのIDmを読み取る方法について記載している。
「PC/SCを利用して実装する」に基づいたソース
参考:https://log.windows78.net/2015/03/1295/
このラッパークラスを使えばTypeA(Mifare), TypeB, FeliCa の ID を読み取ることが出来ます。VB.netでの実装ノウハウがネット上に少なく苦労しましたので、メモ書きとしてここに残したいと思います
上記サイトを参考に整理したソースを記載いたします。
ほとんどの内容は、上記サイト製作者様による成果となります。
環境
- Windows 10 64bit
- PaSoRi RC-S380
- Visual Studio 2019
- .Net Framework 3.5
- NFCポートソフトウェア
注意点
- Felicaのみ動作確認
- Sugoca、および購入したNFCタグでは動作確認済み
- ソース内でカードリーダーの名称をバイト配列から文字列に変換するところがうまくいかなかったため、以下のように埋め込みとしています。ぜひ間違いをご指摘いただけますと助かります。
Me.CardReaderName = System.Text.Encoding.Unicode.GetString(mszReaders)
Me.CardReaderName = Me.CardReaderName.Substring(0, Me.CardReaderName.IndexOf(vbNullChar))
Me.CardReaderName = "Sony FeliCa Port/PaSoRi 3.0 0"
-
コメントにて、上記の解決方法をご指摘いただきました!@anchanBiz さんありがとうございます。
関連:https://www.pinvoke.net/default.aspx/winscard.scardlistreaders
Me.CardReaderName = Encoding.ASCII.GetString(mszReaders).Split(vbNullChar.ToCharArray)(0)
-
SCardConnect
での指定WinSCardWrapper.SCARD_PROTOCOL_T0 Or WinSCardWrapper.SCARD_PROTOCOL_T1
は、WinSCardWrapper.SCARD_PROTOCOL_T1
でよい可能性があります。
ソース
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim cardNoNumeric = ""
If IDCardUtility.TryGetCardNoNumeric(cardNoNumeric) Then
txtICtag.Text = cardNoNumeric.ToLower
Else
txtICtag.Text = ""
End If
End Sub
'https://log.windows78.net/2015/03/1295/
Public Class IDCardUtility
Private Sub New()
End Sub
Public Shared Function TryGetCardNo(ByRef cardNo As String) As Boolean
cardNo = ""
Dim c = New WinSCard
If Not c.TrySCardEstablishContext() Then Return False
If Not c.TrySCardListReaders() Then Return False
c.ProcessState = WinSCard.EnumProcessState.State3
If Not c.TrySCardConnect() Then Return False
If Not c.TrySCardTransmit() Then Return False
If Not c.TrySCardDisconnect() Then Return False
cardNo = c.CardNo
Return True
End Function
Public Shared Function TryGetCardNoNumeric(ByRef cardNoNumeric As String) As Boolean
cardNoNumeric = ""
Dim c = New WinSCard
If Not c.TrySCardEstablishContext() Then Return False
If Not c.TrySCardListReaders() Then Return False
c.ProcessState = WinSCard.EnumProcessState.State3
If Not c.TrySCardConnect() Then Return False
If Not c.TrySCardTransmit() Then Return False
If Not c.TrySCardDisconnect() Then Return False
cardNoNumeric = c.CardNoNumeric
Return True
End Function
End Class
'-----------------------------------------------------------
' All Rights Reserved , Copyright (C) 2014
'https://log.windows78.net/2015/03/1295/
'-----------------------------------------------------------
Imports System.Runtime.InteropServices
Imports System.Text
Public Class WinSCard
Public Enum EnumProcessState
State0 = 0
State1 = 1
State2 = 2
State3 = 3
State4 = 4
State5 = 5
End Enum
Public ProcessState As EnumProcessState
Public CardReaderName As String
Public SerialNumber As String
''' <summary>
''' FelicaのIDmやMifareのUID
''' </summary>
Public CardNo As String
Public CardType As Integer '0:Felica 1:Mifare
Private hCard As IntPtr
Private hContext As IntPtr
Private ReadOnly intPolling As Integer = 500 'ICカードを読み込むポーリング間隔
Private readerState As WinSCardWrapper.SCARD_READERSTATE = New WinSCardWrapper.SCARD_READERSTATE
Public ReadOnly Property CardNoNumeric As String
Get
Return Me.CardNo.Replace("-"c, "")
End Get
End Property
Public Sub New()
Me.ProcessState = EnumProcessState.State0
hContext = IntPtr.Zero
CardReaderName = vbNullString
SerialNumber = vbNullString
hCard = IntPtr.Zero
CardNo = String.Empty
'state.dwCurrentState = WinSCardWrapper.SCARD_STATE_EMPTY
readerState.dwCurrentState = WinSCardWrapper.SCARD_STATE_UNAWARE
End Sub
Public Function TrySCardEstablishContext() As Boolean
If Me.ProcessState <> EnumProcessState.State0 Then Return False
'変数定義
'SmartCardサービスの確認
Dim URtn As UInteger = WinSCardWrapper.SCardEstablishContext(WinSCardWrapper.SCARD_SCOPE_USER,
IntPtr.Zero,
IntPtr.Zero,
Me.hContext)
If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
'エラー内容をスロー
Throw New Exception($"{URtn}:{WinSCardWrapper.GetErrorMessage(URtn)}")
End If
Me.ProcessState = EnumProcessState.State1
Return True
End Function
Public Function TrySCardListReaders() As Boolean
If Me.ProcessState <> WinSCard.EnumProcessState.State1 Then Return False
Dim pcchReaders As UInteger = 0
Dim mszReaders As Byte()
'変数定義
'接続されているカードリーダーを確認
'ここで取得できるカードリーダーの名前はNull文字で区切られた文字数
Dim URtn As UInteger = WinSCardWrapper.SCardListReaders(Me.hContext, Nothing, Nothing, pcchReaders)
If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
'エラー内容をスロー
Throw New Exception($"{URtn}:{WinSCardWrapper.GetErrorMessage(URtn)}")
End If
'接続されているカードリーダの名前を取得
'ここで取得できるカードリーダーの名前はNull文字で区切られたバイト配列(2バイト1文字)
mszReaders = New Byte(Convert.ToInt32(pcchReaders) * 2 - 1) {}
URtn = WinSCardWrapper.SCardListReaders(Me.hContext, Nothing, mszReaders, pcchReaders)
If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
'エラー内容をスロー
Throw New Exception($"{URtn}:{WinSCardWrapper.GetErrorMessage(URtn)}")
End If
' 例:"Sony FeliCa Port/PaSoRi 3.0 0"
Me.CardReaderName = Encoding.ASCII.GetString(mszReaders).Split(vbNullChar.ToCharArray)(0)
'状態を1→2に遷移
Me.ProcessState = EnumProcessState.State2
Return True
End Function
Public Function TrySCardGetStatusChange() As Boolean
If Me.ProcessState <> WinSCard.EnumProcessState.State2 Then Return False
readerState.szReader = Me.CardReaderName
'変数定義
'SmartCardステータス遷移
Dim URtn As UInteger = WinSCardWrapper.SCardGetStatusChange(Me.hContext, -1, readerState, 1)
If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
'エラー内容をスロー
Throw New Exception($"{URtn}:{WinSCardWrapper.GetErrorMessage(URtn)}")
End If
'状態遷移
If readerState.dwEventState = WinSCardWrapper.SCARD_STATE_PRESENT Then
'状態を2→3に遷移
Me.ProcessState = EnumProcessState.State3
Return True
Else
Return False
End If
End Function
Public Function TrySCardConnect() As Boolean
If Me.ProcessState <> WinSCard.EnumProcessState.State3 Then Return False
Dim pdwActiveProtocol As IntPtr = IntPtr.Zero
'変数定義
'カードを確認
Dim URtn As UInteger = WinSCardWrapper.SCardConnect(Me.hContext,
Me.CardReaderName,
WinSCardWrapper.SCARD_SHARE_SHARED,
WinSCardWrapper.SCARD_PROTOCOL_T0 Or WinSCardWrapper.SCARD_PROTOCOL_T1,
Me.hCard, pdwActiveProtocol)
If URtn = WinSCardWrapper.SCARD_S_SUCCESS Then
'続行
ElseIf URtn = WinSCardWrapper.GetUInteger(WinSCardWrapper.SCARD_W_REMOVED_CARD) Then
'continue
System.Threading.Thread.Sleep(intPolling)
Return False
Else
'エラー内容をスロー
Throw New Exception($"{URtn}:{WinSCardWrapper.GetErrorMessage(URtn)}")
End If
'※以下のカードシリアル番号取得は別になくても構わない・・・たぶん
Dim controlCode As Integer = &H3136B0
Dim sendBuffer As Byte() = New Byte() {&HC0, &H8}
Dim recvBuffer As Byte() = New Byte(64) {}
Dim bytesReturned As Integer = 0
'カードシリアル番号取得
URtn = WinSCardWrapper.SCardControl(
Me.hCard, controlCode, sendBuffer,
sendBuffer.Length,
recvBuffer,
recvBuffer.Length,
bytesReturned)
If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
'エラー内容をスロー
Throw New Exception($"{URtn}:{WinSCardWrapper.GetErrorMessage(URtn)}")
End If
Me.SerialNumber = (New ASCIIEncoding).GetString(recvBuffer, 0, bytesReturned - 1)
Me.ProcessState = EnumProcessState.State4
Return True
End Function
Public Function TrySCardTransmit() As Boolean
If Me.ProcessState <> WinSCard.EnumProcessState.State4 Then Return False
Dim sendBuffer As Byte() = New Byte() {&HFF, &HCA, &H0, &H0, &H0} 'Felica IDm取得コマンド
'Dim sendBuffer As Byte() = New Byte() {&HFF, &HCA, &H0, &H0, &H4} 'Mifare UID取得コマンド
Dim recvBuffer As Byte() = New Byte(511) {}
Dim recvBufferLen As Integer = recvBuffer.Length
'動的にライブラリのポインタを取得・・・
Dim hLoader As IntPtr = WinSCardWrapper.LoadLibrary("winscard.dll")
Dim SCARD_PCI_T1 As IntPtr = WinSCardWrapper.GetProcAddress(hLoader, "g_rgSCardT1Pci")
WinSCardWrapper.FreeLibrary(hLoader)
Dim pioRecvRequest As WinSCardWrapper.SCARD_IO_REQUEST = Nothing
'変数定義
Dim URtn As UInteger = WinSCardWrapper.SCardTransmit(Me.hCard, SCARD_PCI_T1, sendBuffer, sendBuffer.Length, pioRecvRequest, recvBuffer, recvBufferLen)
If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
'エラー内容をスロー
Throw New Exception($"{URtn}:{WinSCardWrapper.GetErrorMessage(URtn)}")
End If
'Me.mCardNo = BitConverter.ToString(recvBuffer, 0, recvBufferLen - 2).Replace("-", "")
Me.CardNo = BitConverter.ToString(recvBuffer, 0, recvBufferLen - 2)
Me.ProcessState = EnumProcessState.State5
Return True
End Function
Public Function TrySCardDisconnect() As Boolean
If Me.ProcessState <> WinSCard.EnumProcessState.State5 Then Return False
'変数定義
'カード解放
Dim URtn As UInteger = WinSCardWrapper.SCardDisconnect(hCard, WinSCardWrapper.SCARD_LEAVE_CARD)
If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
'カードの解放に失敗
End If
Return True
End Function
Public Sub SCardFreeMemory()
'変数定義
Dim URtn As UInteger = WinSCardWrapper.SCardFreeMemory(hContext, CardReaderName)
If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
'カードリーダーの解放に失敗
End If
End Sub
Public Sub SCardReleaseContext()
'変数定義
Dim URtn As UInteger = WinSCardWrapper.SCardReleaseContext(hContext)
If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
'カードリーダーの解放に失敗
End If
End Sub
Private Class WinSCardWrapper
Public Const SCARD_S_SUCCESS As Integer = 0
Public Const SCARD_F_INTERNAL_ERROR As Integer = &H80100001
Public Const SCARD_E_CANCELLED As Integer = &H80100002
Public Const SCARD_E_INVALID_HANDLE As Integer = &H80100003
Public Const SCARD_E_INVALID_PARAMETER As Integer = &H80100004
Public Const SCARD_E_INVALID_TARGET As Integer = &H80100005
Public Const SCARD_E_NO_MEMORY As Integer = &H80100006
Public Const SCARD_F_WAITED_TOO_LONG As Integer = &H80100007
Public Const SCARD_E_INSUFFICIENT_BUFFER As Integer = &H80100008
Public Const SCARD_E_UNKNOWN_READER As Integer = &H80100009
Public Const SCARD_E_TIMEOUT As Integer = &H8010000A
Public Const SCARD_E_SHARING_VIOLATION As Integer = &H8010000B
Public Const SCARD_E_NO_SMARTCARD As Integer = &H8010000C
Public Const SCARD_E_UNKNOWN_CARD As Integer = &H8010000D
Public Const SCARD_E_CANT_DISPOSE As Integer = &H8010000E
Public Const SCARD_E_PROTO_MISMATCH As Integer = &H8010000F
Public Const SCARD_E_NOT_READY As Integer = &H80100010
Public Const SCARD_E_INVALID_VALUE As Integer = &H80100011
Public Const SCARD_E_SYSTEM_CANCELLED As Integer = &H80100012
Public Const SCARD_E_COMM_ERROR As Integer = &H80100013
Public Const SCARD_F_UNKNOWN_ERROR As Integer = &H80100014
Public Const SCARD_E_INVALID_ATR As Integer = &H80100015
Public Const SCARD_E_NOT_TRANSACTED As Integer = &H80100016
Public Const SCARD_E_READER_UNAVAILABLE As Integer = &H80100017
Public Const SCARD_P_SHUTDOWN As Integer = &H80100018
Public Const SCARD_E_PCI_TOO_SMALL As Integer = &H80100019
Public Const SCARD_E_READER_UNSUPPORTED As Integer = &H8010001A
Public Const SCARD_E_DUPLICATE_READER As Integer = &H8010001B
Public Const SCARD_E_CARD_UNSUPPORTED As Integer = &H8010001C
Public Const SCARD_E_NO_SERVICE As Integer = &H8010001D
Public Const SCARD_E_SERVICE_STOPPED As Integer = &H8010001E
Public Const SCARD_E_UNEXPECTED As Integer = &H8010001F
Public Const SCARD_E_ICC_INSTALLATION As Integer = &H80100020
Public Const SCARD_E_ICC_CREATEORDER As Integer = &H80100021
Public Const SCARD_E_UNSUPPORTED_FEATURE As Integer = &H80100022
Public Const SCARD_E_DIR_NOT_FOUND As Integer = &H80100023
Public Const SCARD_E_FILE_NOT_FOUND As Integer = &H80100024
Public Const SCARD_E_NO_DIR As Integer = &H80100025
Public Const SCARD_E_NO_FILE As Integer = &H80100026
Public Const SCARD_E_NO_ACCESS As Integer = &H80100027
Public Const SCARD_E_WRITE_TOO_MANY As Integer = &H80100028
Public Const SCARD_E_BAD_SEEK As Integer = &H80100029
Public Const SCARD_E_INVALID_CHV As Integer = &H8010002A
Public Const SCARD_E_UNKNOWN_RES_MNG As Integer = &H8010002B
Public Const SCARD_E_NO_SUCH_CERTIFICATE As Integer = &H8010002C
Public Const SCARD_E_CERTIFICATE_UNAVAILABLE As Integer = &H8010002D
Public Const SCARD_E_NO_READERS_AVAILABLE As Integer = &H8010002E
Public Const SCARD_E_COMM_DATA_LOST As Integer = &H8010002F
Public Const SCARD_E_NO_KEY_CONTAINER As Integer = &H80100030
Public Const SCARD_E_SERVER_TOO_BUSY As Integer = &H80100031
Public Const SCARD_E_PIN_CACHE_EXPIRED As Integer = &H80100032
Public Const SCARD_E_NO_PIN_CACHE As Integer = &H80100033
Public Const SCARD_E_READ_ONLY_CARD As Integer = &H80100034
Public Const SCARD_W_UNSUPPORTED_CARD As Integer = &H80100065
Public Const SCARD_W_UNRESPONSIVE_CARD As Integer = &H80100066
Public Const SCARD_W_UNPOWERED_CARD As Integer = &H80100067
Public Const SCARD_W_RESET_CARD As Integer = &H80100068
Public Const SCARD_W_REMOVED_CARD As Integer = &H80100069
Public Const SCARD_W_SECURITY_VIOLATION As Integer = &H8010006A
Public Const SCARD_W_WRONG_CHV As Integer = &H8010006B
Public Const SCARD_W_CHV_BLOCKED As Integer = &H8010006C
Public Const SCARD_W_EOF As Integer = &H8010006D
Public Const SCARD_W_CANCELLED_BY_USER As Integer = &H8010006E
Public Const SCARD_W_CARD_NOT_AUTHENTICATED As Integer = &H8010006F
Public Const SCARD_W_CACHE_ITEM_NOT_FOUND As Integer = &H80100070
Public Const SCARD_W_CACHE_ITEM_STALE As Integer = &H80100071
Public Const SCARD_W_CACHE_ITEM_TOO_BIG As Integer = &H80100072
Public Const SCARD_PROTOCOL_T0 As Integer = 1
Public Const SCARD_PROTOCOL_T1 As Integer = 2
Public Const SCARD_PROTOCOL_RAW As Integer = 4
Public Const SCARD_SCOPE_USER As UInteger = 0
Public Const SCARD_SCOPE_TERMINAL As UInteger = 1
Public Const SCARD_SCOPE_SYSTEM As UInteger = 2
Public Const SCARD_STATE_UNAWARE As Integer = &H0
Public Const SCARD_STATE_IGNORE As Integer = &H1
Public Const SCARD_STATE_CHANGED As Integer = &H2
Public Const SCARD_STATE_UNKNOWN As Integer = &H4
Public Const SCARD_STATE_UNAVAILABLE As Integer = &H8
Public Const SCARD_STATE_EMPTY As Integer = &H10
Public Const SCARD_STATE_PRESENT As Integer = &H20
Public Const SCARD_STATE_AIRMATCH As Integer = &H40
Public Const SCARD_STATE_EXCLUSIVE As Integer = &H80
Public Const SCARD_STATE_INUSE As Integer = &H100
Public Const SCARD_STATE_MUTE As Integer = &H200
Public Const SCARD_STATE_UNPOWERED As Integer = &H400
Public Const SCARD_SHARE_EXCLUSIVE As Integer = &H1
Public Const SCARD_SHARE_SHARED As Integer = &H2
Public Const SCARD_SHARE_DIRECT As Integer = &H3
Public Const SCARD_LEAVE_CARD As Integer = 0
Public Const SCARD_RESET_CARD As Integer = 1
Public Const SCARD_UNPOWER_CARD As Integer = 2
Public Const SCARD_EJECT_CARD As Integer = 3
<DllImport("winscard.dll")>
Public Shared Function SCardEstablishContext(ByVal dwScope As UInteger,
ByVal pvReserved1 As IntPtr,
ByVal pvReserved2 As IntPtr,
ByRef phContext As IntPtr) As UInteger
End Function
<DllImport("winscard.dll")>
Public Shared Function SCardListReaders(ByVal hContext As IntPtr,
ByVal mszGroups As Byte(),
ByVal mszReaders As Byte(),
ByRef pcchReaders As UInt32) As UInteger
End Function
<DllImport("winscard.dll")>
Public Shared Function SCardReleaseContext(ByVal phContext As IntPtr) As UInteger
End Function
<DllImport("winscard.dll")>
Public Shared Function SCardConnect(ByVal hContext As IntPtr,
ByVal szReader As String,
ByVal dwShareMode As UInteger,
ByVal dwPreferredProtocols As UInteger,
ByRef phCard As IntPtr,
ByRef pdwActiveProtocol As IntPtr) As UInteger
End Function
<DllImport("winscard.dll")>
Public Shared Function SCardDisconnect(ByVal hCard As IntPtr,
ByVal Disposition As Integer) As UInteger
End Function
Public Class SCARD_IO_REQUEST
Friend dwProtocol As UInteger
Friend cbPciLength As Integer
Public Sub New()
dwProtocol = 0
End Sub
End Class
<DllImport("winscard.dll")>
Public Shared Function SCardStatus(ByVal hCard As IntPtr,
ByVal szReaderName As String,
ByVal SendBuff As Byte(),
ByVal SendBuffLen As Integer,
ByVal pioRecvRequest As SCARD_IO_REQUEST,
ByVal RecvBuff As Byte(),
ByRef RecvBuffLen As Integer) As UInteger
End Function
<DllImport("winscard.dll")>
Public Shared Function SCardTransmit(ByVal hCard As IntPtr,
ByVal pioSendRequest As IntPtr,
ByVal SendBuff As Byte(),
ByVal SendBuffLen As Integer,
ByVal pioRecvRequest As SCARD_IO_REQUEST,
ByVal RecvBuff As Byte(),
ByRef RecvBuffLen As Integer) As UInteger
End Function
<DllImport("winscard.dll")>
Public Shared Function SCardControl(ByVal hCard As IntPtr,
ByVal controlCode As Integer,
ByVal inBuffer As Byte(),
ByVal inBufferLen As Integer,
ByVal outBuffer As Byte(),
ByVal outBufferLen As Integer,
ByRef bytesReturned As Integer) As UInteger
End Function
Public Structure SCARD_READERSTATE
Friend szReader As String
Friend pvUserData As IntPtr
Friend dwCurrentState As UInt32
Friend dwEventState As UInt32
Friend cbAtr As UInt32
Friend rgbAtr As Byte()
End Structure
<DllImport("winscard.dll")>
Public Shared Function SCardGetStatusChange(ByVal hContext As IntPtr,
ByVal dwTimeout As Integer,
ByVal rgReaderStates As SCARD_READERSTATE,
ByVal cReaders As Integer) As UInteger
End Function
<DllImport("winscard.dll")>
Public Shared Function SCardFreeMemory(ByVal hContext As IntPtr,
ByVal szReader As String) As UInteger
End Function
<DllImport("kernel32.dll")>
Public Shared Function LoadLibrary(ByVal lpFileName As String) As IntPtr
End Function
<DllImport("kernel32.dll")>
Public Shared Sub FreeLibrary(ByVal handle As IntPtr)
End Sub
<DllImport("kernel32.dll")>
Public Shared Function GetProcAddress(ByVal handle As IntPtr,
ByVal procName As String) As IntPtr
End Function
Public Shared Function GetErrorMessage(ByVal errNo As UInteger) As String
Dim strMessage As String
Select Case errNo
Case WinSCardWrapper.GetUInteger(SCARD_F_INTERNAL_ERROR)
strMessage = errNo.ToString + " INTERNAL ERROR"
Case WinSCardWrapper.GetUInteger(SCARD_E_CANCELLED)
strMessage = errNo.ToString + " CANCELLED"
Case WinSCardWrapper.GetUInteger(SCARD_E_INVALID_HANDLE)
strMessage = errNo.ToString + " INVALID HANDLE"
Case WinSCardWrapper.GetUInteger(SCARD_E_INVALID_PARAMETER)
strMessage = errNo.ToString + " INVALID PARAMETER"
Case WinSCardWrapper.GetUInteger(SCARD_E_INVALID_TARGET)
strMessage = errNo.ToString + " INVALID TARGET"
Case WinSCardWrapper.GetUInteger(SCARD_E_NO_MEMORY)
strMessage = errNo.ToString + " NO MEMORY"
Case WinSCardWrapper.GetUInteger(SCARD_F_WAITED_TOO_LONG)
strMessage = errNo.ToString + " WAITED TOO LONG"
Case WinSCardWrapper.GetUInteger(SCARD_E_INSUFFICIENT_BUFFER)
strMessage = errNo.ToString + " INSUFFICIENT BUFFER"
Case WinSCardWrapper.GetUInteger(SCARD_E_UNKNOWN_READER)
strMessage = errNo.ToString + " UNKNOWN READER"
Case WinSCardWrapper.GetUInteger(SCARD_E_TIMEOUT)
strMessage = errNo.ToString + " TIMEOUT"
Case WinSCardWrapper.GetUInteger(SCARD_E_SHARING_VIOLATION)
strMessage = errNo.ToString + " SHARING VIOLATION"
Case WinSCardWrapper.GetUInteger(SCARD_E_NO_SMARTCARD)
strMessage = errNo.ToString + " NO SMARTCARD"
Case WinSCardWrapper.GetUInteger(SCARD_E_UNKNOWN_CARD)
strMessage = errNo.ToString + " UNKNOWN CARD"
Case WinSCardWrapper.GetUInteger(SCARD_E_CANT_DISPOSE)
strMessage = errNo.ToString + " CANT DISPOSE"
Case WinSCardWrapper.GetUInteger(SCARD_E_PROTO_MISMATCH)
strMessage = errNo.ToString + " PROTO MISMATCH"
Case WinSCardWrapper.GetUInteger(SCARD_E_NOT_READY)
strMessage = errNo.ToString + " NOT READY"
Case WinSCardWrapper.GetUInteger(SCARD_E_INVALID_VALUE)
strMessage = errNo.ToString + " INVALID VALUE"
Case WinSCardWrapper.GetUInteger(SCARD_E_SYSTEM_CANCELLED)
strMessage = errNo.ToString + " SYSTEM CANCELLED"
Case WinSCardWrapper.GetUInteger(SCARD_E_COMM_ERROR)
strMessage = errNo.ToString + " COMM ERROR"
Case WinSCardWrapper.GetUInteger(SCARD_F_UNKNOWN_ERROR)
strMessage = errNo.ToString + " UNKNOWN ERROR"
Case WinSCardWrapper.GetUInteger(SCARD_E_INVALID_ATR)
strMessage = errNo.ToString + " INVALID ATR"
Case WinSCardWrapper.GetUInteger(SCARD_E_NOT_TRANSACTED)
strMessage = errNo.ToString + " NOT TRANSACTED"
Case WinSCardWrapper.GetUInteger(SCARD_E_READER_UNAVAILABLE)
strMessage = errNo.ToString + " READER UNAVAILABLE"
Case WinSCardWrapper.GetUInteger(SCARD_P_SHUTDOWN)
strMessage = errNo.ToString + " SHUTDOWN"
Case WinSCardWrapper.GetUInteger(SCARD_E_PCI_TOO_SMALL)
strMessage = errNo.ToString + " PCI TOO SMALL"
Case WinSCardWrapper.GetUInteger(SCARD_E_READER_UNSUPPORTED)
strMessage = errNo.ToString + " READER UNSUPPORTED"
Case WinSCardWrapper.GetUInteger(SCARD_E_DUPLICATE_READER)
strMessage = errNo.ToString + " DUPLICATE READER"
Case WinSCardWrapper.GetUInteger(SCARD_E_CARD_UNSUPPORTED)
strMessage = errNo.ToString + " CARD UNSUPPORTED"
Case WinSCardWrapper.GetUInteger(SCARD_E_NO_SERVICE)
strMessage = errNo.ToString + " NO SERVICE"
Case WinSCardWrapper.GetUInteger(SCARD_E_SERVICE_STOPPED)
strMessage = errNo.ToString + " SERVICE STOPPED"
Case WinSCardWrapper.GetUInteger(SCARD_E_UNEXPECTED)
strMessage = errNo.ToString + " UNEXPECTED"
Case WinSCardWrapper.GetUInteger(SCARD_E_ICC_INSTALLATION)
strMessage = errNo.ToString + " ICC INSTALLATION"
Case WinSCardWrapper.GetUInteger(SCARD_E_ICC_CREATEORDER)
strMessage = errNo.ToString + " ICC CREATEORDER"
Case WinSCardWrapper.GetUInteger(SCARD_E_UNSUPPORTED_FEATURE)
strMessage = errNo.ToString + " UNSUPPORTED FEATURE"
Case WinSCardWrapper.GetUInteger(SCARD_E_DIR_NOT_FOUND)
strMessage = errNo.ToString + " DIR NOT FOUND"
Case WinSCardWrapper.GetUInteger(SCARD_E_FILE_NOT_FOUND)
strMessage = errNo.ToString + " FILE NOT FOUND"
Case WinSCardWrapper.GetUInteger(SCARD_E_NO_DIR)
strMessage = errNo.ToString + " NO DIR"
Case WinSCardWrapper.GetUInteger(SCARD_E_NO_FILE)
strMessage = errNo.ToString + " NO FILE"
Case WinSCardWrapper.GetUInteger(SCARD_E_NO_ACCESS)
strMessage = errNo.ToString + " NO ACCESS"
Case WinSCardWrapper.GetUInteger(SCARD_E_WRITE_TOO_MANY)
strMessage = errNo.ToString + " WRITE TOO MANY"
Case WinSCardWrapper.GetUInteger(SCARD_E_BAD_SEEK)
strMessage = errNo.ToString + " BAD SEEK"
Case WinSCardWrapper.GetUInteger(SCARD_E_INVALID_CHV)
strMessage = errNo.ToString + " INVALID CHV"
Case WinSCardWrapper.GetUInteger(SCARD_E_UNKNOWN_RES_MNG)
strMessage = errNo.ToString + " UNKNOWN RES MNG"
Case WinSCardWrapper.GetUInteger(SCARD_E_NO_SUCH_CERTIFICATE)
strMessage = errNo.ToString + " NO SUCH CERTIFICATE"
Case WinSCardWrapper.GetUInteger(SCARD_E_CERTIFICATE_UNAVAILABLE)
strMessage = errNo.ToString + " CERTIFICATE UNAVAILABLE"
Case WinSCardWrapper.GetUInteger(SCARD_E_NO_READERS_AVAILABLE)
strMessage = errNo.ToString + " NO READERS AVAILABLE"
Case WinSCardWrapper.GetUInteger(SCARD_E_COMM_DATA_LOST)
strMessage = errNo.ToString + " COMM DATA LOST"
Case WinSCardWrapper.GetUInteger(SCARD_E_NO_KEY_CONTAINER)
strMessage = errNo.ToString + " NO KEY CONTAINER"
Case WinSCardWrapper.GetUInteger(SCARD_E_SERVER_TOO_BUSY)
strMessage = errNo.ToString + " SERVER TOO BUSY"
Case WinSCardWrapper.GetUInteger(SCARD_E_PIN_CACHE_EXPIRED)
strMessage = errNo.ToString + " PIN CACHE EXPIRED"
Case WinSCardWrapper.GetUInteger(SCARD_E_NO_PIN_CACHE)
strMessage = errNo.ToString + " NO PIN CACHE"
Case WinSCardWrapper.GetUInteger(SCARD_E_READ_ONLY_CARD)
strMessage = errNo.ToString + " READ ONLY CARD"
Case WinSCardWrapper.GetUInteger(SCARD_W_UNSUPPORTED_CARD)
strMessage = errNo.ToString + " UNSUPPORTED CARD"
Case WinSCardWrapper.GetUInteger(SCARD_W_UNRESPONSIVE_CARD)
strMessage = errNo.ToString + " UNRESPONSIVE CARD"
Case WinSCardWrapper.GetUInteger(SCARD_W_UNPOWERED_CARD)
strMessage = errNo.ToString + " UNPOWERED CARD"
Case WinSCardWrapper.GetUInteger(SCARD_W_RESET_CARD)
strMessage = errNo.ToString + " RESET CARD"
Case WinSCardWrapper.GetUInteger(SCARD_W_REMOVED_CARD)
strMessage = errNo.ToString + " REMOVED CARD"
Case WinSCardWrapper.GetUInteger(SCARD_W_SECURITY_VIOLATION)
strMessage = errNo.ToString + " SECURITY VIOLATION"
Case WinSCardWrapper.GetUInteger(SCARD_W_WRONG_CHV)
strMessage = errNo.ToString + " WRONG CHV"
Case WinSCardWrapper.GetUInteger(SCARD_W_CHV_BLOCKED)
strMessage = errNo.ToString + " CHV BLOCKED"
Case WinSCardWrapper.GetUInteger(SCARD_W_EOF)
strMessage = errNo.ToString + " EOF"
Case WinSCardWrapper.GetUInteger(SCARD_W_CANCELLED_BY_USER)
strMessage = errNo.ToString + " CANCELLED BY USER"
Case WinSCardWrapper.GetUInteger(SCARD_W_CARD_NOT_AUTHENTICATED)
strMessage = errNo.ToString + " CARD NOT AUTHENTICATED"
Case WinSCardWrapper.GetUInteger(SCARD_W_CACHE_ITEM_NOT_FOUND)
strMessage = errNo.ToString + " CACHE ITEM NOT FOUND"
Case WinSCardWrapper.GetUInteger(SCARD_W_CACHE_ITEM_STALE)
strMessage = errNo.ToString + " CACHE ITEM STALE"
Case WinSCardWrapper.GetUInteger(SCARD_W_CACHE_ITEM_TOO_BIG)
strMessage = errNo.ToString + " CACHE ITEM TOO BIG"
Case Else
strMessage = errNo.ToString + " OTHER ERROR"
End Select
Return strMessage
End Function
Public Shared Function GetUInteger(ByVal p_Value As Integer) As UInteger
Return CUInt(p_Value + 2 ^ 32)
End Function
End Class
End Class
用語説明
PC/SC
PC/SC (Personal Computer/Smart Card)は、Windows環境でICカードを利用するための標準アプリケーションインターフェイス仕様である。
SDKを購入せずにMicrosoft社が無償で提供する標準インターフェース仕様PC/SC APIを利用すれば、サブライセンスフィー等の追加費用も不要。
IDm
IDmは、FeliCaのICチップ製造時に、ICチップに記録され書き換えができない固有のID番号である。IDmは8byte(16桁)の数字で、トレーサビリティと個体識別を目的としてソニーが製造するICチップに書き込まれ同じ番号が流通しないようにソニーが管理をおこなっている。編集は不可能であり比較的簡単に利用できることから、応用範囲が広く、このID番号を使ったアプリケーション・システムが広く普及している。
近年FeliCaの上位規格NFCで簡単に読み取ることが可能となっている。NFCでもこのIDmを簡単にリードできるためIDmを利用したアプリケーションが広がっている。一方、ソニーは、高いセキュリティが必要とされるサービスについてはこのIDmのみに依存しないよう推奨しており、高いセキュリティ利用にはFeliCaの暗号領域を利用したり、Mifareを利用して高セキュリティを実現する場合は内部の暗号鍵エリアでの読み書きなどが使用されている。公共の電子マネーサービスではこのIDmやUIDは利用されていない。IDmと混同しがちな番号の中には、サービスのID番号(Edy番号など)や携帯電話のPIN番号、各会社向けに発行されたシステムコードなどIDチップの中に格納されている各種番号が存在する。なおEdyやSuiCaなどのFeliCaカードやおサイフケータイもこのIDmを保有しており読み取ることができる。
カードのプロトコル
SCARD_PROTOCOL_T0
T=0はキャラクタベースのプロトコルであり、SCARD_PROTOCOL_T0で表されます
SCARD_PROTOCOL_T1
T=1はブロックベースのプロトコルであり、SCARD_PROTOCOL_T1で表されます
SCARD_PROTOCOL_T0 or SCARD_PROTOCOL_T1
この場合、実際にカードのプロトコルを特定するには、pdwActiveProtocolを参照します。 これが、たとえばSCARD_PROTOCOL_T0であるならば、 セットされているカードのプロトコルはT=0ということになります。 基本的に、カードベンダーは、カードの仕様説明の箇所にプロトコルを記述しています。
IDm/UIDの桁数
TypeA、TypeB、Felica
非接触ICカードの規格には、世界標準規格である「Type A」と「Type B」、そしてほぼ日本独自の規格である「FeliCa(フェリカ)」の3種類があります。多くの交通系ICカードやおサイフケータイなどは、このFeliCaを利用しています。
■Type A
オランダのフィリップス社で開発された「Mifare」など、欧米を中心に広く使用されています。
コストを抑えて作ることができ、日本では社員証に埋め込み、企業の入退室管理などに利用されています。
■Type B
アメリカのモトローラ社で開発されました。
セキュリティレベルが高く、運転免許証や住基カード、キャッシュカードなどに利用されています。
■FeliCa
ソニー社によって開発され、処理速度の速さには海外でも定評があります。
Suicaへ採用する方式の決定時に出された条件「処理速度0.1秒以内」をクリアすることができたのは、FeliCaだけだったらしいという逸話も。
リソース