Changeset 7feeb84 in mainline


Ignore:
Timestamp:
2010-12-13T14:25:49Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
76daaf9f
Parents:
8f8ae1fd
Message:

usbvirt: more flexible callbacks for endpoint zero

Location:
uspace
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/virtusbkbd/virtusbkbd.c

    r8f8ae1fd r7feeb84  
    7676}
    7777
    78 static int on_class_request(struct usbvirt_device *dev,
    79     usb_device_request_setup_packet_t *request, uint8_t *data)
    80 {       
    81         printf("%s: class request (%d)\n", NAME, (int) request->request);
    82        
    83         return EOK;
    84 }
    8578
    8679/** Compares current and last status of pressed keys.
     
    138131}
    139132
     133static usbvirt_control_transfer_handler_t endpoint_zero_handlers[] = {
     134        {
     135                .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(
     136                    USB_DIRECTION_IN,
     137                    USBVIRT_REQUEST_TYPE_STANDARD,
     138                    USBVIRT_REQUEST_RECIPIENT_DEVICE),
     139                .request = USB_DEVREQ_GET_DESCRIPTOR,
     140                .callback = stdreq_on_get_descriptor
     141        },
     142        {
     143                .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(
     144                    USB_DIRECTION_IN,
     145                    USBVIRT_REQUEST_TYPE_CLASS,
     146                    USBVIRT_REQUEST_RECIPIENT_DEVICE),
     147                .request = USB_DEVREQ_GET_DESCRIPTOR,
     148                .callback = stdreq_on_get_descriptor
     149        },
     150        USBVIRT_CONTROL_TRANSFER_HANDLER_LAST
     151};
    140152
    141153/** Keyboard callbacks.
     
    143155 */
    144156static usbvirt_device_ops_t keyboard_ops = {
    145         .on_standard_request[USB_DEVREQ_GET_DESCRIPTOR]
    146             = stdreq_on_get_descriptor,
    147         .on_class_device_request = on_class_request,
     157        .control_transfer_handlers = endpoint_zero_handlers,
    148158        .on_data = on_incoming_data,
    149159        .on_data_request = on_request_for_data
  • uspace/drv/vhc/hubops.c

    r8f8ae1fd r7feeb84  
    6161static int on_set_configuration(struct usbvirt_device *dev,
    6262    usb_device_request_setup_packet_t *request, uint8_t *data);
    63 static int on_class_request(struct usbvirt_device *dev,
    64     usb_device_request_setup_packet_t *request, uint8_t *data);
    6563static int on_data_request(struct usbvirt_device *dev,
    6664    usb_endpoint_t endpoint,
     
    6967static void clear_port_status_change_nl(hub_port_t *, uint16_t);
    7068static void set_port_state_nl(hub_port_t *, hub_port_state_t);
    71 
    72 /** Hub operations. */
    73 usbvirt_device_ops_t hub_ops = {
    74         .on_standard_request[USB_DEVREQ_GET_DESCRIPTOR] = on_get_descriptor,
    75         .on_standard_request[USB_DEVREQ_SET_CONFIGURATION] = on_set_configuration,
    76         .on_class_device_request = on_class_request,
    77         .on_data = NULL,
    78         .on_data_request = on_data_request
    79 };
     69static int get_port_status(uint16_t portindex);
    8070
    8171/** Callback for GET_DESCRIPTOR request. */
     
    300290}
    301291
    302 static int get_port_status(uint16_t portindex)
     292int get_port_status(uint16_t portindex)
    303293{
    304294        _GET_PORT(port, portindex);
     
    384374
    385375
    386 /** Callback for class request. */
    387 static int on_class_request(struct usbvirt_device *dev,
    388     usb_device_request_setup_packet_t *request, uint8_t *data)
    389 {       
    390         dprintf(2, "hub class request (%d)", (int) request->request);
    391        
    392         uint8_t recipient = request->request_type & 31;
    393         uint8_t direction = request->request_type >> 7;
    394        
    395 #define _VERIFY(cond) \
    396         do { \
    397                 if (!(cond)) { \
    398                         dprintf(0, "WARN: invalid class request (%s not met).\n", \
    399                             NAME, #cond); \
    400                         return EINVAL; \
    401                 } \
    402         } while (0)
    403        
    404         switch (request->request) {
    405                 case USB_HUB_REQUEST_CLEAR_FEATURE:
    406                         _VERIFY(direction == 0);
    407                         _VERIFY(request->length == 0);
    408                         if (recipient == 0) {
    409                                 _VERIFY(request->index == 0);
    410                                 return clear_hub_feature(request->value);
    411                         } else {
    412                                 _VERIFY(recipient == 3);
    413                                 return clear_port_feature(request->value,
    414                                     request->index);
    415                         }
    416                        
    417                 case USB_HUB_REQUEST_GET_STATE:
    418                         return get_bus_state(request->index);
    419                        
    420                 case USB_HUB_REQUEST_GET_DESCRIPTOR:
    421                         return get_hub_descriptor(dev, request->value_low,
    422                             request->value_high, request->length);
    423                        
    424                 case USB_HUB_REQUEST_GET_STATUS:
    425                         if (recipient == 0) {
    426                                 return get_hub_status();
    427                         } else {
    428                                 return get_port_status(request->index);
    429                         }
    430                        
    431                 case USB_HUB_REQUEST_SET_FEATURE:
    432                         if (recipient == 0) {
    433                                 return set_hub_feature(request->value);
    434                         } else {
    435                                 return set_port_feature(request->value, request->index);
    436                         }
    437                        
    438                 default:
    439                         dprintf(0, "WARN: unknown request (%d)!\n",
    440                             request->request);
    441                         break;
    442         }
    443        
    444 #undef _VERIFY 
    445 
    446 
    447         return EOK;
    448 }
    449 
    450376void clear_port_status_change_nl(hub_port_t *port, uint16_t change)
    451377{
     
    509435
    510436
     437
     438static int req_clear_hub_feature(usbvirt_device_t *dev,
     439    usb_device_request_setup_packet_t *request,
     440    uint8_t *data)
     441{
     442        return clear_hub_feature(request->value);
     443}
     444
     445static int req_clear_port_feature(usbvirt_device_t *dev,
     446    usb_device_request_setup_packet_t *request,
     447    uint8_t *data)
     448{
     449        return clear_port_feature(request->value, request->index);
     450}
     451
     452static int req_get_bus_state(usbvirt_device_t *dev,
     453    usb_device_request_setup_packet_t *request,
     454    uint8_t *data)
     455{
     456        return get_bus_state(request->index);
     457}
     458
     459static int req_get_hub_descriptor(usbvirt_device_t *dev,
     460    usb_device_request_setup_packet_t *request,
     461    uint8_t *data)
     462{
     463        return get_hub_descriptor(dev, request->value_low,
     464            request->value_high, request->length);
     465}
     466
     467static int req_get_hub_status(usbvirt_device_t *dev,
     468    usb_device_request_setup_packet_t *request,
     469    uint8_t *data)
     470{
     471        return get_hub_status();
     472}
     473
     474static int req_get_port_status(usbvirt_device_t *dev,
     475    usb_device_request_setup_packet_t *request,
     476    uint8_t *data)
     477{
     478        return get_port_status(request->index);
     479}
     480
     481static int req_set_hub_feature(usbvirt_device_t *dev,
     482    usb_device_request_setup_packet_t *request,
     483    uint8_t *data)
     484{
     485        return set_hub_feature(request->value);
     486}
     487
     488static int req_set_port_feature(usbvirt_device_t *dev,
     489    usb_device_request_setup_packet_t *request,
     490    uint8_t *data)
     491{
     492        return set_port_feature(request->value, request->index);
     493}
     494
     495#define CLASS_REQ_IN(recipient) \
     496        USBVIRT_MAKE_CONTROL_REQUEST_TYPE(USB_DIRECTION_IN, \
     497        USBVIRT_REQUEST_TYPE_CLASS, recipient)
     498#define CLASS_REQ_OUT(recipient) \
     499        USBVIRT_MAKE_CONTROL_REQUEST_TYPE(USB_DIRECTION_OUT, \
     500        USBVIRT_REQUEST_TYPE_CLASS, recipient)
     501
     502#define REC_OTHER USBVIRT_REQUEST_RECIPIENT_OTHER
     503#define REC_DEVICE USBVIRT_REQUEST_RECIPIENT_DEVICE
     504#define DIR_IN USB_DIRECTION_IN
     505#define DIR_OUT USB_DIRECTION_OUT
     506
     507#define CLASS_REQ(direction, recipient, req) \
     508        .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \
     509            USBVIRT_REQUEST_TYPE_CLASS, recipient), \
     510        .request = req
     511
     512#define STD_REQ(direction, recipient, req) \
     513        .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \
     514            USBVIRT_REQUEST_TYPE_STANDARD, recipient), \
     515        .request = req
     516
     517/** Hub operations on control endpoint zero. */
     518static usbvirt_control_transfer_handler_t endpoint_zero_handlers[] = {
     519        {
     520                STD_REQ(DIR_OUT, REC_DEVICE, USB_DEVREQ_SET_CONFIGURATION),
     521                .callback = on_set_configuration
     522        },
     523        {
     524                STD_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
     525                .callback = on_get_descriptor
     526        },
     527        {
     528                CLASS_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
     529                .callback = on_get_descriptor
     530        },
     531        {
     532                CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATUS),
     533                .callback = req_get_port_status
     534        },
     535        {
     536                CLASS_REQ(DIR_OUT, REC_DEVICE, USB_HUB_REQUEST_CLEAR_FEATURE),
     537                .callback = req_clear_hub_feature
     538        },
     539        {
     540                CLASS_REQ(DIR_OUT, REC_OTHER, USB_HUB_REQUEST_CLEAR_FEATURE),
     541                .callback = req_clear_port_feature
     542        },
     543        {
     544                CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATE),
     545                .callback = req_get_bus_state
     546        },
     547        {
     548                CLASS_REQ(DIR_IN, REC_DEVICE, USB_HUB_REQUEST_GET_DESCRIPTOR),
     549                .callback = req_get_hub_descriptor
     550        },
     551        {
     552                CLASS_REQ(DIR_IN, REC_DEVICE, USB_HUB_REQUEST_GET_STATUS),
     553                .callback = req_get_hub_status
     554        },
     555        {
     556                CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATUS),
     557                .callback = req_get_port_status
     558        },
     559        {
     560                CLASS_REQ(DIR_OUT, REC_DEVICE, USB_HUB_REQUEST_SET_FEATURE),
     561                .callback = req_set_hub_feature
     562        },
     563        {
     564                CLASS_REQ(DIR_OUT, REC_OTHER, USB_HUB_REQUEST_SET_FEATURE),
     565                .callback = req_set_port_feature
     566        },
     567        USBVIRT_CONTROL_TRANSFER_HANDLER_LAST
     568};
     569
     570
     571/** Hub operations. */
     572usbvirt_device_ops_t hub_ops = {
     573        .control_transfer_handlers = endpoint_zero_handlers,
     574        .on_data = NULL,
     575        .on_data_request = on_data_request
     576};
     577
    511578/**
    512579 * @}
  • uspace/lib/usbvirt/include/usbvirt/device.h

    r8f8ae1fd r7feeb84  
    4040#include <usb/devreq.h>
    4141
     42typedef enum {
     43        USBVIRT_REQUEST_TYPE_STANDARD = 0,
     44        USBVIRT_REQUEST_TYPE_CLASS = 1
     45} usbvirt_request_type_t;
     46
     47typedef enum {
     48        USBVIRT_REQUEST_RECIPIENT_DEVICE = 0,
     49        USBVIRT_REQUEST_RECIPIENT_INTERFACE = 1,
     50        USBVIRT_REQUEST_RECIPIENT_ENDPOINT = 2,
     51        USBVIRT_REQUEST_RECIPIENT_OTHER = 3
     52} usbvirt_request_recipient_t;
     53
    4254typedef struct usbvirt_device usbvirt_device_t;
    4355struct usbvirt_control_transfer;
     
    4759        uint8_t *data);
    4860
     61typedef int (*usbvirt_control_request_callback_t)(usbvirt_device_t *dev,
     62        usb_device_request_setup_packet_t *request,
     63        uint8_t *data);
     64
     65typedef struct {
     66        uint8_t request_type;
     67        uint8_t request;
     68        usbvirt_control_request_callback_t callback;
     69} usbvirt_control_transfer_handler_t;
     70
     71#define USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, type, recipient) \
     72        ((((direction) == USB_DIRECTION_IN) ? 1 : 0) << 7) \
     73        | (((type) & 3) << 5) \
     74        | (((recipient) & 31))
     75
     76#define USBVIRT_CONTROL_TRANSFER_HANDLER_LAST { 0, 0, NULL }
     77
    4978/** Device operations. */
    5079typedef struct {
    51         /** Callbacks for standard device requests.
    52          * The callbacks are indexed by usb_stddevreq_t enum.
    53          */
    54         usbvirt_on_device_request_t on_standard_request[USB_DEVREQ_LAST_STD];
    55         /** Callback for class-specific USB request. */
    56         usbvirt_on_device_request_t on_class_device_request;
    57        
     80        /** Callbacks for transfers over control pipe zero. */
     81        usbvirt_control_transfer_handler_t *control_transfer_handlers;
     82
    5883        int (*on_control_transfer)(usbvirt_device_t *dev,
    5984            usb_endpoint_t endpoint, struct usbvirt_control_transfer *transfer);
  • uspace/lib/usbvirt/src/ctrlpipe.c

    r8f8ae1fd r7feeb84  
    3737#include "private.h"
    3838
    39 #define REQUEST_TYPE_STANDARD 0
    40 #define REQUEST_TYPE_CLASS 1
     39/** Compares handler type with request packet type.
     40 *
     41 * @param handler Handler.
     42 * @param request_packet Request packet.
     43 * @return Whether handler can serve this packet.
     44 */
     45static bool is_suitable_handler(usbvirt_control_transfer_handler_t *handler,
     46    usb_device_request_setup_packet_t *request_packet)
     47{
     48        return (
     49            (handler->request_type == request_packet->request_type)
     50            && (handler->request == request_packet->request));
    4151
    42 #define GET_MIDBITS_MASK(size, shift) \
    43         (((1 << size) - 1) << shift)
    44 #define GET_MIDBITS(value, size, shift) \
    45         ((value & GET_MIDBITS_MASK(size, shift)) >> shift)
     52}
     53
     54/** Find suitable transfer handler for given request packet.
     55 *
     56 * @param handlers Array of available handlers.
     57 * @param request_packet Request SETUP packet.
     58 * @return Handler or NULL.
     59 */
     60static usbvirt_control_transfer_handler_t *find_handler(
     61    usbvirt_control_transfer_handler_t *handlers,
     62    usb_device_request_setup_packet_t *request_packet)
     63{
     64        if (handlers == NULL) {
     65                return NULL;
     66        }
     67
     68        while (handlers->callback != NULL) {
     69                if (is_suitable_handler(handlers, request_packet)) {
     70                        return handlers;
     71                }
     72                handlers++;
     73        }
     74
     75        return NULL;
     76}
    4677
    4778
    48 static const char *str_request_type(int type)
    49 {
    50         switch (type) {
    51                 case REQUEST_TYPE_STANDARD:
    52                         return "standard";
    53                 case REQUEST_TYPE_CLASS:
    54                         return "class";
    55                 default:
    56                         return "unknown";
    57         }
    58 }
    59 
    60 /** Tell request type.
    61  * By type is meant either standard, class, vendor or other.
    62  */
    63 static int request_get_type(uint8_t request_type)
    64 {
    65         return GET_MIDBITS(request_type, 2, 5);
    66 }
    6779
    6880/** Handle communication over control pipe zero.
     
    7789        }
    7890       
    79         usb_device_request_setup_packet_t *request = (usb_device_request_setup_packet_t *) transfer->request;
    80         uint8_t *remaining_data = transfer->data;
     91        usb_device_request_setup_packet_t *request
     92            = (usb_device_request_setup_packet_t *) transfer->request;
     93        printf("Request: %d,%d\n", request->request_type, request->request);
    8194       
    82         int type = request_get_type(request->request_type);
    83        
    84         int rc = EOK;
    85        
    86         device->lib_debug(device, 2, USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO,
    87             "request type: %s", str_request_type(type));
    88        
    89         switch (type) {
    90                 case REQUEST_TYPE_STANDARD:
    91                         rc = handle_std_request(device, request, remaining_data);
    92                         break;
    93                 case REQUEST_TYPE_CLASS:
    94                         if (DEVICE_HAS_OP(device, on_class_device_request)) {
    95                                 rc = device->ops->on_class_device_request(device,
    96                                     request, remaining_data);
    97                         }
    98                         break;
    99                 default:
    100                         break;
     95        /*
     96         * First, see whether user provided its own callback.
     97         */
     98        int rc = EFORWARD;
     99        if (device->ops) {
     100                usbvirt_control_transfer_handler_t *user_handler
     101                    = find_handler(device->ops->control_transfer_handlers,
     102                    request);
     103                if (user_handler != NULL) {
     104                        rc = user_handler->callback(device, request,
     105                            transfer->data);
     106                }
     107        }
     108
     109        /*
     110         * If there was no user callback or the callback returned EFORWARD,
     111         * we need to run a local handler.
     112         */
     113        if (rc == EFORWARD) {
     114                usbvirt_control_transfer_handler_t *lib_handler
     115                    = find_handler(control_pipe_zero_local_handlers,
     116                    request);
     117                if (lib_handler != NULL) {
     118                        rc = lib_handler->callback(device, request,
     119                            transfer->data);
     120                }
    101121        }
    102122       
     123        /*
     124         * Check for SET_ADDRESS finalization.
     125         */
    103126        if (device->new_address != -1) {
    104127                /*
  • uspace/lib/usbvirt/src/private.h

    r8f8ae1fd r7feeb84  
    8787}
    8888
     89extern usbvirt_control_transfer_handler_t control_pipe_zero_local_handlers[];
     90
    8991#endif
    9092/**
  • uspace/lib/usbvirt/src/stdreq.c

    r8f8ae1fd r7feeb84  
    4040#include "private.h"
    4141
    42 
    43 typedef int (*usbvirt_stdreq_handler_t)(usbvirt_device_t *,
    44 usb_device_request_setup_packet_t *, uint8_t *);
    45 
    4642/*
    4743 * All sub handlers must return EFORWARD to inform the caller that
     
    177173}
    178174
    179 static usbvirt_stdreq_handler_t local_handlers[USB_DEVREQ_LAST_STD] = {
    180         [USB_DEVREQ_GET_DESCRIPTOR] = handle_get_descriptor,
    181         [USB_DEVREQ_SET_ADDRESS] = handle_set_address,
    182         [USB_DEVREQ_SET_CONFIGURATION] = handle_set_configuration
     175
     176#define MAKE_BM_REQUEST(direction, recipient) \
     177        USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \
     178            USBVIRT_REQUEST_TYPE_STANDARD, recipient)
     179#define MAKE_BM_REQUEST_DEV(direction) \
     180        MAKE_BM_REQUEST(direction, USBVIRT_REQUEST_RECIPIENT_DEVICE)
     181
     182usbvirt_control_transfer_handler_t control_pipe_zero_local_handlers[] = {
     183        {
     184                .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_IN),
     185                .request = USB_DEVREQ_GET_DESCRIPTOR,
     186                .callback = handle_get_descriptor
     187        },
     188        {
     189                .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT),
     190                .request = USB_DEVREQ_SET_ADDRESS,
     191                .callback = handle_set_address
     192        },
     193        {
     194                .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT),
     195                .request = USB_DEVREQ_SET_CONFIGURATION,
     196                .callback = handle_set_configuration
     197        },
     198        USBVIRT_CONTROL_TRANSFER_HANDLER_LAST
    183199};
    184 
    185 /** Handle standard device request. */
    186 int handle_std_request(usbvirt_device_t *device,
    187     usb_device_request_setup_packet_t *request_packet, uint8_t *data)
    188 {
    189         int request = request_packet->request;
    190 
    191         device->lib_debug(device, 3, USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO,
    192             "handling standard request %d", request);
    193 
    194         if (request >= USB_DEVREQ_LAST_STD) {
    195                 return ENOTSUP;
    196         }
    197        
    198         int rc = EFORWARD;
    199         if ((device->ops)
    200             && (device->ops->on_standard_request[request])) {
    201                 rc = device->ops->on_standard_request[request](device,
    202                     request_packet, data);
    203         }
    204 
    205         if (rc == EFORWARD) {
    206                 if (local_handlers[request]) {
    207                         rc = local_handlers[request](device,
    208                             request_packet, data);
    209                 } else {
    210                         rc = ENOTSUP;
    211                 }
    212         }
    213 
    214         assert(rc != EFORWARD);
    215         return rc;
    216 }
    217200
    218201/**
Note: See TracChangeset for help on using the changeset viewer.