qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2 2/2] usb-mtp: added object properties


From: Bandan Das
Subject: Re: [Qemu-devel] [PATCH v2 2/2] usb-mtp: added object properties
Date: Wed, 27 Jul 2016 16:41:10 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux)

Isaac Lozano <address@hidden> writes:

> Windows uses object properties to determine the size of a file, so to
> add object properties, we must also add a minimum set of new commands
> and object properties. Most object properties are data that we already
> have, except for the unique persistant object identifier. Windows
> doesn't use this property, it seems, so we can cheat a bit and just use
> the object handle for it.
>
> Signed-off-by: Isaac Lozano <address@hidden>
> ---
>  hw/usb/dev-mtp.c | 186 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 181 insertions(+), 5 deletions(-)
>
> diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
> index 6f6a270..fa0c81e 100644
> --- a/hw/usb/dev-mtp.c
> +++ b/hw/usb/dev-mtp.c
> @@ -48,6 +48,9 @@ enum mtp_code {
>      CMD_GET_OBJECT_INFO            = 0x1008,
>      CMD_GET_OBJECT                 = 0x1009,
>      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,
> @@ -59,10 +62,12 @@ enum mtp_code {
>      RES_INCOMPLETE_TRANSFER        = 0x2007,
>      RES_INVALID_STORAGE_ID         = 0x2008,
>      RES_INVALID_OBJECT_HANDLE      = 0x2009,
> +    RES_INVALID_OBJECT_FORMAT_CODE = 0x200b,
>      RES_SPEC_BY_FORMAT_UNSUPPORTED = 0x2014,
>      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,
> @@ -72,6 +77,22 @@ enum mtp_code {
>      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 {
> @@ -778,6 +799,9 @@ static MTPData *usb_mtp_get_device_info(MTPState *s, 
> MTPControl *c)
>          CMD_GET_OBJECT_INFO,
>          CMD_GET_OBJECT,
>          CMD_GET_PARTIAL_OBJECT,
> +        CMD_GET_OBJECT_PROPS_SUPPORTED,
> +        CMD_GET_OBJECT_PROP_DESC,
> +        CMD_GET_OBJECT_PROP_VALUE,
>      };
>      static const uint16_t fmt[] = {
>          FMT_UNDEFINED_OBJECT,
> @@ -886,8 +910,7 @@ static MTPData *usb_mtp_get_object_info(MTPState *s, 
> MTPControl *c,
>  
>      if (o->stat.st_size > 0xFFFFFFFF) {
>          usb_mtp_add_u32(d, 0xFFFFFFFF);
> -    }
> -    else {
> +    } else {
>          usb_mtp_add_u32(d, o->stat.st_size);
>      }
>  
> @@ -972,6 +995,122 @@ static MTPData *usb_mtp_get_partial_object(MTPState *s, 
> MTPControl *c,
>      return d;
>  }
>  
> +static MTPData *usb_mtp_get_object_props_supported(MTPState *s, MTPControl 
> *c)
> +{
> +    static const uint16_t props[] = {
> +        PROP_STORAGE_ID,
> +        PROP_OBJECT_FORMAT,
> +        PROP_OBJECT_COMPRESSED_SIZE,
> +        PROP_PARENT_OBJECT,
> +        PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER,
> +        PROP_NAME,
> +    };
> +    MTPData *d = usb_mtp_data_alloc(c);
> +    usb_mtp_add_u16_array(d, ARRAY_SIZE(props), props);
> +
> +    return d;
> +}
> +
> +static MTPData *usb_mtp_get_object_prop_desc(MTPState *s, MTPControl *c)
> +{
> +    MTPData *d = usb_mtp_data_alloc(c);
> +    switch (c->argv[0]) {
> +    case PROP_STORAGE_ID:
> +        usb_mtp_add_u16(d, PROP_STORAGE_ID);
> +        usb_mtp_add_u16(d, DATA_TYPE_UINT32);
> +        usb_mtp_add_u8(d, 0x00);
> +        usb_mtp_add_u32(d, 0x00000000);
> +        usb_mtp_add_u32(d, 0x00000000);
> +        usb_mtp_add_u8(d, 0x00);
> +        break;
Stylistic:

Can rewrite all 0 valued calls to usb_mtp_add_u32(d, 0) and the like
but this is fine too :)

> +    case PROP_OBJECT_FORMAT:
> +        usb_mtp_add_u16(d, PROP_OBJECT_FORMAT);
> +        usb_mtp_add_u16(d, DATA_TYPE_UINT16);
> +        usb_mtp_add_u8(d, 0x00);
> +        usb_mtp_add_u16(d, 0x0000);
> +        usb_mtp_add_u32(d, 0x00000000);
> +        usb_mtp_add_u8(d, 0x00);
> +        break;
> +    case PROP_OBJECT_COMPRESSED_SIZE:
> +        usb_mtp_add_u16(d, PROP_OBJECT_COMPRESSED_SIZE);
> +        usb_mtp_add_u16(d, DATA_TYPE_UINT64);
> +        usb_mtp_add_u8(d, 0x00);
> +        usb_mtp_add_u64(d, 0x0000000000000000);
> +        usb_mtp_add_u32(d, 0x00000000);
> +        usb_mtp_add_u8(d, 0x00);
> +        break;
> +    case PROP_PARENT_OBJECT:
> +        usb_mtp_add_u16(d, PROP_PARENT_OBJECT);
> +        usb_mtp_add_u16(d, DATA_TYPE_UINT32);
> +        usb_mtp_add_u8(d, 0x00);
> +        usb_mtp_add_u32(d, 0x00000000);
> +        usb_mtp_add_u32(d, 0x00000000);
> +        usb_mtp_add_u8(d, 0x00);
> +        break;
> +    case PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER:
> +        usb_mtp_add_u16(d, PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER);
> +        usb_mtp_add_u16(d, DATA_TYPE_UINT128);
> +        usb_mtp_add_u8(d, 0x00);
> +        usb_mtp_add_u64(d, 0x0000000000000000);
> +        usb_mtp_add_u64(d, 0x0000000000000000);
> +        usb_mtp_add_u32(d, 0x00000000);
> +        usb_mtp_add_u8(d, 0x00);
> +        break;
> +    case PROP_NAME:
> +        usb_mtp_add_u16(d, PROP_NAME);
> +        usb_mtp_add_u16(d, DATA_TYPE_STRING);
> +        usb_mtp_add_u8(d, 0x00);
> +        usb_mtp_add_u8(d, 0x00);
> +        usb_mtp_add_u32(d, 0x00000000);
> +        usb_mtp_add_u8(d, 0x00);
> +        break;
> +    default:
> +        usb_mtp_data_free(d);
> +        return NULL;
> +    }
> +
> +    return d;
> +}
> +
> +static MTPData *usb_mtp_get_object_prop_value(MTPState *s, MTPControl *c,
> +                                              MTPObject *o)
> +{
> +    MTPData *d = usb_mtp_data_alloc(c);
> +    switch (c->argv[1]) {
> +    case PROP_STORAGE_ID:
> +        usb_mtp_add_u32(d, QEMU_STORAGE_ID);
> +        break;
> +    case PROP_OBJECT_FORMAT:
> +        usb_mtp_add_u16(d, o->format);
> +        break;
> +    case PROP_OBJECT_COMPRESSED_SIZE:
> +        usb_mtp_add_u64(d, o->stat.st_size);
> +        break;
> +    case PROP_PARENT_OBJECT:
> +        if (o->parent == NULL) {
> +            usb_mtp_add_u32(d, 0x00000000);
> +        } else {
> +            usb_mtp_add_u32(d, o->parent->handle);
> +        }
> +        break;
> +    case PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER:
> +        /* Should be persistant between sessions,
> +         * but using our objedt ID is "good enough"
s/objedt/object

> +         * for now */
> +        usb_mtp_add_u64(d, 0x0000000000000000);
> +        usb_mtp_add_u64(d, o->handle);

I thought we decided on the inode number ? Probably harmless but can't be handle
be different across sessions ? For example, a new file is added followed by a 
new
session.

Bandan

> +        break;
> +    case PROP_NAME:
> +        usb_mtp_add_str(d, o->name);
> +        break;
> +    default:
> +        usb_mtp_data_free(d);
> +        return NULL;
> +    }
> +
> +    return d;
> +}
> +
>  static void usb_mtp_command(MTPState *s, MTPControl *c)
>  {
>      MTPData *data_in = NULL;
> @@ -1119,6 +1258,43 @@ static void usb_mtp_command(MTPState *s, MTPControl *c)
>          nres = 1;
>          res0 = data_in->length;
>          break;
> +    case CMD_GET_OBJECT_PROPS_SUPPORTED:
> +        if (c->argv[0] != FMT_UNDEFINED_OBJECT &&
> +            c->argv[0] != FMT_ASSOCIATION) {
> +            usb_mtp_queue_result(s, RES_INVALID_OBJECT_FORMAT_CODE,
> +                                 c->trans, 0, 0, 0);
> +            return;
> +        }
> +        data_in = usb_mtp_get_object_props_supported(s, c);
> +        break;
> +    case CMD_GET_OBJECT_PROP_DESC:
> +        if (c->argv[1] != FMT_UNDEFINED_OBJECT &&
> +            c->argv[1] != FMT_ASSOCIATION) {
> +            usb_mtp_queue_result(s, RES_INVALID_OBJECT_FORMAT_CODE,
> +                                 c->trans, 0, 0, 0);
> +            return;
> +        }
> +        data_in = usb_mtp_get_object_prop_desc(s, c);
> +        if (data_in == NULL) {
> +            usb_mtp_queue_result(s, RES_INVALID_OBJECT_PROP_CODE,
> +                                 c->trans, 0, 0, 0);
> +            return;
> +        }
> +        break;
> +    case CMD_GET_OBJECT_PROP_VALUE:
> +        o = usb_mtp_object_lookup(s, c->argv[0]);
> +        if (o == NULL) {
> +            usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE,
> +                                 c->trans, 0, 0, 0);
> +            return;
> +        }
> +        data_in = usb_mtp_get_object_prop_value(s, c, o);
> +        if (data_in == NULL) {
> +            usb_mtp_queue_result(s, RES_INVALID_OBJECT_PROP_CODE,
> +                                 c->trans, 0, 0, 0);
> +            return;
> +        }
> +        break;
>      default:
>          trace_usb_mtp_op_unknown(s->dev.addr, c->code);
>          usb_mtp_queue_result(s, RES_OPERATION_NOT_SUPPORTED,
> @@ -1204,9 +1380,9 @@ static void usb_mtp_handle_data(USBDevice *dev, 
> USBPacket *p)
>                  trace_usb_mtp_data_in(s->dev.addr, d->trans, d->length);
>                  if (d->length + sizeof(container) > 0xFFFFFFFF) {
>                      container.length = cpu_to_le32(0xFFFFFFFF);
> -                }
> -                else {
> -                    container.length = cpu_to_le32(d->length + 
> sizeof(container));
> +                } else {
> +                    container.length = cpu_to_le32(d->length +
> +                                                   sizeof(container));
>                  }
>                  container.type   = cpu_to_le16(TYPE_DATA);
>                  container.code   = cpu_to_le16(d->code);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]