luxonis / depthai-core

DepthAI C++ Library
MIT License
231 stars 126 forks source link

[Feature-Request] Modify USB pid #877

Open ibaiGorordo opened 1 year ago

ibaiGorordo commented 1 year ago

Start with the why:

In certain systems, the fact that the USB device profile changes when the device is started and closed generates some issues. Like WSL (Ref: https://discuss.luxonis.com/d/693-i-got-depthai-demo-to-run-in-wsl/4) or Android (even though it is not officially supported) with USB permissions.

Move to the what:

I have tried flashing a config with a new pid value to match the pid defined when the device starts (code below), but even though the config is flashed correctly, the device pid is not changed. Since the Device Manager example does not give the option to modify the pid, does it mean that it is not possible to modify it?

# Create pipeline
pipeline = dai.Pipeline()

# Set board config
config = dai.DeviceBootloader.Config()
config.usb.pid = 0xf63b

(res, info) = dai.DeviceBootloader.getFirstAvailableDevice()
with dai.DeviceBootloader(info) as bootloader:
    progress = lambda p : print(f'Flashing progress: {p*100:.1f}%')
    (r, errmsg) = bootloader.flashConfig(config)
    if r:
        print("Flashed successfully")
    else:
        print(f"Error: {errmsg}")

(res, info) = dai.DeviceBootloader.getFirstAvailableDevice()
with dai.DeviceBootloader(info) as bootloader:
    print('Current flashed configuration')
    print(json.dumps(bootloader.readConfigData()))

On the other hand, is it possible to modify the pid value when the device starts? I have tried also something like this but with no luck either:

dai::BoardConfig boardConfig;
boardConfig.usb.pid = 0x03E7;
pipeline.setBoardConfig(boardConfig);

I have also looked checked about standalone app so that it will automatically boot and avoid having the pre-boot pid, but in my case, I want to get access to the data from the OAKD using the XLINKOut nodes, so I think it would be possible.

It would be great if there was some way to do it.

Move to the how:

No other ideas apart what is mentioned above.

Thanks!

themarpe commented 1 year ago

@ibaiGorordo try without flashing and just boot the device - is it applied correctly in that case? Also try latest develop branch. Otherwise this is a bug that we'll have to patch in FW

In certain systems, the fact that the USB device profile changes when the device is started and closed generates some issues. Like WSL (Ref: https://discuss.luxonis.com/d/693-i-got-depthai-demo-to-run-in-wsl/4) or Android (even though it is not officially supported) with USB permissions.

Technicalities asside - this alone likely won't do, as device discovery and state is recognized based off device PID. BL has a separate PID than running Device FW has.

One'd have to tweak discovery mechanism of XLink as well to allow for this (shouldn't be too difficult however, relying on eg device name, etc...)

ibaiGorordo commented 1 year ago

Hi @themarpe ,

Thank you for the quick reply! I am not sure if I understand all you mentioned so please correct me if I misunderstood something. The first method of flashing to the bootloader would only modify the PID of the device when booted into the BL, so it is not really an option.

The other option of setting the board config in the pipeline, actually changed the PID this time (I think nothing was happening last time I tested it a few weeks ago), but I get an error because as you mention XLINK is expecting a certain PID.

    with dai.Device(pipeline) as device:
RuntimeError: Failed to find device after booting, error message: X_LINK_DEVICE_NOT_FOUND

Would it be possible to add that feature to the roadmap? If not, could you please give some guidance on where in the XLINK repo should I make the changes?

Thanks! Ibai

ibaiGorordo commented 1 year ago

I was able to get it working in a quick and dirty way.

Since I am not expecting any other devices connected, if the state is not correct, I just check if the devicePath has changed: https://github.com/luxonis/XLink/commit/2e4a813317349975d103c0d36d6098ea66e69b81

And opening the device like this:

auto deviceInfoVec = dai::Device::getAllAvailableDevices();
dai::Device device(pipeline, deviceInfoVec[0], dai::UsbSpeed::SUPER_PLUS);

That was the best I could come up with :see_no_evil:. I would love to hear if there (for sure must be) is a better way to do it.

themarpe commented 1 year ago

@ibaiGorordo best way to do it is to have filtering be done through some other means than PID. That'd be perhaps using the product name: BoardConfig.USB.productName where "booted" could then contain same PID as Bootloader (0xf63b) but productName would be used to differentiate. XLink changes would be required to do so, check:


        if(vidPidToDeviceState.count(vidpid) > 0){
            // Device found

            // Device status
            XLinkError_t status = X_LINK_SUCCESS;

            // Get device state
            XLinkDeviceState_t state = vidPidToDeviceState.at(vidpid);
            // Check if compare with state
            if(in_deviceRequirements.state != X_LINK_ANY_STATE && state != in_deviceRequirements.state){
                // Current device doesn't match the "filter"
                continue;
            }

where as this simple vidPidToDeviceState map would have to be changed to a function that also reads out product string from string descriptors of the device. That way, instead of Luxonis Bootloader it could say Luxonis Device while having PID of bootloader (0xf63b).


Note, product name will already be Luxonis Device, so no need to change productName under BoardConfig, just tweak filtering to take that into account as well