[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.dotnet.framework.interop

Mangaged to Unmanaged code I2C device access violation issue

Tonofit

6/8/2007 11:55:00 PM

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);
2 Answers

Ben Voigt [C++ MVP]

6/9/2007 5:32:00 PM

0


"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);
}
};

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);

Ben Voigt [C++ MVP]

6/9/2007 5:48:00 PM

0


"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);
>