Skip to main content

C API Reference

ABI-stable C interface defined in Reader/Reader_C.h. Provides extern "C" linkage for FFI from C, C#, Python, Rust, and other languages.

note

The C API uses extern "C" linkage for ABI stability but is typically consumed from C++ source files. The examples and type signatures below use C++ syntax for namespace-qualified types (e.g. RikCommon::ReaderDefinition).

#include "Reader/Reader_C.h"

Handle Types

Opaque pointer types used to reference reader instances.

typedef struct Reader_Handle* ReaderPtr;

The ReaderPtr handle is used for all common methods and reader-specific functions.

Error Handling

Every function takes RikResult& rikResult as its first parameter. Check rikResult.HasException after each call.

RikResult

typedef struct {
bool HasException;
char ExceptionType[256];
char Message[2048];
char FileName[2048];
int LineNumber;
char FunctionName[256];

bool HasProtocolException;
char ProtocolExceptionType[256];
char ProtocolMessage[2048];
char ProtocolFileName[2048];
int ProtocolLineNumber;
char ProtocolFunctionName[256];
} RikResult;
FieldDescription
HasExceptiontrue if the call failed
ExceptionTypeException class name
MessageHuman-readable error description
FileNameSource file where the error originated
LineNumberLine number of the error
FunctionNameFunction that raised the error
HasProtocolExceptiontrue if a protocol-level error also occurred
Protocol*Matching fields for the inner protocol exception

Usage pattern:

RikResult result = {0};

Rik_Init(result, handle);

if (result.HasException) {
fprintf(stderr, "Error: %s\n", result.Message);
fprintf(stderr, " at %s:%d in %s\n",
result.FileName, result.LineNumber, result.FunctionName);

if (result.HasProtocolException) {
fprintf(stderr, "Protocol error: %s\n", result.ProtocolMessage);
}
}

Factory Functions

RikReader_Open

Opens a connection to a reader.

ReaderPtr RikReader_Open(
RikResult& rikResult,
const RikCommon::ReaderDefinition& readerDefinition,
int retryCount);
ParameterTypeDescription
rikResultRikResult&Error output
readerDefinitionconst ReaderDefinition&Reader connection parameters
retryCountintNumber of connection retry attempts

Returns: Handle to the reader instance, or NULL on failure.

Common Methods

These functions accept any ReaderPtr.

Rik_Close

Closes the reader connection and destroys the handle.

void Rik_Close(RikResult& rikResult, ReaderPtr handle);
warning

Always call Rik_Close when finished, even if earlier operations failed.

Rik_Init

Initializes the reader after opening. Must be called before any other operations.

void Rik_Init(RikResult& rikResult, ReaderPtr handle);

Rik_RefreshMetadata

Forces a refresh of cached reader metadata from the device.

void Rik_RefreshMetadata(RikResult& rikResult, ReaderPtr handle);

Rik_GetMetadataStruct

Retrieves reader metadata (part number, serial, firmware version, etc.).

void Rik_GetMetadataStruct(
RikResult& rikResult,
ReaderPtr handle,
ReaderMetadataStruct* outStruct,
bool forceRefresh = false);
ParameterTypeDescription
rikResultRikResult&Error output
handleReaderPtrReader handle
outStructReaderMetadataStruct*Output buffer for metadata
forceRefreshboolBypass cache and query device (default: false)

Reader Methods

All reader methods require a ReaderPtr handle.

RikReader_Beep

Causes the reader to beep.

void RikReader_Beep(
RikResult& rikResult,
ReaderPtr handle,
uint8_t beepCount,
uint8_t duration);
ParameterTypeDescription
beepCountuint8_tNumber of beeps
durationuint8_tBeep duration enum value

RikReader_GetCardData

Reads raw card data from the reader.

void RikReader_GetCardData(
RikResult& rikResult,
ReaderPtr handle,
uint8_t* cardDataOut,
size_t bufferLength,
uint32_t& bitCount,
RikProtocol::GetCardDataSizeParameters sizeParameter = RikProtocol::READ_32_BYTES);
ParameterTypeDescription
cardDataOutuint8_t*Output buffer for card bytes
bufferLengthsize_tSize of the output buffer
bitCountuint32_t&Output: number of valid bits read
sizeParameterRikProtocol::GetCardDataSizeParametersOptional. Read size; defaults to RikProtocol::READ_32_BYTES. See GetCardDataSizeParameters.
8-byte reads truncate silently

RikProtocol::READ_8_BYTES returns at most the first 8 bytes of the credential. The output buffer is still 32 bytes of card data: bytes 0–7 hold the returned data and bytes 8–31 are zero. bitCount always reports the full credential width, so a bit count greater than 64 means the card carries more data than was returned. Prefer RikProtocol::READ_32_BYTES. Reader_C.h is a C++ header with extern "C" linkage; C++ callers may omit sizeParameter because of the default argument.

RikReader_EnableKeystroking

Enables or disables keystroking.

void RikReader_EnableKeystroking(
RikResult& rikResult,
ReaderPtr handle,
bool enable);

RikReader_EnableTransparentMode

Enables or disables transparent mode. The writeToFlash parameter controls whether the setting persists across reader power cycles.

void RikReader_EnableTransparentMode(
RikResult& rikResult,
ReaderPtr handle,
uint8_t enable,
uint8_t writeToFlash);

RikReader_GetTransparentModeStatus

Returns the current transparent mode state and readiness status.

void RikReader_GetTransparentModeStatus(
RikResult& rikResult,
ReaderPtr handle,
RikProtocol::TransparentModeState& state,
RikProtocol::TransparentModeStatus& status);

RikReader_GetBeeperVolume / SetBeeperVolume

void RikReader_GetBeeperVolume(
RikResult& rikResult,
ReaderPtr handle,
uint8_t& volume);

void RikReader_SetBeeperVolume(
RikResult& rikResult,
ReaderPtr handle,
uint8_t volume);

RikReader_GetReaderConfiguration / SetReaderConfiguration

void RikReader_GetReaderConfiguration(
RikResult& rikResult,
ReaderPtr handle,
const uint8_t configNum,
ReaderConfigurationStruct& config,
ExtendedConfiguration& extConfig);

void RikReader_SetReaderConfiguration(
RikResult& rikResult,
ReaderPtr handle,
const uint8_t configNum,
const ReaderConfigurationStruct& config,
const ExtendedConfiguration& extConfig,
const HashData* hashData = nullptr);
ParameterTypeDescription
configNumuint8_tConfiguration slot number
configReaderConfigurationStruct&Reader configuration data
extConfigExtendedConfiguration&Extended configuration data
hashDataconst HashData*Optional hash data (Set only, default: nullptr)

RikReader_GetModuleState / SetModuleState

void RikReader_GetModuleState(
RikResult& rikResult,
ReaderPtr handle,
uint8_t moduleId,
uint32_t& state);

void RikReader_SetModuleState(
RikResult& rikResult,
ReaderPtr handle,
uint8_t moduleId,
uint32_t state);

RikReader_GetLedConfiguration / SetLedConfiguration

void RikReader_GetLedConfiguration(
RikResult& rikResult,
ReaderPtr handle,
uint8_t configNum,
LedConfiguration& ledConfig);

void RikReader_SetLedConfiguration(
RikResult& rikResult,
ReaderPtr handle,
uint8_t configNum,
const LedConfiguration& ledConfig);

RikReader_GetLuid / SetLuid

void RikReader_GetLuid(
RikResult& rikResult,
ReaderPtr handle,
LuidResponseInformation& luidInfo);

void RikReader_SetLuid(
RikResult& rikResult,
ReaderPtr handle,
uint16_t luid);

RikReader_GetSupportedCardTypes

void RikReader_GetSupportedCardTypes(
RikResult& rikResult,
ReaderPtr handle,
SupportedCardTypesResult* outResult);

RikReader_OnCredentialPresented

Registers a callback that fires when a card is presented to the reader. The library polls on a background thread and invokes the callback on the leading edge of card presence.

typedef void (*CredentialCallback)(const uint8_t* cardData, uint32_t bitCount);

uint32_t RikReader_OnCredentialPresented(
RikResult& rikResult,
ReaderPtr handle,
CredentialCallback callback,
RikProtocol::GetCardDataSizeParameters sizeParameter = RikProtocol::READ_32_BYTES);
ParameterTypeDescription
rikResultRikResult&Error output
handleReaderPtrReader handle
callbackCredentialCallbackFunction pointer called with card data and bit count
sizeParameterRikProtocol::GetCardDataSizeParametersOptional. Read size used by the shared polling thread; defaults to RikProtocol::READ_32_BYTES. See GetCardDataSizeParameters.

Returns: Subscription ID (0 on error).

Read size is shared across subscribers

There is one read size per reader instance. A later RikReader_OnCredentialPresented call with a different sizeParameter changes the payload delivered to all existing subscribers on that reader.

RikReader_UnsubscribeCredentialCallback

Removes a previously registered credential callback.

void RikReader_UnsubscribeCredentialCallback(
RikResult& rikResult,
ReaderPtr handle,
uint32_t subscriptionId);
ParameterTypeDescription
rikResultRikResult&Error output
handleReaderPtrReader handle
subscriptionIduint32_tID returned by RikReader_OnCredentialPresented

RikReader_ReadBleConfigurationFromReader / WriteBleConfigurationToReader

void RikReader_ReadBleConfigurationFromReader(
RikResult& rikResult,
ReaderPtr handle,
uint8_t dataType,
const char* fileName);

void RikReader_WriteBleConfigurationToReader(
RikResult& rikResult,
ReaderPtr handle,
uint8_t dataType,
const char* fileName);
ParameterTypeDescription
dataTypeuint8_tBLE data type identifier
fileNameconst char*Path to the BLE configuration file

RikReader_WriteUserDefaultsToReader

Copies the reader's active flash configuration to stored (user-default) flash.

void RikReader_WriteUserDefaultsToReader(
RikResult& rikResult,
ReaderPtr handle);

RikReader_ResetReaderConfiguration

Resets the reader configuration to a checkpoint.

void RikReader_ResetReaderConfiguration(
RikResult& rikResult,
ReaderPtr handle,
uint8_t checkpointType);
ParameterTypeDescription
checkpointTypeuint8_tCheckpoint to restore (1 = FactoryDefaults, 2 = UserSettings)

RikReader_WriteHwgFileToReader / ReadHwgFileFromReader

Writes an HWG configuration file to the reader, or reads the current configuration from the reader into an HWG file.

void RikReader_WriteHwgFileToReader(
RikResult& rikResult,
ReaderPtr handle,
const char* fileName);

void RikReader_ReadHwgFileFromReader(
RikResult& rikResult,
ReaderPtr handle,
const char* fileName,
bool secureHwgFormat = true);
ParameterTypeDescription
fileNameconst char*Path to the HWG file
secureHwgFormatboolRead only. If true (default), writes the AES-128 encrypted format

RikReader_WriteSmartCardConfigurationToReader / ReadSmartCardConfigurationFromReader

Writes a smart card configuration file to the reader, or reads the reader's smart card configuration into the provided struct.

void RikReader_WriteSmartCardConfigurationToReader(
RikResult& rikResult,
ReaderPtr handle,
const char* fileName);

void RikReader_ReadSmartCardConfigurationFromReader(
RikResult& rikResult,
ReaderPtr handle,
RikCommon::SmartCardConfigurationStruct& configuration);
ParameterTypeDescription
fileNameconst char*Write only. Path to the smart card configuration file
configurationSmartCardConfigurationStruct&Read only. Output: smart card configuration read from the reader

Reader Discovery

Standalone function -- no handle required.

Rik_DiscoverUsbReaders

Discovers all connected rf IDEAS USB readers. Uses a two-call pattern: call first with readers set to nullptr to get the count, then allocate a buffer and call again to retrieve the results.

void Rik_DiscoverUsbReaders(
RikResult& rikResult,
RikCommon::ReaderDefinition* readers,
size_t* readerCount);
ParameterTypeDescription
rikResultRikResult&Error output
readersReaderDefinition*Output buffer, or nullptr to query count only
readerCountsize_t*In/out: buffer size on input, number of readers found on output

Each returned ReaderDefinition has DeviceId.VendorId, DeviceId.ProductId, DeviceId.UsbPath, DeviceId.SerialNumber, and ProtocolType populated and can be passed directly to RikReader_Open.

RikResult result = {0};
size_t count = 0;

// First call: get count
Rik_DiscoverUsbReaders(result, nullptr, &count);
if (result.HasException || count == 0) return;

// Second call: retrieve readers
RikCommon::ReaderDefinition* readers =
(RikCommon::ReaderDefinition*)calloc(count, sizeof(RikCommon::ReaderDefinition));
Rik_DiscoverUsbReaders(result, readers, &count);

if (!result.HasException) {
for (size_t i = 0; i < count; i++) {
printf("Reader %zu: VID=%04X PID=%04X Path=%s\n",
i, readers[i].DeviceId.VendorId,
readers[i].DeviceId.ProductId,
readers[i].DeviceId.UsbPath);
}
}

free(readers);

See Discovering USB Readers for a full walkthrough.

Library Info

Standalone function -- no handle required.

LibraryInfo Rik_BuildLibraryInfo();

Returns: LibraryInfo struct containing version and build information.

LibraryInfo info = Rik_BuildLibraryInfo();
printf("RIK %s\n", info.VersionString);

Examples

Open, Init, Use, Close

#include <stdio.h>
#include "Reader/Reader_C.h"

int main() {
RikResult result = {0};

// 1. Open
RikCommon::ReaderDefinition readerDef = {0};
readerDef.DeviceId.VendorId = 0x0C27;
readerDef.DeviceId.ProductId = 0x3BFA;
readerDef.ProtocolType = PROTOCOL_TYPE_FEATURE_REPORT;

ReaderPtr handle = RikReader_Open(result, readerDef, 3);
if (result.HasException) {
fprintf(stderr, "Open failed: %s\n", result.Message);
return 1;
}

// 2. Init
Rik_Init(result, handle);
if (result.HasException) {
fprintf(stderr, "Init failed: %s\n", result.Message);
Rik_Close(result, handle);
return 1;
}

// 3. Use -- read metadata
ReaderMetadataStruct metadata = {0};
Rik_GetMetadataStruct(result, handle, &metadata, false);
if (!result.HasException) {
printf("Part Number: %s\n", metadata.PartNumber);
printf("Serial: %s\n", metadata.ESN);
}

// 3. Use -- beep
RikReader_Beep(result, handle, 2, BEEP_DURATION_SHORT);

// 4. Close
Rik_Close(result, handle);
return 0;
}

Error Handling with Goto Cleanup

int configure_reader(const RikCommon::ReaderDefinition* readerDef) {
RikResult result = {0};
int rc = 0;

ReaderPtr handle = RikReader_Open(result, *readerDef, 3);
if (result.HasException) { rc = 1; goto done; }

Rik_Init(result, handle);
if (result.HasException) { rc = 1; goto cleanup; }

// Disable keystroking
RikReader_EnableKeystroking(result, handle, false);
if (result.HasException) { rc = 1; goto cleanup; }

printf("Reader configured successfully\n");

cleanup:
{
RikResult closeResult = {0};
Rik_Close(closeResult, handle);
}
done:
if (rc != 0) {
fprintf(stderr, "Error: %s\n", result.Message);
}
return rc;
}

Reading Card Data

void poll_card(ReaderPtr handle) {
RikResult result = {0};
uint8_t cardBuffer[64] = {0};
uint32_t bitCount = 0;

RikReader_GetCardData(result, handle, cardBuffer, sizeof(cardBuffer), bitCount);

if (result.HasException) {
fprintf(stderr, "Card read error: %s\n", result.Message);
return;
}

if (bitCount == 0) {
printf("No card present\n");
return;
}

printf("Card data (%u bits):", bitCount);
size_t byteCount = (bitCount + 7) / 8;
for (size_t i = 0; i < byteCount; i++) {
printf(" %02X", cardBuffer[i]);
}
printf("\n");
}
uint8_t cardBuffer[32] = {0};
uint32_t bitCount = 0;

// 8-byte read
RikReader_GetCardData(result, handle, cardBuffer, sizeof(cardBuffer), bitCount,
RikProtocol::READ_8_BYTES);
if (bitCount > 64) {
// bytes 8-31 are zero; data was truncated
}

See Also