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 18 BUSBInterface::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 33 BUSBInterface::~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 51 uint32 52 BUSBInterface::Index() const 53 { 54 return fIndex; 55 } 56 57 58 uint32 59 BUSBInterface::AlternateIndex() const 60 { 61 if (fAlternate == B_USB_RAW_ACTIVE_ALTERNATE) 62 return ActiveAlternateIndex(); 63 return fAlternate; 64 } 65 66 67 const BUSBConfiguration * 68 BUSBInterface::Configuration() const 69 { 70 return fConfiguration; 71 } 72 73 74 const BUSBDevice * 75 BUSBInterface::Device() const 76 { 77 return fConfiguration->Device(); 78 } 79 80 81 uint8 82 BUSBInterface::Class() const 83 { 84 return fDescriptor.interface_class; 85 } 86 87 88 uint8 89 BUSBInterface::Subclass() const 90 { 91 return fDescriptor.interface_subclass; 92 } 93 94 95 uint8 96 BUSBInterface::Protocol() const 97 { 98 return fDescriptor.interface_protocol; 99 } 100 101 102 const char * 103 BUSBInterface::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 119 const usb_interface_descriptor * 120 BUSBInterface::Descriptor() const 121 { 122 return &fDescriptor; 123 } 124 125 126 status_t 127 BUSBInterface::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 148 uint32 149 BUSBInterface::CountEndpoints() const 150 { 151 return fDescriptor.num_endpoints; 152 } 153 154 155 const BUSBEndpoint * 156 BUSBInterface::EndpointAt(uint32 index) const 157 { 158 if (index >= fDescriptor.num_endpoints || fEndpoints == NULL) 159 return NULL; 160 161 return fEndpoints[index]; 162 } 163 164 165 uint32 166 BUSBInterface::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 179 const BUSBInterface * 180 BUSBInterface::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 207 uint32 208 BUSBInterface::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 221 status_t 222 BUSBInterface::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 237 void 238 BUSBInterface::_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