Changeset 7feeb84 in mainline for uspace/lib/usbvirt


Ignore:
Timestamp:
2010-12-13T14:25:49Z (15 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/lib/usbvirt
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • 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.