Example #1
0
void MtpDevice::close() {
    if (mDevice) {
        usb_device_release_interface(mDevice, mInterface);
        usb_device_close(mDevice);
        mDevice = NULL;
    }
}
Example #2
0
void upsdrv_cleanup(void)
{
	usb_device_close(udev);

	free(usbdevice.Vendor);
	free(usbdevice.Product);
	free(usbdevice.Serial);
	free(usbdevice.Bus);
}
static int usb_device_removed(const char *devname, void* client_data) {
    if (sDevice && !strcmp(usb_device_get_name(sDevice), devname)) {
        usb_device_close(sDevice);
        sDevice = NULL;
        // exit when we are disconnected
        return 1;
    }
    return 0;
}
Example #4
0
void upsdrv_updateinfo(void)
{
	char	reply[REPLY_PACKETSIZE];
	int	ret, online, battery_normal;

	if (!udev) {
		ret = usb_device_open(&udev, &usbdevice, &device_matcher, &driver_callback);

		if (ret < 0) {
			return;
		}
	}

	ret = query_ups(reply);

	if (ret < 4) {
		usb_comm_fail("Query to UPS failed");
		dstate_datastale();

		usb_device_close(udev);
		udev = NULL;

		return;
	}

	usb_comm_good();
	dstate_dataok();

	/*
	 * 3rd bit of 4th byte indicates whether the UPS is on line (1)
	 * or on battery (0)
	 */
	online = (reply[3]&4)>>2;

	/*
	 * 2nd bit of 4th byte indicates battery status; normal (1)
	 * or low (0)
	 */
	battery_normal = (reply[3]&2)>>1;

	status_init();

	if (online) {
	    status_set("OL");
	} else {
	    status_set("OB");
	}

	if (!battery_normal) {
	    status_set("LB");
	}

	status_commit();
}
Example #5
0
void iqrf_device_close(iqrf_t *iqrf)
{
	/* get semaphore */
	iqrf_lock(iqrf);

	usb_device_close(iqrf->dev);
	iqrf->dev = NULL;

	/* see SEM_DESTROY(3) (destroying blocked semaphore) */
	sem_destroy(&iqrf->sem);

	free(iqrf);
	DBG("device closed\n");
	return;
}
Example #6
0
    // Callback for notification when USB devices are removed. Return true to exit from usb_host_run.
  int usb_device_removed (const char * devname, void * client_data) {
    logd ("usb_device_removed client_data: %p  devname: %s", client_data, devname);

    //pthread_mutex_lock (& device_mutex);
                                                                        //
    if  (current_device) {                                              // If we have a current device...
      const char * curr_devname = usb_device_get_name (current_device);
      if (! strcmp (curr_devname, devname)) {                           // If current device was removed...
        logd ("usb_device_removed current device disconnected");
        usb_device_close (current_device);
        current_device = NULL;
      }
    }

    //pthread_mutex_unlock (& device_mutex);
    return (0);                                                       // 0 = Leave usb_host_run() running
  }
Example #7
0
static int lsusb_device_added(const char *dev_name, void *client_data)
{
    struct usb_device *dev = usb_device_open(dev_name);

    if (!dev) {
        fprintf(stderr, "can't open device %s: %s\n", dev_name, strerror(errno));
        return 0;
    }

    if (verbose) {
        struct usb_descriptor_iter iter;
        struct usb_descriptor_header *desc;

        printf("%s:\n", dev_name);

        usb_descriptor_iter_init(dev, &iter);

        while ((desc = usb_descriptor_iter_next(&iter)) != NULL)
            lsusb_parse_descriptor(dev, desc);

    } else {
        uint16_t vid, pid;
        char *mfg_name, *product_name, *serial;

        vid = usb_device_get_vendor_id(dev);
        pid = usb_device_get_product_id(dev);
        mfg_name = usb_device_get_manufacturer_name(dev);
        product_name = usb_device_get_product_name(dev);
        serial = usb_device_get_serial(dev);

        printf("%s: %04x:%04x %s %s %s\n", dev_name, vid, pid,
               mfg_name, product_name, serial);

        free(mfg_name);
        free(product_name);
        free(serial);
    }

    usb_device_close(dev);

    return 0;
}
/**
 * handle bus event
 *
 * @param [in, out] h
 *
 * @return E_ERR_SUCCESS
 */
e_mmgr_errors_t bus_ev_hdle_events(bus_ev_hdle_t *h)
{
    e_mmgr_errors_t ret = E_ERR_FAILED;
    bus_ev_t *bus_events = (bus_ev_t *)h;
    int i;

    for (i = 0; i < bus_events->cli_ctx.i; i++) {
        LOG_DEBUG("Event: %s %d", bus_events->cli_ctx.evs[i].path,
                  bus_events->cli_ctx.evs[i].event);
        if (bus_events->cli_ctx.evs[i].event == EV_ADDED) {
            struct usb_device *dev;

            LOG_DEBUG("EVENT ADDED");

            dev = usb_device_open(bus_events->cli_ctx.evs[i].path);
            if (dev == NULL) {
                LOG_ERROR("Failed to open path: %s",
                          bus_events->cli_ctx.evs[i].path);
            } else {
                if (is_pid_and_vid(dev,
                                   bus_events->modem_flash_pid,
                                   bus_events->modem_flash_vid)) {
                    bus_events->mdm_state |= MDM_FLASH_READY;
                    strncpy(bus_events->modem_flash_path,
                            bus_events->cli_ctx.evs[i].path, PATH_MAX);
                    ret = E_ERR_SUCCESS;
                    LOG_DEBUG("+Modem flash is READY");
                } else if (is_pid_and_vid(dev,
                                          bus_events->modem_bb_pid,
                                          bus_events->modem_bb_vid)) {
                    bus_events->mdm_state |= MDM_BB_READY;
                    strncpy(bus_events->modem_bb_path,
                            bus_events->cli_ctx.evs[i].path, PATH_MAX);
                    ret = E_ERR_SUCCESS;
                    LOG_DEBUG("+Modem base band READY");
                } else if (is_pid_and_vid(dev,
                                          bus_events->mcdr_bb_pid,
                                          bus_events->mcdr_bb_vid)) {
                    bus_events->mdm_state |= MDM_CD_READY;
                    strncpy(bus_events->modem_cd_path,
                            bus_events->cli_ctx.evs[i].path, PATH_MAX);
                    ret = E_ERR_SUCCESS;
                    LOG_DEBUG("+Modem core dump READY");
                }

                usb_device_close(dev);
            }
        } else if (bus_events->cli_ctx.evs[i].event == EV_DELETED) {
            LOG_DEBUG("EVENT DELETED");
            if (strncmp(bus_events->modem_flash_path,
                        bus_events->cli_ctx.evs[i].path, PATH_MAX) == 0) {
                bus_events->mdm_state &= ~MDM_FLASH_READY;
                bus_events->modem_flash_path[0] = '\0';
                ret = E_ERR_SUCCESS;
                LOG_DEBUG("-Modem flash not READY");
            } else if (strncmp(bus_events->modem_bb_path,
                               bus_events->cli_ctx.evs[i].path,
                               PATH_MAX) == 0) {
                bus_events->mdm_state &= ~MDM_BB_READY;
                bus_events->modem_bb_path[0] = '\0';
                ret = E_ERR_SUCCESS;
                LOG_DEBUG("-Modem base band not READY");
            } else if (strncmp(bus_events->modem_cd_path,
                               bus_events->cli_ctx.evs[i].path,
                               PATH_MAX) == 0) {
                bus_events->mdm_state &= ~MDM_CD_READY;
                bus_events->modem_cd_path[0] = '\0';
                ret = E_ERR_SUCCESS;
                LOG_DEBUG("-Modem core dump not READY");
            }
        }
    }

    bus_events->cli_ctx.i = 0;
    return ret;
}
Example #9
0
static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDeviceMatcher_t *matcher,
	int (*callback)(usb_dev_handle *handle, USBDevice_t *device))
{
	struct usb_bus	*bus;

	/* libusb base init */
	usb_init();
	usb_find_busses();
	usb_find_devices();

#ifndef __linux__ /* SUN_LIBUSB (confirmed to work on Solaris and FreeBSD) */
	/* Causes a double free corruption in linux if device is detached! */
	usb_device_close(*handlep);
#endif

	for (bus = usb_busses; bus; bus = bus->next) {

		struct usb_device	*dev;
		usb_dev_handle		*handle;

		for (dev = bus->devices; dev; dev = dev->next) {

			int	i, ret;
			USBDeviceMatcher_t	*m;

			upsdebugx(4, "Checking USB device [%04x:%04x] (%s/%s)", dev->descriptor.idVendor,
				dev->descriptor.idProduct, bus->dirname, dev->filename);
			
			/* supported vendors are now checked by the supplied matcher */

			/* open the device */
			*handlep = handle = usb_open(dev);
			if (!handle) {
				upsdebugx(4, "Failed to open USB device, skipping: %s", usb_strerror());
				continue;
			}

			/* collect the identifying information of this
			   device. Note that this is safe, because
			   there's no need to claim an interface for
			   this (and therefore we do not yet need to
			   detach any kernel drivers). */

			free(device->Vendor);
			free(device->Product);
			free(device->Serial);
			free(device->Bus);

			memset(device, 0, sizeof(*device));

			device->VendorID = dev->descriptor.idVendor;
			device->ProductID = dev->descriptor.idProduct;
			device->Bus = strdup(bus->dirname);
			
			if (dev->descriptor.iManufacturer) {
				char	buf[SMALLBUF];
				ret = usb_get_string_simple(handle, dev->descriptor.iManufacturer,
					buf, sizeof(buf));
				if (ret > 0) {
					device->Vendor = strdup(buf);
				}
			}

			if (dev->descriptor.iProduct) {
				char	buf[SMALLBUF];
				ret = usb_get_string_simple(handle, dev->descriptor.iProduct,
					buf, sizeof(buf));
				if (ret > 0) {
					device->Product = strdup(buf);
				}
			}

			if (dev->descriptor.iSerialNumber) {
				char	buf[SMALLBUF];
				ret = usb_get_string_simple(handle, dev->descriptor.iSerialNumber,
					buf, sizeof(buf));
				if (ret > 0) {
					device->Serial = strdup(buf);
				}
			}

			upsdebugx(4, "- VendorID     : %04x", device->VendorID);
			upsdebugx(4, "- ProductID    : %04x", device->ProductID);
			upsdebugx(4, "- Manufacturer : %s", device->Vendor ? device->Vendor : "unknown");
			upsdebugx(4, "- Product      : %s", device->Product ? device->Product : "unknown");
			upsdebugx(4, "- Serial Number: %s", device->Serial ? device->Serial : "unknown");
			upsdebugx(4, "- Bus          : %s", device->Bus ? device->Bus : "unknown");

			for (m = matcher; m; m = m->next) {
				
				switch (m->match_function(device, m->privdata))
				{
				case 0:
					upsdebugx(4, "Device does not match - skipping");
					goto next_device;
				case -1:
					fatal_with_errno(EXIT_FAILURE, "matcher");
					goto next_device;
				case -2:
					upsdebugx(4, "matcher: unspecified error");
					goto next_device;
				}
			}

			for (i = 0; i < 3; i++) {

				ret = callback(handle, device);
				if (ret >= 0) {
					upsdebugx(4, "USB device [%04x:%04x] opened", device->VendorID, device->ProductID);
					return ret;
				}
#ifdef HAVE_USB_DETACH_KERNEL_DRIVER_NP
				/* this method requires at least libusb 0.1.8:
				 * it force device claiming by unbinding
				 * attached driver... From libhid */
				if (usb_detach_kernel_driver_np(handle, 0) < 0) {
					upsdebugx(4, "failed to detach kernel driver from USB device: %s", usb_strerror());
				} else {
					upsdebugx(4, "detached kernel driver from USB device...");
				}
#endif
			}

			fatalx(EXIT_FAILURE, "USB device [%04x:%04x] matches, but driver callback failed: %s",
				device->VendorID, device->ProductID, usb_strerror());

		next_device:
			usb_close(handle);
		}
	}

	*handlep = NULL;
	upsdebugx(4, "No matching USB device found");

	return -1;
}
Example #10
0
    // Callback for notification when new USB devices are attached. Return true to exit from usb_host_run.
  int usb_device_added (const char * devname, void * client_data) {
    logd ("\n");
    //logd ("client_data: %p  devname: %s", client_data, devname);
    logd ("devname: %s", devname);

    uint16_t usb_vid, usb_pid;
    int ret;
    //int unused = (int) client_data;

    if (ena_su_perm) {    // Set Permission w/ SU:
      char cmd [256] = "su -c chmod 777 ";
      strlcat (cmd, devname, sizeof (cmd));
      //strlcat (cmd, " 2>&1 > /sdcard/res", sizeof (cmd));
      errno = 0;
      ret = system (cmd);                                             // !! Binaries like ssd that write to stdout cause C system() to crash !
      logd ("system() ret: %d  errno: %d (%s)", ret, errno, strerror (errno));
    }

    struct usb_device * device = usb_device_open (devname);
    if  (! device) {
      loge ("usb_device_open failed");
      return (0);                                                       // 0 = Leave usb_host_run() running
    }

    usb_vid = usb_device_get_vendor_id  (device);
    usb_pid = usb_device_get_product_id (device);
    char * usb_ser = usb_device_get_serial (device);

    logd ("usb_vid: 0x%x (%d - %s)  usb_pid: 0x%x  usb_ser: %s", usb_vid, usb_vid, usb_vid_get (usb_vid), usb_pid, usb_ser);

    if (current_device != NULL) {                                       // If we already have a device, just ignore
      logd ("Ignoring have current_device: %p", current_device);
      usb_device_close (device);
      return (0);                                                       // 0 = Leave usb_host_run() running
    }

    if  (usb_vid != USB_VID_GOO || usb_pid >= USB_PID_ACC_MIN ||  usb_pid <= USB_PID_ACC_MAX) { // If not in Google Accessory mode...
      logd ("Found new device - attempting to switch to accessory mode");

      uint16_t protocol = -1;
      errno = 0;
      ret = usb_device_control_transfer (device, USB_DIR_IN | USB_TYPE_VENDOR, ACC_REQ_GET_PROTOCOL, 0, 0, & protocol, sizeof (protocol), 1000);
      if  (ret < 0) {
        loge ("No Acc OAP protocol ret: %d  errno: %d", ret, errno);
        usb_device_close (device);
        return (0);                                                     // 0 = Leave usb_host_run() running
      }
      if  (protocol < 2) {
        loge ("Acc OAP protocol version %d", protocol);
        usb_device_close (device);
        return (0);                                                   // 0 = Leave usb_host_run() running
      }
      logd ("Acc OAP protocol version %d", protocol);

      send_string (device, ACC_IDX_MAN, AAP_VAL_MAN);                 // Send Acc strings
      send_string (device, ACC_IDX_MOD, AAP_VAL_MOD);
      //send_string (device, ACC_IDX_DES, AAP_VAL_DES);
      //send_string (device, ACC_IDX_VER, AAP_VAL_VER);
      //send_string (device, ACC_IDX_URI, AAP_VAL_URI);
      //send_string (device, ACC_IDX_SER, AAP_VAL_SER);

      errno = 0;
      ret = usb_device_control_transfer (device, USB_DIR_OUT | USB_TYPE_VENDOR, ACC_REQ_START, 0, 0, NULL, 0, 1000);
      if  (ret < 0)
        loge ("Acc Start ret: %d errno: %d", ret, errno);
      else
        logd ("Acc Start ret: %d", ret);


    }

    logd ("Found android device in accessory mode");

    //pthread_mutex_lock (& device_mutex);
    //pthread_cond_broadcast (& device_cond);
    //pthread_mutex_unlock (& device_mutex);

    struct usb_descriptor_iter        iter;
    struct usb_descriptor_header    * desc  = NULL;
    struct usb_interface_descriptor * intf  = NULL;
    struct usb_endpoint_descriptor  * ep   = NULL;

    usb_descriptor_iter_init (device, & iter);                        // Init for iterating USB descriptors
    
    read_ep  = 255;
    write_ep = 255;

    while  ((desc = usb_descriptor_iter_next (& iter)) != NULL) {
      if (0);
      else if  (desc->bDescriptorType == LIBUSB_DT_DEVICE) {
        logd ("Device desc: %p", desc);
      }
      else if  (desc->bDescriptorType == LIBUSB_DT_CONFIG) {
        logd ("Config desc: %p", desc);
      }
      else if  (desc->bDescriptorType == LIBUSB_DT_STRING) {
        logd ("String desc: %p", desc);
      }
      else if  (desc->bDescriptorType == LIBUSB_DT_HID) {
        logd ("HID desc: %p", desc);
      }
      else if  (desc->bDescriptorType == LIBUSB_DT_REPORT) {
        logd ("HID Report desc: %p", desc);
      }
      else if  (desc->bDescriptorType == LIBUSB_DT_PHYSICAL) {
        logd ("Physical desc: %p", desc);
      }
      else if  (desc->bDescriptorType == LIBUSB_DT_HUB) {
        logd ("Hub desc: %p", desc);
      }
      else if  (desc->bDescriptorType == LIBUSB_DT_INTERFACE) {
        intf =  (struct usb_interface_descriptor *) desc;
        logd ("Interface desc/intf: %p", desc);
      }
      else if  (desc->bDescriptorType == LIBUSB_DT_ENDPOINT) {
        logd ("Endpoint  desc/ep:   %p", desc);
        ep = (struct usb_endpoint_descriptor *) desc;
        uint8_t ep_addr = ep->bEndpointAddress;
        if  ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
          if (read_ep == 255) {
            read_ep  = ep_addr;
            logd ("Set as first read endpoint ep_addr: %d");
          }
          else
            loge ("Ignored already have read endpoint ep_addr: %d");
        }
        else {
          if (write_ep == 255) {
            write_ep = ep_addr;
            logd ("Set as first write endpoint ep_addr: %d");
          }
          else
            loge ("Ignored already have write endpoint ep_addr: %d");
        }
      }
      else
        loge ("Unknown desc->bDescriptorType: %d", desc->bDescriptorType);
    }

    if  (! intf) {
      loge ("interface not found");
      usb_device_close (device);
      return (0);                                                     // 0 = Leave usb_host_run() running
    }
    if  (read_ep == 255 || write_ep == 255) {
      loge ("Read and/or write endpoints not found");
      usb_device_close (device);
      return (0);                                                     // 0 = Leave usb_host_run() running
    }

    errno = 0;
    ret = usb_device_claim_interface (device, intf->bInterfaceNumber);
    if  (ret) {
      loge ("Error usb_device_claim_interface() errno: %d", errno);
      usb_device_close (device);
      return (0);                                                     // 0 = Leave usb_host_run() running
    }

    current_device = device;

    loge ("Success usb_device_claim_interface() : Can start AA protocol now");

    //ret = hu_aap_start ();

    byte vr_buf [] = {0, 3, 0, 6, 0, 1, 0, 1, 0, 1};                    // Version Request
    //ret = hu_aap_usb_send (vr_buf, sizeof (vr_buf), 1000);             // Send Version Request
    errno = 0;
    ret = hu_bulk_send (vr_buf, sizeof (vr_buf));
    if (ret) {
      loge ("Error hu_bulk_send() ret: %d  errno: %d (%s)", ret, errno, strerror (errno));
      usb_device_close (device);
      return (0);                                                     // 0 = Leave usb_host_run() running
    }
    logd ("Success hu_bulk_send()");

    return (0);                                                         // 0 = Leave usb_host_run() running
  }
Example #11
0
MtpDevice* MtpDevice::open(const char* deviceName, int fd) {
    struct usb_device *device = usb_device_new(deviceName, fd);
    if (!device) {
        ALOGE("usb_device_new failed for %s", deviceName);
        return NULL;
    }

    struct usb_descriptor_header* desc;
    struct usb_descriptor_iter iter;

    usb_descriptor_iter_init(device, &iter);

    while ((desc = usb_descriptor_iter_next(&iter)) != NULL) {
        if (desc->bDescriptorType == USB_DT_INTERFACE) {
            struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)desc;

            if (interface->bInterfaceClass == USB_CLASS_STILL_IMAGE &&
                interface->bInterfaceSubClass == 1 && // Still Image Capture
                interface->bInterfaceProtocol == 1)     // Picture Transfer Protocol (PIMA 15470)
            {
                char* manufacturerName = usb_device_get_manufacturer_name(device);
                char* productName = usb_device_get_product_name(device);
                ALOGD("Found camera: \"%s\" \"%s\"\n", manufacturerName, productName);
                free(manufacturerName);
                free(productName);
            } else if (interface->bInterfaceClass == 0xFF &&
                    interface->bInterfaceSubClass == 0xFF &&
                    interface->bInterfaceProtocol == 0) {
                char* interfaceName = usb_device_get_string(device, interface->iInterface);
                if (!interfaceName) {
                    continue;
                } else if (strcmp(interfaceName, "MTP")) {
                    free(interfaceName);
                    continue;
                }
                free(interfaceName);

                // Looks like an android style MTP device
                char* manufacturerName = usb_device_get_manufacturer_name(device);
                char* productName = usb_device_get_product_name(device);
                ALOGD("Found MTP device: \"%s\" \"%s\"\n", manufacturerName, productName);
                free(manufacturerName);
                free(productName);
            }
#if 0
             else {
                // look for special cased devices based on vendor/product ID
                // we are doing this mainly for testing purposes
                uint16_t vendor = usb_device_get_vendor_id(device);
                uint16_t product = usb_device_get_product_id(device);
                if (!isMtpDevice(vendor, product)) {
                    // not an MTP or PTP device
                    continue;
                }
                // request MTP OS string and descriptor
                // some music players need to see this before entering MTP mode.
                char buffer[256];
                memset(buffer, 0, sizeof(buffer));
                int ret = usb_device_control_transfer(device,
                        USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_STANDARD,
                        USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) | 0xEE,
                        0, buffer, sizeof(buffer), 0);
                printf("usb_device_control_transfer returned %d errno: %d\n", ret, errno);
                if (ret > 0) {
                    printf("got MTP string %s\n", buffer);
                    ret = usb_device_control_transfer(device,
                            USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_VENDOR, 1,
                            0, 4, buffer, sizeof(buffer), 0);
                    printf("OS descriptor got %d\n", ret);
                } else {
                    printf("no MTP string\n");
                }
            }
#endif
            // if we got here, then we have a likely MTP or PTP device

            // interface should be followed by three endpoints
            struct usb_endpoint_descriptor *ep;
            struct usb_endpoint_descriptor *ep_in_desc = NULL;
            struct usb_endpoint_descriptor *ep_out_desc = NULL;
            struct usb_endpoint_descriptor *ep_intr_desc = NULL;
            for (int i = 0; i < 3; i++) {
                ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter);
                if (!ep || ep->bDescriptorType != USB_DT_ENDPOINT) {
                    ALOGE("endpoints not found\n");
                    usb_device_close(device);
                    return NULL;
                }
                if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK) {
                    if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
                        ep_in_desc = ep;
                    else
                        ep_out_desc = ep;
                } else if (ep->bmAttributes == USB_ENDPOINT_XFER_INT &&
                    ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
                    ep_intr_desc = ep;
                }
            }
            if (!ep_in_desc || !ep_out_desc || !ep_intr_desc) {
                ALOGE("endpoints not found\n");
                usb_device_close(device);
                return NULL;
            }

            if (usb_device_claim_interface(device, interface->bInterfaceNumber)) {
                ALOGE("usb_device_claim_interface failed errno: %d\n", errno);
                usb_device_close(device);
                return NULL;
            }

            MtpDevice* mtpDevice = new MtpDevice(device, interface->bInterfaceNumber,
                        ep_in_desc, ep_out_desc, ep_intr_desc);
            mtpDevice->initialize();
            return mtpDevice;
        }
    }

    usb_device_close(device);
    ALOGE("device not found");
    return NULL;
}
static int usb_device_added(const char *devname, void* client_data) {
    struct usb_descriptor_header* desc;
    struct usb_descriptor_iter iter;
    uint16_t vendorId, productId;
    int ret;
    pthread_t th;

    struct usb_device *device = usb_device_open(devname);
    if (!device) {
        fprintf(stderr, "usb_device_open failed\n");
        return 0;
    }

    vendorId = usb_device_get_vendor_id(device);
    productId = usb_device_get_product_id(device);

    if (!sDevice && (vendorId == 0x18D1 && (productId == 0x2D00 || productId == 0x2D01))) {
        struct usb_descriptor_header* desc;
        struct usb_descriptor_iter iter;
        struct usb_interface_descriptor *intf = NULL;
        struct usb_endpoint_descriptor *ep1 = NULL;
        struct usb_endpoint_descriptor *ep2 = NULL;

        printf("Found Android device in accessory mode (%x:%x)...\n",
               vendorId, productId);
        sDevice = device;

        usb_descriptor_iter_init(device, &iter);
        while ((desc = usb_descriptor_iter_next(&iter)) != NULL && (!intf || !ep1 || !ep2)) {
            if (desc->bDescriptorType == USB_DT_INTERFACE) {
                intf = (struct usb_interface_descriptor *)desc;
            } else if (desc->bDescriptorType == USB_DT_ENDPOINT) {
                if (ep1)
                    ep2 = (struct usb_endpoint_descriptor *)desc;
                else
                    ep1 = (struct usb_endpoint_descriptor *)desc;
            }
        }

        if (!intf) {
            fprintf(stderr, "Interface not found\n");
            exit(1);
        }
        if (!ep1 || !ep2) {
            fprintf(stderr, "Endpoints not found\n");
            exit(1);
        }

        if (usb_device_claim_interface(device, intf->bInterfaceNumber)) {
            fprintf(stderr, "usb_device_claim_interface failed errno: %d\n", errno);
            exit(1);
        }

        int endpoints[2];
        if ((ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
            endpoints[0] = ep1->bEndpointAddress;
            endpoints[1] = ep2->bEndpointAddress;
        } else {
            endpoints[0] = ep2->bEndpointAddress;
            endpoints[1] = ep1->bEndpointAddress;
        }
        pthread_create(&th, NULL, message_thread, (void *)endpoints);
    } else {
        printf("Found possible Android device (%x:%x) "
                "- attempting to switch to accessory mode...\n", vendorId, productId);

        uint16_t protocol = 0;
        ret = usb_device_control_transfer(device, USB_DIR_IN | USB_TYPE_VENDOR,
                ACCESSORY_GET_PROTOCOL, 0, 0, &protocol, sizeof(protocol), 0);
        if (ret == 2)
            printf("Device supports protocol version %d\n", protocol);
        else
            fprintf(stderr, "Failed to read protocol version\n");

        send_string(device, ACCESSORY_STRING_MANUFACTURER, "Android CTS");
        send_string(device, ACCESSORY_STRING_MODEL, "CTS USB Accessory");
        send_string(device, ACCESSORY_STRING_DESCRIPTION, "CTS USB Accessory");
        send_string(device, ACCESSORY_STRING_VERSION, "1.0");
        send_string(device, ACCESSORY_STRING_URI,
                "http://source.android.com/compatibility/cts-intro.html");
        send_string(device, ACCESSORY_STRING_SERIAL, "1234567890");

        ret = usb_device_control_transfer(device, USB_DIR_OUT | USB_TYPE_VENDOR,
                ACCESSORY_START, 0, 0, 0, 0, 0);
        return 0;
    }

    if (device != sDevice)
        usb_device_close(device);

    return 0;
}