xref: /haiku/src/add-ons/kernel/drivers/network/ether/usb_ecm/Driver.cpp (revision 52c4471a3024d2eb81fe88e2c3982b9f8daa5e56)
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>
9 #include <lock.h>
10 
11 #include <bus/USB.h>
12 
13 
14 #include "Driver.h"
15 #include "ECMDevice.h"
16 
17 
18 #define DEVICE_BASE_NAME "net/usb_ecm/"
19 usb_module_info *gUSBModule = NULL;
20 device_manager_info *gDeviceManager;
21 
22 
23 #define USB_ECM_DRIVER_MODULE_NAME "drivers/network/usb_ecm/driver_v1"
24 #define USB_ECM_DEVICE_MODULE_NAME "drivers/network/usb_ecm/device_v1"
25 #define USB_ECM_DEVICE_ID_GENERATOR	"usb_ecm/device_id"
26 
27 
28 //	#pragma mark - device module API
29 
30 
31 static status_t
32 usb_ecm_init_device(void* _info, void** _cookie)
33 {
34 	CALLED();
35 	usb_ecm_driver_info* info = (usb_ecm_driver_info*)_info;
36 
37 	device_node* parent = gDeviceManager->get_parent_node(info->node);
38 	gDeviceManager->get_driver(parent, (driver_module_info **)&info->usb,
39 		(void **)&info->usb_device);
40 	gDeviceManager->put_node(parent);
41 
42 	usb_device device;
43 	if (gDeviceManager->get_attr_uint32(info->node, USB_DEVICE_ID_ITEM, &device, true) != B_OK)
44 		return B_ERROR;
45 
46 	ECMDevice *ecmDevice = new ECMDevice(device);
47 	status_t status = ecmDevice->InitCheck();
48 	if (status < B_OK) {
49 		delete ecmDevice;
50 		return status;
51 	}
52 
53 	info->device = ecmDevice;
54 
55 	*_cookie = info;
56 	return status;
57 }
58 
59 
60 static void
61 usb_ecm_uninit_device(void* _cookie)
62 {
63 	CALLED();
64 	usb_ecm_driver_info* info = (usb_ecm_driver_info*)_cookie;
65 
66 	delete info->device;
67 }
68 
69 
70 static void
71 usb_ecm_device_removed(void* _cookie)
72 {
73 	CALLED();
74 	usb_ecm_driver_info* info = (usb_ecm_driver_info*)_cookie;
75 	info->device->Removed();
76 }
77 
78 
79 static status_t
80 usb_ecm_open(void* _info, const char* path, int openMode, void** _cookie)
81 {
82 	CALLED();
83 	usb_ecm_driver_info* info = (usb_ecm_driver_info*)_info;
84 
85 	status_t status = info->device->Open();
86 	if (status != B_OK)
87 		return status;
88 
89 	*_cookie = info->device;
90 	return B_OK;
91 }
92 
93 
94 static status_t
95 usb_ecm_read(void *cookie, off_t position, void *buffer, size_t *numBytes)
96 {
97 	TRACE("read(%p, %" B_PRIdOFF", %p, %lu)\n", cookie, position, buffer, *numBytes);
98 	ECMDevice *device = (ECMDevice *)cookie;
99 	return device->Read((uint8 *)buffer, numBytes);
100 }
101 
102 
103 static status_t
104 usb_ecm_write(void *cookie, off_t position, const void *buffer,
105 	size_t *numBytes)
106 {
107 	TRACE("write(%p, %" B_PRIdOFF", %p, %lu)\n", cookie, position, buffer, *numBytes);
108 	ECMDevice *device = (ECMDevice *)cookie;
109 	return device->Write((const uint8 *)buffer, numBytes);
110 }
111 
112 
113 static status_t
114 usb_ecm_control(void *cookie, uint32 op, void *buffer, size_t length)
115 {
116 	TRACE("control(%p, %" B_PRIu32 ", %p, %lu)\n", cookie, op, buffer, length);
117 	ECMDevice *device = (ECMDevice *)cookie;
118 	return device->Control(op, buffer, length);
119 }
120 
121 
122 static status_t
123 usb_ecm_close(void *cookie)
124 {
125 	TRACE("close(%p)\n", cookie);
126 	ECMDevice *device = (ECMDevice *)cookie;
127 	return device->Close();
128 }
129 
130 
131 static status_t
132 usb_ecm_free(void *cookie)
133 {
134 	TRACE("free(%p)\n", cookie);
135 	ECMDevice *device = (ECMDevice *)cookie;
136 	return device->Free();
137 }
138 
139 
140 //	#pragma mark - driver module API
141 
142 
143 static float
144 usb_ecm_supports_device(device_node *parent)
145 {
146 	CALLED();
147 	const char *bus;
148 
149 	// make sure parent is really the usb bus manager
150 	if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
151 		return -1;
152 
153 	if (strcmp(bus, "usb"))
154 		return 0.0;
155 
156 
157 	// check whether it's really an ECM device
158 	device_attr *attr = NULL;
159 	uint8 baseClass = 0, subclass = 0;
160 	while (gDeviceManager->get_next_attr(parent, &attr) == B_OK) {
161 		if (attr->type != B_UINT8_TYPE)
162 			continue;
163 
164 		if (!strcmp(attr->name, USB_DEVICE_CLASS))
165 			baseClass = attr->value.ui8;
166 		if (!strcmp(attr->name, USB_DEVICE_SUBCLASS))
167 			subclass = attr->value.ui8;
168 		if (baseClass != 0 && subclass != 0) {
169 			if (baseClass == USB_INTERFACE_CLASS_CDC && subclass == USB_INTERFACE_SUBCLASS_ECM)
170 				break;
171 			baseClass = subclass = 0;
172 		}
173 	}
174 
175 	if (baseClass != USB_INTERFACE_CLASS_CDC || subclass != USB_INTERFACE_SUBCLASS_ECM)
176 		return 0.0;
177 
178 	TRACE("USB-ECM device found!\n");
179 
180 	return 0.6;
181 }
182 
183 
184 static status_t
185 usb_ecm_register_device(device_node *node)
186 {
187 	CALLED();
188 
189 	device_attr attrs[] = {
190 		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "USB ECM"} },
191 		{ NULL }
192 	};
193 
194 	return gDeviceManager->register_node(node, USB_ECM_DRIVER_MODULE_NAME,
195 		attrs, NULL, NULL);
196 }
197 
198 
199 static status_t
200 usb_ecm_init_driver(device_node *node, void **cookie)
201 {
202 	CALLED();
203 
204 	usb_ecm_driver_info* info = (usb_ecm_driver_info*)malloc(
205 		sizeof(usb_ecm_driver_info));
206 	if (info == NULL)
207 		return B_NO_MEMORY;
208 
209 	memset(info, 0, sizeof(*info));
210 	info->node = node;
211 
212 	*cookie = info;
213 	return B_OK;
214 }
215 
216 
217 static void
218 usb_ecm_uninit_driver(void *_cookie)
219 {
220 	CALLED();
221 	usb_ecm_driver_info* info = (usb_ecm_driver_info*)_cookie;
222 	free(info);
223 }
224 
225 
226 static status_t
227 usb_ecm_register_child_devices(void* _cookie)
228 {
229 	CALLED();
230 	usb_ecm_driver_info* info = (usb_ecm_driver_info*)_cookie;
231 	status_t status;
232 
233 	int32 id = gDeviceManager->create_id(USB_ECM_DEVICE_ID_GENERATOR);
234 	if (id < 0)
235 		return id;
236 
237 	char name[64];
238 	snprintf(name, sizeof(name), DEVICE_BASE_NAME "%" B_PRId32,
239 		id);
240 
241 	status = gDeviceManager->publish_device(info->node, name,
242 		USB_ECM_DEVICE_MODULE_NAME);
243 
244 	return status;
245 }
246 
247 
248 //	#pragma mark -
249 
250 
251 module_dependency module_dependencies[] = {
252 	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager },
253 	{ B_USB_MODULE_NAME, (module_info**)&gUSBModule},
254 	{ NULL }
255 };
256 
257 struct device_module_info sUsbEcmDevice = {
258 	{
259 		USB_ECM_DEVICE_MODULE_NAME,
260 		0,
261 		NULL
262 	},
263 
264 	usb_ecm_init_device,
265 	usb_ecm_uninit_device,
266 	usb_ecm_device_removed,
267 
268 	usb_ecm_open,
269 	usb_ecm_close,
270 	usb_ecm_free,
271 	usb_ecm_read,
272 	usb_ecm_write,
273 	NULL,	// io
274 	usb_ecm_control,
275 
276 	NULL,	// select
277 	NULL,	// deselect
278 };
279 
280 struct driver_module_info sUsbEcmDriver = {
281 	{
282 		USB_ECM_DRIVER_MODULE_NAME,
283 		0,
284 		NULL
285 	},
286 
287 	usb_ecm_supports_device,
288 	usb_ecm_register_device,
289 	usb_ecm_init_driver,
290 	usb_ecm_uninit_driver,
291 	usb_ecm_register_child_devices,
292 	NULL,	// rescan
293 	NULL,	// removed
294 };
295 
296 module_info* modules[] = {
297 	(module_info*)&sUsbEcmDriver,
298 	(module_info*)&sUsbEcmDevice,
299 	NULL
300 };
301