From 1affb32b667d1d16ab6eafb3303d72cb07774c71 Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Sat, 10 Sep 2022 14:00:19 +0100 Subject: Allow emulating failed events This is required to emulate devices that just reset (without completing the current transfer) when asked to reset. --- gusb/gusb-device-event-private.h | 2 ++ gusb/gusb-device-event.c | 41 ++++++++++++++++++++++++++++++++++++++++ gusb/gusb-device-event.h | 2 ++ gusb/gusb-device.c | 34 +++++++++++++++++++++++++++++++++ gusb/libgusb.ver | 1 + 5 files changed, 80 insertions(+) diff --git a/gusb/gusb-device-event-private.h b/gusb/gusb-device-event-private.h index 0e78cff..5bd8616 100644 --- a/gusb/gusb-device-event-private.h +++ b/gusb/gusb-device-event-private.h @@ -17,6 +17,8 @@ GUsbDeviceEvent * _g_usb_device_event_new(const gchar *id); void _g_usb_device_event_set_bytes_raw(GUsbDeviceEvent *self, gconstpointer buf, gsize bufsz); +void +_g_usb_device_event_set_status(GUsbDeviceEvent *self, gint status); gboolean _g_usb_device_event_load(GUsbDeviceEvent *self, JsonObject *json_object, GError **error); diff --git a/gusb/gusb-device-event.c b/gusb/gusb-device-event.c index 4f38131..d268807 100644 --- a/gusb/gusb-device-event.c +++ b/gusb/gusb-device-event.c @@ -17,6 +17,7 @@ struct _GUsbDeviceEvent { GObject parent_instance; gchar *id; + gint status; GBytes *bytes; }; @@ -58,6 +59,9 @@ _g_usb_device_event_load(GUsbDeviceEvent *self, JsonObject *json_object, GError #if JSON_CHECK_VERSION(1, 6, 0) /* optional properties */ self->id = g_strdup(json_object_get_string_member_with_default(json_object, "Id", NULL)); + self->status = json_object_get_int_member_with_default(json_object, + "Status", + LIBUSB_TRANSFER_COMPLETED); /* extra data */ str = json_object_get_string_member_with_default(json_object, "Data", NULL); @@ -92,6 +96,10 @@ _g_usb_device_event_save(GUsbDeviceEvent *self, JsonBuilder *json_builder, GErro json_builder_set_member_name(json_builder, "Id"); json_builder_add_string_value(json_builder, self->id); } + if (self->status != LIBUSB_TRANSFER_COMPLETED) { + json_builder_set_member_name(json_builder, "Status"); + json_builder_add_int_value(json_builder, self->status); + } if (self->bytes != NULL) { g_autofree gchar *str = g_base64_encode(g_bytes_get_data(self->bytes, NULL), g_bytes_get_size(self->bytes)); @@ -138,6 +146,39 @@ g_usb_device_event_get_id(GUsbDeviceEvent *self) return self->id; } +/** + * g_usb_device_event_get_status: + * @self: a #GUsbDeviceEvent + * + * Gets any status data from the event. + * + * Return value: (transfer none): a `enum libusb_transfer_status`, or -1 for failure + * + * Since: 0.4.0 + **/ +gint +g_usb_device_event_get_status(GUsbDeviceEvent *self) +{ + g_return_val_if_fail(G_USB_IS_DEVICE_EVENT(self), -1); + return self->status; +} + +/** + * _g_usb_device_event_set_status: + * @self: a #GUsbDeviceEvent + * @status: `enum libusb_transfer_status` + * + * Set the status of the event, e.g. `LIBUSB_TRANSFER_COMPLETED`. + * + * Since: 0.4.0 + **/ +void +_g_usb_device_event_set_status(GUsbDeviceEvent *self, gint status) +{ + g_return_if_fail(G_USB_IS_DEVICE_EVENT(self)); + self->status = status; +} + /** * g_usb_device_event_get_bytes: * @self: a #GUsbDeviceEvent diff --git a/gusb/gusb-device-event.h b/gusb/gusb-device-event.h index f44db43..c9e48a9 100644 --- a/gusb/gusb-device-event.h +++ b/gusb/gusb-device-event.h @@ -18,6 +18,8 @@ const gchar * g_usb_device_event_get_id(GUsbDeviceEvent *self); GBytes * g_usb_device_event_get_bytes(GUsbDeviceEvent *self); +gint +g_usb_device_event_get_status(GUsbDeviceEvent *self); void g_usb_device_event_set_bytes(GUsbDeviceEvent *self, GBytes *bytes); diff --git a/gusb/gusb-device.c b/gusb/gusb-device.c index 0458451..f1135c8 100644 --- a/gusb/gusb-device.c +++ b/gusb/gusb-device.c @@ -1836,6 +1836,8 @@ g_usb_device_async_transfer_cb(struct libusb_transfer *transfer) /* did request fail? */ ret = g_usb_device_libusb_status_to_gerror(transfer->status, &error); if (!ret) { + if (req->event != NULL) + _g_usb_device_event_set_status(req->event, transfer->status); g_task_return_error(task, error); } else { if (req->event != NULL) { @@ -1866,6 +1868,8 @@ g_usb_device_control_transfer_cb(struct libusb_transfer *transfer) /* did request fail? */ ret = g_usb_device_libusb_status_to_gerror(transfer->status, &error); if (!ret) { + if (req->event != NULL) + _g_usb_device_event_set_status(req->event, transfer->status); g_task_return_error(task, error); } else { memmove(req->data, @@ -1988,6 +1992,16 @@ g_usb_device_control_transfer_async(GUsbDevice *self, event_id); return; } + if (g_usb_device_event_get_status(event) != LIBUSB_TRANSFER_COMPLETED) { + g_usb_device_libusb_status_to_gerror(g_usb_device_event_get_status(event), + &error); + g_task_report_error(self, + callback, + user_data, + g_usb_device_control_transfer_async, + error); + return; + } bytes = g_usb_device_event_get_bytes(event); if (bytes == NULL) { g_task_report_new_error(self, @@ -2165,6 +2179,16 @@ g_usb_device_bulk_transfer_async(GUsbDevice *self, event_id); return; } + if (g_usb_device_event_get_status(event) != LIBUSB_TRANSFER_COMPLETED) { + g_usb_device_libusb_status_to_gerror(g_usb_device_event_get_status(event), + &error); + g_task_report_error(self, + callback, + user_data, + g_usb_device_control_transfer_async, + error); + return; + } bytes = g_usb_device_event_get_bytes(event); if (bytes == NULL) { g_task_report_new_error(self, @@ -2331,6 +2355,16 @@ g_usb_device_interrupt_transfer_async(GUsbDevice *self, event_id); return; } + if (g_usb_device_event_get_status(event) != LIBUSB_TRANSFER_COMPLETED) { + g_usb_device_libusb_status_to_gerror(g_usb_device_event_get_status(event), + &error); + g_task_report_error(self, + callback, + user_data, + g_usb_device_control_transfer_async, + error); + return; + } bytes = g_usb_device_event_get_bytes(event); if (bytes == NULL) { g_task_report_new_error(self, diff --git a/gusb/libgusb.ver b/gusb/libgusb.ver index fbe7890..9977a36 100644 --- a/gusb/libgusb.ver +++ b/gusb/libgusb.ver @@ -176,6 +176,7 @@ LIBGUSB_0.4.0 { g_usb_context_save; g_usb_device_event_get_bytes; g_usb_device_event_get_id; + g_usb_device_event_get_status; g_usb_device_event_get_type; g_usb_device_event_set_bytes; g_usb_device_get_bos_descriptor; -- cgit v1.2.1