/* This file demonstrates how to access a card in "VHL & Autoread" operation mode.
 *
 * This requires the reader to be configured for VHL & Autoread.
 *
 * Please refer to "./AppNote_VHL_&_Autoread-01.balcfg" as an example for
 * configuration for factory-new MIFARE Classic cards.
 */
 
 
#include <stdio.h>
#include <baltech_sdk.h>


// Name of VHL file to use for reading
// (to find it, open configuration in ConfigEditor and see
// "Configuration Components" list)
#define VHL_FILE_CARD_NAME      "VHL File for Counter"


static void exit_on_error(brp_errcode errcode, char *errormessage,
						  brp_protocol dev)
{
	if (errcode != BRP_OK)
	{
		char * errname = brp_map_errcode(errcode);
		if (errname == NULL)
			fprintf(stderr, "%s [brp_errcode:%08X]\n", errormessage, errcode);
		else
			fprintf(stderr, "%s [%s]\n", errormessage, errname);
		brp_destroy(dev);
		exit(EXIT_FAILURE);
	}
}


int main(int argc, char *argv[])
{
	unsigned vhlfile_id;
	brp_errcode errcode;
	bool is_configured_vhlfile_cardname, is_configured_vhlfile_ctrval;
	
	brp_protocol dev = brp_create();
	brp_set_io(dev, brp_create_usb_hid(0));
	errcode = brp_open(dev);
	exit_on_error(errcode, "Failed to connect to USB/HID device", dev);
	
	errcode = brp_VHL_ResolveFilename((brp_VHL_ResolveFilename_t){
		dev, .FileName=VHL_FILE_CARD_NAME, .Id=&vhlfile_id});
	exit_on_error(errcode, "Missing VHL file in reader configuration", dev);

	// Start scanning with Autoread and stop after first detected card
	// to run further VHL commands
	errcode = brp_AR_SetMode((brp_AR_SetMode_t){
		dev, .Mode=brp_AutoReadMode_EnableOnce});
	exit_on_error(errcode, "Reader is not configured for the Autoread operation mode", dev);
	
	printf("Please present card...");
	while (1)
	{
		printf(".");
		
		brp_buf uid;
		size_t uid_len;
		
		// Probe if card is detected
		errcode = brp_AR_GetMessage((brp_AR_GetMessage_t){
			dev, .MsgData=&uid, .MsgData_len=&uid_len});
		if (errcode == BRP_AR_ErrNoMessage) continue;
		exit_on_error(errcode, "Failed to poll for card", dev);
		break;
	}
	
	unsigned cntr;
	brp_buf read_cntr;
	
	// Read data from card
	errcode = brp_VHL_Read((brp_VHL_Read_t){
		dev, .Id=vhlfile_id, .Adr=0, .Len=sizeof(cntr),
		.Data=&read_cntr});
	exit_on_error(errcode, "Failed to read counter from card", dev);
	cntr = *(unsigned*)read_cntr;
	
	printf("\nDetected Card\n");
	printf("Counter value = %u\n", cntr);
	cntr += 1;
	
	// Write new data to card
	errcode = brp_VHL_Write((brp_VHL_Write_t){
		dev, .Id=vhlfile_id, .Adr=0,
		.Data=(brp_buf)&cntr, .Data_len=sizeof(cntr)});
	exit_on_error(errcode, "Failed to write counter to card", dev);
	
	printf("New counter value = %u\n", cntr);
	
	printf("Now remove card again...");
	while (1)
	{
		printf(".");
		
		// Probe if card is removed again
		errcode = brp_VHL_IsSelected((brp_VHL_IsSelected_t){dev});
		if (errcode == BRP_VHL_ErrCardNotSelected) break;
		exit_on_error(errcode, "Failed to probe for card", dev);
	}
	
	printf("\nDone\n");
	
	brp_destroy(dev);
	return EXIT_SUCCESS;
}
