Ignore:
File:
1 edited

Legend:

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

    r56b962d r1e32a63  
    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);
     71
     72/** Standard USB requests. */
     73static usbvirt_standard_device_request_ops_t standard_request_ops = {
     74        .on_get_status = NULL,
     75        .on_clear_feature = NULL,
     76        .on_set_feature = NULL,
     77        .on_set_address = NULL,
     78        .on_get_descriptor = on_get_descriptor,
     79        .on_set_descriptor = NULL,
     80        .on_get_configuration = NULL,
     81        .on_set_configuration = on_set_configuration,
     82        .on_get_interface = NULL,
     83        .on_set_interface = NULL,
     84        .on_synch_frame = NULL
     85};
    6686
    6787/** Hub operations. */
    6888usbvirt_device_ops_t hub_ops = {
    69         .on_standard_request[USB_DEVREQ_GET_DESCRIPTOR] = on_get_descriptor,
     89        .standard_request_ops = &standard_request_ops,
    7090        .on_class_device_request = on_class_request,
    7191        .on_data = NULL,
     
    87107}
    88108
     109/** Callback for SET_CONFIGURATION request. */
     110int on_set_configuration(struct usbvirt_device *dev,
     111    usb_device_request_setup_packet_t *request, uint8_t *data)
     112{
     113        /* We must suspend power source to all ports. */
     114        size_t i;
     115        for (i = 0; i < HUB_PORT_COUNT; i++) {
     116                hub_port_t *port = &hub_dev.ports[i];
     117               
     118                set_port_state(port, HUB_PORT_STATE_POWERED_OFF);
     119        }
     120       
     121        /* Let the framework handle the rest of the job. */
     122        return EFORWARD;
     123}
     124
     125struct delay_port_state_change {
     126        suseconds_t delay;
     127        hub_port_state_t old_state;
     128        hub_port_state_t new_state;
     129        hub_port_t *port;
     130};
     131
     132static int set_port_state_delayed_fibril(void *arg)
     133{
     134        struct delay_port_state_change *change
     135            = (struct delay_port_state_change *) arg;
     136       
     137        async_usleep(change->delay);
     138       
     139        fibril_mutex_lock(&change->port->guard);
     140        if (change->port->state == change->old_state) {
     141                set_port_state_nl(change->port, change->new_state);
     142        }
     143        fibril_mutex_unlock(&change->port->guard);
     144       
     145        free(change);
     146       
     147        return EOK;
     148}
     149
     150static void set_port_state_delayed(hub_port_t *port,
     151    suseconds_t delay_time,
     152    hub_port_state_t old_state, hub_port_state_t new_state)
     153{
     154        struct delay_port_state_change *change
     155            = malloc(sizeof(struct delay_port_state_change));
     156        change->port = port;
     157        change->delay = delay_time;
     158        change->old_state = old_state;
     159        change->new_state = new_state;
     160        fid_t fibril = fibril_create(set_port_state_delayed_fibril, change);
     161        if (fibril == 0) {
     162                printf("Failed to create fibril\n");
     163                return;
     164        }
     165        fibril_add_ready(fibril);
     166}
     167
    89168/** Change port status and updates status change status fields.
    90169 */
    91 static void set_port_state(hub_port_t *port, hub_port_state_t state)
    92 {
     170void set_port_state(hub_port_t *port, hub_port_state_t state)
     171{
     172        fibril_mutex_lock(&port->guard);
     173        set_port_state_nl(port, state);
     174        fibril_mutex_unlock(&port->guard);
     175}
     176
     177void set_port_state_nl(hub_port_t *port, hub_port_state_t state)
     178{
     179
     180        dprintf(2, "setting port %d state to %d (%c) from %c (change=%u)",
     181            port->index,
     182            state, hub_port_state_as_char(state),
     183            hub_port_state_as_char(port->state),
     184            (unsigned int) port->status_change);
     185       
     186        if (state == HUB_PORT_STATE_POWERED_OFF) {
     187                clear_port_status_change_nl(port, HUB_STATUS_C_PORT_CONNECTION);
     188                clear_port_status_change_nl(port, HUB_STATUS_C_PORT_ENABLE);
     189                clear_port_status_change_nl(port, HUB_STATUS_C_PORT_RESET);
     190        }
     191        if (state == HUB_PORT_STATE_RESUMING) {
     192                set_port_state_delayed(port, 10*1000,
     193                    HUB_PORT_STATE_RESUMING, HUB_PORT_STATE_ENABLED);
     194        }
     195        if (state == HUB_PORT_STATE_RESETTING) {
     196                set_port_state_delayed(port, 10*1000,
     197                    HUB_PORT_STATE_RESETTING, HUB_PORT_STATE_ENABLED);
     198        }
     199        if ((port->state == HUB_PORT_STATE_RESETTING)
     200            && (state == HUB_PORT_STATE_ENABLED)) {
     201                set_port_status_change_nl(port, HUB_STATUS_C_PORT_RESET);
     202        }
     203       
    93204        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         }
    112205}
    113206
     
    122215                } \
    123216        } while (false); \
    124         hub_port_t *portvar = &hub_dev.ports[index]
     217        hub_port_t *portvar = &hub_dev.ports[index-1]
    125218
    126219
     
    134227        _GET_PORT(port, portindex);
    135228       
     229        fibril_mutex_lock(&port->guard);
     230        int rc = ENOTSUP;
     231
    136232        switch (feature) {
    137233                case USB_HUB_FEATURE_PORT_ENABLE:
    138234                        if ((port->state != HUB_PORT_STATE_NOT_CONFIGURED)
    139235                            && (port->state != HUB_PORT_STATE_POWERED_OFF)) {
    140                                 set_port_state(port, HUB_PORT_STATE_DISABLED);
    141                         }
    142                         return EOK;
     236                                set_port_state_nl(port, HUB_PORT_STATE_DISABLED);
     237                        }
     238                        rc = EOK;
     239                        break;
    143240               
    144241                case USB_HUB_FEATURE_PORT_SUSPEND:
    145242                        if (port->state != HUB_PORT_STATE_SUSPENDED) {
    146                                 return EOK;
    147                         }
    148                         set_port_state(port, HUB_PORT_STATE_RESUMING);
    149                         return EOK;
     243                                rc = EOK;
     244                                break;
     245                        }
     246                        set_port_state_nl(port, HUB_PORT_STATE_RESUMING);
     247                        rc = EOK;
     248                        break;
    150249                       
    151250                case USB_HUB_FEATURE_PORT_POWER:
    152251                        if (port->state != HUB_PORT_STATE_NOT_CONFIGURED) {
    153                                 set_port_state(port, HUB_PORT_STATE_POWERED_OFF);
    154                         }
    155                         return EOK;
     252                                set_port_state_nl(port, HUB_PORT_STATE_POWERED_OFF);
     253                        }
     254                        rc = EOK;
     255                        break;
    156256               
    157257                case USB_HUB_FEATURE_C_PORT_CONNECTION:
    158                         clear_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
    159                         return EOK;
     258                        clear_port_status_change_nl(port, HUB_STATUS_C_PORT_CONNECTION);
     259                        rc = EOK;
     260                        break;
    160261               
    161262                case USB_HUB_FEATURE_C_PORT_ENABLE:
    162                         clear_port_status_change(port, HUB_STATUS_C_PORT_ENABLE);
    163                         return EOK;
     263                        clear_port_status_change_nl(port, HUB_STATUS_C_PORT_ENABLE);
     264                        rc = EOK;
     265                        break;
    164266               
    165267                case USB_HUB_FEATURE_C_PORT_SUSPEND:
    166                         clear_port_status_change(port, HUB_STATUS_C_PORT_SUSPEND);
    167                         return EOK;
     268                        clear_port_status_change_nl(port, HUB_STATUS_C_PORT_SUSPEND);
     269                        rc = EOK;
     270                        break;
    168271                       
    169272                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        
     273                        clear_port_status_change_nl(port, HUB_STATUS_C_PORT_OVER_CURRENT);
     274                        rc = EOK;
     275                        break;
     276
     277                case USB_HUB_FEATURE_C_PORT_RESET:
     278                        clear_port_status_change_nl(port, HUB_STATUS_C_PORT_RESET);
     279                        rc = EOK;
     280                        break;
     281        }
     282       
     283        fibril_mutex_unlock(&port->guard);
     284
     285        return rc;
     286}
     287
     288static int get_bus_state(uint16_t portindex)
     289{
    174290        return ENOTSUP;
    175291}
    176292
    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 {
     293static int get_hub_descriptor(struct usbvirt_device *dev,
     294    uint8_t descriptor_index,
     295    uint8_t descriptor_type, uint16_t length)
     296{
     297        if (descriptor_type == USB_DESCTYPE_HUB) {
     298                int rc = dev->control_transfer_reply(dev, 0,
     299                    &hub_descriptor, hub_descriptor.length);
     300
     301                return rc;
     302
     303        }
     304
    185305        return ENOTSUP;
    186306}
     
    198318        _GET_PORT(port, portindex);
    199319       
     320        fibril_mutex_lock(&port->guard);
     321
    200322        uint32_t status;
    201323        status = MAKE_BYTE(
     
    225347        status |= (port->status_change << 16);
    226348       
     349        fibril_mutex_unlock(&port->guard);
     350
     351        dprintf(2, "GetPortStatus(port=%d, status=%u)\n", (int)portindex,
     352            (unsigned int) status);
    227353        return virthub_dev.control_transfer_reply(&virthub_dev, 0, &status, 4);
    228354}
     
    238364        _GET_PORT(port, portindex);
    239365       
     366        fibril_mutex_lock(&port->guard);
     367
     368        int rc = ENOTSUP;
     369
    240370        switch (feature) {
    241371                case USB_HUB_FEATURE_PORT_RESET:
    242372                        if (port->state != HUB_PORT_STATE_POWERED_OFF) {
    243                                 set_port_state(port, HUB_PORT_STATE_RESETTING);
    244                         }
    245                         return EOK;
     373                                set_port_state_nl(port, HUB_PORT_STATE_RESETTING);
     374                        }
     375                        rc = EOK;
     376                        break;
    246377               
    247378                case USB_HUB_FEATURE_PORT_SUSPEND:
    248379                        if (port->state == HUB_PORT_STATE_ENABLED) {
    249                                 set_port_state(port, HUB_PORT_STATE_SUSPENDED);
    250                         }
    251                         return EOK;
     380                                set_port_state_nl(port, HUB_PORT_STATE_SUSPENDED);
     381                        }
     382                        rc = EOK;
     383                        break;
    252384               
    253385                case USB_HUB_FEATURE_PORT_POWER:
    254386                        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;
     387                                set_port_state_nl(port, HUB_PORT_STATE_DISCONNECTED);
     388                        }
     389                        rc = EOK;
     390                        break;
     391        }
     392
     393        fibril_mutex_unlock(&port->guard);
     394        return rc;
    260395}
    261396
     
    267402    usb_device_request_setup_packet_t *request, uint8_t *data)
    268403{       
    269         dprintf(2, "hub class request (%d)\n", (int) request->request);
     404        dprintf(2, "hub class request (%d)", (int) request->request);
    270405       
    271406        uint8_t recipient = request->request_type & 31;
     
    298433                       
    299434                case USB_HUB_REQUEST_GET_DESCRIPTOR:
    300                         return get_hub_descriptor(request->value_low,
     435                        return get_hub_descriptor(dev, request->value_low,
    301436                            request->value_high, request->length);
    302437                       
     
    316451                       
    317452                default:
     453                        dprintf(0, "WARN: unknown request (%d)!\n",
     454                            request->request);
    318455                        break;
    319456        }
     
    325462}
    326463
     464void clear_port_status_change_nl(hub_port_t *port, uint16_t change)
     465{
     466        port->status_change &= (~change);
     467        dprintf(2, "cleared port %d status change %d (%u)", port->index,
     468            (int)change, (unsigned int) port->status_change);
     469}
     470
     471void set_port_status_change_nl(hub_port_t *port, uint16_t change)
     472{
     473        port->status_change |= change;
     474        dprintf(2, "set port %d status change %d (%u)", port->index,
     475            (int)change, (unsigned int) port->status_change);
     476
     477}
     478
    327479void clear_port_status_change(hub_port_t *port, uint16_t change)
    328480{
    329         port->status_change &= (~change);
     481        fibril_mutex_lock(&port->guard);
     482        clear_port_status_change_nl(port, change);
     483        fibril_mutex_unlock(&port->guard);
    330484}
    331485
    332486void set_port_status_change(hub_port_t *port, uint16_t change)
    333487{
    334         port->status_change |= change;
     488        fibril_mutex_lock(&port->guard);
     489        set_port_status_change_nl(port, change);
     490        fibril_mutex_unlock(&port->guard);
    335491}
    336492
     
    350506                hub_port_t *port = &hub_dev.ports[i];
    351507               
     508                fibril_mutex_lock(&port->guard);
    352509                if (port->status_change != 0) {
    353510                        change_map |= (1 << (i + 1));
    354511                }
     512                fibril_mutex_unlock(&port->guard);
    355513        }
    356514       
Note: See TracChangeset for help on using the changeset viewer.