Exemplo n.º 1
0
// this method will override the Platform specific implementation of joinPMtree
// it will cause any IOUSBDevice and IOUSBInterface clients to join the IOPower tree as
// children of the IOUSHubPolicyMaker for the hub to which they are attached
void
IOUSBNub::joinPMtree ( IOService * driver )
{
	IOUSBHubPolicyMaker			*hubPolicyMaker = NULL;
	IOUSBDevice					*device = OSDynamicCast(IOUSBDevice, this);
	IOUSBInterface				*interface = NULL;
	
	
	// we should be either an IOUSBDevice or an IOUSBInterface
	if (device)
		hubPolicyMaker = device->GetHubParent();
	else
	{
		interface = OSDynamicCast(IOUSBInterface, this);

		if (interface && interface->GetDevice())
			hubPolicyMaker = interface->GetDevice()->GetHubParent();
	}

	if (hubPolicyMaker)
	{
		hubPolicyMaker->joinPMtree(driver);
	}
	else
	{
		USBLog(1, "%s[%p]::joinPMtree - no hub policy maker - calling through to super::joinPMtree", getName(), this);
		super::joinPMtree(driver);
	}
	
}
bool com_yaqinking_MyFirstUSBDriver::start(IOService *provider)
{
    IOUSBInterface* interface;
    IOUSBFindEndpointRequest request;
    IOUSBPipe* pipe = NULL;
    
    IOLog("%s(%p)::start \n",getName(),this);
    
    if (!super::start(provider)) {
        return false;
    }
    
    interface = OSDynamicCast(IOUSBInterface, provider);
    if (interface == NULL) {
        IOLog("%s(%p)::start -> provider not a IOUSBInterface \n",getName(),this);
        return false;
    }
    
    request.type = kUSBBulk;
    request.direction = kUSBOut;
    pipe = interface->FindNextPipe(NULL, &request,true);
    if (pipe) {
        logEndPoint(pipe);
        pipe->release();
    }
    return true;
}
Exemplo n.º 3
0
bool AppleUSBCDC::confirmControl(UInt8 subClass, IOUSBInterface *CInterface)
{
    IOUSBFindInterfaceRequest	req;
    IOUSBInterface		*Comm;
    UInt8			intSubClass;
    bool			driverOK = false;

    XTRACE(this, subClass, 0, "confirmControl");
    
        // We need to look for CDC interfaces of the specified subclass
    
    req.bInterfaceClass	= kUSBCommunicationClass;
//    req.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
	req.bInterfaceSubClass = subClass;
    req.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
    req.bAlternateSetting = kIOUSBFindInterfaceDontCare;
    
    Comm = fpDevice->FindNextInterface(NULL, &req);
    if (!Comm)
    {
        XTRACE(this, 0, 0, "confirmDriver - Finding the first CDC interface failed");
        return false;
    }

    while (Comm)
    {
        intSubClass = Comm->GetInterfaceSubClass();
        if (intSubClass == subClass)					// Just to make sure...
        {
			XTRACE(this, Comm->GetInterfaceNumber(), CInterface->GetInterfaceNumber(), "confirmControl - Checking interfaces");
            if (Comm == CInterface)
			{
				driverOK = true;
				break;
			}
        }

            // see if there's another CDC interface
            
		req.bInterfaceClass = kUSBCommunicationClass;
//		req.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
		req.bInterfaceSubClass = subClass;
		req.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
		req.bAlternateSetting = kIOUSBFindInterfaceDontCare;
            
        Comm = fpDevice->FindNextInterface(Comm, &req);
        if (!Comm)
        {
            XTRACE(this, 0, 0, "confirmControl - No more CDC interfaces");
        }
    }
    
    return driverOK;

}/* end confirmControl */
Exemplo n.º 4
0
bool HoRNDISUSBInterface::start(IOService *provider) {
	IOUSBInterface *intf;

	intf = OSDynamicCast(IOUSBInterface, provider);
	if (!intf) {
		LOG(V_ERROR, "cast to IOUSBInterface failed?");
		return false;
	}
	
	fpDevice = intf->GetDevice();
	
	return HoRNDIS::start(provider);
}
Exemplo n.º 5
0
bool XboxOneControllerDriver::handleStart(IOService *provider)
{
	IOUSBInterface* interface = nullptr;
	IOUSBPipe* interruptPipe = nullptr;
	IOReturn ior = kIOReturnSuccess;
	
	IOUSBFindEndpointRequest pipeRequest = {
		.type = kUSBInterrupt,
		.direction = kUSBOut,
	};
	
	// Apple says you should call super::handleStart at the *beginning* of the method.
	if (!super::handleStart(provider))
	{
		goto cleanup;
	}
	
	// Paranoid check: is it the correct kind of object?
	interface = OSDynamicCast(IOUSBInterface, provider);
	if (interface == nullptr)
	{
		IO_LOG_DEBUG("IOUSBHIDDriver is handling start on an object that's not a IOUSBInterface??");
		goto cleanup;
	}
	
	// Find the pipe through which we have to send the hello message.
	// This is redundant with work that IOUSBHIDDriver already did, but there are no accessors.
	interruptPipe = interface->FindNextPipe(nullptr, &pipeRequest);
	if (interruptPipe == nullptr)
	{
		IO_LOG_DEBUG("No interrupt pipe found on controller");
		goto cleanup;
	}
	
	// `sendHello` needs _interruptPipe to be set, but only retain it if it succeeds.
	_interruptPipe = interruptPipe;
	ior = sendHello();
	if (ior != kIOReturnSuccess)
	{
		IO_LOG_DEBUG("Couldn't send hello message: %08x", ior);
		_interruptPipe = nullptr;
		goto cleanup;
	}
	
	_interruptPipe->retain();
	
cleanup:
	return _interruptPipe != nullptr;
}
// Start device
bool WirelessGamingReceiver::start(IOService *provider)
{
    const IOUSBConfigurationDescriptor *cd;
    IOUSBFindInterfaceRequest interfaceRequest;
    IOUSBFindEndpointRequest pipeRequest;
    IOUSBInterface *interface;
    int iConnection, iOther, i;
    
    if (!IOService::start(provider))
    {
//        IOLog("start - superclass failed\n");
        return false;
    }

    device = OSDynamicCast(IOUSBDevice, provider);
    if (device == NULL)
    {
//        IOLog("start - invalid provider\n");
        goto fail;
    }

    // Check for configurations
    if (device->GetNumConfigurations() < 1)
    {
        device = NULL;
//        IOLog("start - device has no configurations!\n");
        goto fail;
    }
    
    // Set configuration
    cd = device->GetFullConfigurationDescriptor(0);
    if (cd == NULL)
    {
        device = NULL;
//        IOLog("start - couldn't get configuration descriptor\n");
        goto fail;
    }
    
    if (!device->open(this))
    {
        device = NULL;
//        IOLog("start - failed to open device\n");
        goto fail;
    }
    if (device->SetConfiguration(this, cd->bConfigurationValue, true) != kIOReturnSuccess)
    {
//        IOLog("start - unable to set configuration\n");
        goto fail;
    }
        
    for (i = 0; i < WIRELESS_CONNECTIONS; i++)
    {
        connections[i].controller = NULL;
        connections[i].controllerIn = NULL;
        connections[i].controllerOut = NULL;
        connections[i].other = NULL;
        connections[i].otherIn = NULL;
        connections[i].otherOut = NULL;
        connections[i].inputArray = NULL;
        connections[i].service = NULL;
        connections[i].controllerStarted = false;
    }
    
    pipeRequest.interval = 0;
    pipeRequest.maxPacketSize = 0;
    pipeRequest.type = kUSBInterrupt;
    interfaceRequest.bInterfaceClass = kIOUSBFindInterfaceDontCare;
    interfaceRequest.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
    interfaceRequest.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
    interfaceRequest.bAlternateSetting = 0;
    interface = NULL;
    iConnection = 0;
    iOther = 0;
    while ((interface = device->FindNextInterface(interface, &interfaceRequest)) != NULL)
    {
        switch(interface->GetInterfaceProtocol())
        {
            case 129:   // Controller
                if (!interface->open(this))
                {
//                    IOLog("start: Failed to open control interface\n");
                    goto fail;
                }
                connections[iConnection].controller = interface;
                pipeRequest.direction = kUSBIn;
                connections[iConnection].controllerIn = interface->FindNextPipe(NULL, &pipeRequest);
                if (connections[iConnection].controllerIn == NULL)
                {
//                    IOLog("start: Failed to open control input pipe\n");
                    goto fail;
                }
                else
                    connections[iConnection].controllerIn->retain();
                pipeRequest.direction = kUSBOut;
                connections[iConnection].controllerOut = interface->FindNextPipe(NULL, &pipeRequest);
                if (connections[iConnection].controllerOut == NULL)
                {
//                    IOLog("start: Failed to open control output pipe\n");
                    goto fail;
                }
                else
                    connections[iConnection].controllerOut->retain();
                iConnection++;
                break;
            case 130:   // It is a mystery
                if (!interface->open(this))
                {
//                    IOLog("start: Failed to open mystery interface\n");
                    goto fail;
                }
                connections[iOther].other = interface;
                pipeRequest.direction = kUSBIn;
                connections[iOther].otherIn = interface->FindNextPipe(NULL, &pipeRequest);
                if (connections[iOther].otherIn == NULL)
                {
//                    IOLog("start: Failed to open mystery input pipe\n");
                    goto fail;
                }
                else
                    connections[iOther].otherIn->retain();
                pipeRequest.direction = kUSBOut;
                connections[iOther].otherOut = interface->FindNextPipe(NULL, &pipeRequest);
                if (connections[iOther].otherOut == NULL)
                {
//                    IOLog("start: Failed to open mystery output pipe\n");
                    goto fail;
                }
                else
                    connections[iOther].otherOut->retain();
                iOther++;
                break;
            default:
//                IOLog("start: Ignoring interface (protocol %d)\n", interface->GetInterfaceProtocol());
                break;
        }
    }
    
    if (iConnection != iOther)
        IOLog("start - interface mismatch?\n");
    connectionCount = iConnection;
    
    for (i = 0; i < connectionCount; i++)
    {
        connections[i].inputArray = OSArray::withCapacity(5);
        if (connections[i].inputArray == NULL)
        {
//            IOLog("start: Failed to allocate packet buffer %d\n", i);
            goto fail;
        }
        if (!QueueRead(i))
        {
//            IOLog("start: Failed to start read %d\n", i);
            goto fail;
        }
    }
    
//    IOLog("start: Transform and roll out (%d interfaces)\n", connectionCount);
    return true;
    
fail:
    ReleaseAll();
    return false;
}
//
// start
// when this method is called, I have been selected as the driver for this device.
// I can still return false to allow a different driver to load
//
bool 
local_IOath3kfrmwr::start(IOService *provider)
{
    IOReturn 				err;
    const IOUSBConfigurationDescriptor *cd;
    
    // Do all the work here, on an IOKit matching thread.
    
    // 0.1 Get my USB Device
    DEBUG_LOG("%s(%p)::start!\n", getName(), this);
    pUsbDev = OSDynamicCast(IOUSBDevice, provider);
    if(!pUsbDev) 
    {
        DEBUG_LOG("%s(%p)::start - Provider isn't a USB device!!!\n", getName(), this);
        return false;
    }

    // 0.2 Reset the device
    err = pUsbDev->ResetDevice();
    if (err)
    {
        DEBUG_LOG("%s(%p)::start - failed to reset the device\n", getName(), this);
        pUsbDev->close(this);
        return false;
    } else IOLog("%s(%p)::start: device reset\n", getName(), this);
    
    // 0.3 Find the first config/interface
    int numconf = 0;
    if ((numconf = pUsbDev->GetNumConfigurations()) < 1)
    {
        DEBUG_LOG("%s(%p)::start - no composite configurations\n", getName(), this);
        return false;
    } else DEBUG_LOG("%s(%p)::start: num configurations %d\n", getName(), this, numconf);
        
    cd = pUsbDev->GetFullConfigurationDescriptor(0);
    
    // Set the configuration to the first config
    if (!cd)
    {
        DEBUG_LOG("%s(%p)::start - no config descriptor\n", getName(), this);
        return false;
    }
	
    // 1.0 Open the USB device
    if (!pUsbDev->open(this))
    {
        DEBUG_LOG("%s(%p)::start - unable to open device for configuration\n", getName(), this);
        return false;
    }
    
    // 1.1 Set the configuration to the first config
    err = pUsbDev->SetConfiguration(this, cd->bConfigurationValue, true);
    if (err)
    {
        DEBUG_LOG("%s(%p)::start - unable to set the configuration\n", getName(), this);
        pUsbDev->close(this);
        return false;
    }
    
    DEBUG_LOG("%s(%p)::start - UPLOADED - %c\n", getName(), this,uploaded);
    //Uploading only one time
    if (!uploaded) {
        
    
    // 1.2 Get the status of the USB device (optional, for diag.)
    USBStatus status;
    err = pUsbDev->GetDeviceStatus(&status);
    if (err)
    {
        DEBUG_LOG("%s(%p)::start - unable to get device status\n", getName(), this);
        pUsbDev->close(this);
        return false;
    } else IOLog("%s(%p)::start: device status %d\n", getName(), this, (int)status);

    // 2.0 Find the interface for bulk endpoint transfers
    IOUSBFindInterfaceRequest request;
    request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
    request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
    request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
    request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
    
    IOUSBInterface * intf = pUsbDev->FindNextInterface(NULL, &request);
    if (!intf) {
        DEBUG_LOG("%s(%p)::start - unable to find interface\n", getName(), this);
        pUsbDev->close(this);
        return false;
    }

    // 2.1 Open the interface
    if (!intf->open(this))
    {
        DEBUG_LOG("%s(%p)::start - unable to open interface\n", getName(), this);
        pUsbDev->close(this);
        return false;
    }

    // 2.2 Get info on endpoints (optional, for diag.)
    int numep = intf->GetNumEndpoints();
    DEBUG_LOG("%s(%p)::start: interface has %d endpoints\n", getName(), this, numep);
    
    UInt8 transferType = 0;
    UInt16 maxPacketSize = 0;
    UInt8 interval = 0;
    err = intf->GetEndpointProperties(0, 0x02, kUSBOut, &transferType, &maxPacketSize, &interval);
    if (err) {
        DEBUG_LOG("%s(%p)::start - failed to get endpoint 2 properties\n", getName(), this);
        intf->close(this);
        pUsbDev->close(this);
        return false;    
    } else DEBUG_LOG("%s(%p)::start: EP2 %d %d %d\n", getName(), this, transferType, maxPacketSize, interval);
    
    err = intf->GetEndpointProperties(0, 0x01, kUSBIn, &transferType, &maxPacketSize, &interval);
    if (err) {
        DEBUG_LOG("%s(%p)::start - failed to get endpoint 1 properties\n", getName(), this);
        intf->close(this);
        pUsbDev->close(this);
        return false;    
    } else {DEBUG_LOG("%s(%p)::start: EP1 %d %d %d\n", getName(), this, transferType, maxPacketSize, interval);
        }

    // 2.3 Get the pipe for bulk endpoint 2 Out
    IOUSBPipe * pipe = intf->GetPipeObj(0x02);
    if (!pipe) {
        DEBUG_LOG("%s(%p)::start - failed to find bulk out pipe\n", getName(), this);
        intf->close(this);
        pUsbDev->close(this);
        return false;    
    }
    /*  // TODO: Test the alternative way to do it:
     IOUSBFindEndpointRequest pipereq;
     pipereq.type = kUSBBulk;
     pipereq.direction = kUSBOut;
     pipereq.maxPacketSize = BULK_SIZE;
     pipereq.interval = 0;
     IOUSBPipe *pipe = intf->FindNextPipe(NULL, &pipereq);
     pipe = intf->FindNextPipe(pipe, &pipereq);
     if (!pipe) {
     DEBUG_LOG("%s(%p)::start - failed to find bulk out pipe 2\n", getName(), this);
     intf->close(this);
     pUsbDev->close(this);
     return false;    
     }
     */

    
    // 3.0 Send request to Control Endpoint to initiate the firmware transfer
    IOUSBDevRequest ctlreq;
    ctlreq.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBDevice);
    ctlreq.bRequest = USB_REQ_DFU_DNLOAD;
    ctlreq.wValue = 0;
    ctlreq.wIndex = 0;
    ctlreq.wLength = 20;
    ctlreq.pData = firmware_buf;

#if 0  // Trying to troubleshoot the problem after Restart (with OSBundleRequired Root)
    for (int irep = 0; irep < 5; irep++) { // retry on error
        err = pUsbDev->DeviceRequest(&ctlreq); // (synchronous, will block)
        if (err)
            DEBUG_LOG("%s(%p)::start - failed to initiate firmware transfer (%d), retrying (%d)\n", getName(), this, err, irep+1);
        else
            break;
    }
#else
    err = pUsbDev->DeviceRequest(&ctlreq); // (synchronous, will block)
#endif
    if (err) {
        DEBUG_LOG("%s(%p)::start - failed to initiate firmware transfer (%d)\n", getName(), this, err);
        intf->close(this);
        pUsbDev->close(this);
        return false;
    }

    // 3.1 Create IOMemoryDescriptor for bulk transfers
    char buftmp[BULK_SIZE];
    IOMemoryDescriptor * membuf = IOMemoryDescriptor::withAddress(&buftmp, BULK_SIZE, kIODirectionNone);
    if (!membuf) {
        DEBUG_LOG("%s(%p)::start - failed to map memory descriptor\n", getName(), this);
        intf->close(this);
        pUsbDev->close(this);
        return false; 
    }
    err = membuf->prepare();
    if (err) {
        DEBUG_LOG("%s(%p)::start - failed to prepare memory descriptor\n", getName(), this);
        intf->close(this);
        pUsbDev->close(this);
        return false; 
    }
    
    // 3.2 Send the rest of firmware to the bulk pipe
    char * buf = firmware_buf;
    int size = sizeof(firmware_buf); 
    buf += 20;
    size -= 20;
    int ii = 1;
    while (size) {
        int to_send = size < BULK_SIZE ? size : BULK_SIZE; 
        
        memcpy(buftmp, buf, to_send);
        err = pipe->Write(membuf, 10000, 10000, to_send);
        if (err) {
            DEBUG_LOG("%s(%p)::start - failed to write firmware to bulk pipe (%d)\n", getName(), this, ii);
            intf->close(this);
            pUsbDev->close(this);
            return false; 
        }
        buf += to_send;
        size -= to_send;
        ii++;
    }
    IOLog("%s(%p)::start: firmware was sent to bulk pipe\n", getName(), this);
    
    err = membuf->complete();
    if (err) {
        DEBUG_LOG("%s(%p)::start - failed to complete memory descriptor\n", getName(), this);
        intf->close(this);
        pUsbDev->close(this);
        uploaded = false;
        return false; 
    }

    /*  // TODO: Test the alternative way to do it:
     IOMemoryDescriptor * membuf = IOMemoryDescriptor::withAddress(&firmware_buf[20], 246804-20, kIODirectionNone); // sizeof(firmware_buf)
     if (!membuf) {
     DEBUG_LOG("%s(%p)::start - failed to map memory descriptor\n", getName(), this);
     intf->close(this);
     pUsbDev->close(this);
     return false; 
     }
     err = membuf->prepare();
     if (err) {
     DEBUG_LOG("%s(%p)::start - failed to prepare memory descriptor\n", getName(), this);
     intf->close(this);
     pUsbDev->close(this);
     return false; 
     }
     
     //err = pipe->Write(membuf);
     err = pipe->Write(membuf, 10000, 10000, 246804-20, NULL);
     if (err) {
     DEBUG_LOG("%s(%p)::start - failed to write firmware to bulk pipe\n", getName(), this);
     intf->close(this);
     pUsbDev->close(this);
     return false; 
     }
     DEBUG_LOG("%s(%p)::start: firmware was sent to bulk pipe\n", getName(), this);
     */
    
    
    // 4.0 Get device status (it fails, but somehow is important for operational device)
    err = pUsbDev->GetDeviceStatus(&status);
    if (err)
    {
        DEBUG_LOG("%s(%p)::start - unable to get device status\n", getName(), this);
        intf->close(this);
        pUsbDev->close(this);
        
        DEBUG_LOG("%s(%p)::start - Firmware Uploaded State Changed to - %c\n", getName(), this,uploaded);
        // Set the Upload State
        uploaded = true;
        
        return false;
    } else {DEBUG_LOG("%s(%p)::start: device status %d\n", getName(), this, (int)status);
    
    }
    
    // Close the interface
    intf->close(this);
        
    DEBUG_LOG("%s(%p)::start - Firmware Uploaded State Changed to - %c\n", getName(), this,uploaded);
    // Set the Upload State
        uploaded = true;
    }
    else {
        IOLog("%s(%p)::Firmware already uploaded\n", getName(), this);
    }
    
    // Close the USB device
    pUsbDev->close(this);
    return false;  // return false to allow a different driver to load
}
Exemplo n.º 8
0
bool AppleUSBCDC::confirmDriver(UInt8 subClass, UInt8 dataInterface)
{
    IOUSBFindInterfaceRequest	req;
    IOUSBInterface		*Comm;
    UInt8			intSubClass;
	UInt8			controlInterfaceNumber;
    bool			driverOK = false;

    XTRACE(this, subClass, dataInterface, "confirmDriver");
    
        // We need to look for CDC interfaces of the specified subclass
    
    req.bInterfaceClass	= kUSBCommunicationClass;
//    req.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
	req.bInterfaceSubClass = subClass;
    req.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
    req.bAlternateSetting = kIOUSBFindInterfaceDontCare;
    
    Comm = fpDevice->FindNextInterface(NULL, &req);
    if (!Comm)
    {
        XTRACE(this, 0, 0, "confirmDriver - Finding the first CDC interface failed");
        return false;
    }

    while (Comm)
    {
		controlInterfaceNumber = Comm->GetInterfaceNumber();
        intSubClass = Comm->GetInterfaceSubClass();
        if (intSubClass == subClass)					// Just to make sure...
        {
            switch (intSubClass)
            {
                case kUSBAbstractControlModel:
                    driverOK = checkACM(Comm, controlInterfaceNumber, dataInterface);
                    break;
                case kUSBEthernetControlModel:
                    driverOK = checkECM(Comm, controlInterfaceNumber, dataInterface);
                    break;
                case kUSBWirelessHandsetControlModel:
                    driverOK = checkWMC(Comm, controlInterfaceNumber, dataInterface);
                    break;
                case kUSBDeviceManagementModel:
                    driverOK = checkDMM(Comm, controlInterfaceNumber, dataInterface);
                    break;
                case kUSBEthernetEmulationModel:
                        // There's only one interface for EEM so the data and the control interface are the same
                        // May need to revisit this
                    
                    if (controlInterfaceNumber == dataInterface)
                    {
                        driverOK = true; 
                    }
                    break;
				case kUSBNetworkControlModel:
					driverOK = checkMBIM(Comm, controlInterfaceNumber, dataInterface);
                    break;
				case kUSBMobileBroadbandInterfaceModel:
					driverOK = checkMBIM(Comm, controlInterfaceNumber, dataInterface);
                    break;
                default:
                    break;
            }
        }
        
        if (driverOK)
        {
            XTRACE(this, 0, 0, "confirmDriver - Interface confirmed");
            break;
        }

            // see if there's another CDC interface
            
        req.bInterfaceClass = kUSBCommunicationClass;
//		req.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
		req.bInterfaceSubClass = subClass;
		req.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
		req.bAlternateSetting = kIOUSBFindInterfaceDontCare;
            
        Comm = fpDevice->FindNextInterface(Comm, &req);
        if (!Comm)
        {
            XTRACE(this, 0, 0, "confirmDriver - No more CDC interfaces");
        }
    }
    
    return driverOK;

}/* end confirmDriver */