From cf92c9d731dc5244ec34a32524dc71046a1cb777 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Wed, 6 Sep 2017 10:03:50 +0200 Subject: vendor --- .../karalabe/hid/libusb/libusb/os/haiku_pollfs.cpp | 367 +++++++++++++++++++++ 1 file changed, 367 insertions(+) create mode 100644 vendor/github.com/karalabe/hid/libusb/libusb/os/haiku_pollfs.cpp (limited to 'vendor/github.com/karalabe/hid/libusb/libusb/os/haiku_pollfs.cpp') diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/haiku_pollfs.cpp b/vendor/github.com/karalabe/hid/libusb/libusb/os/haiku_pollfs.cpp new file mode 100644 index 0000000..e0c7713 --- /dev/null +++ b/vendor/github.com/karalabe/hid/libusb/libusb/os/haiku_pollfs.cpp @@ -0,0 +1,367 @@ +/* + * Copyright 2007-2008, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz + */ + +#include "haiku_usb.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class WatchedEntry { +public: + WatchedEntry(BMessenger *, entry_ref *); + ~WatchedEntry(); + bool EntryCreated(entry_ref *ref); + bool EntryRemoved(ino_t node); + bool InitCheck(); + +private: + BMessenger* fMessenger; + node_ref fNode; + bool fIsDirectory; + USBDevice* fDevice; + WatchedEntry* fEntries; + WatchedEntry* fLink; + bool fInitCheck; +}; + + +class RosterLooper : public BLooper { +public: + RosterLooper(USBRoster *); + void Stop(); + virtual void MessageReceived(BMessage *); + bool InitCheck(); + +private: + USBRoster* fRoster; + WatchedEntry* fRoot; + BMessenger* fMessenger; + bool fInitCheck; +}; + + +WatchedEntry::WatchedEntry(BMessenger *messenger, entry_ref *ref) + : fMessenger(messenger), + fIsDirectory(false), + fDevice(NULL), + fEntries(NULL), + fLink(NULL), + fInitCheck(false) +{ + BEntry entry(ref); + entry.GetNodeRef(&fNode); + + BDirectory directory; + if (entry.IsDirectory() && directory.SetTo(ref) >= B_OK) { + fIsDirectory = true; + + while (directory.GetNextEntry(&entry) >= B_OK) { + if (entry.GetRef(ref) < B_OK) + continue; + + WatchedEntry *child = new(std::nothrow) WatchedEntry(fMessenger, ref); + if (child == NULL) + continue; + if (child->InitCheck() == false) { + delete child; + continue; + } + + child->fLink = fEntries; + fEntries = child; + } + + watch_node(&fNode, B_WATCH_DIRECTORY, *fMessenger); + } + else { + if (strncmp(ref->name, "raw", 3) == 0) + return; + + BPath path, parent_path; + entry.GetPath(&path); + fDevice = new(std::nothrow) USBDevice(path.Path()); + if (fDevice != NULL && fDevice->InitCheck() == true) { + // Add this new device to each active context's device list + struct libusb_context *ctx; + unsigned long session_id = (unsigned long)&fDevice; + + usbi_mutex_lock(&active_contexts_lock); + list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { + struct libusb_device *dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev) { + usbi_dbg("using previously allocated device with location %lu", session_id); + libusb_unref_device(dev); + continue; + } + usbi_dbg("allocating new device with location %lu", session_id); + dev = usbi_alloc_device(ctx, session_id); + if (!dev) { + usbi_dbg("device allocation failed"); + continue; + } + *((USBDevice **)dev->os_priv) = fDevice; + + // Calculate pseudo-device-address + int addr, tmp; + if (strcmp(path.Leaf(), "hub") == 0) + tmp = 100; //Random Number + else + sscanf(path.Leaf(), "%d", &tmp); + addr = tmp + 1; + path.GetParent(&parent_path); + while (strcmp(parent_path.Leaf(), "usb") != 0) { + sscanf(parent_path.Leaf(), "%d", &tmp); + addr += tmp + 1; + parent_path.GetParent(&parent_path); + } + sscanf(path.Path(), "/dev/bus/usb/%d", &dev->bus_number); + dev->device_address = addr - (dev->bus_number + 1); + + if (usbi_sanitize_device(dev) < 0) { + usbi_dbg("device sanitization failed"); + libusb_unref_device(dev); + continue; + } + usbi_connect_device(dev); + } + usbi_mutex_unlock(&active_contexts_lock); + } + else if (fDevice) { + delete fDevice; + fDevice = NULL; + return; + } + } + fInitCheck = true; +} + + +WatchedEntry::~WatchedEntry() +{ + if (fIsDirectory) { + watch_node(&fNode, B_STOP_WATCHING, *fMessenger); + + WatchedEntry *child = fEntries; + while (child) { + WatchedEntry *next = child->fLink; + delete child; + child = next; + } + } + + if (fDevice) { + // Remove this device from each active context's device list + struct libusb_context *ctx; + struct libusb_device *dev; + unsigned long session_id = (unsigned long)&fDevice; + + usbi_mutex_lock(&active_contexts_lock); + list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { + dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev != NULL) { + usbi_disconnect_device(dev); + libusb_unref_device(dev); + } else { + usbi_dbg("device with location %lu not found", session_id); + } + } + usbi_mutex_static_unlock(&active_contexts_lock); + delete fDevice; + } +} + + +bool +WatchedEntry::EntryCreated(entry_ref *ref) +{ + if (!fIsDirectory) + return false; + + if (ref->directory != fNode.node) { + WatchedEntry *child = fEntries; + while (child) { + if (child->EntryCreated(ref)) + return true; + child = child->fLink; + } + return false; + } + + WatchedEntry *child = new(std::nothrow) WatchedEntry(fMessenger, ref); + if (child == NULL) + return false; + child->fLink = fEntries; + fEntries = child; + return true; +} + + +bool +WatchedEntry::EntryRemoved(ino_t node) +{ + if (!fIsDirectory) + return false; + + WatchedEntry *child = fEntries; + WatchedEntry *lastChild = NULL; + while (child) { + if (child->fNode.node == node) { + if (lastChild) + lastChild->fLink = child->fLink; + else + fEntries = child->fLink; + delete child; + return true; + } + + if (child->EntryRemoved(node)) + return true; + + lastChild = child; + child = child->fLink; + } + return false; +} + + +bool +WatchedEntry::InitCheck() +{ + return fInitCheck; +} + + +RosterLooper::RosterLooper(USBRoster *roster) + : BLooper("LibusbRoster Looper"), + fRoster(roster), + fRoot(NULL), + fMessenger(NULL), + fInitCheck(false) +{ + BEntry entry("/dev/bus/usb"); + if (!entry.Exists()) { + usbi_err(NULL, "usb_raw not published"); + return; + } + + Run(); + fMessenger = new(std::nothrow) BMessenger(this); + if (fMessenger == NULL) { + usbi_err(NULL, "error creating BMessenger object"); + return; + } + + if (Lock()) { + entry_ref ref; + entry.GetRef(&ref); + fRoot = new(std::nothrow) WatchedEntry(fMessenger, &ref); + Unlock(); + if (fRoot == NULL) + return; + if (fRoot->InitCheck() == false) { + delete fRoot; + fRoot = NULL; + return; + } + } + fInitCheck = true; +} + + +void +RosterLooper::Stop() +{ + Lock(); + delete fRoot; + delete fMessenger; + Quit(); +} + + +void +RosterLooper::MessageReceived(BMessage *message) +{ + int32 opcode; + if (message->FindInt32("opcode", &opcode) < B_OK) + return; + + switch (opcode) { + case B_ENTRY_CREATED: + { + dev_t device; + ino_t directory; + const char *name; + if (message->FindInt32("device", &device) < B_OK || + message->FindInt64("directory", &directory) < B_OK || + message->FindString("name", &name) < B_OK) + break; + + entry_ref ref(device, directory, name); + fRoot->EntryCreated(&ref); + break; + } + case B_ENTRY_REMOVED: + { + ino_t node; + if (message->FindInt64("node", &node) < B_OK) + break; + fRoot->EntryRemoved(node); + break; + } + } +} + + +bool +RosterLooper::InitCheck() +{ + return fInitCheck; +} + + +USBRoster::USBRoster() + : fLooper(NULL) +{ +} + + +USBRoster::~USBRoster() +{ + Stop(); +} + + +int +USBRoster::Start() +{ + if (fLooper == NULL) { + fLooper = new(std::nothrow) RosterLooper(this); + if (fLooper == NULL || ((RosterLooper *)fLooper)->InitCheck() == false) { + if (fLooper) + fLooper = NULL; + return LIBUSB_ERROR_OTHER; + } + } + return LIBUSB_SUCCESS; +} + + +void +USBRoster::Stop() +{ + if (fLooper) { + ((RosterLooper *)fLooper)->Stop(); + fLooper = NULL; + } +} -- cgit v1.2.3