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