usb_ecm: Use the current configuration instead of a fixed one.
[haiku.git] / src / add-ons / kernel / drivers / network / usb_ecm / Driver.cpp
blobac25820d04b3fd020950f0cfe4e5e03df0fa481b
1 /*
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.
5 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
10 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
11 #include <lock.h> // for mutex
12 #else
13 #include "BeOSCompatibility.h" // for pseudo mutex
14 #endif
16 #include "Driver.h"
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;
24 mutex gDriverLock;
27 status_t
28 usb_ecm_device_added(usb_device device, void **cookie)
30 *cookie = NULL;
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)
36 continue;
38 if (gECMDevices[i]->CompareAndReattach(device) != B_OK)
39 continue;
41 TRACE_ALWAYS("ecm device %" B_PRId32 " replugged\n", i);
42 *cookie = gECMDevices[i];
43 mutex_unlock(&gDriverLock);
44 return B_OK;
47 // no such device yet, create a new one
48 ECMDevice *ecmDevice = new ECMDevice(device);
49 status_t status = ecmDevice->InitCheck();
50 if (status < B_OK) {
51 delete ecmDevice;
52 mutex_unlock(&gDriverLock);
53 return status;
56 for (int32 i = 0; i < MAX_DEVICES; i++) {
57 if (gECMDevices[i] != NULL)
58 continue;
60 gECMDevices[i] = ecmDevice;
61 *cookie = ecmDevice;
63 TRACE_ALWAYS("ecm device %" B_PRId32 " added\n", i);
64 mutex_unlock(&gDriverLock);
65 return B_OK;
68 // no space for the device
69 delete ecmDevice;
70 mutex_unlock(&gDriverLock);
71 return B_ERROR;
75 status_t
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
85 device->Removed();
86 } else {
87 gECMDevices[i] = NULL;
88 delete device;
90 break;
94 mutex_unlock(&gDriverLock);
95 return B_OK;
99 //#pragma mark -
102 status_t
103 init_hardware()
105 TRACE("init_hardware()\n");
106 return B_OK;
110 status_t
111 init_driver()
113 TRACE("init_driver()\n");
114 status_t status = get_module(B_USB_MODULE_NAME,
115 (module_info **)&gUSBModule);
116 if (status < B_OK)
117 return status;
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, &notifyHooks);
138 return B_OK;
142 void
143 uninit_driver()
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);
166 static status_t
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);
172 *cookie = NULL;
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);
181 return status;
185 static status_t
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);
194 static status_t
195 usb_ecm_write(void *cookie, off_t position, const void *buffer,
196 size_t *numBytes)
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);
204 static status_t
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);
213 static status_t
214 usb_ecm_close(void *cookie)
216 TRACE("close(%p)\n", cookie);
217 ECMDevice *device = (ECMDevice *)cookie;
218 return device->Close();
222 static status_t
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;
234 delete device;
235 break;
239 mutex_unlock(&gDriverLock);
240 return status;
244 const char **
245 publish_devices()
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)
257 continue;
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]);
264 deviceCount++;
265 } else
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];
275 device_hooks *
276 find_device(const char *name)
278 TRACE("find_device(%s)\n", name);
279 static device_hooks deviceHooks = {
280 usb_ecm_open,
281 usb_ecm_close,
282 usb_ecm_free,
283 usb_ecm_control,
284 usb_ecm_read,
285 usb_ecm_write,
286 NULL, /* select */
287 NULL /* deselect */
290 return &deviceHooks;