Move USB CDC Ethernet descriptor to shared header

Use the same structure in usb_ecm and listusb

Change-Id: I8d33b434560bb18bb2f6247090d1580c267adab2
Reviewed-on: https://review.haiku-os.org/c/haiku/+/11046
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
PulkoMandy
2026-06-01 08:00:34 +00:00
committed by Adrien Destugues
parent 30cb44085c
commit 96037d5af2
5 changed files with 66 additions and 66 deletions
+13 -2
View File
@@ -16,7 +16,7 @@ enum { // Communication Interface Subclasses
USB_CDC_COMMUNICATION_INTERFACE_TCM_SUBCLASS, // Telephone Control Model USB_CDC_COMMUNICATION_INTERFACE_TCM_SUBCLASS, // Telephone Control Model
USB_CDC_COMMUNICATION_INTERFACE_MCCM_SUBCLASS, // Multi-Channel Control Model USB_CDC_COMMUNICATION_INTERFACE_MCCM_SUBCLASS, // Multi-Channel Control Model
USB_CDC_COMMUNICATION_INTERFACE_CAPICM_SUBCLASS, // CAPI Control Model USB_CDC_COMMUNICATION_INTERFACE_CAPICM_SUBCLASS, // CAPI Control Model
USB_CDC_COMMUNICATION_INTERFACE_ENCM_SUBCLASS, // Ethernet Networking Control Model USB_CDC_COMMUNICATION_INTERFACE_ECM_SUBCLASS, // Ethernet Control Model
USB_CDC_COMMUNICATION_INTERFACE_ATMNCM_SUBCLASS // ATM Networking Control Model USB_CDC_COMMUNICATION_INTERFACE_ATMNCM_SUBCLASS // ATM Networking Control Model
}; };
@@ -35,7 +35,8 @@ enum { // Functional Descriptors Subtypes
USB_CDC_HEADER_FUNCTIONAL_DESCRIPTOR = 0x00, USB_CDC_HEADER_FUNCTIONAL_DESCRIPTOR = 0x00,
USB_CDC_CM_FUNCTIONAL_DESCRIPTOR, USB_CDC_CM_FUNCTIONAL_DESCRIPTOR,
USB_CDC_ACM_FUNCTIONAL_DESCRIPTOR, USB_CDC_ACM_FUNCTIONAL_DESCRIPTOR,
USB_CDC_UNION_FUNCTIONAL_DESCRIPTOR = 0x06 USB_CDC_UNION_FUNCTIONAL_DESCRIPTOR = 0x06,
USB_CDC_ETHERNET_FUNCTIONAL_DESCRIPTOR = 0x0f
}; };
typedef struct usb_cdc_header_function_descriptor { typedef struct usb_cdc_header_function_descriptor {
@@ -80,6 +81,16 @@ typedef struct usb_cdc_union_functional_descriptor {
uint8 slave_interfaces[1]; uint8 slave_interfaces[1];
} _PACKED usb_cdc_union_functional_descriptor; } _PACKED usb_cdc_union_functional_descriptor;
typedef struct usb_cdc_ethernet_functional_descriptor {
uint8 length;
uint8 descriptor_type;
uint8 descriptor_subtype; // USB_CDC_ETHERNET_FUNCTIONAL_DESCRIPTOR
uint8 mac_address_index;
uint32 ethernet_statistics;
uint16 max_segment_size;
uint16 num_multi_cast_filters;
uint8 num_wakeup_pattern_filters;
} _PACKED usb_cdc_ethernet_functional_descriptor;
enum { // Management Element Requests (p62) enum { // Management Element Requests (p62)
USB_CDC_SEND_ENCAPSULATED_COMMAND = 0x00, USB_CDC_SEND_ENCAPSULATED_COMMAND = 0x00,
@@ -166,13 +166,15 @@ usb_ecm_supports_device(device_node *parent)
if (!strcmp(attr->name, USB_DEVICE_SUBCLASS)) if (!strcmp(attr->name, USB_DEVICE_SUBCLASS))
subclass = attr->value.ui8; subclass = attr->value.ui8;
if (baseClass != 0 && subclass != 0) { if (baseClass != 0 && subclass != 0) {
if (baseClass == USB_INTERFACE_CLASS_CDC && subclass == USB_INTERFACE_SUBCLASS_ECM) if (baseClass == USB_COMMUNICATION_DEVICE_CLASS
&& subclass == USB_CDC_COMMUNICATION_INTERFACE_ECM_SUBCLASS)
break; break;
baseClass = subclass = 0; baseClass = subclass = 0;
} }
} }
if (baseClass != USB_INTERFACE_CLASS_CDC || subclass != USB_INTERFACE_SUBCLASS_ECM) if (baseClass != USB_CDC_COMMUNICATION_INTERFACE_CLASS
|| subclass != USB_CDC_COMMUNICATION_INTERFACE_ECM_SUBCLASS)
return 0.0; return 0.0;
TRACE("USB-ECM device found!\n"); TRACE("USB-ECM device found!\n");
@@ -11,6 +11,7 @@
#include <KernelExport.h> #include <KernelExport.h>
#include <OS.h> #include <OS.h>
#include <USB3.h> #include <USB3.h>
#include <usb/USB_cdc.h>
#include <util/kernel_cpp.h> #include <util/kernel_cpp.h>
@@ -18,24 +19,8 @@
#define MAX_DEVICES 8 #define MAX_DEVICES 8
/* class and subclass codes */ /* class and subclass codes */
#define USB_INTERFACE_CLASS_CDC 0x02
#define USB_INTERFACE_SUBCLASS_ECM 0x06
#define USB_INTERFACE_CLASS_CDC_DATA 0x0a
#define USB_INTERFACE_SUBCLASS_DATA 0x00 #define USB_INTERFACE_SUBCLASS_DATA 0x00
/* communication device descriptor subtypes */
#define FUNCTIONAL_SUBTYPE_UNION 0x06
#define FUNCTIONAL_SUBTYPE_ETHERNET 0x0f
typedef struct ethernet_functional_descriptor_s {
uint8 functional_descriptor_subtype;
uint8 mac_address_index;
uint32 ethernet_statistics;
uint16 max_segment_size;
uint16 num_multi_cast_filters;
uint8 num_wakeup_pattern_filters;
} _PACKED ethernet_functional_descriptor;
/* notification definitions */ /* notification definitions */
#define CDC_NOTIFY_NETWORK_CONNECTION 0x00 #define CDC_NOTIFY_NETWORK_CONNECTION 0x00
#define CDC_NOTIFY_CONNECTION_SPEED_CHANGE 0x2a #define CDC_NOTIFY_CONNECTION_SPEED_CHANGE 0x2a
@@ -303,7 +303,7 @@ ECMDevice::Removed()
// the notify hook is different from the read and write hooks as it does // the notify hook is different from the read and write hooks as it does
// itself schedule traffic (while the other hooks only release a semaphore // itself schedule traffic (while the other hooks only release a semaphore
// to notify another thread which in turn safly checks for the removed // to notify another thread which in turn safely checks for the removed
// case) - so we must ensure that we are not inside the notify hook anymore // case) - so we must ensure that we are not inside the notify hook anymore
// before returning, as we would otherwise violate the promise not to use // before returning, as we would otherwise violate the promise not to use
// any of the pipes after returning from the removed hook // any of the pipes after returning from the removed hook
@@ -397,8 +397,8 @@ ECMDevice::_SetupDevice()
for (size_t j = 0; j < config->interface_count && !found; j++) { for (size_t j = 0; j < config->interface_count && !found; j++) {
const usb_interface_info *interface = config->interface[j].active; const usb_interface_info *interface = config->interface[j].active;
usb_interface_descriptor *descriptor = interface->descr; usb_interface_descriptor *descriptor = interface->descr;
if (descriptor->interface_class != USB_INTERFACE_CLASS_CDC if (descriptor->interface_class != USB_CDC_COMMUNICATION_INTERFACE_CLASS
|| descriptor->interface_subclass != USB_INTERFACE_SUBCLASS_ECM || descriptor->interface_subclass != USB_CDC_COMMUNICATION_INTERFACE_ECM_SUBCLASS
|| interface->generic_count == 0) { || interface->generic_count == 0) {
continue; continue;
} }
@@ -409,14 +409,14 @@ ECMDevice::_SetupDevice()
for (size_t k = 0; k < interface->generic_count; k++) { for (size_t k = 0; k < interface->generic_count; k++) {
usb_generic_descriptor *generic = &interface->generic[k]->generic; usb_generic_descriptor *generic = &interface->generic[k]->generic;
if (generic->length >= 5 if (generic->length >= 5
&& generic->data[0] == FUNCTIONAL_SUBTYPE_UNION) { && generic->data[0] == USB_CDC_UNION_FUNCTIONAL_DESCRIPTOR) {
controlIndex = generic->data[1]; controlIndex = generic->data[1];
dataIndex = generic->data[2]; dataIndex = generic->data[2];
foundUnionDescriptor = true; foundUnionDescriptor = true;
} else if (generic->length >= sizeof(ethernet_functional_descriptor) } else if (generic->length >= sizeof(usb_cdc_ethernet_functional_descriptor)
&& generic->data[0] == FUNCTIONAL_SUBTYPE_ETHERNET) { && generic->data[0] == USB_CDC_ETHERNET_FUNCTIONAL_DESCRIPTOR) {
ethernet_functional_descriptor *ethernet usb_cdc_ethernet_functional_descriptor *ethernet
= (ethernet_functional_descriptor *)generic->data; = (usb_cdc_ethernet_functional_descriptor *)generic;
fMACAddressIndex = ethernet->mac_address_index; fMACAddressIndex = ethernet->mac_address_index;
fMaxSegmentSize = ethernet->max_segment_size; fMaxSegmentSize = ethernet->max_segment_size;
foundEthernetDescriptor = true; foundEthernetDescriptor = true;
@@ -450,8 +450,8 @@ ECMDevice::_SetupDevice()
// check that the indicated control interface fits our needs // check that the indicated control interface fits our needs
usb_interface_info *interface = config->interface[controlIndex].active; usb_interface_info *interface = config->interface[controlIndex].active;
usb_interface_descriptor *descriptor = interface->descr; usb_interface_descriptor *descriptor = interface->descr;
if ((descriptor->interface_class != USB_INTERFACE_CLASS_CDC if ((descriptor->interface_class != USB_COMMUNICATION_DEVICE_CLASS
|| descriptor->interface_subclass != USB_INTERFACE_SUBCLASS_ECM) || descriptor->interface_subclass != USB_CDC_COMMUNICATION_INTERFACE_ECM_SUBCLASS)
|| interface->endpoint_count == 0) { || interface->endpoint_count == 0) {
TRACE_ALWAYS("control interface invalid\n"); TRACE_ALWAYS("control interface invalid\n");
return B_ERROR; return B_ERROR;
@@ -475,7 +475,7 @@ ECMDevice::_SetupDevice()
// alternate 0 is the disabled, endpoint-less default interface // alternate 0 is the disabled, endpoint-less default interface
interface = &config->interface[dataIndex].alt[1]; interface = &config->interface[dataIndex].alt[1];
descriptor = interface->descr; descriptor = interface->descr;
if (descriptor->interface_class != USB_INTERFACE_CLASS_CDC_DATA if (descriptor->interface_class != USB_CDC_DATA_INTERFACE_CLASS
|| interface->endpoint_count < 2) { || interface->endpoint_count < 2) {
TRACE_ALWAYS("data interface invalid\n"); TRACE_ALWAYS("data interface invalid\n");
return B_ERROR; return B_ERROR;
+37 -35
View File
@@ -121,180 +121,182 @@ DumpCDCDescriptor(const usb_generic_descriptor* descriptor, const BUSBInterface*
case 0x0E: case 0x0E:
printf("CAPI control\n"); printf("CAPI control\n");
break; break;
case 0x0F: case USB_CDC_ETHERNET_FUNCTIONAL_DESCRIPTOR:
{ {
printf("Ethernet\n"); printf("Ethernet\n");
const usb_cdc_ethernet_functional_descriptor* ethDesc
= (const usb_cdc_ethernet_functional_descriptor*)descriptor;
printf(" MAC Address ...... %s\n", printf(" MAC Address ...... %s\n",
interface->Device()->DecodeStringDescriptor(descriptor->data[1])); interface->Device()->DecodeStringDescriptor(ethDesc->mac_address_index));
printf(" Statistics ....... "); printf(" Statistics ....... ");
bool somethingPrinted = false; bool somethingPrinted = false;
if ((descriptor->data[2] & 0x01) != 0) { if ((ethDesc->ethernet_statistics & 0x01) != 0) {
printf("XMIT_OK"); printf("XMIT_OK");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[2] & 0x02) != 0) { if ((ethDesc->ethernet_statistics & 0x02) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("RCV_OK"); printf("RCV_OK");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[2] & 0x04) != 0) { if ((ethDesc->ethernet_statistics & 0x04) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("XMIT_ERROR"); printf("XMIT_ERROR");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[2] & 0x08) != 0) { if ((ethDesc->ethernet_statistics & 0x08) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("RCV_ERROR"); printf("RCV_ERROR");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[2] & 0x10) != 0) { if ((ethDesc->ethernet_statistics & 0x10) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("RCV_NO_BUFFER"); printf("RCV_NO_BUFFER");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[2] & 0x20) != 0) { if ((ethDesc->ethernet_statistics & 0x20) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("DIRECTED_BYTES_XMIT"); printf("DIRECTED_BYTES_XMIT");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[2] & 0x40) != 0) { if ((ethDesc->ethernet_statistics & 0x40) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("DIRECTED_FRAMES_XMIT"); printf("DIRECTED_FRAMES_XMIT");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[2] & 0x80) != 0) { if ((ethDesc->ethernet_statistics & 0x80) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("MULTICAST_BYTES_XMIT"); printf("MULTICAST_BYTES_XMIT");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[3] & 0x01) != 0) { if ((ethDesc->ethernet_statistics & 0x0100) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("MULTICAST_FRAMES_XMIT"); printf("MULTICAST_FRAMES_XMIT");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[3] & 0x02) != 0) { if ((ethDesc->ethernet_statistics & 0x0200) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("BROADCAST_BYTES_XMIT"); printf("BROADCAST_BYTES_XMIT");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[3] & 0x04) != 0) { if ((ethDesc->ethernet_statistics & 0x0400) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("BROADCAST_FRAMES_XMIT"); printf("BROADCAST_FRAMES_XMIT");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[3] & 0x08) != 0) { if ((ethDesc->ethernet_statistics & 0x0800) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("DIRECTED_BYTES_RCV"); printf("DIRECTED_BYTES_RCV");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[3] & 0x10) != 0) { if ((ethDesc->ethernet_statistics & 0x1000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("DIRECTED_FRAMES_RCV"); printf("DIRECTED_FRAMES_RCV");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[3] & 0x20) != 0) { if ((ethDesc->ethernet_statistics & 0x2000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("MULTICAST_BYTES_RCV"); printf("MULTICAST_BYTES_RCV");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[3] & 0x40) != 0) { if ((ethDesc->ethernet_statistics & 0x4000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("MULTICAST_FRAMES_RCV"); printf("MULTICAST_FRAMES_RCV");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[3] & 0x80) != 0) { if ((ethDesc->ethernet_statistics & 0x8000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("BROADCAST_BYTES_RCV"); printf("BROADCAST_BYTES_RCV");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[4] & 0x01) != 0) { if ((ethDesc->ethernet_statistics & 0x010000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("BROADCAST_FRAMES_RCV"); printf("BROADCAST_FRAMES_RCV");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[4] & 0x02) != 0) { if ((ethDesc->ethernet_statistics & 0x020000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("RCV_CRC_ERROR"); printf("RCV_CRC_ERROR");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[4] & 0x04) != 0) { if ((ethDesc->ethernet_statistics & 0x040000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("TRANSMIT_QUEUE_LENGTH"); printf("TRANSMIT_QUEUE_LENGTH");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[4] & 0x08) != 0) { if ((ethDesc->ethernet_statistics & 0x080000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("RCV_ERROR_ALIGNMENT"); printf("RCV_ERROR_ALIGNMENT");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[4] & 0x10) != 0) { if ((ethDesc->ethernet_statistics & 0x100000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("XMIT_ONE_COLLISION"); printf("XMIT_ONE_COLLISION");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[4] & 0x20) != 0) { if ((ethDesc->ethernet_statistics & 0x200000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("XMIT_MORE_COLLISIONS"); printf("XMIT_MORE_COLLISIONS");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[4] & 0x40) != 0) { if ((ethDesc->ethernet_statistics & 0x400000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("XMIT_DEFERRED"); printf("XMIT_DEFERRED");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[4] & 0x80) != 0) { if ((ethDesc->ethernet_statistics & 0x800000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("XMIT_MAX_COLLISIONS"); printf("XMIT_MAX_COLLISIONS");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[5] & 0x01) != 0) { if ((ethDesc->ethernet_statistics & 0x01000000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("RCV_OVERRUN"); printf("RCV_OVERRUN");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[5] & 0x02) != 0) { if ((ethDesc->ethernet_statistics & 0x02000000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("XMIT_UNDERRUN"); printf("XMIT_UNDERRUN");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[5] & 0x04) != 0) { if ((ethDesc->ethernet_statistics & 0x04000000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("XMIT_HEARTBEAT_FAILURE"); printf("XMIT_HEARTBEAT_FAILURE");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[5] & 0x08) != 0) { if ((ethDesc->ethernet_statistics & 0x08000000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("XMIT_TIMES_CRS_LOST"); printf("XMIT_TIMES_CRS_LOST");
somethingPrinted = true; somethingPrinted = true;
} }
if ((descriptor->data[5] & 0x10) != 0) { if ((ethDesc->ethernet_statistics & 0x10000000) != 0) {
if (somethingPrinted) if (somethingPrinted)
printf(", "); printf(", ");
printf("XMIT_LATE_COLLISIONS"); printf("XMIT_LATE_COLLISIONS");
@@ -305,11 +307,11 @@ DumpCDCDescriptor(const usb_generic_descriptor* descriptor, const BUSBInterface*
printf("None"); printf("None");
printf("\n"); printf("\n");
printf(" Max. Segment Size %d\n", printf(" Max. Segment Size %d\n",
descriptor->data[6] | descriptor->data[7] << 8); ethDesc->max_segment_size);
printf(" Multicast filters %d\n", printf(" Multicast filters %d\n",
descriptor->data[8] | descriptor->data[9] << 8); ethDesc->num_multi_cast_filters);
printf(" Power filters ... %d\n", printf(" Wakeup filters .. %d\n",
descriptor->data[10]); ethDesc->num_wakeup_pattern_filters);
return; return;
} }
case 0x10: case 0x10: