Changeset 75732da in mainline for uspace/drv/vhc/hubops.c


Ignore:
Timestamp:
2010-12-13T07:20:20Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
309dea52
Parents:
84439d7 (diff), 37f7cfe (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge development/ changes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/vhc/hubops.c

    r84439d7 r75732da  
    5959static int on_get_descriptor(struct usbvirt_device *dev,
    6060    usb_device_request_setup_packet_t *request, uint8_t *data);
     61static int on_set_configuration(struct usbvirt_device *dev,
     62    usb_device_request_setup_packet_t *request, uint8_t *data);
    6163static int on_class_request(struct usbvirt_device *dev,
    6264    usb_device_request_setup_packet_t *request, uint8_t *data);
     
    6466    usb_endpoint_t endpoint,
    6567    void *buffer, size_t size, size_t *actual_size);
     68static void set_port_state(hub_port_t *, hub_port_state_t);
     69static void clear_port_status_change_nl(hub_port_t *, uint16_t);
     70static void set_port_state_nl(hub_port_t *, hub_port_state_t);
    6671
    6772/** Hub operations. */
    6873usbvirt_device_ops_t hub_ops = {
    6974        .on_standard_request[USB_DEVREQ_GET_DESCRIPTOR] = on_get_descriptor,
     75        .on_standard_request[USB_DEVREQ_SET_CONFIGURATION] = on_set_configuration,
    7076        .on_class_device_request = on_class_request,
    7177        .on_data = NULL,
     
    8793}
    8894
     95/** Callback for SET_CONFIGURATION request. */
     96int on_set_configuration(struct usbvirt_device *dev,
     97    usb_device_request_setup_packet_t *request, uint8_t *data)
     98{
     99        /* We must suspend power source to all ports. */
     100        size_t i;
     101        for (i = 0; i < HUB_PORT_COUNT; i++) {
     102                hub_port_t *port = &hub_dev.ports[i];
     103               
     104                set_port_state(port, HUB_PORT_STATE_POWERED_OFF);
     105        }
     106       
     107        /* Let the framework handle the rest of the job. */
     108        return EFORWARD;
     109}
     110
     111struct delay_port_state_change {
     112        suseconds_t delay;
     113        hub_port_state_t old_state;
     114        hub_port_state_t new_state;
     115        hub_port_t *port;
     116};
     117
     118static int set_port_state_delayed_fibril(void *arg)
     119{
     120        struct delay_port_state_change *change
     121            = (struct delay_port_state_change *) arg;
     122       
     123        async_usleep(change->delay);
     124       
     125        fibril_mutex_lock(&change->port->guard);
     126        if (change->port->state == change->old_state) {
     127                set_port_state_nl(change->port, change->new_state);
     128        }
     129        fibril_mutex_unlock(&change->port->guard);
     130       
     131        free(change);
     132       
     133        return EOK;
     134}
     135
     136static void set_port_state_delayed(hub_port_t *port,
     137    suseconds_t delay_time,
     138    hub_port_state_t old_state, hub_port_state_t new_state)
     139{
     140        struct delay_port_state_change *change
     141            = malloc(sizeof(struct delay_port_state_change));
     142        change->port = port;
     143        change->delay = delay_time;
     144        change->old_state = old_state;
     145        change->new_state = new_state;
     146        fid_t fibril = fibril_create(set_port_state_delayed_fibril, change);
     147        if (fibril == 0) {
     148                printf("Failed to create fibril\n");
     149                return;
     150        }
     151        fibril_add_ready(fibril);
     152}
     153
    89154/** Change port status and updates status change status fields.
    90155 */
    91 static void set_port_state(hub_port_t *port, hub_port_state_t state)
    92 {
     156void set_port_state(hub_port_t *port, hub_port_state_t state)
     157{
     158        fibril_mutex_lock(&port->guard);
     159        set_port_state_nl(port, state);
     160        fibril_mutex_unlock(&port->guard);
     161}
     162
     163void set_port_state_nl(hub_port_t *port, hub_port_state_t state)
     164{
     165
     166        dprintf(2, "setting port %d state to %d (%c) from %c (change=%u)",
     167            port->index,
     168            state, hub_port_state_as_char(state),
     169            hub_port_state_as_char(port->state),
     170            (unsigned int) port->status_change);
     171       
     172        if (state == HUB_PORT_STATE_POWERED_OFF) {
     173                clear_port_status_change_nl(port, HUB_STATUS_C_PORT_CONNECTION);
     174                clear_port_status_change_nl(port, HUB_STATUS_C_PORT_ENABLE);
     175                clear_port_status_change_nl(port, HUB_STATUS_C_PORT_RESET);
     176        }
     177        if (state == HUB_PORT_STATE_RESUMING) {
     178                set_port_state_delayed(port, 10*1000,
     179                    HUB_PORT_STATE_RESUMING, HUB_PORT_STATE_ENABLED);
     180        }
     181        if (state == HUB_PORT_STATE_RESETTING) {
     182                set_port_state_delayed(port, 10*1000,
     183                    HUB_PORT_STATE_RESETTING, HUB_PORT_STATE_ENABLED);
     184        }
     185        if ((port->state == HUB_PORT_STATE_RESETTING)
     186            && (state == HUB_PORT_STATE_ENABLED)) {
     187                set_port_status_change_nl(port, HUB_STATUS_C_PORT_RESET);
     188        }
     189       
    93190        port->state = state;
    94         if (state == HUB_PORT_STATE_POWERED_OFF) {
    95                 clear_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
    96                 clear_port_status_change(port, HUB_STATUS_C_PORT_ENABLE);
    97                 clear_port_status_change(port, HUB_STATUS_C_PORT_RESET);
    98         }
    99         if (state == HUB_PORT_STATE_RESUMING) {
    100                 async_usleep(10*1000);
    101                 if (port->state == state) {
    102                         set_port_state(port, HUB_PORT_STATE_ENABLED);
    103                 }
    104         }
    105         if (state == HUB_PORT_STATE_RESETTING) {
    106                 async_usleep(10*1000);
    107                 if (port->state == state) {
    108                         set_port_status_change(port, HUB_STATUS_C_PORT_RESET);
    109                         set_port_state(port, HUB_PORT_STATE_ENABLED);
    110                 }
    111         }
    112191}
    113192
     
    122201                } \
    123202        } while (false); \
    124         hub_port_t *portvar = &hub_dev.ports[index]
     203        hub_port_t *portvar = &hub_dev.ports[index-1]
    125204
    126205
     
    134213        _GET_PORT(port, portindex);
    135214       
     215        fibril_mutex_lock(&port->guard);
     216        int rc = ENOTSUP;
     217
    136218        switch (feature) {
    137219                case USB_HUB_FEATURE_PORT_ENABLE:
    138220                        if ((port->state != HUB_PORT_STATE_NOT_CONFIGURED)
    139221                            && (port->state != HUB_PORT_STATE_POWERED_OFF)) {
    140                                 set_port_state(port, HUB_PORT_STATE_DISABLED);
    141                         }
    142                         return EOK;
     222                                set_port_state_nl(port, HUB_PORT_STATE_DISABLED);
     223                        }
     224                        rc = EOK;
     225                        break;
    143226               
    144227                case USB_HUB_FEATURE_PORT_SUSPEND:
    145228                        if (port->state != HUB_PORT_STATE_SUSPENDED) {
    146                                 return EOK;
    147                         }
    148                         set_port_state(port, HUB_PORT_STATE_RESUMING);
    149                         return EOK;
     229                                rc = EOK;
     230                                break;
     231                        }
     232                        set_port_state_nl(port, HUB_PORT_STATE_RESUMING);
     233                        rc = EOK;
     234                        break;
    150235                       
    151236                case USB_HUB_FEATURE_PORT_POWER:
    152237                        if (port->state != HUB_PORT_STATE_NOT_CONFIGURED) {
    153                                 set_port_state(port, HUB_PORT_STATE_POWERED_OFF);
    154                         }
    155                         return EOK;
     238                                set_port_state_nl(port, HUB_PORT_STATE_POWERED_OFF);
     239                        }
     240                        rc = EOK;
     241                        break;
    156242               
    157243                case USB_HUB_FEATURE_C_PORT_CONNECTION:
    158                         clear_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
    159                         return EOK;
     244                        clear_port_status_change_nl(port, HUB_STATUS_C_PORT_CONNECTION);
     245                        rc = EOK;
     246                        break;
    160247               
    161248                case USB_HUB_FEATURE_C_PORT_ENABLE:
    162                         clear_port_status_change(port, HUB_STATUS_C_PORT_ENABLE);
    163                         return EOK;
     249                        clear_port_status_change_nl(port, HUB_STATUS_C_PORT_ENABLE);
     250                        rc = EOK;
     251                        break;
    164252               
    165253                case USB_HUB_FEATURE_C_PORT_SUSPEND:
    166                         clear_port_status_change(port, HUB_STATUS_C_PORT_SUSPEND);
    167                         return EOK;
     254                        clear_port_status_change_nl(port, HUB_STATUS_C_PORT_SUSPEND);
     255                        rc = EOK;
     256                        break;
    168257                       
    169258                case USB_HUB_FEATURE_C_PORT_OVER_CURRENT:
    170                         clear_port_status_change(port, HUB_STATUS_C_PORT_OVER_CURRENT);
    171                         return EOK;
    172         }
    173        
     259                        clear_port_status_change_nl(port, HUB_STATUS_C_PORT_OVER_CURRENT);
     260                        rc = EOK;
     261                        break;
     262
     263                case USB_HUB_FEATURE_C_PORT_RESET:
     264                        clear_port_status_change_nl(port, HUB_STATUS_C_PORT_RESET);
     265                        rc = EOK;
     266                        break;
     267        }
     268       
     269        fibril_mutex_unlock(&port->guard);
     270
     271        return rc;
     272}
     273
     274static int get_bus_state(uint16_t portindex)
     275{
    174276        return ENOTSUP;
    175277}
    176278
    177 static int get_bus_state(uint16_t portindex)
    178 {
    179         return ENOTSUP;
    180 }
    181 
    182 static int get_hub_descriptor(uint8_t descriptor_type,
    183     uint8_t descriptor_index, uint16_t length)
    184 {
     279static int get_hub_descriptor(struct usbvirt_device *dev,
     280    uint8_t descriptor_index,
     281    uint8_t descriptor_type, uint16_t length)
     282{
     283        if (descriptor_type == USB_DESCTYPE_HUB) {
     284                int rc = dev->control_transfer_reply(dev, 0,
     285                    &hub_descriptor, hub_descriptor.length);
     286
     287                return rc;
     288
     289        }
     290
    185291        return ENOTSUP;
    186292}
     
    198304        _GET_PORT(port, portindex);
    199305       
     306        fibril_mutex_lock(&port->guard);
     307
    200308        uint32_t status;
    201309        status = MAKE_BYTE(
     
    225333        status |= (port->status_change << 16);
    226334       
     335        fibril_mutex_unlock(&port->guard);
     336
     337        dprintf(2, "GetPortStatus(port=%d, status=%u)\n", (int)portindex,
     338            (unsigned int) status);
    227339        return virthub_dev.control_transfer_reply(&virthub_dev, 0, &status, 4);
    228340}
     
    238350        _GET_PORT(port, portindex);
    239351       
     352        fibril_mutex_lock(&port->guard);
     353
     354        int rc = ENOTSUP;
     355
    240356        switch (feature) {
    241357                case USB_HUB_FEATURE_PORT_RESET:
    242358                        if (port->state != HUB_PORT_STATE_POWERED_OFF) {
    243                                 set_port_state(port, HUB_PORT_STATE_RESETTING);
    244                         }
    245                         return EOK;
     359                                set_port_state_nl(port, HUB_PORT_STATE_RESETTING);
     360                        }
     361                        rc = EOK;
     362                        break;
    246363               
    247364                case USB_HUB_FEATURE_PORT_SUSPEND:
    248365                        if (port->state == HUB_PORT_STATE_ENABLED) {
    249                                 set_port_state(port, HUB_PORT_STATE_SUSPENDED);
    250                         }
    251                         return EOK;
     366                                set_port_state_nl(port, HUB_PORT_STATE_SUSPENDED);
     367                        }
     368                        rc = EOK;
     369                        break;
    252370               
    253371                case USB_HUB_FEATURE_PORT_POWER:
    254372                        if (port->state == HUB_PORT_STATE_POWERED_OFF) {
    255                                 set_port_state(port, HUB_PORT_STATE_DISCONNECTED);
    256                         }
    257                         return EOK;
    258         }
    259         return ENOTSUP;
     373                                set_port_state_nl(port, HUB_PORT_STATE_DISCONNECTED);
     374                        }
     375                        rc = EOK;
     376                        break;
     377        }
     378
     379        fibril_mutex_unlock(&port->guard);
     380        return rc;
    260381}
    261382
     
    267388    usb_device_request_setup_packet_t *request, uint8_t *data)
    268389{       
    269         dprintf(2, "hub class request (%d)\n", (int) request->request);
     390        dprintf(2, "hub class request (%d)", (int) request->request);
    270391       
    271392        uint8_t recipient = request->request_type & 31;
     
    298419                       
    299420                case USB_HUB_REQUEST_GET_DESCRIPTOR:
    300                         return get_hub_descriptor(request->value_low,
     421                        return get_hub_descriptor(dev, request->value_low,
    301422                            request->value_high, request->length);
    302423                       
     
    316437                       
    317438                default:
     439                        dprintf(0, "WARN: unknown request (%d)!\n",
     440                            request->request);
    318441                        break;
    319442        }
     
    325448}
    326449
     450void clear_port_status_change_nl(hub_port_t *port, uint16_t change)
     451{
     452        port->status_change &= (~change);
     453        dprintf(2, "cleared port %d status change %d (%u)", port->index,
     454            (int)change, (unsigned int) port->status_change);
     455}
     456
     457void set_port_status_change_nl(hub_port_t *port, uint16_t change)
     458{
     459        port->status_change |= change;
     460        dprintf(2, "set port %d status change %d (%u)", port->index,
     461            (int)change, (unsigned int) port->status_change);
     462
     463}
     464
    327465void clear_port_status_change(hub_port_t *port, uint16_t change)
    328466{
    329         port->status_change &= (~change);
     467        fibril_mutex_lock(&port->guard);
     468        clear_port_status_change_nl(port, change);
     469        fibril_mutex_unlock(&port->guard);
    330470}
    331471
    332472void set_port_status_change(hub_port_t *port, uint16_t change)
    333473{
    334         port->status_change |= change;
     474        fibril_mutex_lock(&port->guard);
     475        set_port_status_change_nl(port, change);
     476        fibril_mutex_unlock(&port->guard);
    335477}
    336478
     
    350492                hub_port_t *port = &hub_dev.ports[i];
    351493               
     494                fibril_mutex_lock(&port->guard);
    352495                if (port->status_change != 0) {
    353496                        change_map |= (1 << (i + 1));
    354497                }
     498                fibril_mutex_unlock(&port->guard);
    355499        }
    356500       
Note: See TracChangeset for help on using the changeset viewer.