From c47062607e3131494062816fe0cd28fcc2367052 Mon Sep 17 00:00:00 2001 From: encrypt Date: Tue, 8 Mar 2016 11:49:31 +0100 Subject: [PATCH] add adc module --- adc/Makefile | 16 +++++ adc/usbio-adc.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 adc/Makefile create mode 100644 adc/usbio-adc.c diff --git a/adc/Makefile b/adc/Makefile new file mode 100644 index 0000000..e4d7bc8 --- /dev/null +++ b/adc/Makefile @@ -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 diff --git a/adc/usbio-adc.c b/adc/usbio-adc.c new file mode 100644 index 0000000..1345c6f --- /dev/null +++ b/adc/usbio-adc.c @@ -0,0 +1,164 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 "); +MODULE_LICENSE("GPL");