All of lore.kernel.org
 help / color / mirror / Atom feed
* [Bluez-devel] A2DP sink code finally
@ 2005-04-24 15:09 Mayank Batra
  2005-04-25  3:24 ` Brad Midgley
  0 siblings, 1 reply; 15+ messages in thread
From: Mayank Batra @ 2005-04-24 15:09 UTC (permalink / raw)
  To: BLUEZ DEVELOPERS LIST; +Cc: Brad Midgley

[-- Attachment #1: Type: text/plain, Size: 504 bytes --]

Hi Brad,

This is the code for the A2DP sink application.

Compilation:

gcc -o a2snk a2snk.c -lbluetooth

Running the application:

./a2snk

Right now the following bugs exist:

1)   Poor sound quality.

2)   Unclean disconnection.

Help me improve the above areas.

Please add this code to the CVS.

Thanks and Regards,

Mayank

________________________________________________________________________
Yahoo! India Matrimony: Find your life partner online
Go to: http://yahoo.shaadi.com/india-matrimony

[-- Attachment #2: a2snk.c --]
[-- Type: text/plain, Size: 18249 bytes --]

/*
 * a2snk.c
 * This program functions as an A2DP sink
 * (Emulation of an A2DP headset)
 * Mayank Batra  <mayankbatra@yahoo.co.in>
 * Abhinav Mathur <abhinavpmathur@yahoo.com>
 * 
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 */
 
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
#include <signal.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/soundcard.h>	//To play the sound on the sound card

#include "sbc/sbc.h"

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/l2cap.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>

#include <netinet/in.h>

/* AVDTP structures */

/* packet components */

struct avdtp_header {
	//uint8_t packet_type:2;
	uint8_t message_type:2;
	uint8_t packet_type:2;
	uint8_t transaction_label:4;
	uint8_t signal_id:6;
	uint8_t rfa0:2;
} __attribute__ ((packed));

struct acp_seid_info {
	uint8_t rfa0:1;
	uint8_t inuse0:1;
	uint8_t acp_seid:6;
	uint8_t rfa2:3;
	uint8_t tsep:1;
	uint8_t media_type:4;
} __attribute__ ((packed));

struct sbc_codec_specific_elements {
	// a2dp p. 20
	uint8_t channel_mode:4;
	uint8_t frequency:4;
	uint8_t allocation_method:2;
	uint8_t subbands:2;
	uint8_t block_length:4;
	uint8_t min_bitpool;
	uint8_t max_bitpool;
} __attribute__ ((packed));

#define MAX_ADDITIONAL_CODEC 0	//Right now only SBC is supported
#define MAX_ADDITIONAL_CODEC_OCTETS (MAX_ADDITIONAL_CODEC*sizeof(struct acp_seid_info))

/* packets */

struct sepd_req {
	struct avdtp_header header;
} __attribute__ ((packed));

struct sepd_resp {
	struct avdtp_header header;
	struct acp_seid_info infos[1 + MAX_ADDITIONAL_CODEC];
} __attribute__ ((packed));

struct getcap_req {
	struct avdtp_header header;
	uint8_t rfa1:2;
	uint8_t acp_seid:6;
} __attribute__ ((packed));

struct getcap_resp {
	struct avdtp_header header;

	uint8_t serv_cap;
	uint8_t serv_cap_len;

	uint8_t cap_type;
	uint8_t length;
	uint8_t media_type;
	uint8_t media_codec_type;

	struct sbc_codec_specific_elements sbc_elements;

} __attribute__ ((packed));

struct set_config {
	struct avdtp_header header;

	uint8_t rfa0:2;
	uint8_t acp_seid:6;
	uint8_t rfa1:2;
	uint8_t int_seid:6;

	uint8_t serv_cap;
	uint8_t serv_cap_len;

	uint8_t cap_type;
	uint8_t length;
	uint8_t media_type;
	uint8_t media_codec_type;

	struct sbc_codec_specific_elements sbc_elements;

} __attribute__ ((packed));

struct set_config_resp {
	struct avdtp_header header;

	// only present for an error

	uint8_t serv_cat;
	uint8_t error_code;
} __attribute__ ((packed));

struct open_stream_cmd {
	struct avdtp_header header;
	uint8_t rfa0:2;
	uint8_t acp_seid:6;
} __attribute__ ((packed));

struct open_stream_rsp {
	struct avdtp_header header;

	// only present for an error

	uint8_t error;
} __attribute__ ((packed));

struct start_stream_cmd {
	struct avdtp_header header;
	uint8_t rfa0:2;
	uint8_t acp_seid:6;
} __attribute__ ((packed));

struct start_stream_rsp {
	struct avdtp_header header;

	// only present for an error

	uint8_t rfa0:2;
	uint8_t acp_seid:6;
	uint8_t error;
} __attribute__ ((packed));

struct close_stream_cmd {
	struct avdtp_header header;
	uint8_t rfa0:2;
	uint8_t acp_seid:6;
} __attribute__ ((packed));

struct close_stream_rsp {
	struct avdtp_header header;

	// only present for an error

	uint8_t error;
} __attribute__ ((packed));

// this is an rtp, not bluetooth header, so values are big endian
struct media_packet_header {
	uint8_t cc:4;
	uint8_t x:1;
	uint8_t p:1;
	uint8_t v:2;

	uint8_t pt:7;
	uint8_t m:1;

	uint16_t sequence_number;
	uint32_t timestamp;
	uint32_t ssrc;
	uint32_t csrc[0];
} __attribute__ ((packed));

struct media_payload_header {
	uint8_t frame_count:4;
	uint8_t rfa0:1;
	uint8_t is_last_fragment:1;
	uint8_t is_first_fragment:1;
	uint8_t is_fragmented:1;
} __attribute__ ((packed));

// SBC file format header

struct sbc_frame_header {
	uint8_t syncword:8;	/* Sync word */
	uint8_t subbands:1;	/* Subbands */
	uint8_t allocation_method:1;	/* Allocation method */
	uint8_t channel_mode:2;	/* Channel mode */
	uint8_t blocks:2;	/* Blocks */
	uint8_t sampling_frequency:2;	/* Sampling frequency */
	uint8_t bitpool:8;	/* Bitpool */
	uint8_t crc_check:8;	/* CRC check */
} __attribute__ ((packed));

//A2DP signal types
#define AVDTP_DISCOVER 1
#define AVDTP_GET_CAPABILITIES 2
#define AVDTP_SET_CONFIGURATION 3
#define AVDTP_OPEN 6
#define AVDTP_START 7
#define AVDTP_CLOSE 8

#define MEDIA_TRANSPORT_CATEGORY 1
#define MEDIA_CODEC 7

#define SBC_MEDIA_CODEC_TYPE 0
#define MPEG12_MEDIA_CODEC_TYPE 1
#define AUDIO_MEDIA_TYPE 0

//Packet Types
#define PACKET_TYPE_SINGLE 0
#define PACKET_TYPE_START 4
#define PACKET_TYPE_CONTINUE 8
#define PACKET_TYPE_END 12

//Message Types
#define MESSAGE_TYPE_COMMAND 0
#define MESSAGE_TYPE_ACCEPT 2
#define MESSAGE_TYPE_REJECT 3

#define BUFS 1024

#define MEDIA_PACKET_HEADER_LENGTH 14

#define NONSPECAUDIO 1

static volatile int terminate = 0;
static int cmdfd;
static struct sbc_frame_header sbc_info;
sbc_t sbc;
int audio_fd;
#define BUF_SIZE 4096
unsigned char audio_buffer[BUF_SIZE];
int speed, channels;


static void sig_term(int sig)
{
	terminate = 1;
}

static void usage()
{
	fprintf(stderr, "use: ./a2snk\n");
}

int opensound()
{
	int format=AFMT_S16_BE,len,i;
	char c;

	if((audio_fd=open("/dev/dsp",O_WRONLY,0))==-1) {
		perror("\nFile open error\n");
		exit(1);
	}
	if(ioctl(audio_fd,SNDCTL_DSP_SETFMT,&format)==-1) {
		perror("\nioctl no. 1\n");
		exit(1);
	}

	if(ioctl(audio_fd,SNDCTL_DSP_CHANNELS,&channels)==-1) {
		perror("\nioctl no. 2\n");
		exit(1);
	}

	if(ioctl(audio_fd,SNDCTL_DSP_SPEED,&speed)==-1) {
		perror("\nioctl no. 3\n");
		exit(1);
	}

	return 1;
}

int closesound()
{
	if(close(audio_fd)<0) {
		perror("\nUnable to close the sound card");
		exit(1);
	}
}


static ssize_t __write(int fd,void *buf,size_t count)
{
	ssize_t len,pos=0;
	while(count>0){
		len=write(fd,buf+pos,count);
		if(len<=0)
			return len;
		count -= len;
		pos += len;
	}
	return pos;
}

static void decode(char *stream,int streamlen)
{
	int fd, id, pos, framelen;
	static int turn = 1;
	pos = 0;

	framelen = sbc_decode(&sbc, stream, streamlen);

	printf("%d Hz, %d channels\n", sbc.rate, sbc.channels);
	channels=sbc.channels;
	speed=sbc.rate;
	if(turn == 1) {
		/* Open the sound card only once during the streaming */
		opensound();
		turn = 0;
	}

	char c;
	while (framelen > 0) {
		//dump_packet(sbc.data,sbc.len);
		write(audio_fd,sbc.data,sbc.len);
	
		pos += framelen;

		framelen = sbc_decode(&sbc, stream + pos, streamlen - pos);
	}

}	



int sk;
static int do_listen(bdaddr_t *src, unsigned short psm, uint16_t *mtu)
{
	struct sockaddr_l2 addr;
	struct l2cap_options opts;
	
	int opt;
	int nsk;

	sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
	if (sk < 0) {
		fprintf(stderr, "Can't create socket. %s(%d)\n",
			strerror(errno), errno);
		return -1;
	}
	
	memset(&addr, 0, sizeof(addr));
	addr.l2_family = AF_BLUETOOTH;
	bacpy(&addr.l2_bdaddr, src);
	addr.l2_psm=htobs(psm);
	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
		fprintf(stderr, "Can't bind socket. %s(%d)\n",
						strerror(errno), errno);
		return -1;
	}
	
	/* Get default options */
	opt = sizeof(opts);
	if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &opt) < 0) {
		fprintf(stderr, "Can't get default L2CAP options. %s(%d)\n",
						strerror(errno), errno);
		return -1;
	}
	
	/* Set new options */
	//opts.omtu = 48;
	//opts.imtu = imtu;
	if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, opt) < 0) {
		fprintf(stderr, "Can't set L2CAP options. %s(%d)\n",
						strerror(errno), errno);
		return -1;
	}

	if(listen(sk,5)<0) {
		fprintf(stderr,"\nCan't listen.%s(%d)\n",strerror(errno),errno);
		close(sk);
		return -1;
	}
	
	socklen_t addrlen;
	
	memset(&addr, 0, sizeof(addr));
	addrlen = sizeof(addr);

	if ((nsk = accept(sk, (struct sockaddr *) &addr, &addrlen)) < 0)
		return -1;
	else printf("\nConnected");
	
	opt = sizeof(opts);
	if (getsockopt(nsk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &opt) < 0) {
		fprintf(stderr, "Can't get L2CAP options. %s(%d)\n",
						strerror(errno), errno);
		close(nsk);
		return -1;
	}

	fprintf(stderr, "Connected [imtu %d, omtu %d, flush_to %d]\n",
					opts.imtu, opts.omtu, opts.flush_to);

	if (mtu)
		*mtu = opts.omtu;

	return nsk;
}

#if 0
static void dump_packet(void *p, int size)
{
	uint8_t *c = (uint8_t *) p;
	while (size-- > 0)
		printf(" %02x\n", *c++);
	printf("\n");
}
#endif

static void init_request(struct avdtp_header * header, int request_id)
{
	static int transaction = 0;

	header->packet_type = PACKET_TYPE_SINGLE;
	header->message_type = MESSAGE_TYPE_ACCEPT;
	header->transaction_label = transaction;
	header->signal_id = request_id;

	// clear rfa bits
	header->rfa0 = 0;
	if(header->signal_id!=AVDTP_OPEN)
		transaction = (transaction + 1) & 0xf;
	else transaction = (transaction + 2) & 0xf;
}


static int calc_frame_len(struct sbc_frame_header *hdr)
{
	int tmp, nrof_subbands, nrof_blocks;

	nrof_subbands = (hdr->subbands + 1) * 4;
	nrof_blocks = (hdr->blocks + 1) * 4;

	switch (hdr->channel_mode) {
	case 0x00:
		nrof_subbands /= 2;
		tmp = nrof_blocks * hdr->bitpool;
		break;
	case 0x01:
		tmp = nrof_blocks * hdr->bitpool * 2;
		break;
	case 0x02:
		tmp = nrof_blocks * hdr->bitpool;
		break;
	case 0x03:
		tmp = nrof_blocks * hdr->bitpool + nrof_subbands;
		break;
	default:
		return 0;
	}

	return (nrof_subbands + ((tmp + 7) / 8));
}

static int read_header(int fd, struct sbc_frame_header *sbc_info) {
	if (read(fd, sbc_info, sizeof(*sbc_info)) < sizeof(*sbc_info)) {
		fprintf(stderr, "reached end of file?\n");
		return -1;
	}

	if (sbc_info->syncword != 0x9c) {
		printf("out of sync (0x%02x)\n", sbc_info->syncword);
		return -1;
	}

	return calc_frame_len(sbc_info);
}

int main(int argc, char *argv[])
{
	struct sigaction sa;
	int streamfd;

	bdaddr_t src, dst;
	unsigned short psm_cmd, psm_stream;
	unsigned long flags;
	int frame_len;
	time_t timestamp;
	uint16_t mtu, seq_num;
	int fd;

	bacpy(&src, BDADDR_ANY);

	psm_cmd=25;
	cmdfd = do_listen(&src, psm_cmd, NULL);
	if (cmdfd < 0) {
		fprintf(stderr, "cannot open psm_cmd = %d\n", psm_cmd);
		exit(-1);
	}
	// avdtp discover request

 	//Reading the discover request
	struct sepd_req get_resp;
	int size;
	size = read(cmdfd, &get_resp, sizeof(get_resp));
	if(get_resp.header.signal_id!=AVDTP_DISCOVER) {
		fprintf(stderr,"Couldn't get avdtp_discover\n");
		close(cmdfd);
		exit(-1);
	}
	else printf("\nGot Stream End Point Discovery Request");
 	
	
	//Writing the discover response

	struct sepd_resp send_resp;
	//Fill in the values in send_resp
	memset(&send_resp,0,sizeof(send_resp));
	init_request(&send_resp.header,AVDTP_DISCOVER);
	send_resp.infos[0].rfa0=0;
	send_resp.infos[0].inuse0=0;
	send_resp.infos[0].acp_seid=1;
	send_resp.infos[0].rfa2=2;
	send_resp.infos[0].tsep=1;
	send_resp.infos[0].media_type=0;
	
	if(write(cmdfd,&send_resp,sizeof(send_resp))!=sizeof(send_resp)) {
		fprintf(stderr,"\nCould not send discover response\n");
		close(cmdfd);
		exit(-1);
	}
	else printf("\nSent Stream End Point Discovery Response\n");

	
	//Now read the get capablities request from the source

	struct getcap_req get_req;
	memset(&get_req,0,sizeof(get_req));
	if(read(cmdfd,&get_req,sizeof(get_req))!=sizeof(get_req) || (get_req.header.signal_id!=AVDTP_GET_CAPABILITIES)) {
		fprintf(stderr,"\nDidn't get a get cap req");
	}
	else printf("\nGot a get capabilities request\n");
	
	//Send a get cap resp
	struct getcap_resp cap_resp;
	memset(&cap_resp,0,sizeof(cap_resp));
	init_request(&cap_resp.header,AVDTP_GET_CAPABILITIES);
	//Fill in the values of the structure
	cap_resp.serv_cap=MEDIA_TRANSPORT_CATEGORY;
	cap_resp.serv_cap_len=0;
	cap_resp.cap_type=MEDIA_CODEC;
	cap_resp.media_type=AUDIO_MEDIA_TYPE;
	cap_resp.length=6;
	cap_resp.media_codec_type=SBC_MEDIA_CODEC_TYPE;
	cap_resp.sbc_elements.channel_mode=15;
	cap_resp.sbc_elements.frequency=15;
	cap_resp.sbc_elements.allocation_method=3;
	cap_resp.sbc_elements.subbands=3;  
	cap_resp.sbc_elements.min_bitpool=2;
	cap_resp.sbc_elements.max_bitpool=250;
	cap_resp.sbc_elements.block_length=15;
	
	if(write(cmdfd,&cap_resp,sizeof(cap_resp))<sizeof(cap_resp)) {
		fprintf(stderr,"couldn't reply the caps\n");
	}
	else printf("\nSent the get capabilities response");
	
	//Now read the set config req

	struct set_config s_config;

	if(read(cmdfd,&s_config,sizeof(s_config))!=sizeof(s_config) || (s_config.header.signal_id!=AVDTP_SET_CONFIGURATION)) {
		fprintf(stderr,"couldn't get a set configurations request\n");
	}
	else printf("\nGot a set configurations request\n");
	
	//Now send the set config resp

	struct set_config_resp s_resp;
	//Fill in the values of the structure
	memset(&s_resp,0,sizeof(s_resp));
	init_request(&s_resp.header,AVDTP_SET_CONFIGURATION);
	s_resp.header.signal_id=AVDTP_SET_CONFIGURATION;
	s_resp.header.message_type=MESSAGE_TYPE_ACCEPT;
	if(write(cmdfd,&s_resp,sizeof(s_resp))!=sizeof(s_resp)) {
		fprintf(stderr,"couldn't send set config resp\n");
	}
	else printf("\nSent a Set configurations response\n");

	
	struct open_stream_cmd open_stream;
      memset(&open_stream, 0, sizeof(open_stream));
                                                                                
      if ((read(cmdfd, &open_stream, sizeof(open_stream)) != sizeof(open_stream)) || (open_stream.header.signal_id!=AVDTP_OPEN)){
               printf("\nDidn't receive an open stream command\n");
               return (-1);
      }
                                                                                
      printf("\nReceived an open stream command\n");
                                                                              
      struct open_stream_rsp open_resp;
	memset(&open_resp,0,sizeof(open_resp));
	init_request(&open_resp.header,AVDTP_OPEN);
	open_resp.header.signal_id=AVDTP_OPEN;
	open_resp.header.message_type=MESSAGE_TYPE_ACCEPT;
      if (write(cmdfd, &open_resp, sizeof(open_resp)) < sizeof(open_resp)) {
              fprintf(stderr, "couldn't send open stream response confirm for seid = %d\n", open_stream.acp_seid);
              return (-1);
      }
                                                                                
      printf("\nSent open stream confirm\n");

	// open the stream l2cap

	mtu = 48;
	socklen_t addrlen;
      struct sockaddr_l2 addr;                                                                                         
      memset(&addr, 0, sizeof(addr));
      addrlen = sizeof(addr);
                                                                                                 
      streamfd = accept(sk, (struct sockaddr *) &addr, &addrlen);
                        
	if (streamfd < 0) {
		fprintf(stderr, "cannot open psm_stream = %d\n", psm_stream);
		exit(-1);
	}
	else printf("\nConnected on the streamfd channel");
	
	// start the stream

	struct start_stream_cmd start_stream;
	memset(&start_stream, 0, sizeof(start_stream));

	//Read the start stream command
	if (read(cmdfd, &start_stream, sizeof(start_stream)) != sizeof(start_stream) || (start_stream.header.signal_id!=AVDTP_START)) {
		fprintf(stderr, "\nDid not get a start stream command\n");
		close(streamfd);
		close(cmdfd);
		exit(-1);
	}

	else printf("\nGot a stream-start command\n");

	//Give the start stream response
	struct start_stream_rsp start_resp;
	//Fill in the values of the structure
	memset(&start_resp,0,sizeof(start_resp));
	init_request(&start_resp.header,AVDTP_START);
	if (write(cmdfd, &start_resp, sizeof(start_resp)) < sizeof(start_resp)) {
		fprintf(stderr, "Couldn't send start stream command confirm");
		close(streamfd);
		close(cmdfd);
		return (-1);
	}

	else printf("\nSent start stream confirm\n");

	char buf[BUFS];
	int psize;

	if (mtu > BUFS)
		mtu = BUFS;

	terminate = 0;
	seq_num = 1;

	sbc_init(&sbc,SBC_NULL);
	struct media_packet_header packet_header;
	struct media_payload_header payload_header;
	memset(&payload_header, 0, sizeof(payload_header));
	int packsize; //Size of the packet that is read
	timestamp = 0;
	packsize=read(streamfd,buf,1024);
	decode(buf+(sizeof(packet_header)+sizeof(payload_header)),(packsize-sizeof(packet_header)-sizeof(payload_header)));

	printf("Channels=%d,speed=%d",channels,speed);
	struct close_stream_cmd close_stream;
	memset(&close_stream,0,sizeof(close_stream));
	while (!terminate) {

		packsize=read(streamfd, buf,1024);
		if(packsize < 0)
			break;
		printf("\nRead:%d bytes",packsize);

		decode(buf+(sizeof(packet_header)+sizeof(payload_header)),(packsize-sizeof(packet_header)-sizeof(payload_header)));
		
		seq_num++;
	}
	sbc_finish(&sbc);
	
	printf("Received %d packets\n", seq_num);

	// signal the stream close
	
	if (read(cmdfd, &close_stream, sizeof(close_stream)) != sizeof(close_stream)) {
		fprintf(stderr, "couldn't get close_stream\n");
		close(streamfd);
		close(cmdfd);
		exit(-1);
	}

	if(close_stream.header.signal_id==AVDTP_CLOSE) {
		printf("Got stream-close\n");
		struct close_stream_rsp close_resp;
		init_request(&close_resp.header,AVDTP_CLOSE);
		if (write(cmdfd, &close_resp, sizeof(close_resp)) < sizeof(close_resp)) {
			fprintf(stderr, "Couldn't send close_resp confirm \n");
			close(streamfd);
			close(cmdfd);
			return (-1);
		}
		else printf("Sent close stream confirm\n");
	}
	else {
		printf("\nDidnt get a stream close as expected");
		close(streamfd);
		close(cmdfd);
		exit(-1);
	}
	closesound();
	close(streamfd);
	close(cmdfd);

	return 0;
}

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Bluez-devel] A2DP sink code finally
  2005-04-24 15:09 Mayank Batra
@ 2005-04-25  3:24 ` Brad Midgley
  2005-04-25  3:58   ` Brad Midgley
                     ` (2 more replies)
  0 siblings, 3 replies; 15+ messages in thread
From: Brad Midgley @ 2005-04-25  3:24 UTC (permalink / raw)
  To: bluez-devel

Mayank,

Thanks for the submission. I corrected some warnings, disabled unused 
functions, and added it to Makefile.am.

We definitely need to do a lot of cleanup (eg now that a2play and a2snk 
have so much duplication), but first off we need to see why audio is 
being distorted...

Brad

Mayank Batra wrote:
> Hi Brad,
> 
> This is the code for the A2DP sink application.
> 
> Compilation:
> 
> gcc -o a2snk a2snk.c -lbluetooth
> 
> Running the application:
> 
> ./a2snk
> 
> Right now the following bugs exist:
> 
> 1)   Poor sound quality.
> 
> 2)   Unclean disconnection.
> 
> Help me improve the above areas.
> 
> Please add this code to the CVS.
> 
> Thanks and Regards,
> 
> Mayank
> 
> ________________________________________________________________________
> Yahoo! India Matrimony: Find your life partner online
> Go to: http://yahoo.shaadi.com/india-matrimony
> 
> 
> ------------------------------------------------------------------------
> 
> /*
>  * a2snk.c
>  * This program functions as an A2DP sink
>  * (Emulation of an A2DP headset)
>  * Mayank Batra  <mayankbatra@yahoo.co.in>
>  * Abhinav Mathur <abhinavpmathur@yahoo.com>
>  * 
>  *   This program is free software; you can redistribute it and/or modify
>  *   it under the terms of the GNU General Public License as published by
>  *   the Free Software Foundation; either version 2 of the License, or
>  *   (at your option) any later version.
>  *
>  *   This program is distributed in the hope that it will be useful,
>  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
>  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>  *   GNU General Public License for more details.
>  *
>  *   You should have received a copy of the GNU General Public License
>  *   along with this program; if not, write to the Free Software
>  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
>  *
>  */
>  
> #ifdef HAVE_CONFIG_H
> #include <config.h>
> #endif
> 
> #include <stdio.h>
> #include <errno.h>
> #include <fcntl.h>
> #include <unistd.h>
> #include <stdlib.h>
> #include <getopt.h>
> #include <signal.h>
> #include <string.h>
> #include <sys/socket.h>
> #include <sys/stat.h>
> #include <sys/soundcard.h>	//To play the sound on the sound card
> 
> #include "sbc/sbc.h"
> 
> #include <bluetooth/bluetooth.h>
> #include <bluetooth/hci.h>
> #include <bluetooth/hci_lib.h>
> #include <bluetooth/l2cap.h>
> #include <bluetooth/sdp.h>
> #include <bluetooth/sdp_lib.h>
> 
> #include <netinet/in.h>
> 
> /* AVDTP structures */
> 
> /* packet components */
> 
> struct avdtp_header {
> 	//uint8_t packet_type:2;
> 	uint8_t message_type:2;
> 	uint8_t packet_type:2;
> 	uint8_t transaction_label:4;
> 	uint8_t signal_id:6;
> 	uint8_t rfa0:2;
> } __attribute__ ((packed));
> 
> struct acp_seid_info {
> 	uint8_t rfa0:1;
> 	uint8_t inuse0:1;
> 	uint8_t acp_seid:6;
> 	uint8_t rfa2:3;
> 	uint8_t tsep:1;
> 	uint8_t media_type:4;
> } __attribute__ ((packed));
> 
> struct sbc_codec_specific_elements {
> 	// a2dp p. 20
> 	uint8_t channel_mode:4;
> 	uint8_t frequency:4;
> 	uint8_t allocation_method:2;
> 	uint8_t subbands:2;
> 	uint8_t block_length:4;
> 	uint8_t min_bitpool;
> 	uint8_t max_bitpool;
> } __attribute__ ((packed));
> 
> #define MAX_ADDITIONAL_CODEC 0	//Right now only SBC is supported
> #define MAX_ADDITIONAL_CODEC_OCTETS (MAX_ADDITIONAL_CODEC*sizeof(struct acp_seid_info))
> 
> /* packets */
> 
> struct sepd_req {
> 	struct avdtp_header header;
> } __attribute__ ((packed));
> 
> struct sepd_resp {
> 	struct avdtp_header header;
> 	struct acp_seid_info infos[1 + MAX_ADDITIONAL_CODEC];
> } __attribute__ ((packed));
> 
> struct getcap_req {
> 	struct avdtp_header header;
> 	uint8_t rfa1:2;
> 	uint8_t acp_seid:6;
> } __attribute__ ((packed));
> 
> struct getcap_resp {
> 	struct avdtp_header header;
> 
> 	uint8_t serv_cap;
> 	uint8_t serv_cap_len;
> 
> 	uint8_t cap_type;
> 	uint8_t length;
> 	uint8_t media_type;
> 	uint8_t media_codec_type;
> 
> 	struct sbc_codec_specific_elements sbc_elements;
> 
> } __attribute__ ((packed));
> 
> struct set_config {
> 	struct avdtp_header header;
> 
> 	uint8_t rfa0:2;
> 	uint8_t acp_seid:6;
> 	uint8_t rfa1:2;
> 	uint8_t int_seid:6;
> 
> 	uint8_t serv_cap;
> 	uint8_t serv_cap_len;
> 
> 	uint8_t cap_type;
> 	uint8_t length;
> 	uint8_t media_type;
> 	uint8_t media_codec_type;
> 
> 	struct sbc_codec_specific_elements sbc_elements;
> 
> } __attribute__ ((packed));
> 
> struct set_config_resp {
> 	struct avdtp_header header;
> 
> 	// only present for an error
> 
> 	uint8_t serv_cat;
> 	uint8_t error_code;
> } __attribute__ ((packed));
> 
> struct open_stream_cmd {
> 	struct avdtp_header header;
> 	uint8_t rfa0:2;
> 	uint8_t acp_seid:6;
> } __attribute__ ((packed));
> 
> struct open_stream_rsp {
> 	struct avdtp_header header;
> 
> 	// only present for an error
> 
> 	uint8_t error;
> } __attribute__ ((packed));
> 
> struct start_stream_cmd {
> 	struct avdtp_header header;
> 	uint8_t rfa0:2;
> 	uint8_t acp_seid:6;
> } __attribute__ ((packed));
> 
> struct start_stream_rsp {
> 	struct avdtp_header header;
> 
> 	// only present for an error
> 
> 	uint8_t rfa0:2;
> 	uint8_t acp_seid:6;
> 	uint8_t error;
> } __attribute__ ((packed));
> 
> struct close_stream_cmd {
> 	struct avdtp_header header;
> 	uint8_t rfa0:2;
> 	uint8_t acp_seid:6;
> } __attribute__ ((packed));
> 
> struct close_stream_rsp {
> 	struct avdtp_header header;
> 
> 	// only present for an error
> 
> 	uint8_t error;
> } __attribute__ ((packed));
> 
> // this is an rtp, not bluetooth header, so values are big endian
> struct media_packet_header {
> 	uint8_t cc:4;
> 	uint8_t x:1;
> 	uint8_t p:1;
> 	uint8_t v:2;
> 
> 	uint8_t pt:7;
> 	uint8_t m:1;
> 
> 	uint16_t sequence_number;
> 	uint32_t timestamp;
> 	uint32_t ssrc;
> 	uint32_t csrc[0];
> } __attribute__ ((packed));
> 
> struct media_payload_header {
> 	uint8_t frame_count:4;
> 	uint8_t rfa0:1;
> 	uint8_t is_last_fragment:1;
> 	uint8_t is_first_fragment:1;
> 	uint8_t is_fragmented:1;
> } __attribute__ ((packed));
> 
> // SBC file format header
> 
> struct sbc_frame_header {
> 	uint8_t syncword:8;	/* Sync word */
> 	uint8_t subbands:1;	/* Subbands */
> 	uint8_t allocation_method:1;	/* Allocation method */
> 	uint8_t channel_mode:2;	/* Channel mode */
> 	uint8_t blocks:2;	/* Blocks */
> 	uint8_t sampling_frequency:2;	/* Sampling frequency */
> 	uint8_t bitpool:8;	/* Bitpool */
> 	uint8_t crc_check:8;	/* CRC check */
> } __attribute__ ((packed));
> 
> //A2DP signal types
> #define AVDTP_DISCOVER 1
> #define AVDTP_GET_CAPABILITIES 2
> #define AVDTP_SET_CONFIGURATION 3
> #define AVDTP_OPEN 6
> #define AVDTP_START 7
> #define AVDTP_CLOSE 8
> 
> #define MEDIA_TRANSPORT_CATEGORY 1
> #define MEDIA_CODEC 7
> 
> #define SBC_MEDIA_CODEC_TYPE 0
> #define MPEG12_MEDIA_CODEC_TYPE 1
> #define AUDIO_MEDIA_TYPE 0
> 
> //Packet Types
> #define PACKET_TYPE_SINGLE 0
> #define PACKET_TYPE_START 4
> #define PACKET_TYPE_CONTINUE 8
> #define PACKET_TYPE_END 12
> 
> //Message Types
> #define MESSAGE_TYPE_COMMAND 0
> #define MESSAGE_TYPE_ACCEPT 2
> #define MESSAGE_TYPE_REJECT 3
> 
> #define BUFS 1024
> 
> #define MEDIA_PACKET_HEADER_LENGTH 14
> 
> #define NONSPECAUDIO 1
> 
> static volatile int terminate = 0;
> static int cmdfd;
> static struct sbc_frame_header sbc_info;
> sbc_t sbc;
> int audio_fd;
> #define BUF_SIZE 4096
> unsigned char audio_buffer[BUF_SIZE];
> int speed, channels;
> 
> 
> static void sig_term(int sig)
> {
> 	terminate = 1;
> }
> 
> static void usage()
> {
> 	fprintf(stderr, "use: ./a2snk\n");
> }
> 
> int opensound()
> {
> 	int format=AFMT_S16_BE,len,i;
> 	char c;
> 
> 	if((audio_fd=open("/dev/dsp",O_WRONLY,0))==-1) {
> 		perror("\nFile open error\n");
> 		exit(1);
> 	}
> 	if(ioctl(audio_fd,SNDCTL_DSP_SETFMT,&format)==-1) {
> 		perror("\nioctl no. 1\n");
> 		exit(1);
> 	}
> 
> 	if(ioctl(audio_fd,SNDCTL_DSP_CHANNELS,&channels)==-1) {
> 		perror("\nioctl no. 2\n");
> 		exit(1);
> 	}
> 
> 	if(ioctl(audio_fd,SNDCTL_DSP_SPEED,&speed)==-1) {
> 		perror("\nioctl no. 3\n");
> 		exit(1);
> 	}
> 
> 	return 1;
> }
> 
> int closesound()
> {
> 	if(close(audio_fd)<0) {
> 		perror("\nUnable to close the sound card");
> 		exit(1);
> 	}
> }
> 
> 
> static ssize_t __write(int fd,void *buf,size_t count)
> {
> 	ssize_t len,pos=0;
> 	while(count>0){
> 		len=write(fd,buf+pos,count);
> 		if(len<=0)
> 			return len;
> 		count -= len;
> 		pos += len;
> 	}
> 	return pos;
> }
> 
> static void decode(char *stream,int streamlen)
> {
> 	int fd, id, pos, framelen;
> 	static int turn = 1;
> 	pos = 0;
> 
> 	framelen = sbc_decode(&sbc, stream, streamlen);
> 
> 	printf("%d Hz, %d channels\n", sbc.rate, sbc.channels);
> 	channels=sbc.channels;
> 	speed=sbc.rate;
> 	if(turn == 1) {
> 		/* Open the sound card only once during the streaming */
> 		opensound();
> 		turn = 0;
> 	}
> 
> 	char c;
> 	while (framelen > 0) {
> 		//dump_packet(sbc.data,sbc.len);
> 		write(audio_fd,sbc.data,sbc.len);
> 	
> 		pos += framelen;
> 
> 		framelen = sbc_decode(&sbc, stream + pos, streamlen - pos);
> 	}
> 
> }	
> 
> 
> 
> int sk;
> static int do_listen(bdaddr_t *src, unsigned short psm, uint16_t *mtu)
> {
> 	struct sockaddr_l2 addr;
> 	struct l2cap_options opts;
> 	
> 	int opt;
> 	int nsk;
> 
> 	sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
> 	if (sk < 0) {
> 		fprintf(stderr, "Can't create socket. %s(%d)\n",
> 			strerror(errno), errno);
> 		return -1;
> 	}
> 	
> 	memset(&addr, 0, sizeof(addr));
> 	addr.l2_family = AF_BLUETOOTH;
> 	bacpy(&addr.l2_bdaddr, src);
> 	addr.l2_psm=htobs(psm);
> 	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
> 		fprintf(stderr, "Can't bind socket. %s(%d)\n",
> 						strerror(errno), errno);
> 		return -1;
> 	}
> 	
> 	/* Get default options */
> 	opt = sizeof(opts);
> 	if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &opt) < 0) {
> 		fprintf(stderr, "Can't get default L2CAP options. %s(%d)\n",
> 						strerror(errno), errno);
> 		return -1;
> 	}
> 	
> 	/* Set new options */
> 	//opts.omtu = 48;
> 	//opts.imtu = imtu;
> 	if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, opt) < 0) {
> 		fprintf(stderr, "Can't set L2CAP options. %s(%d)\n",
> 						strerror(errno), errno);
> 		return -1;
> 	}
> 
> 	if(listen(sk,5)<0) {
> 		fprintf(stderr,"\nCan't listen.%s(%d)\n",strerror(errno),errno);
> 		close(sk);
> 		return -1;
> 	}
> 	
> 	socklen_t addrlen;
> 	
> 	memset(&addr, 0, sizeof(addr));
> 	addrlen = sizeof(addr);
> 
> 	if ((nsk = accept(sk, (struct sockaddr *) &addr, &addrlen)) < 0)
> 		return -1;
> 	else printf("\nConnected");
> 	
> 	opt = sizeof(opts);
> 	if (getsockopt(nsk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &opt) < 0) {
> 		fprintf(stderr, "Can't get L2CAP options. %s(%d)\n",
> 						strerror(errno), errno);
> 		close(nsk);
> 		return -1;
> 	}
> 
> 	fprintf(stderr, "Connected [imtu %d, omtu %d, flush_to %d]\n",
> 					opts.imtu, opts.omtu, opts.flush_to);
> 
> 	if (mtu)
> 		*mtu = opts.omtu;
> 
> 	return nsk;
> }
> 
> #if 0
> static void dump_packet(void *p, int size)
> {
> 	uint8_t *c = (uint8_t *) p;
> 	while (size-- > 0)
> 		printf(" %02x\n", *c++);
> 	printf("\n");
> }
> #endif
> 
> static void init_request(struct avdtp_header * header, int request_id)
> {
> 	static int transaction = 0;
> 
> 	header->packet_type = PACKET_TYPE_SINGLE;
> 	header->message_type = MESSAGE_TYPE_ACCEPT;
> 	header->transaction_label = transaction;
> 	header->signal_id = request_id;
> 
> 	// clear rfa bits
> 	header->rfa0 = 0;
> 	if(header->signal_id!=AVDTP_OPEN)
> 		transaction = (transaction + 1) & 0xf;
> 	else transaction = (transaction + 2) & 0xf;
> }
> 
> 
> static int calc_frame_len(struct sbc_frame_header *hdr)
> {
> 	int tmp, nrof_subbands, nrof_blocks;
> 
> 	nrof_subbands = (hdr->subbands + 1) * 4;
> 	nrof_blocks = (hdr->blocks + 1) * 4;
> 
> 	switch (hdr->channel_mode) {
> 	case 0x00:
> 		nrof_subbands /= 2;
> 		tmp = nrof_blocks * hdr->bitpool;
> 		break;
> 	case 0x01:
> 		tmp = nrof_blocks * hdr->bitpool * 2;
> 		break;
> 	case 0x02:
> 		tmp = nrof_blocks * hdr->bitpool;
> 		break;
> 	case 0x03:
> 		tmp = nrof_blocks * hdr->bitpool + nrof_subbands;
> 		break;
> 	default:
> 		return 0;
> 	}
> 
> 	return (nrof_subbands + ((tmp + 7) / 8));
> }
> 
> static int read_header(int fd, struct sbc_frame_header *sbc_info) {
> 	if (read(fd, sbc_info, sizeof(*sbc_info)) < sizeof(*sbc_info)) {
> 		fprintf(stderr, "reached end of file?\n");
> 		return -1;
> 	}
> 
> 	if (sbc_info->syncword != 0x9c) {
> 		printf("out of sync (0x%02x)\n", sbc_info->syncword);
> 		return -1;
> 	}
> 
> 	return calc_frame_len(sbc_info);
> }
> 
> int main(int argc, char *argv[])
> {
> 	struct sigaction sa;
> 	int streamfd;
> 
> 	bdaddr_t src, dst;
> 	unsigned short psm_cmd, psm_stream;
> 	unsigned long flags;
> 	int frame_len;
> 	time_t timestamp;
> 	uint16_t mtu, seq_num;
> 	int fd;
> 
> 	bacpy(&src, BDADDR_ANY);
> 
> 	psm_cmd=25;
> 	cmdfd = do_listen(&src, psm_cmd, NULL);
> 	if (cmdfd < 0) {
> 		fprintf(stderr, "cannot open psm_cmd = %d\n", psm_cmd);
> 		exit(-1);
> 	}
> 	// avdtp discover request
> 
>  	//Reading the discover request
> 	struct sepd_req get_resp;
> 	int size;
> 	size = read(cmdfd, &get_resp, sizeof(get_resp));
> 	if(get_resp.header.signal_id!=AVDTP_DISCOVER) {
> 		fprintf(stderr,"Couldn't get avdtp_discover\n");
> 		close(cmdfd);
> 		exit(-1);
> 	}
> 	else printf("\nGot Stream End Point Discovery Request");
>  	
> 	
> 	//Writing the discover response
> 
> 	struct sepd_resp send_resp;
> 	//Fill in the values in send_resp
> 	memset(&send_resp,0,sizeof(send_resp));
> 	init_request(&send_resp.header,AVDTP_DISCOVER);
> 	send_resp.infos[0].rfa0=0;
> 	send_resp.infos[0].inuse0=0;
> 	send_resp.infos[0].acp_seid=1;
> 	send_resp.infos[0].rfa2=2;
> 	send_resp.infos[0].tsep=1;
> 	send_resp.infos[0].media_type=0;
> 	
> 	if(write(cmdfd,&send_resp,sizeof(send_resp))!=sizeof(send_resp)) {
> 		fprintf(stderr,"\nCould not send discover response\n");
> 		close(cmdfd);
> 		exit(-1);
> 	}
> 	else printf("\nSent Stream End Point Discovery Response\n");
> 
> 	
> 	//Now read the get capablities request from the source
> 
> 	struct getcap_req get_req;
> 	memset(&get_req,0,sizeof(get_req));
> 	if(read(cmdfd,&get_req,sizeof(get_req))!=sizeof(get_req) || (get_req.header.signal_id!=AVDTP_GET_CAPABILITIES)) {
> 		fprintf(stderr,"\nDidn't get a get cap req");
> 	}
> 	else printf("\nGot a get capabilities request\n");
> 	
> 	//Send a get cap resp
> 	struct getcap_resp cap_resp;
> 	memset(&cap_resp,0,sizeof(cap_resp));
> 	init_request(&cap_resp.header,AVDTP_GET_CAPABILITIES);
> 	//Fill in the values of the structure
> 	cap_resp.serv_cap=MEDIA_TRANSPORT_CATEGORY;
> 	cap_resp.serv_cap_len=0;
> 	cap_resp.cap_type=MEDIA_CODEC;
> 	cap_resp.media_type=AUDIO_MEDIA_TYPE;
> 	cap_resp.length=6;
> 	cap_resp.media_codec_type=SBC_MEDIA_CODEC_TYPE;
> 	cap_resp.sbc_elements.channel_mode=15;
> 	cap_resp.sbc_elements.frequency=15;
> 	cap_resp.sbc_elements.allocation_method=3;
> 	cap_resp.sbc_elements.subbands=3;  
> 	cap_resp.sbc_elements.min_bitpool=2;
> 	cap_resp.sbc_elements.max_bitpool=250;
> 	cap_resp.sbc_elements.block_length=15;
> 	
> 	if(write(cmdfd,&cap_resp,sizeof(cap_resp))<sizeof(cap_resp)) {
> 		fprintf(stderr,"couldn't reply the caps\n");
> 	}
> 	else printf("\nSent the get capabilities response");
> 	
> 	//Now read the set config req
> 
> 	struct set_config s_config;
> 
> 	if(read(cmdfd,&s_config,sizeof(s_config))!=sizeof(s_config) || (s_config.header.signal_id!=AVDTP_SET_CONFIGURATION)) {
> 		fprintf(stderr,"couldn't get a set configurations request\n");
> 	}
> 	else printf("\nGot a set configurations request\n");
> 	
> 	//Now send the set config resp
> 
> 	struct set_config_resp s_resp;
> 	//Fill in the values of the structure
> 	memset(&s_resp,0,sizeof(s_resp));
> 	init_request(&s_resp.header,AVDTP_SET_CONFIGURATION);
> 	s_resp.header.signal_id=AVDTP_SET_CONFIGURATION;
> 	s_resp.header.message_type=MESSAGE_TYPE_ACCEPT;
> 	if(write(cmdfd,&s_resp,sizeof(s_resp))!=sizeof(s_resp)) {
> 		fprintf(stderr,"couldn't send set config resp\n");
> 	}
> 	else printf("\nSent a Set configurations response\n");
> 
> 	
> 	struct open_stream_cmd open_stream;
>       memset(&open_stream, 0, sizeof(open_stream));
>                                                                                 
>       if ((read(cmdfd, &open_stream, sizeof(open_stream)) != sizeof(open_stream)) || (open_stream.header.signal_id!=AVDTP_OPEN)){
>                printf("\nDidn't receive an open stream command\n");
>                return (-1);
>       }
>                                                                                 
>       printf("\nReceived an open stream command\n");
>                                                                               
>       struct open_stream_rsp open_resp;
> 	memset(&open_resp,0,sizeof(open_resp));
> 	init_request(&open_resp.header,AVDTP_OPEN);
> 	open_resp.header.signal_id=AVDTP_OPEN;
> 	open_resp.header.message_type=MESSAGE_TYPE_ACCEPT;
>       if (write(cmdfd, &open_resp, sizeof(open_resp)) < sizeof(open_resp)) {
>               fprintf(stderr, "couldn't send open stream response confirm for seid = %d\n", open_stream.acp_seid);
>               return (-1);
>       }
>                                                                                 
>       printf("\nSent open stream confirm\n");
> 
> 	// open the stream l2cap
> 
> 	mtu = 48;
> 	socklen_t addrlen;
>       struct sockaddr_l2 addr;                                                                                         
>       memset(&addr, 0, sizeof(addr));
>       addrlen = sizeof(addr);
>                                                                                                  
>       streamfd = accept(sk, (struct sockaddr *) &addr, &addrlen);
>                         
> 	if (streamfd < 0) {
> 		fprintf(stderr, "cannot open psm_stream = %d\n", psm_stream);
> 		exit(-1);
> 	}
> 	else printf("\nConnected on the streamfd channel");
> 	
> 	// start the stream
> 
> 	struct start_stream_cmd start_stream;
> 	memset(&start_stream, 0, sizeof(start_stream));
> 
> 	//Read the start stream command
> 	if (read(cmdfd, &start_stream, sizeof(start_stream)) != sizeof(start_stream) || (start_stream.header.signal_id!=AVDTP_START)) {
> 		fprintf(stderr, "\nDid not get a start stream command\n");
> 		close(streamfd);
> 		close(cmdfd);
> 		exit(-1);
> 	}
> 
> 	else printf("\nGot a stream-start command\n");
> 
> 	//Give the start stream response
> 	struct start_stream_rsp start_resp;
> 	//Fill in the values of the structure
> 	memset(&start_resp,0,sizeof(start_resp));
> 	init_request(&start_resp.header,AVDTP_START);
> 	if (write(cmdfd, &start_resp, sizeof(start_resp)) < sizeof(start_resp)) {
> 		fprintf(stderr, "Couldn't send start stream command confirm");
> 		close(streamfd);
> 		close(cmdfd);
> 		return (-1);
> 	}
> 
> 	else printf("\nSent start stream confirm\n");
> 
> 	char buf[BUFS];
> 	int psize;
> 
> 	if (mtu > BUFS)
> 		mtu = BUFS;
> 
> 	terminate = 0;
> 	seq_num = 1;
> 
> 	sbc_init(&sbc,SBC_NULL);
> 	struct media_packet_header packet_header;
> 	struct media_payload_header payload_header;
> 	memset(&payload_header, 0, sizeof(payload_header));
> 	int packsize; //Size of the packet that is read
> 	timestamp = 0;
> 	packsize=read(streamfd,buf,1024);
> 	decode(buf+(sizeof(packet_header)+sizeof(payload_header)),(packsize-sizeof(packet_header)-sizeof(payload_header)));
> 
> 	printf("Channels=%d,speed=%d",channels,speed);
> 	struct close_stream_cmd close_stream;
> 	memset(&close_stream,0,sizeof(close_stream));
> 	while (!terminate) {
> 
> 		packsize=read(streamfd, buf,1024);
> 		if(packsize < 0)
> 			break;
> 		printf("\nRead:%d bytes",packsize);
> 
> 		decode(buf+(sizeof(packet_header)+sizeof(payload_header)),(packsize-sizeof(packet_header)-sizeof(payload_header)));
> 		
> 		seq_num++;
> 	}
> 	sbc_finish(&sbc);
> 	
> 	printf("Received %d packets\n", seq_num);
> 
> 	// signal the stream close
> 	
> 	if (read(cmdfd, &close_stream, sizeof(close_stream)) != sizeof(close_stream)) {
> 		fprintf(stderr, "couldn't get close_stream\n");
> 		close(streamfd);
> 		close(cmdfd);
> 		exit(-1);
> 	}
> 
> 	if(close_stream.header.signal_id==AVDTP_CLOSE) {
> 		printf("Got stream-close\n");
> 		struct close_stream_rsp close_resp;
> 		init_request(&close_resp.header,AVDTP_CLOSE);
> 		if (write(cmdfd, &close_resp, sizeof(close_resp)) < sizeof(close_resp)) {
> 			fprintf(stderr, "Couldn't send close_resp confirm \n");
> 			close(streamfd);
> 			close(cmdfd);
> 			return (-1);
> 		}
> 		else printf("Sent close stream confirm\n");
> 	}
> 	else {
> 		printf("\nDidnt get a stream close as expected");
> 		close(streamfd);
> 		close(cmdfd);
> 		exit(-1);
> 	}
> 	closesound();
> 	close(streamfd);
> 	close(cmdfd);
> 
> 	return 0;
> }


-------------------------------------------------------
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
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Bluez-devel] A2DP sink code finally
  2005-04-25  3:24 ` Brad Midgley
@ 2005-04-25  3:58   ` Brad Midgley
  2005-04-25  6:08   ` Henryk Plötz
  2005-04-26 12:23   ` Mayank Batra
  2 siblings, 0 replies; 15+ messages in thread
From: Brad Midgley @ 2005-04-25  3:58 UTC (permalink / raw)
  To: bluez-devel

Mayank,

I suspect the distortion could be happening if the read() gets an sbc 
frame fragment at the end... it would be discarded by the decoder if 
that happens.

Brad


-------------------------------------------------------
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
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Bluez-devel] A2DP sink code finally
  2005-04-25  3:24 ` Brad Midgley
  2005-04-25  3:58   ` Brad Midgley
@ 2005-04-25  6:08   ` Henryk Plötz
  2005-04-25 14:40     ` Brad Midgley
  2005-04-26 12:23   ` Mayank Batra
  2 siblings, 1 reply; 15+ messages in thread
From: Henryk Plötz @ 2005-04-25  6:08 UTC (permalink / raw)
  To: bluez-devel

[-- Attachment #1: Type: text/plain, Size: 754 bytes --]

Moin,

Am Sun, 24 Apr 2005 21:24:04 -0600 schrieb Brad Midgley:

> Thanks for the submission. I corrected some warnings, disabled unused 
> functions, and added it to Makefile.am.

Ah, thanks.

> We definitely need to do a lot of cleanup (eg now that a2play and
> a2snk  have so much duplication), but first off we need to see why
> audio is  being distorted...

Hmm, how do I test that? I can't seem to get my audio dongle to connect.
Is there anything else I've got to do apart from 
| hciconfig hci0 class 0x200404
| sdptool add A2SNK
| ./a2snk
?

-- 
Henryk Plötz
Grüße aus Berlin
~~~~~~~ Un-CDs, nein danke! http://www.heise.de/ct/cd-register/ ~~~~~~~
~ Help Microsoft fight software piracy: Give Linux to a friend today! ~

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Bluez-devel] A2DP sink code finally
  2005-04-25  6:08   ` Henryk Plötz
@ 2005-04-25 14:40     ` Brad Midgley
  0 siblings, 0 replies; 15+ messages in thread
From: Brad Midgley @ 2005-04-25 14:40 UTC (permalink / raw)
  To: bluez-devel

Henryk,

I'm not sure anyone has used the dongle yet. (Mayank?)

I'll be trying it once I have another machine set up to run a2play.

Brad

Henryk Plötz wrote:
> Moin,
> 
> Am Sun, 24 Apr 2005 21:24:04 -0600 schrieb Brad Midgley:
> 
> 
>>Thanks for the submission. I corrected some warnings, disabled unused 
>>functions, and added it to Makefile.am.
> 
> 
> Ah, thanks.
> 
> 
>>We definitely need to do a lot of cleanup (eg now that a2play and
>>a2snk  have so much duplication), but first off we need to see why
>>audio is  being distorted...
> 
> 
> Hmm, how do I test that? I can't seem to get my audio dongle to connect.
> Is there anything else I've got to do apart from 
> | hciconfig hci0 class 0x200404
> | sdptool add A2SNK
> | ./a2snk
> ?
> 


-------------------------------------------------------
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
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Bluez-devel] A2DP sink code finally
  2005-04-25  3:24 ` Brad Midgley
  2005-04-25  3:58   ` Brad Midgley
  2005-04-25  6:08   ` Henryk Plötz
@ 2005-04-26 12:23   ` Mayank Batra
  2 siblings, 0 replies; 15+ messages in thread
From: Mayank Batra @ 2005-04-26 12:23 UTC (permalink / raw)
  To: bluez-devel

Brad,

> Thanks for the submission. I corrected some
> warnings, disabled unused 
> functions, and added it to Makefile.am.

Great!
 
> We definitely need to do a lot of cleanup (eg now
> that a2play and a2snk 
> have so much duplication), but first off we need to
> see why audio is 
> being distorted...

Exactly. Once the audio part is ok then we can take
care of the duplication part.


Mayank

> Mayank Batra wrote:
> > Hi Brad,
> > 
> > This is the code for the A2DP sink application.
> > 
> > Compilation:
> > 
> > gcc -o a2snk a2snk.c -lbluetooth
> > 
> > Running the application:
> > 
> > ./a2snk
> > 
> > Right now the following bugs exist:
> > 
> > 1)   Poor sound quality.
> > 
> > 2)   Unclean disconnection.
> > 
> > Help me improve the above areas.
> > 
> > Please add this code to the CVS.
> > 
> > Thanks and Regards,
> > 
> > Mayank
> > 
> >
>
________________________________________________________________________
> > Yahoo! India Matrimony: Find your life partner
> online
> > Go to: http://yahoo.shaadi.com/india-matrimony
> > 
> > 
> >
>
------------------------------------------------------------------------
> > 
> > /*
> >  * a2snk.c
> >  * This program functions as an A2DP sink
> >  * (Emulation of an A2DP headset)
> >  * Mayank Batra  <mayankbatra@yahoo.co.in>
> >  * Abhinav Mathur <abhinavpmathur@yahoo.com>
> >  * 
> >  *   This program is free software; you can
> redistribute it and/or modify
> >  *   it under the terms of the GNU General Public
> License as published by
> >  *   the Free Software Foundation; either version
> 2 of the License, or
> >  *   (at your option) any later version.
> >  *
> >  *   This program is distributed in the hope that
> it will be useful,
> >  *   but WITHOUT ANY WARRANTY; without even the
> implied warranty of
> >  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR
> PURPOSE.  See the
> >  *   GNU General Public License for more details.
> >  *
> >  *   You should have received a copy of the GNU
> General Public License
> >  *   along with this program; if not, write to the
> Free Software
> >  *   Foundation, Inc., 59 Temple Place, Suite 330,
> Boston, MA  02111-1307 USA
> >  *
> >  */
> >  
> > #ifdef HAVE_CONFIG_H
> > #include <config.h>
> > #endif
> > 
> > #include <stdio.h>
> > #include <errno.h>
> > #include <fcntl.h>
> > #include <unistd.h>
> > #include <stdlib.h>
> > #include <getopt.h>
> > #include <signal.h>
> > #include <string.h>
> > #include <sys/socket.h>
> > #include <sys/stat.h>
> > #include <sys/soundcard.h>	//To play the sound on
> the sound card
> > 
> > #include "sbc/sbc.h"
> > 
> > #include <bluetooth/bluetooth.h>
> > #include <bluetooth/hci.h>
> > #include <bluetooth/hci_lib.h>
> > #include <bluetooth/l2cap.h>
> > #include <bluetooth/sdp.h>
> > #include <bluetooth/sdp_lib.h>
> > 
> > #include <netinet/in.h>
> > 
> > /* AVDTP structures */
> > 
> > /* packet components */
> > 
> > struct avdtp_header {
> > 	//uint8_t packet_type:2;
> > 	uint8_t message_type:2;
> > 	uint8_t packet_type:2;
> > 	uint8_t transaction_label:4;
> > 	uint8_t signal_id:6;
> > 	uint8_t rfa0:2;
> > } __attribute__ ((packed));
> > 
> > struct acp_seid_info {
> > 	uint8_t rfa0:1;
> > 	uint8_t inuse0:1;
> > 	uint8_t acp_seid:6;
> > 	uint8_t rfa2:3;
> > 	uint8_t tsep:1;
> > 	uint8_t media_type:4;
> > } __attribute__ ((packed));
> > 
> > struct sbc_codec_specific_elements {
> > 	// a2dp p. 20
> > 	uint8_t channel_mode:4;
> > 	uint8_t frequency:4;
> > 	uint8_t allocation_method:2;
> > 	uint8_t subbands:2;
> > 	uint8_t block_length:4;
> > 	uint8_t min_bitpool;
> > 	uint8_t max_bitpool;
> > } __attribute__ ((packed));
> > 
> > #define MAX_ADDITIONAL_CODEC 0	//Right now only
> SBC is supported
> > #define MAX_ADDITIONAL_CODEC_OCTETS
> (MAX_ADDITIONAL_CODEC*sizeof(struct acp_seid_info))
> > 
> > /* packets */
> > 
> > struct sepd_req {
> > 	struct avdtp_header header;
> > } __attribute__ ((packed));
> > 
> > struct sepd_resp {
> > 	struct avdtp_header header;
> > 	struct acp_seid_info infos[1 +
> MAX_ADDITIONAL_CODEC];
> > } __attribute__ ((packed));
> > 
> > struct getcap_req {
> > 	struct avdtp_header header;
> > 	uint8_t rfa1:2;
> > 	uint8_t acp_seid:6;
> > } __attribute__ ((packed));
> > 
> > struct getcap_resp {
> > 	struct avdtp_header header;
> > 
> > 	uint8_t serv_cap;
> > 	uint8_t serv_cap_len;
> > 
> > 	uint8_t cap_type;
> > 	uint8_t length;
> > 	uint8_t media_type;
> > 	uint8_t media_codec_type;
> > 
> > 	struct sbc_codec_specific_elements sbc_elements;
> > 
> > } __attribute__ ((packed));
> > 
> > struct set_config {
> > 	struct avdtp_header header;
> > 
> > 	uint8_t rfa0:2;
> > 	uint8_t acp_seid:6;
> > 	uint8_t rfa1:2;
> > 	uint8_t int_seid:6;
> > 
> > 	uint8_t serv_cap;
> > 	uint8_t serv_cap_len;
> > 
> > 	uint8_t cap_type;
> > 	uint8_t length;
> > 	uint8_t media_type;
> > 	uint8_t media_codec_type;
> > 
> > 	struct sbc_codec_specific_elements sbc_elements;
> > 
> > } __attribute__ ((packed));
> 
=== message truncated === 

________________________________________________________________________
Yahoo! India Matrimony: Find your life partner online
Go to: http://yahoo.shaadi.com/india-matrimony


-------------------------------------------------------
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
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Bluez-devel] A2DP sink code finally
@ 2005-04-26 12:29 Mayank Batra
  0 siblings, 0 replies; 15+ messages in thread
From: Mayank Batra @ 2005-04-26 12:29 UTC (permalink / raw)
  To: bluez-devel

Brad,
 
> I suspect the distortion could be happening if the
> read() gets an sbc 
> frame fragment at the end... it would be discarded
> by the decoder if 
> that happens.
 
Well, I did printf()s whenever each sbc frame was
being deoded and it turned out that the no. of sbc
frames being decoded from the a2dp packet were EXACTLY
the no. present in the packet.

If mtu is 676 then there are approx 8 sbc frames, and
exactly 8 were getting decoded.
Also, the sound produced(whatever that was being
produced) was similar to the original music.

Just the fact that it is not exactly same.
It means two things:

1) Either we are not configuring the sound card
properly.

2) Or our SBC decoder is not working properly. Henryk,
what do you say about this possibility. Is it possible
?

Mayank

Mayank Batra


Whether you think you can or whether you think you can't, you are right. -Henry Ford.

________________________________________________________________________
Yahoo! India Matrimony: Find your life partner online
Go to: http://yahoo.shaadi.com/india-matrimony


-------------------------------------------------------
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
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Bluez-devel] A2DP sink code finally
@ 2005-04-26 12:34 Mayank Batra
  2005-04-27 16:27 ` Brad Midgley
  2005-05-01 15:16 ` Henryk Plötz
  0 siblings, 2 replies; 15+ messages in thread
From: Mayank Batra @ 2005-04-26 12:34 UTC (permalink / raw)
  To: bluez-devel

Henryk,

> Hmm, how do I test that? I can't seem to get my
> audio dongle to connect.
> Is there anything else I've got to do apart from 
> | hciconfig hci0 class 0x200404

Don't know whether this is required...?

> | sdptool add A2SNK
> | ./a2snk
> ?

I think this is sufficient.

Are u sure that the a2play code is correct?
Because I've used exactly this code to connect with
BlueSoleil, and the connection takes place very well.

Otherwise, BlueSoleil is a very clumsy sw and it sends
disconnect even if we skip or mix a step.
So, this means that maybe u r making some mistake.

Mayank

________________________________________________________________________
Yahoo! India Matrimony: Find your life partner online
Go to: http://yahoo.shaadi.com/india-matrimony


-------------------------------------------------------
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
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Bluez-devel] A2DP sink code finally
@ 2005-04-26 12:35 Mayank Batra
  2005-04-26 13:10 ` Brad Midgley
  0 siblings, 1 reply; 15+ messages in thread
From: Mayank Batra @ 2005-04-26 12:35 UTC (permalink / raw)
  To: bluez-devel

Brad,

> I'm not sure anyone has used the dongle yet.
> (Mayank?)
> 

Yes I have definitely used dongles (Simple USB Dongle,
I don't know what does an audio dongle mean. I hope
there is not much of a difference)

Mayank

Mayank Batra


Whether you think you can or whether you think you can't, you are right. -Henry Ford.

________________________________________________________________________
Yahoo! India Matrimony: Find your life partner online
Go to: http://yahoo.shaadi.com/india-matrimony


-------------------------------------------------------
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
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Bluez-devel] A2DP sink code finally
  2005-04-26 12:35 [Bluez-devel] A2DP sink code finally Mayank Batra
@ 2005-04-26 13:10 ` Brad Midgley
  2005-04-26 15:50   ` Marcel Holtmann
  0 siblings, 1 reply; 15+ messages in thread
From: Brad Midgley @ 2005-04-26 13:10 UTC (permalink / raw)
  To: bluez-devel

Mayank,

The term is overloaded. Henryk is trying to use the little box from 
bluetake that runs as an a2dp source. It only has one button on it, so 
it has to be able to find the sink using only sdp.

Brad

Mayank Batra wrote:
> Brad,
> 
> 
>>I'm not sure anyone has used the dongle yet.
>>(Mayank?)
>>
> 
> 
> Yes I have definitely used dongles (Simple USB Dongle,
> I don't know what does an audio dongle mean. I hope
> there is not much of a difference)
> 
> Mayank
> 
> Mayank Batra
> 
> 
> Whether you think you can or whether you think you can't, you are right. -Henry Ford.
> 
> ________________________________________________________________________
> Yahoo! India Matrimony: Find your life partner online
> Go to: http://yahoo.shaadi.com/india-matrimony
> 
> 
> -------------------------------------------------------
> 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
> Bluez-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/bluez-devel


-------------------------------------------------------
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
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Bluez-devel] A2DP sink code finally
  2005-04-26 13:10 ` Brad Midgley
@ 2005-04-26 15:50   ` Marcel Holtmann
  2005-04-27 19:08     ` Brad Midgley
  0 siblings, 1 reply; 15+ messages in thread
From: Marcel Holtmann @ 2005-04-26 15:50 UTC (permalink / raw)
  To: bluez-devel

Hi Brad,

> The term is overloaded. Henryk is trying to use the little box from 
> bluetake that runs as an a2dp source. It only has one button on it, so 
> it has to be able to find the sink using only sdp.

I tried the box from my Aiptek headphone once and it was not really
working, because I think all GCT devices expect a role switch at some
time.

Regards

Marcel




-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start!  http://www.idcswdc.com/cgi-bin/survey?id=105hix
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Bluez-devel] A2DP sink code finally
  2005-04-26 12:34 Mayank Batra
@ 2005-04-27 16:27 ` Brad Midgley
  2005-05-01 15:16 ` Henryk Plötz
  1 sibling, 0 replies; 15+ messages in thread
From: Brad Midgley @ 2005-04-27 16:27 UTC (permalink / raw)
  To: bluez-devel

Guys,

I updated the docs to reflect the new a2play usage and basic a2snk 
operation.

I think the best effort spent on a2play now would be to:

  - use the real-time clock for timing
  - optionally open and perform ioctls on /dev/dsp to operate directly on it

Both of these should make live streaming tighter.

Timing improvements include both inserting delays and throwing out data 
when the link doesn't accept it fast enough (or to take up delay), but 
you only need the latter for live streaming.

Brad


-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start!  http://www.idcswdc.com/cgi-bin/survey?id=105hix
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Bluez-devel] A2DP sink code finally
  2005-04-26 15:50   ` Marcel Holtmann
@ 2005-04-27 19:08     ` Brad Midgley
  0 siblings, 0 replies; 15+ messages in thread
From: Brad Midgley @ 2005-04-27 19:08 UTC (permalink / raw)
  To: bluez-devel

Marcel

>>The term is overloaded. Henryk is trying to use the little box from 
>>bluetake that runs as an a2dp source. It only has one button on it, so 
>>it has to be able to find the sink using only sdp.
> 
> 
> I tried the box from my Aiptek headphone once and it was not really
> working, because I think all GCT devices expect a role switch at some
> time.

Forgive my ignorance, but is a role switch something we have to 
accommodate in our code, like in a2snk.c or is it just in hcid.conf?

Brad


-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start!  http://www.idcswdc.com/cgi-bin/survey?id=105hix
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Bluez-devel] A2DP sink code finally
  2005-04-26 12:34 Mayank Batra
  2005-04-27 16:27 ` Brad Midgley
@ 2005-05-01 15:16 ` Henryk Plötz
  2005-05-03 13:23   ` Mayank Batra
  1 sibling, 1 reply; 15+ messages in thread
From: Henryk Plötz @ 2005-05-01 15:16 UTC (permalink / raw)
  To: bluez-devel

[-- Attachment #1: Type: text/plain, Size: 835 bytes --]

Moin,

Am Tue, 26 Apr 2005 13:34:12 +0100 (BST) schrieb Mayank Batra:

> > Hmm, how do I test that? I can't seem to get my
> > audio dongle to connect.

Ah, stupid me. I forgot to enable pairing mode on the audio dongle.

> > Is there anything else I've got to do apart from 
> > | hciconfig hci0 class 0x200404
> 
> Don't know whether this is required...?

Seems so. After doing

> > | sdptool add A2SNK
> > | ./a2snk

_and_ enabling pairing on the audio dongle nothing happened. But as soon
as I changed my device class the audio dongle started a connection. Now
a2snk stalls after "Sent Stream End Point Discovery Response".

-- 
Henryk Plötz
Grüße aus Berlin
~~~~~~~ Un-CDs, nein danke! http://www.heise.de/ct/cd-register/ ~~~~~~~
~ Help Microsoft fight software piracy: Give Linux to a friend today! ~

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Bluez-devel] A2DP sink code finally
  2005-05-01 15:16 ` Henryk Plötz
@ 2005-05-03 13:23   ` Mayank Batra
  0 siblings, 0 replies; 15+ messages in thread
From: Mayank Batra @ 2005-05-03 13:23 UTC (permalink / raw)
  To: bluez-devel

Henryk,

> Ah, stupid me. I forgot to enable pairing mode on
> the audio dongle.

Never mind. better late than never.

> > > Is there anything else I've got to do apart from
> 
> > > | hciconfig hci0 class 0x200404
> > 
> > Don't know whether this is required...?
> 
> Seems so. After doing
> 
> > > | sdptool add A2SNK
> > > | ./a2snk
> 
> _and_ enabling pairing on the audio dongle nothing
> happened. But as soon
> as I changed my device class the audio dongle
> started a connection. Now
> a2snk stalls after "Sent Stream End Point Discovery
> Response".


I suggest you scan the hcidump and see whether  avdtp
commands are being exchanged properly. This was the
problem i faced while coding the a2recv. Please refer
to my query mail in which i raised the question of
exchanging the position of packet_type and
message_type.

I interchanged them and it started working.

If i don't, then the sink sends a cont command which
the source rejects and sends a disconnection.

Also, do send me a copy of the dump.

Regards,

Mayank

________________________________________________________________________
Yahoo! India Matrimony: Find your life partner online
Go to: http://yahoo.shaadi.com/india-matrimony


-------------------------------------------------------
This SF.Net email is sponsored by: NEC IT Guy Games.
Get your fingers limbered up and give it your best shot. 4 great events, 4
opportunities to win big! Highest score wins.NEC IT Guy Games. Play to
win an NEC 61 plasma display. Visit http://www.necitguy.com/?r=20
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2005-05-03 13:23 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-04-26 12:35 [Bluez-devel] A2DP sink code finally Mayank Batra
2005-04-26 13:10 ` Brad Midgley
2005-04-26 15:50   ` Marcel Holtmann
2005-04-27 19:08     ` Brad Midgley
  -- strict thread matches above, loose matches on Subject: below --
2005-04-26 12:34 Mayank Batra
2005-04-27 16:27 ` Brad Midgley
2005-05-01 15:16 ` Henryk Plötz
2005-05-03 13:23   ` Mayank Batra
2005-04-26 12:29 Mayank Batra
2005-04-24 15:09 Mayank Batra
2005-04-25  3:24 ` Brad Midgley
2005-04-25  3:58   ` Brad Midgley
2005-04-25  6:08   ` Henryk Plötz
2005-04-25 14:40     ` Brad Midgley
2005-04-26 12:23   ` Mayank Batra

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.