puhitaku / mtplvcap

Nikon to USB Webcam. Supports older models that Nikon WU does not. Windows/macOS/Linux. No HDMI capture dongle is needed. Ask me on Twitter @puhitaku

Home Page:https://twitter.com/puhitaku

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Does not work on macOS Ventura 13.1

puhitaku opened this issue · comments

Failing part

The current master branch fails to open the DSLR prompting the following error:

$ ./mtplvcap
[0000]  INFO usb: found: 04b0:0431
[0000] ERROR mtp: fatal error LIBUSB_ERROR_NOT_FOUND; closing connection.
[0000] FATAL main: failed to detect MTP devices: could not open 04b0:0431: mtp: no MTP extensions in ''

With a patch to fix the lack of error handling (which is a shame,) like the following:

@@ -120,10 +125,14 @@ func (d *DeviceDirect) Open() error {
                log.USB.Debugf("open, err: %v", err)
        }
        if err != nil {
-               return err
+               return fmt.Errorf("failed to open: %w", err)
+       }
+
+       err = d.claim()
+       if err != nil {
+               return fmt.Errorf("failed to claim: %w", err)
        }

-       d.claim()
        if d.ifaceDescr.InterfaceStringIndex == 0 {
                // Some of the win8phones have no interface field.
                info := DeviceInfo{}

The actual error in claim function shows up:

$ ./mtplvcap
[0000]  INFO usb: found: 04b0:0431
[0000] FATAL main: failed to detect MTP devices: could not open 04b0:0431: failed to claim: LIBUSB_ERROR_ACCESS

Root cause

macOS Ventura has some changes related to MTP devices. For example,

Many people say that it is due to a kernel driver that occupies the device. So I added a call to libusb_detach_kernel_driver:

@@ -93,7 +93,12 @@ func (d *DeviceDirect) claim() error {
                return fmt.Errorf("mtp: claim: device not open")
        }

-       err := d.h.ClaimInterface(d.ifaceDescr.InterfaceNumber)
+       err := d.h.DetachKernelDriver(d.ifaceDescr.InterfaceNumber)
+       if err != nil {
+               return err
+       }
+
+       err = d.h.ClaimInterface(d.ifaceDescr.InterfaceNumber)
        if d.Debug.USB {
                log.USB.Debugf("claimInterface 0x%x, err: %v", d.ifaceDescr.InterfaceNumber, err)
        }

It worked as I expected, but only with the superuser privilege.

Mysterious though, even after detaching the kernel driver, mtplvcap without super privilege has no access to the device.

# With the privilege, it works without a problem

$ sudo ./mtplvcap
Password:
[0000]  INFO usb: found: 04b0:0431
[0000]  INFO main: started
^C[0003]  INFO main: caught signal: interrupt
[0004] ERROR main: interrupt

# Without the privilege, it finds no MTP device.

: mtplvcap $ ./mtplvcap
[0000] FATAL main: failed to detect MTP devices: no MTP devices found

Temporary solution

The only way to make it work is to apply the patch above and run mtplvcap as a superuser.

Released version 1.6.1 that has #69 changes. Closing.