btsco2 Patch
Hi,
this patch fix some problems:
1. use nonblocking socket on rfcomm connect this allow to wait for more than one headset
2. Before seting the SCO filedescriptor to the kernel ir send -1 for closing the actual one.
+ If an SCO connection is lost from last time it become close and with the next try is available again
3. Move the SCO loopback testroutine to poll informations
4. Handle Headset disconnect (power off)
Cu Thomas
p.s. I hope this tine the patch is in correct format
btsco2.c renamed from btsco2.c.orig +34 -17
@@ -91,6 +91,7 @@ {struct sockaddr_rc addr;int sk; +int opt; sk =socket (PF_BLUETOOTH ,SOCK_STREAM ,BTPROTO_RFCOMM );if (sk <0 )
@@ -105,12 +106,18 @@return -1 ; } +/* Try to use non blocking IO */ + opt =1 ; +ioctl (sk,FIONBIO , &opt); +memset (&addr,0 ,sizeof (addr)); addr.rc_family =AF_BLUETOOTH ;bacpy (&addr.rc_bdaddr, dst); addr.rc_channel = channel;if (connect (sk, (struct sockaddr *) &addr,sizeof (addr)) <0 ) { +if (errno ==EAGAIN ) +return sk;close (sk);return -1 ; }
@@ -300,10 +307,10 @@if (headset ==NULL )return 0 ; +/* disconnect SCO stream */ +bt_sco_set_fd (headset->handle,-1 );if (headset->sco_fd !=-1 ) {/* close bt_sco audio handle */ -bt_sco_set_fd (headset->handle,-1 ); -/* disconnect SCO stream */ close (headset->sco_fd); headset->sco_fd =-1 ;fprintf (stderr,"disconnected SCO channel\n" );
@@ -401,16 +408,13 @@return 1 ; } -static void headset_destroy (struct s_headset *headset) +static void headset_close (struct s_headset *headset) {if (headset ==NULL )return ; -if (headset->sco_fd !=-1 ) {bt_sco_set_fd (headset->handle,-1 ); +if (headset->sco_fd !=-1 )close (headset->sco_fd); - } - -sleep (1 );if (headset->rfcomm_fd !=-1 )close (headset->rfcomm_fd);if (headset->handle !=NULL )
@@ -418,6 +422,7 @@ headset->sco_fd =-1 ; headset->rfcomm_fd =-1 ; headset->handle =NULL ; +sleep (1 ); }static void cleanup (void )
@@ -426,7 +431,8 @@ akt_headset = first;while (akt_headset !=NULL ) {struct s_headset *next = akt_headset->next; -headset_destroy (akt_headset); +headset_close (akt_headset); +free (akt_headset); akt_headset = next; } }
@@ -513,10 +519,6 @@str2ba (argv[1 ], &akt_headset->bdaddr); akt_headset->channel =atoi (argv[2 ]);/* open hwdep on audio device */ -if ((err =snd_hwdep_open (&akt_headset->handle, hwdep_name,O_RDWR )) <0 ) { -fprintf (stderr,"btsco open (%i-%i): %s\n" , card, dev,snd_strerror (err)); -return -1 ; - }break ;default :usage ();
@@ -548,13 +550,26 @@ &akt_headset->bdaddr, akt_headset->channel)) < 0) fprintf(stderr, "Can't connect RFCOMM channel"); - else + else {fprintf (stderr,"RFCOMM channel %i connected\n" , akt_headset->channel); +if ((err =snd_hwdep_open (&akt_headset->handle, hwdep_name,O_RDWR )) <0 ) { +fprintf (stderr,"Can not open soudncard %s for Headset\n" , hwdep_name); +close (akt_headset->rfcomm_fd); + akt_headset->rfcomm_fd =-1 ; + } + } }if (akt_headset->rfcomm_fd !=-1 ) { pfds[nfds].fd = akt_headset->rfcomm_fd; + pfds[nfds].events =POLLIN |POLLERR ; + nfds++; + } +#ifdef TEST +if (akt_headset->sco_fd !=-1 ) { + pfds[nfds].fd = akt_headset->sco_fd; pfds[nfds++].events =POLLIN ; } +#endif if (akt_headset->handle !=NULL ) {/* polling data from hwdep interface */ nfds +=snd_hwdep_poll_descriptors (akt_headset->handle, &pfds[nfds],1 );
@@ -574,16 +589,16 @@if (pfds[j].fd == akt_headset->rfcomm_fd) {if (pfds[j].revents &POLLIN )headset_from_bt (akt_headset); +if (pfds[j].revents &POLLERR ) +headset_close (akt_headset);continue ; }#ifdef TEST if (pfds[j].fd == akt_headset->sco_fd) {/* Just for testing; handled by kernel driver */ -fd_set rfds; -if (0 &&FD_ISSET (akt_headset->sco_fd, &rfds)) { +if (0 && pfds[j].revents &POLLIN ) {int i;unsigned char buf[2048 ]; -memset (buf,0 ,sizeof (buf)); rlen =read (akt_headset->sco_fd, buf,sizeof (buf));write (akt_headset->sco_fd, buf, rlen);
@@ -594,7 +609,9 @@ }#endif /* Volume polling (sound card) */ -if (!snd_hwdep_poll_descriptors_revents (akt_headset->handle, &pfds[j],1 , &revents) && revents &POLLIN ) +if (akt_headset->handle !=NULL ) +if (!snd_hwdep_poll_descriptors_revents ( akt_headset->handle, &pfds[j],1 , &revents) && + revents &POLLIN )headset_volume_fromcard (akt_headset); } }