public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
From: Fabien Chevalier <fabchevalier@free.fr>
To: BlueZ development <bluez-devel@lists.sourceforge.net>,
	Brad Midgley <bmidgley@xmission.com>,
	Johan Hedberg <johan.hedberg@nokia.com>,
	thiagossantos@gmail.com, Marcel Holtmann <marcel@holtmann.org>,
	Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Subject: Concept implementation: (still to be named) newipc.h
Date: Tue, 09 Oct 2007 23:33:06 +0200	[thread overview]
Message-ID: <470BF392.9050409@free.fr> (raw)

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

All,

Please find attached a conceptual new API between the audio service and 
whatever audio framework we have (ALSA, GStreamer, PulseAudio, or 
whatever). :-)

This new API would be defined under LGPL, so that guys like me can use 
it for some in house closed source projects( Luiz, and Johan,
i hope that's OK with you :-) ).

The principles of the API are the following:
  - define a set of messages (that would be the functions in 
traditionnal C programming)
  - define a set of structs, *one per message* (that would be the
list of arguments in traditionnal C programming).
  - define a reduced set of a few helper functions to bootstrap the 
message exchange process, as well as to retrieve the data fd through 
ancilliary data.

The usage of the API should be relatively straightforward : you would 
use bz_audio_service_open() to retrieve the file descriptor, and then 
integrated it in your main loop or whatever.

Then you would read fixed size data chunks that you would cast to 
t_bz_audio_msg_header to retrieve the message type. Once you have the 
message type, you would cast again the result to a structure that 
matches the message name, and obtain the list of parameters that are 
relevant for this message.

I didn't want to bring more features in the API as otherwise we would 
start to implement toolkit-dependant behaviours (such as need a 
mainloop, or a need for GLIB, or ...)

I think this API is a lot easier to maintain in the long term that what 
we have today, where structure are shared between messages, and some 
messages have more that one data structure. :-)

If we can reach an agreement quite rapidly (that would mean today :-)), 
then i could start implementing it right away and hopefully have a 
mostly working implementation on sunday night.

As always, comments are welcomed !

Cheers,

Fabien


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: newipc.h --]
[-- Type: text/x-chdr; name="newipc.h", Size: 7702 bytes --]

/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2004-2007  Marcel Holtmann <marcel@holtmann.org>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

/*
  Message sequence chart of streaming sequence for A2DP transport
  
  Audio daemon                       User
                             on snd_pcm_open
                 <--BZ_GETCAPABILITIES_REQ

  BZ_GETCAPABILITIES_RSP-->

                        on snd_pcm_hw_params
                <--BZ_SETCONFIGURATION_REQ

  BZ_SETCONFIGURATION_RSP-->

			on snd_pcm_prepare
                <--BZ_STREAMSTART_REQ

  <Moves to streaming state>
  BZ_STREAMSTART_RSP-->

  BZ_DATAFD_IND -->

                          <  streams data >
                             ..........

               on snd_pcm_drop/snd_pcm_drain

                <--BZ_STREAMSTOP_REQ

  <Moves to open state>
  BZ_STREAMSTOP_RSP-->
    
			on IPC close or appl crash 
  <Moves to idle>
			
 */

#ifndef NEWIPC_H

#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>

#define BZ_AUDIO_IPC_MTU   128
#define BZ_IPC_SOCKET_NAME "\0/org/bluez/audio"

#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX 108
#endif

/* Generic message header definition */
typedef struct {
	uint8_t msg_type;
} __attribute__ ((packed)) t_bz_audio_msg_header;

/* Messages list */
#define BZ_GETCAPABILITIES_REQ		0
#define BZ_GETCAPABILITIES_RSP		1

#define BZ_SETCONFIGURATION_REQ		2
#define BZ_SETCONFIGURATION_RSP		3

#define BZ_STREAMSTART_REQ		4
#define BZ_STREAMSTART_RSP		5

#define BZ_STREAMSTOP_REQ		6
#define BZ_STREAMSTOP_RSP		7

#define BZ_CONTROL_REQ			8
#define BZ_CONTROL_RSP			9
#define BZ_CONTROL_IND		       10

#define BZ_DATAFD_IND		       11

/* BZ_CAPABILITIES_REQ */

#define BZ_CAPABILITIES_REQ_TRANSPORT_A2DP	0
#define BZ_CAPABILITIES_REQ_TRANSPORT_SCO	1
#define BZ_CAPABILITIES_REQ_TRANSPORT_ANY	2

struct bz_capabilites_req {
	t_bz_audio_msg_header h;
 	uint8_t transport;
} __attribute__ ((packed));

/* BZ_CAPABILITIES_RSP */

/**
 * SBC Codec parameters as per A2DP profile 1.0 § 4.3
 */

#define BZ_A2DP_SAMPLING_FREQ_16000		(1 << 3)
#define BZ_A2DP_SAMPLING_FREQ_32000		(1 << 2)
#define BZ_A2DP_SAMPLING_FREQ_44100		(1 << 1)
#define BZ_A2DP_SAMPLING_FREQ_48000		1

#define BZ_A2DP_CHANNEL_MODE_MONO		(1 << 3)
#define BZ_A2DP_CHANNEL_MODE_DUAL_CHANNEL	(1 << 2)
#define BZ_A2DP_CHANNEL_MODE_STEREO		(1 << 1)
#define BZ_A2DP_CHANNEL_MODE_JOINT_STEREO	1

#define BZ_A2DP_BLOCK_LENGTH_4			(1 << 3)
#define BZ_A2DP_BLOCK_LENGTH_8			(1 << 2)
#define BZ_A2DP_BLOCK_LENGTH_12			(1 << 1)
#define BZ_A2DP_BLOCK_LENGTH_16			1

#define BZ_A2DP_SUBBANDS_4			(1 << 1)
#define BZ_A2DP_SUBBANDS_8			1

#define BZ_A2DP_ALLOCATION_SNR			(1 << 1)
#define BZ_A2DP_ALLOCATION_LOUDNESS		1

typedef struct {
	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)) t_SBC_capabilities ;

/* To be defined */
typedef struct {
} __attribute__ ((packed)) t_MPEG_capabilities;

struct bz_capabilites_rsp {
	t_bz_audio_msg_header	h;
	uint8_t			posix_errno;
	uint8_t			transport;          /* Selected transport */
	uint8_t			pkt_len;            /* Max length that transport supports */
	t_SBC_capabilities	sbc_capabilities;   /* A2DP only */
	t_MPEG_capabilities	mpeg_capabilities;  /* A2DP only */
	uint16_t		sampling_rate;	    /* SCO only */
} __attribute__ ((packed));

/* BZ_CONFIGURATION_REQ */
struct bz_configuration_req {
	t_bz_audio_msg_header	h;
	t_SBC_capabilities 	sbc_capabilities;   /* A2DP only - only one of this field
						   and next one must be filled */
	t_MPEG_capabilities	mpeg_capabilities;  /* A2DP only */
} __attribute__ ((packed));

/* BZ_CONFIGURATION_RSP */
struct bz_configuration_rsp {
	t_bz_audio_msg_header 	h;
	uint8_t 		posix_errno;
} __attribute__ ((packed));

/* BZ_STREAMSTART_REQ */
#define BZ_STREAM_ACCESS_READ		0
#define BZ_STREAM_ACCESS_WRITE		1
#define BZ_STREAM_ACCESS_READWRITE	2
struct bz_streamstart_req {
	t_bz_audio_msg_header 	h;
	uint8_t			stream_access;
} __attribute__ ((packed));

/* BZ_STREAMSTART_RSP */
struct bz_streamstart_rsp {
	t_bz_audio_msg_header 	h;
	uint8_t 		posix_errno;
} __attribute__ ((packed));

/* BZ_DATAFD_IND */
/* This message is followed by one byte of data containing the stream data fd
   as ancilliary data */
struct bz_datafd_ind {
	t_bz_audio_msg_header 	h;
} __attribute__ ((packed));


/* BZ_CONTROL_REQ */

#define BZ_CONTROL_KEY_POWER			0x40
#define BZ_CONTROL_KEY_VOL_UP			0x41
#define BZ_CONTROL_KEY_VOL_DOWN			0x42
#define BZ_CONTROL_KEY_MUTE			0x43
#define BZ_CONTROL_KEY_PLAY			0x44
#define BZ_CONTROL_KEY_STOP			0x45
#define BZ_CONTROL_KEY_PAUSE			0x46
#define BZ_CONTROL_KEY_RECORD			0x47
#define BZ_CONTROL_KEY_REWIND			0x48
#define BZ_CONTROL_KEY_FAST_FORWARD		0x49
#define BZ_CONTROL_KEY_EJECT			0x4A
#define BZ_CONTROL_KEY_FORWARD			0x4B
#define BZ_CONTROL_KEY_BACKWARD			0x4C

struct bz_control_req {
	t_bz_audio_msg_header 	h;
	uint8_t 		mode;		/* Control Mode */
	uint8_t 		key;		/* Control Key */
} __attribute__ ((packed));

/* BZ_CONTROL_RSP */
struct bz_volume_rsp {
	t_bz_audio_msg_header 	h;
	uint8_t 		posix_errno;
	uint8_t 		mode;		/* Control Mode */
	uint8_t 		key;		/* Control Key */
} __attribute__ ((packed));

/* BZ_CONTROL_IND */
struct bz_volume_ind {
	t_bz_audio_msg_header 	h;
	uint8_t 		mode;		/* Control Mode */
	uint8_t 		key;		/* Control Key */
} __attribute__ ((packed));

/* Function definitions */

static inline int bz_audio_service_open()
{
	int sk;
	int err;
	struct sockaddr_un addr = {
		AF_UNIX, "\0/org/bluez/audio"
	};

	sk = socket(PF_LOCAL, SOCK_STREAM, 0);
	if (sk < 0) {
		err = errno;
		fprintf(stderr, "%s: Cannot open socket: %s (%d)\n", __FUNCTION__, strerror(err), err);
		errno = err;
		return -1;
	}

	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
		err = errno;
		fprintf(stderr, "%s: Connection fail: %s (%d)\n", __FUNCTION__, strerror(err), err);
		close(sk);
		errno = err;
		return -1;
	}
}

static inline int bz_audio_service_close(int sk)
{
	return close(sk);
}

static inline int bz_audio_service_get_data_fd(int sk)
{
	char cmsg_b[CMSG_SPACE(sizeof(int))], m;
	int err, ret;
	struct iovec iov = { &m, sizeof(m) };
	struct msghdr msgh;
	struct cmsghdr *cmsg;

	memset(&msgh, 0, sizeof(msgh));
	msgh.msg_iov = &iov;
	msgh.msg_iovlen = 1;
	msgh.msg_control = &cmsg_b;
	msgh.msg_controllen = CMSG_LEN(sizeof(int));

	ret = recvmsg(sk, &msgh, 0);
	if (ret < 0) {
		err = errno;
		fprintf(stderr, "%s: Unable to receive fd: %s (%d)\n", __FUNCTION__, strerror(err), err);
		errno = err;
		return -1;
	}

	/* Receive auxiliary data in msgh */
	for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
			cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
		if (cmsg->cmsg_level == SOL_SOCKET
				&& cmsg->cmsg_type == SCM_RIGHTS) {
			return (*(int *) CMSG_DATA(cmsg));
		}
	}

	errno = EINVAL;
	return -1;
}

#endif /* NEWIPC_H */

             reply	other threads:[~2007-10-09 21:33 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-10-09 21:33 Fabien Chevalier [this message]
2007-10-11 11:47 ` Concept implementation: (still to be named) newipc.h Fabien Chevalier
2007-10-11 12:25   ` [Bluez-devel] Concept implementation: (still to be named)newipc.h Niels v/d Spek

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=470BF392.9050409@free.fr \
    --to=fabchevalier@free.fr \
    --cc=bluez-devel@lists.sourceforge.net \
    --cc=bmidgley@xmission.com \
    --cc=johan.hedberg@nokia.com \
    --cc=luiz.dentz@gmail.com \
    --cc=marcel@holtmann.org \
    --cc=thiagossantos@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox