feat: port MT76 firmware load and download script
Add chip::load_firmware(): validates the xow_dongle.bin header, DMAs the ILM and DLM images in 0x3800-byte chunks over EP 0x04 OUT with FCE completion polling, then loads the IVB and waits for the firmware to start. Probe now issues a USB reset first (port of usb_reset_device), matching xone_dongle_probe. The chip keeps its firmware across a USB reset on macOS and does not set the upstream reset-complete bit, so load_firmware falls back to the running firmware when the chip is still alive. Verified on hardware: fresh load and re-plug both return success. Add scripts/download-firmware.sh (port of install/firmware.sh), which fetches the driver CAB from Windows Update and extracts firmware/xow_dongle.bin, hash-verified. Co-Authored-By: qwen3.8-27b@q2_k_xl: ported firmware load and download script
This commit is contained in:
@@ -87,7 +87,8 @@ struct transport::state {
|
||||
// struct, and methods are called as (*ref)->Method(ref, ...).
|
||||
io_service_t service = 0;
|
||||
IOCFPlugInInterface **dev_iodev = nullptr;
|
||||
IOUSBDeviceInterface197 **dev_ref = nullptr;
|
||||
// Version 500 interface: adds ResetDevice (port of usb_reset_device).
|
||||
IOUSBDeviceInterface500 **dev_ref = nullptr;
|
||||
bool dev_opened = false;
|
||||
|
||||
struct iface_conn {
|
||||
@@ -232,12 +233,12 @@ auto transport::open(frame_callback frames, disconnect_callback disconnected) ->
|
||||
|
||||
void *slot = nullptr;
|
||||
HRESULT hr = (*state_->dev_iodev)->QueryInterface(state_->dev_iodev,
|
||||
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID197), &slot);
|
||||
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID500), &slot);
|
||||
if (hr != S_OK || !slot) {
|
||||
xone::log_msg(log_level::error, "usb: query device interface failed");
|
||||
return false;
|
||||
}
|
||||
state_->dev_ref = static_cast<IOUSBDeviceInterface197 **>(slot);
|
||||
state_->dev_ref = static_cast<IOUSBDeviceInterface500 **>(slot);
|
||||
|
||||
kr = (*state_->dev_ref)->USBDeviceOpen(state_->dev_ref);
|
||||
if (kr != kIOReturnSuccess) {
|
||||
@@ -246,6 +247,14 @@ auto transport::open(frame_callback frames, disconnect_callback disconnected) ->
|
||||
}
|
||||
state_->dev_opened = true;
|
||||
|
||||
// Reset the chip so it starts from the boot ROM (port of the
|
||||
// usb_reset_device call in xone_dongle_probe).
|
||||
kr = (*state_->dev_ref)->ResetDevice(state_->dev_ref);
|
||||
if (kr != kIOReturnSuccess) {
|
||||
xone::log_msg(log_level::error, "usb: reset device failed (%d)", kr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Open every interface and collect the endpoint pipes we need.
|
||||
io_iterator_t children = 0;
|
||||
kr = IORegistryEntryGetChildIterator(state_->service, kIOServicePlane, &children);
|
||||
|
||||
Reference in New Issue
Block a user