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, int rawFD) 19 : fConfiguration(config), 20 fIndex(index), 21 fRawFD(rawFD), 22 fEndpoints(NULL), 23 fInterfaceString(NULL) 24 { 25 _UpdateDescriptorAndEndpoints(); 26 } 27 28 29 BUSBInterface::~BUSBInterface() 30 { 31 delete[] fInterfaceString; 32 for (int32 i = 0; i < fDescriptor.num_endpoints; i++) 33 delete fEndpoints[i]; 34 delete[] fEndpoints; 35 } 36 37 38 uint32 39 BUSBInterface::Index() const 40 { 41 return fIndex; 42 } 43 44 45 const BUSBConfiguration * 46 BUSBInterface::Configuration() const 47 { 48 return fConfiguration; 49 } 50 51 52 const BUSBDevice * 53 BUSBInterface::Device() const 54 { 55 return fConfiguration->Device(); 56 } 57 58 59 uint8 60 BUSBInterface::Class() const 61 { 62 return fDescriptor.interface_class; 63 } 64 65 66 uint8 67 BUSBInterface::Subclass() const 68 { 69 return fDescriptor.interface_subclass; 70 } 71 72 73 uint8 74 BUSBInterface::Protocol() const 75 { 76 return fDescriptor.interface_protocol; 77 } 78 79 80 const char * 81 BUSBInterface::InterfaceString() const 82 { 83 if (fDescriptor.interface == 0) 84 return ""; 85 86 if (fInterfaceString) 87 return fInterfaceString; 88 89 fInterfaceString = Device()->DecodeStringDescriptor(fDescriptor.interface); 90 if (!fInterfaceString) { 91 fInterfaceString = new char[1]; 92 fInterfaceString[0] = 0; 93 } 94 95 return fInterfaceString; 96 } 97 98 99 const usb_interface_descriptor * 100 BUSBInterface::Descriptor() const 101 { 102 return &fDescriptor; 103 } 104 105 106 status_t 107 BUSBInterface::OtherDescriptorAt(uint32 index, usb_descriptor *descriptor, 108 size_t length) const 109 { 110 if (length > 0 && descriptor == NULL) 111 return B_BAD_VALUE; 112 113 usb_raw_command command; 114 command.generic.descriptor = descriptor; 115 command.generic.config_index = fConfiguration->Index(); 116 command.generic.interface_index = fIndex; 117 command.generic.length = length; 118 command.generic.generic_index = index; 119 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR, &command, 120 sizeof(command)) || command.generic.status != B_USB_RAW_STATUS_SUCCESS) 121 return B_ERROR; 122 123 return B_OK; 124 } 125 126 127 uint32 128 BUSBInterface::CountEndpoints() const 129 { 130 return fDescriptor.num_endpoints; 131 } 132 133 134 const BUSBEndpoint * 135 BUSBInterface::EndpointAt(uint32 index) const 136 { 137 if (index >= fDescriptor.num_endpoints) 138 return NULL; 139 140 return fEndpoints[index]; 141 } 142 143 144 uint32 145 BUSBInterface::CountAlternates() const 146 { 147 uint32 alternateCount; 148 usb_raw_command command; 149 command.alternate.alternate_count = &alternateCount; 150 command.alternate.config_index = fConfiguration->Index(); 151 command.alternate.interface_index = fIndex; 152 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, &command, 153 sizeof(command)) || command.alternate.status != B_USB_RAW_STATUS_SUCCESS) 154 return 1; 155 156 return alternateCount; 157 } 158 159 160 usb_interface_descriptor * 161 BUSBInterface::AlternateAt(uint32 alternateIndex) 162 { 163 usb_interface_descriptor *descriptor 164 = new(std::nothrow) usb_interface_descriptor; 165 if (descriptor == NULL) 166 return NULL; 167 168 usb_raw_command command; 169 command.alternate.descriptor = descriptor; 170 command.alternate.config_index = fConfiguration->Index(); 171 command.alternate.interface_index = fIndex; 172 command.alternate.alternate_index = alternateIndex; 173 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ALT_INTERFACE_DESCRIPTOR, &command, 174 sizeof(command)) || command.alternate.status != B_USB_RAW_STATUS_SUCCESS) { 175 delete descriptor; 176 return NULL; 177 } 178 179 return descriptor; 180 } 181 182 183 status_t 184 BUSBInterface::SetAlternate(uint32 alternateIndex) 185 { 186 usb_raw_command command; 187 command.alternate.config_index = fConfiguration->Index(); 188 command.alternate.interface_index = fIndex; 189 command.alternate.alternate_index = alternateIndex; 190 if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_ALT_INTERFACE, &command, 191 sizeof(command)) || command.alternate.status != B_USB_RAW_STATUS_SUCCESS) 192 return B_ERROR; 193 194 _UpdateDescriptorAndEndpoints(); 195 return B_OK; 196 } 197 198 199 void 200 BUSBInterface::_UpdateDescriptorAndEndpoints() 201 { 202 usb_raw_command command; 203 command.interface.descriptor = &fDescriptor; 204 command.interface.config_index = fConfiguration->Index(); 205 command.interface.interface_index = fIndex; 206 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR, &command, 207 sizeof(command)) || command.interface.status != B_USB_RAW_STATUS_SUCCESS) 208 memset(&fDescriptor, 0, sizeof(fDescriptor)); 209 210 if (fEndpoints) { 211 // Delete old endpoints 212 for (int32 i = 0; i < fDescriptor.num_endpoints; i++) 213 delete fEndpoints[i]; 214 delete fEndpoints; 215 } 216 217 fEndpoints = new BUSBEndpoint *[fDescriptor.num_endpoints]; 218 for (int32 i = 0; i < fDescriptor.num_endpoints; i++) 219 fEndpoints[i] = new BUSBEndpoint(this, i, fRawFD); 220 } 221