1/* 2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 cc -fno-rtti -fno-exceptions -fcheck-new -fvtable-thunks -I.. -I../../BUILD/obj/EXPORT_HDRS/libkern -I../../BUILD/obj/EXPORT_HDRS/osfmk USBTest.cpp ../../BUILD/obj/RELEASE_PPC/IOKit/User/libIOKit.A.dylib -o USBTest 25*/ 26 27#include <ctype.h> 28#include <stdlib.h> 29#include <stdio.h> 30 31#include <IOKit/IOLib.h> 32#include <IOKit/IOKitLib.h> 33#include <IOKit/IOContainers.h> 34#include <IOKit/IOSerialize.h> 35#include <IOKit/usb/IOUSBLib.h> 36 37mach_port_t master_device_port; 38 39void printUSBInterface(IOUSBInterface *intf) 40{ 41 int i; 42 int nEP = intf->descriptor->numEndpoints; 43 printf("%d endpoints\n", nEP); 44 45 for(i=0; i<nEP; i++) { 46 IOUSBEndpoint *ep = intf->endpoints[i]; 47 printf("ep #%d, dir %d, type %d, maxPack %d\n", 48 ep->number, ep->direction, ep->transferType, 49 ep->maxPacketSize); 50 } 51} 52 53void processDevice(IOUSBIteratorRef enumer) 54{ 55 kern_return_t kr2; 56 IOUSBDeviceDescriptor desc; 57 IOUSBInterfaceDescriptor intf; 58 59 kr2 = IOUSBGetDeviceDescriptor(enumer, &desc, sizeof(desc)); 60 if (kr2) { 61 printf("IOUSBGetDeviceDescriptor failed, kr=%d\n", kr2); 62 return; 63 } 64 printf("Device Descriptor\n------------\n"); 65 printf("length = %d\n", desc.length); 66 printf("descType = %d\n", desc.descType); 67 printf("usbRel = %d\n", desc.usbRel); 68 printf("deviceClass = %d\n", desc.deviceClass); 69 printf("deviceSubClass = %d\n", desc.deviceSubClass); 70 printf("protocol = %d\n", desc.protocol); 71 printf("maxPacketSize = %d\n", desc.maxPacketSize); 72 printf("vendor = %d\n", desc.vendor); 73 printf("product = %d\n", desc.product); 74 printf("devRel = %d\n", desc.devRel); 75 printf("manuIdx = %d\n", desc.manuIdx); 76 printf("prodIdx = %d\n", desc.prodIdx); 77 printf("serialIdx = %d\n", desc.serialIdx); 78 printf("numConf = %d\n", desc.numConf); 79 80 81 82 kr2 = IOUSBGetInterfaceDescriptor(enumer, &intf, sizeof(intf)); 83 if (kr2) { 84 UInt8 conf = 123; 85 IOUSBDeviceRef dev; 86 printf("IOUSBGetInterfaceDescriptor failed, kr=%x\n", kr2); 87 88 kr2 = IOUSBNewDeviceRef( enumer, &dev); 89 90 if(kIOReturnSuccess != kr2) { 91 printf("IOUSBNewDeviceRef: err = %x\n", kr2); 92 } 93 else { 94 kr2 = IOUSBGetConfiguration(dev, &conf); 95 if(kIOReturnSuccess == kr2) 96 printf("IOUSBGetConfiguration: conf = %d\n", conf); 97 else 98 printf("IOUSBGetConfiguration: err = %x\n", kr2); 99 if(0 == conf || kIOReturnSuccess != kr2) { 100 conf = 1; 101 kr2 = IOUSBSetConfiguration(dev, conf); 102 if(kIOReturnSuccess == kr2) 103 printf("IOUSBSetConfiguration: conf = %d\n", conf); 104 else 105 printf("IOUSBSetConfiguration: err = %x\n", kr2); 106 kr2 = IOUSBGetConfiguration(dev, &conf); 107 if(kIOReturnSuccess == kr2) 108 printf("IOUSBGetConfiguration: conf = %d\n", conf); 109 else 110 printf("IOUSBGetConfiguration: err = %x\n", kr2); 111 } 112 // Get full configuration 113 char hack[1024]; 114 IOUSBConfigurationDescriptorPtr conf; 115 kr2 = IOUSBGetConfigDescriptor(dev, 0, &conf); 116 if(kIOReturnSuccess == kr2) { 117 printf("IOUSBGetConfigDescriptor(%d) %x %x %x %x %x %x %x\n", 118 USBToHostWord(conf->totalLength), conf->length, 119 conf->descriptorType, conf->numInterfaces, 120 conf->configValue, 121 conf->configStrIndex, conf->attributes, conf->maxPower); 122 } 123 else 124 printf("IOUSBGetConfigDescriptor: err = %x\n", kr2); 125 126 // Try to get first string descriptor 127 UInt16 size = sizeof(hack); 128 kr2 = IOUSBDeviceRequest(dev, 129 USBMakeBMRequestType(kUSBIn, kUSBStandard, kUSBDevice), 130 kUSBRqGetDescriptor, (kUSBStringDesc << 8) | 1, 0x409, 131 hack, &size); 132 if(kIOReturnSuccess == kr2) { 133 int i; 134 printf("String 1(%d/%d):", size, hack[0]); 135 for(i=2; i<hack[0]; i+=2) 136 printf("%c", hack[i]); 137 printf("\n"); 138 } 139 else 140 printf("IOUSBDeviceRequest: err = %x\n", kr2); 141 142 IOUSBInterface *ioint; 143 IOUSBFindInterfaceRequest freq; 144 145 freq.theClass = 0; // requested class, 0 = don't care 146 freq.subClass = 0; // requested subclass; 0 = don't care 147 freq.protocol = 0; // requested protocol; 0 = don't care 148 freq.busPowered = 0; // 1 = not bus powered, 2 = bus powered, 149 // 0 = don't care 150 freq.selfPowered = 0; // 1 = not self powered, 2 = self powered, 151 // 0 = don't care 152 freq.remoteWakeup = 0; // 1 = doesn't support remote wakeup; 2 = does 153 // 0 = don't care 154 freq.reserved = 0; 155 freq.maxPower = 0; // max power in 2ma increments; 0 = don't care 156 freq.alternateIndex = 0; // alternate #; 0xff = find first only 157 freq.configIndex = 0; // 0 = start at beginning 158 freq.interfaceIndex = 0; // 0 = start at beginning 159 160 while(ioint = IOUSBFindNextInterface(dev, &freq)) { 161 printUSBInterface(ioint); 162 163 IOUSBDisposeInterface(ioint); 164 } 165 // test vendor specific read/write for ISVF 166 if(desc.vendor == 0xc706) { 167 printf("Found ImageStudioVF!\n"); 168 size = 3; 169 kr2 = IOUSBDeviceRequest(dev, 170 USBMakeBMRequestType(kUSBIn, kUSBVendor, kUSBDevice), 171 4, 0, 0, 172 hack, &size); 173 if(kIOReturnSuccess == kr2) { 174 int i; 175 printf("Read %d:", size); 176 for(i=0; i<size; i++) 177 printf("%d ", hack[i]); 178 printf("\n"); 179 } 180 else { 181 printf("IOUSBDeviceRequest: err = %x\n", kr2); 182 return; 183 } 184 size = 3; 185 hack[0]++; 186 hack[1] += 2; 187 hack[2] += 3; 188 kr2 = IOUSBDeviceRequest(dev, 189 USBMakeBMRequestType(kUSBOut, kUSBVendor, kUSBDevice), 190 4, 0, 0, 191 hack, &size); 192 if(kIOReturnSuccess != kr2) { 193 printf("IOUSBDeviceRequest: err = %x\n", kr2); 194 return; 195 } 196 size = 3; 197 kr2 = IOUSBDeviceRequest(dev, 198 USBMakeBMRequestType(kUSBIn, kUSBVendor, kUSBDevice), 199 4, 0, 0, 200 hack, &size); 201 if(kIOReturnSuccess == kr2) { 202 int i; 203 printf("Now Read %d:", size); 204 for(i=0; i<size; i++) 205 printf("%d ", hack[i]); 206 printf("\n"); 207 } 208 else { 209 printf("IOUSBDeviceRequest: err = %x\n", kr2); 210 return; 211 } 212 213 } 214 IOUSBDisposeRef(dev); 215 } 216 } 217 else { 218 printf("Interface Descriptor\n------------\n"); 219 printf("length = %d\n", intf.length); 220 printf("descType = %d\n", intf.descriptorType); 221 printf("interfaceNumber = %d\n", intf.interfaceNumber); 222 printf("alternateSetting = %d\n", intf.alternateSetting); 223 printf("numEndpoints = %d\n", intf.numEndpoints); 224 printf("interfaceClass = %d\n", intf.interfaceClass); 225 printf("interfaceSubClass = %d\n", intf.interfaceSubClass); 226 printf("interfaceProtocol = %d\n", intf.interfaceProtocol); 227 printf("interfaceStrIndex = %d\n", intf.interfaceStrIndex); 228 229 // See if we have a HID interface, if so open and read the interupt pipe a few times. 230 if(intf.interfaceClass == kUSBHIDClass) { 231 char hack[1024]; 232 UInt16 size; 233 IOUSBDeviceRef dev; 234 IOUSBPipeRef pipe; 235 int i; 236 237 printf("HID Interface\n"); 238 kr2 = IOUSBNewDeviceRef( enumer, &dev); 239 if(kIOReturnSuccess != kr2) 240 return; 241 /* 242 * If a boot device, SetProtocol to Boot protocol 243 * SetIdle to read complete after 24mSec 244 * Open interface's first pipe 245 * Read 8 bytes from pipe 246 * Close pipe 247 */ 248 size = 0; 249 if(1 == intf.interfaceSubClass) { // 1 = Boot Interface subclass 250 kr2 = IOUSBDeviceRequest(dev, 251 USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface), 252 kHIDRqSetProtocol, kHIDBootProtocolValue, 253 intf.interfaceNumber, 254 NULL, &size); 255 } 256 if(kIOReturnSuccess != kr2) { 257 printf("HIDRqSetProtocol: err = %x\n", kr2); 258 return; 259 } 260#if 0 261 size = 0; 262 kr2 = IOUSBDeviceRequest(dev, 263 USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface), 264 kHIDRqSetIdle, (24/4)<<8, intf.interfaceNumber, 265 NULL, &size); 266 if(kIOReturnSuccess != kr2) { 267 printf("HIDRqSetIdle: err = %x\n", kr2); 268 continue; 269 } 270#endif 271 size = 4; 272 kr2 = IOUSBDeviceRequest(dev, 273 USBMakeBMRequestType(kUSBIn, kUSBClass, kUSBInterface), 274 kHIDRqGetReport, kHIDRtInputReport<<8, 275 intf.interfaceNumber, 276 hack, &size); 277 if(kIOReturnSuccess != kr2) { 278 printf("HIDRqGetReport: err = %x\n", kr2); 279 return; 280 } 281 printf("Read %d:%d %d %d %d\n", size, 282 hack[0], hack[1], hack[2], hack[3]); 283 284 IOUSBInterface *ioint; 285 IOUSBFindInterfaceRequest freq; 286 IOUSBEndpoint *ep; 287 288 freq.theClass = intf.interfaceClass; 289 freq.subClass = intf.interfaceSubClass; 290 freq.protocol = intf.interfaceProtocol; 291 freq.busPowered = 0; 292 freq.selfPowered = 0; 293 freq.remoteWakeup = 0; 294 freq.reserved = 0; 295 freq.maxPower = 0; 296 freq.alternateIndex = 0; 297 freq.configIndex = 0; 298 freq.interfaceIndex = 0; 299 300 ioint = IOUSBFindNextInterface(dev, &freq); 301 if(!ioint) { 302 printf("No HID Interfaces found!!\n"); 303 return; 304 } 305 printUSBInterface(ioint); 306 ep = 0; 307 for(i=0; i < ioint->descriptor->numEndpoints; i++) { 308 if(ioint->endpoints[i]->direction == kUSBIn && 309 ioint->endpoints[i]->transferType == kUSBInterrupt) { 310 ep = ioint->endpoints[i]; 311 break; 312 } 313 } 314 if(ep) { 315 kr2 = IOUSBOpenPipe(dev, ep, &pipe); 316 if(kIOReturnSuccess != kr2) { 317 printf("IOUSBOpenPipe: err = %x\n", kr2); 318 IOUSBDisposeRef(dev); 319 return; 320 } 321 for(int i=0; i<4; i++) { 322 UInt32 len = 4; 323 kr2 = IOUSBReadPipe(pipe, hack, &len); 324 if(kIOReturnSuccess != kr2) { 325 printf("IOUSBReadPipe: err = %x\n", kr2); 326 break; 327 } 328 else { 329 printf("Read %d:%d %d %d %d\n", len, 330 hack[0], hack[1], hack[2], hack[3]); 331 } 332 } 333 IOUSBClosePipe(pipe); 334 } 335 IOUSBDisposeInterface(ioint); 336 IOUSBDisposeRef(dev); 337 } 338 } 339} 340int pokeDevices(IOUSBMatch * descMatch) 341{ 342 kern_return_t kr; 343 IOUSBIteratorRef enumer; 344 mach_port_t port; 345 unsigned long int notifyType; 346 unsigned long int ref; 347 struct { 348 mach_msg_header_t msgHdr; 349 OSNotificationHeader notifyHeader; 350 mach_msg_trailer_t trailer; 351 } msg; 352 353 kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port); 354 if(KERN_SUCCESS != kr) { 355 printf("Failed to create port!:%d\n", kr); 356 return kr; 357 } 358 359 kr = IOUSBCreateIterator(master_device_port, port, descMatch, &enumer); 360 if(kIOReturnSuccess != kr) { 361 printf("IOUSBCreateIterator = %d\n", kr); 362 return kr; 363 } 364 365 // First process any devices already connected 366 while(kIOReturnSuccess == IOUSBIteratorNext(enumer)) { 367 processDevice(enumer); 368 } 369 370 // Now wait for a new device (or devices) to appear and 371 // process them. 372 kr = mach_msg(&msg.msgHdr, MACH_RCV_MSG, 373 0, sizeof(msg), port, 0, MACH_PORT_NULL); 374 kr = OSGetNotificationFromMessage( &msg.msgHdr, 0, ¬ifyType, &ref, 375 0, 0 ); 376 377 if(ref == (unsigned long int)enumer) { 378 while(kIOReturnSuccess == IOUSBIteratorNext(enumer)) { 379 processDevice(enumer); 380 } 381 } 382 else 383 printf("Unexpected notification type %d, ref %d\n", 384 notifyType, ref); 385 kr = IOUSBDisposeIterator( enumer); 386 return kr; 387} 388 389int 390main(int argc, char **argv) 391{ 392 kern_return_t kr; 393 394 IOUSBMatch match = { 395 kIOUSBAnyClass, 396 kIOUSBAnySubClass, 397 kIOUSBAnyProtocol, 398 kIOUSBAnyVendor, 399 kIOUSBAnyProduct 400 }; 401 402 if(argc > 1) 403 match.usbClass = atoi(argv[1]); 404 if(argc > 2) 405 match.usbSubClass = atoi(argv[2]); 406 if(argc > 3) 407 match.usbProtocol = atoi(argv[3]); 408 if(argc > 4) 409 match.usbVendor = atoi(argv[4]); 410 if(argc > 5) 411 match.usbProduct = atoi(argv[5]); 412 413 /* 414 * Get master device port 415 */ 416 kr = IOMasterPort(bootstrap_port, 417 &master_device_port); 418 419 if (kr != KERN_SUCCESS) 420 printf("IOMasterPort failed: %lx\n", kr); 421 422 printf("Looking for devices matching class=%d subclass=%d ", 423 match.usbClass, match.usbSubClass); 424 printf("protocol=%d vendor=%d product=%d\n", match.usbProtocol, 425 match.usbVendor, match.usbProduct); 426 pokeDevices(&match); 427} 428 429