While inserting my kernel module INSMOD exits with error "bad address", warns about "Kernel mismatch" - linux

I am developing this module for custom device that, in fact, a 4*8-bit i-o ports attached to ISA bus with addresses 0x0120 - 0x0123. This driver is based on "scull" by Alessandro Rubini and Jonathan Corbet. My OS is Ubuntu 10.04, kernel is 2.6.32-74 generic, I use built-in console-oriented compiler gcc.
While inserting compiled module using "insmod" I get an error "bad address" and module was not loaded. I've tried to debug it using "printk" and found out that my module successfully gets a range of i-o ports, major and minor numbers and then, when trying to do "Reset_Port" function it generates an error "bad address" and exits.
Can anybody tell me, what am I doing wrong?
Here are __exit and __init functions of my module
void __exit ET3201_exit(void)
{
int i;
dev_t devno = MKDEV(ET3201_major, ET3201_minor);
/* Get rid of our char dev entries */
if (ET3201_devices) {
for (i = 0; i < ET3201_nr_devs; i++) {
ET3201_trim(ET3201_devices + i);
cdev_del(&ET3201_devices[i].cdev);
}
kfree(ET3201_devices);
}
#ifdef ET3201_DEBUG /* use proc only if debugging */
ET3201_remove_proc();
#endif
/* cleanup_module is never called if registering failed */
unregister_chrdev_region(devno, ET3201_nr_devs);
if ( ! port ) release_region(BaseIO, 8);
printk(KERN_INFO "Goodbye, cruel world - ET3201 is unloaded\n");
/* and call the cleanup functions for friend devices */
/*ET3201_access_cleanup();*/
}
/*----------------------------------------------------------------------------*/
/* Set up the char_dev structure for this device. */
static void ET3201_setup_cdev(struct ET3201_dev *dev, int index)
{
int err, devno = MKDEV(ET3201_major, ET3201_minor + index);
cdev_init(&dev->cdev, &ET3201_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &ET3201_fops;
dev->CAMAC_Module_Number = CAMAC_Nmod;
dev->CAMAC_Command_Adress = CAMAC_Adcom;
dev->Driver_Number = ET3201_minor + index;
err = cdev_add (&dev->cdev, devno, 1);
/* Fail gracefully if need be */
if (err)
printk(KERN_NOTICE "Error %d adding ET3201%d", err, index);
}
/*----------------------------------------------------------------------------*/
int __init ET3201_init(void)
{
int result = 0;
int i;
dev_t dev = 0;
BaseIO = Base;
/* Get a range of minor numbers to work with, asking for a dynamic
major unless directed otherwise at load time. */
if (ET3201_major) {
dev = MKDEV(ET3201_major, ET3201_minor);
result = register_chrdev_region(dev, ET3201_nr_devs, "ET3201");
} else {
result = alloc_chrdev_region(&dev, ET3201_minor, ET3201_nr_devs, "ET3201");
ET3201_major = MAJOR(dev);
}
if (result < 0) {
printk(KERN_WARNING "ET3201: can't get major %d\n", ET3201_major);
return result;
}
port = request_region(BaseIO, 8, "ET3201");
if ( port == NULL ) {
printk(KERN_WARNING "ET3201 cannot reserve i-o ports %lu \n", BaseIO);
return -ENODEV;
goto fail;
}
/*
* allocate the devices -- we can't have them static, as the number
* can be specified at load time
*/
ET3201_devices = kmalloc(ET3201_nr_devs * sizeof(struct ET3201_dev), GFP_KERNEL);
if (! ET3201_devices) {
result = -ENOMEM;
printk(KERN_ALERT "ET3201: can't get memory \n");
goto fail; /* Fail gracefully if need be */
}
memset(ET3201_devices, 0, ET3201_nr_devs * sizeof(struct ET3201_dev));
/* Initialize each device. */
for (i = 0; i < ET3201_nr_devs; i++) {
ET3201_devices[i].quantum = ET3201_quantum;
ET3201_devices[i].qset = ET3201_qset;
init_MUTEX(&ET3201_devices[i].sem);
ET3201_setup_cdev(&ET3201_devices[i], i);
}
/* At this point call the init function for any friend device */
dev = MKDEV(ET3201_major, ET3201_minor + ET3201_nr_devs);
/*dev += ET3201_access_init(dev);*/
printk(KERN_INFO "ET3201 is initialized with major %d\n", ET3201_major);
if ( port != NULL ){
printk(KERN_INFO "ET3201 is trying to reset %d devices\n", ET3201_nr_devs);
result = Reset_Port();
}
if ( result != 0 ) {
printk(KERN_ALERT "ET3201: device cannot reset with result %d\n", result);
result = -EFAULT;
goto fail;
}
#ifdef ET3201_DEBUG /* only when debugging */
ET3201_create_proc();
#endif
return 0; /* succeed */
fail:
ET3201_exit();
return result;
}
/*----------------------------------------------------------------------------*/
module_init(ET3201_init);
module_exit(ET3201_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(ET3201_minor);
and next will be Reset_Port()
static int Reset_Port(void)
{
int result = -EIO;
int count;
if (port == NULL) goto fail;
for ( count = 0; count < ET3201_nr_devs; count++ )
{
outb(0x00, ports[count]);
}
wmb(); /*write memory barrier*/
LastOp = E_Reset;
result = 0; /* success */
fail:
return result;
}
EXPORT_SYMBOL(Reset_Port);
Now, after fixing 'int Reset_Port(void)' I've got another problem -
'WARNING: modpost: Found 1 section mismatch(es).'
After debugging I see that this is a result of calling 'ET3201_exit()'
from 'module_init()' - when I remarked this call, warning disappeared.
Surprising that exactly the same call was made in "scull" driver of respected authors - and it works.
Question: What can lead to kernel mismatch in this code?

Yes! The bug is fixed - after declaring ' int Reset_Port(void) ' the module was inserted and removed successfully. I thought,(but it was wrong) that all functions that can be called from within ' module_init() ' must not be declared as static.

Related

U-boot does not silence its output

I have this uboot
VERSION = 2017
PATCHLEVEL = 03
I am trying to silent the console using the silent variable.I defined this #define CONFIG_SILENT_CONSOLE
So at boot time I am interrupting the console, and entering
setenv silent 1
save
reset
Now after reset, or power on reset I try again get console logs.After seeing env variables
printenv
I see my saved variable correctly in env varibles
silent=1
but still u-boot is not silent. I suspect this function is failing at checking for this env variable,
char *getenv(const char *name)
{
if (gd->flags & GD_FLG_ENV_READY) { /* after import into hashtable */
ENTRY e, *ep;
WATCHDOG_RESET();
e.key = name;
e.data = NULL;
hsearch_r(e, FIND, &ep, &env_htab, 0); /*this function is maybe returning*/
return ep ? ep->data : NULL;
}
/* restricted capabilities before import */
if (getenv_f(name, (char *)(gd->env_buf), sizeof(gd->env_buf)) > 0)
return (char *)(gd->env_buf);
return NULL;
}
But what exactly is happening?
Is there something like before relocation time env variables and after relocation env variables because the function,
static void console_update_silent(void)
{
#ifdef CONFIG_SILENT_CONSOLE
if (getenv("silent") != NULL){
puts("silent");
gd->flags |= GD_FLG_SILENT;
}
else{
puts("Non silent");
gd->flags &= ~GD_FLG_SILENT;
}
#endif
}
/* Called before relocation - use serial functions */
int console_init_f(void)
{
gd->have_console = 1;
console_update_silent();
print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT1_SERIAL);
return 0;
}
console_init_f says its before relocation.
I have put some prints to see and always gets non silent, even if I have saved the silent variable,
I am using a sd card to boot(mmc), I don't have any debugger, so I
I tried printing default environment, as
env print default
## Error: "default" not defined
So there is not default environment too.
Any tips or help will make me understand.
P.S.
I explicitly defined silent in #define CONFIG_EXTRA_ENV_SETTINGS
Now u-boot is silent.
Doing a setenv silent should remove this from env variable, and I can see that its gone, but still on reboot my uboot is silent.
So something about environment variable is clearly mystery to me.
P.P.S
I come to see this code,
int getenv_f(const char *name, char *buf, unsigned len)
{
int i, nxt;
for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
int val, n;
for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) {
if (nxt >= CONFIG_ENV_SIZE)
return -1;
}
val = envmatch((uchar *)name, i);
if (val < 0)
continue;
/* found; copy out */
for (n = 0; n < len; ++n, ++buf) {
*buf = env_get_char(val++);
if (*buf == '\0')
return n;
}
if (n)
*--buf = '\0';
printf("env_buf [%d bytes] too small for value of \"%s\"\n",
len, name);
return n;
}
return -1;
}
Which is called by this
char *getenv(const char *name)
{
if (gd->flags & GD_FLG_ENV_READY) { /* after import into hashtable */
ENTRY e, *ep;
WATCHDOG_RESET();
e.key = name;
e.data = NULL;
hsearch_r(e, FIND, &ep, &env_htab, 0);
return ep ? ep->data : NULL;
}
/* restricted capabilities before import */
if (getenv_f(name, (char *)(gd->env_buf), sizeof(gd->env_buf)) > 0)
return (char *)(gd->env_buf);
return NULL;
}
From early board_init_f
this function
int env_init(void)
{
/* use default */
gd->env_addr = (ulong)&default_environment[0];
gd->env_valid = 1;
return 0;
}
makes env_addr to point always to read only memory of the code, and does not point to anything else such as where mmc environment are saved.
So this function always point to default_environment variable.
__weak uchar env_get_char_spec(int index)
{
return *((uchar *)(gd->env_addr + index));
}
static uchar env_get_char_init(int index)
{
/* if crc was bad, use the default environment */
if (gd->env_valid)
return env_get_char_spec(index);
else
return default_environment[index];
}
uchar env_get_char_memory(int index)
{
return *env_get_addr(index);
}
uchar env_get_char(int index)
{
/* if relocated to RAM */
if (gd->flags & GD_FLG_RELOC)
return env_get_char_memory(index);
else
return env_get_char_init(index);
}
So I conclude that inherently, u-boot code there is no possibility to point the mmc area where environments are stored.
Can anyone confirm this?

custom memory allocator - segfault

me and my friend are trying to develop custom memory allocator in linux ubuntu 16.04.
We got stuck because of an error, btw its our first time
that we are trying to code something like that so we are not the best debuggers the error is : Segmentation fault (core dumped)
and here is the code.
can anybody help us understand whats wrong ?
Thank you!
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <stdio.h>
struct header_t {
size_t size;
unsigned is_free;
struct header_t *next; };
struct header_t *head = NULL, *tail = NULL;
pthread_mutex_t global_malloc_lock;
struct header_t *get_free_block(size_t size)
{
struct header_t *curr = head;
while(curr) {
/* see if there's a free block that can accomodate requested size */
if (curr->is_free && curr->size >= size)
return curr;
curr = curr->next;
}
return NULL;
}
void free(void *block)
{
struct header_t *header, *tmp;
/* program break is the end of the
process's data segment */
void *programbreak;
if (!block)
return;
pthread_mutex_lock(&global_malloc_lock);
header = (struct header_t*)block - 1;
/* sbrk(0) gives the current program break address */
programbreak = sbrk(0);
/*
Check if the block to be freed is the last one in the
linked list. If it is, then we could shrink the size of the
heap and release memory to OS. Else, we will keep the block
but mark it as free. */
if ((char*)block + header->size == programbreak) {
if (head == tail) {
head = tail = NULL;
} else {
tmp = head;
while (tmp) {
if(tmp->next == tail) {
tmp->next = NULL;
tail = tmp;
}
tmp = tmp->next;
}
}
/* sbrk() with a negative argument decrements the program break.
So memory is released by the program to OS. */
sbrk(0 - header->size - sizeof(struct header_t));
/* Note: This lock does not really assure thread
safety, because sbrk() itself is not really
thread safe. Suppose there occurs a foregin sbrk(N)
after we find the program break and before we decrement
it, then we end up realeasing the memory obtained by
the foreign sbrk(). */
pthread_mutex_unlock(&global_malloc_lock);
return;
}
header->is_free = 1;
pthread_mutex_unlock(&global_malloc_lock);
}
void *malloc(size_t size)
{
size_t total_size;
void *block;
struct header_t *header;
if (!size)
return NULL;
pthread_mutex_lock(&global_malloc_lock);
header = get_free_block(size);
if (header) {
/* Woah, found a free block to accomodate requested memory. */
header->is_free = 0;
pthread_mutex_unlock(&global_malloc_lock);
return (void*)(header + 1);
}
/* We need to get memory to fit in the requested block and header
from OS. */
total_size = sizeof(struct header_t) + size;
block = sbrk(total_size);
if (block == (void*) -1) {
pthread_mutex_unlock(&global_malloc_lock);
return NULL;
}
header = block;
header->size = size;
header->is_free = 0;
header->next = NULL;
if (!head)
head = header;
if (tail)
tail->next = header;
tail = header;
pthread_mutex_unlock(&global_malloc_lock);
return (void*)(header + 1);
}
void *calloc(size_t num, size_t nsize)
{
size_t size;
void *block;
if (!num || !nsize)
return NULL;
size = num * nsize;
/* check mul overflow */
if (nsize != size / num)
return NULL;
block = malloc(size);
if (!block)
return NULL;
memset(block, 0, size);
return block;
}
void *realloc(void *block, size_t size)
{
struct header_t *header;
void *ret;
if (!block || !size)
return malloc(size);
header = (struct header_t*)block - 1;
if (header->size >= size)
return block;
ret = malloc(size);
if (ret) {
/* Relocate contents to the new bigger block */
memcpy(ret, block, header->size);
/* Free the old memory block */
free(block);
}
return ret;
}
The problem occurred because the functions were not prototyped [decalred].
Once I added functions prototype. The code worked.
For more information about prototyping: http://www.trytoprogram.com/c-programming/function-prototype-in-c/
mutex variable should be initialized before using it for applying lock. your global_malloc_lock is not initialized.
you can't initialize mutex variable as of normal variable.
pthread_mutex_t global_malloc_lock = 0 ;// invalid .. you may thinking since it's it declared as global it's initialized with 0 which is wrong
Initialize the mutex variable by calling pthread_mutex_init() or using PTHREAD_MUTEX_INITIALIZER ;
for your code add this
pthread_mutex_t global_malloc_lock = pthread_mutex_t global_malloc_lock;

How to get ipv4 address of an interface using libnl3 (netlink version 3) on linux?

I'm learning the netlink library version 3 and I want to know how to get the ipv4 address of a specified network interface. I can get the mac address and even requery the interface name from a link data structure, but I can not figure out how to get the ip address using the libnl and libnl-route libs. I did find some code to get the ip address using the libnl-cli lib but that is for dumping the results to a file descriptor (think stdout). I have sent mail to the mailing list for this library but I have not gotten a response.
Here is my code:
https://gist.github.com/netskink/4f554ed6657954b17ab255ad5bc6d1f0
Here are my results:
./stats
Returned link name is enp6s0
Returned link addr is a0:36:9f:66:93:13
Ive seen the mechanism to retrieve the ip address using ioctls, but since netlink lib can return the ip address using the cli sublibrary I figure it can be done but I can not figure out a way.
Interface can have multiple addresses (ipv4 and ipv6 addresses - code sample gave me one ipv4 and one ipv6), so there is no such function that returns one address for interface. If only you had specific local address, you could have called rtnl_addr_get. Instead you can iterate addresses.
#include <libnl3/netlink/cache.h>
void addr_cb(struct nl_object *o, void *data)
{
int ifindex = (int)(intptr_t)data;
struct rtnl_addr *addr = (rtnl_addr *)o;
if (NULL == addr) {
/* error */
printf("addr is NULL %d\n", errno);
return;
}
int cur_ifindex = rtnl_addr_get_ifindex(addr);
if(cur_ifindex != ifindex)
return;
const struct nl_addr *local = rtnl_addr_get_local(addr);
if (NULL == local) {
/* error */
printf("rtnl_addr_get failed\n");
return;
}
char addr_str[ADDR_STR_BUF_SIZE];
const char *addr_s = nl_addr2str(local, addr_str, sizeof(addr_str));
if (NULL == addr_s) {
/* error */
printf("nl_addr2str failed\n");
return;
}
fprintf(stdout, "\naddr is: %s\n", addr_s);
}
You can iterate addresses from cache and see if they contain needed address (looking at ifindex). Please take a look at https://www.infradead.org/~tgr/libnl/doc/api/cache_8c_source.html for useful functions (there is some filter function).
int ifindex = rtnl_link_get_ifindex(p_rtnl_link);
printf("ifindex: %d\n", ifindex);
bool empty = nl_cache_is_empty(addr_cache);
printf("empty: %d\n", empty);
nl_cache_foreach(addr_cache,
addr_cb, (void*)(intptr_t)ifindex);
And to check ip version use rtnl_addr_get_family.
Building upon user2518959's answer.
The rtnl_addr_alloc_cache and rtnl_link_alloc_cache both return a nl_cache object/structure. Even those these two results are of the same type, they have different routines which can be used on each.
The nl_cache returned from rtnl_addr_alloc_cache can be used to get rtnl_addr object/structures. Which are in turn can be used to call rtnl_addr_get_local to get the ipv4 or ipv6 address.
In contrast, the nl_cache returned from rtnl_link_alloc_cache can be used to get the interface name (eth0, enp6s0, ...) and the mac address. The routines are rtnl_link_get_by_name and rtnl_link_get_addr respectively.
In either case, the common link between the two is routine rtnl_addr_get_index and rtnl_link_get_index which return an interface index which can be used to relate either entry from each cache. ie. interface 1 from the addr version of nl_cache and interface 1 from the link nl_cache are the same interface. One gives the ip address and the other gives the mac address and name.
Lastly, a tunnel will have an ip address but no mac so it will not have a link name or mac address.
Here is some code which shows user25185959 approach and an alternate method which shows the relationship explictly. User2518959 passed the interface number into the callback to filter out interfaces.
#include <libnl3/netlink/netlink.h>
#include <libnl3/netlink/route/link.h>
#include <libnl3/netlink/route/addr.h>
#include <libnl3/netlink/cache.h>
#include <libnl3/netlink/route/addr.h>
#include <errno.h>
/*
gcc ipchange.c -o ipchange $(pkg-config --cflags --libs libnl-3.0 libnl-route-3.0 libnl-cli-3.0)
*/
#include <stdbool.h>
#define ADDR_STR_BUF_SIZE 80
void addr_cb(struct nl_object *p_nl_object, void *data) {
int ifindex = (int) (intptr_t) data; // this is the link index passed as a parm
struct rtnl_addr *p_rtnl_addr;
p_rtnl_addr = (struct rtnl_addr *) p_nl_object;
int result;
if (NULL == p_rtnl_addr) {
/* error */
printf("addr is NULL %d\n", errno);
return;
}
// This routine is not mentioned in the doxygen help.
// It is listed under Attributes, but no descriptive text.
// this routine just returns p_rtnl_addr->a_ifindex
int cur_ifindex = rtnl_addr_get_ifindex(p_rtnl_addr);
if(cur_ifindex != ifindex) {
// skip interaces where the index differs.
return;
}
// Adding this to see if I can filter on ipv4 addr
// this routine just returns p_rtnl_addr->a_family
// this is not the one to use
// ./linux/netfilter.h: NFPROTO_IPV6 = 10,
// ./linux/netfilter.h: NFPROTO_IPV4 = 2,
// this is the one to use
// x86_64-linux-gnu/bits/socket.h
// defines AF_INET6 = PF_INET6 = 10
// defines AF_INET = PF_INET = 2
result = rtnl_addr_get_family(p_rtnl_addr);
// printf( "family is %d\n",result);
if (AF_INET6 == result) {
// early exit, I don't care about IPV6
return;
}
// This routine just returns p_rtnl_addr->a_local
const struct nl_addr *p_nl_addr_local = rtnl_addr_get_local(p_rtnl_addr);
if (NULL == p_nl_addr_local) {
/* error */
printf("rtnl_addr_get failed\n");
return;
}
char addr_str[ADDR_STR_BUF_SIZE];
const char *addr_s = nl_addr2str(p_nl_addr_local, addr_str, sizeof(addr_str));
if (NULL == addr_s) {
/* error */
printf("nl_addr2str failed\n");
return;
}
fprintf(stdout, "\naddr is: %s\n", addr_s);
}
int main(int argc, char **argv, char **envp) {
int err;
struct nl_sock *p_nl_sock;
struct nl_cache *link_cache;
struct nl_cache *addr_cache;
struct rtnl_addr *p_rtnl_addr;
struct nl_addr *p_nl_addr;
struct nl_link *p_nl_link;
struct rtnl_link *p_rtnl_link;
char addr_str[ADDR_STR_BUF_SIZE];
char *pchLinkName;
char *pchLinkAddr;
char *pchIPAddr;
char *interface;
interface = "enp6s0";
pchLinkAddr = malloc(40);
pchIPAddr = malloc(40);
strcpy(pchLinkAddr,"11:22:33:44:55:66");
strcpy(pchIPAddr,"123.456.789.abc");
p_nl_sock = nl_socket_alloc();
if (!p_nl_sock) {
fprintf(stderr, "Could not allocate netlink socket.\n");
exit(ENOMEM);
}
// Connect to socket
if(err = nl_connect(p_nl_sock, NETLINK_ROUTE)) {
fprintf(stderr, "netlink error: %s\n", nl_geterror(err));
p_nl_sock = NULL;
exit(err);
}
// Either choice, the result below is a mac address
err = rtnl_link_alloc_cache(p_nl_sock, AF_UNSPEC, &link_cache);
//err = rtnl_link_alloc_cache(p_nl_sock, AF_INET, &link_cache);
//err = rtnl_link_alloc_cache(p_nl_sock, IFA_LOCAL, &link_cache);
if (0 != err) {
/* error */
printf("rtnl_link_alloc_cache failed: %s\n", nl_geterror(err));
return(EXIT_FAILURE);
}
err = rtnl_addr_alloc_cache(p_nl_sock, &addr_cache);
if (0 != err) {
/* error */
printf("rtnl_addr_alloc_cache failed: %s\n", nl_geterror(err));
return(EXIT_FAILURE);
}
p_rtnl_link = rtnl_link_get_by_name(link_cache, "enp6s0");
if (NULL == p_rtnl_link) {
/* error */
printf("rtnl_link_get_by_name failed\n");
return(EXIT_FAILURE);
}
pchLinkName = rtnl_link_get_name(p_rtnl_link);
if (NULL == pchLinkName) {
/* error */
printf("rtnl_link_get_name failed\n");
return(EXIT_FAILURE);
}
printf("Returned link name is %s\n",pchLinkName);
////////////////////////////////// mac address
p_nl_addr = rtnl_link_get_addr(p_rtnl_link);
if (NULL == p_nl_addr) {
/* error */
printf("rtnl_link_get_addr failed\n");
return(EXIT_FAILURE);
}
pchLinkAddr = nl_addr2str(p_nl_addr, pchLinkAddr, 40);
if (NULL == pchLinkAddr) {
/* error */
printf("rtnl_link_get_name failed\n");
return(EXIT_FAILURE);
}
printf("Returned link addr is %s\n",pchLinkAddr);
////////////////////////////////// ip address
// How to get ip address for a specified interface?
//
// The way she showed me.
//
// Return interface index of link object
int ifindex = rtnl_link_get_ifindex(p_rtnl_link);
printf("ifindex: %d\n", ifindex);
// She gave me this but its not necessary
// Returns true if the cache is empty. True if the cache is empty.
// bool empty = nl_cache_is_empty(addr_cache);
// printf("empty: %d\n", empty);
// Call a callback on each element of the cache. The
// arg is passed on the callback function.
// addr_cache is the cache to iterate on
// addr_cb is the callback function
// ifindex is the argument passed to the callback function
//
nl_cache_foreach(addr_cache, addr_cb, (void*)(intptr_t)ifindex);
// This shows that the link index returned from rtnl_addr_get_index
// and rtnl_link_get_index are equivalent when using the rtnl_addr
// and rtnl_link from the two respective caches.
// Another way...
// This will iterate through the cache of ip's
printf("Getting the list of interfaces by ip addr cache\n");
int count = nl_cache_nitems(addr_cache);
printf("addr_cache has %d items\n",count);
struct nl_object *p_nl_object;
p_nl_object = nl_cache_get_first(addr_cache);
p_rtnl_addr = (struct rtnl_addr *) p_nl_object;
for (int i=0; i<count; i++) {
// This routine just returns p_rtnl_addr->a_local
const struct nl_addr *p_nl_addr_local = rtnl_addr_get_local(p_rtnl_addr);
if (NULL == p_nl_addr_local) {
/* error */
printf("rtnl_addr_get failed\n");
return(EXIT_FAILURE);
}
int cur_ifindex = rtnl_addr_get_ifindex(p_rtnl_addr);
printf("This is index %d\n",cur_ifindex);
const char *addr_s = nl_addr2str(p_nl_addr_local, addr_str, sizeof(addr_str));
if (NULL == addr_s) {
/* error */
printf("nl_addr2str failed\n");
return(EXIT_FAILURE);
}
fprintf(stdout, "\naddr is: %s\n", addr_s);
//
printf("%d\n",i);
p_nl_object = nl_cache_get_next(p_nl_object);
p_rtnl_addr = (struct rtnl_addr *) p_nl_object;
// Just for grins
}
// Another way...
// This will iterate through the cache of LLC
printf("Getting the list of interfaces by mac cache\n");
count = nl_cache_nitems(link_cache);
printf("addr_cache has %d items\n",count);
p_nl_object = nl_cache_get_first(link_cache);
p_rtnl_link = (struct rtnl_link *) p_nl_object;
for (int i=0; i<count; i++) {
// This routine just returns p_rtnl_addr->a_local
const struct nl_addr *p_nl_addr_mac = rtnl_link_get_addr(p_rtnl_link);
if (NULL == p_nl_addr_mac) {
/* error */
printf("rtnl_addr_get failed\n");
return(EXIT_FAILURE);
}
int cur_ifindex = rtnl_link_get_ifindex(p_rtnl_link);
printf("This is index %d\n",cur_ifindex);
const char *addr_s = nl_addr2str(p_nl_addr_mac, addr_str, sizeof(addr_str));
if (NULL == addr_s) {
/* error */
printf("nl_addr2str failed\n");
return(EXIT_FAILURE);
}
fprintf(stdout, "\naddr is: %s\n", addr_s);
//
printf("%d\n",i);
p_nl_object = nl_cache_get_next(p_nl_object);
p_rtnl_link = (struct rtnl_link *) p_nl_object;
}
return(EXIT_SUCCESS);
}

Linux Device Driver open error

I am new with Linux.
I have made a USB skeleton driver and one application program which open and close skeleton.
But it gives error can't open device.
Can anyone tell me the possible reason why this may happen?
This simple driver programs needs any device attached with usb port ?
Here is my application programs
int main()
/* no memory-swapping for this programm */
ret = mlockall(MCL_CURRENT | MCL_FUTURE);
if (ret) {
perror("ERROR : mlockall has failled");
exit(1);
}
/*
* Turn the NRTcurrent task into a RT-task.
* */
ret = rt_task_shadow(&rt_task_desc, NULL, 1, 0);
if (ret)
{
fprintf(stderr, "ERROR : rt_task_shadow: %s\n",
strerror(-ret));
exit(1);
}
/* open the device */
device = rt_dev_open(DEVICE_NAME, 0);
if (device < 0) {
printf("ERROR : can't open device %s (%s)\n",
DEVICE_NAME, strerror(-device));
exit(1);
}
/*
* If an argument was given on the command line, write it to the device,
* otherwise, read from the device.
*/
/* close the device */
ret = rt_dev_close(device);
if (ret < 0) {
printf("ERROR : can't close device %s (%s)\n",
DEVICE_NAME, strerror(-ret));
exit(1);
}
return 0;
}
Here is a my driver open function
static int skel_open(struct inode *inode, struct file *file)
{
struct usb_skel *dev;
struct usb_interface *interface;
int subminor;
int retval = 0;
subminor = iminor(inode);
interface = usb_find_interface(&skel_driver, subminor);
if (!interface) {
pr_err("%s - error, can't find device for minor %d\n",
__func__, subminor);
retval = -ENODEV;
goto exit;
}
dev = usb_get_intfdata(interface);
if (!dev) {
retval = -ENODEV;
goto exit;
}
/* increment our usage count for the device */
kref_get(&dev->kref);
/* lock the device to allow correctly handling errors
* in resumption */
mutex_lock(&dev->io_mutex);
retval = usb_autopm_get_interface(interface);
if (retval)
goto out_err;
/* save our object in the file's private structure */
file->private_data = dev;
mutex_unlock(&dev->io_mutex);
exit:
return retval;
}

Call to ioctl() on a usb device using usbfs does not work

I am trying to create my own driver for my Gamepad right now, I found out the original reason why I wanted to create it does not exist but I still want to do it for the experience. So please don't tell me there is a better way to do this than writing my own driver.
The part in kernelspace with the ioctl function that should be called is:
static int xpad_ioctl (struct usb_interface *intf, unsigned int code,void *buf) {
//struct usb_xpad *xpad = usb_get_intfdata(intf);
printk(KERN_INFO"(Ongy)IOCTL called\n");
//if (_IOC_TYPE(code) != XPAD_IOMAGIC) return -ENOTTY;
//if (_IOC_NR(code) > XPAD_IOMAX) return -ENOTTY;
switch(code){
case XPAD_IORMAP:
printk(KERN_INFO"(Ongy)IORMAP called\n");
break;
default:
return -EINVAL;
}
return 0;
}
static struct usb_driver xpad_driver =
{
.name = "Cyborg-V5-driver",
.probe = xpad_probe,
.disconnect = xpad_disconnect,
.unlocked_ioctl = xpad_ioctl,
.id_table = xpad_table,
};
The part in userspace to call it is (this is part of a Qt-application):
int openfile() {
char *device = "/dev/bus/usb/005/009";
printf("Opening device %s\n", device);
return open(device, /*O_RDONLY*/O_WRONLY | O_NONBLOCK );
}
[...] the closefile(int file_desc) is missing here, this and the openfile functions exist because of me not knowing one can call "::open()" when Qt overrides function calls.
void MainContainer::callioctl() {
int file_desc, ret_val;
errno = 0;
file_desc = openfile();
if (file_desc==-1){
printf("Ioctl notcalled because of: error %s\n", strerror(errno));
}
else
{
errno = 0;
//struct usbdevfs_getdriver* driver = (usbdevfs_getdriver*)malloc(sizeof(struct usbdevfs_getdriver));
struct mappingpair* pair = (mappingpair*)malloc(sizeof(struct mappingpair));
ret_val = ioctl(file_desc, XPAD_IORMAP, pair);
//printf("Drivername %s\n", driver->driver);
closefile(file_desc);
if (ret_val==-1) printf("Ioctl failed with error %s\n", strerror(errno));
else printf("Ioctl call successfull\n");
}
}
ok, the string to the file I open I get with a call to lsusb and change it by hand in the code, this is only for debugging and until I get the ioctl calls working
When I call the callioctl() it prints:
Ioctl failed with error Unpassender IOCTL (I/O-Control) für das Gerät
The German part means "wrong ioctl (I/O-Control) for the device" and nothing appears in dmesg, that is why I think my ioctl function in the driver is not called.
If you look at http://www.hep.by/gnu/kernel/usb/usbfs.html it says that to send an ioctl to the usb_driver device you need to do:
struct usbdevfs_ioctl {
int ifno;
int ioctl_code;
void *data;
};
/* user mode call looks like this.
* 'request' becomes the driver->ioctl() 'code' parameter.
* the size of 'param' is encoded in 'request', and that data
* is copied to or from the driver->ioctl() 'buf' parameter.
*/
static int
usbdev_ioctl (int fd, int ifno, unsigned request, void *param)
{
struct usbdevfs_ioctl wrapper;
wrapper.ifno = ifno;
wrapper.ioctl_code = request;
wrapper.data = param;
return ioctl (fd, USBDEVFS_IOCTL, &wrapper);
}
The documentation is listing usb device under /proc/bus so admittedly this may have changed.

Resources