/*
* Media Transfer Protocol implementation, backed by host filesystem.
*
* Copyright Red Hat, Inc 2014
*
* Author:
* Gerd Hoffmann <kraxel@redhat.com>
*
* This code is licensed under the GPL v2 or later.
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include <wchar.h>
#include <dirent.h>
#include <glib/gstdio.h>
#include <sys/statvfs.h>
#include "qemu/iov.h"
#include "qemu/module.h"
#include "qemu/filemonitor.h"
#include "trace.h"
#include "hw/qdev-properties.h"
#include "hw/usb.h"
#include "migration/vmstate.h"
#include "desc.h"
#include "qemu/units.h"
#include "qom/object.h"
/* ----------------------------------------------------------------------- */
enum mtp_container_type {
TYPE_COMMAND = 1,
TYPE_DATA = 2,
TYPE_RESPONSE = 3,
TYPE_EVENT = 4,
};
/* MTP write stage, for internal use only */
enum mtp_write_status {
WRITE_START = 1,
WRITE_CONTINUE = 2,
WRITE_END = 3,
};
enum mtp_code {
/* command codes */
CMD_GET_DEVICE_INFO = 0x1001,
CMD_OPEN_SESSION = 0x1002,
CMD_CLOSE_SESSION = 0x1003,
CMD_GET_STORAGE_IDS = 0x1004,
CMD_GET_STORAGE_INFO = 0x1005,
CMD_GET_NUM_OBJECTS = 0x1006,
CMD_GET_OBJECT_HANDLES = 0x1007,
CMD_GET_OBJECT_INFO = 0x1008,
CMD_GET_OBJECT = 0x1009,
CMD_DELETE_OBJECT = 0x100b,
CMD_SEND_OBJECT_INFO = 0x100c,
CMD_SEND_OBJECT = 0x100d,
CMD_GET_PARTIAL_OBJECT = 0x101b,
CMD_GET_OBJECT_PROPS_SUPPORTED = 0x9801,
CMD_GET_OBJECT_PROP_DESC = 0x9802,
CMD_GET_OBJECT_PROP_VALUE = 0x9803,
/* response codes */
RES_OK = 0x2001,
RES_GENERAL_ERROR = 0x2002,
RES_SESSION_NOT_OPEN = 0x2003,
RES_INVALID_TRANSACTION_ID = 0x2004,
RES_OPERATION_NOT_SUPPORTED = 0x2005,
RES_PARAMETER_NOT_SUPPORTED = 0x2006,
RES_INCOMPLETE_TRANSFER = 0x2007,
RES_INVALID_STORAGE_ID = 0x2008,
RES_INVALID_OBJECT_HANDLE = 0x2009,
RES_INVALID_OBJECT_FORMAT_CODE = 0x200b,
RES_STORE_FULL = 0x200c,
RES_STORE_READ_ONLY = 0x200e,
RES_PARTIAL_DELETE = 0x2012,
RES_STORE_NOT_AVAILABLE = 0x2013,
RES_SPEC_BY_FORMAT_UNSUPPORTED = 0x2014,
RES_INVALID_OBJECTINFO = 0x2015,
RES_DESTINATION_UNSUPPORTED = 0x2020,
RES_INVALID_PARENT_OBJECT = 0x201a,
RES_INVALID_PARAMETER = 0x201d,
RES_SESSION_ALREADY_OPEN = 0x201e,
RES_INVALID_OBJECT_PROP_CODE = 0xA801,
/* format codes */
FMT_UNDEFINED_OBJECT = 0x3000,
FMT_ASSOCIATION = 0x3001,
/* event codes */
EVT_CANCEL_TRANSACTION = 0x4001,
EVT_OBJ_ADDED = 0x4002,
EVT_OBJ_REMOVED = 0x4003,
EVT_OBJ_INFO_CHANGED = 0x4007,
/* object properties */
PROP_STORAGE_ID = 0xDC01,
PROP_OBJECT_FORMAT = 0xDC02,
PROP_OBJECT_COMPRESSED_SIZE = 0xDC04,
PROP_PARENT_OBJECT = 0xDC0B,
PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER = 0xDC41,
PROP_NAME = 0xDC44,
};
enum mtp_data_type {
DATA_TYPE_UINT16 = 0x0004,
DATA_TYPE_UINT32 = 0x0006,
DATA_TYPE_UINT64 = 0x0008,
DATA_TYPE_UINT128 = 0x000a,
DATA_TYPE_STRING = 0xffff,
};
typedef struct {
uint32_t length;
uint16_t type;
uint16_t code;
uint32_t trans;
} QEMU_PACKED mtp_container;
/* ----------------------------------------------------------------------- */
typedef struct MTPState MTPState;
typedef struct MTPControl MTPControl;
typedef struct MTPData MTPData;
typedef struct MTPObject MTPObject;
enum {
EP_DATA_IN = 1,
EP_DATA_OUT,
EP_EVENT,
};
typedef struct MTPMonEntry MTPMonEntry;
struct MTPMonEntry {
uint32_t event;
uint32_t handle;
QTAILQ_ENTRY(MTPMonEntry) next;
};
struct MTPControl {
uint16_t code;
uint32_t trans;
int argc;
uint32_t argv[5];
};
struct MTPData {
uint16_t code;
uint32_t trans;
uint64_t offset;
uint64_t length;
uint64_t alloc;
uint8_t *data;
bool first;
/* Used for >4G file sizes */
bool pending;
int fd;
uint8_t write_status;
/* Internal pointer per every MTP_WRITE_BUF_SZ */
uint64_t data_offset;
};
struct MTPObject {
|