# Ccall() to ioctl

**URL:** <https://discourse.julialang.org/t/ccall-to-ioctl/6219>\
**Category:** General Usage\
**Tags:** question\
**Created:** [October 3, 2017, 3:17pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219 "2017-10-03T15:17:48Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 3, 2017, 3:17pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/1 "2017-10-03T15:17:48Z")

</div>

Hi,

I’m trying to make a ccall to ioctl, but I seem to be getting the parameter types wrong. Here’s some code:

```julia
const I2C_SLAVE =	0x0703

addr = 0x1D

if ((file = open(filename,"r+")) < 0)
	error("Failed to open the bus.")
	# ERROR HANDLING; you can check errno to see what went wrong 
	return
end
ret = -1
ret = ccall((:ioctl, "libc"), Int, (Int, Int, Ptr{UInt8}), file, I2C_SLAVE, addr) 
if (ret < 0)
	error("Failed to acquire bus access and/or talk to slave.")
         # ERROR HANDLING; you can check errno to see what went wrong 
end

```

I get the following error:

ERROR: MethodError: no method matching unsafe\_convert(::Type{Ptr{UInt8}}, ::UInt8)  
Closest candidates are:  
unsafe\_convert(::Type{Ptr{UInt8}}, ::Symbol) at pointer.jl:35  
unsafe\_convert(::Type{Ptr{UInt8}}, ::String) at pointer.jl:37  
unsafe\_convert(::Type{T\<:Ptr}, ::T\<:Ptr) where T\<:Ptr at essentials.jl:152  
…  
Stacktrace:  
[1] anonymous at ./:?

Here’s the info. on iotcl():

The ioctl() function manipulates the underlying device parameters of special files. In particular, many operating characteristics of character special files (e.g. terminals) may be controlled with ioctl() requests. The argument d must be an open file descriptor.

The second argument is a device-dependent request code. The third argument is an untyped pointer to memory. It’s traditionally char \*argp (from the days before void \* was valid C), and will be so named for this discussion.

An ioctl() request has encoded in it whether the argument is an in parameter or out parameter, and the size of the argument argp in bytes. Macros and defines used in specifying an ioctl() request are located in the file \<sys/ioctl.h\>.  
RETURN VALUE  
Usually, on success zero is returned. A few ioctl() requests use the return value as an output parameter and return a nonnegative value on success. On error, -1 is returned, and errno is set appropriately.

Thanks.

---

<div class="post-metadata">

**Author:** ![lobingera](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lobingera/32/211_2.png) [@lobingera](https://discourse.julialang.org/u/lobingera)\
**Post date:** [October 3, 2017, 3:38pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/2 "2017-10-03T15:38:11Z")

</div>

I think there is a mismatch between your interface definition of Ptr{Uint8} as third argument and providing a value of Uint8. Reread [https://docs.julialang.org/en/stable/manual/calling-c-and-fortran-code/#When-to-use-T,-Ptr{T}-and-Ref{T}-1](https://docs.julialang.org/en/stable/manual/calling-c-and-fortran-code/#When-to-use-T,-Ptr%7BT%7D-and-Ref%7BT%7D-1)  
and following.

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 3, 2017, 3:58pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/3 "2017-10-03T15:58:33Z")

</div>

OK. I changed it to a Ref{UInt8} and at least I’m not getting an error. So, onwards. Thanks.

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 3, 2017, 4:08pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/4 "2017-10-03T16:08:14Z")

</div>

So, another question is how do you get the errno from a ccall? I’m getting an -1 on return so I would like to check the errno.

RETURN VALUE

```
   Usually, on success zero is returned. A few ioctl() requests use the
   return value as an output parameter and return a nonnegative value on
   success. On error, -1 is returned, and errno is set appropriately.

```

ERRORS

```
   EBADF fd is not a valid file descriptor.

   EFAULT argp references an inaccessible memory area.

   EINVAL request or argp is not valid.

   ENOTTY fd is not associated with a character special device.

   ENOTTY The specified request does not apply to the kind of object
          that the file descriptor fd references.

```

---

<div class="post-metadata">

**Author:** ![lobingera](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lobingera/32/211_2.png) [@lobingera](https://discourse.julialang.org/u/lobingera)\
**Post date:** [October 3, 2017, 4:22pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/5 "2017-10-03T16:22:42Z")

</div>

i’d assume that errno is available as symbol in the libc and that’s maybe a good reason, why this is actually an example in [https://docs.julialang.org/en/stable/manual/calling-c-and-fortran-code/#Accessing-Global-Variables-1](https://docs.julialang.org/en/stable/manual/calling-c-and-fortran-code/#Accessing-Global-Variables-1)

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 3, 2017, 4:34pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/6 "2017-10-03T16:34:29Z")

</div>

OK. Thanks. I, also, found Base.libc.errno() and they both give the same results (22 - which is an invalid parameter).

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 3, 2017, 4:52pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/7 "2017-10-03T16:52:38Z")

</div>

Just fyi - this is all being done on a Raspberry Pi. I have a MMA8451 Triple-Axis accelerometer attached to the i2c pins (along with power and ground). I have a python program that is able to read it, but I wanted to see if I can do it from Julia [should just be open(), ioctl(), read(), write()]. I have a Beowulf cluster that consists of a Beaglebone Black, Raspberry Pi, Udoo X86, and a NanoPi Duo [development boards] and building a bunch routines that allow me do GPIO remotely from my Dell desktop. Now, I’m working on i2c. So, your help is greatly appreciated. I’m fairly new to Julia [just a few months], but I’m a long time programmer.

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 3, 2017, 5:25pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/8 "2017-10-03T17:25:04Z")

</div>

This seems to be working (at least no errors and clean return codes):

```julia
const I2C_SLAVE =	0x0703 # Use this slave address

#//////////
#// Init I2Cdevice
#//////////
function i2c_init(filename::String, addr::UInt8)
   file = open(filename,"r+")
   fileDes = fd(file)
   if (fileDes < 0)
	error("Failed to open the bus.")
	# ERROR HANDLING; you can check errno to see what went wrong 
	return
   end
   ret = ccall((:ioctl, "libc"), Int, (Int, Int, UInt8), fileDes, I2C_SLAVE, addr) 
   if (ret < 0)
      error("Failed to acquire bus access and/or talk to slave.")
      # ERROR HANDLING; you can check errno to see what went wrong 
    end
    return fileDes
end

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 3, 2017, 5:33pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/9 "2017-10-03T17:33:22Z")

</div>

> [@Frank\_Applin](#):
>
> (Int, Int, UInt8)

This is wrong, it should be `(Cint, Cint, Cint...)`

> [@lobingera](#):
>
> i’d assume that errno is available as symbol in the libc and that’s maybe a good reason, why this is actually an example in [https://docs.julialang.org/en/stable/manual/calling-c-and-fortran-code/#Accessing-Global-Variables-1](https://docs.julialang.org/en/stable/manual/calling-c-and-fortran-code/#Accessing-Global-Variables-1)

It is not really… That example should probably be removed since it’ll encourage wrong code. `errno` is a special name that’s actually a function call.

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 3, 2017, 5:43pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/10 "2017-10-03T17:43:22Z")

</div>

OK. That worked, too.

```julia
function i2c_init(filename::String, addr::UInt8)
   file = open(filename,"r+")
   fileDes = fd(file)
   if (fileDes < 0)
      error("Failed to open the bus.")
     # ERROR HANDLING; you can check errno to see what went wrong 
     return
   end
   ret = ccall((:ioctl, "libc"), Int, (Cint, Cint, Cint), fileDes, I2C_SLAVE, addr) 
   if (ret < 0)
      error("Failed to acquire bus access and/or talk to slave.")
      # ERROR HANDLING; you can check errno to see what went wrong 
   end
   return fileDes
end

```

Thanks.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 3, 2017, 5:53pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/11 "2017-10-03T17:53:15Z")

</div>

> [@Frank\_Applin](#):
>
> (Cint, Cint, Cint)

Still wrong, you are missing the `...`

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 3, 2017, 6:02pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/12 "2017-10-03T18:02:34Z")

</div>

```julia
function i2c_init(filename::String, addr::UInt8)
   file = open(filename,"r+")
   fileDes = fd(file)
   if (fileDes < 0)
      error("Failed to open the bus.")
      # ERROR HANDLING; you can check errno to see what went wrong 
      return
   end
   ret = ccall((:ioctl, "libc"), Int, (Cint, Cint, Cint...), fileDes, I2C_SLAVE, addr) 
   if (ret < 0)
      error("Failed to acquire bus access and/or talk to slave.")
       # ERROR HANDLING; you can check errno to see what went wrong 
   end
   return fileDes
end

```

So, what does the … signify?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 3, 2017, 7:23pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/13 "2017-10-03T19:23:27Z")

</div>

[https://docs.julialang.org/en/latest/manual/calling-c-and-fortran-code/#ccall/cfunction-argument-translation-guide-1](https://docs.julialang.org/en/latest/manual/calling-c-and-fortran-code/#ccall/cfunction-argument-translation-guide-1)

> - `...` (e.g. a vararg)
> - `T...`, where `T` is the Julia type

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [October 3, 2017, 8:33pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/14 "2017-10-03T20:33:02Z")

</div>

I believe it signifies that the function uses the C varargs calling convention. Based on the signature in the man page for `ioctl`:

```nohighlight
int ioctl(int fildes, unsigned long request, ...);

```

shouldn’t the `ccall` be:

```julia
ccall(:ioctl, Cint, (Cint, Culong, Cint...), fileDes, I2C_SLAVE, addr)

```

Note the `Cint` return type and the second argument being `Culong` rather than `Cint`.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 3, 2017, 8:45pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/15 "2017-10-03T20:45:53Z")

</div>

Posix man page gives `int ioctl(int, int, ...)`, Linux one gives `int ioctl(int, unsigned long, ...)` so I guess `Culong` should be used at on linux. Fortunately this doesn’t make any difference on any platforms we support. (OTOH, vararg does…)

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 3, 2017, 8:56pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/16 "2017-10-03T20:56:18Z")

</div>

The different ioctl() signatures could be kernel versus user space (my guess). I’m doing all of this via user space.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 3, 2017, 9:07pm UTC](https://discourse.julialang.org/t/ccall-to-ioctl/6219/17 "2017-10-03T21:07:04Z")

</div>

Both are userspace. The Linux header gives `unsigned long` so that should be used. Since as I said, the interger type actually doesn’t matter that much for any architectures, the linux signature is basically an extension to the posix signature.

P.S. On the kernel side, everything is passed as long in completely different way.
