source: mainline/uspace/lib/usbvirt/src/ctrlpipe.c@ 7feeb84

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7feeb84 was 7feeb84, checked in by Vojtech Horky <vojtechhorky@…>, 15 years ago

usbvirt: more flexible callbacks for endpoint zero

  • Property mode set to 100644
File size: 4.4 KB
RevLine 
[bc9a629]1/*
2 * Copyright (c) 2010 Vojtech Horky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
[b8100da]29/** @addtogroup libusbvirt usb
[bc9a629]30 * @{
31 */
32/** @file
[b8100da]33 * @brief Device control pipe.
[bc9a629]34 */
[b8100da]35#include <errno.h>
[bc9a629]36
[b8100da]37#include "private.h"
[bc9a629]38
[7feeb84]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)
[aab02fb]47{
[7feeb84]48 return (
49 (handler->request_type == request_packet->request_type)
50 && (handler->request == request_packet->request));
51
[aab02fb]52}
[954ea70]53
[7feeb84]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.
[ca07cd3]59 */
[7feeb84]60static usbvirt_control_transfer_handler_t *find_handler(
61 usbvirt_control_transfer_handler_t *handlers,
62 usb_device_request_setup_packet_t *request_packet)
[4971812]63{
[7feeb84]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;
[4971812]76}
77
[7feeb84]78
79
[ca07cd3]80/** Handle communication over control pipe zero.
81 */
82int control_pipe(usbvirt_device_t *device, usbvirt_control_transfer_t *transfer)
[b8100da]83{
[aab02fb]84 device->lib_debug(device, 1, USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO,
85 "op on control pipe zero (request_size=%u)", transfer->request_size);
86
[7a7bfeb3]87 if (transfer->request_size < sizeof(usb_device_request_setup_packet_t)) {
[4971812]88 return ENOMEM;
89 }
90
[7feeb84]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);
[954ea70]94
[7feeb84]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 }
[4971812]121 }
122
[7feeb84]123 /*
124 * Check for SET_ADDRESS finalization.
125 */
[ca07cd3]126 if (device->new_address != -1) {
[954ea70]127 /*
128 * TODO: handle when this request is invalid (e.g.
129 * setting address when in configured state).
130 */
[ca07cd3]131 if (device->new_address == 0) {
[954ea70]132 device->state = USBVIRT_STATE_DEFAULT;
133 } else {
134 device->state = USBVIRT_STATE_ADDRESS;
135 }
[ca07cd3]136 device->address = device->new_address;
[954ea70]137
[ca07cd3]138 device->new_address = -1;
[aab02fb]139
140 device->lib_debug(device, 2, USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO,
141 "device address changed to %d (state %s)",
142 device->address, str_device_state(device->state));
[954ea70]143 }
144
145 return rc;
[b8100da]146}
[bc9a629]147
148/**
149 * @}
150 */
Note: See TracBrowser for help on using the repository browser.