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