1/* 2 * Copyright 2007-2008, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 */ 8 9#include <USBKit.h> 10#include <usb_raw.h> 11#include <unistd.h> 12#include <string.h> 13 14 15BUSBEndpoint::BUSBEndpoint(BUSBInterface *interface, uint32 index, int rawFD) 16 : fInterface(interface), 17 fIndex(index), 18 fRawFD(rawFD) 19{ 20 usb_raw_command command; 21 command.endpoint_etc.descriptor = &fDescriptor; 22 command.endpoint_etc.config_index = fInterface->Configuration()->Index(); 23 command.endpoint_etc.interface_index = fInterface->Index(); 24 command.endpoint_etc.alternate_index = fInterface->AlternateIndex(); 25 command.endpoint_etc.endpoint_index = fIndex; 26 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC, &command, 27 sizeof(command)) || command.endpoint_etc.status != B_USB_RAW_STATUS_SUCCESS) 28 memset(&fDescriptor, 0, sizeof(fDescriptor)); 29} 30 31 32BUSBEndpoint::~BUSBEndpoint() 33{ 34} 35 36 37uint32 38BUSBEndpoint::Index() const 39{ 40 return fIndex; 41} 42 43 44const BUSBInterface * 45BUSBEndpoint::Interface() const 46{ 47 return fInterface; 48} 49 50 51const BUSBConfiguration * 52BUSBEndpoint::Configuration() const 53{ 54 return fInterface->Configuration(); 55} 56 57 58const BUSBDevice * 59BUSBEndpoint::Device() const 60{ 61 return fInterface->Device(); 62} 63 64 65bool 66BUSBEndpoint::IsBulk() const 67{ 68 return (fDescriptor.attributes & USB_ENDPOINT_ATTR_MASK) 69 == USB_ENDPOINT_ATTR_BULK; 70} 71 72 73bool 74BUSBEndpoint::IsInterrupt() const 75{ 76 return (fDescriptor.attributes & USB_ENDPOINT_ATTR_MASK) 77 == USB_ENDPOINT_ATTR_INTERRUPT; 78} 79 80 81bool 82BUSBEndpoint::IsIsochronous() const 83{ 84 return (fDescriptor.attributes & USB_ENDPOINT_ATTR_MASK) 85 == USB_ENDPOINT_ATTR_ISOCHRONOUS; 86} 87 88 89bool 90BUSBEndpoint::IsControl() const 91{ 92 return (fDescriptor.attributes & USB_ENDPOINT_ATTR_MASK) 93 == USB_ENDPOINT_ATTR_CONTROL; 94} 95 96 97bool 98BUSBEndpoint::IsInput() const 99{ 100 return (fDescriptor.endpoint_address & USB_ENDPOINT_ADDR_DIR_IN) 101 == USB_ENDPOINT_ADDR_DIR_IN; 102} 103 104 105bool 106BUSBEndpoint::IsOutput() const 107{ 108 return (fDescriptor.endpoint_address & USB_ENDPOINT_ADDR_DIR_IN) 109 == USB_ENDPOINT_ADDR_DIR_OUT; 110} 111 112 113uint16 114BUSBEndpoint::MaxPacketSize() const 115{ 116 return fDescriptor.max_packet_size; 117} 118 119 120uint8 121BUSBEndpoint::Interval() const 122{ 123 return fDescriptor.interval; 124} 125 126 127const usb_endpoint_descriptor * 128BUSBEndpoint::Descriptor() const 129{ 130 return &fDescriptor; 131} 132 133 134ssize_t 135BUSBEndpoint::ControlTransfer(uint8 requestType, uint8 request, uint16 value, 136 uint16 index, uint16 length, void *data) const 137{ 138 if (length > 0 && data == NULL) 139 return B_BAD_VALUE; 140 141 usb_raw_command command; 142 command.control.request_type = requestType; 143 command.control.request = request; 144 command.control.value = value; 145 command.control.index = index; 146 command.control.length = length; 147 command.control.data = data; 148 149 if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command, 150 sizeof(command)) || command.control.status != B_USB_RAW_STATUS_SUCCESS) 151 return B_ERROR; 152 153 return command.control.length; 154} 155 156 157ssize_t 158BUSBEndpoint::InterruptTransfer(void *data, size_t length) const 159{ 160 if (length > 0 && data == NULL) 161 return B_BAD_VALUE; 162 163 usb_raw_command command; 164 command.transfer.interface = fInterface->Index(); 165 command.transfer.endpoint = fIndex; 166 command.transfer.data = data; 167 command.transfer.length = length; 168 169 if (ioctl(fRawFD, B_USB_RAW_COMMAND_INTERRUPT_TRANSFER, &command, 170 sizeof(command)) || command.transfer.status != B_USB_RAW_STATUS_SUCCESS) 171 return B_ERROR; 172 173 return command.transfer.length; 174} 175 176 177ssize_t 178BUSBEndpoint::BulkTransfer(void *data, size_t length) const 179{ 180 if (length > 0 && data == NULL) 181 return B_BAD_VALUE; 182 183 usb_raw_command command; 184 command.transfer.interface = fInterface->Index(); 185 command.transfer.endpoint = fIndex; 186 command.transfer.data = data; 187 command.transfer.length = length; 188 189 if (ioctl(fRawFD, B_USB_RAW_COMMAND_BULK_TRANSFER, &command, 190 sizeof(command)) || command.transfer.status != B_USB_RAW_STATUS_SUCCESS) 191 return B_ERROR; 192 193 return command.transfer.length; 194} 195 196 197ssize_t 198BUSBEndpoint::IsochronousTransfer(void *data, size_t length, 199 usb_iso_packet_descriptor *packetDescriptors, uint32 packetCount) const 200{ 201 if (length > 0 && data == NULL) 202 return B_BAD_VALUE; 203 204 usb_raw_command command; 205 command.isochronous.interface = fInterface->Index(); 206 command.isochronous.endpoint = fIndex; 207 command.isochronous.data = data; 208 command.isochronous.length = length; 209 command.isochronous.packet_descriptors = packetDescriptors; 210 command.isochronous.packet_count = packetCount; 211 212 if (ioctl(fRawFD, B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER, &command, 213 sizeof(command)) || command.isochronous.status != B_USB_RAW_STATUS_SUCCESS) 214 return B_ERROR; 215 216 return command.isochronous.length; 217} 218 219 220bool 221BUSBEndpoint::IsStalled() const 222{ 223 uint16 status = 0; 224 Device()->ControlTransfer(USB_REQTYPE_ENDPOINT_IN, 225 USB_REQUEST_GET_STATUS, USB_FEATURE_ENDPOINT_HALT, 226 fDescriptor.endpoint_address, sizeof(status), &status); 227 return status != 0; 228} 229 230 231status_t 232BUSBEndpoint::ClearStall() const 233{ 234 return Device()->ControlTransfer(USB_REQTYPE_ENDPOINT_OUT, 235 USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 236 fDescriptor.endpoint_address, 0, NULL); 237} 238