Ticket #13793: 0001-usb_ecm-support-for-QEmu-CDCE-network-device.patch

File 0001-usb_ecm-support-for-QEmu-CDCE-network-device.patch, 5.0 KB (added by korli, 6 years ago)
  • src/add-ons/kernel/drivers/network/usb_ecm/ECMDevice.cpp

    From 04c7ffa20228057d7439a419ffb32fb9313e4ef1 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= <jerome.duval@gmail.com>
    Date: Wed, 22 Nov 2017 23:02:35 +0100
    Subject: [PATCH] usb_ecm: support for QEmu CDCE network device.
    
    * the CDCE configuration happens to not be the first: iterate the configurations.
    * we set the alternate control interface
    * queue interrupt requests once opened.
    ---
     .../kernel/drivers/network/usb_ecm/ECMDevice.cpp   | 58 ++++++++++++++--------
     1 file changed, 37 insertions(+), 21 deletions(-)
    
    diff --git a/src/add-ons/kernel/drivers/network/usb_ecm/ECMDevice.cpp b/src/add-ons/kernel/drivers/network/usb_ecm/ECMDevice.cpp
    index 7150927..adcb9ce 100644
    a b ECMDevice::Open()  
    112112    config = gUSBModule->get_configuration(fDevice);
    113113    gUSBModule->set_alt_interface(fDevice,
    114114        &config->interface[fDataInterfaceIndex].alt[1]);
     115    gUSBModule->set_alt_interface(fDevice,
     116        &config->interface[fControlInterfaceIndex].alt[0]);
    115117
    116118    // update again
    117119    config = gUSBModule->get_configuration(fDevice);
    ECMDevice::Open()  
    136138        return B_ERROR;
    137139    }
    138140
     141    if (gUSBModule->queue_interrupt(fNotifyEndpoint, fNotifyBuffer,
     142        fNotifyBufferLength, _NotifyCallback, this) != B_OK) {
     143        // we cannot use notifications - hardcode to active connection
     144        fHasConnection = true;
     145        fDownstreamSpeed = 1000 * 1000 * 10; // 10Mbps
     146        fUpstreamSpeed = 1000 * 1000 * 10; // 10Mbps
     147    }
     148
    139149    // the device should now be ready
    140150    fOpen = true;
    141151    return B_OK;
    ECMDevice::Close()  
    150160        return B_OK;
    151161    }
    152162
     163    gUSBModule->cancel_queued_transfers(fNotifyEndpoint);
    153164    gUSBModule->cancel_queued_transfers(fReadEndpoint);
    154165    gUSBModule->cancel_queued_transfers(fWriteEndpoint);
    155166
    ECMDevice::CompareAndReattach(usb_device device)  
    367378status_t
    368379ECMDevice::_SetupDevice()
    369380{
    370     const usb_configuration_info *config
    371         = gUSBModule->get_configuration(fDevice);
     381    const usb_device_descriptor *deviceDescriptor
     382                = gUSBModule->get_device_descriptor(fDevice);
    372383
    373     if (config == NULL) {
    374         TRACE_ALWAYS("failed to get device configuration\n");
     384    if (deviceDescriptor == NULL) {
     385        TRACE_ALWAYS("failed to get device descriptor\n");
    375386        return B_ERROR;
    376387    }
    377388
    ECMDevice::_SetupDevice()  
    379390    uint8 dataIndex = 0;
    380391    bool foundUnionDescriptor = false;
    381392    bool foundEthernetDescriptor = false;
    382     for (size_t i = 0; i < config->interface_count
    383         && (!foundUnionDescriptor || !foundEthernetDescriptor); i++) {
    384         usb_interface_info *interface = config->interface[i].active;
    385         usb_interface_descriptor *descriptor = interface->descr;
    386         if (descriptor->interface_class == USB_INTERFACE_CLASS_CDC
    387             && descriptor->interface_subclass == USB_INTERFACE_SUBCLASS_ECM
    388             && interface->generic_count > 0) {
     393    const usb_configuration_info *config = NULL;
     394    for (int i = 0; i < deviceDescriptor->num_configurations; i++) {
     395        config = gUSBModule->get_nth_configuration(fDevice, i);
     396        if (config == NULL)
     397            continue;
     398
     399        for (size_t j = 0; j < config->interface_count; j++) {
     400            const usb_interface_info *interface = config->interface[j].active;
     401            usb_interface_descriptor *descriptor = interface->descr;
     402            if (descriptor->interface_class != USB_INTERFACE_CLASS_CDC
     403                || descriptor->interface_subclass != USB_INTERFACE_SUBCLASS_ECM
     404                || interface->generic_count == 0) {
     405                continue;
     406            }
     407
    389408            // try to find and interpret the union and ethernet functional
    390409            // descriptors
    391410            foundUnionDescriptor = foundEthernetDescriptor = false;
    392             for (size_t j = 0; j < interface->generic_count; j++) {
    393                 usb_generic_descriptor *generic = &interface->generic[j]->generic;
     411            for (size_t k = 0; k < interface->generic_count; k++) {
     412                usb_generic_descriptor *generic = &interface->generic[k]->generic;
    394413                if (generic->length >= 5
    395414                    && generic->data[0] == FUNCTIONAL_SUBTYPE_UNION) {
    396415                    controlIndex = generic->data[1];
    ECMDevice::_SetupDevice()  
    406425                }
    407426
    408427                if (foundUnionDescriptor && foundEthernetDescriptor)
    409                     break;
     428                    goto found;
    410429            }
    411430        }
    412431    }
    ECMDevice::_SetupDevice()  
    421440        return B_ERROR;
    422441    }
    423442
     443found:
     444    // set the current configuration
     445    gUSBModule->set_configuration(fDevice, config);
    424446    if (controlIndex >= config->interface_count) {
    425447        TRACE_ALWAYS("control interface index invalid\n");
    426448        return B_ERROR;
    ECMDevice::_SetupDevice()  
    438460
    439461    fControlInterfaceIndex = controlIndex;
    440462    fNotifyEndpoint = interface->endpoint[0].handle;
    441     if (gUSBModule->queue_interrupt(fNotifyEndpoint, fNotifyBuffer,
    442         fNotifyBufferLength, _NotifyCallback, this) != B_OK) {
    443         // we cannot use notifications - hardcode to active connection
    444         fHasConnection = true;
    445         fDownstreamSpeed = 1000 * 1000 * 10; // 10Mbps
    446         fUpstreamSpeed = 1000 * 1000 * 10; // 10Mbps
    447     }
     463    fNotifyBufferLength = interface->endpoint[0].descr->max_packet_size;
    448464
    449465    if (dataIndex >= config->interface_count) {
    450466        TRACE_ALWAYS("data interface index invalid\n");