diff options
Diffstat (limited to 'media/tests/mtp/mtp.cpp')
-rw-r--r-- | media/tests/mtp/mtp.cpp | 370 |
1 files changed, 370 insertions, 0 deletions
diff --git a/media/tests/mtp/mtp.cpp b/media/tests/mtp/mtp.cpp new file mode 100644 index 0000000..2c5e23b --- /dev/null +++ b/media/tests/mtp/mtp.cpp @@ -0,0 +1,370 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#if HAVE_READLINE +#include <readline/readline.h> +#include <readline/history.h> +#endif + +#include "MtpClient.h" +#include "MtpDevice.h" +#include "MtpObjectInfo.h" + +#include "MtpFile.h" + +#define PROMPT "mtp> " + +using namespace android; + +static MtpClient* sClient = NULL; + +// current working directory information for interactive shell +static MtpFile* sCurrentDirectory = NULL; + +static MtpFile* parse_path(char* path) { + return MtpFile::parsePath(sCurrentDirectory, path); +} + +class MyClient : public MtpClient { +private: + virtual void deviceAdded(MtpDevice *device) { + } + + virtual void deviceRemoved(MtpDevice *device) { + } + +public: +}; + +static void init() { + sClient = new MyClient; + sClient->start(); + MtpFile::init(sClient); +} + +static int set_cwd(int argc, char* argv[]) { + if (argc != 1) { + fprintf(stderr, "cd should have one argument\n"); + return -1; + } + if (!strcmp(argv[0], "/")) { + delete sCurrentDirectory; + sCurrentDirectory = NULL; + } + else { + MtpFile* file = parse_path(argv[0]); + if (file) { + delete sCurrentDirectory; + sCurrentDirectory = file; + } else { + fprintf(stderr, "could not find %s\n", argv[0]); + return -1; + } + } + return 0; +} + +static void list_devices() { + // TODO - need to make sure the list will not change while iterating + MtpDeviceList& devices = sClient->getDeviceList(); + for (int i = 0; i < devices.size(); i++) { + MtpDevice* device = devices[i]; + MtpFile* file = new MtpFile(device); + file->print(); + delete file; + } +} + +static int list(int argc, char* argv[]) { + if (argc == 0) { + // list cwd + if (sCurrentDirectory) { + sCurrentDirectory->list(); + } else { + list_devices(); + } + } + + for (int i = 0; i < argc; i++) { + char* path = argv[i]; + if (!strcmp(path, "/")) { + list_devices(); + } else { + MtpFile* file = parse_path(path); + if (!file) { + fprintf(stderr, "could not find %s\n", path); + return -1; + } + file->list(); + } + } + + return 0; +} + +static int get_file(int argc, char* argv[]) { + int ret = -1; + int srcFD = -1; + int destFD = -1; + MtpFile* srcFile = NULL; + MtpObjectInfo* info = NULL; + char* dest; + + if (argc < 1) { + fprintf(stderr, "not enough arguments\n"); + return -1; + } else if (argc > 2) { + fprintf(stderr, "too many arguments\n"); + return -1; + } + + // find source object + char* src = argv[0]; + srcFile = parse_path(src); + if (!srcFile) { + fprintf(stderr, "could not find %s\n", src); + return -1; + } + info = srcFile->getObjectInfo(); + if (!info) { + fprintf(stderr, "could not find object info for %s\n", src); + goto fail; + } + if (info->mFormat == MTP_FORMAT_ASSOCIATION) { + fprintf(stderr, "copying directories not implemented yet\n"); + goto fail; + } + + dest = (argc > 1 ? argv[1] : info->mName); + destFD = open(dest, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (destFD < 0) { + fprintf(stderr, "could not create %s\n", dest); + goto fail; + } + srcFD = srcFile->getDevice()->readObject(info->mHandle, info->mCompressedSize); + if (srcFD < 0) + goto fail; + + char buffer[65536]; + while (1) { + int count = read(srcFD, buffer, sizeof(buffer)); + if (count <= 0) + break; + write(destFD, buffer, count); + } + // FIXME - error checking and reporting + ret = 0; + +fail: + delete srcFile; + delete info; + if (srcFD >= 0) + close(srcFD); + if (destFD >= 0) + close(destFD); + return ret; +} + +static int put_file(int argc, char* argv[]) { + int ret = -1; + int srcFD = -1; + MtpFile* destFile = NULL; + MtpObjectInfo* srcInfo = NULL; + MtpObjectInfo* destInfo = NULL; + MtpObjectHandle handle; + struct stat statbuf; + const char* lastSlash; + + if (argc < 1) { + fprintf(stderr, "not enough arguments\n"); + return -1; + } else if (argc > 2) { + fprintf(stderr, "too many arguments\n"); + return -1; + } + const char* src = argv[0]; + srcFD = open(src, O_RDONLY); + if (srcFD < 0) { + fprintf(stderr, "could not open %s\n", src); + goto fail; + } + if (argc == 2) { + char* dest = argv[1]; + destFile = parse_path(dest); + if (!destFile) { + fprintf(stderr, "could not find %s\n", dest); + goto fail; + } + } else { + if (!sCurrentDirectory) { + fprintf(stderr, "current working directory not set\n"); + goto fail; + } + destFile = new MtpFile(sCurrentDirectory); + } + + destInfo = destFile->getObjectInfo(); + if (!destInfo) { + fprintf(stderr, "could not find object info destination directory\n"); + goto fail; + } + if (destInfo->mFormat != MTP_FORMAT_ASSOCIATION) { + fprintf(stderr, "destination not a directory\n"); + goto fail; + } + + if (fstat(srcFD, &statbuf)) + goto fail; + + srcInfo = new MtpObjectInfo(0); + srcInfo->mStorageID = destInfo->mStorageID; + srcInfo->mFormat = MTP_FORMAT_EXIF_JPEG; // FIXME + srcInfo->mCompressedSize = statbuf.st_size; + srcInfo->mParent = destInfo->mHandle; + lastSlash = strrchr(src, '/'); + srcInfo->mName = strdup(lastSlash ? lastSlash + 1 : src); + srcInfo->mDateModified = statbuf.st_mtime; + handle = destFile->getDevice()->sendObjectInfo(srcInfo); + if (handle <= 0) { + printf("sendObjectInfo returned %04X\n", handle); + goto fail; + } + if (destFile->getDevice()->sendObject(srcInfo, srcFD)) + ret = 0; + +fail: + delete destFile; + delete srcInfo; + delete destInfo; + if (srcFD >= 0) + close(srcFD); + printf("returning %d\n", ret); + return ret; +} + +typedef int (* command_func)(int argc, char* argv[]); + +struct command_table_entry { + const char* name; + command_func func; +}; + +const command_table_entry command_list[] = { + { "cd", set_cwd }, + { "ls", list }, + { "get", get_file }, + { "put", put_file }, + { NULL, NULL }, +}; + + +static int do_command(int argc, char* argv[]) { + const command_table_entry* command = command_list; + const char* name = *argv++; + argc--; + + while (command->name) { + if (!strcmp(command->name, name)) + return command->func(argc, argv); + else + command++; + } + fprintf(stderr, "unknown command %s\n", name); + return -1; +} + +static int shell() { + int argc; + int result = 0; +#define MAX_ARGS 100 + char* argv[MAX_ARGS]; + +#if HAVE_READLINE + using_history(); +#endif + + while (1) { +#if HAVE_READLINE + char* line = readline(PROMPT); + if (!line) { + printf("\n"); + exit(0); + } +#else + char buffer[1000]; + printf("%s", PROMPT); + char* line = NULL; + size_t length = 0; + + buffer[0] = 0; + fgets(buffer, sizeof(buffer), stdin); + int count = strlen(buffer); + if (count > 0 && buffer[0] == EOF) { + printf("\n"); + exit(0); + } + if (count > 0 && line[count - 1] == '\n') + line[count - 1] == 0; +#endif + char* tok = strtok(line, " \t\n\r"); + if (!tok) + continue; + if (!strcmp(tok, "quit") || !strcmp(tok, "exit")) { + exit(0); + } +#if HAVE_READLINE + add_history(line); +#endif + argc = 0; + while (tok) { + if (argc + 1 == MAX_ARGS) { + fprintf(stderr, "too many arguments\n"); + result = -1; + goto bottom_of_loop; + } + + argv[argc++] = strdup(tok); + tok = strtok(NULL, " \t\n\r"); + } + + result = do_command(argc, argv); + +bottom_of_loop: + for (int i = 0; i < argc; i++) + free(argv[i]); + free(line); + } + + return result; +} + +int main(int argc, char* argv[]) { + init(); + + if (argc == 1) + return shell(); + else + return do_command(argc - 1, argv + 1); +} |