Commiting reimplemented USBKit that is compatible with the old Be sample code version.
It is supposed to be cleaner and more object oriented. It also adds some features (like a string getter for the interface) that were appearantly left out in the Be implementation. It is currently built as a small static library from src/libs. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19913 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _USBKIT_H
|
||||
#define _USBKIT_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <USB_spec.h>
|
||||
|
||||
|
||||
// Keep compatibility with original USBKit classes
|
||||
#define USBRoster BUSBRoster
|
||||
#define USBDevice BUSBDevice
|
||||
#define USBConfiguration BUSBConfiguration
|
||||
#define USBInterface BUSBInterface
|
||||
#define USBEndpoint BUSBEndpoint
|
||||
|
||||
|
||||
class BUSBRoster;
|
||||
class BUSBDevice;
|
||||
class BUSBConfiguration;
|
||||
class BUSBInterface;
|
||||
class BUSBEndpoint;
|
||||
|
||||
|
||||
/* The BUSBRoster class can be used to watch for devices that get attached or
|
||||
removed from the USB bus.
|
||||
You subclass the roster and implement the pure virtual DeviceAdded() and
|
||||
DeviceRemoved() hooks. */
|
||||
class BUSBRoster {
|
||||
public:
|
||||
BUSBRoster();
|
||||
virtual ~BUSBRoster();
|
||||
|
||||
// The DeviceAdded() hook will be called when a new device gets
|
||||
// attached to the USB bus. The hook is called with an initialized
|
||||
// BUSBDevice object. If you return B_OK from your hook the object
|
||||
// will stay valid and the DeviceRemoved() hook will be called with
|
||||
// for it. Otherwise the object is deleted and DeviceRemoved()
|
||||
// is not called.
|
||||
virtual status_t DeviceAdded(BUSBDevice *device) = 0;
|
||||
|
||||
// When a device gets detached from the bus that you hold a
|
||||
// BUSBDevice object for (gotten through DeviceAdded()) the
|
||||
// DeviceRemoved() hook will be called. The device object gets
|
||||
// invalid and will be deleted as soon as you return from the hook
|
||||
// so be sure to remove all references to it.
|
||||
virtual void DeviceRemoved(BUSBDevice *device) = 0;
|
||||
|
||||
void Start();
|
||||
void Stop();
|
||||
|
||||
private:
|
||||
void *fLooper;
|
||||
};
|
||||
|
||||
|
||||
/* The BUSBDevice presents an interface to USB device. You can either get
|
||||
it through the BUSBRoster or by creating one yourself and setting it to
|
||||
a valid raw usb device (with a path of "/dev/bus/usb/x").
|
||||
The device class provides direct accessors for descriptor fields as well
|
||||
as convenience functions to directly get string representations of fields.
|
||||
The BUSBDevice also provides access for the BUSBConfiguration objects of
|
||||
a device. These objects and all of their child objects depend on the
|
||||
parent device and will be deleted as soon as the device object is
|
||||
destroyed */
|
||||
class BUSBDevice {
|
||||
public:
|
||||
BUSBDevice(const char *path = NULL);
|
||||
virtual ~BUSBDevice();
|
||||
|
||||
virtual status_t InitCheck();
|
||||
|
||||
status_t SetTo(const char *path);
|
||||
void Unset();
|
||||
|
||||
// Returns the location on the bus represented as hub/device sequence
|
||||
const char *Location() const;
|
||||
bool IsHub() const;
|
||||
|
||||
// These are direct accessors to descriptor fields
|
||||
uint16 USBVersion() const;
|
||||
uint8 Class() const;
|
||||
uint8 Subclass() const;
|
||||
uint8 Protocol() const;
|
||||
uint8 MaxEndpoint0PacketSize() const;
|
||||
uint16 VendorID() const;
|
||||
uint16 ProductID() const;
|
||||
uint16 Version() const;
|
||||
|
||||
// The string functions return the string representation of the
|
||||
// descriptor data. The strings are decoded to normal 0 terminated
|
||||
// c strings and are cached and owned by the object.
|
||||
// If a string is not available an empty string is returned.
|
||||
const char *ManufacturerString() const;
|
||||
const char *ProductString() const;
|
||||
const char *SerialNumberString() const;
|
||||
|
||||
const usb_device_descriptor *Descriptor() const;
|
||||
|
||||
// GetStringDescriptor() can be used to retrieve the raw
|
||||
// usb_string_descriptor with a given index. The strings contained
|
||||
// in these descriptors are usually two-byte unicode encoded.
|
||||
size_t GetStringDescriptor(uint32 index,
|
||||
usb_string_descriptor *descriptor,
|
||||
size_t length) const;
|
||||
|
||||
// Use the DecodeStringDescriptor() convenience function to get a
|
||||
// 0-terminated c string for a given string index. Note that this
|
||||
// will allocate the string as "new char[];" and needs to be deleted
|
||||
// like "delete[] string;" by the caller.
|
||||
char *DecodeStringDescriptor(uint32 index) const;
|
||||
|
||||
size_t GetDescriptor(uint8 type, uint8 index,
|
||||
uint16 languageID, void *data,
|
||||
size_t length) const;
|
||||
|
||||
// With ConfigurationAt() or ActiveConfiguration() you can get an
|
||||
// object that represents the configuration at a certain index or at
|
||||
// the index that is currently configured. Note that the index does not
|
||||
// necessarily correspond with the configuration value.
|
||||
// Use the returned object as an argument to SetConfiguration() to
|
||||
// change the active configuration of a device.
|
||||
uint32 CountConfigurations() const;
|
||||
const BUSBConfiguration *ConfigurationAt(uint32 index) const;
|
||||
|
||||
const BUSBConfiguration *ActiveConfiguration() const;
|
||||
status_t SetConfiguration(
|
||||
const BUSBConfiguration *configuration);
|
||||
|
||||
// ControlTransfer() sends requests using the default pipe
|
||||
ssize_t ControlTransfer(uint8 requestType,
|
||||
uint8 request, uint16 value,
|
||||
uint16 index, uint16 length,
|
||||
void *data) const;
|
||||
|
||||
private:
|
||||
char *fPath;
|
||||
int fRawFD;
|
||||
|
||||
usb_device_descriptor fDescriptor;
|
||||
BUSBConfiguration **fConfigurations;
|
||||
uint32 fActiveConfiguration;
|
||||
|
||||
mutable char *fManufacturerString;
|
||||
mutable char *fProductString;
|
||||
mutable char *fSerialNumberString;
|
||||
};
|
||||
|
||||
|
||||
/* A BUSBConfiguration object represents one of possibly multiple
|
||||
configurations a device might have. A valid object can only be gotten
|
||||
through the ConfigurationAt() and ActiveConfiguration() methods of a
|
||||
BUSBDevice.
|
||||
The BUSBConfiguration provides further access into the configuration by
|
||||
providing CountInterfaces() and InterfaceAt() to retrieve BUSBInterface
|
||||
objects. */
|
||||
class BUSBConfiguration {
|
||||
public:
|
||||
// Device() returns the parent device of this configuration. This
|
||||
// configuration is located at the index returned by Index() within
|
||||
// that parent device.
|
||||
uint32 Index() const;
|
||||
const BUSBDevice *Device() const;
|
||||
|
||||
// Gets a describing string of this configuration if available.
|
||||
// Otherwise an empty string is returned.
|
||||
const char *ConfigurationString() const;
|
||||
|
||||
const usb_configuration_descriptor
|
||||
*Descriptor() const;
|
||||
|
||||
// With CountInterfaces() and InterfaceAt() you can iterate through
|
||||
// the child interfaces of this configuration. It is the only valid
|
||||
// way to get a BUSBInterface object.
|
||||
// Note that the interface objects retrieved using InterfaceAt() will
|
||||
// be invalid and deleted as soon as this configuration gets deleted.
|
||||
uint32 CountInterfaces() const;
|
||||
const BUSBInterface *InterfaceAt(uint32 index) const;
|
||||
|
||||
private:
|
||||
friend class BUSBDevice;
|
||||
BUSBConfiguration(BUSBDevice *device,
|
||||
uint32 index, int rawFD);
|
||||
~BUSBConfiguration();
|
||||
|
||||
BUSBDevice *fDevice;
|
||||
uint32 fIndex;
|
||||
int fRawFD;
|
||||
|
||||
usb_configuration_descriptor fDescriptor;
|
||||
BUSBInterface **fInterfaces;
|
||||
|
||||
mutable char *fConfigurationString;
|
||||
};
|
||||
|
||||
|
||||
/* The BUSBInterface class can be used to access the descriptor fields of
|
||||
an underleying USB interface. Most importantly though it can be used to
|
||||
iterate over and retrieve BUSBEndpoint objects that can be used to
|
||||
transfer data over the bus. */
|
||||
class BUSBInterface {
|
||||
public:
|
||||
// Configuration() returns the parent configuration of this interface.
|
||||
// This interface is located at the index returned by Index() in that
|
||||
// parent configuration.
|
||||
// Device() is a convenience function to directly reach the parent
|
||||
// device of this interface instead of going through the configuration.
|
||||
uint32 Index() const;
|
||||
const BUSBConfiguration *Configuration() const;
|
||||
const BUSBDevice *Device() const;
|
||||
|
||||
// These are accessors to descriptor fields. InterfaceString() tries
|
||||
// to return a describing string of this interface. If no string is
|
||||
// available an empty string will be returned.
|
||||
uint8 Class() const;
|
||||
uint8 Subclass() const;
|
||||
uint8 Protocol() const;
|
||||
const char *InterfaceString() const;
|
||||
|
||||
const usb_interface_descriptor
|
||||
*Descriptor() const;
|
||||
|
||||
// Use OtherDescriptorAt() to get generic descriptors of an interface.
|
||||
// These are usually vendor or device specific extensions.
|
||||
status_t OtherDescriptorAt(uint32 index,
|
||||
usb_descriptor *descriptor,
|
||||
size_t length) const;
|
||||
|
||||
// CountEndpoints() and EndpointAt() can be used to iterate over the
|
||||
// available endpoints within an interface. EndpointAt() is the only
|
||||
// valid way to get BUSBEndpoint object. Note that these objects will
|
||||
// get invalid and deleted as soon as the parent interface is deleted.
|
||||
uint32 CountEndpoints() const;
|
||||
const BUSBEndpoint *EndpointAt(uint32 index) const;
|
||||
|
||||
private:
|
||||
friend class BUSBConfiguration;
|
||||
BUSBInterface(BUSBConfiguration *config,
|
||||
uint32 index, int rawFD);
|
||||
~BUSBInterface();
|
||||
|
||||
BUSBConfiguration *fConfiguration;
|
||||
uint32 fIndex;
|
||||
int fRawFD;
|
||||
|
||||
usb_interface_descriptor fDescriptor;
|
||||
BUSBEndpoint **fEndpoints;
|
||||
|
||||
mutable char *fInterfaceString;
|
||||
};
|
||||
|
||||
|
||||
/* The BUSBEndpoint represent a device endpoint that can be used to send or
|
||||
receive data. It also alows to query endpoint characteristics like
|
||||
endpoint type or direction. */
|
||||
class BUSBEndpoint {
|
||||
public:
|
||||
// Interface() returns the parent interface of this endpoint.
|
||||
// This endpoint is located at the index returned by Index() in the
|
||||
// parent interface.
|
||||
// Configuration() and Device() are convenience functions to directly
|
||||
// reach the parent configuration or device of this endpoint instead
|
||||
// of going through the parent objects.
|
||||
uint32 Index() const;
|
||||
const BUSBInterface *Interface() const;
|
||||
const BUSBConfiguration *Configuration() const;
|
||||
const BUSBDevice *Device() const;
|
||||
|
||||
// These methods can be used to check for endpoint characteristics.
|
||||
bool IsBulk() const;
|
||||
bool IsInterrupt() const;
|
||||
bool IsIsochronous() const;
|
||||
bool IsControl() const;
|
||||
|
||||
bool IsInput() const;
|
||||
bool IsOutput() const;
|
||||
|
||||
uint16 MaxPacketSize() const;
|
||||
uint8 Interval() const;
|
||||
|
||||
const usb_endpoint_descriptor
|
||||
*Descriptor() const;
|
||||
|
||||
// These methods initiate transfers to or from the endpoint. All
|
||||
// transfers are synchronous and the actually transfered amount of
|
||||
// data is returned as a result. A negative value indicates an error.
|
||||
// Which transfer type to use depends on the endpoint type.
|
||||
ssize_t ControlTransfer(uint8 requestType,
|
||||
uint8 request, uint16 value,
|
||||
uint16 index, uint16 length,
|
||||
void *data) const;
|
||||
ssize_t InterruptTransfer(void *data,
|
||||
size_t length) const;
|
||||
ssize_t BulkTransfer(void *data,
|
||||
size_t length) const;
|
||||
|
||||
private:
|
||||
friend class BUSBInterface;
|
||||
BUSBEndpoint(BUSBInterface *interface,
|
||||
uint32 index, int rawFD);
|
||||
~BUSBEndpoint();
|
||||
|
||||
BUSBInterface *fInterface;
|
||||
uint32 fIndex;
|
||||
int fRawFD;
|
||||
|
||||
usb_endpoint_descriptor fDescriptor;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -14,5 +14,6 @@ SubInclude HAIKU_TOP src libs pdflib ;
|
||||
SubInclude HAIKU_TOP src libs png ;
|
||||
SubInclude HAIKU_TOP src libs stdc++ ;
|
||||
SubInclude HAIKU_TOP src libs termcap ;
|
||||
SubInclude HAIKU_TOP src libs usb ;
|
||||
SubInclude HAIKU_TOP src libs util ;
|
||||
SubInclude HAIKU_TOP src libs zlib ;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
SubDir HAIKU_TOP src libs usb ;
|
||||
|
||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
|
||||
# for USBKit.h, usb_raw.h and lock.h
|
||||
UseLibraryHeaders usb ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel drivers bus usb ] : true ;
|
||||
UsePrivateHeaders kernel ;
|
||||
|
||||
StaticLibrary USBKit.a :
|
||||
USBRoster.cpp
|
||||
USBDevice.cpp
|
||||
USBConfiguration.cpp
|
||||
USBInterface.cpp
|
||||
USBEndpoint.cpp
|
||||
;
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
#include <USBKit.h>
|
||||
#include <usb_raw.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
BUSBConfiguration::BUSBConfiguration(BUSBDevice *device, uint32 index, int rawFD)
|
||||
: fDevice(device),
|
||||
fIndex(index),
|
||||
fRawFD(rawFD),
|
||||
fInterfaces(NULL),
|
||||
fConfigurationString(NULL)
|
||||
{
|
||||
raw_command command;
|
||||
command.config.descriptor = &fDescriptor;
|
||||
command.config.config_index = fIndex;
|
||||
if (ioctl(fRawFD, RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR, &command, sizeof(command))
|
||||
|| command.config.status != RAW_STATUS_SUCCESS) {
|
||||
memset(&fDescriptor, 0, sizeof(fDescriptor));
|
||||
}
|
||||
|
||||
fInterfaces = new BUSBInterface *[fDescriptor.number_interfaces];
|
||||
for (uint32 i = 0; i < fDescriptor.number_interfaces; i++)
|
||||
fInterfaces[i] = new BUSBInterface(this, i, fRawFD);
|
||||
}
|
||||
|
||||
|
||||
BUSBConfiguration::~BUSBConfiguration()
|
||||
{
|
||||
delete[] fConfigurationString;
|
||||
for (int32 i = 0; i < fDescriptor.number_interfaces; i++)
|
||||
delete fInterfaces[i];
|
||||
delete[] fInterfaces;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
BUSBConfiguration::Index() const
|
||||
{
|
||||
return fIndex;
|
||||
}
|
||||
|
||||
|
||||
const BUSBDevice *
|
||||
BUSBConfiguration::Device() const
|
||||
{
|
||||
return fDevice;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
BUSBConfiguration::ConfigurationString() const
|
||||
{
|
||||
if (fDescriptor.configuration == 0)
|
||||
return "";
|
||||
|
||||
if (fConfigurationString)
|
||||
return fConfigurationString;
|
||||
|
||||
fConfigurationString = Device()->DecodeStringDescriptor(fDescriptor.configuration);
|
||||
if (!fConfigurationString) {
|
||||
fConfigurationString = new char[1];
|
||||
fConfigurationString[0] = 0;
|
||||
}
|
||||
|
||||
return fConfigurationString;
|
||||
}
|
||||
|
||||
|
||||
const usb_configuration_descriptor *
|
||||
BUSBConfiguration::Descriptor() const
|
||||
{
|
||||
return &fDescriptor;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
BUSBConfiguration::CountInterfaces() const
|
||||
{
|
||||
return fDescriptor.number_interfaces;
|
||||
}
|
||||
|
||||
|
||||
const BUSBInterface *
|
||||
BUSBConfiguration::InterfaceAt(uint32 index) const
|
||||
{
|
||||
if (index >= fDescriptor.number_interfaces)
|
||||
return NULL;
|
||||
|
||||
return fInterfaces[index];
|
||||
}
|
||||
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
#include <USBKit.h>
|
||||
#include <usb_raw.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <malloc.h>
|
||||
|
||||
|
||||
BUSBDevice::BUSBDevice(const char *path)
|
||||
: fPath(NULL),
|
||||
fRawFD(-1),
|
||||
fConfigurations(NULL),
|
||||
fActiveConfiguration(0),
|
||||
fManufacturerString(NULL),
|
||||
fProductString(NULL),
|
||||
fSerialNumberString(NULL)
|
||||
{
|
||||
memset(&fDescriptor, 0, sizeof(fDescriptor));
|
||||
|
||||
if (path)
|
||||
SetTo(path);
|
||||
}
|
||||
|
||||
|
||||
BUSBDevice::~BUSBDevice()
|
||||
{
|
||||
Unset();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BUSBDevice::InitCheck()
|
||||
{
|
||||
return (fRawFD >= 0 ? B_OK : B_ERROR);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BUSBDevice::SetTo(const char *path)
|
||||
{
|
||||
if (!path)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
fPath = strdup(path);
|
||||
fRawFD = open(path, O_RDWR);
|
||||
if (fRawFD < 0) {
|
||||
Unset();
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
raw_command command;
|
||||
if (ioctl(fRawFD, RAW_COMMAND_GET_VERSION, &command, sizeof(command))
|
||||
|| command.version.status != 0x0015) {
|
||||
Unset();
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
command.device.descriptor = &fDescriptor;
|
||||
if (ioctl(fRawFD, RAW_COMMAND_GET_DEVICE_DESCRIPTOR, &command, sizeof(command))
|
||||
|| command.device.status != RAW_STATUS_SUCCESS) {
|
||||
Unset();
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
fConfigurations = new BUSBConfiguration *[fDescriptor.num_configurations];
|
||||
for (uint32 i = 0; i < fDescriptor.num_configurations; i++)
|
||||
fConfigurations[i] = new BUSBConfiguration(this, i, fRawFD);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BUSBDevice::Unset()
|
||||
{
|
||||
if (fRawFD >= 0)
|
||||
close(fRawFD);
|
||||
fRawFD = -1;
|
||||
|
||||
free(fPath);
|
||||
fPath = NULL;
|
||||
|
||||
delete[] fManufacturerString;
|
||||
delete[] fProductString;
|
||||
delete[] fSerialNumberString;
|
||||
fManufacturerString = fProductString = fSerialNumberString = NULL;
|
||||
|
||||
for (int32 i = 0; i < fDescriptor.num_configurations; i++)
|
||||
delete fConfigurations[i];
|
||||
|
||||
delete[] fConfigurations;
|
||||
memset(&fDescriptor, 0, sizeof(fDescriptor));
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
BUSBDevice::Location() const
|
||||
{
|
||||
if (!fPath || strlen(fPath) < 12)
|
||||
return NULL;
|
||||
|
||||
return &fPath[12];
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BUSBDevice::IsHub() const
|
||||
{
|
||||
return fDescriptor.device_class == 0x09;
|
||||
}
|
||||
|
||||
|
||||
uint16
|
||||
BUSBDevice::USBVersion() const
|
||||
{
|
||||
return fDescriptor.usb_version;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
BUSBDevice::Class() const
|
||||
{
|
||||
return fDescriptor.device_class;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
BUSBDevice::Subclass() const
|
||||
{
|
||||
return fDescriptor.device_subclass;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
BUSBDevice::Protocol() const
|
||||
{
|
||||
return fDescriptor.device_protocol;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
BUSBDevice::MaxEndpoint0PacketSize() const
|
||||
{
|
||||
return fDescriptor.max_packet_size_0;
|
||||
}
|
||||
|
||||
|
||||
uint16
|
||||
BUSBDevice::VendorID() const
|
||||
{
|
||||
return fDescriptor.vendor_id;
|
||||
}
|
||||
|
||||
|
||||
uint16
|
||||
BUSBDevice::ProductID() const
|
||||
{
|
||||
return fDescriptor.product_id;
|
||||
}
|
||||
|
||||
|
||||
uint16
|
||||
BUSBDevice::Version() const
|
||||
{
|
||||
return fDescriptor.device_version;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
BUSBDevice::ManufacturerString() const
|
||||
{
|
||||
if (fDescriptor.manufacturer == 0)
|
||||
return "";
|
||||
|
||||
if (fManufacturerString)
|
||||
return fManufacturerString;
|
||||
|
||||
fManufacturerString = DecodeStringDescriptor(fDescriptor.manufacturer);
|
||||
if (!fManufacturerString) {
|
||||
fManufacturerString = new char[1];
|
||||
fManufacturerString[0] = 0;
|
||||
}
|
||||
|
||||
return fManufacturerString;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
BUSBDevice::ProductString() const
|
||||
{
|
||||
if (fDescriptor.product == 0)
|
||||
return "";
|
||||
|
||||
if (fProductString)
|
||||
return fProductString;
|
||||
|
||||
fProductString = DecodeStringDescriptor(fDescriptor.product);
|
||||
if (!fProductString) {
|
||||
fProductString = new char[1];
|
||||
fProductString[0] = 0;
|
||||
}
|
||||
|
||||
return fProductString;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
BUSBDevice::SerialNumberString() const
|
||||
{
|
||||
if (fDescriptor.serial_number == 0)
|
||||
return "";
|
||||
|
||||
if (fSerialNumberString)
|
||||
return fSerialNumberString;
|
||||
|
||||
fSerialNumberString = DecodeStringDescriptor(fDescriptor.serial_number);
|
||||
if (!fSerialNumberString) {
|
||||
fSerialNumberString = new char[1];
|
||||
fSerialNumberString[0] = 0;
|
||||
}
|
||||
|
||||
return fSerialNumberString;
|
||||
}
|
||||
|
||||
|
||||
const usb_device_descriptor *
|
||||
BUSBDevice::Descriptor() const
|
||||
{
|
||||
return &fDescriptor;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
BUSBDevice::GetStringDescriptor(uint32 index,
|
||||
usb_string_descriptor *descriptor, size_t length) const
|
||||
{
|
||||
if (!descriptor)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
raw_command command;
|
||||
command.string.descriptor = descriptor;
|
||||
command.string.string_index = index;
|
||||
command.string.length = length;
|
||||
|
||||
if (ioctl(fRawFD, RAW_COMMAND_GET_STRING_DESCRIPTOR, &command, sizeof(command))
|
||||
|| command.string.status != RAW_STATUS_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return command.string.length;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
BUSBDevice::DecodeStringDescriptor(uint32 index) const
|
||||
{
|
||||
char buffer[300];
|
||||
usb_string_descriptor *stringDescriptor;
|
||||
stringDescriptor = (usb_string_descriptor *)&buffer;
|
||||
|
||||
size_t stringLength = GetStringDescriptor(index, stringDescriptor,
|
||||
sizeof(buffer) - sizeof(usb_string_descriptor));
|
||||
|
||||
if (stringLength < 3)
|
||||
return NULL;
|
||||
|
||||
// pseudo convert unicode string
|
||||
stringLength = (stringLength - 2) / 2;
|
||||
char *result = new char[stringLength + 1];
|
||||
for (size_t i = 0; i < stringLength; i++)
|
||||
result[i] = stringDescriptor->string[i * 2];
|
||||
result[stringLength] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
BUSBDevice::GetDescriptor(uint8 type, uint8 index, uint16 languageID,
|
||||
void *data, size_t length) const
|
||||
{
|
||||
if (length > 0 && data == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
raw_command command;
|
||||
command.descriptor.type = type;
|
||||
command.descriptor.index = index;
|
||||
command.descriptor.language_id = languageID;
|
||||
command.descriptor.data = data;
|
||||
command.descriptor.length = length;
|
||||
|
||||
if (ioctl(fRawFD, RAW_COMMAND_GET_DESCRIPTOR, &command, sizeof(command))
|
||||
|| command.descriptor.status != RAW_STATUS_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return command.descriptor.length;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
BUSBDevice::CountConfigurations() const
|
||||
{
|
||||
return fDescriptor.num_configurations;
|
||||
}
|
||||
|
||||
|
||||
const BUSBConfiguration *
|
||||
BUSBDevice::ConfigurationAt(uint32 index) const
|
||||
{
|
||||
if (index >= fDescriptor.num_configurations)
|
||||
return NULL;
|
||||
|
||||
return fConfigurations[index];
|
||||
}
|
||||
|
||||
|
||||
const BUSBConfiguration *
|
||||
BUSBDevice::ActiveConfiguration() const
|
||||
{
|
||||
return fConfigurations[fActiveConfiguration];
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BUSBDevice::SetConfiguration(const BUSBConfiguration *configuration)
|
||||
{
|
||||
if (!configuration || configuration->Index() >= fDescriptor.num_configurations)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
raw_command command;
|
||||
command.config.config_index = configuration->Index();
|
||||
|
||||
if (ioctl(fRawFD, RAW_COMMAND_SET_CONFIGURATION, &command, sizeof(command))
|
||||
|| command.config.status != RAW_STATUS_SUCCESS) {
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
fActiveConfiguration = configuration->Index();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
BUSBDevice::ControlTransfer(uint8 requestType, uint8 request, uint16 value,
|
||||
uint16 index, uint16 length, void *data) const
|
||||
{
|
||||
if (length > 0 && data == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
raw_command command;
|
||||
command.control.request_type = requestType;
|
||||
command.control.request = request;
|
||||
command.control.value = value;
|
||||
command.control.index = index;
|
||||
command.control.length = length;
|
||||
command.control.data = data;
|
||||
|
||||
if (ioctl(fRawFD, RAW_COMMAND_CONTROL_TRANSFER, &command, sizeof(command))
|
||||
|| command.control.status != RAW_STATUS_SUCCESS) {
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
return command.control.length;
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
#include <USBKit.h>
|
||||
#include <usb_raw.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
BUSBEndpoint::BUSBEndpoint(BUSBInterface *interface, uint32 index, int rawFD)
|
||||
: fInterface(interface),
|
||||
fIndex(index),
|
||||
fRawFD(rawFD)
|
||||
{
|
||||
raw_command command;
|
||||
command.endpoint.descriptor = &fDescriptor;
|
||||
command.endpoint.config_index = fInterface->Configuration()->Index();
|
||||
command.endpoint.interface_index = fInterface->Index();
|
||||
command.endpoint.endpoint_index = fIndex;
|
||||
if (ioctl(fRawFD, RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR, &command, sizeof(command))
|
||||
|| command.config.status != RAW_STATUS_SUCCESS) {
|
||||
memset(&fDescriptor, 0, sizeof(fDescriptor));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BUSBEndpoint::~BUSBEndpoint()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
BUSBEndpoint::Index() const
|
||||
{
|
||||
return fIndex;
|
||||
}
|
||||
|
||||
|
||||
const BUSBInterface *
|
||||
BUSBEndpoint::Interface() const
|
||||
{
|
||||
return fInterface;
|
||||
}
|
||||
|
||||
|
||||
const BUSBConfiguration *
|
||||
BUSBEndpoint::Configuration() const
|
||||
{
|
||||
return fInterface->Configuration();
|
||||
}
|
||||
|
||||
|
||||
const BUSBDevice *
|
||||
BUSBEndpoint::Device() const
|
||||
{
|
||||
return fInterface->Device();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BUSBEndpoint::IsBulk() const
|
||||
{
|
||||
return (fDescriptor.attributes & USB_ENDPOINT_ATTR_MASK) == USB_ENDPOINT_ATTR_BULK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BUSBEndpoint::IsInterrupt() const
|
||||
{
|
||||
return (fDescriptor.attributes & USB_ENDPOINT_ATTR_MASK) == USB_ENDPOINT_ATTR_INTERRUPT;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BUSBEndpoint::IsIsochronous() const
|
||||
{
|
||||
return (fDescriptor.attributes & USB_ENDPOINT_ATTR_MASK) == USB_ENDPOINT_ATTR_ISOCHRONOUS;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BUSBEndpoint::IsControl() const
|
||||
{
|
||||
return (fDescriptor.attributes & USB_ENDPOINT_ATTR_MASK) == USB_ENDPOINT_ATTR_CONTROL;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BUSBEndpoint::IsInput() const
|
||||
{
|
||||
return (fDescriptor.endpoint_address & USB_ENDPOINT_ADDR_DIR_IN) == USB_ENDPOINT_ADDR_DIR_IN;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BUSBEndpoint::IsOutput() const
|
||||
{
|
||||
return (fDescriptor.endpoint_address & USB_ENDPOINT_ADDR_DIR_IN) == USB_ENDPOINT_ADDR_DIR_OUT;
|
||||
}
|
||||
|
||||
|
||||
uint16
|
||||
BUSBEndpoint::MaxPacketSize() const
|
||||
{
|
||||
return fDescriptor.max_packet_size;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
BUSBEndpoint::Interval() const
|
||||
{
|
||||
return fDescriptor.interval;
|
||||
}
|
||||
|
||||
|
||||
const usb_endpoint_descriptor *
|
||||
BUSBEndpoint::Descriptor() const
|
||||
{
|
||||
return &fDescriptor;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
BUSBEndpoint::ControlTransfer(uint8 requestType, uint8 request, uint16 value,
|
||||
uint16 index, uint16 length, void *data) const
|
||||
{
|
||||
if (length > 0 && data == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
raw_command command;
|
||||
command.control.request_type = requestType;
|
||||
command.control.request = request;
|
||||
command.control.value = value;
|
||||
command.control.index = index;
|
||||
command.control.length = length;
|
||||
command.control.data = data;
|
||||
|
||||
if (ioctl(fRawFD, RAW_COMMAND_CONTROL_TRANSFER, &command, sizeof(command))
|
||||
|| command.control.status != RAW_STATUS_SUCCESS) {
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
return command.control.length;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
BUSBEndpoint::InterruptTransfer(void *data, size_t length) const
|
||||
{
|
||||
if (length > 0 && data == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
raw_command command;
|
||||
command.transfer.interface = fInterface->Index();
|
||||
command.transfer.endpoint = fIndex;
|
||||
command.transfer.data = data;
|
||||
command.transfer.length = length;
|
||||
|
||||
if (ioctl(fRawFD, RAW_COMMAND_INTERRUPT_TRANSFER, &command, sizeof(command))
|
||||
|| command.transfer.status != RAW_STATUS_SUCCESS) {
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
return command.transfer.length;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
BUSBEndpoint::BulkTransfer(void *data, size_t length) const
|
||||
{
|
||||
if (length > 0 && data == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
raw_command command;
|
||||
command.transfer.interface = fInterface->Index();
|
||||
command.transfer.endpoint = fIndex;
|
||||
command.transfer.data = data;
|
||||
command.transfer.length = length;
|
||||
|
||||
if (ioctl(fRawFD, RAW_COMMAND_BULK_TRANSFER, &command, sizeof(command))
|
||||
|| command.transfer.status != RAW_STATUS_SUCCESS) {
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
return command.transfer.length;
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
#include <USBKit.h>
|
||||
#include <usb_raw.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
BUSBInterface::BUSBInterface(BUSBConfiguration *config, uint32 index, int rawFD)
|
||||
: fConfiguration(config),
|
||||
fIndex(index),
|
||||
fRawFD(rawFD),
|
||||
fEndpoints(NULL),
|
||||
fInterfaceString(NULL)
|
||||
{
|
||||
raw_command command;
|
||||
command.interface.descriptor = &fDescriptor;
|
||||
command.interface.config_index = fConfiguration->Index();
|
||||
command.interface.interface_index = fIndex;
|
||||
if (ioctl(fRawFD, RAW_COMMAND_GET_INTERFACE_DESCRIPTOR, &command, sizeof(command))
|
||||
|| command.interface.status != RAW_STATUS_SUCCESS) {
|
||||
memset(&fDescriptor, 0, sizeof(fDescriptor));
|
||||
}
|
||||
|
||||
fEndpoints = new BUSBEndpoint *[fDescriptor.num_endpoints];
|
||||
for (int32 i = 0; i < fDescriptor.num_endpoints; i++)
|
||||
fEndpoints[i] = new BUSBEndpoint(this, i, fRawFD);
|
||||
}
|
||||
|
||||
|
||||
BUSBInterface::~BUSBInterface()
|
||||
{
|
||||
delete[] fInterfaceString;
|
||||
for (int32 i = 0; i < fDescriptor.num_endpoints; i++)
|
||||
delete fEndpoints[i];
|
||||
delete[] fEndpoints;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
BUSBInterface::Index() const
|
||||
{
|
||||
return fIndex;
|
||||
}
|
||||
|
||||
|
||||
const BUSBConfiguration *
|
||||
BUSBInterface::Configuration() const
|
||||
{
|
||||
return fConfiguration;
|
||||
}
|
||||
|
||||
|
||||
const BUSBDevice *
|
||||
BUSBInterface::Device() const
|
||||
{
|
||||
return fConfiguration->Device();
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
BUSBInterface::Class() const
|
||||
{
|
||||
return fDescriptor.interface_class;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
BUSBInterface::Subclass() const
|
||||
{
|
||||
return fDescriptor.interface_subclass;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
BUSBInterface::Protocol() const
|
||||
{
|
||||
return fDescriptor.interface_protocol;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
BUSBInterface::InterfaceString() const
|
||||
{
|
||||
if (fDescriptor.interface == 0)
|
||||
return "";
|
||||
|
||||
if (fInterfaceString)
|
||||
return fInterfaceString;
|
||||
|
||||
fInterfaceString = Device()->DecodeStringDescriptor(fDescriptor.interface);
|
||||
if (!fInterfaceString) {
|
||||
fInterfaceString = new char[1];
|
||||
fInterfaceString[0] = 0;
|
||||
}
|
||||
|
||||
return fInterfaceString;
|
||||
}
|
||||
|
||||
|
||||
const usb_interface_descriptor *
|
||||
BUSBInterface::Descriptor() const
|
||||
{
|
||||
return &fDescriptor;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BUSBInterface::OtherDescriptorAt(uint32 index, usb_descriptor *descriptor,
|
||||
size_t length) const
|
||||
{
|
||||
if (length > 0 && descriptor == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
raw_command command;
|
||||
command.generic.descriptor = descriptor;
|
||||
command.generic.config_index = fConfiguration->Index();
|
||||
command.generic.interface_index = fIndex;
|
||||
command.generic.length = length;
|
||||
if (ioctl(fRawFD, RAW_COMMAND_GET_GENERIC_DESCRIPTOR, &command, sizeof(command))
|
||||
|| command.generic.status != RAW_STATUS_SUCCESS) {
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
BUSBInterface::CountEndpoints() const
|
||||
{
|
||||
return fDescriptor.num_endpoints;
|
||||
}
|
||||
|
||||
|
||||
const BUSBEndpoint *
|
||||
BUSBInterface::EndpointAt(uint32 index) const
|
||||
{
|
||||
if (index >= fDescriptor.num_endpoints)
|
||||
return NULL;
|
||||
|
||||
return fEndpoints[index];
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
#include <USBKit.h>
|
||||
#include <usb_raw.h>
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <Looper.h>
|
||||
#include <Messenger.h>
|
||||
#include <Node.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <Path.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
class WatchedEntry {
|
||||
public:
|
||||
WatchedEntry(BUSBRoster *roster,
|
||||
BMessenger *messenger, entry_ref *ref);
|
||||
~WatchedEntry();
|
||||
|
||||
bool EntryCreated(entry_ref *ref);
|
||||
bool EntryRemoved(ino_t node);
|
||||
|
||||
private:
|
||||
BUSBRoster *fRoster;
|
||||
BMessenger *fMessenger;
|
||||
|
||||
node_ref fNode;
|
||||
bool fIsDirectory;
|
||||
BUSBDevice *fDevice;
|
||||
|
||||
WatchedEntry *fEntries;
|
||||
WatchedEntry *fLink;
|
||||
};
|
||||
|
||||
|
||||
class RosterLooper : public BLooper {
|
||||
public:
|
||||
RosterLooper(BUSBRoster *roster);
|
||||
|
||||
void Stop();
|
||||
|
||||
virtual void MessageReceived(BMessage *message);
|
||||
|
||||
private:
|
||||
BUSBRoster *fRoster;
|
||||
WatchedEntry *fRoot;
|
||||
BMessenger *fMessenger;
|
||||
};
|
||||
|
||||
|
||||
WatchedEntry::WatchedEntry(BUSBRoster *roster, BMessenger *messenger,
|
||||
entry_ref *ref)
|
||||
: fRoster(roster),
|
||||
fMessenger(messenger),
|
||||
fIsDirectory(false),
|
||||
fDevice(NULL),
|
||||
fEntries(NULL),
|
||||
fLink(NULL)
|
||||
{
|
||||
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 WatchedEntry(fRoster, fMessenger, ref);
|
||||
child->fLink = fEntries;
|
||||
fEntries = child;
|
||||
}
|
||||
|
||||
watch_node(&fNode, B_WATCH_DIRECTORY, *fMessenger);
|
||||
} else {
|
||||
// filter pseudoentry that only handles ioctls
|
||||
if (strncmp(ref->name, "raw", 3) == 0)
|
||||
return;
|
||||
|
||||
BPath path;
|
||||
entry.GetPath(&path);
|
||||
fDevice = new BUSBDevice(path.Path());
|
||||
if (fRoster->DeviceAdded(fDevice) != B_OK) {
|
||||
delete fDevice;
|
||||
fDevice = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
fRoster->DeviceRemoved(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 WatchedEntry(fRoster, fMessenger, ref);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
RosterLooper::RosterLooper(BUSBRoster *roster)
|
||||
: fRoster(roster),
|
||||
fRoot(NULL),
|
||||
fMessenger(NULL)
|
||||
{
|
||||
BEntry entry("/dev/bus/usb");
|
||||
if (!entry.Exists()) {
|
||||
fprintf(stderr, "USBKit: usb_raw not published");
|
||||
return;
|
||||
}
|
||||
|
||||
Run();
|
||||
fMessenger = new BMessenger(this);
|
||||
|
||||
if (Lock()) {
|
||||
entry_ref ref;
|
||||
entry.GetRef(&ref);
|
||||
fRoot = new WatchedEntry(fRoster, fMessenger, &ref);
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RosterLooper::Stop()
|
||||
{
|
||||
Lock();
|
||||
delete fRoot;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BUSBRoster::BUSBRoster()
|
||||
: fLooper(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BUSBRoster::~BUSBRoster()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BUSBRoster::Start()
|
||||
{
|
||||
if (fLooper)
|
||||
return;
|
||||
|
||||
fLooper = new RosterLooper(this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BUSBRoster::Stop()
|
||||
{
|
||||
if (!fLooper)
|
||||
return;
|
||||
|
||||
((RosterLooper *)fLooper)->Stop();
|
||||
fLooper = NULL;
|
||||
}
|
||||
Reference in New Issue
Block a user