Initial commit
[platform/upstream/ccid.git] / examples / PCSCv2part10.c
1 /*
2     PCSCv2part10.c: helper functions for PC/SC v2 part 10 services
3     Copyright (C) 2012   Ludovic Rousseau
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Lesser General Public
7     License as published by the Free Software Foundation; either
8     version 2.1 of the License, or (at your option) any later version.
9
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Lesser General Public License for more details.
14
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; if not, write to the Free Software
17     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19
20 #include <stdio.h>
21 #include <arpa/inet.h>
22
23 #ifdef __APPLE__
24 #include <PCSC/winscard.h>
25 #include <PCSC/wintypes.h>
26 #else
27 #include <winscard.h>
28 #endif
29
30 #include "PCSCv2part10.h"
31
32 int PCSCv2Part10_find_TLV_property_by_tag_from_buffer(
33         unsigned char *buffer, int length, int property, int * value_int)
34 {
35         unsigned char *p;
36         int found = 0, len;
37         int value = -1;
38         int ret = -1;   /* not found by default */
39
40         p = buffer;
41         while (p-buffer < length)
42         {
43                 if (*p++ == property)
44                 {
45                         found = 1;
46                         break;
47                 }
48
49                 /* go to next tag */
50                 len = *p++;
51                 p += len;
52         }
53
54         if (found)
55         {
56                 len = *p++;
57                 ret = 0;
58
59                 switch(len)
60                 {
61                         case 1:
62                                 value = *p;
63                                 break;
64                         case 2:
65                                 value = *p + (*(p+1)<<8);
66                                 break;
67                         case 4:
68                                 value = *p + (*(p+1)<<8) + (*(p+2)<<16) + (*(p+3)<<24);
69                                 break;
70                         default:
71                                 /* wrong length for an integer */
72                                 ret = -2;
73                 }
74         }
75
76         if (value_int)
77                 *value_int = value;
78
79         return ret;
80 } /* PCSCv2Part10_find_TLV_property_by_tag_from_buffer */
81
82 int PCSCv2Part10_find_TLV_property_by_tag_from_hcard(SCARDHANDLE hCard,
83         int property, int * value)
84 {
85         unsigned char buffer[MAX_BUFFER_SIZE];
86         LONG rv;
87         DWORD length;
88         unsigned int i;
89         PCSC_TLV_STRUCTURE *pcsc_tlv;
90         DWORD properties_in_tlv_ioctl;
91         int found;
92
93         rv = SCardControl(hCard, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0,
94                 buffer, sizeof buffer, &length);
95         if (rv != SCARD_S_SUCCESS)
96                 return -1;
97
98         /* get the number of elements instead of the complete size */
99         length /= sizeof(PCSC_TLV_STRUCTURE);
100
101         pcsc_tlv = (PCSC_TLV_STRUCTURE *)buffer;
102         found = 0;
103         for (i = 0; i < length; i++)
104         {
105                 if (FEATURE_GET_TLV_PROPERTIES == pcsc_tlv[i].tag)
106                 {
107                         properties_in_tlv_ioctl = ntohl(pcsc_tlv[i].value);
108                         found = 1;
109                 }
110         }
111
112         if (! found)
113                 return -3;
114
115         rv= SCardControl(hCard, properties_in_tlv_ioctl, NULL, 0,
116                 buffer, sizeof buffer, &length);
117         if (rv != SCARD_S_SUCCESS)
118                 return -1;
119
120         return PCSCv2Part10_find_TLV_property_by_tag_from_buffer(buffer,
121                 length, property, value);
122 }
123