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 15 BUSBEndpoint::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 32 BUSBEndpoint::~BUSBEndpoint() 33 { 34 } 35 36 37 uint32 38 BUSBEndpoint::Index() const 39 { 40 return fIndex; 41 } 42 43 44 const BUSBInterface * 45 BUSBEndpoint::Interface() const 46 { 47 return fInterface; 48 } 49 50 51 const BUSBConfiguration * 52 BUSBEndpoint::Configuration() const 53 { 54 return fInterface->Configuration(); 55 } 56 57 58 const BUSBDevice * 59 BUSBEndpoint::Device() const 60 { 61 return fInterface->Device(); 62 } 63 64 65 bool 66 BUSBEndpoint::IsBulk() const 67 { 68 return (fDescriptor.attributes & USB_ENDPOINT_ATTR_MASK) 69 == USB_ENDPOINT_ATTR_BULK; 70 } 71 72 73 bool 74 BUSBEndpoint::IsInterrupt() const 75 { 76 return (fDescriptor.attributes & USB_ENDPOINT_ATTR_MASK) 77 == USB_ENDPOINT_ATTR_INTERRUPT; 78 } 79 80 81 bool 82 BUSBEndpoint::IsIsochronous() const 83 { 84 return (fDescriptor.attributes & USB_ENDPOINT_ATTR_MASK) 85 == USB_ENDPOINT_ATTR_ISOCHRONOUS; 86 } 87 88 89 bool 90 BUSBEndpoint::IsControl() const 91 { 92 return (fDescriptor.attributes & USB_ENDPOINT_ATTR_MASK) 93 == USB_ENDPOINT_ATTR_CONTROL; 94 } 95 96 97 bool 98 BUSBEndpoint::IsInput() const 99 { 100 return (fDescriptor.endpoint_address & USB_ENDPOINT_ADDR_DIR_IN) 101 == USB_ENDPOINT_ADDR_DIR_IN; 102 } 103 104 105 bool 106 BUSBEndpoint::IsOutput() const 107 { 108 return (fDescriptor.endpoint_address & USB_ENDPOINT_ADDR_DIR_IN) 109 == USB_ENDPOINT_ADDR_DIR_OUT; 110 } 111 112 113 uint16 114 BUSBEndpoint::MaxPacketSize() const 115 { 116 return fDescriptor.max_packet_size; 117 } 118 119 120 uint8 121 BUSBEndpoint::Interval() const 122 { 123 return fDescriptor.interval; 124 } 125 126 127 const usb_endpoint_descriptor * 128 BUSBEndpoint::Descriptor() const 129 { 130 return &fDescriptor; 131 } 132 133 134 ssize_t 135 BUSBEndpoint::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 157 ssize_t 158 BUSBEndpoint::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 177 ssize_t 178 BUSBEndpoint::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 197 ssize_t 198 BUSBEndpoint::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 220 bool 221 BUSBEndpoint::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 231 status_t 232 BUSBEndpoint::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