xref: /haiku/src/system/kernel/platform/openfirmware/openfirmware_devices.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
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  */
20 status_t
21 of_get_next_device(int *_cookie, int root, const char *type, char *path,
22 	size_t pathSize)
23 {
24 	int node = *_cookie;
25 
26 	while (true) {
27 		int 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