blob: 0a36f49ce4d6ea07e67003281730edeeec75e62b [file] [log] [blame]
Harald Welted54c2ee2012-01-17 18:25:50 +01001#include <string.h>
2#include <stdint.h>
3#include <stdio.h>
4#include <errno.h>
5
6#include <osmocom/core/talloc.h>
7#include <osmocom/sim/sim.h>
8
9#include <PCSC/wintypes.h>
10#include <PCSC/winscard.h>
11
12#include "sim_int.h"
13
14#define PCSC_ERROR(rv, text) \
15if (rv != SCARD_S_SUCCESS) { \
16 fprintf(stderr, text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \
17 goto end; \
18} else { \
19 printf(text ": OK\n\n"); \
20}
21
22
23
24struct pcsc_reader_state {
25 SCARDCONTEXT hContext;
26 SCARDHANDLE hCard;
27 DWORD dwActiveProtocol;
28 const SCARD_IO_REQUEST *pioSendPci;
29 SCARD_IO_REQUEST pioRecvPci;
30 char *name;
31};
32
33static struct osim_reader_hdl *pcsc_reader_open(int num, const char *id, void *ctx)
34{
35 struct osim_reader_hdl *rh;
36 struct pcsc_reader_state *st;
37 long rc;
38 LPSTR mszReaders = NULL;
39 DWORD dwReaders;
40 unsigned int num_readers;
41 char *ptr;
42
43 /* FIXME: implement matching on id or num */
44
45 rh = talloc_zero(ctx, struct osim_reader_hdl);
46 st = rh->priv = talloc_zero(rh, struct pcsc_reader_state);
47
48 rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL,
49 &st->hContext);
50 if (rc != SCARD_S_SUCCESS)
51 goto end;
52
53 dwReaders = SCARD_AUTOALLOCATE;
54 rc = SCardListReaders(st->hContext, NULL, (LPSTR)&mszReaders, &dwReaders);
55 PCSC_ERROR(rc, "SCardListReaders");
56
57 num_readers = 0;
58 ptr = mszReaders;
59 while (*ptr != '\0') {
60 ptr += strlen(ptr)+1;
61 num_readers++;
62 }
63
64 if (num_readers == 0)
65 goto end;
66
67 st->name = talloc_strdup(rh, mszReaders);
68 st->dwActiveProtocol = -1;
69
70 return rh;
71end:
72 talloc_free(rh);
73 return NULL;
74}
75
76static struct osim_card_hdl *pcsc_card_open(struct osim_reader_hdl *rh)
77{
78 struct pcsc_reader_state *st = rh->priv;
79 struct osim_card_hdl *card;
80 struct osim_chan_hdl *chan;
81 int rc;
82
83 rc = SCardConnect(st->hContext, st->name, SCARD_SHARE_SHARED,
84 SCARD_PROTOCOL_T0, &st->hCard, &st->dwActiveProtocol);
85 PCSC_ERROR(rc, "SCardConnect");
86
87 st->pioSendPci = SCARD_PCI_T0;
88
89 card = talloc_zero(rh, struct osim_card_hdl);
90 INIT_LLIST_HEAD(&card->channels);
91 card->reader = rh;
92 rh->card = card;
93
94 /* create a default channel */
95 chan = talloc_zero(card, struct osim_chan_hdl);
96 chan->card = card;
97 llist_add(&chan->list, &card->channels);
98
99 return card;
100
101end:
102 return NULL;
103}
104
105
106static int pcsc_transceive(struct osim_reader_hdl *rh, struct msgb *msg)
107{
108 struct pcsc_reader_state *st = rh->priv;
109 DWORD rlen = msgb_tailroom(msg);
110 int rc;
111
112 printf("TX: %s\n", osmo_hexdump(msg->data, msg->len));
113
114 rc = SCardTransmit(st->hCard, st->pioSendPci, msg->data, msgb_length(msg),
115 &st->pioRecvPci, msg->tail, &rlen);
116 PCSC_ERROR(rc, "SCardEndTransaction");
117
118 printf("RX: %s\n", osmo_hexdump(msg->tail, rlen));
119 msgb_put(msg, rlen);
120 msgb_apdu_le(msg) = rlen;
121
122 return 0;
123end:
124 return -EIO;
125}
126
127const struct osim_reader_ops pcsc_reader_ops = {
128 .name = "PC/SC",
129 .reader_open = pcsc_reader_open,
130 .card_open = pcsc_card_open,
131 .transceive = pcsc_transceive,
132};
133