--- btsco2.c.orig 2004-12-01 15:06:13.000000000 +0100 +++ btsco2.c 2004-12-01 16:41:34.698979692 +0100 @@ -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); } }