Changeset 7feeb84 in mainline for uspace/lib/usbvirt/src/ctrlpipe.c


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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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                /*
Note: See TracChangeset for help on using the changeset viewer.