[ag-automation] FDDI Progress

Robert Schwebel r.schwebel at pengutronix.de
Wed May 30 21:30:57 CEST 2007


On Tue, May 29, 2007 at 10:04:23AM +0200, Dieter Hess wrote:
> The header contains all data types and all functions of the fddi.

See my comments below. Btw, it would be better to post these things
inline, because it makes quoting & review easier.

For the final header files we should make sure the lines are smaller
than 80 characters.

> The following things are planned to be delivered in the next few days:
> 
> - an implementation proposal for the fddi
> - a definition of configuration profile for a field bus protocol
>   (which should we use as a first example? We at 3S have definitions for
>   CANopen, Profibus, EtherCat and SERCOS III)

Some use cases would also be a good thing, just to get the picture how
these things are supposte to work.

> /* fieldbus device driver interface */

Header files should clearly state a license; I'd suggest LGPL or BSD, to
make proprietary and oss programs possible.

> /* #include "lldi.h" */
> typedef void *LL_INTERFACE;
> 
> /* result codes */

Please use the normal errno return values, which would be ...

#define RESOK 0					0 (no need to define something here)
#define RESERR_INTERFACE_ALREADY_REGISTERD 1	EBUSY
#define RESERR_LLINTERFACE_ALREADY_IN_USE 2	EBUSY
#define RESERR_LLINTERFACE_HAS_WRONG_TYPE 3	?
#define RESERR_OUT_OF_MEM 4			ENOMEM
#define RESERR_TIMEOUT 5			ETIMEDOUT
#define RESERR_NO_ACCESS 6			EACC
#define RESERR_BUFFER_TO_SMALL 7		ENOBUFS
#define RESERR_WRONGTPUTYPE 8			?

> /* io-interface */
> struct _io_interface

Why the underscore?

> {
> 	char* name;				/* name of the interface */
> 	unsigned long version;	/* version of the interface */
> 
> 	int (*_fptr_bind_io_interface)(char* name, LL_INTERFACE llitf, struct _io_interface_inst **result);
> 	/* function pointer of the bind_io_interface method (see bind_io_interface for further information) */
> 	int (*_fptr_configure_io_interface_inst)(struct _io_interface_inst *itfinst, struct _io_device *root);
> 	/* function pointer of the configure_io_interface_inst method (see configure_io_interface for further information) */
> 	int (*_fptr_scan_io_interface_inst)(struct _io_interface_inst *itfinst, struct _io_device **root);
> 	/* function pointer of the scan_io_interface_inst method (see scan_io_interface_inst for further information) */
> };

Uuuh, just taking the style into account, what about

struct _io_interface
{
	char* name;
	unsigned long version;

	int (*bind)(char *name, LL_INTERFACE llitf, struct io_interface_inst **result);
	int (*configure)(struct _io_interface_inst *itfinst, struct _io_device *root);
	int (*scan)(struct _io_interface_inst *itfinst, struct _io_device **root);
};

You get the picture. There is no need to prefix functions with type
hints; if we design this API in a typesafe way, the compiler is much
better in checking the right types than the programmer. And don't add
unnecessary comments: everyone sees that it's a function pointer, and
it's obvious where to look for it's description. It just makes the code
less readable.

I don't comment the functions here, because that's probably better when
we have some use cases / test programs.

> typedef struct _io_interface *IO_INTERFACE;

Only macros should be upper case.

> /* instance of io-interface */
> struct _io_interface_inst
> {
> 	char* name;			/* name of the io-interface-instance */
> 	IO_INTERFACE ioitf;	/* the type of the io-interface */
> 	LL_INTERFACE llitf;	/* the low level interface, to which the io-interface is bound to */
> 
> 	struct _io_device *root; /* root device, set during configuration */
> 
> 	int num_tpus;		/* number of io-transport units (set after configuration) */
> 	struct _io_transport_units *tpus; /* list of io-transport units (set after configuration) */
> 
> 	void* inst_data;	/* type specific management data */
> };
> 
> typedef struct _io_interface_inst *IO_INTERFACE_INST;
> 
> 
> /* io-device */
> enum _io_device_state
> {
> 	DEVSTATE_VOID,				/* the device is not configured */
> 	DEVSTATE_MISSING,			/* the configuration of the device failed, because it is missing */ 
> 	DEVSTATE_CONFIG_ERROR,		/* the configuration of the device failed, because of wrong config data */ 
> 	DEVSTATE_PREOPERATIONAL,	/* the device is configured, but not working */
> 	DEVSTATE_OPERATIONAL,		/* the device is working */
> 	DEVSTATE_OPERATION_ERROR	/* the device encountered an error, while it is working */
> };
> 
> typedef enum _io_device_state IO_DEVICE_STATE;
> 
> enum _io_device_command
> {
> 	DEVCMD_START,		/* start the device */
> 	DEVCMD_STOP,		/* stop the device */ 
> 	DEVCMD_RESET,		/* reset the device */ 
> 	DEVCMD_IDENTIFY,	/* let the device do something to identify itself (like blinking with a LED) */
> 	DEVCMD_QUITERR		/* quit an error of the device, to return to normal operation */
> };
> 
> typedef enum _io_device_command IO_DEVICE_COMMAND;
> /* use this datatype with the function cmd_iodevice */
> 
> struct _io_device_param
> {
> 	unsigned long key;
> 	unsigned long value;
> 	unsigned short flags;
> };
> 
> #define PARAMFLAG_PTR  0	 /* value contains a pointer to a struct (frist word of the struct is size) */
> #define PARAMFLAG_BYTE 1	 /* value contais a byte */
> #define PARAMFLAG_WORD 2	 /* value contains a word */
> #define PARAMFLAG_LONG 3	 /* value contains a double word */
> #define PARAMFLAG_TYPEMASK 3 /* value contains a double word */
> #define PARAMFLAG_DEFAULT 4  /* value contains a device default parameter. the parameter is used to set up the configuration,
>                               * but need not to be sent to the device

Why no enum here? It makes these constants compile time type safe.

> typedef struct _io_device_param IO_DEVICE_PARAM;
> 
> struct _io_device
> {
> 	IO_INTERFACE_INST itfinst;	/* reference to owning io-interface instance (set by fddi) */
> 
> 	unsigned long physical_id;	/* physical id of the device */
> 	unsigned long logical_id;	/* logical id of the device */
> 	unsigned long type_id;		/* type id of the device */
> 	char* name;					/* optional name of the device (from configuration) */
> 	
> 	int num_params;				/* number of parameters */
> 	IO_DEVICE_PARAM* params;	/* pointer to list of parameters */
> 
> 	struct _io_device* parent;  /* parent device */
> 	struct _io_device* first_child; /* first child device of this device */
> 	struct _io_device* next_child;/* next child of the same parent */
> 
> 	IO_DEVICE_STATE state;		/* state of the device */   
> };
> 
> typedef struct _io_device *IO_DEVICE;
> 
> 
> /* io-transport unit */
> struct _io_transport_unit
> {
> 	IO_INTERFACE_INST itfinst;	/* reference to owning io-interface instance (set by fddi) */
> 
> 	unsigned long  id;
> 	unsigned long  time_stamp;
> 	unsigned long  flags;
> 	unsigned long  size;
> 	unsigned char* buf_read;
> 	unsigned char* buf_write;
> };
> 
> #define TPUFLAG_IN		1	/* application reads from this transport unit */
> #define TPUFLAG_OUT		2	/* application writes to this transport unit */
> #define TPUFLAG_SYNC	4	/* this transport unit synchronizes a group of io-devices */
> #define TPUFLAG_EXTMEM	8	/* the memory of this transport unit is not maintained by the fddi */
> #define TPUFLAG_CONSIST	16	/* the memory of this transport unit is kept consistent by the fddi (cannot be used with TPUFLAG_EXTMEM) */

Same here, why no enum?

> typedef struct _io_transport_unit *IO_TRANSPORT_UNIT;
> 
> 
> /* io-variable */
> struct _io_variable
> {
> 	char* name;				/* optional name of the variable */
> 	unsigned long size;		/* size of the variable */
> 	unsigned long offset;	/* offset of the variable in io-transport unit */
> 
> 	IO_TRANSPORT_UNIT iotpu;/* reference to io-transport unit */
> 	IO_DEVICE iodev;		/* reference to io-device */
> };
> 
> typedef struct _io_variable *IO_VARIABLE;

[...]

> /* functions of the fddi */
> int register_io_interface(IO_INTERFACE ioitf);
> 	/* registers a new io-interface to the fddi layer (for example a CANopen stack)
> 	*  
> 	*  ioitf:	[in] the definition of the new interface
> 	*
> 	*  result:	RESOK, RESERR_INTERFACE_ALREADY_REGISTERD, RESERR_OUT_OF_MEM 
> 	*
> 	*  remarks:	this function is only called by the module which implements his own driver
> 	*			it need not to be called by users of an existiong driver
> 	*/

For API documentation, please use docbook style.

More comments when we've seen some test code.

Robert
-- 
 Dipl.-Ing. Robert Schwebel | http://www.pengutronix.de
 Pengutronix - Linux Solutions for Science and Industry
   Handelsregister:  Amtsgericht Hildesheim, HRA 2686
     Hannoversche Str. 2, 31134 Hildesheim, Germany
   Phone: +49-5121-206917-0 |  Fax: +49-5121-206917-9



More information about the ag-automation mailing list