The simplest option is to use one or two
QThreads.
One QThread reads from the device. Whenever it has a complete block or multiple blocks of data, it emits the data using a Qt signal.
The other QThread writes to the device. It implements a slot that writes data to the device.
Both of these are trivial "worker" threads, with a suitable skeleton shown in the QThread documentation.
For query-response communications, without asynchronous responses from the device (i.e., the device won't send any data except as a response to a query), you implement a single QThread. Comparing to the QThread worker example, you implement the slot (doWork() in the example) to do one query-response round, with the response emitted as a signal.
Anticipated question: Why the need for separate threads?
If the query-response comms are done in the main thread, nothing else can happen during the query-response cycle.
Technically, you can do the two-QThread solution with writes to the device in the main thread, but buffering may become an issue. Depending on the underlying libusb implementation, the write may block until all data has been sent to the device.
Obviously, the continuous read/receive thread must be a separate thread, so that you can use a blocking read/receive for the data. (This also maximizes the read/receive bandwidth on most OSes; you should be able to do full high-speed USB (480 Mbit/s, or about 49 Mbytes/second), on almost any host hardware.)
There is some overhead in Qt signal/slot mechanism, so you'll want to carefully consider how small/large chunks of data you deliver in each signal/slot call. To maximize bandwidth, I'd target 10 to 100 signal calls per second; to minimize latency (for smaller amounts of data), I would consider up to 1000 signal calls per second. Anything above is waste of resources, really.