diff mbox series

[07/25] efw-downloader: efw-proto: emit responded signal at receiving response

Message ID 20200821073111.134857-8-o-takashi@sakamocchi.jp (mailing list archive)
State New, archived
Headers show
Series alsa-tools: efw-downloader: add initial version of firmwre downloader for Echo Audio Fireworks devices | expand

Commit Message

Takashi Sakamoto Aug. 21, 2020, 7:30 a.m. UTC
HinawaFwResp has class virtual method for applications to handle received
frame on 1394 OHCI controller by overriding the method with own function
implementation.

This commit overrides the class virtual method and emits 'responded'
signal with the data of received response frame. The content of frame
is aligned to host-endianness, then passed to signal handlers.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 efw-downloader/src/efw-proto.c | 43 ++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)
diff mbox series

Patch

diff --git a/efw-downloader/src/efw-proto.c b/efw-downloader/src/efw-proto.c
index 72959ac..bef81b3 100644
--- a/efw-downloader/src/efw-proto.c
+++ b/efw-downloader/src/efw-proto.c
@@ -3,6 +3,8 @@ 
 #include "efw-proto.h"
 #include "efw-proto-sigs-marshal.h"
 
+#include <sound/firewire.h>
+
 /**
  * SECTION:efw_proto
  * @Title: EfwProto
@@ -38,12 +40,16 @@  static void proto_finalize(GObject *obj)
     G_OBJECT_CLASS(efw_proto_parent_class)->finalize(obj);
 }
 
+static HinawaFwRcode proto_handle_response(HinawaFwResp *resp, HinawaFwTcode tcode);
+
 static void efw_proto_class_init(EfwProtoClass *klass)
 {
     GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
 
     gobject_class->finalize = proto_finalize;
 
+    HINAWA_FW_RESP_CLASS(klass)->requested = proto_handle_response;
+
     /**
      * EfwProto::responded:
      * @self: A #EfwProto.
@@ -126,3 +132,40 @@  void efw_proto_unbind(EfwProto *self)
 
     g_free(priv->buf);
 }
+
+static HinawaFwRcode proto_handle_response(HinawaFwResp *resp, HinawaFwTcode tcode)
+{
+    EfwProto *self = EFW_PROTO(resp);
+    EfwProtoPrivate *priv = efw_proto_get_instance_private(self);
+    const guint8 *req_frame = NULL;
+    gsize length = 0;
+    const struct snd_efw_transaction *frame;
+    guint status;
+    guint seqnum;
+    guint category;
+    guint command;
+    guint param_count;
+    int i;
+
+    hinawa_fw_resp_get_req_frame(resp, &req_frame, &length);
+    if (length < sizeof(*frame))
+        return HINAWA_FW_RCODE_DATA_ERROR;
+    frame = (const struct snd_efw_transaction *)req_frame;
+
+    status = GUINT32_FROM_BE(frame->status);
+    if (status > HINAWA_SND_EFW_STATUS_BAD_PARAMETER)
+        status = HINAWA_SND_EFW_STATUS_BAD;
+
+    seqnum = GUINT32_FROM_BE(frame->seqnum);
+    category = GUINT32_FROM_BE(frame->category);
+    command = GUINT32_FROM_BE(frame->command);
+    param_count = GUINT32_FROM_BE(frame->length) - sizeof(*frame) / sizeof(guint32);
+
+    for (i = 0; i < param_count; ++i)
+        priv->buf[i] = GUINT32_FROM_BE(frame->params[i]);
+
+    g_signal_emit(self, efw_proto_sigs[EFW_PROTO_SIG_TYPE_RESPONDED], 0,
+                  status, seqnum, category, command, priv->buf, param_count);
+
+    return HINAWA_FW_RCODE_COMPLETE;
+}