static int piv_match_card_continued(sc_card_t *card)
{
	int i, r = 0;
	int type  = -1;
	piv_private_data_t *priv = NULL;
	int saved_type = card->type;

	/* Since we send an APDU, the card's logout function may be called...
	 * however it may be in dirty memory */
	card->ops->logout = NULL;

	/* piv_match_card may be called with card->type, set by opensc.conf */
	/* user provide card type must be one we know */
	switch (card->type) {
		case -1:
		case SC_CARD_TYPE_PIV_II_GENERIC:
		case SC_CARD_TYPE_PIV_II_HIST:
		case SC_CARD_TYPE_PIV_II_NEO:
		case SC_CARD_TYPE_PIV_II_YUBIKEY4:
		case SC_CARD_TYPE_PIV_II_GI_DE_DUAL_CAC:
		case SC_CARD_TYPE_PIV_II_GI_DE:
		case SC_CARD_TYPE_PIV_II_GEMALTO_DUAL_CAC:
		case SC_CARD_TYPE_PIV_II_GEMALTO:
		case SC_CARD_TYPE_PIV_II_OBERTHUR_DUAL_CAC:
		case SC_CARD_TYPE_PIV_II_OBERTHUR:
		case SC_CARD_TYPE_PIV_II_PIVKEY:
			type = card->type;
			break;
		default:
			return 0; /* can not handle the card */
	}
	sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d type:%d r:%d\n", card->type, type, r);
	if (type == -1) {

		/*
		 *try to identify card by ATR or historical data in ATR
		 * currently all PIV card will respond to piv_find_aid
		 * the same. But in future may need to know card type first,
		 * so do it here.
		 */

		if (card->reader->atr_info.hist_bytes != NULL) {
			if (card->reader->atr_info.hist_bytes_len == 8 &&
					!(memcmp(card->reader->atr_info.hist_bytes, "Yubikey4", 8))) {
				type = SC_CARD_TYPE_PIV_II_YUBIKEY4;
			}
			else if (card->reader->atr_info.hist_bytes_len >= 7 &&
					!(memcmp(card->reader->atr_info.hist_bytes, "Yubikey", 7))) {
				type = SC_CARD_TYPE_PIV_II_NEO;
			}
			else if (card->reader->atr_info.hist_bytes_len > 0
					&& card->reader->atr_info.hist_bytes[0] == 0x80u) { /* compact TLV */
				size_t datalen;
				const u8 *data;

				if ((data = sc_compacttlv_find_tag(card->reader->atr_info.hist_bytes + 1,
						card->reader->atr_info.hist_bytes_len - 1, 0x50, &datalen))) {
					if (datalen == 7 && !(memcmp(data, "YubiKey", 7))) {
						type = SC_CARD_TYPE_PIV_II_YUBIKEY4;   /* reader says 4  really 5 */
					}
					/* Yubikey 5 NFC ATR using ACR122 contactless reader does not match
					 * https://developers.yubico.com/PIV/Introduction/Yubico_extensions.html
					 * On Windows 10, using Omnikey 5021, the ATR is correct
					 * will look at only 6 bytes that do match
					 */
					else if (datalen == 7 && !(memcmp(data, "YubiKe", 6))) {
						type = SC_CARD_TYPE_PIV_II_YUBIKEY4;   /* reader says 4 really 5 */
					}
				} else if ((data = sc_compacttlv_find_tag(card->reader->atr_info.hist_bytes + 1,
						card->reader->atr_info.hist_bytes_len - 1, 0xF0, &datalen))) {
					int k;

					for (k = 0; piv_aids[k].len_long != 0; k++) {
						if (datalen == piv_aids[k].len_long
							&& !memcmp(data, piv_aids[k].value, datalen)) {
							type = SC_CARD_TYPE_PIV_II_HIST;
							break;
						}
					}
				}
			}
		}
		sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d type:%d r:%d\n", card->type, type, r);

		if (type == -1) {
			/* use known ATRs  */
			i = _sc_match_atr(card, piv_atrs, &type);
			if (i < 0)
				type = SC_CARD_TYPE_PIV_II_GENERIC; /* may still be CAC with PIV Endpoint */
		}
	}

	sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d type:%d r:%d\n", card->type, type, r);
	/* allocate and init basic fields */

	priv = calloc(1, sizeof(piv_private_data_t));

	if (!priv)
		LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);

	if (card->type == -1)
		card->type = type;

	card->drv_data = priv; /* will free if no match, or pass on to piv_init */
	priv->selected_obj = -1;
	priv->pin_preference = 0x80; /* 800-73-3 part 1, table 3 */
	/* TODO Dual CAC/PIV are bases on 800-73-1 where priv->pin_preference = 0. need to check later */
	priv->logged_in = SC_PIN_STATE_UNKNOWN;
	priv->tries_left = 10; /* will assume OK at start */
	priv->pstate = PIV_STATE_MATCH;

	/* Some objects will only be present if History object says so */
	for (i=0; i < PIV_OBJ_LAST_ENUM -1; i++)
		if(piv_objects[i].flags & PIV_OBJECT_NOT_PRESENT)
			priv->obj_cache[i].flags |= PIV_OBJ_CACHE_NOT_PRESENT;

	r = sc_lock(card);
	if (r != SC_SUCCESS) {
		sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "sc_lock failed\n");
		piv_finish(card);
		card->type = saved_type;
		return 0;
	}

	/*
	 * Detect if active AID is PIV. NIST 800-73 says only one PIV application per card
	 * and PIV must be the default application.
	 * Try to avoid doing a select_aid and losing the login state on some cards.
	 * We may get interference on some cards by other drivers trying SELECT_AID before
	 * we get to see if PIV application is still active
	 * putting PIV driver first might help.
	 * This may fail if the wrong AID is active.
	 * Discovery Object introduced in 800-73-3 so will return 0 if found and PIV applet active.
	 * Will fail with SC_ERROR_FILE_NOT_FOUND if 800-73-3 and no Discovery object.
	 * But some other card could also return SC_ERROR_FILE_NOT_FOUND.
	 * Will fail for other reasons if wrong applet is selected, or bad PIV implementation.
	 */
	
	sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d CI:%08x r:%d\n", card->type,  priv->card_issues, r);
	if (priv->card_issues & CI_DISCOVERY_USELESS) /* TODO may be in wrong place */
		i = -1;
	else
		i = piv_find_discovery(card);

	sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r);
	if (i < 0) {
		/* Detect by selecting applet */
		i = piv_find_aid(card);
	}

	sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r);
	if (i >= 0) {
		int iccc = 0;
		 /* We now know PIV AID is active, test CCC object  800-73-* say CCC is required */
		switch (card->type)  {
			/*
			 * For cards that may also be CAC, try and read the CCC
			 * CCC is required and all Dual PIV/CAC will have a CCC
			 * Currently Dual PIV/CAC are based on NIST 800-73-1 which does not have Discovery or History
			 */
			case SC_CARD_TYPE_PIV_II_GENERIC: /* i.e. really dont know what this is */
			case SC_CARD_TYPE_PIV_II_HIST:
			case SC_CARD_TYPE_PIV_II_GI_DE:
			case SC_CARD_TYPE_PIV_II_GEMALTO:
			case SC_CARD_TYPE_PIV_II_OBERTHUR:
				iccc = piv_process_ccc(card);
				sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d iccc:%d ccc_flags:%08x CI:%08x r:%d\n",
						card->type, iccc, priv->ccc_flags, priv->card_issues, r);
				/* ignore an error? */
				/* if CCC says it has CAC with PKI on card set to one of the SC_CARD_TYPE_PIV_II_*_DUAL_CAC */
				if (priv->ccc_flags & PIV_CCC_F3_CAC_PKI) {
					switch (card->type)  {
						case SC_CARD_TYPE_PIV_II_GENERIC:
						case SC_CARD_TYPE_PIV_II_HIST:
						case SC_CARD_TYPE_PIV_II_GI_DE:
						    card->type = SC_CARD_TYPE_PIV_II_GI_DE_DUAL_CAC;
						    priv->card_issues |= CI_DISCOVERY_USELESS;
						    priv->obj_cache[PIV_OBJ_DISCOVERY].flags |= PIV_OBJ_CACHE_NOT_PRESENT;
						    break;
						case SC_CARD_TYPE_PIV_II_GEMALTO_DUAL_CAC:
						case SC_CARD_TYPE_PIV_II_GEMALTO:
							card->type = SC_CARD_TYPE_PIV_II_GEMALTO_DUAL_CAC;
							priv->card_issues |= CI_DISCOVERY_USELESS;
							priv->obj_cache[PIV_OBJ_DISCOVERY].flags |= PIV_OBJ_CACHE_NOT_PRESENT;
							break;
						case SC_CARD_TYPE_PIV_II_OBERTHUR_DUAL_CAC:
						case SC_CARD_TYPE_PIV_II_OBERTHUR:
							card->type =  SC_CARD_TYPE_PIV_II_OBERTHUR_DUAL_CAC;
							priv->card_issues |= CI_DISCOVERY_USELESS;
							priv->obj_cache[PIV_OBJ_DISCOVERY].flags |= PIV_OBJ_CACHE_NOT_PRESENT;
							break;
					}
				}
				break;

				/* if user forced it to be one of the CAC types, assume it is CAC */
			case SC_CARD_TYPE_PIV_II_GI_DE_DUAL_CAC:
			case SC_CARD_TYPE_PIV_II_GEMALTO_DUAL_CAC:
			case SC_CARD_TYPE_PIV_II_OBERTHUR_DUAL_CAC:
				priv->card_issues |= CI_DISCOVERY_USELESS;
				priv->obj_cache[PIV_OBJ_DISCOVERY].flags |= PIV_OBJ_CACHE_NOT_PRESENT;
				break;
			}
		}
	sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r);
	if (i >= 0 && (priv->card_issues & CI_DISCOVERY_USELESS) == 0) {
		/*
		 * We now know PIV AID is active, test DISCOVERY object again
		 * Some PIV don't support DISCOVERY and return
		 * SC_ERROR_INCORRECT_PARAMETERS. Any error
		 * including SC_ERROR_FILE_NOT_FOUND means we cannot use discovery
		 * to test for active AID.
		 */
		int i7e = piv_find_discovery(card);

		sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i7e:%d CI:%08x r:%d\n", card->type, i7e, priv->card_issues, r);
		if (i7e < 0) {
			priv->card_issues |= CI_DISCOVERY_USELESS;
			priv->obj_cache[PIV_OBJ_DISCOVERY].flags |= PIV_OBJ_CACHE_NOT_PRESENT;
		}
	}

	sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r);
	if (i < 0) {
		/* don't match. Does not have a PIV applet. */
		sc_unlock(card);
		piv_finish(card);
		card->type = saved_type;
		return 0;
	}

	sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r);
	/* Matched, caller will use or free priv and sc_lock as needed */
	priv->pstate=PIV_STATE_INIT;
	return 1; /* match */
}
static int piv_match_card_continued(sc_card_t *card)
{
	int i, r = 0;
	int type  = -1;
	piv_private_data_t *priv = NULL;
	int saved_type = card->type;

	 
	card->ops->logout = NULL;

	 
	 
	switch (card->type) {
		case -1:
		case SC_CARD_TYPE_PIV_II_GENERIC:
		case SC_CARD_TYPE_PIV_II_HIST:
		case SC_CARD_TYPE_PIV_II_NEO:
		case SC_CARD_TYPE_PIV_II_YUBIKEY4:
		case SC_CARD_TYPE_PIV_II_GI_DE_DUAL_CAC:
		case SC_CARD_TYPE_PIV_II_GI_DE:
		case SC_CARD_TYPE_PIV_II_GEMALTO_DUAL_CAC:
		case SC_CARD_TYPE_PIV_II_GEMALTO:
		case SC_CARD_TYPE_PIV_II_OBERTHUR_DUAL_CAC:
		case SC_CARD_TYPE_PIV_II_OBERTHUR:
		case SC_CARD_TYPE_PIV_II_PIVKEY:
			type = card->type;
			break;
		default:
			return 0;  
	}
	sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d type:%d r:%d\n", card->type, type, r);
	if (type == -1) {

		 

		if (card->reader->atr_info.hist_bytes != NULL) {
			if (card->reader->atr_info.hist_bytes_len == 8 &&
					!(memcmp(card->reader->atr_info.hist_bytes, "Yubikey4", 8))) {
				type = SC_CARD_TYPE_PIV_II_YUBIKEY4;
			}
			else if (card->reader->atr_info.hist_bytes_len >= 7 &&
					!(memcmp(card->reader->atr_info.hist_bytes, "Yubikey", 7))) {
				type = SC_CARD_TYPE_PIV_II_NEO;
			}
			else if (card->reader->atr_info.hist_bytes_len > 0
					&& card->reader->atr_info.hist_bytes[0] == 0x80u) {  
				size_t datalen;
				const u8 *data;

				if ((data = sc_compacttlv_find_tag(card->reader->atr_info.hist_bytes + 1,
						card->reader->atr_info.hist_bytes_len - 1, 0x50, &datalen))) {
					if (datalen == 7 && !(memcmp(data, "YubiKey", 7))) {
						type = SC_CARD_TYPE_PIV_II_YUBIKEY4;    
					}
					 
					else if (datalen == 7 && !(memcmp(data, "YubiKe", 6))) {
						type = SC_CARD_TYPE_PIV_II_YUBIKEY4;    
					}
				} else if ((data = sc_compacttlv_find_tag(card->reader->atr_info.hist_bytes + 1,
						card->reader->atr_info.hist_bytes_len - 1, 0xF0, &datalen))) {
					int k;

					for (k = 0; piv_aids[k].len_long != 0; k++) {
						if (datalen == piv_aids[k].len_long
							&& !memcmp(data, piv_aids[k].value, datalen)) {
							type = SC_CARD_TYPE_PIV_II_HIST;
							break;
						}
					}
				}
			}
		}
		sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d type:%d r:%d\n", card->type, type, r);

		if (type == -1) {
			 
			i = _sc_match_atr(card, piv_atrs, &type);
			if (i < 0)
				type = SC_CARD_TYPE_PIV_II_GENERIC;  
		}
	}

	sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d type:%d r:%d\n", card->type, type, r);
	 

	priv = calloc(1, sizeof(piv_private_data_t));

	if (!priv)
		LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);

	if (card->type == -1)
		card->type = type;

	card->drv_data = priv;  
	priv->selected_obj = -1;
	priv->pin_preference = 0x80;  
	 
	priv->logged_in = SC_PIN_STATE_UNKNOWN;
	priv->tries_left = 10;  
	priv->pstate = PIV_STATE_MATCH;

	 
	for (i=0; i < PIV_OBJ_LAST_ENUM -1; i++)
		if(piv_objects[i].flags & PIV_OBJECT_NOT_PRESENT)
			priv->obj_cache[i].flags |= PIV_OBJ_CACHE_NOT_PRESENT;

	r = sc_lock(card);
	if (r != SC_SUCCESS) {
		sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "sc_lock failed\n");
		piv_finish(card);
		card->type = saved_type;
		return 0;
	}

	 
	
	sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d CI:%08x r:%d\n", card->type,  priv->card_issues, r);
	if (priv->card_issues & CI_DISCOVERY_USELESS)  
		i = -1;
	else
		i = piv_find_discovery(card);

	sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r);
	if (i < 0) {
		 
		i = piv_find_aid(card);
	}

	sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r);
	if (i >= 0) {
		int iccc = 0;
		  
		switch (card->type)  {
			 
			case SC_CARD_TYPE_PIV_II_GENERIC:  
			case SC_CARD_TYPE_PIV_II_HIST:
			case SC_CARD_TYPE_PIV_II_GI_DE:
			case SC_CARD_TYPE_PIV_II_GEMALTO:
			case SC_CARD_TYPE_PIV_II_OBERTHUR:
				iccc = piv_process_ccc(card);
				sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d iccc:%d ccc_flags:%08x CI:%08x r:%d\n",
						card->type, iccc, priv->ccc_flags, priv->card_issues, r);
				 
				 
				if (priv->ccc_flags & PIV_CCC_F3_CAC_PKI) {
					switch (card->type)  {
						case SC_CARD_TYPE_PIV_II_GENERIC:
						case SC_CARD_TYPE_PIV_II_HIST:
						case SC_CARD_TYPE_PIV_II_GI_DE:
						    card->type = SC_CARD_TYPE_PIV_II_GI_DE_DUAL_CAC;
						    priv->card_issues |= CI_DISCOVERY_USELESS;
						    priv->obj_cache[PIV_OBJ_DISCOVERY].flags |= PIV_OBJ_CACHE_NOT_PRESENT;
						    break;
						case SC_CARD_TYPE_PIV_II_GEMALTO_DUAL_CAC:
						case SC_CARD_TYPE_PIV_II_GEMALTO:
							card->type = SC_CARD_TYPE_PIV_II_GEMALTO_DUAL_CAC;
							priv->card_issues |= CI_DISCOVERY_USELESS;
							priv->obj_cache[PIV_OBJ_DISCOVERY].flags |= PIV_OBJ_CACHE_NOT_PRESENT;
							break;
						case SC_CARD_TYPE_PIV_II_OBERTHUR_DUAL_CAC:
						case SC_CARD_TYPE_PIV_II_OBERTHUR:
							card->type =  SC_CARD_TYPE_PIV_II_OBERTHUR_DUAL_CAC;
							priv->card_issues |= CI_DISCOVERY_USELESS;
							priv->obj_cache[PIV_OBJ_DISCOVERY].flags |= PIV_OBJ_CACHE_NOT_PRESENT;
							break;
					}
				}
				break;

				 
			case SC_CARD_TYPE_PIV_II_GI_DE_DUAL_CAC:
			case SC_CARD_TYPE_PIV_II_GEMALTO_DUAL_CAC:
			case SC_CARD_TYPE_PIV_II_OBERTHUR_DUAL_CAC:
				priv->card_issues |= CI_DISCOVERY_USELESS;
				priv->obj_cache[PIV_OBJ_DISCOVERY].flags |= PIV_OBJ_CACHE_NOT_PRESENT;
				break;
			}
		}
	sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r);
	if (i >= 0 && (priv->card_issues & CI_DISCOVERY_USELESS) == 0) {
		 
		int i7e = piv_find_discovery(card);

		sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i7e:%d CI:%08x r:%d\n", card->type, i7e, priv->card_issues, r);
		if (i7e < 0) {
			priv->card_issues |= CI_DISCOVERY_USELESS;
			priv->obj_cache[PIV_OBJ_DISCOVERY].flags |= PIV_OBJ_CACHE_NOT_PRESENT;
		}
	}

	sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r);
	if (i < 0) {
		 
		sc_unlock(card);
		piv_finish(card);
		card->type = saved_type;
		return 0;
	}

	sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r);
	 
	priv->pstate=PIV_STATE_INIT;
	return 1;  
}