int twrpMtp::start(void) { MTPI("Starting MTP\n"); twmtp_MtpServer *mtp = new twmtp_MtpServer(); mtp->set_storages(mtpstorages); mtp->start(); return 0; }
MtpStorage::MtpStorage(MtpStorageID id, const char* filePath, const char* description, uint64_t reserveSpace, bool removable, uint64_t maxFileSize, MtpServer* refserver) : mStorageID(id), mFilePath(filePath), mDescription(description), mMaxCapacity(0), mMaxFileSize(maxFileSize), mReserveSpace(reserveSpace), mRemovable(removable), mServer(refserver) { MTPI("MtpStorage id: %d path: %s\n", id, filePath); inotify_thread = 0; inotify_fd = -1; // Threading has not started yet so we should be safe to set these directly instead of using atomics inotify_thread_kill.set_value(0); sendEvents = false; handleCurrentlySending = 0; use_mutex = true; if (pthread_mutex_init(&mtpMutex, NULL) != 0) { MTPE("Failed to init mtpMutex\n"); use_mutex = false; } if (pthread_mutex_init(&inMutex, NULL) != 0) { MTPE("Failed to init inMutex\n"); pthread_mutex_destroy(&mtpMutex); use_mutex = false; } }
int twmtp_MtpServer::mtppipe_thread(void) { if (mtp_read_pipe == -1) { MTPD("mtppipe_thread exiting because mtp_read_pipe not set\n"); return 0; } MTPD("Starting twmtp_MtpServer::mtppipe_thread\n"); int read_count; struct mtpmsg mtp_message; while (1) { read_count = ::read(mtp_read_pipe, &mtp_message, sizeof(mtp_message)); MTPD("read %i from mtppipe\n", read_count); if (read_count == sizeof(mtp_message)) { if (mtp_message.message_type == MTP_MESSAGE_ADD_STORAGE) { MTPI("mtppipe add storage %i '%s'\n", mtp_message.storage_id, mtp_message.path); if (mtp_message.storage_id) { long reserveSpace = 1; bool removable = false; MtpStorage* storage = new MtpStorage(mtp_message.storage_id, mtp_message.path, mtp_message.display, reserveSpace, removable, mtp_message.maxFileSize, refserver); server->addStorage(storage); MTPD("mtppipe done adding storage\n"); } else { MTPE("Invalid storage ID %i specified\n", mtp_message.storage_id); } } else if (mtp_message.message_type == MTP_MESSAGE_REMOVE_STORAGE) { MTPI("mtppipe remove storage %i\n", mtp_message.storage_id); remove_storage(mtp_message.storage_id); MTPD("mtppipe done removing storage\n"); } else { MTPE("Unknown mtppipe message value: %i\n", mtp_message.message_type); } } else { MTPE("twmtp_MtpServer::mtppipe_thread unexpected read_count %i\n", read_count); close(mtp_read_pipe); break; } } MTPD("twmtp_MtpServer::mtppipe_thread closing\n"); return 0; }
void twmtp_MtpServer::start() { usePtp = false; MyMtpDatabase* mtpdb = new MyMtpDatabase(); /* Sleep for a bit before we open the MTP USB device because some * devices are not ready due to the kernel not responding to our * sysfs requests right away. */ usleep(800000); #ifdef USB_MTP_DEVICE #define STRINGIFY(x) #x #define EXPAND(x) STRINGIFY(x) const char* mtp_device = EXPAND(USB_MTP_DEVICE); MTPI("Using '%s' for MTP device.\n", EXPAND(USB_MTP_DEVICE)); #else const char* mtp_device = "/dev/mtp_usb"; #endif int fd = open(mtp_device, O_RDWR); if (fd < 0) { MTPE("could not open MTP driver, errno: %d\n", errno); return; } MTPD("fd: %d\n", fd); server = new MtpServer(mtpdb, usePtp, 0, 0664, 0775); refserver = server; MTPI("created new mtpserver object\n"); add_storage(); MTPD("Starting add / remove mtppipe monitor thread\n"); pthread_t thread; ThreadPtr mtpptr = &twmtp_MtpServer::mtppipe_thread; PThreadPtr p = *(PThreadPtr*)&mtpptr; pthread_create(&thread, NULL, p, this); // This loop restarts the MTP process if the device is unplugged and replugged in while (true) { server->run(fd); fd = open(mtp_device, O_RDWR); usleep(800000); } }
void MtpObjectInfo::print() { MTPI("MtpObject Info %08X: %s\n", mHandle, mName); MTPI(" mStorageID: %08X mFormat: %04X mProtectionStatus: %d\n", mStorageID, mFormat, mProtectionStatus); MTPI(" mCompressedSize: %d mThumbFormat: %04X mThumbCompressedSize: %d\n", mCompressedSize, mFormat, mThumbCompressedSize); MTPI(" mThumbPixWidth: %d mThumbPixHeight: %d\n", mThumbPixWidth, mThumbPixHeight); MTPI(" mImagePixWidth: %d mImagePixHeight: %d mImagePixDepth: %d\n", mImagePixWidth, mImagePixHeight, mImagePixDepth); MTPI(" mParent: %08X mAssociationType: %04X mAssociationDesc: %04X\n", mParent, mAssociationType, mAssociationDesc); MTPI(" mSequenceNumber: %d mDateCreated: %ld mDateModified: %ld mKeywords: %s\n", mSequenceNumber, mDateCreated, mDateModified, mKeywords); }
void MtpServer::run() { int fd = mFD; MTPI("MtpServer::run fd: %d\n", fd); while (1) { MTPD("About to read device...\n"); int ret = mRequest.read(fd); if (ret < 0) { if (errno == ECANCELED) { // return to top of loop and wait for next command MTPD("request read returned %d ECANCELED, starting over\n", ret); continue; } MTPE("request read returned %d, errno: %d, exiting MtpServer::run loop\n", ret, errno); break; } MtpOperationCode operation = mRequest.getOperationCode(); MtpTransactionID transaction = mRequest.getTransactionID(); MTPD("operation: %s", MtpDebug::getOperationCodeName(operation)); mRequest.dump(); // FIXME need to generalize this bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO || operation == MTP_OPERATION_SET_OBJECT_REFERENCES || operation == MTP_OPERATION_SET_OBJECT_PROP_VALUE || operation == MTP_OPERATION_SET_DEVICE_PROP_VALUE); if (dataIn) { int ret = mData.read(fd); if (ret < 0) { if (errno == ECANCELED) { // return to top of loop and wait for next command MTPD("data read returned %d ECANCELED, starting over\n", ret); continue; } MTPD("data read returned %d, errno: %d, exiting MtpServer::run loop\n", ret, errno); break; } MTPD("received data:"); mData.dump(); } else { mData.reset(); } if (handleRequest()) { if (!dataIn && mData.hasData()) { mData.setOperationCode(operation); mData.setTransactionID(transaction); MTPD("sending data:"); mData.dump(); ret = mData.write(fd); if (ret < 0) { if (errno == ECANCELED) { // return to top of loop and wait for next command MTPD("data write returned %d ECANCELED, starting over\n", ret); continue; } MTPE("data write returned %d, errno: %d, exiting MtpServer::run loop\n", ret, errno); break; } } mResponse.setTransactionID(transaction); MTPD("sending response %04X\n", mResponse.getResponseCode()); ret = mResponse.write(fd); MTPD("ret: %d\n", ret); mResponse.dump(); if (ret < 0) { if (errno == ECANCELED) { // return to top of loop and wait for next command MTPD("response write returned %d ECANCELED, starting over\n", ret); continue; } MTPE("response write returned %d, errno: %d, exiting MtpServer::run loop\n", ret, errno); break; } } else { MTPD("skipping response\n"); } } // commit any open edits int count = mObjectEditList.size(); for (int i = 0; i < count; i++) { ObjectEdit* edit = mObjectEditList[i]; commitEdit(edit); delete edit; } mObjectEditList.clear(); if (mSessionOpen) mDatabase->sessionEnded(); close(fd); mFD = -1; }