Project

General

Profile

Bug #11511

usbsacm fails to open sigma designs device

Added by Michael Zeller about 1 year ago. Updated about 1 year ago.

Status:
Closed
Priority:
Normal
Category:
driver - device drivers
Start date:
Due date:
% Done:

100%

Estimated time:
Difficulty:
Bite-size
Tags:
Gerrit CR:

Description

This issue was found on a personal SmartOS server I am running. I have the following USB device plugged into the server: https://aeotec.com/z-wave-usb-stick. From what I understand the device presents a usb serial modem that allows you interact with the device for its intended purpose.

The physical device has some LED lights that can be toggled off via this command

echo -e -n "\x01\x08\x00\xF2\x51\x01\x00\x05\x01\x51" > /dev/cua0

However, on my SmartOS box that results in ENXIO as seen below:

open64("/devices/pci@0,0/pci15d9,400@1d/communications@2/modem@0:0,cu", O_WRONLY|O_CREAT|O_TRUNC, 0666) Err#6 ENXIO

So, I started to dig into the problem to see what I could find. Here is an information dump of what I have so far.

The device descriptor tree:

> ::prtusb -t -v -i b
INDEX   DRIVER      INST  NODE          GEN  VID.PID     PRODUCT
b       usb_mid     1     communications2.0  0658.0200   No Product String
usba_device: 0x84fcf000
mfg_prod_sn: NULL - NULL -NULL
communications, instance #1 (driver name: usb_mid)
  /pci@0,0/pci15d9,400@1d/communications@2
  dip: 0xf3b67008
  usb_mid_statep: 0xde7d1e8
  usb_mid_errlevel: 0x4
{
    modem, instance #0 (driver name: usbsacm)
      /pci@0,0/pci15d9,400@1d/communications@2/modem@0
      dip: 0xd2566aa0
      usbsacm_statep: 0x75591850
      usbsacm_errlevel: 0x4
    data, instance #-1 (driver not attached)
      /pci@0,0/pci15d9,400@1d/communications@2/data
      dip: 0x55d12010
}
Device Descriptor
{
    bLength = 0x12
    bDescriptorType = 0x1
    bcdUSB = 0x200
    bDeviceClass = 0x2
    bDeviceSubClass = 0
    bDeviceProtocol = 0
    bMaxPacketSize0 = 0x8
    idVendor = 0x658
    idProduct = 0x200
    bcdDevice = 0
    iManufacturer = 0
    iProduct = 0
    iSerialNumber = 0
    bNumConfigurations = 0x1
}
    -- Active Config Index 0
    Configuration Descriptor
    {
        bLength = 0x9
        bDescriptorType = 0x2
        wTotalLength = 0x43
        bNumInterfaces = 0x2
        bConfigurationValue = 0x1
        iConfiguration = 0x0
        bmAttributes = 0x80
        bMaxPower = 0x32
    }
        Interface Descriptor
        {
            bLength = 0x9
            bDescriptorType = 0x4
            bInterfaceNumber = 0x0
            bAlternateSetting = 0x0
            bNumEndpoints = 0x1
            bInterfaceClass = 0x2
            bInterfaceSubClass = 0x2
            bInterfaceProtocol = 0x1
            iInterface = 0x0
        }
            Unknown_Interface:0x24
            {
            05 24 00 10 01
            }
            Unknown_Interface:0x24
            {
            05 24 01 00 01
            }
            Unknown_Interface:0x24
            {
            04 24 02 00
            }
            Unknown_Interface:0x24
            {
            05 24 06 00 01
            }
        Endpoint Descriptor
        {
            bLength = 0x7
            bDescriptorType = 0x5
            bEndpointAddress = 0x81
            bmAttributes = 0x3
            wMaxPacketSize = 0x8
            bInterval = 0x20
        }
        Interface Descriptor
        {
            bLength = 0x9
            bDescriptorType = 0x4
            bInterfaceNumber = 0x1
            bAlternateSetting = 0x0
            bNumEndpoints = 0x2
            bInterfaceClass = 0xa
            bInterfaceSubClass = 0x0
            bInterfaceProtocol = 0x0
            iInterface = 0x0
        }
        Endpoint Descriptor
        {
            bLength = 0x7
            bDescriptorType = 0x5
            bEndpointAddress = 0x82
            bmAttributes = 0x2
            wMaxPacketSize = 0x20
            bInterval = 0x0
        }
        Endpoint Descriptor
        {
            bLength = 0x7
            bDescriptorType = 0x5
            bEndpointAddress = 0x2
            bmAttributes = 0x2
            wMaxPacketSize = 0x20
            bInterval = 0x0
        }

If we trace the usbsacm_open path when attempting to echo the example above we see

# ./downstack_usbsacm.d
dtrace: script './downstack_usbsacm.d' matched 1212 probes
CPU FUNCTION
 14  -> usbsacm_open
              genunix`qattach+0xf6
              genunix`stropen+0x347
              specfs`spec_open+0x379
              genunix`fop_open+0x91
              genunix`vn_openat+0x234
              genunix`copen+0x204
              genunix`openat64+0x2a
              genunix`open64+0x25
              unix`_sys_sysenter_post_swapgs+0x153
 14   | usbsacm_open:entry
 14    -> usbser_open
 14      -> usbser_open_setup
 14        -> usbser_open_init
 14          -> usbser_check_port_props
 14          <- usbser_check_port_props       Returns 0x0
 14          -> usbser_thr_dispatch
 14          <- usbser_thr_dispatch           Returns 0x0
 14          -> usbser_thr_dispatch
 14          <- usbser_thr_dispatch           Returns 0x0
 14          -> usbsacm_ds_open_port
 14            -> usbsacm_pm_set_busy
 14            <- usbsacm_pm_set_busy         Returns 0x0
 14            -> usbsacm_open_port_pipes
 14              -> usb_lookup_ep_data
 14              <- usb_lookup_ep_data        Returns 0xfffffede8c72fab0
 14              -> usb_lookup_ep_data
 14              <- usb_lookup_ep_data        Returns 0xfffffee1a1c5e280
 14              -> usb_lookup_ep_data
 14              <- usb_lookup_ep_data        Returns 0xfffffee1a1c5e2a0
 14              -> usb_pipe_open
 14                -> usb_pipe_xopen
 14                  -> usba_get_usba_device
 14                    -> usba_is_root_hub
 14                    <- usba_is_root_hub    Returns 0x0
 14                  <- usba_get_usba_device  Returns 0xfffffee184fcf000
 14                  -> usb_get_ep_index
 14                  <- usb_get_ep_index      Returns 0x12
 14                  -> usba_init_pipe_handle
 14                    -> usba_hcdi_get_hcdi
 14                    <- usba_hcdi_get_hcdi  Returns 0xfffffede1caad558
 14                    -> usba_init_list
 14                    <- usba_init_list      Returns 0x0
 14                    -> usba_init_list
 14                    <- usba_init_list      Returns 0x0
 14                  <- usba_init_pipe_handle Returns 0x0
 14                  -> usba_hcdi_get_data_toggle
 14                    -> usb_get_ep_index
 14                    <- usb_get_ep_index    Returns 0x12
 14                  <- usba_hcdi_get_data_toggle Returns 0x0
 14                  -> usba_pipe_new_state
 14                  <- usba_pipe_new_state   Returns 0x0
 14                <- usb_pipe_xopen          Returns 0x0
 14              <- usb_pipe_open             Returns 0x0
 14              -> usb_pipe_open
 14                -> usb_pipe_xopen
 14                  -> usba_get_usba_device
 14                    -> usba_is_root_hub
 14                    <- usba_is_root_hub    Returns 0x0
 14                  <- usba_get_usba_device  Returns 0xfffffee184fcf000
 14                  -> usb_get_ep_index
 14                  <- usb_get_ep_index      Returns 0x2
 14                  -> usba_init_pipe_handle
 14                    -> usba_hcdi_get_hcdi
 14                    <- usba_hcdi_get_hcdi  Returns 0xfffffede1caad558
 14                    -> usba_init_list
 14                    <- usba_init_list      Returns 0x0
 14                    -> usba_init_list
 14                    <- usba_init_list      Returns 0x0
 14                  <- usba_init_pipe_handle Returns 0x0
 14                  -> usba_hcdi_get_data_toggle
 14                    -> usb_get_ep_index
 14                    <- usb_get_ep_index    Returns 0x2
 14                  <- usba_hcdi_get_data_toggle Returns 0x0
 14                  -> usba_pipe_new_state
 14                  <- usba_pipe_new_state   Returns 0x0
 14                <- usb_pipe_xopen          Returns 0x0
 14              <- usb_pipe_open             Returns 0x0
 14              -> usb_pipe_open
 14                -> usb_pipe_xopen
 14                  -> usba_get_usba_device
 14                    -> usba_is_root_hub
 14                    <- usba_is_root_hub    Returns 0x0
 14                  <- usba_get_usba_device  Returns 0xfffffee184fcf000
 14                  -> usb_get_ep_index
 14                  <- usb_get_ep_index      Returns 0x11
 14                  -> usba_init_pipe_handle
 14                    -> usba_hcdi_get_hcdi
 14                    <- usba_hcdi_get_hcdi  Returns 0xfffffede1caad558
 14                    -> usba_init_list
 14                    <- usba_init_list      Returns 0x0
 14                    -> usba_init_list
 14                    <- usba_init_list      Returns 0x0
 14                  <- usba_init_pipe_handle Returns 0x0
 14                  -> usba_hcdi_get_data_toggle
 14                    -> usb_get_ep_index
 14                    <- usb_get_ep_index    Returns 0x11
 14                  <- usba_hcdi_get_data_toggle Returns 0x0
 14                  -> usba_pipe_new_state
 14                  <- usba_pipe_new_state   Returns 0x0
 14                <- usb_pipe_xopen          Returns 0x0
 14              <- usb_pipe_open             Returns 0x0
 14              -> usbsacm_pipe_start_polling
 14                -> usb_alloc_intr_req
 14                  -> usba_req_wrapper_alloc
 14                    -> usba_get_usba_device
 14                      -> usba_is_root_hub
 14                      <- usba_is_root_hub  Returns 0x0
 14                    <- usba_get_usba_device Returns 0xfffffee184fcf000
 14                    -> usba_hcdi_get_hcdi
 14                    <- usba_hcdi_get_hcdi  Returns 0xfffffede1caad558
 14                    -> usba_init_list
 14                    <- usba_init_list      Returns 0x0
 14                    -> usba_init_list
 14                    <- usba_init_list      Returns 0x0
 14                    -> usba_add_to_list
 14                    <- usba_add_to_list    Returns 0x0
 14                  <- usba_req_wrapper_alloc Returns 0xfffffee08a2a5c70
 14                <- usb_alloc_intr_req      Returns 0xfffffee08a2a5d00
 14                -> usb_pipe_intr_xfer
 14                  -> usba_hold_ph_data
 14                  <- usba_hold_ph_data     Returns 0xfffffef2dd1bb078
 14                  -> usba_check_req
 14                    -> usba_check_in_list
 14                    <- usba_check_in_list  Returns 0x0
 14                    -> usba_flags_attr_check
 14                    <- usba_flags_attr_check Returns 0x0
 14                  <- usba_check_req        Returns 0x0
 14                  -> usba_get_ph_state
 14                  <- usba_get_ph_state     Returns 0x1
 14                  -> usba_pipe_new_state
 14                  <- usba_pipe_new_state   Returns 0x0
 14                  -> usba_hcdi_dup_intr_req
 14                    -> usb_alloc_intr_req
 14                      -> usba_req_wrapper_alloc
 14                        -> usba_get_usba_device
 14                          -> usba_is_root_hub
 14                          <- usba_is_root_hub Returns 0x0
 14                        <- usba_get_usba_device Returns 0xfffffee184fcf000
 14                        -> usba_hcdi_get_hcdi
 14                        <- usba_hcdi_get_hcdi Returns 0xfffffede1caad558
 14                        -> usba_init_list
 14                        <- usba_init_list  Returns 0x0
 14                        -> usba_init_list
 14                        <- usba_init_list  Returns 0x0
 14                        -> usba_add_to_list
 14                        <- usba_add_to_list Returns 0xfffffee08a2a5ca0
 14                      <- usba_req_wrapper_alloc Returns 0xfffffee3c5b7b2d0
 14                    <- usb_alloc_intr_req  Returns 0xfffffee3c5b7b360
 14                  <- usba_hcdi_dup_intr_req Returns 0xfffffee3c5b7b360
 14                  -> usba_release_ph_data
 14                  <- usba_release_ph_data  Returns 0x0
 14                <- usb_pipe_intr_xfer      Returns 0x0
 14              <- usbsacm_pipe_start_polling Returns 0x0
 14            <- usbsacm_open_port_pipes     Returns 0x0
 14            -> usbsacm_rx_start
 14              -> usb_alloc_bulk_req
 14                -> usba_req_wrapper_alloc
 14                  -> usba_get_usba_device
 14                    -> usba_is_root_hub
 14                    <- usba_is_root_hub    Returns 0x0
 14                  <- usba_get_usba_device  Returns 0xfffffee184fcf000
 14                  -> usba_hcdi_get_hcdi
 14                  <- usba_hcdi_get_hcdi    Returns 0xfffffede1caad558
 14                  -> usba_init_list
 14                  <- usba_init_list        Returns 0x0
 14                  -> usba_init_list
 14                  <- usba_init_list        Returns 0x0
 14                  -> usba_add_to_list
 14                  <- usba_add_to_list      Returns 0xfffffee3c5b7b300
 14                <- usba_req_wrapper_alloc  Returns 0xfffffee3c43fb710
 14              <- usb_alloc_bulk_req        Returns 0xfffffee3c43fb7a0
 14              -> usb_pipe_bulk_xfer
 14                -> usba_hold_ph_data
 14                <- usba_hold_ph_data       Returns 0xfffffedfcebd1330
 14                -> usba_check_req
 14                  -> usba_check_in_list
 14                  <- usba_check_in_list    Returns 0x0
 14                  -> usba_flags_attr_check
 14                  <- usba_flags_attr_check Returns 0x0
 14                <- usba_check_req          Returns 0x0
 14                -> usba_get_ph_state
 14                <- usba_get_ph_state       Returns 0x1
 14                -> usba_pipe_new_state
 14                <- usba_pipe_new_state     Returns 0x0
 14                -> usba_release_ph_data
 14                <- usba_release_ph_data    Returns 0x0
 14              <- usb_pipe_bulk_xfer        Returns 0x0
 14            <- usbsacm_rx_start            Returns 0x0
 14          <- usbsacm_ds_open_port          Returns 0x0
 14          -> usbser_port_program
 14            -> usbsacm_ds_set_port_params
 14              -> usb_dprintf2
 14                -> usba_vlog
 14                  -> usb_vprintf
 14                  <- usb_vprintf           Returns 0xfffffeddf24b00b9
 14                <- usba_vlog               Returns 0x0
 14              <- usb_dprintf2              Returns 0x0
 14            <- usbsacm_ds_set_port_params  Returns 0xffffffff
 14          <- usbser_port_program           Returns 0x16
 14        <- usbser_open_init                Returns 0x6
 14        -> usbser_open_fini
 14          -> usbsacm_ds_close_port
 14            -> usbsacm_close_port_pipes
 14              -> usb_pipe_reset
 14                -> usba_hold_ph_data
 14                <- usba_hold_ph_data       Returns 0xfffffedfcebd1330
 14                -> usba_check_intr_context
 14                <- usba_check_intr_context Returns 0x0
 14                -> usba_pipe_setup_func_call
 14                  -> usba_pipe_sync_reset
 14                    -> usba_get_ph_data
 14                    <- usba_get_ph_data    Returns 0xfffffedfcebd1330
 14                    -> usb_dprintf2
 14                      -> usba_vlog
 14                        -> usb_vprintf
 14                        <- usb_vprintf     Returns 0xfffffeddf24b00e8
 14                      <- usba_vlog         Returns 0x0
 14                    <- usb_dprintf2        Returns 0x0
 14                    -> usb_dprintf2
 14                      -> usba_vlog
 14                        -> usb_vprintf
 14                        <- usb_vprintf     Returns 0xfffffeddf24b0130
 14                      <- usba_vlog         Returns 0x0
 14                    <- usb_dprintf2        Returns 0x0
 14                    -> usba_hcdi_cb
 14                      -> usba_hcdi_get_hcdi
 14                      <- usba_hcdi_get_hcdi Returns 0xfffffede1caad558
 14                      -> usba_add_to_list
 14                      <- usba_add_to_list  Returns 0x0
 14                      -> usba_async_ph_req
 14                      <- usba_async_ph_req Returns 0x0
 14                    <- usba_hcdi_cb        Returns 0x0
 14                    -> usba_drain_cbs
 14                      -> usba_rm_first_pvt_from_list
 14                        -> usba_rm_first_from_list
 14                        <- usba_rm_first_from_list Returns 0x0
 14                      <- usba_rm_first_pvt_from_list Returns 0x0
 14                      -> usba_list_entry_count
 14                      <- usba_list_entry_count Returns 0x0
  1                      -> usba_list_entry_count
  1                      <- usba_list_entry_count Returns 0x0
  1                    <- usba_drain_cbs      Returns 0x0
  1                    -> usba_pipe_new_state
  1                    <- usba_pipe_new_state Returns 0x0
  1                    -> usba_start_next_req
  1                      -> usba_get_ph_state
  1                      <- usba_get_ph_state Returns 0x1
  1                      -> usba_rm_first_pvt_from_list
  1                        -> usba_rm_first_from_list
  1                        <- usba_rm_first_from_list Returns 0x0
  1                      <- usba_rm_first_pvt_from_list Returns 0x0
  1                    <- usba_start_next_req Returns 0x0
  1                    -> usba_release_ph_data
  1                    <- usba_release_ph_data Returns 0x0
  1                  <- usba_pipe_sync_reset  Returns 0x0
  1                <- usba_pipe_setup_func_call Returns 0x0
  1              <- usb_pipe_reset            Returns 0x0
  1              -> usb_pipe_close
  1                -> usba_check_intr_context
  1                <- usba_check_intr_context Returns 0x0
  1                -> usba_hold_ph_data
  1                <- usba_hold_ph_data       Returns 0xfffffedfcebd1330
  1                -> usba_pipe_setup_func_call
  1                  -> usba_pipe_sync_close
  1                    -> usba_get_ph_data
  1                    <- usba_get_ph_data    Returns 0xfffffedfcebd1330
  1                    -> usba_hcdi_set_data_toggle
  1                      -> usb_get_ep_index
  1                      <- usb_get_ep_index  Returns 0x12
  1                    <- usba_hcdi_set_data_toggle Returns 0x0
  1                    -> usba_destroy_pipe_handle
  1                      -> usba_destroy_list
  1                      <- usba_destroy_list Returns 0xfffffee195fa6c46
  1                      -> usba_destroy_list
  1                      <- usba_destroy_list Returns 0xfffffee195fa6c46
  1                    <- usba_destroy_pipe_handle Returns 0xfffffee3d54b7940
  1                  <- usba_pipe_sync_close  Returns 0x0
  1                <- usba_pipe_setup_func_call Returns 0x0
  1              <- usb_pipe_close            Returns 0x0
  1              -> usb_pipe_close
  1                -> usba_check_intr_context
  1                <- usba_check_intr_context Returns 0x0
  1                -> usba_hold_ph_data
  1                <- usba_hold_ph_data       Returns 0xfffffee3d913d3e0
  1                -> usba_pipe_setup_func_call
  1                  -> usba_pipe_sync_close
  1                    -> usba_get_ph_data
  1                    <- usba_get_ph_data    Returns 0xfffffee3d913d3e0
  1                    -> usba_hcdi_set_data_toggle
  1                      -> usb_get_ep_index
  1                      <- usb_get_ep_index  Returns 0x2
  1                    <- usba_hcdi_set_data_toggle Returns 0x0
  1                    -> usba_destroy_pipe_handle
  1                      -> usba_destroy_list
  1                      <- usba_destroy_list Returns 0xfffffee195fa6c46
  1                      -> usba_destroy_list
  1                      <- usba_destroy_list Returns 0xfffffee195fa6c46
  1                    <- usba_destroy_pipe_handle Returns 0xfffffee3d54b7940
  1                  <- usba_pipe_sync_close  Returns 0x0
  1                <- usba_pipe_setup_func_call Returns 0x0
  1              <- usb_pipe_close            Returns 0x0
  1              -> usb_pipe_stop_intr_polling
  1                -> usba_hold_ph_data
  1                <- usba_hold_ph_data       Returns 0xfffffef2dd1bb078
  1                -> usba_pipe_setup_func_call
  1                  -> usba_pipe_sync_stop_intr_polling
  1                    -> usba_get_ph_data
  1                    <- usba_get_ph_data    Returns 0xfffffef2dd1bb078
  1                    -> usba_get_ph_state
  1                    <- usba_get_ph_state   Returns 0x2
  1                    -> usba_get_ph_state
  1                    <- usba_get_ph_state   Returns 0x2
  1                    -> usba_hcdi_set_data_toggle
  1                      -> usb_get_ep_index
  1                      <- usb_get_ep_index  Returns 0x11
  1                    <- usba_hcdi_set_data_toggle Returns 0x0
  1                    -> usb_free_intr_req
  1                      -> usba_req_wrapper_free
  1                        -> usba_rm_from_list
  1                        <- usba_rm_from_list Returns 0xffffffff
  1                        -> usba_get_usba_device
  1                          -> usba_is_root_hub
  1                          <- usba_is_root_hub Returns 0x0
  1                        <- usba_get_usba_device Returns 0xfffffee184fcf000
  1                        -> usba_rm_from_list
  1                        <- usba_rm_from_list Returns 0x0
  1                        -> usba_destroy_list
  1                        <- usba_destroy_list Returns 0xfffffee195fa6c46
  1                        -> usba_destroy_list
  1                        <- usba_destroy_list Returns 0xfffffee195fa6c46
  1                      <- usba_req_wrapper_free Returns 0xfffffee3d54b7940
  1                    <- usb_free_intr_req   Returns 0xfffffee3d54b7940
  1                    -> usba_hcdi_cb
  1                      -> usba_hcdi_get_hcdi
  1                      <- usba_hcdi_get_hcdi Returns 0xfffffede1caad558
  1                      -> usba_add_to_list
  1                      <- usba_add_to_list  Returns 0x0
  1                      -> usba_async_ph_req
  1                      <- usba_async_ph_req Returns 0x0
  1                    <- usba_hcdi_cb        Returns 0x0
  1                    -> usba_drain_cbs
  1                      -> usba_rm_first_pvt_from_list
  1                        -> usba_rm_first_from_list
  1                        <- usba_rm_first_from_list Returns 0x0
  1                      <- usba_rm_first_pvt_from_list Returns 0x0
  1                      -> usba_list_entry_count
  1                      <- usba_list_entry_count Returns 0x0
 14                      -> usba_list_entry_count
 14                      <- usba_list_entry_count Returns 0x0
 14                    <- usba_drain_cbs      Returns 0x0
 14                    -> usba_release_ph_data
 14                    <- usba_release_ph_data Returns 0x0
 14                  <- usba_pipe_sync_stop_intr_polling Returns 0x0
 14                <- usba_pipe_setup_func_call Returns 0x0
 14              <- usb_pipe_stop_intr_polling Returns 0x0
 14              -> usb_pipe_close
 14                -> usba_check_intr_context
 14                <- usba_check_intr_context Returns 0x0
 14                -> usba_hold_ph_data
 14                <- usba_hold_ph_data       Returns 0xfffffef2dd1bb078
 14                -> usba_pipe_setup_func_call
 14                  -> usba_pipe_sync_close
 14                    -> usba_get_ph_data
 14                    <- usba_get_ph_data    Returns 0xfffffef2dd1bb078
 14                    -> usba_hcdi_set_data_toggle
 14                      -> usb_get_ep_index
 14                      <- usb_get_ep_index  Returns 0x11
 14                    <- usba_hcdi_set_data_toggle Returns 0x0
 14                    -> usba_destroy_pipe_handle
 14                      -> usba_destroy_list
 14                      <- usba_destroy_list Returns 0xfffffee195fa6c46
 14                      -> usba_destroy_list
 14                      <- usba_destroy_list Returns 0xfffffee195fa6c46
 14                    <- usba_destroy_pipe_handle Returns 0xfffffee3d708c580
 14                  <- usba_pipe_sync_close  Returns 0x0
 14                <- usba_pipe_setup_func_call Returns 0x0
 14              <- usb_pipe_close            Returns 0x0
 14            <- usbsacm_close_port_pipes    Returns 0x0
 14            -> usbsacm_fifo_flush_locked
 14            <- usbsacm_fifo_flush_locked   Returns 0x0
 14            -> usbsacm_pm_set_idle
 14            <- usbsacm_pm_set_idle         Returns 0x0
 14          <- usbsacm_ds_close_port         Returns 0x0
 14          -> usbser_thr_cancel
 14          <- usbser_thr_cancel             Returns 0x0
 14          -> usbser_thr_cancel
 14          <- usbser_thr_cancel             Returns 0x0
 14        <- usbser_open_fini                Returns 0x0
 14      <- usbser_open_setup                 Returns 0x6
 14    <- usbser_open                         Returns 0x6
 14  <- usbsacm_open                          Returns 0x6

Digging through the above output I see that the call to usbsacm_ds_set_port_params() is returning -1 aka USB_FAILURE . Judging by the flow trace that function takes it looks like we we might not be getting passed this check.

        /*
         * If device conform to acm spec, check if it support to set port param.
         */
        if ((acm_port->acm_cap & USB_CDC_ACM_CAP_SERIAL_LINE) == 0 &&
            acmp->acm_compatibility == B_TRUE) {
                mutex_exit(&acm_port->acm_port_mutex);
                USB_DPRINTF_L2(PRINT_MASK_ALL, acmp->acm_lh,
                    "usbsacm_ds_set_port_params: " 
                    "don't support Set_Line_Coding.");
                return (USB_FAILURE);
        }

Since this box is not running a DEBUG build I snooped in on the logs with this dtrace line and confirmed we are indeed returning USB_FAILURE there.

# dtrace -n 'usb_vprintf:entry {print(stringof(args[3]))}' | grep usbsacm
dtrace: description 'usb_vprintf:entry ' matched 1 probe
 12  59311                usb_vprintf:entry string "usbsacm_ds_set_port_params: don't support Set_Line_Coding." 

Next I wanted to see where the acm_cap member of the usbsacm_port_t was coming from which happens to be in usbsacm_get_descriptors on line 1721: http://src.illumos.org/source/xref/illumos-gate/usr/src/uts/common/io/usb/clients/usbser/usbsacm/usbsacm.c#1721

So next I printed out the contents of the usb_alt_if_data_t structure grabbing its address with:

#!/usr/sbin/dtrace -s
usbsacm_get_descriptors:entry
{
        this->acmp = args[0];
        /* print(this->acmp); */
        this->acm_port = this->acmp->acm_ports;
        this->cfg = this->acmp->acm_dev_data->dev_curr_cfg;
        this->altif = this->cfg->cfg_if[this->acm_port->acm_ctrl_if_no].if_alt[0];
        print(this->altif);
}

Which gives us:

# ./zwave_attach.d
dtrace: script './zwave_attach.d' matched 1 probe
CPU     ID                    FUNCTION:NAME
 15  62983    usbsacm_get_descriptors:entry struct usb_alt_if_data {
    usb_if_descr_t altif_descr = {
        uint8_t bLength = 0x9
        uint8_t bDescriptorType = 0x4
        uint8_t bInterfaceNumber = 0
        uint8_t bAlternateSetting = 0
        uint8_t bNumEndpoints = 0x1
        uint8_t bInterfaceClass = 0x2
        uint8_t bInterfaceSubClass = 0x2
        uint8_t bInterfaceProtocol = 0x1
        uint8_t iInterface = 0
    }
    struct usb_ep_data *altif_ep = 0xfffffede96dceb58
    struct usb_cvs_data *altif_cvs = 0xfffffede5a4e0040
    char *altif_str = 0xfffffedef7d38b88
    uint_t altif_n_ep = 0x1
    uint_t altif_n_cvs = 0x4
    uint_t altif_strsize = 0x7
}
> 0xfffffede5a4e0040,4::print "struct usb_cvs_data" 
{
    cvs_buf = 0xfffffef2d6368de8
    cvs_buf_len = 0x5
}
{
    cvs_buf = 0xfffffee3ddc290b0
    cvs_buf_len = 0x5
}
{
    cvs_buf = 0xfffffedf55cc1038
    cvs_buf_len = 0x4
}
{
    cvs_buf = 0xfffffedf55c9e3b8
    cvs_buf_len = 0x5
}

If we look at the 3rd member we see

> 0xfffffedf55cc1038,4/V
0xfffffedf55cc1038:             4       36      2       0

We know the code checks for USB_CDC_DESCR_TYPE_ACM when setting up acm_port->acm_cap which is defined as 0x02. So the buffer I dumped above shows USB_CDC_DESCR_TYPE_ACM in the field the code is switching over aka cvs->cvs_buf2. The code then sets the field like so: acm_port->acm_cap = cvs->cvs_buf[3]; Which we can see in the above output is "0".

I can manually modify this field with mdb and verify that I can toggle the LED lights on and off on the physical device. I am also able to confirm that the real technical features of the device function as expected.

addr/W 2

Some relavant info from a linux box where the device works:

[377981.025628] usb 1-4: new full-speed USB device number 4 using xhci_hcd
[377981.345033] usb 1-4: New USB device found, idVendor=0658, idProduct=0200, bcdDevice= 0.00
[377981.345036] usb 1-4: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[377981.362847] cdc_acm 1-4:1.0: ttyACM0: USB ACM device
[377981.365070] usbcore: registered new interface driver cdc_acm
[377981.365071] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
$ sudo lsusb -D /dev/bus/usb/001/004
Device: ID 0658:0200 Sigma Designs, Inc. Aeotec Z-Stick Gen5 (ZW090) - UZB
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            2 Communications
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0         8
  idVendor           0x0658 Sigma Designs, Inc.
  idProduct          0x0200 Aeotec Z-Stick Gen5 (ZW090) - UZB
  bcdDevice            0.00
  iManufacturer           0
  iProduct                0
  iSerial                 0
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0043
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      1 AT-commands (v.25ter)
      iInterface              0
      CDC Header:
        bcdCDC               1.10
      CDC Call Management:
        bmCapabilities       0x00
        bDataInterface          1
      CDC ACM:
        bmCapabilities       0x00
      CDC Union:
        bMasterInterface        0
        bSlaveInterface         1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              32
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0020  1x 32 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0020  1x 32 bytes
        bInterval               0
can't get device qualifier: Resource temporarily unavailable
can't get debug descriptor: Resource temporarily unavailable
Device Status:     0x0000
  (Bus Powered)

The descriptors seem to match up perfectly from with what each OS is reading from the device.
Since Linux reports CDC ACM as 0x00 it seems that the Linux driver doesn't have the same issue we do.

History

#1

Updated by Michael Zeller about 1 year ago

Robert Mustacchi noted the following:

"It appears that the major difference between us and the other operating systems is that we care about that particular capability. The rest basically still try to set it regardless of whether or not that flag says they should or shouldn't. It appears Linux will more explicitly warn about that case when it fails. We may want to consider just not having that check there and warning about it if it fails when that's not there. I suspect that the impact of such a change isn't terribly high."

#2

Updated by Jorge Schrauwen about 1 year ago

I also have a zwave usb stick, but from a different vendor: https://z-wave.me/uzb/

This one also identifies as the same device, as the design is open they all share the same chips from silabs.
https://www.silabs.com/products/development-tools/software/z-wave

#3

Updated by Michael Zeller about 1 year ago

Testing notes from https://www.illumos.org/rb/r/2206/ :

Built and ran this patch on a SmartOS platform and confirmed that the USB device was successfully able to control z-wave devices on my network. I also had two more community members, sjorge and bahamas10, confirm that it made their devices function correctly as well. Bahamas10 and I have the same USB device while sjorge has another device using the same Sigma Designs, Inc chip.

#4

Updated by Electric Monk about 1 year ago

  • Status changed from In Progress to Closed
  • % Done changed from 0 to 100

git commit 8072728215ff40bc56f6ad193cd22da6fbc03bc6

commit  8072728215ff40bc56f6ad193cd22da6fbc03bc6
Author: Mike Zeller <mike@mikezeller.net>
Date:   2019-08-05T16:53:04.000Z

    11511 usbsacm fails to open sigma designs device
    Reviewed by: Joshua M. Clulow <josh@sysmgr.org>
    Reviewed by: Gergő Doma <domag02@gmail.com>
    Reviewed by: Toomas Soome <tsoome@me.com>
    Approved by: Dan McDonald <danmcd@joyent.com>

Also available in: Atom PDF