Linux kernel module to read out GPS device via USB - linux

I'm writing a Linux kernel module to read out a GPS device (a u-blox NEO-7) via USB by using the book Linux Device Drivers.
I already can probe and read out data from the device successfully. But, there is a problem when reading the device with multiple applications simultaneously (I used "cat /dev/ublox" to read indefinitely). When the active/reading applications is cancelled via "Ctrl + C", the next reading attempt from the other application fails (exactly method call usb_submit_urb(...) returns -EINVAL).
I use following ideas for my implementation:
The kernel module methods should be re-entrant. Therefore, I use a mutex to protect critical sections. E.g. allowing only one reader simultaneously.
To safe ressources, I reuse the struct urb for different reading requests (see an explanation)
Device-specific data like USB endpoint address and so on is held in a device-specific struct called ublox_device.
After submitting the USB read request, the calling process is sent to sleep until the asynchronous complete handler is called.
I verified that the ideas are implemented correctly: I have run two instances of "cat /dev/ublox" simultaneously and I got the correct output (only one instance accessed the critical read section at a time). And also reusing the "struct urb" is working. Both instances read out data alternatively.
The problem only occurs if the currently active instance is cancelled via "Ctrl + C". I can solve the problem by not reusing the "struct urb" but I would like to avoid that. I.e. by allocating a new "struct urb" for each read request via usb_alloc_urb(...) (usually it is allocated once when probing the USB device).
My code follows the USB skeleton driver from Greg Kroah-Hartman who also reuse the "struct urb" for different reading requests.
Maybe someone has a clue what's going wrong here.
The complete code can be found on pastebin. Here is a small excerpt of the read method and the USB request complete handler.
static ssize_t ublox_read(struct file *file, char *buffer, size_t count, loff_t *pos)
{
struct ublox_device *ublox_device = file->private_data;
...
return_value = mutex_lock_interruptible(&ublox_device->bulk_in_mutex);
if (return_value < 0)
return -EINTR;
...
retry:
usb_fill_bulk_urb(...);
ublox_device->read_in_progress = 1;
/* Next call fails if active application is cancelled via "Ctrl + C" */
return_value = usb_submit_urb(ublox_device->bulk_in_urb, GFP_KERNEL);
if (return_value) {
printk(KERN_ERR "usb_submit_urb(...) failed!\n");
ublox_device->read_in_progress = 0;
goto exit;
}
/* Go to sleep until read operation has finished */
return_value = wait_event_interruptible(ublox_device->bulk_in_wait_queue, (!ublox_device->read_in_progress));
if (return_value < 0)
goto exit;
...
exit:
mutex_unlock(&ublox_device->bulk_in_mutex);
return return_value;
}
static void ublox_read_bulk_callback(struct urb *urb)
{
struct ublox_device *ublox_device = urb->context;
int status = urb->status;
/* Evaluate status... */
...
ublox_device->transferred_bytes = urb->actual_length;
ublox_device->read_in_progress = 0;
wake_up_interruptible(&ublox_device->bulk_in_wait_queue);
}

Now, I allocate a new struct urb for each read request. This avoids the problem with the messed up struct urb after an active read request is cancelled by the calling application. The allocated struct is freed in the complete handler.
I will come back to LKML when I optimize my code. For now, it is okay to allocate a new struct urb for each single read request. The complete code of the kernel module is on pastebin.
static ssize_t ublox_read(struct file *file, char *buffer, size_t count, loff_t *pos)
{
struct ublox_device *ublox_device = file->private_data;
...
retry:
ublox_device->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL);
...
usb_fill_bulk_urb(...);
...
return_value = usb_submit_urb(ublox_device->bulk_in_urb, GFP_KERNEL);
...
}
static void ublox_read_bulk_callback(struct urb *urb)
{
struct ublox_device *ublox_device = urb->context;
...
usb_free_urb(ublox_device->bulk_in_urb);
...
}

Related

linux device driver control high-speed SPI ADC

Recently I have a project to use a Linux host to communicate with an ADC device(SPI communication). I use my knowledge to write a device driver for it.
The goal of this driver is to read ADC data and transfer them to userspace. My idea is when the Linux host gets the DRDY signal(data ready signal, the signal means the data of ADC can be read) from ADC, an interrupt will be triggered, and the SPI read API of the driver will read data from the SPI bus. the data will fill into a buffer, when the buffer is full, the driver sends a SIGNAL to the userspace program, and the data in the buffer will be read by the userspace.
Although this idea may not be a perfect plan to realize my goal, I finish the code above. Unfortunately, I face a question that makes my goal failed.
The SPI transfer API of the Linux host should be put into the bottom half of the interrupt(due to the sleep mechanic of SPI API), that is to say, if the sample rate of AD is too fast, the bottom half of the interrupt may read a delayed data of ADC, when I use 4kHz sample rate, there are 7997 interrupts, but only 7907 data has been read. When I use the 250Hz sample rate, my idea is OK. But, I must use at least 4ksps.
I do not know whether you have some experience with this kind of problem, or maybe my idea is not suited for the high-speed ADC, I hope you can give me some suggestions, thanks a lot.
Here is some core code of my idea. The SPI transfer function:
int get_ad_data(struct spi_device *ad_spi_dev)
{
int ret = -1;
gpio_set_value(ADS1299_CS_PIN, 0);
if( ad_spi_dev )
{
struct spi_transfer tr =
{
.tx_buf = &send_data,
.rx_buf = &get_data,
.len = 27,
};
ret = spi_sync_transfer(ad_spi_dev, &tr, 1);
}
printk("%02x, %02x, %02x\r\n",get_data[6],get_data[7],get_data[8]);
gpio_set_value(ADS1299_CS_PIN, 1);
return ret;
}
The interrupt handler:
static irqreturn_t drdy_handler(int irq, void *dev_id)
{
struct ads1299_dev *dev = dev_id;
schedule_work(&dev->drdy_irq.work_drdy);
return IRQ_HANDLED;
}
static void drdy_work(struct work_struct *work)
{
int ret;
ret = get_ad_data(ads1299_spi_dev);
}

Python3 read fron character device in blocking mode

I wrote a character device driver. Now I want to use python to read from it when there is data.
However, I found that the modules "io" as well as "os" do not block upon reading. The latter even when I set os.set_blocking(fd,true).
Is there a way to access the device in blocking mode?
Or do I miss something in the device driver (tail works fine)?
f=io.open("/dev/tstty0","r")
while (1)
data=str(f.read(32))
print("mark") # <--- endless list of marks
#do somthing
The read function of the device driver:
static ssize_t tstty_read(
struct file *filp,
char *buffer,
size_t length,
loff_t *offset)
{
unsigned char b;
unsigned long ofs=0;
devConfig* dev=filp->private_data;
if (dev)
{
while (fifoGet(&dev->tcp2dev,&b) && (ofs<length))
{
if (put_user(b,buffer+ofs))
{
printk(KERN_ERR "Could not copy user data");
return -EINVAL;
}
ofs++;
}
//printk(KERN_INFO "Reading device");
return ofs;
}
printk(KERN_ERR "Unknown device: %s",filp->f_path.dentry->d_iname);
return -EINVAL;
};
The read function reads any bytes available from a fifo. I none is available 0 is returned.
Kudos to Ian Abbott. A character device has to implement the ability to block a read request. The read file operation has to evaluate filp->f_flags & O_NONBLOCK to check if a client has requested blocking I/O.
This link helped me with an example:
simple linux driver code for blocking and non-blocking read
This example works but one has to consider two more things not covered in the example: a) What to do when you want to unload the driver while in read operation (just dont do it or wake up and abort)?
b) How to abort a client caught in blocking I/O?

Kernel driver, ioremap necessary in MMU-less system?

So, I am a total newbie when it comes to kernel drivers and have a question regarding ioremap function.
I am writing a driver for accessing some registers defined in a custom VHDL-module on a SoC with a ARM Cortex-M3 and FPGA fabric.
Looking at examples I figured I should use ioremap, but since the Cortex-M3 does not have a MMU, I don't really see the point, as per the following example:
/* Physical addresses */
static u32* rcu_trig_recv_physaddr = ((u32 *) 0x50040000);
static int rcu_trig_recv_size = 0x10; // size of 16 for testing
/* Virtual addresses */
static u32* rcu_trig_recv_virtbase = NULL;
/*removed code not relevant for the question*/
static int __init rcumodule_init(void)
{
int iResult = 0; // holding result of operations
u32 buffer;
// Register the driver
iResult = register_chrdev(rcuc_majorID, "rcuc", &rcuc_fops);
if (iResult < 0) {
printk(KERN_INFO "module init: can't register driver\n");
}
else{
printk(KERN_INFO "module init: success!\n");
}
// Map physical address to virtual address
if(rcu_trig_recv_size){
rcu_trig_recv_virtbase = (u32*) ioremap_nocache( (u32 *)rcu_trig_recv_physaddr, rcu_trig_recv_size );
printk("Remapped TRGRECV from 0x%p to 0x%p\n", rcu_trig_recv_physaddr, rcu_trig_recv_virtbase);
}
// try to read some stuff, expecting 0x17240f09
buffer = readl(rcu_trig_recv_virtbase);
printk("read %lx, at 0x%p\n", buffer, rcu_trig_recv_virtbase);
return iResult;
}
This then return, when I insmod the driver:
# insmod trigger.ko
module init: success!
Remapped TRGRECV from 0x50040000 to 0x50040000
read 17240f09, at 0x50040000
According to this, I would just be better off reading the physical address instead. Or is that a bad idea and I should be messing with my registers in a better way?
It's possible that you can get away with this if you know your code will never need to be used on another device, but you're much safer sticking with using ioremap(). Basing your code around obtaining and using the pointers provided by memory-mapped IO will make your code more portable and maintainable than utilizing hard-coded physical addresses.
Even if you don't plan on taking this code to a different device, using physical addresses could potentially break your code when simply upgrading to a newer chip in the same line.

Develop simple net_device in the linux kernel

I am trying to implement a netdevice (net_device) in linux kernel. This is simple net_device which pass the command/data from user space to kernel space and vice versa this is the goal of this simple net_device. I am using socket for passing command/data from user space to kernel space . After googling i successed in registering net_device and able to see my device in /sys/class/net/abc0 (device name)
when coming to file operation there is no clear idea of the flow
struct net_device_ops
{
.ndo_open =open,
.ndo_close = close,
.ndo_start_xmit = start_xmit
}
if i issue write in socket will it call start_xmit in data link layer.
If i want to call open method, how to call it using socket
How to call start_xmit using socket
How will i find , there is data packet in the receive buffer and pass it to user space.
There is no clear flow/information about simple net_device (except ethernet) can any suggest a link/pdf.
I tried writing simple socket program to test open,close,start_xmit. where socket read/write is not calling open,close,star_xmit .
Is there any way to test the developed net_device ?
Thank you
I found how to test the open,close function .
type : ifconfig abc0(Device name) up will call open method
type : ifconfig abc0(Device name) down will call close method
Can some one help me how to test these methods with sockets.
SIOCSIFFLAGS, -> IFF_UP you can actually set or unset it while doing an ioctl to the netdevice abc0.
first off you have to create a dgram socket,
then use ifreq structure defined in net/if.h
and fill interface and iff_flags
iff_flags can be set with IFF_UP or can be negated with the same IFF_UP to make interface down
and then close the socket.
#include <net/if.h>
....
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
goto fail;
}
struct ifreq ifreq;
strcpy(ifreq.ifr_name, "abcd0");
ifreq.iff_flags |= IFF_UP;
if (ioctl(sock, &ifreq, sizeof(ifreq) < 0) {
perror("ioctl setting interface up");
}
ifreq.iff_flags ~= IFF_UP;
if (ioctl(sock, &ifreq, sizeof(ifreq) < 0) {
perror("ioctl setting interface down");
}
close(sock);
offtopic:
will you please share your code? we can understand too about your network device :)

Kernel module get data from user space

What is the proper way of sending some data to a loaded and running kernel module, without using netlink and without using features that may not be in place (e.g. debugfs)?
I'd like to see a clean and safe way of doing this which should work on most kernels (or preferably all modern ones), or at best an approximation of that.
The user who wants to send data to the module is the root user, the amount of data is probably under 64 kiB and consists of a series of strings.
I've already looked into trying to read files from the module, which is not only highly frowned upon for various reasons but also hard to do.
I've looked at netlink, which socket() tells me on my kernel is not supported.
I've looked at debugfs, which is not supported either on my kernel.
Obviously I could use a different kernel but as I mentioned I'd like a proper way of doing this. If someone could show me a simple example of a module that will just do a printk() of a string sent from user space that would be great.
... a simple example of a module that will just do a printk() of a string sent from user space, printkm.c:
#include <linux/module.h>
#include <linux/proc_fs.h>
MODULE_DESCRIPTION("printk example module");
MODULE_AUTHOR("Dietmar.Schindler#manroland-web.com");
MODULE_LICENSE("GPL");
static
ssize_t write(struct file *file, const char *buf, size_t count, loff_t *pos)
{
printk("%.*s", count, buf);
return count;
}
static struct file_operations file_ops;
int init_module(void)
{
printk("init printk example module\n");
struct proc_dir_entry *entry = proc_create("printk", 0, NULL, &file_ops);
if (!entry) return -ENOENT;
file_ops.owner = THIS_MODULE,
file_ops.write = write;
return 0;
}
void cleanup_module(void)
{
remove_proc_entry("printk", NULL);
printk("exit printk example module\n");
}
Example use:
root#kw:~# insmod printkm.ko
root#kw:~# echo a string >/proc/printk
root#kw:~# dmesg|tail -1
[193634.164459] a string
I think you can use a char device. Take a look at Linux Device Driver 3th Chapter 3. With the function *copy_to_user* and *copy_from_user* you can copy data safely to and from userspace.

Resources