November 17, 2023

Let's learn USB! -- Wireshark and the CP2102

Now that I have some basic knowledge about Wireshark and USB, let's look at my CP2102 USB to serial dongle.

I get rid of the hub (cut out the middle man) and plug it in. Linux shows this in the logs:

Nov 17 13:02:20 trona kernel: usb 4-1.1: new full-speed USB device number 12 using ehci-pci
Nov 17 13:02:20 trona kernel: usb 4-1.1: New USB device found, idVendor=10c4, idProduct=ea60, bcdDevice= 1.00
Nov 17 13:02:20 trona kernel: usb 4-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Nov 17 13:02:20 trona kernel: usb 4-1.1: Product: CP2102 USB to UART Bridge Controller
Nov 17 13:02:20 trona kernel: usb 4-1.1: Manufacturer: Silicon Labs
Nov 17 13:02:20 trona kernel: usb 4-1.1: SerialNumber: 0001
Nov 17 13:02:20 trona kernel: cp210x 4-1.1:1.0: cp210x converter detected
Nov 17 13:02:20 trona kernel: usb 4-1.1: cp210x converter now attached to ttyUSB0
So there you go. It is on USB bus 4 and linux has a driver for it, making it /dev/ttyUSB0. Let's fire up Wireshark on USB bus 4 and repeat the exercise. I use:
usb.dst=="4.12.0" or usb.src=="4.12.0"
I see 22 packets exchanged during enumeration. It will be a little painful, but I intend to transcribe the data for all 11 responses.

1 - Here is the device descriptor:

Frame 986: 82 bytes on wire (656 bits), 82 bytes captured (656 bits) on interface usbmon4, id 0
USB URB
DEVICE DESCRIPTOR
    bLength: 18
    bDescriptorType: 0x01 (DEVICE)
    bcdUSB: 0x0110
    bDeviceClass: Device (0x00)
    bDeviceSubClass: 0
    bDeviceProtocol: 0 (Use class code info from Interface Descriptors)
    bMaxPacketSize0: 64
    idVendor: Silicon Labs (0x10c4)
    idProduct: CP210x UART Bridge (0xea60)
    bcdDevice: 0x0100
    iManufacturer: 1
    iProduct: 2
    iSerialNumber: 3
    bNumConfigurations: 1

2 - Here is the first config descriptor:

Frame 988: 73 bytes on wire (584 bits), 73 bytes captured (584 bits) on interface usbmon4, id 0
USB URB
CONFIGURATION DESCRIPTOR
    bLength: 9
    bDescriptorType: 0x02 (CONFIGURATION)
    wTotalLength: 32
    bNumInterfaces: 1
    bConfigurationValue: 1
    iConfiguration: 0
    Configuration bmAttributes: 0x80  NOT SELF-POWERED  NO REMOTE-WAKEUP
    bMaxPower: 50  (100mA)

3 - Here is the second config descriptor:

Frame 990: 96 bytes on wire (768 bits), 96 bytes captured (768 bits) on interface usbmon4, id 0
USB URB
CONFIGURATION DESCRIPTOR
    bLength: 9
    bDescriptorType: 0x02 (CONFIGURATION)
    wTotalLength: 32
    bNumInterfaces: 1
    bConfigurationValue: 1
    iConfiguration: 0
    Configuration bmAttributes: 0x80  NOT SELF-POWERED  NO REMOTE-WAKEUP
    bMaxPower: 50  (100mA)
INTERFACE DESCRIPTOR (0.0): class Vendor Specific
    bLength: 9
    bDescriptorType: 0x04 (INTERFACE)
    bInterfaceNumber: 0
    bAlternateSetting: 0
    bNumEndpoints: 2
    bInterfaceClass: Vendor Specific (0xff)
    bInterfaceSubClass: 0x00
    bInterfaceProtocol: 0x00
    iInterface: 2
ENDPOINT DESCRIPTOR
    bLength: 7
    bDescriptorType: 0x05 (ENDPOINT)
    bEndpointAddress: 0x81  IN  Endpoint:1
    bmAttributes: 0x02
    wMaxPacketSize: 64
    bInterval: 0
ENDPOINT DESCRIPTOR
    bLength: 7
    bDescriptorType: 0x05 (ENDPOINT)
    bEndpointAddress: 0x01  OUT  Endpoint:1
    bmAttributes: 0x02
    wMaxPacketSize: 64
    bInterval: 0

4 - Here is the first string descriptor (for index 0):

Frame 992: 68 bytes on wire (544 bits), 68 bytes captured (544 bits) on interface usbmon4, id 0
USB URB
STRING DESCRIPTOR
    bLength: 4
    bDescriptorType: 0x03 (STRING)
    wLANGID: English (United States) (0x0409)

5 - Here is the second string descriptor (for index 2):

Frame 994: 138 bytes on wire (1104 bits), 138 bytes captured (1104 bits) on interface usbmon4, id 0
USB URB
STRING DESCRIPTOR
    bLength: 74
    bDescriptorType: 0x03 (STRING)
    bString: CP2102 USB to UART Bridge Controller

6 - Here is the third string descriptor (for index 1):

Frame 996: 90 bytes on wire (720 bits), 90 bytes captured (720 bits) on interface usbmon4, id 0
USB URB
STRING DESCRIPTOR
    bLength: 26
    bDescriptorType: 0x03 (STRING)
    bString: Silicon Labs

7 - Here is the fourth string descriptor (for index 3):

Frame 998: 74 bytes on wire (592 bits), 74 bytes captured (592 bits) on interface usbmon4, id 0
USB URB
STRING DESCRIPTOR
    bLength: 10
    bDescriptorType: 0x03 (STRING)
    bString: 0001

8 - Here is the configuration request (response has no data).

Frame 999: 64 bytes on wire (512 bits), 64 bytes captured (512 bits) on interface usbmon4, id 0
USB URB
Setup Data
    bmRequestType: 0x00
    bRequest: SET CONFIGURATION (9)
    bConfigurationValue: 1
    wIndex: 0 (0x0000)
    wLength: 0

9 - Here is another string descriptor (for index 2 -- again).

Frame 1002: 138 bytes on wire (1104 bits), 138 bytes captured (1104 bits) on interface usbmon4, id 0
USB URB
STRING DESCRIPTOR
    bLength: 74
    bDescriptorType: 0x03 (STRING)
    bString: CP2102 USB to UART Bridge Controller

10 - Here is the first control request (response is a single byte 0x02)

Frame 1003: 64 bytes on wire (512 bits), 64 bytes captured (512 bits) on interface usbmon4, id 0
USB URB
Setup Data
    bmRequestType: 0xc0
    bRequest: 255
    wValue: 0x370b
    wIndex: 0 (0x0000)
    wLength: 1

11 - Here is the second control exchange (response again is a single byte 0x02)

Frame 1005: 64 bytes on wire (512 bits), 64 bytes captured (512 bits) on interface usbmon4, id 0
USB URB
Setup Data
    bmRequestType: 0xc0
    bRequest: 255
    wValue: 0x370b
    wIndex: 0 (0x0000)
    wLength: 2
I am gratified by two things compared to the ACM enumeration: No nonsense with a useless control endpoint and with doing IN on endpoint 2 and OUT on endpoint 3. We use the same endpoint for IN and OUT.

Look at some traffic

Now we use the display filter:
usb.dst=="4.12.1" or usb.src=="4.12.1"
I type using picocom and see single byte transfers using URB BULK out, no terrific surprises.

Conclusion

When I get around to setting up my own tty device on the F103, I don't intend to declare myself as an ACM device. I plan to lie and claim I am a CP2102. I may have to ignore some CONTROL traffic if people try to change baud rate or toggle handshake lines or something, but I can deal with that.
Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org