int main(int argc, char ** argv) { libusb_context * ctx = NULL; libusb_device_handle * dev = NULL; setup_libusb(&ctx, &dev); /// if (!InitGSCommsNoisy(dev, RETRIES, 1)) { fprintf(stderr, "init failed\n"); exit(-1); } // check for Neon64 already present unsigned char check_sig[4] = {0xff,0xff,0xff,0xff}; // ReadRAM(dev, check_sig, 0x80000404UL, 4); //ReadRAM(dev, check_sig, 0xA07919B0UL, 4); //ReadRAM(dev, check_sig, 0x80300000UL, 4); ReadRAM(dev, check_sig, 0xA0787CD8, 4); printf("%02x%02x%02x%02x\n", check_sig[0], check_sig[1], check_sig[2], check_sig[3]); Disconnect(dev); cleanup_libusb(ctx, dev); dev = NULL; ctx = NULL; return 0; }
/******************************************************************************* * Function Name : MainTrim * Description : STC3115 internal register configuration function * This function has to be called at stable battery voltage during the application magnufacturing * This function is checking itself the propper configuration of the device. *******************************************************************************/ int MainTrim(struct i2c_client *client) { unsigned char IDCode; int ii,error,testnbr; if (client) sav_client = client; else return STC_CONFIG_CLIENT_FAIL; //Check the cut v ersion I2C_ReadByte(0xE0,0x18,&IDCode,1); //read IDcode if(IDCode == 0x13) { return STC_CONFIG_IDCODE_NOTMATCH; } ReadRAM(); //Enter test mode ReadSector(0, Sector0); //read sector 0 ExitTest(); //exit test mode if ( (Sector0[1] & 0x01) == 0 ) { testnbr=0; do { ReadRAM(); //Enter test mode ReadSector(0, Sector0); //read sector 0 ExitTest(); //exit test mode Sector0 [1] = Sector0[1] | 0x01 ; PreWriteNVN(0x40); //Enter test mode WriteSector(6,Sector0);//write sector 0 in 6 ExitTest(); ReadRAM(); //Enter test mode ReadSector(6, Sector6); //read sector 6 ExitTest(); //exit test mode error=0; for(ii=0;ii<8;ii++) { if(Sector0[ii] != Sector6[ii]) error++; } testnbr++; } while(error > 0 && testnbr < 5); if (testnbr >= 3) return STC_CONFIG_TEST_FAIL; testnbr=0; do { PreWriteNVN(0x01); //Enter test mode WriteSector(0,Sector6);//write sector 0 in 0 ExitTest(); ReadRAM(); //Enter test mode ReadSector(0, Sector0); //read sector 0 ExitTest(); //exit test mode error=0; for(ii=0;ii<8;ii++) { if(Sector0[ii] != Sector6[ii]) error++; } testnbr++; } while(error > 0 && testnbr < 5); } //Check sector 6 status #if defined (CONFIG_MACH_HENDRIX) || \ defined (CONFIG_MACH_LT02) || \ defined (CONFIG_MACH_COCOA7) Sector3 [ 0 ]=0x82 ; Sector3 [ 1 ]=0x8C ; Sector3 [ 2 ]=0xA0 ; Sector3 [ 3 ]=0xB4 ; Sector3 [ 4 ]=0xC8 ; Sector3 [ 5 ]=0x70 ; Sector3 [ 6 ]=0x17 ; Sector3 [ 7 ]=0x27 ; Sector4 [ 0 ]=0x19 ; Sector4 [ 1 ]=0xB2 ; Sector4 [ 2 ]=0x19 ; Sector4 [ 3 ]=0xFA ; Sector4 [ 4 ]=0x19 ; Sector4 [ 5 ]=0x3E ; Sector4 [ 6 ]=0x1A ; Sector4 [ 7 ]=0x6D ; Sector5 [ 0 ]=0x1A ; Sector5 [ 1 ]=0x9D ; Sector5 [ 2 ]=0x1A ; Sector5 [ 3 ]=0xB7 ; Sector5 [ 4 ]=0x1A ; Sector5 [ 5 ]=0xD5 ; Sector5 [ 6 ]=0x1A ; Sector5 [ 7 ]=0x01 ; Sector6 [ 0 ]=0x1B ; Sector6 [ 1 ]=0x6F ; Sector6 [ 2 ]=0x1B ; Sector6 [ 3 ]=0xB1 ; Sector6 [ 4 ]=0x1B ; Sector6 [ 5 ]=0xE7 ; Sector6 [ 6 ]=0x1B ; Sector6 [ 7 ]=0x59 ; ReadRAM(); //Enter test mode ReadSector(7, Sector0); //read sector 7 ReadSector(7, Sector7); //read sector 7 ExitTest(); //exit test mode Sector7 [ 0 ]=0x1C ; Sector7 [ 1 ]=0xF3 ; Sector7 [ 2 ]=0x1C ; Sector7 [ 3 ]=0xA8 ; Sector7 [ 4 ]=0x1D ; error=0; for(ii=0;ii<8;ii++) { if(Sector0[ii] != Sector7[ii]) error++; } testnbr=0; while(error > 0 && testnbr < 5) { PreWriteNVN(0x80); //Enter test mode WriteSector(7,Sector7);//write sector 7 in 7 ExitTest(); ReadRAM(); //Enter test mode ReadSector(7, Sector0); //read sector 7 ExitTest(); //exit test mode error=0; for(ii=0;ii<8;ii++) { if(Sector7[ii] != Sector0[ii]) error++; } testnbr++; } //write sector 3 in 3 ReadRAM(); //Enter test mode ReadSector(3, Sector0); //read sector 3 ExitTest(); //exit test mode error=0; for(ii=0;ii<8;ii++) { if(Sector0[ii] != Sector3[ii]) error++; } testnbr=0; while(error > 0 && testnbr < 5) { PreWriteNVN(0x08); //Enter test mode WriteSector(3,Sector3);//write sector 3 in 3 ExitTest(); ReadRAM(); //Enter test mode ReadSector(3, Sector0); //read sector 3 ExitTest(); //exit test mode error=0; for(ii=0;ii<8;ii++) { if(Sector3[ii] != Sector0[ii]) error++; } testnbr++; } //write sector 4 in 4 ReadRAM(); //Enter test mode ReadSector(4, Sector0); //read sector 4 ExitTest(); //exit test mode error=0; for(ii=0;ii<8;ii++) { if(Sector0[ii] != Sector4[ii]) error++; } testnbr=0; while(error > 0 && testnbr < 5) { PreWriteNVN(0x10); //Enter test mode WriteSector(4,Sector4);//write sector 4 in 4 ExitTest(); ReadRAM(); //Enter test mode ReadSector(4, Sector0); //read sector 4 ExitTest(); //exit test mode error=0; for(ii=0;ii<8;ii++) { if(Sector4[ii] != Sector0[ii]) error++; } testnbr++; } //write sector 5 in 5 ReadRAM(); //Enter test mode ReadSector(5, Sector0); //read sector 5 ExitTest(); //exit test mode error=0; for(ii=0;ii<8;ii++) { if(Sector0[ii] != Sector5[ii]) error++; } testnbr=0; while(error > 0 && testnbr < 5) { PreWriteNVN(0x20); //Enter test mode WriteSector(5,Sector5);//write sector 5 in 5 ExitTest(); ReadRAM(); //Enter test mode ReadSector(5, Sector0); //read sector 5 ExitTest(); //exit test mode error=0; for(ii=0;ii<8;ii++) { if(Sector5[ii] != Sector0[ii]) error++; } testnbr++; } //write sector 6 in 6 ReadRAM(); //Enter test mode ReadSector(6, Sector0); //read sector 6 ExitTest(); //exit test mode #else Sector6 [ 0 ]=0x1B ; Sector6 [ 1 ]=0xCD ; Sector6 [ 2 ]=0x1B ; Sector6 [ 3 ]=0x13 ; Sector6 [ 4 ]=0x1C ; Sector6 [ 5 ]=0x57 ; Sector6 [ 6 ]=0x1C ; Sector6 [ 7 ]=0x09 ; ReadRAM(); //Enter test mode ReadSector(6, Sector0); //read sector 0 ExitTest(); //exit test mode #endif error=0; for(ii=0;ii<8;ii++) { if(Sector0[ii] != Sector6[ii]) error++; } testnbr=0; while(error > 0 && testnbr < 5) { PreWriteNVN(0x40); //Enter test mode WriteSector(6,Sector6);//write sector 6 in 6 ExitTest(); ReadRAM(); //Enter test mode ReadSector(6, Sector0); //read sector 0 ExitTest(); //exit test mode error=0; for(ii=0;ii<8;ii++) { if(Sector0[ii] != Sector6[ii]) error++; } testnbr++; } return -1; }
/******************************************************************************* * Function Name : MainTrim * Description : STC3115 internal register configuration function * This function has to be called at stable battery voltage during the application magnufacturing * This function is checking itself the propper configuration of the device. *******************************************************************************/ int MainTrim(struct i2c_client *client) { unsigned char IDCode,RAMBuffer[16]; int ii,error,testnbr; if (client) sav_client = client; else return STC_CONFIG_CLIENT_FAIL; //Check the cut v ersion I2C_ReadByte(0xE0,0x18,&IDCode,1); //read IDcode if(IDCode == 0x13) { return STC_CONFIG_IDCODE_NOTMATCH; } I2C_ReadByte(0xE0,0x20,RAMBuffer,16); //read RAM memory content ReadRAM(); //Enter test mode ReadSector(0, Sector0); //read sector 0 ExitTest(); //exit test mode if ( (Sector0[1] & 0x01) == 0 ) { testnbr=0; do { ReadRAM(); //Enter test mode ReadSector(0, Sector0); //read sector 0 ExitTest(); //exit test mode Sector0 [1] = Sector0[1] | 0x01 ; PreWriteNVN(0x40); //Enter test mode WriteSector(6,Sector0);//write sector 0 in 6 ExitTest(); ReadRAM(); //Enter test mode ReadSector(6, Sector6); //read sector 6 ExitTest(); //exit test mode error=0; for(ii=0;ii<8;ii++) { if(Sector0[ii] != Sector6[ii]) error++; } testnbr++; } while(error > 0 && testnbr < 5); if (testnbr >= 3) { I2C_WriteByte(0xE0,0x20,RAMBuffer,16);//restore RAM memory content return STC_CONFIG_TEST_FAIL; } testnbr=0; do { PreWriteNVN(0x01); //Enter test mode WriteSector(0,Sector6);//write sector 0 in 0 ExitTest(); ReadRAM(); //Enter test mode ReadSector(0, Sector0); //read sector 0 ExitTest(); //exit test mode error=0; for(ii=0;ii<8;ii++) { if(Sector0[ii] != Sector6[ii]) error++; } testnbr++; } while(error > 0 && testnbr < 5); } //Check sector 6 status Sector6 [ 0 ]=0x1B ; Sector6 [ 1 ]=0xCD ; Sector6 [ 2 ]=0x1B ; Sector6 [ 3 ]=0x13 ; Sector6 [ 4 ]=0x1C ; Sector6 [ 5 ]=0x57 ; Sector6 [ 6 ]=0x1C ; Sector6 [ 7 ]=0x09 ; ReadRAM(); //Enter test mode ReadSector(6, Sector0); //read sector 7 ExitTest(); //exit test mode error=0; for(ii=0;ii<8;ii++) { if(Sector0[ii] != Sector6[ii]) error++; } testnbr=0; while(error > 0 && testnbr < 5) { PreWriteNVN(0x40); //Enter test mode WriteSector(6,Sector6);//write sector 7 in 7 ExitTest(); ReadRAM(); //Enter test mode ReadSector(6, Sector0); //read sector 7 ExitTest(); //exit test mode error=0; for(ii=0;ii<8;ii++) { if(Sector0[ii] != Sector6[ii]) error++; } testnbr++; } I2C_WriteByte(0xE0,0x20,RAMBuffer,16);//restore RAM memory content return -1; }
// 并行处理 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); }