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