Recent

Author Topic: _IOR and Raspberry PI  (Read 3690 times)

JimKueneman

  • Full Member
  • ***
  • Posts: 246
_IOR and Raspberry PI
« on: August 09, 2015, 10:55:40 pm »
I am trying to translate some headers with _IOR.  In Raspian _IOR is defined as

Code: [Select]
#ifndef _IOR
# define _IOR(x,y,z) (((x)<<8)|y)
#endif

So if I have this:
Code: [Select]
#define SPI_IOC_MAGIC                   'k'
#define SPI_IOC_RD_MODE                 _IOR(SPI_IOC_MAGIC, 1, __u8)

I did this:
Code: [Select]
const
  SPI_IOC_MAGIC = ord('k');
  SPI_IOC_RD_MODE = (SPI_IOC_MAGIC shl 8) or 1;

which does not seem to work:

Code: [Select]
var
    devPath              : string = '/dev/spidev0.0';

var
    ModePtr: ^Byte;
    Mode: Byte;
    IOCtlResult: Integer;

begin

    handle := fpopen(devPath,O_RDWR);

    Mode := SPI_IOC_RD_MODE;
    ModePtr := @Mode;
    IOCtlResult := fpIOCtl(handle, SPI_IOC_RD_MODE, ModePtr);

IOCtlResult returns -1.

It appears the "Z" parameter is not used in the macro and the dummy parameter is the "__u8"

What I am doing wrong?

I do get a valid handle from fpopen()

Jim
« Last Edit: August 09, 2015, 10:57:15 pm by JimKueneman »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12712
  • FPC developer.
Re: _IOR and Raspberry PI
« Reply #1 on: August 09, 2015, 11:06:12 pm »
You take something with shl 8 in it and then put it in a BYTE?

JimKueneman

  • Full Member
  • ***
  • Posts: 246
Re: _IOR and Raspberry PI
« Reply #2 on: August 09, 2015, 11:09:46 pm »
Yea, I just saw that.  The call does not _use_ what I put in Mode it is suppose fill in Mode in the call.  I just assigned it to a word to be sure SPI_IOC_RD_MODE is the value I expected, and it is $6B01.

It should work if I am translating the C macro correctly I think.

Jim

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12712
  • FPC developer.
Re: _IOR and Raspberry PI
« Reply #3 on: August 09, 2015, 11:18:21 pm »
It's supposed to fill modeptr, not mode ?

Anyway, the best way to debug this is to use strace/ktrace and look what values the call receives and if he recognizes it (then it is turned into a symbol instead of numeric value). This is how I debugged the freebsd ioctls which are never more annoying.

The "z" value is the size of the allocate structure (allows to guard against bufferoverflow and versioning), but Linux iirc doesn't use it. *BSD does.

JimKueneman

  • Full Member
  • ***
  • Posts: 246
Re: _IOR and Raspberry PI
« Reply #4 on: August 10, 2015, 12:12:00 am »
Nice tool....

Code: [Select]
var
    Mode: Byte;
    IOCtlResult: Integer;

begin

try
    handle := fpopen(devPath,O_RDWR);

    if handle > -1 then
    begin
      IOCtlResult := SPI_IOC_RD_MODE;
      Mode := $FF;
      IOCtlResult := fpIOCtl(handle, SPI_IOC_RD_MODE, Pointer(Mode));
      FpClose(handle);
    end;
    Halt;

Quote
open("/dev/spidev0.0", O_RDWR|O_LARGEFILE) = 3
ioctl(3, 0x6b01, 0xff)                  = -1 ENOTTY (Inappropriate ioctl for device)
close(3)                                = 0
munmap(0x76fd0000, 32768)               = 0
munmap(0x76fd8000, 32768)               = 0
munmap(0x76fb8000, 32768)               = 0
munmap(0x76fc0000, 32768)               = 0
exit_group(0)                           = ?


It looks like the parameters are all what I expect but it still does not work...

Jim

JimKueneman

  • Full Member
  • ***
  • Posts: 246
Re: _IOR and Raspberry PI
« Reply #5 on: August 10, 2015, 12:42:23 am »
Ok found a *.c example and compiled and ran it, again strace is great!

Code: [Select]
int main(int argc, char *argv[])
{
    int ret = 0;
    int fd;

    parse_opts(argc, argv);

    fd = open(device, O_RDWR);
    if (fd < 0)
        pabort("can't open device");

    /*
     * spi mode
     */
    ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
    if (ret == -1)
        pabort("can't set spi mode");

    ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
    if (ret == -1)
        pabort("can't get spi mode");

Quote
open("/dev/spidev0.0", O_RDWR)          = 3
ioctl(3, 0x40016b01, 0x11376)           = 0
ioctl(3, 0x80016b01, 0x11376)           = 0
ioctl(3, 0x40016b03, 0x11368)           = 0
ioctl(3, 0x80016b03, 0x11368)           = 0

Clearly the _IOR and _IOW are different than what I am doing.    I hardcoded the high word for read and write in the _IOW _IOR and it is working.  I still don't see in the Linux code where this is defined any different..

Jim

 

TinyPortal © 2005-2018