Cannot detect hardware trigger event of a UVC camera

I’m facing the same issue described in this thread: http://www.osronline.com/showThread.cfm?link=254507

My camera has an hardware button for still image capture; it mounts an Empia SOC.
I want to detect the camera button pressure for custom purpose.
The capture filter exposes 2 output pins, one for live capture and the other for still image capture (UVC still image capture mode = 2).
Directshow correctly manage the hardware trigger: using Graphedit and rendering both pins, I see a new frame each time I press the camera button.
I haven’t been able to detect the event inside my user app.

I also checked the actual USB communication with an USB analyzer: each time I press the camera button, even with the graph stopped, the camera sends the following 2 USB interrupt packets:

  1. 02010001
  2. 02010000

Here is the code snippet I’m currently using for testing.

HRESULT hr;
HANDLE hndEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);

KSEVENT Event = {0};
Event.Set = KSEVENTSETID_VIDCAPNotify;
Event.Id = KSEVENT_VIDCAPTOSTI_EXT_TRIGGER;
Event.Flags = KSEVENT_TYPE_ENABLE;

KSEVENTDATA EventData = {0};
EventData.NotificationType = KSEVENTF_EVENT_HANDLE;
EventData.EventHandle.Event = hndEvent;
EventData.EventHandle.Reserved[0] = 0;
EventData.EventHandle.Reserved[1] = 0;

// I’ve tried with pKsControl as the capture filter an as each one of the 4 nodes retrieved from the filter topology. It returns S_OK for all these controls.
hr = pKsControl->KsEvent(
&Event,
sizeof(Event),
&EventData,
sizeof(EventData),
&ulBytesReturned);

// It always returns WAIT_TIMEOUT
DWORD dwError = WaitForSingleObject(hEvent, 10000);

Any help will be very appreciated.

xxxxx@libero.it wrote:

My camera has an hardware button for still image capture; it mounts an Empia SOC.
I want to detect the camera button pressure for custom purpose.
The capture filter exposes 2 output pins, one for live capture and the other for still image capture (UVC still image capture mode = 2).

Why can’t you simply use the arrival of a frame on the still image pin
as an indication that the button was pressed?

Here is the code snippet I’m currently using for testing.

HRESULT hr;
HANDLE hndEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);

KSEVENT Event = {0};
Event.Set = KSEVENTSETID_VIDCAPNotify;
Event.Id = KSEVENT_VIDCAPTOSTI_EXT_TRIGGER;
Event.Flags = KSEVENT_TYPE_ENABLE;

You didn’t read the documentation. The input structure needs to be a
KSE_NODE, not a KSEVENT. The KSE_NODE contains the KSEVENT, plus the
node ID.

I have not found a good method of mapping UVC component IDs into Kernel
Streaming node IDs. Every time I need to use a node-based property or
event, I’ve had to use trial and error.

KSE_NODE Event = {
{
KSEVENTSETID_VIDCAPNotify,
KSEVENT_VIDCAPTOSTI_EXT_TRIGGER,
KSEVENT_TYPE_ENABLE
},
0 // here you need to substitute the node ID
};


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Sorry, now I better understand the documentation.
I changed source code as following, but still doesn’t work.


// I’ve tried with nodeID from 0 to 4 (topology consists in 4 nodes), but without any result
KSE_NODE EventNode = {
{
KSEVENTSETID_VIDCAPNotify,
KSEVENT_VIDCAPTOSTI_EXT_TRIGGER,
KSEVENT_TYPE_ENABLE
},
nodeID,
0
};

// I’ve tried with pKsControl as the capture filter an as each one of the 4
nodes retrieved from the filter topology. It returns S_OK for all these controls.
hr = pKsControl->KsEvent(
(KSEVENT*)&EventNode,
sizeof(EventNode),
&EventData,
sizeof(EventData),
&ulBytesReturned);

I’ve tried both with the still capture pin connected and disconnected.
Is there any property that I must set up to enable event signaling?

If I understand well the KSEVENT_VIDCAPTOSTI_EXT_TRIGGER event documentation, the target of the event must be a pin, not a filter or a node.
I’ve tried assigning to pKsControl both the output pins (video capture and still capture): in both cases KsEvent() fails, returning ERROR_SET_NOT_FOUND.

According to KSEVENT documentation, if you provide a KSE_NODE instead of a KSEVENT, you should add KSEVENT_TYPE_TOPOLOGY flag to Flags field.
I tried this way using controls from the source filter and its nodes: this time KsEvent() always fails, returning ERROR_NOT_FOUND, if NodeID=0…3, with ERROR_INVALID_FUNCTION, with NodeID >= 4.

xxxxx@libero.it wrote:

According to KSEVENT documentation, if you provide a KSE_NODE instead of a KSEVENT, you should add KSEVENT_TYPE_TOPOLOGY flag to Flags field.
I tried this way using controls from the source filter and its nodes: this time KsEvent() always fails, returning ERROR_NOT_FOUND, if NodeID=0…3, with ERROR_INVALID_FUNCTION, with NodeID >= 4.

Right. So, you need KSE_NODE, you need KSEVENT_TYPE_TOPOLOGY, you need
to send to the pin’s file handle, and you need the right nodeId. Are
you sending to the pin’s file handle?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Uhm, I think so.
First I used KsEvent() method of a IKsControl instance queried from the pin.
Now I’m using KsSynchronousDeviceControl() function, passing the object handle of the pin as first argument (see code below).
The two approaches seem to be equivalent and I get same results.


CComQIPtr pKsObj(pKsControl);
if (pKsObj && pKsObj->KsGetObjectHandle())
{
hr = ::KsSynchronousDeviceControl(
pKsObj->KsGetObjectHandle(),
IOCTL_KS_ENABLE_EVENT,
&EventNode,
sizeof(EventNode),
&EventData,
sizeof(EventData),
&ulBytesReturned);
}
else
hr = E_HANDLE;

I used KsStudio to investigate camera filter behaviour.
The filter declares that supports the KSEVENTSETID_VIDCAPNotify set; both output pins, instead, support only the KSEVENTSETID_Connection set.
When KsStudio checks events supported by pins, it gets always ERROR_NOT_FOUND, for all events and all nodes (see KsStudio log snippet below).

Could it be either a driver issue or a device issue?


KSSTUDIO Log


Instantiating Pin 2

Querying for structure size for KSEVENT_TYPE_SETSUPPORT
SyncGetSupportedEventSets: size query got 16 bytes back
Getting event KSEVENT_TYPE_SETSUPPORT:
Pin Event set supported:
KSEVENTSETID_Connection

0x00000490 = ERROR_NOT_FOUND
Same results for other nodes

Node (0) KSNODETYPE_VIDEO_CAMERA_TERMINAL (Terminale videocamera)
Supported PropertySets:
Filter reports support for PropertySet PROPSETID_VIDCAP_CAMERACONTROL on node 0
Supported EventSets:
Filter reports support for EventSet KSEVENTSETID_Connection
SyncIoctl: DeviceIoControl failed. Last Error = 0x00000490
Filter does not report support for Event KSEVENT_CONNECTION_POSITIONUPDATE on node
SyncIoctl: DeviceIoControl failed. Last Error = 0x00000490
Filter does not report support for Event KSEVENT_CONNECTION_DATADISCONTINUITY on node
SyncIoctl: DeviceIoControl failed. Last Error = 0x00000490
Filter does not report support for Event KSEVENT_CONNECTION_TIMEDISCONTINUITY on node
SyncIoctl: DeviceIoControl failed. Last Error = 0x00000490
Filter does not report support for Event KSEVENT_CONNECTION_PRIORITY on node
SyncIoctl: DeviceIoControl failed. Last Error = 0x00000490
Filter does not report support for Event KSEVENT_CONNECTION_ENDOFSTREAM on node

I’ve found a post in Microsoft Community: it seems that something in Still Image Capture Event mechanism, that correctly works in Win XP, is broken in Windows 7.

http://answers.microsoft.com/en-us/windows/forum/windows_7-hardware/usbvideosys-uvc-driver-in-vista-and-7-not-as-good/eb07dcfd-c7e4-4a84-ba32-10f458e202b3

I’m going to try my code on Win XP ASAP.
However, the use in Win 7 of the Win XP driver, is not an acceptable solution.

I have just begun to investigate another way to achieve my goal (get trigger button events in a user app).
I want to create a lower filter of usbvideo.sys inside which intercept raw URB packets and notify the user app when the pressure of the camera button is detected.
Could this be a valid solution?

On Sep 1, 2014, at 4:18 AM, xxxxx@libero.it wrote:

I have just begun to investigate another way to achieve my goal (get trigger button events in a user app).
I want to create a lower filter of usbvideo.sys inside which intercept raw URB packets and notify the user app when the pressure of the camera button is detected.
Could this be a valid solution?

Assuming the event really isn?t exposed by usbvideo.sys, then yes, this could work.

Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Unfortunately I have not been able to receive trigger events in the canonical way.
I don’t know if it is my fault or an usbvideo bug.
However, I believe that I’ve done everything in the right way, following Microsoft documentation.

Now I am stuck, so I need to try another way.
There are only a few things that I know for sure:

  1. the camera correctly sends trigger packets
  2. direct show capture filter correctly receives (and handles) trigger packets
    So I would try to put some code in the middle, parsing URB packets looking for trigger events.
    Next week I’ll start to develop this new solution.

Thank you very much, Tim, for your support.