From: Frederic Danis <frederic.danis@palmsource.com>
To: bluez-devel@lists.sourceforge.net
Subject: [Bluez-devel] RFComm doesn't disconnect in server mode
Date: Tue, 12 Apr 2005 17:38:22 +0200 [thread overview]
Message-ID: <425BEB6E.4080500@palmsource.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 1556 bytes --]
Hello,
I am working on headset profile implementation. In server mode, the
headset (Jabra BT200) connects fine, but once my program close the
RFComm socket, the ACL link is still up, until I stop the headset.
I get in console :
fdanis:> ./hstest server - 00:07:A4:05:B6:DA
Server RFCOMM socket 3 listen on RFComm 2
RFComm connected
AT+CKPD=200
RFComm disconnected
fdanis:>
Here are the last traces I got before stopping headset :
> HCI Event: Mode Change (0x14) plen 6
0000: 00 29 00 02 00 08 .)....
< ACL data: handle 0x0029 flags 0x02 dlen 8
L2CAP(d): cid 0x0042 len 4 [psm 3]
RFCOMM(s): DISC: cr 0 dlci 4 pf 1 ilen 0 fcs 0x16
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> ACL data: handle 0x0029 flags 0x02 dlen 8
L2CAP(d): cid 0x0041 len 4 [psm 3]
RFCOMM(s): UA: cr 0 dlci 4 pf 1 ilen 0 fcs 0x3c
Maybe a RFCOMM DISC frame on the DLCI 0 is missing.
After, disconnecting headset :
> HCI Event: Mode Change (0x14) plen 6
0000: 00 29 00 00 00 00 .)....
> HCI Event: Disconn Complete (0x05) plen 4
0000: 00 29 00 08 .)..
I attached changes I do to hstest to exercise it, and HCI dump.
I used SUSE 9.2 with kernel 2.6.8-24.5.
I certainly made something wrong, but I don't no what.
Regards
Fred
-----------------------------------------------
[-- Attachment #2: hci-dump.txt --]
[-- Type: text/plain, Size: 9253 bytes --]
HCIDump - HCI packet analyzer ver 1.11
device: hci1 snap_len: 1028 filter: 0xffffffff
> HCI Event: Connect Request (0x04) plen 10
0000: da b6 05 a4 07 00 0c 04 20 01 ........ .
< HCI Command: Accept Connection Request (0x01|0x0009) plen 7
0000: da b6 05 a4 07 00 01 .......
> HCI Event: Command Status (0x0f) plen 4
0000: 00 01 09 04 ....
> HCI Event: Link Key Request (0x17) plen 6
0000: da b6 05 a4 07 00 ......
< HCI Command: Link Key Request Reply (0x01|0x000b) plen 22
0000: da b6 05 a4 07 00 f1 1b 51 e3 a2 ea 97 8d 29 1f ........Q.....).
0010: da f8 9c ee a3 f0 ......
> HCI Event: Command Complete (0x0e) plen 10
0000: 01 0b 04 00 da b6 05 a4 07 00 ..........
> HCI Event: Connect Complete (0x03) plen 11
0000: 00 29 00 da b6 05 a4 07 00 01 01 .).........
< HCI Command: Write Link Policy Settings (0x02|0x000d) plen 4
0000: 29 00 0f 00 )...
> HCI Event: Page Scan Repetition Mode Change (0x20) plen 7
0000: da b6 05 a4 07 00 01 .......
> HCI Event: Max Slots Change (0x1b) plen 3
0000: 29 00 05 )..
> ACL data: handle 0x0029 flags 0x02 dlen 12
L2CAP(s): Connect req: psm 1 scid 0x0041
< ACL data: handle 0x0029 flags 0x02 dlen 16
L2CAP(s): Connect rsp: dcid 0x0040 scid 0x0041 result 0 status 0
> HCI Event: Command Complete (0x0e) plen 6
0000: 01 0d 08 00 29 00 ....).
< HCI Command: Change Connection Packet Type (0x01|0x000f) plen 4
0000: 29 00 18 cc )...
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> HCI Event: Command Status (0x0f) plen 4
0000: 00 01 0f 04 ....
> HCI Event: Connection Packet Type Changed (0x1d) plen 5
0000: 00 29 00 18 cc .)...
> ACL data: handle 0x0029 flags 0x02 dlen 16
L2CAP(s): Config req: dcid 0x0040 flags 0x0000 clen 4
MTU 48
< ACL data: handle 0x0029 flags 0x02 dlen 14
L2CAP(s): Config rsp: scid 0x0041 flags 0x0000 result 0 clen 0
< ACL data: handle 0x0029 flags 0x02 dlen 12
L2CAP(s): Config req: dcid 0x0041 flags 0x0000 clen 0
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> ACL data: handle 0x0029 flags 0x02 dlen 14
L2CAP(s): Config rsp: scid 0x0040 flags 0x0000 result 0 clen 0
> ACL data: handle 0x0029 flags 0x02 dlen 19
L2CAP(d): cid 0x0040 len 15 [psm 1]
SDP SS Req: tid 0x1 len 0xa
pat uuid-32 0x1112 (AG)
max 0x28
cont 00
< ACL data: handle 0x0029 flags 0x02 dlen 18
L2CAP(d): cid 0x0041 len 14 [psm 1]
SDP SS Rsp: tid 0x1 len 0x9
tot 0x1 cur 0x1 hndl 0x10006
cont 00
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> ACL data: handle 0x0029 flags 0x02 dlen 21
L2CAP(d): cid 0x0040 len 17 [psm 1]
SDP SA Req: tid 0x2 len 0xc
hndl 0x10006
max 0x26
aid(s) 0x0004 (ProtocolDescList)
cont 00
< ACL data: handle 0x0029 flags 0x02 dlen 31
L2CAP(d): cid 0x0041 len 27 [psm 1]
SDP SA Rsp: tid 0x2 len 0x16
cnt 0x13
aid 0x0004 (ProtocolDescList)
< < uuid-16 0x0100 (L2CAP) > <
uuid-16 0x0003 (RFCOMM) uint 0x2 > >
cont 00
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> ACL data: handle 0x0029 flags 0x02 dlen 12
L2CAP(s): Connect req: psm 3 scid 0x0042
< ACL data: handle 0x0029 flags 0x02 dlen 16
L2CAP(s): Connect rsp: dcid 0x0041 scid 0x0042 result 0 status 0
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> ACL data: handle 0x0029 flags 0x02 dlen 16
L2CAP(s): Config req: dcid 0x0041 flags 0x0000 clen 4
MTU 132
< ACL data: handle 0x0029 flags 0x02 dlen 14
L2CAP(s): Config rsp: scid 0x0042 flags 0x0000 result 0 clen 0
< ACL data: handle 0x0029 flags 0x02 dlen 16
L2CAP(s): Config req: dcid 0x0042 flags 0x0000 clen 4
MTU 1024
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> ACL data: handle 0x0029 flags 0x02 dlen 18
L2CAP(s): Config rsp: scid 0x0041 flags 0x0000 result 0 clen 4
MTU 132
> ACL data: handle 0x0029 flags 0x02 dlen 8
L2CAP(d): cid 0x0041 len 4 [psm 3]
RFCOMM(s): SABM: cr 1 dlci 0 pf 1 ilen 0 fcs 0x1c
< ACL data: handle 0x0029 flags 0x02 dlen 8
L2CAP(d): cid 0x0042 len 4 [psm 3]
RFCOMM(s): UA: cr 1 dlci 0 pf 1 ilen 0 fcs 0xd7
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> ACL data: handle 0x0029 flags 0x02 dlen 18
L2CAP(d): cid 0x0041 len 14 [psm 3]
RFCOMM(s): PN CMD: cr 1 dlci 0 pf 0 ilen 10 fcs 0x70 mcc_len 8
dlci 4 frame_type 0 credit_flow 15 pri 0 ack_timer 0
frame_size 126 max_retrans 0 credits 0
< ACL data: handle 0x0029 flags 0x02 dlen 18
L2CAP(d): cid 0x0042 len 14 [psm 3]
RFCOMM(s): PN RSP: cr 0 dlci 0 pf 0 ilen 10 fcs 0xaa mcc_len 8
dlci 4 frame_type 0 credit_flow 14 pri 0 ack_timer 0
frame_size 126 max_retrans 0 credits 7
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> ACL data: handle 0x0029 flags 0x02 dlen 8
L2CAP(d): cid 0x0041 len 4 [psm 3]
RFCOMM(s): SABM: cr 1 dlci 4 pf 1 ilen 0 fcs 0x96
< ACL data: handle 0x0029 flags 0x02 dlen 8
L2CAP(d): cid 0x0042 len 4 [psm 3]
RFCOMM(s): UA: cr 1 dlci 4 pf 1 ilen 0 fcs 0x5d
< ACL data: handle 0x0029 flags 0x02 dlen 12
L2CAP(d): cid 0x0042 len 8 [psm 3]
RFCOMM(s): MSC CMD: cr 0 dlci 0 pf 0 ilen 4 fcs 0xaa mcc_len 2
dlci 4 fc 0 rtc 1 rtr 1 ic 0 dv 1 b1 1 b2 1 b3 0 len 0
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> ACL data: handle 0x0029 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 3]
RFCOMM(s): MSC RSP: cr 1 dlci 0 pf 0 ilen 4 fcs 0x70 mcc_len 2
dlci 4 fc 0 rtc 1 rtr 1 ic 0 dv 1 b1 1 b2 1 b3 0 len 0
> ACL data: handle 0x0029 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 3]
RFCOMM(s): MSC CMD: cr 1 dlci 0 pf 0 ilen 4 fcs 0x70 mcc_len 2
dlci 4 fc 0 rtc 1 rtr 1 ic 0 dv 0 b1 1 b2 1 b3 0 len 0
< ACL data: handle 0x0029 flags 0x02 dlen 12
L2CAP(d): cid 0x0042 len 8 [psm 3]
RFCOMM(s): MSC RSP: cr 0 dlci 0 pf 0 ilen 4 fcs 0xaa mcc_len 2
dlci 4 fc 0 rtc 1 rtr 1 ic 0 dv 0 b1 1 b2 1 b3 0 len 0
< ACL data: handle 0x0029 flags 0x02 dlen 9
L2CAP(d): cid 0x0042 len 5 [psm 3]
RFCOMM(d): UIH: cr 0 dlci 4 pf 1 ilen 0 fcs 0xa3 credits 33
> ACL data: handle 0x0029 flags 0x02 dlen 9
L2CAP(d): cid 0x0041 len 5 [psm 3]
RFCOMM(d): UIH: cr 1 dlci 4 pf 1 ilen 0 fcs 0x79 credits 15
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> ACL data: handle 0x0029 flags 0x02 dlen 12
L2CAP(s): Disconn req: dcid 0x0040 scid 0x0041
< ACL data: handle 0x0029 flags 0x02 dlen 12
L2CAP(s): Disconn rsp: dcid 0x0040 scid 0x0041
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> ACL data: handle 0x0029 flags 0x02 dlen 20
L2CAP(d): cid 0x0041 len 16 [psm 3]
RFCOMM(d): UIH: cr 1 dlci 4 pf 0 ilen 12 fcs 0x65
0000: 41 54 2b 43 4b 50 44 3d 32 30 30 0d AT+CKPD=200.
< ACL data: handle 0x0029 flags 0x02 dlen 12
L2CAP(d): cid 0x0042 len 8 [psm 3]
RFCOMM(d): UIH: cr 0 dlci 4 pf 0 ilen 4 fcs 0xbf
0000: 4f 4b 0d 0a OK..
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> HCI Event: Mode Change (0x14) plen 6
0000: 00 29 00 02 00 08 .)....
< ACL data: handle 0x0029 flags 0x02 dlen 8
L2CAP(d): cid 0x0042 len 4 [psm 3]
RFCOMM(s): DISC: cr 0 dlci 4 pf 1 ilen 0 fcs 0x16
> HCI Event: Number of Completed Packets (0x13) plen 5
0000: 01 29 00 01 00 .)...
> ACL data: handle 0x0029 flags 0x02 dlen 8
L2CAP(d): cid 0x0041 len 4 [psm 3]
RFCOMM(s): UA: cr 0 dlci 4 pf 1 ilen 0 fcs 0x3c
[-- Attachment #3: hstest.c --]
[-- Type: text/plain, Size: 10967 bytes --]
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2002-2004 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
* CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
* COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
* SOFTWARE IS DISCLAIMED.
*
*
* $Id: hstest.c,v 1.6 2004/12/25 17:43:20 holtmann Exp $
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <termios.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/sco.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
static volatile int terminate = 0;
static void sig_term(int sig) {
terminate = 1;
}
static int rfcomm_connect(bdaddr_t *src, bdaddr_t *dst, uint8_t channel)
{
struct sockaddr_rc addr;
int s;
if ((s = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.rc_family = AF_BLUETOOTH;
bacpy(&addr.rc_bdaddr, src);
addr.rc_channel = 0;
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
close(s);
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.rc_family = AF_BLUETOOTH;
bacpy(&addr.rc_bdaddr, dst);
addr.rc_channel = channel;
if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0 ){
close(s);
return -1;
}
return s;
}
static int sco_connect(bdaddr_t *src, bdaddr_t *dst, uint16_t *handle, uint16_t *mtu)
{
struct sockaddr_sco addr;
struct sco_conninfo conn;
struct sco_options opts;
int s, size;
if ((s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)) < 0) {
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sco_family = AF_BLUETOOTH;
bacpy(&addr.sco_bdaddr, src);
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
close(s);
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sco_family = AF_BLUETOOTH;
bacpy(&addr.sco_bdaddr, dst);
if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0 ){
close(s);
return -1;
}
memset(&conn, 0, sizeof(conn));
size = sizeof(conn);
if (getsockopt(s, SOL_SCO, SCO_CONNINFO, &conn, &size) < 0) {
close(s);
return -1;
}
memset(&opts, 0, sizeof(opts));
size = sizeof(opts);
if (getsockopt(s, SOL_SCO, SCO_OPTIONS, &opts, &size) < 0) {
close(s);
return -1;
}
if (handle)
*handle = conn.hci_handle;
if (mtu)
*mtu = opts.mtu;
return s;
}
#define PLAY 1
#define RECORD 2
#define SERVER 3
static int client(bdaddr_t bdaddr, uint8_t channel, int fd, int mode)
{
fd_set rfds;
struct timeval timeout;
unsigned char buf[2048], *p;
int maxfd, sel, rlen, wlen;
int rd, sd;
uint16_t sco_handle, sco_mtu, vs;
if ((rd = rfcomm_connect(BDADDR_ANY, &bdaddr, channel)) < 0) {
perror("Can't connect RFCOMM channel");
return -1;
}
fprintf(stderr, "RFCOMM channel connected\n");
if ((sd = sco_connect(BDADDR_ANY, &bdaddr, &sco_handle, &sco_mtu)) < 0) {
perror("Can't connect SCO audio channel");
close(rd);
return -1;
}
fprintf(stderr, "SCO audio channel connected (handle %d, mtu %d)\n", sco_handle, sco_mtu);
if (mode == RECORD)
write(rd, "RING\r\n", 6);
maxfd = (rd > sd) ? rd : sd;
while (!terminate) {
FD_ZERO(&rfds);
FD_SET(rd, &rfds);
FD_SET(sd, &rfds);
timeout.tv_sec = 0;
timeout.tv_usec = 10000;
if ((sel = select(maxfd + 1, &rfds, NULL, NULL, &timeout)) > 0) {
if (FD_ISSET(rd, &rfds)) {
memset(buf, 0, sizeof(buf));
rlen = read(rd, buf, sizeof(buf));
if (rlen > 0) {
fprintf(stderr, "%s\n", buf);
wlen = write(rd, "OK\r\n", 4);
}
}
if (FD_ISSET(sd, &rfds)) {
memset(buf, 0, sizeof(buf));
rlen = read(sd, buf, sizeof(buf));
if (rlen > 0)
switch (mode) {
case PLAY:
rlen = read(fd, buf, rlen);
wlen = 0;
p = buf;
while (rlen > sco_mtu) {
wlen += write(sd, p, sco_mtu);
rlen -= sco_mtu;
p += sco_mtu;
}
wlen += write(sd, p, rlen);
break;
case RECORD:
wlen = write(fd, buf, rlen);
break;
default:
break;
}
}
}
}
close(sd);
sleep(5);
close(rd);
return 0;
}
static int server(int fd)
{
int rsd, rd;
struct sockaddr_rc addr;
socklen_t addrlen;
sdp_session_t *sdpSession;
sdp_record_t *recordP;
sdp_list_t *svclass, *pfseq, *apseq, *root, *aproto;
uuid_t root_uuid, l2cap, rfcomm, svcuuid;
sdp_profile_desc_t sdp_profile[1];
sdp_list_t *proto[2];
fd_set rfds;
struct timeval timeout;
int maxfd, sel, rlen, wlen;
unsigned char buf[2048];
int error;
// Create incoming RFComm socket
rsd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
if (rsd < 0)
{
perror("ERROR failed to create socket");
return -1;
}
/* Bind to local address */
addr.rc_family = AF_BLUETOOTH;
bacpy(&addr.rc_bdaddr, BDADDR_ANY);
addr.rc_channel = 0;
if (bind(rsd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
{
perror("ERROR Server RFCOMM binding error");
close(rsd);
return -1;
}
/* Listen for connections */
if (listen(rsd, 1))
{
perror("ERROR Server RFCOMM listen error");
close(rsd);
return -1;
}
memset(&addr, 0, sizeof(addr));
addrlen = sizeof(addr);
if (getsockname(rsd, (struct sockaddr *) &addr, &addrlen) < 0)
{
perror("ERROR Server RFCOMM getsockname error");
close(rsd);
return -1;
}
fprintf(stderr, "Server RFCOMM socket %lu listen on RFComm %lu\n", (unsigned long) rsd, (unsigned long) addr.rc_channel);
// Prepare SDP record
sdpSession = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0);
if (!sdpSession)
{
perror("ERROR Can not start SDP session");
return -1;
}
recordP = sdp_record_alloc();
if (!recordP)
{
perror("ERROR Allocate for service description failed");
return -1;
}
// Add to Public Browse Group
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
root = sdp_list_append(NULL, &root_uuid);
sdp_set_browse_groups(recordP, root);
// Set Protocol descriptors
sdp_uuid16_create(&l2cap, L2CAP_UUID);
proto[0] = sdp_list_append(NULL, &l2cap);
apseq = sdp_list_append(NULL, proto[0]);
sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
proto[1] = sdp_list_append(NULL, &rfcomm);
proto[1] = sdp_list_append(proto[1], sdp_data_alloc(SDP_UINT8, &addr.rc_channel));
apseq = sdp_list_append(apseq, proto[1]);
aproto = sdp_list_append(NULL, apseq);
sdp_set_access_protos(recordP, aproto);
// Set service class
sdp_uuid16_create(&svcuuid, HEADSET_AGW_SVCLASS_ID);
svclass = sdp_list_append(NULL, &svcuuid);
sdp_uuid16_create(&svcuuid, GENERIC_AUDIO_SVCLASS_ID);
svclass = sdp_list_append(svclass, &svcuuid);
sdp_set_service_classes(recordP, svclass);
// Set profile descriptor
sdp_uuid16_create(&sdp_profile[0].uuid, HEADSET_AGW_PROFILE_ID);
sdp_profile[0].version = 0x0100;
pfseq = sdp_list_append(NULL, &sdp_profile[0]);
sdp_set_profile_descs(recordP, pfseq);
sdp_set_info_attr(recordP, "Voice gateway", NULL, NULL);
// Advertise SDP record
error = sdp_record_register(sdpSession, recordP, 0);
if (error)
{
perror("ERROR Unable to advertise service");
sdp_record_free(recordP);
recordP = NULL;
return -1;
}
while (!terminate)
{
FD_ZERO(&rfds);
FD_SET(rsd, &rfds);
timeout.tv_sec = 0;
timeout.tv_usec = 10000;
if ((sel = select(rsd + 1, &rfds, NULL, NULL, &timeout)) > 0)
{
if (FD_ISSET(rsd, &rfds))
{
if ((rd = accept(rsd, (struct sockaddr *) &addr, &addrlen)) < 0)
{
perror("ERROR accept failed");
break;
}
fprintf(stderr, "RFComm connected\n");
while (!terminate)
{
FD_ZERO(&rfds);
FD_SET(rd, &rfds);
timeout.tv_sec = 0;
timeout.tv_usec = 10000;
if ((sel = select(rd + 1, &rfds, NULL, NULL, &timeout)) > 0)
{
if (FD_ISSET(rd, &rfds))
{
memset(buf, 0, sizeof(buf));
rlen = read(rd, buf, sizeof(buf));
if (rlen > 0)
{
fprintf(stderr, "%s\n", buf);
wlen = write(rd, "OK\r\n", 4);
}
}
}
}
fprintf(stderr, "RFComm disconnected\n");
sleep(5);
close(rd);
}
}
}
sleep(5);
close(rsd);
sdp_record_unregister(sdpSession, recordP);
sdp_close(sdpSession);
}
static void usage(void)
{
printf("Usage:\n"
"\thstest play <file> <bdaddr> [channel]\n"
"\thstest record <file> <bdaddr> [channel]\n"
"\thstest server <file> <bdaddr> [channel]\n");
}
int main(int argc, char *argv[])
{
struct sigaction sa;
bdaddr_t local;
bdaddr_t bdaddr;
uint8_t channel;
char *filename;
mode_t filemode;
int mode = 0;
int dd, fd;
switch (argc) {
case 4:
str2ba(argv[3], &bdaddr);
channel = 6;
break;
case 5:
str2ba(argv[3], &bdaddr);
channel = atoi(argv[4]);
break;
default:
usage();
exit(-1);
}
if (strncmp(argv[1], "play", 4) == 0) {
mode = PLAY;
filemode = O_RDONLY;
} else if (strncmp(argv[1], "rec", 3) == 0) {
mode = RECORD;
filemode = O_WRONLY | O_CREAT | O_TRUNC;
} else if (strncmp(argv[1], "serv", 4) == 0) {
mode = SERVER;
filemode = O_WRONLY | O_CREAT | O_TRUNC;
} else {
usage();
exit(-1);
}
filename = argv[2];
/* hci_devba(0, &local);
dd = hci_open_dev(0);
hci_read_voice_setting(dd, &vs, 1000);
vs = htobs(vs);
fprintf(stderr, "Voice setting: 0x%04x\n", vs);
close(dd);
/* if (vs != 0x0060) {
fprintf(stderr, "The voice setting must be 0x0060\n");
return -1;
}
*/
if (strcmp(filename, "-") == 0) {
switch (mode) {
case PLAY:
fd = 0;
break;
case RECORD:
case SERVER:
fd = 1;
break;
default:
return -1;
}
} else {
if ((fd = open(filename, filemode)) < 0) {
perror("Can't open input/output file");
return -1;
}
}
memset(&sa, 0, sizeof(sa));
sa.sa_flags = SA_NOCLDSTOP;
sa.sa_handler = sig_term;
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sa.sa_handler = SIG_IGN;
sigaction(SIGCHLD, &sa, NULL);
sigaction(SIGPIPE, &sa, NULL);
if (mode == SERVER)
server(fd);
else
client(bdaddr, channel, fd, mode);
close(fd);
return 0;
}
next reply other threads:[~2005-04-12 15:38 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-04-12 15:38 Frederic Danis [this message]
2005-04-13 11:33 ` [Bluez-devel] RFComm doesn't disconnect in server mode Marcel Holtmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=425BEB6E.4080500@palmsource.com \
--to=frederic.danis@palmsource.com \
--cc=bluez-devel@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox