I am new to Linux kernel and I am presently learning USB device drivers.
I wrote a simple USB driver with probe callback and disconnect callback functions.
In the probe callback I try to display values of the struct usb_device_id argument passed to it. The problem is that structure variable shows product id and vendor id as 0.
What is the reason for this? Am I doing all right?
The code snippets from the driver are
#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/usb.h>
int probe_callback(struct usb_interface *intf, const struct usb_device_id *id);
void disconnect_callback(struct usb_interface *intf);
struct usb_device_id usb_ids[]={
{.driver_info=42},
{}
};
struct usb_driver USB_DRIVER={
.name="NEW USB",
.id_table=usb_ids,
.probe=probe_callback,
.disconnect=disconnect_callback
};
//PROBLEM IS IN THE FUNCTION BELOW .....................
int probe_callback(struct usb_interface *intf, const struct usb_device_id *id)
{
printk(KERN_ALERT "probe callback\n");
__u16 vendor_id=id->idVendor;
__u16 product_id=id->idProduct;
printk("product id : %x vendor id : %x\n", product_id, vendor_id);
return 0;
}
//..........................
void disconnect_callback(struct usb_interface *intf)
{
printk(KERN_ALERT "disconnect callback\n");
}
static int start(void)
{
printk(KERN_ALERT "module registered\n");
int result;
result=usb_register(&USB_DRIVER);
if(result)
{
printk("error in registering usb driver...Error code = %d\n", result);
}
return result;
}
static void stop(void)
{
printk(KERN_ALERT "module unregistered\n");
usb_deregister(&USB_DRIVER);
}
module_init(start);
module_exit(stop);
The logs I get when I execute dmesg are
[ 1539.714265] probe callback
[ 1539.714277] product id : 0 vendor id : 0
Thanks in advance for any help
Your usb_id table does not contain vendor and product IDs. The id pointer passed to your probe_callback points to the element of usb_id that matched the device being probed.
You need to fill in the elements of your usb_id table properly to match the devices you are interested in, for example using the USB_DEVICE(vend, prod) macro.
Related
This question already has an answer here:
Why my kernel log is not showing the latest output?
(1 answer)
Closed 2 years ago.
I have a question about linux workqueue.
I found example kernel module using workqueue and tested it.
Here is the code.
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
MODULE_LICENSE( "GPL" );
static struct workqueue_struct *my_wq;
typedef struct {
struct work_struct my_work;
int x;
} my_work_t;
my_work_t *work, *work2;
static void my_wq_function( struct work_struct *work)
{
my_work_t *my_work = (my_work_t *)work;
printk( "my_work.x %d", my_work->x );
kfree( (void *)work );
return;
}
static int __init init_workqueue( void )
{
int ret;
my_wq = create_workqueue("my_queue");
if (my_wq) {
/* Queue some work (item 1) */
work = (my_work_t *)kmalloc(sizeof(my_work_t), GFP_KERNEL);
if (work) {
INIT_WORK( (struct work_struct *)work, my_wq_function );
work->x = 1;
ret = queue_work( my_wq, (struct work_struct *)work );
}
/* Queue some additional work (item 2) */
work2 = (my_work_t *)kmalloc(sizeof(my_work_t), GFP_KERNEL);
if (work2) {
INIT_WORK( (struct work_struct *)work2, my_wq_function );
work2->x = 2;
ret = queue_work( my_wq, (struct work_struct *)work2 );
}
}
return 0;
}
static void __exit exit_workqueue( void )
{
flush_workqueue( my_wq );
destroy_workqueue( my_wq );
return;
}
module_init(init_workqueue)
module_exit(exit_workqueue)
And this is result. left shows what I entered and right shows the dmesg.
I don't know why work2's printk doesn't show up.
After I reinsert my module, then it appears.
How can I get printk message from queued work?
Your calls to printk() don't end with a newline character (\n) and therefore dmesg does not print anything until the next call adds a new entry in the kernel message buffer.
Just add a newline at the end of your format strings, like this:
printk("my_work.x %d\n", my_work->x);
// ^^
After registering a PCI driver by calling pci_register_driver() within the init_module function, the driver is supposed to take control of any PCI devices which do not already have drivers, assuming that the devices match the vendor ID, device ID, etc. as specified in the struct pci_device_id.
I would like to force the Ethernet Controller to use my driver, just for the sake of experimentation (e.g. reading configuration bytes). On a Virtualbox guest (Mint, kernel 3.13.0), I blacklisted the Ethernet Controller's driver, ran update-initramfs -u, and rebooted. This successfully disassociated the default driver from the Controller, as the driver no longer showed up in the output of lspci -k.
However, when I loaded the module, a few devices that had previously been missing showed up in the output of lspci -k (with my driver controlling them), but the Ethernet Controller still lacked a "Kernel driver in use: " line. How can I make my module recognize and own the Controller?
Note that I used PCI_ANY_ID for the vendor and device fields, and left the other fields of the struct pci_device_id uninitialized. So I would expect the driver to probe any device which currently lacks a driver.
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/pci.h>
MODULE_LICENSE("GPL");
int init_module(void);
void cleanup_module(void);
static int pci_probe(struct pci_dev *, const struct pci_device_id *);
static void pci_remove(struct pci_dev *dev);
#define SUCCESS 0
#define FAILURE -1
static struct pci_device_id my_pci_id = {
.vendor = PCI_ANY_ID,
.device = PCI_ANY_ID
};
static struct pci_driver my_pci_driver = {
.name = "kmod_driver",
.id_table = &my_pci_id,
.probe = pci_probe,
.remove = pci_remove
};
int init_module(void)
{
return pci_register_driver(&my_pci_driver);
}
void cleanup_module(void)
{
pci_unregister_driver(&my_pci_driver);
}
static int pci_probe(struct pci_dev *dev, const pci_device_id *id)
{
int enableStatus = pci_enable_device(dev);
.....
return SUCCESS;
}
static void pci_remove(struct pci_dev *dev)
{
return;
}
You also need to include the subvendor and subdevice fields (setting them to PCI_ANY_ID as well). The matching function is this:
static inline const struct pci_device_id *
pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
{
if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) &&
(id->device == PCI_ANY_ID || id->device == dev->device) &&
(id->subvendor == PCI_ANY_ID || id->subvendor == dev->subsystem_vendor) &&
(id->subdevice == PCI_ANY_ID || id->subdevice == dev->subsystem_device) &&
!((id->class ^ dev->class) & id->class_mask))
return id;
return NULL;
}
You can use the PCI_DEVICE macro to supply the appropriate sub members:
static struct pci_device_id my_pci_id = {
PCI_DEVICE(PCI_ANY_ID, PCI_ANY_ID),
};
I am trying to implement client/ server program in c (c_glib) using thrift.
I have implemented the client/ server passing variables as function arguments. Now I need to pass structure as function argument.
The thrift file am using is given below
#!/usr/local/bin/thrift --gen c_glib
struct packet {
1: i32 header,
2: i32 data
}
service Calculator {
void ping(),
i32 calculate(1:i32 id, 2:i32 num),
void stop_transfer(),
void set_packet(1:packet pac_data)
}
The steps which I followed for passing the structure is :
In client side1. g_object_new(TYPE_PACKET, NULL)2. Pass the pointer of structure to the server. calculator_if_set_packet (client, trans_packet, &error)3. g_object_get(tans_packet, "header", &head, "data", &dat, NULL) to get the data set in server4. Print the structure to show that the data set in server is reflected back in client
The client side relevant code is given below
int main (void)
{
gint head;
gint dat;
packet *trans_packet;
trans_packet = g_object_new (TYPE_PACKET, NULL);
if(!error && calculator_if_set_packet (client, trans_packet, &error)) {
g_object_get((packet *) trans_packet,
"header", &head,
"data", &dat,
NULL);
printf("struct->header : %d\n", head);
printf("struct->data : %d\n", dat);
}
g_object_unref (trans_packet);
}
In server side1. g_object_get(pac_data, "header", &header, "data", &data, NULL) to get the properties of pac_data2. g_object_setg_object_get(tans_packet, "header", 111, "data", 999, NULL)
The server side function is given below
static gboolean
tutorial_calculator_handler_set_packet(CalculatorIf *iface,
const packet * pac_data,
GError **error)
{
gint header;
gint data;
THRIFT_UNSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
g_object_get((packet *) pac_data,
"header", &header,
"data", &data,
NULL);
g_object_set((packet *) pac_data,
"header", 123,
"data", 999,
NULL);
return TRUE;
}
When am doing this, the server is not returning anything to the client when am calling calculator_if_set_packet().
Can anyone help me on this?
The struct you have shown is not using C syntax, even for a bit field:
struct packet { //Not C syntax
1: i32 header, //1nvalid struct field declaration
2: i32 data //invalid struct field declaration
} //missing ;
You are not showing the prototype of your function(s) that take a struct as an argument, but say for example your struct was defined as such:
typedef struct {
int header;
int data;
} PACKET; //symbol PACKET would be used like your "struct packet"
Then using this typedef, you can create an instance, and a pointer to that struct like this:
PACKET packet, *pPacket;
In main, you can initialize the pointer by using the instance, like this:
int main(void)
{
//pointer instance
pPacket = &packet;
pPacket = malloc(sizeof(PACKET));//provide memory for pointer
...
free(pPacket);//free dynamic memory
return 0;
}
Then, say for example you have one function prototype that takes an instance, and another that takes a pointer to that struct:
void someFunc1(PACKET pkt); // takes an instance of PACKET
void someFunc2(PACKET *pkt); //takes an instance of PACKET *
Then in main, you can pass then like this:
int main(void)
{
pPacket = &packet; //initialize pointer using instance
pPacket = malloc(sizeof(PACKET));//provide memory for pointer
someFunc1(packet); //pass instance of PACKET
someFunc2(pPacket); //pass pointer to PACKET
someFunc2(&packet); //same as previous
...
free(pPacket);//free dynamic memory
return 0;
}
I could find the solution for the above problem.
I changed the thrift file as follows :
#!/usr/local/bin/thrift --gen c_glib
struct packet {
1: i32 header,
2: i32 data
}
service Calculator {
void ping(),
i32 calculate(1:i32 id, 2:i32 num),
void stop_transfer(),
packet set_packet(1:packet pac_data)
}
The corresponding modification in client and server part as given below :
In client part
int main (void)
{
gint head;
gint dat;
packet *trans_packet;
packet *ret_packet;
trans_packet = g_object_new (TYPE_PACKET, NULL);
ret_packet = g_object_new (TYPE_PACKET, NULL);
if(!error && calculator_if_set_packet (client, &ret_packet, trans_packet, &error)) {
g_object_get((packet *) ret_packet,
"header", &head,
"data", &dat,
NULL);
printf("struct->header : %d\n", head);
printf("struct->data : %d\n", dat);
}
g_object_unref (trans_packet);
g_object_unref (ret_packet);
}
In server part
static gboolean
tutorial_calculator_handler_set_packet(CalculatorIf *iface,
packet ** _return,
const packet * pac_data,
GError **error)
{
gint header;
gint data;
THRIFT_UNSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
g_object_get((packet *) pac_data,
"header", &header,
"data", &data,
NULL);
g_object_set(*_return,
"header", 123,
"data", 999,
NULL);
return TRUE;
}
Now whatever I set in the server am getting that in client.
If there is any other solution, do update the answer.
I trying to write i2c device driver and all is gone fine:
device detected successfully
device in sysfs class with value attribute created too
then I init a hrtimer and start it
I am trying to send data from store function of attribute and it's work fine
but when I trying to send data from hrtimer callback function my system going down. Here is some code (i was remove incudes, defines and non-important code):
led-indicator.h
struct timer_job {
ktime_t period;
struct hrtimer timer;
...
};
struct ledindicator {
struct i2c_client *client;
struct device *device;
struct timer_job job;
int value;
};
led-indicator.c
include "led-indicator.h"
static struct ledindicator *li;
// device attribute [value] store function
static ssize_t value_store(struct device *device, struct device_attribute *attr, const char *buffer, size_t count)
{
int val;
kstrtoint(buffer, 10, &val);
li->value = val;
i2c_smbus_write_byte_data(li->client, 0xBA, 0x02); // this is work fine
LOG("New value is %d \n", li->value);
return count;
}
//timer callback, fire each timer_job.period
static enum hrtimer_restart send_next(struct hrtimer * tim) {
long start = jiffies;
struct timer_job *job = container_of(tim, struct timer_job, timer);
i2c_smbus_write_byte_data(li->client, 0xBA, 0x02); // this cause system fault
hrtimer_forward_now(tim, job->period);
return HRTIMER_RESTART;
}
//when device is detected I am create sysfs device and init timer.
enter code here//Also I am crate led_indicator structure and save i2c_client pointer for future use
static int li_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int ret = 0;
li = kmalloc(sizeof(*li), GFP_KERNEL);
li->client = client;
li->value = 0;
...
// here creating device and attribute for it
...
hrtimer_init(&(li->job.timer), CLOCK_MONOTONIC, HRTIMER_MODE_REL);
li->job.timer.function = send_next;
li->job.period = ktime_set(1, 0); //1 sec
hrtimer_start(&(li->job.timer), li->job.period, HRTIMER_MODE_REL);
return ret;
}
What is wrong?
Is it possible to notify the module when one of it's sys files was changed? My task is to do a file which controls size of buffer inside the module, I want to resize the buffer when the value in the file is changed.
My other idea (if I can't notify the module) was to check the previous value each time the module is used and then resize the buffer.
Isn't this the purpose of Sysfs?
When you create a kobject and give it a representation in Sysfs (which is a directory), you then create attributes for that object which will become files in that directory. You provide a store and a show callback to the kobject, which are basically equivalents of resp. write and read.
store is what you want here. It looks like this:
ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
const char *buffer, size_t size);
You receive size bytes within buffer as soon as the virtual file is written in user land.
Have a look at this module which does it (taken from here):
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
struct my_attr {
struct attribute attr;
int value;
};
static struct my_attr my_first = {
.attr.name="first",
.attr.mode = 0644,
.value = 1,
};
static struct my_attr my_second = {
.attr.name="second",
.attr.mode = 0644,
.value = 2,
};
static struct attribute * myattr[] = {
&my_first.attr,
&my_second.attr,
NULL
};
static ssize_t default_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
struct my_attr *a = container_of(attr, struct my_attr, attr);
return scnprintf(buf, PAGE_SIZE, "%d\n", a->value);
}
static ssize_t default_store(struct kobject *kobj, struct attribute *attr,
const char *buf, size_t len)
{
struct my_attr *a = container_of(attr, struct my_attr, attr);
sscanf(buf, "%d", &a->value);
return sizeof(int);
}
static struct sysfs_ops myops = {
.show = default_show,
.store = default_store,
};
static struct kobj_type mytype = {
.sysfs_ops = &myops,
.default_attrs = myattr,
};
struct kobject *mykobj;
static int __init sysfsexample_module_init(void)
{
int err = -1;
mykobj = kzalloc(sizeof(*mykobj), GFP_KERNEL);
if (mykobj) {
kobject_init(mykobj, &mytype);
if (kobject_add(mykobj, NULL, "%s", "sysfs_sample")) {
err = -1;
printk("Sysfs creation failed\n");
kobject_put(mykobj);
mykobj = NULL;
}
err = 0;
}
return err;
}
static void __exit sysfsexample_module_exit(void)
{
if (mykobj) {
kobject_put(mykobj);
kfree(mykobj);
}
}
module_init(sysfsexample_module_init);
module_exit(sysfsexample_module_exit);
MODULE_LICENSE("GPL");
Also: you might want to output the buffer size to the user when the entry is read. This is usually the way of doing it. Also make sure the information (read and written) is in a human-readable format to keep up with the Unix philosophy.
Update: see this recent interesting article about Sysfs file creation written by Greg Kroah-Hartman, one of the top kernel developers.