add adc module

This commit is contained in:
encrypt 2016-03-08 11:49:31 +01:00
parent a97d98549f
commit c47062607e
2 changed files with 180 additions and 0 deletions

16
adc/Makefile Normal file
View file

@ -0,0 +1,16 @@
obj-m := usbio-adc.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
DEPMOD:=$(shell which depmod)
# possible bug: maybe this will work only on debian based systems
SYSMAP:= /boot/System.map-$(shell uname -r)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
install:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules_install
$(DEPMOD) -ae -F $(SYSMAP)
clean:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean

164
adc/usbio-adc.c Normal file
View file

@ -0,0 +1,164 @@
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/driver.h>
#include <linux/iio/machine.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/usb.h>
#define USBIO_VENDOR_ID 0x04d8
#define USBIO_PRODUCT_ID 0x003f
struct usbio_adc {
struct usb_device *udev;
int value;
};
static const struct iio_chan_spec const usbio_adc_channels[] = {
{
.indexed = 1,
.type = IIO_VOLTAGE,
.channel = 0,
.datasheet_name = "DM0",
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
}, {
.indexed = 1,
.type = IIO_VOLTAGE,
.channel = 1,
.datasheet_name = "DM1",
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
}
};
static int usbio_adc_read(struct usb_device *usb_dev, int channel, int *val)
{
u8 data[64];
int ret, actual_len;
actual_len = 1;
data[0] = 0x37+channel;
*val = 0;
printk(KERN_INFO "reading from %x", data[0]);
ret = usb_interrupt_msg(usb_dev,
usb_sndintpipe(usb_dev, 1),
data, sizeof(data), &actual_len, USB_CTRL_SET_TIMEOUT);
if(ret < 0)
return -EIO;
actual_len = 64;
memset(data, 0, 64);
ret = usb_bulk_msg(usb_dev,
usb_rcvbulkpipe(usb_dev, 0x81),
data, sizeof(data), &actual_len, USB_CTRL_SET_TIMEOUT);
if(ret < 0)
return -EIO;
printk(KERN_INFO "back from %x",data[0]);
*val = (data[2] << 8) | data[1];
return IIO_VAL_INT;
}
static int usbio_adc_read_raw(struct iio_dev *usbio_adc_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{
int ret;
struct usbio_adc *adc = iio_priv(usbio_adc_dev);
mutex_lock(&usbio_adc_dev->mlock);
switch(mask) {
case IIO_CHAN_INFO_RAW:
ret = usbio_adc_read(adc->udev, chan->channel, val);
break;
default:
ret = -EINVAL;
}
mutex_unlock(&usbio_adc_dev->mlock);
return ret;
}
static const struct iio_info usbio_adc_iio_info = {
.read_raw = &usbio_adc_read_raw,
.driver_module = THIS_MODULE
};
static struct iio_map usbio_adc_default_maps[] = {
{
.adc_channel_label = "DM0",
.consumer_dev_name = "usbio-adc",
.consumer_channel = "usbio-adc0",
},
{
.adc_channel_label = "DM1",
.consumer_dev_name = "usbio-adc",
.consumer_channel = "usbio-adc1",
}
};
static int usbio_adc_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(interface);
struct iio_dev *usbio_adc_dev;
struct usbio_adc *adc = NULL;
int ret;
usbio_adc_dev = devm_iio_device_alloc(&udev->dev, sizeof(*adc));
if(!usbio_adc_dev)
return -ENOMEM;
adc = iio_priv(usbio_adc_dev);
adc->udev = udev;
adc->value = 0;
usb_set_intfdata(interface, usbio_adc_dev);
usbio_adc_dev->dev.parent = &udev->dev;
usbio_adc_dev->name = "usbio-adc";
usbio_adc_dev->channels = usbio_adc_channels;
usbio_adc_dev->num_channels = ARRAY_SIZE(usbio_adc_channels);
usbio_adc_dev->info = &usbio_adc_iio_info;
usbio_adc_dev->modes = INDIO_DIRECT_MODE;
ret = iio_map_array_register(usbio_adc_dev, usbio_adc_default_maps);
if(ret < 0) {
dev_err(&udev->dev, "something went wrong");
return ret;
}
ret = iio_device_register(usbio_adc_dev);
if(ret < 0) {
dev_err(&udev->dev, "unable to register iiodevice \n");
goto err_array_unregister;
}
return 0;
err_array_unregister:
iio_map_array_unregister(usbio_adc_dev);
return ret;
}
static void usbio_adc_disconnect(struct usb_interface *interface)
{
struct iio_dev *usbio_adc_dev = usb_get_intfdata(interface);
struct usbio_adc *adc = iio_priv(usbio_adc_dev);
//usb_set_intfdata(interface, NULL);
usb_put_dev(adc->udev);
// kfree(adc);
iio_device_unregister(usbio_adc_dev);
iio_map_array_unregister(usbio_adc_dev);
}
static struct usb_device_id usbio_id_table[] = {
{ USB_DEVICE(USBIO_VENDOR_ID, USBIO_PRODUCT_ID) },
{}
};
MODULE_DEVICE_TABLE(usb, usbio_id_table);
static struct usb_driver usbio_adc_driver = {
.name = "usbio_adc",
.probe = usbio_adc_probe,
.disconnect = usbio_adc_disconnect,
.id_table = usbio_id_table
};
module_usb_driver(usbio_adc_driver);
MODULE_DESCRIPTION("USBIO ADC");
MODULE_AUTHOR("encrypt <encrypt@labr.xyz>");
MODULE_LICENSE("GPL");