add adc module
This commit is contained in:
parent
a97d98549f
commit
c47062607e
2 changed files with 180 additions and 0 deletions
16
adc/Makefile
Normal file
16
adc/Makefile
Normal 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
164
adc/usbio-adc.c
Normal 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");
|
Loading…
Reference in a new issue