--- bluez-utils-2.0-pre9.org/tools/l2test.c	Wed Mar 27 06:30:35 2002
+++ bluez-utils-2.0-pre9/tools/l2test.c	Sun May 26 23:52:43 2002
@@ -54,7 +54,9 @@
 	DUMP,
 	CONNECT,
 	CRECV,
-	LSEND
+	LSEND,
+	BILISTEN,
+	BICONNECT
 };
 
 unsigned char *buf;
@@ -74,6 +76,13 @@
 int auth = 0;
 int encrypt = 0;
 
+
+uint32_t verify_data(unsigned char *buf, int r, uint32_t seq);
+void bi_send_recv(int s);
+
+unsigned char *bi_recv_buf;
+int bi_recv_count=10000;
+
 float tv2fl(struct timeval tv)
 {
 	return (float)tv.tv_sec + (float)(tv.tv_usec/1000000.0);
@@ -246,9 +255,7 @@
 		gettimeofday(&tv_beg,NULL);
 		total = 0;
 		while (total < data_size) {
-			uint32_t sq;
-			uint16_t l;
-			int i,r;
+			int r;
 
 			if ((r = recv(s, buf, data_size, 0)) <= 0) {
 				if (r < 0)
@@ -257,26 +264,7 @@
 				return;	
 			}
 
-			/* Check sequence */
-			sq = btohl(*(uint32_t *)buf);
-			if (seq != sq) {
-				syslog(LOG_INFO, "seq missmatch: %d -> %d", seq, sq);
-				seq = sq;
-			}
-			seq++;
-			
-			/* Check length */
-			l = btohs(*(uint16_t *)(buf+4));
-			if (r != l) {
-				syslog(LOG_INFO, "size missmatch: %d -> %d", r, l);
-				continue;
-			}
-			
-			/* Verify data */	
-			for (i=6; i < r; i++) {
-				if (buf[i] != 0x7f)
-					syslog(LOG_INFO, "data missmatch: byte %d 0x%2.2x", i, buf[i]);
-			}
+			seq = verify_data(buf, r, seq);
 
 			total += r;
 		}
@@ -311,6 +299,101 @@
 	}
 }
 
+void bi_connect_mode(char* svr) {
+  int s;
+  if( (s = do_connect(svr)) < 0 )
+    exit(1);
+  bi_send_recv(s);
+}
+
+void bi_send_recv(int s) {
+  int i, r;
+  long total;
+  uint32_t recv_seq, send_seq;
+  struct timeval tv_beg, tv_end, tv_diff;
+  fd_set rset, wset;
+
+  /* Incoming packets are limited by the -I option */
+  if (!(bi_recv_buf = malloc(imtu))) {
+    perror("Can't allocate data buffer");
+    exit(1);
+  }
+  for(i=6; i < imtu; i++) buf[i]=0x7f;
+
+  send_seq = 0;
+  recv_seq = 0;
+  total = 0;
+  FD_ZERO(&rset);
+  FD_ZERO(&wset); 
+  gettimeofday(&tv_beg,NULL);
+  while(1) {
+    FD_SET(s, &rset);
+    FD_SET(s, &wset);
+    if (select(s+1, &rset, &wset, NULL, NULL)<0){
+      syslog(LOG_ERR, "Select failed. %s(%d)", strerror(errno), errno);
+      exit(-1);
+    }
+
+    if(FD_ISSET(s, &wset)) {
+      *(uint32_t *)buf = htobl(send_seq++);
+      *(uint16_t *)(buf+4) = htobs(data_size);
+	
+      if( send(s, buf, data_size, 0) <= 0 ) {
+	syslog(LOG_ERR, "Send failed. %s(%d)", strerror(errno), errno);
+	exit(1);
+      }
+    }
+    if(FD_ISSET(s, &rset)) {
+      if ((r = recv(s, bi_recv_buf, imtu, 0)) < 0) {
+	if (r < 0)
+	  syslog(LOG_ERR, "Read failed. %s(%d)", strerror(errno), errno);
+	return;
+      }
+      recv_seq = verify_data(bi_recv_buf, r, recv_seq);
+      total += r;
+
+      if(total >= bi_recv_count) {
+	gettimeofday(&tv_end,NULL);
+	timersub(&tv_end,&tv_beg,&tv_diff);
+	syslog(LOG_INFO,"Received %ld bytes in %.2f sec, %.2f kB/s", total,
+	       tv2fl(tv_diff), (float)(total / tv2fl(tv_diff) ) / 1024.0);
+	tv_beg=tv_end;
+	total=0;
+      }
+    }
+  }
+}
+
+uint32_t verify_data(unsigned char* buf, int r, uint32_t seq){
+  uint32_t sq;
+  uint16_t l;
+  int i;
+
+  /* Check sequence */
+  sq = btohl(*(uint32_t *)buf);
+  if (seq != sq) {
+    printf("seq missmatch: %d -> %d", seq, sq);
+    syslog(LOG_INFO, "seq missmatch: %d -> %d", seq, sq);
+    seq = sq;
+  }
+  seq++;
+			
+  /* Check length */
+  l = btohs(*(uint16_t *)(buf+4));
+  if (r != l) {
+    syslog(LOG_INFO, "size missmatch: %d -> %d", r, l);
+    goto done;
+  }
+		
+  /* Verify data */	
+  for (i=6; i < r; i++) {
+    if (buf[i] != 0x7f)
+      syslog(LOG_INFO, "data missmatch: byte %d 0x%2.2x", i, buf[i]);
+  }
+ done:
+  return seq;
+}
+
 void reconnect_mode(char *svr)
 {
 	while(1){
@@ -361,7 +444,9 @@
 		"\t-u connect and receive\n"
 		"\t-n connect and be silent\n"
 		"\t-c connect, disconnect, connect, ...\n"
-		"\t-m multiple connects\n");
+		"\t-m multiple connects\n"
+                "\t-x biderectional send/recv - listen\n"
+                "\t-y biderectional send/recv - connect\n");
 
 	printf("Options:\n"
 		"\t[-b bytes] [-S bdaddr] [-P psm]\n"
@@ -381,7 +466,7 @@
 
 	mode = RECV; need_addr = 0;
 	
-	while ((opt=getopt(argc,argv,"rdscuwmnb:P:I:O:S:MAE")) != EOF) {
+	while ((opt=getopt(argc,argv,"rdscuwmnxyxb:P:I:O:S:MAE")) != EOF) {
 		switch(opt) {
 		case 'r':
 			mode = RECV;
@@ -424,6 +509,15 @@
 			data_size = atoi(optarg);
 			break;
 
+		case 'x':
+		        mode=BILISTEN;
+			break;
+
+		case 'y':
+		        mode=BICONNECT;
+			need_addr = 1;
+			break;
+
 		case 'S':
 			baswap(&bdaddr, strtoba(optarg));
 			break;
@@ -476,6 +570,14 @@
 	openlog("l2test", LOG_PERROR | LOG_PID, LOG_LOCAL0);
 
 	switch( mode ){
+	        case BILISTEN:
+		        do_listen(bi_send_recv);
+ 		        break;
+
+	        case BICONNECT:
+	                bi_connect_mode(argv[optind]);
+ 		        break;
+
 		case RECV:
 			do_listen(recv_mode);
 			break;

