DecodeEndpointDescriptor.m [plain text]
/*
* Copyright © 1998-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#import "DecodeEndpointDescriptor.h"
@implementation DecodeEndpointDescriptor
+ (void)decodeBytes:(Byte *)p forDevice:(BusProbeDevice *)thisDevice isOtherSpeedDesc:(BOOL)isOtherSpeedDesc {
/* struct IOUSBEndpointDescriptor {
UInt8 bLength;
UInt8 bDescriptorType;
UInt8 bEndpointAddress;
UInt8 bmAttributes;
UInt16 wMaxPacketSize;
UInt8 bInterval;
}; */
static int xferTypes2[] = { 0, 1, 2, 3 };
IOUSBEndpointDescriptor endpointDescriptor;
char endpointHeading[500];
char str[500];
char temporaryString[500];
bool controlOrBulk = false;
bool isoch = false;
bool interrupt = false;
bool useHighSpeedDefinition = false;
bool printPollingInterval = true;
// The bInterval field of an endpoint descriptor changes depending if it is a high speed endpoint or not. When parsing
// the "Other Speed Configuration Descriptor", we need to know the speed of the device and whether this is an "other" speed
// descriptor. Hence the following code:
//
if ( ([thisDevice usbRelease] >= kUSBRel20) )
{
if ( (([thisDevice speed] == kUSBDeviceSpeedHigh ) && !isOtherSpeedDesc) ||
(([thisDevice speed] != kUSBDeviceSpeedHigh ) && isOtherSpeedDesc) )
useHighSpeedDefinition = true;
}
bool useUSB3Definition = false;
if ( ([thisDevice usbRelease] >= kUSBRel30) )
{
useUSB3Definition = true;
}
endpointDescriptor = *(IOUSBEndpointDescriptor *)p;
Swap16(&endpointDescriptor.wMaxPacketSize);
switch (xferTypes2[endpointDescriptor.bmAttributes & 3])
{
case 0:
sprintf(endpointHeading, "Endpoint 0x break;
case 1:
if ( (endpointDescriptor.bEndpointAddress & kEndpointAddressMask ) == 0 )
sprintf(endpointHeading, "Endpoint 0x else
sprintf(endpointHeading, "Endpoint 0x break;
case 2:
if ( (endpointDescriptor.bEndpointAddress & kEndpointAddressMask ) == 0 )
sprintf(endpointHeading, "Endpoint 0x else
sprintf(endpointHeading, "Endpoint 0x break;
case 3:
if ( (endpointDescriptor.bEndpointAddress & kEndpointAddressMask ) == 0 )
sprintf(endpointHeading, "Endpoint 0x else
sprintf(endpointHeading, "Endpoint 0x break;
default:
sprintf(endpointHeading, "Endpoint 0x break;
}
[thisDevice addProperty:endpointHeading withValue:"" atDepth:ENDPOINT_LEVEL-1];
if (!(xferTypes2[endpointDescriptor.bmAttributes & 3] == 0))
{
// we dont need to show direction for Control Endpoints
//
if ( (endpointDescriptor.bEndpointAddress & kEndpointAddressMask ) == 0 )
sprintf(temporaryString, "0x else
sprintf(temporaryString, "0x [thisDevice addProperty:"Address:" withValue:temporaryString atDepth:ENDPOINT_LEVEL];
}
sprintf(str, "0x switch ( endpointDescriptor.bmAttributes & 0x03)
{
case 0: strcat(str, " (Control"); controlOrBulk = true; break;
case 1: strcat(str, " (Isochronous"); isoch = true; break;
case 2: strcat(str, " (Bulk"); controlOrBulk = true; break;
case 3: strcat(str, " (Interrupt"); interrupt = true; break;
}
if ( isoch )
{
switch ( (endpointDescriptor.bmAttributes & 0x0C) >> 2)
{
case 0: strcat(str, " no synchronization"); break;
case 1: strcat(str, " asynchronous"); break;
case 2: strcat(str, " adaptive"); break;
case 3: strcat(str, " synchronous"); break;
}
switch ( (endpointDescriptor.bmAttributes & 0x30) >> 4)
{
case 0: strcat(str, " data endpoint"); break;
case 1: strcat(str, " feedback endpoint"); break;
case 2: strcat(str, " implicit feedback data endpoint"); break;
case 3: strcat(str, " (error: bit 5 is Reserved)"); break;
}
}
else if ( useUSB3Definition && interrupt )
{
switch ( (endpointDescriptor.bmAttributes & 0x30) >> 4)
{
case 0: strcat(str, " periodic"); break;
case 1: strcat(str, " notification"); break;
case 2: strcat(str, " reserved"); break;
case 3: strcat(str, " reserved"); break;
}
}
strcat(str, ")");
[thisDevice addProperty:"Attributes:" withValue:str atDepth:ENDPOINT_LEVEL];
sprintf(temporaryString, "
if (useUSB3Definition)
{
UInt32 maxPacketSize = USBToHostWord(endpointDescriptor.wMaxPacketSize);
if ( (endpointDescriptor.bmAttributes & 0x03) == kUSBControl )
if (maxPacketSize != 512 )
sprintf(temporaryString, "0x
if ( (endpointDescriptor.bmAttributes & 0x03) == kUSBIsoc )
if (maxPacketSize > 1024 )
sprintf(temporaryString, "0x
if ( (endpointDescriptor.bmAttributes & 0x03) == kUSBBulk )
if (maxPacketSize != 1024 )
sprintf(temporaryString, "0x
if ( (endpointDescriptor.bmAttributes & 0x03) == kUSBInterrupt )
if (maxPacketSize > 1024 || maxPacketSize == 0 )
sprintf(temporaryString, "0x }
else if (useHighSpeedDefinition)
{
// If we have a USB 2.0 compliant device running at high speed, then the wMaxPacketSize calculation is funky
//
if ( interrupt || isoch)
{
UInt32 transPerMicroFrame = (endpointDescriptor.wMaxPacketSize & 0x1800) >> 11;
UInt32 bytesPerTransfer = endpointDescriptor.wMaxPacketSize & 0x07ff;
// If bits 15..13 are not 0, it's illegal. If bits 12..11 are 11b, it's illegal
if ((endpointDescriptor.wMaxPacketSize & 0xe000) != 0 )
sprintf(temporaryString, "0x else if (transPerMicroFrame == 3)
sprintf(temporaryString, "0x else if ( transPerMicroFrame == 0 && bytesPerTransfer > 1024)
sprintf(temporaryString, "0x else if ( transPerMicroFrame == 1 && ((bytesPerTransfer > 1024) || (bytesPerTransfer < 513)) )
sprintf(temporaryString, "0x else if ( transPerMicroFrame == 2 && ((bytesPerTransfer > 1024) || (bytesPerTransfer < 683)) )
sprintf(temporaryString, "0x else
sprintf(temporaryString, "0x }
}
[thisDevice addProperty:"Max Packet Size:" withValue:temporaryString atDepth:ENDPOINT_LEVEL];
if (useHighSpeedDefinition || useUSB3Definition)
{
// If we have a USB compliant device running at high speed, then the bInterval calculation is funky
//
if ( controlOrBulk)
{
if ( useHighSpeedDefinition)
{
if ( endpointDescriptor.bInterval == 0)
sprintf(temporaryString, " else
sprintf(temporaryString, " }
else
{
printPollingInterval = false;
}
}
if ( interrupt )
{
if ( (endpointDescriptor.bInterval == 0) || (endpointDescriptor.bInterval > 16) )
sprintf(temporaryString, " else
sprintf(temporaryString, " (endpointDescriptor.bInterval > 3 ? (1 << (endpointDescriptor.bInterval-1))/8 : endpointDescriptor.bInterval * 125), endpointDescriptor.bInterval > 3?"msecs":"microsecs" );
}
if ( isoch )
{
if ( (endpointDescriptor.bInterval == 0) || (endpointDescriptor.bInterval > 16) )
sprintf(temporaryString, "Illegal value for bInterval for a hi-speed/SuperSpeed isoch endpoint: else
sprintf(temporaryString, " endpointDescriptor.bInterval > 3 ? (1 << (endpointDescriptor.bInterval-1))/8 : endpointDescriptor.bInterval * 125, endpointDescriptor.bInterval > 3?"msecs":"microsecs" );
}
}
else
{
if ( isoch )
if ( (endpointDescriptor.bInterval == 0) || (endpointDescriptor.bInterval > 16) )
sprintf(temporaryString, "Illegal value for bInterval for a full speed isoch endpoint: else
sprintf(temporaryString, " else
sprintf(temporaryString, " }
if ( printPollingInterval )
[thisDevice addProperty:"Polling Interval:" withValue:temporaryString atDepth:ENDPOINT_LEVEL];
}
+ (void)decodeBytesCompanion:(Byte *)p forDevice:(BusProbeDevice *)thisDevice endpoint:(UInt8) epType {
IOUSBSuperSpeedEndpointCompanionDescriptor * epCompanionDescriptor = (IOUSBSuperSpeedEndpointCompanionDescriptor*)p;
char buf[128];
// Only defined for USB 3.0
if ( ([thisDevice usbRelease] != kUSBRel30) )
{
return;
}
[thisDevice addProperty:"SuperSpeed Endpoint Companion" withValue:"" atDepth:ENDPOINT_LEVEL];
if (epCompanionDescriptor->bMaxBurst > 15)
{
sprintf(buf, "Illegal value of [thisDevice addProperty:"bMaxBurst:" withValue:buf atDepth:ENDPOINT_LEVEL+1];
}
else
{
sprintf(buf, " [thisDevice addProperty:"bMaxBurst:" withValue:buf atDepth:ENDPOINT_LEVEL+1];
}
switch (epType)
{
case kUSBBulk:
if ( epCompanionDescriptor->bmAttributes > 16 )
{
sprintf(buf, "Illegal value of [thisDevice addProperty:"bmAttributes:" withValue:buf atDepth:ENDPOINT_LEVEL+1];
}
else
{
sprintf(buf, " [thisDevice addProperty:"bmAttributes:" withValue:buf atDepth:ENDPOINT_LEVEL+1];
}
break;
case kUSBControl:
if ( epCompanionDescriptor->bmAttributes != 0 )
{
sprintf(buf, "Illegal value of [thisDevice addProperty:"bmAttributes:" withValue:buf atDepth:ENDPOINT_LEVEL+1];
}
else
{
[thisDevice addProperty:"bmAttributes:" withValue:"0" atDepth:ENDPOINT_LEVEL+1];
}
case kUSBInterrupt:
case kUSBIsoc:
if ( epCompanionDescriptor->bmAttributes > 2 )
{
sprintf(buf, "Illegal value of [thisDevice addProperty:"bmAttributes:" withValue:buf atDepth:ENDPOINT_LEVEL+1];
}
else
{
sprintf(buf, " [thisDevice addProperty:"bmAttributes:" withValue:buf atDepth:ENDPOINT_LEVEL+1];
}
}
if ( epType == kUSBInterrupt || epType == kUSBIsoc )
{
sprintf(buf, " [thisDevice addProperty:"wBytesPerInterval:" withValue:buf atDepth:ENDPOINT_LEVEL+1];
}
}
@end