BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / drivers / network / usb_davicom / Driver.cpp
blobb96d87a3f68c5f215a8a7070d49cc8d9e6a4526e
1 /*
2 * Davicom DM9601 USB 1.1 Ethernet Driver.
3 * Copyright (c) 2008, 2011 Siarzhuk Zharski <imker@gmx.li>
4 * Copyright (c) 2009 Adrien Destugues <pulkomandy@gmail.com>
5 * Distributed under the terms of the MIT license.
7 * Heavily based on code of the
8 * Driver for USB Ethernet Control Model devices
9 * Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
10 * Distributed under the terms of the MIT license.
14 #include "Driver.h"
16 #include <stdio.h>
18 #include <lock.h>
19 #include <util/AutoLock.h>
21 #include "DavicomDevice.h"
22 #include "Settings.h"
25 int32 api_version = B_CUR_DRIVER_API_VERSION;
26 static const char *sDeviceBaseName = "net/usb_davicom/";
27 DavicomDevice *gDavicomDevices[MAX_DEVICES];
28 char *gDeviceNames[MAX_DEVICES + 1];
29 usb_module_info *gUSBModule = NULL;
30 mutex gDriverLock;
33 // IMPORTANT: keep entries sorted by ids to let the
34 // binary search lookup procedure work correctly !!!
35 DeviceInfo gSupportedDevices[] = {
36 { { 0x01e1, 0x9601 }, "Noname DM9601" },
37 { { 0x07aa, 0x9601 }, "Corega FEther USB-TXC" },
38 { { 0x0a46, 0x0268 }, "ShanTou ST268 USB NIC" },
39 { { 0x0a46, 0x6688 }, "ZT6688 USB NIC" },
40 { { 0x0a46, 0x8515 }, "ADMtek ADM8515 USB NIC" },
41 { { 0x0a46, 0x9000 }, "DM9000E" },
42 { { 0x0a46, 0x9601 }, "Davicom DM9601" },
43 { { 0x0a47, 0x9601 }, "Hirose USB-100" },
44 { { 0x0fe6, 0x8101 }, "Sunrising SR9600" },
45 { { 0x0fe6, 0x9700 }, "Kontron DM9601" }
49 DavicomDevice *
50 lookup_and_create_device(usb_device device)
52 const usb_device_descriptor *deviceDescriptor
53 = gUSBModule->get_device_descriptor(device);
55 if (deviceDescriptor == NULL) {
56 TRACE_ALWAYS("Error of getting USB device descriptor.\n");
57 return NULL;
60 TRACE("trying %#06x:%#06x.\n",
61 deviceDescriptor->vendor_id, deviceDescriptor->product_id);
63 // use binary search to lookup device in table
64 uint32 id = deviceDescriptor->vendor_id << 16
65 | deviceDescriptor->product_id;
66 int left = -1;
67 int right = B_COUNT_OF(gSupportedDevices);
68 while ((right - left) > 1) {
69 int i = (left + right) / 2;
70 ((gSupportedDevices[i].Key() < id) ? left : right) = i;
73 if (gSupportedDevices[right].Key() == id)
74 return new DavicomDevice(device, gSupportedDevices[right]);
76 TRACE_ALWAYS("Search for %#x failed %d-%d.\n", id, left, right);
77 return NULL;
81 status_t
82 usb_davicom_device_added(usb_device device, void **cookie)
84 *cookie = NULL;
86 MutexLocker lock(gDriverLock); // released on exit
88 // check if this is a replug of an existing device first
89 for (int32 i = 0; i < MAX_DEVICES; i++) {
90 if (gDavicomDevices[i] == NULL)
91 continue;
93 if (gDavicomDevices[i]->CompareAndReattach(device) != B_OK)
94 continue;
96 TRACE("The device is plugged back. Use entry at %ld.\n", i);
97 *cookie = gDavicomDevices[i];
98 return B_OK;
101 // no such device yet, create a new one
102 DavicomDevice *davicomDevice = lookup_and_create_device(device);
103 if (davicomDevice == 0) {
104 return ENODEV;
107 status_t status = davicomDevice->InitCheck();
108 if (status < B_OK) {
109 delete davicomDevice;
110 return status;
113 status = davicomDevice->SetupDevice(false);
114 if (status < B_OK) {
115 delete davicomDevice;
116 return status;
119 for (int32 i = 0; i < MAX_DEVICES; i++) {
120 if (gDavicomDevices[i] != NULL)
121 continue;
123 gDavicomDevices[i] = davicomDevice;
124 *cookie = davicomDevice;
126 TRACE("New device is added at %ld.\n", i);
127 return B_OK;
130 // no space for the device
131 TRACE_ALWAYS("Error: no more device entries availble.\n");
133 delete davicomDevice;
134 return B_ERROR;
138 status_t
139 usb_davicom_device_removed(void *cookie)
141 MutexLocker lock(gDriverLock); // released on exit
143 DavicomDevice *device = (DavicomDevice *)cookie;
144 for (int32 i = 0; i < MAX_DEVICES; i++) {
145 if (gDavicomDevices[i] == device) {
146 if (device->IsOpen()) {
147 // the device will be deleted upon being freed
148 device->Removed();
149 } else {
150 gDavicomDevices[i] = NULL;
151 delete device;
152 TRACE("Device at %ld deleted.\n", i);
154 break;
158 return B_OK;
162 // #pragma mark -
165 status_t
166 init_hardware()
168 return B_OK;
172 status_t
173 init_driver()
175 status_t status = get_module(B_USB_MODULE_NAME,
176 (module_info **)&gUSBModule);
177 if (status < B_OK)
178 return status;
180 load_settings();
182 TRACE_ALWAYS("%s\n", kVersion);
184 for (int32 i = 0; i < MAX_DEVICES; i++)
185 gDavicomDevices[i] = NULL;
187 gDeviceNames[0] = NULL;
188 mutex_init(&gDriverLock, DRIVER_NAME"_devices");
190 static usb_notify_hooks notifyHooks = {
191 &usb_davicom_device_added,
192 &usb_davicom_device_removed
195 const size_t count = B_COUNT_OF(gSupportedDevices);
196 static usb_support_descriptor sDescriptors[count] = {{ 0 }};
198 for (size_t i = 0; i < count; i++) {
199 sDescriptors[i].vendor = gSupportedDevices[i].VendorId();
200 sDescriptors[i].product = gSupportedDevices[i].ProductId();
203 gUSBModule->register_driver(DRIVER_NAME, sDescriptors, count, NULL);
204 gUSBModule->install_notify(DRIVER_NAME, &notifyHooks);
205 return B_OK;
209 void
210 uninit_driver()
212 gUSBModule->uninstall_notify(DRIVER_NAME);
213 mutex_lock(&gDriverLock);
215 for (int32 i = 0; i < MAX_DEVICES; i++) {
216 if (gDavicomDevices[i]) {
217 delete gDavicomDevices[i];
218 gDavicomDevices[i] = NULL;
222 for (int32 i = 0; gDeviceNames[i]; i++) {
223 free(gDeviceNames[i]);
224 gDeviceNames[i] = NULL;
227 mutex_destroy(&gDriverLock);
228 put_module(B_USB_MODULE_NAME);
230 release_settings();
234 static status_t
235 usb_davicom_open(const char *name, uint32 flags, void **cookie)
237 MutexLocker lock(gDriverLock); // released on exit
239 *cookie = NULL;
240 status_t status = ENODEV;
241 int32 index = strtol(name + strlen(sDeviceBaseName), NULL, 10);
242 if (index >= 0 && index < MAX_DEVICES && gDavicomDevices[index]) {
243 status = gDavicomDevices[index]->Open(flags);
244 *cookie = gDavicomDevices[index];
247 return status;
251 static status_t
252 usb_davicom_read(void *cookie, off_t position, void *buffer, size_t *numBytes)
254 DavicomDevice *device = (DavicomDevice *)cookie;
255 return device->Read((uint8 *)buffer, numBytes);
259 static status_t
260 usb_davicom_write(void *cookie, off_t position, const void *buffer,
261 size_t *numBytes)
263 DavicomDevice *device = (DavicomDevice *)cookie;
264 return device->Write((const uint8 *)buffer, numBytes);
268 static status_t
269 usb_davicom_control(void *cookie, uint32 op, void *buffer, size_t length)
271 DavicomDevice *device = (DavicomDevice *)cookie;
272 return device->Control(op, buffer, length);
276 static status_t
277 usb_davicom_close(void *cookie)
279 DavicomDevice *device = (DavicomDevice *)cookie;
280 return device->Close();
284 static status_t
285 usb_davicom_free(void *cookie)
287 DavicomDevice *device = (DavicomDevice *)cookie;
289 MutexLocker lock(gDriverLock); // released on exit
291 status_t status = device->Free();
292 for (int32 i = 0; i < MAX_DEVICES; i++) {
293 if (gDavicomDevices[i] == device) {
294 // the device is removed already but as it was open the
295 // removed hook has not deleted the object
296 gDavicomDevices[i] = NULL;
297 delete device;
298 TRACE("Device at %ld deleted.\n", i);
299 break;
303 return status;
307 const char **
308 publish_devices()
310 for (int32 i = 0; gDeviceNames[i]; i++) {
311 free(gDeviceNames[i]);
312 gDeviceNames[i] = NULL;
315 MutexLocker lock(gDriverLock); // released on exit
317 int32 deviceCount = 0;
318 for (int32 i = 0; i < MAX_DEVICES; i++) {
319 if (gDavicomDevices[i] == NULL)
320 continue;
322 gDeviceNames[deviceCount] = (char *)malloc(strlen(sDeviceBaseName) + 4);
323 if (gDeviceNames[deviceCount]) {
324 sprintf(gDeviceNames[deviceCount], "%s%" B_PRId32, sDeviceBaseName, i);
325 TRACE("publishing %s\n", gDeviceNames[deviceCount]);
326 deviceCount++;
327 } else
328 TRACE_ALWAYS("Error: out of memory during allocating dev.name.\n");
331 gDeviceNames[deviceCount] = NULL;
332 return (const char **)&gDeviceNames[0];
336 device_hooks *
337 find_device(const char *name)
339 static device_hooks deviceHooks = {
340 usb_davicom_open,
341 usb_davicom_close,
342 usb_davicom_free,
343 usb_davicom_control,
344 usb_davicom_read,
345 usb_davicom_write,
346 NULL, // select
347 NULL // deselect
350 return &deviceHooks;