I am using an ACR122U NFC reader to password protect an NTAG213 NFC label. I think I have managed to set the password correctly, but I cannot authenticate and change the label afterward. My code for authenticating looks like this:
#include <winscard.h>
#include <iostream>
#pragma comment(lib, "winscard.lib")
const char *ReaderName = "ACS ACR122 0";
unsigned Password = 0x12345678;
int main()
{
//Establish context
SCARDCONTEXT hContext;
DWORD SCard_Status1 = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &hContext);
if(SCard_Status1 != SCARD_S_SUCCESS)
return 1;
//connect to the card
SCARDHANDLE hCardHandle;
DWORD Protocol;
DWORD SCard_Status2 = SCardConnect(hContext, ReaderName, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &hCardHandle, &Protocol);
if(SCard_Status2 != SCARD_S_SUCCESS)
{
SCardReleaseContext(hContext);
return 1;
}
SCARD_IO_REQUEST Request;
Request.dwProtocol = Protocol;
Request.cbPciLength = sizeof(SCARD_IO_REQUEST);
BYTE TxData[] =
{
0xFF, //CLA
0x00, //INS
0x00, //P1
0x00, //P2
0x08, //LC
0xD4,
0x40,
0x01,
0x1B, //PWD_AUTH (See data sheet)
Password,
Password >> 8,
Password >> 16,
Password >> 24,
};
BYTE RxData[254];
unsigned long RxLength = sizeof(RxData);
DWORD SCard_Status3 = SCardTransmit(hCardHandle, &Request, TxData, sizeof(TxData), NULL, RxData, &RxLength);
std::cout << "SCard_Status = " << SCard_Status3 << std::endl;
std::cout << "RxLength = " << RxLength << std::endl;
SCardDisconnect(hCardHandle, SCARD_EJECT_CARD);
SCardReleaseContext(hContext);
return 0;
}
This should send the PWD_AUTH command to the NTAG213 with the Pwd. I expected to receive an error if the password is wrong or two bytes with the PACK if the password is correct. But SCard_Status is SCARD_S_SUCCESS and RxLength is 0 afterwards. And if I try to write to the label I get an error.
I am having trouble finding any examples showing how to do this. Can anyone see what I am doing wrong?
I am going to answer this myself. I managed to make it work by changing TxData to this:
BYTE TxData[] =
{
0xFF, //CLA
0x00, //INS
0x00, //P1
0x00, //P2
0x07, //LC
0xD4, 0x42, //InCommunicateThru
0x1B, //PWD_AUTH (See data sheet)
Password,
Password >> 8,
Password >> 16,
Password >> 24,
};
I found the command InCommunicateThru (D4 42) as a replacement for InDataExchange (D4 40) in the data sheet for the PN532, which is the NFC processor inside the ACR122U.
Related
I'm using an NTAG I2C plus 2k memory tag and using the react-native-nfc-manager library to interface with the tag.
Is there a way to specify the sector that you're intending to write to?
I know there is an API to specify the page offset to write to, but how do you specify the sector the page offsets are in?
(Updated to include below code sample)
let tech = Platform.OS === 'ios' ? NfcTech.MifareIOS : NfcTech.NfcA;
await NfcManager.requestTechnology(tech, {
alertMessage: 'Hold your phone close to the NFC tag.',
});
let fullLength = data.length + 7;
let payloadLength = data.length + 3;
let cmd =
Platform.OS === 'ios'
? NfcManager.sendMifareCommandIOS
: NfcManager.transceive;
// select sector 2 prior to writing data
await cmd([0xc2, 0xff]);
await cmd([0x02, 0x00, 0x00, 0x00]);
await cmd([
0xa2,
MEMORY_MAPPING[`${chunkToWriteTo}`][1],
0x03,
fullLength,
0xd1,
0x01,
]);
await cmd([
0xa2,
MEMORY_MAPPING[`${chunkToWriteTo}`][2],
payloadLength,
0x54,
0x02,
0x65,
]);
let currentPage = MEMORY_MAPPING[`${chunkToWriteTo}`][0] + 2;
let currentPayload = [0xa2, currentPage, 0x6e];
for (let i = 0; i < data.length; i++) {
currentPayload.push(parseInt(data[i]));
if (currentPayload.length == 6) {
try {
await cmd(currentPayload);
} catch (error) {
console.log(error);
}
currentPage += 1;
currentPayload = [0xa2, currentPage];
}
}
Thanks in advance.
So "NTAG I2C plus 2k" seems to be a Certified Type 2 tag using NfcA comms.
It's datasheet
This Tag has additional commands over the Type 2 Standard to select the sector because Type 2 Tag's don't normally have Sectors.
So reading the datasheet Section 10.12 you would transceive the following commands bytes an example
C2h FFh - Select Sector
03h 00h 00h 00h - Sector 3
Then write to page address as normal with the A2h command byte
react-native-nfc-manage offers an nfcAHandler with a transceive method to send and receive these low level commands to the NFC chip.
Update:
For iOS it treats Type 2 Tags as Mifare Ultralight's and thus sendMifareCommandIOS from the API to send the same commands.
(Both Android and iOS have the nfcAHandler)
Note I've not tried this, I just do things with normal Type 2 Tags
I need to detect when a gamepad is plugged in for my game (I'm not using a higher-level input API for reasons), how can I do this? I've already enumerated all HID devices and opened files on them (except keyboard, mouse ofc) and can get all the info on the device, but what info do I want? What value(s) will tell me right away that this is an xbox controller, for example, and where are these values?
My code for enumerating over the devices (very messy atm :p):
DWORD required_size = 0, determined_size;
SP_DEVICE_INTERFACE_DATA device_interface_data;
device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
PSP_DEVICE_INTERFACE_DETAIL_DATA device_interface_detail_data;
HANDLE current_device;
PHIDP_PREPARSED_DATA preparsed_data;
WCHAR product_string[128];
for (int i = 0; ; ++i) /* Enumerate HID devices */
{
rv = SetupDiEnumDeviceInterfaces(device_enumeration, NULL, &interface_guid, i, &device_interface_data); /* Does the actual enumeration,
each time we increase index i
to get the next device */
error = GetLastError();
if (error == ERROR_NO_MORE_ITEMS) /* If there are no more devices, break */
break;
else if (!rv && error != ERROR_NO_MORE_ITEMS) /* Otherwise, we have a legit error */
{
cr_print_error(GetLastError());
return EXIT_FAILURE;
}
SetupDiGetDeviceInterfaceDetail(device_enumeration, &device_interface_data, NULL, 0, &required_size, NULL); /* Probing call only to get buffer size,
so error code (122) ignored */
/* Allocate new device detail struct using buffer size we obtained */
determined_size = required_size;
device_interface_detail_data = cr_safe_malloc(required_size);
device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
/* Get detailed info about device */
rv = SetupDiGetDeviceInterfaceDetail(device_enumeration, &device_interface_data, device_interface_detail_data, determined_size, &required_size, NULL);
if (!rv)
{
cr_print_error(GetLastError());
return EXIT_FAILURE;
}
cr_printf("FOUNDD DEVICE: %s\n\n", device_interface_detail_data->DevicePath);
current_device = cr_open_device(device_interface_detail_data->DevicePath);
if (!current_device && GetLastError() == ERROR_ACCESS_DENIED)
goto Done;
cr_printf("OPENED DEVICE: %s\n\n", device_interface_detail_data->DevicePath);
preparsed_data = HidD_GetPreparsedData(current_device, &preparsed_data);
if (!preparsed_data)
{
cr_print_error(GetLastError());
return EXIT_FAILURE;
}
HidD_GetProductString(current_device, product_string, sizeof(product_string));
cr_printf("PRODUCT STRING: %S\n\n", product_string);
HidD_FreePreparsedData(&preparsed_data);
DeleteFile(device_interface_detail_data->DevicePath);
Done:
cr_safe_free(&device_interface_detail_data);
}
SetupDiDestroyDeviceInfoList(device_enumeration);
As you can see I've found the product string, which tells me what the device actually is, but maybe comparing product strings is not the best way to do PnP?
Check if the device ID contains "IG_". If it does, then it's an XInput device.
More info on that. But which device corresponds to which XInput dwUserIndex is more difficult question...
Also you can try to check for XUSB interface:
// {EC87F1E3-C13B-4100-B5F7-8B84D54260CB}
DEFINE_GUID(XUSB_INTERFACE_CLASS_GUID, 0xEC87F1E3, 0xC13B, 0x4100, 0xB5, 0xF7, 0x8B, 0x84, 0xD5, 0x42, 0x60, 0xCB);
I am trying to open a device driver in order to send it an ioctl. There are many examples on SO and elsewhere but virtually all address opening "\\.\PhysicalDrive0" or the like. But I am trying to open a non-disk driver, compiled from Microsoft sample code at GitHub "Windows-driver-samples", namely "simgpio". It appears to have installed correctly but I don't know what "\\.\name" to use. I tried "\\.\simgpio" with no joy. Suggestions?
For reference, I've included the driver's .INF file below.
;/*++
;
;Copyright (c) Microsoft Corporation. All rights reserved.
;
;Module Name:
;
; SIMGPIO.INF
;
;Abstract:
; INF file for installing Simulated GPIO Client Driver.
;
;--*/
[Version]
Signature="$WINDOWS NT$"
Class=System
ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}
Provider=%ProviderName%
DriverVer = 06/30/2020,15.29.58.35
CatalogFile=gpiosamples.cat
[SourceDisksNames]
3426=windows cd
[SourceDisksFiles]
simgpio.sys = 3426
[DestinationDirs]
DefaultDestDir = 12
[ControlFlags]
BasicDriverOk = *
ExcludeFromSelect = *
;******************************************
; SIMGPIO Client driver Install Section
;******************************************
[Manufacturer]
%ManufacturerName%=Standard,NTx86
[Standard.NTx86]
%GPIO.DeviceDesc% = GPIO_Inst,ACPI\TEST0001
[GPIO_Inst.NT]
Copyfiles = GPIOCopyFiles
[GPIOCopyFiles]
simgpio.sys,,,0x100
[GPIO_Inst.NT.Services]
AddService = simgpio,%SPSVCINST_ASSOCSERVICE%,GPIO_Service_Inst
[GPIO_Service_Inst]
DisplayName = %GPIO.SvcDesc%
ServiceType = %SERVICE_KERNEL_DRIVER%
StartType = %SERVICE_DEMAND_START%
ErrorControl = %SERVICE_ERROR_NORMAL%
ServiceBinary = %12%\simgpio.sys
[strings]
; localizable strings
ProviderName = "TODO-Set-Provider"
ManufacturerName = "TODO-Set-Manufacturer"
GPIO.DeviceDesc = "Simulated GPIO Client Driver"
GPIO.SvcDesc = "Simulated GPIO Client Driver"
; non-localizable strings
SPSVCINST_TAGTOFRONT = 0x00000003
SPSVCINST_ASSOCSERVICE = 0x00000002
SERVICE_KERNEL_DRIVER = 1
SERVICE_BOOT_START = 0
SERVICE_SYSTEM_START = 1
SERVICE_DEMAND_START = 3
SERVICE_ERROR_NORMAL = 1
SERVICE_ERROR_IGNORE = 0
SERVICE_ERROR_CRITICAL = 3
REG_EXPAND_SZ = 0x00020000
REG_DWORD = 0x00010001
REG_SZ = 0x00000000
Thanks to comment by #Eryk, I was able to open a driver. I include a sample program below. All error checking was omitted for clarity. I used the CDROM driver class in this example. The real challenge is finding the elusive GUID to use - you must do some deep digging in the SDK, DDK, include files or your driver.
// enumdevices.c - enumerate and open device(s)
#pragma warning( disable : 4090 )
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <setupapi.h>
#include <cfgmgr32.h>
int
main( int argc,char** argv)
{
#define ALLOC(size) GlobalAlloc( GPTR, size)
SP_DEVINFO_DATA *devData;
HANDLE devSet;
HANDLE hDev;
SP_DEVICE_INTERFACE_DATA *devIfData;
SP_DEVICE_INTERFACE_DETAIL_DATA *Details;
GUID *devGuid;
DWORD needed;
DWORD unused;
int count; // count of enumerated devices
DWORD idev; // device index
DWORD iface; // interface index
char deviceID[200]; // device id string
int IDSize;
BOOL ok;
devData = ALLOC( sizeof(SP_DEVINFO_DATA) );
devData->cbSize = sizeof(SP_DEVINFO_DATA);
// GET SET OF DEVICE INTERFACES PRESENT OF SPECIFIED devGuid
devGuid = &GUID_DEVINTERFACE_CDROM; // set dev class guid to enumerate
devSet = SetupDiGetClassDevs( devGuid, NULL, NULL, DIGCF_DEVICEINTERFACE|DIGCF_PRESENT );
// OUTER LOOP
idev = 0;
count = 0;
while( TRUE ) {
// GET DEVICE INFO DATA
ok = SetupDiEnumDeviceInfo( devSet, idev, devData );
if (!ok) break;
// GET ID SIZE
devData->cbSize = sizeof(SP_DEVINFO_DATA);
CM_Get_Device_ID_Size( &IDSize, devData->DevInst, 0 );
// GET DEVICE ID
CM_Get_Device_ID( devData->DevInst, deviceID, 200, 0 );
printf("Device Instance #%d: deviceId = \"%s\"\n", devData->DevInst, deviceID ); // print it
count++;
devIfData = ALLOC( sizeof(SP_DEVICE_INTERFACE_DATA) );
devIfData->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
iface = 0; // init index
while ( TRUE ) { // loop over all interfaces in set
// GET DEVICE INTERFACE DATA index=iface
ok = SetupDiEnumDeviceInterfaces(
devSet, // handle to interface set
devData,
devGuid, //&GUID_DEVINTERFACE_USB_DEVICE,
iface, // interface index
devIfData);
if( !ok ) break;
// GET NEEDED BUFFER SIZE
devIfData->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
ok = SetupDiGetDeviceInterfaceDetail(
devSet,
devIfData,
NULL,
0,
&needed,
0 );
Details = ALLOC( needed );
Details->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); // IMPORTANT!
// GET DEVICE DETAILS
ok = SetupDiGetDeviceInterfaceDetail(
devSet, // device set
devIfData, // device info data
Details, // detail data
needed, // size of Details
&unused, // unused
NULL ); // device info data (can be NULL)
printf("%s\n", Details->DevicePath); // announce
// OPEN DEVICE
hDev = CreateFile(Details->DevicePath,
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if( hDev != INVALID_HANDLE_VALUE ) {
printf( "Device successfully opened\n" );
// DO SOMETHING WITH DEVICE HANDLE (e.g., DeviceIoControl)...
CloseHandle(hDev);
}
iface++;
}
idev++; // next device
}
printf("\nenumerated %d device interfaces\n", count);
fprintf(stderr, "Press any key to exit...\n");
_getch();
}
Here are some other GUIDs you can use:
static GUID GUID_DEVINTERFACE_DISK =
{ 0x4d36e967L, 0xe325, 0x11ce, { 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 } };
static GUID GUID_DEVINTERFACE_USB_DEVICE =
{ 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
static GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER =
{ 0x3abf6f2d, 0x71c4, 0x462a, {0x8a, 0x92, 0x1e, 0x68, 0x61, 0xe6, 0xaf, 0x27} };
static GUID GUID_DEVINTERFACE_USB_HUB =
{ 0xf18a0e88, 0xc30c, 0x11d0, {0x88, 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8} };
I would like map a chars that doesn't exists on my keyboard layout is it possible?
My keyboard layout is italian and the the chars is ~ and `
I would like remap when I press AltGr (VK_RMENU) + VK_OEM_4 or VK_OEM_6.
But this chars aren't in Virtual-Key Codes list, so I think I coud't use SendInput for remapping...
For others chars SendInput works
But this chars aren't in Virtual-Key Codes list, so I think I coud't
use SendInput for remapping...
The ~ and ` are in the Virtual-Key Codes list. It is VK_OEM_3 (0xC0).
You can use SendInput enter ~ and ` like this:
UINT result = 0;
DWORD errCode = 0;
tagINPUT inputArray[2] = {};
tagKEYBDINPUT keyboardInput[2] = {};
keyboardInput[1].wVk = 0xC0; // Virtual-Key code for the '`~' key.
keyboardInput[1].wScan = 0x29; // Scan code for the '`~' key.
inputArray[1].type = INPUT_KEYBOARD;
inputArray[1].ki = keyboardInput[1];
keyboardInput[0].wVk = 0x10; // Virtual-Key code for the 'shift' key.
keyboardInput[0].wScan = 0x2A; // Scan code for the 'shift' key.
inputArray[0].type = INPUT_KEYBOARD;
inputArray[0].ki = keyboardInput[0];
// Enter '~' (shift + '`~' key)
result = SendInput(2, inputArray, sizeof(tagINPUT));
errCode = GetLastError();
// Enter '`'
result = SendInput(1, &inputArray[1], sizeof(tagINPUT));
errCode = GetLastError();
If you want to enter these two chars the SendMessage also can do this (similar issue):
LPCWSTR Target_window_Name = TEXT("Untitled - Notepad"); //<- Has to match window name
HWND hWindowHandle = FindWindow(NULL, Target_window_Name);
HWND EditClass = FindWindowEx(hWindowHandle, NULL, L"Edit", NULL);
SendMessage(EditClass, WM_KEYDOWN, 0xC0, 0x002C0001); //VK_OEM_3 0xC0
SendMessage(EditClass, WM_CHAR, 0x7E, 0x002C0001); //~
SendMessage(EditClass, WM_KEYUP, 0xC0, 0xC02C0001);
SendMessage(EditClass, WM_KEYDOWN, 0xC0, 0x002C0001); //VK_OEM_3 0xC0
SendMessage(EditClass, WM_CHAR, 0x60, 0x002C0001); //`
SendMessage(EditClass, WM_KEYUP, 0xC0, 0xC02C0001);
References: "SendInput" "SendMessage"
For scan code you can search "Keyboard Scan Code Specification - Microsoft".
how to get the serial port name by my red pen. Not COM5.COM5 can be gotten by windows-API. If you know it, please let me know. I'll appreciate it!
enter image description here
Now, I can get both serial ports full name and COMX. But which is true? I know how to find true one by manual manipulation instead of my coding program. But how to find true one by my coding program.
enter code here
GUID classGuids = {0x4D36E978L, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18}; //GetClassGUIDs("ports"); //&GUID_DEVCLASS_PORTS
HDEVINFO hDevInfo = SetupDiGetClassDevs((LPGUID)&classGuids, NULL, NULL, 0);
if(hDevInfo)
{
SP_DEVINFO_DATA SpDevInfo={sizeof(SP_DEVINFO_DATA)};
for(DWORD iDevIndex=0; SetupDiEnumDeviceInfo(hDevInfo, iDevIndex, &SpDevInfo); iDevIndex++)
{
TCHAR szName[512] = {0};
if(SetupDiGetDeviceRegistryProperty(hDevInfo, &SpDevInfo, SPDRP_FRIENDLYNAME,
NULL, (PBYTE)szName, sizeof(szName), NULL))
{
_tprintf(_T("........%s\n"), szName);
}
}
SetupDiDestroyDeviceInfoList(hDevInfo);