HaikuDepot: notify work status from main window
[haiku.git] / src / kits / device / USBRoster.cpp
blob7a5af559136195a7540b55211502ecdbc46b33ec
1 /*
2 * Copyright 2007-2008, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Michael Lotz <mmlr@mlotz.ch>
7 */
9 #include <USBKit.h>
10 #include <Directory.h>
11 #include <Entry.h>
12 #include <Looper.h>
13 #include <Messenger.h>
14 #include <Node.h>
15 #include <NodeMonitor.h>
16 #include <Path.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <new>
22 class WatchedEntry {
23 public:
24 WatchedEntry(BUSBRoster *roster,
25 BMessenger *messenger, entry_ref *ref);
26 ~WatchedEntry();
28 bool EntryCreated(entry_ref *ref);
29 bool EntryRemoved(ino_t node);
31 private:
32 BUSBRoster * fRoster;
33 BMessenger * fMessenger;
35 node_ref fNode;
36 bool fIsDirectory;
37 BUSBDevice * fDevice;
39 WatchedEntry * fEntries;
40 WatchedEntry * fLink;
44 class RosterLooper : public BLooper {
45 public:
46 RosterLooper(BUSBRoster *roster);
48 void Stop();
50 virtual void MessageReceived(BMessage *message);
52 private:
53 BUSBRoster * fRoster;
54 WatchedEntry * fRoot;
55 BMessenger * fMessenger;
59 WatchedEntry::WatchedEntry(BUSBRoster *roster, BMessenger *messenger,
60 entry_ref *ref)
61 : fRoster(roster),
62 fMessenger(messenger),
63 fIsDirectory(false),
64 fDevice(NULL),
65 fEntries(NULL),
66 fLink(NULL)
68 BEntry entry(ref);
69 entry.GetNodeRef(&fNode);
71 BDirectory directory;
72 if (entry.IsDirectory() && directory.SetTo(ref) >= B_OK) {
73 fIsDirectory = true;
75 while(directory.GetNextEntry(&entry) >= B_OK) {
76 if (entry.GetRef(ref) < B_OK)
77 continue;
79 WatchedEntry *child = new(std::nothrow) WatchedEntry(fRoster,
80 fMessenger, ref);
81 if (child == NULL)
82 continue;
84 child->fLink = fEntries;
85 fEntries = child;
88 watch_node(&fNode, B_WATCH_DIRECTORY, *fMessenger);
89 } else {
90 // filter pseudoentry that only handles ioctls
91 if (strncmp(ref->name, "raw", 3) == 0)
92 return;
94 BPath path;
95 entry.GetPath(&path);
96 fDevice = new(std::nothrow) BUSBDevice(path.Path());
97 if (fDevice != NULL) {
98 if (fRoster->DeviceAdded(fDevice) != B_OK) {
99 delete fDevice;
100 fDevice = NULL;
107 WatchedEntry::~WatchedEntry()
109 if (fIsDirectory) {
110 watch_node(&fNode, B_STOP_WATCHING, *fMessenger);
112 WatchedEntry *child = fEntries;
113 while (child) {
114 WatchedEntry *next = child->fLink;
115 delete child;
116 child = next;
120 if (fDevice) {
121 fRoster->DeviceRemoved(fDevice);
122 delete fDevice;
127 bool
128 WatchedEntry::EntryCreated(entry_ref *ref)
130 if (!fIsDirectory)
131 return false;
133 if (ref->directory != fNode.node) {
134 WatchedEntry *child = fEntries;
135 while (child) {
136 if (child->EntryCreated(ref))
137 return true;
138 child = child->fLink;
141 return false;
144 WatchedEntry *child = new(std::nothrow) WatchedEntry(fRoster, fMessenger,
145 ref);
146 if (child == NULL)
147 return false;
149 child->fLink = fEntries;
150 fEntries = child;
151 return true;
155 bool
156 WatchedEntry::EntryRemoved(ino_t node)
158 if (!fIsDirectory)
159 return false;
161 WatchedEntry *child = fEntries;
162 WatchedEntry *lastChild = NULL;
163 while (child) {
164 if (child->fNode.node == node) {
165 if (lastChild)
166 lastChild->fLink = child->fLink;
167 else
168 fEntries = child->fLink;
170 delete child;
171 return true;
174 if (child->EntryRemoved(node))
175 return true;
177 lastChild = child;
178 child = child->fLink;
181 return false;
185 RosterLooper::RosterLooper(BUSBRoster *roster)
186 : BLooper("BUSBRoster looper"),
187 fRoster(roster),
188 fRoot(NULL),
189 fMessenger(NULL)
191 BEntry entry("/dev/bus/usb");
192 if (!entry.Exists()) {
193 fprintf(stderr, "USBKit: usb_raw not published\n");
194 return;
197 Run();
198 fMessenger = new(std::nothrow) BMessenger(this);
199 if (fMessenger == NULL)
200 return;
202 if (Lock()) {
203 entry_ref ref;
204 entry.GetRef(&ref);
205 fRoot = new(std::nothrow) WatchedEntry(fRoster, fMessenger, &ref);
206 Unlock();
211 void
212 RosterLooper::Stop()
214 Lock();
215 delete fRoot;
216 Quit();
220 void
221 RosterLooper::MessageReceived(BMessage *message)
223 int32 opcode;
224 if (message->FindInt32("opcode", &opcode) < B_OK)
225 return;
227 switch (opcode) {
228 case B_ENTRY_CREATED: {
229 dev_t device;
230 ino_t directory;
231 const char *name;
232 if (message->FindInt32("device", &device) < B_OK
233 || message->FindInt64("directory", &directory) < B_OK
234 || message->FindString("name", &name) < B_OK)
235 break;
237 entry_ref ref(device, directory, name);
238 fRoot->EntryCreated(&ref);
239 break;
242 case B_ENTRY_REMOVED: {
243 ino_t node;
244 if (message->FindInt64("node", &node) < B_OK)
245 break;
247 fRoot->EntryRemoved(node);
248 break;
254 BUSBRoster::BUSBRoster()
255 : fLooper(NULL)
260 BUSBRoster::~BUSBRoster()
262 Stop();
266 void
267 BUSBRoster::Start()
269 if (fLooper)
270 return;
272 fLooper = new(std::nothrow) RosterLooper(this);
276 void
277 BUSBRoster::Stop()
279 if (!fLooper)
280 return;
282 ((RosterLooper *)fLooper)->Stop();
283 fLooper = NULL;
287 // definition of reserved virtual functions
288 void BUSBRoster::_ReservedUSBRoster1() {};
289 void BUSBRoster::_ReservedUSBRoster2() {};
290 void BUSBRoster::_ReservedUSBRoster3() {};
291 void BUSBRoster::_ReservedUSBRoster4() {};
292 void BUSBRoster::_ReservedUSBRoster5() {};