qdl: add QUD backend so on Windows flashing via the official QDLoader 9008 driver works#233
qdl: add QUD backend so on Windows flashing via the official QDLoader 9008 driver works#233igoropaniuk wants to merge 4 commits into
Conversation
dd12407 to
522e271
Compare
|
I don't think it's good UX to rely on the user to tell us which USB driver they have installed. In my work-in-progress, I integrated the QUD support directly into usb.c to make it try both on Windows - to make this choice fully transparent... Code is a little bit messier still, which is why I haven't posted it, but UX is much better. Remember, we don't want the user to have to know how flashing works to flash the device. |
By default, the "backend" is selected automatically ("auto"). The--backend CLI option is needed to override this selection and choose manually. |
Right, but unless I'm reading the code incorrectly, decode_backend("auto") will return QDL_DEVICE_QUD on Windows, regardless of me having the QUD installed or not. So, a Windows user that can run QDL today, will face exactly the same problem that the QUD-users are facing today, and they will have to know that they need to say "--backend usb" to get things working again. Similarly, but hopefully a less frequent problem, is that you will have QUD-users who connect the USB cable and then go "--backend usb", because that sounds like the obvious choice. |
7ca72bf to
ed71d83
Compare
|
@andersson added proper auto resultion of the backend:
|
ed71d83 to
896a6d8
Compare
|
This is better, but I think the auto-probe timeout is going to come back and bit us. I think we need to make the USB probe loop check both cases - even though it means that this can't be a clean "backend". |
Introduce QDL_DEVICE_QUD as a third device-transport flavour alongside the libusb-based USB backend and the SIM backend used by --dry-run. After this patch --backend=qud parses successfully but errors out at init time on every host. The actual transport is added in a follow-up. The intent is to support kernel-mode drivers that expose the EDL device as a character file (e.g. the official QDLoader 9008 driver on Windows, where the device shows up as \\.\COMx), so libusb is not required on hosts where claiming the USB interface from user space is inconvenient. Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
Wire up an actual transport for the QUD backend on Windows. The official QDLoader 9008 driver exposes a Qualcomm EDL device as a serial port (\\.\COMx). The Sahara/Firehose framing on top is identical to the libusb backend; this patch only deals with how user space reaches the underlying bulk pipes. Non-Windows hosts keep the stub from the previous patch. Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
firehose_read() previously assumed each qdl_read() returns a single Firehose XML document. That holds on libusb (each USB bulk-in transfer surfaces as its own read return), but not on stream-oriented transports. The Windows COM port driver behind the QUD backend just streams bytes into its RX buffer, and a single ReadFile() can deliver several back-to-back Firehose responses concatenated; on top of that the binary payload of a rawmode response (e.g. the sector data that follows a <read> ACK) can be spliced onto the same buffer right after the closing </data> tag. Walk the read buffer using "<?xml" as the document start and "</data>" as the envelope end, then dispatch each XML chunk through the existing firehose_response_parse() + response_parser path. <log/> and <response/> elements are still honoured in arrival order, and rawmode is observed on whichever chunk carries it. When that chunk is followed by trailing bytes, those bytes are the first sectors of the binary payload: hand them to qdl_push_back() so the next qdl_read() picks them up before the transport is touched again. firehose_issue_read() now accumulates each sector-chunk across qdl_read() calls instead of requiring a single full-sized return, since on a stream transport the rawmode tail and the remaining sector bytes generally arrive in several reads. libusb keeps delivering an entire bulk transfer in one call, so the inner loop runs once there. The change is a no-op on libusb where each read already contains exactly one document and the rawmode payload arrives in its own bulk transfer; it unblocks all current and future stream-oriented transports without touching the libusb path's behaviour. Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
Add a meta-backend QDL_DEVICE_AUTO that defers the transport choice
to qdl_open(): instead of picking libusb or QUD upfront, its open()
runs a unified wait loop and binds whichever transport first reaches
an EDL device. The "auto" --backend token (and the default) maps to
it.
Each 250 ms tick the loop does:
1. usb_open_attempt() - one libusb scan-and-open. On success the
libusb device is bound as the inner transport.
2. On Windows, if libusb saw the device but could not open it
(-EBUSY: the QDLoader 9008 driver has claimed the interface)
or SetupAPI sees a Qualcomm COM port libusb missed, calls
qud_open(). On success the QUD device is bound as the inner.
3. Otherwise sleeps and retries. No timeout: the loop waits
indefinitely, same cadence as the prior libusb-only loop.
qdl_read/write/close on the outer auto wrapper forward to the inner.
Pre-open out_chunk_size is stashed on the wrapper and applied at
bind time; vip_data and slot live on the outer where firehose
accesses them, so no forwarding is needed for those.
usb_open_attempt() (factored out of usb_open()) returns
0 / -ENODEV / -EBUSY / -EIO. The --backend usb path loops over it
with visibility-transition messaging. The auto loop owns its own
messaging and never emits the -EBUSY diagnostic because that
condition triggers the QUD attempt in the same tick.
qdl-ramdump now uses QDL_DEVICE_AUTO so Windows users with the
official driver can collect crash dumps without re-binding the USB
driver to WinUSB.
QDL_DEVICE_AUTO is explicitly a meta-backend, not a peer of the USB
and QUD backends: its job is to defer the transport choice to the
moment a probe reaches a device. The libusb and QUD backends remain
standalone and selectable via --backend usb / --backend qud.
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
896a6d8 to
a8e70d4
Compare
|
@andersson I've completely reworked the usb backend selection based on your suggestions and also rebased on the latest master. Could you take a look? |
| { | ||
| struct qdl_device_auto *wrap = to_auto(qdl); | ||
| struct qdl_device *usb_dev; | ||
| #ifdef _WIN32 |
There was a problem hiding this comment.
we can drop this _WIN32 later, when there is support for Linux QUD driver
On Windows, the official Qualcomm Userspace Driver / QDLoader 9008 kernel-mode driver claims the EDL device's USB interface during PnP enumeration and exposes it as
\\.\COMx.libusbcan't reach the bulk endpoints in that state, so today the only way to flash with qdl on Windows is to swap the binding toWinUSB(for example via Zadig - which is awkward, sometimes blocked by IT policy, and breaks any other QC tooling that expects the COM-port view.This PR adds a second transport ("QUD" - Qualcomm USB Driver) that talks to the device through the kernel-mode driver's COM-port file directly, leaving Sahara/Firehose framing untouched. Linux is untouched and continues to use libusb.