/************************************************************************/ /* 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 #include #include #include #include #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" );