Index: demos/inputinfo.c
===================================================================
RCS file: /cvsroot/ggi/ggi-core/libgii/demos/inputinfo.c,v
retrieving revision 1.13
diff -u -p -r1.13 inputinfo.c
--- demos/inputinfo.c	14 Oct 2006 08:43:58 -0000	1.13
+++ demos/inputinfo.c	27 Dec 2006 22:05:27 -0000
@@ -702,49 +702,92 @@ static void show_event(gii_event *ev)
 	fflush(stdout);
 }
 
+static void iter_devices(void)
+{
+	struct gii_source_iter src_iter;
+	struct gii_device_iter dev_iter;
+	uint32_t src_origin, dev_origin;
+	struct gii_cmddata_devinfo *DI;
+
+	src_iter.stem = inp;
+	giiIterSource(&src_iter);
+	GG_ITER_FOREACH(&src_iter) {
+		src_origin = src_iter.origin;
+
+		dev_iter.stem = inp;
+		dev_iter.src = src_iter.src;
+
+		printf("source  origin %u  ptr %p\n", src_origin, src_iter.src);
+		giiIterDevice(&dev_iter);
+		GG_ITER_FOREACH(&dev_iter) {
+			dev_origin = dev_iter.origin;
+			DI = &dev_iter.devinfo;
+
+			printf("  device origin %u\n", dev_origin);
+			printf("    devinfo  deviceName=\"%s\" vendorId=%x productId=%x numRegisters=%d\n"
+			       "             buttons=%d valuators=%d generate=0x%06x\n",
+			       DI->devname, DI->vendor_id, DI->product_id, DI->num_registers,
+			       DI->num_buttons, DI->num_valuators,
+			       DI->can_generate);
+		}
+		GG_ITER_DONE(&dev_iter);
+	}
+	GG_ITER_DONE(&src_iter);
+}
+
 int main(int ac, char** av)
 {
-	int i, n, dump, quit, max;
+	int i, n, dump, iter, quit, max;
 	gii_event ev;
 	
 	max  = 100;
 	dump = 0;
+	iter = 0;
 	quit = 0;
-	for(i=1;i<ac;i++) {
-		if(!strcmp(av[i], "-help")) {
+	for (i = 1; i < ac; i++) {
+		if (!strcmp(av[i], "-help")) {
 			printf("usage: %s [-dump] [-exit]\n"
 			       "  -help:  show this message and exit\n"
 			       "  -dump:  display input's internal state once opened\n"
+			       "  -iter:  iterate and show all input sources/devices found\n"
 			       "  -exit:  exit immediatly, do not poll for events\n", av[0]);
 			return 0;
 		}
-		if(!strcmp(av[i], "-dump")) {
+		if (!strcmp(av[i], "-dump")) {
 			dump = 1;
 		}
-		if(!strcmp(av[i], "-exit")) {
+		if (!strcmp(av[i], "-iter")) {
+			iter = 1;
+		}
+		if (!strcmp(av[i], "-exit")) {
 			quit = 1;
 		}
 	}
 	
 	/* open default input */
 	
-	if((inp = ggNewStem(libgii, NULL)) == NULL)
+	if ((inp = ggNewStem(libgii, NULL)) == NULL)
 		ggPanic("Couldn't create new stem with libgii\n");
 		
-	if(giiOpen(inp, NULL, NULL) <= 0)
+	if (giiOpen(inp, NULL, NULL) <= 0)
 		ggPanic("Couldn't open default input\n");
 	
 	if (dump) {
 		/* show internal input state*/
 		ggDumpStem(libgii, inp);
 	}
+
+	if (iter) {
+		/* iterate over input sources/devices */
+		iter_devices();
+	}
 	
 	/* The input target sends device infos
 	 * about all available devices at opening time.
 	 * So we just read them here and that's it.
 	 */
 	if (!quit)
-		for (i=0;i<max;i++) {
+		for (i = 0; i < max; i++) {
 			giiEventPoll(inp, emAll, NULL);
 			n = giiEventsQueued(inp, emAll);
 			if (n == 0) break;
Index: gii/EXPSYMS
===================================================================
RCS file: /cvsroot/ggi/ggi-core/libgii/gii/EXPSYMS,v
retrieving revision 1.9
diff -u -p -r1.9 EXPSYMS
--- gii/EXPSYMS	20 Mar 2006 09:06:20 -0000	1.9
+++ gii/EXPSYMS	27 Dec 2006 22:05:27 -0000
@@ -12,6 +12,8 @@ giiEventsQueued
 giiExit
 giiGetEventMask
 giiInit
+giiIterDevice
+giiIterSource
 giiOpen
 giiPostEvent
 giiQueryDeviceInfo
Index: gii/gii-internal.h
===================================================================
RCS file: /cvsroot/ggi/ggi-core/libgii/gii/gii-internal.h,v
retrieving revision 1.5
diff -u -p -r1.5 gii-internal.h
--- gii/gii-internal.h	11 Nov 2006 13:32:35 -0000	1.5
+++ gii/gii-internal.h	27 Dec 2006 22:05:27 -0000
@@ -99,6 +99,7 @@ struct gii_input {
 
 #define input_INIT_SOURCES(inp)     GG_LIST_INIT(&inp->sources)
 #define input_FIRST_SOURCE(inp)     GG_LIST_FIRST(&inp->sources)
+#define input_NEXT_SOURCE(inp,v)    GG_LIST_NEXT(v,impl.le0)
 #define input_FOREACH_SOURCE(inp,v) GG_LIST_FOREACH(v,&inp->sources,impl.le0)
 #define input_ADD_SOURCE(inp,v)     GG_LIST_INSERT_HEAD(&inp->sources,v,impl.le0)
 #define input_REM_SOURCE(inp,v)     GG_LIST_REMOVE(v,impl.le0)
@@ -140,6 +141,7 @@ struct gii_source_internal {
 
 #define source_INIT_DEVICES(src)     GG_LIST_INIT(&src->impl.devices)
 #define source_FIRST_DEVICE(src)     GG_LIST_FIRST(&src->impl.devices)
+#define source_NEXT_DEVICE(src,v)    GG_LIST_NEXT(v,devices)
 #define source_FOREACH_DEVICE(src,v) GG_LIST_FOREACH(v,&src->impl.devices,devices)
 #define source_ADD_DEVICE(src,v)     GG_LIST_INSERT_HEAD(&src->impl.devices,v,devices)
 #define source_REM_DEVICE(src,v)     GG_LIST_REMOVE(v,devices)
Index: gii/gii.c
===================================================================
RCS file: /cvsroot/ggi/ggi-core/libgii/gii/gii.c,v
retrieving revision 1.57
diff -u -p -r1.57 gii.c
--- gii/gii.c	14 Oct 2006 16:01:37 -0000	1.57
+++ gii/gii.c	27 Dec 2006 22:05:28 -0000
@@ -967,6 +967,80 @@ giiEventSend(gii_input stem, gii_event *
 	return GGI_EEVNOTARGET;
 }
 
+static int _source_next(struct gii_source_iter *iter)
+{
+	struct gii_source *src;
+
+	src = (struct gii_source *)iter->_state;
+
+	while (src) {
+		iter->origin = src->origin;
+		iter->src = iter->_state;
+		iter->_state = input_NEXT_SOURCE(iter->stem, src);
+		return ITER_YIELD;
+	}
+	return ITER_DONE;
+}
+
+int giiIterSource(struct gii_source_iter *iter)
+{
+	struct gii_input *inp;
+
+	DPRINT("giiIterSource(%p)\n", iter);
+
+	inp = GII_INPUT(iter->stem);
+	GG_ITER_PREPARE(iter, _source_next, NULL);
+	iter->src = NULL; 
+	iter->_state = input_FIRST_SOURCE(inp);
+	return GGI_OK;	
+}
+
+static int _device_next(struct gii_device_iter *iter)
+{
+	struct gii_device *dev;
+
+	dev = (struct gii_device *)iter->_state;
+
+	while (dev) {
+		iter->origin = dev->origin;
+		iter->devinfo = *dev->devinfo;
+		iter->_state = source_NEXT_DEVICE(iter->stem, dev);
+		return ITER_YIELD;
+	}
+	return ITER_DONE;
+}
+
+int giiIterDevice(struct gii_device_iter *iter)
+{
+	struct gii_device *dev = NULL;
+	struct gii_source *src = NULL;
+	struct gii_input *inp;
+
+	DPRINT("giiIterDevice(%p)\n", iter);
+
+	inp = GII_INPUT(iter->stem);
+	if (iter->src == NULL) {
+		input_FOREACH_SOURCE(inp, src) {
+			if (!GII_IS_SAME_SOURCE(src->origin, iter->source_origin))
+				continue;
+			dev = source_FIRST_DEVICE(src);
+			break;
+		}
+	} else {
+		src = iter->src;
+		dev = source_FIRST_DEVICE(src);
+	}
+
+	GG_ITER_PREPARE(iter, _device_next, NULL);
+	iter->_state = dev;
+	if (dev) {
+		iter->devinfo = *dev->devinfo;
+	} else {
+		memset(&iter->devinfo, 0,
+			sizeof(struct gii_cmddata_devinfo));
+	}
+	return GGI_OK;
+}
 
 int
 giiQueryDeviceInfo(gii_input stem, uint32_t origin,
Index: include/ggi/gii.h
===================================================================
RCS file: /cvsroot/ggi/ggi-core/libgii/include/ggi/gii.h,v
retrieving revision 1.14
diff -u -p -r1.14 gii.h
--- include/ggi/gii.h	11 Nov 2006 11:55:23 -0000	1.14
+++ include/ggi/gii.h	27 Dec 2006 22:05:28 -0000
@@ -125,10 +125,48 @@ GIIAPIFUNC int            giiEventSend(g
 
 /*
 ************************************************************************
-**  Miscellaneous functions
+**  Input device information
 ************************************************************************
 */
 
+struct gii_source_iter {
+	struct gg_iter iter;
+
+	/* These must be set by the caller before calling
+	 * giiIterSource
+	 */
+	gii_input stem;
+
+	/* Placeholders for results */
+	uint32_t origin;
+	void *src;
+
+	/* Internal */
+	void *_state;
+};
+
+struct gii_device_iter {
+	struct gg_iter iter;
+
+	/* These must be set by the caller before calling
+	 * giiIterDevice
+	 */
+	gii_input stem;
+	uint32_t source_origin;
+	void *src;		/* NULL means use source_origin */
+
+	/* Placeholders for results */
+	uint32_t origin;
+	struct gii_cmddata_devinfo devinfo;
+
+	/* Internal */
+	void *_state;
+};
+
+GIIAPIFUNC int giiIterSource(struct gii_source_iter *iter);
+GIIAPIFUNC int giiIterDevice(struct gii_device_iter *iter);
+
+
 GIIAPIFUNC int giiQueryDeviceInfo(gii_input stem,
 				  uint32_t origin,
 				  struct gii_cmddata_devinfo *info);
@@ -138,6 +176,14 @@ GIIAPIFUNC int giiQueryValInfo(gii_input
 			       uint32_t valnumber,
 			       struct gii_cmddata_valinfo *info);
 
+
+
+/*
+************************************************************************
+**  Miscellaneous functions
+************************************************************************
+*/
+
 GIIAPIFUNC const char * giiGetConfDir(void);
 
 /*
