static jobject
android_mtp_MtpDevice_get_storage_info(JNIEnv *env, jobject thiz, jint storageID)
{
    MtpDevice* device = get_device_from_object(env, thiz);
    if (!device)
        return NULL;
    MtpStorageInfo* storageInfo = device->getStorageInfo(storageID);
    if (!storageInfo)
        return NULL;

    jobject info = env->NewObject(clazz_storageInfo, constructor_storageInfo);
    if (info == NULL) {
        ALOGE("Could not create a MtpStorageInfo object");
        delete storageInfo;
        return NULL;
    }

    if (storageInfo->mStorageID)
        env->SetIntField(info, field_storageInfo_storageId, storageInfo->mStorageID);
    if (storageInfo->mMaxCapacity)
        env->SetLongField(info, field_storageInfo_maxCapacity, storageInfo->mMaxCapacity);
    if (storageInfo->mFreeSpaceBytes)
        env->SetLongField(info, field_storageInfo_freeSpace, storageInfo->mFreeSpaceBytes);
    if (storageInfo->mStorageDescription)
        env->SetObjectField(info, field_storageInfo_description,
            env->NewStringUTF(storageInfo->mStorageDescription));
    if (storageInfo->mVolumeIdentifier)
        env->SetObjectField(info, field_storageInfo_volumeIdentifier,
            env->NewStringUTF(storageInfo->mVolumeIdentifier));

    delete storageInfo;
    return info;
}
static jlong
android_mtp_MtpDevice_get_storage_id(JNIEnv *env, jobject thiz, jint object_id)
{
    MtpDevice* device = get_device_from_object(env, thiz);
    if (device)
        return (jlong)device->getStorageID(object_id);
    else
        return -1;
}
static jlong
android_mtp_MtpDevice_get_parent(JNIEnv *env, jobject thiz, jint object_id)
{
    MtpDevice* device = get_device_from_object(env, thiz);
    if (device)
        return device->getParent(object_id);
    else
        return -1;
}
static jboolean
android_mtp_MtpDevice_delete_object(JNIEnv *env, jobject thiz, jint object_id)
{
    MtpDevice* device = get_device_from_object(env, thiz);
    if (device)
        return device->deleteObject(object_id);
    else
        return NULL;
}
static jboolean
android_mtp_MtpDevice_delete_object(JNIEnv *env, jobject thiz, jint object_id)
{
    MtpDevice* device = get_device_from_object(env, thiz);
    if (device && device->deleteObject(object_id)) {
        return JNI_TRUE;
    } else {
        return JNI_FALSE;
    }
}
static void
android_mtp_MtpDevice_close(JNIEnv *env, jobject thiz)
{
    MtpDevice* device = get_device_from_object(env, thiz);
    if (device) {
        device->close();
        delete device;
        env->SetLongField(thiz, field_context, 0);
    }
}
static jboolean
android_mtp_MtpDevice_import_file(JNIEnv *env, jobject thiz, jint object_id, jstring dest_path)
{
    MtpDevice* device = get_device_from_object(env, thiz);
    if (device) {
        const char *destPathStr = env->GetStringUTFChars(dest_path, NULL);
        if (destPathStr == NULL) {
            return JNI_FALSE;
        }

        jboolean result = device->readObject(object_id, destPathStr, AID_SDCARD_RW, 0664);
        env->ReleaseStringUTFChars(dest_path, destPathStr);
        return result;
    }

    return JNI_FALSE;
}
static jbyteArray
android_mtp_MtpDevice_get_thumbnail(JNIEnv *env, jobject thiz, jint objectID)
{
    MtpDevice* device = get_device_from_object(env, thiz);
    if (!device)
        return NULL;

    int length;
    void* thumbnail = device->getThumbnail(objectID, length);
    if (! thumbnail)
        return NULL;
    jbyteArray array = env->NewByteArray(length);
    env->SetByteArrayRegion(array, 0, length, (const jbyte *)thumbnail);

    free(thumbnail);
    return array;
}
static jintArray
android_mtp_MtpDevice_get_storage_ids(JNIEnv *env, jobject thiz)
{
    MtpDevice* device = get_device_from_object(env, thiz);
    if (!device)
        return NULL;
    MtpStorageIDList* storageIDs = device->getStorageIDs();
    if (!storageIDs)
        return NULL;

    int length = storageIDs->size();
    jintArray array = env->NewIntArray(length);
    // FIXME is this cast safe?
    env->SetIntArrayRegion(array, 0, length, (const jint *)storageIDs->array());

    delete storageIDs;
    return array;
}
static jintArray
android_mtp_MtpDevice_get_object_handles(JNIEnv *env, jobject thiz,
        jint storageID, jint format, jint objectID)
{
    MtpDevice* device = get_device_from_object(env, thiz);
    if (!device)
        return NULL;
    MtpObjectHandleList* handles = device->getObjectHandles(storageID, format, objectID);
    if (!handles)
        return NULL;

    int length = handles->size();
    jintArray array = env->NewIntArray(length);
    // FIXME is this cast safe?
    env->SetIntArrayRegion(array, 0, length, (const jint *)handles->array());

    delete handles;
    return array;
}
static jbyteArray
android_mtp_MtpDevice_get_object(JNIEnv *env, jobject thiz, jint objectID, jint objectSize)
{
    MtpDevice* device = get_device_from_object(env, thiz);
    if (!device)
        return NULL;

    jbyteArray array = env->NewByteArray(objectSize);
    if (!array) {
        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
        return NULL;
    }

    get_object_callback_data data;
    data.env = env;
    data.array = array;

    if (device->readObject(objectID, get_object_callback, objectSize, &data))
        return array;
    return NULL;
}
static jobject
android_mtp_MtpDevice_get_device_info(JNIEnv *env, jobject thiz)
{
    MtpDevice* device = get_device_from_object(env, thiz);
    if (!device) {
        ALOGD("android_mtp_MtpDevice_get_device_info device is null");
        return NULL;
    }
    MtpDeviceInfo* deviceInfo = device->getDeviceInfo();
    if (!deviceInfo) {
        ALOGD("android_mtp_MtpDevice_get_device_info deviceInfo is null");
        return NULL;
    }
    jobject info = env->NewObject(clazz_deviceInfo, constructor_deviceInfo);
    if (info == NULL) {
        ALOGE("Could not create a MtpDeviceInfo object");
        delete deviceInfo;
        return NULL;
    }

    if (deviceInfo->mManufacturer)
        env->SetObjectField(info, field_deviceInfo_manufacturer,
            env->NewStringUTF(deviceInfo->mManufacturer));
    if (deviceInfo->mModel)
        env->SetObjectField(info, field_deviceInfo_model,
            env->NewStringUTF(deviceInfo->mModel));
    if (deviceInfo->mVersion)
        env->SetObjectField(info, field_deviceInfo_version,
            env->NewStringUTF(deviceInfo->mVersion));
    if (deviceInfo->mSerial)
        env->SetObjectField(info, field_deviceInfo_serialNumber,
            env->NewStringUTF(deviceInfo->mSerial));

    delete deviceInfo;
    return info;
}
static jobject
android_mtp_MtpDevice_get_object_info(JNIEnv *env, jobject thiz, jint objectID)
{
    MtpDevice* device = get_device_from_object(env, thiz);
    if (!device)
        return NULL;
    MtpObjectInfo* objectInfo = device->getObjectInfo(objectID);
    if (!objectInfo)
        return NULL;
    jobject info = env->NewObject(clazz_objectInfo, constructor_objectInfo);
    if (info == NULL) {
        ALOGE("Could not create a MtpObjectInfo object");
        delete objectInfo;
        return NULL;
    }

    if (objectInfo->mHandle)
        env->SetIntField(info, field_objectInfo_handle, objectInfo->mHandle);
    if (objectInfo->mStorageID)
        env->SetIntField(info, field_objectInfo_storageId, objectInfo->mStorageID);
    if (objectInfo->mFormat)
        env->SetIntField(info, field_objectInfo_format, objectInfo->mFormat);
    if (objectInfo->mProtectionStatus)
        env->SetIntField(info, field_objectInfo_protectionStatus, objectInfo->mProtectionStatus);
    if (objectInfo->mCompressedSize)
        env->SetIntField(info, field_objectInfo_compressedSize, objectInfo->mCompressedSize);
    if (objectInfo->mThumbFormat)
        env->SetIntField(info, field_objectInfo_thumbFormat, objectInfo->mThumbFormat);
    if (objectInfo->mThumbCompressedSize)
        env->SetIntField(info, field_objectInfo_thumbCompressedSize, objectInfo->mThumbCompressedSize);
    if (objectInfo->mThumbPixWidth)
        env->SetIntField(info, field_objectInfo_thumbPixWidth, objectInfo->mThumbPixWidth);
    if (objectInfo->mThumbPixHeight)
        env->SetIntField(info, field_objectInfo_thumbPixHeight, objectInfo->mThumbPixHeight);
    if (objectInfo->mImagePixWidth)
        env->SetIntField(info, field_objectInfo_imagePixWidth, objectInfo->mImagePixWidth);
    if (objectInfo->mImagePixHeight)
        env->SetIntField(info, field_objectInfo_imagePixHeight, objectInfo->mImagePixHeight);
    if (objectInfo->mImagePixDepth)
        env->SetIntField(info, field_objectInfo_imagePixDepth, objectInfo->mImagePixDepth);
    if (objectInfo->mParent)
        env->SetIntField(info, field_objectInfo_parent, objectInfo->mParent);
    if (objectInfo->mAssociationType)
        env->SetIntField(info, field_objectInfo_associationType, objectInfo->mAssociationType);
    if (objectInfo->mAssociationDesc)
        env->SetIntField(info, field_objectInfo_associationDesc, objectInfo->mAssociationDesc);
    if (objectInfo->mSequenceNumber)
        env->SetIntField(info, field_objectInfo_sequenceNumber, objectInfo->mSequenceNumber);
    if (objectInfo->mName)
        env->SetObjectField(info, field_objectInfo_name, env->NewStringUTF(objectInfo->mName));
    if (objectInfo->mDateCreated)
        env->SetLongField(info, field_objectInfo_dateCreated, objectInfo->mDateCreated * 1000LL);
    if (objectInfo->mDateModified)
        env->SetLongField(info, field_objectInfo_dateModified, objectInfo->mDateModified * 1000LL);
    if (objectInfo->mKeywords)
        env->SetObjectField(info, field_objectInfo_keywords,
            env->NewStringUTF(objectInfo->mKeywords));

    delete objectInfo;
    return info;
}
Beispiel #14
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;
}