| /*! \file reader_pcsc.c |
| * PC/SC Card reader backend for libosmosim. */ |
| /* |
| * (C) 2012 by Harald Welte <laforge@gnumonks.org> |
| * |
| * All Rights Reserved |
| * |
| * SPDX-License-Identifier: GPL-2.0+ |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License along |
| * with this program; if not, write to the Free Software Foundation, Inc., |
| * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| */ |
| |
| |
| #include <string.h> |
| #include <stdint.h> |
| #include <stdio.h> |
| #include <errno.h> |
| |
| #include <talloc.h> |
| #include <osmocom/core/linuxlist.h> |
| #include <osmocom/sim/sim.h> |
| |
| #include <wintypes.h> |
| #include <winscard.h> |
| |
| #include "internal.h" |
| |
| #define PCSC_ERROR(rv, text) \ |
| if (rv != SCARD_S_SUCCESS) { \ |
| fprintf(stderr, text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \ |
| goto end; \ |
| } else { \ |
| printf(text ": OK\n\n"); \ |
| } |
| |
| static void pcsc_readers_probe(void *ctx) |
| { |
| LONG rc; |
| LPSTR mszReaders = NULL; |
| DWORD dwReaders; |
| SCARDCONTEXT hContext; |
| unsigned int num_readers; |
| char *ptr; |
| |
| rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); |
| PCSC_ERROR(rc, "SCardEstablishContext"); |
| |
| dwReaders = SCARD_AUTOALLOCATE; |
| rc = SCardListReaders(hContext, NULL, (LPSTR)&mszReaders, &dwReaders); |
| PCSC_ERROR(rc, "SCardListReaders"); |
| |
| num_readers = 0; |
| ptr = mszReaders; |
| while (*ptr != '\0') { |
| struct card_reader *cr; |
| /* while CCID has the nice feature to distinguish between readers and slots, PC/SC |
| * doesn't have this distinction, so we end up having one "reader" per slot */ |
| cr = card_reader_alloc(ctx, ptr, NULL, NULL); |
| card_reader_slot_alloc(cr, 0); |
| ptr += strlen(ptr)+1; |
| num_readers++; |
| } |
| |
| printf("num_readers=%d\n", num_readers); |
| |
| end: |
| if (mszReaders) |
| SCardFreeMemory(hContext, mszReaders); |
| } |
| |
| static int pcsc_reader_open_slot(struct card_reader_slot *slot) |
| { |
| #if 0 |
| struct osim_card_hdl *card; |
| LONG rc; |
| |
| if (proto != OSIM_PROTO_T0) |
| return NULL; |
| |
| rc = SCardConnect(st->hContext, st->name, SCARD_SHARE_SHARED, |
| SCARD_PROTOCOL_T0, &st->hCard, &st->dwActiveProtocol); |
| PCSC_ERROR(rc, "SCardConnect"); |
| |
| st->pioSendPci = SCARD_PCI_T0; |
| |
| card = talloc_zero(rh, struct osim_card_hdl); |
| INIT_LLIST_HEAD(&card->channels); |
| card->reader = rh; |
| rh->card = card; |
| |
| end: |
| #endif |
| return -1; |
| } |
| |
| |
| static const struct card_reader_driver_ops pcsc_driver_ops = { |
| .probe = pcsc_readers_probe, |
| .open_slot = pcsc_reader_open_slot, |
| .close_slot = NULL, |
| .transceive_apdu = NULL, |
| }; |
| |
| static struct card_reader_driver pcsc_driver = { |
| .name = "PCSC", |
| .ops = &pcsc_driver_ops, |
| }; |
| |
| __attribute__ ((constructor)) void pcsc_reader_init(void) |
| { |
| card_reader_driver_register(&pcsc_driver); |
| } |