Skip to contentSkip to conversation

RFComm doesn't disconnect in server mode

Bluez-devel Frederic Danis 2 participants 2 messages Apr 12, 2005 – Apr 13, 2005 Bluetooth drivers

lore
Share & tools
lore
#0 lore raw

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 :

Quoted 1 line

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 :

Quoted 1 line

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

-----------------------------------------------

HCIDump - HCI packet analyzer ver 1.11
device: hci1 snap_len: 1028 filter: 0xffffffff

Quoted 1 line

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 .......

Quoted 1 line

HCI Event: Command Status (0x0f) plen 4

0000: 00 01 09 04 ....

Quoted 1 line

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 ......

Quoted 1 line

HCI Event: Command Complete (0x0e) plen 10

0000: 01 0b 04 00 da b6 05 a4 07 00 ..........

Quoted 1 line

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 )...

Quoted 1 line

HCI Event: Page Scan Repetition Mode Change (0x20) plen 7

0000: da b6 05 a4 07 00 01 .......

Quoted 1 line

HCI Event: Max Slots Change (0x1b) plen 3

0000: 29 00 05 )..

Quoted 1 line

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
Quoted 1 line

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 )...

Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

HCI Event: Command Status (0x0f) plen 4

0000: 00 01 0f 04 ....

Quoted 1 line

HCI Event: Connection Packet Type Changed (0x1d) plen 5

0000: 00 29 00 18 cc .)...

Quoted 1 line

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
Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

ACL data: handle 0x0029 flags 0x02 dlen 14

    L2CAP(s): Config rsp: scid 0x0040 flags 0x0000 result 0 clen 0
Quoted 1 line

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 
Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

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 
Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

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
Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

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 
Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

ACL data: handle 0x0029 flags 0x02 dlen 18

    L2CAP(s): Config rsp: scid 0x0041 flags 0x0000 result 0 clen 4
    MTU 132 
Quoted 1 line

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 
Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

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

Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

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
Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

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
Quoted 1 line

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
Quoted 1 line

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
Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

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
Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

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..
Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

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 
Quoted 1 line

HCI Event: Number of Completed Packets (0x13) plen 5

0000: 01 29 00 01 00 .)...

Quoted 1 line

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 

/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2002-2004 Marcel Holtmann <[email protected]> *
*

 *  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;
}
maintainer
#1 lore raw

Hi Frederic,

Quoted 24 lines

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
Quoted 1 line

Maybe a RFCOMM DISC frame on the DLCI 0 is missing.

the guys from TomTom discovered the same problem some time ago. This is a reference counting problem on our side and a fix for that was posted to the mailing list and is in the 2.6.12-rc2 kernel. However it seems that this fix introduces an oops at some point. I haven't had the time to investigate this any further.

The funny things with these kind of problems are that the specification misses some words on who is responsible for terminating a signal channel or the underlaying ACL link. Basically in your case the headset is the initiator and it is too stupid too terminate its own RFCOMM signal channel that it created previous. I have no idea why this is not caught by the qualification tests.

I think the Jabra headsets are CSR based and maybe the CSR developers are interested to hear about it. Please post the "hcitool info" output for them.

Regards

Marcel

-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users. Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel