The Ohh F**k Incidence.

Standard

Well it has been a while since I wrote anything. The truth is, I’m basically in a very monotonous loop of self destruction again. Please, don’t hate me as I hate myself more than you ever could but really it is just because I have nothing to do right now. And so, I looked into Linux kernel drivers.

Also, I looked into someone’s eyes. Have you ever seen someone so astonishingly pretty that they seem unreal? I mean those eyes shutdown my whole freakin’ system in a fraction of a second. So fast, that my only reaction was that I blurted out “Ohh fuck!”. Right on the face like a punch out of no where. And all I saw were those two black stars which held a deep freakin’ secret waiting to be revealed.

Ohh wait, I’ll open up my terminal. So what we are going to do today is to learn how to write IOCTLS, which, in UNIX lingo means Input Output ConTroLS. I’m going to refer to this book for every little line of code in this article. I read this book in my formative years as a bible and it seems to be a good starting point to brush up those forgotten things.

So what are IOCTLS? If you read the introduction of IOCTLS in the book, it gives a very fucked up example. I’m a useless programmer, how am I supposed to know what it means? Linux is supposed to be friendly to useless programmers too. What it basically wants to say is this: Take Arduino for example. Burning a sketch to your Arduino can be handled by system calls. They just have to write the respective device files. And you can set different baud rates too. The baud rates are set by communicating directly with the serial port. The application must do that, so we have this cool feature of IOCTLs. They provide an application to directly communicate with their respective devices for some device specific work.

Ok what I meant by shutdown my system… well, lets rewind a bit. Its a Tuesday morning, a slight chill, I’m in for work quite early and then it was all going good. I made a small program in QML that does nothing right now apart from making an AJAX request. 25 minutes before lunch time and we get up to keep our boxes in the kitchen hot box. Some confusion in the aisle and I was suddenly pushed in front of a person. Now, this person is so freakin’ umm… I don’t know. I mean for that one pure second of eye contact, every thing just stopped. Just fucking stopped. Like there was nothing around and I took a jump into void.

Small dimple on the right cheek, slightly tinted hairs, spotless and glowing face, soft and radiant skin, deep black eyes complimented by black mascara… stop breathing, system overload, internal system error… unable to find drivers to process her face. Boom, complete system failure… shutdown. Blank… and all this, in a fraction of a second. At such breakneck speeds, the only reaction that occurred to me was “Ohh fuck.”. Right on her beautiful face.

Lets start with some code. I’m using the code given in the book but since I’m working on Kernel 3.x I may have to make some changes that I’ll make while reading.

static ssize_t deviceRead(struct *file, char __user *buffer /* user space buffer */, size_t length, loff_t *offset) {
        int bytes_read = 0;

        #if 1
                printk(KERN_INFO "device read (%p %p %d)\n", file, buffer, length);
        #endif

        if(msgPtr == 0) // indicates EOF
                return 0;
        while (length && msgPtr) {
                put_user(*(msgPtr++), buffer++);
                length--;
                bytes_read++;
        }
        return bytes_read;
}

static ssize_t deviceWrite(struct *file, char __user *buffer, size_t length, loff_t *offset) {
        #if 1
                printk(KERN_INFO "device_write (%p %p %d)\n", file, buffer, length);
        #endif
        int i = 0;
        for(i = 0; i < BUF_LEN; i++) {
                get_user(message[i], buffer + i);
        }
        return i; // number of bytes read
}

If you are following the book, you can look up the source from there, I don’t want to make this article too code heavy. I just want to look into put_user and get_user functions. The read and write functions are pretty straight forward. Note that we are doing kernel work and more specifically, we are playing with a DEVICE FILE. The meaning of read and write get mirrored in kernel. Read means that the USER wants to read the file and write means that the USER wants to write the file.

put_user() copies some data from kernel to user space so that a user space process can use it. So if your application reads a device file, the kernel has to write that data. Similarly, get_user() copies data from user space process and saves it in a kernel space message array. This is necessary because this what device drivers are for. I mean I cannot explain it more simply.

Imagine you have a very wild dream and its in 1080p Ultra HD quality and you can actually feel every damn thing in it. Suddenly you wake up after having a fall. You look around for a few seconds wondering what the fuck just happened. Exactly. Get it now? Thats what happened to me in broad fucking daylight. I looked in her eyes and at her face and I was taken into a limbo. Black out. Like an overdose of Marijuana. Those 10-15 seconds seemed like 5 full days and nights.

Her face was spotless. Radiant. Like a glowing candle in a cave. Or maybe the cool moon shine of an autumn night. But her smile was another story. It was like the rising sun. It comes up everyday to break through the cold darkness of the night. She smiled as if she will tell you something if you listen closely enough.

It was all contradicting. Her eyes were even more. They were black and deep, like you can look into them but never be able to decipher what lies beneath them.

I mean she was very umm pretty. I mean she was absurdly pretty. She doesn’t even have to look pretty, she was just pretty. While my system was shutting down, I did not have the time to process what to say. So I just said “Ohh fuck.”… There was a very strange smile on her face. But what I don’t understand is, why would that happen to any sane person? A sane person always processes what he has to say! No one in their right mind blanks out like this. But it happened all of a sudden, it was so fast! Like she cropped in front of me and shorted a nerve in my brain. And all I saw was a face and two eyes. Like it is now burned into my brain’s firmware. Not cool.

int deviceIOCTL(struct inode *inode, struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) {
        int i;
        char *temp, ch;
        // this function will be called whenever there is an IOCTL call by a process.
        switch(ioctl_num) {
        case IOCTL_SET_MSG:
                temp = (char *) ioctl_param;
                get_user(ch, temp);
                // get the IOCTL message from process
                for(i = 0; ch && i < BUF_LEN; i++, temp++) {
                        get_user(ch, temp);
                }
                deviceWrite(file, (char *)ioctl_param, i, 0);
                break;
        case IOCTL_GET_MSG:
                i = deviceRead(file, (char *)ioctl_param, 99, 0);
                put_user('', (char *)ioctl_param+i); // end with a null character.
                break;
        case IOCTL_GET_NTH_BYTE:
                message[ioctl_param];
                break;
        }
        return SUCCESS;
}

These are the IOCTLS that are yet to be coded. Notice how the SET_MSG and GET_MSG are implemented. SET_MSG sets a message by reading data from user space. Vice versa for GET_MSG. Really enjoying this I’m… :D.

Now like every character device driver, we have to register file operations. the file operations structure is used to do this. I’ll be using the new syntax for declaring the file operations structure as there comes a strange error when I use the syntax given in the book.

struct file_operations fops = {
        read: deviceRead,
        write: deviceWrite,
        ioctl: deviceIOCTL,
        open: deviceOpen,
        release: deviceRelease
};

int init_module() {
        int ret = register_chrdev(MAJOR_NUMBER, DEVICE_NAME, &fops);
        if(ret < 0) {
                printk(KERN_ALERT "%s failed with %d\n", DEVICE_NAME, major);
                return ret;
        }
        return 0;
}

void cleanup() {
        int ret;
        ret = unregister_chrdev(MAJOR_NUMBER, DEVICE_NAME);
        if(ret < 0) {
                printk(KERN_ALERT "unable to unregister %s\n", DEVICE_NAME);
        }
}

If you have programmed kernel modules before, you’d know that init and cleanup initialize and cleans up the kernel module at initialization and unlinking respectively. A small point to notice is: in function register_chrdev(0, DEVICE_NAME, &fops) passing 0 as the first parameter generates a unique major number which is returned as the return value. This ensures that your device (and hence IOCTLS) remain unique across all devices. We cannot do this with IOCTLS. IOCTLS need to know what major number it will be using.

She said “its ok”. Yes, she spoke… you know that sound that a person makes using their tongue and vocal cords. Now recall that small jingle that plays when Windows (or any OS) boots up. The BIOS checked my peripherals, loaded the OS from the disk and after the boot was completed, I’m presented with my desktop with a jingle. The jingle… her voice… “it’s ok.”. Boom, another crash… her voice was almost musical, like a very mysterious note that just got plucked on a harp. You cannot simply process something like that.

Now make chardev.h file. The book shows a heavily commented code. Use it. If you have queries, I’ll be happy to help. There is nothing there to explain though.

At last, we have come to writing our own application that will communicate with our driver. I actually did something else on my end but that will just extend this post unnecessarily. I’ll just explain what’s in the book.

The code in book is an example of a user space process interacting with a driver. Go ahead try it. I tried it on my system and it works great. Today I got a deeper insight of what beats beneath the hood. Next article will probably cover system calls.

That small moment today hit me somewhere very hard. I was unable to focus on anything for a while. Her face, her eyes, her sly smile, her softly glowing skin… all imprinted on my mind. Embossed and never to be erased. It was the purest moment I have ever had. I cannot really understand what I’m feeling right now and I guess it will take a day or two to get back to normal.

Well, its almost 2 hours into the midnight, so I probably stop talking and sleep.

Sionara to all and especially to her.

Drona.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s