Re: [Qemu-devel] [PATCH v4 5/5] usb-mtp: Advertise SendObjectInfo for write support

2018-02-21 Thread Daniel P . Berrangé
On Tue, Feb 20, 2018 at 05:59:04PM -0500, Bandan Das wrote:
> This patch implements a dummy ObjectInfo structure so that
> it's easy to typecast the incoming data. If the metadata is
> valid, write_pending is set. Also, the incoming filename
> is utf-16, so, instead of depending on external libraries, just
> implement a simple function to get the filename
> 
> Signed-off-by: Bandan Das 
> ---
>  hw/usb/dev-mtp.c | 132 
> ++-
>  1 file changed, 130 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
> index 9b51708614..086296f415 100644
> --- a/hw/usb/dev-mtp.c
> +++ b/hw/usb/dev-mtp.c
> @@ -47,6 +47,7 @@ enum mtp_code {
>  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,
> @@ -67,8 +68,10 @@ enum mtp_code {
>  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,
> @@ -196,6 +199,34 @@ struct MTPState {
>  } dataset;
>  };
>  
> +/*
> + * ObjectInfo dataset received from initiator
> + * Fields we don't care about are ignored
> + */
> +typedef struct {
> +uint32_t storage_id; /*unused*/
> +uint16_t format;
> +uint16_t protection_status; /*unused*/
> +uint32_t size;
> +uint16_t thumb_format; /*unused*/
> +uint32_t thumb_comp_sz; /*unused*/
> +uint32_t thumb_pix_width; /*unused*/
> +uint32_t thumb_pix_height; /*unused*/
> +uint32_t image_pix_width; /*unused*/
> +uint32_t image_pix_height; /*unused*/
> +uint32_t image_bit_depth; /*unused*/
> +uint32_t parent; /*unused*/
> +uint16_t assoc_type;
> +uint32_t assoc_desc;
> +uint32_t seq_no; /*unused*/
> +uint8_t length; /*part of filename field*/
> +uint16_t filename[0];
> +char date_created[0]; /*unused*/
> +char date_modified[0]; /*unused*/
> +char keywords[0]; /*unused*/
> +/* string and other data follows */
> +} QEMU_PACKED ObjectInfo;
> +
>  #define TYPE_USB_MTP "usb-mtp"
>  #define USB_MTP(obj) OBJECT_CHECK(MTPState, (obj), TYPE_USB_MTP)
>  
> @@ -437,7 +468,6 @@ static MTPObject *usb_mtp_add_child(MTPState *s, 
> MTPObject *o,
>  return child;
>  }
>  
> -#ifdef CONFIG_INOTIFY1
>  static MTPObject *usb_mtp_object_lookup_name(MTPObject *parent,
>   char *name, int len)
>  {
> @@ -452,6 +482,7 @@ static MTPObject *usb_mtp_object_lookup_name(MTPObject 
> *parent,
>  return NULL;
>  }
>  
> +#ifdef CONFIG_INOTIFY1
>  static MTPObject *usb_mtp_object_lookup_wd(MTPState *s, int wd)
>  {
>  MTPObject *iter;
> @@ -815,6 +846,7 @@ static MTPData *usb_mtp_get_device_info(MTPState *s, 
> MTPControl *c)
>  CMD_GET_OBJECT_HANDLES,
>  CMD_GET_OBJECT_INFO,
>  CMD_DELETE_OBJECT,
> +CMD_SEND_OBJECT_INFO,

Same question about filtering this out for read-only devices,
and somewhere else in this patch validating it too.

>  CMD_SEND_OBJECT,
>  CMD_GET_OBJECT,
>  CMD_GET_PARTIAL_OBJECT,
> @@ -1243,7 +1275,7 @@ static void usb_mtp_object_delete(MTPState *s, uint32_t 
> handle,
>  static void usb_mtp_command(MTPState *s, MTPControl *c)
>  {
>  MTPData *data_in = NULL;
> -MTPObject *o;
> +MTPObject *o = NULL;
>  uint32_t nres = 0, res0 = 0;
>  
>  /* sanity checks */
> @@ -1390,6 +1422,37 @@ static void usb_mtp_command(MTPState *s, MTPControl *c)
>  nres = 1;
>  res0 = data_in->length;
>  break;
> +case CMD_SEND_OBJECT_INFO:
> +/* First parameter points to storage id or is 0 */
> +if (c->argv[0] && (c->argv[0] != QEMU_STORAGE_ID)) {
> +usb_mtp_queue_result(s, RES_STORE_NOT_AVAILABLE, c->trans,
> + 0, 0, 0, 0);
> +} else if (c->argv[1] && !c->argv[0]) {
> +/* If second parameter is specified, first must also be 
> specified */
> +usb_mtp_queue_result(s, RES_DESTINATION_UNSUPPORTED, c->trans,
> + 0, 0, 0, 0);
> +} else {
> +uint32_t handle = c->argv[1];
> +if (handle == 0x || handle == 0) {
> +/* root object */
> +o = QTAILQ_FIRST(>objects);
> +} else {
> +o = usb_mtp_object_lookup(s, handle);
> +}
> +

[Qemu-devel] [PATCH v4 5/5] usb-mtp: Advertise SendObjectInfo for write support

2018-02-20 Thread Bandan Das
This patch implements a dummy ObjectInfo structure so that
it's easy to typecast the incoming data. If the metadata is
valid, write_pending is set. Also, the incoming filename
is utf-16, so, instead of depending on external libraries, just
implement a simple function to get the filename

Signed-off-by: Bandan Das 
---
 hw/usb/dev-mtp.c | 132 ++-
 1 file changed, 130 insertions(+), 2 deletions(-)

diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 9b51708614..086296f415 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -47,6 +47,7 @@ enum mtp_code {
 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,
@@ -67,8 +68,10 @@ enum mtp_code {
 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,
@@ -196,6 +199,34 @@ struct MTPState {
 } dataset;
 };
 
+/*
+ * ObjectInfo dataset received from initiator
+ * Fields we don't care about are ignored
+ */
+typedef struct {
+uint32_t storage_id; /*unused*/
+uint16_t format;
+uint16_t protection_status; /*unused*/
+uint32_t size;
+uint16_t thumb_format; /*unused*/
+uint32_t thumb_comp_sz; /*unused*/
+uint32_t thumb_pix_width; /*unused*/
+uint32_t thumb_pix_height; /*unused*/
+uint32_t image_pix_width; /*unused*/
+uint32_t image_pix_height; /*unused*/
+uint32_t image_bit_depth; /*unused*/
+uint32_t parent; /*unused*/
+uint16_t assoc_type;
+uint32_t assoc_desc;
+uint32_t seq_no; /*unused*/
+uint8_t length; /*part of filename field*/
+uint16_t filename[0];
+char date_created[0]; /*unused*/
+char date_modified[0]; /*unused*/
+char keywords[0]; /*unused*/
+/* string and other data follows */
+} QEMU_PACKED ObjectInfo;
+
 #define TYPE_USB_MTP "usb-mtp"
 #define USB_MTP(obj) OBJECT_CHECK(MTPState, (obj), TYPE_USB_MTP)
 
@@ -437,7 +468,6 @@ static MTPObject *usb_mtp_add_child(MTPState *s, MTPObject 
*o,
 return child;
 }
 
-#ifdef CONFIG_INOTIFY1
 static MTPObject *usb_mtp_object_lookup_name(MTPObject *parent,
  char *name, int len)
 {
@@ -452,6 +482,7 @@ static MTPObject *usb_mtp_object_lookup_name(MTPObject 
*parent,
 return NULL;
 }
 
+#ifdef CONFIG_INOTIFY1
 static MTPObject *usb_mtp_object_lookup_wd(MTPState *s, int wd)
 {
 MTPObject *iter;
@@ -815,6 +846,7 @@ static MTPData *usb_mtp_get_device_info(MTPState *s, 
MTPControl *c)
 CMD_GET_OBJECT_HANDLES,
 CMD_GET_OBJECT_INFO,
 CMD_DELETE_OBJECT,
+CMD_SEND_OBJECT_INFO,
 CMD_SEND_OBJECT,
 CMD_GET_OBJECT,
 CMD_GET_PARTIAL_OBJECT,
@@ -1243,7 +1275,7 @@ static void usb_mtp_object_delete(MTPState *s, uint32_t 
handle,
 static void usb_mtp_command(MTPState *s, MTPControl *c)
 {
 MTPData *data_in = NULL;
-MTPObject *o;
+MTPObject *o = NULL;
 uint32_t nres = 0, res0 = 0;
 
 /* sanity checks */
@@ -1390,6 +1422,37 @@ static void usb_mtp_command(MTPState *s, MTPControl *c)
 nres = 1;
 res0 = data_in->length;
 break;
+case CMD_SEND_OBJECT_INFO:
+/* First parameter points to storage id or is 0 */
+if (c->argv[0] && (c->argv[0] != QEMU_STORAGE_ID)) {
+usb_mtp_queue_result(s, RES_STORE_NOT_AVAILABLE, c->trans,
+ 0, 0, 0, 0);
+} else if (c->argv[1] && !c->argv[0]) {
+/* If second parameter is specified, first must also be specified 
*/
+usb_mtp_queue_result(s, RES_DESTINATION_UNSUPPORTED, c->trans,
+ 0, 0, 0, 0);
+} else {
+uint32_t handle = c->argv[1];
+if (handle == 0x || handle == 0) {
+/* root object */
+o = QTAILQ_FIRST(>objects);
+} else {
+o = usb_mtp_object_lookup(s, handle);
+}
+if (o == NULL) {
+usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE, c->trans,
+ 0, 0, 0, 0);
+}
+if (o->format != FMT_ASSOCIATION) {
+usb_mtp_queue_result(s, RES_INVALID_PARENT_OBJECT, c->trans,
+ 0, 0, 0, 0);
+}
+}
+if (o) {
+s->dataset.parent_handle = o->handle;
+