示例#1
0
static NTSTATUS UsbChief_ReadAndSelectDescriptors(IN WDFDEVICE Device)
{
	PDEVICE_CONTEXT pDeviceContext;
	NTSTATUS Status;

	PAGED_CODE();

	pDeviceContext = GetDeviceContext(Device);

	if (!pDeviceContext->WdfUsbTargetDevice) {
		Status = WdfUsbTargetDeviceCreate(Device,
						  WDF_NO_OBJECT_ATTRIBUTES,
						  &pDeviceContext->WdfUsbTargetDevice);

		if (!NT_SUCCESS(Status))
			return Status;
	}

	WdfUsbTargetDeviceGetDeviceDescriptor(pDeviceContext->WdfUsbTargetDevice,
					      &pDeviceContext->UsbDeviceDescriptor);
	return UsbChief_ConfigureDevice(Device);
}
示例#2
0
/*++
Routine Description:

This routine configures the USB device.
In this routines we get the device descriptor,
the configuration descriptor and select the
configuration.

Arguments:

Device - Handle to a framework device

Return Value:

NTSTATUS - NT status value.
--*/
NTSTATUS ReadAndSelectDescriptors(IN WDFDEVICE Device)
{
    NTSTATUS               status;
    PDEVICE_CONTEXT        pDeviceContext;

    PAGED_CODE();

    // initialize variables
    pDeviceContext = GetDeviceContext(Device);

    // Create a USB device handle so that we can communicate with the
    // underlying USB stack. The WDFUSBDEVICE handle is used to query,
    // configure, and manage all aspects of the USB device.
    // These aspects include device properties, bus properties,
    // and I/O creation and synchronization. We only create device the first
    // the PrepareHardware is called. If the device is restarted by pnp manager
    // for resource re-balance, we will use the same device handle but then select
    // the interfaces again because the USB stack could reconfigure the device on
    // restart.
    if (pDeviceContext->WdfUsbTargetDevice == NULL)
	{
        status = WdfUsbTargetDeviceCreate(Device, WDF_NO_OBJECT_ATTRIBUTES, &pDeviceContext->WdfUsbTargetDevice);
        if (!NT_SUCCESS(status))
		{
			PSDrv_DbgPrint(3, ("WdfUsbTargetDeviceCreate failed! (Status = %x)\n", status));
            return status;
        }
    }
    
    WdfUsbTargetDeviceGetDeviceDescriptor(pDeviceContext->WdfUsbTargetDevice, &pDeviceContext->UsbDeviceDescriptor);

    ASSERT(pDeviceContext->UsbDeviceDescriptor.bNumConfigurations);

    status = ConfigureDevice(Device);

    return status;
}
示例#3
0
文件: usb.c 项目: uri247/wdk80
NTSTATUS
HidFx2EvtDevicePrepareHardware(
    IN WDFDEVICE    Device,
    IN WDFCMRESLIST ResourceList,
    IN WDFCMRESLIST ResourceListTranslated
    )
/*++

Routine Description:

    In this callback, the driver does whatever is necessary to make the
    hardware ready to use.  In the case of a USB device, this involves
    reading and selecting descriptors.

Arguments:

    Device - handle to a device

    ResourceList - A handle to a framework resource-list object that
    identifies the raw hardware resourcest

    ResourceListTranslated - A handle to a framework resource-list object
    that identifies the translated hardware resources

Return Value:

    NT status value

--*/
{
    NTSTATUS                            status = STATUS_SUCCESS;
    PDEVICE_EXTENSION                   devContext = NULL;
    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;
    WDF_OBJECT_ATTRIBUTES               attributes;
    PUSB_DEVICE_DESCRIPTOR              usbDeviceDescriptor = NULL;

    UNREFERENCED_PARAMETER(ResourceList);
    UNREFERENCED_PARAMETER(ResourceListTranslated);

    PAGED_CODE ();

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
        "HidFx2EvtDevicePrepareHardware Enter\n");

    devContext = GetDeviceContext(Device);

    //
    // Create a WDFUSBDEVICE object. WdfUsbTargetDeviceCreate obtains the
    // USB device descriptor and the first USB configuration descriptor from
    // the device and stores them. It also creates a framework USB interface
    // object for each interface in the device's first configuration.
    //
    // The parent of each USB device object is the driver's framework driver
    // object. The driver cannot change this parent, and the ParentObject
    // member or the WDF_OBJECT_ATTRIBUTES structure must be NULL.
    //
    // We only create device the first time PrepareHardware is called. If 
    // the device is restarted by pnp manager for resource rebalance, we 
    // will use the same device handle but then select the interfaces again
    // because the USB stack could reconfigure the device on restart.
    //
    if (devContext->UsbDevice == NULL) {
        status = WdfUsbTargetDeviceCreate(Device,
                                          WDF_NO_OBJECT_ATTRIBUTES,
                                          &devContext->UsbDevice);
  
        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfUsbTargetDeviceCreate failed 0x%x\n", status);
            return status;
        }
    }

    //
    // Select a device configuration by using a
    // WDF_USB_DEVICE_SELECT_CONFIG_PARAMS structure to specify USB
    // descriptors, a URB, or handles to framework USB interface objects.
    //
    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE( &configParams);

    status = WdfUsbTargetDeviceSelectConfig(devContext->UsbDevice,
                                        WDF_NO_OBJECT_ATTRIBUTES,
                                        &configParams);
    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfUsbTargetDeviceSelectConfig failed %!STATUS!\n",
            status);
        return status;
    }

    devContext->UsbInterface =
                configParams.Types.SingleInterface.ConfiguredUsbInterface;

    //
    // Get the device descriptor and store it in device context
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = Device;
    status = WdfMemoryCreate(
                             &attributes,
                             NonPagedPool,
                             0,
                             sizeof(USB_DEVICE_DESCRIPTOR),
                             &devContext->DeviceDescriptor,
                             &usbDeviceDescriptor
                             );

    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfMemoryCreate for Device Descriptor failed %!STATUS!\n",
            status);
        return status;
    }

    WdfUsbTargetDeviceGetDeviceDescriptor(
          devContext->UsbDevice,
          usbDeviceDescriptor
          );

    //
    // Get the Interrupt pipe. There are other endpoints but we are only
    // interested in interrupt endpoint since our HID data comes from that
    // endpoint. Another way to get the interrupt endpoint is by enumerating
    // through all the pipes in a loop and looking for pipe of Interrupt type.
    //
    devContext->InterruptPipe = WdfUsbInterfaceGetConfiguredPipe(
                                                  devContext->UsbInterface,
                                                  INTERRUPT_ENDPOINT_INDEX,
                                                  NULL);// pipeInfo

    if (NULL == devContext->InterruptPipe) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "Failed to get interrupt pipe info\n");
        status = STATUS_INVALID_DEVICE_STATE;
        return status;
    }

    //
    // Tell the framework that it's okay to read less than
    // MaximumPacketSize
    //
    WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(devContext->InterruptPipe);

    //
    //configure continuous reader
    //
    status = HidFx2ConfigContReaderForInterruptEndPoint(devContext);

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
        "HidFx2EvtDevicePrepareHardware Exit, Status:0x%x\n", status);

    return status;
}
// 并行处理
VOID CY001Drv::DeviceIoControlParallel(IN WDFQUEUE  Queue,
						IN WDFREQUEST  Request,
						IN size_t  OutputBufferLength,
						IN size_t  InputBufferLength,
						IN ULONG  IoControlCode)
{
	NTSTATUS status = STATUS_SUCCESS;
	ULONG ulRetLen = 0;

	size_t size = 0;
	void* pBufferInput = NULL;
	void* pBufferOutput = NULL;

	KDBG(DPFLTR_INFO_LEVEL, "[DeviceIoControlParallel] CtlCode:0x%0.8X", IoControlCode);

	// 取得输入缓冲区,判断其有效性
	if(InputBufferLength){
		status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &pBufferInput, &size);
		if(status != STATUS_SUCCESS || pBufferInput == NULL || size < InputBufferLength){
			WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
			return;
		}
	}

	// 取得输出缓冲区,判断其有效性
	if(OutputBufferLength){
		status = WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, &pBufferOutput, &size);
		if(status != STATUS_SUCCESS || pBufferOutput == NULL || size < OutputBufferLength){
			WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
			return;
		}
	}

	//
	// 下面是主处理过程。
	//
	switch(IoControlCode)
	{
		// 取得驱动的版本信息
	case IOCTL_GET_DRIVER_VERSION:
		{
			PDRIVER_VERSION pVersion = (PDRIVER_VERSION)pBufferOutput;
			ULONG length;
			char tcsBuffer[120];
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_GET_DRIVER_VERSION");

			if(OutputBufferLength < sizeof(DRIVER_VERSION)){
				status = STATUS_BUFFER_TOO_SMALL;
				break;
			}

			pVersion->DriverType = DR_WDF;
			pVersion->FirmwareType = FW_NOT_CY001;
			ulRetLen = sizeof(DRIVER_VERSION);// 告示返回长度

			// 根据String描述符,判断Firmware代码是否已经被加载。
			GetStringDes(2, 0, tcsBuffer, 120, &length);

			if(length){
				WCHAR* pCyName = L"CY001 V";
				size_t len;
				int nIndex;

				if(length < 8)
					break;

				RtlStringCchLengthW(pCyName, 7, &len);
				for(nIndex = 0; nIndex < len; nIndex++){
					if(pCyName[nIndex] != ((WCHAR*)tcsBuffer)[nIndex])
						break;
				}

				if(nIndex == len)
					pVersion->FirmwareType = FW_CY001; // 完全相符,说明新版Firmware已经加载到开发板。
			}
			break;
		}
		
		// 收到App发送过来的一个同步Request,我们应该把它保存到同步Queue中,等到有同步事件发生的时候再从Queue中取出并完成。
	case IOCTL_USB_SYNC:
		KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_SYNC");
		status = WdfRequestForwardToIoQueue(Request, m_hAppSyncManualQueue);

		// 直接返回,不调用WdfRequestComplete函数。
		// 请求者将不会为此而等待;请求的完成在将来的某个时刻。
		// 这就是所谓的异步处理之要义了。
		if(NT_SUCCESS(status))
			return;
		break;

		// 清空同步队列中的所有请求
	case IOCTL_USB_SYNC_RELEASE:
		KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_SYNC");
		ClearSyncQueue();
		break;

		// 应用程序退出,取消所有被阻塞的请求。
	case IOCTL_APP_EXIT_CANCEL: 
			
		// 取消USB设备的所有IO操作。它将连带取消所有Pipe的IO操作。
		//WdfIoTargetStop(WdfUsbTargetDeviceGetIoTarget(m_hUsbDevice), WdfIoTargetCancelSentIo);
		break;

		// 取得当前的配置号.总是设置为0,因为在WDF框架中,0以外的配置是不被支持的。
	case IOCTL_USB_GET_CURRENT_CONFIG:
		{
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_CURRENT_CONFIG");
			if(InputBufferLength < 4){
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			*(PULONG)pBufferInput = 0;// 直接赋值0,即总是选择0号配置。也可以发送URB到总线获取当前配置选项。
			ulRetLen = sizeof(ULONG);
			break;
		}

	case IOCTL_USB_ABORTPIPE:
		{
			ULONG pipenum = *((PULONG) pBufferOutput);
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_ABORTPIPE");

			status = AbortPipe(pipenum);
		}      
		break;

		// 获取Pipe信息
	case IOCTL_USB_GET_PIPE_INFO:
		{
			// 遍历获取Pipe信息,复制到输出缓冲中。
			BYTE byCurSettingIndex = 0;
			BYTE byPipeNum = 0;
			BYTE index;
			USB_INTERFACE_DESCRIPTOR  interfaceDescriptor;
			WDF_USB_PIPE_INFORMATION  pipeInfor;

			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_PIPE_INFO");

			// 取得Pipe数。根据Pipe数计算缓冲区长度
			byCurSettingIndex = WdfUsbInterfaceGetConfiguredSettingIndex(m_hUsbInterface); 
			WdfUsbInterfaceGetDescriptor(m_hUsbInterface, byCurSettingIndex, &interfaceDescriptor);
			byPipeNum = WdfUsbInterfaceGetNumConfiguredPipes(m_hUsbInterface);		

			if(OutputBufferLength < byPipeNum * sizeof(pipeInfor)){
				status = STATUS_BUFFER_TOO_SMALL; // 缓冲区不足
			}else{

				ulRetLen = byPipeNum*sizeof(pipeInfor);

				// 遍历获取全部管道信息,拷贝到输出缓冲中。
				// 应用程序得到输出缓冲的时候,也应该使用WDF_USB_PIPE_INFORMATION结构体解析缓冲区。
				for(index = 0; index < byPipeNum; index++)
				{
					WDF_USB_PIPE_INFORMATION_INIT(&pipeInfor);
					WdfUsbInterfaceGetEndpointInformation(m_hUsbInterface, byCurSettingIndex, index, &pipeInfor);
					RtlCopyMemory((PUCHAR)pBufferOutput + index*pipeInfor.Size, &pipeInfor, sizeof(pipeInfor));
				}
			}
		}

		break;

		// 获取设备描述符
	case IOCTL_USB_GET_DEVICE_DESCRIPTOR:
		{
			USB_DEVICE_DESCRIPTOR  UsbDeviceDescriptor;
			WdfUsbTargetDeviceGetDeviceDescriptor(m_hUsbDevice, &UsbDeviceDescriptor);
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_DEVICE_DESCRIPTOR");

			// 判断输入缓冲区的长度是否足够长
			if(OutputBufferLength < UsbDeviceDescriptor.bLength)
				status = STATUS_BUFFER_TOO_SMALL;
			else{
				RtlCopyMemory(pBufferOutput, &UsbDeviceDescriptor, UsbDeviceDescriptor.bLength);
				ulRetLen = UsbDeviceDescriptor.bLength;
			}

			break;
		}

		// 获取字符串描述符
	case IOCTL_USB_GET_STRING_DESCRIPTOR:
		{
			PGET_STRING_DESCRIPTOR Input = (PGET_STRING_DESCRIPTOR)pBufferInput;
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_STRING_DESCRIPTOR");
			status = GetStringDes(Input->Index, Input->LanguageId, pBufferOutput, OutputBufferLength, &ulRetLen);
			
			// 由字符长度调整为字节长度
			if(NT_SUCCESS(status) && ulRetLen > 0)
				ulRetLen *= (sizeof(WCHAR)/sizeof(char));
			break;
		}

		// 获取配置描述信息。
	case IOCTL_USB_GET_CONFIGURATION_DESCRIPTOR:
		{
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_CONFIGURATION_DESCRIPTOR");

			// 首先获得配置描述符的长度。
			status = WdfUsbTargetDeviceRetrieveConfigDescriptor(m_hUsbDevice, NULL, (USHORT*)&size);
			if(!NT_SUCCESS(status) && status != STATUS_BUFFER_TOO_SMALL)
				break;

			// 输出缓冲区不够长
			if(OutputBufferLength < size)
				break;

			// 正式取得配置描述符。
			status = WdfUsbTargetDeviceRetrieveConfigDescriptor(m_hUsbDevice, pBufferOutput, (USHORT*)&size);
			if(!NT_SUCCESS(status))
				break;

			ulRetLen = size;
			break;
		}

		// 根据可选值配置接口
	case IOCTL_USB_SET_INTERFACE:
		{
			BYTE byAlterSetting = *(BYTE*)pBufferInput;
			BYTE byCurSetting = WdfUsbInterfaceGetConfiguredSettingIndex(m_hUsbInterface); // 当前Alternate值

			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_SETINTERFACE");

			if(InputBufferLength < 1 || OutputBufferLength < 1)
			{
				status = STATUS_BUFFER_TOO_SMALL;
				break;
			}
			
			// 如果传入的可选值与当前的不同,则重新配置接口;
			// 否则直接返回。
			if(byCurSetting != byAlterSetting)
			{
				WDF_USB_INTERFACE_SELECT_SETTING_PARAMS par;
				WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_SETTING(&par, byAlterSetting);
				status = WdfUsbInterfaceSelectSetting(m_hUsbInterface, NULL, &par);
			}

			*(BYTE*)pBufferOutput = byCurSetting;
			break;
		}

		// 固件Rest。自定义命令,与Port Rest是两码事。
	case IOCTL_USB_FIRMWRAE_RESET:
		{
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_FIRMWRAE_RESET");
			if(InputBufferLength < 1 || pBufferInput == NULL)
				status = STATUS_INVALID_PARAMETER;
			else
				status = FirmwareReset(*(char*)pBufferInput);

			break;
		}

		// 重置USB总线端口
	case IOCTL_USB_PORT_RESET:
		{
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_PORT_RESET");			
			WdfUsbTargetDeviceResetPortSynchronously(m_hUsbDevice);
			break;
		}

		// 管道重置
	case IOCTL_USB_PIPE_RESET:
		{
			UCHAR uchPipe;
			WDFUSBPIPE pipe = NULL;

			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_PIPE_RESET");			

			if(InputBufferLength < 1){
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			// 根据ID找到对应的Pipe
			uchPipe = *(UCHAR*)pBufferInput;
			pipe = WdfUsbInterfaceGetConfiguredPipe(m_hUsbInterface, uchPipe, NULL);
			if(pipe == NULL){ 
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			status = WdfUsbTargetPipeResetSynchronously(pipe, NULL, NULL);
			break;
		}

		// 中断管道,放弃管道当前正在进行的操作
	case IOCTL_USB_PIPE_ABORT:
		{
			UCHAR uchPipe;
			WDFUSBPIPE pipe = NULL;

			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_PIPE_ABORT");

			if(InputBufferLength < 1){
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			// 根据ID找到对应的Pipe
			uchPipe = *(UCHAR*)pBufferInput;
			pipe = WdfUsbInterfaceGetConfiguredPipe(m_hUsbInterface, uchPipe, NULL);
			if(pipe == NULL){ 
				status = STATUS_INVALID_PARAMETER;
				break;
			}
			
			status = WdfUsbTargetPipeAbortSynchronously(pipe, NULL, NULL);
			break;
		}

		// 取得驱动错误信息,驱动总是把最后一次发现的错误保存在设备对象的环境块中。
		// 这个逻辑虽然实现了,但目前的版本中,应用程序并没有利用这个接口。
	case IOCTL_USB_GET_LAST_ERROR:
		{
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_LAST_ERROR");

			if (OutputBufferLength >= sizeof(ULONG))
				*((PULONG)pBufferOutput) = m_ulLastUSBErrorStatusValue;
			else
				status = STATUS_BUFFER_TOO_SMALL;

			ulRetLen = sizeof(ULONG);
			break;
		}

		// Clear feature命令
	case IOCTL_USB_SET_CLEAR_FEATURE:
		{
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_SET_CLEAR_FEATURE");
			status = UsbSetOrClearFeature(Request);
			break;
		}

		// 为USB设备加载固件程序。带有偏移量参数,用这个分支;不带偏移量,可用下一个分支。
		// 带偏移量的情况下,固件代码是一段一段地加载;
		// 不带偏移量的情况,固件代码作为一整块一次性被加载。
	case IOCTL_FIRMWARE_UPLOAD_OFFSET:
		{
			void* pData = pBufferOutput;
			WORD offset = 0;

			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_FIRMWARE_UPLOAD_OFFSET");

			if(InputBufferLength < sizeof(WORD)){
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			offset = *(WORD*)pBufferInput;
			status = FirmwareUpload((PUCHAR)pData, OutputBufferLength, offset);
			break;
		}

		// 为USB设备加载固件程序。
	case IOCTL_FIRMWARE_UPLOAD:
		{
			void* pData = pBufferOutput;
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_FIRMWARE_UPLOAD");
			status = FirmwareUpload((PUCHAR)pData, InputBufferLength, 0);
			break;
		}

		// 读取开发板设备的RAM内容。RAM也就是内存。
		// 每次从同一地址读取的内容可能不尽相同,开发板中固件程序在不断运行,RAM被用来储数据(包括临时数据)。
	case IOCTL_FIRMWARE_READ_RAM:
		{
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_FIRMWARE_READ_RAM");
			status = ReadRAM(Request, &ulRetLen);// inforVal中保存读取的长度
			break;
		}

		// 其他的请求
	default:
		{
			// 一律转发到SerialQueue中去。			
			WdfRequestForwardToIoQueue(Request, m_hIoCtlSerialQueue);

			// 命令转发之后,这里必须直接返回,千万不可调用WdfRequestComplete函数。
			// 否则会导致一个Request被完成两次的错误。
			return;
		}
	}

	// 完成请求
	WdfRequestCompleteWithInformation(Request, status, ulRetLen);
}
示例#5
0
文件: usb.c 项目: 340211173/Driver
// In this callback, the driver does whatever is necessary to make the hardware ready to use.
// In the case of a USB device, this involves reading and selecting descriptors.
NTSTATUS
HidFx2EvtDevicePrepareHardware(
    _In_ WDFDEVICE    hDevice,
    _In_ WDFCMRESLIST hResourceList,
    _In_ WDFCMRESLIST hResourceListTranslated
   )
{
    NTSTATUS                            status = STATUS_SUCCESS;
    PDEVICE_EXTENSION                   pDevContext = NULL;
    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;
    WDF_OBJECT_ATTRIBUTES               attributes;
    PUSB_DEVICE_DESCRIPTOR              pUsbDeviceDescriptor = NULL;

    UNREFERENCED_PARAMETER(hResourceList);
    UNREFERENCED_PARAMETER(hResourceListTranslated);

    PAGED_CODE ();

    TraceVerbose(DBG_INIT, "(%!FUNC!) Enter\n");

    pDevContext = GetDeviceContext(hDevice);

    // Create a WDFUSBDEVICE object. WdfUsbTargetDeviceCreate obtains the USB device descriptor and the first USB configuration
    //descriptor from the device and stores them. It also creates a framework USB interface object for each interface in the device's first configuration.
    //
    // The parent of each USB device object is the driver's framework driver object. The driver cannot change this parent, and the ParentObject
    // member or the WDF_OBJECT_ATTRIBUTES structure must be NULL.
    //
    // We only create device the first time PrepareHardware is called. If the device is restarted by pnp manager for resource rebalance, we 
    // will use the same device handle but then select the interfaces again because the USB stack could reconfigure the device on restart.
    if (pDevContext->hUsbDevice == NULL)
    {
        status = WdfUsbTargetDeviceCreate(hDevice, WDF_NO_OBJECT_ATTRIBUTES, &pDevContext->hUsbDevice);
        if (!NT_SUCCESS(status))
        {
            TraceErr(DBG_PNP, "(%!FUNC!) WdfUsbTargetDeviceCreate failed %!STATUS!\n", status);
            return status;
        }
    }

    // Select a device configuration by using a WDF_USB_DEVICE_SELECT_CONFIG_PARAMS
    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&configParams);
    status = WdfUsbTargetDeviceSelectConfig(pDevContext->hUsbDevice, WDF_NO_OBJECT_ATTRIBUTES, &configParams);
    if (!NT_SUCCESS(status))
    {
        TraceErr(DBG_PNP, "(%!FUNC!) WdfUsbTargetDeviceSelectConfig failed %!STATUS!\n", status);
        return status;
    }

    pDevContext->hUsbInterface = configParams.Types.SingleInterface.ConfiguredUsbInterface;

    // Get the device descriptor and store it in device context
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = hDevice;
    status = WdfMemoryCreate(&attributes,
                             NonPagedPool,
                             0,
                             sizeof(USB_DEVICE_DESCRIPTOR),
                             &pDevContext->hDeviceDescriptor,
                             &pUsbDeviceDescriptor);
    if (!NT_SUCCESS(status))
    {
        TraceErr(DBG_PNP, "(%!FUNC!) WdfMemoryCreate for Device Descriptor failed %!STATUS!\n", status);
        return status;
    }

    WdfUsbTargetDeviceGetDeviceDescriptor(pDevContext->hUsbDevice, pUsbDeviceDescriptor);

    // Get the Interrupt pipe. There are other endpoints but we are only interested in interrupt endpoint since our HID data comes from this
    pDevContext->hInterruptPipe = WdfUsbInterfaceGetConfiguredPipe(pDevContext->hUsbInterface, INTERRUPT_ENDPOINT_INDEX, NULL);
    if (NULL == pDevContext->hInterruptPipe)
    {
        TraceErr(DBG_PNP, "(%!FUNC!) Failed to get interrupt pipe info\n");
        status = STATUS_INVALID_DEVICE_STATE;
        return status;
    }

    // Tell the framework that it's okay to read less than MaximumPacketSize
    WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pDevContext->hInterruptPipe);

    //configure continuous reader
    status = HidFx2ConfigContReaderForInterruptEndPoint(pDevContext);

    TraceVerbose(DBG_INIT, "(%!FUNC!) Exit, Status: %!STATUS!\n", status);

    return status;
}
NTSTATUS AndroidUsbDeviceObject::OnEvtDevicePrepareHardware(
    WDFCMRESLIST resources_raw,
    WDFCMRESLIST resources_translated) {
  ASSERT_IRQL_PASSIVE();

  // Create a USB device handle so that we can communicate with the underlying
  // USB stack. The wdf_target_device_ handle is used to query, configure, and
  // manage all aspects of the USB device. These aspects include device
  // properties, bus properties, and I/O creation and synchronization. This
  // call gets the device and configuration descriptors and stores them in
  // wdf_target_device_ object.
  NTSTATUS status = WdfUsbTargetDeviceCreate(wdf_device(),
                                             WDF_NO_OBJECT_ATTRIBUTES,
                                             &wdf_target_device_);
  ASSERT(NT_SUCCESS(status) && (NULL != wdf_target_device_));
  if (!NT_SUCCESS(status))
    return status;

  // Retrieve USBD version information, port driver capabilites and device
  // capabilites such as speed, power, etc.
  WDF_USB_DEVICE_INFORMATION_INIT(&usb_device_info_);
  status = WdfUsbTargetDeviceRetrieveInformation(wdf_target_device(),
                                                 &usb_device_info_);
  ASSERT(NT_SUCCESS(status));
  if (!NT_SUCCESS(status))
    return status;

  WdfUsbTargetDeviceGetDeviceDescriptor(wdf_target_device(),
                                        &usb_device_descriptor_);
#if DBG
  PrintUsbTargedDeviceInformation(usb_device_info());
  PrintUsbDeviceDescriptor(&usb_device_descriptor_);
#endif  // DBG

  // Save device serial number
  status =
    WdfUsbTargetDeviceAllocAndQueryString(wdf_target_device(),
                                          WDF_NO_OBJECT_ATTRIBUTES,
                                          &serial_number_handle_,
                                          &serial_number_char_len_,
                                          usb_device_descriptor_.iSerialNumber,
                                          0x0409);  // English (US)
  if (!NT_SUCCESS(status))
    return status;

#if DBG
  UNICODE_STRING ser_num;
  ser_num.Length = serial_number_byte_len();
  ser_num.MaximumLength = ser_num.Length;
  ser_num.Buffer = const_cast<WCHAR*>
    (serial_number());
  GoogleDbgPrint("\n*** Device serial number %wZ", &ser_num);
#endif  // DBG

  // Configure our device now
  status = ConfigureDevice();
  ASSERT(NT_SUCCESS(status));
  if (!NT_SUCCESS(status))
    return status;

  // Select device interfaces
  status = SelectInterfaces();
  if (!NT_SUCCESS(status))
    return status;

  return status;
}
示例#7
0
NTSTATUS
  CyEvtDevicePrepareHardware (
    IN WDFDEVICE  Device,
    IN WDFCMRESLIST  ResourcesRaw,
    IN WDFCMRESLIST  ResourcesTranslated
    )
{
	NTSTATUS  NTStatus;
	PDEVICE_CONTEXT  pDeviceContext;
	WDF_USB_DEVICE_INFORMATION UsbDeviceInfo;
    ULONG ulWaitWakeEnable;

	UNICODE_STRING unicodeSCRIPTFILE;	
	WDF_OBJECT_ATTRIBUTES  attributes;
	WDFMEMORY  hScriptFileNameBufMem;
	PVOID  pScriptFNBuf=NULL;
	ULONG ScripFileNtBufferlen=0;

	UNREFERENCED_PARAMETER(ResourcesRaw);
    UNREFERENCED_PARAMETER(ResourcesTranslated);
    ulWaitWakeEnable = FALSE;

    PAGED_CODE();

    CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "Start CyEvtDevicePrepareHardware\n");

    pDeviceContext = CyGetDeviceContext(Device);

	//
    // Create a USB device handle so that we can communicate with the
    // underlying USB stack. The WDFUSBDEVICE handle is used to query,
    // configure, and manage all aspects of the USB device.
    // These aspects include device properties, bus properties,
    // and I/O creation and synchronization. We only create device the first
    // the PrepareHardware is called. If the device is restarted by pnp manager
    // for resource rebalance, we will use the same device handle but then select
    // the interfaces again because the USB stack could reconfigure the device on
    // restart.
    //	
    if (pDeviceContext->CyUsbDevice == NULL)
	{
        NTStatus = WdfUsbTargetDeviceCreate(Device,
                                    WDF_NO_OBJECT_ATTRIBUTES,
                                    &pDeviceContext->CyUsbDevice);
        if (!NT_SUCCESS(NTStatus)) {
            CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                 "WdfUsbTargetDeviceCreate failed with Status code %!STATUS!\n", NTStatus);
            return NTStatus;
        }
    }    

	 //
    // Retrieve USBD version information, port driver capabilites and device
    // capabilites such as speed, power, etc.
    //
    WDF_USB_DEVICE_INFORMATION_INIT(&UsbDeviceInfo);

    NTStatus = WdfUsbTargetDeviceRetrieveInformation(
                                pDeviceContext->CyUsbDevice,
                                &UsbDeviceInfo);
    if (NT_SUCCESS(NTStatus))
	{
        CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "IsDeviceHighSpeed: %s\n",
            (UsbDeviceInfo.Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED) ? "TRUE" : "FALSE");
        CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                    "IsDeviceSelfPowered: %s\n",
            (UsbDeviceInfo.Traits & WDF_USB_DEVICE_TRAIT_SELF_POWERED) ? "TRUE" : "FALSE");

        ulWaitWakeEnable = UsbDeviceInfo.Traits &
                            WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE;

        CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                            "IsDeviceRemoteWakeable: %s\n",
                            ulWaitWakeEnable ? "TRUE" : "FALSE");
        
        pDeviceContext->ulUSBDeviceTrait = UsbDeviceInfo.Traits;
		pDeviceContext->ulUSBDIVersion = UsbDeviceInfo.UsbdVersionInformation.USBDI_Version;
		pDeviceContext->ulWaitWakeEnable = ulWaitWakeEnable;
    }   
	
	//Get device descriptor
	WdfUsbTargetDeviceGetDeviceDescriptor(
									  pDeviceContext->CyUsbDevice,
									  &pDeviceContext->UsbDeviceDescriptor
									  );
	
    NTStatus = CySelectInterfaces(Device);

    if (!NT_SUCCESS(NTStatus))
	{
        CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "SelectInterfaces failed 0x%x\n", NTStatus);

        return NTStatus;
    }
   
	if (ulWaitWakeEnable)
	{
        NTStatus = CySetPowerPolicy(Device);
        if (!NT_SUCCESS (NTStatus)) 
		{
            CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                                "Set power policy failed  %!STATUS!\n", NTStatus);
            return NTStatus;
        }
    }
	// Check for the script file in the registry and execute if it is exist
	
	// Allocate buffer to get the registry key
	WDF_OBJECT_ATTRIBUTES_INIT(&attributes);	
	NTStatus = WdfMemoryCreate(
							 &attributes,
							 NonPagedPool,
							 0,
							 CYREGSCRIPT_BUFFER_SIZE,
							 &hScriptFileNameBufMem,
							 &pScriptFNBuf
							 );
	if (!NT_SUCCESS(NTStatus)) {
		CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfMemoryCreate failed  %!STATUS!\n",NTStatus);        
		return FALSE;
	}

	
    if(GetRegistryKey(Device, NULL, REG_SZ, CYREG_SCRIPTFILE, pScriptFNBuf,&ScripFileNtBufferlen)) 
    {	
        CyExecuteScriptFile(Device, pScriptFNBuf);
    }
	CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "End CyEvtDevicePrepareHardware\n");		
        
	////
	CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "End CyEvtDevicePrepareHardware\n");	
	return NTStatus;
}