Index: /tags/release_0_0_6/libfreebob/config.h.in =================================================================== --- /tags/release_0_0_6/libfreebob/config.h.in (revision 155) +++ /tags/release_0_0_6/libfreebob/config.h.in (revision 155) @@ -0,0 +1,82 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Freebob major version */ +#undef FREEBOB_MAJOR_VERSION + +/* Freebob micro version */ +#undef FREEBOB_MICRO_VERSION + +/* Freebob minor version */ +#undef FREEBOB_MINOR_VERSION + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#undef HAVE_LIBPTHREAD + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `unsigned' if does not define. */ +#undef size_t + +/* Define to empty if the keyword `volatile' does not work. Warning: valid + code using `volatile' can become incorrect without. Disable with care. */ +#undef volatile Index: /tags/release_0_0_6/libfreebob/libfreebob.pc.in =================================================================== --- /tags/release_0_0_6/libfreebob/libfreebob.pc.in (revision 156) +++ /tags/release_0_0_6/libfreebob/libfreebob.pc.in (revision 156) @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libfreebob +Description: FreeBob +Version: @VERSION@ +Libs: -L${libdir} -lfreebob +Cflags: -I${includedir} Index: /tags/release_0_0_6/libfreebob/tests/test-freebob.c =================================================================== --- /tags/release_0_0_6/libfreebob/tests/test-freebob.c (revision 153) +++ /tags/release_0_0_6/libfreebob/tests/test-freebob.c (revision 153) @@ -0,0 +1,398 @@ +/* test-freebob.c + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include + +#include "libfreebob/freebob.h" + +#include +#include +#include +#include + +const char *argp_program_version = PACKAGE_STRING; +const char *argp_program_bug_address = PACKAGE_BUGREPORT; + +// Program documentation. +static char doc[] = "FreeBob -- a driver for BeBob devices (test application)\n\n" + "OPERATION: discover\n" + " setsamplerate\n" + " xmldump\n" + " testmultidevicediscovery\n" + " streamformats\n"; + +// A description of the arguments we accept. +static char args_doc[] = "OPERATION"; + +struct arguments +{ + short silent; + short verbose; + int port; + int node_id; + int node_id_set; + char* args[2]; +}; + +// The options we understand. +static struct argp_option options[] = { + {"verbose", 'v', 0, 0, "Produce verbose output" }, + {"quiet", 'q', 0, 0, "Don't produce any output" }, + {"silent", 's', 0, OPTION_ALIAS }, + {"node", 'n', "id", 0, "Node to use" }, + {"port", 'p', "nr", 0, "IEEE1394 Port to use" }, + { 0 } +}; + +//------------------------------------------------------------- + +// Parse a single option. +static error_t +parse_opt( int key, char* arg, struct argp_state* state ) +{ + // Get the input argument from `argp_parse', which we + // know is a pointer to our arguments structure. + struct arguments* arguments = ( struct arguments* ) state->input; + char* tail; + + switch (key) { + case 'q': case 's': + arguments->silent = 1; + break; + case 'v': + arguments->verbose = 1; + break; + case 'p': + if (arg) { + arguments->port = strtol( arg, &tail, 0 ); + if ( errno ) { + fprintf( stderr, "Could not parse 'port' argument\n" ); + return ARGP_ERR_UNKNOWN; + } + } else { + if ( errno ) { + fprintf( stderr, "Could not parse 'port' argumen\n" ); + return ARGP_ERR_UNKNOWN; + } + } + break; + case 'n': + if (arg) { + arguments->node_id = strtol( arg, &tail, 0 ); + if ( errno ) { + fprintf( stderr, "Could not parse 'node' argument\n" ); + return ARGP_ERR_UNKNOWN; + } + arguments->node_id_set=1; + } else { + if ( errno ) { + fprintf( stderr, "Could not parse 'node' argumen\n" ); + return ARGP_ERR_UNKNOWN; + } + } + break; + case ARGP_KEY_ARG: + if (state->arg_num >= 2) { + // Too many arguments. + argp_usage( state ); + } + arguments->args[state->arg_num] = arg; + break; + case ARGP_KEY_END: + if (state->arg_num < 1) { + // Not enough arguments. + argp_usage( state ); + } + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +// Our argp parser. +static struct argp argp = { options, parse_opt, args_doc, doc }; + +int +main( int argc, char **argv ) +{ + struct arguments arguments; + + // Default values. + arguments.silent = 0; + arguments.verbose = 0; + arguments.port = 0; + arguments.node_id = 0; + arguments.node_id_set = 0; // if we don't specify a node, discover all + arguments.args[0] = ""; + arguments.args[1] = ""; + + // Parse our arguments; every option seen by `parse_opt' will + // be reflected in `arguments'. + if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) { + fprintf( stderr, "Could not parse command line\n" ); + return -1; + } + + printf( "Using freebob library version: %s\n\n", freebob_get_version() ); + + if ( strcmp( arguments.args[0], "discover" ) == 0 ) { + freebob_handle_t fb_handle = freebob_new_handle( arguments.port ); + if ( !fb_handle ) { + fprintf( stderr, "Could not create freebob handle\n" ); + return -1; + } + + if ( freebob_discover_devices( fb_handle ) != 0 ) { + fprintf( stderr, "Could not discover devices\n" ); + freebob_destroy_handle( fb_handle ); + return -1; + } + + freebob_connection_info_t* test_info; + + if(arguments.node_id_set) { + printf(" port = %d, node_id = %d\n", arguments.port, arguments.node_id); + test_info = freebob_get_connection_info( fb_handle, + arguments.node_id, + 0 ); + freebob_print_connection_info( test_info ); + freebob_free_connection_info( test_info ); + + printf("\n"); + + test_info = freebob_get_connection_info( fb_handle, + arguments.node_id, + 1 ); + freebob_print_connection_info( test_info ); + freebob_free_connection_info( test_info ); + } else { + int i=0; + + int devices_on_bus = freebob_get_nb_devices_on_bus(fb_handle); + printf(" port = %d, devices_on_bus = %d\n", arguments.port, devices_on_bus); + + for(i=0;i + +using namespace std; + +//////////////////////////////////////////////// +// arg parsing +//////////////////////////////////////////////// +const char *argp_program_version = "test-extplugcmd 0.2"; +const char *argp_program_bug_address = ""; +static char doc[] = "test-extplugcmd -- tests some extended plug info commands on a BeBoB device"; +static char args_doc[] = "NODE_ID"; +static struct argp_option options[] = { + {"verbose", 'v', 0, 0, "Produce verbose output" }, + {"port", 'p', "PORT", 0, "Set port" }, + { 0 } +}; + +struct arguments +{ + arguments() + : verbose( false ) + , test( false ) + , port( 0 ) + { + args[0] = 0; + } + + char* args[1]; + bool verbose; + bool test; + int port; +} arguments; + +// Parse a single option. +static error_t +parse_opt( int key, char* arg, struct argp_state* state ) +{ + // Get the input argument from `argp_parse', which we + // know is a pointer to our arguments structure. + struct arguments* arguments = ( struct arguments* ) state->input; + + char* tail; + switch (key) { + case 'v': + arguments->verbose = true; + break; + case 't': + arguments->test = true; + break; + case 'p': + errno = 0; + arguments->port = strtol(arg, &tail, 0); + if (errno) { + perror("argument parsing failed:"); + return errno; + } + break; + case ARGP_KEY_ARG: + if (state->arg_num >= 1) { + // Too many arguments. + argp_usage (state); + } + arguments->args[state->arg_num] = arg; + break; + case ARGP_KEY_END: + if (state->arg_num < 1) { + // Not enough arguments. + argp_usage (state); + } + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static struct argp argp = { options, parse_opt, args_doc, doc }; + +//////////////////////////////////////// +// Application +//////////////////////////////////////// + +bool +doPlugType( Ieee1394Service& ieee1394service, int node_id ) +{ + ExtendedPlugInfoCmd extPlugInfoCmd( &ieee1394service ); + UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, 0 ); + extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input, + PlugAddress::ePAM_Unit, + unitPlugAddress ) ); + extPlugInfoCmd.setNodeId( node_id ); + extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status ); + extPlugInfoCmd.setVerbose( arguments.verbose ); + ExtendedPlugInfoInfoType extendedPlugInfoInfoType( ExtendedPlugInfoInfoType::eIT_PlugType ); + extendedPlugInfoInfoType.initialize(); + extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType ); + + if ( extPlugInfoCmd.fire() ) { + CoutSerializer se; + extPlugInfoCmd.serialize( se ); + } + + ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType(); + if ( infoType + && infoType->m_plugType ) + { + plug_type_t plugType = infoType->m_plugType->m_plugType; + + printf( "iso input plug %d is of type %d (%s)\n", + 0, + plugType, + extendedPlugInfoPlugTypeToString( plugType ) ); + } else { + fprintf( stderr, "Not plug name specific data found\n" ); + return false; + } + + return true; +} + + +bool +doPlugName( Ieee1394Service& ieee1394service, int node_id ) +{ + ExtendedPlugInfoCmd extPlugInfoCmd( &ieee1394service ); + UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, 0 ); + extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input, + PlugAddress::ePAM_Unit, + unitPlugAddress ) ); + extPlugInfoCmd.setNodeId( node_id ); + extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status ); + extPlugInfoCmd.setVerbose( arguments.verbose ); + ExtendedPlugInfoInfoType extendedPlugInfoInfoType( ExtendedPlugInfoInfoType::eIT_PlugName ); + extendedPlugInfoInfoType.initialize(); + extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType ); + + if ( extPlugInfoCmd.fire() ) { + CoutSerializer se; + extPlugInfoCmd.serialize( se ); + } + + ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType(); + if ( infoType + && infoType->m_plugName ) + { + printf( "iso input plug %d has name '%s'\n", + 0, + infoType->m_plugName->m_name.c_str() ); + } else { + fprintf( stderr, "Not plug name specific data found\n" ); + return false; + } + + return true; +} + +bool +doApp(Ieee1394Service& ieee1394service, int node_id ) +{ + bool success; + + success = doPlugType( ieee1394service, node_id ); + success &= doPlugName( ieee1394service, node_id ); + + return success; +} + +/////////////////////////// +// main +////////////////////////// +int +main(int argc, char **argv) +{ + // arg parsing + argp_parse (&argp, argc, argv, 0, 0, &arguments); + + errno = 0; + char* tail; + int node_id = strtol(arguments.args[0], &tail, 0); + if (errno) { + perror("argument parsing failed:"); + return -1; + } + Ieee1394Service ieee1394service; + if ( !ieee1394service.initialize( arguments.port ) ) { + fprintf( stderr, "could not set port on ieee1394service\n" ); + return -1; + } + + doApp( ieee1394service, node_id ); + + return 0; +} Index: /tags/release_0_0_6/libfreebob/tests/.cvsignore =================================================================== --- /tags/release_0_0_6/libfreebob/tests/.cvsignore (revision 134) +++ /tags/release_0_0_6/libfreebob/tests/.cvsignore (revision 134) @@ -0,0 +1,9 @@ +.cvsignore +Makefile +Makefile.in +.deps +.libs +*.lo +*.la +test-extplugcmd +test-freebob Index: /tags/release_0_0_6/libfreebob/configure.ac =================================================================== --- /tags/release_0_0_6/libfreebob/configure.ac (revision 155) +++ /tags/release_0_0_6/libfreebob/configure.ac (revision 155) @@ -0,0 +1,174 @@ +# configure.ac - Configure script for FreeBob. +# Copyright (C) 2005 by Daniel Wagner. +# +# This file is part of FreeBob. +# +# FreeBob 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. +# FreeBob 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 FreeBob; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.57) + +m4_define(freebob_major_version, 0) +m4_define(freebob_minor_version, 0) +m4_define(freebob_micro_version, 6) +m4_define(freebob_version, freebob_major_version.freebob_minor_version.freebob_micro_version) + +AC_INIT(libfreebob, freebob_version, ) + +# Before making a release, the LT_VERSION string should be modified. +# The string is of the form C:R:A. +# - If interfaces have been changed or added, but binary compatibility has +# been preserved, change to C+1:0:A+1 +# - If binary compatibility has been broken (eg removed or changed interfaces) +# change to C+1:0:0 +# - If the interface is the same as the previous version, change to C:R+1:A + +LT_VERSION=1:0:1 +AC_SUBST(LT_VERSION) + +AC_DEFINE(FREEBOB_MAJOR_VERSION, freebob_major_version,[Freebob major version]) +AC_DEFINE(FREEBOB_MINOR_VERSION, freebob_minor_version,[Freebob minor version]) +AC_DEFINE(FREEBOB_MICRO_VERSION, freebob_micro_version,[Freebob micro version]) +AC_SUBST(FREEBOB_MINOR_VERSION, freebob_minor_version) +AC_SUBST(FREEBOB_MAJOR_VERSION, freebob_major_version) +AC_SUBST(FREEBOB_MICRO_VERSION, freebob_micro_version) + +AM_INIT_AUTOMAKE +AM_MAINTAINER_MODE +AC_CONFIG_SRCDIR([src/freebob.cpp]) +AC_CONFIG_HEADER([config.h]) +AC_GNU_SOURCE +AC_LANG(C++) + +# Prefix handling +AC_MSG_CHECKING(prefix) +defaultprefix=/usr/local +if test -z "$prefix" -o "$prefix" = "NONE"; then + prefix=$defaultprefix +fi +AC_PREFIX_DEFAULT($prefix) +AC_MSG_RESULT($prefix) + +maintainer_mode=${enable_maintainer_mode-no} + +# Checks for programs. +# AC_PROG_CC and AC_PROG_CXX will add by default "-g -O2" if +# CFLAGS and CXXFLAGS do not exists. Disable this feature. +test ".$CFLAGS" = "." && CFLAGS="" +test ".$CXXFLAGS" = "." && CXXFLAGS="" +AC_PROG_CC +AC_PROG_CXX +AM_PROG_AS +AC_PROG_LIBTOOL +AC_CHECK_TOOL([AR], [ar], :) +AC_CHECK_TOOL([NM], [nm], :) +AC_PATH_PROG([SED], [sed], :) +AC_PATH_PROG([SORT], [sort], :) + +# Required for building the documentation + +# Checks for libraries. +AC_PROG_LIBTOOL + +# Checks for typedefs, structures, and compiler characteristics. +AC_CANONICAL_HOST +AC_C_CONST +AC_C_VOLATILE +AC_TYPE_SIZE_T + +# XXX Debian specific hack: +# by Marcelo Magallon +# Turn around -rpath problem with libtool 1.0c +# This define should be improbable enough to not conflict with anything +case ${host} in + *-pc-linux-gnu) + AC_MSG_RESULT([Fixing libtool for -rpath problems.]) + sed < libtool > libtool-2 \ + 's/^hardcode_libdir_flag_spec.*$/hardcode_libdir_flag_spec=" -D__LIBTOOL_IS_A_FOOL__ "/' + mv libtool-2 libtool + chmod 755 libtool + ;; +esac + +AC_CHECK_LIB(pthread, pthread_create,, +[ + AC_ERROR(You need the pthread library to compile freebob) +]) + +# Check for dependencies +PKG_CHECK_MODULES(LIBRAW1394, libraw1394 >= 1.2.0) +PKG_CHECK_MODULES(LIBIEC61883, libiec61883 >= 1.1.0) +PKG_CHECK_MODULES(LIBAVC1394, libavc1394 >= 0.5.2) +PKG_CHECK_MODULES(ALSA, alsa >= 1.0.0) +PKG_CHECK_MODULES(LIBXML, libxml-2.0 >= 2.6.0) + +# Setup CFLAGS and CXXFLAGS +AC_ARG_ENABLE(debug, +[ --enable-debug Turn on debugging], +[case "${enableval}" in + yes) debug=true;; + no) ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;; +esac],[debug=false]) + +CFLAGS="$CFLAGS -g -Wall -std=gnu99" +CXXFLAGS="$CXXFLAGS -g -Wall" + +if test "${debug}" = true; then + CFLAGS="$CFLAGS -DDEBUG" + CXXFLAGS="$CXXFLAGS -DDEBUG" +else + CFLAGS="$CFLAGS -O2" + CXXFLAGS="$CXXFLAGS -O2" +fi; + +AC_SUBST([CFLAGS]) +AC_SUBST([CXXFLAGS]) + +# Configure components. +AC_ENABLE_STATIC(yes) +AC_ENABLE_SHARED(yes) + +AC_SUBST([LIBSIGC_CFLAGS]) +AC_SUBST([LIBSIGC_LIBS]) +AC_SUBST([ALSA_CFLAGS]) +AC_SUBST([ALSA_LIBS]) +AC_SUBST([LIBRAW1394_CFLAGS]) +AC_SUBST([LIBRAW1394_LIBS]) +AC_SUBST([LIBIEC61883_CFLAGS]) +AC_SUBST([LIBIEC61883_LIBS]) +AC_SUBST([LIBAVC1394_CFLAGS]) +AC_SUBST([LIBAVC1394_LIBS]) +AC_SUBST([LIBXML_LIBS]) +AC_SUBST([LIBXML_CFLAGS]) + +AC_CONFIG_FILES([Makefile + libfreebob/Makefile + src/debugmodule/Makefile + src/libfreebobavc/Makefile + src/Makefile + tests/Makefile + libfreebob.pc]) +AC_OUTPUT + +# Print a summary so that important information isn't missed. +AC_MSG_RESULT([ + +FreeBob is now configured for $canonical_host_type + + Source directory: $srcdir + Installation prefix: $prefix + C++ compiler: $CXX $CXXFLAGS +]) Index: /tags/release_0_0_6/libfreebob/AUTHORS =================================================================== --- /tags/release_0_0_6/libfreebob/AUTHORS (revision 156) +++ /tags/release_0_0_6/libfreebob/AUTHORS (revision 156) @@ -0,0 +1,1 @@ +Daniel Wagner Index: /tags/release_0_0_6/libfreebob/TODO =================================================================== --- /tags/release_0_0_6/libfreebob/TODO (revision 142) +++ /tags/release_0_0_6/libfreebob/TODO (revision 142) @@ -0,0 +1,10 @@ +- xml output is a bit wierd -> generate a more generic output +- correct string encoding +- position information of channel in stream: bebob indexes from 1 + but iec61883 expects it from 0. see todo in avdevice.cpp +- check all std::cout and std:cerr if they couldn't be replaced with + the DebugModule's methods. The idea is to have a more consistant + code. +- All libfreebobavc interfaces should use references instead of pointers + like in ExtendedPlugInfoCmd( Ieee1394Service* ieee1394service, ... ) + -> ExtendedPlugInfoCmd( Ieee1394Service& ieee1394service, Index: /tags/release_0_0_6/libfreebob/INSTALL =================================================================== --- /tags/release_0_0_6/libfreebob/INSTALL (revision 155) +++ /tags/release_0_0_6/libfreebob/INSTALL (revision 155) @@ -0,0 +1,229 @@ +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + Index: /tags/release_0_0_6/libfreebob/ChangeLog =================================================================== --- /tags/release_0_0_6/libfreebob/ChangeLog (revision 155) +++ /tags/release_0_0_6/libfreebob/ChangeLog (revision 155) @@ -0,0 +1,223 @@ +2006-01-19 Daniel Wagner + + * This patch cleans up the external dependency detection for + libfreebob. At present, building libfreebob is not possible + if libraries are outside the system include/library paths + (ie /usr/ and /usr/local). Use the results of pkg-config to + specify the correct paths to the automake system. + + Becuase we're using pkgconfig, there's no real need to use + AC_CHECK_LIB or AC_CHECK_HEADERS. However, these could + potentially be reinstated, but need to be fixed to check in + the locations specified by pkgconfig. + + * It is not currently possible to build freebob in a directory + outside the source dir (ie, builddir != srcdir). This patch + fixes the include paths to allow this. (it's handy for keeping + the source tree clean, or when building on multiple architectures + - I use a build dir of $srcdir/obj-$arch-$os) + + Both patches are written by Jeremy Kerr + +2006-01-12 Daniel Wagner + + * src/avdevice.cpp: Include stdint.h. + Some compilers seem to need the definitions. + +2006-01-08 Daniel Wagner + + * libfreebob/freebob.h + libfreebob/xmlparser.h + src/avdevice.cpp + src/xmlparser.c + tests/test-freebob.c: + Add stream format info support. + + * src/avdevice.h + src/avdevice.cpp: + Refactoring and code duplication removal. + + * src/avdevice.cpp (getModelName): + Return model name and not vendor name. + (getVendorName): + Return vendor name and not model name. + (discoverStep10Plug): Implementation added. + (enumerateSubUnits): max_subunit_id removed. + (addXmlDescription): Add stream format infos. + + * src/avdevice.h: discoverStep10 added. + Renaming of addPlugToXmlDescription to addXmlDescriptionPlug. + ESampleRate to ESamplingFrequency changes. + + * src/avplug.cpp (getSampleRate): + Use convertESamplingFrequency instead of + local implementation. + + * src/avplug.h: + ESampleRate to ESamplingFrequency changes. + Added FormatInfo struct. + + * src/devicemanager.cpp (getXmlDescription): + Print GUID correctly. + + * src/freebob.cpp (parseSampleRate): + Moved to avc_definitions.cpp + + * src/libfreebobavc/avc_definitions.h + src/libfreebobavc/avc_definitions.cpp: + Renamed ESampleRate back to ESamlingFrequency. + Added connvert functions for ESamplingFrequency. + + * configure.ac: New micro version. + +2006-01-06 Daniel Wagner + + * tests/test-freebob.c (main): setsamplerate on all + devices takes now the samplerate argument. + + * src/freebob.cpp (freebob_set_samplerate): After setting + sampling rate rediscover devices. + + * src/devicemanager.cpp (discover): Clear vector as well after + delete all elements. Cout and cerr replaced with debugModule. + + * src/avdevice.cpp (discoverStep8): Skip sync plug. + (discoverStep9): Sanity check fixed and reenabled. + + * configure.ac: New micro version. + + * src/avdevice.h + src/avdevice.cpp (setSampleRate): Implementation added. + + * src/devicemanager.cpp + src/devicemanager.h (getAvDevice): New functions + (setNodeSampleFrequency): removed. + + * src/freebob.cpp (parseSampleRate): New function. + (freebob_set_samplerate): Use AvDevice directly + for setting samplerate. + + * src/libfreebobavc/avc_definitions.h + src/libfreebobavc/avc_definitions.cpp: Changed ESampleFrequency + to ESampleRate. + + * tests/test-freebob.c: Info added about OPERATION arguments. + Parse sample rate for setsamplerate command. + Let emacs reindent code. Sorry Pieter :) + +2006-01-04 Daniel Wagner + + * tests/test-extplugcmd.cpp: Changed test application + to use PlugType and PlugName command for testing. + + * src/libfreebobavc/avc_extended_plug_info.cpp (serialize): + The string.length() thing did not work as expected. A workaround + added which converts the C++ string into a C string before strlen + is used. + +2006-01-03 Daniel Wagner + + * src/devicemanager.cpp (discover): If config rom initializing + failes just skip this device. The PHY might be in power safe + mode and then there is no config rom to be discovered. + +2006-01-02 Pieter Palmer + + * tests/test-freebob.c: Added support for scanning the whole bus. + Added xmldump operation to dump an XML description of the FW bus. + + * src/freebob.cpp src/freebob.h: Added freebob_print_xml_description + to print an XML description of the bus. + Added freebob_node_is_valid_freebob_device(). + Added freebob_get_nb_devices_on_bus(). + Added freebob_get_device_node_id(). + Added freebob_set_samplerate() as a dummy (unimplemented) + + * src/libfreebobavc/avc_connect.cpp + src/libfreebobavc/avc_extended_stream_format.cpp + src/libfreebobavc/avc_extended_stream_format.h + src/libfreebobavc/avc_plug_info.cpp + src/libfreebobavc/avc_signal_source.cpp + src/avcdevice.cpp + src/avdevice.h + src/avplug.cpp + src/avplug.h + src/devicemanager.cpp + src/devicemanager.h: + Fixed NodeId bug. + Commented out sanity check that failed for midi channels. + Fixed Dimension bug. + Increased all "XXX random length" requests. + Made a mess of clean code ;) + + * configure.ac: Bumped library verson + + * src/xmlparser.c + tests/test-freeebob.c: Added support to detect & use + multiple devices on the bus. + + * src/libfreebobavc/avc_extendec_plug_info.cpp + src/configrom.cpp: + Some small memory access bugfixes. + +2006-01-02 Daniel Wagner + + * src/avdevice.cpp (discoverStep9): Sanity check: 8 logical + midi channel fit into 1 channel. + +2005-12-31 Daniel Wagner + + * src/debugmodule/debugmodule.h: debugFatal, debugError + and debugWarning declaration always declared. + + * src/xmlparser.c (freebob_xmlparse_connection): Parse IsoChannel + node. + + * src/freebob.cpp (freebob_print_connection_info): Print all + members from connection_spec (IsoChannel and IsMaster). + + * src/avdevice.cpp (addPlugToXmlDescription): Set direction + according library interface definition and not according + avc model. + Add IsoChannel node. + + * configure.ac: Version set to 0.0.2 + +2005-12-30 Daniel Wagner + + * src/libfreebobavc/avc_extended_stream_format.cpp (fire): Buffer + length increased. + + * src/avdevice.cpp (discoverStep9): Error message extended. + More debug info added. + + * src/debugmodule/debugmodule.h: Enable debugFatal, debugError and + also in the release case. + +2005-12-28 Daniel Wagner + + * tests/test-freebob.c (main): Debug info added. + + * src/libfreebobavc/ieee1394service.cpp (initialize): Use + raw1394_new_handle_on_port instead of raw1394_new_handle and + raw1394_set_port. + + * src/devicemanager.cpp (initialize): After deleteing 1394 service + clear also pointer. + + * libfreebob/freebob.h: freebob_direction enum names changed + members which jack backed freebob needs to freebob_connection added + + * configure.ac: Update library version depency. + +2005-12-27 Daniel Wagner + + * src/libfreebobavc/avc_extended_plug_info.cpp (serialize): + Do cast of the length field to let the compiler know which version + of the serializing code it has to take. + +2005-12-26 Daniel Wagner + + * Initial check-in and first beta relase 'late x-mass gift'. + + Index: /tags/release_0_0_6/libfreebob/src/avplug.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/avplug.cpp (revision 151) +++ /tags/release_0_0_6/libfreebob/src/avplug.cpp (revision 151) @@ -0,0 +1,184 @@ +/* avplug.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "avplug.h" + +#include "libfreebobavc/avc_extended_plug_info.h" +#include "libfreebobavc/avc_definitions.h" + +IMPL_DEBUG_MODULE( AvPlug, AvPlug, DEBUG_LEVEL_VERBOSE ); + +AvPlug::AvPlug() + : m_plugType( 0xff ) + , m_plugId( 0xff ) + , m_subunitType( 0xff ) + , m_subunitId( 0xff ) + , m_direction( 0xff ) + , m_nrOfChannels( 0 ) + , m_samplingFrequency( 0xff ) +{ +} + +AvPlug::AvPlug( const AvPlug& rhs ) + : m_plugType( rhs.m_plugType ) + , m_plugId( rhs.m_plugId ) + , m_subunitType( rhs.m_subunitType ) + , m_subunitId( rhs.m_subunitType ) + , m_direction( rhs.m_direction ) + , m_name( rhs.m_name ) + , m_nrOfChannels( rhs.m_nrOfChannels ) + , m_samplingFrequency( rhs.m_samplingFrequency ) + , m_clusterInfos( rhs.m_clusterInfos ) +{ +} + +AvPlug::~AvPlug() +{ +} + +bool +AvPlug::copyClusterInfo(ExtendedPlugInfoPlugChannelPositionSpecificData& + channelPositionData ) +{ + int index = 1; + for ( ExtendedPlugInfoPlugChannelPositionSpecificData::ClusterInfoVector::const_iterator it + = channelPositionData.m_clusterInfos.begin(); + it != channelPositionData.m_clusterInfos.end(); + ++it ) + { + const ExtendedPlugInfoPlugChannelPositionSpecificData::ClusterInfo* + extPlugSpClusterInfo = &( *it ); + + ClusterInfo clusterInfo; + clusterInfo.m_nrOfChannels = extPlugSpClusterInfo->m_nrOfChannels; + clusterInfo.m_index = index; + index++; + + for ( ExtendedPlugInfoPlugChannelPositionSpecificData::ChannelInfoVector::const_iterator cit + = extPlugSpClusterInfo->m_channelInfos.begin(); + cit != extPlugSpClusterInfo->m_channelInfos.end(); + ++cit ) + { + const ExtendedPlugInfoPlugChannelPositionSpecificData::ChannelInfo* + extPlugSpChannelInfo = &( *cit ); + + ChannelInfo channelInfo; + channelInfo.m_streamPosition = + extPlugSpChannelInfo->m_streamPosition; + channelInfo.m_location = + extPlugSpChannelInfo->m_location; + + clusterInfo.m_channelInfos.push_back( channelInfo ); + } + m_clusterInfos.push_back( clusterInfo ); + } + + return true; +} + +void +AvPlug::debugOutputClusterInfos( int debugLevel ) +{ + for ( ClusterInfoVector::const_iterator it = m_clusterInfos.begin(); + it != m_clusterInfos.end(); + ++it ) + { + const ClusterInfo* clusterInfo = &( *it ); + + debugOutput( debugLevel, "number of channels: %d\n", + clusterInfo->m_nrOfChannels ); + + for ( ChannelInfoVector::const_iterator cit + = clusterInfo->m_channelInfos.begin(); + cit != clusterInfo->m_channelInfos.end(); + ++cit ) + { + const ChannelInfo* channelInfo = &( *cit ); + debugOutput( debugLevel, + "stream position: %d\n", + channelInfo->m_streamPosition ); + debugOutput( debugLevel, + "location: %d\n", + channelInfo->m_location ); + } + } +} + +AvPlug::ClusterInfo* +AvPlug::getClusterInfoByIndex(int index) +{ + for ( AvPlug::ClusterInfoVector::iterator clit = + m_clusterInfos.begin(); + clit != m_clusterInfos.end(); + ++clit ) + { + ClusterInfo* info = &*clit; + if ( info->m_index == index ) { + return info; + } + } + return 0; +} + +int +AvPlug::getNrOfStreams() +{ + int nrOfChannels = 0; + for ( ClusterInfoVector::const_iterator it = m_clusterInfos.begin(); + it != m_clusterInfos.end(); + ++it ) + { + const ClusterInfo* clusterInfo = &( *it ); + nrOfChannels += clusterInfo->m_nrOfChannels; + } + return nrOfChannels; +} + +int +AvPlug::getNrOfChannels() +{ + return m_nrOfChannels; +} + +int +AvPlug::getSampleRate() +{ + return convertESamplingFrequency( static_cast( m_samplingFrequency ) ); +} + +//////////////////////////////////// + +AvPlugCluster::AvPlugCluster() +{ +} + +AvPlugCluster::~AvPlugCluster() +{ +} + +//////////////////////////////////// + +AvPlugConnection::AvPlugConnection() +{ +} + +AvPlugConnection::~AvPlugConnection() +{ +} Index: /tags/release_0_0_6/libfreebob/src/devicemanager.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/devicemanager.h (revision 144) +++ /tags/release_0_0_6/libfreebob/src/devicemanager.h (revision 144) @@ -0,0 +1,60 @@ +/* template.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef FREEBOBDEVICEMANAGER_H +#define FREEBOBDEVICEMANAGER_H + +#include "debugmodule/debugmodule.h" + +#include "libfreebob/xmlparser.h" + +#include + +class Ieee1394Service; +class AvDevice; + +typedef std::vector< AvDevice* > AvDeviceVector; +typedef std::vector< AvDevice* >::iterator AvDeviceVectorIterator; + +class DeviceManager{ + public: + DeviceManager(); + ~DeviceManager(); + + bool initialize( int port ); + bool deinitialize(); + + bool discover(); + + bool isValidNode( int node ); + int getNbDevices(); + int getDeviceNodeId( int deviceNr ); + + AvDevice* getAvDevice( int nodeId ); + + xmlDocPtr getXmlDescription(); + protected: + Ieee1394Service* m_1394Service; + AvDeviceVector m_avDevices; + + DECLARE_DEBUG_MODULE; +}; + +#endif Index: /tags/release_0_0_6/libfreebob/src/avdevicesubunit.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/avdevicesubunit.cpp (revision 156) +++ /tags/release_0_0_6/libfreebob/src/avdevicesubunit.cpp (revision 156) @@ -0,0 +1,97 @@ +/* avdevicesubunit.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "avdevicesubunit.h" +#include "avdevice.h" +#include "avplug.h" + +IMPL_DEBUG_MODULE( AvDeviceSubunit, AvDeviceSubunit, DEBUG_LEVEL_VERBOSE ); + +//////////////////////////////////////////// + +AvDeviceSubunit::AvDeviceSubunit( AvDevice* avDevice, subunit_type_t type, subunit_t id ) + : m_avDevice( avDevice ) + , m_sbType( type ) + , m_sbId( id ) +{ +} + +AvDeviceSubunit::~AvDeviceSubunit() +{ + for ( AvPlugVector::iterator it = m_plugs.begin(); + it != m_plugs.end(); + ++it ) + { + delete *it; + } +} + +bool +AvDeviceSubunit::addPlug( AvPlug& plug ) +{ + m_plugs.push_back( &plug ); + return true; +} + +//////////////////////////////////////////// + +AvDeviceSubunitAudio::AvDeviceSubunitAudio( AvDevice* avDevice, subunit_t id ) + : AvDeviceSubunit( avDevice, AVCCommand::eST_Audio, id ) +{ +} + +AvDeviceSubunitAudio::~AvDeviceSubunitAudio() +{ +} + +bool +AvDeviceSubunitAudio::discover() +{ + return true; +} + +const char* +AvDeviceSubunitAudio::getName() +{ + return "AudioSubunit"; +} + +//////////////////////////////////////////// + +AvDeviceSubunitMusic::AvDeviceSubunitMusic( AvDevice* avDevice, subunit_t id ) + : AvDeviceSubunit( avDevice, AVCCommand::eST_Music, id ) +{ +} + +AvDeviceSubunitMusic::~AvDeviceSubunitMusic() +{ +} + +bool +AvDeviceSubunitMusic::discover() +{ + return true; +} + +const char* +AvDeviceSubunitMusic::getName() +{ + return "MusicSubunit"; +} Index: /tags/release_0_0_6/libfreebob/src/csr1212.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/csr1212.h (revision 156) +++ /tags/release_0_0_6/libfreebob/src/csr1212.h (revision 156) @@ -0,0 +1,734 @@ +/* + * csr1212.h -- IEEE 1212 Control and Status Register support for Linux + * + * Copyright (C) 2003 Francois Retief + * Steve Kinneberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __CSR1212_H__ +#define __CSR1212_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Compatibility layer */ +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include + +#define CSR1212_MALLOC(size) vmalloc((size)) +#define CSR1212_FREE(ptr) vfree(ptr) +#define CSR1212_BE16_TO_CPU(quad) be16_to_cpu(quad) +#define CSR1212_CPU_TO_BE16(quad) cpu_to_be16(quad) +#define CSR1212_BE32_TO_CPU(quad) be32_to_cpu(quad) +#define CSR1212_CPU_TO_BE32(quad) cpu_to_be32(quad) +#define CSR1212_BE64_TO_CPU(quad) be64_to_cpu(quad) +#define CSR1212_CPU_TO_BE64(quad) cpu_to_be64(quad) + +#define CSR1212_LE16_TO_CPU(quad) le16_to_cpu(quad) +#define CSR1212_CPU_TO_LE16(quad) cpu_to_le16(quad) +#define CSR1212_LE32_TO_CPU(quad) le32_to_cpu(quad) +#define CSR1212_CPU_TO_LE32(quad) cpu_to_le32(quad) +#define CSR1212_LE64_TO_CPU(quad) le64_to_cpu(quad) +#define CSR1212_CPU_TO_LE64(quad) cpu_to_le64(quad) + +#include +#define CSR1212_SUCCESS (0) +#define CSR1212_EINVAL (-EINVAL) +#define CSR1212_ENOMEM (-ENOMEM) +#define CSR1212_ENOENT (-ENOENT) +#define CSR1212_EIO (-EIO) +#define CSR1212_EBUSY (-EBUSY) + +#else /* Userspace */ + +#include +#include +#define CSR1212_MALLOC(size) calloc(1,size) +#define CSR1212_FREE(ptr) free(ptr) +#include +#if __BYTE_ORDER == __LITTLE_ENDIAN +#include +#define CSR1212_BE16_TO_CPU(quad) bswap_16(quad) +#define CSR1212_CPU_TO_BE16(quad) bswap_16(quad) +#define CSR1212_BE32_TO_CPU(quad) bswap_32(quad) +#define CSR1212_CPU_TO_BE32(quad) bswap_32(quad) +#define CSR1212_BE64_TO_CPU(quad) bswap_64(quad) +#define CSR1212_CPU_TO_BE64(quad) bswap_64(quad) + +#define CSR1212_LE16_TO_CPU(quad) (quad) +#define CSR1212_CPU_TO_LE16(quad) (quad) +#define CSR1212_LE32_TO_CPU(quad) (quad) +#define CSR1212_CPU_TO_LE32(quad) (quad) +#define CSR1212_LE64_TO_CPU(quad) (quad) +#define CSR1212_CPU_TO_LE64(quad) (quad) +#else +#define CSR1212_BE16_TO_CPU(quad) (quad) +#define CSR1212_CPU_TO_BE16(quad) (quad) +#define CSR1212_BE32_TO_CPU(quad) (quad) +#define CSR1212_CPU_TO_BE32(quad) (quad) +#define CSR1212_BE64_TO_CPU(quad) (quad) +#define CSR1212_CPU_TO_BE64(quad) (quad) + +#define CSR1212_LE16_TO_CPU(quad) bswap_16(quad) +#define CSR1212_CPU_TO_LE16(quad) bswap_16(quad) +#define CSR1212_LE32_TO_CPU(quad) bswap_32(quad) +#define CSR1212_CPU_TO_LE32(quad) bswap_32(quad) +#define CSR1212_LE64_TO_CPU(quad) bswap_64(quad) +#define CSR1212_CPU_TO_LE64(quad) bswap_64(quad) +#endif + +#include +#define CSR1212_SUCCESS (0) +#define CSR1212_EINVAL (EINVAL) +#define CSR1212_ENOMEM (ENOMEM) +#define CSR1212_ENOENT (ENOENT) +#define CSR1212_EIO (EIO) +#define CSR1212_EBUSY (EBUSY) + +#endif + + +#define CSR1212_KV_VAL_MASK 0xffffff +#define CSR1212_KV_KEY_SHIFT 24 +#define CSR1212_KV_KEY_TYPE_SHIFT 6 +#define CSR1212_KV_KEY_ID_MASK 0x3f +#define CSR1212_KV_KEY_TYPE_MASK 0x3 /* After shift */ + + +/* CSR 1212 key types */ +#define CSR1212_KV_TYPE_IMMEDIATE 0 +#define CSR1212_KV_TYPE_CSR_OFFSET 1 +#define CSR1212_KV_TYPE_LEAF 2 +#define CSR1212_KV_TYPE_DIRECTORY 3 + + +/* CSR 1212 key ids */ +#define CSR1212_KV_ID_DESCRIPTOR 0x01 +#define CSR1212_KV_ID_BUS_DEPENDENT_INFO 0x02 +#define CSR1212_KV_ID_VENDOR 0x03 +#define CSR1212_KV_ID_HARDWARE_VERSION 0x04 +#define CSR1212_KV_ID_MODULE 0x07 +#define CSR1212_KV_ID_NODE_CAPABILITIES 0x0C +#define CSR1212_KV_ID_EUI_64 0x0D +#define CSR1212_KV_ID_UNIT 0x11 +#define CSR1212_KV_ID_SPECIFIER_ID 0x12 +#define CSR1212_KV_ID_VERSION 0x13 +#define CSR1212_KV_ID_DEPENDENT_INFO 0x14 +#define CSR1212_KV_ID_UNIT_LOCATION 0x15 +#define CSR1212_KV_ID_MODEL 0x17 +#define CSR1212_KV_ID_INSTANCE 0x18 +#define CSR1212_KV_ID_KEYWORD 0x19 +#define CSR1212_KV_ID_FEATURE 0x1A +#define CSR1212_KV_ID_EXTENDED_ROM 0x1B +#define CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID 0x1C +#define CSR1212_KV_ID_EXTENDED_KEY 0x1D +#define CSR1212_KV_ID_EXTENDED_DATA 0x1E +#define CSR1212_KV_ID_MODIFIABLE_DESCRIPTOR 0x1F +#define CSR1212_KV_ID_DIRECTORY_ID 0x20 +#define CSR1212_KV_ID_REVISION 0x21 + + +/* IEEE 1212 Address space map */ +#define CSR1212_ALL_SPACE_BASE (0x000000000000ULL) +#define CSR1212_ALL_SPACE_SIZE (1ULL << 48) +#define CSR1212_ALL_SPACE_END (CSR1212_ALL_SPACE_BASE + CSR1212_ALL_SPACE_SIZE) + +#define CSR1212_MEMORY_SPACE_BASE (0x000000000000ULL) +#define CSR1212_MEMORY_SPACE_SIZE ((256ULL * (1ULL << 40)) - (512ULL * (1ULL << 20))) +#define CSR1212_MEMORY_SPACE_END (CSR1212_MEMORY_SPACE_BASE + CSR1212_MEMORY_SPACE_SIZE) + +#define CSR1212_PRIVATE_SPACE_BASE (0xffffe0000000ULL) +#define CSR1212_PRIVATE_SPACE_SIZE (256ULL * (1ULL << 20)) +#define CSR1212_PRIVATE_SPACE_END (CSR1212_PRIVATE_SPACE_BASE + CSR1212_PRIVATE_SPACE_SIZE) + +#define CSR1212_REGISTER_SPACE_BASE (0xfffff0000000ULL) +#define CSR1212_REGISTER_SPACE_SIZE (256ULL * (1ULL << 20)) +#define CSR1212_REGISTER_SPACE_END (CSR1212_REGISTER_SPACE_BASE + CSR1212_REGISTER_SPACE_SIZE) + +#define CSR1212_CSR_ARCH_REG_SPACE_BASE (0xfffff0000000ULL) +#define CSR1212_CSR_ARCH_REG_SPACE_SIZE (512) +#define CSR1212_CSR_ARCH_REG_SPACE_END (CSR1212_CSR_ARCH_REG_SPACE_BASE + CSR1212_CSR_ARCH_REG_SPACE_SIZE) +#define CSR1212_CSR_ARCH_REG_SPACE_OFFSET (CSR1212_CSR_ARCH_REG_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE) + +#define CSR1212_CSR_BUS_DEP_REG_SPACE_BASE (0xfffff0000200ULL) +#define CSR1212_CSR_BUS_DEP_REG_SPACE_SIZE (512) +#define CSR1212_CSR_BUS_DEP_REG_SPACE_END (CSR1212_CSR_BUS_DEP_REG_SPACE_BASE + CSR1212_CSR_BUS_DEP_REG_SPACE_SIZE) +#define CSR1212_CSR_BUS_DEP_REG_SPACE_OFFSET (CSR1212_CSR_BUS_DEP_REG_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE) + +#define CSR1212_CONFIG_ROM_SPACE_BASE (0xfffff0000400ULL) +#define CSR1212_CONFIG_ROM_SPACE_SIZE (1024) +#define CSR1212_CONFIG_ROM_SPACE_END (CSR1212_CONFIG_ROM_SPACE_BASE + CSR1212_CONFIG_ROM_SPACE_SIZE) +#define CSR1212_CONFIG_ROM_SPACE_OFFSET (CSR1212_CONFIG_ROM_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE) + +#define CSR1212_UNITS_SPACE_BASE (0xfffff0000800ULL) +#define CSR1212_UNITS_SPACE_SIZE ((256ULL * (1ULL << 20)) - 2048) +#define CSR1212_UNITS_SPACE_END (CSR1212_UNITS_SPACE_BASE + CSR1212_UNITS_SPACE_SIZE) +#define CSR1212_UNITS_SPACE_OFFSET (CSR1212_UNITS_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE) + +#define CSR1212_EXTENDED_ROM_SIZE (0x10000 * sizeof(u_int32_t)) + + +/* Config ROM image structures */ +struct csr1212_bus_info_block_img { + u_int8_t length; + u_int8_t crc_length; + u_int16_t crc; + + /* Must be last */ + u_int32_t data[0]; /* older gcc can't handle [] which is standard */ +}; + +#define CSR1212_KV_KEY(quad) (CSR1212_BE32_TO_CPU(quad) >> CSR1212_KV_KEY_SHIFT) +#define CSR1212_KV_KEY_TYPE(quad) (CSR1212_KV_KEY(quad) >> CSR1212_KV_KEY_TYPE_SHIFT) +#define CSR1212_KV_KEY_ID(quad) (CSR1212_KV_KEY(quad) & CSR1212_KV_KEY_ID_MASK) +#define CSR1212_KV_VAL(quad) (CSR1212_BE32_TO_CPU(quad) & CSR1212_KV_VAL_MASK) + +#define CSR1212_SET_KV_KEY(quad, key) ((quad) = \ + CSR1212_CPU_TO_BE32(CSR1212_KV_VAL(quad) | ((key) << CSR1212_KV_KEY_SHIFT))) +#define CSR1212_SET_KV_VAL(quad, val) ((quad) = \ + CSR1212_CPU_TO_BE32((CSR1212_KV_KEY(quad) << CSR1212_KV_KEY_SHIFT) | (val))) +#define CSR1212_SET_KV_TYPEID(quad, type, id) ((quad) = \ + CSR1212_CPU_TO_BE32(CSR1212_KV_VAL(quad) | \ + (((((type) & CSR1212_KV_KEY_TYPE_MASK) << CSR1212_KV_KEY_TYPE_SHIFT) | \ + ((id) & CSR1212_KV_KEY_ID_MASK)) << CSR1212_KV_KEY_SHIFT))) + +typedef u_int32_t csr1212_quad_t; + + +struct csr1212_keyval_img { + u_int16_t length; + u_int16_t crc; + + /* Must be last */ + csr1212_quad_t data[0]; /* older gcc can't handle [] which is standard */ +}; + +struct csr1212_leaf { + int len; + u_int32_t *data; +}; + +struct csr1212_dentry { + struct csr1212_dentry *next, *prev; + struct csr1212_keyval *kv; +}; + +struct csr1212_directory { + int len; + struct csr1212_dentry *dentries_head, *dentries_tail; +}; + +struct csr1212_keyval { + struct { + u_int8_t type; + u_int8_t id; + } key; + union { + u_int32_t immediate; + u_int32_t csr_offset; + struct csr1212_leaf leaf; + struct csr1212_directory directory; + } value; + struct csr1212_keyval *associate; + int refcnt; + + /* used in generating and/or parsing CSR image */ + struct csr1212_keyval *next, *prev; /* flat list of CSR elements */ + u_int32_t offset; /* position in CSR from 0xffff f000 0000 */ + u_int8_t valid; /* flag indicating keyval has valid data*/ +}; + + +struct csr1212_cache_region { + struct csr1212_cache_region *next, *prev; + u_int32_t offset_start; /* inclusive */ + u_int32_t offset_end; /* exclusive */ +}; + +struct csr1212_csr_rom_cache { + struct csr1212_csr_rom_cache *next, *prev; + struct csr1212_cache_region *filled_head, *filled_tail; + struct csr1212_keyval *layout_head, *layout_tail; + size_t size; + u_int32_t offset; + struct csr1212_keyval *ext_rom; + size_t len; + + /* Must be last */ + u_int32_t data[0]; /* older gcc can't handle [] which is standard */ +}; + +struct csr1212_csr { + size_t bus_info_len; /* bus info block length in bytes */ + size_t crc_len; /* crc length in bytes */ + u_int32_t *bus_info_data; /* bus info data incl bus name and EUI */ + + void *private_data; /* private_data, bus specific data */ + struct csr1212_bus_ops *ops; + + struct csr1212_keyval *root_kv; + + int max_rom; /* max bytes readable in Config ROM region */ + + /* Items below used for image parsing and generation */ + struct csr1212_csr_rom_cache *cache_head, *cache_tail; +}; + +struct csr1212_bus_ops { + /* This function is used by csr1212 to read additional information + * from remote nodes when parsing a Config ROM (i.e., read Config ROM + * entries located in the Units Space. Must return 0 on success + * anything else indicates an error. */ + int (*bus_read) (struct csr1212_csr *csr, u_int64_t addr, + u_int16_t length, void *buffer, void *private_data); + + /* This function is used by csr1212 to allocate a region in units space + * in the event that Config ROM entries don't all fit in the predefined + * 1K region. The void *private_data parameter is private_data member of struct + * csr1212_csr. */ + u_int64_t (*allocate_addr_range) (u_int64_t size, u_int32_t alignment, + void *private_data); + + + /* This function is used by csr1212 to release a region in units space + * that is no longer needed. */ + void (*release_addr) (u_int64_t addr, void *private_data); + + /* This function is used by csr1212 to determine the max read request + * supported by a remote node when reading the ConfigROM space. Must + * return 0, 1, or 2 per IEEE 1212. */ + int (*get_max_rom) (u_int32_t *bus_info, void *private_data); +}; + + + + +/* Descriptor Leaf manipulation macros */ +#define CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT 24 +#define CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK 0xffffff +#define CSR1212_DESCRIPTOR_LEAF_OVERHEAD (1 * sizeof(u_int32_t)) + +#define CSR1212_DESCRIPTOR_LEAF_TYPE(kv) \ + (CSR1212_BE32_TO_CPU((kv)->value.leaf.data[0]) >> CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT) +#define CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) \ + (CSR1212_BE32_TO_CPU((kv)->value.leaf.data[0]) & \ + CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK) +#define CSR1212_DESCRIPTOR_LEAF_DATA(kv) \ + (&((kv)->value.leaf.data[1])) + +#define CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, type) \ + ((kv)->value.leaf.data[0] = \ + CSR1212_CPU_TO_BE32(CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) | \ + ((type) << CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT))) +#define CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, spec_id) \ + ((kv)->value.leaf.data[0] = \ + CSR1212_CPU_TO_BE32((CSR1212_DESCRIPTOR_LEAF_TYPE(kv) << \ + CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT) | \ + ((spec_id) & CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK))) + +/* Text Descriptor Leaf manipulation macros */ +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT 28 +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK 0xf /* after shift */ +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT 16 +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK 0xfff /* after shift */ +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK 0xffff +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD (1 * sizeof(u_int32_t)) + +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) \ + (CSR1212_BE32_TO_CPU((kv)->value.leaf.data[1]) >> \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT) +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) \ + ((CSR1212_BE32_TO_CPU((kv)->value.leaf.data[1]) >> \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT) & \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK) +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) \ + (CSR1212_BE32_TO_CPU((kv)->value.leaf.data[1]) & \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK) +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv) \ + (&((kv)->value.leaf.data[2])) + +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_WIDTH(kv, width) \ + ((kv)->value.leaf.data[1] = \ + ((kv)->value.leaf.data[1] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK << \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT))) | \ + CSR1212_CPU_TO_BE32(((width) & \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK) << \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT)) +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_CHAR_SET(kv, char_set) \ + ((kv)->value.leaf.data[1] = \ + ((kv)->value.leaf.data[1] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK << \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT))) | \ + CSR1212_CPU_TO_BE32(((char_set) & \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK) << \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT)) +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language) \ + ((kv)->value.leaf.data[1] = \ + ((kv)->value.leaf.data[1] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK))) | \ + CSR1212_CPU_TO_BE32(((language) & \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK))) + + +/* Icon Descriptor Leaf manipulation macros */ +#define CSR1212_ICON_DESCRIPTOR_LEAF_VERSION_MASK 0xffffff +#define CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_SHIFT 30 +#define CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_MASK 0x3 /* after shift */ +#define CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_SHIFT 16 +#define CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_MASK 0xf /* after shift */ +#define CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE_MASK 0xffff +#define CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_SHIFT 16 +#define CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_MASK 0xffff /* after shift */ +#define CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN_MASK 0xffff +#define CSR1212_ICON_DESCRIPTOR_LEAF_OVERHEAD (3 * sizeof(u_int32_t)) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_VERSION(kv) \ + (CSR1212_BE32_TO_CPU((kv)->value.leaf.data[2]) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_VERSION_MASK) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH(kv) \ + (CSR1212_BE32_TO_CPU((kv)->value.leaf.data[3]) >> \ + CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_SHIFT) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE(kv) \ + ((CSR1212_BE32_TO_CPU((kv)->value.leaf.data[3]) >> \ + CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_SHIFT) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_MASK) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE(kv) \ + (CSR1212_BE32_TO_CPU((kv)->value.leaf.data[3]) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE_MASK) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN(kv) \ + ((CSR1212_BE32_TO_CPU((kv)->value.leaf.data[4]) >> \ + CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_HSCAN_SHIFT) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_HSCAN_MASK) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN(kv) \ + (CSR1212_BE32_TO_CPU((kv)->value.leaf.data[4]) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN_MASK) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE(kv) \ + (&((kv)->value.leaf.data[5])) + +static inline u_int32_t *CSR1212_ICON_DESCRIPTOR_LEAF_PIXELS(struct csr1212_keyval *kv) +{ + static const int pd[4] = { 0, 4, 16, 256 }; + static const int cs[16] = { 4, 2 }; + int ps = pd[CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH(kv)]; + + return &kv->value.leaf.data[5 + + (ps * cs[CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE(kv)]) / + sizeof(u_int32_t)]; +} + +#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_VERSION(kv, version) \ + ((kv)->value.leaf.data[2] = \ + ((kv)->value.leaf.data[2] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_VERSION_MASK))) | \ + CSR1212_CPU_TO_BE32(((version) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_VERSION_MASK))) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_PALETTE_DEPTH(kv, palette_depth) \ + ((kv)->value.leaf.data[3] = \ + ((kv)->value.leaf.data[3] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_MASK << \ + CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_SHIFT))) | \ + CSR1212_CPU_TO_BE32(((palette_depth) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_MASK) << \ + CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_SHIFT)) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_COLOR_SPACE(kv, color_space) \ + ((kv)->value.leaf.data[3] = \ + ((kv)->value.leaf.data[3] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_MASK << \ + CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_SHIFT))) | \ + CSR1212_CPU_TO_BE32(((color_space) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_MASK) << \ + CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_SHIFT)) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language) \ + ((kv)->value.leaf.data[3] = \ + ((kv)->value.leaf.data[3] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE_MASK))) | \ + CSR1212_CPU_TO_BE32(((language) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE_MASK))) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_HSCAN(kv, hscan) \ + ((kv)->value.leaf.data[4] = \ + ((kv)->value.leaf.data[4] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_MASK << \ + CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_SHIFT))) | \ + CSR1212_CPU_TO_BE32(((hscan) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_MASK) << \ + CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_SHIFT)) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_VSCAN(kv, vscan) \ + ((kv)->value.leaf.data[4] = \ + (((kv)->value.leaf.data[4] & \ + CSR1212_CPU_TO_BE32(~CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN_MASK))) | \ + CSR1212_CPU_TO_BE32(((vscan) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN_MASK))) + + +/* Modifiable Descriptor Leaf manipulation macros */ +#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_SHIFT 16 +#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_MASK 0xffff +#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_HI_SHIFT 32 +#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_HI_MASK 0xffff +#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_LO_MASK 0xffffffffULL + +#define CSR1212_MODIFIABLE_DESCRIPTOR_MAX_SIZE(kv) \ + CSR1212_BE16_TO_CPU((kv)->value.leaf.data[0] >> CSR1212_MODIFIABLE_DESCRIPTOR_MAX_SIZE_SHIFT) + +#define CSR1212_MODIFIABLE_DESCRIPTOR_ADDRESS(kv) \ + (CSR1212_BE16_TO_CPU(((u_int64_t)((kv)->value.leaf.data[0])) << \ + CSR1212_MODIFIABLE_DESCRIPTOR_ADDR_HI_SHIFT) | \ + CSR1212_BE32_TO_CPU((kv)->value.leaf.data[1])) + +#define CSR1212_MODIFIABLE_DESCRIPTOR_SET_MAX_SIZE(kv, size) \ + ((kv)->value.leaf.data[0] = \ + ((kv)->value.leaf.data[0] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_MASK << \ + CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_SHIFT))) | \ + CSR1212_CPU_TO_BE32(((size) & \ + CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_MASK) << \ + CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_SHIFT)) + +#define CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_HI(kv, addr) \ + ((kv)->value.leaf.data[0] = \ + ((kv)->value.leaf.data[0] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_HI_MASK))) | \ + CSR1212_CPU_TO_BE32(((addr) & \ + CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_HI_MASK))) + +#define CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_LO(kv, addr) \ + ((kv)->value.leaf.data[1] = \ + CSR1212_CPU_TO_BE32(addr & CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_LO_MASK)) + + + +/* The following 2 function are for creating new Configuration ROM trees. The + * first function is used for both creating local trees and parsing remote + * trees. The second function adds pertinent information to local Configuration + * ROM trees - namely data for the bus information block. */ +extern struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops, + size_t bus_info_size, + void *private_data); +extern void csr1212_init_local_csr(struct csr1212_csr *csr, + const u_int32_t *bus_info_data, int max_rom); + + +/* The following function destroys a Configuration ROM tree and release all + * memory taken by the tree. */ +extern void csr1212_destroy_csr(struct csr1212_csr *csr); + + +/* The following set of functions are fore creating new keyvals for placement in + * a Configuration ROM tree. Code that creates new keyvals with these functions + * must release those keyvals with csr1212_release_keyval() when they are no + * longer needed. */ +extern struct csr1212_keyval *csr1212_new_immediate(u_int8_t key, u_int32_t value); +extern struct csr1212_keyval *csr1212_new_leaf(u_int8_t key, const void *data, + size_t data_len); +extern struct csr1212_keyval *csr1212_new_csr_offset(u_int8_t key, + u_int32_t csr_offset); +extern struct csr1212_keyval *csr1212_new_directory(u_int8_t key); +extern struct csr1212_keyval *csr1212_new_extended_immediate(u_int32_t spec, + u_int32_t key, + u_int32_t value); +extern struct csr1212_keyval *csr1212_new_extended_leaf(u_int32_t spec, + u_int32_t key, + const void *data, + size_t data_len); +extern struct csr1212_keyval *csr1212_new_descriptor_leaf(u_int8_t dtype, + u_int32_t specifier_id, + const void *data, + size_t data_len); +extern struct csr1212_keyval *csr1212_new_textual_descriptor_leaf(u_int8_t cwidth, + u_int16_t cset, + u_int16_t language, + const void *data, + size_t data_len); +extern struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s); +extern struct csr1212_keyval *csr1212_new_icon_descriptor_leaf(u_int32_t version, + u_int8_t palette_depth, + u_int8_t color_space, + u_int16_t language, + u_int16_t hscan, + u_int16_t vscan, + u_int32_t *palette, + u_int32_t *pixels); +extern struct csr1212_keyval *csr1212_new_modifiable_descriptor_leaf(u_int16_t max_size, + u_int64_t address); +extern struct csr1212_keyval *csr1212_new_keyword_leaf(int strc, + const char *strv[]); + + +/* The following functions manage association between keyvals. Typically, + * Descriptor Leaves and Directories will be associated with another keyval and + * it is desirable for the Descriptor keyval to be place immediately after the + * keyval that it is associated with.*/ +extern int csr1212_associate_keyval(struct csr1212_keyval *kv, + struct csr1212_keyval *associate); +extern void csr1212_disassociate_keyval(struct csr1212_keyval *kv); + + +/* The following functions manage the association of a keyval and directories. + * A keyval may be attached to more than one directory. */ +extern int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, + struct csr1212_keyval *kv); +extern void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir, + struct csr1212_keyval *kv); + + +/* The following functions create a Configuration ROM image from the tree of + * keyvals provided. csr1212_generate_csr_image() creates a complete image in + * the list of caches available via csr->cache_head. The other functions are + * provided should there be a need to create a flat image without restrictions + * placed by IEEE 1212. */ +extern struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *cache, + struct csr1212_keyval *start_kv, + int start_pos); +extern size_t csr1212_generate_layout_order(struct csr1212_keyval *kv); +extern void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache); +extern int csr1212_generate_csr_image(struct csr1212_csr *csr); + + +/* This is a convience function for reading a block of data out of one of the + * caches in the csr->cache_head list. */ +extern int csr1212_read(struct csr1212_csr *csr, u_int32_t offset, void *buffer, + u_int32_t len); + + +/* The following functions are in place for parsing Configuration ROM images. + * csr1212_parse_keyval() is used should there be a need to directly parse a + * Configuration ROM directly. */ +extern int csr1212_parse_keyval(struct csr1212_keyval *kv, + struct csr1212_csr_rom_cache *cache); +extern int csr1212_parse_csr(struct csr1212_csr *csr); + +/* These are internal functions referenced by inline functions below. */ +extern int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv); +extern void _csr1212_destroy_keyval(struct csr1212_keyval *kv); + + +/* This function allocates a new cache which may be used for either parsing or + * generating sub-sets of Configuration ROM images. */ +static inline struct csr1212_csr_rom_cache *csr1212_rom_cache_malloc(u_int32_t offset, + size_t size) +{ + struct csr1212_csr_rom_cache *cache; + + cache = (struct csr1212_csr_rom_cache*)CSR1212_MALLOC(sizeof(struct csr1212_csr_rom_cache) + size); + if (!cache) + return NULL; + + cache->next = NULL; + cache->prev = NULL; + cache->filled_head = NULL; + cache->filled_tail = NULL; + cache->layout_head = NULL; + cache->layout_tail = NULL; + cache->offset = offset; + cache->size = size; + cache->ext_rom = NULL; + + return cache; +} + + +/* This function ensures that a keyval contains data when referencing a keyval + * created by parsing a Configuration ROM. */ +static inline struct csr1212_keyval *csr1212_get_keyval(struct csr1212_csr *csr, + struct csr1212_keyval *kv) +{ + if (!kv) + return NULL; + if (!kv->valid) + if (_csr1212_read_keyval(csr, kv) != CSR1212_SUCCESS) + return NULL; + return kv; +} + + +/* This function increments the reference count for a keyval should there be a + * need for code to retain a keyval that has been parsed. */ +static inline void csr1212_keep_keyval(struct csr1212_keyval *kv) +{ + kv->refcnt++; +} + + +/* This function decrements a keyval's reference count and will destroy the + * keyval when there are no more users of the keyval. This should be called by + * any code that calls csr1212_keep_keyval() or any of the keyval creation + * routines csr1212_new_*(). */ +static inline void csr1212_release_keyval(struct csr1212_keyval *kv) +{ + if (kv->refcnt > 1) + kv->refcnt--; + else + _csr1212_destroy_keyval(kv); +} + + +/* + * This macro allows for looping over the keyval entries in a directory and it + * ensures that keyvals from remote ConfigROMs are parsed properly. + * + * _csr is a struct csr1212_csr * that points to CSR associated with dir. + * _kv is a struct csr1212_keyval * that'll point to the current keyval (loop index). + * _dir is a struct csr1212_keyval * that points to the directory to be looped. + * _pos is a struct csr1212_dentry * that is used internally for indexing. + * + * kv will be NULL upon exit of the loop. + */ +#define csr1212_for_each_dir_entry(_csr, _kv, _dir, _pos) \ + for (csr1212_get_keyval((_csr), (_dir)), \ + _pos = (_dir)->value.directory.dentries_head, \ + _kv = (_pos) ? csr1212_get_keyval((_csr), _pos->kv) : NULL; \ + (_kv) && (_pos); \ + (_kv->associate == NULL) ? \ + ((_pos = _pos->next), \ + (_kv = (_pos) ? csr1212_get_keyval((_csr), _pos->kv) : \ + NULL)) : \ + (_kv = csr1212_get_keyval((_csr), _kv->associate))) + + + +#ifdef __cplusplus + } +#endif + +#endif /* __CSR1212_H__ */ Index: /tags/release_0_0_6/libfreebob/src/avplug.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/avplug.h (revision 151) +++ /tags/release_0_0_6/libfreebob/src/avplug.h (revision 151) @@ -0,0 +1,145 @@ +/* avplug.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef AVPLUG_H +#define AVPLUG_H + +#include "debugmodule/debugmodule.h" +#include "libfreebobavc/avc_definitions.h" + +#include + +class AvPlugCluster; +class ExtendedPlugInfoPlugChannelPositionSpecificData; + +class AvPlug { +public: + AvPlug(); + AvPlug( const AvPlug& rhs ); + virtual ~AvPlug(); + + plug_type_t getPlugType() + { return m_plugType; } + plug_id_t getPlugId() + { return m_plugId; } + subunit_type_t getSubunitType() + { return m_subunitType; } + subunit_id_t getSubunitId() + { return m_subunitId; } + const char* getName() + { return m_name.c_str(); } + plug_direction_t getPlugDirection() + { return m_direction; } + sampling_frequency_t getSamplingFrequency() + { return m_samplingFrequency; } + int getSampleRate(); // 22050, 24000, 32000, ... + int getNrOfChannels(); + int getNrOfStreams(); + + plug_type_t m_plugType; + plug_id_t m_plugId; + subunit_type_t m_subunitType; + subunit_id_t m_subunitId; + plug_direction_t m_direction; + std::string m_name; + nr_of_channels_t m_nrOfChannels; + sampling_frequency_t m_samplingFrequency; + + + // --- + // Channel & Cluster Info + struct ChannelInfo { + stream_position_t m_streamPosition; + stream_position_location_t m_location; + std::string m_name; + }; + typedef std::vector ChannelInfoVector; + + struct ClusterInfo { + int m_index; + port_type_t m_portType; + std::string m_name; + + nr_of_channels_t m_nrOfChannels; + ChannelInfoVector m_channelInfos; + stream_format_t m_streamFormat; + }; + typedef std::vector ClusterInfoVector; + + ClusterInfoVector m_clusterInfos; + + // --- + // Stream Format + struct FormatInfo { + FormatInfo() + : m_samplingFrequency( eSF_DontCare ) + , m_isSyncStream( false ) + , m_audioChannels( 0 ) + , m_midiChannels( 0 ) + , m_index( 0xff ) + {} + sampling_frequency_t m_samplingFrequency; + bool m_isSyncStream; + number_of_channels_t m_audioChannels; + number_of_channels_t m_midiChannels; + byte_t m_index; + }; + typedef std::vector FormatInfoVector; + + FormatInfoVector m_formatInfos; + // --- + + void debugOutputClusterInfos( int debugLevel ); + + bool copyClusterInfo(ExtendedPlugInfoPlugChannelPositionSpecificData& + channelPositionData ); + + ClusterInfo* getClusterInfoByIndex(int index); + ClusterInfoVector& getClusterInfos() + { return m_clusterInfos; } + + + DECLARE_DEBUG_MODULE; +}; + +typedef std::vector AvPlugVector; + +class AvPlugCluster { +public: + AvPlugCluster(); + virtual ~AvPlugCluster(); + + std::string m_name; + + AvPlugVector m_avPlugs; +}; + +class AvPlugConnection { +public: + AvPlugConnection(); + ~AvPlugConnection(); + + AvPlug* m_srcPlug; + AvPlug* m_destPlug; +}; + +typedef std::vector AvPlugConnectionVector; + +#endif Index: /tags/release_0_0_6/libfreebob/src/freebob.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/freebob.cpp (revision 153) +++ /tags/release_0_0_6/libfreebob/src/freebob.cpp (revision 153) @@ -0,0 +1,334 @@ +/* freebob.h + * Copyright (C) 2005 Pieter Palmers, Daniel Wagner + * + * This file is part of FreeBoB + * + * 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 Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include "config.h" + +#include "libfreebob/freebob.h" +#include "libfreebob/xmlparser.h" + +#include "debugmodule/debugmodule.h" +#include "fbtypes.h" +#include "devicemanager.h" +#include "avdevice.h" + +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DEBUG_MODULE; +IMPL_GLOBAL_DEBUG_MODULE( FreeBob, DEBUG_LEVEL_VERBOSE ); + +const char* +freebob_get_version() { + return PACKAGE_STRING; +} + +freebob_handle_t +freebob_new_handle( int port ) +{ + freebob_handle_t handle = new struct freebob_handle; + if (! handle ) { + debugFatal( "Could not allocate memory for new handle\n" ); + return 0; + } + + handle->m_deviceManager = new DeviceManager; + if ( !handle->m_deviceManager ) { + debugFatal( "Could not allocate device manager\n" ); + delete handle; + return 0; + } + if ( !handle->m_deviceManager->initialize( port ) ) { + debugFatal( "Could not initialize device manager\n" ); + delete handle->m_deviceManager; + delete handle; + return 0; + } + return handle; +} + +int +freebob_destroy_handle( freebob_handle_t freebob_handle ) +{ + delete freebob_handle->m_deviceManager; + delete freebob_handle; + return 0; +} + +int +freebob_discover_devices( freebob_handle_t freebob_handle ) +{ + return freebob_handle->m_deviceManager->discover()? 0 : -1; +} + +freebob_connection_info_t* +freebob_get_connection_info( freebob_handle_t freebob_handle, + int node_id, + enum freebob_direction direction ) +{ + xmlDocPtr doc; + doc = freebob_handle->m_deviceManager->getXmlDescription(); + if ( !doc ) { + debugFatal( "Could not get XML description\n" ); + return 0; + } + + return freebob_xmlparse_get_connection_info( doc, node_id, direction ); +} + +freebob_supported_stream_format_info_t* +freebob_get_supported_stream_format_info( freebob_handle_t freebob_handle, + int node_id, + enum freebob_direction direction ) +{ + xmlDocPtr doc; + doc = freebob_handle->m_deviceManager->getXmlDescription(); + if ( !doc ) { + debugFatal( "Could not get XML description\n" ); + return 0; + } + + return freebob_xmlparse_get_stream_formats( doc, node_id, direction ); +} + +int +freebob_node_is_valid_freebob_device( freebob_handle_t freebob_handle, int node_id ) +{ + return freebob_handle->m_deviceManager->isValidNode( node_id ); +} + +int +freebob_get_nb_devices_on_bus( freebob_handle_t freebob_handle ) +{ + return freebob_handle->m_deviceManager->getNbDevices(); +} + +int +freebob_get_device_node_id( freebob_handle_t freebob_handle, int device_nr ) +{ + return freebob_handle->m_deviceManager->getDeviceNodeId(device_nr); +} + +int +freebob_set_samplerate( freebob_handle_t freebob_handle, int node_id, int samplerate ) +{ + AvDevice* avDevice = freebob_handle->m_deviceManager->getAvDevice( node_id ); + if ( avDevice ) { + if ( avDevice->setSamplingFrequency( parseSampleRate( samplerate ) ) ) { + return freebob_handle->m_deviceManager->discover()? 1 : 0; + } + } + return 0; +} + +void +freebob_free_connection_info( freebob_connection_info_t* connection_info ) +{ + if ( !connection_info ) { + return; + } + + for ( int i = 0; i < connection_info->nb_connections; ++i ) { + freebob_free_connection_spec( connection_info->connections[i] ); + } + + free( connection_info->connections ); + free( connection_info ); +} + +void +freebob_free_connection_spec( freebob_connection_spec_t* connection_spec ) +{ + if ( !connection_spec ) { + return; + } + + freebob_free_stream_info( connection_spec->stream_info ); + free( connection_spec ); +} + +void freebob_free_stream_info( freebob_stream_info_t* stream_info ) +{ + if ( !stream_info ) { + return; + } + + for ( int i = 0; i < stream_info->nb_streams; ++i ) { + freebob_free_stream_spec( stream_info->streams[i] ); + } + + free(stream_info->streams); + free(stream_info); +} + +void freebob_free_stream_spec( freebob_stream_spec_t* stream_spec ) +{ + if ( !stream_spec ) { + return; + } + + free( stream_spec ); +} + +void +freebob_free_supported_stream_format_info( freebob_supported_stream_format_info_t* stream_info ) +{ + if ( !stream_info ) { + return; + } + + for ( int i = 0; i < stream_info->nb_formats; ++i ) { + freebob_free_supported_stream_format_spec( stream_info->formats[i] ); + } + + free(stream_info->formats); + free(stream_info); +} + +void +freebob_free_supported_stream_format_spec( freebob_supported_stream_format_spec_t* stream_spec ) +{ + if ( !stream_spec ) { + return; + } + + free( stream_spec ); +} + +void +freebob_print_connection_info( freebob_connection_info_t* connection_info ) +{ + if ( !connection_info ) { + fprintf( stderr, "connection_info==NULL\n" ); + return; + } + + printf( "Direction: %d (%s)\n\n", connection_info->direction, + connection_info->direction? "playback" : "capture" ); + + puts( "Connection Info" ); + puts( "===============\n" ); + + printf("Number of connections: %d\n\n", + connection_info->nb_connections ); + + for ( int i = 0; i < connection_info->nb_connections; ++i) { + freebob_connection_spec_t* connection_spec + = connection_info->connections[i]; + + + if ( connection_spec ) { + printf( " Connection %2d\n", i ); + printf( " -------------\n" ); + printf( " [%2d] Id: %d\n", i, connection_spec->id ); + printf( " [%2d] Port: %d\n", i, connection_spec->port ); + printf( " [%2d] Node: %d\n", i, connection_spec->node ); + printf( " [%2d] Plug: %d\n", i, connection_spec->plug ); + printf( " [%2d] Dimension: %d\n", i, connection_spec->dimension ); + printf( " [%2d] Samplerate: %d\n", i, connection_spec->samplerate ); + printf( " [%2d] IsoChannel: %d\n", i, connection_spec->iso_channel ); + printf( " [%2d] IsMaster: %d\n", i, connection_spec->is_master ); + + if ( connection_info->connections[i]->stream_info ) { + printf(" [%2d] Number of stream infos: %d\n\n", + i, connection_spec->stream_info->nb_streams ); + + printf(" StreamId Position Location Format Type DPort Name\n"); + printf(" --------------------------------------------------\n"); + + for ( int j = 0; + j < connection_spec->stream_info->nb_streams; + ++j ) + { + freebob_stream_spec_t* stream_spec + = connection_spec->stream_info->streams[j]; + + printf(" [%2d]:[%2d] " + "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x %s\n", + i, j, + stream_spec->position, + stream_spec->location, + stream_spec->format, + stream_spec->type, + stream_spec->destination_port, + stream_spec->name ); + } + } + } + printf( "\n" ); + } + + return; +} + +void +freebob_print_supported_stream_format_info( freebob_supported_stream_format_info_t* stream_info ) +{ + if ( !stream_info ) { + fprintf( stderr, "stream_info==NULL\n" ); + return; + } + + printf( "Direction: %d (%s)\n\n", stream_info->direction, + stream_info->direction? "playback" : "capture" ); + + printf( "Samplerate AudioChannels MidiChannels\n" ); + printf( "-------------------------------------\n" ); + for ( int i = 0; i < stream_info->nb_formats; ++i) { + freebob_supported_stream_format_spec_t* format_spec + = stream_info->formats[i]; + + if ( format_spec ) { + printf( "%05d %02d %02d\n", + format_spec->samplerate, + format_spec->nb_audio_channels, + format_spec->nb_midi_channels ); + } + } + + return; +} + +/* debug function */ +void +freebob_print_xml_description( freebob_handle_t freebob_handle, + int node_id, + enum freebob_direction direction ) +{ + xmlDocPtr doc; + doc = freebob_handle->m_deviceManager->getXmlDescription(); + if ( !doc ) { + debugFatal( "Could not get XML description\n" ); + return; + } + + xmlChar* xmlbuff; + int buffersize; + xmlDocDumpFormatMemory( doc, &xmlbuff, &buffersize, 1 ); + + printf("%s\n",(char *)xmlbuff); + + xmlFree(xmlbuff); + xmlFree(doc); + return; +} Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_plug_info.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_plug_info.h (revision 125) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_plug_info.h (revision 125) @@ -0,0 +1,311 @@ +/* avc_extended_plug_info.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef AVCEXTENDEDPLUGINFO_H +#define AVCEXTENDEDPLUGINFO_H + +#include "avc_extended_cmd_generic.h" +#include "avc_generic.h" + +#include + +#include +#include + +class ExtendedPlugInfoPlugTypeSpecificData : public IBusData +{ +public: + enum EExtendedPlugInfoPlugType { + eEPIPT_IsoStream = 0x0, + eEPIPT_AsyncStream = 0x1, + eEPIPT_Midi = 0x2, + eEPIPT_Sync = 0x3, + eEPIPT_Analog = 0x4, + eEPIPT_Digital = 0x5, + + eEPIPT_Unknown = 0x6, + }; + + ExtendedPlugInfoPlugTypeSpecificData( EExtendedPlugInfoPlugType ePlugType = eEPIPT_Unknown); + virtual ~ExtendedPlugInfoPlugTypeSpecificData(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual ExtendedPlugInfoPlugTypeSpecificData* clone() const; + + typedef byte_t plug_type_t; + + plug_type_t m_plugType; +}; + +const char* extendedPlugInfoPlugTypeToString( plug_type_t plugType ); + +///////////////////////////////////////// + +class ExtendedPlugInfoPlugNameSpecificData : public IBusData +{ +public: + ExtendedPlugInfoPlugNameSpecificData(); + virtual ~ExtendedPlugInfoPlugNameSpecificData(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual ExtendedPlugInfoPlugNameSpecificData* clone() const; + + std::string m_name; +}; + +///////////////////////////////////////// + +class ExtendedPlugInfoPlugNumberOfChannelsSpecificData : public IBusData +{ +public: + ExtendedPlugInfoPlugNumberOfChannelsSpecificData(); + virtual ~ExtendedPlugInfoPlugNumberOfChannelsSpecificData(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual ExtendedPlugInfoPlugNumberOfChannelsSpecificData* clone() const; + + nr_of_channels_t m_nrOfChannels; +}; + + +///////////////////////////////////////// + +class ExtendedPlugInfoPlugChannelPositionSpecificData : public IBusData +{ +public: + enum ELocation { + eEPI_LeftFront = 0x01, + eEPI_RightFront = 0x02, + eEPI_Center = 0x03, + eEPI_Subwoofer = 0x04, + eEPI_LeftSurround = 0x05, + eEPI_RightSurround = 0x06, + eEPI_LeftOfCenter = 0x07, + eEPI_RightOfCenter = 0x08, + eEPI_Surround = 0x09, + eEPI_SideLeft = 0x0a, + eEPI_SideRight = 0x0b, + eEPI_Top = 0x0c, + eEPI_Bottom = 0x0d, + eEPI_LeftFrontEffect = 0x0e, + eEPI_RightFrontEffect = 0x0f, + eEPI_NoPostion = 0xff, + }; + + struct ChannelInfo { + stream_position_t m_streamPosition; + stream_position_location_t m_location; + }; + + typedef std::vector ChannelInfoVector; + + struct ClusterInfo { + nr_of_channels_t m_nrOfChannels; + ChannelInfoVector m_channelInfos; + }; + + ExtendedPlugInfoPlugChannelPositionSpecificData(); + virtual ~ExtendedPlugInfoPlugChannelPositionSpecificData(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual ExtendedPlugInfoPlugChannelPositionSpecificData* clone() const; + + typedef std::vector ClusterInfoVector; + + nr_of_clusters_t m_nrOfClusters; + ClusterInfoVector m_clusterInfos; +}; + +///////////////////////////////////////// + +class ExtendedPlugInfoPlugChannelNameSpecificData : public IBusData +{ +public: + ExtendedPlugInfoPlugChannelNameSpecificData(); + virtual ~ExtendedPlugInfoPlugChannelNameSpecificData(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual ExtendedPlugInfoPlugChannelNameSpecificData* clone() const; + + stream_position_t m_streamPosition; + string_length_t m_stringLength; + std::string m_plugChannelName; +}; + +///////////////////////////////////////// + +class ExtendedPlugInfoPlugInputSpecificData : public IBusData +{ +public: + ExtendedPlugInfoPlugInputSpecificData(); + ExtendedPlugInfoPlugInputSpecificData( const ExtendedPlugInfoPlugInputSpecificData& rhs ); + virtual ~ExtendedPlugInfoPlugInputSpecificData(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual ExtendedPlugInfoPlugInputSpecificData* clone() const; + + PlugAddressSpecificData* m_plugAddress; +}; + + +///////////////////////////////////////// + +class ExtendedPlugInfoPlugOutputSpecificData : public IBusData +{ +public: + ExtendedPlugInfoPlugOutputSpecificData(); + ExtendedPlugInfoPlugOutputSpecificData( const ExtendedPlugInfoPlugOutputSpecificData& rhs ); + virtual ~ExtendedPlugInfoPlugOutputSpecificData(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual ExtendedPlugInfoPlugOutputSpecificData* clone() const; + + number_of_output_plugs_t m_nrOfOutputPlugs; + + typedef std::vector PlugAddressVector; + PlugAddressVector m_outputPlugAddresses; +}; + +///////////////////////////////////////// + +class ExtendedPlugInfoClusterInfoSpecificData : public IBusData +{ +public: + enum EPortType { + ePT_Speaker = 0x00, + ePT_Headphone = 0x01, + ePT_Microphone = 0x02, + ePT_Line = 0x03, + ePT_SPDIF = 0x04, + ePT_ADAT = 0x05, + ePT_TDIF = 0x06, + ePT_MADI = 0x07, + ePT_Analog = 0x08, + ePT_Digital = 0x09, + ePT_MIDI = 0x0a, + ePT_NoType = 0xff, + }; + + ExtendedPlugInfoClusterInfoSpecificData(); + virtual ~ExtendedPlugInfoClusterInfoSpecificData(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual ExtendedPlugInfoClusterInfoSpecificData* clone() const; + + cluster_index_t m_clusterIndex; + port_type_t m_portType; + string_length_t m_stringLength; + std::string m_clusterName; +}; + +const char* extendedPlugInfoClusterInfoPortTypeToString( port_type_t portType ); + +///////////////////////////////////////// + +#define AVC1394_EXTENDED_PLUG_INFO_INFO_TYPE_PLUG_TYPE 0x00 +#define AVC1394_EXTENDED_PLUG_INFO_INFO_TYPE_PLUG_NAME 0x01 +#define AVC1394_EXTENDED_PLUG_INFO_INFO_TYPE_PLUG_NO_OF_CHANNELS 0x02 +#define AVC1394_EXTENDED_PLUG_INFO_INFO_TYPE_PLUG_CHANNEL_POSITION 0x03 +#define AVC1394_EXTENDED_PLUG_INFO_INFO_TYPE_PLUG_CHANNEL_NAME 0x04 +#define AVC1394_EXTENDED_PLUG_INFO_INFO_TYPE_PLUG_INPUT 0x05 +#define AVC1394_EXTENDED_PLUG_INFO_INFO_TYPE_PLUG_OUTPUT 0x06 +#define AVC1394_EXTENDED_PLUG_INFO_INFO_TYPE_PLUG_CLUSTER_INFO 0x07 + +class ExtendedPlugInfoInfoType : public IBusData +{ +public: + enum EInfoType { + eIT_PlugType = AVC1394_EXTENDED_PLUG_INFO_INFO_TYPE_PLUG_TYPE, + eIT_PlugName = AVC1394_EXTENDED_PLUG_INFO_INFO_TYPE_PLUG_NAME, + eIT_NoOfChannels = AVC1394_EXTENDED_PLUG_INFO_INFO_TYPE_PLUG_NO_OF_CHANNELS, + eIT_ChannelPosition = AVC1394_EXTENDED_PLUG_INFO_INFO_TYPE_PLUG_CHANNEL_POSITION, + eIT_ChannelName = AVC1394_EXTENDED_PLUG_INFO_INFO_TYPE_PLUG_CHANNEL_NAME, + eIT_PlugInput = AVC1394_EXTENDED_PLUG_INFO_INFO_TYPE_PLUG_INPUT, + eIT_PlugOutput = AVC1394_EXTENDED_PLUG_INFO_INFO_TYPE_PLUG_OUTPUT, + eIT_ClusterInfo = AVC1394_EXTENDED_PLUG_INFO_INFO_TYPE_PLUG_CLUSTER_INFO, + }; + + ExtendedPlugInfoInfoType(EInfoType eInfoType); + virtual ~ExtendedPlugInfoInfoType(); + + bool initialize(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual ExtendedPlugInfoInfoType* clone() const; + + typedef byte_t info_type_t; + info_type_t m_infoType; + + ExtendedPlugInfoPlugTypeSpecificData* m_plugType; + ExtendedPlugInfoPlugNameSpecificData* m_plugName; + ExtendedPlugInfoPlugNumberOfChannelsSpecificData* m_plugNrOfChns; + ExtendedPlugInfoPlugChannelPositionSpecificData* m_plugChannelPosition; + ExtendedPlugInfoPlugChannelNameSpecificData* m_plugChannelName; + ExtendedPlugInfoPlugInputSpecificData* m_plugInput; + ExtendedPlugInfoPlugOutputSpecificData* m_plugOutput; + ExtendedPlugInfoClusterInfoSpecificData* m_plugClusterInfo; +}; + +///////////////////////////////////////////////////////// + +#define AVC1394_PLUG_INFO_SUBFUNCTION_EXTENDED_PLUG_INFO_CMD 0xC0 +#define AVC1394_PLUG_INFO_SUBFUNCTION_SERIAL_BUS_NOT_USED 0xFF + + +class ExtendedPlugInfoCmd: public AVCCommand +{ +public: + enum ESubFunction { + eSF_ExtendedPlugInfoCmd = AVC1394_PLUG_INFO_SUBFUNCTION_EXTENDED_PLUG_INFO_CMD, + eSF_NotUsed = AVC1394_PLUG_INFO_SUBFUNCTION_SERIAL_BUS_NOT_USED, + }; + + ExtendedPlugInfoCmd( Ieee1394Service* ieee1394service, + ESubFunction eSubFunction = eSF_ExtendedPlugInfoCmd ); + virtual ~ExtendedPlugInfoCmd(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + + virtual bool fire(); + + bool setPlugAddress( const PlugAddress& plugAddress ); + bool setSubFunction( ESubFunction subFunction ); + bool setInfoType( const ExtendedPlugInfoInfoType& infoType ); + ExtendedPlugInfoInfoType* getInfoType() + { return m_infoType; } + +protected: + subfunction_t m_subFunction; + PlugAddress* m_plugAddress; + ExtendedPlugInfoInfoType* m_infoType; +}; + + +#endif Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_subunit_info.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_subunit_info.h (revision 125) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_subunit_info.h (revision 125) @@ -0,0 +1,72 @@ +/* avc_subunit_info.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef AVCSubUnitInfo_h +#define AVCSubUnitInfo_h + +#include "avc_generic.h" + +#include + + +// No extended subunit queries supported + +class SubUnitInfoCmd: public AVCCommand +{ +public: + SubUnitInfoCmd( Ieee1394Service* ieee1349service ); + virtual ~SubUnitInfoCmd(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + + virtual bool fire(); + + bool clear(); + + page_t m_page; + extension_code_t m_extension_code; + + + + enum { + eMaxSubunitsPerPage = 4, + eMaxSubunitsPerUnit = 32, + }; + + struct TableEntry { + subunit_type_t m_subunit_type; + max_subunit_id_t m_max_subunit_id; + }; + + struct TableEntry m_table[eMaxSubunitsPerPage]; + + short getMaxNoOfPages() + { return eMaxSubunitsPerUnit / eMaxSubunitsPerPage; } + + + short m_nrOfValidEntries; + short getNrOfValidEntries() + { return m_nrOfValidEntries; } + +}; + + +#endif // AVCSubUnitInfo_h Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_definitions.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_definitions.cpp (revision 156) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_definitions.cpp (revision 156) @@ -0,0 +1,140 @@ +/* avc_defintions.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "avc_definitions.h" + + +int +convertESamplingFrequency(ESamplingFrequency freq) +{ + int value = 0; + + switch ( freq ) { + case eSF_22050Hz: + value = 22050; + break; + case eSF_24000Hz: + value = 24000; + break; + case eSF_32000Hz: + value = 32000; + break; + case eSF_44100Hz: + value = 44100; + break; + case eSF_48000Hz: + value = 48000; + break; + case eSF_88200Hz: + value = 88200; + break; + case eSF_96000Hz: + value = 96000; + break; + case eSF_176400Hz: + value = 176400; + break; + case eSF_192000Hz: + value = 192000; + break; + default: + value = 0; + } + + + return value; +} + +ESamplingFrequency +parseSampleRate( int sampleRate ) +{ + ESamplingFrequency efreq; + switch ( sampleRate ) { + case 22050: + efreq = eSF_22050Hz; + break; + case 24000: + efreq = eSF_24000Hz; + break; + case 32000: + efreq = eSF_32000Hz; + break; + case 44100: + efreq = eSF_44100Hz; + break; + case 48000: + efreq = eSF_48000Hz; + break; + case 88200: + efreq = eSF_88200Hz; + break; + case 96000: + efreq = eSF_96000Hz; + break; + case 176400: + efreq = eSF_176400Hz; + break; + case 192000: + efreq = eSF_192000Hz; + break; + default: + efreq = eSF_DontCare; + } + + return efreq; +} + +std::ostream& operator<<( std::ostream& stream, ESamplingFrequency samplingFrequency ) +{ + char* str; + switch ( samplingFrequency ) { + case eSF_22050Hz: + str = "22050"; + break; + case eSF_24000Hz: + str = "24000"; + break; + case eSF_32000Hz: + str = "32000"; + break; + case eSF_44100Hz: + str = "44100"; + break; + case eSF_48000Hz: + str = "48000"; + break; + case eSF_88200Hz: + str = "88200"; + break; + case eSF_96000Hz: + str = "96000"; + break; + case eSF_176400Hz: + str = "176400"; + break; + case eSF_192000Hz: + str = "192000"; + break; + case eSF_DontCare: + default: + str = "unknown"; + } + return stream << str; +}; Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_generic.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_generic.cpp (revision 125) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_generic.cpp (revision 125) @@ -0,0 +1,156 @@ +/* avc_generic.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "avc_generic.h" +#include "serialize.h" +#include "ieee1394service.h" + +AVCCommand::AVCCommand( Ieee1394Service* ieee1394service, + opcode_t opcode ) + : m_1394Service( ieee1394service ) + , m_nodeId( 0 ) + , m_ctype( eCT_Unknown ) + , m_subunit( 0xff ) + , m_opcode( opcode ) + , m_eResponse( eR_Unknown ) + , m_verbose( false ) +{ +} + +bool +AVCCommand::serialize( IOSSerialize& se ) +{ + se.write( m_ctype, "AVCCommand ctype" ); + se.write( m_subunit, "AVCCommand subunit" ); + se.write( m_opcode, "AVCCommand opcode" ); + return true; +} + +bool +AVCCommand::deserialize( IISDeserialize& de ) +{ + de.read( &m_ctype ); + de.read( &m_subunit ); + de.read( &m_opcode ); + return true; +} + +bool +AVCCommand::setCommandType( ECommandType commandType ) +{ + m_ctype = commandType; + m_commandType = commandType; + return true; +} + +AVCCommand::ECommandType +AVCCommand::getCommandType() +{ + return m_commandType; +} + +AVCCommand::EResponse +AVCCommand::getResponse() +{ + return m_eResponse; +} + +bool +AVCCommand::parseResponse( byte_t response ) +{ + m_eResponse = static_cast( response ); + return true; +} + +bool +AVCCommand::setSubunitType(ESubunitType subunitType) +{ + byte_t subT = subunitType; + + m_subunit = ( subT << 3 ) | ( m_subunit & 0x7 ); + return true; +} + +bool +AVCCommand::setNodeId( fb_nodeid_t nodeId ) +{ + m_nodeId = nodeId; + return true; +} + +bool +AVCCommand::setSubunitId(subunit_id_t subunitId) +{ + m_subunit = ( subunitId & 0x7 ) | ( m_subunit & 0xf8 ); + return true; +} + +AVCCommand::ESubunitType +AVCCommand::getSubunitType() +{ + return static_cast( ( m_subunit >> 3 ) ); +} + +subunit_id_t +AVCCommand::getSubunitId() +{ + return m_subunit & 0x7; +} + +bool +AVCCommand::setVerbose( bool enable ) +{ + m_verbose = enable; + return true; +} + +bool +AVCCommand::isVerbose() +{ + return m_verbose; +} + + +const char* subunitTypeStrings[] = +{ + "Monitor", + "Audio", + "Printer", + "Disc recorder", + "Tape recorder/VCR", + "Tuner", + "CA", + "Video camera", + "unknown", + "Panel", + "Bulletin board", + "Camera storage", + "Music", +}; + +const char* +subunitTypeToString( subunit_type_t subunitType ) +{ + if ( subunitType > sizeof( subunitTypeStrings ) ) { + return "unknown"; + } else { + return subunitTypeStrings[subunitType]; + } +} Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_cmd_generic.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_cmd_generic.cpp (revision 125) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_cmd_generic.cpp (revision 125) @@ -0,0 +1,431 @@ +/* avc_extended_cmd_generic.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "avc_extended_cmd_generic.h" +#include "serialize.h" +#include "ieee1394service.h" + +UnitPlugAddress::UnitPlugAddress( EPlugType plugType, plug_type_t plugId ) + : m_plugType( plugType ) + , m_plugId( plugId ) + , m_reserved( 0xff ) +{ +} + +UnitPlugAddress::~UnitPlugAddress() +{ +} + +bool +UnitPlugAddress::serialize( IOSSerialize& se ) +{ + se.write( m_plugType, "UnitPlugAddress plugType" ); + se.write( m_plugId, "UnitPlugAddress plugId" ); + se.write( m_reserved, "UnitPlugAddress reserved" ); + return true; +} + +bool +UnitPlugAddress::deserialize( IISDeserialize& de ) +{ + de.read( &m_plugType ); + de.read( &m_plugId ); + de.read( &m_reserved ); + return true; +} + +UnitPlugAddress* +UnitPlugAddress::clone() const +{ + return new UnitPlugAddress( *this ); +} + +//////////////////////////////////////////////////////////// + +SubunitPlugAddress::SubunitPlugAddress( plug_id_t plugId ) + : m_plugId( plugId ) + , m_reserved0( 0xff ) + , m_reserved1( 0xff ) +{ +} + +SubunitPlugAddress::~SubunitPlugAddress() +{ +} + +bool +SubunitPlugAddress::serialize( IOSSerialize& se ) +{ + se.write( m_plugId, "SubunitPlugAddress plugId" ); + se.write( m_reserved0, "SubunitPlugAddress reserved0" ); + se.write( m_reserved1, "SubunitPlugAddress reserved1" ); + return true; +} + +bool +SubunitPlugAddress::deserialize( IISDeserialize& de ) +{ + de.read( &m_plugId ); + de.read( &m_reserved0 ); + de.read( &m_reserved1 ); + return true; +} + +SubunitPlugAddress* +SubunitPlugAddress::clone() const +{ + return new SubunitPlugAddress( *this ); +} + +//////////////////////////////////////////////////////////// + +FunctionBlockPlugAddress::FunctionBlockPlugAddress( function_block_type_t functionBlockType, + function_block_id_t functionBlockId, + plug_id_t plugId ) + : m_functionBlockType( functionBlockType ) + , m_functionBlockId( functionBlockId ) + , m_plugId( plugId ) +{ +} + +FunctionBlockPlugAddress::~FunctionBlockPlugAddress() +{ +} + +bool +FunctionBlockPlugAddress::serialize( IOSSerialize& se ) +{ + se.write( m_functionBlockType, "FunctionBlockPlugAddress functionBlockType" ); + se.write( m_functionBlockId, "FunctionBlockPlugAddress functionBlockId" ); + se.write( m_plugId, "FunctionBlockPlugAddress plugId" ); + return true; +} + +bool +FunctionBlockPlugAddress::deserialize( IISDeserialize& de ) +{ + de.read( &m_functionBlockType ); + de.read( &m_functionBlockId ); + de.read( &m_plugId ); + return true; +} + +FunctionBlockPlugAddress* +FunctionBlockPlugAddress:: clone() const +{ + return new FunctionBlockPlugAddress( *this ); +} + +//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// + +UnitPlugSpecificDataPlugAddress::UnitPlugSpecificDataPlugAddress( EPlugType plugType, plug_type_t plugId ) + : m_plugType( plugType ) + , m_plugId( plugId ) + , m_reserved0( 0xff ) + , m_reserved1( 0xff ) + , m_reserved2( 0xff ) +{ +} + +UnitPlugSpecificDataPlugAddress::~UnitPlugSpecificDataPlugAddress() +{ +} + +bool +UnitPlugSpecificDataPlugAddress::serialize( IOSSerialize& se ) +{ + se.write( m_plugType, "UnitPlugSpecificDataPlugAddress plugType" ); + se.write( m_plugId, "UnitPlugSpecificDataPlugAddress plugId" ); + se.write( m_reserved0, "UnitPlugSpecificDataPlugAddress reserved0" ); + se.write( m_reserved1, "UnitPlugSpecificDataPlugAddress reserved1" ); + se.write( m_reserved2, "UnitPlugSpecificDataPlugAddress reserved2" ); + return true; +} + +bool +UnitPlugSpecificDataPlugAddress::deserialize( IISDeserialize& de ) +{ + de.read( &m_plugType ); + de.read( &m_plugId ); + de.read( &m_reserved0 ); + de.read( &m_reserved1 ); + de.read( &m_reserved2 ); + return true; +} + +UnitPlugSpecificDataPlugAddress* +UnitPlugSpecificDataPlugAddress::clone() const +{ + return new UnitPlugSpecificDataPlugAddress( *this ); +} + +//////////////////////////////////////////////////////////// + +SubunitPlugSpecificDataPlugAddress::SubunitPlugSpecificDataPlugAddress( + AVCCommand::ESubunitType subunitType, + subunit_id_t subunitId, + plug_id_t plugId ) + : m_subunitType( subunitType ) + , m_subunitId( subunitId ) + , m_plugId( plugId ) + , m_reserved0( 0xff ) + , m_reserved1( 0xff ) +{ +} + +SubunitPlugSpecificDataPlugAddress::~SubunitPlugSpecificDataPlugAddress() +{ +} + +bool +SubunitPlugSpecificDataPlugAddress::serialize( IOSSerialize& se ) +{ + se.write( m_subunitType, "SubunitPlugSpecificDataPlugAddress subunitType" ); + se.write( m_subunitId, "SubunitPlugSpecificDataPlugAddress subunitId" ); + se.write( m_plugId, "SubunitPlugSpecificDataPlugAddress plugId" ); + se.write( m_reserved0, "SubunitPlugSpecificDataPlugAddress reserved0" ); + se.write( m_reserved1, "SubunitPlugSpecificDataPlugAddress reserved1" ); + return true; +} + +bool +SubunitPlugSpecificDataPlugAddress::deserialize( IISDeserialize& de ) +{ + de.read( &m_subunitType ); + de.read( &m_subunitId ); + de.read( &m_plugId ); + de.read( &m_reserved0 ); + de.read( &m_reserved1 ); + return true; +} + +SubunitPlugSpecificDataPlugAddress* +SubunitPlugSpecificDataPlugAddress::clone() const +{ + return new SubunitPlugSpecificDataPlugAddress( *this ); +} + +//////////////////////////////////////////////////////////// + +FunctionBlockPlugSpecificDataPlugAddress::FunctionBlockPlugSpecificDataPlugAddress( + AVCCommand::ESubunitType subunitType, + subunit_id_t subunitId, + function_block_type_t functionBlockType, + function_block_id_t functionBlockId, + plug_id_t plugId ) + : m_subunitType( subunitType ) + , m_subunitId( subunitId ) + , m_functionBlockType( functionBlockType ) + , m_functionBlockId( functionBlockId ) + , m_plugId( plugId ) +{ +} + +FunctionBlockPlugSpecificDataPlugAddress::~FunctionBlockPlugSpecificDataPlugAddress() +{ +} + +bool +FunctionBlockPlugSpecificDataPlugAddress::serialize( IOSSerialize& se ) +{ + se.write( m_subunitType, "FunctionPlugSpecificDataBlockPlugAddress subunitType" ); + se.write( m_subunitId, "FunctionPlugSpecificDataBlockPlugAddress subunitId" ); + se.write( m_functionBlockType, "FunctionBlockPlugSpecificDataPlugAddress functionBlockType" ); + se.write( m_functionBlockId, "FunctionBlockPlugSpecificDataPlugAddress functionBlockId" ); + se.write( m_plugId, "FunctionBlockPlugSpecificDataPlugAddress plugId" ); + return true; +} + +bool +FunctionBlockPlugSpecificDataPlugAddress::deserialize( IISDeserialize& de ) +{ + de.read( &m_subunitType ); + de.read( &m_subunitId ); + de.read( &m_functionBlockType ); + de.read( &m_functionBlockId ); + de.read( &m_plugId ); + return true; +} + +FunctionBlockPlugSpecificDataPlugAddress* +FunctionBlockPlugSpecificDataPlugAddress:: clone() const +{ + return new FunctionBlockPlugSpecificDataPlugAddress( *this ); +} + +//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// + +PlugAddress::PlugAddress( EPlugDirection plugDirection, + EPlugAddressMode plugAddressMode, + UnitPlugAddress& unitPlugAddress ) + : m_plugDirection( plugDirection ) + , m_addressMode( plugAddressMode ) + , m_plugAddressData( new UnitPlugAddress( unitPlugAddress ) ) +{ +} + +PlugAddress::PlugAddress( EPlugDirection plugDirection, + EPlugAddressMode plugAddressMode, + SubunitPlugAddress& subUnitPlugAddress ) + : m_plugDirection( plugDirection ) + , m_addressMode( plugAddressMode ) + , m_plugAddressData( new SubunitPlugAddress( subUnitPlugAddress ) ) +{ +} + +PlugAddress::PlugAddress( EPlugDirection plugDirection, + EPlugAddressMode plugAddressMode, + FunctionBlockPlugAddress& functionBlockPlugAddress ) + : m_plugDirection( plugDirection ) + , m_addressMode( plugAddressMode ) + , m_plugAddressData( new FunctionBlockPlugAddress( functionBlockPlugAddress ) ) +{ +} + +PlugAddress::PlugAddress( const PlugAddress& pa ) + : m_plugDirection( pa.m_plugDirection ) + , m_addressMode( pa.m_addressMode ) + , m_plugAddressData( dynamic_cast( pa.m_plugAddressData->clone() ) ) +{ +} + +PlugAddress::~PlugAddress() +{ + delete m_plugAddressData; + m_plugAddressData = 0; +} + +bool +PlugAddress::serialize( IOSSerialize& se ) +{ + se.write( m_plugDirection, "PlugAddress plugDirection" ); + se.write( m_addressMode, "PlugAddress addressMode" ); + return m_plugAddressData->serialize( se ); +} + +bool +PlugAddress::deserialize( IISDeserialize& de ) +{ + de.read( &m_plugDirection ); + de.read( &m_addressMode ); + return m_plugAddressData->deserialize( de ); +} + +PlugAddress* +PlugAddress::clone() const +{ + return new PlugAddress( *this ); +} + +//////////////////////////////////////////////////////////// + +PlugAddressSpecificData::PlugAddressSpecificData( EPlugDirection plugDirection, + EPlugAddressMode plugAddressMode, + UnitPlugSpecificDataPlugAddress& unitPlugAddress ) + : m_plugDirection( plugDirection ) + , m_addressMode( plugAddressMode ) + , m_plugAddressData( new UnitPlugSpecificDataPlugAddress( unitPlugAddress ) ) +{ +} + +PlugAddressSpecificData::PlugAddressSpecificData( EPlugDirection plugDirection, + EPlugAddressMode plugAddressMode, + SubunitPlugSpecificDataPlugAddress& subUnitPlugAddress ) + : m_plugDirection( plugDirection ) + , m_addressMode( plugAddressMode ) + , m_plugAddressData( new SubunitPlugSpecificDataPlugAddress( subUnitPlugAddress ) ) +{ +} + +PlugAddressSpecificData::PlugAddressSpecificData( EPlugDirection plugDirection, + EPlugAddressMode plugAddressMode, + FunctionBlockPlugSpecificDataPlugAddress& functionBlockPlugAddress ) + : m_plugDirection( plugDirection ) + , m_addressMode( plugAddressMode ) + , m_plugAddressData( new FunctionBlockPlugSpecificDataPlugAddress( functionBlockPlugAddress ) ) +{ +} + +PlugAddressSpecificData::PlugAddressSpecificData( const PlugAddressSpecificData& pa ) + : m_plugDirection( pa.m_plugDirection ) + , m_addressMode( pa.m_addressMode ) + , m_plugAddressData( dynamic_cast( pa.m_plugAddressData->clone() ) ) +{ +} + +PlugAddressSpecificData::~PlugAddressSpecificData() +{ + delete m_plugAddressData; + m_plugAddressData = 0; +} + +bool +PlugAddressSpecificData::serialize( IOSSerialize& se ) +{ + se.write( m_plugDirection, "PlugAddressSpecificData plugDirection" ); + se.write( m_addressMode, "PlugAddressSpecificData addressMode" ); + return m_plugAddressData->serialize( se ); +} + +bool +PlugAddressSpecificData::deserialize( IISDeserialize& de ) +{ + de.read( &m_plugDirection ); + de.read( &m_addressMode ); + if ( m_plugAddressData ) { + delete m_plugAddressData; + } + switch ( m_addressMode ) { + case ePAM_Unit: + m_plugAddressData = + new UnitPlugSpecificDataPlugAddress( + UnitPlugSpecificDataPlugAddress::ePT_PCR, + 0xff ); + break; + case ePAM_Subunit: + m_plugAddressData = + new SubunitPlugSpecificDataPlugAddress( + AVCCommand::eST_Reserved, + 0xff, + 0xff ); + break; + case ePAM_FunctionBlock: + m_plugAddressData = + new FunctionBlockPlugSpecificDataPlugAddress( + AVCCommand::eST_Reserved, + 0xff, + 0xff, + 0xff, + 0xff); + break; + } + + return m_plugAddressData->deserialize( de ); +} + +PlugAddressSpecificData* +PlugAddressSpecificData::clone() const +{ + return new PlugAddressSpecificData( *this ); +} + + Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_definitions.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_definitions.h (revision 156) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_definitions.h (revision 156) @@ -0,0 +1,93 @@ +/* avc_definitions.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef AVCDefinitions_h +#define AVCDefinitions_h + +#include +#include + +typedef byte_t ctype_t; +typedef byte_t unit_t; +typedef byte_t unit_type_t; +typedef byte_t subunit_t; +typedef byte_t opcode_t; +typedef byte_t plug_type_t; +typedef byte_t plug_id_t; +typedef byte_t reserved_t; +typedef byte_t function_block_type_t; +typedef byte_t function_block_id_t; +typedef byte_t plug_direction_t; +typedef byte_t plug_address_mode_t; +typedef byte_t status_t; +typedef byte_t number_of_channels_t; +typedef byte_t stream_format_t; +typedef byte_t sampling_frequency_t; +typedef byte_t rate_control_t; +typedef byte_t number_of_stream_format_infos_t; +typedef byte_t nr_of_plugs_t; +typedef byte_t subunit_id_t; +typedef byte_t subfunction_t; +typedef byte_t opcode_t; +typedef byte_t page_t; +typedef byte_t extension_code_t; +typedef byte_t subunit_type_t; +typedef byte_t max_subunit_id_t; +typedef byte_t nr_of_channels_t; +typedef byte_t stream_position_t; +typedef byte_t stream_position_location_t; +typedef byte_t nr_of_clusters_t; +typedef byte_t string_length_t; +typedef byte_t cluster_index_t; +typedef byte_t port_type_t; +typedef byte_t number_of_output_plugs_t; + +typedef quadlet_t company_id_t; + +enum ESamplingFrequency { + eSF_22050Hz = 0x00, + eSF_24000Hz = 0x01, + eSF_32000Hz = 0x02, + eSF_44100Hz = 0x03, + eSF_48000Hz = 0x04, + eSF_88200Hz = 0x0A, + eSF_96000Hz = 0x05, + eSF_176400Hz = 0x06, + eSF_192000Hz = 0x07, + eSF_DontCare = 0x0F, +}; + +int convertESamplingFrequency(ESamplingFrequency freq); +ESamplingFrequency parseSampleRate( int sampleRate ); + +std::ostream& operator<<( std::ostream& stream, ESamplingFrequency samplingFrequency ); + +#define AVC1394_SUBUNIT_AUDIO 1 +#define AVC1394_SUBUNIT_PRINTER 2 +#define AVC1394_SUBUNIT_CA 6 +#define AVC1394_SUBUNIT_PANEL 9 +#define AVC1394_SUBUNIT_BULLETIN_BOARD 0xA +#define AVC1394_SUBUNIT_CAMERA_STORAGE 0xB +#define AVC1394_SUBUNIT_MUSIC 0xC +#define AVC1394_SUBUNIT_RESERVED 0x1D + +#define AVC1394_SUBUNIT_ID_RESERVED 0x06 + +#endif // AVCDefinitions_h Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/ieee1394service.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/ieee1394service.cpp (revision 156) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/ieee1394service.cpp (revision 156) @@ -0,0 +1,88 @@ +/* tempate.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ +#include "ieee1394service.h" + +#include + +#include + +#include + +using namespace std; + +Ieee1394Service::Ieee1394Service() + : m_handle( 0 ) + , m_port( -1 ) +{ +} + +Ieee1394Service::~Ieee1394Service() +{ +} + +bool +Ieee1394Service::initialize( int port ) +{ + m_handle = raw1394_new_handle_on_port( port ); + if ( !m_handle ) { + if ( !errno ) { + cerr << "libraw1394 not compatible" << endl; + } else { + perror( "Ieee1394Service::initialize: Could not get 1394 handle" ); + cerr << "Is ieee1394 and raw1394 driver loaded?" << endl; + } + return false; + } + + m_port = port; + return true; +} + +int +Ieee1394Service::getNodeCount() +{ + return raw1394_get_nodecount( m_handle ); +} + +bool +Ieee1394Service::read( fb_nodeid_t nodeId, + fb_nodeaddr_t addr, + size_t size, + fb_quadlet_t* buffer ) +{ + return raw1394_read( m_handle, nodeId, addr, size, buffer ) != 0; +} + +bool +Ieee1394Service::write( fb_nodeid_t nodeId, + fb_nodeaddr_t addr, + size_t length, + fb_quadlet_t *data ) +{ + return raw1394_write( m_handle, nodeId, addr, length, data ) != 0; +} + +fb_quadlet_t* +Ieee1394Service::transactionBlock( fb_nodeid_t nodeId, + fb_quadlet_t* buf, + int len ) +{ + return avc1394_transaction_block( m_handle, nodeId, buf, len, 1 ); +} Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_generic.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_generic.h (revision 125) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_generic.h (revision 125) @@ -0,0 +1,128 @@ +/* avc_generic.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef AVCGeneric_h +#define AVCGeneric_h + +#include "avc_definitions.h" + +#include "../fbtypes.h" + +#include + +class IOSSerialize; +class IISDeserialize; +class Ieee1394Service; + +class IBusData { +public: + IBusData() {} + virtual ~IBusData() {} + + virtual bool serialize( IOSSerialize& se ) = 0; + virtual bool deserialize( IISDeserialize& de ) = 0; + + virtual IBusData* clone() const = 0; +}; + +class AVCCommand +{ +public: + enum EResponse { + eR_Unknown = 0, + eR_NotImplemented = AVC1394_RESP_NOT_IMPLEMENTED, + eR_Accepted = AVC1394_RESP_ACCEPTED, + eR_Rejected = AVC1394_RESP_REJECTED, + eR_InTransition = AVC1394_RESP_IN_TRANSITION, + eR_Implemented = AVC1394_RESP_IMPLEMENTED, + eR_Changed = AVC1394_RESP_CHANGED, + eR_Interim = AVC1394_RESP_INTERIM, + }; + + enum ECommandType { + eCT_Control = AVC1394_CTYP_CONTROL, + eCT_Status = AVC1394_CTYP_STATUS, + eCT_SpecificInquiry = AVC1394_CTYP_SPECIFIC_INQUIRY, + eCT_Notify = AVC1394_CTYP_NOTIFY, + eCT_GeneralInquiry = AVC1394_CTYP_GENERAL_INQUIRY, + eCT_Unknown = 0xff, + }; + + enum ESubunitType { + eST_Monitor = AVC1394_SUBUNIT_VIDEO_MONITOR, + eST_Audio = AVC1394_SUBUNIT_AUDIO, + eST_Printer = AVC1394_SUBUNIT_PRINTER, + eST_Disc = AVC1394_SUBUNIT_DISC_RECORDER, + eST_VCR = AVC1394_SUBUNIT_VCR, + eST_Tuner = AVC1394_SUBUNIT_TUNER, + eST_CA = AVC1394_SUBUNIT_CA, + eST_Camera = AVC1394_SUBUNIT_VIDEO_CAMERA, + eST_Panel = AVC1394_SUBUNIT_PANEL, + eST_BulltinBoard = AVC1394_SUBUNIT_BULLETIN_BOARD, + eST_CameraStorage = AVC1394_SUBUNIT_CAMERA_STORAGE, + eST_Music = AVC1394_SUBUNIT_MUSIC, + eST_VendorUnique = AVC1394_SUBUNIT_VENDOR_UNIQUE, + eST_Reserved = AVC1394_SUBUNIT_RESERVED, + eST_Extended = AVC1394_SUBUNIT_EXTENDED, + eST_Unit = AVC1394_SUBUNIT_UNIT, + }; + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + + virtual bool setCommandType( ECommandType commandType ); + virtual bool fire() = 0; + + EResponse getResponse(); + + bool setNodeId( fb_nodeid_t nodeId ); + bool setSubunitType( ESubunitType subunitType ); + bool setSubunitId( subunit_id_t subunitId ); + + ESubunitType getSubunitType(); + subunit_id_t getSubunitId(); + + bool setVerbose( bool enable ); + bool isVerbose(); + + +protected: + AVCCommand( Ieee1394Service* ieee1394service, opcode_t opcode ); + virtual ~AVCCommand() {} + + bool parseResponse( byte_t response ); + ECommandType getCommandType(); + + Ieee1394Service* m_1394Service; + fb_nodeid_t m_nodeId; + +private: + ctype_t m_ctype; + subunit_t m_subunit; + opcode_t m_opcode; + EResponse m_eResponse; + bool m_verbose; + ECommandType m_commandType; +}; + + +const char* subunitTypeToString( subunit_type_t subunitType ); + +#endif // AVCGeneric_h Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_plug_info.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_plug_info.cpp (revision 156) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_plug_info.cpp (revision 156) @@ -0,0 +1,216 @@ +/* avc_plug_info.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "avc_plug_info.h" +#include "serialize.h" +#include "ieee1394service.h" + +#include +#include + +using namespace std; + +PlugInfoCmd::PlugInfoCmd( Ieee1394Service* ieee1394service, + ESubFunction eSubFunction ) + : AVCCommand( ieee1394service, AVC1394_CMD_PLUG_INFO ) + , m_serialBusIsochronousInputPlugs( 0xff ) + , m_serialBusIsochronousOutputPlugs( 0xff ) + , m_externalInputPlugs( 0xff ) + , m_externalOutputPlugs( 0xff ) + , m_serialBusAsynchronousInputPlugs( 0xff ) + , m_serialBusAsynchronousOuputPlugs( 0xff ) + , m_destinationPlugs( 0xff ) + , m_sourcePlugs( 0xff ) + , m_subFunction( eSubFunction ) +{ +} + +PlugInfoCmd::~PlugInfoCmd() +{ +} + +bool +PlugInfoCmd::serialize( IOSSerialize& se ) +{ + byte_t reserved = 0xff; + + AVCCommand::serialize( se ); + se.write( m_subFunction, "PlugInfoCmd subFunction" ); + switch( getSubunitType() ) { + case eST_Unit: + switch( m_subFunction ) { + case eSF_SerialBusIsochronousAndExternalPlug: + se.write( m_serialBusIsochronousInputPlugs, "PlugInfoCmd serialBusIsochronousInputPlugs" ); + se.write( m_serialBusIsochronousOutputPlugs, "PlugInfoCmd serialBusIsochronousOutputPlugs" ); + se.write( m_externalInputPlugs, "PlugInfoCmd externalInputPlugs" ); + se.write( m_externalOutputPlugs, "PlugInfoCmd externalOutputPlugs" ); + break; + case eSF_SerialBusAsynchonousPlug: + se.write( m_serialBusAsynchronousInputPlugs, "PlugInfoCmd serialBusAsynchronousInputPlugs" ); + se.write( m_serialBusAsynchronousOuputPlugs, "PlugInfoCmd serialBusAsynchronousOuputPlugs" ); + se.write( reserved, "PlugInfoCmd" ); + se.write( reserved, "PlugInfoCmd" ); + break; + default: + cerr << "Could not serialize with subfucntion " << m_subFunction << endl; + return false; + } + break; + default: + se.write( m_destinationPlugs, "PlugInfoCmd destinationPlugs" ); + se.write( m_sourcePlugs, "PlugInfoCmd sourcePlugs" ); + se.write( reserved, "PlugInfoCmd" ); + se.write( reserved, "PlugInfoCmd" ); + } + return true; +} + +bool +PlugInfoCmd::deserialize( IISDeserialize& de ) +{ + byte_t reserved; + + AVCCommand::deserialize( de ); + de.read( &m_subFunction ); + switch ( getSubunitType() ) { + case eST_Unit: + switch ( m_subFunction ) { + case eSF_SerialBusIsochronousAndExternalPlug: + de.read( &m_serialBusIsochronousInputPlugs ); + de.read( &m_serialBusIsochronousOutputPlugs ); + de.read( &m_externalInputPlugs ); + de.read( &m_externalOutputPlugs ); + break; + case eSF_SerialBusAsynchonousPlug: + de.read( &m_serialBusAsynchronousInputPlugs ); + de.read( &m_serialBusAsynchronousOuputPlugs ); + de.read( &reserved ); + de.read( &reserved ); + break; + default: + cerr << "Could not deserialize with subfunction " << m_subFunction << endl; + return false; + } + break; + default: + de.read( &m_destinationPlugs ); + de.read( &m_sourcePlugs ); + de.read( &reserved ); + de.read( &reserved ); + } + return true; +} + +bool +PlugInfoCmd::fire() +{ + bool result = false; + + #define STREAM_FORMAT_REQUEST_SIZE 20 // XXX random length + union UPacket { + quadlet_t quadlet[STREAM_FORMAT_REQUEST_SIZE]; + unsigned char byte[STREAM_FORMAT_REQUEST_SIZE*4]; + }; + typedef union UPacket packet_t; + + packet_t req; + packet_t* resp; + + // initialize complete packet + memset( &req, 0xff, sizeof( req ) ); + + BufferSerialize se( req.byte, sizeof( req ) ); + if ( !serialize( se ) ) { + printf( "PlugInfoCmd::fire: Could not serialize\n" ); + return false; + } + + // reorder the bytes to the correct layout + for (int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i) { + req.quadlet[i] = ntohl( req.quadlet[i] ); + } + + if ( isVerbose() ) { + // debug output + puts("request:"); + for (int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i) { + printf(" %2d: 0x%08x\n", i, req.quadlet[i]); + } + } + + resp = reinterpret_cast( + m_1394Service->transactionBlock( m_nodeId, + req.quadlet, + STREAM_FORMAT_REQUEST_SIZE ) ); + if ( resp ) { + if ( isVerbose() ) { + // debug output + puts("response:"); + for ( int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i ) { + printf( " %2d: 0x%08x\n", i, resp->quadlet[i] ); + } + } + + // reorder the bytes to the correct layout + for ( int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i ) { + resp->quadlet[i] = htonl( resp->quadlet[i] ); + } + + if ( isVerbose() ) { + // a more detailed debug output + printf( "\n" ); + printf( " idx type value\n" ); + printf( "-------------------------------------\n" ); + printf( " %02d ctype: 0x%02x\n", 0, resp->byte[0] ); + printf( " %02d subunit_type + subunit_id: 0x%02x\n", 1, resp->byte[1] ); + printf( " %02d opcode: 0x%02x\n", 2, resp->byte[2] ); + + for ( int i = 3; i < STREAM_FORMAT_REQUEST_SIZE * 4; ++i ) { + printf( " %02d operand %2d: 0x%02x\n", i, i-3, resp->byte[i] ); + } + } + + // parse output + parseResponse( resp->byte[0] ); + switch ( getResponse() ) + { + case eR_Implemented: + { + BufferDeserialize de( resp->byte, sizeof( req ) ); + deserialize( de ); + result = true; + } + break; + default: + printf( "unexpected response received (0x%x)\n", getResponse() ); + } + } else { + printf( "no response\n" ); + } + + return result; +} + +bool +PlugInfoCmd::setSubFunction( ESubFunction subFunction ) +{ + m_subFunction = subFunction; + return true; +} Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_stream_format.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_stream_format.cpp (revision 156) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_stream_format.cpp (revision 156) @@ -0,0 +1,462 @@ +/* avc_extended_stream_format.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "avc_extended_stream_format.h" +#include "serialize.h" +#include "ieee1394service.h" + +#include + +/////////////////////////////////////////////////////////// +std::ostream& operator<<( std::ostream& stream, StreamFormatInfo info ) +{ +/* stream << info.m_freq << " Hz ("; + if ( info.m_format ) { + stream << "sync "; + } else { + stream << "compound "; + } + stream << "stream, "; + stream << "audio channels: " << info.m_audioChannels + << ", midi channels: " << info.m_midiChannels << ")"; +*/ + stream << " NbChannels " << (int)info.m_numberOfChannels << ", Format " << (int)info.m_streamFormat; + return stream; +} + +StreamFormatInfo::StreamFormatInfo() + : IBusData() +{ +} + +bool +StreamFormatInfo::serialize( IOSSerialize& se ) +{ + se.write( m_numberOfChannels, "StreamFormatInfo numberOfChannels" ); + se.write( m_streamFormat, "StreamFormatInfo streamFormat" ); + return true; +} + +bool +StreamFormatInfo::deserialize( IISDeserialize& de ) +{ + de.read( &m_numberOfChannels ); + de.read( &m_streamFormat ); + return true; +} + +StreamFormatInfo* +StreamFormatInfo::clone() const +{ + return new StreamFormatInfo( *this ); +} + +//////////////////////////////////////////////////////////// + +FormatInformationStreamsSync::FormatInformationStreamsSync() + : FormatInformationStreams() + , m_reserved0( 0xff ) + , m_samplingFrequency( eSF_DontCare ) + , m_rateControl( eRC_DontCare ) + , m_reserved1( 0xff ) +{ +} + +bool +FormatInformationStreamsSync::serialize( IOSSerialize& se ) +{ + se.write( m_reserved0, "FormatInformationStreamsSync reserved" ); + + // we have to clobber some bits + byte_t operand = ( m_samplingFrequency << 4 ) | 0x0e; + if ( m_rateControl == eRC_DontCare) { + operand |= 0x1; + } + se.write( operand, "FormatInformationStreamsSync sampling frequency and rate control" ); + + se.write( m_reserved1, "FormatInformationStreamsSync reserved" ); + return true; +} + +bool +FormatInformationStreamsSync::deserialize( IISDeserialize& de ) +{ + de.read( &m_reserved0 ); + + byte_t operand; + de.read( &operand ); + m_samplingFrequency = operand >> 4; + m_rateControl = operand & 0x01; + + de.read( &m_reserved1 ); + return true; +} + +FormatInformationStreamsSync* +FormatInformationStreamsSync::clone() const +{ + return new FormatInformationStreamsSync( *this ); +} + +//////////////////////////////////////////////////////////// +std::ostream& operator<<( std::ostream& stream, FormatInformationStreamsCompound info ) +{ + stream << (int)info.m_samplingFrequency << " Hz (rate control: "; + stream << (int)info.m_rateControl << ")" << std::endl; + + for ( FormatInformationStreamsCompound::StreamFormatInfoVector::iterator it = info.m_streamFormatInfos.begin(); + it != info.m_streamFormatInfos.end(); + ++it ) + { + StreamFormatInfo* sfi=*it; + stream << " > " << *sfi << std::endl; + } + + return stream; +} + +FormatInformationStreamsCompound::FormatInformationStreamsCompound() + : FormatInformationStreams() + , m_samplingFrequency( eSF_DontCare ) + , m_rateControl( eRC_DontCare ) + , m_numberOfStreamFormatInfos( 0 ) +{ +} + +FormatInformationStreamsCompound::~FormatInformationStreamsCompound() +{ + for ( StreamFormatInfoVector::iterator it = m_streamFormatInfos.begin(); + it != m_streamFormatInfos.end(); + ++it ) + { + delete *it; + } +} + +bool +FormatInformationStreamsCompound::serialize( IOSSerialize& se ) +{ + se.write( m_samplingFrequency, "FormatInformationStreamsCompound samplingFrequency" ); + se.write( m_rateControl, "FormatInformationStreamsCompound rateControl" ); + se.write( m_numberOfStreamFormatInfos, "FormatInformationStreamsCompound numberOfStreamFormatInfos" ); + for ( StreamFormatInfoVector::iterator it = m_streamFormatInfos.begin(); + it != m_streamFormatInfos.end(); + ++it ) + { + ( *it )->serialize( se ); + } + return true; +} + +bool +FormatInformationStreamsCompound::deserialize( IISDeserialize& de ) +{ + de.read( &m_samplingFrequency ); + de.read( &m_rateControl ); + de.read( &m_numberOfStreamFormatInfos ); + for ( int i = 0; i < m_numberOfStreamFormatInfos; ++i ) { + StreamFormatInfo* streamFormatInfo = new StreamFormatInfo; + if ( !streamFormatInfo->deserialize( de ) ) { + return false; + } + m_streamFormatInfos.push_back( streamFormatInfo ); + } + return true; +} + +FormatInformationStreamsCompound* +FormatInformationStreamsCompound::clone() const +{ + return new FormatInformationStreamsCompound( *this ); +} + +//////////////////////////////////////////////////////////// + +FormatInformation::FormatInformation() + : IBusData() + , m_root( eFHR_Invalid ) + , m_level1( eFHL1_AUDIOMUSIC_DONT_CARE ) + , m_level2( eFHL2_AM824_DONT_CARE ) + , m_streams( 0 ) +{ +} + +FormatInformation::~FormatInformation() +{ + delete m_streams; + m_streams = 0; +} + +bool +FormatInformation::serialize( IOSSerialize& se ) +{ + if ( m_root != eFHR_Invalid ) { + se.write( m_root, "FormatInformation hierarchy root" ); + if ( m_level1 != eFHL1_AUDIOMUSIC_DONT_CARE ) { + se.write( m_level1, "FormatInformation hierarchy level 1" ); + if ( m_level2 != eFHL2_AM824_DONT_CARE ) { + se.write( m_level2, "FormatInformation hierarchy level 2" ); + } + } + } + if ( m_streams ) { + return m_streams->serialize( se ); + } + return true; +} + +bool +FormatInformation::deserialize( IISDeserialize& de ) +{ + bool result = false; + + delete m_streams; + m_streams = 0; + + // this code just parses BeBoB replies. + de.read( &m_root ); + + // just parse an audio and music hierarchy + if ( m_root == eFHR_AudioMusic ) { + de.read( &m_level1 ); + + switch ( m_level1 ) { + case eFHL1_AUDIOMUSIC_AM824: + { + // note: compound streams don't have a second level + de.read( &m_level2 ); + + if (m_level2 == eFHL2_AM824_SYNC_STREAM ) { + m_streams = new FormatInformationStreamsSync(); + result = m_streams->deserialize( de ); + } else { + // anything but the sync stream workds currently. + printf( "could not parse format information. (format hierarchy level 2 not recognized)\n" ); + } + } + break; + case eFHL1_AUDIOMUSIC_AM824_COMPOUND: + { + m_streams = new FormatInformationStreamsCompound(); + result = m_streams->deserialize( de ); + } + break; + default: + printf( "could not parse format information. (format hierarchy level 1 not recognized)\n" ); + } + } + + return result; +} + +FormatInformation* +FormatInformation::clone() const +{ + return new FormatInformation( *this ); +} + +//////////////////////////////////////////////////////////// + +ExtendedStreamFormatCmd::ExtendedStreamFormatCmd( Ieee1394Service* service, + ESubFunction eSubFunction ) + : AVCCommand( service, AVC1394_STREAM_FORMAT_SUPPORT ) + , m_subFunction( eSubFunction ) + , m_status( eS_NotUsed ) + , m_indexInStreamFormat( 0 ) + , m_formatInformation( new FormatInformation ) +{ + UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, 0x00 ); + m_plugAddress = new PlugAddress( PlugAddress::ePD_Output, PlugAddress::ePAM_Unit, unitPlugAddress ); +} + +ExtendedStreamFormatCmd::~ExtendedStreamFormatCmd() +{ + delete m_plugAddress; + m_plugAddress = 0; + delete m_formatInformation; + m_formatInformation = 0; +} + +bool +ExtendedStreamFormatCmd::setPlugAddress( const PlugAddress& plugAddress ) +{ + delete m_plugAddress; + m_plugAddress = plugAddress.clone(); + return true; +} + +bool +ExtendedStreamFormatCmd::setIndexInStreamFormat( const int index ) +{ + m_indexInStreamFormat = index; + return true; +} + +bool +ExtendedStreamFormatCmd::serialize( IOSSerialize& se ) +{ + AVCCommand::serialize( se ); + se.write( m_subFunction, "ExtendedStreamFormatCmd subFunction" ); + m_plugAddress->serialize( se ); + se.write( m_status, "ExtendedStreamFormatCmd status" ); + if ( m_subFunction == eSF_ExtendedStreamFormatInformationCommandList ) { + se.write( m_indexInStreamFormat, "indexInStreamFormat" ); + } + m_formatInformation->serialize( se ); + return true; +} + +bool +ExtendedStreamFormatCmd::deserialize( IISDeserialize& de ) +{ + AVCCommand::deserialize( de ); + de.read( &m_subFunction ); + m_plugAddress->deserialize( de ); + de.read( &m_status ); + if ( m_subFunction == eSF_ExtendedStreamFormatInformationCommandList ) { + de.read( &m_indexInStreamFormat ); + } + m_formatInformation->deserialize( de ); + return true; +} + +bool +ExtendedStreamFormatCmd::fire() +{ + bool result = false; + + #define STREAM_FORMAT_REQUEST_SIZE 20 // XXX random length + union UPacket { + quadlet_t quadlet[STREAM_FORMAT_REQUEST_SIZE]; + unsigned char byte[STREAM_FORMAT_REQUEST_SIZE*4]; + }; + typedef union UPacket packet_t; + + packet_t req; + packet_t* resp; + + // initialize complete packet + memset( &req, 0xff, sizeof( req ) ); + + BufferSerialize se( req.byte, sizeof( req ) ); + if ( !serialize( se ) ) { + printf( "ExtendedStreamFormatCmd::fire: Could not serialize\n" ); + return false; + } + + // reorder the bytes to the correct layout + for (int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i) { + req.quadlet[i] = ntohl( req.quadlet[i] ); + } + + if ( isVerbose() ) { + // debug output + puts("request:"); + for (int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i) { + printf(" %2d: 0x%08x\n", i, req.quadlet[i]); + } + } + resp = reinterpret_cast( + m_1394Service->transactionBlock( m_nodeId, + req.quadlet, + STREAM_FORMAT_REQUEST_SIZE ) ); + if ( resp ) { + if ( isVerbose() ) { + // debug output + puts("response:"); + for ( int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i ) { + printf( " %2d: 0x%08x\n", i, resp->quadlet[i] ); + } + } + + // reorder the bytes to the correct layout + for ( int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i ) { + resp->quadlet[i] = htonl( resp->quadlet[i] ); + } + + if ( isVerbose() ) { + // a more detailed debug output + printf( "\n" ); + printf( " idx type value\n" ); + printf( "-------------------------------------\n" ); + printf( " %02d ctype: 0x%02x\n", 0, resp->byte[0] ); + printf( " %02d subunit_type + subunit_id: 0x%02x\n", 1, resp->byte[1] ); + printf( " %02d opcode: 0x%02x\n", 2, resp->byte[2] ); + + for ( int i = 3; i < STREAM_FORMAT_REQUEST_SIZE * 4; ++i ) { + printf( " %02d operand %2d: 0x%02x\n", i, i-3, resp->byte[i] ); + } + } + + // parse output + parseResponse( resp->byte[0] ); + switch ( getResponse() ) + { + case eR_Implemented: + { + BufferDeserialize de( resp->byte, sizeof( req ) ); + deserialize( de ); + result = true; + } + break; + case eR_Rejected: + if ( m_subFunction == eSF_ExtendedStreamFormatInformationCommandList ) { + if ( isVerbose() ) { + printf( "no futher stream formats defined\n" ); + } + result = true; + } else { + printf( "request rejected\n" ); + } + break; + default: + printf( "unexpected response received (0x%x)\n", getResponse() ); + } + } else { + printf( "no response\n" ); + } + + return result; +} + +status_t +ExtendedStreamFormatCmd::getStatus() +{ + return m_status; +} + +FormatInformation* +ExtendedStreamFormatCmd::getFormatInformation() +{ + return m_formatInformation; +} + +ExtendedStreamFormatCmd::index_in_stream_format_t +ExtendedStreamFormatCmd::getIndex() +{ + return m_indexInStreamFormat; +} + +bool +ExtendedStreamFormatCmd::setSubFunction( ESubFunction subFunction ) +{ + m_subFunction = subFunction; + return true; +} Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_cmd_generic.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_cmd_generic.h (revision 125) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_cmd_generic.h (revision 125) @@ -0,0 +1,240 @@ +/* avc_extended_cmd_generic.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef AVCEXTENDEDCMDGENERIC_H +#define AVCEXTENDEDCMDGENERIC_H + +#include "avc_generic.h" + +//////////////////////////////////////////////////////////// + +class PlugAddressData : public IBusData { +}; + +//////////////////////////////////////////////////////////// + +class UnitPlugAddress : public PlugAddressData +{ +public: + enum EPlugType { + ePT_PCR = 0x00, + ePT_ExternalPlug = 0x01, + ePT_AsynchronousPlug = 0x02, + }; + + UnitPlugAddress( EPlugType plugType, plug_type_t plugId ); + virtual ~UnitPlugAddress(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual UnitPlugAddress* clone() const; + + plug_id_t m_plugType; + plug_type_t m_plugId; + reserved_t m_reserved; +}; + +//////////////////////////////////////////////////////////// + +class SubunitPlugAddress : public PlugAddressData +{ +public: + SubunitPlugAddress( plug_id_t plugId ); + virtual ~SubunitPlugAddress(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual SubunitPlugAddress* clone() const; + + plug_id_t m_plugId; + reserved_t m_reserved0; + reserved_t m_reserved1; +}; + + +//////////////////////////////////////////////////////////// + +class FunctionBlockPlugAddress : public PlugAddressData +{ +public: + FunctionBlockPlugAddress( function_block_type_t functionBlockType, + function_block_id_t functionBlockId, + plug_id_t plugId ); + virtual ~FunctionBlockPlugAddress(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual FunctionBlockPlugAddress* clone() const; + + function_block_type_t m_functionBlockType; + function_block_id_t m_functionBlockId; + plug_id_t m_plugId; +}; + +//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// + +class UnitPlugSpecificDataPlugAddress : public PlugAddressData +{ +public: + enum EPlugType { + ePT_PCR = 0x00, + ePT_ExternalPlug = 0x01, + ePT_AsynchronousPlug = 0x02, + }; + + UnitPlugSpecificDataPlugAddress( EPlugType plugType, + plug_type_t plugId ); + virtual ~UnitPlugSpecificDataPlugAddress(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual UnitPlugSpecificDataPlugAddress* clone() const; + + plug_type_t m_plugType; + plug_id_t m_plugId; + reserved_t m_reserved0; + reserved_t m_reserved1; + reserved_t m_reserved2; +}; + +//////////////////////////////////////////////////////////// + +class SubunitPlugSpecificDataPlugAddress : public PlugAddressData +{ +public: + SubunitPlugSpecificDataPlugAddress( AVCCommand::ESubunitType subunitType, + subunit_id_t subunitId, + plug_id_t plugId ); + virtual ~SubunitPlugSpecificDataPlugAddress(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual SubunitPlugSpecificDataPlugAddress* clone() const; + + subunit_type_t m_subunitType; + subunit_id_t m_subunitId; + plug_id_t m_plugId; + reserved_t m_reserved0; + reserved_t m_reserved1; +}; + +//////////////////////////////////////////////////////////// + +class FunctionBlockPlugSpecificDataPlugAddress : public PlugAddressData +{ +public: + FunctionBlockPlugSpecificDataPlugAddress( AVCCommand::ESubunitType subunitType, + subunit_id_t subunitId, + function_block_type_t functionBlockType, + function_block_id_t functionBlockId, + plug_id_t plugId); + virtual ~FunctionBlockPlugSpecificDataPlugAddress(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual FunctionBlockPlugSpecificDataPlugAddress* clone() const; + + subunit_type_t m_subunitType; + subunit_id_t m_subunitId; + function_block_type_t m_functionBlockType; + function_block_id_t m_functionBlockId; + plug_id_t m_plugId; +}; + +//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// + +class PlugAddress : public IBusData { +public: + enum EPlugDirection { + ePD_Input = 0x00, + ePD_Output = 0x01, + }; + + enum EPlugAddressMode { + ePAM_Unit = 0x00, + ePAM_Subunit = 0x01, + ePAM_FunctionBlock = 0x02, + }; + + PlugAddress( EPlugDirection plugDirection, + EPlugAddressMode plugAddressMode, + UnitPlugAddress& unitPlugAddress ); + PlugAddress( EPlugDirection plugDirection, + EPlugAddressMode plugAddressMode, + SubunitPlugAddress& subUnitPlugAddress ); + PlugAddress( EPlugDirection plugDirection, + EPlugAddressMode plugAddressMode, + FunctionBlockPlugAddress& functionBlockPlugAddress ); + PlugAddress( const PlugAddress& pa ); + + virtual ~PlugAddress(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + + virtual PlugAddress* clone() const; + + plug_direction_t m_plugDirection; + plug_address_mode_t m_addressMode; + PlugAddressData* m_plugAddressData; +}; + +//////////////////////////////////////////////////////////// + +class PlugAddressSpecificData : public IBusData { +public: + enum EPlugDirection { + ePD_Input = 0x00, + ePD_Output = 0x01, + }; + + enum EPlugAddressMode { + ePAM_Unit = 0x00, + ePAM_Subunit = 0x01, + ePAM_FunctionBlock = 0x02, + }; + + PlugAddressSpecificData( EPlugDirection plugDirection, + EPlugAddressMode plugAddressMode, + UnitPlugSpecificDataPlugAddress& unitPlugAddress ); + PlugAddressSpecificData( EPlugDirection plugDirection, + EPlugAddressMode plugAddressMode, + SubunitPlugSpecificDataPlugAddress& subUnitPlugAddress ); + PlugAddressSpecificData( EPlugDirection plugDirection, + EPlugAddressMode plugAddressMode, + FunctionBlockPlugSpecificDataPlugAddress& functionBlockPlugAddress ); + PlugAddressSpecificData( const PlugAddressSpecificData& pa ); + + virtual ~PlugAddressSpecificData(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + + virtual PlugAddressSpecificData* clone() const; + + plug_direction_t m_plugDirection; + plug_address_mode_t m_addressMode; + PlugAddressData* m_plugAddressData; +}; + + +#endif Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/ieee1394service.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/ieee1394service.h (revision 156) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/ieee1394service.h (revision 156) @@ -0,0 +1,94 @@ +/* Ieee1394Service.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef FREEBOBIEEE1394SERVICE_H +#define FREEBOBIEEE1394SERVICE_H + +#include "fbtypes.h" + +#include + +class Ieee1394Service{ +public: + Ieee1394Service(); + ~Ieee1394Service(); + + bool initialize( int port ); + + int getPort() + { return m_port; } + /** + * getNodecount - get number of nodes on the bus + * + * Since the root node always has + * the highest node ID, this number can be used to determine that ID (it's + * LOCAL_BUS|(count-1)). + * + * Returns: the number of nodes on the bus to which the port is connected. + * This value can change with every bus reset. + */ + int getNodeCount(); + + /** + * read - send async read request to a node and wait for response. + * @node: target node + * @addr: address to read from + * @length: amount of data to read in quadlets + * @buffer: pointer to buffer where data will be saved + * + * This does the complete transaction and will return when it's finished. + * + * Returns: truee on success or false on failure (sets errno) + */ + bool read( fb_nodeid_t nodeId, + fb_nodeaddr_t addr, + size_t size, + fb_quadlet_t* buffer ); + + /** + * write - send async write request to a node and wait for response. + * @node: target node + * @addr: address to write to + * @length: amount of data to write in quadlets + * @data: pointer to data to be sent + * + * This does the complete transaction and will return when it's finished. + * + * Returns: true on success or false on failure (sets errno) + */ + bool write( fb_nodeid_t nodeId, + fb_nodeaddr_t addr, + size_t length, + fb_quadlet_t *data ); + + + fb_quadlet_t* transactionBlock( fb_nodeid_t nodeId, + fb_quadlet_t* buf, + int len ); + + + + +private: + raw1394handle_t m_handle; + int m_port; +}; + +#endif Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_plug_info.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_plug_info.h (revision 125) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_plug_info.h (revision 125) @@ -0,0 +1,71 @@ +/* avc_plug_info.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef AVCPlugInfo_h +#define AVCPlugInfo_h + +#include "avc_generic.h" + +#include + +#define AVC1394_PLUG_INFO_SUBFUNCTION_SERIAL_BUS_ISOCHRONOUS_AND_EXTERNAL_PLUG 0x00 +#define AVC1394_PLUG_INFO_SUBFUNCTION_SERIAL_BUS_ASYNCHRONOUS_PLUG 0x01 +#define AVC1394_PLUG_INFO_SUBFUNCTION_SERIAL_BUS_GENERIC_BUS_PLUG_BLUETOOTH 0x40 +#define AVC1394_PLUG_INFO_SUBFUNCTION_SERIAL_BUS_NOT_USED 0xFF + + +class PlugInfoCmd: public AVCCommand +{ +public: + enum ESubFunction { + eSF_SerialBusIsochronousAndExternalPlug = AVC1394_PLUG_INFO_SUBFUNCTION_SERIAL_BUS_ISOCHRONOUS_AND_EXTERNAL_PLUG, + eSF_SerialBusAsynchonousPlug = AVC1394_PLUG_INFO_SUBFUNCTION_SERIAL_BUS_ASYNCHRONOUS_PLUG, + eSF_SerialBusPlug = AVC1394_PLUG_INFO_SUBFUNCTION_SERIAL_BUS_GENERIC_BUS_PLUG_BLUETOOTH, + eSF_NotUsed = AVC1394_PLUG_INFO_SUBFUNCTION_SERIAL_BUS_NOT_USED, + }; + + PlugInfoCmd( Ieee1394Service* ieee1394service, + ESubFunction eSubFunction = eSF_SerialBusIsochronousAndExternalPlug ); + virtual ~PlugInfoCmd(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + + virtual bool fire(); + + + nr_of_plugs_t m_serialBusIsochronousInputPlugs; + nr_of_plugs_t m_serialBusIsochronousOutputPlugs; + nr_of_plugs_t m_externalInputPlugs; + nr_of_plugs_t m_externalOutputPlugs; + nr_of_plugs_t m_serialBusAsynchronousInputPlugs; + nr_of_plugs_t m_serialBusAsynchronousOuputPlugs; + nr_of_plugs_t m_destinationPlugs; + nr_of_plugs_t m_sourcePlugs; + + bool setSubFunction( ESubFunction subFunction ); + +protected: + subfunction_t m_subFunction; + +}; + + +#endif // AVCPlugInfo_h Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_stream_format.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_stream_format.h (revision 156) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_stream_format.h (revision 156) @@ -0,0 +1,283 @@ +/* avc_extended_stream_format.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef AVCExtendedStreamFormat_h +#define AVCExtendedStreamFormat_h + +#include "avc_generic.h" +#include "avc_extended_cmd_generic.h" + +#include +#include +#include + +#define AVC1394_STREAM_FORMAT_SUPPORT 0x2F +#define AVC1394_STREAM_FORMAT_SUBFUNCTION_INPUT 0x00 +#define AVC1394_STREAM_FORMAT_SUBFUNCTION_OUTPUT 0x01 + +// BridgeCo extensions +#define AVC1394_STREAM_FORMAT_SUBFUNCTION_EXTENDED_STREAM_FORMAT 0xC0 +#define AVC1394_STREAM_FORMAT_SUBFUNCTION_EXTENDED_STREAM_FORMAT_LIST 0xC1 + + +#define AVC1394_STREAM_FORMAT_HIERARCHY_ROOT_DVCR 0x80 +#define AVC1394_STREAM_FORMAT_HIERARCHY_ROOT_AUDIOMUSIC 0x90 +#define AVC1394_STREAM_FORMAT_HIERARCHY_ROOT_INVALID 0xFF + +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_DVCR_SD525_60 0x00 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_DVCR_SDL525_60 0x04 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_DVCR_HD1125_60 0x08 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_DVCR_SD625_60 0x80 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_DVCR_SDL625_50 0x84 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_DVCR_HD1250_50 0x88 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_AUDIOMUSIC_AM824 0x00 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_AUDIOMUSIC_24_4_AUDIO_PACK 0x01 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_AUDIOMUSIC_32_FLOATING_POINT_DATA 0x02 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_AUDIOMUSIC_AM824_COMPOUND 0x40 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_AUDIOMUSIC_DONT_CARE 0xFF + + +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_IEC60968_3 0x00 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_IEC61937_3 0x01 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_IEC61937_4 0x02 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_IEC61937_5 0x03 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_IEC61937_6 0x04 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_IEC61937_7 0x05 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_MULTI_BIT_LINEAR_AUDIO_RAW 0x06 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_MULTI_BIT_LINEAR_AUDIO_DVD_AUDIO 0x07 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_ONE_BIT_AUDIO_PLAIN_RAW 0x08 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_ONE_BIT_AUDIO_PLAIN_SACD 0x09 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_ONE_BIT_AUDIO_ENCODED_RAW 0x0A +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_ONE_BIT_AUDIO_ENCODED_SACD 0x0B +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_HIGH_PRECISION_MULTIBIT_LINEAR_AUDIO 0x0C +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_MIDI_CONFORMANT 0x0D +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_SYNC_STREAM 0x40 +#define AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_DONT_CARE 0xFF + +#define AVC1394_STREAM_FORMAT_AM824_IEC60968_3 0x00 +#define AVC1394_STREAM_FORMAT_AM824_IEC61937_3 0x01 +#define AVC1394_STREAM_FORMAT_AM824_IEC61937_4 0x02 +#define AVC1394_STREAM_FORMAT_AM824_IEC61937_5 0x03 +#define AVC1394_STREAM_FORMAT_AM824_IEC61937_6 0x04 +#define AVC1394_STREAM_FORMAT_AM824_IEC61937_7 0x05 +#define AVC1394_STREAM_FORMAT_AM824_MULTI_BIT_LINEAR_AUDIO_RAW 0x06 +#define AVC1394_STREAM_FORMAT_AM824_MULTI_BIT_LINEAR_AUDIO_DVD_AUDIO 0x07 +#define AVC1394_STREAM_FORMAT_AM824_HIGH_PRECISION_MULTIBIT_LINEAR_AUDIO 0x0C +#define AVC1394_STREAM_FORMAT_AM824_MIDI_CONFORMANT 0x0D +#define AVC1394_STREAM_FORMAT_AM824_DONT_CARE 0xFF + +/* +// As defined in 'AV/C Stream Format Information Specification 1.0 TA Document 2001002' +// Not used for extended stream format +#define AVC1394_STREAM_FORMAT_SUPPORT_STATUS_SUPPORTED_AND_CONFIGURED 0x00 +#define AVC1394_STREAM_FORMAT_SUPPORT_STATUS_SUPPORTED_AND_HAS_NOT_BEEN_CONFIGURED 0x01 +#define AVC1394_STREAM_FORMAT_SUPPORT_STATUS_SUPPORTED_AND_READY_TO_CONFIGURE 0x02 +#define AVC1394_STREAM_FORMAT_SUPPORT_STATUS_SUPPORTED_AND_NOT_CONFIGURED 0x03 +#define AVC1394_STREAM_FORMAT_SUPPORT_STATUS_NOT_SUPPORTED 0x04 +// 0x05 - 0xFE reserved +#define AVC1394_STREAM_FORMAT_SUPPORT_STATUS_NO_INFORMATION 0xFF +*/ + +#define AVC1394_EXTENDED_STREAM_FORMAT_INFO_STATUS_ACTIVE 0x00 +#define AVC1394_EXTENDED_STREAM_FORMAT_INFO_STATUS_INACTIVE 0x01 +#define AVC1394_EXTENDED_STREAM_FORMAT_INFO_STATUS_NO_STREAM_FORMAT 0x02 +#define AVC1394_EXTENDED_STREAM_FORMAT_INFO_STATUS_NOT_USED 0xff + +class IOSSerialize; +class IISDeserialize; + +enum ERateControl { + eRC_Supported = 0x00, + eRC_DontCare = 0x01, +}; + +//////////////////////////////////////////////////////////// + +class StreamFormatInfo: public IBusData +{ +public: + StreamFormatInfo(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + + virtual StreamFormatInfo* clone() const; + + number_of_channels_t m_numberOfChannels; + stream_format_t m_streamFormat; +}; +std::ostream& operator<<( std::ostream& stream, StreamFormatInfo info ); + +//////////////////////////////////////////////////////////// + +class FormatInformationStreams: public IBusData +{ +public: + FormatInformationStreams() {} + virtual ~FormatInformationStreams() {} +}; + +//////////////////////////////////////////////////////////// + +class FormatInformationStreamsSync: public FormatInformationStreams +{ +public: + FormatInformationStreamsSync(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual FormatInformationStreamsSync* clone() const; + + reserved_t m_reserved0; + sampling_frequency_t m_samplingFrequency; + rate_control_t m_rateControl; + reserved_t m_reserved1; +}; + +//////////////////////////////////////////////////////////// + +class FormatInformationStreamsCompound: public FormatInformationStreams +{ +public: + FormatInformationStreamsCompound(); + virtual ~FormatInformationStreamsCompound(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual FormatInformationStreamsCompound* clone() const; + + sampling_frequency_t m_samplingFrequency; + rate_control_t m_rateControl; + number_of_stream_format_infos_t m_numberOfStreamFormatInfos; + + typedef std::vector< StreamFormatInfo* > StreamFormatInfoVector; + StreamFormatInfoVector m_streamFormatInfos; +}; +std::ostream& operator<<( std::ostream& stream, FormatInformationStreamsCompound info ); + + +//////////////////////////////////////////////////////////// + +class FormatInformation: public IBusData +{ +public: + enum EFormatHierarchyRoot { + eFHR_DVCR = AVC1394_STREAM_FORMAT_HIERARCHY_ROOT_DVCR, + eFHR_AudioMusic = AVC1394_STREAM_FORMAT_HIERARCHY_ROOT_AUDIOMUSIC, + eFHR_Invalid = AVC1394_STREAM_FORMAT_HIERARCHY_ROOT_INVALID, + }; + + enum EFomatHierarchyLevel1 { + eFHL1_DVCR_SD525_60 = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_DVCR_SD525_60, + eFHL1_DVCR_SDL525_60 = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_DVCR_SDL525_60, + eFHL1_DVCR_HD1125_60 = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_DVCR_HD1125_60, + eFHL1_DVCR_SD625_60 = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_DVCR_SD625_60, + eFHL1_DVCR_SDL625_50 = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_DVCR_SDL625_50, + eFHL1_DVCR_HD1250_50 = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_DVCR_HD1250_50, + eFHL1_AUDIOMUSIC_AM824 = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_AUDIOMUSIC_AM824, + eFHL1_AUDIOMUSIC_24_4_AUDIO_PACK = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_AUDIOMUSIC_24_4_AUDIO_PACK, + eFHL1_AUDIOMUSIC_32_FLOATING = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_AUDIOMUSIC_32_FLOATING_POINT_DATA, + eFHL1_AUDIOMUSIC_AM824_COMPOUND = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_AUDIOMUSIC_AM824_COMPOUND, + eFHL1_AUDIOMUSIC_DONT_CARE = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_1_AUDIOMUSIC_DONT_CARE, + }; + + enum EFormatHierarchyLevel2 { + eFHL2_AM824_IEC60968_3 = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_IEC60968_3, + eFHL2_AM824_IEC61937_3 = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_IEC61937_3, + eFHL2_AM824_IEC61937_4 = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_IEC61937_4, + eFHL2_AM824_IEC61937_5 = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_IEC61937_5, + eFHL2_AM824_IEC61937_6 = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_IEC61937_6, + eFHL2_AM824_IEC61937_7 = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_IEC61937_7, + eFHL2_AM824_MULTI_BIT_LINEAR_AUDIO_RAW = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_MULTI_BIT_LINEAR_AUDIO_RAW, + eFHL2_AM824_MULTI_BIT_LINEAR_AUDIO_DVD_AUDIO = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_MULTI_BIT_LINEAR_AUDIO_DVD_AUDIO, + eFHL2_AM824_ONE_BIT_AUDIO_PLAIN_RAW = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_ONE_BIT_AUDIO_PLAIN_RAW, + eFHL2_AM824_ONE_BIT_AUDIO_PLAIN_SACD = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_ONE_BIT_AUDIO_PLAIN_SACD, + eFHL2_AM824_ONE_BIT_AUDIO_ENCODED_RAW = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_ONE_BIT_AUDIO_ENCODED_RAW, + eFHL2_AM824_ONE_BIT_AUDIO_ENCODED_SACD = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_ONE_BIT_AUDIO_ENCODED_SACD, + eFHL2_AM824_HIGH_PRECISION_MULTIBIT_LINEAR_AUDIO = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_HIGH_PRECISION_MULTIBIT_LINEAR_AUDIO, + eFHL2_AM824_MIDI_CONFORMANT = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_MIDI_CONFORMANT, + eFHL2_AM824_SYNC_STREAM = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_SYNC_STREAM, + eFHL2_AM824_DONT_CARE = AVC1394_STREAM_FORMAT_HIERARCHY_LEVEL_2_AM824_DONT_CARE, + }; + + typedef byte_t format_hierarchy_root_t; + typedef byte_t format_hierarchy_level1_t; + typedef byte_t format_hierarchy_level2_t; + + FormatInformation(); + virtual ~FormatInformation(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + + virtual FormatInformation* clone() const; + + format_hierarchy_root_t m_root; + format_hierarchy_level1_t m_level1; + format_hierarchy_level2_t m_level2; + FormatInformationStreams* m_streams; +}; + +/////////////////////////////////////////////////////////// + +class ExtendedStreamFormatCmd: public AVCCommand +{ +public: + enum ESubFunction { + eSF_Input = AVC1394_STREAM_FORMAT_SUBFUNCTION_INPUT, + eSF_Output = AVC1394_STREAM_FORMAT_SUBFUNCTION_OUTPUT, + eSF_ExtendedStreamFormatInformationCommand = AVC1394_STREAM_FORMAT_SUBFUNCTION_EXTENDED_STREAM_FORMAT, + eSF_ExtendedStreamFormatInformationCommandList = AVC1394_STREAM_FORMAT_SUBFUNCTION_EXTENDED_STREAM_FORMAT_LIST, + }; + + enum EStatus { + eS_Active = AVC1394_EXTENDED_STREAM_FORMAT_INFO_STATUS_ACTIVE, + eS_Inactive = AVC1394_EXTENDED_STREAM_FORMAT_INFO_STATUS_INACTIVE, + eS_NoStreamFormat = AVC1394_EXTENDED_STREAM_FORMAT_INFO_STATUS_NO_STREAM_FORMAT, + eS_NotUsed = AVC1394_EXTENDED_STREAM_FORMAT_INFO_STATUS_NOT_USED, + }; + typedef byte_t status_t; + typedef byte_t index_in_stream_format_t; + + ExtendedStreamFormatCmd( Ieee1394Service* ieee1349service, ESubFunction eSubFunction = eSF_ExtendedStreamFormatInformationCommand ); + virtual ~ExtendedStreamFormatCmd(); + + bool setPlugAddress( const PlugAddress& plugAddress ); + bool setIndexInStreamFormat( const int index ); + bool setSubFunction( ESubFunction subFunction ); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + + virtual bool fire(); + + status_t getStatus(); + FormatInformation* getFormatInformation(); + index_in_stream_format_t getIndex(); + +protected: + subfunction_t m_subFunction; + PlugAddress* m_plugAddress; + status_t m_status; + index_in_stream_format_t m_indexInStreamFormat; + FormatInformation* m_formatInformation; +}; + +#endif // AVCExtendedStreamFormat_h Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_connect.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_connect.cpp (revision 156) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_connect.cpp (revision 156) @@ -0,0 +1,144 @@ +/* avc_connect.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "avc_connect.h" +#include "serialize.h" +#include "ieee1394service.h" + +#include +#include + +using namespace std; + +ConnectCmd::ConnectCmd(Ieee1394Service* ieee1394service) + : AVCCommand( ieee1394service, AVC1394_CMD_CONNECT ) +{ +} + +ConnectCmd::~ConnectCmd() +{ +} + +bool +ConnectCmd::serialize( IOSSerialize& se ) +{ + AVCCommand::serialize( se ); + return true; +} + +bool +ConnectCmd::deserialize( IISDeserialize& de ) +{ + AVCCommand::deserialize( de ); + return true; +} + +bool +ConnectCmd::fire( ECommandType commandType, + raw1394handle_t handle, + unsigned int node_id ) +{ + bool result = false; + + #define STREAM_FORMAT_REQUEST_SIZE 20 // XXX random length + union UPacket { + quadlet_t quadlet[STREAM_FORMAT_REQUEST_SIZE]; + unsigned char byte[STREAM_FORMAT_REQUEST_SIZE*4]; + }; + typedef union UPacket packet_t; + + packet_t req; + packet_t* resp; + + setCommandType( commandType ); + // initialize complete packet + memset( &req, 0xff, sizeof( req ) ); + + BufferSerialize se( req.byte, sizeof( req ) ); + if ( !serialize( se ) ) { + printf( "ConnectCmd::fire: Could not serialize\n" ); + return false; + } + + // reorder the bytes to the correct layout + for (int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i) { + req.quadlet[i] = ntohl( req.quadlet[i] ); + } + + if ( isVerbose() ) { + // debug output + puts("request:"); + for (int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i) { + printf(" %2d: 0x%08x\n", i, req.quadlet[i]); + } + } + + resp = reinterpret_cast( + m_1394Service->transactionBlock( m_nodeId, + req.quadlet, + STREAM_FORMAT_REQUEST_SIZE ) ); + if ( resp ) { + if ( isVerbose() ) { + // debug output + puts("response:"); + for ( int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i ) { + printf( " %2d: 0x%08x\n", i, resp->quadlet[i] ); + } + } + + // reorder the bytes to the correct layout + for ( int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i ) { + resp->quadlet[i] = htonl( resp->quadlet[i] ); + } + + if ( isVerbose() ) { + // a more detailed debug output + printf( "\n" ); + printf( " idx type value\n" ); + printf( "-------------------------------------\n" ); + printf( " %02d ctype: 0x%02x\n", 0, resp->byte[0] ); + printf( " %02d subunit_type + subunit_id: 0x%02x\n", 1, resp->byte[1] ); + printf( " %02d opcode: 0x%02x\n", 2, resp->byte[2] ); + + for ( int i = 3; i < STREAM_FORMAT_REQUEST_SIZE * 4; ++i ) { + printf( " %02d operand %2d: 0x%02x\n", i, i-3, resp->byte[i] ); + } + } + + // parse output + parseResponse( resp->byte[0] ); + switch ( getResponse() ) + { + case eR_Implemented: + { + BufferDeserialize de( resp->byte, sizeof( req ) ); + deserialize( de ); + result = true; + } + break; + default: + printf( "unexpected response received (0x%x)\n", getResponse() ); + } + } else { + printf( "no response\n" ); + } + + return result; +} Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_unit_info.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_unit_info.cpp (revision 125) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_unit_info.cpp (revision 125) @@ -0,0 +1,172 @@ +/* avc_unit_info.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "avc_unit_info.h" +#include "serialize.h" +#include "ieee1394service.h" + +#include +#include + +using namespace std; + +UnitInfoCmd::UnitInfoCmd( Ieee1394Service* ieee1349service ) + : AVCCommand( ieee1349service, AVC1394_CMD_UNIT_INFO ) + , m_reserved( 0xff ) + , m_unit_type( 0xff ) + , m_unit( 0xff ) + , m_company_id( 0xffffffff ) +{ +} + +UnitInfoCmd::~UnitInfoCmd() +{ +} + +bool +UnitInfoCmd::serialize( IOSSerialize& se ) +{ + AVCCommand::serialize( se ); + + se.write( m_reserved, "UnitInfoCmd reserved" ); + byte_t operand = ( m_unit_type << 3 ) | ( m_unit & 0x7 ); + se.write( operand, "UnitInfoCmd unit_type and unit" ); + operand = ( m_company_id >> 16 ) & 0xff; + se.write( operand, "UnitInfoCmd company_ID (2)" ); + operand = ( m_company_id >> 8 ) & 0xff; + se.write( operand, "UnitInfoCmd company_ID (1)" ); + operand = ( m_company_id >> 0 ) & 0xff; + se.write( operand, "UnitInfoCmd company_ID (0)" ); + + return true; +} + +bool +UnitInfoCmd::deserialize( IISDeserialize& de ) +{ + AVCCommand::deserialize( de ); + + de.read( &m_reserved ); + + byte_t operand; + de.read( &operand ); + m_unit_type = ( operand >> 3 ); + m_unit = ( operand & 0x7 ); + + de.read( &operand ); + m_company_id = 0; + m_company_id |= operand << 16; + de.read( &operand ); + m_company_id |= operand << 8; + de.read( &operand ); + m_company_id |= operand; + + return true; +} + +bool +UnitInfoCmd::fire() +{ + bool result = false; + + #define STREAM_FORMAT_REQUEST_SIZE 2 + union UPacket { + quadlet_t quadlet[STREAM_FORMAT_REQUEST_SIZE]; + unsigned char byte[STREAM_FORMAT_REQUEST_SIZE*4]; + }; + typedef union UPacket packet_t; + + packet_t req; + packet_t* resp; + + // initialize complete packet + memset( &req, 0xff, sizeof( req ) ); + + BufferSerialize se( req.byte, sizeof( req ) ); + if ( !serialize( se ) ) { + printf( "UnitInoCmd::fire: Could not serialize\n" ); + return false; + } + + // reorder the bytes to the correct layout + for (int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i) { + req.quadlet[i] = ntohl( req.quadlet[i] ); + } + + if ( isVerbose() ) { + // debug output + puts("request:"); + for (int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i) { + printf(" %2d: 0x%08x\n", i, req.quadlet[i]); + } + } + + resp = reinterpret_cast( + m_1394Service->transactionBlock( m_nodeId, + req.quadlet, + STREAM_FORMAT_REQUEST_SIZE ) ); + if ( resp ) { + if ( isVerbose() ) { + // debug output + puts("response:"); + for ( int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i ) { + printf( " %2d: 0x%08x\n", i, resp->quadlet[i] ); + } + } + + // reorder the bytes to the correct layout + for ( int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i ) { + resp->quadlet[i] = htonl( resp->quadlet[i] ); + } + + if ( isVerbose() ) { + // a more detailed debug output + printf( "\n" ); + printf( " idx type value\n" ); + printf( "-------------------------------------\n" ); + printf( " %02d ctype: 0x%02x\n", 0, resp->byte[0] ); + printf( " %02d subunit_type + subunit_id: 0x%02x\n", 1, resp->byte[1] ); + printf( " %02d opcode: 0x%02x\n", 2, resp->byte[2] ); + + for ( int i = 3; i < STREAM_FORMAT_REQUEST_SIZE * 4; ++i ) { + printf( " %02d operand %2d: 0x%02x\n", i, i-3, resp->byte[i] ); + } + } + + // parse output + parseResponse( resp->byte[0] ); + switch ( getResponse() ) + { + case eR_Implemented: + { + BufferDeserialize de( resp->byte, sizeof( req ) ); + deserialize( de ); + result = true; + } + break; + default: + printf( "unexpected response received (0x%x)\n", getResponse() ); + } + } else { + printf( "no response\n" ); + } + + return result; +} Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_signal_source.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_signal_source.cpp (revision 156) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_signal_source.cpp (revision 156) @@ -0,0 +1,375 @@ +/* avc_signal_source.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "avc_signal_source.h" +#include "serialize.h" +#include "ieee1394service.h" + +#include +#include + +using namespace std; + +#define AVC1394_CMD_SIGNAL_SOURCE 0x1A + +SignalUnitAddress::SignalUnitAddress() + : m_plugId( ePI_Invalid ) +{ +} + +bool +SignalUnitAddress::serialize( IOSSerialize& se ) +{ + byte_t reserved = 0xff; + se.write( reserved, "SignalUnitAddress" ); + se.write( m_plugId, "SignalUnitAddress plugId" ); + return true; +} + +bool +SignalUnitAddress::deserialize( IISDeserialize& de ) +{ + byte_t operand; + de.read( &operand ); + de.read( &m_plugId ); + return true; +} + +SignalUnitAddress* +SignalUnitAddress::clone() const +{ + return new SignalUnitAddress( *this ); +} + +//////////////////////////////////////// + +SignalSubunitAddress::SignalSubunitAddress() + : m_subunitType( AVC1394_SUBUNIT_RESERVED ) + , m_subunitId( AVC1394_SUBUNIT_ID_RESERVED ) + , m_plugId( ePI_Invalid ) +{ +} + +bool +SignalSubunitAddress::serialize( IOSSerialize& se ) +{ + byte_t operand = ( m_subunitType << 3 ) | ( m_subunitId & 0x7 ); + se.write( operand, "SignalSubunitAddress subunitType & subunitId" ); + se.write( m_plugId, "SignalSubunitAddress plugId" ); + return true; +} + +bool +SignalSubunitAddress::deserialize( IISDeserialize& de ) +{ + byte_t operand; + de.read( &operand ); + m_subunitType = operand >> 3; + m_subunitId = operand & 0x7; + de.read( &m_plugId ); + return true; +} + +SignalSubunitAddress* +SignalSubunitAddress::clone() const +{ + return new SignalSubunitAddress( *this ); +} + +//////////////////////////////////////// + + +SignalSourceCmd::SignalSourceCmd( Ieee1394Service* ieee1394service ) + : AVCCommand( ieee1394service, AVC1394_CMD_SIGNAL_SOURCE ) + , m_resultStatus( 0xff ) + , m_outputStatus( 0xff ) + , m_conv( 0xff ) + , m_signalStatus( 0xff ) + , m_signalSource( 0 ) + , m_signalDestination( 0 ) +{ +} + +SignalSourceCmd::~SignalSourceCmd() +{ + delete m_signalSource; + m_signalSource = 0; + delete m_signalDestination; + m_signalDestination = 0; +} + +bool +SignalSourceCmd::serialize( IOSSerialize& se ) +{ + AVCCommand::serialize( se ); + + byte_t operand; + switch ( getCommandType() ) { + case eCT_Status: + operand = ( m_outputStatus << 5 ) + | ( ( m_conv & 0x1 ) << 4 ) + | ( m_signalStatus & 0xf ); + se.write( operand, "SignalSourceCmd outputStatus & conv & signalStatus" ); + break; + case eCT_Control: + case eCT_SpecificInquiry: + operand = m_resultStatus & 0xf; + se.write( operand, "SignalSourceCmd resultStatus" ); + break; + default: + cerr << "Can't handle command type " << getCommandType() << endl; + return false; + } + + switch( getSubunitType() ) { + case eST_Unit: + case eST_Audio: + case eST_Music: + { + if ( m_signalSource ) { + m_signalSource->serialize( se ); + } else { + byte_t reserved = 0xff; + se.write( reserved, "SignalSourceCmd" ); + se.write( reserved, "SignalSourceCmd" ); + } + + if ( m_signalDestination ) { + m_signalDestination->serialize( se ); + } else { + byte_t reserved = 0xff; + se.write( reserved, "SignalSourceCmd" ); + se.write( reserved, "SignalSourceCmd" ); + } + } + break; + default: + cerr << "Can't handle subunit type " << getSubunitType() << endl; + return false; + } + + return true; +} + +bool +SignalSourceCmd::deserialize( IISDeserialize& de ) +{ + delete m_signalSource; + m_signalSource = 0; + delete m_signalDestination; + m_signalDestination = 0; + + AVCCommand::deserialize( de ); + + byte_t operand; + switch ( getCommandType() ) { + case eCT_Status: + de.read( &operand ); + m_outputStatus = operand >> 5; + m_conv = ( operand & 0x10 ) >> 4; + m_signalStatus = operand & 0xf; + break; + case eCT_Control: + case eCT_SpecificInquiry: + de.read( &operand ); + m_resultStatus = operand & 0xf; + break; + default: + cerr << "Can't handle command type " << getCommandType() << endl; + return false; + } + + switch( getSubunitType() ) { + case eST_Unit: + case eST_Audio: + case eST_Music: + { + byte_t operand; + de.peek( &operand ); + if ( operand == 0xff ) { + m_signalSource = new SignalUnitAddress; + } else { + m_signalSource = new SignalSubunitAddress; + } + + m_signalSource->deserialize( de ); + + de.peek( &operand ); + if ( operand == 0xff ) { + m_signalDestination = new SignalUnitAddress; + } else { + m_signalDestination = new SignalSubunitAddress; + } + m_signalDestination->deserialize( de ); + } + break; + default: + cerr << "Can't handle subunit type " << getSubunitType() << endl; + return false; + } + + return true; +} + +bool +SignalSourceCmd::fire( raw1394handle_t handle, + unsigned int node_id ) +{ + bool result = false; + + #define STREAM_FORMAT_REQUEST_SIZE 20 // XXX random length + union UPacket { + quadlet_t quadlet[STREAM_FORMAT_REQUEST_SIZE]; + unsigned char byte[STREAM_FORMAT_REQUEST_SIZE*4]; + }; + typedef union UPacket packet_t; + + packet_t req; + packet_t* resp; + + // initialize complete packet + memset( &req, 0xff, sizeof( req ) ); + + BufferSerialize se( req.byte, sizeof( req ) ); + if ( !serialize( se ) ) { + printf( "SignalSourceCmd::fire: Could not serialize\n" ); + return false; + } + + // reorder the bytes to the correct layout + for (int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i) { + req.quadlet[i] = ntohl( req.quadlet[i] ); + } + + if ( isVerbose() ) { + // debug output + puts("request:"); + for (int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i) { + printf(" %2d: 0x%08x\n", i, req.quadlet[i]); + } + } + + resp = reinterpret_cast( + m_1394Service->transactionBlock( m_nodeId, + req.quadlet, + STREAM_FORMAT_REQUEST_SIZE ) ); + if ( resp ) { + if ( isVerbose() ) { + // debug output + puts("response:"); + for ( int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i ) { + printf( " %2d: 0x%08x\n", i, resp->quadlet[i] ); + } + } + + // reorder the bytes to the correct layout + for ( int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i ) { + resp->quadlet[i] = htonl( resp->quadlet[i] ); + } + + if ( isVerbose() ) { + // a more detailed debug output + printf( "\n" ); + printf( " idx type value\n" ); + printf( "-------------------------------------\n" ); + printf( " %02d ctype: 0x%02x\n", 0, resp->byte[0] ); + printf( " %02d subunit_type + subunit_id: 0x%02x\n", 1, resp->byte[1] ); + printf( " %02d opcode: 0x%02x\n", 2, resp->byte[2] ); + + for ( int i = 3; i < STREAM_FORMAT_REQUEST_SIZE * 4; ++i ) { + printf( " %02d operand %2d: 0x%02x\n", i, i-3, resp->byte[i] ); + } + } + + // parse output + parseResponse( resp->byte[0] ); + switch ( getResponse() ) + { + case eR_Implemented: + case eR_NotImplemented: + case eR_Accepted: + case eR_Rejected: + { + BufferDeserialize de( resp->byte, sizeof( req ) ); + deserialize( de ); + result = true; + } + break; + default: + printf( "unexpected response received (0x%x)\n", getResponse() ); + } + } else { + printf( "no response\n" ); + } + + return result; +} + +bool +SignalSourceCmd::setSignalSource( SignalUnitAddress& signalAddress ) +{ + if ( m_signalSource ) { + delete m_signalSource; + } + m_signalSource = signalAddress.clone(); + return true; +} + +bool +SignalSourceCmd::setSignalSource( SignalSubunitAddress& signalAddress ) +{ + if ( m_signalSource ) { + delete m_signalSource; + } + m_signalSource = signalAddress.clone(); + return true; +} + +bool +SignalSourceCmd::setSignalDestination( SignalUnitAddress& signalAddress ) +{ + if ( m_signalDestination ) { + delete m_signalDestination; + } + m_signalDestination = signalAddress.clone(); + return true; +} + +bool +SignalSourceCmd::setSignalDestination( SignalSubunitAddress& signalAddress ) +{ + if ( m_signalDestination ) { + delete m_signalDestination; + } + m_signalDestination = signalAddress.clone(); + return true; +} + +SignalAddress* +SignalSourceCmd::getSignalSource() +{ + return m_signalSource; +} + +SignalAddress* +SignalSourceCmd::getSignalDestination() +{ + return m_signalDestination; +} Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_connect.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_connect.h (revision 125) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_connect.h (revision 125) @@ -0,0 +1,43 @@ +/* avc_connect.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef AVCConnect_h +#define AVCConnect_h + +#include "avc_generic.h" + +#include + +class ConnectCmd: public AVCCommand +{ +public: + ConnectCmd(Ieee1394Service* ieee1394service); + virtual ~ConnectCmd(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + + virtual bool fire( ECommandType commandType, + raw1394handle_t handle, + unsigned int node_id ); +}; + + +#endif // AVCConnect_h Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/serialize.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/serialize.cpp (revision 125) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/serialize.cpp (revision 125) @@ -0,0 +1,122 @@ +/* serialize.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "serialize.h" + +#include +#include + +using namespace std; + +bool +CoutSerializer::write( byte_t d, const char* name ) +{ + cout << name << ": 0x" << setfill( '0' ) << hex << static_cast( d ) << endl; + return true; +} + +bool +CoutSerializer::write( quadlet_t d, const char* name ) +{ + cout << name << ": 0x" << setfill( '0' ) << setw( 8 ) << hex << d << endl; + return true; +} + +////////////////////////////////////////////////// + +bool +BufferSerialize::write( byte_t value, const char* name ) +{ + bool result = false; + if ( isCurPosValid() ) { + *m_curPos = value; + m_curPos += sizeof( byte_t ); + result = true; + } + return result; +} + +bool +BufferSerialize::write( quadlet_t value, const char* name ) +{ + bool result = false; + if ( isCurPosValid() ) { + * ( quadlet_t* )m_curPos = value; + m_curPos += sizeof( quadlet_t ); + result = true; + } + return result; +} + +bool +BufferSerialize::isCurPosValid() const +{ + if ( static_cast( ( m_curPos - m_buffer ) ) >= m_length ) { + return false; + } + return true; +} + +////////////////////////////////////////////////// + +bool +BufferDeserialize::read( byte_t* value ) +{ + bool result = false; + if ( isCurPosValid() ) { + *value = *m_curPos; + m_curPos += sizeof( byte_t ); + result = true; + } + return result; +} + +bool +BufferDeserialize::read( quadlet_t* value ) +{ + bool result = false; + if ( isCurPosValid() ) { + *value = *m_curPos; + m_curPos += sizeof( quadlet_t ); + result = true;; + } + return result; +} + +bool +BufferDeserialize::peek( byte_t* value ) +{ + bool result = false; + if ( isCurPosValid() ) { + *value = *m_curPos; + result = true; + } + return result; +} + +bool +BufferDeserialize::isCurPosValid() const +{ + if ( static_cast( ( m_curPos - m_buffer ) ) >= m_length ) { + return false; + } + return true; +} + Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/Makefile.am =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/Makefile.am (revision 156) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/Makefile.am (revision 156) @@ -0,0 +1,51 @@ +# Makefile.am - Makefile template +# Copyright (C) 2005 by Daniel Wagner. +# +# This file is part of FreeBob. +# +# FreeBob 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. +# FreeBob 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 FreeBob; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +noinst_LTLIBRARIES = libfreebobavc.la + +libfreebobavc_la_SOURCES = \ + avc_connect.h \ + avc_connect.cpp \ + avc_definitions.h \ + avc_definitions.cpp \ + avc_extended_cmd_generic.h \ + avc_extended_cmd_generic.cpp \ + avc_extended_stream_format.h \ + avc_extended_stream_format.cpp \ + avc_extended_plug_info.h \ + avc_extended_plug_info.cpp \ + avc_generic.h \ + avc_generic.cpp \ + avc_plug_info.h \ + avc_plug_info.cpp \ + avc_signal_source.h \ + avc_signal_source.cpp \ + avc_unit_info.h \ + avc_unit_info.cpp \ + avc_subunit_info.h \ + avc_subunit_info.cpp \ + serialize.h \ + serialize.cpp \ + ieee1394service.h \ + ieee1394service.cpp + +INCLUDES = $(LIBRAW1394_CFLAGS) $(LIBIEC61883_CFLAGS) $(LIBAVC1394_CFLAGS) \ + -I$(top_srcdir)/src +libfreebobavc_la_LIBADD = $(LIBRAW1394_LIBS) $(LIBIEC61883_LIBS) \ + $(LIBAVC1394_LIBS) + +MAINTAINERCLEANFILES = Makefile.in Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_unit_info.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_unit_info.h (revision 125) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_unit_info.h (revision 125) @@ -0,0 +1,68 @@ +/* avc_unit_info.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef AVCUnitInfo_h +#define AVCUnitInfo_h + +#include "avc_generic.h" + +#include + +class UnitInfoCmd: public AVCCommand +{ +public: + + enum EUnitType { + eUT_Monitor = AVC1394_SUBUNIT_VIDEO_MONITOR, + eUT_Audio = AVC1394_SUBUNIT_AUDIO, + eUT_Printer = AVC1394_SUBUNIT_PRINTER, + eUT_Disc = AVC1394_SUBUNIT_DISC_RECORDER, + eUT_VCR = AVC1394_SUBUNIT_VCR, + eUT_Tuner = AVC1394_SUBUNIT_TUNER, + eUT_CA = AVC1394_SUBUNIT_CA, + eUT_Camera = AVC1394_SUBUNIT_VIDEO_CAMERA, + eUT_Panel = AVC1394_SUBUNIT_PANEL, + eUT_BulltinBoard = AVC1394_SUBUNIT_BULLETIN_BOARD, + eUT_CameraStorage = AVC1394_SUBUNIT_CAMERA_STORAGE, + eUT_Music = AVC1394_SUBUNIT_MUSIC, + eUT_VendorUnique = AVC1394_SUBUNIT_VENDOR_UNIQUE, + eUT_Reserved = AVC1394_SUBUNIT_RESERVED, + eUT_Extended = AVC1394_SUBUNIT_EXTENDED, + eUT_Unit = AVC1394_SUBUNIT_UNIT, + }; + + UnitInfoCmd( Ieee1394Service* ieee1349service ); + virtual ~UnitInfoCmd(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + + virtual bool fire(); + + + reserved_t m_reserved; + unit_type_t m_unit_type; + unit_t m_unit; + + company_id_t m_company_id; +}; + + +#endif // AVCUnitInfo_h Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_plug_info.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_plug_info.cpp (revision 156) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_extended_plug_info.cpp (revision 156) @@ -0,0 +1,858 @@ +/* avc_extended_plug_info.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "avc_extended_plug_info.h" +#include "serialize.h" +#include "ieee1394service.h" + +#include +#include + +using namespace std; + +///////////////////////////////////////// +///////////////////////////////////////// + +ExtendedPlugInfoPlugTypeSpecificData::ExtendedPlugInfoPlugTypeSpecificData( EExtendedPlugInfoPlugType ePlugType ) + : IBusData() + , m_plugType( ePlugType ) +{ +} + +ExtendedPlugInfoPlugTypeSpecificData::~ExtendedPlugInfoPlugTypeSpecificData() +{ +} + +bool +ExtendedPlugInfoPlugTypeSpecificData::serialize( IOSSerialize& se ) +{ + se.write( m_plugType, "ExtendedPlugInfoPlugTypeSpecificData plugType" ); + return true; +} + + +bool +ExtendedPlugInfoPlugTypeSpecificData::deserialize( IISDeserialize& de ) +{ + de.read( &m_plugType ); + return true; +} + +ExtendedPlugInfoPlugTypeSpecificData* ExtendedPlugInfoPlugTypeSpecificData::clone() const +{ + return new ExtendedPlugInfoPlugTypeSpecificData( *this ); +} + +const char* extendedPlugInfoPlugTypeStrings[] = +{ + "IsoStream", + "AsyncStream", + "Midi", + "Sync", + "Analog", + "Digital", + "Unknown", +}; + +const char* extendedPlugInfoPlugTypeToString( plug_type_t plugType ) +{ + if ( plugType > sizeof( extendedPlugInfoPlugTypeStrings ) ) { + return "Unknown"; + } else { + return extendedPlugInfoPlugTypeStrings[plugType]; + } +} + +///////////////////////////////////////// +///////////////////////////////////////// + +ExtendedPlugInfoPlugNameSpecificData::ExtendedPlugInfoPlugNameSpecificData() + : IBusData() +{ +} + +ExtendedPlugInfoPlugNameSpecificData::~ExtendedPlugInfoPlugNameSpecificData() +{ +} + +bool +ExtendedPlugInfoPlugNameSpecificData::serialize( IOSSerialize& se ) +{ + byte_t length = strlen( m_name.c_str() ); + se.write( length, + "ExtendedPlugInfoPlugNameSpecificData: string length" ); + for ( unsigned int i = 0; i < length; ++i ) { + se.write( static_cast( m_name[i] ), + "ExtendedPlugInfoPlugNameSpecificData: char" ); + } + + return true; +} + +bool +ExtendedPlugInfoPlugNameSpecificData::deserialize( IISDeserialize& de ) +{ + byte_t length; + de.read( &length ); + m_name.clear(); + for ( int i = 0; i < length; ++length ) { + byte_t c; + de.read( &c ); + // \todo do correct encoding + if ( c == '&' ) { + c = '+'; + } + m_name += c; + } + return true; +} + +ExtendedPlugInfoPlugNameSpecificData::ExtendedPlugInfoPlugNameSpecificData* +ExtendedPlugInfoPlugNameSpecificData::clone() const +{ + return new ExtendedPlugInfoPlugNameSpecificData( *this ); +} + + +///////////////////////////////////////// +///////////////////////////////////////// + +ExtendedPlugInfoPlugNumberOfChannelsSpecificData::ExtendedPlugInfoPlugNumberOfChannelsSpecificData() + : IBusData() + , m_nrOfChannels( 0 ) +{ +} + +ExtendedPlugInfoPlugNumberOfChannelsSpecificData::~ExtendedPlugInfoPlugNumberOfChannelsSpecificData() +{ +} + +bool +ExtendedPlugInfoPlugNumberOfChannelsSpecificData::serialize( IOSSerialize& se ) +{ + se.write( m_nrOfChannels, + "ExtendedPlugInfoPlugNumberOfChannelsSpecificData: " + "number of channels" ); + return true; +} + +bool +ExtendedPlugInfoPlugNumberOfChannelsSpecificData::deserialize( IISDeserialize& de ) +{ + de.read( &m_nrOfChannels ); + return true; +} + +ExtendedPlugInfoPlugNumberOfChannelsSpecificData::ExtendedPlugInfoPlugNumberOfChannelsSpecificData* +ExtendedPlugInfoPlugNumberOfChannelsSpecificData::clone() const +{ + return new ExtendedPlugInfoPlugNumberOfChannelsSpecificData( *this ); +} + +///////////////////////////////////////// +///////////////////////////////////////// + +ExtendedPlugInfoPlugChannelPositionSpecificData::ExtendedPlugInfoPlugChannelPositionSpecificData() + : IBusData() + , m_nrOfClusters( 0 ) +{ +} + +ExtendedPlugInfoPlugChannelPositionSpecificData::~ExtendedPlugInfoPlugChannelPositionSpecificData() +{ +} + +bool +ExtendedPlugInfoPlugChannelPositionSpecificData::serialize( IOSSerialize& se ) +{ + se.write( m_nrOfClusters, + "ExtendedPlugInfoPlugChannelPositionSpecificData: " + "number of clusters" ); + + for ( ClusterInfoVector::const_iterator it = m_clusterInfos.begin(); + it != m_clusterInfos.end(); + ++it ) + { + const ClusterInfo* clusterInfo = &( *it ); + + se.write( clusterInfo->m_nrOfChannels, + "ExtendedPlugInfoPlugChannelPositionSpecificData: " + "number of channels" ); + for ( ChannelInfoVector::const_iterator cit + = clusterInfo->m_channelInfos.begin(); + cit != clusterInfo->m_channelInfos.end(); + ++cit ) + { + const ChannelInfo* channelInfo = &( *cit ); + se.write( channelInfo->m_streamPosition, + "ExtendedPlugInfoPlugChannelPositionSpecificData: " + "stream position" ); + se.write( channelInfo->m_location, + "ExtendedPlugInfoPlugChannelPositionSpecificData: " + "location" ); + } + } + + return true; +} + +bool +ExtendedPlugInfoPlugChannelPositionSpecificData::deserialize( IISDeserialize& de ) +{ + m_clusterInfos.clear(); + + de.read( &m_nrOfClusters ); + for ( int i = 0; i < m_nrOfClusters; ++i ) { + ClusterInfo clusterInfo; + de.read ( &clusterInfo.m_nrOfChannels ); + for ( int j = 0; j < clusterInfo.m_nrOfChannels; ++j ) { + ChannelInfo channelInfo; + de.read( &channelInfo.m_streamPosition ); + de.read( &channelInfo.m_location ); + clusterInfo.m_channelInfos.push_back( channelInfo ); + } + m_clusterInfos.push_back( clusterInfo ); + } + return true; +} + +ExtendedPlugInfoPlugChannelPositionSpecificData::ExtendedPlugInfoPlugChannelPositionSpecificData* +ExtendedPlugInfoPlugChannelPositionSpecificData::clone() const +{ + return new ExtendedPlugInfoPlugChannelPositionSpecificData( *this ); +} + +///////////////////////////////////////// +///////////////////////////////////////// + +ExtendedPlugInfoPlugChannelNameSpecificData::ExtendedPlugInfoPlugChannelNameSpecificData() + : IBusData() + , m_streamPosition( 0 ) + , m_stringLength( 0xff ) +{ +} + +ExtendedPlugInfoPlugChannelNameSpecificData::~ExtendedPlugInfoPlugChannelNameSpecificData() +{ +} + +bool +ExtendedPlugInfoPlugChannelNameSpecificData::serialize( IOSSerialize& se ) +{ + se.write( m_streamPosition, + "ExtendedPlugInfoPlugChannelNameSpecificData: stream position" ); + se.write( m_stringLength, + "ExtendedPlugInfoPlugChannelNameSpecificData: string length" ); + for ( unsigned int i = 0; i < m_plugChannelName.size(); ++i ) { + se.write( static_cast( m_plugChannelName[i] ), + "ExtendedPlugInfoPlugChannelNameSpecificData: char" ); + } + + return true; +} + +bool +ExtendedPlugInfoPlugChannelNameSpecificData::deserialize( IISDeserialize& de ) +{ + de.read( &m_streamPosition ); + de.read( &m_stringLength ); + + char* name = new char[m_stringLength+1]; + for ( int i = 0; i < m_stringLength; ++i ) { + byte_t c; + de.read( &c ); + // \todo do correct encoding + if ( c == '&' ) { + c = '+'; + } + name[i] = c; + } + name[m_stringLength] = '\0'; + m_plugChannelName = name; + delete[] name; + + return true; +} + +ExtendedPlugInfoPlugChannelNameSpecificData::ExtendedPlugInfoPlugChannelNameSpecificData* +ExtendedPlugInfoPlugChannelNameSpecificData::clone() const +{ + return new ExtendedPlugInfoPlugChannelNameSpecificData( *this ); +} + +///////////////////////////////////////// +///////////////////////////////////////// +ExtendedPlugInfoPlugInputSpecificData::ExtendedPlugInfoPlugInputSpecificData() + : IBusData() +{ + UnitPlugSpecificDataPlugAddress + unitPlug( UnitPlugSpecificDataPlugAddress::ePT_PCR, 0x00 ); + m_plugAddress + = new PlugAddressSpecificData( PlugAddressSpecificData::ePD_Output, + PlugAddressSpecificData::ePAM_Unit, + unitPlug ); +} + +ExtendedPlugInfoPlugInputSpecificData::ExtendedPlugInfoPlugInputSpecificData(const ExtendedPlugInfoPlugInputSpecificData& rhs ) +{ + m_plugAddress = rhs.m_plugAddress->clone(); +} + + +ExtendedPlugInfoPlugInputSpecificData::~ExtendedPlugInfoPlugInputSpecificData() +{ + delete m_plugAddress; +} + +bool +ExtendedPlugInfoPlugInputSpecificData::serialize( IOSSerialize& se ) +{ + if ( m_plugAddress ) { + return m_plugAddress->serialize( se ); + } else { + return false; + } +} + +bool +ExtendedPlugInfoPlugInputSpecificData::deserialize( IISDeserialize& de ) +{ + return m_plugAddress->deserialize( de ); +} + +ExtendedPlugInfoPlugInputSpecificData::ExtendedPlugInfoPlugInputSpecificData* +ExtendedPlugInfoPlugInputSpecificData::clone() const +{ + return new ExtendedPlugInfoPlugInputSpecificData( *this ); +} + +///////////////////////////////////////// +///////////////////////////////////////// + +ExtendedPlugInfoPlugOutputSpecificData::ExtendedPlugInfoPlugOutputSpecificData() + : IBusData() + , m_nrOfOutputPlugs( 0 ) +{ +} + +ExtendedPlugInfoPlugOutputSpecificData::ExtendedPlugInfoPlugOutputSpecificData( const ExtendedPlugInfoPlugOutputSpecificData& rhs) + : IBusData() + , m_nrOfOutputPlugs( rhs.m_nrOfOutputPlugs ) +{ + for ( PlugAddressVector::const_iterator it = rhs.m_outputPlugAddresses.begin(); + it != rhs.m_outputPlugAddresses.end(); + ++it ) + { + m_outputPlugAddresses.push_back( ( *it )->clone() ); + } + +} + + +ExtendedPlugInfoPlugOutputSpecificData::~ExtendedPlugInfoPlugOutputSpecificData() +{ + for ( PlugAddressVector::iterator it = m_outputPlugAddresses.begin(); + it != m_outputPlugAddresses.end(); + ++it ) + { + delete *it; + } +} + +bool +ExtendedPlugInfoPlugOutputSpecificData::serialize( IOSSerialize& se ) +{ + se.write( m_nrOfOutputPlugs, "ExtendedPlugInfoPlugOutputSpecificData: number of output plugs" ); + for ( PlugAddressVector::const_iterator it = m_outputPlugAddresses.begin(); + it != m_outputPlugAddresses.end(); + ++it ) + { + ( *it )->serialize( se ); + } + + return true; +} + +bool +ExtendedPlugInfoPlugOutputSpecificData::deserialize( IISDeserialize& de ) +{ + de.read( &m_nrOfOutputPlugs ); + + for ( int i = 0; i < m_nrOfOutputPlugs; ++i ) + { + UnitPlugSpecificDataPlugAddress + unitPlug( UnitPlugSpecificDataPlugAddress::ePT_PCR, 0x00 ); + PlugAddressSpecificData* plugAddress + = new PlugAddressSpecificData( PlugAddressSpecificData::ePD_Output, + PlugAddressSpecificData::ePAM_Unit, + unitPlug ); + if ( !plugAddress->deserialize( de ) ) { + return false; + } + + m_outputPlugAddresses.push_back( plugAddress ); + } + + return true; +} + +ExtendedPlugInfoPlugOutputSpecificData::ExtendedPlugInfoPlugOutputSpecificData* +ExtendedPlugInfoPlugOutputSpecificData::clone() const +{ + return new ExtendedPlugInfoPlugOutputSpecificData( *this ); +} + +///////////////////////////////////////// +///////////////////////////////////////// +ExtendedPlugInfoClusterInfoSpecificData::ExtendedPlugInfoClusterInfoSpecificData() + : IBusData() + , m_clusterIndex( 0 ) + , m_portType( ePT_NoType ) + , m_stringLength( 0xff ) +{ +} + +ExtendedPlugInfoClusterInfoSpecificData::~ExtendedPlugInfoClusterInfoSpecificData() +{ +} + +bool +ExtendedPlugInfoClusterInfoSpecificData::serialize( IOSSerialize& se ) +{ + se.write( m_clusterIndex, + "ExtendedPlugInfoClusterInfoSpecificData: cluster index" ); + se.write( m_portType, + "ExtendedPlugInfoClusterInfoSpecificData: port type" ); + se.write( m_stringLength, + "ExtendedPlugInfoClusterInfoSpecificData: string length" ); + for ( unsigned int i = 0; i < m_clusterName.length(); ++i ) { + se.write( static_cast( m_clusterName[i] ), + "ExtendedPlugInfoClusterInfoSpecificData: char" ); + } + + return true; +} + +bool +ExtendedPlugInfoClusterInfoSpecificData::deserialize( IISDeserialize& de ) +{ + + de.read( &m_clusterIndex ); + de.read( &m_portType ); + de.read( &m_stringLength ); + + char* name = new char[m_stringLength+1]; + for ( int i = 0; i < m_stringLength; ++i ) { + byte_t c; + de.read( &c ); + // \todo do correct encoding + if ( c == '&' ) { + c = '+'; + } + name[i] = c; + } + name[m_stringLength] = '\0'; + m_clusterName = name; + delete[] name; + + return true; +} + +ExtendedPlugInfoClusterInfoSpecificData::ExtendedPlugInfoClusterInfoSpecificData* +ExtendedPlugInfoClusterInfoSpecificData::clone() const +{ + return new ExtendedPlugInfoClusterInfoSpecificData( *this ); +} + +const char* extendedPlugInfoPortTypeStrings[] = +{ + "Speaker", + "Headphone", + "Microphone", + "Line", + "SPDIF", + "ADAT", + "TDIF", + "MADI", + "Analog", + "Digital", + "MIDI", +}; + +const char* extendedPlugInfoClusterInfoPortTypeToString( port_type_t portType ) +{ + if ( portType > sizeof( extendedPlugInfoPortTypeStrings ) ) { + return "Unknown"; + } else { + return extendedPlugInfoPortTypeStrings[portType]; + } +} + +///////////////////////////////////////// +///////////////////////////////////////// +///////////////////////////////////////// +///////////////////////////////////////// + +ExtendedPlugInfoInfoType::ExtendedPlugInfoInfoType(EInfoType eInfoType) + : IBusData() + , m_infoType( eInfoType ) + , m_plugType( 0 ) + , m_plugName( 0 ) + , m_plugNrOfChns( 0 ) + , m_plugChannelPosition( 0 ) + , m_plugChannelName( 0 ) + , m_plugInput( 0 ) + , m_plugOutput( 0 ) + , m_plugClusterInfo( 0 ) +{ +} + +ExtendedPlugInfoInfoType::~ExtendedPlugInfoInfoType() +{ + delete( m_plugType ); + delete( m_plugName ); + delete( m_plugNrOfChns ); + delete( m_plugChannelPosition ); + delete( m_plugChannelName ); + delete( m_plugInput ); + delete( m_plugOutput ); + delete( m_plugClusterInfo ); + } + +bool +ExtendedPlugInfoInfoType::initialize() +{ + switch ( m_infoType ) { + case eIT_PlugType: + m_plugType = new ExtendedPlugInfoPlugTypeSpecificData; + break; + case eIT_PlugName: + m_plugName = new ExtendedPlugInfoPlugNameSpecificData; + break; + case eIT_NoOfChannels: + m_plugNrOfChns = new ExtendedPlugInfoPlugNumberOfChannelsSpecificData; + break; + case eIT_ChannelPosition: + m_plugChannelPosition = new ExtendedPlugInfoPlugChannelPositionSpecificData; + break; + case eIT_ChannelName: + m_plugChannelName = new ExtendedPlugInfoPlugChannelNameSpecificData; + break; + case eIT_PlugInput: + m_plugInput = new ExtendedPlugInfoPlugInputSpecificData; + break; + case eIT_PlugOutput: + m_plugOutput = new ExtendedPlugInfoPlugOutputSpecificData; + break; + case eIT_ClusterInfo: + m_plugClusterInfo = new ExtendedPlugInfoClusterInfoSpecificData; + break; + default: + return false; + } + + return true; +} + +bool +ExtendedPlugInfoInfoType::serialize( IOSSerialize& se ) +{ + se.write( m_infoType, "ExtendedPlugInfoInfoType infoType" ); + + switch ( m_infoType ) { + case eIT_PlugType: + if ( m_plugType ) { + m_plugType->serialize( se ); + } + break; + case eIT_PlugName: + if ( m_plugName ) { + m_plugName->serialize( se ); + } + break; + case eIT_NoOfChannels: + if ( m_plugNrOfChns ) { + m_plugNrOfChns->serialize( se ); + } + break; + case eIT_ChannelPosition: + if ( m_plugChannelPosition ) { + m_plugChannelPosition->serialize( se ); + } + break; + case eIT_ChannelName: + if ( m_plugChannelName ) { + m_plugChannelName->serialize( se ); + } + break; + case eIT_PlugInput: + if ( m_plugInput ) { + m_plugInput->serialize( se ); + } + break; + case eIT_PlugOutput: + if ( m_plugOutput ) { + m_plugOutput->serialize( se ); + } + break; + case eIT_ClusterInfo: + if ( m_plugClusterInfo ) { + m_plugClusterInfo->serialize( se ); + } + break; + default: + return false; + } + + return true; +} + +bool +ExtendedPlugInfoInfoType::deserialize( IISDeserialize& de ) +{ + de.read( &m_infoType ); + + switch ( m_infoType ) { + case eIT_PlugType: + if ( !m_plugType ) { + m_plugType = new ExtendedPlugInfoPlugTypeSpecificData; + } + m_plugType->deserialize( de ); + break; + case eIT_PlugName: + if ( !m_plugName ) { + m_plugName = new ExtendedPlugInfoPlugNameSpecificData; + } + m_plugName->deserialize( de ); + break; + case eIT_NoOfChannels: + if ( !m_plugNrOfChns ) { + m_plugNrOfChns = + new ExtendedPlugInfoPlugNumberOfChannelsSpecificData; + } + m_plugNrOfChns->deserialize( de ); + break; + case eIT_ChannelPosition: + if ( !m_plugChannelPosition ) { + m_plugChannelPosition = + new ExtendedPlugInfoPlugChannelPositionSpecificData; + } + m_plugChannelPosition->deserialize( de ); + + break; + case eIT_ChannelName: + if ( !m_plugChannelName ) { + m_plugChannelName = + new ExtendedPlugInfoPlugChannelNameSpecificData; + } + m_plugChannelName->deserialize( de ); + break; + case eIT_PlugInput: + if ( !m_plugInput ) { + m_plugInput = new ExtendedPlugInfoPlugInputSpecificData; + } + m_plugInput->deserialize( de ); + break; + case eIT_PlugOutput: + if ( !m_plugOutput ) { + m_plugOutput = new ExtendedPlugInfoPlugOutputSpecificData; + } + m_plugOutput->deserialize( de ); + break; + case eIT_ClusterInfo: + if ( !m_plugClusterInfo ) { + m_plugClusterInfo = new ExtendedPlugInfoClusterInfoSpecificData; + } + m_plugClusterInfo->deserialize( de ); + break; + default: + return false; + } + + return true; +} + +ExtendedPlugInfoInfoType* +ExtendedPlugInfoInfoType::clone() const +{ + ExtendedPlugInfoInfoType* extPlugInfoInfoType + = new ExtendedPlugInfoInfoType( *this ); + extPlugInfoInfoType->initialize(); + return extPlugInfoInfoType; +} + +////////////////////////////////////////////// + +ExtendedPlugInfoCmd::ExtendedPlugInfoCmd( Ieee1394Service* ieee1394service, + ESubFunction eSubFunction ) + : AVCCommand( ieee1394service, AVC1394_CMD_PLUG_INFO ) +{ + setSubFunction( eSubFunction ); + UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, 0x00 ); + m_plugAddress = new PlugAddress( PlugAddress::ePD_Output, + PlugAddress::ePAM_Unit, + unitPlugAddress ); + m_infoType = + new ExtendedPlugInfoInfoType( ExtendedPlugInfoInfoType::eIT_PlugType ); + m_infoType->initialize(); +} + +ExtendedPlugInfoCmd::~ExtendedPlugInfoCmd() +{ + delete m_plugAddress; + m_plugAddress = 0; + delete m_infoType; + m_infoType = 0; +} + +bool +ExtendedPlugInfoCmd::serialize( IOSSerialize& se ) +{ + AVCCommand::serialize( se ); + se.write( m_subFunction, "ExtendedPlugInfoCmd subFunction" ); + m_plugAddress->serialize( se ); + m_infoType->serialize( se ); + + return true; +} + +bool +ExtendedPlugInfoCmd::deserialize( IISDeserialize& de ) +{ + AVCCommand::deserialize( de ); + de.read( &m_subFunction ); + m_plugAddress->deserialize( de ); + m_infoType->deserialize( de ); + + return true; +} + +bool +ExtendedPlugInfoCmd::fire() +{ + bool result = false; + + #define STREAM_FORMAT_REQUEST_SIZE 20 // XXX random length + union UPacket { + quadlet_t quadlet[STREAM_FORMAT_REQUEST_SIZE]; + unsigned char byte[STREAM_FORMAT_REQUEST_SIZE*4]; + }; + typedef union UPacket packet_t; + + packet_t req; + packet_t* resp; + + // initialize complete packet + memset( &req, 0xff, sizeof( req ) ); + + BufferSerialize se( req.byte, sizeof( req ) ); + if ( !serialize( se ) ) { + printf( "ExtendedPlugInfoCmd::fire: Could not serialize\n" ); + return false; + } + + // reorder the bytes to the correct layout + for (int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i) { + req.quadlet[i] = ntohl( req.quadlet[i] ); + } + + if ( isVerbose() ) { + // debug output + puts("request:"); + for (int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i) { + printf(" %2d: 0x%08x\n", i, req.quadlet[i]); + } + } + + resp = reinterpret_cast( + m_1394Service->transactionBlock( m_nodeId, + req.quadlet, + STREAM_FORMAT_REQUEST_SIZE ) ); + if ( resp ) { + if ( isVerbose() ) { + // debug output + puts("response:"); + for ( int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i ) { + printf( " %2d: 0x%08x\n", i, resp->quadlet[i] ); + } + } + + // reorder the bytes to the correct layout + for ( int i = 0; i < STREAM_FORMAT_REQUEST_SIZE; ++i ) { + resp->quadlet[i] = htonl( resp->quadlet[i] ); + } + + if ( isVerbose() ) { + // a more detailed debug output + printf( "\n" ); + printf( " idx type value\n" ); + printf( "-------------------------------------\n" ); + printf( " %02d ctype: 0x%02x\n", 0, resp->byte[0] ); + printf( " %02d subunit_type + subunit_id: 0x%02x\n", 1, resp->byte[1] ); + printf( " %02d opcode: 0x%02x\n", 2, resp->byte[2] ); + + for ( int i = 3; i < STREAM_FORMAT_REQUEST_SIZE * 4; ++i ) { + printf( " %02d operand %2d: 0x%02x\n", i, i-3, resp->byte[i] ); + } + } + + // parse output + parseResponse( resp->byte[0] ); + switch ( getResponse() ) + { + case eR_Implemented: + { + BufferDeserialize de( resp->byte, sizeof( req ) ); + deserialize( de ); + result = true; + } + break; + default: + printf( "unexpected response received (0x%x)\n", getResponse() ); + } + } else { + printf( "no response\n" ); + } + + return result; +} + +bool +ExtendedPlugInfoCmd::setPlugAddress( const PlugAddress& plugAddress ) +{ + delete m_plugAddress; + m_plugAddress = plugAddress.clone(); + return true; +} + +bool +ExtendedPlugInfoCmd::setSubFunction( ESubFunction subFunction ) +{ + m_subFunction = subFunction; + return true; +} + +bool +ExtendedPlugInfoCmd::setInfoType( const ExtendedPlugInfoInfoType& infoType ) +{ + delete m_infoType; + m_infoType = infoType.clone(); + return true; +} Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_signal_source.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_signal_source.h (revision 125) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_signal_source.h (revision 125) @@ -0,0 +1,98 @@ +/* avc_signal_source.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef AVCSignalSource_h +#define AVCSignalSource_h + +#include "avc_generic.h" +#include "avc_definitions.h" + +#include + +class SignalAddress: public IBusData +{ +public: + enum EPlugId { + ePI_AnyAvailableSerialBusPlug = 0x7e, + ePI_Invalid = 0xfe, + ePI_AnyAvailableExternalPlug = 0xff, + }; +}; + +class SignalUnitAddress: public SignalAddress +{ +public: + SignalUnitAddress(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual SignalUnitAddress* clone() const; + + byte_t m_plugId; +}; + +class SignalSubunitAddress: public SignalAddress +{ +public: + SignalSubunitAddress(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + virtual SignalSubunitAddress* clone() const; + + byte_t m_subunitType; + byte_t m_subunitId; + byte_t m_plugId; +}; + +class SignalSourceCmd: public AVCCommand +{ +public: + SignalSourceCmd( Ieee1394Service* ieee1394service ); + virtual ~SignalSourceCmd(); + + virtual bool serialize( IOSSerialize& se ); + virtual bool deserialize( IISDeserialize& de ); + + virtual bool fire( raw1394handle_t handle, + unsigned int node_id ); + + bool setSignalSource( SignalUnitAddress& signalAddress ); + bool setSignalSource( SignalSubunitAddress& signalAddress ); + bool setSignalDestination( SignalUnitAddress& signalAddress ); + bool setSignalDestination( SignalSubunitAddress& signalAddress ); + + SignalAddress* getSignalSource(); + SignalAddress* getSignalDestination(); + + // Control response + byte_t m_resultStatus; + + // Status response + byte_t m_outputStatus; + byte_t m_conv; + byte_t m_signalStatus; + + SignalAddress* m_signalSource; + SignalAddress* m_signalDestination; +}; + + +#endif // AVCSignalSource_h Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/.cvsignore =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/.cvsignore (revision 156) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/.cvsignore (revision 156) @@ -0,0 +1,7 @@ +.cvsignore +Makefile +Makefile.in +.deps +.libs +*.lo +*.la Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/serialize.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/serialize.h (revision 125) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/serialize.h (revision 125) @@ -0,0 +1,106 @@ +/* serialize.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef Serialize_h +#define Serialize_h + +#include // byte_t and quadlet_t declaration + +// Interfaces + +class IOSSerialize { +public: + IOSSerialize() {} + virtual ~IOSSerialize() {} + + virtual bool write( byte_t value, const char* name = "" ) = 0; + virtual bool write( quadlet_t value, const char* name = "" ) = 0; +}; + +class IISDeserialize { +public: + IISDeserialize() {} + virtual ~IISDeserialize() {} + + virtual bool read( byte_t* value ) = 0; + virtual bool read( quadlet_t* value ) = 0; + virtual bool peek( byte_t* value ) = 0; +}; + +// Specialized implementations of previously defined interfaces + +class CoutSerializer: public IOSSerialize { +public: + CoutSerializer() + : IOSSerialize() + {} + virtual ~CoutSerializer() {} + + virtual bool write( byte_t value, const char* name = "" ); + virtual bool write( quadlet_t value, const char* name = "" ); +}; + +class BufferSerialize: public IOSSerialize { +public: + BufferSerialize( unsigned char* buffer, size_t length ) + : IOSSerialize() + , m_buffer( buffer ) + , m_curPos( m_buffer ) + , m_length( length ) + {} + virtual ~BufferSerialize() {} + + virtual bool write( byte_t value, const char* name = "" ); + virtual bool write( quadlet_t value, const char* name = "" ); + +protected: + inline bool isCurPosValid() const; + +private: + unsigned char* m_buffer; + unsigned char* m_curPos; + size_t m_length; +}; + +class BufferDeserialize: public IISDeserialize { +public: + BufferDeserialize( const unsigned char* buffer, size_t length ) + : IISDeserialize() + , m_buffer( const_cast( buffer ) ) + , m_curPos( m_buffer ) + , m_length( length ) + {} + virtual ~BufferDeserialize() {} + + virtual bool read( byte_t* value ); + virtual bool read( quadlet_t* value ); + virtual bool peek( byte_t* value ); + +protected: + inline bool isCurPosValid() const; + +private: + unsigned char* m_buffer; // start of the buffer + unsigned char* m_curPos; // current read pos + size_t m_length; // length of buffer +}; + +#endif // Serialize_h + Index: /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_subunit_info.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_subunit_info.cpp (revision 125) +++ /tags/release_0_0_6/libfreebob/src/libfreebobavc/avc_subunit_info.cpp (revision 125) @@ -0,0 +1,187 @@ +/* avc_subunit_info.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "avc_subunit_info.h" +#include "serialize.h" +#include "ieee1394service.h" + +#include +#include + +using namespace std; + +SubUnitInfoCmd::SubUnitInfoCmd( Ieee1394Service* ieee1349service ) + : AVCCommand( ieee1349service, AVC1394_CMD_SUBUNIT_INFO ) +{ + clear(); +} + +bool +SubUnitInfoCmd::clear() +{ + m_page = 0xff; + m_extension_code = 0x7; + for ( int i = 0; i < eMaxSubunitsPerPage; ++i ) { + m_table[i].m_subunit_type = 0xff; + m_table[i].m_max_subunit_id = 0xff; + } + m_nrOfValidEntries = 0; + return true; +} + + +SubUnitInfoCmd::~SubUnitInfoCmd() +{ +} + +bool +SubUnitInfoCmd::serialize( IOSSerialize& se ) +{ + AVCCommand::serialize( se ); + + byte_t operand = 0; + operand = (( m_page & 0x7 ) << 4 ) | ( m_extension_code & 0x7 ); + se.write( operand, "SubUnitInfoCmd page and extension_code" ); + + for ( int i = 0; i < eMaxSubunitsPerPage; ++i ) { + operand = ( m_table[i].m_subunit_type << 3 ) + | ( m_table[i].m_max_subunit_id & 0x7 ); + se.write( operand, "SubUnitInfoCmd subunit_type and max_subunit_ID" ); + } + + return true; +} + +bool +SubUnitInfoCmd::deserialize( IISDeserialize& de ) +{ + AVCCommand::deserialize( de ); + + byte_t operand; + de.read( &operand ); + m_page = ( operand >> 4 ) & 0x7; + m_extension_code = operand & 0x7; + + m_nrOfValidEntries = 0; + for ( int i = 0; i < eMaxSubunitsPerPage; ++i ) { + de.read( &operand ); + m_table[i].m_subunit_type = operand >> 3; + m_table[i].m_max_subunit_id = operand & 0x7; + + if ( operand != 0xff ) { + m_nrOfValidEntries++; + } + } + + return true; +} + +bool +SubUnitInfoCmd::fire() +{ + bool result = false; + + #define REQUEST_SIZE 2 + union UPacket { + quadlet_t quadlet[REQUEST_SIZE]; + unsigned char byte[REQUEST_SIZE*4]; + }; + typedef union UPacket packet_t; + + packet_t req; + packet_t* resp; + + // initialize complete packet + memset( &req, 0xff, sizeof( req ) ); + + BufferSerialize se( req.byte, sizeof( req ) ); + if ( !serialize( se ) ) { + printf( "UnitInoCmd::fire: Could not serialize\n" ); + return false; + } + + // reorder the bytes to the correct layout + for (int i = 0; i < REQUEST_SIZE; ++i) { + req.quadlet[i] = ntohl( req.quadlet[i] ); + } + + if ( isVerbose() ) { + // debug output + puts("request:"); + for (int i = 0; i < REQUEST_SIZE; ++i) { + printf(" %2d: 0x%08x\n", i, req.quadlet[i]); + } + } + + resp = reinterpret_cast( + m_1394Service->transactionBlock( m_nodeId, + req.quadlet, + REQUEST_SIZE ) ); + if ( resp ) { + if ( isVerbose() ) { + // debug output + puts("response:"); + for ( int i = 0; i < REQUEST_SIZE; ++i ) { + printf( " %2d: 0x%08x\n", i, resp->quadlet[i] ); + } + } + + // reorder the bytes to the correct layout + for ( int i = 0; i < REQUEST_SIZE; ++i ) { + resp->quadlet[i] = htonl( resp->quadlet[i] ); + } + + if ( isVerbose() ) { + // a more detailed debug output + printf( "\n" ); + printf( " idx type value\n" ); + printf( "-------------------------------------\n" ); + printf( " %02d ctype: 0x%02x\n", 0, resp->byte[0] ); + printf( " %02d subunit_type + subunit_id: 0x%02x\n", 1, resp->byte[1] ); + printf( " %02d opcode: 0x%02x\n", 2, resp->byte[2] ); + + for ( int i = 3; i < REQUEST_SIZE * 4; ++i ) { + printf( " %02d operand %2d: 0x%02x\n", i, i-3, resp->byte[i] ); + } + } + + // parse output + parseResponse( resp->byte[0] ); + switch ( getResponse() ) + { + case eR_Implemented: + { + BufferDeserialize de( resp->byte, sizeof( req ) ); + deserialize( de ); + result = true; + } + break; + case eR_NotImplemented: + break; + + default: + printf( "unexpected response received (0x%x)\n", getResponse() ); + } + } else { + printf( "no response\n" ); + } + + return result; +} Index: /tags/release_0_0_6/libfreebob/src/avdevicesubunit.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/avdevicesubunit.h (revision 156) +++ /tags/release_0_0_6/libfreebob/src/avdevicesubunit.h (revision 156) @@ -0,0 +1,83 @@ +/* avdevicesubunit.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef AVDEVICESUBUNIT_H +#define AVDEVICESUBUNIT_H + +#include "avplug.h" + +#include "debugmodule/debugmodule.h" +#include "libfreebobavc/avc_definitions.h" +#include "libfreebobavc/avc_generic.h" + +#include + +class AvDevice; + +class AvDeviceSubunit { + public: + AvDeviceSubunit( AvDevice* avDevice, subunit_type_t type, subunit_t id ); + virtual ~AvDeviceSubunit(); + + virtual bool discover() = 0; + virtual const char* getName() = 0; + + bool addPlug( AvPlug& plug ); + + subunit_t getSubunitId() + { return m_sbId; } + subunit_type_t getSubunitType() + { return m_sbType; } + + protected: + AvDevice* m_avDevice; + subunit_type_t m_sbType; + subunit_t m_sbId; + + AvPlugVector m_plugs; + + DECLARE_DEBUG_MODULE; +}; + +typedef std::vector AvDeviceSubunitVector; + +///////////////////////////// + +class AvDeviceSubunitAudio: public AvDeviceSubunit { + public: + AvDeviceSubunitAudio( AvDevice* avDevice, subunit_t id ); + virtual ~AvDeviceSubunitAudio(); + + virtual bool discover(); + virtual const char* getName(); +}; + +///////////////////////////// + +class AvDeviceSubunitMusic: public AvDeviceSubunit { + public: + AvDeviceSubunitMusic( AvDevice* avDevice, subunit_t id ); + virtual ~AvDeviceSubunitMusic(); + + virtual bool discover(); + virtual const char* getName(); +}; + +#endif Index: /tags/release_0_0_6/libfreebob/src/debugmodule/debugmodule.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/debugmodule/debugmodule.h (revision 156) +++ /tags/release_0_0_6/libfreebob/src/debugmodule/debugmodule.h (revision 156) @@ -0,0 +1,172 @@ +/* debugmodule.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef DEBUGMODULE_H +#define DEBUGMODULE_H + +#include "../fbtypes.h" + +#include +#include + +typedef short debug_level_t; + +#define debugFatal( format, args... ) \ + m_debugModule.print( DebugModule::eDL_Fatal, \ + __FILE__, \ + __FUNCTION__, \ + __LINE__, \ + format, \ + ##args ) +#define debugError( format, args... ) \ + m_debugModule.print( DebugModule::eDL_Error, \ + __FILE__, \ + __FUNCTION__, \ + __LINE__, \ + format, \ + ##args ) +#define debugWarning( format, args... ) \ + m_debugModule.print( DebugModule::eDL_Warning, \ + __FILE__, \ + __FUNCTION__, \ + __LINE__, \ + format, \ + ##args ) + +#define debugFatalShort( format, args... ) \ + m_debugModule.printShort( DebugModule::eDL_Fatal, \ + format, \ + ##args ) +#define debugErrorShort( format, args... ) \ + m_debugModule.printShort( DebugModule::eDL_Error, \ + format, \ + ##args ) +#define debugWarningShort( format, args... ) \ + m_debugModule.printShort( DebugModule::eDL_Warning, \ + format, \ + ##args ) + +#define DECLARE_DEBUG_MODULE static DebugModule m_debugModule +#define IMPL_DEBUG_MODULE( ClassName, RegisterName, Level ) \ + DebugModule ClassName::m_debugModule = \ + DebugModule( #RegisterName, Level ) + +#define DECLARE_GLOBAL_DEBUG_MODULE extern DebugModule m_debugModule +#define IMPL_GLOBAL_DEBUG_MODULE( RegisterName, Level ) \ + DebugModule m_debugModule = \ + DebugModule( #RegisterName, Level ) + + + +#ifdef DEBUG + + #define debugOutput( level, format, args... ) \ + m_debugModule.print( level, \ + __FILE__, \ + __FUNCTION__, \ + __LINE__, \ + format, \ + ##args ) + + #define debugOutputShort( level, format, args... ) \ + m_debugModule.printShort( level, \ + format, \ + ##args ) + +#else + + #define debugOutput( level, format, args... ) + #define debugOutputShort( level, format, args... ) + +#endif + +unsigned char toAscii( unsigned char c ); +void quadlet2char( fb_quadlet_t quadlet, unsigned char* buff ); +void hexDump( unsigned char *data_start, unsigned int length ); +void hexDumpQuadlets( quadlet_t *data_start, unsigned int length ); + +class DebugModule { +public: + enum { + eDL_Fatal = 0, + eDL_Error = 1, + eDL_Warning = 2, + eDL_Normal = 3, + eDL_Verbose = 4, + } EDebugLevel; + + DebugModule( std::string name, debug_level_t level ); + virtual ~DebugModule(); + + void printShort( debug_level_t level, + const char* format, + ... ) const; + + void print( debug_level_t level, + const char* file, + const char* function, + unsigned int line, + const char* format, + ... ) const; + + bool setLevel( debug_level_t level ) + { m_level = level; return true; } + debug_level_t getLevel() + { return m_level; } + std::string getName() + { return m_name; } + +protected: + const char* getPreSequence( debug_level_t level ) const; + const char* getPostSequence( debug_level_t level ) const; + +private: + std::string m_name; + debug_level_t m_level; +}; + +#define DEBUG_LEVEL_NORMAL DebugModule::eDL_Normal +#define DEBUG_LEVEL_VERBOSE DebugModule::eDL_Verbose + + +class DebugModuleManager { +public: + friend class DebugModule; + + static DebugModuleManager* instance(); + bool setDebugLevel( std::string name, debug_level_t level ); + +protected: + bool registerModule( DebugModule& debugModule ); + bool unregisterModule( DebugModule& debugModule ); + +private: + DebugModuleManager(); + ~DebugModuleManager(); + + typedef std::vector< DebugModule* > DebugModuleVector; + typedef std::vector< DebugModule* >::iterator DebugModuleVectorIterator; + + + static DebugModuleManager* m_instance; + DebugModuleVector m_debugModules; +}; + +#endif Index: /tags/release_0_0_6/libfreebob/src/debugmodule/Makefile.am =================================================================== --- /tags/release_0_0_6/libfreebob/src/debugmodule/Makefile.am (revision 125) +++ /tags/release_0_0_6/libfreebob/src/debugmodule/Makefile.am (revision 125) @@ -0,0 +1,30 @@ +# Makefile.am - Makefile template +# Copyright (C) 2005 by Daniel Wagner. +# +# This file is part of FreeBob. +# +# FreeBob 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. +# FreeBob 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 FreeBob; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +noinst_LTLIBRARIES = libdebugmodule.la + + +libdebugmodule_la_SOURCES = \ + debugmodule.h \ + debugmodule.cpp + + +noinst_PROGRAMS = test_debugmodule +test_debugmodule_SOURCES = test_debugmodule.cpp +test_debugmodule_LDADD = libdebugmodule.la + +MAINTAINERCLEANFILES = Makefile.in Index: /tags/release_0_0_6/libfreebob/src/debugmodule/test_debugmodule.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/debugmodule/test_debugmodule.cpp (revision 125) +++ /tags/release_0_0_6/libfreebob/src/debugmodule/test_debugmodule.cpp (revision 125) @@ -0,0 +1,78 @@ +#include "debugmodule.h" + +#include + +using namespace std; + +class Test +{ +public: + Test() + {} + ~Test() + {} + + bool run() { + cout << "######################" << endl; + cout << "### Test arguments ###" << endl; + cout << "######################" << endl; + debugOutput( DEBUG_LEVEL_NORMAL, "arg0 = %d, arg1 = 0x%08x\n" + , 1, 0xdeedbeef ); + cout << endl << endl; + + + cout << "###################" << endl; + cout << "### Test levels ###" << endl; + cout << "###################" << endl; + for ( debug_level_t level = DEBUG_LEVEL_VERBOSE; + level >= 0; + --level ) + { + DebugModuleManager::instance()->setDebugLevel( "Test", level ); + + cout << endl << "*** Debug Level = " << level << endl << endl; + + debugFatal( "fatal text\n" ); + debugError( "error text\n" ); + debugWarning( "warning text\n" ); + debugOutput( DEBUG_LEVEL_NORMAL, "normal output\n" ); + debugOutput( DEBUG_LEVEL_VERBOSE, "verbose output\n" ); + debugFatalShort( "fatal short text\n" ); + debugErrorShort( "error short text\n" ); + debugWarningShort( "warning short text\n" ); + debugOutputShort( DEBUG_LEVEL_NORMAL, "normal short output\n" ); + debugOutputShort( DEBUG_LEVEL_VERBOSE, "verbose short output\n" ); + } + cout << endl << endl; + + return true; + } + + DECLARE_DEBUG_MODULE; +}; + +IMPL_DEBUG_MODULE( Test, Test, DEBUG_LEVEL_VERBOSE ); + +DECLARE_GLOBAL_DEBUG_MODULE; +IMPL_GLOBAL_DEBUG_MODULE( Test, DEBUG_LEVEL_VERBOSE ); + +int main( int argc, char** argv ) +{ + cout << "#################################" << endl; + cout << "### Test global debug module ###" << endl; + cout << "#################################" << endl; + debugOutput( DEBUG_LEVEL_NORMAL, "foobar\n" ); + cout << endl << endl; + + Test test; + test.run(); + + return 0; +} + +/* + * Local variables: + * compile-command: "g++ -Wall -g -DDEBUG -o test test.cpp -L. -ldebugmodule" + * End: + */ + Index: /tags/release_0_0_6/libfreebob/src/debugmodule/.cvsignore =================================================================== --- /tags/release_0_0_6/libfreebob/src/debugmodule/.cvsignore (revision 156) +++ /tags/release_0_0_6/libfreebob/src/debugmodule/.cvsignore (revision 156) @@ -0,0 +1,8 @@ +.cvsignore +Makefile +Makefile.in +.deps +.libs +*.lo +*.la +test_debugmodule Index: /tags/release_0_0_6/libfreebob/src/debugmodule/debugmodule.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/debugmodule/debugmodule.cpp (revision 125) +++ /tags/release_0_0_6/libfreebob/src/debugmodule/debugmodule.cpp (revision 125) @@ -0,0 +1,302 @@ +/* debugmodule.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "debugmodule.h" + +#include +#include + +#include + +using namespace std; + +struct ColorEntry { + const char* preSequence; + const char* postSequence; +}; + +ColorEntry colorTable[] = { + { "\033[31mFatal", "\033[0m" }, + { "\033[31mError", "\033[0m" }, + { "\033[31mWarning", "\033[0m" }, + { "Debug", "" }, +}; + + +DebugModule::DebugModule( std::string name, debug_level_t level ) + : m_name( name ) + , m_level( level ) +{ + if ( !DebugModuleManager::instance()->registerModule( *this ) ) { + cerr << "Could not register DebugModule (" << name + << ") at DebugModuleManager" + << endl; + } +} + +DebugModule::~DebugModule() +{ + if ( !DebugModuleManager::instance()->unregisterModule( *this ) ) { + cerr << "Could not unregister DebugModule at DebugModuleManager" + << endl; + } +} + +void +DebugModule::printShort( debug_level_t level, + const char* format, + ... ) const +{ + if ( level > m_level ) { + return; + } + + va_list arg; + + va_start( arg, format ); + if ( printf( "%s: ", getPreSequence( level ) ) < 0 ) { + cerr << "Could not create debug string with printf" << endl; + return; + } + if ( vprintf( format, arg ) < 0 ) { + cerr << "Could not create debug string with printf" << endl; + return; + } + if ( printf( "%s", getPostSequence( level ) ) < 0 ) { + cerr << "Could not create debug string with printf" << endl; + return; + } + va_end( arg ); +} + +void +DebugModule::print( debug_level_t level, + const char* file, + const char* function, + unsigned int line, + const char* format, + ... ) const +{ + if ( level > m_level ) { + return; + } + + va_list arg; + va_start( arg, format ); + + if ( printf( "%s (%s)[%d] %s: ", getPreSequence( level ), + file, line, function ) < 0 ) { + cerr << "Could not create debug string with printf" << endl; + return; + } + if ( vprintf( format, arg ) < 0 ) { + cerr << "Could not create debug string with printf" << endl; + return; + } + if ( printf( "%s", getPostSequence( level ) ) < 0 ) { + cerr << "Could not create debug string with printf" << endl; + return; + } + va_end( arg );} + +const char* +DebugModule::getPreSequence( debug_level_t level ) const +{ + if ( ( level <= eDL_Normal ) && ( level >= eDL_Fatal ) ) { + return colorTable[level].preSequence; + } + return colorTable[eDL_Normal].preSequence; +} + +const char* +DebugModule::getPostSequence( debug_level_t level ) const +{ + if ( ( level <= eDL_Normal ) && ( level >= eDL_Fatal ) ) { + return colorTable[level].postSequence; + } + return colorTable[eDL_Normal].postSequence; +} + +//-------------------------------------- + +DebugModuleManager* DebugModuleManager::m_instance = 0; + +DebugModuleManager::DebugModuleManager() +{ +} + +DebugModuleManager::~DebugModuleManager() +{ +} + +DebugModuleManager* +DebugModuleManager::instance() +{ + if ( !m_instance ) { + m_instance = new DebugModuleManager; + if ( !m_instance ) { + cerr << "DebugModuleManager::instance Failed to create " + << "DebugModuleManager" << endl; + } + } + return m_instance; +} + +bool +DebugModuleManager::registerModule( DebugModule& debugModule ) +{ + m_debugModules.push_back( &debugModule ); + return true; +} + +bool +DebugModuleManager::unregisterModule( DebugModule& debugModule ) +{ + for ( DebugModuleVectorIterator it = m_debugModules.begin(); + it != m_debugModules.end(); + ++it ) + { + if ( *it == &debugModule ) { + m_debugModules.erase( it ); + return true; + } + } + + cerr << "DebugModuleManager::unregisterModule: Could not unregister " + << "DebugModule (" << debugModule.getName() << ")" << endl; + return false; +} + +bool +DebugModuleManager::setDebugLevel( std::string name, debug_level_t level ) +{ + for ( DebugModuleVectorIterator it = m_debugModules.begin(); + it != m_debugModules.end(); + ++it ) + { + if ( (*it)->getName() == name ) { + return (*it)->setLevel( level ); + } + } + + cerr << "setDebugLevel: Did not find DebugModule (" + << name << ")" << endl; + return false; +} + +//---------------------------------------- + +unsigned char +toAscii( unsigned char c ) +{ + if ( ( c > 31 ) && ( c < 126) ) { + return c; + } else { + return '.'; + } +} + +/* converts a quadlet to a uchar * buffer + * not implemented optimally, but clear + */ +void +quadlet2char( quadlet_t quadlet, unsigned char* buff ) +{ + *(buff) = (quadlet>>24)&0xFF; + *(buff+1) = (quadlet>>16)&0xFF; + *(buff+2) = (quadlet>> 8)&0xFF; + *(buff+3) = (quadlet) &0xFF; +} + +void +hexDump( unsigned char *data_start, unsigned int length ) +{ + unsigned int i=0; + unsigned int byte_pos; + unsigned int bytes_left; + + if ( length <= 0 ) { + return; + } + if ( length >= 7 ) { + for ( i = 0; i < (length-7); i += 8 ) { + printf( "%04X: %02X %02X %02X %02X %02X %02X %02X %02X " + "- [%c%c%c%c%c%c%c%c]\n", + + i, + + *(data_start+i+0), + *(data_start+i+1), + *(data_start+i+2), + *(data_start+i+3), + *(data_start+i+4), + *(data_start+i+5), + *(data_start+i+6), + *(data_start+i+7), + + toAscii( *(data_start+i+0) ), + toAscii( *(data_start+i+1) ), + toAscii( *(data_start+i+2) ), + toAscii( *(data_start+i+3) ), + toAscii( *(data_start+i+4) ), + toAscii( *(data_start+i+5) ), + toAscii( *(data_start+i+6) ), + toAscii( *(data_start+i+7) ) + ); + } + } + byte_pos = i; + bytes_left = length - byte_pos; + + printf( "%04X:" ,i ); + for ( i = byte_pos; i < length; i += 1 ) { + printf( " %02X", *(data_start+i) ); + } + for ( i=0; i < 8-bytes_left; i+=1 ) { + printf( " " ); + } + + printf( " - [" ); + for ( i = byte_pos; i < length; i += 1) { + printf( "%c", toAscii(*(data_start+i))); + } + for ( i = 0; i < 8-bytes_left; i += 1) { + printf( " " ); + } + + printf( "]" ); + printf( "\n" ); +} + +void +hexDumpQuadlets( quadlet_t *data, unsigned int length ) +{ + unsigned int i=0; + + if ( length <= 0 ) { + return; + } + for (i = 0; i< length; i += 1) { + printf( "%02d %04X: %08X (%08X)" + "\n", i, i*4, data[i],ntohl(data[i])); + } +} + + Index: /tags/release_0_0_6/libfreebob/src/xmlparser.c =================================================================== --- /tags/release_0_0_6/libfreebob/src/xmlparser.c (revision 153) +++ /tags/release_0_0_6/libfreebob/src/xmlparser.c (revision 153) @@ -0,0 +1,787 @@ +/* xmlparser.cpp + * Copyright (C) 2005,06 Pieter Palmers, Daniel Wagner + * + * This file is part of FreeBoB + * + * 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 Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include "libfreebob/xmlparser.h" +#include "libfreebob/freebob.h" + +#include +#include + +#include +#include +#include +#include + +#undef DEBUG +#ifdef DEBUG +#define debugPrint( format, args... ) printf( format, ##args ) +#else +#define debugPrint( format, args... ) +#endif + +/* XML parsing functions + */ +freebob_stream_spec_t* +freebob_xmlparse_stream( xmlDocPtr doc, xmlNodePtr cur ) +{ + freebob_stream_spec_t *stream_spec; + + // allocate memory + stream_spec = malloc( sizeof(freebob_stream_spec_t) ); + if ( !stream_spec ) { + fprintf( stderr, "Could not allocate memory for stream_spec" ); + return 0; + } + +#define StreamSpecParseNode( NodeName, Member ) \ + if ( !xmlStrcmp( cur->name, (const xmlChar*) NodeName ) ) { \ + xmlChar* key = \ + xmlNodeListGetString( doc, cur->xmlChildrenNode, 1 ); \ + debugPrint( "\t\t"#NodeName": %s\n", key ); \ + stream_spec->Member = strtol( (const char*) key, \ + (char**) 0, 10 ); \ + xmlFree( key ); \ + } + + cur = cur->xmlChildrenNode; + while ( cur ) { + StreamSpecParseNode( "Position", position ); + StreamSpecParseNode( "Location", location ); + StreamSpecParseNode( "Format", format ); + StreamSpecParseNode( "Type", type ); + StreamSpecParseNode( "DestinationPort", destination_port ); + + if ( !xmlStrcmp( cur->name, (const xmlChar *) "Name" ) ) { + xmlChar* key = + xmlNodeListGetString( doc, cur->xmlChildrenNode, 1 ); + debugPrint( "\t\tname: %s\n", key ); + strncpy( stream_spec->name, (const char*) key, + FREEBOB_MAX_NAME_LEN ); + xmlFree( key ); + } + cur = cur->next; + } +#undef StreamSpecParseNode + + return stream_spec; +} + +freebob_stream_info_t * +freebob_xmlparse_streams( xmlDocPtr doc, xmlNodePtr node ) +{ + freebob_stream_info_t* stream_info; + + // allocate memory + stream_info = malloc( sizeof(freebob_stream_info_t) ); + if ( !stream_info ) { + fprintf( stderr, "Could not allocate memory for stream_info" ); + return 0; + } + + // count number of child streams + stream_info->nb_streams=0; + xmlNodePtr cur = node->xmlChildrenNode; + while (cur != NULL) { + if ( !xmlStrcmp( cur->name, (const xmlChar*) "Stream" ) ) { + stream_info->nb_streams++; + } + cur = cur->next; + } + + if ( stream_info->nb_streams ) { + // allocate memory for the stream_spec pointer array + stream_info->streams = + (freebob_stream_spec_t**) calloc( stream_info->nb_streams, + sizeof(freebob_stream_spec_t*) ); + + if ( !stream_info->streams ) { + fprintf( stderr, "Could not allocate memory for stream specs" ); + free( stream_info ); + return 0; + } + + // parse the child stream_specs + cur = node->xmlChildrenNode; + int i = 0; + while ( cur ) { + if ( !xmlStrcmp( cur->name, (const xmlChar*) "Stream" ) ) { + stream_info->streams[i] = + freebob_xmlparse_stream( doc, cur ); + + if ( !stream_info->streams[i] ) { + // invalid XML or memory problem, clean up. + while ( --i ) { + free( stream_info->streams[i] ); + } + free( stream_info->streams ); + stream_info->streams = 0; + free( stream_info ); + return 0; + } + i++; + } + cur = cur->next; + } + } + return stream_info; +} + + + + +freebob_connection_spec_t* +freebob_xmlparse_connection( xmlDocPtr doc, xmlNodePtr cur ) +{ +#define ConnectionSpecParseNode( NodeName, Member ) \ + if ( !xmlStrcmp( cur->name, (const xmlChar*) NodeName ) ) { \ + xmlChar* key = \ + xmlNodeListGetString( doc, cur->xmlChildrenNode, 1 ); \ + debugPrint( "\t"#NodeName": %s\n", key ); \ + connection_spec->Member = strtol( (const char*) key, \ + (char**) 0, 10 ); \ + xmlFree( key ); \ + } + + // allocate memory + freebob_connection_spec_t* connection_spec = + calloc( 1, sizeof(freebob_connection_spec_t) ); + if ( !connection_spec ) { + fprintf( stderr, "Could not allocate memory for connection_spec" ); + return 0; + } + + cur = cur->xmlChildrenNode; + while ( cur ) { + ConnectionSpecParseNode( "Id", id ); + ConnectionSpecParseNode( "Node", node ); + ConnectionSpecParseNode( "Port", port ); + ConnectionSpecParseNode( "Plug", plug ); + ConnectionSpecParseNode( "Dimension", dimension ); + ConnectionSpecParseNode( "Samplerate", samplerate ); + ConnectionSpecParseNode( "IsoChannel", iso_channel ); + + if ( !xmlStrcmp( cur->name, (const xmlChar*) "Streams" ) ) { + connection_spec->stream_info + = freebob_xmlparse_streams( doc, cur ); + if ( !connection_spec->stream_info ) { + free( connection_spec ); + return 0; + } + } + cur = cur->next; + } +#undef ConnectionSpecParseNode + + return connection_spec; +} + +freebob_supported_stream_format_spec_t* +freebob_xmlparse_supported_stream_format_node( xmlDocPtr doc, xmlNodePtr cur ) +{ +#define FormatSpecParseNode( NodeName, Member ) \ + if ( !xmlStrcmp( cur->name, (const xmlChar*) NodeName ) ) { \ + xmlChar* key = \ + xmlNodeListGetString( doc, cur->xmlChildrenNode, 1 ); \ + debugPrint( "\t"#NodeName": %s\n", key ); \ + format_spec->Member = strtol( (const char*) key, \ + (char**) 0, 10 ); \ + xmlFree( key ); \ + } + + // allocate memory + freebob_supported_stream_format_spec_t* format_spec = + calloc( 1, sizeof(freebob_supported_stream_format_spec_t) ); + if ( !format_spec ) { + fprintf( stderr, "Could not allocate memory for format_spec" ); + return 0; + } + + cur = cur->xmlChildrenNode; + while ( cur ) { + FormatSpecParseNode( "Samplerate", samplerate ); + FormatSpecParseNode( "AudioChannels", nb_audio_channels ); + FormatSpecParseNode( "MidiChannels", nb_midi_channels ); + cur = cur->next; + } +#undef FormatSpecParseNode + + return format_spec; +} + +freebob_connection_info_t* +freebob_xmlparse_connectionset( xmlDocPtr doc, xmlNodePtr node ) +{ + assert( node ); + + // allocate memory + freebob_connection_info_t* connection_info = + malloc( sizeof(freebob_connection_info_t) ); + if ( !connection_info ) { + fprintf( stderr, "Could not allocate memory for connection_info" ); + return 0; + } + + // count number of child streams + connection_info->nb_connections = 0; + xmlNodePtr cur = node->xmlChildrenNode; + while ( cur ) { + if ( !xmlStrcmp( cur->name, (const xmlChar*) "Connection" ) ) { + connection_info->nb_connections = + connection_info->nb_connections + 1; + debugPrint( "nb_connections: %d\n", + connection_info->nb_connections ); + } + + if ( !xmlStrcmp( cur->name, (const xmlChar*) "Direction" ) ) { + xmlChar* key = + xmlNodeListGetString( doc, cur->xmlChildrenNode, 1 ); + debugPrint( "\tdirection: %s\n", key ); + connection_info->direction = strtol( (const char*) key, + (char**) 0, 10); + xmlFree( key ); + } + cur = cur->next; + } + + debugPrint( "ConnectionInfo contains %d connection_specs\n", + connection_info->nb_connections ); + + if ( connection_info->nb_connections ) { + // allocate memory for the connection_spec pointer array + connection_info->connections = + (freebob_connection_spec_t**) + calloc( connection_info->nb_connections, + sizeof(freebob_connection_spec_t*) ); + + if ( !connection_info->connections ) { + fprintf( stderr, + "Could not allocate memory for connection specs" ); + free( connection_info ); + return 0; + } + + // parse the child stream_specs + cur = node->xmlChildrenNode; + int i = 0; + while ( cur ) { + if ( !xmlStrcmp( cur->name, (const xmlChar*) "Connection" ) ) { + connection_info->connections[i] = + freebob_xmlparse_connection( doc, cur ); + + if ( !connection_info->connections[i] ) { + // invalid XML or memory problem, clean up. + while ( --i ) { + freebob_free_connection_spec( connection_info->connections[i] ); + } + free( connection_info->connections ); + connection_info->connections = 0; + free( connection_info ); + return 0; + } + i++; + } + cur = cur->next; + } + } + + return connection_info; +} + +freebob_supported_stream_format_info_t* +freebob_xmlparse_supported_stream_format( xmlDocPtr doc, xmlNodePtr node ) +{ + assert( node ); + + // allocate memory + freebob_supported_stream_format_info_t* stream_info = + malloc( sizeof(freebob_supported_stream_format_info_t) ); + if ( !stream_info ) { + fprintf( stderr, "Could not allocate memory for stream_info" ); + return 0; + } + + // count number of child streams + stream_info->nb_formats = 0; + xmlNodePtr cur = node->xmlChildrenNode; + while ( cur ) { + if ( !xmlStrcmp( cur->name, (const xmlChar*) "Format" ) ) { + stream_info->nb_formats += 1; + debugPrint( "\tnb_formats: %d\n", + stream_info->nb_formats ); + } + + if ( !xmlStrcmp( cur->name, (const xmlChar*) "Direction" ) ) { + xmlChar* key = + xmlNodeListGetString( doc, cur->xmlChildrenNode, 1 ); + debugPrint( "\tdirection: %s\n", key ); + stream_info->direction = strtol( (const char*) key, + (char**) 0, 10); + xmlFree( key ); + } + cur = cur->next; + } + + debugPrint( "StreamFormatInfo contains %d stream_format_specs\n", + stream_info->nb_formats ); + + if ( stream_info->nb_formats ) { + // allocate memory for the connection_spec pointer array + stream_info->formats = + (freebob_supported_stream_format_spec_t**) + calloc( stream_info->nb_formats, + sizeof(freebob_supported_stream_format_spec_t*) ); + + if ( !stream_info->formats ) { + fprintf( stderr, + "Could not allocate memory for stream format specs" ); + free( stream_info ); + return 0; + } + + // parse the child stream_specs + cur = node->xmlChildrenNode; + int i = 0; + while ( cur ) { + if ( !xmlStrcmp( cur->name, (const xmlChar*) "Format" ) ) { + stream_info->formats[i] = + freebob_xmlparse_supported_stream_format_node( doc, cur ); + + if ( !stream_info->formats[i] ) { + // invalid XML or memory problem, clean up. + while ( --i ) { + freebob_free_supported_stream_format_spec( stream_info->formats[i] ); + } + free( stream_info->formats ); + stream_info->formats = 0; + free( stream_info ); + return 0; + } + i++; + } + cur = cur->next; + } + } + + return stream_info; +} + + +xmlNodePtr +freebob_xmlparse_get_connectionset_node( xmlDocPtr doc, + xmlNodePtr cur, + int direction ) +{ + while ( cur ) { + if ( !xmlStrcmp( cur->name, (const xmlChar*) "ConnectionSet" ) ) { + xmlNodePtr cur2 = cur->xmlChildrenNode; + while ( cur2 ) { + if ( !xmlStrcmp( cur2->name, (const xmlChar*) "Direction" ) ) { + xmlChar* key = xmlNodeListGetString( doc, + cur2->xmlChildrenNode, + 1 ); + int tmp_direction = strtol( (const char*) key, + (char**) 0, 10 ); + xmlFree( key ); + if( tmp_direction == direction) { + return cur; + } + } + cur2 = cur2->next; + } + } + cur = cur->next; + } + return 0; +} + +xmlNodePtr +freebob_xmlparse_get_supported_stream_format_node( xmlDocPtr doc, + xmlNodePtr cur, + int direction ) +{ + while ( cur ) { + if ( !xmlStrcmp( cur->name, (const xmlChar*) "StreamFormats" ) ) { + xmlNodePtr cur2 = cur->xmlChildrenNode; + while ( cur2 ) { + if ( !xmlStrcmp( cur2->name, (const xmlChar*) "Direction" ) ) { + xmlChar* key = xmlNodeListGetString( doc, + cur2->xmlChildrenNode, + 1 ); + int tmp_direction = strtol( (const char*) key, + (char**) 0, 10 ); + xmlFree( key ); + if( tmp_direction == direction) { + return cur; + } + } + cur2 = cur2->next; + } + } + cur = cur->next; + } + return 0; +} + +xmlNodePtr +freebob_xmlparse_get_connection_set_by_node_id( xmlDocPtr doc, + xmlNodePtr cur, + int nodeId ) +{ + while ( cur ) { + if ( !xmlStrcmp( cur->name, (const xmlChar*) "Device" ) ) { + xmlNodePtr cur2 = cur->xmlChildrenNode; + while ( cur2 ) { + if ( !xmlStrcmp( cur2->name, + (const xmlChar*) "NodeId" ) ) + { + xmlChar* key = xmlNodeListGetString( doc, + cur2->xmlChildrenNode, + 1 ); + int tmp_node_id = strtol( (const char*) key, + (char**) 0, 10 ); + xmlFree( key ); + + if ( tmp_node_id == nodeId ) { + xmlNodePtr cur3 = cur->xmlChildrenNode; + while ( cur3 ) { + if ( !xmlStrcmp( cur3->name, + (const xmlChar*) "ConnectionSet" ) ) + { + return cur3; + } + cur3 = cur3->next; + } + } + } + cur2 = cur2->next; + } + } + cur = cur->next; + } + + return 0; +} + +xmlNodePtr +freebob_xmlparse_get_supported_stream_format_set_by_node_id( xmlDocPtr doc, + xmlNodePtr cur, + int nodeId ) +{ + while ( cur ) { + if ( !xmlStrcmp( cur->name, (const xmlChar*) "Device" ) ) { + xmlNodePtr cur2 = cur->xmlChildrenNode; + while ( cur2 ) { + if ( !xmlStrcmp( cur2->name, + (const xmlChar*) "NodeId" ) ) + { + xmlChar* key = xmlNodeListGetString( doc, + cur2->xmlChildrenNode, + 1 ); + int tmp_node_id = strtol( (const char*) key, + (char**) 0, 10 ); + xmlFree( key ); + + if ( tmp_node_id == nodeId ) { + xmlNodePtr cur3 = cur->xmlChildrenNode; + while ( cur3 ) { + if ( !xmlStrcmp( cur3->name, + (const xmlChar*) "StreamFormats" ) ) + { + return cur3; + } + cur3 = cur3->next; + } + } + } + cur2 = cur2->next; + } + } + cur = cur->next; + } + + return 0; +} + +xmlNodePtr +freebob_xmlparse_get_connection_set_by_device( xmlDocPtr doc, + xmlNodePtr cur, + int device ) +{ + int count=0; + while ( count < device ) { + if(!cur) { + return NULL; + } + + if(!xmlStrcmp( cur->name, (const xmlChar*) "Device" )) { + count++; + } + cur=cur->next; + } + + if ( !xmlStrcmp( cur->name, (const xmlChar*) "Device" ) ) { + xmlNodePtr cur3 = cur->xmlChildrenNode; + while ( cur3 ) { + if ( !xmlStrcmp( cur3->name, + (const xmlChar*) "ConnectionSet" ) ) + { + return cur3; + } + cur3 = cur3->next; + } + } else { + return NULL; + } + + return NULL; +} + +// a side effect is that both old connection info's are freed, unless NULL is returned! +freebob_connection_info_t* +freebob_xmlparse_append_connectionset(freebob_connection_info_t* connection_info, freebob_connection_info_t* cinfo) +{ + if(connection_info==NULL) return cinfo; + if(cinfo==NULL) return connection_info; + + if (connection_info->direction != cinfo->direction) { + // direction mismatch + return NULL; + } + + freebob_connection_info_t *tmpci=calloc(1,sizeof(freebob_connection_info_t)); + if (!tmpci) { + return NULL; + } + + tmpci->nb_connections=connection_info->nb_connections+cinfo->nb_connections; + tmpci->connections = calloc( tmpci->nb_connections, sizeof(freebob_connection_spec_t*)); + + int i=0; + int c=0; + for(i=0;inb_connections;i++) { + tmpci->connections[c]=connection_info->connections[i]; // these are pointers + c++; + } + for(i=0;inb_connections;i++) { + tmpci->connections[c]=cinfo->connections[i]; // these are pointers + c++; + } + + free(connection_info->connections); + free(cinfo->connections); + + free(connection_info); + free(cinfo); + + connection_info=NULL; + cinfo=NULL; + + return tmpci; +} + +// a side effect is that both old connection info's are freed, unless NULL is returned! +freebob_supported_stream_format_info_t* +freebob_xmlparse_append_stream_format(freebob_supported_stream_format_info_t* stream_info, + freebob_supported_stream_format_info_t* cinfo) +{ + if ( !stream_info ) { + return cinfo; + } + if ( !cinfo ) { + return stream_info; + } + + if ( stream_info->direction != cinfo->direction ) { + return 0; + } + + freebob_supported_stream_format_info_t* tmpci = + calloc( 1, sizeof( freebob_supported_stream_format_info_t ) ); + if ( !tmpci ) { + return 0; + } + + tmpci->nb_formats = + stream_info->nb_formats + cinfo->nb_formats; + tmpci->formats = + calloc( tmpci->nb_formats, + sizeof( freebob_supported_stream_format_spec_t* ) ); + + int c = 0; + for( int i = 0; i < stream_info->nb_formats; i++, c++ ) { + tmpci->formats[c] = stream_info->formats[i]; + } + for ( int i = 0; i < cinfo->nb_formats; i++, c++ ) { + tmpci->formats[c] = cinfo->formats[i]; + } + + free( stream_info->formats ); + free( cinfo->formats ); + + free( stream_info ); + free( cinfo ); + + stream_info = 0; + cinfo = 0; + + return tmpci; +} + +int +freebob_xmlparse_get_nb_devices( xmlDocPtr doc, + xmlNodePtr cur) +{ + int count=0; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"Device"))) { + count++; + } + cur = cur->next; + } + return count; +} + +freebob_connection_info_t* +freebob_xmlparse_get_connection_info( xmlDocPtr doc, + int node_id, + int direction ) +{ + xmlNodePtr base = xmlDocGetRootElement(doc); + xmlNodePtr cur; + + if ( !base ) { + fprintf( stderr, "empty document\n"); + return 0; + } + + if ( xmlStrcmp( base->name, (const xmlChar*) "FreeBobConnectionInfo") ) { + fprintf( stderr, + "document of the wrong type, root node " + "!= FreeBobConnectionInfo\n" ); + return 0; + } + + base = base->xmlChildrenNode; + if ( !base ) { + fprintf( stderr, "Root node has no children!\n" ); + return 0; + } + + if( node_id > -1) { + cur = freebob_xmlparse_get_connection_set_by_node_id( doc, base, node_id ); + if ( !cur ) { + fprintf( stderr, + "Could not get description for node id %d\n", node_id ); + return 0; + } + cur = freebob_xmlparse_get_connectionset_node( doc, cur, direction ); + if ( !cur ) { + fprintf( stderr, + "Could not get a connection set for direction %d\n", + direction ); + return 0; + } + + freebob_connection_info_t* connection_info = + freebob_xmlparse_connectionset( doc, cur ); + + return connection_info; + } else { + freebob_connection_info_t* connection_info=NULL; + + int device_nr=0; + + int nb_devices=freebob_xmlparse_get_nb_devices(doc, base); + + fprintf( stderr, + "Nb devices %d\n", + nb_devices ); + + for(device_nr=0;device_nrname, (const xmlChar*) "FreeBobConnectionInfo") ) { + fprintf( stderr, + "document of the wrong type, root node " + "!= FreeBobConnectionInfo\n" ); + return 0; + } + + base = base->xmlChildrenNode; + if ( !base ) { + fprintf( stderr, "Root node has no children!\n" ); + return 0; + } + + cur = freebob_xmlparse_get_supported_stream_format_set_by_node_id( doc, base, node_id ); + if ( !cur ) { + fprintf( stderr, + "Could not get description for node id %d\n", node_id ); + return 0; + } + cur = freebob_xmlparse_get_supported_stream_format_node( doc, cur, direction ); + if ( !cur ) { + fprintf( stderr, + "Could not get a connection set for direction %d\n", + direction ); + return 0; + } + + freebob_supported_stream_format_info_t* stream_info = + freebob_xmlparse_supported_stream_format( doc, cur ); + + return stream_info; return 0; +} Index: /tags/release_0_0_6/libfreebob/src/fbtypes.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/fbtypes.h (revision 156) +++ /tags/release_0_0_6/libfreebob/src/fbtypes.h (revision 156) @@ -0,0 +1,38 @@ +/* fbtypes.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef FBTYPES_H +#define FBTYPES_H + +#include + +typedef quadlet_t fb_quadlet_t; +typedef byte_t fb_byte_t; +typedef octlet_t fb_octlet_t; +typedef nodeid_t fb_nodeid_t; +typedef nodeaddr_t fb_nodeaddr_t; + +class DeviceManager; + +struct freebob_handle { + DeviceManager* m_deviceManager; +}; + +#endif Index: /tags/release_0_0_6/libfreebob/src/configrom.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/configrom.cpp (revision 140) +++ /tags/release_0_0_6/libfreebob/src/configrom.cpp (revision 140) @@ -0,0 +1,332 @@ +/* configrom.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "configrom.h" +#include "libfreebobavc/ieee1394service.h" + +#include +#include + +#include + +using namespace std; + +IMPL_DEBUG_MODULE( ConfigRom, ConfigRom, DEBUG_LEVEL_NORMAL ); + +static int busRead( struct csr1212_csr* csr, + u_int64_t addr, + u_int16_t length, + void* buffer, + void* private_data ); + +static int getMaxRom( u_int32_t* bus_info_data, + void* private_data ); + +static struct csr1212_bus_ops configrom_csr1212_ops = { + busRead, + 0, + 0, + getMaxRom +}; + +struct config_csr_info { + Ieee1394Service* service; + fb_nodeid_t nodeId; +}; + +//------------------------------------------------------------- + +ConfigRom::ConfigRom( Ieee1394Service* ieee1394service, fb_nodeid_t nodeId ) + : m_1394Service( ieee1394service ) + , m_nodeId( nodeId ) + , m_avcDevice( false ) + , m_guid( 0 ) + , m_vendorName( "" ) + , m_modelName( "" ) + , m_vendorNameKv( 0 ) + , m_modelNameKv( 0 ) + , m_csr( 0 ) +{ +} + +ConfigRom::~ConfigRom() +{ +} + +bool +ConfigRom::initialize() +{ + struct config_csr_info csr_info; + csr_info.service = m_1394Service; + csr_info.nodeId = 0xffc0 | m_nodeId; + + m_csr = csr1212_create_csr( &configrom_csr1212_ops, + 5 * sizeof(fb_quadlet_t), // XXX Why 5 ?!? + &csr_info ); + if (!m_csr || csr1212_parse_csr( m_csr ) != CSR1212_SUCCESS) { + debugError( "Could not parse config rom" ); + if (m_csr) { + csr1212_destroy_csr(m_csr); + m_csr = 0; + } + return false; + } + + processRootDirectory(m_csr); + + if ( m_vendorNameKv ) { + int len = ( m_vendorNameKv->value.leaf.len - 2) * sizeof( quadlet_t ); + char* buf = new char[len+2]; + memcpy( buf, + ( void* )CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA( m_vendorNameKv ), + len ); + + while ((buf + len - 1) == '\0') { + len--; + } + // \todo XXX seems a bit strage to do this but the nodemgr.c code does + // it. try to figure out why this is needed (or not) + buf[len++] = ' '; + buf[len] = '\0'; + + + debugOutput( DEBUG_LEVEL_VERBOSE, "Vendor name: '%s'\n", buf ); + m_vendorName = buf; + delete[] buf; + } + if ( m_modelNameKv ) { + int len = ( m_modelNameKv->value.leaf.len - 2) * sizeof( quadlet_t ); + char* buf = new char[len+2]; + memcpy( buf, + ( void* )CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA( m_modelNameKv ), + len ); + while ((buf + len - 1) == '\0') { + len--; + } + // \todo XXX for edirol fa-66 it seems somehow broken. see above + // todo as well. + buf[len++] = ' '; + buf[len] = '\0'; + + debugOutput( DEBUG_LEVEL_VERBOSE, "Model name: '%s'\n", buf); + m_modelName = buf; + delete[] buf; + } + + m_guid = ((u_int64_t)CSR1212_BE32_TO_CPU(m_csr->bus_info_data[3]) << 32) + | CSR1212_BE32_TO_CPU(m_csr->bus_info_data[4]); + + if ( m_vendorNameKv ) { + csr1212_release_keyval( m_vendorNameKv ); + m_vendorNameKv = 0; + } + if ( m_modelNameKv ) { + csr1212_release_keyval( m_modelNameKv ); + m_modelNameKv = 0; + } + if ( m_csr ) { + csr1212_destroy_csr(m_csr); + m_csr = 0; + } + return true; +} + +const bool +ConfigRom::isAvcDevice() const +{ + return m_avcDevice; +} + + +static int +busRead( struct csr1212_csr* csr, + u_int64_t addr, + u_int16_t length, + void* buffer, + void* private_data ) +{ + struct config_csr_info* csr_info = (struct config_csr_info*) private_data; + + if ( csr_info->service->read( csr_info->nodeId, + addr, + length, + ( quadlet_t* )buffer) ) + { + cerr << "ConfigRom: Read failed" << endl; + return -1; + } + + return 0; +} + +static int +getMaxRom( u_int32_t* bus_info_data, + void* /*private_data*/) +{ + return (CSR1212_BE32_TO_CPU( bus_info_data[2] ) >> 8) & 0x3; +} + + +void +ConfigRom::processUnitDirectory( struct csr1212_csr* csr, + struct csr1212_keyval* ud_kv, + unsigned int *id ) +{ + struct csr1212_dentry *dentry; + struct csr1212_keyval *kv; + unsigned int last_key_id = 0; + unsigned int specifier_id = 0; + + debugOutput( DEBUG_LEVEL_VERBOSE, "process unit directory:\n" ); + csr1212_for_each_dir_entry(csr, kv, ud_kv, dentry) { + switch (kv->key.id) { + case CSR1212_KV_ID_VENDOR: + if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) { + debugOutput( DEBUG_LEVEL_VERBOSE, + "\tvendor_id = 0x%08x\n", + kv->value.immediate); + } + break; + + case CSR1212_KV_ID_MODEL: + debugOutput( DEBUG_LEVEL_VERBOSE, + "\tmodel_id = 0x%08x\n", + kv->value.immediate); + break; + + case CSR1212_KV_ID_SPECIFIER_ID: + debugOutput( DEBUG_LEVEL_VERBOSE, + "\tspecifier_id = 0x%08x\n", + kv->value.immediate); + specifier_id = kv->value.immediate; + break; + + case CSR1212_KV_ID_VERSION: + debugOutput( DEBUG_LEVEL_VERBOSE, + "\tversion = 0x%08x\n", + kv->value.immediate); + if ( specifier_id == 0x0000a02d ) // XXX + { + if ( kv->value.immediate == 0x10001 ) { + m_avcDevice = true; + } + } + break; + + case CSR1212_KV_ID_DESCRIPTOR: + if (kv->key.type == CSR1212_KV_TYPE_LEAF && + CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 && + CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 && + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 && + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 && + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) + { + switch (last_key_id) { + case CSR1212_KV_ID_VENDOR: + csr1212_keep_keyval(kv); + m_vendorNameKv = kv; + break; + + case CSR1212_KV_ID_MODEL: + m_modelNameKv = kv; + csr1212_keep_keyval(kv); + break; + + } + } /* else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) ... */ + break; + + case CSR1212_KV_ID_DEPENDENT_INFO: + if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) { + /* This should really be done in SBP2 as this is + * doing SBP2 specific parsing. */ + processUnitDirectory(csr, kv, id); + } + + break; + + default: + break; + } + last_key_id = kv->key.id; + } +} + +void +ConfigRom::processRootDirectory(struct csr1212_csr* csr) +{ + unsigned int ud_id = 0; + struct csr1212_dentry *dentry; + struct csr1212_keyval *kv; + unsigned int last_key_id = 0; + + csr1212_for_each_dir_entry(csr, kv, csr->root_kv, dentry) { + switch (kv->key.id) { + case CSR1212_KV_ID_VENDOR: + debugOutput( DEBUG_LEVEL_VERBOSE, + "vendor id = 0x%08x\n", kv->value.immediate); + break; + + case CSR1212_KV_ID_NODE_CAPABILITIES: + debugOutput( DEBUG_LEVEL_VERBOSE, + "capabilities = 0x%08x\n", kv->value.immediate); + break; + + case CSR1212_KV_ID_UNIT: + processUnitDirectory(csr, kv, &ud_id); + break; + + case CSR1212_KV_ID_DESCRIPTOR: + if (last_key_id == CSR1212_KV_ID_VENDOR) { + if (kv->key.type == CSR1212_KV_TYPE_LEAF && + CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 && + CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 && + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 && + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 && + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) + { + m_vendorNameKv = kv; + csr1212_keep_keyval(kv); + } + } + break; + } + last_key_id = kv->key.id; + } + +} + +const fb_octlet_t +ConfigRom::getGuid() const +{ + return m_guid; +} + +const std::string +ConfigRom::getModelName() const +{ + return m_modelName; +} + +const std::string +ConfigRom::getVendorName() const +{ + return m_vendorName; +} Index: /tags/release_0_0_6/libfreebob/src/avdevice.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/avdevice.cpp (revision 154) +++ /tags/release_0_0_6/libfreebob/src/avdevice.cpp (revision 154) @@ -0,0 +1,1670 @@ +/* avdevice.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "avdevice.h" +#include "configrom.h" +#include "avdevicesubunit.h" + +#include "libfreebobavc/avc_plug_info.h" +#include "libfreebobavc/avc_extended_plug_info.h" +#include "libfreebobavc/avc_subunit_info.h" +#include "libfreebobavc/avc_extended_stream_format.h" +#include "libfreebobavc/serialize.h" +#include "libfreebobavc/ieee1394service.h" +#include "libfreebobavc/avc_definitions.h" + +#include "debugmodule/debugmodule.h" + +#include +#include + +using namespace std; + +IMPL_DEBUG_MODULE( AvDevice, AvDevice, DEBUG_LEVEL_VERBOSE ); + +AvDevice::AvDevice( Ieee1394Service* ieee1394service, + ConfigRom* configRom, + int nodeId ) + : m_1394Service( ieee1394service ) + , m_configRom( configRom ) + , m_nodeId( nodeId ) +{ + debugOutput( DEBUG_LEVEL_VERBOSE, "Found AvDevice (NodeID %d)\n", nodeId ); +} + +AvDevice::~AvDevice() +{ + delete m_configRom; + for ( AvDeviceSubunitVector::iterator it = m_subunits.begin(); + it != m_subunits.end(); + ++it ) + { + delete *it; + } + for ( AvPlugConnectionVector::iterator it = m_plugConnections.begin(); + it != m_plugConnections.end(); + ++it ) + { + delete *it; + } + for ( AvPlugVector::iterator it = m_isoInputPlugs.begin(); + it != m_isoInputPlugs.end(); + ++it ) + { + delete *it; + } + for ( AvPlugVector::iterator it = m_isoOutputPlugs.begin(); + it != m_isoOutputPlugs.end(); + ++it ) + { + delete *it; + } +} + +bool +AvDevice::discover() +{ + if ( !enumerateSubUnits() ) { + debugError( "Could not enumarate sub units\n" ); + return false; + } + + if ( !discoverStep1() ) { + debugError( "Discover step 1 failed\n" ); + return false; + } + if ( !discoverStep2() ) { + debugError( "Discover step 2 failed\n" ); + return false; + } + if ( !discoverStep3() ) { + debugError( "Discover step 3 failed\n" ); + return false; + } + if ( !discoverStep4() ) { + debugError( "Discover step 4 failed\n" ); + return false; + } + if ( !discoverStep5() ) { + debugError( "Discover step 5 failed\n" ); + return false; + } + if ( !discoverStep6() ) { + debugError( "Discover step 6 failed\n" ); + return false; + } + if ( !discoverStep7() ) { + debugError( "Discover step 7 failed\n" ); + return false; + } + if ( !discoverStep8() ) { + debugError( "Discover step 8 failed\n" ); + return false; + } + if ( !discoverStep9() ) { + debugError( "Discover step 9 failed\n" ); + return false; + } + if ( !discoverStep10() ) { + debugError( "Discover step 10 failed\n" ); + return false; + } + + return true; +} + +bool +AvDevice::discoverStep1() +{ + ////////////////////////////////////////////// + // Step 1: Get number of available isochronous input + // and output plugs of unit + + PlugInfoCmd plugInfoCmd( m_1394Service ); + plugInfoCmd.setNodeId( m_nodeId ); + plugInfoCmd.setCommandType( AVCCommand::eCT_Status ); + + if ( !plugInfoCmd.fire() ) { + debugError( "discover: plug info command failed (step 1)\n" ); + return false; + } + + for ( int plugId = 0; plugId < plugInfoCmd.m_serialBusIsochronousInputPlugs; ++plugId ) + { + AvPlug* plug = new AvPlug; + plug->m_plugId = plugId; + plug->m_subunitType = PlugAddress::ePAM_Unit; + plug->m_direction = PlugAddress::ePD_Input; + plug->m_name = "IsoStreamInput"; + + m_isoInputPlugs.push_back( plug ); + } + + for ( int plugId = 0; plugId < plugInfoCmd.m_serialBusIsochronousOutputPlugs; ++plugId ) + { + AvPlug* plug = new AvPlug; + plug->m_plugId = plugId; + plug->m_subunitType = PlugAddress::ePAM_Unit; + plug->m_direction = PlugAddress::ePD_Output; + plug->m_name = "IsoStreamOutput"; + + m_isoOutputPlugs.push_back( plug ); + } + + debugOutput( DEBUG_LEVEL_VERBOSE, + "number of iso input plugs = %d, " + "number of iso output plugs = %d\n", + plugInfoCmd.m_serialBusIsochronousInputPlugs, + plugInfoCmd.m_serialBusIsochronousOutputPlugs ); + + return true; +} + +bool +AvDevice::discoverStep2() +{ + ////////////////////////////////////////////// + // Step 2: For each ISO input plug: get internal + // output connections (data sink) of the ISO input plug + + for ( AvPlugVector::iterator it = m_isoInputPlugs.begin(); + it != m_isoInputPlugs.end(); + ++it ) + { + AvPlug* isoInputPlug = *it; + + ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service ); + UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, + isoInputPlug->getPlugId() ); + extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input, + PlugAddress::ePAM_Unit, + unitPlugAddress ) ); + extPlugInfoCmd.setNodeId( m_nodeId ); + extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status ); + //extPlugInfoCmd.setVerbose( true ); + ExtendedPlugInfoInfoType extendedPlugInfoInfoType( + ExtendedPlugInfoInfoType::eIT_PlugOutput ); + extendedPlugInfoInfoType.initialize(); + extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType ); + + if ( !extPlugInfoCmd.fire() ) { + debugError( "discoverStep2: plug outputs command failed\n" ); + return false; + } + + ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType(); + if ( infoType + && infoType->m_plugOutput ) + { + debugOutput( DEBUG_LEVEL_VERBOSE, + "number of output plugs is %d for iso input " + "plug %d\n", + infoType->m_plugOutput->m_nrOfOutputPlugs, + isoInputPlug->getPlugId() ); + + if ( infoType->m_plugOutput->m_nrOfOutputPlugs + != infoType->m_plugOutput->m_outputPlugAddresses.size() ) + { + debugError( "number of output plugs (%d) disagree with " + "number of elements in plug address vector (%d)\n", + infoType->m_plugOutput->m_nrOfOutputPlugs, + infoType->m_plugOutput->m_outputPlugAddresses.size()); + } + for ( unsigned int i = 0; + i < infoType->m_plugOutput->m_outputPlugAddresses.size(); + ++i ) + { + PlugAddressSpecificData* plugAddress + = infoType->m_plugOutput->m_outputPlugAddresses[i]; + + + UnitPlugSpecificDataPlugAddress* pUnitPlugAddress = + dynamic_cast + ( plugAddress->m_plugAddressData ); + + if ( pUnitPlugAddress ) { + debugOutput( DEBUG_LEVEL_VERBOSE, + "unit plug address is not handled\n" ); + } + + SubunitPlugSpecificDataPlugAddress* pSubunitPlugAddress = + dynamic_cast + ( plugAddress->m_plugAddressData ); + + if ( pSubunitPlugAddress ) { + debugOutput( DEBUG_LEVEL_VERBOSE, + "output plug %d is owned by subunit_type %d, " + "subunit_id = %d\n", + pSubunitPlugAddress->m_plugId, + pSubunitPlugAddress->m_subunitType, + pSubunitPlugAddress->m_subunitId ); + + if ( !discoverPlugConnection( *isoInputPlug, + *pSubunitPlugAddress ) ) + { + debugError( "Discovering of plug connection failed\n" ); + return false; + } + } + + FunctionBlockPlugSpecificDataPlugAddress* + pFunctionBlockPlugAddress = + dynamic_cast + ( plugAddress->m_plugAddressData ); + + if ( pFunctionBlockPlugAddress ) { + debugOutput( DEBUG_LEVEL_VERBOSE, + "function block address is not handled\n" ); + } + } + } else { + debugError( "discoverStep2: no valid info type, output plug\n" ); + return false; + } + } + + return true; +} + +bool +AvDevice::discoverStep3() +{ + ////////////////////////////////////////////// + // Step 3: For each ISO output plug: get internal + // intput connections (data source) of the ISO output plug + + for ( AvPlugVector::iterator it = m_isoOutputPlugs.begin(); + it != m_isoOutputPlugs.end(); + ++it ) + { + AvPlug* isoOutputPlug = *it; + + ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service ); + UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, + isoOutputPlug->getPlugId() ); + extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Output, + PlugAddress::ePAM_Unit, + unitPlugAddress ) ); + extPlugInfoCmd.setNodeId( m_nodeId ); + extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status ); + //extPlugInfoCmd.setVerbose( true ); + ExtendedPlugInfoInfoType extendedPlugInfoInfoType( + ExtendedPlugInfoInfoType::eIT_PlugInput ); + extendedPlugInfoInfoType.initialize(); + extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType ); + + if ( !extPlugInfoCmd.fire() ) { + debugError( "discoverStep3: plug inputs command failed\n" ); + return false; + } + + ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType(); + if ( infoType + && infoType->m_plugInput ) + { + PlugAddressSpecificData* plugAddress + = infoType->m_plugInput->m_plugAddress; + + + UnitPlugSpecificDataPlugAddress* pUnitPlugAddress = + dynamic_cast + ( plugAddress->m_plugAddressData ); + + if ( pUnitPlugAddress ) { + debugOutput( DEBUG_LEVEL_VERBOSE, + "unit plug address is not handled\n" ); + } + + SubunitPlugSpecificDataPlugAddress* pSubunitPlugAddress = + dynamic_cast + ( plugAddress->m_plugAddressData ); + + if ( pSubunitPlugAddress ) { + debugOutput( DEBUG_LEVEL_VERBOSE, + "output plug %d is owned by subunit_type %d, " + "subunit_id %d\n", + pSubunitPlugAddress->m_plugId, + pSubunitPlugAddress->m_subunitType, + pSubunitPlugAddress->m_subunitId ); + + if ( !discoverPlugConnection( *isoOutputPlug, *pSubunitPlugAddress ) ) { + debugError( "Discovering of plug connection failed\n" ); + return false; + } + } + + FunctionBlockPlugSpecificDataPlugAddress* + pFunctionBlockPlugAddress = + dynamic_cast + ( plugAddress->m_plugAddressData ); + + if ( pFunctionBlockPlugAddress ) { + debugOutput( DEBUG_LEVEL_VERBOSE, + "function block address is not handled\n" ); + } + } else { + debugError( "discoverStep3: no valid info type, input plug\n" ); + return false; + } + } + + return true; +} + +bool +AvDevice::discoverStep4Plug( AvPlugVector& isoPlugs ) +{ + ////////////////////////////////////////////// + // Step 4: For all ISO plugs with valid internal connections: + // get type of data stream flowing through plug. + // Stream type of interest: iso stream & sync stream + + for ( AvPlugVector::iterator it = isoPlugs.begin(); + it != isoPlugs.end(); + ++it ) + { + AvPlug* isoPlug = *it; + + AvPlugConnection* plugConnection = getPlugConnection( *isoPlug ); + if ( !plugConnection ) { + debugOutput( DEBUG_LEVEL_VERBOSE, + "plug %d has no valid connecton -> skip\n", + isoPlug->getPlugId() ); + continue; + } + + ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service ); + UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, + isoPlug->getPlugId() ); + PlugAddress::EPlugDirection direction = + static_cast( isoPlug->getPlugDirection() ); + extPlugInfoCmd.setPlugAddress( PlugAddress( direction, + PlugAddress::ePAM_Unit, + unitPlugAddress ) ); + extPlugInfoCmd.setNodeId( m_nodeId ); + extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status ); + //extPlugInfoCmd.setVerbose( true ); + ExtendedPlugInfoInfoType extendedPlugInfoInfoType( + ExtendedPlugInfoInfoType::eIT_PlugType ); + extendedPlugInfoInfoType.initialize(); + extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType ); + + if ( !extPlugInfoCmd.fire() ) { + debugError( "discoverStep4Plug: plug type command failed\n" ); + return false; + } + + ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType(); + if ( infoType + && infoType->m_plugType ) + { + plug_type_t plugType = infoType->m_plugType->m_plugType; + + debugOutput( DEBUG_LEVEL_VERBOSE, + "plug %d is of type %d (%s)\n", + isoPlug->getPlugId(), + plugType, + extendedPlugInfoPlugTypeToString( plugType ) ); + + isoPlug->m_plugType = plugType; + } + } + + return true; +} + +bool +AvDevice::discoverStep4() +{ + bool success; + success = discoverStep4Plug( m_isoInputPlugs ); + success &= discoverStep4Plug( m_isoOutputPlugs ); + + return success; +} + +bool +AvDevice::discoverStep5Plug( AvPlugVector& isoPlugs ) +{ + ////////////////////////////////////////////// + // Step 5: For all ISO plugs with valid internal connections: + // get data block size of the stream flowing through the plug + + for ( AvPlugVector::iterator it = isoPlugs.begin(); + it != isoPlugs.end(); + ++it ) + { + AvPlug* isoPlug = *it; + + AvPlugConnection* plugConnection = getPlugConnection( *isoPlug ); + if ( !plugConnection ) { + debugOutput( DEBUG_LEVEL_VERBOSE, + "plug %d has no valid connecton -> skip\n", + isoPlug->getPlugId() ); + continue; + } + + ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service ); + UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, + isoPlug->getPlugId() ); + PlugAddress::EPlugDirection direction = + static_cast( isoPlug->getPlugDirection() ); + extPlugInfoCmd.setPlugAddress( PlugAddress( direction, + PlugAddress::ePAM_Unit, + unitPlugAddress ) ); + extPlugInfoCmd.setNodeId( m_nodeId ); + extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status ); + //extPlugInfoCmd.setVerbose( true ); + ExtendedPlugInfoInfoType extendedPlugInfoInfoType( + ExtendedPlugInfoInfoType::eIT_NoOfChannels ); + extendedPlugInfoInfoType.initialize(); + extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType ); + + if ( !extPlugInfoCmd.fire() ) { + debugError( "discoverStep5Plug: number of channels command failed\n" ); + return false; + } + + ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType(); + if ( infoType + && infoType->m_plugNrOfChns ) + { + nr_of_channels_t nrOfChannels + = infoType->m_plugNrOfChns->m_nrOfChannels; + + debugOutput( DEBUG_LEVEL_VERBOSE, + "plug %d has %d channels\n", + isoPlug->getPlugId(), + nrOfChannels ); + + isoPlug->m_nrOfChannels = nrOfChannels; + } + } + + return true; +} + + +bool +AvDevice::discoverStep5() +{ + bool success; + success = discoverStep5Plug( m_isoInputPlugs ); + success &= discoverStep5Plug( m_isoOutputPlugs ); + + return success; +} + +bool +AvDevice::discoverStep6Plug( AvPlugVector& isoPlugs ) +{ + ////////////////////////////////////////////// + // Step 6: For all ISO plugs with valid internal connections: + // get position of channels within data block + + for ( AvPlugVector::iterator it = isoPlugs.begin(); + it != isoPlugs.end(); + ++it ) + { + AvPlug* isoPlug = *it; + + AvPlugConnection* plugConnection = getPlugConnection( *isoPlug ); + if ( !plugConnection ) { + debugOutput( DEBUG_LEVEL_VERBOSE, + "plug %d has no valid connecton -> skip\n", + isoPlug->getPlugId() ); + continue; + } + + ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service ); + UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, + isoPlug->getPlugId() ); + PlugAddress::EPlugDirection direction = + static_cast( isoPlug->getPlugDirection() ); + extPlugInfoCmd.setPlugAddress( PlugAddress( direction, + PlugAddress::ePAM_Unit, + unitPlugAddress ) ); + extPlugInfoCmd.setNodeId( m_nodeId ); + extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status ); + //extPlugInfoCmd.setVerbose( true ); + ExtendedPlugInfoInfoType extendedPlugInfoInfoType( + ExtendedPlugInfoInfoType::eIT_ChannelPosition ); + extendedPlugInfoInfoType.initialize(); + extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType ); + + if ( !extPlugInfoCmd.fire() ) { + debugError( "discoverStep6Plug: channels position command failed\n" ); + return false; + } + + ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType(); + if ( infoType + && infoType->m_plugChannelPosition ) + { + if ( !isoPlug->copyClusterInfo( + *( infoType->m_plugChannelPosition ) ) ) + { + debugError( "discoverStep6Plug: Could not copy channel position " + "information\n" ); + return false; + } + + debugOutput( DEBUG_LEVEL_VERBOSE, + "plug %d: channel position information " + "retrieved\n", + isoPlug->getPlugId() ); + + isoPlug->debugOutputClusterInfos( DEBUG_LEVEL_VERBOSE ); + } + } + + return true; +} + +bool +AvDevice::discoverStep6() +{ + bool success; + success = discoverStep6Plug( m_isoInputPlugs ); + success &= discoverStep6Plug( m_isoOutputPlugs ); + + return success; +} + +bool +AvDevice::discoverStep7Plug( AvPlugVector& isoPlugs ) +{ + ////////////////////////////////////////////// + // Step 7: For all ISO plugs with valid internal connections: + // get hardware name of channel + + for ( AvPlugVector::iterator it = isoPlugs.begin(); + it != isoPlugs.end(); + ++it ) + { + AvPlug* isoPlug = *it; + + AvPlugConnection* plugConnection = getPlugConnection( *isoPlug ); + if ( !plugConnection ) { + debugOutput( DEBUG_LEVEL_VERBOSE, + "plug %d has no valid connecton -> skip\n", + isoPlug->getPlugId() ); + continue; + } + + for ( AvPlug::ClusterInfoVector::iterator clit = + isoPlug->m_clusterInfos.begin(); + clit != isoPlug->m_clusterInfos.end(); + ++clit ) + { + AvPlug::ClusterInfo* clitInfo = &*clit; + + for ( AvPlug::ChannelInfoVector::iterator pit = + clitInfo->m_channelInfos.begin(); + pit != clitInfo->m_channelInfos.end(); + ++pit ) + { + AvPlug::ChannelInfo* channelInfo = &*pit; + + ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service ); + UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, + isoPlug->getPlugId() ); + PlugAddress::EPlugDirection direction = + static_cast( isoPlug->getPlugDirection() ); + extPlugInfoCmd.setPlugAddress( PlugAddress( direction, + PlugAddress::ePAM_Unit, + unitPlugAddress ) ); + extPlugInfoCmd.setNodeId( m_nodeId ); + extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status ); + //extPlugInfoCmd.setVerbose( true ); + ExtendedPlugInfoInfoType extendedPlugInfoInfoType( + ExtendedPlugInfoInfoType::eIT_ChannelName ); + extendedPlugInfoInfoType.initialize(); + extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType ); + + ExtendedPlugInfoInfoType* infoType = + extPlugInfoCmd.getInfoType(); + if ( infoType ) { + infoType->m_plugChannelName->m_streamPosition = + channelInfo->m_streamPosition; + } + if ( !extPlugInfoCmd.fire() ) { + debugError( "discoverStep7: channel name command failed\n" ); + return false; + } + infoType = extPlugInfoCmd.getInfoType(); + if ( infoType + && infoType->m_plugChannelName ) + { + debugOutput( DEBUG_LEVEL_VERBOSE, + "plug %d stream " + "position %d: channel name = %s\n", + isoPlug->getPlugId(), + channelInfo->m_streamPosition, + infoType->m_plugChannelName->m_plugChannelName.c_str() ); + channelInfo->m_name = + infoType->m_plugChannelName->m_plugChannelName; + } + + } + } + } + + return true; +} +bool +AvDevice::discoverStep7() +{ + bool success; + success = discoverStep7Plug( m_isoInputPlugs ); + success &= discoverStep7Plug( m_isoOutputPlugs ); + + return success; +} + +bool +AvDevice::discoverStep8Plug( AvPlugVector& isoPlugs ) +{ + ////////////////////////////////////////////// + // Step 8: For all ISO plugs with valid internal connections: + // get logical input and output streams provided by the device + + for ( AvPlugVector::iterator it = isoPlugs.begin(); + it != isoPlugs.end(); + ++it ) + { + AvPlug* isoPlug = *it; + + AvPlugConnection* plugConnection = getPlugConnection( *isoPlug ); + if ( !plugConnection ) { + debugOutput( DEBUG_LEVEL_VERBOSE, + "%s plug %d has no valid connecton -> skip\n", + isoPlug->getName(), + isoPlug->getPlugId() ); + continue; + } + + if ( isoPlug->getPlugType() + == ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_Sync ) + { + // If the plug is of type sync it is either a normal 2 channel + // stream (not compound stream) or it is a compound stream + // with exactly one cluster. This depends on the + // extended stream format command version which is used. + // We are not interested in this plug so we skip it. + debugOutput( DEBUG_LEVEL_VERBOSE, + "%s plug %d is of type sync -> skip\n", + isoPlug->getName(), + isoPlug->getPlugId() ); + continue; + } + + for ( AvPlug::ClusterInfoVector::iterator clit = + isoPlug->m_clusterInfos.begin(); + clit != isoPlug->m_clusterInfos.end(); + ++clit ) + { + AvPlug::ClusterInfo* clusterInfo = &*clit; + + ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service ); + UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, + isoPlug->getPlugId() ); + PlugAddress::EPlugDirection direction = + static_cast( isoPlug->getPlugDirection() ); + extPlugInfoCmd.setPlugAddress( PlugAddress( direction, + PlugAddress::ePAM_Unit, + unitPlugAddress ) ); + extPlugInfoCmd.setNodeId( m_nodeId ); + extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status ); + //extPlugInfoCmd.setVerbose( true ); + ExtendedPlugInfoInfoType extendedPlugInfoInfoType( + ExtendedPlugInfoInfoType::eIT_ClusterInfo ); + extendedPlugInfoInfoType.initialize(); + extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType ); + + extPlugInfoCmd.getInfoType()->m_plugClusterInfo->m_clusterIndex = + clusterInfo->m_index; + + if ( !extPlugInfoCmd.fire() ) { + debugError( "discoverStep8Plug: cluster info command failed\n" ); + return false; + } + + ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType(); + if ( infoType + && infoType->m_plugClusterInfo ) + { + debugOutput( DEBUG_LEVEL_VERBOSE, + "%s plug %d: cluster index = %d, " + "portType %s, cluster name = %s\n", + isoPlug->getName(), + isoPlug->getPlugId(), + infoType->m_plugClusterInfo->m_clusterIndex, + extendedPlugInfoClusterInfoPortTypeToString( + infoType->m_plugClusterInfo->m_portType ), + infoType->m_plugClusterInfo->m_clusterName.c_str() ); + + clusterInfo->m_portType = infoType->m_plugClusterInfo->m_portType; + clusterInfo->m_name = infoType->m_plugClusterInfo->m_clusterName; + } + } + } + + return true; +} + +bool +AvDevice::discoverStep8() +{ + bool success; + success = discoverStep8Plug( m_isoInputPlugs ); + success &= discoverStep8Plug( m_isoOutputPlugs ); + + return success; +} + +bool +AvDevice::discoverStep9Plug( AvPlugVector& isoPlugs ) +{ + ////////////////////////////////////////////// + // Step 9: For all ISO plugs with valid internal connections: + // get current stream format + + for ( AvPlugVector::iterator it = isoPlugs.begin(); + it != isoPlugs.end(); + ++it ) + { + AvPlug* isoPlug = *it; + + AvPlugConnection* plugConnection = getPlugConnection( *isoPlug ); + if ( !plugConnection ) { + debugOutput( DEBUG_LEVEL_VERBOSE, + "%s plug %d has no valid connecton -> skip\n", + isoPlug->getName(), + isoPlug->getPlugId() ); + continue; + } + + ExtendedStreamFormatCmd extStreamFormatCmd( m_1394Service ); + UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, + isoPlug->getPlugId() ); + PlugAddress::EPlugDirection direction = + static_cast( isoPlug->getPlugDirection() ); + extStreamFormatCmd.setPlugAddress( PlugAddress( direction, + PlugAddress::ePAM_Unit, + unitPlugAddress ) ); + + extStreamFormatCmd.setNodeId( m_nodeId ); + extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status ); + //extStreamFormatCmd.setVerbose( true ); + + if ( !extStreamFormatCmd.fire() ) { + debugError( "discoverStep9Plug: stream format command failed\n" ); + return false; + } + + FormatInformation* formatInfo = + extStreamFormatCmd.getFormatInformation(); + FormatInformationStreamsCompound* compoundStream + = dynamic_cast< FormatInformationStreamsCompound* > ( + formatInfo->m_streams ); + if ( compoundStream ) { + isoPlug->m_samplingFrequency = + compoundStream->m_samplingFrequency; + debugOutput( DEBUG_LEVEL_VERBOSE, + "discoverStep9Plug: %s plug %d uses " + "sampling frequency %d\n", + isoPlug->getName(), + isoPlug->getPlugId(), + isoPlug->m_samplingFrequency ); + + for ( int i = 1; + i <= compoundStream->m_numberOfStreamFormatInfos; + ++i ) + { + AvPlug::ClusterInfo* clusterInfo = + isoPlug->getClusterInfoByIndex( i ); + + if ( !clusterInfo ) { + debugError( "discoverStep9Plug: No matching cluster info found " + "for index %d\n", i ); + return false; + } + StreamFormatInfo* streamFormatInfo = + compoundStream->m_streamFormatInfos[ i - 1 ]; + + int nrOfChannels = clusterInfo->m_nrOfChannels; + if ( streamFormatInfo->m_streamFormat == + FormatInformation::eFHL2_AM824_MIDI_CONFORMANT ) + { + // 8 logical midi channels fit into 1 channel + nrOfChannels = ( ( nrOfChannels + 7 ) / 8 ); + } + // sanity checks + if ( nrOfChannels != + streamFormatInfo->m_numberOfChannels ) + { + debugError( "discoverStep9Plug: Number of channels " + "mismatch: %s plug %d discovering reported " + "%d channels for cluster '%s', while stream format " + "reported %d\n", + isoPlug->getName(), + isoPlug->getPlugId(), + nrOfChannels, + clusterInfo->m_name.c_str(), + streamFormatInfo->m_numberOfChannels); + return false; + } + clusterInfo->m_streamFormat = streamFormatInfo->m_streamFormat; + + debugOutput( DEBUG_LEVEL_VERBOSE, + "%s plug %d cluster info %d ('%s'): stream format %d\n", + isoPlug->getName(), + isoPlug->getPlugId(), + i, + clusterInfo->m_name.c_str(), + clusterInfo->m_streamFormat ); + } + } + + FormatInformationStreamsSync* syncStream + = dynamic_cast< FormatInformationStreamsSync* > ( + formatInfo->m_streams ); + if ( syncStream ) { + isoPlug->m_samplingFrequency = + syncStream->m_samplingFrequency; + debugOutput( DEBUG_LEVEL_VERBOSE, + "%s plug %d is sync stream with sampling frequency %d\n", + isoPlug->getName(), + isoPlug->getPlugId(), + isoPlug->m_samplingFrequency ); + } + + if ( !compoundStream && !syncStream ) { + debugError( "discoverStep9Plug: Unsupported stream format\n" ); + return false; + } + } + + return true; +} + +bool +AvDevice::discoverStep9() +{ + bool success; + success = discoverStep9Plug( m_isoInputPlugs ); + success &= discoverStep9Plug( m_isoOutputPlugs ); + + return success; +} + +bool +AvDevice::discoverStep10Plug( AvPlugVector& isoPlugs ) +{ + for ( AvPlugVector::iterator it = isoPlugs.begin(); + it != isoPlugs.end(); + ++it ) + { + AvPlug* isoPlug = *it; + ExtendedStreamFormatCmd extStreamFormatCmd( m_1394Service, + ExtendedStreamFormatCmd::eSF_ExtendedStreamFormatInformationCommandList); + UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, + isoPlug->getPlugId() ); + PlugAddress::EPlugDirection direction = + static_cast( isoPlug->getPlugDirection() ); + extStreamFormatCmd.setPlugAddress( PlugAddress( direction, + PlugAddress::ePAM_Unit, + unitPlugAddress ) ); + + extStreamFormatCmd.setNodeId( m_nodeId ); + //extStreamFormatCmd.setVerbose( true ); + + int i = 0; + bool cmdSuccess = false; + + do { + extStreamFormatCmd.setIndexInStreamFormat( i ); + extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status ); + cmdSuccess = extStreamFormatCmd.fire(); + if ( cmdSuccess + && ( extStreamFormatCmd.getResponse() == AVCCommand::eR_Implemented ) ) + { + AvPlug::FormatInfo formatInfo; + formatInfo.m_index = i; + + FormatInformationStreamsSync* syncStream + = dynamic_cast< FormatInformationStreamsSync* > + ( extStreamFormatCmd.getFormatInformation()->m_streams ); + if ( syncStream ) { + formatInfo.m_samplingFrequency = + syncStream->m_samplingFrequency; + formatInfo.m_isSyncStream = true ; + } + + FormatInformationStreamsCompound* compoundStream + = dynamic_cast< FormatInformationStreamsCompound* > + ( extStreamFormatCmd.getFormatInformation()->m_streams ); + if ( compoundStream ) { + formatInfo.m_samplingFrequency = + compoundStream->m_samplingFrequency; + formatInfo.m_isSyncStream = false; + for ( int j = 0; + j < compoundStream->m_numberOfStreamFormatInfos; + ++j ) + { + switch ( compoundStream->m_streamFormatInfos[j]->m_streamFormat ) { + case AVC1394_STREAM_FORMAT_AM824_MULTI_BIT_LINEAR_AUDIO_RAW: + formatInfo.m_audioChannels += + compoundStream->m_streamFormatInfos[j]->m_numberOfChannels; + break; + case AVC1394_STREAM_FORMAT_AM824_MIDI_CONFORMANT: + formatInfo.m_midiChannels += + compoundStream->m_streamFormatInfos[j]->m_numberOfChannels; + break; + default: + debugWarning( "discoverStep10Plug: unknown stream " + "format for channel (%d)\n", j ); + } + } + } + + debugOutput( DEBUG_LEVEL_VERBOSE, + "[%s:%d] formatInfo[%d].m_samplingFrequency = %d\n", + isoPlug->getName(), isoPlug->getPlugId(), + i, formatInfo.m_samplingFrequency ); + debugOutput( DEBUG_LEVEL_VERBOSE, + "[%s:%d] formatInfo[%d].m_isSyncStream = %d\n", + isoPlug->getName(), isoPlug->getPlugId(), + i, formatInfo.m_isSyncStream ); + debugOutput( DEBUG_LEVEL_VERBOSE, + "[%s:%d] formatInfo[%d].m_audioChannels = %d\n", + isoPlug->getName(), isoPlug->getPlugId(), + i, formatInfo.m_audioChannels ); + debugOutput( DEBUG_LEVEL_VERBOSE, + "[%s:%d] formatInfo[%d].m_midiChannels = %d\n", + isoPlug->getName(), isoPlug->getPlugId(), + i, formatInfo.m_midiChannels ); + + isoPlug->m_formatInfos.push_back( formatInfo ); + } + + ++i; + } while ( cmdSuccess && ( extStreamFormatCmd.getResponse() + == ExtendedStreamFormatCmd::eR_Implemented ) ); + } + + return true; +} + + +bool +AvDevice::discoverStep10() +{ + ////////////////////////////////////////////// + // Step 10: For all ISO plugs: get all stream + // supported formats + + bool success; + + success = discoverStep10Plug( m_isoInputPlugs ); + success &= discoverStep10Plug( m_isoOutputPlugs ); + + return success; +} + +bool +AvDevice::discoverPlugConnection( AvPlug& srcPlug, + SubunitPlugSpecificDataPlugAddress& subunitPlugAddress ) +{ + AvDeviceSubunit* subunit = getSubunit( subunitPlugAddress.m_subunitType, + subunitPlugAddress.m_subunitId ); + + if ( subunit ) { + debugOutput( DEBUG_LEVEL_VERBOSE, + "%s plug %d has a valid connection to plug %d of " + "%s subunit %d \n", + srcPlug.getName(), + srcPlug.getPlugId(), + subunitPlugAddress.m_plugId, + subunit->getName(), + subunit->getSubunitId() ); + + AvPlug* destPlug = new AvPlug; + destPlug->m_plugId = subunitPlugAddress.m_plugId; + destPlug->m_subunitType = subunitPlugAddress.m_subunitType; + destPlug->m_subunitId = subunitPlugAddress.m_subunitId; + + if ( !subunit->addPlug( *destPlug ) ) { + debugError( "Could not add plug %d to subunit %d\n", + destPlug->getPlugId(), subunit->getSubunitId() ); + return false; + } + + AvPlugConnection* plugConnection = new AvPlugConnection; + plugConnection->m_srcPlug = &srcPlug; + plugConnection->m_destPlug = destPlug; + m_plugConnections.push_back( plugConnection ); + + return true; + } else { + debugOutput( DEBUG_LEVEL_VERBOSE, + "found plug address points to unhandled " + "subunit -> ignored\n" ); + } + + return true; +} + +bool +AvDevice::enumerateSubUnits() +{ + SubUnitInfoCmd subUnitInfoCmd( m_1394Service ); + //subUnitInfoCmd.setVerbose( 1 ); + subUnitInfoCmd.setCommandType( AVCCommand::eCT_Status ); + + // BeBob has always exactly one audio and one music subunit. This + // means is fits into the first page of the SubUnitInfo command. + // So there is no need to do more than needed + + subUnitInfoCmd.m_page = 0; + subUnitInfoCmd.setNodeId( m_nodeId ); + if ( !subUnitInfoCmd.fire() ) { + debugError( "Subunit info command failed\n" ); + } + + for ( int i = 0; i < subUnitInfoCmd.getNrOfValidEntries(); ++i ) { + subunit_type_t subunit_type + = subUnitInfoCmd.m_table[i].m_subunit_type; + + unsigned int subunitId = getNrOfSubunits( subunit_type ); + + debugOutput( DEBUG_LEVEL_VERBOSE, + "subunit_id = %2d, subunit_type = %2d (%s)\n", + subunitId, + subunit_type, + subunitTypeToString( subunit_type ) ); + + AvDeviceSubunit* subunit = 0; + switch( subunit_type ) { + case AVCCommand::eST_Audio: + subunit = new AvDeviceSubunitAudio( this, subunitId ); + if ( !subunit ) { + debugFatal( "Could not allocate AvDeviceSubunitAudio\n" ); + return false; + } + break; + case AVCCommand::eST_Music: + subunit = new AvDeviceSubunitMusic( this, subunitId ); + if ( !subunit ) { + debugFatal( "Could not allocate AvDeviceSubunitMusic\n" ); + return false; + } + break; + default: + debugOutput( DEBUG_LEVEL_NORMAL, + "Unsupported subunit found, subunit_type = %d (%s)\n", + subunit_type, + subunitTypeToString( subunit_type ) ); + + } + + m_subunits.push_back( subunit ); + } + + return true; +} + + +AvDeviceSubunit* +AvDevice::getSubunit( subunit_type_t subunitType, + subunit_id_t subunitId ) const +{ + for ( AvDeviceSubunitVector::const_iterator it = m_subunits.begin(); + it != m_subunits.end(); + ++it ) + { + AvDeviceSubunit* subunit = *it; + if ( ( subunitType == subunit->getSubunitType() ) + && ( subunitId == subunit->getSubunitId() ) ) + { + return subunit; + } + } + + return 0; +} + + +unsigned int +AvDevice::getNrOfSubunits( subunit_type_t subunitType ) const +{ + unsigned int nrOfSubunits = 0; + + for ( AvDeviceSubunitVector::const_iterator it = m_subunits.begin(); + it != m_subunits.end(); + ++it ) + { + AvDeviceSubunit* subunit = *it; + if ( subunitType == subunit->getSubunitType() ) { + nrOfSubunits++; + } + } + + return nrOfSubunits; +} + +AvPlugConnection* +AvDevice::getPlugConnection( AvPlug& srcPlug ) const +{ + for ( AvPlugConnectionVector::const_iterator it + = m_plugConnections.begin(); + it != m_plugConnections.end(); + ++it ) + { + AvPlugConnection* plugConnection = *it; + if ( plugConnection->m_srcPlug == &srcPlug ) { + return plugConnection; + } + } + + return 0; +} + +AvPlug* +AvDevice::getPlugById( AvPlugVector& plugs, int id ) +{ + for ( AvPlugVector::iterator it = plugs.begin(); + it != plugs.end(); + ++it ) + { + AvPlug* plug = *it; + if ( id == plug->getPlugId() ) { + return plug; + } + } + + return 0; +} + +std::string +AvDevice::getVendorName() +{ + return m_configRom->getVendorName(); +} + +std::string +AvDevice::getModelName() +{ + return m_configRom->getModelName(); +} + +uint64_t +AvDevice::getGuid() +{ + return m_configRom->getGuid(); +} + +bool +AvDevice::addXmlDescriptionPlug( AvPlug& plug, + xmlNodePtr connectionSet ) +{ + char* result; + + int direction; + switch ( plug.getPlugDirection() ) { + case 0: + direction = FREEBOB_PLAYBACK; + break; + case 1: + direction = FREEBOB_CAPTURE; + break; + default: + debugError( "plug direction invalid (%d)\n", + plug.getPlugDirection() ); + return false; + } + + asprintf( &result, "%d", direction ); + if ( !xmlNewChild( connectionSet, + 0, + BAD_CAST "Direction", + BAD_CAST result ) ) + { + debugError( "Couldn't create 'Direction' node\n" ); + return false; + } + + xmlNodePtr connection = xmlNewChild( connectionSet, 0, + BAD_CAST "Connection", 0 ); + if ( !connection ) { + debugError( "Couldn't create 'Connection' node for " + "direction %d\n", plug.getPlugDirection() ); + return false; + } + + asprintf( &result, "%08x%08x", + ( quadlet_t )( m_configRom->getGuid() >> 32 ), + ( quadlet_t )( m_configRom->getGuid() & 0xfffffff ) ); + if ( !xmlNewChild( connection, 0, + BAD_CAST "GUID", BAD_CAST result ) ) { + debugError( "Couldn't create 'GUID' node\n" ); + return false; + } + + asprintf( &result, "%d", m_1394Service->getPort() ); + if ( !xmlNewChild( connection, 0, + BAD_CAST "Port", BAD_CAST result ) ) { + debugError( "Couldn't create 'Port' node\n" ); + return false; + } + + asprintf( &result, "%d", m_nodeId); + if ( !xmlNewChild( connection, 0, + BAD_CAST "Node", BAD_CAST result ) ) { + debugError( "Couldn't create 'Node' node\n" ); + return false; + } + + asprintf( &result, "%d", plug.getNrOfChannels() ); + if ( !xmlNewChild( connection, 0, + BAD_CAST "Dimension", BAD_CAST result ) ) { + debugError( "Couldn't create 'Dimension' node\n" ); + return false; + } + + asprintf( &result, "%d", plug.getSampleRate() ); + if ( !xmlNewChild( connection, 0, + BAD_CAST "Samplerate", BAD_CAST result ) ) { + debugError( "Couldn't create 'Samplerate' node\n" ); + return false; + } + + if ( !xmlNewChild( connection, 0, + BAD_CAST "IsoChannel", BAD_CAST "-1" ) ) + { + debugError( "Couldn't create 'IsoChannel' node\n" ); + return false; + } + + xmlNodePtr streams = xmlNewChild( connection, 0, + BAD_CAST "Streams", 0 ); + if ( !streams ) { + debugError( "Couldn't create 'Streams' node for " + "direction %d\n", plug.getPlugDirection() ); + return false; + } + + AvPlug::ClusterInfoVector& clusterInfos = plug.getClusterInfos(); + for ( AvPlug::ClusterInfoVector::const_iterator it = clusterInfos.begin(); + it != clusterInfos.end(); + ++it ) + { + const AvPlug::ClusterInfo* clusterInfo = &( *it ); + + AvPlug::ChannelInfoVector channelInfos = clusterInfo->m_channelInfos; + for ( AvPlug::ChannelInfoVector::const_iterator it = channelInfos.begin(); + it != channelInfos.end(); + ++it ) + { + const AvPlug::ChannelInfo* channelInfo = &( *it ); + + xmlNodePtr stream = xmlNewChild( streams, 0, + BAD_CAST "Stream", 0 ); + if ( !stream ) { + debugError( "Coulnd't create 'Stream' node" ); + return false; + } + + // \todo: iec61883 backend expects indexing starting from 0 + // but bebob reports it starting from 1. Decide where + // and how to handle this + asprintf( &result, "%d", channelInfo->m_streamPosition - 1 ); + if ( !xmlNewChild( stream, 0, + BAD_CAST "Position", BAD_CAST result ) ) + { + debugError( "Couldn't create 'Position' node" ); + return false; + } + + asprintf( &result, "%d", channelInfo->m_location ); + if ( !xmlNewChild( stream, 0, + BAD_CAST "Location", BAD_CAST result ) ) + { + debugError( "Couldn't create 'Location' node" ); + return false; + } + + asprintf( &result, "%d", clusterInfo->m_streamFormat ); + if ( !xmlNewChild( stream, 0, + BAD_CAST "Format", BAD_CAST result ) ) + { + debugError( "Couldn't create 'Format' node" ); + return false; + } + + asprintf( &result, "%d", clusterInfo->m_portType ); + if ( !xmlNewChild( stream, 0, + BAD_CAST "Type", BAD_CAST result ) ) + { + debugError( "Couldn't create 'Type' node" ); + return false; + } + + // \todo XXX: What do to do with DestinationPort value?? + asprintf( &result, "%d", 0 ); + if ( !xmlNewChild( stream, 0, + BAD_CAST "DestinationPort", BAD_CAST result ) ) + { + debugError( "Couldn't create 'DestinationPort' node" ); + return false; + } + + if ( !xmlNewChild( stream, 0, + BAD_CAST "Name", + BAD_CAST channelInfo->m_name.c_str() ) ) + { + debugError( "Couldn't create 'Name' node" ); + return false; + } + } + } + + return true; +} + +bool +AvDevice::addXmlDescriptionStreamFormats( AvPlug& plug, + xmlNodePtr streamFormatNode ) +{ + int direction; + switch ( plug.getPlugDirection() ) { + case 0: + direction = FREEBOB_PLAYBACK; + break; + case 1: + direction = FREEBOB_CAPTURE; + break; + default: + debugError( "addXmlDescriptionStreamFormats: plug direction invalid (%d)\n", + plug.getPlugDirection() ); + return false; + } + + char* result; + asprintf( &result, "%d", direction ); + if ( !xmlNewChild( streamFormatNode, + 0, + BAD_CAST "Direction", + BAD_CAST result ) ) + { + debugError( "addXmlDescriptionStreamFormats: Could not create 'Direction' node\n" ); + return false; + } + + for ( AvPlug::FormatInfoVector::iterator it = + plug.m_formatInfos.begin(); + it != plug.m_formatInfos.end(); + ++it ) + { + AvPlug::FormatInfo formatInfo = *it; + xmlNodePtr formatNode = xmlNewChild( streamFormatNode, 0, + BAD_CAST "Format", 0 ); + if ( !formatNode ) { + debugError( "addXmlDescriptionStreamFormats: Could not create 'Format' node\n" ); + return false; + } + + asprintf( &result, "%d", + convertESamplingFrequency( static_cast( formatInfo.m_samplingFrequency ) ) ); + if ( !xmlNewChild( formatNode, 0, + BAD_CAST "Samplerate", BAD_CAST result ) ) + { + debugError( "Couldn't create 'Samplerate' node\n" ); + return false; + } + + asprintf( &result, "%d", formatInfo.m_audioChannels ); + if ( !xmlNewChild( formatNode, 0, + BAD_CAST "AudioChannels", BAD_CAST result ) ) + { + debugError( "Couldn't create 'AudioChannels' node\n" ); + return false; + } + + asprintf( &result, "%d", formatInfo.m_midiChannels ); + if ( !xmlNewChild( formatNode, 0, + BAD_CAST "MidiChannels", BAD_CAST result ) ) + { + debugError( "Couldn't create 'MidiChannels' node\n" ); + return false; + } + } + + return true; +} + +bool +AvDevice::addXmlDescription( xmlNodePtr deviceNode ) +{ + // connection set + // direction + // connection + // id + // port + // node + // plug + // dimension + // samplerate + // streams + // stream + + + /////////// + // get plugs + + AvPlug* inputPlug = getPlugById( m_isoInputPlugs, 0 ); + if ( !inputPlug ) { + debugError( "addXmlDescription: No iso input plug found with id %d\n" ); + return false; + } + AvPlug* outputPlug = getPlugById( m_isoOutputPlugs, 0 ); + if ( !outputPlug ) { + debugError( "addXmlDescription: No iso output plug found with id %d\n" ); + return false; + } + + /////////// + // add connection set output + + xmlNodePtr connectionSet = xmlNewChild( deviceNode, 0, + BAD_CAST "ConnectionSet", 0 ); + if ( !connectionSet ) { + debugError( "addXmlDescription:: Could not create 'ConnnectionSet' node for " + "direction 1 (playback)\n" ); + return false; + } + + if ( !addXmlDescriptionPlug( *inputPlug, connectionSet ) ) { + debugError( "addXmlDescription: Could not add iso input plug 0 to XML description\n" ); + return false; + } + + // add connection set input + + connectionSet = xmlNewChild( deviceNode, 0, + BAD_CAST "ConnectionSet", 0 ); + if ( !connectionSet ) { + debugError( "addXmlDescription: Couldn't create 'ConnectionSet' node for " + "direction 0 (recorder)\n" ); + return false; + } + + if ( !addXmlDescriptionPlug( *outputPlug, connectionSet ) ) { + debugError( "addXmlDescription: Could not add iso output plug 0 to XML description\n" ); + return false; + } + + //////////// + // add stream format + + xmlNodePtr streamFormatNode = xmlNewChild( deviceNode, 0, + BAD_CAST "StreamFormats", 0 ); + if ( !streamFormatNode ) { + debugError( "addXmlDescription: Could not create 'StreamFormats' node\n" ); + return false; + } + + if ( !addXmlDescriptionStreamFormats( *inputPlug, streamFormatNode ) ) { + debugError( "addXmlDescription:: Could not add stream format info\n" ); + return false; + } + + streamFormatNode= xmlNewChild( deviceNode, 0, + BAD_CAST "StreamFormats", 0 ); + if ( !streamFormatNode ) { + debugError( "addXmlDescription: Could not create 'StreamFormat' node\n" ); + return false; + } + + if ( !addXmlDescriptionStreamFormats( *outputPlug, streamFormatNode ) ) { + debugError( "addXmlDescription:: Could not add stream format info\n" ); + return false; + } + + return true; +} + +bool +AvDevice::setSamplingFrequencyPlug( AvPlug& plug, + PlugAddress::EPlugDirection direction, + ESamplingFrequency samplingFrequency ) +{ + ExtendedStreamFormatCmd extStreamFormatCmd( m_1394Service, + ExtendedStreamFormatCmd::eSF_ExtendedStreamFormatInformationCommandList ); + UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, + plug.getPlugId() ); + extStreamFormatCmd.setPlugAddress( PlugAddress( direction, + PlugAddress::ePAM_Unit, + unitPlugAddress ) ); + + extStreamFormatCmd.setNodeId( m_nodeId ); + extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status ); + //extStreamFormatCmd.setVerbose( true ); + + int i = 0; + bool cmdSuccess = false; + bool correctFormatFound = false; + + do { + extStreamFormatCmd.setIndexInStreamFormat( i ); + extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status ); + + cmdSuccess = extStreamFormatCmd.fire(); + if ( cmdSuccess + && ( extStreamFormatCmd.getResponse() == AVCCommand::eR_Implemented ) ) + { + ESamplingFrequency foundFreq = eSF_DontCare; + + FormatInformation* formatInfo = + extStreamFormatCmd.getFormatInformation(); + FormatInformationStreamsCompound* compoundStream + = dynamic_cast< FormatInformationStreamsCompound* > ( + formatInfo->m_streams ); + if ( compoundStream ) { + foundFreq = static_cast( compoundStream->m_samplingFrequency ); + } + + FormatInformationStreamsSync* syncStream + = dynamic_cast< FormatInformationStreamsSync* > ( + formatInfo->m_streams ); + if ( syncStream ) { + foundFreq = static_cast( compoundStream->m_samplingFrequency ); + } + + if ( foundFreq == samplingFrequency ) + { + correctFormatFound = true; + break; + } + } + + ++i; + } while ( cmdSuccess && ( extStreamFormatCmd.getResponse() + == ExtendedStreamFormatCmd::eR_Implemented ) ); + + if ( !cmdSuccess ) { + debugError( "setSampleRatePlug: Failed to retrieve format info\n" ); + return false; + } + + if ( !correctFormatFound ) { + debugError( "setSampleRatePlug: %s plug %d does not support sample rate %d\n", + plug.getName(), + plug.getPlugId(), + convertESamplingFrequency( samplingFrequency ) ); + return false; + } + + extStreamFormatCmd.setSubFunction( + ExtendedStreamFormatCmd::eSF_ExtendedStreamFormatInformationCommand ); + extStreamFormatCmd.setCommandType( AVCCommand::eCT_Control ); + + if ( !extStreamFormatCmd.fire() ) { + debugError( "setSampleRate: Could not set sample rate %d " + "to %s plug %d\n", + convertESamplingFrequency( samplingFrequency ), + plug.getName(), + plug.getPlugId() ); + return false; + } + + return true; +} + +bool +AvDevice::setSamplingFrequency( ESamplingFrequency samplingFrequency ) +{ + AvPlug* plug = getPlugById( m_isoInputPlugs, 0 ); + if ( !plug ) { + debugError( "setSampleRate: Could not retrieve iso input plug 0\n" ); + return false; + } + + if ( !setSamplingFrequencyPlug( *plug, PlugAddress::ePD_Input, samplingFrequency ) ) { + debugError( "setSampleRate: Setting sample rate failed\n" ); + return false; + } + + plug = getPlugById( m_isoOutputPlugs, 0 ); + if ( !plug ) { + debugError( "setSampleRate: Could not retrieve iso output plug 0\n" ); + return false; + } + + if ( !setSamplingFrequencyPlug( *plug, PlugAddress::ePD_Output, samplingFrequency ) ) { + debugError( "setSampleRate: Setting sample rate failed\n" ); + return false; + } + + debugOutput( DEBUG_LEVEL_VERBOSE, + "setSampleRate: Set sample rate to %d\n", convertESamplingFrequency( samplingFrequency ) ); + return true; +} Index: /tags/release_0_0_6/libfreebob/src/configrom.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/configrom.h (revision 156) +++ /tags/release_0_0_6/libfreebob/src/configrom.h (revision 156) @@ -0,0 +1,70 @@ +/* configrom.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef CONFIGROM_H +#define CONFIGROM_H + +#include "fbtypes.h" +#include "csr1212.h" + +#include "debugmodule/debugmodule.h" + +#include + +class Ieee1394Service; + +class ConfigRom { + public: + ConfigRom( Ieee1394Service* ieee1394service, fb_nodeid_t nodeId ); + virtual ~ConfigRom(); + + bool initialize(); + + const bool isAvcDevice() const; + const fb_octlet_t getGuid() const; + const std::string getModelName() const; + const std::string getVendorName() const; + + protected: + void processUnitDirectory( struct csr1212_csr* csr, + struct csr1212_keyval* ud_kv, + unsigned int* id ); + + void processRootDirectory( struct csr1212_csr* csr ); + + Ieee1394Service* m_1394Service; + fb_nodeid_t m_nodeId; + bool m_avcDevice; + fb_octlet_t m_guid; + std::string m_vendorName; + std::string m_modelName; + + /* only used during parsing */ + struct csr1212_keyval* m_vendorNameKv; + struct csr1212_keyval* m_modelNameKv; + struct csr1212_csr* m_csr; + +private: + ConfigRom( const ConfigRom& ); + + DECLARE_DEBUG_MODULE; +}; + +#endif /* CONFIGROM_H */ Index: /tags/release_0_0_6/libfreebob/src/Makefile.am =================================================================== --- /tags/release_0_0_6/libfreebob/src/Makefile.am (revision 155) +++ /tags/release_0_0_6/libfreebob/src/Makefile.am (revision 155) @@ -0,0 +1,47 @@ +# Makefile.am - Makefile template +# Copyright (C) 2005 by Daniel Wagner. +# +# This file is part of FreeBob. +# +# FreeBob 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. +# FreeBob 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 FreeBob; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +SUBDIRS = debugmodule libfreebobavc + +INCLUDES = $(LIBSIGC_CFLAGS) $(LIBRAW1394_CFLAGS) $(LIBIEC61883_CFLAGS) \ + $(LIBAVC1394_CFLAGS) $(LIBLO_CFLAGS) $(LIBXML_CFLAGS) \ + -I$(top_srcdir) -I$(top_srcdir)/src + +lib_LTLIBRARIES = libfreebob.la + +libfreebob_la_SOURCES = \ + freebob.cpp \ + xmlparser.c \ + devicemanager.h \ + devicemanager.cpp \ + avdevice.h \ + avdevice.cpp \ + avdevicesubunit.h \ + avdevicesubunit.cpp \ + avplug.h \ + avplug.cpp \ + configrom.h \ + configrom.cpp \ + csr1212.h \ + csr1212.c \ + fbtypes.h + +libfreebob_la_LDFLAGS = -version-info $(LT_VERSION) -lpthread $(LIBSIGC_LIBS) \ + $(LIBRAW1394_LIBS) $(LIBIEC61883_LIBS) $(LIBAVC1394_LIBS) \ + $(LIBLO_LIBS) $(LIBXML_LIBS) debugmodule/libdebugmodule.la \ + libfreebobavc/libfreebobavc.la -safe-temps + Index: /tags/release_0_0_6/libfreebob/src/devicemanager.cpp =================================================================== --- /tags/release_0_0_6/libfreebob/src/devicemanager.cpp (revision 151) +++ /tags/release_0_0_6/libfreebob/src/devicemanager.cpp (revision 151) @@ -0,0 +1,290 @@ +/* devicemanager.cpp + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#include "fbtypes.h" + +#include "devicemanager.h" +#include "avdevice.h" +#include "configrom.h" + +#include "libfreebobavc/ieee1394service.h" +#include "debugmodule/debugmodule.h" + +#include + +using namespace std; + +IMPL_DEBUG_MODULE( DeviceManager, DeviceManager, DEBUG_LEVEL_VERBOSE ); + +DeviceManager::DeviceManager() + : m_1394Service( 0 ) +{ +} + +DeviceManager::~DeviceManager() +{ + for ( AvDeviceVectorIterator it = m_avDevices.begin(); + it != m_avDevices.end(); + ++it ) + { + delete *it; + } + + delete m_1394Service; +} + +bool +DeviceManager::initialize(int port) +{ + m_1394Service = new Ieee1394Service(); + if ( !m_1394Service ) { + debugFatal( "Could not create Ieee1349Service object\n" ); + return false; + } + + if ( !m_1394Service->initialize( port ) ) { + debugFatal( "Could not initialize Ieee1349Service object\n" ); + delete m_1394Service; + m_1394Service = 0; + return false; + } + + return true; +} + +bool +DeviceManager::discover() +{ + for ( AvDeviceVectorIterator it = m_avDevices.begin(); + it != m_avDevices.end(); + ++it ) + { + delete *it; + } + m_avDevices.clear(); + + for ( fb_nodeid_t nodeId = 0; + nodeId < m_1394Service->getNodeCount(); + ++nodeId ) + { + ConfigRom* configRom = new ConfigRom( m_1394Service, nodeId ); + if ( !configRom->initialize() ) { + // \todo If a PHY on the bus in power safe mode than + // the config rom is missing. So this might be just + // such a case and we can safely skip it. But it might + // be there is a real software problem on our side. + // This should be handled more carefuly. + debugOutput( DEBUG_LEVEL_NORMAL, + "Could not read config rom from device (noe id %d). " + "Skip device discovering for this node\n", + nodeId ); + delete configRom; + continue; + } + + if ( !configRom->isAvcDevice() ) { + delete configRom; + continue; + } + + AvDevice* avDevice = new AvDevice( m_1394Service, configRom, nodeId ); + if ( !avDevice ) { + debugError( "discover: Could not allocate AvDevice\n" ); + delete configRom; + return false; + } + + if ( !avDevice->discover() ) { + debugError( "discover: Could not discover device (node id %d)\n", + nodeId ); + delete avDevice; + return false; + } + + m_avDevices.push_back( avDevice ); + } + + return true; +} + +bool +DeviceManager::isValidNode(int node) +{ + for ( AvDeviceVectorIterator it = m_avDevices.begin(); + it != m_avDevices.end(); + ++it ) + { + AvDevice* avDevice = *it; + + if (avDevice->getNodeId() == node) { + return true; + } + } + return false; +} + +int +DeviceManager::getNbDevices() +{ + return m_avDevices.size(); +} + +int +DeviceManager::getDeviceNodeId( int deviceNr ) +{ + if ( ! ( deviceNr < getNbDevices() ) ) { + debugError( "Device number out of range (%d)\n", deviceNr ); + return -1; + } + + AvDevice* avDevice = m_avDevices.at( deviceNr ); + + if ( !avDevice ) { + debugError( "Could not get device at position (%d)\n", deviceNr ); + } + + return avDevice->getNodeId(); +} + +AvDevice* +DeviceManager::getAvDevice( int nodeId ) +{ + for ( AvDeviceVectorIterator it = m_avDevices.begin(); + it != m_avDevices.end(); + ++it ) + { + AvDevice* avDevice = *it; + if ( avDevice->getNodeId() == nodeId ) { + return avDevice; + } + } + + return 0; +} + +xmlDocPtr +DeviceManager::getXmlDescription() +{ + xmlDocPtr doc = xmlNewDoc( BAD_CAST "1.0" ); + if ( !doc ) { + debugError( "Couldn't create new xml doc\n" ); + return 0; + } + + xmlNodePtr rootNode = xmlNewNode( 0, BAD_CAST "FreeBobConnectionInfo" ); + if ( !rootNode ) { + debugError( "Couldn't create root node\n" ); + xmlFreeDoc( doc ); + xmlCleanupParser(); + return 0; + } + xmlDocSetRootElement( doc, rootNode ); + + for ( AvDeviceVectorIterator it = m_avDevices.begin(); + it != m_avDevices.end(); + ++it ) + { + AvDevice* avDevice = *it; + + xmlNodePtr deviceNode = xmlNewChild( rootNode, 0, + BAD_CAST "Device", 0 ); + if ( !deviceNode ) { + debugError( "Couldn't create device node\n" ); + xmlFreeDoc( doc ); + xmlCleanupParser(); + return 0; + } + + char* result; + asprintf( &result, "%d", avDevice->getNodeId() ); + if ( !xmlNewChild( deviceNode, 0, + BAD_CAST "NodeId", BAD_CAST result ) ) + { + debugError( "Couldn't create 'NodeId' node" ); + return false; + } + + std::string res = "Connection Information for " + + avDevice->getVendorName() + +", " + + avDevice->getModelName() + + " configuration"; + if ( !xmlNewChild( deviceNode, + 0, + BAD_CAST "Comment", + BAD_CAST res.c_str() ) ) { + debugError( "Couldn't create comment node\n" ); + xmlFreeDoc( doc ); + xmlCleanupParser(); + return 0; + } + + res = avDevice->getVendorName(); + + if ( !xmlNewChild( deviceNode, + 0, + BAD_CAST "Vendor", + BAD_CAST res.c_str() ) ) { + debugError( "Couldn't create vendor node\n" ); + xmlFreeDoc( doc ); + xmlCleanupParser(); + return 0; + } + + res = avDevice->getModelName(); + + if ( !xmlNewChild( deviceNode, + 0, + BAD_CAST "Model", + BAD_CAST res.c_str() ) ) { + debugError( "Couldn't create model node\n" ); + xmlFreeDoc( doc ); + xmlCleanupParser(); + return 0; + } + + asprintf( &result, "%08x%08x", + ( quadlet_t )( avDevice->getGuid() >> 32 ), + ( quadlet_t )( avDevice->getGuid() & 0xfffffff ) ); + if ( !xmlNewChild( deviceNode, 0, + BAD_CAST "GUID", BAD_CAST result ) ) { + debugError( "Couldn't create 'GUID' node\n" ); + xmlFreeDoc( doc ); + xmlCleanupParser(); + return false; + } + + if ( !avDevice->addXmlDescription( deviceNode ) ) { + debugError( "Adding XML description failed\n" ); + xmlFreeDoc( doc ); + xmlCleanupParser(); + return 0; + } + } + + return doc; +} + +bool +DeviceManager::deinitialize() +{ + return true; +} + Index: /tags/release_0_0_6/libfreebob/src/avdevice.h =================================================================== --- /tags/release_0_0_6/libfreebob/src/avdevice.h (revision 152) +++ /tags/release_0_0_6/libfreebob/src/avdevice.h (revision 152) @@ -0,0 +1,116 @@ +/* avdevice.h + * Copyright (C) 2005 by Daniel Wagner + * + * This file is part of FreeBob. + * + * FreeBob 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. + * FreeBob 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 FreeBob; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA. + */ + +#ifndef AVDEVICE_H +#define AVDEVICE_H + +#include "debugmodule/debugmodule.h" +#include "libfreebobavc/avc_definitions.h" +#include "libfreebobavc/avc_extended_cmd_generic.h" +#include "libfreebob/xmlparser.h" + +#include "avplug.h" +#include "avdevicesubunit.h" + +class ConfigRom; +class Ieee1394Service; +class SubunitPlugSpecificDataPlugAddress; + +class AvDevice { +public: + friend class AvDeviceSubunitAudio; + friend class AvDeviceSubunitMusic; + + // takes ownership of config rom + AvDevice( Ieee1394Service* ieee1394service, + ConfigRom* configRom, + int nodeId ); + virtual ~AvDevice(); + + bool discover(); + + std::string getVendorName(); + std::string getModelName(); + + uint64_t getGuid(); + + bool addXmlDescription( xmlNodePtr deviceNode ); + int getNodeId() + { return m_nodeId; } + + bool setSamplingFrequency( ESamplingFrequency samplingFrequency ); + +protected: + bool discoverStep1(); + bool discoverStep2(); + bool discoverStep3(); + bool discoverStep4(); + bool discoverStep4Plug( AvPlugVector& isoPlugs ); + bool discoverStep5(); + bool discoverStep5Plug( AvPlugVector& isoPlugs ); + bool discoverStep6(); + bool discoverStep6Plug( AvPlugVector& isoPlugs ); + bool discoverStep7(); + bool discoverStep7Plug( AvPlugVector& isoPlugs ); + bool discoverStep8(); + bool discoverStep8Plug( AvPlugVector& isoPlugs ); + bool discoverStep9(); + bool discoverStep9Plug( AvPlugVector& isoPlugs ); + bool discoverStep10(); + bool discoverStep10Plug( AvPlugVector& isoPlugs ); + + bool discoverPlugConnection( AvPlug& srcPlug, + SubunitPlugSpecificDataPlugAddress& subunitPlugAddress ); + + bool enumerateSubUnits(); + + AvDeviceSubunit* getSubunit( subunit_type_t subunitType, + subunit_id_t subunitId ) const; + + unsigned int getNrOfSubunits( subunit_type_t subunitType ) const; + AvPlugConnection* getPlugConnection( AvPlug& srcPlug ) const; + + + AvPlug* getPlugById( AvPlugVector& plugs, int id ); + bool addXmlDescriptionPlug( AvPlug& plug, xmlNodePtr conectionSet ); + bool addXmlDescriptionStreamFormats( AvPlug& plug, xmlNodePtr streamFormats ); + + bool setSamplingFrequencyPlug( AvPlug& plug, + PlugAddress::EPlugDirection direction, + ESamplingFrequency samplingFrequency ); +protected: + Ieee1394Service* m_1394Service; + ConfigRom* m_configRom; + int m_nodeId; + + AvPlugVector m_isoInputPlugs; + AvPlugVector m_isoOutputPlugs; + + AvPlugConnectionVector m_plugConnections; + + AvDeviceSubunitVector m_subunits; + + nr_of_plugs_t m_serialBusIsochronousInputPlugs; + nr_of_plugs_t m_serialBusIsochronousOutputPlugs; + + DECLARE_DEBUG_MODULE; +}; + +#endif Index: /tags/release_0_0_6/libfreebob/src/.cvsignore =================================================================== --- /tags/release_0_0_6/libfreebob/src/.cvsignore (revision 134) +++ /tags/release_0_0_6/libfreebob/src/.cvsignore (revision 134) @@ -0,0 +1,7 @@ +.cvsignore +Makefile +Makefile.in +.deps +.libs +*.lo +*.la Index: /tags/release_0_0_6/libfreebob/src/csr1212.c =================================================================== --- /tags/release_0_0_6/libfreebob/src/csr1212.c (revision 156) +++ /tags/release_0_0_6/libfreebob/src/csr1212.c (revision 156) @@ -0,0 +1,1629 @@ +/* + * csr1212.c -- IEEE 1212 Control and Status Register support for Linux + * + * Copyright (C) 2003 Francois Retief + * Steve Kinneberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/* TODO List: + * - Verify interface consistency: i.e., public functions that take a size + * parameter expect size to be in bytes. + * - Convenience functions for reading a block of data from a given offset. + */ + +#ifndef __KERNEL__ +#include +#endif + +#include "csr1212.h" + + +/* Permitted key type for each key id */ +#define __I (1 << CSR1212_KV_TYPE_IMMEDIATE) +#define __C (1 << CSR1212_KV_TYPE_CSR_OFFSET) +#define __D (1 << CSR1212_KV_TYPE_DIRECTORY) +#define __L (1 << CSR1212_KV_TYPE_LEAF) +static const u_int8_t csr1212_key_id_type_map[0x30] = { + 0, /* Reserved */ + __D | __L, /* Descriptor */ + __I | __D | __L, /* Bus_Dependent_Info */ + __I | __D | __L, /* Vendor */ + __I, /* Hardware_Version */ + 0, 0, /* Reserved */ + __D | __L, /* Module */ + 0, 0, 0, 0, /* Reserved */ + __I, /* Node_Capabilities */ + __L, /* EUI_64 */ + 0, 0, 0, /* Reserved */ + __D, /* Unit */ + __I, /* Specifier_ID */ + __I, /* Version */ + __I | __C | __D | __L, /* Dependent_Info */ + __L, /* Unit_Location */ + 0, /* Reserved */ + __I, /* Model */ + __D, /* Instance */ + __L, /* Keyword */ + __D, /* Feature */ + __L, /* Extended_ROM */ + __I, /* Extended_Key_Specifier_ID */ + __I, /* Extended_Key */ + __I | __C | __D | __L, /* Extended_Data */ + __L, /* Modifiable_Descriptor */ + __I, /* Directory_ID */ + __I, /* Revision */ +}; +#undef __I +#undef __C +#undef __D +#undef __L + + +#define quads_to_bytes(_q) ((_q) * sizeof(u_int32_t)) +#define bytes_to_quads(_b) (((_b) + sizeof(u_int32_t) - 1) / sizeof(u_int32_t)) + +static inline void free_keyval(struct csr1212_keyval *kv) +{ + if ((kv->key.type == CSR1212_KV_TYPE_LEAF) && + (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)) + CSR1212_FREE(kv->value.leaf.data); + + CSR1212_FREE(kv); +} + +static u_int16_t csr1212_crc16(const u_int32_t *buffer, size_t length) +{ + int shift; + u_int32_t data; + u_int16_t sum, crc = 0; + + for (; length; length--) { + data = CSR1212_BE32_TO_CPU(*buffer); + buffer++; + for (shift = 28; shift >= 0; shift -= 4 ) { + sum = ((crc >> 12) ^ (data >> shift)) & 0xf; + crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum); + } + crc &= 0xffff; + } + + return CSR1212_CPU_TO_BE16(crc); +} + +#if 0 +/* Microsoft computes the CRC with the bytes in reverse order. Therefore we + * have a special version of the CRC algorithm to account for their buggy + * software. */ +static u_int16_t csr1212_msft_crc16(const u_int32_t *buffer, size_t length) +{ + int shift; + u_int32_t data; + u_int16_t sum, crc = 0; + + for (; length; length--) { + data = CSR1212_LE32_TO_CPU(*buffer); + buffer++; + for (shift = 28; shift >= 0; shift -= 4 ) { + sum = ((crc >> 12) ^ (data >> shift)) & 0xf; + crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum); + } + crc &= 0xffff; + } + + return CSR1212_CPU_TO_BE16(crc); +} +#endif + +static inline struct csr1212_dentry *csr1212_find_keyval(struct csr1212_keyval *dir, + struct csr1212_keyval *kv) +{ + struct csr1212_dentry *pos; + + for (pos = dir->value.directory.dentries_head; + pos != NULL; pos = pos->next) { + if (pos->kv == kv) + return pos; + } + return NULL; +} + + +static inline struct csr1212_keyval *csr1212_find_keyval_offset(struct csr1212_keyval *kv_list, + u_int32_t offset) +{ + struct csr1212_keyval *kv; + + for (kv = kv_list->next; kv && (kv != kv_list); kv = kv->next) { + if (kv->offset == offset) + return kv; + } + return NULL; +} + + +/* Creation Routines */ +struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops, + size_t bus_info_size, void *private_data) +{ + struct csr1212_csr *csr; + + csr = CSR1212_MALLOC(sizeof(*csr)); + if (!csr) + return NULL; + + csr->cache_head = + csr1212_rom_cache_malloc(CSR1212_CONFIG_ROM_SPACE_OFFSET, + CSR1212_CONFIG_ROM_SPACE_SIZE); + if (!csr->cache_head) { + CSR1212_FREE(csr); + return NULL; + } + + /* The keyval key id is not used for the root node, but a valid key id + * that can be used for a directory needs to be passed to + * csr1212_new_directory(). */ + csr->root_kv = csr1212_new_directory(CSR1212_KV_ID_VENDOR); + if (!csr->root_kv) { + CSR1212_FREE(csr->cache_head); + CSR1212_FREE(csr); + return NULL; + } + + csr->bus_info_data = csr->cache_head->data; + csr->bus_info_len = bus_info_size; + csr->crc_len = bus_info_size; + csr->ops = ops; + csr->private_data = private_data; + csr->cache_tail = csr->cache_head; + + return csr; +} + + + +void csr1212_init_local_csr(struct csr1212_csr *csr, + const u_int32_t *bus_info_data, int max_rom) +{ + static const int mr_map[] = { 4, 64, 1024, 0 }; + +#ifdef __KERNEL__ + BUG_ON(max_rom & ~0x3); + csr->max_rom = mr_map[max_rom]; +#else + if (max_rom & ~0x3) /* caller supplied invalid argument */ + csr->max_rom = 0; + else + csr->max_rom = mr_map[max_rom]; +#endif + memcpy(csr->bus_info_data, bus_info_data, csr->bus_info_len); +} + + +static struct csr1212_keyval *csr1212_new_keyval(u_int8_t type, u_int8_t key) +{ + struct csr1212_keyval *kv; + + if (key < 0x30 && ((csr1212_key_id_type_map[key] & (1 << type)) == 0)) + return NULL; + + kv = CSR1212_MALLOC(sizeof(*kv)); + if (!kv) + return NULL; + + kv->key.type = type; + kv->key.id = key; + + kv->associate = NULL; + kv->refcnt = 1; + + kv->next = NULL; + kv->prev = NULL; + kv->offset = 0; + kv->valid = 0; + return kv; +} + +struct csr1212_keyval *csr1212_new_immediate(u_int8_t key, u_int32_t value) +{ + struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_IMMEDIATE, key); + + if (!kv) + return NULL; + + kv->value.immediate = value; + kv->valid = 1; + return kv; +} + +struct csr1212_keyval *csr1212_new_leaf(u_int8_t key, const void *data, size_t data_len) +{ + struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, key); + + if (!kv) + return NULL; + + if (data_len > 0) { + kv->value.leaf.data = CSR1212_MALLOC(data_len); + if (!kv->value.leaf.data) { + CSR1212_FREE(kv); + return NULL; + } + + if (data) + memcpy(kv->value.leaf.data, data, data_len); + } else { + kv->value.leaf.data = NULL; + } + + kv->value.leaf.len = bytes_to_quads(data_len); + kv->offset = 0; + kv->valid = 1; + + return kv; +} + +struct csr1212_keyval *csr1212_new_csr_offset(u_int8_t key, u_int32_t csr_offset) +{ + struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_CSR_OFFSET, key); + + if (!kv) + return NULL; + + kv->value.csr_offset = csr_offset; + + kv->offset = 0; + kv->valid = 1; + return kv; +} + +struct csr1212_keyval *csr1212_new_directory(u_int8_t key) +{ + struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_DIRECTORY, key); + + if (!kv) + return NULL; + + kv->value.directory.len = 0; + kv->offset = 0; + kv->value.directory.dentries_head = NULL; + kv->value.directory.dentries_tail = NULL; + kv->valid = 1; + return kv; +} + +int csr1212_associate_keyval(struct csr1212_keyval *kv, + struct csr1212_keyval *associate) +{ + if (!kv || !associate) + return CSR1212_EINVAL; + + if (kv->key.id == CSR1212_KV_ID_DESCRIPTOR || + (associate->key.id != CSR1212_KV_ID_DESCRIPTOR && + associate->key.id != CSR1212_KV_ID_DEPENDENT_INFO && + associate->key.id != CSR1212_KV_ID_EXTENDED_KEY && + associate->key.id != CSR1212_KV_ID_EXTENDED_DATA && + associate->key.id < 0x30)) + return CSR1212_EINVAL; + + if (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID && + associate->key.id != CSR1212_KV_ID_EXTENDED_KEY) + return CSR1212_EINVAL; + + if (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY && + associate->key.id != CSR1212_KV_ID_EXTENDED_DATA) + return CSR1212_EINVAL; + + if (associate->key.id == CSR1212_KV_ID_EXTENDED_KEY && + kv->key.id != CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) + return CSR1212_EINVAL; + + if (associate->key.id == CSR1212_KV_ID_EXTENDED_DATA && + kv->key.id != CSR1212_KV_ID_EXTENDED_KEY) + return CSR1212_EINVAL; + + if (kv->associate) + csr1212_release_keyval(kv->associate); + + associate->refcnt++; + kv->associate = associate; + + return CSR1212_SUCCESS; +} + +int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, + struct csr1212_keyval *kv) +{ + struct csr1212_dentry *dentry; + + if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY) + return CSR1212_EINVAL; + + dentry = CSR1212_MALLOC(sizeof(*dentry)); + if (!dentry) + return CSR1212_ENOMEM; + + dentry->kv = kv; + + kv->refcnt++; + + dentry->next = NULL; + dentry->prev = dir->value.directory.dentries_tail; + + if (!dir->value.directory.dentries_head) + dir->value.directory.dentries_head = dentry; + + if (dir->value.directory.dentries_tail) + dir->value.directory.dentries_tail->next = dentry; + dir->value.directory.dentries_tail = dentry; + + return CSR1212_SUCCESS; +} + +struct csr1212_keyval *csr1212_new_extended_immediate(u_int32_t spec, u_int32_t key, + u_int32_t value) +{ + struct csr1212_keyval *kvs, *kvk, *kvv; + + kvs = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID, spec); + kvk = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY, key); + kvv = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_DATA, value); + + if (!kvs || !kvk || !kvv) { + if (kvs) + free_keyval(kvs); + if (kvk) + free_keyval(kvk); + if (kvv) + free_keyval(kvv); + return NULL; + } + + /* Don't keep a local reference to the extended key or value. */ + kvk->refcnt = 0; + kvv->refcnt = 0; + + csr1212_associate_keyval(kvk, kvv); + csr1212_associate_keyval(kvs, kvk); + + return kvs; +} + +struct csr1212_keyval *csr1212_new_extended_leaf(u_int32_t spec, u_int32_t key, + const void *data, size_t data_len) +{ + struct csr1212_keyval *kvs, *kvk, *kvv; + + kvs = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID, spec); + kvk = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY, key); + kvv = csr1212_new_leaf(CSR1212_KV_ID_EXTENDED_DATA, data, data_len); + + if (!kvs || !kvk || !kvv) { + if (kvs) + free_keyval(kvs); + if (kvk) + free_keyval(kvk); + if (kvv) + free_keyval(kvv); + return NULL; + } + + /* Don't keep a local reference to the extended key or value. */ + kvk->refcnt = 0; + kvv->refcnt = 0; + + csr1212_associate_keyval(kvk, kvv); + csr1212_associate_keyval(kvs, kvk); + + return kvs; +} + +struct csr1212_keyval *csr1212_new_descriptor_leaf(u_int8_t dtype, u_int32_t specifier_id, + const void *data, size_t data_len) +{ + struct csr1212_keyval *kv; + + kv = csr1212_new_leaf(CSR1212_KV_ID_DESCRIPTOR, NULL, + data_len + CSR1212_DESCRIPTOR_LEAF_OVERHEAD); + if (!kv) + return NULL; + + CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, dtype); + CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, specifier_id); + + if (data) { + memcpy(CSR1212_DESCRIPTOR_LEAF_DATA(kv), data, data_len); + } + + return kv; +} + + +struct csr1212_keyval *csr1212_new_textual_descriptor_leaf(u_int8_t cwidth, + u_int16_t cset, + u_int16_t language, + const void *data, + size_t data_len) +{ + struct csr1212_keyval *kv; + char *lstr; + + kv = csr1212_new_descriptor_leaf(0, 0, NULL, data_len + + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD); + if (!kv) + return NULL; + + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_WIDTH(kv, cwidth); + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_CHAR_SET(kv, cset); + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language); + + lstr = (char*)CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv); + + /* make sure last quadlet is zeroed out */ + *((u_int32_t*)&(lstr[(data_len - 1) & ~0x3])) = 0; + + /* don't copy the NUL terminator */ + memcpy(lstr, data, data_len); + + return kv; +} + +static int csr1212_check_minimal_ascii(const char *s) +{ + static const char minimal_ascii_table[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x0a, 0x00, 0x0C, 0x0D, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x21, 0x22, 0x00, 0x00, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x5f, + 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + for (; *s; s++) { + if (minimal_ascii_table[*s & 0x7F] != *s) + return -1; /* failed */ + } + /* String conforms to minimal-ascii, as specified by IEEE 1212, + * par. 7.4 */ + return 0; +} + +struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s) +{ + /* Check if string conform to minimal_ascii format */ + if (csr1212_check_minimal_ascii(s)) + return NULL; + + /* IEEE 1212, par. 7.5.4.1 Textual descriptors (minimal ASCII) */ + return csr1212_new_textual_descriptor_leaf(0, 0, 0, s, strlen(s)); +} + +struct csr1212_keyval *csr1212_new_icon_descriptor_leaf(u_int32_t version, + u_int8_t palette_depth, + u_int8_t color_space, + u_int16_t language, + u_int16_t hscan, + u_int16_t vscan, + u_int32_t *palette, + u_int32_t *pixels) +{ + static const int pd[4] = { 0, 4, 16, 256 }; + static const int cs[16] = { 4, 2 }; + struct csr1212_keyval *kv; + int palette_size; + int pixel_size = (hscan * vscan + 3) & ~0x3; + + if (!pixels || (!palette && palette_depth) || + (palette_depth & ~0x3) || (color_space & ~0xf)) + return NULL; + + palette_size = pd[palette_depth] * cs[color_space]; + + kv = csr1212_new_descriptor_leaf(1, 0, NULL, + palette_size + pixel_size + + CSR1212_ICON_DESCRIPTOR_LEAF_OVERHEAD); + if (!kv) + return NULL; + + CSR1212_ICON_DESCRIPTOR_LEAF_SET_VERSION(kv, version); + CSR1212_ICON_DESCRIPTOR_LEAF_SET_PALETTE_DEPTH(kv, palette_depth); + CSR1212_ICON_DESCRIPTOR_LEAF_SET_COLOR_SPACE(kv, color_space); + CSR1212_ICON_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language); + CSR1212_ICON_DESCRIPTOR_LEAF_SET_HSCAN(kv, hscan); + CSR1212_ICON_DESCRIPTOR_LEAF_SET_VSCAN(kv, vscan); + + if (palette_size) + memcpy(CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE(kv), palette, + palette_size); + + memcpy(CSR1212_ICON_DESCRIPTOR_LEAF_PIXELS(kv), pixels, pixel_size); + + return kv; +} + +struct csr1212_keyval *csr1212_new_modifiable_descriptor_leaf(u_int16_t max_size, + u_int64_t address) +{ + struct csr1212_keyval *kv; + + /* IEEE 1212, par. 7.5.4.3 Modifiable descriptors */ + kv = csr1212_new_leaf(CSR1212_KV_ID_MODIFIABLE_DESCRIPTOR, NULL, sizeof(u_int64_t)); + if(!kv) + return NULL; + + CSR1212_MODIFIABLE_DESCRIPTOR_SET_MAX_SIZE(kv, max_size); + CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_HI(kv, address); + CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_LO(kv, address); + + return kv; +} + +static int csr1212_check_keyword(const char *s) +{ + for (; *s; s++) { + + if (('A' <= *s) && (*s <= 'Z')) + continue; + if (('0' <= *s) && (*s <= '9')) + continue; + if (*s == '-') + continue; + + return -1; /* failed */ + } + /* String conforms to keyword, as specified by IEEE 1212, + * par. 7.6.5 */ + return CSR1212_SUCCESS; +} + +struct csr1212_keyval *csr1212_new_keyword_leaf(int strc, const char *strv[]) +{ + struct csr1212_keyval *kv; + char *buffer; + int i, data_len = 0; + + /* Check all keywords to see if they conform to restrictions: + * Only the following characters is allowed ['A'..'Z','0'..'9','-'] + * Each word is zero-terminated. + * Also calculate the total length of the keywords. + */ + for (i = 0; i < strc; i++) { + if (!strv[i] || csr1212_check_keyword(strv[i])) { + return NULL; + } + data_len += strlen(strv[i]) + 1; /* Add zero-termination char. */ + } + + /* IEEE 1212, par. 7.6.5 Keyword leaves */ + kv = csr1212_new_leaf(CSR1212_KV_ID_KEYWORD, NULL, data_len); + if (!kv) + return NULL; + + buffer = (char *)kv->value.leaf.data; + + /* make sure last quadlet is zeroed out */ + *((u_int32_t*)&(buffer[(data_len - 1) & ~0x3])) = 0; + + /* Copy keyword(s) into leaf data buffer */ + for (i = 0; i < strc; i++) { + int len = strlen(strv[i]) + 1; + memcpy(buffer, strv[i], len); + buffer += len; + } + return kv; +} + + +/* Destruction Routines */ + +void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir, + struct csr1212_keyval *kv) +{ + struct csr1212_dentry *dentry; + + if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY) + return; + + dentry = csr1212_find_keyval(dir, kv); + + if (!dentry) + return; + + if (dentry->prev) + dentry->prev->next = dentry->next; + if (dentry->next) + dentry->next->prev = dentry->prev; + if (dir->value.directory.dentries_head == dentry) + dir->value.directory.dentries_head = dentry->next; + if (dir->value.directory.dentries_tail == dentry) + dir->value.directory.dentries_tail = dentry->prev; + + CSR1212_FREE(dentry); + + csr1212_release_keyval(kv); +} + + +void csr1212_disassociate_keyval(struct csr1212_keyval *kv) +{ + if (kv->associate) { + csr1212_release_keyval(kv->associate); + } + + kv->associate = NULL; +} + + +/* This function is used to free the memory taken by a keyval. If the given + * keyval is a directory type, then any keyvals contained in that directory + * will be destroyed as well if their respective refcnts are 0. By means of + * list manipulation, this routine will descend a directory structure in a + * non-recursive manner. */ +void _csr1212_destroy_keyval(struct csr1212_keyval *kv) +{ + struct csr1212_keyval *k, *a; + struct csr1212_dentry dentry; + struct csr1212_dentry *head, *tail; + + dentry.kv = kv; + dentry.next = NULL; + dentry.prev = NULL; + + head = &dentry; + tail = head; + + while (head) { + k = head->kv; + + while (k) { + k->refcnt--; + + if (k->refcnt > 0) + break; + + a = k->associate; + + if (k->key.type == CSR1212_KV_TYPE_DIRECTORY) { + /* If the current entry is a directory, then move all + * the entries to the destruction list. */ + if (k->value.directory.dentries_head) { + tail->next = k->value.directory.dentries_head; + k->value.directory.dentries_head->prev = tail; + tail = k->value.directory.dentries_tail; + } + } + free_keyval(k); + k = a; + } + + head = head->next; + if (head) { + if (head->prev && head->prev != &dentry) { + CSR1212_FREE(head->prev); + } + head->prev = NULL; + } else if (tail != &dentry) + CSR1212_FREE(tail); + } +} + + +void csr1212_destroy_csr(struct csr1212_csr *csr) +{ + struct csr1212_csr_rom_cache *c, *oc; + struct csr1212_cache_region *cr, *ocr; + + csr1212_release_keyval(csr->root_kv); + + c = csr->cache_head; + while (c) { + oc = c; + cr = c->filled_head; + while (cr) { + ocr = cr; + cr = cr->next; + CSR1212_FREE(ocr); + } + c = c->next; + CSR1212_FREE(oc); + } + + CSR1212_FREE(csr); +} + + + +/* CSR Image Creation */ + +static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize) +{ + struct csr1212_csr_rom_cache *cache; + u_int64_t csr_addr; + + if (!csr || !csr->ops || !csr->ops->allocate_addr_range || + !csr->ops->release_addr || csr->max_rom < 1) + return CSR1212_EINVAL; + + /* ROM size must be a multiple of csr->max_rom */ + romsize = (romsize + (csr->max_rom - 1)) & ~(csr->max_rom - 1); + + csr_addr = csr->ops->allocate_addr_range(romsize, csr->max_rom, csr->private_data); + if (csr_addr == ~0ULL) { + return CSR1212_ENOMEM; + } + if (csr_addr < CSR1212_REGISTER_SPACE_BASE) { + /* Invalid address returned from allocate_addr_range(). */ + csr->ops->release_addr(csr_addr, csr->private_data); + return CSR1212_ENOMEM; + } + + cache = csr1212_rom_cache_malloc(csr_addr - CSR1212_REGISTER_SPACE_BASE, romsize); + if (!cache) { + csr->ops->release_addr(csr_addr, csr->private_data); + return CSR1212_ENOMEM; + } + + cache->ext_rom = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, CSR1212_KV_ID_EXTENDED_ROM); + if (!cache->ext_rom) { + csr->ops->release_addr(csr_addr, csr->private_data); + CSR1212_FREE(cache); + return CSR1212_ENOMEM; + } + + if (csr1212_attach_keyval_to_directory(csr->root_kv, cache->ext_rom) != CSR1212_SUCCESS) { + csr1212_release_keyval(cache->ext_rom); + csr->ops->release_addr(csr_addr, csr->private_data); + CSR1212_FREE(cache); + return CSR1212_ENOMEM; + } + cache->ext_rom->offset = csr_addr - CSR1212_REGISTER_SPACE_BASE; + cache->ext_rom->value.leaf.len = -1; + cache->ext_rom->value.leaf.data = cache->data; + + /* Add cache to tail of cache list */ + cache->prev = csr->cache_tail; + csr->cache_tail->next = cache; + csr->cache_tail = cache; + return CSR1212_SUCCESS; +} + +static inline void csr1212_remove_cache(struct csr1212_csr *csr, + struct csr1212_csr_rom_cache *cache) +{ + if (csr->cache_head == cache) + csr->cache_head = cache->next; + if (csr->cache_tail == cache) + csr->cache_tail = cache->prev; + + if (cache->prev) + cache->prev->next = cache->next; + if (cache->next) + cache->next->prev = cache->prev; + + if (cache->ext_rom) { + csr1212_detach_keyval_from_directory(csr->root_kv, cache->ext_rom); + csr1212_release_keyval(cache->ext_rom); + } + + CSR1212_FREE(cache); +} + +static int csr1212_generate_layout_subdir(struct csr1212_keyval *dir, + struct csr1212_keyval **layout_tail) +{ + struct csr1212_dentry *dentry; + struct csr1212_keyval *dkv; + struct csr1212_keyval *last_extkey_spec = NULL; + struct csr1212_keyval *last_extkey = NULL; + int num_entries = 0; + + for (dentry = dir->value.directory.dentries_head; dentry; + dentry = dentry->next) { + for (dkv = dentry->kv; dkv; dkv = dkv->associate) { + /* Special Case: Extended Key Specifier_ID */ + if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) { + if (last_extkey_spec == NULL) { + last_extkey_spec = dkv; + } else if (dkv->value.immediate != last_extkey_spec->value.immediate) { + last_extkey_spec = dkv; + } else { + continue; + } + /* Special Case: Extended Key */ + } else if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY) { + if (last_extkey == NULL) { + last_extkey = dkv; + } else if (dkv->value.immediate != last_extkey->value.immediate) { + last_extkey = dkv; + } else { + continue; + } + } + + num_entries += 1; + + switch(dkv->key.type) { + default: + case CSR1212_KV_TYPE_IMMEDIATE: + case CSR1212_KV_TYPE_CSR_OFFSET: + break; + case CSR1212_KV_TYPE_LEAF: + case CSR1212_KV_TYPE_DIRECTORY: + /* Remove from list */ + if (dkv->prev && (dkv->prev->next == dkv)) + dkv->prev->next = dkv->next; + if (dkv->next && (dkv->next->prev == dkv)) + dkv->next->prev = dkv->prev; + //if (dkv == *layout_tail) + // *layout_tail = dkv->prev; + + /* Special case: Extended ROM leafs */ + if (dkv->key.id == CSR1212_KV_ID_EXTENDED_ROM) { + dkv->value.leaf.len = -1; + /* Don't add Extended ROM leafs in the layout list, + * they are handled differently. */ + break; + } + + /* Add to tail of list */ + dkv->next = NULL; + dkv->prev = *layout_tail; + (*layout_tail)->next = dkv; + *layout_tail = dkv; + break; + } + } + } + return num_entries; +} + +size_t csr1212_generate_layout_order(struct csr1212_keyval *kv) +{ + struct csr1212_keyval *ltail = kv; + size_t agg_size = 0; + + while(kv) { + switch(kv->key.type) { + case CSR1212_KV_TYPE_LEAF: + /* Add 1 quadlet for crc/len field */ + agg_size += kv->value.leaf.len + 1; + break; + + case CSR1212_KV_TYPE_DIRECTORY: + kv->value.directory.len = csr1212_generate_layout_subdir(kv, <ail); + /* Add 1 quadlet for crc/len field */ + agg_size += kv->value.directory.len + 1; + break; + } + kv = kv->next; + } + return quads_to_bytes(agg_size); +} + +struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *cache, + struct csr1212_keyval *start_kv, + int start_pos) +{ + struct csr1212_keyval *kv = start_kv; + struct csr1212_keyval *okv = start_kv; + int pos = start_pos; + int kv_len = 0, okv_len = 0; + + cache->layout_head = kv; + + while(kv && pos < cache->size) { + /* Special case: Extended ROM leafs */ + if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) { + kv->offset = cache->offset + pos; + } + + switch(kv->key.type) { + case CSR1212_KV_TYPE_LEAF: + kv_len = kv->value.leaf.len; + break; + + case CSR1212_KV_TYPE_DIRECTORY: + kv_len = kv->value.directory.len; + break; + + default: + /* Should never get here */ + break; + } + + pos += quads_to_bytes(kv_len + 1); + + if (pos <= cache->size) { + okv = kv; + okv_len = kv_len; + kv = kv->next; + } + } + + cache->layout_tail = okv; + cache->len = (okv->offset - cache->offset) + quads_to_bytes(okv_len + 1); + + return kv; +} + +static void csr1212_generate_tree_subdir(struct csr1212_keyval *dir, + u_int32_t *data_buffer) +{ + struct csr1212_dentry *dentry; + struct csr1212_keyval *last_extkey_spec = NULL; + struct csr1212_keyval *last_extkey = NULL; + int index = 0; + + for (dentry = dir->value.directory.dentries_head; dentry; dentry = dentry->next) { + struct csr1212_keyval *a; + + for (a = dentry->kv; a; a = a->associate) { + u_int32_t value = 0; + + /* Special Case: Extended Key Specifier_ID */ + if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) { + if (last_extkey_spec == NULL) { + last_extkey_spec = a; + } else if (a->value.immediate != last_extkey_spec->value.immediate) { + last_extkey_spec = a; + } else { + continue; + } + /* Special Case: Extended Key */ + } else if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY) { + if (last_extkey == NULL) { + last_extkey = a; + } else if (a->value.immediate != last_extkey->value.immediate) { + last_extkey = a; + } else { + continue; + } + } + + switch(a->key.type) { + case CSR1212_KV_TYPE_IMMEDIATE: + value = a->value.immediate; + break; + case CSR1212_KV_TYPE_CSR_OFFSET: + value = a->value.csr_offset; + break; + case CSR1212_KV_TYPE_LEAF: + value = a->offset; + value -= dir->offset + quads_to_bytes(1+index); + value = bytes_to_quads(value); + break; + case CSR1212_KV_TYPE_DIRECTORY: + value = a->offset; + value -= dir->offset + quads_to_bytes(1+index); + value = bytes_to_quads(value); + break; + default: + /* Should never get here */ + break; /* GDB breakpoint */ + } + + value |= (a->key.id & CSR1212_KV_KEY_ID_MASK) << CSR1212_KV_KEY_SHIFT; + value |= (a->key.type & CSR1212_KV_KEY_TYPE_MASK) << + (CSR1212_KV_KEY_SHIFT + CSR1212_KV_KEY_TYPE_SHIFT); + data_buffer[index] = CSR1212_CPU_TO_BE32(value); + index++; + } + } +} + +void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache) +{ + struct csr1212_keyval *kv, *nkv; + struct csr1212_keyval_img *kvi; + + for (kv = cache->layout_head; kv != cache->layout_tail->next; kv = nkv) { + kvi = (struct csr1212_keyval_img *) + (cache->data + bytes_to_quads(kv->offset - cache->offset)); + switch(kv->key.type) { + default: + case CSR1212_KV_TYPE_IMMEDIATE: + case CSR1212_KV_TYPE_CSR_OFFSET: + /* Should never get here */ + break; /* GDB breakpoint */ + + case CSR1212_KV_TYPE_LEAF: + /* Don't copy over Extended ROM areas, they are + * already filled out! */ + if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) + memcpy(kvi->data, kv->value.leaf.data, + quads_to_bytes(kv->value.leaf.len)); + + kvi->length = CSR1212_CPU_TO_BE16(kv->value.leaf.len); + kvi->crc = csr1212_crc16(kvi->data, kv->value.leaf.len); + break; + + case CSR1212_KV_TYPE_DIRECTORY: + csr1212_generate_tree_subdir(kv, kvi->data); + + kvi->length = CSR1212_CPU_TO_BE16(kv->value.directory.len); + kvi->crc = csr1212_crc16(kvi->data, kv->value.directory.len); + break; + } + + nkv = kv->next; + if (kv->prev) + kv->prev->next = NULL; + if (kv->next) + kv->next->prev = NULL; + kv->prev = NULL; + kv->next = NULL; + } +} + +int csr1212_generate_csr_image(struct csr1212_csr *csr) +{ + struct csr1212_bus_info_block_img *bi; + struct csr1212_csr_rom_cache *cache; + struct csr1212_keyval *kv; + size_t agg_size; + int ret; + int init_offset; + + if (!csr) + return CSR1212_EINVAL; + + cache = csr->cache_head; + + bi = (struct csr1212_bus_info_block_img*)cache->data; + + bi->length = bytes_to_quads(csr->bus_info_len) - 1; + bi->crc_length = bi->length; + bi->crc = csr1212_crc16(bi->data, bi->crc_length); + + csr->root_kv->next = NULL; + csr->root_kv->prev = NULL; + + agg_size = csr1212_generate_layout_order(csr->root_kv); + + init_offset = csr->bus_info_len; + + for (kv = csr->root_kv, cache = csr->cache_head; kv; cache = cache->next) { + if (!cache) { + /* Estimate approximate number of additional cache + * regions needed (it assumes that the cache holding + * the first 1K Config ROM space always exists). */ + int est_c = agg_size / (CSR1212_EXTENDED_ROM_SIZE - + (2 * sizeof(u_int32_t))) + 1; + + /* Add additional cache regions, extras will be + * removed later */ + for (; est_c; est_c--) { + ret = csr1212_append_new_cache(csr, CSR1212_EXTENDED_ROM_SIZE); + if (ret != CSR1212_SUCCESS) + return ret; + } + /* Need to re-layout for additional cache regions */ + agg_size = csr1212_generate_layout_order(csr->root_kv); + kv = csr->root_kv; + cache = csr->cache_head; + init_offset = csr->bus_info_len; + } + kv = csr1212_generate_positions(cache, kv, init_offset); + agg_size -= cache->len; + init_offset = sizeof(u_int32_t); + } + + /* Remove unused, excess cache regions */ + while (cache) { + struct csr1212_csr_rom_cache *oc = cache; + + cache = cache->next; + csr1212_remove_cache(csr, oc); + } + + /* Go through the list backward so that when done, the correct CRC + * will be calculated for the Extended ROM areas. */ + for(cache = csr->cache_tail; cache; cache = cache->prev) { + /* Only Extended ROM caches should have this set. */ + if (cache->ext_rom) { + int leaf_size; + + /* Make sure the Extended ROM leaf is a multiple of + * max_rom in size. */ + if (csr->max_rom < 1) + return CSR1212_EINVAL; + leaf_size = (cache->len + (csr->max_rom - 1)) & + ~(csr->max_rom - 1); + + /* Zero out the unused ROM region */ + memset(cache->data + bytes_to_quads(cache->len), 0x00, + leaf_size - cache->len); + + /* Subtract leaf header */ + leaf_size -= sizeof(u_int32_t); + + /* Update the Extended ROM leaf length */ + cache->ext_rom->value.leaf.len = + bytes_to_quads(leaf_size); + } else { + /* Zero out the unused ROM region */ + memset(cache->data + bytes_to_quads(cache->len), 0x00, + cache->size - cache->len); + } + + /* Copy the data into the cache buffer */ + csr1212_fill_cache(cache); + + if (cache != csr->cache_head) { + /* Set the length and CRC of the extended ROM. */ + struct csr1212_keyval_img *kvi = + (struct csr1212_keyval_img*)cache->data; + + kvi->length = CSR1212_CPU_TO_BE16(bytes_to_quads(cache->len) - 1); + kvi->crc = csr1212_crc16(kvi->data, + bytes_to_quads(cache->len) - 1); + + } + } + + return CSR1212_SUCCESS; +} + +int csr1212_read(struct csr1212_csr *csr, u_int32_t offset, void *buffer, u_int32_t len) +{ + struct csr1212_csr_rom_cache *cache; + + for (cache = csr->cache_head; cache; cache = cache->next) { + if (offset >= cache->offset && + (offset + len) <= (cache->offset + cache->size)) { + memcpy(buffer, + &cache->data[bytes_to_quads(offset - cache->offset)], + len); + return CSR1212_SUCCESS; + } + } + return CSR1212_ENOENT; +} + + + +/* Parse a chunk of data as a Config ROM */ + +static int csr1212_parse_bus_info_block(struct csr1212_csr *csr) +{ + struct csr1212_bus_info_block_img *bi; + struct csr1212_cache_region *cr; + int i; + int ret; + + /* IEEE 1212 says that the entire bus info block should be readable in + * a single transaction regardless of the max_rom value. + * Unfortunately, many IEEE 1394 devices do not abide by that, so the + * bus info block will be read 1 quadlet at a time. The rest of the + * ConfigROM will be read according to the max_rom field. */ + for (i = 0; i < csr->bus_info_len; i += sizeof(csr1212_quad_t)) { + ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i, + sizeof(csr1212_quad_t), + &csr->cache_head->data[bytes_to_quads(i)], + csr->private_data); + if (ret != CSR1212_SUCCESS) + return ret; + } + + bi = (struct csr1212_bus_info_block_img*)csr->cache_head->data; + csr->crc_len = quads_to_bytes(bi->crc_length); + + /* IEEE 1212 recommends that crc_len be equal to bus_info_len, but that is not + * always the case, so read the rest of the crc area 1 quadlet at a time. */ + for (i = csr->bus_info_len; i <= csr->crc_len; i += sizeof(csr1212_quad_t)) { + ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i, + sizeof(csr1212_quad_t), + &csr->cache_head->data[bytes_to_quads(i)], + csr->private_data); + if (ret != CSR1212_SUCCESS) + return ret; + } + + if (bytes_to_quads(csr->bus_info_len - sizeof(csr1212_quad_t)) != bi->length) + return CSR1212_EINVAL; + +#if 0 + /* Apparently there are too many differnt wrong implementations of the + * CRC algorithm that verifying them is moot. */ + if ((csr1212_crc16(bi->data, bi->crc_length) != bi->crc) && + (csr1212_msft_crc16(bi->data, bi->crc_length) != bi->crc)) + return CSR1212_EINVAL; +#endif + + cr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region)); + if (!cr) + return CSR1212_ENOMEM; + + cr->next = NULL; + cr->prev = NULL; + cr->offset_start = 0; + cr->offset_end = csr->crc_len + 4; + + csr->cache_head->filled_head = cr; + csr->cache_head->filled_tail = cr; + + return CSR1212_SUCCESS; +} + +static int csr1212_parse_dir_entry(struct csr1212_keyval *dir, + csr1212_quad_t ki, + u_int32_t kv_pos) +{ + int ret = CSR1212_SUCCESS; + struct csr1212_keyval *k = NULL; + u_int32_t offset; + + switch(CSR1212_KV_KEY_TYPE(ki)) { + case CSR1212_KV_TYPE_IMMEDIATE: + k = csr1212_new_immediate(CSR1212_KV_KEY_ID(ki), + CSR1212_KV_VAL(ki)); + if (!k) { + ret = CSR1212_ENOMEM; + goto fail; + } + + k->refcnt = 0; /* Don't keep local reference when parsing. */ + break; + + case CSR1212_KV_TYPE_CSR_OFFSET: + k = csr1212_new_csr_offset(CSR1212_KV_KEY_ID(ki), + CSR1212_KV_VAL(ki)); + if (!k) { + ret = CSR1212_ENOMEM; + goto fail; + } + k->refcnt = 0; /* Don't keep local reference when parsing. */ + break; + + default: + /* Compute the offset from 0xffff f000 0000. */ + offset = quads_to_bytes(CSR1212_KV_VAL(ki)) + kv_pos; + if (offset == kv_pos) { + /* Uh-oh. Can't have a relative offset of 0 for Leaves + * or Directories. The Config ROM image is most likely + * messed up, so we'll just abort here. */ + ret = CSR1212_EIO; + goto fail; + } + + k = csr1212_find_keyval_offset(dir, offset); + + if (k) + break; /* Found it. */ + + if (CSR1212_KV_KEY_TYPE(ki) == CSR1212_KV_TYPE_DIRECTORY) { + k = csr1212_new_directory(CSR1212_KV_KEY_ID(ki)); + } else { + k = csr1212_new_leaf(CSR1212_KV_KEY_ID(ki), NULL, 0); + } + if (!k) { + ret = CSR1212_ENOMEM; + goto fail; + } + k->refcnt = 0; /* Don't keep local reference when parsing. */ + k->valid = 0; /* Contents not read yet so it's not valid. */ + k->offset = offset; + + k->prev = dir; + k->next = dir->next; + dir->next->prev = k; + dir->next = k; + } + ret = csr1212_attach_keyval_to_directory(dir, k); + +fail: + if (ret != CSR1212_SUCCESS) { + if (k) + free_keyval(k); + } + return ret; +} + + +int csr1212_parse_keyval(struct csr1212_keyval *kv, + struct csr1212_csr_rom_cache *cache) +{ + struct csr1212_keyval_img *kvi; + int i; + int ret = CSR1212_SUCCESS; + int kvi_len; + + kvi = (struct csr1212_keyval_img*)&cache->data[bytes_to_quads(kv->offset - + cache->offset)]; + kvi_len = CSR1212_BE16_TO_CPU(kvi->length); + +#if 0 + /* Apparently there are too many differnt wrong implementations of the + * CRC algorithm that verifying them is moot. */ + if ((csr1212_crc16(kvi->data, kvi_len) != kvi->crc) && + (csr1212_msft_crc16(kvi->data, kvi_len) != kvi->crc)) { + ret = CSR1212_EINVAL; + goto fail; + } +#endif + + switch(kv->key.type) { + case CSR1212_KV_TYPE_DIRECTORY: + for (i = 0; i < kvi_len; i++) { + csr1212_quad_t ki = kvi->data[i]; + + /* Some devices put null entries in their unit + * directories. If we come across such an entry, + * then skip it. */ + if (ki == 0x0) + continue; + ret = csr1212_parse_dir_entry(kv, ki, + (kv->offset + + quads_to_bytes(i + 1))); + } + kv->value.directory.len = kvi_len; + break; + + case CSR1212_KV_TYPE_LEAF: + if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) { + kv->value.leaf.data = CSR1212_MALLOC(quads_to_bytes(kvi_len)); + if (!kv->value.leaf.data) + { + ret = CSR1212_ENOMEM; + goto fail; + } + + kv->value.leaf.len = kvi_len; + memcpy(kv->value.leaf.data, kvi->data, quads_to_bytes(kvi_len)); + } + break; + } + + kv->valid = 1; + +fail: + return ret; +} + + +int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) +{ + struct csr1212_cache_region *cr, *ncr, *newcr = NULL; + struct csr1212_keyval_img *kvi = NULL; + struct csr1212_csr_rom_cache *cache; + int cache_index; + u_int64_t addr; + u_int32_t *cache_ptr; + u_int16_t kv_len = 0; + + if (!csr || !kv || csr->max_rom < 1) + return CSR1212_EINVAL; + + /* First find which cache the data should be in (or go in if not read + * yet). */ + for (cache = csr->cache_head; cache; cache = cache->next) { + if (kv->offset >= cache->offset && + kv->offset < (cache->offset + cache->size)) + break; + } + + if (!cache) { + csr1212_quad_t q; + u_int32_t cache_size; + + /* Only create a new cache for Extended ROM leaves. */ + if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) + return CSR1212_EINVAL; + + if (csr->ops->bus_read(csr, + CSR1212_REGISTER_SPACE_BASE + kv->offset, + sizeof(csr1212_quad_t), &q, csr->private_data)) { + return CSR1212_EIO; + } + + kv->value.leaf.len = CSR1212_BE32_TO_CPU(q) >> 16; + + cache_size = (quads_to_bytes(kv->value.leaf.len + 1) + + (csr->max_rom - 1)) & ~(csr->max_rom - 1); + + cache = csr1212_rom_cache_malloc(kv->offset, cache_size); + if (!cache) + return CSR1212_ENOMEM; + + kv->value.leaf.data = &cache->data[1]; + csr->cache_tail->next = cache; + cache->prev = csr->cache_tail; + cache->next = NULL; + csr->cache_tail = cache; + cache->filled_head = + CSR1212_MALLOC(sizeof(struct csr1212_cache_region)); + if (!cache->filled_head) { + return CSR1212_ENOMEM; + } + + cache->filled_head->offset_start = 0; + cache->filled_head->offset_end = sizeof(csr1212_quad_t); + cache->filled_tail = cache->filled_head; + cache->filled_head->next = NULL; + cache->filled_head->prev = NULL; + cache->data[0] = q; + + /* Don't read the entire extended ROM now. Pieces of it will + * be read when entries inside it are read. */ + return csr1212_parse_keyval(kv, cache); + } + + cache_index = kv->offset - cache->offset; + + /* Now seach read portions of the cache to see if it is there. */ + for (cr = cache->filled_head; cr; cr = cr->next) { + if (cache_index < cr->offset_start) { + newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region)); + if (!newcr) + return CSR1212_ENOMEM; + + newcr->offset_start = cache_index & ~(csr->max_rom - 1); + newcr->offset_end = newcr->offset_start; + newcr->next = cr; + newcr->prev = cr->prev; + cr->prev = newcr; + cr = newcr; + break; + } else if ((cache_index >= cr->offset_start) && + (cache_index < cr->offset_end)) { + kvi = (struct csr1212_keyval_img*) + (&cache->data[bytes_to_quads(cache_index)]); + kv_len = quads_to_bytes(CSR1212_BE16_TO_CPU(kvi->length) + + 1); + break; + } else if (cache_index == cr->offset_end) + break; + } + + if (!cr) { + cr = cache->filled_tail; + newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region)); + if (!newcr) + return CSR1212_ENOMEM; + + newcr->offset_start = cache_index & ~(csr->max_rom - 1); + newcr->offset_end = newcr->offset_start; + newcr->prev = cr; + newcr->next = cr->next; + cr->next = newcr; + cr = newcr; + cache->filled_tail = newcr; + } + + while(!kvi || cr->offset_end < cache_index + kv_len) { + cache_ptr = &cache->data[bytes_to_quads(cr->offset_end & + ~(csr->max_rom - 1))]; + + addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset + + cr->offset_end) & ~(csr->max_rom - 1); + + if (csr->ops->bus_read(csr, addr, csr->max_rom, cache_ptr, + csr->private_data)) { + if (csr->max_rom == 4) + /* We've got problems! */ + return CSR1212_EIO; + + /* Apperently the max_rom value was a lie, set it to + * do quadlet reads and try again. */ + csr->max_rom = 4; + continue; + } + + cr->offset_end += csr->max_rom - (cr->offset_end & + (csr->max_rom - 1)); + + if (!kvi && (cr->offset_end > cache_index)) { + kvi = (struct csr1212_keyval_img*) + (&cache->data[bytes_to_quads(cache_index)]); + kv_len = quads_to_bytes(CSR1212_BE16_TO_CPU(kvi->length) + + 1); + } + + if ((kv_len + (kv->offset - cache->offset)) > cache->size) { + /* The Leaf or Directory claims its length extends + * beyond the ConfigROM image region and thus beyond the + * end of our cache region. Therefore, we abort now + * rather than seg faulting later. */ + return CSR1212_EIO; + } + + ncr = cr->next; + + if (ncr && (cr->offset_end >= ncr->offset_start)) { + /* consolidate region entries */ + ncr->offset_start = cr->offset_start; + + if (cr->prev) + cr->prev->next = cr->next; + ncr->prev = cr->prev; + if (cache->filled_head == cr) + cache->filled_head = ncr; + CSR1212_FREE(cr); + cr = ncr; + } + } + + return csr1212_parse_keyval(kv, cache); +} + + + +int csr1212_parse_csr(struct csr1212_csr *csr) +{ + static const int mr_map[] = { 4, 64, 1024, 0 }; + struct csr1212_dentry *dentry; + int ret; + + if (!csr || !csr->ops || !csr->ops->bus_read) + return CSR1212_EINVAL; + + ret = csr1212_parse_bus_info_block(csr); + if (ret != CSR1212_SUCCESS) + return ret; + + if (!csr->ops->get_max_rom) + csr->max_rom = mr_map[0]; /* default value */ + else { + int i = csr->ops->get_max_rom(csr->bus_info_data, + csr->private_data); + if (i & ~0x3) + return CSR1212_EINVAL; + csr->max_rom = mr_map[i]; + } + + csr->cache_head->layout_head = csr->root_kv; + csr->cache_head->layout_tail = csr->root_kv; + + csr->root_kv->offset = (CSR1212_CONFIG_ROM_SPACE_BASE & 0xffff) + + csr->bus_info_len; + + csr->root_kv->valid = 0; + csr->root_kv->next = csr->root_kv; + csr->root_kv->prev = csr->root_kv; + csr1212_get_keyval(csr, csr->root_kv); + + /* Scan through the Root directory finding all extended ROM regions + * and make cache regions for them */ + for (dentry = csr->root_kv->value.directory.dentries_head; + dentry; dentry = dentry->next) { + if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM) { + csr1212_get_keyval(csr, dentry->kv); + + if (ret != CSR1212_SUCCESS) + return ret; + } + } + + return CSR1212_SUCCESS; +} Index: /tags/release_0_0_6/libfreebob/Makefile.am =================================================================== --- /tags/release_0_0_6/libfreebob/Makefile.am (revision 156) +++ /tags/release_0_0_6/libfreebob/Makefile.am (revision 156) @@ -0,0 +1,42 @@ +# Makefile.am - Makefile template +# Copyright (C) 2005 by Daniel Wagner. +# +# This file is part of FreeBob. +# +# FreeBob 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. +# FreeBob 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 FreeBob; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +SUBDIRS = libfreebob src tests + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libfreebob.pc + +$(srcdir)/configure: configure.ac aclocal.m4 + cd $(srcdir) && autoconf + +# autoheader might not change config.h.in, so touch a stamp file. +$(srcdir)/config.h.in: stamp-h.in +$(srcdir)/stamp-h.in: configure.ac aclocal.m4 + cd $(srcdir) && autoheader + echo timestamp > $(srcdir)/stamp-h.in + +config.h: stamp-h +stamp-h: config.h.in config.status + ./config.status + +Makefile: Makefile.am config.status + ./config.status + +config.status: configure + ./config.status --recheck + + Index: /tags/release_0_0_6/libfreebob/autogen.sh =================================================================== --- /tags/release_0_0_6/libfreebob/autogen.sh (revision 156) +++ /tags/release_0_0_6/libfreebob/autogen.sh (revision 156) @@ -0,0 +1,7 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + + +autoreconf -f -i -s +./configure --enable-maintainer-mode +make Index: /tags/release_0_0_6/libfreebob/libfreebob/xmlparser.h =================================================================== --- /tags/release_0_0_6/libfreebob/libfreebob/xmlparser.h (revision 153) +++ /tags/release_0_0_6/libfreebob/libfreebob/xmlparser.h (revision 153) @@ -0,0 +1,47 @@ +/* freebob.h + * Copyright (C) 2005 Pieter Palmers + * + * This file is part of FreeBoB + * + * 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 Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifndef XMLPARSER_H +#define XMLPARSER_H + +#include "libfreebob/freebob.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +freebob_connection_info_t* +freebob_xmlparse_get_connection_info( xmlDocPtr doc, + int node_id, + int direction ); + +freebob_supported_stream_format_info_t* +freebob_xmlparse_get_stream_formats( xmlDocPtr doc, + int node_id, + int direction ); +#ifdef __cplusplus +} +#endif + +#endif /* XMLPARSER_H */ Index: /tags/release_0_0_6/libfreebob/libfreebob/Makefile.am =================================================================== --- /tags/release_0_0_6/libfreebob/libfreebob/Makefile.am (revision 156) +++ /tags/release_0_0_6/libfreebob/libfreebob/Makefile.am (revision 156) @@ -0,0 +1,20 @@ +# Makefile.am - Makefile template +# Copyright (C) 2005 by Daniel Wagner. +# +# This file is part of FreeBob. +# +# FreeBob 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. +# FreeBob 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 FreeBob; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +libfreebobincludedir = $(includedir)/libfreebob +libfreebobinclude_HEADERS = freebob.h xmlparser.h Index: /tags/release_0_0_6/libfreebob/libfreebob/freebob.h =================================================================== --- /tags/release_0_0_6/libfreebob/libfreebob/freebob.h (revision 153) +++ /tags/release_0_0_6/libfreebob/libfreebob/freebob.h (revision 153) @@ -0,0 +1,167 @@ +/* freebob.h + * Copyright (C) 2005 Pieter Palmers + * + * This file is part of FreeBoB + * + * 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 Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifndef FREEBOB_H +#define FREEBOB_H + +#define FREEBOB_MAX_NAME_LEN 256 + +enum freebob_direction { + FREEBOB_CAPTURE = 0, + FREEBOB_PLAYBACK = 1, +}; + +typedef struct freebob_handle* freebob_handle_t; + +/* + * Buffer specification + */ +typedef struct _freebob_stream_spec freebob_stream_spec_t; +typedef struct _freebob_stream_info freebob_stream_info_t; +typedef struct _freebob_connection_spec freebob_connection_spec_t; +typedef struct _freebob_connection_info freebob_connection_info_t; +typedef struct _freebob_supported_stream_format_spec freebob_supported_stream_format_spec_t; +typedef struct _freebob_supported_stream_format_info freebob_supported_stream_format_info_t; + +/* + * Stream specification + */ +struct _freebob_stream_spec { + int location; + int position; + int format; + int type; + int destination_port; + char name[FREEBOB_MAX_NAME_LEN]; +}; + +struct _freebob_stream_info { + int nb_streams; + freebob_stream_spec_t** streams; +}; + +/* + * Connection specification + */ +struct _freebob_connection_spec { + int id; + int port; + int node; + int plug; + int dimension; /* due to the midi stuff, the dimension isn't equal */ + /* to the number of streams */ + int samplerate; /* this should be equal for all connections when */ + /* using jack. maybe not when using other api's */ + int iso_channel; + enum freebob_direction direction; + int is_master; + freebob_stream_info_t* stream_info; +}; + +/* + * topology info + */ +struct _freebob_connection_info { + int direction; + int nb_connections; + freebob_connection_spec_t** connections; +}; + +/* + * Supported stream formats + */ +struct _freebob_supported_stream_format_spec { + int samplerate; + int nb_audio_channels; + int nb_midi_channels; +}; + +struct _freebob_supported_stream_format_info { + int direction; + int nb_formats; + freebob_supported_stream_format_spec_t** formats; +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +freebob_handle_t +freebob_new_handle( int port ); + +int +freebob_destroy_handle( freebob_handle_t freebob_handle ); + +int +freebob_discover_devices( freebob_handle_t freebob_handle ); + + +freebob_connection_info_t* +freebob_get_connection_info( freebob_handle_t freebob_handle, + int node_id, + enum freebob_direction direction ); + +freebob_supported_stream_format_info_t* +freebob_get_supported_stream_format_info( freebob_handle_t freebob_handle, + int node_id, + enum freebob_direction direction ); + +void +freebob_free_connection_info( freebob_connection_info_t* connection_info ); +void +freebob_free_connection_spec( freebob_connection_spec_t* connection_spec ); +void +freebob_free_stream_info( freebob_stream_info_t* stream_info ); +void +freebob_free_stream_spec( freebob_stream_spec_t* stream_spec ); +void +freebob_free_supported_stream_format_info( freebob_supported_stream_format_info_t* stream_info ); +void +freebob_free_supported_stream_format_spec( freebob_supported_stream_format_spec_t* stream_spec ); + + + +void +freebob_print_connection_info( freebob_connection_info_t* connection_info ); +void +freebob_print_supported_stream_format_info( freebob_supported_stream_format_info_t* stream_info ); + +int freebob_node_is_valid_freebob_device(freebob_handle_t fb_handle, int node_id); +int freebob_get_nb_devices_on_bus(freebob_handle_t fb_handle); + +int freebob_get_device_node_id(freebob_handle_t fb_handle, int device_nr); +int freebob_set_samplerate(freebob_handle_t freebob_handle, int node_id, int samplerate); + +/* debug function */ +void +freebob_print_xml_description( freebob_handle_t freebob_handle, + int node_id, + enum freebob_direction direction ); + +const char* +freebob_get_version(); + +#ifdef __cplusplus +} +#endif + +#endif /* FREEBOB_H */ Index: /tags/release_0_0_6/libfreebob/libfreebob/.cvsignore =================================================================== --- /tags/release_0_0_6/libfreebob/libfreebob/.cvsignore (revision 134) +++ /tags/release_0_0_6/libfreebob/libfreebob/.cvsignore (revision 134) @@ -0,0 +1,3 @@ +.cvsignore +Makefile +Makefile.in Index: /tags/release_0_0_6/libfreebob/NEWS =================================================================== --- /tags/release_0_0_6/libfreebob/NEWS (revision 156) +++ /tags/release_0_0_6/libfreebob/NEWS (revision 156) @@ -0,0 +1,1 @@ +26.12.2005: First beta release of libfreebob called 'late x-mass gift' release. Index: /tags/release_0_0_6/libfreebob/.cvsignore =================================================================== --- /tags/release_0_0_6/libfreebob/.cvsignore (revision 134) +++ /tags/release_0_0_6/libfreebob/.cvsignore (revision 134) @@ -0,0 +1,11 @@ +.cvsignore +Makefile +Makefile.in +aclocal.m4 +autom4te.cache +config.* +configure +libfreebob.pc +libtool +stamp* +libfreebob-*.tar.gz Index: /tags/release_0_0_6/libfreebob/README =================================================================== --- /tags/release_0_0_6/libfreebob/README (revision 156) +++ /tags/release_0_0_6/libfreebob/README (revision 156) @@ -0,0 +1,503 @@ +FreeBob version 0.0.1 +===================== + +This project aims to provide a free driver implemenation for the BeBoB +platform. The BeBob is used in many available IEEE 1394 based break-out +boxes. + +This is the first beta release of libfreebob. Currently it depends +still on the old streaming backend driver from the prealpha-release 2.1. +In order to use libfreebob you need to download and install it this +special version. + +The device discovering is done completely different to the +prealpha-release version of freebob. In the old version +it is done using the descriptors. But this version has several sever +drawbacks, e.g. not every BeBoB device is supported. This implemention +now uses a some extended commands like the extended plug info command. +This allows to discover any BeBoB device. Furthermore it provides +more information and it is extremly faster... which is of course +not very important because it is only device discovering and not +streaming :) + +Dependencies +------------ + +To build libfreebob you need several libraries. For all libraries a version +is provided which is a 'known good' version (all tested with a debian testing +installation). The first few libraries it seems it is not necessary that +the version must match. The chances that it works also with an older versions +are good: + +alsa (>= 1.0.11) +libxml2 (>= 2.6.22) +libpthread (>= 2.3.5) + +These libraries here should be at least the version listed: + +libraw1394 (>= 1.2.0), http://www.linux1394.org +libiec61883 (>= 1.1.0), http://www.linux1394.org +libavc1394 (>= 0.5.1), http://sourceforge.net/projects/libavc1394 + +And finally, you need the special jackd version which uses libfreebob. +It can be downloaded from sf.net as well. + + +How to build +------------ + +Building the code is straight forward if PKG_CONFIG_PATH, LD_LIBRARY_PATH +and INCLUDE_PATH is correctly set up. + +E.g on my system I have installed libraw1394, libiec61883 and libavc1394 +under /usr/local: + +$ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig +$ export LD_LIBRARY_PATH=/usr/local/lib + +If you want to build the release version you can do following (CVS checkout) + +$ ./autogen.sh +$ make install + +If you have not a CVS checkout you can do following: + +$ ./configure +$ make +$ make install + +If you want some debug information (because something seems not +to work correctly) you can try do following (not CVS checkout): + +$ ./configure --enable-debug +$ make +$ make install + +After you have install libfreebob you can start building the +special jack version with the iec61883 backend driver which is using +libfreebob. + + +Testing +------- + +Under the tests directory there is a test program. You should first +try to run this. + +If you don't have installed libfreebob then you can adapt your +LD_LIBRARY_PATH environment variable to + +$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../src/.libs + +Then you can try running the program without having to install it. + +With the release version you see something like this (note that you +have to provide the correct node id, in this example '-n 0'): + +wagi@cruxam:~/src/libfreebob/tests$ ./test-freebob -n 0 discover +Using freebob library version: libfreebob 0.0.1 + +Direction: 0 (capture) + +Connection Info +=============== + +Number of connections: 1 + + Connection 0 + ------------- + [ 0] Id: 0 + [ 0] Port: 0 + [ 0] Node: 0 + [ 0] Plug: 0 + [ 0] Dimension: 7 + [ 0] Samplerate: 48000 + [ 0] Number of stream infos: 7 + + StreamId Position Location Format Type DPort Name + -------------------------------------------------- + [ 0]:[ 0] 0x01 0x01 0x06 0x03 0x00 LineOut 1+2 left + [ 0]:[ 1] 0x04 0x02 0x06 0x03 0x00 LineOut 1+2 right + [ 0]:[ 2] 0x02 0x01 0x06 0x03 0x00 LineOut 3+4 left + [ 0]:[ 3] 0x05 0x02 0x06 0x03 0x00 LineOut 3+4 right + [ 0]:[ 4] 0x00 0x01 0x06 0x04 0x00 SpdifOut left + [ 0]:[ 5] 0x03 0x02 0x06 0x04 0x00 SpdifOut right + [ 0]:[ 6] 0x06 0x01 0x0d 0x0a 0x00 MidiPort_1 + + +Direction: 1 (playback) + +Connection Info +=============== + +Number of connections: 1 + + Connection 0 + ------------- + [ 0] Id: 0 + [ 0] Port: 0 + [ 0] Node: 0 + [ 0] Plug: 0 + [ 0] Dimension: 7 + [ 0] Samplerate: 48000 + [ 0] Number of stream infos: 7 + + StreamId Position Location Format Type DPort Name + -------------------------------------------------- + [ 0]:[ 0] 0x01 0x01 0x06 0x02 0x00 MicIn1 left + [ 0]:[ 1] 0x04 0x02 0x06 0x02 0x00 MicIn1 right + [ 0]:[ 2] 0x02 0x01 0x06 0x03 0x00 LineIn 3+4 left + [ 0]:[ 3] 0x05 0x02 0x06 0x03 0x00 LineIn 3+4 right + [ 0]:[ 4] 0x00 0x01 0x06 0x04 0x00 SpdifIn left + [ 0]:[ 5] 0x03 0x02 0x06 0x04 0x00 SpdifIn right + [ 0]:[ 6] 0x06 0x01 0x0d 0x0a 0x00 MidiPort_1 + + +To impress friends you need of course to use the debug version +which looks like this: + +wagi@cruxam:~/src/libfreebob/tests$ ./test-freebob -n 0 discover +Using freebob library version: libfreebob 0.0.1 + +Debug (avdevice.cpp)[47] AvDevice: Found AvDevice (NodeID 0) +Debug (avdevice.cpp)[1262] enumerateSubUnits: subunit_id = 0, subunit_type = 1 (Audio), max_subunit_ID = 0 +Debug (avdevice.cpp)[1262] enumerateSubUnits: subunit_id = 0, subunit_type = 12 (Music), max_subunit_ID = 0 +Debug (avdevice.cpp)[169] discoverStep1: number of iso input plugs = 2, number of iso output plugs = 2 +Debug (avdevice.cpp)[214] discoverStep2: number of output plugs is 1 for iso input plug 0 +Debug (avdevice.cpp)[251] discoverStep2: output plug 0 is owned by subunit_type 12, subunit_id = 0 +Debug (avdevice.cpp)[1203] discoverPlugConnection: IsoStreamInput plug 0 has a valid connection to plug 0 of MusicSubunit subunit 0 +Debug (avdevice.cpp)[214] discoverStep2: number of output plugs is 0 for iso input plug 1 +Debug (avdevice.cpp)[339] discoverStep3: output plug 0 is owned by subunit_type 12, subunit_id 0 +Debug (avdevice.cpp)[1203] discoverPlugConnection: IsoStreamOutput plug 0 has a valid connection to plug 0 of MusicSubunit subunit 0 +Debug (avdevice.cpp)[339] discoverStep3: output plug 5 is owned by subunit_type 12, subunit_id 0 +Debug (avdevice.cpp)[1203] discoverPlugConnection: IsoStreamOutput plug 1 has a valid connection to plug 5 of MusicSubunit subunit 0 +Debug (avdevice.cpp)[416] discoverStep4: iso input plug 0 is of type 0 (IsoStream) +Debug (avdevice.cpp)[383] discoverStep4: iso input plug 1 has no valid connecton -> skip +Debug (avdevice.cpp)[465] discoverStep4: iso output plug 0 is of type 0 (IsoStream) +Debug (avdevice.cpp)[465] discoverStep4: iso output plug 1 is of type 3 (Sync) +Debug (avdevice.cpp)[524] discoverStep5: iso input plug 0 has 7 channels +Debug (avdevice.cpp)[491] discoverStep5: iso input plug 1 has no valid connecton -> skip +Debug (avdevice.cpp)[573] discoverStep5: iso output plug 0 has 7 channels +Debug (avdevice.cpp)[573] discoverStep5: iso output plug 1 has 2 channels +Debug (avdevice.cpp)[636] discoverStep6: iso input plug 0: channel position information retrieved +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 2 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 2 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 5 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 2 +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 2 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 3 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 6 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 2 +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 2 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 1 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 4 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 2 +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 7 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avdevice.cpp)[598] discoverStep6: iso input plug 1 has no valid connecton -> skip +Debug (avdevice.cpp)[690] discoverStep6: iso output plug 0: channel position information retrieved +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 2 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 2 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 5 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 2 +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 2 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 3 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 6 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 2 +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 2 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 1 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 4 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 2 +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 7 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avdevice.cpp)[690] discoverStep6: iso output plug 1: channel position information retrieved +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 2 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 1 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 2 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 2 +Debug (avdevice.cpp)[767] discoverStep7: iso input plug 0 stream position 2: channel name = LineOut 1+2 left +Debug (avdevice.cpp)[767] discoverStep7: iso input plug 0 stream position 5: channel name = LineOut 1+2 right +Debug (avdevice.cpp)[767] discoverStep7: iso input plug 0 stream position 3: channel name = LineOut 3+4 left +Debug (avdevice.cpp)[767] discoverStep7: iso input plug 0 stream position 6: channel name = LineOut 3+4 right +Debug (avdevice.cpp)[767] discoverStep7: iso input plug 0 stream position 1: channel name = SpdifOut left +Debug (avdevice.cpp)[767] discoverStep7: iso input plug 0 stream position 4: channel name = SpdifOut right +Debug (avdevice.cpp)[767] discoverStep7: iso input plug 0 stream position 7: channel name = MidiPort_1 +Debug (avdevice.cpp)[716] discoverStep7: iso input plug 1 has no valid connecton -> skip +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 0 stream position 2: channel name = MicIn1 left +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 0 stream position 5: channel name = MicIn1 right +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 0 stream position 3: channel name = LineIn 3+4 left +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 0 stream position 6: channel name = LineIn 3+4 right +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 0 stream position 1: channel name = SpdifIn left +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 0 stream position 4: channel name = SpdifIn right +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 0 stream position 7: channel name = MidiPort_1 +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 1 stream position 1: channel name = SynchChannel1 +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 1 stream position 2: channel name = SynchChannel2 +Debug (avdevice.cpp)[910] discoverStep8: iso input plug 0: cluster index = 1, portType Line, cluster name = LineOut 1+2 +Debug (avdevice.cpp)[910] discoverStep8: iso input plug 0: cluster index = 2, portType Line, cluster name = LineOut 3+4 +Debug (avdevice.cpp)[910] discoverStep8: iso input plug 0: cluster index = 3, portType SPDIF, cluster name = SpdifOut +Debug (avdevice.cpp)[910] discoverStep8: iso input plug 0: cluster index = 4, portType MIDI, cluster name = MidiSection.0 +Debug (avdevice.cpp)[866] discoverStep8: iso input plug 1 has no valid connecton -> skip +Debug (avdevice.cpp)[980] discoverStep8: iso output plug 0: cluster index = 1, portType Microphone, cluster name = MicIn1 +Debug (avdevice.cpp)[980] discoverStep8: iso output plug 0: cluster index = 2, portType Line, cluster name = LineIn 3+4 +Debug (avdevice.cpp)[980] discoverStep8: iso output plug 0: cluster index = 3, portType SPDIF, cluster name = SpdifIn +Debug (avdevice.cpp)[980] discoverStep8: iso output plug 0: cluster index = 4, portType MIDI, cluster name = MidiSection.0 +Warning (avdevice.cpp)[936] discoverStep8: Skipping plugs with id > 0. Further investigation needed +Debug (avdevice.cpp)[1040] discoverStep9: discoverStep9: iso input plug 0 uses sampling frequency 4 +Debug (avdevice.cpp)[1070] discoverStep9: iso input plug 0 cluster info 1: stream format 6 +Debug (avdevice.cpp)[1070] discoverStep9: iso input plug 0 cluster info 2: stream format 6 +Debug (avdevice.cpp)[1070] discoverStep9: iso input plug 0 cluster info 3: stream format 6 +Debug (avdevice.cpp)[1070] discoverStep9: iso input plug 0 cluster info 4: stream format 13 +Debug (avdevice.cpp)[1008] discoverStep9: iso input plug 1 has no valid connecton -> skip +Debug (avdevice.cpp)[1134] discoverStep9: discoverStep9: iso output plug 0 uses sampling frequency 4 +Debug (avdevice.cpp)[1164] discoverStep9: iso output plug 0 cluster info 1: stream format 6 +Debug (avdevice.cpp)[1164] discoverStep9: iso output plug 0 cluster info 2: stream format 6 +Debug (avdevice.cpp)[1164] discoverStep9: iso output plug 0 cluster info 3: stream format 6 +Debug (avdevice.cpp)[1164] discoverStep9: iso output plug 0 cluster info 4: stream format 13 +Debug (avdevice.cpp)[1177] discoverStep9: iso output plug 1 is sync stream with sampling frequency 4 +Direction: 0 (capture) + +Connection Info +=============== + +Number of connections: 1 + + Connection 0 + ------------- + [ 0] Id: 0 + [ 0] Port: 0 + [ 0] Node: 0 + [ 0] Plug: 0 + [ 0] Dimension: 7 + [ 0] Samplerate: 48000 + [ 0] Number of stream infos: 7 + + StreamId Position Location Format Type DPort Name + -------------------------------------------------- + [ 0]:[ 0] 0x01 0x01 0x06 0x03 0x00 LineOut 1+2 left + [ 0]:[ 1] 0x04 0x02 0x06 0x03 0x00 LineOut 1+2 right + [ 0]:[ 2] 0x02 0x01 0x06 0x03 0x00 LineOut 3+4 left + [ 0]:[ 3] 0x05 0x02 0x06 0x03 0x00 LineOut 3+4 right + [ 0]:[ 4] 0x00 0x01 0x06 0x04 0x00 SpdifOut left + [ 0]:[ 5] 0x03 0x02 0x06 0x04 0x00 SpdifOut right + [ 0]:[ 6] 0x06 0x01 0x0d 0x0a 0x00 MidiPort_1 + + +Direction: 1 (playback) + +Connection Info +=============== + +Number of connections: 1 + + Connection 0 + ------------- + [ 0] Id: 0 + [ 0] Port: 0 + [ 0] Node: 0 + [ 0] Plug: 0 + [ 0] Dimension: 7 + [ 0] Samplerate: 48000 + [ 0] Number of stream infos: 7 + + StreamId Position Location Format Type DPort Name + -------------------------------------------------- + [ 0]:[ 0] 0x01 0x01 0x06 0x02 0x00 MicIn1 left + [ 0]:[ 1] 0x04 0x02 0x06 0x02 0x00 MicIn1 right + [ 0]:[ 2] 0x02 0x01 0x06 0x03 0x00 LineIn 3+4 left + [ 0]:[ 3] 0x05 0x02 0x06 0x03 0x00 LineIn 3+4 right + [ 0]:[ 4] 0x00 0x01 0x06 0x04 0x00 SpdifIn left + [ 0]:[ 5] 0x03 0x02 0x06 0x04 0x00 SpdifIn right + [ 0]:[ 6] 0x06 0x01 0x0d 0x0a 0x00 MidiPort_1 + + +Running jackd +------------- + +In order to get it running you need to provide some arguments to +jackd, e.g. + +$ jackd -d iec61883 -n 1 -d 0 -p 512 -b 1000 -b 1000 -i 20 -r 8192 + +Note that '-n' most be addapted to your local 1394 bus configuraiton. +This is the node number of the device. + +On my screen I get: + +wagi@cruxam:~/src/jack-audio-connection-kit+freebob-0.100.0$ jackd -d iec61883 -n 1 -d 0 -p 512 -b 1000 -b 1000 -i 20 -r 8192 +jackd 0.100.0 +Copyright 2001-2005 Paul Davis and others. +jackd comes with ABSOLUTELY NO WARRANTY +This is free software, and you are welcome to redistribute it +under certain conditions; see the file COPYING for details + +JACK compiled with System V SHM support. +loading driver .. +IEC61883: Using libfreebob version libfreebob 0.0.1 +Debug (avdevice.cpp)[47] AvDevice: Found AvDevice (NodeID 1) +Debug (avdevice.cpp)[1262] enumerateSubUnits: subunit_id = 0, subunit_type = 1 (Audio), max_subunit_ID = 0 +Debug (avdevice.cpp)[1262] enumerateSubUnits: subunit_id = 0, subunit_type = 12 (Music), max_subunit_ID = 0 +Debug (avdevice.cpp)[169] discoverStep1: number of iso input plugs = 2, number of iso output plugs = 2 +Debug (avdevice.cpp)[214] discoverStep2: number of output plugs is 1 for iso input plug 0 +Debug (avdevice.cpp)[251] discoverStep2: output plug 0 is owned by subunit_type 12, subunit_id = 0 +Debug (avdevice.cpp)[1203] discoverPlugConnection: IsoStreamInput plug 0 has a valid connection to plug 0 of MusicSubunit subunit 0 +Debug (avdevice.cpp)[214] discoverStep2: number of output plugs is 0 for iso input plug 1 +Debug (avdevice.cpp)[339] discoverStep3: output plug 0 is owned by subunit_type 12, subunit_id 0 +Debug (avdevice.cpp)[1203] discoverPlugConnection: IsoStreamOutput plug 0 has a valid connection to plug 0 of MusicSubunit subunit 0 +Debug (avdevice.cpp)[339] discoverStep3: output plug 5 is owned by subunit_type 12, subunit_id 0 +Debug (avdevice.cpp)[1203] discoverPlugConnection: IsoStreamOutput plug 1 has a valid connection to plug 5 of MusicSubunit subunit 0 +Debug (avdevice.cpp)[416] discoverStep4: iso input plug 0 is of type 0 (IsoStream) +Debug (avdevice.cpp)[383] discoverStep4: iso input plug 1 has no valid connecton -> skip +Debug (avdevice.cpp)[465] discoverStep4: iso output plug 0 is of type 0 (IsoStream) +Debug (avdevice.cpp)[465] discoverStep4: iso output plug 1 is of type 3 (Sync) +Debug (avdevice.cpp)[524] discoverStep5: iso input plug 0 has 7 channels +Debug (avdevice.cpp)[491] discoverStep5: iso input plug 1 has no valid connecton -> skip +Debug (avdevice.cpp)[573] discoverStep5: iso output plug 0 has 7 channels +Debug (avdevice.cpp)[573] discoverStep5: iso output plug 1 has 2 channels +Debug (avdevice.cpp)[636] discoverStep6: iso input plug 0: channel position information retrieved +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 2 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 2 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 5 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 2 +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 2 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 3 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 6 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 2 +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 2 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 1 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 4 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 2 +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 7 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avdevice.cpp)[598] discoverStep6: iso input plug 1 has no valid connecton -> skip +Debug (avdevice.cpp)[690] discoverStep6: iso output plug 0: channel position information retrieved +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 2 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 2 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 5 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 2 +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 2 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 3 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 6 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 2 +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 2 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 1 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 4 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 2 +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 7 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avdevice.cpp)[690] discoverStep6: iso output plug 1: channel position information retrieved +Debug (avplug.cpp)[105] debugOutputClusterInfos: number of channels: 2 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 1 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 1 +Debug (avplug.cpp)[115] debugOutputClusterInfos: stream position: 2 +Debug (avplug.cpp)[118] debugOutputClusterInfos: location: 2 +Debug (avdevice.cpp)[767] discoverStep7: iso input plug 0 stream position 2: channel name = LineOut 1+2 left +Debug (avdevice.cpp)[767] discoverStep7: iso input plug 0 stream position 5: channel name = LineOut 1+2 right +Debug (avdevice.cpp)[767] discoverStep7: iso input plug 0 stream position 3: channel name = LineOut 3+4 left +Debug (avdevice.cpp)[767] discoverStep7: iso input plug 0 stream position 6: channel name = LineOut 3+4 right +Debug (avdevice.cpp)[767] discoverStep7: iso input plug 0 stream position 1: channel name = SpdifOut left +Debug (avdevice.cpp)[767] discoverStep7: iso input plug 0 stream position 4: channel name = SpdifOut right +Debug (avdevice.cpp)[767] discoverStep7: iso input plug 0 stream position 7: channel name = MidiPort_1 +Debug (avdevice.cpp)[716] discoverStep7: iso input plug 1 has no valid connecton -> skip +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 0 stream position 2: channel name = MicIn1 left +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 0 stream position 5: channel name = MicIn1 right +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 0 stream position 3: channel name = LineIn 3+4 left +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 0 stream position 6: channel name = LineIn 3+4 right +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 0 stream position 1: channel name = SpdifIn left +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 0 stream position 4: channel name = SpdifIn right +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 0 stream position 7: channel name = MidiPort_1 +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 1 stream position 1: channel name = SynchChannel1 +Debug (avdevice.cpp)[838] discoverStep7: iso output plug 1 stream position 2: channel name = SynchChannel2 +Debug (avdevice.cpp)[910] discoverStep8: iso input plug 0: cluster index = 1, portType Line, cluster name = LineOut 1+2 +Debug (avdevice.cpp)[910] discoverStep8: iso input plug 0: cluster index = 2, portType Line, cluster name = LineOut 3+4 +Debug (avdevice.cpp)[910] discoverStep8: iso input plug 0: cluster index = 3, portType SPDIF, cluster name = SpdifOut +Debug (avdevice.cpp)[910] discoverStep8: iso input plug 0: cluster index = 4, portType MIDI, cluster name = MidiSection.0 +Debug (avdevice.cpp)[866] discoverStep8: iso input plug 1 has no valid connecton -> skip +Debug (avdevice.cpp)[980] discoverStep8: iso output plug 0: cluster index = 1, portType Microphone, cluster name = MicIn1 +Debug (avdevice.cpp)[980] discoverStep8: iso output plug 0: cluster index = 2, portType Line, cluster name = LineIn 3+4 +Debug (avdevice.cpp)[980] discoverStep8: iso output plug 0: cluster index = 3, portType SPDIF, cluster name = SpdifIn +Debug (avdevice.cpp)[980] discoverStep8: iso output plug 0: cluster index = 4, portType MIDI, cluster name = MidiSection.0 +Warning (avdevice.cpp)[936] discoverStep8: Skipping plugs with id > 0. Further investigation needed +Debug (avdevice.cpp)[1040] discoverStep9: discoverStep9: iso input plug 0 uses sampling frequency 4 +Debug (avdevice.cpp)[1070] discoverStep9: iso input plug 0 cluster info 1: stream format 6 +Debug (avdevice.cpp)[1070] discoverStep9: iso input plug 0 cluster info 2: stream format 6 +Debug (avdevice.cpp)[1070] discoverStep9: iso input plug 0 cluster info 3: stream format 6 +Debug (avdevice.cpp)[1070] discoverStep9: iso input plug 0 cluster info 4: stream format 13 +Debug (avdevice.cpp)[1008] discoverStep9: iso input plug 1 has no valid connecton -> skip +Debug (avdevice.cpp)[1134] discoverStep9: discoverStep9: iso output plug 0 uses sampling frequency 4 +Debug (avdevice.cpp)[1164] discoverStep9: iso output plug 0 cluster info 1: stream format 6 +Debug (avdevice.cpp)[1164] discoverStep9: iso output plug 0 cluster info 2: stream format 6 +Debug (avdevice.cpp)[1164] discoverStep9: iso output plug 0 cluster info 3: stream format 6 +Debug (avdevice.cpp)[1164] discoverStep9: iso output plug 0 cluster info 4: stream format 13 +Debug (avdevice.cpp)[1177] discoverStep9: iso output plug 1 is sync stream with sampling frequency 4 +IEC61883: Adding 1 capture connection(s)... +IEC61883: capture connection 0: 0 streams, dim 1 from (0,7,7) +IEC61883: adding stream 0: (1,1) 0x06 0x03 -> 0 (LineOut 1+2 left) +IEC61883: adding stream 1: (4,2) 0x06 0x03 -> 0 (LineOut 1+2 right) +IEC61883: adding stream 2: (2,1) 0x06 0x03 -> 0 (LineOut 3+4 left) +IEC61883: adding stream 3: (5,2) 0x06 0x03 -> 0 (LineOut 3+4 right) +IEC61883: adding stream 4: (0,1) 0x06 0x04 -> 0 (SpdifOut left) +IEC61883: adding stream 5: (3,2) 0x06 0x04 -> 0 (SpdifOut right) +IEC61883: adding stream 6: (6,1) 0x0D 0x0A -> 0 (MidiPort_1) +IEC61883: Adding 1 playback connection(s)... +IEC61883: playback connection 0: 0 streams, dim 1 to (0,7,7) +IEC61883: adding stream 0: (1,1) 0x06 0x02 -> 0 (MicIn1 left) +IEC61883: adding stream 1: (4,2) 0x06 0x02 -> 0 (MicIn1 right) +IEC61883: adding stream 2: (2,1) 0x06 0x03 -> 0 (LineIn 3+4 left) +IEC61883: adding stream 3: (5,2) 0x06 0x03 -> 0 (LineIn 3+4 right) +IEC61883: adding stream 4: (0,1) 0x06 0x04 -> 0 (SpdifIn left) +IEC61883: adding stream 5: (3,2) 0x06 0x04 -> 0 (SpdifIn right) +IEC61883: adding stream 6: (6,1) 0x0D 0x0A -> 0 (MidiPort_1) +IEC61883D: Creating driver (period_size=512, ringbuffer_size=8192) +Creating IEC61883 client... 512/8192/48000 + poll timeout = 10 ms +Creating 7 buffers of 8192 quadlets... +IEC61883C: Creating playback connection from node 65473, plug 0 + prebuffers=0, buffers=1000, irq_interval=20 +Creating 7 buffers of 8192 quadlets... +IEC61883 Client created... +IEC61883CM: registered jack port cap_0_1_0_LineOut 1+2 left +IEC61883CM: registered jack port cap_0_1_0_LineOut 1+2 right +IEC61883CM: registered jack port cap_0_1_0_LineOut 3+4 left +IEC61883CM: registered jack port cap_0_1_0_LineOut 3+4 right +IEC61883CM: registered jack port cap_0_1_0_SpdifOut left +IEC61883CM: registered jack port cap_0_1_0_SpdifOut right +IEC61883CM: registered midi port MidiIn_0_1_0_MidiPort_1_1 as 128:0 +IEC61883CM: registered jack port pbk_0_1_0_MicIn1 left +IEC61883CM: registered jack port pbk_0_1_0_MicIn1 right +IEC61883CM: registered jack port pbk_0_1_0_LineIn 3+4 left +IEC61883CM: registered jack port pbk_0_1_0_LineIn 3+4 right +IEC61883CM: registered jack port pbk_0_1_0_SpdifIn left +IEC61883CM: registered jack port pbk_0_1_0_SpdifIn right +IEC61883CM: registered midi port MidiOut_0_1_0_MidiPort_1_1 as 128:1 +Client start... + creating capture connections... +libiec61883 warning: Established connection on channel 0. +You may need to manually set the channel on the receiving node. +Init ISO master receive handler on channel 0... + (BUFFER=1000,PACKET_MAX=2048,IRQ=20)... +Start ISO master receive... + creating playback connections... +libiec61883 warning: Established connection on channel 1. +You may need to manually set the channel on the transmitting node. +Init ISO slave transmit handler on channel 1... + other mode (BUFFER=1000,PACKET_MAX=2048,IRQ=20)... +Start ISO slave transmit... PREBUFFER=0 + -> 2618k Packets, Bufferfill (I: 512, O: 0), Packets dropped (I: 0, O: 11), XRUNS ( 0)(1, 8/0) +