xref: /haiku/src/add-ons/kernel/drivers/input/hid_shared/DeviceList.cpp (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
1 /*
2 	Generic device list for use in drivers.
3 	Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
4 	Distributed under the terms of the MIT license.
5 */
6 #include "DeviceList.h"
7 #include <util/kernel_cpp.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <new>
11 
12 struct device_list_entry {
13 	char *				name;
14 	void *				device;
15 	device_list_entry *	next;
16 };
17 
18 
19 DeviceList::DeviceList()
20 	:	fDeviceList(NULL),
21 		fDeviceCount(0),
22 		fPublishList(NULL)
23 {
24 }
25 
26 
27 DeviceList::~DeviceList()
28 {
29 	_FreePublishList();
30 
31 	device_list_entry *current = fDeviceList;
32 	while (current) {
33 		device_list_entry *next = current->next;
34 		free(current->name);
35 		delete current;
36 		current = next;
37 	}
38 }
39 
40 
41 status_t
42 DeviceList::AddDevice(const char *name, void *device)
43 {
44 	device_list_entry *entry = new(std::nothrow) device_list_entry;
45 	if (entry == NULL)
46 		return B_NO_MEMORY;
47 
48 	entry->name = strdup(name);
49 	if (entry->name == NULL) {
50 		delete entry;
51 		return B_NO_MEMORY;
52 	}
53 
54 	entry->device = device;
55 	entry->next = NULL;
56 
57 	if (fDeviceList == NULL)
58 		fDeviceList = entry;
59 	else {
60 		device_list_entry *current = fDeviceList;
61 		while (current) {
62 			if (current->next == NULL) {
63 				current->next = entry;
64 				break;
65 			}
66 
67 			current = current->next;
68 		}
69 	}
70 
71 	fDeviceCount++;
72 	return B_OK;
73 }
74 
75 
76 status_t
77 DeviceList::RemoveDevice(const char *name, void *device)
78 {
79 	if (name == NULL && device == NULL)
80 		return B_BAD_VALUE;
81 
82 	device_list_entry *previous = NULL;
83 	device_list_entry *current = fDeviceList;
84 	while (current) {
85 		if ((name != NULL && strcmp(current->name, name) == 0)
86 			|| (device != NULL && current->device == device)) {
87 			if (previous == NULL)
88 				fDeviceList = current->next;
89 			else
90 				previous->next = current->next;
91 
92 			free(current->name);
93 			delete current;
94 			fDeviceCount--;
95 			return B_OK;
96 		}
97 
98 		previous = current;
99 		current = current->next;
100 	}
101 
102 	return B_ENTRY_NOT_FOUND;
103 }
104 
105 
106 void *
107 DeviceList::FindDevice(const char *name, void *device)
108 {
109 	if (name == NULL && device == NULL)
110 		return NULL;
111 
112 	device_list_entry *current = fDeviceList;
113 	while (current) {
114 		if ((name != NULL && strcmp(current->name, name) == 0)
115 			|| (device != NULL && current->device == device))
116 			return current->device;
117 
118 		current = current->next;
119 	}
120 
121 	return NULL;
122 }
123 
124 
125 int32
126 DeviceList::CountDevices(const char *baseName)
127 {
128 	if (baseName == NULL)
129 		return fDeviceCount;
130 
131 	int32 count = 0;
132 	int32 baseNameLength = strlen(baseName);
133 	device_list_entry *current = fDeviceList;
134 	while (current) {
135 		if (strncmp(current->name, baseName, baseNameLength) == 0)
136 			count++;
137 
138 		current = current->next;
139 	}
140 
141 	return count;
142 }
143 
144 
145 void *
146 DeviceList::DeviceAt(int32 index)
147 {
148 	device_list_entry *current = fDeviceList;
149 	while (current) {
150 		if (index-- == 0)
151 			return current->device;
152 
153 		current = current->next;
154 	}
155 
156 	return NULL;
157 }
158 
159 
160 const char **
161 DeviceList::PublishDevices()
162 {
163 	_FreePublishList();
164 
165 	fPublishList = (char **)malloc((fDeviceCount + 1) * sizeof(char *));
166 	if (fPublishList == NULL)
167 		return NULL;
168 
169 	int32 index = 0;
170 	device_list_entry *current = fDeviceList;
171 	while (current) {
172 		fPublishList[index++] = strdup(current->name);
173 		current = current->next;
174 	}
175 
176 	fPublishList[index] = NULL;
177 	return (const char **)fPublishList;
178 }
179 
180 
181 void
182 DeviceList::_FreePublishList()
183 {
184 	if (fPublishList == NULL)
185 		return;
186 
187 	int32 index = 0;
188 	while (fPublishList[index] != NULL) {
189 		free(fPublishList[index]);
190 		index++;
191 	}
192 
193 	free(fPublishList);
194 	fPublishList = NULL;
195 }
196