📄 pnp.c
字号:
pdo = wd->pdo; IOTRACE("%p, %p", pdo, IoGetAttachedDevice(pdo)); memset(&irp_sl, 0, sizeof(irp_sl)); irp_sl.params.power.state.device_state = state; irp_sl.params.power.type = DevicePowerState; if (state > PowerDeviceD0) { status = IoSendIrpTopDev(pdo, IRP_MJ_POWER, IRP_MN_QUERY_POWER, &irp_sl); if (status != STATUS_SUCCESS) { TRACE1("query of power to %d returns %08X", state, status); EXIT1(return status); } } status = IoSendIrpTopDev(pdo, IRP_MJ_POWER, IRP_MN_SET_POWER, &irp_sl); if (status != STATUS_SUCCESS) WARNING("setting power to %d failed: %08X", state, status); EXIT1(return status);}NTSTATUS pnp_start_device(struct wrap_device *wd){ struct device_object *fdo; struct device_object *pdo; struct io_stack_location irp_sl; NTSTATUS status; pdo = wd->pdo; /* TODO: for now we use same resources for both translated * resources and raw resources */ memset(&irp_sl, 0, sizeof(irp_sl)); irp_sl.params.start_device.allocated_resources = wd->resource_list; irp_sl.params.start_device.allocated_resources_translated = wd->resource_list; status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_START_DEVICE, &irp_sl); fdo = IoGetAttachedDevice(pdo); if (status == STATUS_SUCCESS) fdo->drv_obj->drv_ext->count++; else WARNING("Windows driver couldn't initialize the device (%08X)", status); EXIT1(return status);}NTSTATUS pnp_stop_device(struct wrap_device *wd){ struct device_object *pdo; NTSTATUS status; pdo = wd->pdo; status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_QUERY_STOP_DEVICE, NULL); if (status != STATUS_SUCCESS) WARNING("status: %08X", status); /* for now we ignore query status */ status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_STOP_DEVICE, NULL); if (status != STATUS_SUCCESS) WARNING("status: %08X", status); if (status != STATUS_SUCCESS) WARNING("status: %08X", status); EXIT2(return status);}NTSTATUS pnp_remove_device(struct wrap_device *wd){ struct device_object *pdo, *fdo; struct driver_object *fdo_drv_obj; NTSTATUS status; pdo = wd->pdo; fdo = IoGetAttachedDevice(pdo); fdo_drv_obj = fdo->drv_obj; TRACE2("%p, %p, %p", pdo, fdo, fdo_drv_obj); status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_QUERY_REMOVE_DEVICE, NULL); if (status != STATUS_SUCCESS) WARNING("status: %08X", status); status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_REMOVE_DEVICE, NULL); if (status != STATUS_SUCCESS) WARNING("status: %08X", status); /* TODO: should we use count in drv_ext or driver's Object * header reference count to keep count of devices associated * with a driver? */ if (status == STATUS_SUCCESS) fdo_drv_obj->drv_ext->count--; TRACE1("count: %d", fdo_drv_obj->drv_ext->count); if (fdo_drv_obj->drv_ext->count < 0) WARNING("wrong count: %d", fdo_drv_obj->drv_ext->count); if (fdo_drv_obj->drv_ext->count == 0) { struct wrap_driver *wrap_driver; TRACE1("unloading driver: %p", fdo_drv_obj); wrap_driver = IoGetDriverObjectExtension(fdo_drv_obj, (void *)WRAP_DRIVER_CLIENT_ID); if (fdo_drv_obj->unload) LIN2WIN1(fdo_drv_obj->unload, fdo_drv_obj); if (wrap_driver) { if (down_interruptible(&loader_mutex)) WARNING("couldn't obtain loader_mutex"); unload_wrap_driver(wrap_driver); up(&loader_mutex); } else ERROR("couldn't get wrap_driver"); ObDereferenceObject(fdo_drv_obj); } IoDeleteDevice(pdo); unload_wrap_device(wd); EXIT1(return status);}WIN_FUNC_DECL(IoInvalidDeviceRequest,2)static struct device_object *alloc_pdo(struct driver_object *drv_obj){ struct device_object *pdo; NTSTATUS status ; int i; struct ansi_string ansi_name; struct unicode_string unicode_name; RtlInitAnsiString(&ansi_name, "NDISpdo"); if (RtlAnsiStringToUnicodeString(&unicode_name, &ansi_name, TRUE) == STATUS_SUCCESS) { status = IoCreateDevice(drv_obj, 0, &unicode_name, FILE_DEVICE_UNKNOWN, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &pdo); RtlFreeUnicodeString(&unicode_name); } else { status = IoCreateDevice(drv_obj, 0, NULL, FILE_DEVICE_UNKNOWN, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &pdo); } TRACE1("%p, %d, %p", drv_obj, status, pdo); if (status != STATUS_SUCCESS) return NULL; /* dispatch routines are called as Windows functions */ for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) drv_obj->major_func[i] = WIN_FUNC_PTR(IoInvalidDeviceRequest,2); drv_obj->major_func[IRP_MJ_INTERNAL_DEVICE_CONTROL] = WIN_FUNC_PTR(pdoDispatchDeviceControl,2); drv_obj->major_func[IRP_MJ_DEVICE_CONTROL] = WIN_FUNC_PTR(pdoDispatchDeviceControl,2); drv_obj->major_func[IRP_MJ_POWER] = WIN_FUNC_PTR(pdoDispatchPower,2); drv_obj->major_func[IRP_MJ_PNP] = WIN_FUNC_PTR(pdoDispatchPnp,2); return pdo;}static int wrap_pnp_start_device(struct wrap_device *wd){ struct wrap_driver *driver; struct device_object *pdo; struct driver_object *pdo_drv_obj; ENTER1("wd: %p", wd); if (!((wrap_is_pci_bus(wd->dev_bus)) || (wrap_is_usb_bus(wd->dev_bus)))) { ERROR("bus type %d (%d) not supported", WRAP_BUS(wd->dev_bus), wd->dev_bus); EXIT1(return -EINVAL); } driver = load_wrap_driver(wd); if (!driver) return -ENODEV; wd->driver = driver; wd->dev_bus = WRAP_DEVICE_BUS(driver->dev_type, WRAP_BUS(wd->dev_bus)); TRACE1("dev type: %d, bus type: %d, %d", WRAP_DEVICE(wd->dev_bus), WRAP_BUS(wd->dev_bus), wd->dev_bus); TRACE1("%d, %d", driver->dev_type, wrap_is_usb_bus(wd->dev_bus)); /* first create pdo */ if (wrap_is_pci_bus(wd->dev_bus)) pdo_drv_obj = find_bus_driver("PCI"); else // if (wrap_is_usb_bus(wd->dev_bus)) pdo_drv_obj = find_bus_driver("USB"); if (!pdo_drv_obj) return -EINVAL; pdo = alloc_pdo(pdo_drv_obj); if (!pdo) return -ENOMEM; wd->pdo = pdo; pdo->reserved = wd; if (WRAP_DEVICE(wd->dev_bus) == WRAP_NDIS_DEVICE) { if (init_ndis_driver(driver->drv_obj)) { IoDeleteDevice(pdo); return -EINVAL; } } TRACE1("%p", driver->drv_obj->drv_ext->add_device); if (driver->drv_obj->drv_ext->add_device(driver->drv_obj, pdo) != STATUS_SUCCESS) { IoDeleteDevice(pdo); return -ENOMEM; } if (pnp_start_device(wd) != STATUS_SUCCESS) { /* TODO: we need proper cleanup, to deallocate memory, * for example */ pnp_remove_device(wd); return -EINVAL; } return 0;}/* * This function should not be marked __devinit because PCI IDs are * added dynamically. */int wrap_pnp_start_pci_device(struct pci_dev *pdev, const struct pci_device_id *ent){ struct load_device load_device; struct wrap_device *wd; ENTER1("called for %04x:%04x:%04x:%04x", pdev->vendor, pdev->device, pdev->subsystem_vendor, pdev->subsystem_device); load_device.bus = WRAP_PCI_BUS; load_device.vendor = pdev->vendor; load_device.device = pdev->device; load_device.subvendor = pdev->subsystem_vendor; load_device.subdevice = pdev->subsystem_device; wd = load_wrap_device(&load_device); if (!wd) EXIT1(return -ENODEV); wd->pci.pdev = pdev; return wrap_pnp_start_device(wd);}void __devexit wrap_pnp_remove_pci_device(struct pci_dev *pdev){ struct wrap_device *wd; wd = (struct wrap_device *)pci_get_drvdata(pdev); ENTER1("%p, %p", pdev, wd); if (!wd) EXIT1(return); pnp_remove_device(wd);}int wrap_pnp_suspend_pci_device(struct pci_dev *pdev, pm_message_t state){ struct wrap_device *wd; wd = (struct wrap_device *)pci_get_drvdata(pdev); return pnp_set_device_power_state(wd, PowerDeviceD3);}int wrap_pnp_resume_pci_device(struct pci_dev *pdev){ struct wrap_device *wd; wd = (struct wrap_device *)pci_get_drvdata(pdev); return pnp_set_device_power_state(wd, PowerDeviceD0);}#ifdef CONFIG_USB#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)int wrap_pnp_start_usb_device(struct usb_interface *intf, const struct usb_device_id *usb_id)#elsevoid *wrap_pnp_start_usb_device(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *usb_id)#endif{ struct wrap_device *wd; int ret;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) struct usb_device *udev = interface_to_usbdev(intf);#else struct usb_interface *intf = usb_ifnum_to_if(udev, ifnum);#endif ENTER1("%04x, %04x, %04x", udev->descriptor.idVendor, udev->descriptor.idProduct, udev->descriptor.bDeviceClass); /* USB device (e.g., RNDIS) may have multiple interfaces; initialize one interface only (is there a way to know which of these interfaces is for network?) */ if ((wd = get_wrap_device(udev, WRAP_USB_BUS))) { TRACE1("device already initialized: %p", wd); usb_set_intfdata(intf, NULL); ret = 0; } else { struct load_device load_device; load_device.bus = WRAP_USB_BUS; load_device.vendor = udev->descriptor.idVendor; load_device.device = udev->descriptor.idProduct; load_device.subvendor = 0; load_device.subdevice = 0; wd = load_wrap_device(&load_device); TRACE2("%p", wd); if (wd) { /* some devices (e.g., TI 4150, RNDIS) need * full reset */ ret = usb_reset_device(udev); if (ret) WARNING("reset failed: %d", ret); usb_set_intfdata(intf, wd); wd->usb.intf = intf; wd->usb.udev = udev; ret = wrap_pnp_start_device(wd); } else ret = -ENODEV; } TRACE2("ret: %d", ret);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) if (ret) EXIT1(return ret); else return 0;#else if (ret) return NULL; else return wd;#endif}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)void __devexit wrap_pnp_remove_usb_device(struct usb_interface *intf){ struct wrap_device *wd; wd = (struct wrap_device *)usb_get_intfdata(intf); ENTER1("%p, %p", intf, wd); if (wd == NULL) EXIT1(return); usb_set_intfdata(intf, NULL); pnp_remove_device(wd);}int wrap_pnp_suspend_usb_device(struct usb_interface *intf, pm_message_t state){ struct wrap_device *wd; struct device_object *pdo; wd = usb_get_intfdata(intf); ENTER1("%p, %p", intf, wd); if (!wd) EXIT1(return 0); pdo = wd->pdo; if (pnp_set_device_power_state(wd, PowerDeviceD3)) return -1; return 0;}int wrap_pnp_resume_usb_device(struct usb_interface *intf){ struct wrap_device *wd; wd = usb_get_intfdata(intf); ENTER1("%p, %p", intf, wd); if (!wd) EXIT1(return 0); if (pnp_set_device_power_state(wd, PowerDeviceD0)) return -1; return 0;}#elsevoid __devexit wrap_pnp_remove_usb_device(struct usb_device *udev, void *ptr){ struct wrap_device *wd = ptr; struct usb_interface *intf; ENTER1("%p, %p", udev, wd); if (wd == NULL) EXIT1(return); intf = wd->usb.intf; pnp_remove_device(wd);}#endif#endif // USB
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -