All of lore.kernel.org
 help / color / mirror / Atom feed
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;
}


             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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.