Skip to content
This repository has been archived by the owner on Dec 10, 2018. It is now read-only.

USB scale not working on Mac #180

Closed
klabarge opened this issue Feb 26, 2016 · 15 comments
Closed

USB scale not working on Mac #180

klabarge opened this issue Feb 26, 2016 · 15 comments
Labels

Comments

@klabarge
Copy link
Member

Mac OS X El Capitan 10.11.3
Chrome, Firefox, and Safari
I am using a Stamps.com Model 510 that works successfully on Windows

I am able to Claim Device and Open Stream properly:

  1. After Open Stream is selected, the Read Data screen is displayed, and no values are read off of the scale. Nothing is displayed in the console at this point.
    image

  2. When clicking "Read as Weight" the Raw data dialogue does not change and the below console errors are shown. This error indefinitely happens until Read as Raw is selected.

    Chrome Console

    image

    Firefox Console

    image

@tresf
Copy link
Contributor

tresf commented Feb 26, 2016

I'm impressed you could claim the device... I'm getting this in an Apple OS X 10.11 VM:

Error: USB error 3: Unable to claim interface: Access denied (insufficient permissions)

Seems to be a duplicate of stackoverflow/28884817 which states OSX claims the devices preventing other applications from doing so. The work-arounds are tragically ugly (creating dummy kext kernel extensions for every VendorID, ProductID that needs to be made available, reboot).

@klabarge
Copy link
Member Author

I initially received the Access Denied error as well. I'm not exactly sure how I got around this, as I did nothing besides basic troubleshooting such as restarting the browser and QZ Tray.

I would like to note that I am receiving almost the exact error on Ubuntu 14.04

Ubuntu 14.04
Error: USB error 3: Can't open device Bus 001 Device 013: ID 1446:6a73: Access denied (insufficient permissions)

@tresf
Copy link
Contributor

tresf commented Feb 26, 2016

It appears Apple fixed some of the USB issues with software updates and my VM is behind... Updating now...

Possible upstream bug report libusb/libusb#96.

@tresf
Copy link
Contributor

tresf commented Feb 26, 2016

More information about this bug... https://github.com/libusb/libusb/wiki/FAQ#How_can_I_run_libusb_applications_under_Mac_OS_X_if_there_is_already_a_kernel_extension_installed_for_the_device

Edit: Kext signing request submitted to Apple. Follow-up: 636837176
Edit2: Started via 2.0...tresf:2.0

@tresf
Copy link
Contributor

tresf commented Feb 26, 2016

I think I got it via 2.0...tresf:2.0

Note, until Apple approves my request for developer signing rights for kernel extensions (kext), the following bash must be run prior to installing.

  1. Install this temporary installer qz-tray-2.0.0-unsigned-kext3.pkg

  2. Run the following command:

    sudo nvram boot-args=kext-dev-mode=1
  3. Then boot in recovery mode and disable System Integrity Protection:

    1. Reboot Mac

    2. Hold the following keys: Command + R

    3. When prompted for Recovery, go to Utilities, Terminal

    4. Type:

      csrutil disable
      reboot
  4. Wait for OSX to load up again...

  5. Fire up QZ, sample.html

  6. Try to read scale

Notes:

  • The reboot step is mandatory even after I get signing rights but only needs to happen after the first install if USB support is needed.
  • It didn't work my first attempt, but it may have been a problem with the USB pass-thru with VMWare fusion.
  • @bberenz there seems to be a range error going on as can be seen in the below picture. The Raw data seems to alternate between 03,04,0c,fe,af,00,00,00 and 04,04,00,00,00,00,00,00.

screen shot 2016-02-26 at 2 35 35 am

@klabarge
Copy link
Member Author

After following the above steps, I now get a NullPointerException when trying to "List Device Interfaces."

Even after rebooting a second time, I get the same error.

image

@tresf
Copy link
Contributor

tresf commented Feb 27, 2016

Can you you start in debug mode and tell is where the NullPointerException is being fired from?

Also, despite that, can you still claim the device?

@klabarge
Copy link
Member Author

I cannot claim the device. I get "Identifier cannot be empty."

  • Here's the stack trace when I click "List Device Interfaces"
[DEBUG] 2016-02-26 21:39:57,824 @ qz.ws.PrintSocketClient:?
    Message: {"call":"usb.listInterfaces","promise":{},"params":{"vendorId":"0x1446","productId":"0x6a73"},"timestamp":1456540797823,"uid":"wat88r"}
[WARN] 2016-02-26 21:39:57,824 @ qz.ws.PrintSocketClient:?
    Bad signature on request
[INFO] 2016-02-26 21:39:58,934 @ qz.common.TrayManager:?
    Allowed localhost to access USB devices
[ERROR] 2016-02-26 21:39:58,935 @ qz.ws.PrintSocketClient:?
    Problem processing message
java.lang.NullPointerException
    at qz.utils.UsbUtilities.getDeviceInterfaces(Unknown Source)
    at qz.utils.UsbUtilities.getDeviceInterfacesJSON(Unknown Source)
    at qz.ws.PrintSocketClient.processMessage(Unknown Source)
    at qz.ws.PrintSocketClient.onMessage(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.eclipse.jetty.websocket.common.events.annotated.CallableMethod.call(CallableMethod.java:70)
    at org.eclipse.jetty.websocket.common.events.annotated.OptionalSessionCallableMethod.call(OptionalSessionCallableMethod.java:68)
    at org.eclipse.jetty.websocket.common.events.JettyAnnotatedEventDriver$2.run(JettyAnnotatedEventDriver.java:210)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
    at java.lang.Thread.run(Thread.java:745)
  • Here's the stack trace when I try to claim the device while inputting the known Device Interface
[DEBUG] 2016-02-26 21:41:46,274 @ qz.ws.PrintSocketClient:?
    Message: {"call":"usb.claimDevice","promise":{},"params":{"vendorId":"0x1446","productId":"0x6a73","interface":"0x00"},"timestamp":1456540906273,"uid":"tw4y9f"}
[WARN] 2016-02-26 21:41:46,274 @ qz.ws.PrintSocketClient:?
    Bad signature on request
[INFO] 2016-02-26 21:41:47,428 @ qz.common.TrayManager:?
    Allowed localhost to claim a USB device
[ERROR] 2016-02-26 21:41:47,429 @ qz.ws.PrintSocketClient:?
    Problem processing message
java.lang.NullPointerException
    at qz.communication.UsbIO.open(Unknown Source)
    at qz.ws.PrintSocketClient.processMessage(Unknown Source)
    at qz.ws.PrintSocketClient.onMessage(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.eclipse.jetty.websocket.common.events.annotated.CallableMethod.call(CallableMethod.java:70)
    at org.eclipse.jetty.websocket.common.events.annotated.OptionalSessionCallableMethod.call(OptionalSessionCallableMethod.java:68)
    at org.eclipse.jetty.websocket.common.events.JettyAnnotatedEventDriver$2.run(JettyAnnotatedEventDriver.java:210)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
    at java.lang.Thread.run(Thread.java:745)

@tresf
Copy link
Contributor

tresf commented Feb 27, 2016

@bberenz I'm going to need some help to fix the NullPointerException.

I've narrowed it down to the fact that this USB device on Mac for some reason has no "Active" configuration.

The work-around for this was to setup a helper function to grab the active configuration and if null, fallback to the first, non-null configuration. This successfully prevents the buttons List Device Interfaces and List Interface Endpoints from returning a NPE.

public static UsbConfiguration getUsbConfiguration(UsbDevice device) throws UsbException {
     UsbConfiguration config = device.getActiveUsbConfiguration();
     if (config != null) {
         return config;
     }

     for (Object o : device.getUsbConfigurations()) {
         if (o != null) {
             return (UsbConfiguration)o;
         }
     }

     throw new UsbException("UsbConfiguration not found for vendorId/productId");
}

Per: https://github.com/tresf/qz-print/commit/d53236e95d56fa2990d30728b086999131144ca0#diff-66e51979c4dd4f537b85c3203a0f1568R120

However, a strict mandate of the USB library is to only allow the claiming of an active configuration. This means when we click Claim Device, a new exception is thrown Configuration not active.

My attempts to workaround this have all failed, but mostly due to my lack of understanding of the way this library works.

The JSR says you can call StandardRequest.setInterface(...) to set the configuration as active, but I'm not sure what the parameters should be (or even if this could be accomplished easier using a libusb4java call.

public void open(byte ifc) throws UsbException {
-     iface = device.getActiveUsbConfiguration().getUsbInterface(ifc);
+     iface = UsbUtilities.getUsbConfiguration(device).getUsbInterface(ifc);
+
+     // FIXME
+     // Sets the interface index, alternate settings index incase the interface isn't active
+     //if (!iface.isActive()) {
+     //    StandardRequest.setInterface(device, ifc, (byte)0x00);
+     //}
+
       iface.claim();
}

Per: https://github.com/tresf/qz-print/commit/d53236e95d56fa2990d30728b086999131144ca0#diff-52ae2363b650928540f4715b3eae938fR36

Help appreciated.

@tresf
Copy link
Contributor

tresf commented Feb 28, 2016

Turns out the nvram hack died hard with an OS X update, so the unsigned kernel extension work-around had to be amended. Instructions have been updated. #180 (comment). Please perform these with caution as they disable integrity checks for the OS.

New installer link has been provided as well.

Note, this still suffers the Configuration not active bug (#180 (comment)), which for some reason I'm now able to reproduce on my 10.11 VM.

Research on #180 (comment) suggests usb_set_configuration() is actually recommended on OS X for libusb, just a matter of finding out the High-Level javax.usb api which calls it...

@tresf
Copy link
Contributor

tresf commented Feb 28, 2016

Still banging my head on this... Filed upstream bug report to ask for help.usb4java/usb4java#51

@tresf
Copy link
Contributor

tresf commented Feb 29, 2016

Low-level API didn't help at all.

After re-reading some libusb threads again, I'm pretty sure the OS X fix hasn't made it downstream yet (10.11.4) per libusb/libusb#123.

I signed up for the OS X beta program.... Installing now...

image

@tresf
Copy link
Contributor

tresf commented Feb 29, 2016

Update: 10.11.4 still does NOT fix this issue. Edit filed an upstream bug report over at libusb. libusb/libusb#158

@tresf
Copy link
Contributor

tresf commented Mar 2, 2016

Well, I made every valiant attempt possible to no avail. Closing as wont-fix, not-our-bug.

The long history of trial and error is better documented with the libusb devs over at libusb/libusb#158.

Here's the last working kernel extension build if we ever have to go back on it... https://github.com/tresf/qz-print/commit/f70c1a5dc27526d7274542671c89a3e8e6ba9399

This feature will be added using official HID support when 2.1 is released. Until then, no USB scale support on Apple (and we can remove it from our test scripts for now).

@tresf tresf closed this as completed Mar 2, 2016
@tresf
Copy link
Contributor

tresf commented Mar 10, 2016

As a status update on this, kext signing was approved for our Apple Developer ID.

We're unlikely to use it for claiming HID devices on Mac, but it's available in case we encounter hardware that requires it.

Team ID: P5DMU6659X 
Company / Organization: QZ INDUSTRIES LLC
Company / Product URL: https://qz.io
Intended Distribution: Consumer or Enterprise Distribution
Reason for Request: Allow a list of pre-approved USB devices through libusb.

Update: HID support has been started in the tray repo here: qzind/tray@1d2f230, available sometime after the 2.0.0-stable release.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants