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.
19 #include <util/AutoLock.h>
21 #include "DavicomDevice.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
;
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" }
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");
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
;
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
);
82 usb_davicom_device_added(usb_device device
, void **cookie
)
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
)
93 if (gDavicomDevices
[i
]->CompareAndReattach(device
) != B_OK
)
96 TRACE("The device is plugged back. Use entry at %ld.\n", i
);
97 *cookie
= gDavicomDevices
[i
];
101 // no such device yet, create a new one
102 DavicomDevice
*davicomDevice
= lookup_and_create_device(device
);
103 if (davicomDevice
== 0) {
107 status_t status
= davicomDevice
->InitCheck();
109 delete davicomDevice
;
113 status
= davicomDevice
->SetupDevice(false);
115 delete davicomDevice
;
119 for (int32 i
= 0; i
< MAX_DEVICES
; i
++) {
120 if (gDavicomDevices
[i
] != NULL
)
123 gDavicomDevices
[i
] = davicomDevice
;
124 *cookie
= davicomDevice
;
126 TRACE("New device is added at %ld.\n", i
);
130 // no space for the device
131 TRACE_ALWAYS("Error: no more device entries availble.\n");
133 delete davicomDevice
;
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
150 gDavicomDevices
[i
] = NULL
;
152 TRACE("Device at %ld deleted.\n", i
);
175 status_t status
= get_module(B_USB_MODULE_NAME
,
176 (module_info
**)&gUSBModule
);
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
, ¬ifyHooks
);
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
);
235 usb_davicom_open(const char *name
, uint32 flags
, void **cookie
)
237 MutexLocker
lock(gDriverLock
); // released on exit
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
];
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
);
260 usb_davicom_write(void *cookie
, off_t position
, const void *buffer
,
263 DavicomDevice
*device
= (DavicomDevice
*)cookie
;
264 return device
->Write((const uint8
*)buffer
, numBytes
);
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
);
277 usb_davicom_close(void *cookie
)
279 DavicomDevice
*device
= (DavicomDevice
*)cookie
;
280 return device
->Close();
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
;
298 TRACE("Device at %ld deleted.\n", i
);
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
)
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
]);
328 TRACE_ALWAYS("Error: out of memory during allocating dev.name.\n");
331 gDeviceNames
[deviceCount
] = NULL
;
332 return (const char **)&gDeviceNames
[0];
337 find_device(const char *name
)
339 static device_hooks deviceHooks
= {