I'm using Python since 2006 and I still discovered gems inside. Yesterday I need to read the DVB card status to find if the acquisition is fine. The status is provided by the DVB driver which is a set a of kernel modules. The DVB Card status could be read using the DVB API of the kernel. Using old-style C and ioctl function , this could be achieved using this lines:
fe_status_t my_status;
int ret = ioctl(fd, FE_READ_STATUS, &my_status);
It works. But my software is written in Python and I don't want to write a binding. C-binding is possible but painful compared of writing pure Python. How to translate this code into Python? Official documentation talks about fcntl module but the description of the usage is not simple. I try this code in Python:
# f previously open
ret_status = array.array('B', [0])
fcntl.ioctl(f, 0x69, ret_status)
My first attempt failed, resulting in an exception "Operation not permitted". Hum, wait a minute I remembered that ioctl system call is unique among all drivers. I looked more carefully the definition of FE_READ_STATUS in the kernel headers in the file ./include/linux/dvb/frontend.h .
#define FE_READ_STATUS _IOR('o', 69, fe_status_t)
_IOR is a macro in the kernel to create unique IOCTL number. I didn't understand all the logic behind. Using a C program I successfully display the real number of the IOCTL FE_READ_STATUS.
printf("REAL VALUE %08x\n", FE_READ_STATUS);
And the final function to get status is now easy:
def is_dvb_locked(adapter_name):
f = open (adapter_name, "rw")
ret_status = array.array('B', [0])
fcntl.ioctl(f, 0x80046f45, ret_status)
try:
value = ret_status.pop()
print "locked %s" % (value & 0x10 == 0x10)
except KeyError as err:
print "Unknown status %s" % err
Definitely Python is "batteries included" and even for low-level Python could do the job. See PEP 206 for more information about "batteries included".