humpingpanda
humpingpanda

Reputation: 51

Creating I2C device driver struct setup

I am writing a device driver which use I2C to communicate to host.

Below is the code I wanted to learn and understand. Do help me out If my understanding is wrong about the code below. "//" is my own comments & my understanding to the code.

// declare there will be a member struct inside the class example_state. This member is pointing to i2c_client.
struct example_state {
struct i2c_client *client; 
};

static int example_probe(struct i2c_client *client, const struct i2c_device_id *id{

// declare this to be a local struct inside the example_probe
struct example_state *state;

// get "struct device" to be pointed client's member name dev
// Question: is "struct device *dev" part of "struct i2c_client"?
// if "struct device *dev" imported from somewhere that why there is no need to allocate memory?
struct device *dev = &client->dev;

// allocate a memory space for "struct example_state"
// at this point "struct example_state" is still empty/NULL
// **Question:** but what is the relationship of this local "struct example_state"
// with the one declared before entering struct example_state function?
state = kzalloc(sizeof(struct example_state), GFP_KERNEL); 
if (state == NULL) {
    dev_err(dev, "failed to create our state\n");
    return -ENOMEM;
}

    // after memory allocated set the "struct i2c_client" point to "struct example_state"'s member namely "client".
state->client = client; 

   // set the our device I2C driver information to the host.
   // Question: Where to we set our device driver data?
i2c_set_clientdata(client, state); 

/* rest of the initialisation goes here. */

dev_info(dev, "example client created\n");

return 0;
}

static int __devexit example_remove(struct i2c_client *client){
  // get the loaded value from host, i guess is like unregister
  // my device driver information from the host when i exited.
struct example_state *state = i2c_get_clientdata(client);

kfree(state);
return 0;
}

static struct i2c_device_id example_idtable[] = {
{ "example", 0 },
{ }
};

Upvotes: 1

Views: 2807

Answers (1)

sarnold
sarnold

Reputation: 104090

I'm going to suggest that instead of studying up on the Linux kernel's i2c support, you ought to take another look at K&R 2 instead:

// declare there will be a member struct inside the class example_state. This member is pointing to i2c_client.
struct example_state {
struct i2c_client *client; 
};

C does not have classes. The Linux kernel's sysfs abstraction introduced the kernel's own idea of what a "class" is -- see drivers/base/class.c -- but it has no relationship at all to classes in C++, Java, C#, or any other language you're familiar with.

static int example_probe(struct i2c_client *client, const struct i2c_device_id *id{

// declare this to be a local struct inside the example_probe
struct example_state *state;

This declares state to be a pointer to a struct example_state piece of memory. (I'd normally use the word object here, but I don't want to counteract the "C does not have classes" speech from the previous paragraph. It's a piece of memory that is as large as or larger than the amount necessary to hold all the members of the struct example_state, and the compiler knows to check operations for type consistency. Maybe I should have just said "object"...)

In any event, there is only enough memory set aside in this line of code for a pointer -- not the structure itself.

// get "struct device" to be pointed client's member name dev
// Question: is "struct device *dev" part of "struct i2c_client"?
// if "struct device *dev" imported from somewhere that why there is no need to allocate memory?
struct device *dev = &client->dev;

The struct device *dev in this line allocates enough memory for a pointer and tells the compiler that the pointer will only point to struct device objects. The =&client->dev looks into the client parameter to find the dev member and makes an alias for easier use within this routine.

// allocate a memory space for "struct example_state"
// at this point "struct example_state" is still empty/NULL
// **Question:** but what is the relationship of this local "struct example_state"
// with the one declared before entering struct example_state function?
state = kzalloc(sizeof(struct example_state), GFP_KERNEL); 
if (state == NULL) {
    dev_err(dev, "failed to create our state\n");
    return -ENOMEM;
}

The struct example_state { .. } from earlier was a type declaration. It only instructed the compiler about the names, sizes, and types, of members stored in structs with the tag struct example_state. It does not allocate any memory. The kzalloc() call here does allocate memory, the size of our struct example_state objects, and it requests that the normal GFP_KERNEL memory allocation pool be used. See include/linux/gfp.h for details on the different "pools" of memory available. Depending upon the flags passed to the kernel's memory allocator, the memory allocation might happen only after the kernel has been forced to perform a "garbage collection" of sorts -- writing dirty memory buffers back to disk, dropping page caches, swapping processes, maybe even invoking the OOM memory killer to allocate memory. The GFP_ATOMIC pool is used when the kernel absolutely must not sleep at that point -- excellent for use when spinlocks are held or in interrupt context.

While it is possible to learn C and kernel internals simultaneously, it is a very unforgiving environment to make mistakes. Following a stray pointer in a normal userspace program segfaults the process but following a stray pointer in the kernel panics the machine or corrupts memory, filesystems, etc.

Upvotes: 2

Related Questions