Changeset 25458

Show
Ignore:
Timestamp:
05/11/08 13:55:12 (6 days ago)
Author:
mmlr
Message:
* Added support for device state change notifications and implemented the
  ETHER_GET_LINK_STATE and ETHER_SET_LINK_STATE_SEM to provide this
  information and notification.
* Don't try to clear an endpoint halt in case of a B_CANCELED status in the
  callbacks as this is triggered by explicitly canceling transfers when the
  device is closed/removed.
* Renamed the semaphore members to *Sem to distinguish them better.
* Some minor other cleanup and some added comments.
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • haiku/trunk/src/add-ons/kernel/drivers/network/usb_ecm/Driver.h

    r25439 r25458  
    3636} _PACKED ethernet_functional_descriptor; 
    3737 
     38/* notification definitions */ 
     39#define CDC_NOTIFY_NETWORK_CONNECTION           0x00 
     40#define CDC_NOTIFY_CONNECTION_SPEED_CHANGE      0x2a 
     41 
     42typedef struct cdc_notification_s { 
     43        uint8   request_type; 
     44        uint8   notification_code; 
     45        uint16  value; 
     46        uint16  index; 
     47        uint16  data_length; 
     48        uint8   data[0]; 
     49} _PACKED cdc_notification; 
     50 
     51typedef struct cdc_connection_speed_s { 
     52        uint32  upstream_speed; /* in bits/s */ 
     53        uint32  downstream_speed; /* in bits/s */ 
     54} _PACKED cdc_connection_speed; 
     55 
    3856extern usb_module_info *gUSBModule; 
    3957 
  • haiku/trunk/src/add-ons/kernel/drivers/network/usb_ecm/ECMDevice.cpp

    r25439 r25458  
    55*/ 
    66#include <ether_driver.h> 
     7#include <net/if_media.h> 
    78#include <string.h> 
    89#include <stdlib.h> 
     
    2122                fMACAddressIndex(0), 
    2223                fMaxSegmentSize(0), 
    23                 fControlEndpoint(0), 
     24                fNotifyEndpoint(0), 
    2425                fReadEndpoint(0), 
    25                 fWriteEndpoint(0) 
     26                fWriteEndpoint(0), 
     27                fNotifyReadSem(-1), 
     28                fNotifyWriteSem(-1), 
     29                fNotifyBuffer(NULL), 
     30                fNotifyBufferLength(0), 
     31                fLinkStateChangeSem(-1), 
     32                fHasConnection(false), 
     33                fDownstreamSpeed(0), 
     34                fUpstreamSpeed(0) 
    2635{ 
    2736        const usb_device_descriptor *deviceDescriptor 
     
    5160                        // try to find and interpret the union and ethernet functional 
    5261                        // descriptors 
     62                        foundUnionDescriptor = foundEthernetDescriptor = false; 
    5363                        for (size_t j = 0; j < interface->generic_count; j++) { 
    5464                                usb_generic_descriptor *generic = &interface->generic[j]->generic; 
     
    104114 
    105115        fControlInterfaceIndex = controlIndex; 
    106         fControlEndpoint = interface->endpoint[0].handle; 
     116        fNotifyEndpoint = interface->endpoint[0].handle; 
     117 
     118        // setup notify buffer and try to schedule a notification transfer 
     119        fNotifyBufferLength = 64; 
     120        fNotifyBuffer = (uint8 *)malloc(fNotifyBufferLength); 
     121        if (fNotifyBuffer == NULL) { 
     122                TRACE_ALWAYS("out of memory for notify buffer allocation\n"); 
     123                return; 
     124        } 
     125 
     126        if (gUSBModule->queue_interrupt(fNotifyEndpoint, fNotifyBuffer, 
     127                fNotifyBufferLength, _NotifyCallback, this) != B_OK) { 
     128                // we cannot use notifications - hardcode to active connection 
     129                fHasConnection = true; 
     130                fDownstreamSpeed = 1000 * 1000 * 10; // 10Mbps 
     131                fUpstreamSpeed = 1000 * 1000 * 10; // 10Mbps 
     132        } 
    107133 
    108134        if (dataIndex >= config->interface_count) { 
     
    127153 
    128154        fDataInterfaceIndex = dataIndex; 
    129         fNotifyRead = create_sem(0, DRIVER_NAME"_notify_read"); 
    130         if (fNotifyRead < B_OK) { 
     155        fNotifyReadSem = create_sem(0, DRIVER_NAME"_notify_read"); 
     156        if (fNotifyReadSem < B_OK) { 
    131157                TRACE_ALWAYS("failed to create read notify sem\n"); 
    132158                return; 
    133159        } 
    134160 
    135         fNotifyWrite = create_sem(0, DRIVER_NAME"_notify_write"); 
    136         if (fNotifyWrite < B_OK) { 
     161        fNotifyWriteSem = create_sem(0, DRIVER_NAME"_notify_write"); 
     162        if (fNotifyWriteSem < B_OK) { 
    137163                TRACE_ALWAYS("failed to create write notify sem\n"); 
    138                 delete_sem(fNotifyRead); 
    139164                return; 
    140165        } 
     
    146171ECMDevice::~ECMDevice() 
    147172{ 
    148         delete_sem(fNotifyRead); 
    149         delete_sem(fNotifyWrite); 
     173        if (fNotifyReadSem >= B_OK) 
     174                delete_sem(fNotifyReadSem); 
     175        if (fNotifyWriteSem >= B_OK) 
     176                delete_sem(fNotifyWriteSem); 
     177 
     178        gUSBModule->cancel_queued_transfers(fNotifyEndpoint); 
     179        free(fNotifyBuffer); 
    150180} 
    151181 
     
    245275        } 
    246276 
    247         result = acquire_sem_etc(fNotifyRead, 1, B_CAN_INTERRUPT, 0); 
     277        result = acquire_sem_etc(fNotifyReadSem, 1, B_CAN_INTERRUPT, 0); 
    248278        if (result < B_OK) { 
    249279                *numBytes = 0; 
     
    251281        } 
    252282 
    253         if (fStatusRead != B_OK) { 
     283        if (fStatusRead != B_OK && fStatusRead != B_CANCELED) { 
    254284                TRACE_ALWAYS("device status error 0x%08lx\n", fStatusRead); 
    255285                result = gUSBModule->clear_feature(fReadEndpoint, 
     
    282312        } 
    283313 
    284         result = acquire_sem_etc(fNotifyWrite, 1, B_CAN_INTERRUPT, 0); 
     314        result = acquire_sem_etc(fNotifyWriteSem, 1, B_CAN_INTERRUPT, 0); 
    285315        if (result < B_OK) { 
    286316                *numBytes = 0; 
     
    288318        } 
    289319 
    290         if (fStatusWrite != B_OK) { 
     320        if (fStatusWrite != B_OK && fStatusWrite != B_CANCELED) { 
    291321                TRACE_ALWAYS("device status error 0x%08lx\n", fStatusWrite); 
    292322                result = gUSBModule->clear_feature(fWriteEndpoint, 
     
    319349                        return B_OK; 
    320350 
     351#if HAIKU_TARGET_PLATFORM_HAIKU 
     352                case ETHER_SET_LINK_STATE_SEM: 
     353                        fLinkStateChangeSem = *(sem_id *)buffer; 
     354                        return B_OK; 
     355 
     356                case ETHER_GET_LINK_STATE: 
     357                { 
     358                        ether_link_state *state = (ether_link_state *)buffer; 
     359                        state->media = IFM_ETHER | IFM_FULL_DUPLEX 
     360                                | (fHasConnection ? IFM_ACTIVE : 0); 
     361                        state->quality = 1000; 
     362                        state->speed = fDownstreamSpeed / 1000; 
     363                        return B_OK; 
     364                } 
     365#endif 
     366 
    321367                default: 
    322368                        TRACE_ALWAYS("unsupported ioctl %lu\n", op); 
     
    368414        device->fActualLengthRead = actualLength; 
    369415        device->fStatusRead = status; 
    370         release_sem_etc(device->fNotifyRead, 1, B_DO_NOT_RESCHEDULE); 
     416        release_sem_etc(device->fNotifyReadSem, 1, B_DO_NOT_RESCHEDULE); 
    371417} 
    372418 
     
    379425        device->fActualLengthWrite = actualLength; 
    380426        device->fStatusWrite = status; 
    381         release_sem_etc(device->fNotifyWrite, 1, B_DO_NOT_RESCHEDULE); 
    382 
     427        release_sem_etc(device->fNotifyWriteSem, 1, B_DO_NOT_RESCHEDULE); 
     428
     429 
     430 
     431void 
     432ECMDevice::_NotifyCallback(void *cookie, int32 status, void *data, 
     433        uint32 actualLength) 
     434
     435        if (status == B_CANCELED) 
     436                return; 
     437 
     438        ECMDevice *device = (ECMDevice *)cookie; 
     439        if (status == B_OK && actualLength >= sizeof(cdc_notification)) { 
     440                bool linkStateChange = false; 
     441                cdc_notification *notification 
     442                        = (cdc_notification *)device->fNotifyBuffer; 
     443 
     444                switch (notification->notification_code) { 
     445                        case CDC_NOTIFY_NETWORK_CONNECTION: 
     446                                TRACE("connection state change to %d\n", notification->value); 
     447                                device->fHasConnection = notification->value > 0; 
     448                                linkStateChange = true; 
     449                                break; 
     450 
     451                        case CDC_NOTIFY_CONNECTION_SPEED_CHANGE: 
     452                        { 
     453                                if (notification->data_length < sizeof(cdc_connection_speed) 
     454                                        || actualLength < sizeof(cdc_notification) 
     455                                        + sizeof(cdc_connection_speed)) { 
     456                                        TRACE_ALWAYS("not enough data in connection speed change\n"); 
     457                                        break; 
     458                                } 
     459 
     460                                cdc_connection_speed *speed; 
     461                                speed = (cdc_connection_speed *)&notification->data[0]; 
     462                                device->fUpstreamSpeed = speed->upstream_speed; 
     463                                device->fDownstreamSpeed = speed->downstream_speed; 
     464                                device->fHasConnection = true; 
     465                                TRACE("connection speed change to %ld/%ld\n", 
     466                                        speed->downstream_speed, speed->upstream_speed); 
     467                                linkStateChange = true; 
     468                                break; 
     469                        } 
     470 
     471                        default: 
     472                                TRACE_ALWAYS("unsupported notification 0x%02x\n", 
     473                                        notification->notification_code); 
     474                                break; 
     475                } 
     476 
     477                if (linkStateChange && device->fLinkStateChangeSem >= B_OK) 
     478                        release_sem_etc(device->fLinkStateChangeSem, 1, B_DO_NOT_RESCHEDULE); 
     479        } 
     480 
     481        if (status != B_OK) { 
     482                TRACE_ALWAYS("device status error 0x%08lx\n", status); 
     483                if (gUSBModule->clear_feature(device->fNotifyEndpoint, 
     484                        USB_FEATURE_ENDPOINT_HALT) != B_OK) 
     485                        TRACE_ALWAYS("failed to clear halt state\n"); 
     486        } 
     487 
     488        // schedule next notification buffer 
     489        gUSBModule->queue_interrupt(device->fNotifyEndpoint, device->fNotifyBuffer, 
     490                device->fNotifyBufferLength, _NotifyCallback, device); 
     491
  • haiku/trunk/src/add-ons/kernel/drivers/network/usb_ecm/ECMDevice.h

    r25439 r25458  
    3434static  void                            _WriteCallback(void *cookie, int32 status, 
    3535                                                                void *data, uint32 actualLength); 
     36static  void                            _NotifyCallback(void *cookie, int32 status, 
     37                                                                void *data, uint32 actualLength); 
    3638 
    3739                status_t                        _ReadMACAddress(); 
    3840 
     41                // state tracking 
    3942                status_t                        fStatus; 
    4043                bool                            fOpen; 
     
    4245                usb_device                      fDevice; 
    4346 
    44                 uint8                           fMACAddress[6]; 
    45  
     47                // interface and device infos 
    4648                uint8                           fControlInterfaceIndex; 
    4749                uint8                           fDataInterfaceIndex; 
     
    4951                uint16                          fMaxSegmentSize; 
    5052 
    51                 usb_pipe                        fControlEndpoint; 
     53                // pipes for notifications and data io 
     54                usb_pipe                        fNotifyEndpoint; 
    5255                usb_pipe                        fReadEndpoint; 
    5356                usb_pipe                        fWriteEndpoint; 
    5457 
     58                // data stores for async usb transfers 
    5559                uint32                          fActualLengthRead; 
    5660                uint32                          fActualLengthWrite; 
    5761                int32                           fStatusRead; 
    5862                int32                           fStatusWrite; 
    59                 sem_id                          fNotifyRead; 
    60                 sem_id                          fNotifyWrite; 
     63                sem_id                          fNotifyReadSem; 
     64                sem_id                          fNotifyWriteSem; 
     65 
     66                uint8 *                         fNotifyBuffer; 
     67                uint32                          fNotifyBufferLength; 
     68 
     69                // connection data 
     70                sem_id                          fLinkStateChangeSem; 
     71                uint8                           fMACAddress[6]; 
     72                bool                            fHasConnection; 
     73                uint32                          fDownstreamSpeed; 
     74                uint32                          fUpstreamSpeed; 
    6175}; 
    6276