Quantcast
Channel: Instrument Control (GPIB, Serial, VISA, IVI) topics
Viewing all articles
Browse latest Browse all 5565

USB Interrupt-IN endpoint data

$
0
0

I am developing firmware for a USB instrument, and using NI-VISA extensively to test and debug it.  I would like to be able to read the data packet that comes on the Interrupt-IN endpoint during a USBTMC-USB488.2 service request (SRQ).  I think the firmware is doing the right thing because this code works:

 

ViSession defaultRM = VI_NULL, instr = VI_NULL;
// clear status; set OPC (operation complete) in event status enable;
// set ESB (event status bit) in Status Byte Enable Register; start an
// overlapped command; and generate a service request (SRQ) when
// the operation completes.
ViByte buf[] = "*CLS;*ESE 1;*SRE 32;:SYST:ARR:CLK 2304;*OPC";
ViUInt32 cnt;
ViUInt16 STB; 
viOpenDefaultRM(&defaultRM);
viOpen(defaultRM, "USB0::0x0000::0x0001::0::INSTR", VI_NULL, VI_NULL, &instr);
// Service request events go into the standard event queue
viEnableEvent(instr, VI_EVENT_SERVICE_REQ, VI_QUEUE, VI_NULL);
// start an overlapped command that takes some time to complete, and wait for the
// service request that indicates it is finished.
viWrite(instr, buf, sizeof(buf)-1, &cnt);
viWaitOnEvent(instr, VI_EVENT_SERVICE_REQ, VI_TMO_INFINITE, VI_NULL, VI_NULL);
// When you receive a VI_EVENT_SERVICE_REQ on an INSTR session, you must call
// viReadSTB() to guarantee delivery of future service request events on the
// given session.
viReadSTB(instr, &STB);

viWaitOnEvent gets the event, and the status byte I read has the right flags set (SRQ and ESB).  Since the status byte value is transmitted from the USB device to the host in a packet from the Interrupt-IN endpoint, it seems like it must be getting that packet.

 

I would like to see that packet.  But various things I have tried to get it from NI-VISA have so far failed.  For example, I tried installing this callback handler:

 

static ViStatus _VI_FUNCH interrupt_in_hndlr(ViSession vi, ViEventType typ, ViEvent evt, ViAddr userHandle)
{
	HANDLE interrupt_in_event = userHandle;
	ViUInt16 size;
	VI_ERROR(viGetAttribute(evt, VI_ATTR_USB_RECV_INTR_SIZE, &size));

	if (typ != VI_EVENT_USB_INTR)
		return VI_ERROR_INV_EVENT;

	if (size > 0) {
		ViPByte buf = new ViByte[size];
		VI_ERROR(viGetAttribute(evt, VI_ATTR_USB_RECV_INTR_DATA, buf));
		printf("Interrupt-IN data =");
		for (int i=0; i<size; ++i)
			printf(" %02x", buf[i]);
		printf("\n");
	} else {
		printf("No Interrupt-IN data!\n");
	}

	SYSERR(SetEvent(interrupt_in_event), FALSE);

	return VI_SUCCESS;
}

with this code

 

	HANDLE interrupt_in_event;

	SYSERR(interrupt_in_event = CreateEvent(NULL, TRUE, FALSE, NULL), NULL);

	// Install a handler for USB Interrupt-IN events
	VI_ERROR(viInstallHandler(instr, VI_EVENT_USB_INTR, interrupt_in_hndlr, interrupt_in_event));
	VI_ERROR(viEnableEvent(instr, VI_EVENT_USB_INTR, VI_HNDLR, VI_NULL));

and it never gets called.  I tried putting those events on the standard event queue, and the call to viEnableEvent fails.  I tried to open the ::RAW device instead of the ::INSTR device, and that fails.

 

Can anyone lend me a clue?

 


Viewing all articles
Browse latest Browse all 5565

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>