Ben Voigt [C++ MVP]
6/9/2007 5:48:00 PM
"Ben Voigt [C++ MVP]" <rbv@nospam.nospam> wrote in message
news:1D5EBAF3-47E0-41FB-94E3-8DCD350EB2AC@microsoft.com...
>
> "Tonofit" <Tonofit@discussions.microsoft.com> wrote in message
> news:141A3D2E-00B8-458A-BE50-ADB6F43E9A7C@microsoft.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);
> }
> };
Of course you should connect to the driver in the PWM constructor, and
implement a destructor that closes it properly (C++ will translate your
destructor into an implementation of IDisposable).
>
> 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);
>