blob: e8075257791f7c558f8299dd6aafe4a76fa334cb [file] [log] [blame]
Harald Welte3aa901d2018-08-13 18:32:36 +02001/*! \file reader_pcsc.c
2 * PC/SC Card reader backend for libosmosim. */
3/*
4 * (C) 2012 by Harald Welte <laforge@gnumonks.org>
5 *
6 * All Rights Reserved
7 *
8 * SPDX-License-Identifier: GPL-2.0+
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
Harald Welte3aa901d2018-08-13 18:32:36 +020020 */
21
22
23#include <string.h>
24#include <stdint.h>
25#include <stdio.h>
26#include <errno.h>
27
28#include <talloc.h>
29#include <osmocom/core/linuxlist.h>
Harald Welte3aa901d2018-08-13 18:32:36 +020030
31#include <wintypes.h>
32#include <winscard.h>
33
34#include "internal.h"
Harald Welte7293e7b2021-12-08 21:29:11 +010035#include "debug.h"
Harald Welte3aa901d2018-08-13 18:32:36 +020036
37#define PCSC_ERROR(rv, text) \
38if (rv != SCARD_S_SUCCESS) { \
Harald Welte7293e7b2021-12-08 21:29:11 +010039 LOGP(DMAIN, LOGL_ERROR, text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \
Harald Welte3aa901d2018-08-13 18:32:36 +020040 goto end; \
41} else { \
Harald Welte7293e7b2021-12-08 21:29:11 +010042 LOGP(DMAIN, LOGL_DEBUG, ": OK\n\n"); \
Harald Welte3aa901d2018-08-13 18:32:36 +020043}
44
45static void pcsc_readers_probe(void *ctx)
46{
47 LONG rc;
48 LPSTR mszReaders = NULL;
49 DWORD dwReaders;
50 SCARDCONTEXT hContext;
51 unsigned int num_readers;
52 char *ptr;
53
54 rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
55 PCSC_ERROR(rc, "SCardEstablishContext");
56
57 dwReaders = SCARD_AUTOALLOCATE;
58 rc = SCardListReaders(hContext, NULL, (LPSTR)&mszReaders, &dwReaders);
59 PCSC_ERROR(rc, "SCardListReaders");
60
61 num_readers = 0;
62 ptr = mszReaders;
63 while (*ptr != '\0') {
64 struct card_reader *cr;
65 /* while CCID has the nice feature to distinguish between readers and slots, PC/SC
66 * doesn't have this distinction, so we end up having one "reader" per slot */
67 cr = card_reader_alloc(ctx, ptr, NULL, NULL);
68 card_reader_slot_alloc(cr, 0);
69 ptr += strlen(ptr)+1;
70 num_readers++;
71 }
72
Harald Welte7293e7b2021-12-08 21:29:11 +010073 LOGP(DMAIN, LOGL_DEBUG, "num_readers=%d\n", num_readers);
Harald Welte3aa901d2018-08-13 18:32:36 +020074
75end:
76 if (mszReaders)
77 SCardFreeMemory(hContext, mszReaders);
78}
79
80static int pcsc_reader_open_slot(struct card_reader_slot *slot)
81{
Harald Welte77911b02018-08-14 23:47:30 +020082#if 0
Harald Welte3aa901d2018-08-13 18:32:36 +020083 struct osim_card_hdl *card;
84 LONG rc;
85
86 if (proto != OSIM_PROTO_T0)
87 return NULL;
88
89 rc = SCardConnect(st->hContext, st->name, SCARD_SHARE_SHARED,
90 SCARD_PROTOCOL_T0, &st->hCard, &st->dwActiveProtocol);
91 PCSC_ERROR(rc, "SCardConnect");
92
93 st->pioSendPci = SCARD_PCI_T0;
94
95 card = talloc_zero(rh, struct osim_card_hdl);
96 INIT_LLIST_HEAD(&card->channels);
97 card->reader = rh;
98 rh->card = card;
99
100end:
Harald Welte77911b02018-08-14 23:47:30 +0200101#endif
102 return -1;
Harald Welte3aa901d2018-08-13 18:32:36 +0200103}
104
105
106static const struct card_reader_driver_ops pcsc_driver_ops = {
107 .probe = pcsc_readers_probe,
108 .open_slot = pcsc_reader_open_slot,
109 .close_slot = NULL,
110 .transceive_apdu = NULL,
111};
112
113static struct card_reader_driver pcsc_driver = {
114 .name = "PCSC",
115 .ops = &pcsc_driver_ops,
116};
117
118__attribute__ ((constructor)) void pcsc_reader_init(void)
119{
120 card_reader_driver_register(&pcsc_driver);
121}