示例#1
0
/*
 *  Retrieve a string for a specified string index from the USB device
 *
 *  device      - USB device pointer
 *  stringIndex - String index to retrieve
 *  output      - Output buffer
 *  len         - Output buffer len
 *
 *  returns true or false on error
 */
bool retrieveString(IOUSBDeviceInterface300** device, const unsigned char stringIndex, char* output, const int len)
{
    IOUSBDevRequest request;
    CFStringRef string;
    const UInt8 buf[512];
    
    // Perform a device request to read the string descriptor.
    request.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
    request.bRequest = kUSBRqGetDescriptor;
    request.wValue = (kUSBStringDesc << 8) | stringIndex;
    request.wIndex = 0; // Language (Optionally 0x409 for US English)
    request.wLength = sizeof(buf);
    request.pData = (void *)buf;
    
    bzero((void *)buf, sizeof(buf));
    
    if ((*device)->DeviceRequest(device, &request) == kIOReturnSuccess)
    {
        int length;
        length = buf[0] - 2; // First byte is length (in bytes)
        
        // Convert from UTF-16 Little Endian
        string = CFStringCreateWithBytes(kCFAllocatorDefault,
                                         &buf[2],
                                         length,
                                         kCFStringEncodingUTF16LE,
                                         false);
        
        // To C String
        CFStringGetCString(string, output, len, kCFStringEncodingUTF8);
        CFRelease(string);
    }
    
    return false;
}
void Xbox360Peripheral::SendInit(UInt16 value, UInt16 index)
{
	IOUSBDevRequest controlReq;
	
	controlReq.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBDevice);
	controlReq.bRequest = 0xa9;
	controlReq.wValue = value;
	controlReq.wIndex = index;
	controlReq.wLength = 0;
	controlReq.pData = NULL;
	device->DeviceRequest(&controlReq, 100, 100, NULL);	// Will fail - but device should still act on it
}
void Xbox360Peripheral::SendSpecial(UInt16 value)
{
	IOUSBDevRequest controlReq;

	controlReq.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBInterface);
	controlReq.bRequest = 0x00;
	controlReq.wValue = value;
	controlReq.wIndex = 0x0002;
	controlReq.wLength = 0;
	controlReq.pData = NULL;
	if (device->DeviceRequest(&controlReq, 100, 100, NULL) != kIOReturnSuccess)
		IOLog("Failed to send special message %.4x\n", value);
}
示例#4
0
文件: main.c 项目: aosm/IOUSBFamily
IOReturn AnchorWrite(IOUSBDeviceInterface245 **dev, UInt16 anchorAddress, UInt16 count, UInt8 writeBuffer[])
{
    IOUSBDevRequest 		request;
    
    request.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBDevice);
    request.bRequest = 0xa0;
    request.wValue = anchorAddress;
    request.wIndex = 0;
    request.wLength = count;
    request.pData = writeBuffer;

    return (*dev)->DeviceRequest(dev, &request);
}
示例#5
0
IOReturn
com_apple_AnchorUSB::AnchorWrite(UInt16 anchorAddress, UInt16 count, UInt8 writeBuffer[])
{
    IOUSBDevRequest request;
    
    request.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBDevice);
    request.bRequest = 0xa0;
    request.wValue = anchorAddress;
    request.wIndex = 0;
    request.wLength = count;
    request.pData = writeBuffer;

    return fDevice->DeviceRequest(&request);
} 
示例#6
0
bool Xbox360Peripheral::SendSwitch(bool sendOut)
{
	IOUSBDevRequest controlReq;

	controlReq.bmRequestType = USBmakebmRequestType(sendOut ? kUSBOut : kUSBIn, kUSBVendor, kUSBDevice);
	controlReq.bRequest = 0xa1;
	controlReq.wValue = 0x0000;
	controlReq.wIndex = 0xe416;
	controlReq.wLength = sizeof(chatpadInit);
	controlReq.pData = chatpadInit;
    IOReturn err = device->DeviceRequest(&controlReq, 100, 100, NULL);
    if (err == kIOReturnSuccess)
        return true;

    const char *errStr = stringFromReturn(err);
    IOLog("start - failed to %s chatpad setting (%s)\n", sendOut ? "write" : "read", errStr);
    return false;
}
示例#7
0
IOReturn AppleUSBCDC::reInitDevice()
{
	IOUSBDevRequest req;
    IOReturn		ior = kIOReturnSuccess;
       
    XTRACE(this, 0, 0, "reInitDevice");
	
	req.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBStandard, kUSBDevice);
    req.bRequest = kUSBRqSetConfig;
    req.wValue = fConfig;
    req.wIndex = 0;
    req.wLength = 0;
    req.pData = 0;
    ior = fpDevice->DeviceRequest(&req, 5000, 0);
	if (ior != kIOReturnSuccess)
	{
		XTRACE(this, 0, ior, "reInitDevice - DeviceRequest (SetConfig) error");
	}
    
    return ior;

}/* end reInitDevice */
示例#8
0
int HoRNDIS::rndisCommand(struct rndis_msg_hdr *buf, int buflen) {
	int count;
	int rc = kIOReturnSuccess;
	IOUSBDevRequestDesc rq;
	IOBufferMemoryDescriptor *txdsc = IOBufferMemoryDescriptor::withCapacity(le32_to_cpu(buf->msg_len), kIODirectionOut);
	IOBufferMemoryDescriptor *rxdsc = IOBufferMemoryDescriptor::withCapacity(RNDIS_CMD_BUF_SZ, kIODirectionIn);

	if (buf->msg_type != RNDIS_MSG_HALT && buf->msg_type != RNDIS_MSG_RESET) {
		/* lock? */
		buf->request_id = cpu_to_le32(xid++);
		if (!buf->request_id)
			buf->request_id = cpu_to_le32(xid++);
	}
		
	memcpy(txdsc->getBytesNoCopy(), buf, le32_to_cpu(buf->msg_len));
	rq.bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND;
	rq.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface);
	rq.wValue = 0;
	rq.wIndex = fCommInterface->GetInterfaceNumber();
	rq.pData = txdsc;
	rq.wLength = cpu_to_le32(buf->msg_len);
		
	if ((rc = fCommInterface->DeviceRequest(&rq)) != kIOReturnSuccess)
		goto bailout;
	
	/* Linux polls on the status channel, too; hopefully this shouldn't be needed if we're just talking to Android. */
	
	/* Now we wait around a while for the device to get back to us. */
	for (count = 0; count < 10; count++) {
		struct rndis_msg_hdr *inbuf = (struct rndis_msg_hdr *) rxdsc->getBytesNoCopy();
		IOUSBDevRequestDesc rxrq;
		
		memset(inbuf, 0, RNDIS_CMD_BUF_SZ);
		rxrq.bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
		rxrq.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBClass, kUSBInterface);
		rxrq.wValue = 0;
		rxrq.wIndex = fCommInterface->GetInterfaceNumber();
		rxrq.pData = rxdsc;
		rxrq.wLength = RNDIS_CMD_BUF_SZ;
				
		if ((rc = fCommInterface->DeviceRequest(&rxrq)) != kIOReturnSuccess)
			goto bailout;
		
		if (rxrq.wLenDone < 8) {
			LOG(V_ERROR, "short read on control request?");
			IOSleep(20);
			continue;
		}
		
		if (inbuf->msg_type == (buf->msg_type | RNDIS_MSG_COMPLETION)) {
			if (inbuf->request_id == buf->request_id) {
				if (inbuf->msg_type == RNDIS_MSG_RESET_C)
					break;
				if (inbuf->status == RNDIS_STATUS_SUCCESS) {
					/* ...and copy it out! */
					LOG(V_DEBUG, "RNDIS command completed");
					memcpy(buf, inbuf, le32_to_cpu(rxrq.wLenDone));
					break;
				}
				LOG(V_ERROR, "RNDIS command returned status %08x", inbuf->status);
				rc = -1;
				break;
			} else {
				LOG(V_ERROR, "RNDIS return had incorrect xid?");
			}
		} else {
			switch (inbuf->msg_type) {
				case RNDIS_MSG_INDICATE:
					LOG(V_ERROR, "unsupported: RNDIS_MSG_INDICATE");
					break;
				case RNDIS_MSG_KEEPALIVE:
					LOG(V_ERROR, "unsupported: RNDIS_MSG_KEEPALIVE");
					break;
				default:
					LOG(V_ERROR, "unexpected msg type %08x, msg_len %08x", inbuf->msg_type, inbuf->msg_len);
					break;
			}
		}
		
		IOSleep(20);
	}
	if (count == 10) {
		LOG(V_ERROR, "command timed out?");
		rc = kIOReturnTimeout;
	}
	
bailout:
	txdsc->complete();
	txdsc->release();
	rxdsc->complete();
	rxdsc->release();
	
	return rc;
}
示例#9
0
/** Try out the given device and see if there's a match. Returns 0 on
 * success, -1 on failure.
 */
static int try_device(io_service_t device, usb_handle *handle) {
    kern_return_t kr;
    IOCFPlugInInterface **plugin = NULL;
    IOUSBDeviceInterface500** dev = NULL;
    SInt32 score;
    HRESULT result;
    UInt8 serialIndex;
    UInt32 locationId;

    // Create an intermediate plugin.
    kr = IOCreatePlugInInterfaceForService(device,
            kIOUSBDeviceUserClientTypeID,
            kIOCFPlugInInterfaceID,
            &plugin, &score);

    if ((kr != 0) || (plugin == NULL)) {
        goto error;
    }

    // Now create the device interface.
    result = (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID500),
                                       (LPVOID*)&dev);
    if ((result != 0) || (dev == NULL)) {
        ERR("Couldn't create a device interface (%08x)\n", (int) result);
        goto error;
    }

    /*
     * We don't need the intermediate interface after the device interface
     * is created.
     */
    IODestroyPlugInInterface(plugin);

    // So, we have a device, finally. Grab its vitals.

    kr = (*dev)->GetDeviceVendor(dev, &handle->info.dev_vendor);
    if (kr != 0) {
        ERR("GetDeviceVendor");
        goto error;
    }

    kr = (*dev)->GetDeviceProduct(dev, &handle->info.dev_product);
    if (kr != 0) {
        ERR("GetDeviceProduct");
        goto error;
    }

    kr = (*dev)->GetDeviceClass(dev, &handle->info.dev_class);
    if (kr != 0) {
        ERR("GetDeviceClass");
        goto error;
    }

    kr = (*dev)->GetDeviceSubClass(dev, &handle->info.dev_subclass);
    if (kr != 0) {
        ERR("GetDeviceSubClass");
        goto error;
    }

    kr = (*dev)->GetDeviceProtocol(dev, &handle->info.dev_protocol);
    if (kr != 0) {
        ERR("GetDeviceProtocol");
        goto error;
    }

    kr = (*dev)->GetLocationID(dev, &locationId);
    if (kr != 0) {
        ERR("GetLocationId");
        goto error;
    }
    snprintf(handle->info.device_path, sizeof(handle->info.device_path),
             "usb:%" PRIu32 "X", (unsigned int)locationId);

    kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex);

    if (serialIndex > 0) {
        IOUSBDevRequest req;
        UInt16  buffer[256];

        req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
        req.bRequest = kUSBRqGetDescriptor;
        req.wValue = (kUSBStringDesc << 8) | serialIndex;
        //language ID (en-us) for serial number string
        req.wIndex = 0x0409;
        req.pData = buffer;
        req.wLength = sizeof(buffer);
        kr = (*dev)->DeviceRequest(dev, &req);

        if (kr == kIOReturnSuccess && req.wLenDone > 0) {
            int i, count;

            // skip first word, and copy the rest to the serial string, changing shorts to bytes.
            count = (req.wLenDone - 1) / 2;
            for (i = 0; i < count; i++)
              handle->info.serial_number[i] = buffer[i + 1];
            handle->info.serial_number[i] = 0;
        }
    } else {
        // device has no serial number
        handle->info.serial_number[0] = 0;
    }
    handle->info.writable = 1;

    if (try_interfaces(dev, handle)) {
        goto error;
    }

    (*dev)->Release(dev);
    return 0;

    error:

    if (dev != NULL) {
        (*dev)->Release(dev);
    }

    return -1;
}
示例#10
0
//Gets a new device descriptor.
//Is also used to see if we can talk to the device.
IOKitError::Enum IOKitDevice::GetNewDescriptor(usb_device_t** device, IOUSBDeviceDescriptor& stDeviceDescriptor)
{

    //Set up request for device descriptor
	IOUSBDevRequest      req;
   req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
   req.bRequest      = kUSBRqGetDescriptor;
   req.wValue        = kUSBDeviceDesc << 8;
   req.wIndex        = 0;
   req.wLength       = sizeof(IOUSBDeviceDescriptor);
   req.pData         = &(stDeviceDescriptor);


   
   //// retrieve device descriptors ////
   //device must be open for DeviceRequest
   (*device)->USBDeviceOpen(device);

   
   IOReturn ret = (*device)->DeviceRequest(device, &req);
   if(ret != kIOReturnSuccess)
   {
      int try_unsuspend = 1;

      #if (DeviceVersion >= 320)
      {
         UInt32 info;

         //device may be suspended. unsuspend it and try again
         //IOUSBFamily 320+ provides a way to detect device suspension but earlier versions do not
         (*device)->GetUSBDeviceInformation(device, &info);

         try_unsuspend = info & (1 << kUSBInformationDeviceIsSuspendedBit);
      }
      #endif

      if(try_unsuspend)
      {
         //resume the device
         (*device)->USBDeviceSuspend(device, 0);

         ret = (*device)->DeviceRequest(device, &req);

         //resuspend the device
         (*device)->USBDeviceSuspend(device, 1);
      }
   }
   
   /*
   //!!Would it just be easier to get this information from the IORegistry?
	//Set up request for product description
    IOUSBDevRequest     product_desc_req;
    string_descriptor productDescription;
    product_desc_req.bmRequestType = LIBUSB_ENDPOINT_IN;
    product_desc_req.bRequest      = LIBUSB_REQUEST_GET_DESCRIPTOR;
    product_desc_req.wValue        = (LIBUSB_DT_STRING << 8) | stDeviceDescriptor.iSerialNumber;
    product_desc_req.wIndex        = 0x409;
    product_desc_req.wLength       = sizeof(productDescription);
    product_desc_req.pData         = &productDescription;

   UCHAR aucBlah[255];

	IOReturn product_desc_ret = (*device)->DeviceRequest(device, &product_desc_req);  //!!Is this guaranteed to be null-terminated?
	if(product_desc_ret == kIOReturnSuccess)
   {
      //Convert from unicode to ascii
      int si, di;
      int length = sizeof(productDescription);
      for(di = 0, si = 0; si < productDescription.length; di++, si+=2)
      {
         if(di >= (length - 1))
            break;

         if(productDescription.string[si] == '\0')
         {
            aucBlah[di] = '\0';
            break;
         }

         if(productDescription.string[si + 1]) //high byte
            aucBlah[di] = '?';
         else
            aucBlah[di] = productDescription.string[si];
      }
      aucBlah[di] = '\0';

   }
   else
   {
		aucBlah[0] = '\0';
   }
   */
   
   

   (*device)->USBDeviceClose(device);
	if(ret != kIOReturnSuccess)
	{
      //could not retrieve device descriptor
      return darwin_to_libusb(ret);
   }
   //// end: retrieve device descriptors ////

	return darwin_to_libusb(ret);
}
#include <IOKit/IOLib.h>
#include <IOKit/IOPlatformExpert.h>
#include <IOKit/hidsystem/IOHidUsageTables.h>
#include <IOKit/IOReturn.h>

#define NAME "TM"

// I don't know what these do, but I recorded this communication between
// the iMate driver and the iMate device. And replaying them with a short pause
// between them seems to get the iMate device to do what I want.
#define kNumInitCmds    15
static UInt8 gCmd1[] = {0x0f, 0xfe};
static UInt8 gCmd2[] = {0x07, 0xfe};
static IOUSBDevRequest gInitSequence[kNumInitCmds] =
{
    {USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBInterface), 0x01, 0x0004, 0x00FF, 0, NULL, 0},
    {USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBInterface), 0x01, 0x0002, 0x0000, 0, NULL, 0},
    {USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBInterface), 0x00, 0x0030, 0x0000, 0, NULL, 0},
    {USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBInterface), 0x00, 0x007f, 0x0000, 0, NULL, 0},
    {USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBInterface), 0x00, 0x00ff, 0x0000, 0, NULL, 0},
    {USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBInterface), 0x00, 0x007b, 0x0000, sizeof(gCmd1), gCmd1, 0},
    {USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBInterface), 0x00, 0x00ff, 0x0000, 0, NULL, 0},
    {USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBInterface), 0x00, 0x007f, 0x0000, 0, NULL, 0},
    {USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBInterface), 0x00, 0x00fb, 0x0000, sizeof(gCmd2), gCmd2, 0},
    {USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBInterface), 0x00, 0x007f, 0x0000, 0, NULL, 0},
    {USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBInterface), 0x01, 0x0001, 0x8000, 0, NULL, 0},
    {USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBInterface), 0x01, 0x0004, 0x00FF, 0, NULL, 0},
    {USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBInterface), 0x01, 0x0004, 0x000a, 0, NULL, 0},
    {USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBInterface), 0x01, 0x0003, 0x0001, 0, NULL, 0},
    {USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBInterface), 0x00, 0x007e, 0x0000, 0, NULL, 0}
};
示例#12
0
static void
AndroidInterfaceAdded(void *refCon, io_iterator_t iterator)
{
    kern_return_t            kr;
    io_service_t             usbDevice;
    io_service_t             usbInterface;
    IOCFPlugInInterface      **plugInInterface = NULL;
    IOUSBInterfaceInterface220  **iface = NULL;
    IOUSBDeviceInterface197  **dev = NULL;
    HRESULT                  result;
    SInt32                   score;
    UInt32                   locationId;
    UInt16                   vendor;
    UInt16                   product;
    UInt8                    serialIndex;
    char                     serial[256];
    char                     devpathBuf[64];
    char                     *devpath = NULL;

    while ((usbInterface = IOIteratorNext(iterator))) {
        //* Create an intermediate interface plugin
        kr = IOCreatePlugInInterfaceForService(usbInterface,
                                               kIOUSBInterfaceUserClientTypeID,
                                               kIOCFPlugInInterfaceID,
                                               &plugInInterface, &score);
        IOObjectRelease(usbInterface);
        if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
            DBG("ERR: Unable to create an interface plug-in (%08x)\n", kr);
            continue;
        }

        //* This gets us the interface object
        result = (*plugInInterface)->QueryInterface(plugInInterface,
                CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID*)
                &iface);
        //* We only needed the plugin to get the interface, so discard it
        (*plugInInterface)->Release(plugInInterface);
        if (result || !iface) {
            DBG("ERR: Couldn't query the interface (%08x)\n", (int) result);
            continue;
        }

        //* this gets us an ioservice, with which we will find the actual
        //* device; after getting a plugin, and querying the interface, of
        //* course.
        //* Gotta love OS X
        kr = (*iface)->GetDevice(iface, &usbDevice);
        if (kIOReturnSuccess != kr || !usbDevice) {
            DBG("ERR: Couldn't grab device from interface (%08x)\n", kr);
            continue;
        }

        plugInInterface = NULL;
        score = 0;
        //* create an intermediate device plugin
        kr = IOCreatePlugInInterfaceForService(usbDevice,
                                               kIOUSBDeviceUserClientTypeID,
                                               kIOCFPlugInInterfaceID,
                                               &plugInInterface, &score);
        //* only needed this to find the plugin
        (void)IOObjectRelease(usbDevice);
        if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
            DBG("ERR: Unable to create a device plug-in (%08x)\n", kr);
            continue;
        }

        result = (*plugInInterface)->QueryInterface(plugInInterface,
                CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*) &dev);
        //* only needed this to query the plugin
        (*plugInInterface)->Release(plugInInterface);
        if (result || !dev) {
            DBG("ERR: Couldn't create a device interface (%08x)\n",
                (int) result);
            continue;
        }

        //* Now after all that, we actually have a ref to the device and
        //* the interface that matched our criteria

        kr = (*dev)->GetDeviceVendor(dev, &vendor);
        kr = (*dev)->GetDeviceProduct(dev, &product);
        kr = (*dev)->GetLocationID(dev, &locationId);
        if (kr == 0) {
            snprintf(devpathBuf, sizeof(devpathBuf), "usb:%lX", locationId);
            devpath = devpathBuf;
        }
        kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex);

	if (serialIndex > 0) {
		IOUSBDevRequest req;
		UInt16          buffer[256];
		UInt16          languages[128];

		memset(languages, 0, sizeof(languages));

		req.bmRequestType =
			USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
		req.bRequest = kUSBRqGetDescriptor;
		req.wValue = (kUSBStringDesc << 8) | 0;
		req.wIndex = 0;
		req.pData = languages;
		req.wLength = sizeof(languages);
		kr = (*dev)->DeviceRequest(dev, &req);

		if (kr == kIOReturnSuccess && req.wLenDone > 0) {

			int langCount = (req.wLenDone - 2) / 2, lang;

			for (lang = 1; lang <= langCount; lang++) {

                                memset(buffer, 0, sizeof(buffer));
                                memset(&req, 0, sizeof(req));

				req.bmRequestType =
					USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
				req.bRequest = kUSBRqGetDescriptor;
				req.wValue = (kUSBStringDesc << 8) | serialIndex;
				req.wIndex = languages[lang];
				req.pData = buffer;
				req.wLength = sizeof(buffer);
				kr = (*dev)->DeviceRequest(dev, &req);

				if (kr == kIOReturnSuccess && req.wLenDone > 0) {
					int i, count;

					// skip first word, and copy the rest to the serial string,
					// changing shorts to bytes.
					count = (req.wLenDone - 1) / 2;
					for (i = 0; i < count; i++)
						serial[i] = buffer[i + 1];
					serial[i] = 0;
                                        break;
				}
			}
		}
	}
        (*dev)->Release(dev);

        DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product,
            serial);

        usb_handle* handle = CheckInterface((IOUSBInterfaceInterface**)iface,
                                            vendor, product);
        if (handle == NULL) {
            DBG("ERR: Could not find device interface: %08x\n", kr);
            (*iface)->Release(iface);
            continue;
        }

        DBG("AndroidDeviceAdded calling register_usb_transport\n");
        register_usb_transport(handle, (serial[0] ? serial : NULL), devpath, 1);

        // Register for an interest notification of this device being removed.
        // Pass the reference to our private data as the refCon for the
        // notification.
        kr = IOServiceAddInterestNotification(notificationPort,
                usbInterface,
                kIOGeneralInterest,
                AndroidInterfaceNotify,
                handle,
                &handle->usbNotification);

        if (kIOReturnSuccess != kr) {
            DBG("ERR: Unable to create interest notification (%08x)\n", kr);
        }
    }
}
//
// 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
}
示例#14
0
    IOUSBFindEndpointRequest findEndpointRequest;
    findEndpointRequest.type = type;
    findEndpointRequest.direction = direction;
    if (IOUSBPipe* pipe = m_pInterface->FindNextPipe(NULL, &findEndpointRequest))
    {
        shim->setPipe(pipe);
        return true;
    }
    return false;
}

IOReturn USBInterfaceShim::hciCommand(void* command, UInt16 length)
{
    IOUSBDevRequest request =
    {
        .bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBDevice),
        .bRequest = 0,
        .wValue = 0,
        .wIndex = 0,
        .wLength = length,
        .pData = command
    };
    return m_pInterface->DeviceRequest(&request);
}

USBPipeShim::USBPipeShim()
{
    m_pPipe = NULL;
}

void USBPipeShim::setPipe(OSObject* pipe)
示例#15
0
IOReturn AppleUSBCDC::setPropertiesWL( OSObject * properties )
{
	IOReturn result = kIOReturnBadArgument;
	OSDictionary *propertyDict;
	
	WWAN_DICTIONARY whichDictionary = WWAN_DICTIONARY_UNKNOWN;
	
	OSObject *	dynamicKey = NULL;
	bool		rc = false;
	
	propertyDict = OSDynamicCast( OSDictionary, properties );

	if ( propertyDict != NULL )
	{
		OSCollectionIterator *propertyIterator;
		
#if TARGET_OS_EMBEDDED
		
		// Suspend support
		OSBoolean *suspendDevice = OSDynamicCast(OSBoolean, propertyDict->getObject("SuspendDevice"));
		
		if ( suspendDevice == kOSBooleanTrue ) 
		{
			Log("AppleUSBCDC::setProperties - SuspendDevice: true\n");
			
			if ( fpDevice->isOpen(this) )
			{
				if ( ( result = fpDevice->SuspendDevice(true) ) != kIOReturnSuccess )
				{
					Log("AppleUSBCDC::setProperties - failed to suspend the device, error: %08x \n", result);
				}
			}
			else
			{
				Log("AppleUSBCDC::setProperties - device was not open \n");
				return kIOReturnError;
			}
			
			return result;			
		}
		else if ( suspendDevice == kOSBooleanFalse )
		{
			Log("AppleUSBCDC::setProperties - SuspendDevice: false\n");
			
			if ( fpDevice->isOpen(this) )
			{
				if ( ( result = fpDevice->SuspendDevice(false) ) != kIOReturnSuccess )
				{
					Log("AppleUSBCDC::setProperties - failed to !suspend the device, error: %08x \n", result);
				}
			}
			else
			{
				IOLog("AppleUSBCDC::setProperties - device was not open \n");
				result = kIOReturnError;
			}
			
			return result;			
		}
		
		
		// Remote Wake-up support
		OSBoolean *remoteWakeup = OSDynamicCast(OSBoolean, propertyDict->getObject("RemoteWakeUp"));
		IOUSBDevRequest	devreq;
		
		if ( remoteWakeup )
		{
			devreq.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBStandard, kUSBDevice);
			if ( remoteWakeup == kOSBooleanTrue )
			{
				devreq.bRequest = kUSBRqSetFeature;
			} else {
				devreq.bRequest = kUSBRqClearFeature;
			}
			devreq.wValue = kUSBFeatureDeviceRemoteWakeup;
			devreq.wIndex = 0;
			devreq.wLength = 0;
			devreq.pData = 0;
			
			result = fpDevice->DeviceRequest(&devreq);
			if ( result == kIOReturnSuccess )
			{
				IOLog("AppleUSBCDC::setProperties - Set/Clear remote wake up feature successful\n");
			} else {
				IOLog("AppleUSBCDC::setProperties - Set/Clear remote wake up feature failed, %08x\n", result);
		}

			return result;			
		}
		
#endif // TARGET_OS_EMBEDDED
		
		if (dynamicKey = propertyDict->getObject(kWWAN_TYPE))
			whichDictionary	= WWAN_SET_DYNAMIC_DICTIONARY;
		else
			if (dynamicKey = propertyDict->getObject(kWWAN_HW_VERSION))					
				whichDictionary	= WWAN_SET_HARDWARE_DICTIONARY;
			else
				if (dynamicKey = propertyDict->getObject("AccessPointName"))
					whichDictionary	= WWAN_SET_MODEM_DICTIONARY;
				else
					if (dynamicKey = propertyDict->getObject("LCPMTU"))
					whichDictionary	= WWAN_SET_PPP_DICTIONARY;
					else
						if (dynamicKey = propertyDict->getObject(kWWAN_UNIQUIFIER))
						whichDictionary	= WWAN_SET_MODEM_DICTIONARY;
					
			// if we still can't determine which dictionary it is
			// Iterate to see if it is a property we know about..
		
		if (whichDictionary == WWAN_DICTIONARY_UNKNOWN) 
		{
		propertyIterator = OSCollectionIterator::withCollection( propertyDict );
		
		if ( propertyIterator != NULL )
		{
			OSSymbol *key;
			
			while( ( key = (OSSymbol *)propertyIterator->getNextObject() ) )
			{
//				Log("[setPropertiesWL] key: %s \n", key->getCStringNoCopy());
//				if (dynamicKey)
//					setProperty(key->getCStringNoCopy(),key);					
//					setProperty(key->getCStringNoCopy(),propertyDict->getObject(key));					
					if (key->isEqualTo(kWWAN_SC_SETUP))
					{
                        if (fTerminate == true)
                            return kIOReturnNoDevice;//We were terminated in the middle of handling a wwand request.
                        
						rc = fpDevice->setProperty(kWWAN_SC_SETUP,propertyDict->getObject(key));
						goto exit;
					}
					/*
					if (key->isEqualTo(kWWAN_UNIQUIFIER))
					{
						rc = fpDevice->setProperty(kWWAN_UNIQUIFIER,propertyDict->getObject(key));
						goto exit;
					}
					*/
					
				}
			propertyIterator->release();
		}
		else
		{
//			Log("[setPropertiesWL] could not obtain an OSCollectionIterator... \n");
			ALERT(0, 0, "setPropertiesWL - Could not obtain an OSCollectionIterator...");
			result = kIOReturnError;
		}
		}
		else
		{		
			switch (whichDictionary)
			{
				case WWAN_SET_DYNAMIC_DICTIONARY:
					rc = fpDevice->setProperty(kWWAN_DynamicDictonary,propertyDict);
//					Log("[setPropertiesWL] setting kWWAN_DynamicDictonary\n");

					break;
				
				case WWAN_SET_HARDWARE_DICTIONARY: 	
				rc = fpDevice->setProperty(kWWAN_HardwareDictionary,propertyDict);
//					Log("[setPropertiesWL] setting kWWAN_HardwareDictionary\n");
					break;
							
				case WWAN_SET_MODEM_DICTIONARY: 	
					rc = fpDevice->setProperty("DeviceModemOverrides",propertyDict);
//					Log("[setPropertiesWL] setting DeviceModemOverrides\n");
					break;
					
				case WWAN_SET_PPP_DICTIONARY: 
					rc = fpDevice->setProperty("DevicePPPOverrides",propertyDict);
//					Log("[setPropertiesWL] setting DevicePPPOverrides\n");
					break;

				case WWAN_DICTIONARY_UNKNOWN: 	
//					Log("AppleWWANSUpport::setPropertiesWL - Unknown Dictionary");
					
					break;

				default:
//					Log("AppleWWANSUpport::setPropertiesWL - default Unknown Dictionary");
					break;
			}
		}

				fpDevice->messageClients ( kIOMessageServicePropertyChange );
//				Log("[setPropertiesWL] set kWWAN_HardwareDictionary [%x] pNub mesaging Clients with  kIOMessageServicePropertyChange \n",rc);
	
	}

exit:
	
	this->messageClients ( kIOMessageServicePropertyChange );
	fpDevice->messageClients ( kIOMessageServicePropertyChange );

	return kIOReturnSuccess;
}