commit 8ff56e1c18d48da7c7c85e326b45be4ada30e015 Author: encrypt Date: Tue Jan 5 19:40:45 2016 +0100 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..98606a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*~ +*.symvers +*.ko +*.order +*.o +*.mod.* +*.cmd \ No newline at end of file diff --git a/.tmp_versions/usbio-led.mod b/.tmp_versions/usbio-led.mod new file mode 100644 index 0000000..6969ee9 --- /dev/null +++ b/.tmp_versions/usbio-led.mod @@ -0,0 +1,2 @@ +/home/marco/projects/usbio-led-lkm/usbio-led.ko +/home/marco/projects/usbio-led-lkm/usbio-led.o diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..47c1974 --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +obj-m := usbio-led.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/usbio-led.c b/usbio-led.c new file mode 100644 index 0000000..7e382f1 --- /dev/null +++ b/usbio-led.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include +#include +#include + +#define USBIO_VENDOR_ID 0x04d8 +#define USBIO_PRODUCT_ID 0x003f + +struct usbio_led { + struct usb_device *udev; + struct led_classdev ldev; + struct mutex lock; +}; + +static void usbio_led_set(struct led_classdev *ldev, enum led_brightness brightness) { + u8 data[] = { 0x80 }; + struct usbio_led *led = container_of(ldev, struct usbio_led, ldev); + int actual_len = 1; + mutex_lock(&led->lock); + usb_interrupt_msg(led->udev, + usb_sndintpipe(led->udev, 1), + data, sizeof(data), &actual_len, USB_CTRL_SET_TIMEOUT); + mutex_unlock(&led->lock); +} + +static int usbio_led_probe(struct usb_interface *interface, const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(interface); + struct usbio_led *led = NULL; + int retval = -ENOMEM; + led = kzalloc(sizeof(struct usbio_led), GFP_KERNEL); + if(led == NULL) { + dev_err(&interface->dev, "Out of memory"); + goto error; + } + led->udev = usb_get_dev(udev); + usb_set_intfdata(interface, led); + dev_info(&interface->dev, "USBIO LED attached\n"); + mutex_init(&led->lock); + led->ldev.name = "usbio_led"; + led->ldev.max_brightness = 1; + led->ldev.brightness = LED_OFF; + led->ldev.brightness_set = usbio_led_set; + + retval = led_classdev_register(&led->udev->dev, &led->ldev); + + if(retval < 0) { + printk("whoops"); + goto error; + } + + return 0; + + error: + printk("errors"); + kfree(led); + return retval; +} + +static void usbio_led_disconnect(struct usb_interface *interface) +{ + struct usbio_led *led; + led = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + usb_put_dev(led->udev); + led_classdev_unregister(&led->ldev); + kfree(led); + dev_info(&interface->dev, "USBIO disconnected"); +} + +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_led_driver = { + .name = "usbio_led", + .probe = usbio_led_probe, + .disconnect = usbio_led_disconnect, + .id_table = usbio_id_table +}; + +module_usb_driver(usbio_led_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("encrypt "); +MODULE_DESCRIPTION("USBIO led");