I recommend changing your code to do asynchronous I/O. This way if you start a read and it turns out that you need to cancel the read you can do it (if you use synchronous calls, you cannot cancel the I/O if you shouldn't have started it). You need this since the NI-488.2 API tells you the current state, but due to timing conditions, the current state may not be "correct" in 1 more second. For example:
(controller) ibwrt "*IDN?"
(device) you will become a listener and will start a read that completes with the correct data
(device) you will still be a listener since that is the correct addressing on the bus, therefore you will start a read again.
(controller) ibrd 100
(device) since you are still doing a read, you cannot respond to the ibrd request.
I used to have some example source code, but I can't seem to find it right now. However, the basic algorithm is to know what you need to wait on:
Default: LACS, DCAS, DTAS
Listening: CMPL, TACS, DCAS, DTAS
Talking: CMPL, LACS, DCAS, DTAS
Then you do the following:
currentwait = default;
loop forever
ibwait (currentwait);
if (DCAS) -> Handle clear, currentwait = default
if (DTAS) -> Handle trigger, currentwait = default
if (LACS) -> if ibwrta in progress stop it, then ibrda, currentwait = listening
if (TACS) -> if ibrda in progress stop it, if data to send, ibwrta, currentwait = talking
if (CMPL) -> handle I/O completion (queue data into queue, read next portion or write next portion if necessary)
Some things to node that if you are listening (ibrda in progress), and it stops due to DTAS or ibstop (due to TACS), you should have received data that you need to queue up.
By the way, if you want to use NI-Device with a PC/104, contact NI Technical Support as they may be able to help.