/************************************************************************/
/* Kerneltreiber fuer den Luftqualitaetsstick */
/* Im Rahmen der Veranstaltung Embedded Systems bei Juergen Quade */
/* Copyright (c) 2017 Florian Scholz */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/************************************************************************/
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/usb.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#define USB_VENDOR_ID 0x03eb
#define USB_DEVICE_ID 0x2013
struct usb_device *dev;
static DEFINE_MUTEX( ulock );
static short airsensorfs_read_sensor_value( void );
static ssize_t airsensorfs_read( struct file *instanz, char *buffer,
size_t count, loff_t *ofs )
{
char pbuf[20];
short value;
value = airsensorfs_read_sensor_value();
int cnt = snprintf(pbuf, count, "%d\n", value);
count -= copy_to_user(buffer,pbuf,cnt);
*ofs += count;
return count;
}
static short airsensorfs_read_sensor_value() {
char buf[1000];
int rcvd_bytes, retval;
short value;
memcpy(buf, "\x40\x68\x2a\x54\x52\x0a\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40", 0x0000010);
mutex_lock(&ulock);
retval = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x2), buf, 0x10, &rcvd_bytes, 1000);
if(retval != 0)
{
printk("airsensorfs: couldn't send write request inital\n");
}
retval = usb_interrupt_msg(dev, usb_rcvintpipe(dev, 0x81), buf, 0x10, &rcvd_bytes, 1000);
if(retval != 0)
{
printk("airsensorfs: failed to read data\n");
}
retval = usb_interrupt_msg(dev, usb_rcvintpipe(dev, 0x81), buf, 0x10, &rcvd_bytes, 1000);
if(retval != 0)
{
printk("airsensorfs: failed to read remaining data\n");
}
mutex_unlock(&ulock);
memcpy(&value, buf+2,2);
return value;
}
static int airsensorfs_open( struct inode *devicefile, struct file *instanz )
{
return 0;
}
static struct file_operations usb_fops = {
.owner = THIS_MODULE,
.open = airsensorfs_open,
.read = airsensorfs_read,
};
static struct usb_device_id usbid [] = {
{ USB_DEVICE(USB_VENDOR_ID, USB_DEVICE_ID), },
{ } /* Terminating entry */
};
struct usb_class_driver class_descr = {
.name = "airsensorfs",
.fops = &usb_fops,
.minor_base = 16,
};
static int airsensorfs_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
dev = interface_to_usbdev(interface);
printk("airsensorfs driver by florian scholz: 0x%4.4x|0x%4.4x, if=%p\n", dev->descriptor.idVendor,
dev->descriptor.idProduct, interface );
if (dev->descriptor.idVendor==USB_VENDOR_ID
&& dev->descriptor.idProduct==USB_DEVICE_ID) {
if (usb_register_dev( interface, &class_descr )) {
return -EIO;
}
printk("got minor= %d\n", interface->minor );
char buf[1000];
int rcvd_bytes;
int retval = usb_interrupt_msg(dev, usb_rcvintpipe(dev, 0x81), buf, 0x10, &rcvd_bytes, 1000);
if(retval != 0)
{
printk("airsensorfs: failed to read remaining data\n");
return 0;
}
}
return -ENODEV;
}
static void airsensorfs_disconnect( struct usb_interface *iface )
{
mutex_lock( &ulock );
usb_deregister_dev( iface, &class_descr );
mutex_unlock( &ulock );
}
static struct usb_driver airsensorfs = {
.name= "airsensorfs",
.id_table= usbid,
.probe= airsensorfs_probe,
.disconnect= airsensorfs_disconnect,
};
static int __init airsensorfs_init(void)
{
if (usb_register(&airsensorfs) ) {
printk("airsensorfs: unable to register usb driver\n");
return -EIO;
}
else
{
printk("airsensorfs: registered usb driver\n");
}
return 0;
}
static void __exit airsensorfs_exit(void)
{
usb_deregister(&airsensorfs);
}
module_init(airsensorfs_init);
module_exit(airsensorfs_exit);
MODULE_LICENSE( "GPL" );
Comments