[PATCH 17/22] unit: Add more test cases for the at parser

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

 



This patch adds unit tests for AT commands required by HFP to establish
SLC.
---
 unit/test-blueatchat.c |  522 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 521 insertions(+), 1 deletion(-)

diff --git a/unit/test-blueatchat.c b/unit/test-blueatchat.c
index ae10ff7..e0cd23b 100644
--- a/unit/test-blueatchat.c
+++ b/unit/test-blueatchat.c
@@ -78,6 +78,24 @@ static void tc_blueat_ok(struct blueat_fixture *fix, gconstpointer test_data)
 	/* one ok command should be found */
 	g_assert_cmpint(called, ==, 1);
 }
+
+static bool tc_blueat_error_cb(GSList *data)
+{
+	called += 1;
+	g_message("ERROR callback");
+	g_assert(!data);
+	return true;
+}
+static void tc_blueat_error(struct blueat_fixture *fix, gconstpointer test_data)
+{
+	fix->msg = "\r\nERROR\r\n";
+
+	g_main_loop_run(fix->loop);
+
+	/* one error command should be found */
+	g_assert_cmpint(called, ==, 1);
+}
+
 static void tc_blueat_garbagemix(struct blueat_fixture *fix,
 					gconstpointer test_data)
 {
@@ -120,6 +138,28 @@ static void tc_blueat_atbrsf(struct blueat_fixture *fix,
 	g_assert_cmpint(called, ==, 1);
 }
 
+static bool tc_blueat_brsf_cb(GSList *data)
+{
+	called += 1;
+	g_message("+BRSF: callback");
+
+	g_assert(data);
+	g_assert(data->data);
+	g_assert_cmpint(*(int *)data->data, ==, 192);
+
+	return true;
+}
+static void tc_blueat_brsf(struct blueat_fixture *fix, gconstpointer test_data)
+{
+	/* Define test case */
+	fix->msg = "\r\n+BRSF: 192\r\n";
+
+	g_main_loop_run(fix->loop);
+
+	/* 1 callback should be called */
+	g_assert_cmpint(called, ==, 1);
+}
+
 static void tc_blueat_garbage(struct blueat_fixture *fix,
 					gconstpointer test_data)
 {
@@ -178,6 +218,383 @@ static void tc_blueat_cnum(struct blueat_fixture *fix, gconstpointer test_data)
 	g_assert_cmpint(called, ==, 1);
 }
 
+static bool tc_blueat_atchld_t_cb(GSList *data)
+{
+	called += 1;
+	g_message("AT+CHLD=? callback");
+	g_assert(!data);
+	return true;
+}
+static void tc_blueat_atchld_t(struct blueat_fixture *fix,
+				gconstpointer test_data)
+{
+	fix->msg = "\r\nAT+CHLD=?\r\n";
+
+	g_main_loop_run(fix->loop);
+	g_assert_cmpint(called, ==, 1);
+}
+
+static bool tc_blueat_atchld_cb(GSList *data)
+{
+	called += 1;
+	g_message("AT+CHLD= callback");
+	g_assert(data);
+	g_assert(data->data);
+	g_assert_cmpint(*(int *)data->data, ==, 3);
+
+	return true;
+}
+static void tc_blueat_atchld(struct blueat_fixture *fix,
+				gconstpointer test_data)
+{
+	fix->msg = "\r\nAT+CHLD=3\r\n";
+
+	g_main_loop_run(fix->loop);
+	g_assert_cmpint(called, ==, 1);
+}
+
+static bool tc_blueat_chld_cb(GSList *data)
+{
+	GSList *item = NULL;
+
+	called += 1;
+	g_message("+CHLD: callback");
+
+	g_assert(data);
+	item = g_slist_reverse(data);
+	g_assert_cmpint(*(int *)item->data, ==, 0);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 1);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 1);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(char *)item->data, ==, 'x');
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 2);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 2);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(char *)item->data, ==, 'x');
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 3);
+
+	return true;
+}
+static void tc_blueat_chld(struct blueat_fixture *fix,
+				gconstpointer test_data)
+{
+	fix->msg = "\r\n+CHLD: (0,1,1x,2,2x,3)\r\n";
+
+	g_main_loop_run(fix->loop);
+	g_assert_cmpint(called, ==, 1);
+}
+
+static bool tc_blueat_atcind_r_cb(GSList *data)
+{
+	called += 1;
+	g_message("AT+CIND? callback");
+
+	g_assert(!data);
+	return true;
+}
+static void tc_blueat_atcind_r(struct blueat_fixture *fix,
+				gconstpointer test_data)
+{
+	fix->msg = "\r\nAT+CIND?\r\n";
+
+	g_main_loop_run(fix->loop);
+	g_assert_cmpint(called, ==, 1);
+}
+
+static bool tc_blueat_atcind_t_cb(GSList *data)
+{
+	called += 1;
+	g_message("AT+CIND=? callback");
+	g_assert(!data);
+	return true;
+}
+static void tc_blueat_atcind_t(struct blueat_fixture *fix,
+				gconstpointer test_data)
+{
+	fix->msg = "\r\nAT+CIND=?\r\n";
+
+	g_main_loop_run(fix->loop);
+	g_assert_cmpint(called, ==, 1);
+}
+
+static bool tc_blueat_cind1_cb(GSList *data)
+{
+	GSList *item = NULL;
+	int values[] = { 1, 1, 0, 0, 5, 0, 0 };
+	int unsigned i;
+
+	called += 1;
+	g_message("1+CIND: callback");
+
+	g_assert(data);
+	item = g_slist_reverse(data);
+
+	for (i = 0; i < sizeof(values) / sizeof(int); ++i) {
+		g_assert(item);
+		g_assert(item->data);
+		g_assert_cmpint(*(int *)item->data, ==, values[i]);
+		item = g_slist_next(item);
+	}
+	/* We declared 20 parameters in descriptor so there can be more data.
+	 * but of course not in this case, because we know what we have sent.
+	 */
+	if (item)
+		for (; i < 19; ++i) {
+			g_assert(item->data == NULL);
+			item = g_slist_next(item);
+		}
+	/* there should be no more data */
+	g_assert(!item);
+	return true;
+}
+static void tc_blueat_cind1(struct blueat_fixture *fix,
+				gconstpointer test_data)
+{
+	fix->msg = "\r\n+CIND: 1,1,0,0,5,0,0\r\n";
+
+	g_main_loop_run(fix->loop);
+	g_assert_cmpint(called, ==, 1);
+}
+
+static bool tc_blueat_cind2_cb(GSList *data)
+{
+	GSList *item = NULL;
+
+	called += 1;
+	g_message("2+CIND: callback");
+	g_assert(data);
+
+	item = g_slist_reverse(data);
+
+	g_assert(item);
+	g_assert(item->data);
+	g_assert((char *)item->data);
+	g_assert_cmpint(strcmp(item->data, "Voice Mail"), ==, 0);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 0);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 1);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(strcmp((char *)item->data, "service"), ==, 0);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 0);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 1);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(strcmp((char *)item->data, "call"), ==, 0);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 0);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 1);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(strcmp((char *)item->data, "Roam"), ==, 0);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 0);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 2);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(strcmp((char *)item->data, "signal"), ==, 0);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 0);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 5);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(strcmp((char *)item->data, "callsetup"), ==, 0);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 0);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 3);
+
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(strcmp((char *)item->data, "smsfull"), ==, 0);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 0);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 1);
+
+	g_assert((item = g_slist_next(item)) == NULL);
+	return true;
+}
+static void tc_blueat_cind2(struct blueat_fixture *fix,
+				gconstpointer test_data)
+{
+	fix->msg = "\r\n+CIND: (\"Voice Mail\",(0,1)),(\"service\",(0,1)),"
+			"(\"call\",(0,1)),(\"Roam\",(0-2)),(\"signal\",(0-5)),"
+			"(\"callsetup\",(0-3)),(\"smsfull\",(0,1))\r\n";
+
+	g_main_loop_run(fix->loop);
+	g_assert_cmpint(called, ==, 1);
+}
+
+static bool tc_blueat_atcmer_cb(GSList *data)
+{
+	GSList *item = NULL;
+
+	called += 1;
+	g_message("AT+CMER= callback");
+	g_assert(data);
+	item = g_slist_reverse(data);
+
+	/* Check for data "ou,ou,ou,ou*" */
+	g_assert(item);
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 3);
+
+	/* no second parameter because its optional */
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data == NULL);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 0);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 1);
+	return true;
+}
+static void tc_blueat_atcmer(struct blueat_fixture *fix,
+				gconstpointer test_data)
+{
+	fix->msg = "\r\nAT+CMER=3,,0,1\r\n";
+
+	g_main_loop_run(fix->loop);
+	g_assert_cmpint(called, ==, 1);
+}
+
+static bool tc_blueat_ciev_cb(GSList *data)
+{
+	GSList *item = NULL;
+
+	called += 1;
+	g_message("+CIEV: callback");
+	g_assert(data);
+	item = g_slist_reverse(data);
+
+	g_assert(item);
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 3);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 0);
+	return true;
+}
+static void tc_blueat_ciev(struct blueat_fixture *fix,
+				gconstpointer test_data)
+{
+	fix->msg = "\r\n+CIEV: 3,0\r\n";
+
+	g_main_loop_run(fix->loop);
+	g_assert_cmpint(called, ==, 1);
+}
+
+static bool tc_blueat_atbac_cb(GSList *data)
+{
+	GSList *item = NULL;
+
+	called += 1;
+	g_message("AT+BAC= callback");
+	g_assert(data);
+	item = g_slist_reverse(data);
+
+	/* Check returned data "u,ou,ou,ou,ou,ou,ou" */
+
+	g_assert(item);
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 1);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 2);
+
+	g_assert((item = g_slist_next(item)));
+	g_assert(item->data);
+	g_assert_cmpint(*(int *)item->data, ==, 12);
+
+	/* According to descriptor there should be 4 nulls but not
+	 * if there was no more data - of course there wont be any here
+	 */
+	item = g_slist_next(item);
+	if (item) {
+		g_assert(item->data == NULL);
+		g_assert((item = g_slist_next(item))->data == NULL);
+		g_assert((item = g_slist_next(item))->data == NULL);
+		g_assert((item = g_slist_next(item))->data == NULL);
+	}
+
+	/* there should be no more data */
+	g_assert(!item);
+	return true;
+}
+static void tc_blueat_atbac(struct blueat_fixture *fix,
+				gconstpointer test_data)
+{
+	fix->msg = "\r\nAT+BAC=1,2,12\r\n";
+
+	g_main_loop_run(fix->loop);
+	g_assert_cmpint(called, ==, 1);
+}
+
 /******************************************************************************
  * Parser configuration and command registration
  ******************************************************************************/
@@ -193,8 +610,72 @@ static struct blueatchat_config cfg = {
 static struct blueatchat_cmd_descriptor commands[] = {
 	/* recognised command | syntax descriptor   |   callback */
 	{"OK",		NULL,				tc_blueat_ok_cb},
-	{"AT+BRSF=",	"u",				tc_blueat_atbrsf_cb},
+	{"ERROR",	NULL,				tc_blueat_error_cb},
+	{"NO CARRIER",	NULL,		/*TODO*/	tc_blueat_unknown_cb},
+	{"BUSY",	NULL,		/*TODO*/	tc_blueat_unknown_cb},
+	{"NO ANSWER",	NULL,		/*TODO*/	tc_blueat_unknown_cb},
+	{"DELAYED",	NULL,		/*TODO*/	tc_blueat_unknown_cb},
+	{"BLACKLISTED",	NULL,		/*TODO*/	tc_blueat_unknown_cb},
+	{"RING",	NULL,		/*TODO*/	tc_blueat_unknown_cb},
+	{"ATA",		NULL,		/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+CCWA=",	"ou",		/*TODO*/	tc_blueat_unknown_cb},
+	{"+CCWA: ",	"s,ou*",	/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+CHLD=?",	NULL,				tc_blueat_atchld_t_cb},
+	{"AT+CHLD=",	"u",				tc_blueat_atchld_cb},
+	{"+CHLD: ",	"(ou,ou,ouc,ou,ouc,ou)",	tc_blueat_chld_cb},
+	{"AT+CHUP",	NULL,		/*TODO*/	tc_blueat_unknown_cb},
+	{"+CHUP",	NULL,		/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+CIND?",	NULL,				tc_blueat_atcind_r_cb},
+	{"AT+CIND=?",	NULL,				tc_blueat_atcind_t_cb},
+	{"+CIND: ",	"ou,ou,ou,ou,ou,ou,ou,ou,ou,ou,"
+			"ou,ou,ou,ou,ou,ou,ou,ou,ou,ou", tc_blueat_cind1_cb},
+	{"+CIND: ",	"(q,(u-u))o,(q,(u-u))o,(q,(u-u))"
+			"o,(q,(u-u))o,(q,(u-u))o,(q,(u-u))"
+			"o,(q,(u-u))o,(q,(u-u))o,(q,(u-u))"
+			"o,(q,(u-u))o,(q,(u-u))o,(q,(u-u))"
+			"o,(q,(u-u))o,(q,(u-u))o,(q,(u-u))"
+			"o,(q,(u-u))o,(q,(u-u))o,(q,(u-u))"
+			"o,(q,(u-u))o,(q,(u-u))",	tc_blueat_cind2_cb},
+	{"AT+CLCC",	NULL,		/*TODO*/	tc_blueat_unknown_cb},
+	{"+CLCC: ",	"u,u,u,u,u,os,ou*",/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+COPS=",	"ou,ou,os*",	/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+COPS?",	NULL,		/*TODO*/	tc_blueat_unknown_cb},
+	{"+COPS: ",	"u,ou,os*",	/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+CMEE=",	"u",		/*TODO*/	tc_blueat_unknown_cb},
+	{"+CMEE ERROR: ",	"u",	/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+CLIP=",	"u",		/*TODO*/	tc_blueat_unknown_cb},
+	{"+CLIP: ",	"q,u*",		/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+CMER=",	"ou,ou,ou,ou*",			tc_blueat_atcmer_cb},
+	{"+CIEV: ",	"u,u",				tc_blueat_ciev_cb},
+	{"AT+VTS=",	"c",		/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+CNUM=?",	NULL,		/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+CNUM",	NULL,		/*TODO*/	tc_blueat_unknown_cb},
 	{"+CNUM: ",	"oq,q,u,ou,u*",			tc_blueat_cnum_cb},
+	{"ATD>",	"q",		/*TODO*/	tc_blueat_unknown_cb},
+	{"ATD",		"s",		/*TODO*/	tc_blueat_unknown_cb},
+	/* Bluetooth cpecific */
+	{"AT+BIA=",	"ou,ou,ou,ou,ou,ou,ou,ou,ou,ou,"
+			"ou,ou,ou,ou,ou,ou,ou,ou,ou,ou", tc_blueat_unknown_cb},
+	{"AT+BINP=",	"u",		/*TODO*/	tc_blueat_unknown_cb},
+	{"+BINP: ",	"q*",		/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+BLDN=",	NULL,		/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+BVRA=",	"u",		/*TODO*/	tc_blueat_unknown_cb},
+	{"+BVRA: ",	"u",		/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+BRSF=",	"u",				tc_blueat_atbrsf_cb},
+	{"+BRSF: ",	"u",				tc_blueat_brsf_cb},
+	{"AT+NREC=",	"u",		/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+VGM=",	"u",		/*TODO*/	tc_blueat_unknown_cb},
+	{"+VGM:",	"u",		/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+VGS=",	"u",		/*TODO*/	tc_blueat_unknown_cb},
+	{"+VGS: ",	"u",		/*TODO*/	tc_blueat_unknown_cb},
+	{"+BSIR: ",	"u",		/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+BTRH=",	"u",		/*TODO*/	tc_blueat_unknown_cb},
+	{"+BTRH: ",	"u",		/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+BCC=",	"u",		/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+BCS=",	"u",		/*TODO*/	tc_blueat_unknown_cb},
+	{"+BCS: ",	"u",		/*TODO*/	tc_blueat_unknown_cb},
+	{"AT+BAC=",	"u,ou,ou,ou,ou,ou,ou",		tc_blueat_atbac_cb},
+	/* used lastly if no other command matches */
 	{NULL,		"s",				tc_blueat_unknown_cb},
 };
 
@@ -327,8 +808,47 @@ int main(int argc, char **argv)
 	g_test_add("/blueatchat/garbage", struct blueat_fixture, 0,
 				blueat_fix_setup, tc_blueat_garbage,
 				blueat_fix_teardown);
+	g_test_add("/blueatchat/error", struct blueat_fixture, 0,
+				blueat_fix_setup, tc_blueat_error,
+				blueat_fix_teardown);
+	g_test_add("/blueatchat/brsf", struct blueat_fixture, 0,
+				blueat_fix_setup, tc_blueat_brsf,
+				blueat_fix_teardown);
+	g_test_add("/blueatchat/atchld_test", struct blueat_fixture, 0,
+				blueat_fix_setup, tc_blueat_atchld_t,
+				blueat_fix_teardown);
+	g_test_add("/blueatchat/atchld", struct blueat_fixture, 0,
+				blueat_fix_setup, tc_blueat_atchld,
+				blueat_fix_teardown);
+	g_test_add("/blueatchat/chld", struct blueat_fixture, 0,
+				blueat_fix_setup, tc_blueat_chld,
+				blueat_fix_teardown);
+	g_test_add("/blueatchat/brsf", struct blueat_fixture, 0,
+				blueat_fix_setup, tc_blueat_brsf,
+				blueat_fix_teardown);
+	g_test_add("/blueatchat/atcind_request", struct blueat_fixture, 0,
+				blueat_fix_setup, tc_blueat_atcind_r,
+				blueat_fix_teardown);
+	g_test_add("/blueatchat/atcind_test", struct blueat_fixture, 0,
+				blueat_fix_setup, tc_blueat_atcind_t,
+				blueat_fix_teardown);
+	g_test_add("/blueatchat/atcmer", struct blueat_fixture, 0,
+				blueat_fix_setup, tc_blueat_atcmer,
+				blueat_fix_teardown);
+	g_test_add("/blueatchat/ciev", struct blueat_fixture, 0,
+				blueat_fix_setup, tc_blueat_ciev,
+				blueat_fix_teardown);
+	g_test_add("/blueatchat/atbac", struct blueat_fixture, 0,
+				blueat_fix_setup, tc_blueat_atbac,
+				blueat_fix_teardown);
 	g_test_add("/blueatchat/cnum", struct blueat_fixture, 0,
 				blueat_fix_setup, tc_blueat_cnum,
 				blueat_fix_teardown);
+	g_test_add("/blueatchat/cind_1", struct blueat_fixture, 0,
+				blueat_fix_setup, tc_blueat_cind1,
+				blueat_fix_teardown);
+	g_test_add("/blueatchat/cind_2", struct blueat_fixture, 0,
+				blueat_fix_setup, tc_blueat_cind2,
+				blueat_fix_teardown);
 	return g_test_run();
 }
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux