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()
|
112 | 112 | config = gUSBModule->get_configuration(fDevice); |
113 | 113 | gUSBModule->set_alt_interface(fDevice, |
114 | 114 | &config->interface[fDataInterfaceIndex].alt[1]); |
| 115 | gUSBModule->set_alt_interface(fDevice, |
| 116 | &config->interface[fControlInterfaceIndex].alt[0]); |
115 | 117 | |
116 | 118 | // update again |
117 | 119 | config = gUSBModule->get_configuration(fDevice); |
… |
… |
ECMDevice::Open()
|
136 | 138 | return B_ERROR; |
137 | 139 | } |
138 | 140 | |
| 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 | |
139 | 149 | // the device should now be ready |
140 | 150 | fOpen = true; |
141 | 151 | return B_OK; |
… |
… |
ECMDevice::Close()
|
150 | 160 | return B_OK; |
151 | 161 | } |
152 | 162 | |
| 163 | gUSBModule->cancel_queued_transfers(fNotifyEndpoint); |
153 | 164 | gUSBModule->cancel_queued_transfers(fReadEndpoint); |
154 | 165 | gUSBModule->cancel_queued_transfers(fWriteEndpoint); |
155 | 166 | |
… |
… |
ECMDevice::CompareAndReattach(usb_device device)
|
367 | 378 | status_t |
368 | 379 | ECMDevice::_SetupDevice() |
369 | 380 | { |
370 | | const usb_configuration_info *config |
371 | | = gUSBModule->get_configuration(fDevice); |
| 381 | const usb_device_descriptor *deviceDescriptor |
| 382 | = gUSBModule->get_device_descriptor(fDevice); |
372 | 383 | |
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"); |
375 | 386 | return B_ERROR; |
376 | 387 | } |
377 | 388 | |
… |
… |
ECMDevice::_SetupDevice()
|
379 | 390 | uint8 dataIndex = 0; |
380 | 391 | bool foundUnionDescriptor = false; |
381 | 392 | 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 | |
389 | 408 | // try to find and interpret the union and ethernet functional |
390 | 409 | // descriptors |
391 | 410 | 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; |
394 | 413 | if (generic->length >= 5 |
395 | 414 | && generic->data[0] == FUNCTIONAL_SUBTYPE_UNION) { |
396 | 415 | controlIndex = generic->data[1]; |
… |
… |
ECMDevice::_SetupDevice()
|
406 | 425 | } |
407 | 426 | |
408 | 427 | if (foundUnionDescriptor && foundEthernetDescriptor) |
409 | | break; |
| 428 | goto found; |
410 | 429 | } |
411 | 430 | } |
412 | 431 | } |
… |
… |
ECMDevice::_SetupDevice()
|
421 | 440 | return B_ERROR; |
422 | 441 | } |
423 | 442 | |
| 443 | found: |
| 444 | // set the current configuration |
| 445 | gUSBModule->set_configuration(fDevice, config); |
424 | 446 | if (controlIndex >= config->interface_count) { |
425 | 447 | TRACE_ALWAYS("control interface index invalid\n"); |
426 | 448 | return B_ERROR; |
… |
… |
ECMDevice::_SetupDevice()
|
438 | 460 | |
439 | 461 | fControlInterfaceIndex = controlIndex; |
440 | 462 | 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; |
448 | 464 | |
449 | 465 | if (dataIndex >= config->interface_count) { |
450 | 466 | TRACE_ALWAYS("data interface index invalid\n"); |