diff --git a/include/control.h b/include/control.h
index 36953423..1b2cc0c6 100644
--- a/include/control.h
+++ b/include/control.h
@@ -427,6 +427,7 @@ void snd_ctl_elem_id_copy(snd_ctl_elem_id_t *dst, const snd_ctl_elem_id_t *src);
 int snd_ctl_elem_id_equal_by_numid(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r);
 int snd_ctl_elem_id_equal_by_tuple(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r);
 int snd_ctl_elem_id_compare_by_numid(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r);
+int snd_ctl_elem_id_compare_by_tuple_arithmetic(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r);
 int snd_ctl_elem_id_compare(snd_ctl_elem_id_t *id1, const snd_ctl_elem_id_t *id2);
 unsigned int snd_ctl_elem_id_get_numid(const snd_ctl_elem_id_t *obj);
 snd_ctl_elem_iface_t snd_ctl_elem_id_get_interface(const snd_ctl_elem_id_t *obj);
diff --git a/src/control/control.c b/src/control/control.c
index 00009614..fbc6aeb7 100644
--- a/src/control/control.c
+++ b/src/control/control.c
@@ -90,7 +90,9 @@ is available.
 
 Many algorithms can be defined to find ordered pair of #snd_ctl_elem_id_t.
 For one of the comparison algorithms according to the numid,
-snd_ctl_elem_id_compare_by_numid() is available.
+snd_ctl_elem_id_compare_by_numid() is available. For one of the comparison
+algorithms according to the tuple, snd_ctl_elem_id_compare_by_tuple_arithmetic()
+is available. They are useful for qsort(3).
 
 \section element_lists Element Lists
 
@@ -1893,6 +1895,47 @@ int snd_ctl_elem_id_compare_by_numid(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
 	return compare_unsigned_integer(l->numid, r->numid);
 }
 
+/**
+ * \brief compare two arguments as ordered pair by one of algorithms according
+ *	  to iface, device, subdevice, name, index fields.
+ * \param l opaque pointer to element ID structure.
+ * \param r opaque pointer to another element ID structure.
+ * \retval positive if left is greater than right, negative if left is less
+ *	   than right, zero if they equal.
+ *
+ * The structure underlying #snd_ctl_elem_id_t is compound one. The comparison
+ * algorithm for it is not single and unique. The API implements one of
+ * algorithm to find order in a pair of control element IDs, according to the
+ * values of iface, device, subdevice, name, and index fields, by below logic:
+ *
+ *  - find order in iface field by this order; card, hwdep, mixer, pcm, rawmidi,
+ *    timer, and sequencer.
+ *  - find order in device field by arithmetic comparison of its value.
+ *  - find order in subdevice field by arithmetic comparison of its value.
+ *  - find order in name field by using unsigned characters, implemented in strcmp(3).
+ *  - find order in index field by arithmetic comparison of its value.
+ */
+int snd_ctl_elem_id_compare_by_tuple_arithmetic(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	int res;
+
+	assert(l && r);
+
+	res = l->iface - r->iface;
+	if (res != 0)
+		return res;
+	res = compare_unsigned_integer(l->device, r->device);
+	if (res != 0)
+		return res;
+	res = compare_unsigned_integer(l->subdevice, r->subdevice);
+	if (res != 0)
+		return res;
+	res = strcmp((const char *)l->name, (const char *)r->name);
+	if (res != 0)
+		return res;
+	return compare_unsigned_integer(l->index, r->index);
+}
+
 /**
  * \brief compare one #snd_ctl_elem_id_t to another
  * \param id1 pointer to first id
diff --git a/test/lsb/ctl-elem-id.c b/test/lsb/ctl-elem-id.c
index 670ec252..02eb24fc 100644
--- a/test/lsb/ctl-elem-id.c
+++ b/test/lsb/ctl-elem-id.c
@@ -135,6 +135,106 @@ static void comparison_by_numid_3(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
 	assert(snd_ctl_elem_id_compare_by_numid(l, r) < 0);
 }
 
+// Case 3.0. The left object with lesser entry in iface field than right object
+//	     should result in negative.
+static void comparison_by_tuple_arithmetic_0(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	set_elem_id_by_tuple(l, SND_CTL_ELEM_IFACE_CARD, 0, 1, "A", 2);
+	set_elem_id_by_tuple(r, SND_CTL_ELEM_IFACE_HWDEP, 0, 1, "A", 2);
+	assert(snd_ctl_elem_id_compare_by_tuple_arithmetic(l, r) < 0);
+}
+
+// Case 3.1. The left object with greater entry in iface field than right object
+//	     should result in positive.
+static void comparison_by_tuple_arithmetic_1(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	set_elem_id_by_tuple(l, SND_CTL_ELEM_IFACE_SEQUENCER, 3, 4, "B", 5);
+	set_elem_id_by_tuple(r, SND_CTL_ELEM_IFACE_TIMER, 3, 4, "B", 5);
+	assert(snd_ctl_elem_id_compare_by_tuple_arithmetic(l, r) > 0);
+}
+
+// Case 3.2. The left object with lesser value in device field than right object
+//	     should result in negative.
+static void comparison_by_tuple_arithmetic_2(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	set_elem_id_by_tuple(l, SND_CTL_ELEM_IFACE_CARD, 1, 7, "C", 8);
+	set_elem_id_by_tuple(r, SND_CTL_ELEM_IFACE_CARD, 6, 7, "C", 8);
+	assert(snd_ctl_elem_id_compare_by_tuple_arithmetic(l, r) < 0);
+}
+
+
+// Case 3.3. The left object with greater value in device field than right object
+//	     should result in positive.
+static void comparison_by_tuple_arithmetic_3(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	set_elem_id_by_tuple(l, SND_CTL_ELEM_IFACE_HWDEP, 9, 10, "D", 11);
+	set_elem_id_by_tuple(r, SND_CTL_ELEM_IFACE_HWDEP, 1, 10, "D", 11);
+	assert(snd_ctl_elem_id_compare_by_tuple_arithmetic(l, r) > 0);
+}
+
+// Case 3.3. The left object with lesser value in subdevice field than right object
+//	     should result in negative.
+static void comparison_by_tuple_arithmetic_4(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	set_elem_id_by_tuple(l, SND_CTL_ELEM_IFACE_MIXER, 12, 1, "E", 14);
+	set_elem_id_by_tuple(r, SND_CTL_ELEM_IFACE_MIXER, 12, 13, "E", 14);
+	assert(snd_ctl_elem_id_compare_by_tuple_arithmetic(l, r) < 0);
+}
+
+// Case 3.4. The left object with greater value in subdevice field than right object
+//	     should result in positive.
+static void comparison_by_tuple_arithmetic_5(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	set_elem_id_by_tuple(l, SND_CTL_ELEM_IFACE_PCM, 15, 16, "F", 17);
+	set_elem_id_by_tuple(r, SND_CTL_ELEM_IFACE_PCM, 15, 1, "F", 17);
+	assert(snd_ctl_elem_id_compare_by_tuple_arithmetic(l, r) > 0);
+}
+
+// Case 3.5. The left object with name beginning lesser character in name field
+//	     than right object should result in negative.
+static void comparison_by_tuple_arithmetic_6(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	set_elem_id_by_tuple(l, SND_CTL_ELEM_IFACE_RAWMIDI, 18, 19, "A", 20);
+	set_elem_id_by_tuple(r, SND_CTL_ELEM_IFACE_RAWMIDI, 18, 19, "H", 20);
+	assert(snd_ctl_elem_id_compare_by_tuple_arithmetic(l, r) < 0);
+}
+
+// Case 3.6. The left object with name beginning greater character in name field
+//	     than right object should result in positive.
+static void comparison_by_tuple_arithmetic_7(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	set_elem_id_by_tuple(l, SND_CTL_ELEM_IFACE_TIMER, 21, 22, "I", 23);
+	set_elem_id_by_tuple(r, SND_CTL_ELEM_IFACE_TIMER, 21, 22, "A", 23);
+	assert(snd_ctl_elem_id_compare_by_tuple_arithmetic(l, r) > 0);
+}
+
+// Case 3.7. The left object with lesser value in index field than right object
+//	     should result in negative.
+static void comparison_by_tuple_arithmetic_8(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	set_elem_id_by_tuple(l, SND_CTL_ELEM_IFACE_SEQUENCER, 24, 25, "J", 1);
+	set_elem_id_by_tuple(r, SND_CTL_ELEM_IFACE_SEQUENCER, 24, 25, "J", 26);
+	assert(snd_ctl_elem_id_compare_by_tuple_arithmetic(l, r) < 0);
+}
+
+// Case 3.8. The left object with greater value in index field than right object
+//	     should result in positive.
+static void comparison_by_tuple_arithmetic_9(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	set_elem_id_by_tuple(l, SND_CTL_ELEM_IFACE_CARD, 27, 28, "K", 29);
+	set_elem_id_by_tuple(r, SND_CTL_ELEM_IFACE_CARD, 27, 28, "K", 1);
+	assert(snd_ctl_elem_id_compare_by_tuple_arithmetic(l, r) > 0);
+}
+
+// Case 3.9. The left object with the same values in iface, device, subdevice,
+//	     name, and index fields as right object should result in zero.
+static void comparison_by_tuple_arithmetic_10(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	set_elem_id_by_tuple(l, SND_CTL_ELEM_IFACE_HWDEP, 30, 31, "L", 32);
+	set_elem_id_by_tuple(r, SND_CTL_ELEM_IFACE_HWDEP, 30, 31, "L", 32);
+	assert(snd_ctl_elem_id_compare_by_tuple_arithmetic(l, r) == 0);
+}
+
 int main()
 {
 	void (*entries[])(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r) = {
@@ -150,6 +250,17 @@ int main()
 		comparison_by_numid_1,
 		comparison_by_numid_2,
 		comparison_by_numid_3,
+		comparison_by_tuple_arithmetic_0,
+		comparison_by_tuple_arithmetic_1,
+		comparison_by_tuple_arithmetic_2,
+		comparison_by_tuple_arithmetic_3,
+		comparison_by_tuple_arithmetic_4,
+		comparison_by_tuple_arithmetic_5,
+		comparison_by_tuple_arithmetic_6,
+		comparison_by_tuple_arithmetic_7,
+		comparison_by_tuple_arithmetic_8,
+		comparison_by_tuple_arithmetic_9,
+		comparison_by_tuple_arithmetic_10,
 	};
 	int count = sizeof(entries) / sizeof(*entries);
 	int fd;
