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 * Salvatore Benedetto <salvatore.benedetto@gmail.com> 8 */ 9 10#include <USBKit.h> 11#include <usb_raw.h> 12 13#include <new> 14#include <string.h> 15#include <unistd.h> 16 17 18BUSBInterface::BUSBInterface(BUSBConfiguration *config, uint32 index, 19 uint32 alternate, int rawFD) 20 : fConfiguration(config), 21 fIndex(index), 22 fAlternate(alternate), 23 fRawFD(rawFD), 24 fEndpoints(NULL), 25 fAlternateCount(0), 26 fAlternates(NULL), 27 fInterfaceString(NULL) 28{ 29 _UpdateDescriptorAndEndpoints(); 30} 31 32 33BUSBInterface::~BUSBInterface() 34{ 35 delete[] fInterfaceString; 36 37 if (fEndpoints != NULL) { 38 for (int32 i = 0; i < fDescriptor.num_endpoints; i++) 39 delete fEndpoints[i]; 40 delete[] fEndpoints; 41 } 42 43 if (fAlternates != NULL) { 44 for (uint32 i = 0; i < fAlternateCount; i++) 45 delete fAlternates[i]; 46 delete[] fAlternates; 47 } 48} 49 50 51uint32 52BUSBInterface::Index() const 53{ 54 return fIndex; 55} 56 57 58uint32 59BUSBInterface::AlternateIndex() const 60{ 61 if (fAlternate == B_USB_RAW_ACTIVE_ALTERNATE) 62 return ActiveAlternateIndex(); 63 return fAlternate; 64} 65 66 67const BUSBConfiguration * 68BUSBInterface::Configuration() const 69{ 70 return fConfiguration; 71} 72 73 74const BUSBDevice * 75BUSBInterface::Device() const 76{ 77 return fConfiguration->Device(); 78} 79 80 81uint8 82BUSBInterface::Class() const 83{ 84 return fDescriptor.interface_class; 85} 86 87 88uint8 89BUSBInterface::Subclass() const 90{ 91 return fDescriptor.interface_subclass; 92} 93 94 95uint8 96BUSBInterface::Protocol() const 97{ 98 return fDescriptor.interface_protocol; 99} 100 101 102const char * 103BUSBInterface::InterfaceString() const 104{ 105 if (fDescriptor.interface == 0) 106 return ""; 107 108 if (fInterfaceString) 109 return fInterfaceString; 110 111 fInterfaceString = Device()->DecodeStringDescriptor(fDescriptor.interface); 112 if (fInterfaceString == NULL) 113 return ""; 114 115 return fInterfaceString; 116} 117 118 119const usb_interface_descriptor * 120BUSBInterface::Descriptor() const 121{ 122 return &fDescriptor; 123} 124 125 126status_t 127BUSBInterface::OtherDescriptorAt(uint32 index, usb_descriptor *descriptor, 128 size_t length) const 129{ 130 if (length <= 0 || descriptor == NULL) 131 return B_BAD_VALUE; 132 133 usb_raw_command command; 134 command.generic_etc.descriptor = descriptor; 135 command.generic_etc.config_index = fConfiguration->Index(); 136 command.generic_etc.interface_index = fIndex; 137 command.generic_etc.alternate_index = fAlternate; 138 command.generic_etc.generic_index = index; 139 command.generic_etc.length = length; 140 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR_ETC, &command, 141 sizeof(command)) || command.generic.status != B_USB_RAW_STATUS_SUCCESS) 142 return B_ERROR; 143 144 return B_OK; 145} 146 147 148uint32 149BUSBInterface::CountEndpoints() const 150{ 151 return fDescriptor.num_endpoints; 152} 153 154 155const BUSBEndpoint * 156BUSBInterface::EndpointAt(uint32 index) const 157{ 158 if (index >= fDescriptor.num_endpoints || fEndpoints == NULL) 159 return NULL; 160 161 return fEndpoints[index]; 162} 163 164 165uint32 166BUSBInterface::CountAlternates() const 167{ 168 usb_raw_command command; 169 command.alternate.config_index = fConfiguration->Index(); 170 command.alternate.interface_index = fIndex; 171 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, &command, 172 sizeof(command)) || command.alternate.status != B_USB_RAW_STATUS_SUCCESS) 173 return 1; 174 175 return command.alternate.alternate_info; 176} 177 178 179const BUSBInterface * 180BUSBInterface::AlternateAt(uint32 alternateIndex) const 181{ 182 if (fAlternateCount > 0 && fAlternates != NULL) { 183 if (alternateIndex >= fAlternateCount) 184 return NULL; 185 186 return fAlternates[alternateIndex]; 187 } 188 189 if (fAlternateCount == 0) 190 fAlternateCount = CountAlternates(); 191 if (alternateIndex >= fAlternateCount) 192 return NULL; 193 194 fAlternates = new(std::nothrow) BUSBInterface *[fAlternateCount]; 195 if (fAlternates == NULL) 196 return NULL; 197 198 for (uint32 i = 0; i < fAlternateCount; i++) { 199 fAlternates[i] = new(std::nothrow) BUSBInterface(fConfiguration, fIndex, 200 i, fRawFD); 201 } 202 203 return fAlternates[alternateIndex]; 204} 205 206 207uint32 208BUSBInterface::ActiveAlternateIndex() const 209{ 210 usb_raw_command command; 211 command.alternate.config_index = fConfiguration->Index(); 212 command.alternate.interface_index = fIndex; 213 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX, &command, 214 sizeof(command)) || command.alternate.status != B_USB_RAW_STATUS_SUCCESS) 215 return 0; 216 217 return command.alternate.alternate_info; 218} 219 220 221status_t 222BUSBInterface::SetAlternate(uint32 alternateIndex) 223{ 224 usb_raw_command command; 225 command.alternate.alternate_info = alternateIndex; 226 command.alternate.config_index = fConfiguration->Index(); 227 command.alternate.interface_index = fIndex; 228 if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_ALT_INTERFACE, &command, 229 sizeof(command)) || command.alternate.status != B_USB_RAW_STATUS_SUCCESS) 230 return B_ERROR; 231 232 _UpdateDescriptorAndEndpoints(); 233 return B_OK; 234} 235 236 237void 238BUSBInterface::_UpdateDescriptorAndEndpoints() 239{ 240 usb_raw_command command; 241 command.interface_etc.descriptor = &fDescriptor; 242 command.interface_etc.config_index = fConfiguration->Index(); 243 command.interface_etc.interface_index = fIndex; 244 command.interface_etc.alternate_index = fAlternate; 245 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC, &command, 246 sizeof(command)) || command.interface.status != B_USB_RAW_STATUS_SUCCESS) 247 memset(&fDescriptor, 0, sizeof(fDescriptor)); 248 249 if (fEndpoints != NULL) { 250 // Delete old endpoints 251 for (int32 i = 0; i < fDescriptor.num_endpoints; i++) 252 delete fEndpoints[i]; 253 delete[] fEndpoints; 254 } 255 256 fEndpoints = new(std::nothrow) BUSBEndpoint *[fDescriptor.num_endpoints]; 257 if (fEndpoints == NULL) 258 return; 259 260 for (int32 i = 0; i < fDescriptor.num_endpoints; i++) 261 fEndpoints[i] = new(std::nothrow) BUSBEndpoint(this, i, fRawFD); 262} 263