What capabilities required for ioctl() on emmc on systemd? - systemd

I want to run my program with systemd with a regular user ( non-root). This program uses ioctl() syscall to access emmc registers.I want to learn which capabilities required to be added to my systemd unit file.
I tried with below unit file:
[Unit]
Description=EMMC-LIFETIME UTILITY
[Service]
User=tron
Group=disk
ExecStart=/HARICI/emmc-lifetime /dev/mmcblk0 -v
CapabilityBoundingSet=CAP_SYS_ADMIN
DeviceAllow=/dev/mmcblk0 rw
[Install]
WantedBy=multi-user.target
Here is the code of emmc-lifetime:
int main(int argc, char **argv)
{
if(argc < 2){
printf("Usage: %s <mmcfilename> (-v)\n", argv[0]);
printf("Example: %s /dev/mmcblk1 -v\n", argv[0]);
return 1;
}
char ext_csd[512], ext_csd_rev;
int fd, ret;
fd = open(argv[1], O_RDWR);
if (fd < 0) {
printf("Failed to open eMMC device, please check which path you have passed\n");
return 1;
}
struct mmc_ioc_cmd idata;
memset(&idata, 0, sizeof(idata));
memset(ext_csd, 0, sizeof(char) * 512);
idata.write_flag = 0;
idata.opcode = MMC_SEND_EXT_CSD;
idata.arg = 0;
idata.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
idata.blksz = 512;
idata.blocks = 1;
mmc_ioc_cmd_set_data(idata, ext_csd);
ret = ioctl(fd, MMC_IOC_CMD, &idata);
if (ret){
printf("ioctl failed, are you sure it is an MMC device???\n");
return ret;
}
ext_csd_rev = ext_csd[EXT_CSD_REV];
if (ext_csd_rev >= 7) {
if(argc==3 && !strcmp(argv[2],"-v")){
printf("EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A: 0x%02x\n",
ext_csd[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A]);
printf("EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B: 0x%02x\n",
ext_csd[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B]);
printf("EXT_CSD_PRE_EOL_INFO: 0x%02x\n",
ext_csd[EXT_CSD_PRE_EOL_INFO]);
}else{
printf("%d\n",ext_csd[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B]*10);
}
}
if(fd)
close(fd);
return ret;
If I comment out "User=tron" in my unit file, everything works expectedly:
Nov 03 01:17:03 tron systemd[1]: Started EMMC-LIFETIME UTILITY.
Nov 03 01:17:03 tron emmc-lifetime[28294]: EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A: 0x01
Nov 03 01:17:03 tron emmc-lifetime[28294]: EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B: 0x01
Nov 03 01:17:03 tron emmc-lifetime[28294]: EXT_CSD_PRE_EOL_INFO: 0x01
But if I uncomment "User=tron", here is the result:
Nov 03 00:57:17 tron systemd[1]: Started EMMC-LIFETIME UTILITY.
Nov 03 00:57:17 tron emmc-lifetime[27706]: ioctl failed, are you sure it is an MMC device???
Nov 03 00:57:17 tron systemd[1]: emmc-info.service: Main process exited, code=exited, status=255/n/a
Nov 03 00:57:18 tron systemd[1]: emmc-info.service: Unit entered failed state.
Nov 03 00:57:18 tron systemd[1]: emmc-info.service: Failed with result 'exit-code'.
What capabilities are required in my unit file to run my executable as "tron" user ?

Solved. For the capabilities side, it must have CAP_SYS_RAWIO.
We can use :
setcap cap_sys_rawio=+eip /HARICI/emmc-lifetime
And by this way, we can run "emmc-lifetime" binary with non-root user. Please note that, this user must be in "disk" group to be able to open "/dev/mmcblkX"
But unfortunately, this doesn't work in systemd unit files.
In systemd unit files, if you write:
User=some-non-root-user
CapabilityBoundingSet=SOME_CAPABILITY
Does not work. Thats why my above code allways fails.
I must find another way to run my binary with non-root privileges.

Related

pid_task() causes kernel panic, linux kernel 5.4

I am trying to send a signal from the kernel space to the user space.
I have the below code and I am seeing a kernel panic.
[ 5230.132362] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: prog_irq_handler+0x1d4/0x2cc [prog_mon]
[ 5230.146795] ---[ end Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: prog_irq_handler+0x1d4/0x2cc
Upon debugging some more, I found that the source of the panic is from the below function:
t = pid_task(find_pid_ns(id, &init_pid_ns), PIDTYPE_PID);
Referencing the value of "t" seems to cause an exception, resulting in a kernel panic.
Is there any known issue with the kernel 5.4 wrt the pid_task().
Any help will be appreciated.
My kernel comes from yocto, and it is:
branch ti-linux-5.4.y
commit 6f3bf13d53820fc12432d7052744be2ee046fc92 (HEAD -> ti-linux-5.4.y)
Merge: d2f658ed506d d5ef1ab82339
Author: LCPD Auto Merger lcpd_integration#list.ti.com
Date: Fri Apr 3 10:50:48 2020 -0500
https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/
Full code below:
send_signal(int val, int id, int sig)
{
struct kernel_siginfo info;
struct task_struct *t;
int ret;
ret = 0;
if ((id > 0) && (sig > 0)) {
memset(&info, 0, sizeof(struct siginfo));
info.si_signo = sig;
/* Using SI_KERNEL here results in real_time data not getting delivered to the user space signal handler */
info.si_code = SI_QUEUE;
/* Real time signals may have 32 bits of data */
info.si_int = val;
info._sifields._rt._sigval.sival_int = val;
info.si_errno = 0;
rcu_read_lock();
t = pid_task(find_pid_ns(id, &init_pid_ns), PIDTYPE_PID);
if(t == NULL) {
printk(KERN_ERR "%s: Invalid user handler PID %d\n", module_name, id);
rcu_read_unlock();
return -ENODEV;
}
ret = send_sig_info(sig, &info, t);
rcu_read_unlock();
if (ret < 0)
printk(KERN_INFO "%s: Failed to signal with data %d to user space\n", module_name, val);
}
return ret
}

<Windows Hello WBDI/EngineAdapter development> A question about Adapter Workflow

I got a problem when I developed the WBDI and EngineAdapter with my fingerprint module on Win10 OS.
The problem is why the EngineAdapter doesn't go into below callback functions, after I finished Step 1 and Step 2 below?
Because the document of Microsoft mentioned that below functions will be called when enrollment workflow goes through.
(https://learn.microsoft.com/zh-tw/windows/win32/secbiomet/adapter-workflow)
Below are the callback functions not be called.
(1) "EngineAdapterCreateEnrollment"
(2) "EngineAdapterSetEnrollmentParameters"
Does anyone know how to solve it?
Many thanks.
Step1
Step2
Adapter Workflow
EngineAdapter log
DllMain, Wed Mar 17 14:22:37 2021
WbioQueryEngineInterface, Wed Mar 17 14:22:37 2021
EngineAdapterAttach, Wed Mar 17 14:22:37 2021
EngineAdapterSelectCalibrationFormat, Wed Mar 17 14:22:37 2021
EngineAdapterPipelineInit, Wed Mar 17 14:22:37 2021
DllMain, Wed Mar 17 14:22:42 2021
EngineAdapterActivate, Wed Mar 17 14:22:42 2021
EngineAdapterQueryExtendedInfo, Wed Mar 17 14:22:42 2021
EngineAdapterSetAccountPolicy, Wed Mar 17 14:22:42 2021
DllMain, Wed Mar 17 14:22:43 2021
EngineAdapterClearContext, Wed Mar 17 14:22:45 2021
EngineAdapterQueryPreferredFormat, Wed Mar 17 14:22:45 2021
EngineAdapterCreateKey, Wed Mar 17 14:22:46 2021
EngineAdapterCreateKey, Wed Mar 17 14:22:46 2021
EngineAdapterAcceptSampleData, Wed Mar 17 14:22:46 2021
EngineAdapterIdentifyFeatureSet, Wed Mar 17 14:22:46 2021
EngineAdapterClearContext, Wed Mar 17 14:22:46 2021
EngineAdapterClearContext, Wed Mar 17 14:22:46 2021
WBDI log
IOCTL_BIOMETRIC_GET_ATTRIBUTES, Wed Mar 17 14:22:37 2021
IOCTL_BIOMETRIC_GET_SENSOR_STATUS, Wed Mar 17 14:22:45 2021
IOCTL_BIOMETRIC_GET_ATTRIBUTES, Wed Mar 17 14:22:45 2021
IOCTL_BIOMETRIC_CAPTURE_DATA, Wed Mar 17 14:22:45 2021
IOCTL_BIOMETRIC_CAPTURE_DATA, Wed Mar 17 14:22:45 2021
IOCTL_BIOMETRIC_GET_SENSOR_STATUS, Wed Mar 17 14:22:46 2021
EngineAdapter code (EngineAdapter.cpp)
static WINBIO_ENGINE_INTERFACE g_EngineInterface = {
#if (NTDDI_VERSION >= NTDDI_WIN10_RS4)
WINBIO_ENGINE_INTERFACE_VERSION_6,
#elif(NTDDI_VERSION >= NTDDI_WIN10_RS3)
WINBIO_ENGINE_INTERFACE_VERSION_5,
#elif(NTDDI_VERSION >= NTDDI_WIN10_RS1)
WINBIO_ENGINE_INTERFACE_VERSION_4,
#elif(NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
WINBIO_ENGINE_INTERFACE_VERSION_3,
#elif(NTDDI_VERSION >= NTDDI_WIN8)
WINBIO_ENGINE_INTERFACE_VERSION_2,
#elif
WINBIO_ENGINE_INTERFACE_VERSION_1,
#endif
WINBIO_ADAPTER_TYPE_ENGINE,
sizeof(WINBIO_ENGINE_INTERFACE),
{0xb876fdc8, 0x34e7, 0x471a, {0x82, 0xc8, 0x9c, 0xba, 0x6a, 0x35, 0x38, 0xec}},
EngineAdapterAttach,
EngineAdapterDetach,
EngineAdapterClearContext,
EngineAdapterQueryPreferredFormat,
EngineAdapterQueryIndexVectorSize,
EngineAdapterQueryHashAlgorithms,
EngineAdapterSetHashAlgorithm,
EngineAdapterAcceptSampleHint,
EngineAdapterAcceptSampleData,
EngineAdapterExportEngineData,
EngineAdapterVerifyFeatureSet,
EngineAdapterIdentifyFeatureSet,
EngineAdapterCreateEnrollment,
EngineAdapterUpdateEnrollment,
EngineAdapterGetEnrollmentStatus,
EngineAdapterGetEnrollmentHash,
EngineAdapterCheckForDuplicate,
EngineAdapterCommitEnrollment,
EngineAdapterDiscardEnrollment,
EngineAdapterControlUnit,
EngineAdapterControlUnitPrivileged,
#if(NTDDI_VERSION >= NTDDI_WIN8)
EngineAdapterNotifyPowerChange,
EngineAdapter_RESERVED,
//EngineAdapterReserved_1;
#endif//(NTDDI_VERSION >= NTDDI_WIN8)
#if(NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
//
// V3.0 methods begin here...
//
EngineAdapterPipelineInit,
EngineAdapterPipelineCleanup,
EngineAdapterActivate,
EngineAdapterDeactivate,
EngineAdapterQueryExtendedInfo,
EngineAdapterIdentifyAll,
EngineAdapterSetEnrollmentSelector,
EngineAdapterSetEnrollmentParameters,
EngineAdapterQueryExtendedEnrollmentStatus,
EngineAdapterRefreshCache,
EngineAdapterSelectCalibrationFormat,
EngineAdapterQueryCalibrationData,
EngineAdapterSetAccountPolicy,
#endif //(NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
#if(NTDDI_VERSION >= NTDDI_WIN10_RS1)
//
// V4.0 methods begin here...
//
EngineAdapterCreateKey,
EngineAdapterIdentifyFeatureSetSecure,
#endif//(NTDDI_VERSION >= NTDDI_WIN10_RS1)
#if(NTDDI_VERSION >= NTDDI_WIN10_RS3)
//
// V5.0 methods begin here...
//
EngineAdapterAcceptPrivateSensorTypeInfo,
#endif(NTDDI_VERSION >= NTDDI_WIN10_RS3)
#if(NTDDI_VERSION >= NTDDI_WIN10_RS4)
//
// V6.0 methods begin here...
//
EngineAdapterCreateEnrollmentAuthenticated,
EngineAdapterIdentifyFeatureSetAuthenticated
#endif//(NTDDI_VERSION >= NTDDI_WIN10_RS4)
};
WBDI code
switch (ControlCode) {
//
// Mandatory IOCTLs
//
case IOCTL_BIOMETRIC_GET_ATTRIBUTES:
m_BiometricDevice->OnGetAttributes(FxRequest);
break;
case IOCTL_BIOMETRIC_RESET:
m_BiometricDevice->OnReset(FxRequest);
break;
case IOCTL_BIOMETRIC_CALIBRATE:
m_BiometricDevice->OnCalibrate(FxRequest);
break;
case IOCTL_BIOMETRIC_GET_SENSOR_STATUS:
m_BiometricDevice->OnGetSensorStatus(FxRequest);
break;
case IOCTL_BIOMETRIC_CAPTURE_DATA:
m_BiometricDevice->OnCaptureData(FxRequest);
break;
}
void
CBiometricDevice::OnGetAttributes(
_Inout_ IWDFIoRequest *FxRequest
)
{
CRequestHelper MyRequest(FxRequest); // RAII helper class
ULONG controlCode = 0;
PUCHAR inputBuffer= NULL;
SIZE_T inputBufferSize = 0;
PWINBIO_SENSOR_ATTRIBUTES sensorAttributes = NULL;
SIZE_T outputBufferSize;
//
// Get the request parameters
//
GetIoRequestParams(FxRequest,
&controlCode,
&inputBuffer,
&inputBufferSize,
(PUCHAR *)&sensorAttributes,
&outputBufferSize);
//
// Make sure we have an output buffer big enough
//
if (sensorAttributes == NULL || outputBufferSize < sizeof(DWORD))
{
// We cannot return size information.
TraceEvents(TRACE_LEVEL_ERROR,
BIOMETRIC_TRACE_DEVICE,
"%!FUNC!Output buffer NULL or too small to return size information.");
MyRequest.SetCompletionHr(E_INVALIDARG);
return;
}
// We only have one supported format, so sizeof (WINBIO_SENSOR_ATTRIBUTES) is sufficient.
if (outputBufferSize < sizeof(WINBIO_SENSOR_ATTRIBUTES))
{
// Buffer too small.
TraceEvents(TRACE_LEVEL_ERROR,
BIOMETRIC_TRACE_DEVICE,
"%!FUNC!Buffer too small - return size necessary in PayloadSize - 0x%x.", sizeof(WINBIO_SENSOR_ATTRIBUTES));
sensorAttributes->PayloadSize = (DWORD) sizeof(WINBIO_SENSOR_ATTRIBUTES);
MyRequest.SetInformation(sizeof(DWORD));
MyRequest.SetCompletionHr(S_OK);
return;
}
//
// Fill in the attribute payload structure
//
RtlZeroMemory(sensorAttributes, outputBufferSize);
sensorAttributes->PayloadSize = (DWORD) sizeof(WINBIO_SENSOR_ATTRIBUTES);
sensorAttributes->WinBioHresult = S_OK;
sensorAttributes->WinBioVersion.MajorVersion = WINBIO_WBDI_MAJOR_VERSION;
sensorAttributes->WinBioVersion.MinorVersion = WINBIO_WBDI_MINOR_VERSION;
sensorAttributes->SensorType = WINBIO_TYPE_FINGERPRINT;
sensorAttributes->SensorSubType = WINBIO_FP_SENSOR_SUBTYPE_TOUCH;// WINBIO_FP_SENSOR_SUBTYPE_SWIPE;//WINBIO_FP_SENSOR_SUBTYPE_TOUCH;
sensorAttributes->Capabilities = WINBIO_CAPABILITY_SENSOR | WINBIO_CAPABILITY_MATCHING | WINBIO_CAPABILITY_DATABASE;// WINBIO_CAPABILITY_SENSOR | WINBIO_CAPABILITY_MATCHING | WINBIO_CAPABILITY_DATABASE | WINBIO_CAPABILITY_PROCESSING;// WINBIO_CAPABILITY_SENSOR;
sensorAttributes->SupportedFormatEntries = 1;
sensorAttributes->SupportedFormat[0].Owner = WINBIO_ANSI_381_FORMAT_OWNER;
sensorAttributes->SupportedFormat[0].Type= WINBIO_ANSI_381_FORMAT_TYPE;
RtlCopyMemory(sensorAttributes->ManufacturerName, SAMPLE_MANUFACTURER_NAME, (wcslen(SAMPLE_MANUFACTURER_NAME)+1)*sizeof(WCHAR));
RtlCopyMemory(sensorAttributes->ModelName, SAMPLE_MODEL_NAME, (wcslen(SAMPLE_MODEL_NAME)+1)*sizeof(WCHAR));
RtlCopyMemory(sensorAttributes->SerialNumber, SAMPLE_SERIAL_NUMBER, (wcslen(SAMPLE_SERIAL_NUMBER)+1)*sizeof(WCHAR));
sensorAttributes->FirmwareVersion.MajorVersion = 1;
sensorAttributes->FirmwareVersion.MinorVersion = 0;
MyRequest.SetInformation(sensorAttributes->PayloadSize);
MyRequest.SetCompletionHr(S_OK);
}
void
CBiometricDevice::OnGetSensorStatus(
_Inout_ IWDFIoRequest *FxRequest
)
{
CRequestHelper MyRequest(FxRequest); // RAII helper class
ULONG controlCode = 0;
PUCHAR inputBuffer= NULL;
SIZE_T inputBufferSize = 0;
PWINBIO_DIAGNOSTICS diagnostics = NULL;
SIZE_T outputBufferSize;
//
// Get the request parameters
//
GetIoRequestParams(FxRequest,
&controlCode,
&inputBuffer,
&inputBufferSize,
(PUCHAR *)&diagnostics,
&outputBufferSize);
//
// Make sure we have an output buffer big enough
//
if (diagnostics == NULL || outputBufferSize < sizeof(DWORD))
{
// We cannot return size information.
TraceEvents(TRACE_LEVEL_ERROR,
BIOMETRIC_TRACE_DEVICE,
"%!FUNC!Output buffer NULL or too small to return size information.");
MyRequest.SetCompletionHr(E_INVALIDARG);
return;
}
if (outputBufferSize < sizeof(WINBIO_DIAGNOSTICS))
{
// Buffer too small.
TraceEvents(TRACE_LEVEL_ERROR,
BIOMETRIC_TRACE_DEVICE,
"%!FUNC!Buffer too small - return size necessary in PayloadSize - 0x%x.", sizeof(WINBIO_DIAGNOSTICS));
diagnostics->PayloadSize = (DWORD)sizeof(WINBIO_DIAGNOSTICS);
MyRequest.SetInformation(sizeof(DWORD));
MyRequest.SetCompletionHr(S_OK);
return;
}
//
// Fill in the OUT payload structure
//
RtlZeroMemory(diagnostics, outputBufferSize);
diagnostics->PayloadSize = (DWORD) sizeof(WINBIO_DIAGNOSTICS);
diagnostics->WinBioHresult = S_OK;
//diagnostics->SensorStatus = WINBIO_SENSOR_READY;
if (SensorStatusFlag)
{
SensorStatusFlag = 0;
diagnostics->SensorStatus = WINBIO_SENSOR_ACCEPT;
}
else
{
diagnostics->SensorStatus = WINBIO_SENSOR_READY;
}
MyRequest.SetInformation(diagnostics->PayloadSize);
MyRequest.SetCompletionHr(S_OK);
}
void
CBiometricDevice::OnCaptureData(
_Inout_ IWDFIoRequest *FxRequest
)
{
ULONG controlCode = 0;
PWINBIO_CAPTURE_PARAMETERS captureParams = NULL;
SIZE_T inputBufferSize = 0;
PWINBIO_CAPTURE_DATA captureData = NULL;
SIZE_T outputBufferSize = 0;
//
// We can only have one outstanding data capture request at a time.
// Check to see if we have a request pending.
//
bool requestPending = false;
EnterCriticalSection(&m_RequestLock);
if (m_PendingRequest == NULL)
{
//
// See if we have an active sleep thread.
// If so, tell it to exit.
// Wait for it to exit.
//
if (m_SleepThread != INVALID_HANDLE_VALUE)
{
LeaveCriticalSection(&m_RequestLock);
// TODO: Add code to signal thread to exit.
// NOTE: Sleeping for INFINITE time is dangerous. A real driver
// should be able to handle the case where the thread does
// not exit.
WaitForSingleObject(m_SleepThread, INFINITE);
CloseHandle(m_SleepThread);
m_SleepThread = INVALID_HANDLE_VALUE;
EnterCriticalSection(&m_RequestLock);
}
//
// We might have had to leave the CS to wait for the sleep thread.
// Double check that the pending request is still NULL.
//
if (m_PendingRequest == NULL)
{
// Save the request.
m_PendingRequest = FxRequest;
// Mark the request as cancellable.
m_PendingRequest->MarkCancelable(this);
}
else
{
requestPending = true;
}
}
else
{
requestPending = true;
}
LeaveCriticalSection(&m_RequestLock);
if (requestPending)
{
// Complete the request to tell the app that there is already
// a pending data collection request.
FxRequest->Complete(WINBIO_E_DATA_COLLECTION_IN_PROGRESS);
return;
}
//
// Get the request parameters
//
GetIoRequestParams(FxRequest,
&controlCode,
(PUCHAR *)&captureParams,
&inputBufferSize,
(PUCHAR *)&captureData,
&outputBufferSize);
//
// Check input parameters.
//
if (inputBufferSize < sizeof (WINBIO_CAPTURE_PARAMETERS))
{
// Invalid arguments
TraceEvents(TRACE_LEVEL_ERROR,
BIOMETRIC_TRACE_DEVICE,
"%!FUNC!Invalid argument(s).");
CompletePendingRequest(E_INVALIDARG, 0);
return;
}
//
// Make sure we have an output buffer big enough
//
if (outputBufferSize < sizeof(DWORD))
{
// We cannot return size information.
TraceEvents(TRACE_LEVEL_ERROR,
BIOMETRIC_TRACE_DEVICE,
"%!FUNC!Output buffer NULL or too small to return size information.");
CompletePendingRequest(E_INVALIDARG, 0);
return;
}
//
// Check output buffer size.
//
if (outputBufferSize < sizeof (WINBIO_CAPTURE_DATA))
{
// Buffer too small.
TraceEvents(TRACE_LEVEL_ERROR,
BIOMETRIC_TRACE_DEVICE,
"%!FUNC!Buffer too small - must be at least 0x%x.", sizeof (WINBIO_CAPTURE_DATA));
//
// NOTE: The output buffer size necessary for this sample is sizeof(WINBIO_CAPTURE_DATA).
// Real devices will need additional space to handle a typical capture.
// The value that should be returned here is sizeof(WINBIO_CAPTURE_DATA) + CaptureBufferSize.
//
captureData->PayloadSize = (DWORD)sizeof(WINBIO_CAPTURE_DATA)+12;
CompletePendingRequest(S_OK, sizeof(DWORD));
return;
}
//
// NOTE: This call always fails in this sample since it is not
// written for a real device.
//
//
// Set default values in output buffer.
//
SensorStatusFlag = 1;
RtlZeroMemory(captureData, outputBufferSize);
captureData->PayloadSize = (DWORD)outputBufferSize;
captureData->WinBioHresult = S_OK;
captureData->SensorStatus = WINBIO_SENSOR_ACCEPT;
captureData->RejectDetail = 0;
captureData->CaptureData.Size = (DWORD)12;
UCHAR szBuffer[] = { 0x01, 0x02, 0x03, 0x04 ,0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04 };
RtlCopyMemory(captureData->CaptureData.Data, szBuffer,12);
//
// Check purpose, format and type.
//
if (captureParams->Purpose == WINBIO_NO_PURPOSE_AVAILABLE)
{
captureData->WinBioHresult = WINBIO_E_UNSUPPORTED_PURPOSE;
}
else if ((captureParams->Format.Type != WINBIO_ANSI_381_FORMAT_TYPE) ||
(captureParams->Format.Owner != WINBIO_ANSI_381_FORMAT_OWNER))
{
captureData->WinBioHresult = WINBIO_E_UNSUPPORTED_DATA_FORMAT;
}
else if (captureParams->Flags != WINBIO_DATA_FLAG_RAW)
{
captureData->WinBioHresult = WINBIO_E_UNSUPPORTED_DATA_TYPE;
}
//
// Create thread to sleep 1 seconds before completing the request.
//
m_SleepParams.SleepValue = 1;
m_SleepParams.Hr = S_OK;
m_SleepParams.Information = captureData->PayloadSize;
m_SleepThread = CreateThread(NULL, // default security attributes
0, // use default stack size
CaptureSleepThread, // thread function name
this, // argument to thread function
0, // use default creation flags
NULL); // returns the thread identifier
}
DWORD WINAPI
CaptureSleepThread(
LPVOID lpParam
)
{
CBiometricDevice *device = (CBiometricDevice *) lpParam;
PCAPTURE_SLEEP_PARAMS sleepParams = device->GetCaptureSleepParams();
//
// Make sure it is less than or equal to 1 minute.
//
if (sleepParams->SleepValue > 60)
{
sleepParams->SleepValue = 60;
}
Sleep(sleepParams->SleepValue * 1000);
device->CompletePendingRequest(sleepParams->Hr, sleepParams->Information);
return 0;
}

Ardulink 2 unable to receive message from analog Pin1 using Serial.print

I have started ardulink mqtt to listen to analog pin 1 of the arduino uno
as follow running on windows 10 with mosquitto mqtt broker 1.5.8
C:\Java\jdk1.8.0_201\bin\java -jar ardulink-mqtt-2.1.0.jar -a 1 -connection "ardulink://serial-jssc?port=COM3&pingprobe=false" -standalone
However I could not get any response despite subscribe the topics with home/devices/ardulink/A1/value/get ?
I do not see any publishing being log from the ardulink log or mosquitto
From the Arduino serial monitor , I did see all the output from Serial.print indicating the sketch was in fact fully uploaded to the Arduino uno.
arduino code
int sensorValue;
// variable to calibrate low value
int sensorLow = 1023;
// variable to calibrate high value
int sensorHigh = 0;
void setup() {
Serial.begin(115200);
// calibrate for the first five seconds after program runs
while (millis() < 5000) {
// record the maximum sensor value
sensorValue = analogRead(A1);
if (sensorValue > sensorHigh) {
sensorHigh = sensorValue;
}
// record the minimum sensor value
if (sensorValue < sensorLow) {
sensorLow = sensorValue;
}
}
}
void loop() {
//read the input from A1 and store it in a variable
sensorValue = analogRead(A1);
Serial.print(sensorValue);
// wait for a moment
delay(1000);
}
Ardulink Mqtt log
C:\ardulink\lib>C:\Java\jdk1.8.0_162\bin\java -jar ardulink-mqtt-2.1.0.jar -a 1 -d 13 -connection "ardulink://serial-jss
c?port=COM4&pingprobe=false" -clientId ardulink
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/ardulink/lib/slf4j-jdk14-1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/ardulink/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.JDK14LoggerFactory]
Apr 01, 2019 2:44:04 PM org.apache.camel.impl.DefaultCamelContext start
INFO: Apache Camel 2.17.1 (CamelContext: camel-1) is starting
Apr 01, 2019 2:44:04 PM org.apache.camel.management.ManagedManagementStrategy doStart
INFO: JMX is enabled
Apr 01, 2019 2:44:04 PM org.apache.camel.impl.converter.DefaultTypeConverter doStart
INFO: Loaded 182 type converters
Apr 01, 2019 2:44:04 PM org.apache.camel.impl.DefaultRuntimeEndpointRegistry doStart
INFO: Runtime endpoint registry is in extended mode gathering usage statistics of all incoming and outgoing endpoints (c
ache limit: 1000)
Apr 01, 2019 2:44:14 PM org.ardulink.core.ConnectionBasedLink startListening
INFO: Starting listening on pin ANALOG 1
Apr 01, 2019 2:44:14 PM org.ardulink.core.ConnectionBasedLink startListening
INFO: Starting listening on pin DIGITAL 13
Apr 01, 2019 2:44:14 PM org.apache.camel.impl.DefaultComponent preProcessUri
WARNING: Supplied URI 'mqtt:mqttMain?host=tcp://localhost:1883&subscribeTopicNames=home/devices/ardulink/#&connectAttemp
tsMax=1&reconnectAttemptsMax=0' contains unsafe characters, please check encoding
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext doStartCamel
INFO: AllowUseOriginalMessage is enabled. If access to the original message is not needed, then its recommended to turn
this option off as it may improve performance.
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext doStartCamel
INFO: StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at h
ttp://camel.apache.org/stream-caching.html
Apr 01, 2019 2:44:15 PM org.apache.camel.processor.aggregate.AggregateProcessor doStart
INFO: Defaulting to MemoryAggregationRepository
Apr 01, 2019 2:44:15 PM org.apache.camel.processor.aggregate.AggregateProcessor doStart
INFO: Using CompletionInterval to run every 250 millis.
Apr 01, 2019 2:44:15 PM org.apache.camel.component.mqtt.MQTTEndpoint connect
INFO: Connecting to tcp://localhost:1883 using 10 seconds timeout
Apr 01, 2019 2:44:15 PM org.apache.camel.component.mqtt.MQTTEndpoint$2 onConnected
INFO: MQTT Connection connected to tcp://localhost:1883
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext doStartOrResumeRouteConsumers
INFO: Route: route1 started and consuming from: Endpoint[ardulink://serial-jssc?listenTo=A1%2CD13&pingprobe=false&port=C
OM4]
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext doStartOrResumeRouteConsumers
INFO: Route: route2 started and consuming from: Endpoint[direct://endOfAnalogAggregation]
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext doStartOrResumeRouteConsumers
INFO: Route: route3 started and consuming from: Endpoint[mqtt:mqttMain?host=tcp://localhost:1883&subscribeTopicNames=hom
e/devices/ardulink/#&connectAttemptsMax=1&reconnectAttemptsMax=0]
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext start
INFO: Total 3 routes, of which 3 are started.
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext start
INFO: Apache Camel 2.17.1 (CamelContext: camel-1) started in 10.898 seconds
It seems that you did not flash Ardulink sketch to the Arduino but something self-written (which does not send any message via the serial link). After flashing Ardulink sketch and starting java mqtt client again everything should work.
I managed to resolve the issue after including the standard ardulink protocol , below is the revised arduino code .
int sensorValue;
// variable to calibrate low value
int sensorLow = 1023;
// variable to calibrate high value
int sensorHigh = 0;
// LED pin
const int ledPin = 13;
String inputString = ""; // a string to hold incoming data (this is general code you can reuse)
boolean stringComplete = false; // whether the string is complete (this is general code you can reuse)
void setup() {
// Make the LED pin an output and turn it on
Serial.begin(115200);
Serial.print("alp://rply/");
Serial.print("ok?id=0");
Serial.print('\n'); // End of Message
Serial.flush();
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH);
// calibrate for the first five seconds after program runs
while (millis() < 5000) {
// record the maximum sensor value
sensorValue = analogRead(A1);
if (sensorValue > sensorHigh) {
sensorHigh = sensorValue;
}
// record the minimum sensor value
if (sensorValue < sensorLow) {
sensorLow = sensorValue;
}
}
digitalWrite(ledPin, LOW);
}
void loop() {
//read the input from A1 and store it in a variable
serialEvent();
sensorValue = analogRead(A1);
if (stringComplete==true){
if(inputString.startsWith("alp://")) {
boolean msgRecognized = true;
if (inputString.substring(6,10)=="ared"){
//Serial.println(sensorValue);
digitalWrite(ledPin, HIGH);
}else{
msgRecognized = false;
}
// Prepare reply message if caller supply a message id (this is general code you can reuse)
int idPosition = inputString.indexOf("?id=");
if(idPosition != -1) {
String id = inputString.substring(idPosition + 4);
// print the reply
Serial.print("alp://rply/");
if(msgRecognized) { // this sketch doesn't know other messages in this case command is ko (not ok)
Serial.print("ok?id=");
} else {
Serial.print("ko?id=");
}
Serial.print(id);
Serial.print('\n'); // End of Message
Serial.flush();
}
}
// clear the string:
inputString = "";
stringComplete = false;
}
if (sensorValue>0){
Serial.print("alp://ared/");
Serial.print("1");
Serial.print("/");
Serial.print(sensorValue);
Serial.print('\n'); // End of Message
Serial.flush();
}
delay(1000);
}
void serialEvent() {
while (Serial.available()>0&&!stringComplete==true) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n') {
stringComplete = true;
}
}
}

SPI1 on Pandaboard ES Rev. B2 with Kernel 3.17

This is the first time I ask a question on stackoverflow.
I tried to access SPI1 on the J3 of my Pandaboard ES. First, I modified the device tree source, omap4-panda-es-b3.dts, by adding
&mcspi1
{
spidev#0
{
compatible = "spidev";
pinctrl-name = "default";
pinctrl-0 = <&spi1_pins>;
spi-max-frequency=<4000000>;
reg = <0>;
};
};
and
spi1_pins: pinmux_spi1_pins {
pinctrl-single,pins = <
0xf2 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* spi1_sclk, gpio134 */
0xf4 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi1_somi, gpio135 */
0xf6 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* spi1_simo, gpio136 */
0xf8 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* spi1_somi, gpio137 */
>;
};
Then, rebuilt the kernel, installed the new kernel and rebooted. The device spidev1.0 showed in the /dev directory as well as /sys/class/spidev.
But when I did "echo 1 > /dev/spi1.0" or ran spi_test from here, nothing came out from the SPI1 pins on the scope. I have double checked the offsets and am sure that they should be correct.
What do I need to do so the SPI1 on the Pandaboard ES works? The output of "uname -a" is
Linux arm 3.17.4-USER1-armv7-x3 #4 SMP Tue Feb 17 19:35:52 CST 2015 armv7l armv7l armv7l GNU/Linux
Thanks
MST

Write to /dev/port as non-root user

I am working on a rather complex C++ code which performs the following operation as standard user
fd = open("/dev/port",O_WRONLY);
...
lseek(fd, 0x2E,SEEK_SET);
...
write(fd,&buf,1);
I get a 'Operation not permitted' error on opening the file, despite having chmodded the file.
crwxrwxrwx 1 root kmem 1, 4 Sep 12 14:32 /dev/port
I know of security issues with chmodding /dev/port, but as far as we're concerned the system will run on a closed LAN.
To make it easier, this:
using namespace std;
int main(int argc, char *argv[])
{
int fd=-1;
// fd1=open("/dev/port",O_RDWR|O_NDELAY);
vector<string> fnames;
fnames.push_back("/dev/port");
fnames.push_back("/dev/tty0");
string fname;
for(int i=0;i<fnames.size();i++)
{
fname = fnames[i];
fd=open(fname.c_str(),O_RDWR | O_NDELAY);
if(fd<0)
{
cout << fname << " " << fd << endl;
cout << fname << " " << strerror(errno) << endl;
}
else
{
cout << "Open ok: " << fname << endl;
}
}
return 0;
}
returns this:
me#myPC:~/test$ ./main
/dev/port -1
/dev/port Operation not permitted
Open ok: /dev/tty0
with these permission rights
me#myPC:~/test$ ll /dev/tty /dev/port
crw-rw-rw- 1 root kmem 1, 4 Sep 12 14:32 /dev/port
crw-rw-rw- 1 root tty 5, 0 Sep 12 15:51 /dev/tty
To open /dev/port you need the capability CAP_SYS_RAWIO, in addition to permission to open the file.
drivers/char/mem.c:730
static int open_port(struct inode * inode, struct file * filp)
{
return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
}
You can either gain this by being root or by setting it for a single executable (similar to set-uid) using setcap.
http://linux.die.net/man/8/setcap

Resources