1/*
2 * Copyright 2003-2005, Axel D��rfler, axeld@pinc-software.de. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6#include <platform/openfirmware/devices.h>
7#include <platform/openfirmware/openfirmware.h>
8#include <util/kernel_cpp.h>
9
10#include <string.h>
11
12
13/** Gets all device types of the specified type by doing a
14 *	depth-first search of the OpenFirmware device tree.
15 *	If a root != 0 is given, the function only traverses the subtree spanned
16 *	by the root (inclusively). Otherwise the whole device tree is searched.
17 *
18 *	The cookie has to be initialized to zero.
19 */
20status_t
21of_get_next_device(intptr_t *_cookie, intptr_t root, const char *type,
22	char *path, size_t pathSize)
23{
24	intptr_t node = *_cookie;
25
26	while (true) {
27		intptr_t next;
28
29		if (node == 0) {
30			// node is NULL, meaning that this is the initial function call.
31			// If a root was supplied, we take that, otherwise the device tree
32			// root.
33			if (root != 0)
34				node = root;
35			else
36				node = of_peer(0);
37
38			if (node == OF_FAILED)
39				return B_ERROR;
40			if (node == 0)
41				return B_ENTRY_NOT_FOUND;
42
43			// We want to visit the root first.
44			next = node;
45		} else
46			next = of_child(node);
47
48		if (next == OF_FAILED)
49			return B_ERROR;
50
51		if (next == 0) {
52			// no child node found
53			next = of_peer(node);
54			if (next == OF_FAILED)
55				return B_ERROR;
56
57			while (next == 0) {
58				// no peer node found, we are using the device
59				// tree itself as our search stack
60
61				next = of_parent(node);
62				if (next == OF_FAILED)
63					return B_ERROR;
64
65				if (next == root || next == 0) {
66					// We have searched the whole device tree
67					return B_ENTRY_NOT_FOUND;
68				}
69
70				// look into the next tree
71				node = next;
72				next = of_peer(node);
73			}
74		}
75
76		*_cookie = node = next;
77
78		char nodeType[16];
79		int length;
80		if (of_getprop(node, "device_type", nodeType, sizeof(nodeType))
81				== OF_FAILED
82			|| strcmp(nodeType, type)
83			|| (length = of_package_to_path(node, path, pathSize - 1))
84					== OF_FAILED) {
85			continue;
86		}
87
88		path[length] = '\0';
89		return B_OK;
90	}
91}
92
93