diff options
| -rw-r--r-- | drivers/usb/misc/Kconfig | 13 | ||||
| -rw-r--r-- | drivers/usb/misc/Makefile | 1 | ||||
| -rw-r--r-- | drivers/usb/misc/phidget.c | 43 | ||||
| -rw-r--r-- | drivers/usb/misc/phidget.h | 12 | ||||
| -rw-r--r-- | drivers/usb/misc/phidgetkit.c | 258 | ||||
| -rw-r--r-- | drivers/usb/misc/phidgetmotorcontrol.c | 126 | ||||
| -rw-r--r-- | drivers/usb/misc/phidgetservo.c | 71 | 
7 files changed, 334 insertions, 190 deletions
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 8affc137d61..20539cf9394 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -115,9 +115,16 @@ config USB_CYTHERM  	  To compile this driver as a module, choose M here: the  	  module will be called cytherm. +config USB_PHIDGET +	tristate "USB Phidgets drivers" +	depends on USB +	help +	  Say Y here to enable the various drivers for devices from +	  Phidgets inc. +  config USB_PHIDGETKIT  	tristate "USB PhidgetInterfaceKit support" -	depends on USB +	depends on USB_PHIDGET  	help  	  Say Y here if you want to connect a PhidgetInterfaceKit USB device  	  from Phidgets Inc. @@ -127,7 +134,7 @@ config USB_PHIDGETKIT  config USB_PHIDGETMOTORCONTROL  	tristate "USB PhidgetMotorControl support" -	depends on USB +	depends on USB_PHIDGET  	help  	  Say Y here if you want to connect a PhidgetMotorControl USB device  	  from Phidgets Inc. @@ -137,7 +144,7 @@ config USB_PHIDGETMOTORCONTROL  config USB_PHIDGETSERVO  	tristate "USB PhidgetServo support" -	depends on USB +	depends on USB_PHIDGET  	help  	  Say Y here if you want to connect an 1 or 4 Motor PhidgetServo   	  servo controller version 2.0 or 3.0. diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 5f329176451..d12a84a1c0a 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_USB_LCD)		+= usblcd.o  obj-$(CONFIG_USB_LD)		+= ldusb.o  obj-$(CONFIG_USB_LED)		+= usbled.o  obj-$(CONFIG_USB_LEGOTOWER)	+= legousbtower.o +obj-$(CONFIG_USB_PHIDGET)	+= phidget.o  obj-$(CONFIG_USB_PHIDGETKIT)	+= phidgetkit.o  obj-$(CONFIG_USB_PHIDGETMOTORCONTROL)	+= phidgetmotorcontrol.o  obj-$(CONFIG_USB_PHIDGETSERVO)	+= phidgetservo.o diff --git a/drivers/usb/misc/phidget.c b/drivers/usb/misc/phidget.c new file mode 100644 index 00000000000..735ed33f4f7 --- /dev/null +++ b/drivers/usb/misc/phidget.c @@ -0,0 +1,43 @@ +/* + * USB Phidgets class + * + * Copyright (C) 2006  Sean Young <sean@mess.org> + * + * 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. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/device.h> + +struct class *phidget_class; + +static int __init init_phidget(void) +{ +	phidget_class = class_create(THIS_MODULE, "phidget"); + +	if (IS_ERR(phidget_class)) +		return PTR_ERR(phidget_class); + +	return 0; +} + +static void __exit cleanup_phidget(void) +{ +	class_destroy(phidget_class); +} + +EXPORT_SYMBOL_GPL(phidget_class); + +module_init(init_phidget); +module_exit(cleanup_phidget); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Sean Young <sean@mess.org>"); +MODULE_DESCRIPTION("Container module for phidget class"); + diff --git a/drivers/usb/misc/phidget.h b/drivers/usb/misc/phidget.h new file mode 100644 index 00000000000..c4011907d43 --- /dev/null +++ b/drivers/usb/misc/phidget.h @@ -0,0 +1,12 @@ +/* + * USB Phidgets class + * + * Copyright (C) 2006  Sean Young <sean@mess.org> + * + * 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. + */ + +extern struct class *phidget_class; diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index bfbbbfbb92b..3f508957def 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c @@ -20,6 +20,8 @@  #include <linux/module.h>  #include <linux/usb.h> +#include "phidget.h" +  #define DRIVER_AUTHOR "Sean Young <sean@mess.org>"  #define DRIVER_DESC "USB PhidgetInterfaceKit Driver" @@ -57,11 +59,15 @@ ifkit(8, 8, 4, 0);  ifkit(0, 8, 8, 1);  ifkit(0, 16, 16, 0); +static unsigned long device_no; +  struct interfacekit {  	struct usb_device *udev;  	struct usb_interface *intf;  	struct driver_interfacekit *ifkit; +	struct device *dev;  	unsigned long outputs; +	int dev_no;  	u8 inputs[MAX_INTERFACES];  	u16 sensors[MAX_INTERFACES];  	u8 lcd_files_on; @@ -180,21 +186,21 @@ exit:  }  #define set_lcd_line(number)	\ -static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)	\ -{											\ -	struct usb_interface *intf = to_usb_interface(dev);				\ -	struct interfacekit *kit = usb_get_intfdata(intf);				\ -	change_string(kit, buf, number - 1);						\ -	return count;									\ -}											\ +static ssize_t lcd_line_##number(struct device *dev,			\ +					struct device_attribute *attr,	\ +					const char *buf, size_t count)	\ +{									\ +	struct interfacekit *kit = dev_get_drvdata(dev);		\ +	change_string(kit, buf, number - 1);				\ +	return count;							\ +}									\  static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number);  set_lcd_line(1);  set_lcd_line(2);  static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)  { -	struct usb_interface *intf = to_usb_interface(dev); -	struct interfacekit *kit = usb_get_intfdata(intf); +	struct interfacekit *kit = dev_get_drvdata(dev);  	int enabled;  	unsigned char *buffer;  	int retval = -ENOMEM; @@ -232,16 +238,15 @@ static void remove_lcd_files(struct interfacekit *kit)  {  	if (kit->lcd_files_on) {  		dev_dbg(&kit->udev->dev, "Removing lcd files\n"); -		device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_1); -		device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_2); -		device_remove_file(&kit->intf->dev, &dev_attr_backlight); +		device_remove_file(kit->dev, &dev_attr_lcd_line_1); +		device_remove_file(kit->dev, &dev_attr_lcd_line_2); +		device_remove_file(kit->dev, &dev_attr_backlight);  	}  }  static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)  { -	struct usb_interface *intf = to_usb_interface(dev); -	struct interfacekit *kit = usb_get_intfdata(intf); +	struct interfacekit *kit = dev_get_drvdata(dev);  	int enable;  	if (kit->ifkit->has_lcd == 0) @@ -253,9 +258,9 @@ static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *att  	if (enable) {  		if (!kit->lcd_files_on) {  			dev_dbg(&kit->udev->dev, "Adding lcd files\n"); -			device_create_file(&kit->intf->dev, &dev_attr_lcd_line_1); -			device_create_file(&kit->intf->dev, &dev_attr_lcd_line_2); -			device_create_file(&kit->intf->dev, &dev_attr_backlight); +			device_create_file(kit->dev, &dev_attr_lcd_line_1); +			device_create_file(kit->dev, &dev_attr_lcd_line_2); +			device_create_file(kit->dev, &dev_attr_backlight);  			kit->lcd_files_on = 1;  		}  	} else { @@ -362,24 +367,24 @@ static void do_notify(void *data)  	for (i=0; i<kit->ifkit->inputs; i++) {  		if (test_and_clear_bit(i, &kit->input_events)) {  			sprintf(sysfs_file, "input%d", i + 1); -			sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); +			sysfs_notify(&kit->dev->kobj, NULL, sysfs_file);  		}  	}  	for (i=0; i<kit->ifkit->sensors; i++) {  		if (test_and_clear_bit(i, &kit->sensor_events)) {  			sprintf(sysfs_file, "sensor%d", i + 1); -			sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); +			sysfs_notify(&kit->dev->kobj, NULL, sysfs_file);  		}  	}  }  #define show_set_output(value)		\ -static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf,	\ -							size_t count)	\ +static ssize_t set_output##value(struct device *dev,			\ +					struct device_attribute *attr,	\ +					const char *buf, size_t count)	\  {									\ -	struct usb_interface *intf = to_usb_interface(dev);		\ -	struct interfacekit *kit = usb_get_intfdata(intf);		\ +	struct interfacekit *kit = dev_get_drvdata(dev);		\  	int enabled;							\  	int retval;							\  									\ @@ -391,10 +396,11 @@ static ssize_t set_output##value(struct device *dev, struct device_attribute *at  	return retval ? retval : count;					\  }									\  									\ -static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf)	\ +static ssize_t show_output##value(struct device *dev, 			\ +					struct device_attribute *attr,	\ +					char *buf)			\  {									\ -	struct usb_interface *intf = to_usb_interface(dev);		\ -	struct interfacekit *kit = usb_get_intfdata(intf);		\ +	struct interfacekit *kit = dev_get_drvdata(dev);		\  									\  	return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\  }									\ @@ -420,8 +426,7 @@ show_set_output(16);  #define show_input(value)	\  static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf)	\  {									\ -	struct usb_interface *intf = to_usb_interface(dev);		\ -	struct interfacekit *kit = usb_get_intfdata(intf);		\ +	struct interfacekit *kit = dev_get_drvdata(dev);		\  									\  	return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]);	\  }									\ @@ -445,10 +450,11 @@ show_input(15);  show_input(16);  #define show_sensor(value)	\ -static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf)	\ +static ssize_t show_sensor##value(struct device *dev,			\ +					struct device_attribute *attr,	\ +					char *buf)			\  {									\ -	struct usb_interface *intf = to_usb_interface(dev);		\ -	struct interfacekit *kit = usb_get_intfdata(intf);		\ +	struct interfacekit *kit = dev_get_drvdata(dev);		\  									\  	return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]);	\  }									\ @@ -471,6 +477,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic  	struct interfacekit *kit;  	struct driver_interfacekit *ifkit;  	int pipe, maxp, rc = -ENOMEM; +	int bit, value;  	ifkit = (struct driver_interfacekit *)id->driver_info;  	if (!ifkit) @@ -493,6 +500,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic  	if (!kit)  		goto out; +	kit->dev_no = -1;  	kit->ifkit = ifkit;  	kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma);  	if (!kit->data) @@ -513,73 +521,88 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic  	usb_set_intfdata(intf, kit); +        do { +                bit = find_first_zero_bit(&device_no, sizeof(device_no)); +                value = test_and_set_bit(bit, &device_no); +        } while(value); +        kit->dev_no = bit; + +        kit->dev = device_create(phidget_class, &kit->udev->dev, 0, +               		"interfacekit%d", kit->dev_no); +        if (IS_ERR(kit->dev)) { +                rc = PTR_ERR(kit->dev); +                kit->dev = NULL; +                goto out; +        } +	dev_set_drvdata(kit->dev, kit); +  	if (usb_submit_urb(kit->irq, GFP_KERNEL)) {  		rc = -EIO;  		goto out;  	}  	if (ifkit->outputs >= 4) { -		device_create_file(&intf->dev, &dev_attr_output1); -		device_create_file(&intf->dev, &dev_attr_output2); -		device_create_file(&intf->dev, &dev_attr_output3); -		device_create_file(&intf->dev, &dev_attr_output4); +		device_create_file(kit->dev, &dev_attr_output1); +		device_create_file(kit->dev, &dev_attr_output2); +		device_create_file(kit->dev, &dev_attr_output3); +		device_create_file(kit->dev, &dev_attr_output4);  	}  	if (ifkit->outputs >= 8) { -		device_create_file(&intf->dev, &dev_attr_output5); -		device_create_file(&intf->dev, &dev_attr_output6); -		device_create_file(&intf->dev, &dev_attr_output7); -		device_create_file(&intf->dev, &dev_attr_output8); +		device_create_file(kit->dev, &dev_attr_output5); +		device_create_file(kit->dev, &dev_attr_output6); +		device_create_file(kit->dev, &dev_attr_output7); +		device_create_file(kit->dev, &dev_attr_output8);  	}   	if (ifkit->outputs == 16) { -		device_create_file(&intf->dev, &dev_attr_output9); -		device_create_file(&intf->dev, &dev_attr_output10); -		device_create_file(&intf->dev, &dev_attr_output11); -		device_create_file(&intf->dev, &dev_attr_output12); -		device_create_file(&intf->dev, &dev_attr_output13); -		device_create_file(&intf->dev, &dev_attr_output14); -		device_create_file(&intf->dev, &dev_attr_output15); -		device_create_file(&intf->dev, &dev_attr_output16); +		device_create_file(kit->dev, &dev_attr_output9); +		device_create_file(kit->dev, &dev_attr_output10); +		device_create_file(kit->dev, &dev_attr_output11); +		device_create_file(kit->dev, &dev_attr_output12); +		device_create_file(kit->dev, &dev_attr_output13); +		device_create_file(kit->dev, &dev_attr_output14); +		device_create_file(kit->dev, &dev_attr_output15); +		device_create_file(kit->dev, &dev_attr_output16);  	}  	if (ifkit->inputs >= 4) { -		device_create_file(&intf->dev, &dev_attr_input1); -		device_create_file(&intf->dev, &dev_attr_input2); -		device_create_file(&intf->dev, &dev_attr_input3); -		device_create_file(&intf->dev, &dev_attr_input4); +		device_create_file(kit->dev, &dev_attr_input1); +		device_create_file(kit->dev, &dev_attr_input2); +		device_create_file(kit->dev, &dev_attr_input3); +		device_create_file(kit->dev, &dev_attr_input4);  	}  	if (ifkit->inputs >= 8) { -		device_create_file(&intf->dev, &dev_attr_input5); -		device_create_file(&intf->dev, &dev_attr_input6); -		device_create_file(&intf->dev, &dev_attr_input7); -		device_create_file(&intf->dev, &dev_attr_input8); +		device_create_file(kit->dev, &dev_attr_input5); +		device_create_file(kit->dev, &dev_attr_input6); +		device_create_file(kit->dev, &dev_attr_input7); +		device_create_file(kit->dev, &dev_attr_input8);  	}  	if (ifkit->inputs == 16) { -		device_create_file(&intf->dev, &dev_attr_input9); -		device_create_file(&intf->dev, &dev_attr_input10); -		device_create_file(&intf->dev, &dev_attr_input11); -		device_create_file(&intf->dev, &dev_attr_input12); -		device_create_file(&intf->dev, &dev_attr_input13); -		device_create_file(&intf->dev, &dev_attr_input14); -		device_create_file(&intf->dev, &dev_attr_input15); -		device_create_file(&intf->dev, &dev_attr_input16); +		device_create_file(kit->dev, &dev_attr_input9); +		device_create_file(kit->dev, &dev_attr_input10); +		device_create_file(kit->dev, &dev_attr_input11); +		device_create_file(kit->dev, &dev_attr_input12); +		device_create_file(kit->dev, &dev_attr_input13); +		device_create_file(kit->dev, &dev_attr_input14); +		device_create_file(kit->dev, &dev_attr_input15); +		device_create_file(kit->dev, &dev_attr_input16);  	}  	if (ifkit->sensors >= 4) { -		device_create_file(&intf->dev, &dev_attr_sensor1); -		device_create_file(&intf->dev, &dev_attr_sensor2); -		device_create_file(&intf->dev, &dev_attr_sensor3); -		device_create_file(&intf->dev, &dev_attr_sensor4); +		device_create_file(kit->dev, &dev_attr_sensor1); +		device_create_file(kit->dev, &dev_attr_sensor2); +		device_create_file(kit->dev, &dev_attr_sensor3); +		device_create_file(kit->dev, &dev_attr_sensor4);  	}  	if (ifkit->sensors >= 7) { -		device_create_file(&intf->dev, &dev_attr_sensor5); -		device_create_file(&intf->dev, &dev_attr_sensor6); -		device_create_file(&intf->dev, &dev_attr_sensor7); +		device_create_file(kit->dev, &dev_attr_sensor5); +		device_create_file(kit->dev, &dev_attr_sensor6); +		device_create_file(kit->dev, &dev_attr_sensor7);  	}  	if (ifkit->sensors == 8) -		device_create_file(&intf->dev, &dev_attr_sensor8); +		device_create_file(kit->dev, &dev_attr_sensor8);  	if (ifkit->has_lcd) -		device_create_file(&intf->dev, &dev_attr_lcd); +		device_create_file(kit->dev, &dev_attr_lcd);  	dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n",  			ifkit->sensors, ifkit->inputs, ifkit->outputs); @@ -592,6 +615,11 @@ out:  			usb_free_urb(kit->irq);  		if (kit->data)  			usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); +		if (kit->dev) +			device_unregister(kit->dev); +		if (kit->dev_no >= 0) +			clear_bit(kit->dev_no, &device_no); +  		kfree(kit);  	} @@ -614,72 +642,76 @@ static void interfacekit_disconnect(struct usb_interface *interface)  	cancel_delayed_work(&kit->do_notify);  	if (kit->ifkit->outputs >= 4) { -		device_remove_file(&interface->dev, &dev_attr_output1); -		device_remove_file(&interface->dev, &dev_attr_output2); -		device_remove_file(&interface->dev, &dev_attr_output3); -		device_remove_file(&interface->dev, &dev_attr_output4); +		device_remove_file(kit->dev, &dev_attr_output1); +		device_remove_file(kit->dev, &dev_attr_output2); +		device_remove_file(kit->dev, &dev_attr_output3); +		device_remove_file(kit->dev, &dev_attr_output4);  	}  	if (kit->ifkit->outputs >= 8) { -		device_remove_file(&interface->dev, &dev_attr_output5); -		device_remove_file(&interface->dev, &dev_attr_output6); -		device_remove_file(&interface->dev, &dev_attr_output7); -		device_remove_file(&interface->dev, &dev_attr_output8); +		device_remove_file(kit->dev, &dev_attr_output5); +		device_remove_file(kit->dev, &dev_attr_output6); +		device_remove_file(kit->dev, &dev_attr_output7); +		device_remove_file(kit->dev, &dev_attr_output8);  	}  	if (kit->ifkit->outputs == 16) { -		device_remove_file(&interface->dev, &dev_attr_output9); -		device_remove_file(&interface->dev, &dev_attr_output10); -		device_remove_file(&interface->dev, &dev_attr_output11); -		device_remove_file(&interface->dev, &dev_attr_output12); -		device_remove_file(&interface->dev, &dev_attr_output13); -		device_remove_file(&interface->dev, &dev_attr_output14); -		device_remove_file(&interface->dev, &dev_attr_output15); -		device_remove_file(&interface->dev, &dev_attr_output16); +		device_remove_file(kit->dev, &dev_attr_output9); +		device_remove_file(kit->dev, &dev_attr_output10); +		device_remove_file(kit->dev, &dev_attr_output11); +		device_remove_file(kit->dev, &dev_attr_output12); +		device_remove_file(kit->dev, &dev_attr_output13); +		device_remove_file(kit->dev, &dev_attr_output14); +		device_remove_file(kit->dev, &dev_attr_output15); +		device_remove_file(kit->dev, &dev_attr_output16);  	}  	if (kit->ifkit->inputs >= 4) { -		device_remove_file(&interface->dev, &dev_attr_input1); -		device_remove_file(&interface->dev, &dev_attr_input2); -		device_remove_file(&interface->dev, &dev_attr_input3); -		device_remove_file(&interface->dev, &dev_attr_input4); +		device_remove_file(kit->dev, &dev_attr_input1); +		device_remove_file(kit->dev, &dev_attr_input2); +		device_remove_file(kit->dev, &dev_attr_input3); +		device_remove_file(kit->dev, &dev_attr_input4);  	}  	if (kit->ifkit->inputs >= 8) { -		device_remove_file(&interface->dev, &dev_attr_input5); -		device_remove_file(&interface->dev, &dev_attr_input6); -		device_remove_file(&interface->dev, &dev_attr_input7); -		device_remove_file(&interface->dev, &dev_attr_input8); +		device_remove_file(kit->dev, &dev_attr_input5); +		device_remove_file(kit->dev, &dev_attr_input6); +		device_remove_file(kit->dev, &dev_attr_input7); +		device_remove_file(kit->dev, &dev_attr_input8);  	}  	if (kit->ifkit->inputs == 16) { -		device_remove_file(&interface->dev, &dev_attr_input9); -		device_remove_file(&interface->dev, &dev_attr_input10); -		device_remove_file(&interface->dev, &dev_attr_input11); -		device_remove_file(&interface->dev, &dev_attr_input12); -		device_remove_file(&interface->dev, &dev_attr_input13); -		device_remove_file(&interface->dev, &dev_attr_input14); -		device_remove_file(&interface->dev, &dev_attr_input15); -		device_remove_file(&interface->dev, &dev_attr_input16); +		device_remove_file(kit->dev, &dev_attr_input9); +		device_remove_file(kit->dev, &dev_attr_input10); +		device_remove_file(kit->dev, &dev_attr_input11); +		device_remove_file(kit->dev, &dev_attr_input12); +		device_remove_file(kit->dev, &dev_attr_input13); +		device_remove_file(kit->dev, &dev_attr_input14); +		device_remove_file(kit->dev, &dev_attr_input15); +		device_remove_file(kit->dev, &dev_attr_input16);  	}  	if (kit->ifkit->sensors >= 4) { -		device_remove_file(&interface->dev, &dev_attr_sensor1); -		device_remove_file(&interface->dev, &dev_attr_sensor2); -		device_remove_file(&interface->dev, &dev_attr_sensor3); -		device_remove_file(&interface->dev, &dev_attr_sensor4); +		device_remove_file(kit->dev, &dev_attr_sensor1); +		device_remove_file(kit->dev, &dev_attr_sensor2); +		device_remove_file(kit->dev, &dev_attr_sensor3); +		device_remove_file(kit->dev, &dev_attr_sensor4);  	}  	if (kit->ifkit->sensors >= 7) { -		device_remove_file(&interface->dev, &dev_attr_sensor5); -		device_remove_file(&interface->dev, &dev_attr_sensor6); -		device_remove_file(&interface->dev, &dev_attr_sensor7); +		device_remove_file(kit->dev, &dev_attr_sensor5); +		device_remove_file(kit->dev, &dev_attr_sensor6); +		device_remove_file(kit->dev, &dev_attr_sensor7);  	}  	if (kit->ifkit->sensors == 8) -		device_remove_file(&interface->dev, &dev_attr_sensor8); +		device_remove_file(kit->dev, &dev_attr_sensor8);  	if (kit->ifkit->has_lcd) -		device_remove_file(&interface->dev, &dev_attr_lcd); +		device_remove_file(kit->dev, &dev_attr_lcd); + +	device_unregister(kit->dev);  	dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n",  		kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs);  	usb_put_dev(kit->udev); +	clear_bit(kit->dev_no, &device_no); +  	kfree(kit);  } diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c index 2972dc2eb27..d9ac7f97f8c 100644 --- a/drivers/usb/misc/phidgetmotorcontrol.c +++ b/drivers/usb/misc/phidgetmotorcontrol.c @@ -15,6 +15,8 @@  #include <linux/module.h>  #include <linux/usb.h> +#include "phidget.h" +  #define DRIVER_AUTHOR "Sean Young <sean@mess.org>"  #define DRIVER_DESC "USB PhidgetMotorControl Driver" @@ -23,9 +25,13 @@  #define URB_INT_SIZE			8 +static unsigned long device_no; +  struct motorcontrol {  	struct usb_device *udev;  	struct usb_interface *intf; +	struct device *dev; +	int dev_no;  	u8 inputs[4];  	s8 desired_speed[2];  	s8 speed[2]; @@ -162,14 +168,14 @@ static void do_notify(void *data)  	for (i=0; i<4; i++) {  		if (test_and_clear_bit(i, &mc->input_events)) {  			sprintf(sysfs_file, "input%d", i); -			sysfs_notify(&mc->intf->dev.kobj, NULL, sysfs_file); +			sysfs_notify(&mc->dev->kobj, NULL, sysfs_file);  		}  	}  	for (i=0; i<2; i++) {  		if (test_and_clear_bit(i, &mc->speed_events)) {  			sprintf(sysfs_file, "speed%d", i); -			sysfs_notify(&mc->intf->dev.kobj, NULL, sysfs_file); +			sysfs_notify(&mc->dev->kobj, NULL, sysfs_file);  		}  	} @@ -181,11 +187,11 @@ static void do_notify(void *data)  }  #define show_set_speed(value)		\ -static ssize_t set_speed##value(struct device *dev, 			\ -	struct device_attribute *attr, const char *buf,	size_t count)	\ +static ssize_t set_speed##value(struct device *dev,			\ +					struct device_attribute *attr,	\ +					const char *buf, size_t count)	\  {									\ -	struct usb_interface *intf = to_usb_interface(dev);		\ -	struct motorcontrol *mc = usb_get_intfdata(intf);		\ +	struct motorcontrol *mc = dev_get_drvdata(dev);			\  	int speed;							\  	int retval;							\  									\ @@ -202,11 +208,11 @@ static ssize_t set_speed##value(struct device *dev, 			\  	return retval ? retval : count;					\  }									\  									\ -static ssize_t show_speed##value(struct device *dev, 			\ -			struct device_attribute *attr, char *buf)	\ +static ssize_t show_speed##value(struct device *dev,			\ +					struct device_attribute *attr,	\ +					char *buf)			\  {									\ -	struct usb_interface *intf = to_usb_interface(dev);		\ -	struct motorcontrol *mc = usb_get_intfdata(intf);		\ +	struct motorcontrol *mc = dev_get_drvdata(dev);			\  									\  	return sprintf(buf, "%d\n", mc->speed[value]);			\  }									\ @@ -217,10 +223,10 @@ show_set_speed(1);  #define show_set_acceleration(value)		\  static ssize_t set_acceleration##value(struct device *dev, 		\ -	struct device_attribute *attr, const char *buf,	size_t count)	\ +					struct device_attribute *attr,	\ +					const char *buf, size_t count)	\  {									\ -	struct usb_interface *intf = to_usb_interface(dev);		\ -	struct motorcontrol *mc = usb_get_intfdata(intf);		\ +	struct motorcontrol *mc = dev_get_drvdata(dev);			\  	int acceleration;						\  	int retval;							\  									\ @@ -237,11 +243,11 @@ static ssize_t set_acceleration##value(struct device *dev, 		\  	return retval ? retval : count;					\  }									\  									\ -static ssize_t show_acceleration##value(struct device *dev, 		\ -			struct device_attribute *attr, char *buf)	\ +static ssize_t show_acceleration##value(struct device *dev,	 	\ +					struct device_attribute *attr,	\ +							char *buf)	\  {									\ -	struct usb_interface *intf = to_usb_interface(dev);		\ -	struct motorcontrol *mc = usb_get_intfdata(intf);		\ +	struct motorcontrol *mc = dev_get_drvdata(dev);			\  									\  	return sprintf(buf, "%d\n", mc->acceleration[value]);		\  }									\ @@ -251,11 +257,11 @@ show_set_acceleration(0);  show_set_acceleration(1);  #define show_current(value)	\ -static ssize_t show_current##value(struct device *dev, 			\ -			struct device_attribute *attr, char *buf)	\ +static ssize_t show_current##value(struct device *dev,			\ +					struct device_attribute *attr,	\ +					char *buf)			\  {									\ -	struct usb_interface *intf = to_usb_interface(dev);		\ -	struct motorcontrol *mc = usb_get_intfdata(intf);		\ +	struct motorcontrol *mc = dev_get_drvdata(dev);			\  									\  	return sprintf(buf, "%dmA\n", (int)mc->_current[value]);	\  }									\ @@ -265,11 +271,11 @@ show_current(0);  show_current(1);  #define show_input(value)	\ -static ssize_t show_input##value(struct device *dev, 			\ -			struct device_attribute *attr, char *buf)	\ +static ssize_t show_input##value(struct device *dev,			\ +					struct device_attribute *attr,	\ +					char *buf)			\  {									\ -	struct usb_interface *intf = to_usb_interface(dev);		\ -	struct motorcontrol *mc = usb_get_intfdata(intf);		\ +	struct motorcontrol *mc = dev_get_drvdata(dev);			\  									\  	return sprintf(buf, "%d\n", (int)mc->inputs[value]);		\  }									\ @@ -287,6 +293,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic  	struct usb_endpoint_descriptor *endpoint;  	struct motorcontrol *mc;  	int pipe, maxp, rc = -ENOMEM; +	int bit, value;  	interface = intf->cur_altsetting;  	if (interface->desc.bNumEndpoints != 1) @@ -306,6 +313,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic  	if (!mc)  		goto out; +	mc->dev_no = -1;  	mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &mc->data_dma);  	if (!mc->data)  		goto out; @@ -326,26 +334,42 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic  	usb_set_intfdata(intf, mc); +	do { +		bit = find_first_zero_bit(&device_no, sizeof(device_no)); +		value = test_and_set_bit(bit, &device_no); +	} while(value); +	mc->dev_no = bit; + +	mc->dev = device_create(phidget_class, &mc->udev->dev, 0, +				"motorcontrol%d", mc->dev_no); +	if (IS_ERR(mc->dev)) { +		rc = PTR_ERR(mc->dev); +		mc->dev = NULL; +		goto out; +	} + +	dev_set_drvdata(mc->dev, mc); +  	if (usb_submit_urb(mc->irq, GFP_KERNEL)) {  		rc = -EIO;  		goto out;  	} -	device_create_file(&intf->dev, &dev_attr_input0); -	device_create_file(&intf->dev, &dev_attr_input1); -	device_create_file(&intf->dev, &dev_attr_input2); -	device_create_file(&intf->dev, &dev_attr_input3); +	device_create_file(mc->dev, &dev_attr_input0); +	device_create_file(mc->dev, &dev_attr_input1); +	device_create_file(mc->dev, &dev_attr_input2); +	device_create_file(mc->dev, &dev_attr_input3); -	device_create_file(&intf->dev, &dev_attr_speed0); -	device_create_file(&intf->dev, &dev_attr_speed1); +	device_create_file(mc->dev, &dev_attr_speed0); +	device_create_file(mc->dev, &dev_attr_speed1); -	device_create_file(&intf->dev, &dev_attr_acceleration0); -	device_create_file(&intf->dev, &dev_attr_acceleration1); +	device_create_file(mc->dev, &dev_attr_acceleration0); +	device_create_file(mc->dev, &dev_attr_acceleration1); -	device_create_file(&intf->dev, &dev_attr_current0); -	device_create_file(&intf->dev, &dev_attr_current1); +	device_create_file(mc->dev, &dev_attr_current0); +	device_create_file(mc->dev, &dev_attr_current1); -	dev_info(&intf->dev, "USB Phidget MotorControl attached\n"); +	dev_info(&intf->dev, "USB PhidgetMotorControl attached\n");  	return 0; @@ -355,6 +379,11 @@ out:  			usb_free_urb(mc->irq);  		if (mc->data)  			usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma); +		if (mc->dev) +			device_unregister(mc->dev); +		if (mc->dev_no >= 0) +			clear_bit(mc->dev_no, &device_no); +  		kfree(mc);  	} @@ -376,24 +405,27 @@ static void motorcontrol_disconnect(struct usb_interface *interface)  	cancel_delayed_work(&mc->do_notify); -	device_remove_file(&interface->dev, &dev_attr_input0); -	device_remove_file(&interface->dev, &dev_attr_input1); -	device_remove_file(&interface->dev, &dev_attr_input2); -	device_remove_file(&interface->dev, &dev_attr_input3); +	device_remove_file(mc->dev, &dev_attr_input0); +	device_remove_file(mc->dev, &dev_attr_input1); +	device_remove_file(mc->dev, &dev_attr_input2); +	device_remove_file(mc->dev, &dev_attr_input3); -	device_remove_file(&interface->dev, &dev_attr_speed0); -	device_remove_file(&interface->dev, &dev_attr_speed1); +	device_remove_file(mc->dev, &dev_attr_speed0); +	device_remove_file(mc->dev, &dev_attr_speed1); -	device_remove_file(&interface->dev, &dev_attr_acceleration0); -	device_remove_file(&interface->dev, &dev_attr_acceleration1); +	device_remove_file(mc->dev, &dev_attr_acceleration0); +	device_remove_file(mc->dev, &dev_attr_acceleration1); -	device_remove_file(&interface->dev, &dev_attr_current0); -	device_remove_file(&interface->dev, &dev_attr_current1); +	device_remove_file(mc->dev, &dev_attr_current0); +	device_remove_file(mc->dev, &dev_attr_current1); -	dev_info(&interface->dev, "USB Phidget MotorControl disconnected\n"); +	device_unregister(mc->dev);  	usb_put_dev(mc->udev); +	clear_bit(mc->dev_no, &device_no);  	kfree(mc); + +	dev_info(&interface->dev, "USB PhidgetMotorControl detached\n");  }  static struct usb_driver motorcontrol_driver = { diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c index c0df79c9653..66be9513fd6 100644 --- a/drivers/usb/misc/phidgetservo.c +++ b/drivers/usb/misc/phidgetservo.c @@ -15,14 +15,6 @@   *   * CAUTION: Generally you should use 0 < degrees < 180 as anything else   * is probably beyond the range of your servo and may damage it. - * - * Jun 16, 2004: Sean Young <sean@mess.org> - *  - cleanups - *  - was using memory after kfree() - * Aug 8, 2004: Sean Young <sean@mess.org> - *  - set the highest angle as high as the hardware allows, there are  - *    some odd servos out there - *   */  #include <linux/kernel.h> @@ -32,6 +24,8 @@  #include <linux/module.h>  #include <linux/usb.h> +#include "phidget.h" +  #define DRIVER_AUTHOR "Sean Young <sean@mess.org>"  #define DRIVER_DESC "USB PhidgetServo Driver" @@ -70,8 +64,12 @@ static struct usb_device_id id_table[] = {  MODULE_DEVICE_TABLE(usb, id_table); +static int unsigned long device_no; +  struct phidget_servo {  	struct usb_device *udev; +	struct device *dev; +	int dev_no;  	ulong type;  	int pulse[4];  	int degrees[4]; @@ -203,16 +201,16 @@ change_position_v20(struct phidget_servo *servo, int servo_no, int degrees,  }  #define show_set(value)	\ -static ssize_t set_servo##value (struct device *dev, struct device_attribute *attr,			\ +static ssize_t set_servo##value (struct device *dev, 			\ +					struct device_attribute *attr,	\  					const char *buf, size_t count)	\  {									\  	int degrees, minutes, retval;					\ -	struct usb_interface *intf = to_usb_interface (dev);		\ -	struct phidget_servo *servo = usb_get_intfdata (intf);		\ +	struct phidget_servo *servo = dev_get_drvdata(dev);		\  									\  	minutes = 0;							\  	/* must at least convert degrees */				\ -	if (sscanf (buf, "%d.%d", °rees, &minutes) < 1) {		\ +	if (sscanf(buf, "%d.%d", °rees, &minutes) < 1) {		\  		return -EINVAL;						\  	}								\  									\ @@ -220,21 +218,22 @@ static ssize_t set_servo##value (struct device *dev, struct device_attribute *at  		return -EINVAL;						\  									\  	if (servo->type & SERVO_VERSION_30)				\ -		retval = change_position_v30 (servo, value, degrees, 	\ +		retval = change_position_v30(servo, value, degrees, 	\  							minutes);	\  	else 								\ -		retval = change_position_v20 (servo, value, degrees, 	\ +		retval = change_position_v20(servo, value, degrees, 	\  							minutes);	\  									\  	return retval < 0 ? retval : count;				\  }									\  									\ -static ssize_t show_servo##value (struct device *dev, struct device_attribute *attr, char *buf) 	\ +static ssize_t show_servo##value (struct device *dev,			\ +					struct device_attribute *attr,	\ +					char *buf) 			\  {									\ -	struct usb_interface *intf = to_usb_interface (dev);		\ -	struct phidget_servo *servo = usb_get_intfdata (intf);		\ +	struct phidget_servo *servo = dev_get_drvdata(dev);		\  									\ -	return sprintf (buf, "%d.%02d\n", servo->degrees[value],	\ +	return sprintf(buf, "%d.%02d\n", servo->degrees[value],		\  				servo->minutes[value]);			\  }									\  static DEVICE_ATTR(servo##value, S_IWUGO | S_IRUGO,			\ @@ -250,6 +249,7 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id)  {  	struct usb_device *udev = interface_to_usbdev(interface);  	struct phidget_servo *dev; +	int bit, value;  	dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL);  	if (dev == NULL) { @@ -261,18 +261,33 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id)  	dev->type = id->driver_info;  	usb_set_intfdata(interface, dev); -	device_create_file(&interface->dev, &dev_attr_servo0); +        do { +                bit = find_first_zero_bit(&device_no, sizeof(device_no)); +                value = test_and_set_bit(bit, &device_no); +        } while(value); +	dev->dev_no = bit; + +	dev->dev = device_create(phidget_class, &dev->udev->dev, 0, +				 "servo%d", dev->dev_no); +	if (IS_ERR(dev->dev)) { +		int rc = PTR_ERR(dev->dev); +		clear_bit(dev->dev_no, &device_no); +		kfree(dev); +		return rc; +	} + +	device_create_file(dev->dev, &dev_attr_servo0);  	if (dev->type & SERVO_COUNT_QUAD) { -		device_create_file(&interface->dev, &dev_attr_servo1); -		device_create_file(&interface->dev, &dev_attr_servo2); -		device_create_file(&interface->dev, &dev_attr_servo3); +		device_create_file(dev->dev, &dev_attr_servo1); +		device_create_file(dev->dev, &dev_attr_servo2); +		device_create_file(dev->dev, &dev_attr_servo3);  	}  	dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n",  		dev->type & SERVO_COUNT_QUAD ? 4 : 1,  		dev->type & SERVO_VERSION_30 ? 3 : 2); -	if(!(dev->type & SERVO_VERSION_30)) +	if (!(dev->type & SERVO_VERSION_30))  		dev_info(&interface->dev,  			 "WARNING: v2.0 not tested! Please report if it works.\n"); @@ -287,19 +302,21 @@ servo_disconnect(struct usb_interface *interface)  	dev = usb_get_intfdata(interface);  	usb_set_intfdata(interface, NULL); -	device_remove_file(&interface->dev, &dev_attr_servo0); +	device_remove_file(dev->dev, &dev_attr_servo0);  	if (dev->type & SERVO_COUNT_QUAD) { -		device_remove_file(&interface->dev, &dev_attr_servo1); -		device_remove_file(&interface->dev, &dev_attr_servo2); -		device_remove_file(&interface->dev, &dev_attr_servo3); +		device_remove_file(dev->dev, &dev_attr_servo1); +		device_remove_file(dev->dev, &dev_attr_servo2); +		device_remove_file(dev->dev, &dev_attr_servo3);  	} +	device_unregister(dev->dev);  	usb_put_dev(dev->udev);  	dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n",  		dev->type & SERVO_COUNT_QUAD ? 4 : 1,  		dev->type & SERVO_VERSION_30 ? 3 : 2); +	clear_bit(dev->dev_no, &device_no);  	kfree(dev);  }  |