views:

32

answers:

1

I'm trying to (re-)write a program that uses USB controlled scanners. I've got my USBIOInterfaceInterface set up, so I can send and receive messages over the pipes. I am successfully calling WritePipeTO and ReadPipeTO synchronously but I want to read from the scanner asynchronously.

I've tried using ReadPipeAsyncTO, but the callback never gets called until the call timesout. The reason Appears to be that I'm not registering the callback somewhere. If I add a CFRunLoopRun after the async read, then it appears to work, but only by having many nested calls to CFRunLoopRun, which can't be a good idea.

I've seen the functions:

    err = (*usbInterfaceInterface)->CreateInterfaceAsyncEventSource(usbInterfaceInterface, &cfSource);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);

but I haven't figured out how to tell the Source what callback should be called when something happens on that interface. When I just create the source, and call the ReadPipeAsyncTO, the callback doesn't get called until timeout.

Is there same sample code somewhere so I can see how these functions are SUPPOSED to work together?

A: 

Calling CFRunLoopRun, or its NSRunLoop equivalent, is almost always a sign that your program's architecture is wrong.

It sounds like it would be a terrible pain to do, but your app would be much better—and would work, using the ReadPipeAsyncTO and WritePipeAsyncTO functions—if you rewrote it to use the run loop instead of whatever manual loop you currently have.

Peter Hosey
Can you give me a pointer to sample code that does that? I'm certainly open to suggestions. The original code used a 20 year deprecated function (GetNextEvent) so an architecture change is probably in order anyway...
Brian Postow
Does what? Uses the run loop properly? Any Cocoa application that doesn't directly call `CFRunLoopRun` or `-[NSRunLoop run…]` (or, while we're at it, `-[NSApplication nextEvent::::]`) qualifies. The run loop is there anyway, and the application is built on it, so all you need to do is schedule the asynchronous operation on it, then finish up, return, and let it get back to you in its own time.
Peter Hosey