Adding USB ECM (Ethernet Control Model) driver. This driver should support

devices of the CDC class (2 - communication) with ECM subclass (6) interfaces.
This type of device can be for example a USB to ethernet adapter or current
UMTS cell phones that support the Wireless Mobile Communications Devices (WMC)
standard.
Note that there is also another, similar, thing called EEM (Ethernet Emulation
Model) which we want to support too and is why I called this driver "usb_ecm"
instead of just "usb_network".
This driver was written in less than half a day and while it works nicely with
my Sony Ericsson K850i (comitting over this very device/driver), it does not
yet contain features like link state reporting and multicast and may obviously
contain a few bugs.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25439 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2008-05-10 23:50:41 +00:00
parent 3560b757c2
commit 745c6cce89
8 changed files with 894 additions and 0 deletions

View File

@ -7,6 +7,7 @@ SubInclude HAIKU_TOP src add-ons kernel drivers network pegasus ;
SubInclude HAIKU_TOP src add-ons kernel drivers network rtl8139 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network rtl8169 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network sis900 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network usb_ecm ;
SubInclude HAIKU_TOP src add-ons kernel drivers network via_rhine ;
SubInclude HAIKU_TOP src add-ons kernel drivers network vlance ;
SubInclude HAIKU_TOP src add-ons kernel drivers network wb840 ;

View File

@ -0,0 +1,59 @@
/*
Driver for USB Ethernet Control Model devices
Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
Distributed under the terms of the MIT license.
*/
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
#ifndef _BEOS_COMPATIBILITY_H_
#define _BEOS_COMPATIBILITY_H_
#include <OS.h>
#define USB_ENDPOINT_ATTR_CONTROL 0x00
#define USB_ENDPOINT_ATTR_ISOCHRONOUS 0x01
#define USB_ENDPOINT_ATTR_BULK 0x02
#define USB_ENDPOINT_ATTR_INTERRUPT 0x03
#define USB_ENDPOINT_ATTR_MASK 0x03
#define USB_ENDPOINT_ADDR_DIR_IN 0x80
#define USB_ENDPOINT_ADDR_DIR_OUT 0x00
typedef struct mutex {
sem_id sem;
int32 count;
} mutex;
static inline void
mutex_init(mutex *lock, const char *name)
{
lock->sem = create_sem(0, name);
lock->count = 0;
}
static inline void
mutex_destroy(mutex *lock)
{
delete_sem(lock->sem);
}
static inline status_t
mutex_lock(mutex *lock)
{
if (atomic_add(&lock->count, -1) < 0)
return acquire_sem(lock->sem);
return B_OK;
}
static inline void
mutex_unlock(mutex *lock)
{
if (atomic_add(&lock->count, 1) < -1)
release_sem(lock->sem);
}
#endif /* !HAIKU_TARGET_PLATFORM_HAIKU */
#endif /* _BEOS_COMPATIBILITY_H_ */

View File

@ -0,0 +1,273 @@
/*
Driver for USB Ethernet Control Model devices
Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
Distributed under the terms of the MIT license.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
#include <lock.h> // for mutex
#else
#include "BeOSCompatibility.h" // for pseudo mutex
#endif
#include "Driver.h"
#include "ECMDevice.h"
static const char *sDeviceBaseName = "net/usb_ecm/";
ECMDevice *gECMDevices[MAX_DEVICES];
char *gDeviceNames[MAX_DEVICES + 1];
usb_module_info *gUSBModule = NULL;
mutex gDriverLock;
status_t
usb_ecm_device_added(usb_device device, void **cookie)
{
*cookie = NULL;
ECMDevice *ecmDevice = new ECMDevice(device);
status_t status = ecmDevice->InitCheck();
if (status < B_OK) {
delete ecmDevice;
return status;
}
mutex_lock(&gDriverLock);
for (int32 i = 0; i < MAX_DEVICES; i++) {
if (gECMDevices[i] != NULL)
continue;
gECMDevices[i] = ecmDevice;
*cookie = ecmDevice;
TRACE_ALWAYS("ecm device %ld added\n", i);
mutex_unlock(&gDriverLock);
return B_OK;
}
// no space for the device
delete ecmDevice;
mutex_unlock(&gDriverLock);
return B_ERROR;
}
status_t
usb_ecm_device_removed(void *cookie)
{
mutex_lock(&gDriverLock);
ECMDevice *device = (ECMDevice *)cookie;
for (int32 i = 0; i < MAX_DEVICES; i++) {
if (gECMDevices[i] == device) {
if (device->IsOpen()) {
// the device will be deleted upon being freed
device->Removed();
} else {
gECMDevices[i] = NULL;
delete device;
}
break;
}
}
mutex_unlock(&gDriverLock);
return B_OK;
}
//#pragma mark -
status_t
init_hardware()
{
TRACE("init_hardware()\n");
return B_OK;
}
status_t
init_driver()
{
TRACE("init_driver()\n");
status_t status = get_module(B_USB_MODULE_NAME,
(module_info **)&gUSBModule);
if (status < B_OK)
return status;
for (int32 i = 0; i < MAX_DEVICES; i++)
gECMDevices[i] = NULL;
gDeviceNames[0] = NULL;
mutex_init(&gDriverLock, DRIVER_NAME"_devices");
static usb_notify_hooks notifyHooks = {
&usb_ecm_device_added,
&usb_ecm_device_removed
};
static usb_support_descriptor supportDescriptor = {
USB_INTERFACE_CLASS_CDC, /* CDC - Communication Device Class */
USB_INTERFACE_SUBCLASS_ECM, /* ECM - Ethernet Control Model */
0, 0, 0 /* no protocol, vendor or device */
};
gUSBModule->register_driver(DRIVER_NAME, &supportDescriptor, 1, NULL);
gUSBModule->install_notify(DRIVER_NAME, &notifyHooks);
return B_OK;
}
void
uninit_driver()
{
TRACE("uninit_driver()\n");
gUSBModule->uninstall_notify(DRIVER_NAME);
mutex_lock(&gDriverLock);
for (int32 i = 0; i < MAX_DEVICES; i++) {
if (gECMDevices[i]) {
delete gECMDevices[i];
gECMDevices[i] = NULL;
}
}
for (int32 i = 0; gDeviceNames[i]; i++) {
free(gDeviceNames[i]);
gDeviceNames[i] = NULL;
}
mutex_destroy(&gDriverLock);
put_module(B_USB_MODULE_NAME);
}
static status_t
usb_ecm_open(const char *name, uint32 flags, void **cookie)
{
TRACE("open(%s, %lu, %p)\n", name, flags, cookie);
mutex_lock(&gDriverLock);
*cookie = NULL;
status_t status = ENODEV;
int32 index = strtol(name + strlen(sDeviceBaseName), NULL, 10);
if (index >= 0 && index < MAX_DEVICES && gECMDevices[index]) {
status = gECMDevices[index]->Open(flags);
*cookie = gECMDevices[index];
}
mutex_unlock(&gDriverLock);
return status;
}
static status_t
usb_ecm_read(void *cookie, off_t position, void *buffer, size_t *numBytes)
{
TRACE("read(%p, %Ld, %p, %lu)\n", cookie, position, buffer, *numBytes);
ECMDevice *device = (ECMDevice *)cookie;
return device->Read((uint8 *)buffer, numBytes);
}
static status_t
usb_ecm_write(void *cookie, off_t position, const void *buffer,
size_t *numBytes)
{
TRACE("write(%p, %Ld, %p, %lu)\n", cookie, position, buffer, *numBytes);
ECMDevice *device = (ECMDevice *)cookie;
return device->Write((const uint8 *)buffer, numBytes);
}
static status_t
usb_ecm_control(void *cookie, uint32 op, void *buffer, size_t length)
{
TRACE("control(%p, %lu, %p, %lu)\n", cookie, op, buffer, length);
ECMDevice *device = (ECMDevice *)cookie;
return device->Control(op, buffer, length);
}
static status_t
usb_ecm_close(void *cookie)
{
TRACE("close(%p)\n", cookie);
ECMDevice *device = (ECMDevice *)cookie;
return device->Close();
}
static status_t
usb_ecm_free(void *cookie)
{
TRACE("free(%p)\n", cookie);
ECMDevice *device = (ECMDevice *)cookie;
mutex_lock(&gDriverLock);
status_t status = device->Free();
for (int32 i = 0; i < MAX_DEVICES; i++) {
if (gECMDevices[i] == device) {
// the device is removed already but as it was open the
// removed hook has not deleted the object
gECMDevices[i] = NULL;
delete device;
break;
}
}
mutex_unlock(&gDriverLock);
return status;
}
const char **
publish_devices()
{
TRACE("publish_devices()\n");
for (int32 i = 0; gDeviceNames[i]; i++) {
free(gDeviceNames[i]);
gDeviceNames[i] = NULL;
}
int32 deviceCount = 0;
mutex_lock(&gDriverLock);
for (int32 i = 0; i < MAX_DEVICES; i++) {
if (gECMDevices[i] == NULL)
continue;
gDeviceNames[deviceCount] = (char *)malloc(strlen(sDeviceBaseName) + 4);
if (gDeviceNames[deviceCount]) {
sprintf(gDeviceNames[deviceCount], "%s%ld", sDeviceBaseName, i);
TRACE("publishing %s\n", gDeviceNames[deviceCount]);
deviceCount++;
} else
TRACE_ALWAYS("publish_devices - no memory to allocate device name\n");
}
gDeviceNames[deviceCount] = NULL;
mutex_unlock(&gDriverLock);
return (const char **)&gDeviceNames[0];
}
device_hooks *
find_device(const char *name)
{
TRACE("find_device(%s)\n", name);
static device_hooks deviceHooks = {
usb_ecm_open,
usb_ecm_close,
usb_ecm_free,
usb_ecm_control,
usb_ecm_read,
usb_ecm_write,
NULL, /* select */
NULL /* deselect */
};
return &deviceHooks;
}

View File

@ -0,0 +1,61 @@
/*
Driver for USB Ethernet Control Model devices
Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
Distributed under the terms of the MIT license.
*/
#ifndef _USB_ECM_DRIVER_H_
#define _USB_ECM_DRIVER_H_
#include <Drivers.h>
#include <KernelExport.h>
#include <OS.h>
#include <USB3.h>
#include "kernel_cpp.h"
#define DRIVER_NAME "usb_ecm"
#define MAX_DEVICES 8
/* class and subclass codes */
#define USB_INTERFACE_CLASS_CDC 0x02
#define USB_INTERFACE_SUBCLASS_ECM 0x06
#define USB_INTERFACE_CLASS_CDC_DATA 0x0a
#define USB_INTERFACE_SUBCLASS_DATA 0x00
/* communication device descriptor subtypes */
#define FUNCTIONAL_SUBTYPE_UNION 0x06
#define FUNCTIONAL_SUBTYPE_ETHERNET 0x0f
typedef struct ethernet_functional_descriptor_s {
uint8 functional_descriptor_subtype;
uint8 mac_address_index;
uint32 ethernet_statistics;
uint16 max_segment_size;
uint16 num_multi_cast_filters;
uint8 num_wakeup_pattern_filters;
} _PACKED ethernet_functional_descriptor;
extern usb_module_info *gUSBModule;
extern "C" {
status_t usb_ecm_device_added(usb_device device, void **cookie);
status_t usb_ecm_device_removed(void *cookie);
status_t init_hardware();
void uninit_driver();
status_t usb_ecm_open(const char *name, uint32 flags, void **cookie);
status_t usb_ecm_read(void *cookie, off_t position, void *buffer, size_t *numBytes);
status_t usb_ecm_write(void *cookie, off_t position, const void *buffer, size_t *numBytes);
status_t usb_ecm_control(void *cookie, uint32 op, void *buffer, size_t length);
status_t usb_ecm_close(void *cookie);
status_t usb_ecm_free(void *cookie);
const char **publish_devices();
device_hooks *find_device(const char *name);
}
#define TRACE(x...) /*dprintf(DRIVER_NAME ": " x)*/
#define TRACE_ALWAYS(x...) dprintf(DRIVER_NAME ": " x)
#endif //_USB_ECM_DRIVER_H_

View File

@ -0,0 +1,382 @@
/*
Driver for USB Ethernet Control Model devices
Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
Distributed under the terms of the MIT license.
*/
#include <ether_driver.h>
#include <string.h>
#include <stdlib.h>
#include "BeOSCompatibility.h"
#include "ECMDevice.h"
#include "Driver.h"
ECMDevice::ECMDevice(usb_device device)
: fStatus(B_ERROR),
fOpen(false),
fRemoved(false),
fDevice(device),
fControlInterfaceIndex(0),
fDataInterfaceIndex(0),
fMACAddressIndex(0),
fMaxSegmentSize(0),
fControlEndpoint(0),
fReadEndpoint(0),
fWriteEndpoint(0)
{
const usb_device_descriptor *deviceDescriptor
= gUSBModule->get_device_descriptor(device);
const usb_configuration_info *config
= gUSBModule->get_nth_configuration(device, 0);
if (deviceDescriptor == NULL || config == NULL) {
TRACE_ALWAYS("failed to get basic device info\n");
return;
}
TRACE_ALWAYS("creating device: vendor: 0x%04x; device: 0x%04x\n",
deviceDescriptor->vendor_id, deviceDescriptor->product_id);
uint8 controlIndex = 0;
uint8 dataIndex = 0;
bool foundUnionDescriptor = false;
bool foundEthernetDescriptor = false;
for (size_t i = 0; i < config->interface_count
&& (!foundUnionDescriptor || !foundEthernetDescriptor); i++) {
usb_interface_info *interface = config->interface[i].active;
usb_interface_descriptor *descriptor = interface->descr;
if (descriptor->interface_class == USB_INTERFACE_CLASS_CDC
&& descriptor->interface_subclass == USB_INTERFACE_SUBCLASS_ECM
&& interface->generic_count > 0) {
// try to find and interpret the union and ethernet functional
// descriptors
for (size_t j = 0; j < interface->generic_count; j++) {
usb_generic_descriptor *generic = &interface->generic[j]->generic;
if (generic->length >= 5
&& generic->data[0] == FUNCTIONAL_SUBTYPE_UNION) {
controlIndex = generic->data[1];
dataIndex = generic->data[2];
foundUnionDescriptor = true;
} else if (generic->length >= sizeof(ethernet_functional_descriptor)
&& generic->data[0] == FUNCTIONAL_SUBTYPE_ETHERNET) {
ethernet_functional_descriptor *ethernet
= (ethernet_functional_descriptor *)generic->data;
fMACAddressIndex = ethernet->mac_address_index;
fMaxSegmentSize = ethernet->max_segment_size;
foundEthernetDescriptor = true;
}
if (foundUnionDescriptor && foundEthernetDescriptor)
break;
}
}
}
if (!foundUnionDescriptor) {
TRACE_ALWAYS("did not find a union descriptor\n");
return;
}
if (!foundEthernetDescriptor) {
TRACE_ALWAYS("did not find an ethernet descriptor\n");
return;
}
if (_ReadMACAddress() != B_OK) {
TRACE_ALWAYS("failed to read mac address\n");
return;
}
if (controlIndex >= config->interface_count) {
TRACE_ALWAYS("control interface index invalid\n");
return;
}
// check that the indicated control interface fits our needs
usb_interface_info *interface = config->interface[controlIndex].active;
usb_interface_descriptor *descriptor = interface->descr;
if ((descriptor->interface_class != USB_INTERFACE_CLASS_CDC
|| descriptor->interface_subclass != USB_INTERFACE_SUBCLASS_ECM)
|| interface->endpoint_count == 0) {
TRACE_ALWAYS("control interface invalid\n");
return;
}
fControlInterfaceIndex = controlIndex;
fControlEndpoint = interface->endpoint[0].handle;
if (dataIndex >= config->interface_count) {
TRACE_ALWAYS("data interface index invalid\n");
return;
}
// check that the indicated data interface fits our needs
if (config->interface[dataIndex].alt_count < 2) {
TRACE_ALWAYS("data interface does not provide two alternate interfaces\n");
return;
}
// alternate 0 is the disabled, endpoint-less default interface
interface = &config->interface[dataIndex].alt[1];
descriptor = interface->descr;
if (descriptor->interface_class != USB_INTERFACE_CLASS_CDC_DATA
|| interface->endpoint_count < 2) {
TRACE_ALWAYS("data interface invalid\n");
return;
}
fDataInterfaceIndex = dataIndex;
fNotifyRead = create_sem(0, DRIVER_NAME"_notify_read");
if (fNotifyRead < B_OK) {
TRACE_ALWAYS("failed to create read notify sem\n");
return;
}
fNotifyWrite = create_sem(0, DRIVER_NAME"_notify_write");
if (fNotifyWrite < B_OK) {
TRACE_ALWAYS("failed to create write notify sem\n");
delete_sem(fNotifyRead);
return;
}
fStatus = B_OK;
}
ECMDevice::~ECMDevice()
{
delete_sem(fNotifyRead);
delete_sem(fNotifyWrite);
}
status_t
ECMDevice::Open(uint32 flags)
{
if (fOpen)
return B_BUSY;
// reset the device by switching the data interface to the disabled first
// interface and then enable it by setting the second actual data interface
const usb_configuration_info *config
= gUSBModule->get_nth_configuration(fDevice, 0);
gUSBModule->set_alt_interface(fDevice,
&config->interface[fDataInterfaceIndex].alt[0]);
// update to the changed config
config = gUSBModule->get_nth_configuration(fDevice, 0);
gUSBModule->set_alt_interface(fDevice,
&config->interface[fDataInterfaceIndex].alt[1]);
// update again
config = gUSBModule->get_nth_configuration(fDevice, 0);
usb_interface_info *interface = config->interface[fDataInterfaceIndex].active;
if (interface->endpoint_count < 2) {
TRACE_ALWAYS("setting the data alternate interface failed\n");
return B_ERROR;
}
if (!(interface->endpoint[0].descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN))
fWriteEndpoint = interface->endpoint[0].handle;
else
fReadEndpoint = interface->endpoint[0].handle;
if (interface->endpoint[1].descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN)
fReadEndpoint = interface->endpoint[1].handle;
else
fWriteEndpoint = interface->endpoint[1].handle;
if (fReadEndpoint == 0 || fWriteEndpoint == 0) {
TRACE_ALWAYS("no read and write endpoints found\n");
return B_ERROR;
}
// the device should now be ready
fOpen = true;
return B_OK;
}
status_t
ECMDevice::Close()
{
if (fRemoved) {
fOpen = false;
return B_OK;
}
gUSBModule->cancel_queued_transfers(fReadEndpoint);
gUSBModule->cancel_queued_transfers(fWriteEndpoint);
// put the device into non-connected mode again by switching the data
// interface to the disabled alternate
const usb_configuration_info *config
= gUSBModule->get_nth_configuration(fDevice, 0);
gUSBModule->set_alt_interface(fDevice,
&config->interface[fDataInterfaceIndex].alt[0]);
fOpen = false;
return B_OK;
}
status_t
ECMDevice::Free()
{
return B_OK;
}
status_t
ECMDevice::Read(uint8 *buffer, size_t *numBytes)
{
if (fRemoved) {
*numBytes = 0;
return B_ERROR;
}
status_t result = gUSBModule->queue_bulk(fReadEndpoint, buffer, *numBytes,
_ReadCallback, this);
if (result != B_OK) {
*numBytes = 0;
return result;
}
result = acquire_sem_etc(fNotifyRead, 1, B_CAN_INTERRUPT, 0);
if (result < B_OK) {
*numBytes = 0;
return result;
}
if (fStatusRead != B_OK) {
TRACE_ALWAYS("device status error 0x%08lx\n", fStatusRead);
result = gUSBModule->clear_feature(fReadEndpoint,
USB_FEATURE_ENDPOINT_HALT);
if (result != B_OK) {
TRACE_ALWAYS("failed to clear halt state\n");
*numBytes = 0;
return result;
}
}
*numBytes = fActualLengthRead;
return B_OK;
}
status_t
ECMDevice::Write(const uint8 *buffer, size_t *numBytes)
{
if (fRemoved) {
*numBytes = 0;
return B_ERROR;
}
status_t result = gUSBModule->queue_bulk(fWriteEndpoint, (uint8 *)buffer,
*numBytes, _WriteCallback, this);
if (result != B_OK) {
*numBytes = 0;
return result;
}
result = acquire_sem_etc(fNotifyWrite, 1, B_CAN_INTERRUPT, 0);
if (result < B_OK) {
*numBytes = 0;
return result;
}
if (fStatusWrite != B_OK) {
TRACE_ALWAYS("device status error 0x%08lx\n", fStatusWrite);
result = gUSBModule->clear_feature(fWriteEndpoint,
USB_FEATURE_ENDPOINT_HALT);
if (result != B_OK) {
TRACE_ALWAYS("failed to clear halt state\n");
*numBytes = 0;
return result;
}
}
*numBytes = fActualLengthWrite;
return B_OK;
}
status_t
ECMDevice::Control(uint32 op, void *buffer, size_t length)
{
switch (op) {
case ETHER_INIT:
return B_OK;
case ETHER_GETADDR:
memcpy(buffer, &fMACAddress, sizeof(fMACAddress));
return B_OK;
case ETHER_GETFRAMESIZE:
*(uint32 *)buffer = fMaxSegmentSize;
return B_OK;
default:
TRACE_ALWAYS("unsupported ioctl %lu\n", op);
}
return B_DEV_INVALID_IOCTL;
}
status_t
ECMDevice::_ReadMACAddress()
{
if (fMACAddressIndex == 0)
return B_BAD_VALUE;
size_t actualLength = 0;
size_t macStringLength = 26;
uint8 macString[macStringLength];
status_t result = gUSBModule->get_descriptor(fDevice, USB_DESCRIPTOR_STRING,
fMACAddressIndex, 0, macString, macStringLength, &actualLength);
if (result != B_OK)
return result;
if (actualLength != macStringLength) {
TRACE_ALWAYS("did not retrieve full mac address\n");
return B_ERROR;
}
char macPart[3];
macPart[2] = 0;
for (int32 i = 0; i < 6; i++) {
macPart[0] = macString[2 + i * 4 + 0];
macPart[1] = macString[2 + i * 4 + 2];
fMACAddress[i] = strtol(macPart, NULL, 16);
}
TRACE_ALWAYS("read mac address: %02x:%02x:%02x:%02x:%02x:%02x\n",
fMACAddress[0], fMACAddress[1], fMACAddress[2], fMACAddress[3],
fMACAddress[4], fMACAddress[5]);
return B_OK;
}
void
ECMDevice::_ReadCallback(void *cookie, int32 status, void *data,
uint32 actualLength)
{
ECMDevice *device = (ECMDevice *)cookie;
device->fActualLengthRead = actualLength;
device->fStatusRead = status;
release_sem_etc(device->fNotifyRead, 1, B_DO_NOT_RESCHEDULE);
}
void
ECMDevice::_WriteCallback(void *cookie, int32 status, void *data,
uint32 actualLength)
{
ECMDevice *device = (ECMDevice *)cookie;
device->fActualLengthWrite = actualLength;
device->fStatusWrite = status;
release_sem_etc(device->fNotifyWrite, 1, B_DO_NOT_RESCHEDULE);
}

View File

@ -0,0 +1,63 @@
/*
Driver for USB Ethernet Control Model devices
Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
Distributed under the terms of the MIT license.
*/
#ifndef _USB_ECM_DEVICE_H_
#define _USB_ECM_DEVICE_H_
#include "Driver.h"
class ECMDevice {
public:
ECMDevice(usb_device device);
~ECMDevice();
status_t InitCheck() { return fStatus; };
status_t Open(uint32 flags);
bool IsOpen() { return fOpen; };
status_t Close();
status_t Free();
status_t Read(uint8 *buffer, size_t *numBytes);
status_t Write(const uint8 *buffer, size_t *numBytes);
status_t Control(uint32 op, void *buffer, size_t length);
void Removed() { fRemoved = true; };
bool IsRemoved() { return fRemoved; };
private:
static void _ReadCallback(void *cookie, int32 status,
void *data, uint32 actualLength);
static void _WriteCallback(void *cookie, int32 status,
void *data, uint32 actualLength);
status_t _ReadMACAddress();
status_t fStatus;
bool fOpen;
bool fRemoved;
usb_device fDevice;
uint8 fMACAddress[6];
uint8 fControlInterfaceIndex;
uint8 fDataInterfaceIndex;
uint8 fMACAddressIndex;
uint16 fMaxSegmentSize;
usb_pipe fControlEndpoint;
usb_pipe fReadEndpoint;
usb_pipe fWriteEndpoint;
uint32 fActualLengthRead;
uint32 fActualLengthWrite;
int32 fStatusRead;
int32 fStatusWrite;
sem_id fNotifyRead;
sem_id fNotifyWrite;
};
#endif //_USB_ECM_DEVICE_H_

View File

@ -0,0 +1,10 @@
SubDir HAIKU_TOP src add-ons kernel drivers network usb_ecm ;
SetSubDirSupportedPlatformsBeOSCompatible ;
UsePrivateHeaders kernel net ;
KernelAddon usb_ecm :
Driver.cpp
ECMDevice.cpp
;

View File

@ -0,0 +1,45 @@
#ifndef _KERNEL_CPP_H_
#define _KERNEL_CPP_H_
#include <malloc.h>
inline void *
operator new(size_t size)
{
return malloc(size);
}
inline void *
operator new[](size_t size)
{
return malloc(size);
}
inline void
operator delete(void *pointer)
{
free(pointer);
}
inline void
operator delete[](void *pointer)
{
free(pointer);
}
inline void
terminate(void)
{
}
static inline void
__throw()
{
}
#endif // _KERNEL_CPP_H_