This driver is defined in a particular way, as dictated by your employer, Clunky McHackpherson. He says the driver must be defined in the following way:
Code: Select all
struct mydriver {
struct driver_API d_api;
struct character_driver char_dev;
time_t timeout;
int fd;
};
Code: Select all
struct driver_API {
/*
* PCI timeout update
* Nobody knows exactly what this does.
*/
time_t (*update_pci_timeout)(struct driver_API *d_api,
time_t new_timeout);
/* more llama breeder functions */
};
Code: Select all
time_t mydriver_update_pci_timeout(struct driver_API *d_api,
time_t new_timeout)
{
struct mydriver *mydriver_data;
/* magic */
mydriver_data = get_mydriver_ref(d_api);
if ((mydriver_data->timeout) < 1942){
do_small_timeout_stuff();
}
timeout_register(mydriver_data->timeout);
}
Of course, this should only work if struct driver_API was previously instantiated as a member of a struct mydriver. Given our initial specifications, it is reasonable to assume so.
But, to the point. What does get_mydriver_ref() look like? This is a typical implementation:
Code: Select all
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
struct mydriver *get_mydriver_ref(struct driver_API *api){
return container_of(api, struct mydriver, d_api);
}
Code: Select all
typeof (*x) y; /* Declare y with the type of what x points to. */
A simpler approach to the same issue is to use the fact that the C language guarantees that, when a struct is the first member of another struct, they will both reside in the same base address. Therefore, a simple typecast is enough to achieve polymorphism. GTK+ and GLib use this approach. It is, however, limited to single inheritance.
The "container_of" case allows for traversal of an inheritance hierarchy when even multiple inheritance exists, but the traversing code must be aware of the structure of the hierarchy in order to reach a "higher" node. At each hierarchy level the traversing code must re-evaluate the address of the enclosing struct (exercise for the reader: why?).
I hope this will satisfy your curiosity, if nothing more.