2 Driver for USB Ethernet Control Model devices
3 Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
4 Distributed under the terms of the MIT license.
10 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
11 #include <lock.h> // for mutex
13 #include "BeOSCompatibility.h" // for pseudo mutex
17 #include "ECMDevice.h"
19 int32 api_version
= B_CUR_DRIVER_API_VERSION
;
20 static const char *sDeviceBaseName
= "net/usb_ecm/";
21 ECMDevice
*gECMDevices
[MAX_DEVICES
];
22 char *gDeviceNames
[MAX_DEVICES
+ 1];
23 usb_module_info
*gUSBModule
= NULL
;
28 usb_ecm_device_added(usb_device device
, void **cookie
)
32 // check if this is a replug of an existing device first
33 mutex_lock(&gDriverLock
);
34 for (int32 i
= 0; i
< MAX_DEVICES
; i
++) {
35 if (gECMDevices
[i
] == NULL
)
38 if (gECMDevices
[i
]->CompareAndReattach(device
) != B_OK
)
41 TRACE_ALWAYS("ecm device %" B_PRId32
" replugged\n", i
);
42 *cookie
= gECMDevices
[i
];
43 mutex_unlock(&gDriverLock
);
47 // no such device yet, create a new one
48 ECMDevice
*ecmDevice
= new ECMDevice(device
);
49 status_t status
= ecmDevice
->InitCheck();
52 mutex_unlock(&gDriverLock
);
56 for (int32 i
= 0; i
< MAX_DEVICES
; i
++) {
57 if (gECMDevices
[i
] != NULL
)
60 gECMDevices
[i
] = ecmDevice
;
63 TRACE_ALWAYS("ecm device %" B_PRId32
" added\n", i
);
64 mutex_unlock(&gDriverLock
);
68 // no space for the device
70 mutex_unlock(&gDriverLock
);
76 usb_ecm_device_removed(void *cookie
)
78 mutex_lock(&gDriverLock
);
80 ECMDevice
*device
= (ECMDevice
*)cookie
;
81 for (int32 i
= 0; i
< MAX_DEVICES
; i
++) {
82 if (gECMDevices
[i
] == device
) {
83 if (device
->IsOpen()) {
84 // the device will be deleted upon being freed
87 gECMDevices
[i
] = NULL
;
94 mutex_unlock(&gDriverLock
);
105 TRACE("init_hardware()\n");
113 TRACE("init_driver()\n");
114 status_t status
= get_module(B_USB_MODULE_NAME
,
115 (module_info
**)&gUSBModule
);
119 for (int32 i
= 0; i
< MAX_DEVICES
; i
++)
120 gECMDevices
[i
] = NULL
;
122 gDeviceNames
[0] = NULL
;
123 mutex_init(&gDriverLock
, DRIVER_NAME
"_devices");
125 static usb_notify_hooks notifyHooks
= {
126 &usb_ecm_device_added
,
127 &usb_ecm_device_removed
130 static usb_support_descriptor supportDescriptor
= {
131 USB_INTERFACE_CLASS_CDC
, /* CDC - Communication Device Class */
132 USB_INTERFACE_SUBCLASS_ECM
, /* ECM - Ethernet Control Model */
133 0, 0, 0 /* no protocol, vendor or device */
136 gUSBModule
->register_driver(DRIVER_NAME
, &supportDescriptor
, 1, NULL
);
137 gUSBModule
->install_notify(DRIVER_NAME
, ¬ifyHooks
);
145 TRACE("uninit_driver()\n");
146 gUSBModule
->uninstall_notify(DRIVER_NAME
);
147 mutex_lock(&gDriverLock
);
149 for (int32 i
= 0; i
< MAX_DEVICES
; i
++) {
150 if (gECMDevices
[i
]) {
151 delete gECMDevices
[i
];
152 gECMDevices
[i
] = NULL
;
156 for (int32 i
= 0; gDeviceNames
[i
]; i
++) {
157 free(gDeviceNames
[i
]);
158 gDeviceNames
[i
] = NULL
;
161 mutex_destroy(&gDriverLock
);
162 put_module(B_USB_MODULE_NAME
);
167 usb_ecm_open(const char *name
, uint32 flags
, void **cookie
)
169 TRACE("open(%s, %lu, %p)\n", name
, flags
, cookie
);
170 mutex_lock(&gDriverLock
);
173 status_t status
= ENODEV
;
174 int32 index
= strtol(name
+ strlen(sDeviceBaseName
), NULL
, 10);
175 if (index
>= 0 && index
< MAX_DEVICES
&& gECMDevices
[index
]) {
176 status
= gECMDevices
[index
]->Open();
177 *cookie
= gECMDevices
[index
];
180 mutex_unlock(&gDriverLock
);
186 usb_ecm_read(void *cookie
, off_t position
, void *buffer
, size_t *numBytes
)
188 TRACE("read(%p, %Ld, %p, %lu)\n", cookie
, position
, buffer
, *numBytes
);
189 ECMDevice
*device
= (ECMDevice
*)cookie
;
190 return device
->Read((uint8
*)buffer
, numBytes
);
195 usb_ecm_write(void *cookie
, off_t position
, const void *buffer
,
198 TRACE("write(%p, %Ld, %p, %lu)\n", cookie
, position
, buffer
, *numBytes
);
199 ECMDevice
*device
= (ECMDevice
*)cookie
;
200 return device
->Write((const uint8
*)buffer
, numBytes
);
205 usb_ecm_control(void *cookie
, uint32 op
, void *buffer
, size_t length
)
207 TRACE("control(%p, %lu, %p, %lu)\n", cookie
, op
, buffer
, length
);
208 ECMDevice
*device
= (ECMDevice
*)cookie
;
209 return device
->Control(op
, buffer
, length
);
214 usb_ecm_close(void *cookie
)
216 TRACE("close(%p)\n", cookie
);
217 ECMDevice
*device
= (ECMDevice
*)cookie
;
218 return device
->Close();
223 usb_ecm_free(void *cookie
)
225 TRACE("free(%p)\n", cookie
);
226 ECMDevice
*device
= (ECMDevice
*)cookie
;
227 mutex_lock(&gDriverLock
);
228 status_t status
= device
->Free();
229 for (int32 i
= 0; i
< MAX_DEVICES
; i
++) {
230 if (gECMDevices
[i
] == device
) {
231 // the device is removed already but as it was open the
232 // removed hook has not deleted the object
233 gECMDevices
[i
] = NULL
;
239 mutex_unlock(&gDriverLock
);
247 TRACE("publish_devices()\n");
248 for (int32 i
= 0; gDeviceNames
[i
]; i
++) {
249 free(gDeviceNames
[i
]);
250 gDeviceNames
[i
] = NULL
;
253 int32 deviceCount
= 0;
254 mutex_lock(&gDriverLock
);
255 for (int32 i
= 0; i
< MAX_DEVICES
; i
++) {
256 if (gECMDevices
[i
] == NULL
)
259 gDeviceNames
[deviceCount
] = (char *)malloc(strlen(sDeviceBaseName
) + 4);
260 if (gDeviceNames
[deviceCount
]) {
261 sprintf(gDeviceNames
[deviceCount
], "%s%" B_PRId32
, sDeviceBaseName
,
263 TRACE("publishing %s\n", gDeviceNames
[deviceCount
]);
266 TRACE_ALWAYS("publish_devices - no memory to allocate device name\n");
269 gDeviceNames
[deviceCount
] = NULL
;
270 mutex_unlock(&gDriverLock
);
271 return (const char **)&gDeviceNames
[0];
276 find_device(const char *name
)
278 TRACE("find_device(%s)\n", name
);
279 static device_hooks deviceHooks
= {