static void send_string(struct usb_device *device, int index, const char* string) {
    int ret = usb_device_control_transfer(device, USB_DIR_OUT | USB_TYPE_VENDOR,
            ACCESSORY_SEND_STRING, 0, index, (void *)string, strlen(string) + 1, 0);

    // some devices can't handle back-to-back requests, so delay a bit
    milli_sleep(10);
}
char* usb_device_get_string(struct usb_device *device, int id)
{
    char string[256];
    __u16 buffer[128];
    __u16 languages[128];
    int i, result;
    int languageCount = 0;

    string[0] = 0;
    memset(languages, 0, sizeof(languages));

    // read list of supported languages
    result = usb_device_control_transfer(device,
            USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR,
            (USB_DT_STRING << 8) | 0, 0, languages, sizeof(languages), 0);
    if (result > 0)
        languageCount = (result - 2) / 2;

    for (i = 1; i <= languageCount; i++) {
        memset(buffer, 0, sizeof(buffer));

        result = usb_device_control_transfer(device,
                USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR,
                (USB_DT_STRING << 8) | id, languages[i], buffer, sizeof(buffer), 0);
        if (result > 0) {
            int i;
            // skip first word, and copy the rest to the string, changing shorts to bytes.
            result /= 2;
            for (i = 1; i < result; i++)
                string[i - 1] = buffer[i];
            string[i - 1] = 0;
            return strdup(string);
        }
    }

    return NULL;
}
Exemple #3
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
  }
Exemple #4
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;
}