1/*
2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
3 * The contents of this file constitute Original Code as defined in and are
4 * subject to the Apple Public Source License Version 1.2 (the 'License').
5 * You may not use this file except in compliance with the License. Please
6 * obtain a copy of the License at http://www.apple.com/publicsource and
7 * read it before using this file.
8 *
9 * This Original Code and all software distributed under the License are
10 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
11 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
12 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
13 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please
14 * see the License for the specific language governing rights and
15 * limitations under the License.
16 */
17
18/*
19 *  PCSCDriverBundles.cpp
20 *  SmartCardServices
21 */
22
23/*
24	Creates a vector of driver bundle info structures from the hot-plug driver
25	directory.
26
27	Returns NULL on error and a pointer to an allocated HPDriver vector on
28	success.  The caller must free the HPDriver with a call to HPDriversRelease().
29
30	See http://developer.apple.com/documentation/CoreFoundation/Reference/CFArrayRef/index.html#//apple_ref/doc/uid/20001192
31	for information about CFArrayApplyFunction
32*/
33
34#include "PCSCDriverBundles.h"
35#include <security_utilities/debugging.h>
36#include <security_utilities/cfutilities.h>
37#include <security_utilities/errors.h>
38#include <map>
39
40namespace PCSCD {
41
42static const char *kPCSCLITE_HP_DROPDIR = "/usr/libexec/SmartCardServices/drivers/";
43static const char *kENV_PCSC_DEBUG_DRIVER = "PCSC_DEBUG_DRIVER_DIR";	// environment var
44
45DriverBundles::DriverBundles()
46{
47	// If debugging, look in build directory
48#if !defined(NDEBUG)
49	const char *envar = kENV_PCSC_DEBUG_DRIVER;
50	if (envar)
51		if (const char *envPath = getenv(envar))
52		{
53			// treat envPath as a classic colon-separated list of directories
54			secdebug("pathlist", "%p configuring from env(\"%s\")", this, envar);
55			while (const char *p = strchr(envPath, ':'))
56			{
57				addDirectory(string(envPath, p - envPath));
58				envPath = p + 1;
59			}
60			addDirectory(envPath);
61		}
62#endif
63	addDirectory(kPCSCLITE_HP_DROPDIR);
64}
65
66bool DriverBundles::find(PCSCD::Device &device)  const
67{
68	// Searches for a driver bundle that matches device. If found,
69	// it sets the libpath for the device and returns true.
70
71	ProductMatchMap matchingProducts;
72
73	for (DriverBundles::const_iterator it=this->begin();it!=this->end();++it)
74	{
75		std::string name;
76		const DriverBundle *bndl = static_cast<DriverBundle *>((*it).get());
77		if (int32_t score = bndl->matches(device, name))
78		{
79			ProductMatchInfo *mi =  new ProductMatchInfo(bndl->path(),name);
80			matchingProducts.push_back(make_pair(score, mi));
81		}
82	}
83
84	if (matchingProducts.empty())
85		return false;
86
87	sort(matchingProducts.begin(), matchingProducts.end());
88	const ProductMatchInfo *mi = (*matchingProducts.rbegin()).second;
89	device.setName(mi->name());
90	device.setPath(mi->path());
91	// clean up
92	for (ProductMatchMap::iterator it = matchingProducts.begin();it!=matchingProducts.end();++it)
93		delete (*it).second;
94	return true;
95}
96
97} // end namespace PCSCD
98