![]() | |
![]() |
| | Thread Tools | Search this Thread | Display Modes |
#1
| |||
| |||
|
#2
| |||
| |||
|
|
I'm doing a IO Control function call to set a I2C device's frequency as the first part of a sequence of other IO calls. I'm getting an access violation in unmanged code in passing PBYTE pBufIn in the function below's signature. I've included a description of the comments for the driver function call and the application user code I wrote. Can someone tell me what I didn't do or tell me how to code this correctly so it passs the PBYTE pBufin argument that represents the frequency value. It is defined as a 4 byte array and the driver code casts this to a DWORD. The frequency value is not being set |
|
--Device Code --- // // Function: I2C_IOControl // // This function sends a command to a device. // // Parameters: // hOpenContext // [in] Handle to the open context of the device. The XXX_Open // function creates and returns this identifier. // dwCode // [in] I/O control operation to perform. These codes are // device-specific and are usually exposed to developers through // a header file. // pBufIn // [in] Pointer to the buffer containing data to transfer to the // device. // dwLenIn // [in] Number of bytes of data in the buffer specified for pBufIn. // // pBufOut // [out] Pointer to the buffer used to transfer the output data // from the device. // dwLenOut // [in] Maximum number of bytes in the buffer specified by pBufOut. // // pdwActualOut // [out] Pointer to the DWORD buffer that this function uses to // return the actual number of bytes received from the device. // // Returns: // The new data pointer for the device indicates success. A value of -1 // indicates failure. BOOL I2C_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut) { BOOL bRet = FALSE; // hOpenContext is a pointer to I2CClass instance! I2CClass* pI2C = (I2CClass*) hOpenContext; DEBUGMSG (ZONE_IOCTL|ZONE_FUNCTION, (TEXT("I2C_IOControl: +hOpenContext=0x%x\r\n"),hOpenContext)); if (pI2C != NULL) { switch (dwCode) { case I2C_IOCTL_SET_FREQUENCY: { if (dwLenIn != sizeof(DWORD)) return FALSE; PDWORD pdwFrequency = (PDWORD) MapCallerPtr(pBufIn, sizeof(DWORD)); DEBUGMSG (ZONE_IOCTL|ZONE_FUNCTION, (TEXT("I2C_IOControl:SET_FREQUENCY + ValIn=0x%x\r\n"), *pdwFrequency)); WORD wClkRate = BSPCalculateClkRateDiv(*pdwFrequency); pI2C->SetClockRateDivider(wClkRate); bRet = TRUE; break; } default: { bRet = FALSE; break; } } } ---Application User Code---- // // IOCTL codes // public static uint CTL_CODE(uint DeviceType, uint Function, uint Method, uint Access) { return(((DeviceType) << 16) | ((Access) << 14) | ((Function) 2) | (Method)); } // // Set the Frequency of I2C device // Byte[] freq = new Byte[4]; Byte[] ba = BitConverter.GetBytes(i2CBus.I2C_SCLK_FREQ); freq[0] = ba[3]; freq[1] = ba[2]; freq[2] = ba[1]; freq[3] = ba[0]; GCHandle handle = GCHandle.Alloc(freq, GCHandleType.Pinned); IntPtr p = handle.AddrOfPinnedObject(); uint objectsize = freq.Length; bool val = I2C.I2CIOControl(m_hI2c, i2CBus.CTL_CODE(i2CBus.FILE_DEVICE_BUS_EXTENDER, i2CBus.I2C_IOCTL_SET_FREQUENCY, i2CBus.METHOD_BUFFERED, i2CBus.FILE_ANY_ACCESS), p, objectsize, IntPtr.Zero, 0, IntPtr.Zero); Marshal.FreeHGlobal(p); |
#3
| |||
| |||
|
|
"Tonofit" <Tonofit (AT) discussions (DOT) microsoft.com> wrote in message news:141A3D2E-00B8-458A-BE50-ADB6F43E9A7C (AT) microsoft (DOT) com... I'm doing a IO Control function call to set a I2C device's frequency as the first part of a sequence of other IO calls. I'm getting an access violation in unmanged code in passing PBYTE pBufIn in the function below's signature. I've included a description of the comments for the driver function call and the application user code I wrote. Can someone tell me what I didn't do or tell me how to code this correctly so it passs the PBYTE pBufin argument that represents the frequency value. It is defined as a 4 byte array and the driver code casts this to a DWORD. The frequency value is not being set Then you should declare the argument as "ref uint", which is the C# equivalent to DWORD. For low-level interaction with device drivers, though, I've always found that C++/CLI is far superior to C#. Just something like: #include <winnt.h ref class PWM { public: property uint Frequency { void set(uint value); } }; |
|
void PWM::Frequency::set(uint value) { if (!I2CIOControl(m_hI2c, I2C_IOCTL_SET_FREQUENCY, &value, sizeof value, nullptr, 0, nullptr)) throw gcnew IOException("Failed to set PWM frequency to " + value.ToString()); } --Device Code --- // // Function: I2C_IOControl // // This function sends a command to a device. // // Parameters: // hOpenContext // [in] Handle to the open context of the device. The XXX_Open // function creates and returns this identifier. // dwCode // [in] I/O control operation to perform. These codes are // device-specific and are usually exposed to developers through // a header file. // pBufIn // [in] Pointer to the buffer containing data to transfer to the // device. // dwLenIn // [in] Number of bytes of data in the buffer specified for pBufIn. // // pBufOut // [out] Pointer to the buffer used to transfer the output data // from the device. // dwLenOut // [in] Maximum number of bytes in the buffer specified by pBufOut. // // pdwActualOut // [out] Pointer to the DWORD buffer that this function uses to // return the actual number of bytes received from the device. // // Returns: // The new data pointer for the device indicates success. A value of -1 // indicates failure. BOOL I2C_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut) { BOOL bRet = FALSE; // hOpenContext is a pointer to I2CClass instance! I2CClass* pI2C = (I2CClass*) hOpenContext; DEBUGMSG (ZONE_IOCTL|ZONE_FUNCTION, (TEXT("I2C_IOControl: +hOpenContext=0x%x\r\n"),hOpenContext)); if (pI2C != NULL) { switch (dwCode) { case I2C_IOCTL_SET_FREQUENCY: { if (dwLenIn != sizeof(DWORD)) return FALSE; PDWORD pdwFrequency = (PDWORD) MapCallerPtr(pBufIn, sizeof(DWORD)); DEBUGMSG (ZONE_IOCTL|ZONE_FUNCTION, (TEXT("I2C_IOControl:SET_FREQUENCY + ValIn=0x%x\r\n"), *pdwFrequency)); WORD wClkRate = BSPCalculateClkRateDiv(*pdwFrequency); pI2C->SetClockRateDivider(wClkRate); bRet = TRUE; break; } default: { bRet = FALSE; break; } } } ---Application User Code---- // // IOCTL codes // public static uint CTL_CODE(uint DeviceType, uint Function, uint Method, uint Access) { return(((DeviceType) << 16) | ((Access) << 14) | ((Function) 2) | (Method)); } // // Set the Frequency of I2C device // Byte[] freq = new Byte[4]; Byte[] ba = BitConverter.GetBytes(i2CBus.I2C_SCLK_FREQ); freq[0] = ba[3]; freq[1] = ba[2]; freq[2] = ba[1]; freq[3] = ba[0]; GCHandle handle = GCHandle.Alloc(freq, GCHandleType.Pinned); IntPtr p = handle.AddrOfPinnedObject(); uint objectsize = freq.Length; bool val = I2C.I2CIOControl(m_hI2c, i2CBus.CTL_CODE(i2CBus.FILE_DEVICE_BUS_EXTENDER, i2CBus.I2C_IOCTL_SET_FREQUENCY, i2CBus.METHOD_BUFFERED, i2CBus.FILE_ANY_ACCESS), p, objectsize, IntPtr.Zero, 0, IntPtr.Zero); Marshal.FreeHGlobal(p); |
![]() |
| Thread Tools | Search this Thread |
| Display Modes | |
| |