1/* 2 * Copyright (c) 2007-2013 ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <stdlib.h> 11#include <barrelfish/barrelfish.h> 12 13#include <usb/usb.h> 14 15#include <usb_controller.h> 16#include <usb_xfer.h> 17#include <usb_device.h> 18#include <usb_endpoint.h> 19#include <usb_pipe.h> 20 21/** 22 * \brief goes through the endpoints of a device and returns the one that 23 * matches the criteria 24 * 25 * \param device the device we want to consider for the lookup 26 * \param iface the interface in which we want to look for 27 * \param filter filter defining which endpoint we want 28 * 29 * \return pointer to the endpoint on success 30 * NULL if no endpoint is fould 31 * 32 * NOTE: Filter may contain a specific direction, endpoint number or type. 33 * Each filter criteria may also be "ANY" 34 */ 35struct usb_endpoint *usb_endpoint_lookup(struct usb_device *device, 36 uint8_t iface, const struct usb_xfer_config *filter) 37{ 38 39 uint8_t ep_index = 0; 40 41 struct usb_endpoint *ep = device->endpoints; 42 43 usb_endpoint_address_t *epaddr; 44 usb_endpoint_attributes_t *epattr; 45 46 uint8_t any = 1; 47 48 /* loop over all endpoints */ 49 for (uint8_t ep_current = 0; ep_current < device->ep_max; ep_current++) { 50 if (ep == NULL) { 51 /* no endpoint allocated, continue with next */ 52 continue; 53 } 54 55 if ((ep->descriptor == NULL) || (ep->iface_index != iface)) { 56 /* there is no descriptor or the wrong interface */ 57 continue; 58 } 59 60 /* we have a valid endpoint sofar, so check filter criteria */ 61 epaddr = &(ep->descriptor->bEndpointAddress); 62 epattr = &(ep->descriptor->bmAttributes); 63 64 /* check for direction */ 65 if (filter->direction != USB_ENDPOINT_DIRECTION_ANY) { 66 any = 0; 67 if (epaddr->direction != filter->direction) { 68 /* wrong direction, check next next */ 69 continue; 70 } 71 } 72 73 /* checking matching endpoint address */ 74 if (filter->endpoint != USB_ENDPOINT_ADDRESS_ANY) { 75 any = 0; 76 if (epaddr->ep_number != filter->endpoint) { 77 /* wrong endpoint address */ 78 continue; 79 } 80 } 81 82 /* checking the matching type */ 83 if (filter->type != USB_ENDPOINT_TYPE_ANY) { 84 any = 0; 85 if (epattr->xfer_type != filter->type) { 86 /* wrong xfer type */ 87 continue; 88 } 89 } 90 91 if (!(ep_index--) && !any) { 92 USB_DEBUG_XFER("Endpoint found: iface=0x%x, ep=0x%x\n", 93 iface, ep->endpoint_address); 94 return (ep); 95 } 96 97 ep++; 98 } 99 100 /* the default control endpoint is not located in the endpoints array */ 101 if (device->ctrl_ep.descriptor && any && !ep_index) { 102 USB_DEBUG_XFER("usb_endpoint_lookup(): found default ctrl ep\n"); 103 return (&device->ctrl_ep); 104 } 105 106 /* no matching endpoint found */ 107 return (NULL); 108} 109 110/** 111 * \brief initializes the endpoint with the correct data 112 * 113 * \param device the usb device this endpoint belongs to 114 * \param iface_index the interface index this endpoint belongs to 115 * \param desc the endpoint descriptor of this endpoint 116 * \param ep the endpoint to initialize 117 */ 118void usb_endpoint_init(struct usb_device *device, uint8_t iface_index, 119 struct usb_endpoint_descriptor *desc, struct usb_endpoint *ep) 120{ 121 USB_DEBUG_TR_ENTER; 122 123 /* 124 * call the endpoint init function of the host controller in a save way 125 * This sets the pipe function pointers to the correspinding transfer type 126 */ 127 struct usb_hcdi_bus_fn *bus_fn = device->controller->hcdi_bus_fn; 128 129 if (bus_fn && bus_fn->endpoint_init) { 130 (bus_fn->endpoint_init)(device, desc, ep); 131 } 132 133 /* set the values of this endpoint */ 134 ep->descriptor = desc; 135 ep->iface_index = iface_index; 136 ep->endpoint_address = desc->bEndpointAddress.ep_number; 137 ep->max_packet_size = desc->wMaxPacketSize; 138 139 /* initialze the endpoint queue */ 140 ep->transfers.head.first = NULL; 141 ep->transfers.head.last_next = &(ep->transfers.head.first); 142 ep->transfers.command = &usb_pipe_start; 143 144 if (ep->pipe_fn == NULL) { 145 return; 146 } 147 148 /* some devices may need a clear stall on new endpoints */ 149 if (bus_fn->clear_stall != NULL) { 150 (bus_fn->clear_stall)(device, ep); 151 } 152} 153