Alsa-Devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
To: clemens@ladisch.de, tiwai@suse.de, perex@perex.cz
Cc: alsa-devel@alsa-project.org,
	linux1394-devel@lists.sourceforge.net, ffado-devel@lists.sf.net
Subject: Sample program for hwdep interface
Date: Fri, 20 Dec 2013 23:46:15 +0900	[thread overview]
Message-ID: <52B45837.2080804@sakamocchi.jp> (raw)
In-Reply-To: <1387545269-3875-1-git-send-email-o-takashi@sakamocchi.jp>

This is how to use hwdep interface for firewire devices.
I hope FFADO developers read this.

With hwdep interface, the program in user land can do:
1.get firewire node infomation
2.get notification when starting/stopping kernel streaming
3.lock/unlock kernel streaming

For jackd with FFADO backend, it's better to lock kernel streaming in 
advance. Then snd-bebob/snd-fireworks can't interrupt FFADO streaming.

And with snd-fireworks, the program can do:
4.transmit command of EFW transaction
5.receive response of EFW transaction

4/5 is my complete solution for ticket #360.
Make echo audiofire 8 and audiofire 12 work with recent firmwares
http://subversion.ffado.org/ticket/360

(I note 4 can be done via /dev/fw*. But I think 4 is easier.)

If someone works for snd-dice to support valid devices, it may be useful 
that the program get dice notification in the same way.
(I have a little knowledgement about Dice.)

I attach sample program (too rough...) to show how to use hwdep interface.


Regards,
Takashi Sakamoto


====
/* monitor.c: program to monitor the status of firewire sound devices */

#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <endian.h>
#include <time.h>
#include <sys/ioctl.h>
#include <sys/epoll.h>
#include <souund/firewire.h>

static struct snd_firewire_get_info hwdep_info;
bool try_lock;
bool fireworks = false;

static void print_event_lock(struct snd_firewire_event_lock_status *msg, 
int fd)
{
	printf("\nLock Status:\n");
	printf("Status:\t%s\n", msg->status ? "Locked" : "Unlocked" );

	if (try_lock) {
		if (ioctl(fd, SNDRV_FIREWIRE_IOCTL_LOCK) < 0)
			printf("lock failed\n");
		printf("lock success\n");
	}

	return;
}

static void print_event_dice(struct snd_firewire_event_dice_notification 
*msg)
{
	printf("\nDice Norification:\n");
	printf("Notification: 0x%x\n", msg->notification);
	return;
}

static void print_event_efw(struct snd_firewire_event_efw_response *evt, 
int count)
{
	uint32_t *resp;
	struct snd_efw_transaction *t;
	unsigned int i, index, length, params;

	resp = evt->response;
	count /= 4;

	index = 0;
	while (count > 0) {
		t = (struct snd_efw_transaction *)resp;
		length = be32toh(t->length);

		printf("\nEFW Response %d:\n", index++);
		printf("Length:\t\t%d\n", be32toh(t->length));
		printf("Version:\t%d\n", be32toh(t->version));
		printf("Seqnum:\t\t%d\n", be32toh(t->seqnum));
		printf("Category:\t%d\n", be32toh(t->category));
		printf("Command:\t%d\n", be32toh(t->command));
		printf("Status:\t\t%d\n", be32toh(t->status));

		params = length - sizeof(struct snd_efw_transaction) / sizeof(uint32_t);
		if (params > 0)
			for (i = 0; i < params; i++)
				printf("params[%d]:\t%08X\n", i, be32toh(t->params[i]));

		resp += length;
		count -= length * sizeof(uint32_t);
	}
}

static int read_event(int fd)
{
	int count;
	char buf[1024] = {0};
	struct snd_firewire_event_common *event;

	count = read(fd, buf, 1024);
	if (count < 0)
		return -1;

	event = (struct snd_firewire_event_common *)buf;
	if (event->type == SNDRV_FIREWIRE_EVENT_LOCK_STATUS)
		print_event_lock((struct snd_firewire_event_lock_status *)buf, fd);
	else if (event->type == SNDRV_FIREWIRE_EVENT_DICE_NOTIFICATION)
		print_event_dice((struct snd_firewire_event_dice_notification *)buf);
	else if (event->type == SNDRV_FIREWIRE_EVENT_EFW_RESPONSE)
		print_event_efw((struct snd_firewire_event_efw_response *)buf, count);

	return 0;
}

static int write_event(int fd)
{
	int count;
	struct snd_efw_transaction *t;
	char buf[1024] = {0};

	t = (struct snd_efw_transaction *)buf;
	t->length	= htobe32(6);
	t->version	= htobe32(1);
	t->seqnum	= htobe32(0);
	t->category	= htobe32(3);
	t->command	= htobe32(5);
	t->status	= htobe32(0);

	count = write(fd, buf, sizeof(struct snd_efw_transaction));
	if (count < 0)
		printf("err: %d\n", count);

	return count;
}

#define EVENTS 10
time_t cmd_deffer = 0;
static int main_loop(int fd)
{
	int epfd, count, i, err;
	time_t now;
	struct epoll_event ev, events[EVENTS];

	epfd = epoll_create(EVENTS);
	if (epfd < 0) {
		printf("error: %s\n", strerror(errno));
		err = errno;
		goto end;
	}

	memset(&ev, 0, sizeof(struct epoll_event));
	ev.events = EPOLLIN;
	ev.data.fd = fd;

	if (fireworks)
		ev.events |= EPOLLOUT;

	if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0)
		return errno;

	while (1) {
		count = epoll_wait(epfd, events, EVENTS, 200);
		if (count == 0)
			continue;
		else if (count < 0) {
			err = errno;
			break;
		}

		for (i = 0; i < count; i++) {
			if (events[i].events & EPOLLOUT) {
				if (time(&now) < 0)
					break;
				if (now > cmd_deffer) {
					if (write_event(events[i].data.fd) < 0) {
						err = errno;
						break;
					}
					cmd_deffer = now + 3;
				}
			}
			if (events[i].events & EPOLLIN) {
				if (read_event(events[i].data.fd) < 0) {
					err = errno;
					break;
				}
			}
		}
	}
end:
	close(epfd);
	return err;
}

int main(int argc, void *argv[])
{
	int fd, count, err;
	char buf[1024] = {};
	struct snd_firewire_event_common *event;

	if (argc > 2)
		try_lock = true;

	fd = open(argv[1], O_RDWR);
	if (fd < 0) {
		printf("fail to open: %s\n", (char *)argv[1]);
		return 1;
	}

	if (ioctl(fd, SNDRV_FIREWIRE_IOCTL_GET_INFO, &hwdep_info) < 0) {
		printf("error: %s\n", strerror(errno));
		return 1;
	}

	printf("Information of Firewire Sound Device\n");
	printf("type: %d\n", hwdep_info.type);
	printf("card: %d\n", hwdep_info.card);
	printf("GUID: 0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
	       hwdep_info.guid[0], hwdep_info.guid[1], hwdep_info.guid[2],
	       hwdep_info.guid[3], hwdep_info.guid[4], hwdep_info.guid[5],
	       hwdep_info.guid[6], hwdep_info.guid[7] );
	printf("Name: %s\n\n", hwdep_info.device_name);

	if (hwdep_info.type == SNDRV_FIREWIRE_TYPE_FIREWORKS)
		fireworks = true;

	err = main_loop(fd);
	close(fd);
	return err;
}

  parent reply	other threads:[~2013-12-20 14:46 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-20 13:13 [RFC v2][PATCH 00/38] Enhancement for support of some firewire devices Takashi Sakamoto
2013-12-20 13:13 ` [PATCH 01/38] firewire-lib: Rename functions, structure, member for AMDTP Takashi Sakamoto
2013-12-20 13:13 ` [PATCH 02/38] firewire-lib: Add macros instead of fixed value " Takashi Sakamoto
2013-12-20 13:13 ` [PATCH 03/38] firewire-lib: Add 'direction' member to 'amdtp_stream' structure Takashi Sakamoto
2013-12-20 13:13 ` [PATCH 04/38] firewire-lib: Split some codes into functions to reuse for both streams Takashi Sakamoto
2013-12-20 13:13 ` [PATCH 05/38] firewire-lib: Add support for AMDTP in-stream and PCM capture Takashi Sakamoto
2013-12-20 13:13 ` [PATCH 06/38] firewire-lib: Add support for MIDI capture/playback Takashi Sakamoto
2013-12-20 13:13 ` [PATCH 07/38] firewire-lib: Give syt value as parameter to handle_out_packet() Takashi Sakamoto
2013-12-20 13:13 ` [PATCH 08/38] firewire-lib: Add support for duplex streams synchronization in blocking mode Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 09/38] firewire-lib: Add sort function for transmitted packet Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 10/38] firewire-lib: Add transfer delay to synchronized duplex streams Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 11/38] firewire-lib: Add support for channel mapping Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 12/38] firewire-lib: Rename macros, variables and functions for CMP Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 13/38] firewire-lib: Add 'direction' member to 'cmp_connection' structure Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 14/38] firewire-lib: Add handling output connection by CMP Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 15/38] firewire-lib: Add a new function to check others' connection Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 16/38] firewire-lib: Add some AV/C general commands Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 17/38] firewire-lib: Add quirks for Fireworks Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 18/38] fireworks: Add skelton for Fireworks based devices Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 19/38] fireworks: Add transaction and some commands Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 20/38] fireworks: Add connection and stream management Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 21/38] fireworks: Add proc interface for debugging purpose Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 22/38] fireworks: Add MIDI interface Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 23/38] fireworks: Add PCM interface Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 24/38] fireworks: Add hwdep interface Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 25/38] fireworks: Add command/response functionality into " Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 26/38] bebob: Add skelton for BeBoB based devices Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 27/38] bebob: Add commands and connections/streams management Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 28/38] bebob: Add proc interface for debugging purpose Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 29/38] bebob: Add MIDI interface Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 30/38] bebob: Add PCM interface Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 31/38] bebob: Add hwdep interface Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 32/38] bebob: Prepare for device specific operations Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 33/38] bebob: Add support for Terratec PHASE, EWS series and Aureon Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 34/38] bebob: Add support for Yamaha GO series Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 35/38] bebob: Add support for Focusrite Saffire/SaffirePro series Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 36/38] bebob: Add support for M-Audio usual Firewire series Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 37/38] bebob: Add support for M-Audio special " Takashi Sakamoto
2013-12-20 13:14 ` [PATCH 38/38] bebob: Send a cue to load firmware for M-Audio " Takashi Sakamoto
2013-12-20 14:46 ` Takashi Sakamoto [this message]
2013-12-21 10:11   ` [FFADO-devel] Sample program for hwdep interface Jonathan Woithe
2013-12-21 13:48     ` Clemens Ladisch
2014-01-05 11:18     ` Takashi Sakamoto
2014-01-12 13:22       ` Stefan Richter
2014-01-12 15:26         ` Takashi Sakamoto
2014-02-02 13:58           ` Echo Fireworks control protocol (was Re: Sample program for hwdep interface) Stefan Richter
2014-02-08 13:22             ` Takashi Sakamoto
2014-02-09 11:42               ` Jonathan Woithe
2014-02-09 14:51                 ` Stefan Richter
2014-02-09 16:53                   ` Takashi Sakamoto
2014-02-09 22:29                   ` Jonathan Woithe

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=52B45837.2080804@sakamocchi.jp \
    --to=o-takashi@sakamocchi.jp \
    --cc=alsa-devel@alsa-project.org \
    --cc=clemens@ladisch.de \
    --cc=ffado-devel@lists.sf.net \
    --cc=linux1394-devel@lists.sourceforge.net \
    --cc=perex@perex.cz \
    --cc=tiwai@suse.de \
    /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