Author Topic: Windows CDC reading wrong interface  (Read 17158 times)

Barry Twycross

  • Frequent Contributor
  • ****
  • Posts: 263
Windows CDC reading wrong interface
« on: August 07, 2014, 03:28:16 pm »
Our device declares itself as a CDC device and has a CDC interfaces to make it look like a modem. We use for this for development. This works with the built in drivers on Linux and Mac OS. On Windows we use a .inf file that someone created a long time ago for a different product, but it seems to work if you know how to point Windows to the .inf file, and a COM port is created. Windows is pretty much a mystery to me, I'm just happy it works.

Recently I added another interface to the device. This is a vendor specific interface with a bulk in pipe used for logging. By my reading of the CDC spec, this is legal. Mac OS and Linux have no problem with this extra interface, the CDC still works and I can read from the vendor specific bulk interface. On Windows, after updating the driver and pointing Windows towards the same .inf file, a COM port appears again. However, the CDC driver is now trying to read from the bulk pipe in the vendor specific interface, not from the bulk pipe in the CDC data interface. This disables our interface, (but we do get the logging over the other interface, which I wasn't expecting.)

Is there anyway I can persuade the Windows CDC driver to read from its own interface?

I tried putting the vendor specific interface first in the configuration, which I don't think is a legal configuration. I was hoping the CDC driver would just take the last bulk pipe, but the Mac OS CDC driver stopped working.

I'm testing this on Windows 7 Home Premium SP1. Our factory may be using a different version of Windows.

The .inf file looks like this:

[Version]
Signature="$Windows NT$"
Class=Ports
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
Provider=%ProviderName%
DriverVer=04/26/2012,1.1.0.0

[MANUFACTURER]
%ProviderName%=DeviceList, NTx86, NTamd64

[DeviceList.NTx86]
%OurCDC%=DriverInstall,USB\VID_1234&PID_0001&MI_01&Class_02&SubClass_02
%AnotherCDC%=DriverInstall,USB\VID_1234&PID_0002&MI_01&Class_02&SubClass_02

[DeviceList.NTamd64]
%OurCDC%=DriverInstall,USB\VID_1234&PID_0001&MI_01&Class_02&SubClass_02
%AnotherCDC%=DriverInstall,USB\VID_1234&PID_0002&MI_01&Class_02&SubClass_02

[DriverInstall]
include=mdmcpq.inf
CopyFiles=FakeModemCopyFileSection
AddReg=LowerFilterAddReg,SerialPropPageAddReg

[DriverInstall.Services]
include = mdmcpq.inf
AddService = usbser, 0x00000002, LowerFilter_Service_Inst

; This adds the serial port property tab to the device properties dialog
[SerialPropPageAddReg]
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"

[Strings]
ProviderName = "OurName"
OurCDC = "Our Product"
AnotherCDC = "Our Product"

And  descriptor dump of the device.

Full Speed device @ 11 (0x1D115000): .............................................   Communication device: "Our Device"
    Port Information:   0x0018
           Not Captive
           External Device
           Connected
           Enabled
    Number Of Endpoints (includes EP0):   
        Total Endpoints for Configuration 1 (current):   5
    Device Descriptor   
        Descriptor Version Number:   0x0110
        Device Class:   2   (Communication)
        Device Subclass:   0
        Device Protocol:   0
        Device MaxPacketSize:   64
        Device VendorID/ProductID:   0x1234/0x0006   (unknown vendor)
        Device Version Number:   0x0000
        Number of Configurations:   1
        Manufacturer String:   1 "Company"
        Product String:   2 "Our Device"
        Serial Number String:   3 "0123456789ABCDEF"
    Configuration Descriptor (current config)   
        Length (and contents):   83
            Raw Descriptor (hex)    0000: 09 02 53 00 03 01 00 C0  32 09 04 00 00 01 02 02 
            Raw Descriptor (hex)    0010: 01 01 05 24 00 10 01 05  24 01 00 01 04 24 02 00 
            Raw Descriptor (hex)    0020: 05 24 06 00 01 07 05 83  03 20 00 02 09 04 01 00
            Raw Descriptor (hex)    0030: 02 0A 00 00 01 07 05 84  02 20 00 00 07 05 05 02 
            Raw Descriptor (hex)    0040: 20 00 00 09 04 02 00 01  FF 01 00 00 07 05 87 02 
            Raw Descriptor (hex)    0050: 40 00 00
        Number of Interfaces:   3
        Configuration Value:   1
        Attributes:   0xC0 (self-powered)
        MaxPower:   100 mA
        Interface #0 - Communications-Control ..............................................   "Company"
            Alternate Setting   0
            Number of Endpoints   1
            Interface Class:   2   (Communications-Control)
            Interface Subclass;   2
            Interface Protocol:   1
            Comm Class Header Functional Descriptor   
                Raw Descriptor (hex)   0000: 05 24 00 10 01
            Comm Class Call Management Functional Descriptor   
                Raw Descriptor (hex)   0000: 05 24 01 00 01
            Comm Class Abstract Control Management Functional Descriptor   
                Raw Descriptor (hex)   0000: 04 24 02 00
            Comm Class Union Functional Descriptor   
                Raw Descriptor (hex)   0000: 05 24 06 00 01
            Endpoint 0x83 - Interrupt Input   
                Address:   0x83  (IN)
                Attributes:   0x03  (Interrupt)
                Max Packet Size:   32
                Polling Interval:   2 ms
        Interface #1 - Communications-Data/Unknown Comm Class Model ..............................................   "Company"
            Alternate Setting   0
            Number of Endpoints   2
            Interface Class:   10   (Communications-Data)
            Interface Subclass;   0   (Unknown Comm Class Model)
            Interface Protocol:   0
            Endpoint 0x84 - Bulk Input   
                Address:   0x84  (IN)
                Attributes:   0x02  (Bulk)
                Max Packet Size:   32
                Polling Interval:   0 ms
            Endpoint 0x05 - Bulk Output   
                Address:   0x05  (OUT)
                Attributes:   0x02  (Bulk)
                Max Packet Size:   32
                Polling Interval:   0 ms
        Interface #2 - Vendor-specific   
            Alternate Setting   0
            Number of Endpoints   1
            Interface Class:   255   (Vendor-specific)
            Interface Subclass;   1   (Vendor-specific)
            Interface Protocol:   0
            Endpoint 0x87 - Bulk Input   
                Address:   0x87  (IN)
                Attributes:   0x02  (Bulk)
                Max Packet Size:   64
                Polling Interval:   0 ms

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Windows CDC reading wrong interface
« Reply #1 on: August 07, 2014, 03:39:58 pm »
The CDC function needs an interface association descriptor.

WinXP SP2 requires a hotfix to support it; Win7 should be OK.

Barry Twycross

  • Frequent Contributor
  • ****
  • Posts: 263
Re: Windows CDC reading wrong interface
« Reply #2 on: August 07, 2014, 03:52:12 pm »
I was hoping to avoid the Interface association descriptor, I'm not sure how well that works on a Mac.

Sec 3.3 of the CDC1.2 spec seems to imply that the Interface association descriptor is only necessary of the device class isn't 2 (which it is for our device).

I notice that sec 3.1 says:

Quote
Data transmission is accomplished using interfaces in addition to the Communications Class interface. These interfaces can use any defined USB class or can be vendor-specific.

I'm assuming that's why its thinks it can grab hold of the Vendor specific interface. Why it ignores a perfectly good data interface is the mystery. I'm wondering if the .inf file could be used to tell the CDC driver to use the data interface instead.

Barry Twycross

  • Frequent Contributor
  • ****
  • Posts: 263
Re: Windows CDC reading wrong interface
« Reply #3 on: August 07, 2014, 04:13:22 pm »
It looks like this is supposed to be controlled by the CDC class union descriptor.

Quote
           Comm Class Union Functional Descriptor   
                Raw Descriptor (hex)   0000: 05 24 06 00 01
Which looks to be correct. Interface zero is a master interface and interface 1 is the subordinate interface, in this case the DATA class interface. It makes no mention of interface 2 which is what Windows is grabbing hold of.

This descriptor maybe why the Mac didn't like me rearranging the interface, I'll investigate. The CDC portion of this is also somewhat of a mystery, I inherited it and it seemed to work.
« Last Edit: August 07, 2014, 04:14:58 pm by Barry Twycross »

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Windows CDC reading wrong interface
« Reply #4 on: August 07, 2014, 05:02:09 pm »
It's possible that Windows requires the IAD even if the spec doesn't.

WinXP, not sure about later editions, also allowed non-compliant CDC devices that use a single interface for data and notifications, but you probably don't want to go down that road.

I don't know of any way to have the INF file specify the data interface.

Barry Twycross

  • Frequent Contributor
  • ****
  • Posts: 263
Re: Windows CDC reading wrong interface
« Reply #5 on: August 07, 2014, 05:29:09 pm »
My first theory was correct. If I make the vendor specific interface first, so the Data interface is last, Windows actually reads from the Data interface and it works. I have to make sure the CDC union descriptor is correct for this.

However, Mac OS doesn't work with that configuration. I might be able to work out why it does't, or I could just turn the vendor specific interface off for Windows. It was never needed under Windows. I don't want to try and detect the host, so I can make it a persistent setting.

Barry Twycross

  • Frequent Contributor
  • ****
  • Posts: 263
Re: Windows CDC reading wrong interface
« Reply #6 on: August 07, 2014, 06:39:20 pm »
Using an interface association descriptor didn't work. I tried both adding a IAC to the CDC class (class 2) device, or making it an IAC device (device class == 0xef, device subclass = 2, device protocol == 1).

Though the .inf file hasn't changed, that's still forcing a match to the device, so the driver has all the interfaces to play with. I'm wondering if a .inf file which just assigns the Interface association to the serial driver, so it doesn't have access to the Vendor specific interface would work. Making such a .inf file would be beyond me though.

Barry Twycross

  • Frequent Contributor
  • ****
  • Posts: 263
Re: Windows CDC reading wrong interface
« Reply #7 on: August 07, 2014, 06:50:13 pm »
The IAC device (device 0xEF, 2, 1) works on Mac OS 10.8.5 (and 10.9). I'm a little surprised, I thought it hadn't been implemented by that time.

Its also working on Linux (Ubuntu 12.04).

Windows is still my problem.

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Windows CDC reading wrong interface
« Reply #8 on: August 07, 2014, 06:58:36 pm »
If you're changing things and keeping the same Vendor ID and Product ID, before trying new descriptors, be sure to remove the device in Device Manager, then physically remove and reattach because otherwise Windows will cache and use the previous descriptors.

Barry Twycross

  • Frequent Contributor
  • ****
  • Posts: 263
Re: Windows CDC reading wrong interface
« Reply #9 on: August 07, 2014, 07:32:30 pm »
If you're changing things and keeping the same Vendor ID and Product ID, before trying new descriptors, be sure to remove the device in Device Manager, then physically remove and reattach because otherwise Windows will cache and use the previous descriptors.
Thanks, I'd forgotten about that.

The IAC device does work on Windows, after remembering that.

Though now I have a permissions problem on Linux, though I suspect that's an entirely different problem.