Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6

This commit is contained in:
Linus Torvalds 2005-10-28 13:09:47 -07:00
commit 84860bf064
244 changed files with 5575 additions and 5209 deletions

View file

@ -65,7 +65,7 @@ o isdn4k-utils 3.1pre1 # isdnctrl 2>&1|grep version
o nfs-utils 1.0.5 # showmount --version o nfs-utils 1.0.5 # showmount --version
o procps 3.2.0 # ps --version o procps 3.2.0 # ps --version
o oprofile 0.9 # oprofiled --version o oprofile 0.9 # oprofiled --version
o udev 058 # udevinfo -V o udev 071 # udevinfo -V
Kernel compilation Kernel compilation
================== ==================

View file

@ -345,7 +345,6 @@ if (!retval) {
<programlisting> <programlisting>
static inline void skel_delete (struct usb_skel *dev) static inline void skel_delete (struct usb_skel *dev)
{ {
if (dev->bulk_in_buffer != NULL)
kfree (dev->bulk_in_buffer); kfree (dev->bulk_in_buffer);
if (dev->bulk_out_buffer != NULL) if (dev->bulk_out_buffer != NULL)
usb_buffer_free (dev->udev, dev->bulk_out_size, usb_buffer_free (dev->udev, dev->bulk_out_size,

View file

@ -14,8 +14,8 @@ struct device_driver {
int (*probe) (struct device * dev); int (*probe) (struct device * dev);
int (*remove) (struct device * dev); int (*remove) (struct device * dev);
int (*suspend) (struct device * dev, pm_message_t state, u32 level); int (*suspend) (struct device * dev, pm_message_t state);
int (*resume) (struct device * dev, u32 level); int (*resume) (struct device * dev);
}; };
@ -194,69 +194,13 @@ device; i.e. anything in the device's driver_data field.
If the device is still present, it should quiesce the device and place If the device is still present, it should quiesce the device and place
it into a supported low-power state. it into a supported low-power state.
int (*suspend) (struct device * dev, pm_message_t state, u32 level); int (*suspend) (struct device * dev, pm_message_t state);
suspend is called to put the device in a low power state. There are suspend is called to put the device in a low power state.
several stages to successfully suspending a device, which is denoted in
the @level parameter. Breaking the suspend transition into several
stages affords the platform flexibility in performing device power
management based on the requirements of the system and the
user-defined policy.
SUSPEND_NOTIFY notifies the device that a suspend transition is about int (*resume) (struct device * dev);
to happen. This happens on system power state transitions to verify
that all devices can successfully suspend.
A driver may choose to fail on this call, which should cause the Resume is used to bring a device back from a low power state.
entire suspend transition to fail. A driver should fail only if it
knows that the device will not be able to be resumed properly when the
system wakes up again. It could also fail if it somehow determines it
is in the middle of an operation too important to stop.
SUSPEND_DISABLE tells the device to stop I/O transactions. When it
stops transactions, or what it should do with unfinished transactions
is a policy of the driver. After this call, the driver should not
accept any other I/O requests.
SUSPEND_SAVE_STATE tells the device to save the context of the
hardware. This includes any bus-specific hardware state and
device-specific hardware state. A pointer to this saved state can be
stored in the device's saved_state field.
SUSPEND_POWER_DOWN tells the driver to place the device in the low
power state requested.
Whether suspend is called with a given level is a policy of the
platform. Some levels may be omitted; drivers must not assume the
reception of any level. However, all levels must be called in the
order above; i.e. notification will always come before disabling;
disabling the device will come before suspending the device.
All calls are made with interrupts enabled, except for the
SUSPEND_POWER_DOWN level.
int (*resume) (struct device * dev, u32 level);
Resume is used to bring a device back from a low power state. Like the
suspend transition, it happens in several stages.
RESUME_POWER_ON tells the driver to set the power state to the state
before the suspend call (The device could have already been in a low
power state before the suspend call to put in a lower power state).
RESUME_RESTORE_STATE tells the driver to restore the state saved by
the SUSPEND_SAVE_STATE suspend call.
RESUME_ENABLE tells the driver to start accepting I/O transactions
again. Depending on driver policy, the device may already have pending
I/O requests.
RESUME_POWER_ON is called with interrupts disabled. The other resume
levels are called with interrupts enabled.
As with the various suspend stages, the driver must not assume that
any other resume calls have been or will be made. Each call should be
self-contained and not dependent on any external state.
Attributes Attributes

View file

@ -350,7 +350,7 @@ When a driver is registered, the bus's list of devices is iterated
over. bus->match() is called for each device that is not already over. bus->match() is called for each device that is not already
claimed by a driver. claimed by a driver.
When a device is successfully bound to a device, device->driver is When a device is successfully bound to a driver, device->driver is
set, the device is added to a per-driver list of devices, and a set, the device is added to a per-driver list of devices, and a
symlink is created in the driver's sysfs directory that points to the symlink is created in the driver's sysfs directory that points to the
device's physical directory: device's physical directory:

View file

@ -550,15 +550,12 @@ struct locomo_save_data {
u16 LCM_SPIMD; u16 LCM_SPIMD;
}; };
static int locomo_suspend(struct device *dev, pm_message_t state, u32 level) static int locomo_suspend(struct device *dev, pm_message_t state)
{ {
struct locomo *lchip = dev_get_drvdata(dev); struct locomo *lchip = dev_get_drvdata(dev);
struct locomo_save_data *save; struct locomo_save_data *save;
unsigned long flags; unsigned long flags;
if (level != SUSPEND_DISABLE)
return 0;
save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL); save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL);
if (!save) if (!save)
return -ENOMEM; return -ENOMEM;
@ -597,16 +594,13 @@ static int locomo_suspend(struct device *dev, pm_message_t state, u32 level)
return 0; return 0;
} }
static int locomo_resume(struct device *dev, u32 level) static int locomo_resume(struct device *dev)
{ {
struct locomo *lchip = dev_get_drvdata(dev); struct locomo *lchip = dev_get_drvdata(dev);
struct locomo_save_data *save; struct locomo_save_data *save;
unsigned long r; unsigned long r;
unsigned long flags; unsigned long flags;
if (level != RESUME_ENABLE)
return 0;
save = (struct locomo_save_data *) dev->power.saved_state; save = (struct locomo_save_data *) dev->power.saved_state;
if (!save) if (!save)
return 0; return 0;

View file

@ -801,7 +801,7 @@ struct sa1111_save_data {
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int sa1111_suspend(struct device *dev, pm_message_t state, u32 level) static int sa1111_suspend(struct device *dev, pm_message_t state)
{ {
struct sa1111 *sachip = dev_get_drvdata(dev); struct sa1111 *sachip = dev_get_drvdata(dev);
struct sa1111_save_data *save; struct sa1111_save_data *save;
@ -809,9 +809,6 @@ static int sa1111_suspend(struct device *dev, pm_message_t state, u32 level)
unsigned int val; unsigned int val;
void __iomem *base; void __iomem *base;
if (level != SUSPEND_DISABLE)
return 0;
save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL); save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
if (!save) if (!save)
return -ENOMEM; return -ENOMEM;
@ -856,23 +853,19 @@ static int sa1111_suspend(struct device *dev, pm_message_t state, u32 level)
/* /*
* sa1111_resume - Restore the SA1111 device state. * sa1111_resume - Restore the SA1111 device state.
* @dev: device to restore * @dev: device to restore
* @level: resume level
* *
* Restore the general state of the SA1111; clock control and * Restore the general state of the SA1111; clock control and
* interrupt controller. Other parts of the SA1111 must be * interrupt controller. Other parts of the SA1111 must be
* restored by their respective drivers, and must be called * restored by their respective drivers, and must be called
* via LDM after this function. * via LDM after this function.
*/ */
static int sa1111_resume(struct device *dev, u32 level) static int sa1111_resume(struct device *dev)
{ {
struct sa1111 *sachip = dev_get_drvdata(dev); struct sa1111 *sachip = dev_get_drvdata(dev);
struct sa1111_save_data *save; struct sa1111_save_data *save;
unsigned long flags, id; unsigned long flags, id;
void __iomem *base; void __iomem *base;
if (level != RESUME_ENABLE)
return 0;
save = (struct sa1111_save_data *)dev->power.saved_state; save = (struct sa1111_save_data *)dev->power.saved_state;
if (!save) if (!save)
return 0; return 0;

View file

@ -102,26 +102,24 @@ static void check_scoop_reg(struct scoop_dev *sdev)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int scoop_suspend(struct device *dev, pm_message_t state, uint32_t level) static int scoop_suspend(struct device *dev, pm_message_t state)
{ {
if (level == SUSPEND_POWER_DOWN) {
struct scoop_dev *sdev = dev_get_drvdata(dev); struct scoop_dev *sdev = dev_get_drvdata(dev);
check_scoop_reg(sdev); check_scoop_reg(sdev);
sdev->scoop_gpwr = SCOOP_REG(sdev->base, SCOOP_GPWR); sdev->scoop_gpwr = SCOOP_REG(sdev->base, SCOOP_GPWR);
SCOOP_REG(sdev->base, SCOOP_GPWR) = (sdev->scoop_gpwr & ~sdev->suspend_clr) | sdev->suspend_set; SCOOP_REG(sdev->base, SCOOP_GPWR) = (sdev->scoop_gpwr & ~sdev->suspend_clr) | sdev->suspend_set;
}
return 0; return 0;
} }
static int scoop_resume(struct device *dev, uint32_t level) static int scoop_resume(struct device *dev)
{ {
if (level == RESUME_POWER_ON) {
struct scoop_dev *sdev = dev_get_drvdata(dev); struct scoop_dev *sdev = dev_get_drvdata(dev);
check_scoop_reg(sdev); check_scoop_reg(sdev);
SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr; SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr;
}
return 0; return 0;
} }
#else #else

View file

@ -222,24 +222,22 @@ static int corgi_ssp_remove(struct device *dev)
return 0; return 0;
} }
static int corgi_ssp_suspend(struct device *dev, pm_message_t state, u32 level) static int corgi_ssp_suspend(struct device *dev, pm_message_t state)
{ {
if (level == SUSPEND_POWER_DOWN) {
ssp_flush(&corgi_ssp_dev); ssp_flush(&corgi_ssp_dev);
ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state); ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state);
}
return 0; return 0;
} }
static int corgi_ssp_resume(struct device *dev, u32 level) static int corgi_ssp_resume(struct device *dev)
{ {
if (level == RESUME_POWER_ON) {
GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */ GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */
GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/ GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/ GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state); ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
ssp_enable(&corgi_ssp_dev); ssp_enable(&corgi_ssp_dev);
}
return 0; return 0;
} }

View file

@ -178,34 +178,28 @@ static int neponset_probe(struct device *dev)
/* /*
* LDM power management. * LDM power management.
*/ */
static int neponset_suspend(struct device *dev, pm_message_t state, u32 level) static int neponset_suspend(struct device *dev, pm_message_t state)
{ {
/* /*
* Save state. * Save state.
*/ */
if (level == SUSPEND_SAVE_STATE ||
level == SUSPEND_DISABLE ||
level == SUSPEND_POWER_DOWN) {
if (!dev->power.saved_state) if (!dev->power.saved_state)
dev->power.saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL); dev->power.saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL);
if (!dev->power.saved_state) if (!dev->power.saved_state)
return -ENOMEM; return -ENOMEM;
*(unsigned int *)dev->power.saved_state = NCR_0; *(unsigned int *)dev->power.saved_state = NCR_0;
}
return 0; return 0;
} }
static int neponset_resume(struct device *dev, u32 level) static int neponset_resume(struct device *dev)
{ {
if (level == RESUME_RESTORE_STATE || level == RESUME_ENABLE) {
if (dev->power.saved_state) { if (dev->power.saved_state) {
NCR_0 = *(unsigned int *)dev->power.saved_state; NCR_0 = *(unsigned int *)dev->power.saved_state;
kfree(dev->power.saved_state); kfree(dev->power.saved_state);
dev->power.saved_state = NULL; dev->power.saved_state = NULL;
} }
}
return 0; return 0;
} }

View file

@ -163,7 +163,7 @@ static int cpuid_class_device_create(int i)
int err = 0; int err = 0;
struct class_device *class_err; struct class_device *class_err;
class_err = class_device_create(cpuid_class, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i); class_err = class_device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
if (IS_ERR(class_err)) if (IS_ERR(class_err))
err = PTR_ERR(class_err); err = PTR_ERR(class_err);
return err; return err;

View file

@ -246,7 +246,7 @@ static int msr_class_device_create(int i)
int err = 0; int err = 0;
struct class_device *class_err; struct class_device *class_err;
class_err = class_device_create(msr_class, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i); class_err = class_device_create(msr_class, NULL, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
if (IS_ERR(class_err)) if (IS_ERR(class_err))
err = PTR_ERR(class_err); err = PTR_ERR(class_err);
return err; return err;

View file

@ -19,6 +19,8 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/module.h> #include <linux/module.h>
#include "base.h"
/* This is a private structure used to tie the classdev and the /* This is a private structure used to tie the classdev and the
* container .. it should never be visible outside this file */ * container .. it should never be visible outside this file */
struct internal_container { struct internal_container {

View file

@ -1,3 +1,15 @@
/* initialisation functions */
extern int devices_init(void);
extern int buses_init(void);
extern int classes_init(void);
extern int firmware_init(void);
extern int platform_bus_init(void);
extern int system_bus_init(void);
extern int cpu_dev_init(void);
extern int attribute_container_init(void);
extern int bus_add_device(struct device * dev); extern int bus_add_device(struct device * dev);
extern void bus_remove_device(struct device * dev); extern void bus_remove_device(struct device * dev);

View file

@ -99,6 +99,7 @@ struct class * class_get(struct class * cls)
void class_put(struct class * cls) void class_put(struct class * cls)
{ {
if (cls)
subsys_put(&cls->subsys); subsys_put(&cls->subsys);
} }
@ -165,14 +166,25 @@ void class_unregister(struct class * cls)
static void class_create_release(struct class *cls) static void class_create_release(struct class *cls)
{ {
pr_debug("%s called for %s\n", __FUNCTION__, cls->name);
kfree(cls); kfree(cls);
} }
static void class_device_create_release(struct class_device *class_dev) static void class_device_create_release(struct class_device *class_dev)
{ {
pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
kfree(class_dev); kfree(class_dev);
} }
/* needed to allow these devices to have parent class devices */
static int class_device_create_hotplug(struct class_device *class_dev,
char **envp, int num_envp,
char *buffer, int buffer_size)
{
pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
return 0;
}
/** /**
* class_create - create a struct class structure * class_create - create a struct class structure
* @owner: pointer to the module that is to "own" this struct class * @owner: pointer to the module that is to "own" this struct class
@ -301,10 +313,12 @@ static void class_dev_release(struct kobject * kobj)
kfree(cd->devt_attr); kfree(cd->devt_attr);
cd->devt_attr = NULL; cd->devt_attr = NULL;
if (cls->release) if (cd->release)
cd->release(cd);
else if (cls->release)
cls->release(cd); cls->release(cd);
else { else {
printk(KERN_ERR "Device class '%s' does not have a release() function, " printk(KERN_ERR "Class Device '%s' does not have a release() function, "
"it is broken and must be fixed.\n", "it is broken and must be fixed.\n",
cd->class_id); cd->class_id);
WARN_ON(1); WARN_ON(1);
@ -382,14 +396,18 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
buffer = &buffer[length]; buffer = &buffer[length];
buffer_size -= length; buffer_size -= length;
if (class_dev->class->hotplug) { if (class_dev->hotplug) {
/* have the bus specific function add its stuff */ /* have the class device specific function add its stuff */
retval = class_dev->class->hotplug (class_dev, envp, num_envp, retval = class_dev->hotplug(class_dev, envp, num_envp,
buffer, buffer_size); buffer, buffer_size);
if (retval) { if (retval)
pr_debug ("%s - hotplug() returned %d\n", pr_debug("class_dev->hotplug() returned %d\n", retval);
__FUNCTION__, retval); } else if (class_dev->class->hotplug) {
} /* have the class specific function add its stuff */
retval = class_dev->class->hotplug(class_dev, envp, num_envp,
buffer, buffer_size);
if (retval)
pr_debug("class->hotplug() returned %d\n", retval);
} }
return retval; return retval;
@ -442,6 +460,13 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
return print_dev_t(buf, class_dev->devt); return print_dev_t(buf, class_dev->devt);
} }
static ssize_t store_uevent(struct class_device *class_dev,
const char *buf, size_t count)
{
kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
return count;
}
void class_device_initialize(struct class_device *class_dev) void class_device_initialize(struct class_device *class_dev)
{ {
kobj_set_kset_s(class_dev, class_obj_subsys); kobj_set_kset_s(class_dev, class_obj_subsys);
@ -469,34 +494,45 @@ static char *make_class_name(struct class_device *class_dev)
int class_device_add(struct class_device *class_dev) int class_device_add(struct class_device *class_dev)
{ {
struct class * parent = NULL; struct class *parent_class = NULL;
struct class_interface * class_intf; struct class_device *parent_class_dev = NULL;
struct class_interface *class_intf;
char *class_name = NULL; char *class_name = NULL;
int error; int error = -EINVAL;
class_dev = class_device_get(class_dev); class_dev = class_device_get(class_dev);
if (!class_dev) if (!class_dev)
return -EINVAL; return -EINVAL;
if (!strlen(class_dev->class_id)) { if (!strlen(class_dev->class_id))
error = -EINVAL;
goto register_done; goto register_done;
}
parent = class_get(class_dev->class); parent_class = class_get(class_dev->class);
if (!parent_class)
goto register_done;
parent_class_dev = class_device_get(class_dev->parent);
pr_debug("CLASS: registering class device: ID = '%s'\n", pr_debug("CLASS: registering class device: ID = '%s'\n",
class_dev->class_id); class_dev->class_id);
/* first, register with generic layer. */ /* first, register with generic layer. */
kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id); kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
if (parent) if (parent_class_dev)
class_dev->kobj.parent = &parent->subsys.kset.kobj; class_dev->kobj.parent = &parent_class_dev->kobj;
else
class_dev->kobj.parent = &parent_class->subsys.kset.kobj;
if ((error = kobject_add(&class_dev->kobj))) error = kobject_add(&class_dev->kobj);
if (error)
goto register_done; goto register_done;
/* add the needed attributes to this device */ /* add the needed attributes to this device */
class_dev->uevent_attr.attr.name = "uevent";
class_dev->uevent_attr.attr.mode = S_IWUSR;
class_dev->uevent_attr.attr.owner = parent_class->owner;
class_dev->uevent_attr.store = store_uevent;
class_device_create_file(class_dev, &class_dev->uevent_attr);
if (MAJOR(class_dev->devt)) { if (MAJOR(class_dev->devt)) {
struct class_device_attribute *attr; struct class_device_attribute *attr;
attr = kzalloc(sizeof(*attr), GFP_KERNEL); attr = kzalloc(sizeof(*attr), GFP_KERNEL);
@ -505,12 +541,10 @@ int class_device_add(struct class_device *class_dev)
kobject_del(&class_dev->kobj); kobject_del(&class_dev->kobj);
goto register_done; goto register_done;
} }
attr->attr.name = "dev"; attr->attr.name = "dev";
attr->attr.mode = S_IRUGO; attr->attr.mode = S_IRUGO;
attr->attr.owner = parent->owner; attr->attr.owner = parent_class->owner;
attr->show = show_dev; attr->show = show_dev;
attr->store = NULL;
class_device_create_file(class_dev, attr); class_device_create_file(class_dev, attr);
class_dev->devt_attr = attr; class_dev->devt_attr = attr;
} }
@ -524,20 +558,23 @@ int class_device_add(struct class_device *class_dev)
class_name); class_name);
} }
/* notify any interfaces this device is now here */
if (parent) {
down(&parent->sem);
list_add_tail(&class_dev->node, &parent->children);
list_for_each_entry(class_intf, &parent->interfaces, node)
if (class_intf->add)
class_intf->add(class_dev);
up(&parent->sem);
}
kobject_hotplug(&class_dev->kobj, KOBJ_ADD); kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
/* notify any interfaces this device is now here */
if (parent_class) {
down(&parent_class->sem);
list_add_tail(&class_dev->node, &parent_class->children);
list_for_each_entry(class_intf, &parent_class->interfaces, node)
if (class_intf->add)
class_intf->add(class_dev, class_intf);
up(&parent_class->sem);
}
register_done: register_done:
if (error && parent) if (error) {
class_put(parent); class_put(parent_class);
class_device_put(parent_class_dev);
}
class_device_put(class_dev); class_device_put(class_dev);
kfree(class_name); kfree(class_name);
return error; return error;
@ -552,21 +589,28 @@ int class_device_register(struct class_device *class_dev)
/** /**
* class_device_create - creates a class device and registers it with sysfs * class_device_create - creates a class device and registers it with sysfs
* @cs: pointer to the struct class that this device should be registered to. * @cs: pointer to the struct class that this device should be registered to.
* @parent: pointer to the parent struct class_device of this new device, if any.
* @dev: the dev_t for the char device to be added. * @dev: the dev_t for the char device to be added.
* @device: a pointer to a struct device that is assiociated with this class device. * @device: a pointer to a struct device that is assiociated with this class device.
* @fmt: string for the class device's name * @fmt: string for the class device's name
* *
* This function can be used by char device classes. A struct * This function can be used by char device classes. A struct
* class_device will be created in sysfs, registered to the specified * class_device will be created in sysfs, registered to the specified
* class. A "dev" file will be created, showing the dev_t for the * class.
* device. The pointer to the struct class_device will be returned from * A "dev" file will be created, showing the dev_t for the device, if
* the call. Any further sysfs files that might be required can be * the dev_t is not 0,0.
* created using this pointer. * If a pointer to a parent struct class_device is passed in, the newly
* created struct class_device will be a child of that device in sysfs.
* The pointer to the struct class_device will be returned from the
* call. Any further sysfs files that might be required can be created
* using this pointer.
* *
* Note: the struct class passed to this function must have previously * Note: the struct class passed to this function must have previously
* been created with a call to class_create(). * been created with a call to class_create().
*/ */
struct class_device *class_device_create(struct class *cls, dev_t devt, struct class_device *class_device_create(struct class *cls,
struct class_device *parent,
dev_t devt,
struct device *device, char *fmt, ...) struct device *device, char *fmt, ...)
{ {
va_list args; va_list args;
@ -585,6 +629,9 @@ struct class_device *class_device_create(struct class *cls, dev_t devt,
class_dev->devt = devt; class_dev->devt = devt;
class_dev->dev = device; class_dev->dev = device;
class_dev->class = cls; class_dev->class = cls;
class_dev->parent = parent;
class_dev->release = class_device_create_release;
class_dev->hotplug = class_device_create_hotplug;
va_start(args, fmt); va_start(args, fmt);
vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args); vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
@ -602,17 +649,18 @@ error:
void class_device_del(struct class_device *class_dev) void class_device_del(struct class_device *class_dev)
{ {
struct class * parent = class_dev->class; struct class *parent_class = class_dev->class;
struct class_interface * class_intf; struct class_device *parent_device = class_dev->parent;
struct class_interface *class_intf;
char *class_name = NULL; char *class_name = NULL;
if (parent) { if (parent_class) {
down(&parent->sem); down(&parent_class->sem);
list_del_init(&class_dev->node); list_del_init(&class_dev->node);
list_for_each_entry(class_intf, &parent->interfaces, node) list_for_each_entry(class_intf, &parent_class->interfaces, node)
if (class_intf->remove) if (class_intf->remove)
class_intf->remove(class_dev); class_intf->remove(class_dev, class_intf);
up(&parent->sem); up(&parent_class->sem);
} }
if (class_dev->dev) { if (class_dev->dev) {
@ -620,6 +668,7 @@ void class_device_del(struct class_device *class_dev)
sysfs_remove_link(&class_dev->kobj, "device"); sysfs_remove_link(&class_dev->kobj, "device");
sysfs_remove_link(&class_dev->dev->kobj, class_name); sysfs_remove_link(&class_dev->dev->kobj, class_name);
} }
class_device_remove_file(class_dev, &class_dev->uevent_attr);
if (class_dev->devt_attr) if (class_dev->devt_attr)
class_device_remove_file(class_dev, class_dev->devt_attr); class_device_remove_file(class_dev, class_dev->devt_attr);
class_device_remove_attrs(class_dev); class_device_remove_attrs(class_dev);
@ -627,8 +676,8 @@ void class_device_del(struct class_device *class_dev)
kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE); kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
kobject_del(&class_dev->kobj); kobject_del(&class_dev->kobj);
if (parent) class_device_put(parent_device);
class_put(parent); class_put(parent_class);
kfree(class_name); kfree(class_name);
} }
@ -708,6 +757,7 @@ struct class_device * class_device_get(struct class_device *class_dev)
void class_device_put(struct class_device *class_dev) void class_device_put(struct class_device *class_dev)
{ {
if (class_dev)
kobject_put(&class_dev->kobj); kobject_put(&class_dev->kobj);
} }
@ -728,7 +778,7 @@ int class_interface_register(struct class_interface *class_intf)
list_add_tail(&class_intf->node, &parent->interfaces); list_add_tail(&class_intf->node, &parent->interfaces);
if (class_intf->add) { if (class_intf->add) {
list_for_each_entry(class_dev, &parent->children, node) list_for_each_entry(class_dev, &parent->children, node)
class_intf->add(class_dev); class_intf->add(class_dev, class_intf);
} }
up(&parent->sem); up(&parent->sem);
@ -747,7 +797,7 @@ void class_interface_unregister(struct class_interface *class_intf)
list_del_init(&class_intf->node); list_del_init(&class_intf->node);
if (class_intf->remove) { if (class_intf->remove) {
list_for_each_entry(class_dev, &parent->children, node) list_for_each_entry(class_dev, &parent->children, node)
class_intf->remove(class_dev); class_intf->remove(class_dev, class_intf);
} }
up(&parent->sem); up(&parent->sem);

View file

@ -154,6 +154,13 @@ static struct kset_hotplug_ops device_hotplug_ops = {
.hotplug = dev_hotplug, .hotplug = dev_hotplug,
}; };
static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
kobject_hotplug(&dev->kobj, KOBJ_ADD);
return count;
}
/** /**
* device_subsys - structure to be registered with kobject core. * device_subsys - structure to be registered with kobject core.
*/ */
@ -225,6 +232,7 @@ void device_initialize(struct device *dev)
klist_children_put); klist_children_put);
INIT_LIST_HEAD(&dev->dma_pools); INIT_LIST_HEAD(&dev->dma_pools);
init_MUTEX(&dev->sem); init_MUTEX(&dev->sem);
device_init_wakeup(dev, 0);
} }
/** /**
@ -258,6 +266,14 @@ int device_add(struct device *dev)
if ((error = kobject_add(&dev->kobj))) if ((error = kobject_add(&dev->kobj)))
goto Error; goto Error;
dev->uevent_attr.attr.name = "uevent";
dev->uevent_attr.attr.mode = S_IWUSR;
if (dev->driver)
dev->uevent_attr.attr.owner = dev->driver->owner;
dev->uevent_attr.store = store_uevent;
device_create_file(dev, &dev->uevent_attr);
kobject_hotplug(&dev->kobj, KOBJ_ADD); kobject_hotplug(&dev->kobj, KOBJ_ADD);
if ((error = device_pm_add(dev))) if ((error = device_pm_add(dev)))
goto PMError; goto PMError;
@ -349,6 +365,7 @@ void device_del(struct device * dev)
if (parent) if (parent)
klist_del(&dev->knode_parent); klist_del(&dev->knode_parent);
device_remove_file(dev, &dev->uevent_attr);
/* Notify the platform of the removal, in case they /* Notify the platform of the removal, in case they
* need to do anything... * need to do anything...
@ -390,11 +407,11 @@ static struct device * next_device(struct klist_iter * i)
/** /**
* device_for_each_child - device child iterator. * device_for_each_child - device child iterator.
* @dev: parent struct device. * @parent: parent struct device.
* @data: data for the callback. * @data: data for the callback.
* @fn: function to be called for each device. * @fn: function to be called for each device.
* *
* Iterate over @dev's child devices, and call @fn for each, * Iterate over @parent's child devices, and call @fn for each,
* passing it @data. * passing it @data.
* *
* We check the return of @fn each time. If it returns anything * We check the return of @fn each time. If it returns anything

View file

@ -9,6 +9,7 @@
#include <linux/topology.h> #include <linux/topology.h>
#include <linux/device.h> #include <linux/device.h>
#include "base.h"
struct sysdev_class cpu_sysdev_class = { struct sysdev_class cpu_sysdev_class = {
set_kset_name("cpu"), set_kset_name("cpu"),

View file

@ -28,6 +28,7 @@ static struct device * next_device(struct klist_iter * i)
/** /**
* driver_for_each_device - Iterator for devices bound to a driver. * driver_for_each_device - Iterator for devices bound to a driver.
* @drv: Driver we're iterating. * @drv: Driver we're iterating.
* @start: Device to begin with
* @data: Data to pass to the callback. * @data: Data to pass to the callback.
* @fn: Function to call for each device. * @fn: Function to call for each device.
* *
@ -57,7 +58,7 @@ EXPORT_SYMBOL_GPL(driver_for_each_device);
/** /**
* driver_find_device - device iterator for locating a particular device. * driver_find_device - device iterator for locating a particular device.
* @driver: The device's driver * @drv: The device's driver
* @start: Device to begin with * @start: Device to begin with
* @data: Data to pass to match function * @data: Data to pass to match function
* @match: Callback function to check device * @match: Callback function to check device

View file

@ -11,6 +11,9 @@
#include <linux/kobject.h> #include <linux/kobject.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/device.h>
#include "base.h"
static decl_subsys(firmware, NULL, NULL); static decl_subsys(firmware, NULL, NULL);

View file

@ -10,14 +10,8 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/init.h> #include <linux/init.h>
extern int devices_init(void); #include "base.h"
extern int buses_init(void);
extern int classes_init(void);
extern int firmware_init(void);
extern int platform_bus_init(void);
extern int system_bus_init(void);
extern int cpu_dev_init(void);
extern int attribute_container_init(void);
/** /**
* driver_init - initialize driver model. * driver_init - initialize driver model.
* *

View file

@ -17,6 +17,8 @@
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/err.h> #include <linux/err.h>
#include "base.h"
struct device platform_bus = { struct device platform_bus = {
.bus_id = "platform", .bus_id = "platform",
}; };
@ -279,13 +281,9 @@ static int platform_suspend(struct device * dev, pm_message_t state)
{ {
int ret = 0; int ret = 0;
if (dev->driver && dev->driver->suspend) { if (dev->driver && dev->driver->suspend)
ret = dev->driver->suspend(dev, state, SUSPEND_DISABLE); ret = dev->driver->suspend(dev, state);
if (ret == 0)
ret = dev->driver->suspend(dev, state, SUSPEND_SAVE_STATE);
if (ret == 0)
ret = dev->driver->suspend(dev, state, SUSPEND_POWER_DOWN);
}
return ret; return ret;
} }
@ -293,13 +291,9 @@ static int platform_resume(struct device * dev)
{ {
int ret = 0; int ret = 0;
if (dev->driver && dev->driver->resume) { if (dev->driver && dev->driver->resume)
ret = dev->driver->resume(dev, RESUME_POWER_ON); ret = dev->driver->resume(dev);
if (ret == 0)
ret = dev->driver->resume(dev, RESUME_RESTORE_STATE);
if (ret == 0)
ret = dev->driver->resume(dev, RESUME_ENABLE);
}
return ret; return ret;
} }

View file

@ -48,8 +48,81 @@ static ssize_t state_store(struct device * dev, struct device_attribute *attr, c
static DEVICE_ATTR(state, 0644, state_show, state_store); static DEVICE_ATTR(state, 0644, state_show, state_store);
/*
* wakeup - Report/change current wakeup option for device
*
* Some devices support "wakeup" events, which are hardware signals
* used to activate devices from suspended or low power states. Such
* devices have one of three values for the sysfs power/wakeup file:
*
* + "enabled\n" to issue the events;
* + "disabled\n" not to do so; or
* + "\n" for temporary or permanent inability to issue wakeup.
*
* (For example, unconfigured USB devices can't issue wakeups.)
*
* Familiar examples of devices that can issue wakeup events include
* keyboards and mice (both PS2 and USB styles), power buttons, modems,
* "Wake-On-LAN" Ethernet links, GPIO lines, and more. Some events
* will wake the entire system from a suspend state; others may just
* wake up the device (if the system as a whole is already active).
* Some wakeup events use normal IRQ lines; other use special out
* of band signaling.
*
* It is the responsibility of device drivers to enable (or disable)
* wakeup signaling as part of changing device power states, respecting
* the policy choices provided through the driver model.
*
* Devices may not be able to generate wakeup events from all power
* states. Also, the events may be ignored in some configurations;
* for example, they might need help from other devices that aren't
* active, or which may have wakeup disabled. Some drivers rely on
* wakeup events internally (unless they are disabled), keeping
* their hardware in low power modes whenever they're unused. This
* saves runtime power, without requiring system-wide sleep states.
*/
static const char enabled[] = "enabled";
static const char disabled[] = "disabled";
static ssize_t
wake_show(struct device * dev, struct device_attribute *attr, char * buf)
{
return sprintf(buf, "%s\n", device_can_wakeup(dev)
? (device_may_wakeup(dev) ? enabled : disabled)
: "");
}
static ssize_t
wake_store(struct device * dev, struct device_attribute *attr,
const char * buf, size_t n)
{
char *cp;
int len = n;
if (!device_can_wakeup(dev))
return -EINVAL;
cp = memchr(buf, '\n', n);
if (cp)
len = cp - buf;
if (len == sizeof enabled - 1
&& strncmp(buf, enabled, sizeof enabled - 1) == 0)
device_set_wakeup_enable(dev, 1);
else if (len == sizeof disabled - 1
&& strncmp(buf, disabled, sizeof disabled - 1) == 0)
device_set_wakeup_enable(dev, 0);
else
return -EINVAL;
return n;
}
static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
static struct attribute * power_attrs[] = { static struct attribute * power_attrs[] = {
&dev_attr_state.attr, &dev_attr_state.attr,
&dev_attr_wakeup.attr,
NULL, NULL,
}; };
static struct attribute_group pm_attr_group = { static struct attribute_group pm_attr_group = {

View file

@ -1,5 +1,5 @@
/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
#define VERSION "12" #define VERSION "14"
#define AOE_MAJOR 152 #define AOE_MAJOR 152
#define DEVICE_NAME "aoe" #define DEVICE_NAME "aoe"

View file

@ -224,7 +224,7 @@ aoechr_init(void)
return PTR_ERR(aoe_class); return PTR_ERR(aoe_class);
} }
for (i = 0; i < ARRAY_SIZE(chardevs); ++i) for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
class_device_create(aoe_class, class_device_create(aoe_class, NULL,
MKDEV(AOE_MAJOR, chardevs[i].minor), MKDEV(AOE_MAJOR, chardevs[i].minor),
NULL, chardevs[i].name); NULL, chardevs[i].name);

View file

@ -8,6 +8,7 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <asm/unaligned.h>
#include "aoe.h" #include "aoe.h"
#define TIMERTICK (HZ / 10) #define TIMERTICK (HZ / 10)
@ -311,16 +312,16 @@ ataid_complete(struct aoedev *d, unsigned char *id)
u16 n; u16 n;
/* word 83: command set supported */ /* word 83: command set supported */
n = le16_to_cpup((__le16 *) &id[83<<1]); n = le16_to_cpu(get_unaligned((__le16 *) &id[83<<1]));
/* word 86: command set/feature enabled */ /* word 86: command set/feature enabled */
n |= le16_to_cpup((__le16 *) &id[86<<1]); n |= le16_to_cpu(get_unaligned((__le16 *) &id[86<<1]));
if (n & (1<<10)) { /* bit 10: LBA 48 */ if (n & (1<<10)) { /* bit 10: LBA 48 */
d->flags |= DEVFL_EXT; d->flags |= DEVFL_EXT;
/* word 100: number lba48 sectors */ /* word 100: number lba48 sectors */
ssize = le64_to_cpup((__le64 *) &id[100<<1]); ssize = le64_to_cpu(get_unaligned((__le64 *) &id[100<<1]));
/* set as in ide-disk.c:init_idedisk_capacity */ /* set as in ide-disk.c:init_idedisk_capacity */
d->geo.cylinders = ssize; d->geo.cylinders = ssize;
@ -331,12 +332,12 @@ ataid_complete(struct aoedev *d, unsigned char *id)
d->flags &= ~DEVFL_EXT; d->flags &= ~DEVFL_EXT;
/* number lba28 sectors */ /* number lba28 sectors */
ssize = le32_to_cpup((__le32 *) &id[60<<1]); ssize = le32_to_cpu(get_unaligned((__le32 *) &id[60<<1]));
/* NOTE: obsolete in ATA 6 */ /* NOTE: obsolete in ATA 6 */
d->geo.cylinders = le16_to_cpup((__le16 *) &id[54<<1]); d->geo.cylinders = le16_to_cpu(get_unaligned((__le16 *) &id[54<<1]));
d->geo.heads = le16_to_cpup((__le16 *) &id[55<<1]); d->geo.heads = le16_to_cpu(get_unaligned((__le16 *) &id[55<<1]));
d->geo.sectors = le16_to_cpup((__le16 *) &id[56<<1]); d->geo.sectors = le16_to_cpu(get_unaligned((__le16 *) &id[56<<1]));
} }
d->ssize = ssize; d->ssize = ssize;
d->geo.start = 0; d->geo.start = 0;

View file

@ -337,10 +337,30 @@ static ssize_t disk_attr_show(struct kobject *kobj, struct attribute *attr,
return ret; return ret;
} }
static ssize_t disk_attr_store(struct kobject * kobj, struct attribute * attr,
const char *page, size_t count)
{
struct gendisk *disk = to_disk(kobj);
struct disk_attribute *disk_attr =
container_of(attr,struct disk_attribute,attr);
ssize_t ret = 0;
if (disk_attr->store)
ret = disk_attr->store(disk, page, count);
return ret;
}
static struct sysfs_ops disk_sysfs_ops = { static struct sysfs_ops disk_sysfs_ops = {
.show = &disk_attr_show, .show = &disk_attr_show,
.store = &disk_attr_store,
}; };
static ssize_t disk_uevent_store(struct gendisk * disk,
const char *buf, size_t count)
{
kobject_hotplug(&disk->kobj, KOBJ_ADD);
return count;
}
static ssize_t disk_dev_read(struct gendisk * disk, char *page) static ssize_t disk_dev_read(struct gendisk * disk, char *page)
{ {
dev_t base = MKDEV(disk->major, disk->first_minor); dev_t base = MKDEV(disk->major, disk->first_minor);
@ -382,6 +402,10 @@ static ssize_t disk_stats_read(struct gendisk * disk, char *page)
jiffies_to_msecs(disk_stat_read(disk, io_ticks)), jiffies_to_msecs(disk_stat_read(disk, io_ticks)),
jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); jiffies_to_msecs(disk_stat_read(disk, time_in_queue)));
} }
static struct disk_attribute disk_attr_uevent = {
.attr = {.name = "uevent", .mode = S_IWUSR },
.store = disk_uevent_store
};
static struct disk_attribute disk_attr_dev = { static struct disk_attribute disk_attr_dev = {
.attr = {.name = "dev", .mode = S_IRUGO }, .attr = {.name = "dev", .mode = S_IRUGO },
.show = disk_dev_read .show = disk_dev_read
@ -404,6 +428,7 @@ static struct disk_attribute disk_attr_stat = {
}; };
static struct attribute * default_attrs[] = { static struct attribute * default_attrs[] = {
&disk_attr_uevent.attr,
&disk_attr_dev.attr, &disk_attr_dev.attr,
&disk_attr_range.attr, &disk_attr_range.attr,
&disk_attr_removable.attr, &disk_attr_removable.attr,

View file

@ -674,7 +674,7 @@ static int __init pg_init(void)
for (unit = 0; unit < PG_UNITS; unit++) { for (unit = 0; unit < PG_UNITS; unit++) {
struct pg *dev = &devices[unit]; struct pg *dev = &devices[unit];
if (dev->present) { if (dev->present) {
class_device_create(pg_class, MKDEV(major, unit), class_device_create(pg_class, NULL, MKDEV(major, unit),
NULL, "pg%u", unit); NULL, "pg%u", unit);
err = devfs_mk_cdev(MKDEV(major, unit), err = devfs_mk_cdev(MKDEV(major, unit),
S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u", S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u",

View file

@ -971,7 +971,7 @@ static int __init pt_init(void)
devfs_mk_dir("pt"); devfs_mk_dir("pt");
for (unit = 0; unit < PT_UNITS; unit++) for (unit = 0; unit < PT_UNITS; unit++)
if (pt[unit].present) { if (pt[unit].present) {
class_device_create(pt_class, MKDEV(major, unit), class_device_create(pt_class, NULL, MKDEV(major, unit),
NULL, "pt%d", unit); NULL, "pt%d", unit);
err = devfs_mk_cdev(MKDEV(major, unit), err = devfs_mk_cdev(MKDEV(major, unit),
S_IFCHR | S_IRUSR | S_IWUSR, S_IFCHR | S_IRUSR | S_IWUSR,
@ -980,7 +980,7 @@ static int __init pt_init(void)
class_device_destroy(pt_class, MKDEV(major, unit)); class_device_destroy(pt_class, MKDEV(major, unit));
goto out_class; goto out_class;
} }
class_device_create(pt_class, MKDEV(major, unit + 128), class_device_create(pt_class, NULL, MKDEV(major, unit + 128),
NULL, "pt%dn", unit); NULL, "pt%dn", unit);
err = devfs_mk_cdev(MKDEV(major, unit + 128), err = devfs_mk_cdev(MKDEV(major, unit + 128),
S_IFCHR | S_IRUSR | S_IWUSR, S_IFCHR | S_IRUSR | S_IWUSR,

View file

@ -515,7 +515,7 @@ static int __init dsp56k_init_driver(void)
err = PTR_ERR(dsp56k_class); err = PTR_ERR(dsp56k_class);
goto out_chrdev; goto out_chrdev;
} }
class_device_create(dsp56k_class, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k"); class_device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
err = devfs_mk_cdev(MKDEV(DSP56K_MAJOR, 0), err = devfs_mk_cdev(MKDEV(DSP56K_MAJOR, 0),
S_IFCHR | S_IRUSR | S_IWUSR, "dsp56k"); S_IFCHR | S_IRUSR | S_IWUSR, "dsp56k");

View file

@ -331,27 +331,27 @@ KERN_INFO
zft_class = class_create(THIS_MODULE, "zft"); zft_class = class_create(THIS_MODULE, "zft");
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i); class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i), devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i),
S_IFCHR | S_IRUSR | S_IWUSR, S_IFCHR | S_IRUSR | S_IWUSR,
"qft%i", i); "qft%i", i);
class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i); class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 4), devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 4),
S_IFCHR | S_IRUSR | S_IWUSR, S_IFCHR | S_IRUSR | S_IWUSR,
"nqft%i", i); "nqft%i", i);
class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i); class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 16), devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 16),
S_IFCHR | S_IRUSR | S_IWUSR, S_IFCHR | S_IRUSR | S_IWUSR,
"zqft%i", i); "zqft%i", i);
class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i); class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 20), devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 20),
S_IFCHR | S_IRUSR | S_IWUSR, S_IFCHR | S_IRUSR | S_IWUSR,
"nzqft%i", i); "nzqft%i", i);
class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i); class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 32), devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 32),
S_IFCHR | S_IRUSR | S_IWUSR, S_IFCHR | S_IRUSR | S_IWUSR,
"rawqft%i", i); "rawqft%i", i);
class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i); class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 36), devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 36),
S_IFCHR | S_IRUSR | S_IWUSR, S_IFCHR | S_IRUSR | S_IWUSR,
"nrawqft%i", i); "nrawqft%i", i);

View file

@ -721,8 +721,9 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
} }
if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR, class_device_create(ip2_class, NULL,
4 * i), NULL, "ipl%d", i); MKDEV(IP2_IPL_MAJOR, 4 * i),
NULL, "ipl%d", i);
err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i), err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i),
S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
"ip2/ipl%d", i); "ip2/ipl%d", i);
@ -732,8 +733,9 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
goto out_class; goto out_class;
} }
class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR, class_device_create(ip2_class, NULL,
4 * i + 1), NULL, "stat%d", i); MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
NULL, "stat%d", i);
err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1), err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
"ip2/stat%d", i); "ip2/stat%d", i);

View file

@ -798,7 +798,7 @@ static void ipmi_new_smi(int if_num)
devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR, devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
"ipmidev/%d", if_num); "ipmidev/%d", if_num);
class_device_create(ipmi_class, dev, NULL, "ipmi%d", if_num); class_device_create(ipmi_class, NULL, dev, NULL, "ipmi%d", if_num);
} }
static void ipmi_smi_gone(int if_num) static void ipmi_smi_gone(int if_num)

View file

@ -5246,7 +5246,8 @@ int __init stli_init(void)
devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i), devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
S_IFCHR | S_IRUSR | S_IWUSR, S_IFCHR | S_IRUSR | S_IWUSR,
"staliomem/%d", i); "staliomem/%d", i);
class_device_create(istallion_class, MKDEV(STL_SIOMEMMAJOR, i), class_device_create(istallion_class, NULL,
MKDEV(STL_SIOMEMMAJOR, i),
NULL, "staliomem%d", i); NULL, "staliomem%d", i);
} }

View file

@ -805,7 +805,7 @@ static int lp_register(int nr, struct parport *port)
if (reset) if (reset)
lp_reset(nr); lp_reset(nr);
class_device_create(lp_class, MKDEV(LP_MAJOR, nr), NULL, class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), NULL,
"lp%d", nr); "lp%d", nr);
devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO, devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO,
"printers/%d", nr); "printers/%d", nr);

View file

@ -920,7 +920,8 @@ static int __init chr_dev_init(void)
mem_class = class_create(THIS_MODULE, "mem"); mem_class = class_create(THIS_MODULE, "mem");
for (i = 0; i < ARRAY_SIZE(devlist); i++) { for (i = 0; i < ARRAY_SIZE(devlist); i++) {
class_device_create(mem_class, MKDEV(MEM_MAJOR, devlist[i].minor), class_device_create(mem_class, NULL,
MKDEV(MEM_MAJOR, devlist[i].minor),
NULL, devlist[i].name); NULL, devlist[i].name);
devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor), devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor),
S_IFCHR | devlist[i].mode, devlist[i].name); S_IFCHR | devlist[i].mode, devlist[i].name);

View file

@ -234,7 +234,7 @@ int misc_register(struct miscdevice * misc)
} }
dev = MKDEV(MISC_MAJOR, misc->minor); dev = MKDEV(MISC_MAJOR, misc->minor);
misc->class = class_device_create(misc_class, dev, misc->dev, misc->class = class_device_create(misc_class, NULL, dev, misc->dev,
"%s", misc->name); "%s", misc->name);
if (IS_ERR(misc->class)) { if (IS_ERR(misc->class)) {
err = PTR_ERR(misc->class); err = PTR_ERR(misc->class);

View file

@ -752,7 +752,7 @@ static struct file_operations pp_fops = {
static void pp_attach(struct parport *port) static void pp_attach(struct parport *port)
{ {
class_device_create(ppdev_class, MKDEV(PP_MAJOR, port->number), class_device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number),
NULL, "parport%d", port->number); NULL, "parport%d", port->number);
} }

View file

@ -128,7 +128,7 @@ raw_ioctl(struct inode *inode, struct file *filp,
static void bind_device(struct raw_config_request *rq) static void bind_device(struct raw_config_request *rq)
{ {
class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor)); class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
class_device_create(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor), class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
NULL, "raw%d", rq->raw_minor); NULL, "raw%d", rq->raw_minor);
} }
@ -307,7 +307,7 @@ static int __init raw_init(void)
unregister_chrdev_region(dev, MAX_RAW_MINORS); unregister_chrdev_region(dev, MAX_RAW_MINORS);
goto error; goto error;
} }
class_device_create(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl"); class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
devfs_mk_cdev(MKDEV(RAW_MAJOR, 0), devfs_mk_cdev(MKDEV(RAW_MAJOR, 0),
S_IFCHR | S_IRUGO | S_IWUGO, S_IFCHR | S_IRUGO | S_IWUGO,

View file

@ -519,14 +519,13 @@ static struct timespec s3c2410_rtc_delta;
static int ticnt_save; static int ticnt_save;
static int s3c2410_rtc_suspend(struct device *dev, pm_message_t state, u32 level) static int s3c2410_rtc_suspend(struct device *dev, pm_message_t state)
{ {
struct rtc_time tm; struct rtc_time tm;
struct timespec time; struct timespec time;
time.tv_nsec = 0; time.tv_nsec = 0;
if (level == SUSPEND_POWER_DOWN) {
/* save TICNT for anyone using periodic interrupts */ /* save TICNT for anyone using periodic interrupts */
ticnt_save = readb(S3C2410_TICNT); ticnt_save = readb(S3C2410_TICNT);
@ -537,12 +536,11 @@ static int s3c2410_rtc_suspend(struct device *dev, pm_message_t state, u32 level
rtc_tm_to_time(&tm, &time.tv_sec); rtc_tm_to_time(&tm, &time.tv_sec);
save_time_delta(&s3c2410_rtc_delta, &time); save_time_delta(&s3c2410_rtc_delta, &time);
s3c2410_rtc_enable(dev, 0); s3c2410_rtc_enable(dev, 0);
}
return 0; return 0;
} }
static int s3c2410_rtc_resume(struct device *dev, u32 level) static int s3c2410_rtc_resume(struct device *dev)
{ {
struct rtc_time tm; struct rtc_time tm;
struct timespec time; struct timespec time;

View file

@ -437,7 +437,7 @@ scdrv_init(void)
continue; continue;
} }
class_device_create(snsc_class, dev, NULL, class_device_create(snsc_class, NULL, dev, NULL,
"%s", devname); "%s", devname);
ia64_sn_irtr_intr_enable(scd->scd_nasid, ia64_sn_irtr_intr_enable(scd->scd_nasid,

View file

@ -424,10 +424,6 @@ static struct sonypi_eventtypes {
#define SONYPI_BUF_SIZE 128 #define SONYPI_BUF_SIZE 128
/* The name of the devices for the input device drivers */
#define SONYPI_JOG_INPUTNAME "Sony Vaio Jogdial"
#define SONYPI_KEY_INPUTNAME "Sony Vaio Keys"
/* Correspondance table between sonypi events and input layer events */ /* Correspondance table between sonypi events and input layer events */
static struct { static struct {
int sonypiev; int sonypiev;
@ -490,8 +486,8 @@ static struct sonypi_device {
struct fasync_struct *fifo_async; struct fasync_struct *fifo_async;
int open_count; int open_count;
int model; int model;
struct input_dev input_jog_dev; struct input_dev *input_jog_dev;
struct input_dev input_key_dev; struct input_dev *input_key_dev;
struct work_struct input_work; struct work_struct input_work;
struct kfifo *input_fifo; struct kfifo *input_fifo;
spinlock_t input_fifo_lock; spinlock_t input_fifo_lock;
@ -779,8 +775,8 @@ static void input_keyrelease(void *data)
static void sonypi_report_input_event(u8 event) static void sonypi_report_input_event(u8 event)
{ {
struct input_dev *jog_dev = &sonypi_device.input_jog_dev; struct input_dev *jog_dev = sonypi_device.input_jog_dev;
struct input_dev *key_dev = &sonypi_device.input_key_dev; struct input_dev *key_dev = sonypi_device.input_key_dev;
struct sonypi_keypress kp = { NULL }; struct sonypi_keypress kp = { NULL };
int i; int i;
@ -1171,18 +1167,16 @@ static int sonypi_disable(void)
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int old_camera_power; static int old_camera_power;
static int sonypi_suspend(struct device *dev, pm_message_t state, u32 level) static int sonypi_suspend(struct device *dev, pm_message_t state)
{ {
if (level == SUSPEND_DISABLE) {
old_camera_power = sonypi_device.camera_power; old_camera_power = sonypi_device.camera_power;
sonypi_disable(); sonypi_disable();
}
return 0; return 0;
} }
static int sonypi_resume(struct device *dev, u32 level) static int sonypi_resume(struct device *dev)
{ {
if (level == RESUME_ENABLE)
sonypi_enable(old_camera_power); sonypi_enable(old_camera_power);
return 0; return 0;
} }
@ -1203,6 +1197,47 @@ static struct device_driver sonypi_driver = {
.shutdown = sonypi_shutdown, .shutdown = sonypi_shutdown,
}; };
static int __devinit sonypi_create_input_devices(void)
{
struct input_dev *jog_dev;
struct input_dev *key_dev;
int i;
sonypi_device.input_jog_dev = jog_dev = input_allocate_device();
if (!jog_dev)
return -ENOMEM;
jog_dev->name = "Sony Vaio Jogdial";
jog_dev->id.bustype = BUS_ISA;
jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
jog_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
jog_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_MIDDLE);
jog_dev->relbit[0] = BIT(REL_WHEEL);
sonypi_device.input_key_dev = key_dev = input_allocate_device();
if (!key_dev) {
input_free_device(jog_dev);
sonypi_device.input_jog_dev = NULL;
return -ENOMEM;
}
key_dev->name = "Sony Vaio Keys";
key_dev->id.bustype = BUS_ISA;
key_dev->id.vendor = PCI_VENDOR_ID_SONY;
/* Initialize the Input Drivers: special keys */
key_dev->evbit[0] = BIT(EV_KEY);
for (i = 0; sonypi_inputkeys[i].sonypiev; i++)
if (sonypi_inputkeys[i].inputev)
set_bit(sonypi_inputkeys[i].inputev, key_dev->keybit);
input_register_device(jog_dev);
input_register_device(key_dev);
return 0;
}
static int __devinit sonypi_probe(void) static int __devinit sonypi_probe(void)
{ {
int i, ret; int i, ret;
@ -1298,34 +1333,10 @@ static int __devinit sonypi_probe(void)
} }
if (useinput) { if (useinput) {
/* Initialize the Input Drivers: jogdial */
int i;
sonypi_device.input_jog_dev.evbit[0] =
BIT(EV_KEY) | BIT(EV_REL);
sonypi_device.input_jog_dev.keybit[LONG(BTN_MOUSE)] =
BIT(BTN_MIDDLE);
sonypi_device.input_jog_dev.relbit[0] = BIT(REL_WHEEL);
sonypi_device.input_jog_dev.name = SONYPI_JOG_INPUTNAME;
sonypi_device.input_jog_dev.id.bustype = BUS_ISA;
sonypi_device.input_jog_dev.id.vendor = PCI_VENDOR_ID_SONY;
input_register_device(&sonypi_device.input_jog_dev); ret = sonypi_create_input_devices();
printk(KERN_INFO "%s input method installed.\n", if (ret)
sonypi_device.input_jog_dev.name); goto out_inputdevices;
/* Initialize the Input Drivers: special keys */
sonypi_device.input_key_dev.evbit[0] = BIT(EV_KEY);
for (i = 0; sonypi_inputkeys[i].sonypiev; i++)
if (sonypi_inputkeys[i].inputev)
set_bit(sonypi_inputkeys[i].inputev,
sonypi_device.input_key_dev.keybit);
sonypi_device.input_key_dev.name = SONYPI_KEY_INPUTNAME;
sonypi_device.input_key_dev.id.bustype = BUS_ISA;
sonypi_device.input_key_dev.id.vendor = PCI_VENDOR_ID_SONY;
input_register_device(&sonypi_device.input_key_dev);
printk(KERN_INFO "%s input method installed.\n",
sonypi_device.input_key_dev.name);
spin_lock_init(&sonypi_device.input_fifo_lock); spin_lock_init(&sonypi_device.input_fifo_lock);
sonypi_device.input_fifo = sonypi_device.input_fifo =
@ -1375,8 +1386,9 @@ static int __devinit sonypi_probe(void)
out_platformdev: out_platformdev:
kfifo_free(sonypi_device.input_fifo); kfifo_free(sonypi_device.input_fifo);
out_infifo: out_infifo:
input_unregister_device(&sonypi_device.input_key_dev); input_unregister_device(sonypi_device.input_key_dev);
input_unregister_device(&sonypi_device.input_jog_dev); input_unregister_device(sonypi_device.input_jog_dev);
out_inputdevices:
free_irq(sonypi_device.irq, sonypi_irq); free_irq(sonypi_device.irq, sonypi_irq);
out_reqirq: out_reqirq:
release_region(sonypi_device.ioport1, sonypi_device.region_size); release_region(sonypi_device.ioport1, sonypi_device.region_size);
@ -1402,8 +1414,8 @@ static void __devexit sonypi_remove(void)
platform_device_unregister(sonypi_device.pdev); platform_device_unregister(sonypi_device.pdev);
if (useinput) { if (useinput) {
input_unregister_device(&sonypi_device.input_key_dev); input_unregister_device(sonypi_device.input_key_dev);
input_unregister_device(&sonypi_device.input_jog_dev); input_unregister_device(sonypi_device.input_jog_dev);
kfifo_free(sonypi_device.input_fifo); kfifo_free(sonypi_device.input_fifo);
} }

View file

@ -3095,7 +3095,9 @@ static int __init stl_init(void)
devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i), devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
S_IFCHR|S_IRUSR|S_IWUSR, S_IFCHR|S_IRUSR|S_IWUSR,
"staliomem/%d", i); "staliomem/%d", i);
class_device_create(stallion_class, MKDEV(STL_SIOMEMMAJOR, i), NULL, "staliomem%d", i); class_device_create(stallion_class, NULL,
MKDEV(STL_SIOMEMMAJOR, i), NULL,
"staliomem%d", i);
} }
stl_serial->owner = THIS_MODULE; stl_serial->owner = THIS_MODULE;

View file

@ -436,7 +436,7 @@ tipar_register(int nr, struct parport *port)
goto out; goto out;
} }
class_device_create(tipar_class, MKDEV(TIPAR_MAJOR, class_device_create(tipar_class, NULL, MKDEV(TIPAR_MAJOR,
TIPAR_MINOR + nr), NULL, "par%d", nr); TIPAR_MINOR + nr), NULL, "par%d", nr);
/* Use devfs, tree: /dev/ticables/par/[0..2] */ /* Use devfs, tree: /dev/ticables/par/[0..2] */
err = devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr), err = devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr),

View file

@ -2728,7 +2728,7 @@ void tty_register_device(struct tty_driver *driver, unsigned index,
pty_line_name(driver, index, name); pty_line_name(driver, index, name);
else else
tty_line_name(driver, index, name); tty_line_name(driver, index, name);
class_device_create(tty_class, dev, device, name); class_device_create(tty_class, NULL, dev, device, "%s", name);
} }
/** /**
@ -2983,14 +2983,14 @@ static int __init tty_init(void)
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
panic("Couldn't register /dev/tty driver\n"); panic("Couldn't register /dev/tty driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty"); devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty"); class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
cdev_init(&console_cdev, &console_fops); cdev_init(&console_cdev, &console_fops);
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
panic("Couldn't register /dev/console driver\n"); panic("Couldn't register /dev/console driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console"); devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console"); class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
#ifdef CONFIG_UNIX98_PTYS #ifdef CONFIG_UNIX98_PTYS
cdev_init(&ptmx_cdev, &ptmx_fops); cdev_init(&ptmx_cdev, &ptmx_fops);
@ -2998,7 +2998,7 @@ static int __init tty_init(void)
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
panic("Couldn't register /dev/ptmx driver\n"); panic("Couldn't register /dev/ptmx driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx"); devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
#endif #endif
#ifdef CONFIG_VT #ifdef CONFIG_VT
@ -3007,7 +3007,7 @@ static int __init tty_init(void)
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
panic("Couldn't register /dev/tty0 driver\n"); panic("Couldn't register /dev/tty0 driver\n");
devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0"); devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0");
class_device_create(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0"); class_device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
vty_init(); vty_init();
#endif #endif

View file

@ -484,8 +484,10 @@ void vcs_make_devfs(struct tty_struct *tty)
devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129), devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129),
S_IFCHR|S_IRUSR|S_IWUSR, S_IFCHR|S_IRUSR|S_IWUSR,
"vcc/a%u", tty->index + 1); "vcc/a%u", tty->index + 1);
class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 1), NULL, "vcs%u", tty->index + 1); class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 129), NULL, "vcsa%u", tty->index + 1); NULL, "vcs%u", tty->index + 1);
class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
NULL, "vcsa%u", tty->index + 1);
} }
void vcs_remove_devfs(struct tty_struct *tty) void vcs_remove_devfs(struct tty_struct *tty)
{ {
@ -503,7 +505,7 @@ int __init vcs_init(void)
devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0"); devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0");
devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0"); devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0");
class_device_create(vc_class, MKDEV(VCS_MAJOR, 0), NULL, "vcs"); class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
class_device_create(vc_class, MKDEV(VCS_MAJOR, 128), NULL, "vcsa"); class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
return 0; return 0;
} }

View file

@ -956,9 +956,9 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
state[i].cur_part = 0; state[i].cur_part = 0;
for (j = 0; j < MAX_PARTITIONS; ++j) for (j = 0; j < MAX_PARTITIONS; ++j)
state[i].part_stat_rwi[j] = VIOT_IDLE; state[i].part_stat_rwi[j] = VIOT_IDLE;
class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL, class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), NULL,
"iseries!vt%d", i); "iseries!vt%d", i);
class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80), class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
NULL, "iseries!nvt%d", i); NULL, "iseries!nvt%d", i);
devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR, devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR,
"iseries/vt%d", i); "iseries/vt%d", i);

View file

@ -464,23 +464,20 @@ static void s3c2410wdt_shutdown(struct device *dev)
static unsigned long wtcon_save; static unsigned long wtcon_save;
static unsigned long wtdat_save; static unsigned long wtdat_save;
static int s3c2410wdt_suspend(struct device *dev, pm_message_t state, u32 level) static int s3c2410wdt_suspend(struct device *dev, pm_message_t state)
{ {
if (level == SUSPEND_POWER_DOWN) {
/* Save watchdog state, and turn it off. */ /* Save watchdog state, and turn it off. */
wtcon_save = readl(wdt_base + S3C2410_WTCON); wtcon_save = readl(wdt_base + S3C2410_WTCON);
wtdat_save = readl(wdt_base + S3C2410_WTDAT); wtdat_save = readl(wdt_base + S3C2410_WTDAT);
/* Note that WTCNT doesn't need to be saved. */ /* Note that WTCNT doesn't need to be saved. */
s3c2410wdt_stop(); s3c2410wdt_stop();
}
return 0; return 0;
} }
static int s3c2410wdt_resume(struct device *dev, u32 level) static int s3c2410wdt_resume(struct device *dev)
{ {
if (level == RESUME_POWER_ON) {
/* Restore watchdog state. */ /* Restore watchdog state. */
writel(wtdat_save, wdt_base + S3C2410_WTDAT); writel(wtdat_save, wdt_base + S3C2410_WTDAT);
@ -489,7 +486,6 @@ static int s3c2410wdt_resume(struct device *dev, u32 level)
printk(KERN_INFO PFX "watchdog %sabled\n", printk(KERN_INFO PFX "watchdog %sabled\n",
(wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis"); (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
}
return 0; return 0;
} }

View file

@ -296,11 +296,9 @@ static int hdaps_probe(struct device *dev)
return 0; return 0;
} }
static int hdaps_resume(struct device *dev, u32 level) static int hdaps_resume(struct device *dev)
{ {
if (level == RESUME_ENABLE)
return hdaps_device_init(); return hdaps_device_init();
return 0;
} }
static struct device_driver hdaps_driver = { static struct device_driver hdaps_driver = {

View file

@ -45,7 +45,7 @@ struct class_device *hwmon_device_register(struct device *dev)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
id = id & MAX_ID_MASK; id = id & MAX_ID_MASK;
cdev = class_device_create(hwmon_class, MKDEV(0,0), dev, cdev = class_device_create(hwmon_class, NULL, MKDEV(0,0), dev,
HWMON_ID_FORMAT, id); HWMON_ID_FORMAT, id);
if (IS_ERR(cdev)) if (IS_ERR(cdev))

View file

@ -879,14 +879,12 @@ static int s3c24xx_i2c_remove(struct device *dev)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int s3c24xx_i2c_resume(struct device *dev, u32 level) static int s3c24xx_i2c_resume(struct device *dev)
{ {
struct s3c24xx_i2c *i2c = dev_get_drvdata(dev); struct s3c24xx_i2c *i2c = dev_get_drvdata(dev);
if (i2c != NULL && level == RESUME_ENABLE) { if (i2c != NULL)
dev_dbg(dev, "resume: level %d\n", level);
s3c24xx_i2c_init(i2c); s3c24xx_i2c_init(i2c);
}
return 0; return 0;
} }

View file

@ -48,7 +48,7 @@ static int i2c_bus_suspend(struct device * dev, pm_message_t state)
int rc = 0; int rc = 0;
if (dev->driver && dev->driver->suspend) if (dev->driver && dev->driver->suspend)
rc = dev->driver->suspend(dev,state,0); rc = dev->driver->suspend(dev, state);
return rc; return rc;
} }
@ -57,7 +57,7 @@ static int i2c_bus_resume(struct device * dev)
int rc = 0; int rc = 0;
if (dev->driver && dev->driver->resume) if (dev->driver && dev->driver->resume)
rc = dev->driver->resume(dev,0); rc = dev->driver->resume(dev);
return rc; return rc;
} }

View file

@ -1013,6 +1013,8 @@ typedef struct ide_tape_obj {
static DECLARE_MUTEX(idetape_ref_sem); static DECLARE_MUTEX(idetape_ref_sem);
static struct class *idetape_sysfs_class;
#define to_ide_tape(obj) container_of(obj, struct ide_tape_obj, kref) #define to_ide_tape(obj) container_of(obj, struct ide_tape_obj, kref)
#define ide_tape_g(disk) \ #define ide_tape_g(disk) \
@ -4704,6 +4706,10 @@ static void ide_tape_release(struct kref *kref)
drive->dsc_overlap = 0; drive->dsc_overlap = 0;
drive->driver_data = NULL; drive->driver_data = NULL;
class_device_destroy(idetape_sysfs_class,
MKDEV(IDETAPE_MAJOR, tape->minor));
class_device_destroy(idetape_sysfs_class,
MKDEV(IDETAPE_MAJOR, tape->minor + 128));
devfs_remove("%s/mt", drive->devfs_name); devfs_remove("%s/mt", drive->devfs_name);
devfs_remove("%s/mtn", drive->devfs_name); devfs_remove("%s/mtn", drive->devfs_name);
devfs_unregister_tape(g->number); devfs_unregister_tape(g->number);
@ -4878,6 +4884,11 @@ static int ide_tape_probe(struct device *dev)
idetape_setup(drive, tape, minor); idetape_setup(drive, tape, minor);
class_device_create(idetape_sysfs_class, NULL,
MKDEV(IDETAPE_MAJOR, minor), dev, "%s", tape->name);
class_device_create(idetape_sysfs_class, NULL,
MKDEV(IDETAPE_MAJOR, minor + 128), dev, "n%s", tape->name);
devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor), devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor),
S_IFCHR | S_IRUGO | S_IWUGO, S_IFCHR | S_IRUGO | S_IWUGO,
"%s/mt", drive->devfs_name); "%s/mt", drive->devfs_name);
@ -4903,6 +4914,7 @@ MODULE_LICENSE("GPL");
static void __exit idetape_exit (void) static void __exit idetape_exit (void)
{ {
driver_unregister(&idetape_driver.gen_driver); driver_unregister(&idetape_driver.gen_driver);
class_destroy(idetape_sysfs_class);
unregister_chrdev(IDETAPE_MAJOR, "ht"); unregister_chrdev(IDETAPE_MAJOR, "ht");
} }
@ -4911,11 +4923,33 @@ static void __exit idetape_exit (void)
*/ */
static int idetape_init (void) static int idetape_init (void)
{ {
int error = 1;
idetape_sysfs_class = class_create(THIS_MODULE, "ide_tape");
if (IS_ERR(idetape_sysfs_class)) {
idetape_sysfs_class = NULL;
printk(KERN_ERR "Unable to create sysfs class for ide tapes\n");
error = -EBUSY;
goto out;
}
if (register_chrdev(IDETAPE_MAJOR, "ht", &idetape_fops)) { if (register_chrdev(IDETAPE_MAJOR, "ht", &idetape_fops)) {
printk(KERN_ERR "ide-tape: Failed to register character device interface\n"); printk(KERN_ERR "ide-tape: Failed to register character device interface\n");
return -EBUSY; error = -EBUSY;
goto out_free_class;
} }
return driver_register(&idetape_driver.gen_driver);
error = driver_register(&idetape_driver.gen_driver);
if (error)
goto out_free_driver;
return 0;
out_free_driver:
driver_unregister(&idetape_driver.gen_driver);
out_free_class:
class_destroy(idetape_sysfs_class);
out:
return error;
} }
module_init(idetape_init); module_init(idetape_init);

View file

@ -2361,7 +2361,7 @@ static void dv1394_add_host (struct hpsb_host *host)
ohci = (struct ti_ohci *)host->hostdata; ohci = (struct ti_ohci *)host->hostdata;
class_device_create(hpsb_protocol_class, MKDEV( class_device_create(hpsb_protocol_class, NULL, MKDEV(
IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
NULL, "dv1394-%d", id); NULL, "dv1394-%d", id);
devfs_mk_dir("ieee1394/dv/host%d", id); devfs_mk_dir("ieee1394/dv/host%d", id);

View file

@ -1292,7 +1292,7 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
if (ud->device.driver && if (ud->device.driver &&
(!ud->device.driver->suspend || (!ud->device.driver->suspend ||
ud->device.driver->suspend(&ud->device, PMSG_SUSPEND, 0))) ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
device_release_driver(&ud->device); device_release_driver(&ud->device);
} }
up_write(&ne->device.bus->subsys.rwsem); up_write(&ne->device.bus->subsys.rwsem);
@ -1315,7 +1315,7 @@ static void nodemgr_resume_ne(struct node_entry *ne)
continue; continue;
if (ud->device.driver && ud->device.driver->resume) if (ud->device.driver && ud->device.driver->resume)
ud->device.driver->resume(&ud->device, 0); ud->device.driver->resume(&ud->device);
} }
up_read(&ne->device.bus->subsys.rwsem); up_read(&ne->device.bus->subsys.rwsem);

View file

@ -2912,7 +2912,7 @@ static int __init init_raw1394(void)
hpsb_register_highlevel(&raw1394_highlevel); hpsb_register_highlevel(&raw1394_highlevel);
if (IS_ERR(class_device_create(hpsb_protocol_class, MKDEV( if (IS_ERR(class_device_create(hpsb_protocol_class, NULL, MKDEV(
IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
NULL, RAW1394_DEVICE_NAME))) { NULL, RAW1394_DEVICE_NAME))) {
ret = -EFAULT; ret = -EFAULT;

View file

@ -1370,7 +1370,7 @@ static void video1394_add_host (struct hpsb_host *host)
hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id); hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id; minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
class_device_create(hpsb_protocol_class, MKDEV( class_device_create(hpsb_protocol_class, NULL, MKDEV(
IEEE1394_MAJOR, minor), IEEE1394_MAJOR, minor),
NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id); NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor), devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),

View file

@ -1300,7 +1300,7 @@ static int __init ib_ucm_init(void)
goto err_class; goto err_class;
} }
class_device_create(ib_ucm_class, IB_UCM_DEV, NULL, "ucm"); class_device_create(ib_ucm_class, NULL, IB_UCM_DEV, NULL, "ucm");
idr_init(&ctx_id_table); idr_init(&ctx_id_table);
init_MUTEX(&ctx_id_mutex); init_MUTEX(&ctx_id_mutex);

View file

@ -20,7 +20,6 @@
#include <linux/major.h> #include <linux/major.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/compat.h> #include <linux/compat.h>
struct evdev { struct evdev {
@ -662,6 +661,7 @@ static struct file_operations evdev_fops = {
static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id) static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{ {
struct evdev *evdev; struct evdev *evdev;
struct class_device *cdev;
int minor; int minor;
for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++); for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++);
@ -687,11 +687,13 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct
evdev_table[minor] = evdev; evdev_table[minor] = evdev;
devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor), cdev = class_device_create(&input_class, &dev->cdev,
S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor);
class_device_create(input_class,
MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor), MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
dev->dev, "event%d", minor); dev->cdev.dev, evdev->name);
/* temporary symlink to keep userspace happy */
sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
evdev->name);
return &evdev->handle; return &evdev->handle;
} }
@ -701,9 +703,9 @@ static void evdev_disconnect(struct input_handle *handle)
struct evdev *evdev = handle->private; struct evdev *evdev = handle->private;
struct evdev_list *list; struct evdev_list *list;
class_device_destroy(input_class, sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name);
class_device_destroy(&input_class,
MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor)); MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
devfs_remove("input/event%d", evdev->minor);
evdev->exist = 0; evdev->exist = 0;
if (evdev->open) { if (evdev->open) {

View file

@ -22,12 +22,12 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/devfs_fs_kernel.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Input core"); MODULE_DESCRIPTION("Input core");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
EXPORT_SYMBOL(input_allocate_device);
EXPORT_SYMBOL(input_register_device); EXPORT_SYMBOL(input_register_device);
EXPORT_SYMBOL(input_unregister_device); EXPORT_SYMBOL(input_unregister_device);
EXPORT_SYMBOL(input_register_handler); EXPORT_SYMBOL(input_register_handler);
@ -39,7 +39,7 @@ EXPORT_SYMBOL(input_close_device);
EXPORT_SYMBOL(input_accept_process); EXPORT_SYMBOL(input_accept_process);
EXPORT_SYMBOL(input_flush_device); EXPORT_SYMBOL(input_flush_device);
EXPORT_SYMBOL(input_event); EXPORT_SYMBOL(input_event);
EXPORT_SYMBOL(input_class); EXPORT_SYMBOL_GPL(input_class);
#define INPUT_DEVICES 256 #define INPUT_DEVICES 256
@ -316,124 +316,21 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st
return NULL; return NULL;
} }
static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, int max)
/*
* Input hotplugging interface - loading event handlers based on
* device bitfields.
*/
#ifdef CONFIG_HOTPLUG
/*
* Input hotplugging invokes what /proc/sys/kernel/hotplug says
* (normally /sbin/hotplug) when input devices get added or removed.
*
* This invokes a user mode policy agent, typically helping to load driver
* or other modules, configure the device, and more. Drivers can provide
* a MODULE_DEVICE_TABLE to help with module loading subtasks.
*
*/
#define SPRINTF_BIT_A(bit, name, max) \
do { \
envp[i++] = scratch; \
scratch += sprintf(scratch, name); \
for (j = NBITS(max) - 1; j >= 0; j--) \
if (dev->bit[j]) break; \
for (; j >= 0; j--) \
scratch += sprintf(scratch, "%lx ", dev->bit[j]); \
scratch++; \
} while (0)
#define SPRINTF_BIT_A2(bit, name, max, ev) \
do { \
if (test_bit(ev, dev->evbit)) \
SPRINTF_BIT_A(bit, name, max); \
} while (0)
static void input_call_hotplug(char *verb, struct input_dev *dev)
{ {
char *argv[3], **envp, *buf, *scratch; int i;
int i = 0, j, value; int len = 0;
if (!hotplug_path[0]) { for (i = NBITS(max) - 1; i > 0; i--)
printk(KERN_ERR "input.c: calling hotplug without a hotplug agent defined\n"); if (bitmap[i])
return; break;
}
if (in_interrupt()) {
printk(KERN_ERR "input.c: calling hotplug from interrupt\n");
return;
}
if (!current->fs->root) {
printk(KERN_WARNING "input.c: calling hotplug without valid filesystem\n");
return;
}
if (!(envp = (char **) kmalloc(20 * sizeof(char *), GFP_KERNEL))) {
printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
return;
}
if (!(buf = kmalloc(1024, GFP_KERNEL))) {
kfree (envp);
printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
return;
}
argv[0] = hotplug_path; for (; i >= 0; i--)
argv[1] = "input"; len += snprintf(buf + len, max(buf_size - len, 0),
argv[2] = NULL; "%lx%s", bitmap[i], i > 0 ? " " : "");
return len;
envp[i++] = "HOME=/";
envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
scratch = buf;
envp[i++] = scratch;
scratch += sprintf(scratch, "ACTION=%s", verb) + 1;
envp[i++] = scratch;
scratch += sprintf(scratch, "PRODUCT=%x/%x/%x/%x",
dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version) + 1;
if (dev->name) {
envp[i++] = scratch;
scratch += sprintf(scratch, "NAME=%s", dev->name) + 1;
}
if (dev->phys) {
envp[i++] = scratch;
scratch += sprintf(scratch, "PHYS=%s", dev->phys) + 1;
}
SPRINTF_BIT_A(evbit, "EV=", EV_MAX);
SPRINTF_BIT_A2(keybit, "KEY=", KEY_MAX, EV_KEY);
SPRINTF_BIT_A2(relbit, "REL=", REL_MAX, EV_REL);
SPRINTF_BIT_A2(absbit, "ABS=", ABS_MAX, EV_ABS);
SPRINTF_BIT_A2(mscbit, "MSC=", MSC_MAX, EV_MSC);
SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED);
SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND);
SPRINTF_BIT_A2(ffbit, "FF=", FF_MAX, EV_FF);
SPRINTF_BIT_A2(swbit, "SW=", SW_MAX, EV_SW);
envp[i++] = NULL;
#ifdef INPUT_DEBUG
printk(KERN_DEBUG "input.c: calling %s %s [%s %s %s %s %s]\n",
argv[0], argv[1], envp[0], envp[1], envp[2], envp[3], envp[4]);
#endif
value = call_usermodehelper(argv [0], argv, envp, 0);
kfree(buf);
kfree(envp);
#ifdef INPUT_DEBUG
if (value != 0)
printk(KERN_DEBUG "input.c: hotplug returned %d\n", value);
#endif
} }
#endif
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_bus_input_dir; static struct proc_dir_entry *proc_bus_input_dir;
@ -455,37 +352,39 @@ static unsigned int input_devices_poll(struct file *file, poll_table *wait)
return 0; return 0;
} }
#define SPRINTF_BIT_B(bit, name, max) \ #define SPRINTF_BIT(ev, bm) \
do { \ do { \
len += sprintf(buf + len, "B: %s", name); \ len += sprintf(buf + len, "B: %s=", #ev); \
for (i = NBITS(max) - 1; i >= 0; i--) \ len += input_print_bitmap(buf + len, INT_MAX, \
if (dev->bit[i]) break; \ dev->bm##bit, ev##_MAX); \
for (; i >= 0; i--) \
len += sprintf(buf + len, "%lx ", dev->bit[i]); \
len += sprintf(buf + len, "\n"); \ len += sprintf(buf + len, "\n"); \
} while (0) } while (0)
#define SPRINTF_BIT_B2(bit, name, max, ev) \ #define TEST_AND_SPRINTF_BIT(ev, bm) \
do { \ do { \
if (test_bit(ev, dev->evbit)) \ if (test_bit(EV_##ev, dev->evbit)) \
SPRINTF_BIT_B(bit, name, max); \ SPRINTF_BIT(ev, bm); \
} while (0) } while (0)
static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data) static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
{ {
struct input_dev *dev; struct input_dev *dev;
struct input_handle *handle; struct input_handle *handle;
const char *path;
off_t at = 0; off_t at = 0;
int i, len, cnt = 0; int len, cnt = 0;
list_for_each_entry(dev, &input_dev_list, node) { list_for_each_entry(dev, &input_dev_list, node) {
path = dev->dynalloc ? kobject_get_path(&dev->cdev.kobj, GFP_KERNEL) : NULL;
len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n", len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version); dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);
len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : ""); len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : ""); len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : "");
len += sprintf(buf + len, "S: Sysfs=%s\n", path ? path : "");
len += sprintf(buf + len, "H: Handlers="); len += sprintf(buf + len, "H: Handlers=");
list_for_each_entry(handle, &dev->h_list, d_node) list_for_each_entry(handle, &dev->h_list, d_node)
@ -493,15 +392,15 @@ static int input_devices_read(char *buf, char **start, off_t pos, int count, int
len += sprintf(buf + len, "\n"); len += sprintf(buf + len, "\n");
SPRINTF_BIT_B(evbit, "EV=", EV_MAX); SPRINTF_BIT(EV, ev);
SPRINTF_BIT_B2(keybit, "KEY=", KEY_MAX, EV_KEY); TEST_AND_SPRINTF_BIT(KEY, key);
SPRINTF_BIT_B2(relbit, "REL=", REL_MAX, EV_REL); TEST_AND_SPRINTF_BIT(REL, rel);
SPRINTF_BIT_B2(absbit, "ABS=", ABS_MAX, EV_ABS); TEST_AND_SPRINTF_BIT(ABS, abs);
SPRINTF_BIT_B2(mscbit, "MSC=", MSC_MAX, EV_MSC); TEST_AND_SPRINTF_BIT(MSC, msc);
SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED); TEST_AND_SPRINTF_BIT(LED, led);
SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND); TEST_AND_SPRINTF_BIT(SND, snd);
SPRINTF_BIT_B2(ffbit, "FF=", FF_MAX, EV_FF); TEST_AND_SPRINTF_BIT(FF, ff);
SPRINTF_BIT_B2(swbit, "SW=", SW_MAX, EV_SW); TEST_AND_SPRINTF_BIT(SW, sw);
len += sprintf(buf + len, "\n"); len += sprintf(buf + len, "\n");
@ -516,6 +415,8 @@ static int input_devices_read(char *buf, char **start, off_t pos, int count, int
if (cnt >= count) if (cnt >= count)
break; break;
} }
kfree(path);
} }
if (&dev->node == &input_dev_list) if (&dev->node == &input_dev_list)
@ -606,6 +507,240 @@ static inline int input_proc_init(void) { return 0; }
static inline void input_proc_exit(void) { } static inline void input_proc_exit(void) { }
#endif #endif
#define INPUT_DEV_STRING_ATTR_SHOW(name) \
static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \
{ \
struct input_dev *input_dev = to_input_dev(dev); \
int retval; \
\
retval = down_interruptible(&input_dev->sem); \
if (retval) \
return retval; \
\
retval = sprintf(buf, "%s\n", input_dev->name ? input_dev->name : ""); \
\
up(&input_dev->sem); \
\
return retval; \
} \
static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL);
INPUT_DEV_STRING_ATTR_SHOW(name);
INPUT_DEV_STRING_ATTR_SHOW(phys);
INPUT_DEV_STRING_ATTR_SHOW(uniq);
static struct attribute *input_dev_attrs[] = {
&class_device_attr_name.attr,
&class_device_attr_phys.attr,
&class_device_attr_uniq.attr,
NULL
};
static struct attribute_group input_dev_group = {
.attrs = input_dev_attrs,
};
#define INPUT_DEV_ID_ATTR(name) \
static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf) \
{ \
struct input_dev *input_dev = to_input_dev(dev); \
return sprintf(buf, "%04x\n", input_dev->id.name); \
} \
static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
INPUT_DEV_ID_ATTR(bustype);
INPUT_DEV_ID_ATTR(vendor);
INPUT_DEV_ID_ATTR(product);
INPUT_DEV_ID_ATTR(version);
static struct attribute *input_dev_id_attrs[] = {
&class_device_attr_bustype.attr,
&class_device_attr_vendor.attr,
&class_device_attr_product.attr,
&class_device_attr_version.attr,
NULL
};
static struct attribute_group input_dev_id_attr_group = {
.name = "id",
.attrs = input_dev_id_attrs,
};
#define INPUT_DEV_CAP_ATTR(ev, bm) \
static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \
{ \
struct input_dev *input_dev = to_input_dev(dev); \
return input_print_bitmap(buf, PAGE_SIZE, input_dev->bm##bit, ev##_MAX);\
} \
static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
INPUT_DEV_CAP_ATTR(EV, ev);
INPUT_DEV_CAP_ATTR(KEY, key);
INPUT_DEV_CAP_ATTR(REL, rel);
INPUT_DEV_CAP_ATTR(ABS, abs);
INPUT_DEV_CAP_ATTR(MSC, msc);
INPUT_DEV_CAP_ATTR(LED, led);
INPUT_DEV_CAP_ATTR(SND, snd);
INPUT_DEV_CAP_ATTR(FF, ff);
INPUT_DEV_CAP_ATTR(SW, sw);
static struct attribute *input_dev_caps_attrs[] = {
&class_device_attr_ev.attr,
&class_device_attr_key.attr,
&class_device_attr_rel.attr,
&class_device_attr_abs.attr,
&class_device_attr_msc.attr,
&class_device_attr_led.attr,
&class_device_attr_snd.attr,
&class_device_attr_ff.attr,
&class_device_attr_sw.attr,
NULL
};
static struct attribute_group input_dev_caps_attr_group = {
.name = "capabilities",
.attrs = input_dev_caps_attrs,
};
static void input_dev_release(struct class_device *class_dev)
{
struct input_dev *dev = to_input_dev(class_dev);
kfree(dev);
module_put(THIS_MODULE);
}
/*
* Input hotplugging interface - loading event handlers based on
* device bitfields.
*/
static int input_add_hotplug_bm_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len,
const char *name, unsigned long *bitmap, int max)
{
if (*cur_index >= num_envp - 1)
return -ENOMEM;
envp[*cur_index] = buffer + *cur_len;
*cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name);
if (*cur_len > buffer_size)
return -ENOMEM;
*cur_len += input_print_bitmap(buffer + *cur_len,
max(buffer_size - *cur_len, 0),
bitmap, max) + 1;
if (*cur_len > buffer_size)
return -ENOMEM;
(*cur_index)++;
return 0;
}
#define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \
do { \
int err = add_hotplug_env_var(envp, num_envp, &i, \
buffer, buffer_size, &len, \
fmt, val); \
if (err) \
return err; \
} while (0)
#define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \
do { \
int err = input_add_hotplug_bm_var(envp, num_envp, &i, \
buffer, buffer_size, &len, \
name, bm, max); \
if (err) \
return err; \
} while (0)
static int input_dev_hotplug(struct class_device *cdev, char **envp,
int num_envp, char *buffer, int buffer_size)
{
struct input_dev *dev = to_input_dev(cdev);
int i = 0;
int len = 0;
INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x",
dev->id.bustype, dev->id.vendor,
dev->id.product, dev->id.version);
if (dev->name)
INPUT_ADD_HOTPLUG_VAR("NAME=\"%s\"", dev->name);
if (dev->phys)
INPUT_ADD_HOTPLUG_VAR("PHYS=\"%s\"", dev->phys);
if (dev->phys)
INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq);
INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX);
if (test_bit(EV_KEY, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX);
if (test_bit(EV_REL, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("REL=", dev->relbit, REL_MAX);
if (test_bit(EV_ABS, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("ABS=", dev->absbit, ABS_MAX);
if (test_bit(EV_MSC, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("MSC=", dev->mscbit, MSC_MAX);
if (test_bit(EV_LED, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("LED=", dev->ledbit, LED_MAX);
if (test_bit(EV_SND, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("SND=", dev->sndbit, SND_MAX);
if (test_bit(EV_FF, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("FF=", dev->ffbit, FF_MAX);
if (test_bit(EV_SW, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
envp[i] = NULL;
return 0;
}
struct class input_class = {
.name = "input",
.release = input_dev_release,
.hotplug = input_dev_hotplug,
};
struct input_dev *input_allocate_device(void)
{
struct input_dev *dev;
dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
if (dev) {
dev->dynalloc = 1;
dev->cdev.class = &input_class;
class_device_initialize(&dev->cdev);
INIT_LIST_HEAD(&dev->h_list);
INIT_LIST_HEAD(&dev->node);
}
return dev;
}
static void input_register_classdevice(struct input_dev *dev)
{
static atomic_t input_no = ATOMIC_INIT(0);
const char *path;
__module_get(THIS_MODULE);
dev->dev = dev->cdev.dev;
snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
"input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
path = kobject_get_path(&dev->cdev.class->subsys.kset.kobj, GFP_KERNEL);
printk(KERN_INFO "input: %s/%s as %s\n",
dev->name ? dev->name : "Unspecified device",
path ? path : "", dev->cdev.class_id);
kfree(path);
class_device_add(&dev->cdev);
sysfs_create_group(&dev->cdev.kobj, &input_dev_group);
sysfs_create_group(&dev->cdev.kobj, &input_dev_id_attr_group);
sysfs_create_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
}
void input_register_device(struct input_dev *dev) void input_register_device(struct input_dev *dev)
{ {
struct input_handle *handle; struct input_handle *handle;
@ -632,15 +767,15 @@ void input_register_device(struct input_dev *dev)
INIT_LIST_HEAD(&dev->h_list); INIT_LIST_HEAD(&dev->h_list);
list_add_tail(&dev->node, &input_dev_list); list_add_tail(&dev->node, &input_dev_list);
if (dev->dynalloc)
input_register_classdevice(dev);
list_for_each_entry(handler, &input_handler_list, node) list_for_each_entry(handler, &input_handler_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((id = input_match_device(handler->id_table, dev))) if ((id = input_match_device(handler->id_table, dev)))
if ((handle = handler->connect(handler, dev, id))) if ((handle = handler->connect(handler, dev, id)))
input_link_handle(handle); input_link_handle(handle);
#ifdef CONFIG_HOTPLUG
input_call_hotplug("add", dev);
#endif
input_wakeup_procfs_readers(); input_wakeup_procfs_readers();
} }
@ -660,12 +795,14 @@ void input_unregister_device(struct input_dev *dev)
handle->handler->disconnect(handle); handle->handler->disconnect(handle);
} }
#ifdef CONFIG_HOTPLUG
input_call_hotplug("remove", dev);
#endif
list_del_init(&dev->node); list_del_init(&dev->node);
if (dev->dynalloc) {
sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
class_device_unregister(&dev->cdev);
}
input_wakeup_procfs_readers(); input_wakeup_procfs_readers();
} }
@ -748,16 +885,14 @@ static struct file_operations input_fops = {
.open = input_open_file, .open = input_open_file,
}; };
struct class *input_class;
static int __init input_init(void) static int __init input_init(void)
{ {
int err; int err;
input_class = class_create(THIS_MODULE, "input"); err = class_register(&input_class);
if (IS_ERR(input_class)) { if (err) {
printk(KERN_ERR "input: unable to register input class\n"); printk(KERN_ERR "input: unable to register input_dev class\n");
return PTR_ERR(input_class); return err;
} }
err = input_proc_init(); err = input_proc_init();
@ -770,24 +905,18 @@ static int __init input_init(void)
goto fail2; goto fail2;
} }
err = devfs_mk_dir("input");
if (err)
goto fail3;
return 0; return 0;
fail3: unregister_chrdev(INPUT_MAJOR, "input");
fail2: input_proc_exit(); fail2: input_proc_exit();
fail1: class_destroy(input_class); fail1: class_unregister(&input_class);
return err; return err;
} }
static void __exit input_exit(void) static void __exit input_exit(void)
{ {
input_proc_exit(); input_proc_exit();
devfs_remove("input");
unregister_chrdev(INPUT_MAJOR, "input"); unregister_chrdev(INPUT_MAJOR, "input");
class_destroy(input_class); class_unregister(&input_class);
} }
subsys_initcall(input_init); subsys_initcall(input_init);

View file

@ -26,7 +26,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/devfs_fs_kernel.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Joystick device interfaces"); MODULE_DESCRIPTION("Joystick device interfaces");
@ -449,6 +448,7 @@ static struct file_operations joydev_fops = {
static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id) static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{ {
struct joydev *joydev; struct joydev *joydev;
struct class_device *cdev;
int i, j, t, minor; int i, j, t, minor;
for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++); for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
@ -514,11 +514,13 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
joydev_table[minor] = joydev; joydev_table[minor] = joydev;
devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor), cdev = class_device_create(&input_class, &dev->cdev,
S_IFCHR|S_IRUGO|S_IWUSR, "input/js%d", minor);
class_device_create(input_class,
MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor), MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
dev->dev, "js%d", minor); dev->cdev.dev, joydev->name);
/* temporary symlink to keep userspace happy */
sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
joydev->name);
return &joydev->handle; return &joydev->handle;
} }
@ -528,8 +530,8 @@ static void joydev_disconnect(struct input_handle *handle)
struct joydev *joydev = handle->private; struct joydev *joydev = handle->private;
struct joydev_list *list; struct joydev_list *list;
class_device_destroy(input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor)); sysfs_remove_link(&input_class.subsys.kset.kobj, joydev->name);
devfs_remove("input/js%d", joydev->minor); class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
joydev->exist = 0; joydev->exist = 0;
if (joydev->open) { if (joydev->open) {

View file

@ -54,7 +54,7 @@ MODULE_LICENSE("GPL");
#define ADI_MIN_LENGTH 8 #define ADI_MIN_LENGTH 8
#define ADI_MIN_LEN_LENGTH 10 #define ADI_MIN_LEN_LENGTH 10
#define ADI_MIN_ID_LENGTH 66 #define ADI_MIN_ID_LENGTH 66
#define ADI_MAX_NAME_LENGTH 48 #define ADI_MAX_NAME_LENGTH 64
#define ADI_MAX_CNAME_LENGTH 16 #define ADI_MAX_CNAME_LENGTH 16
#define ADI_MAX_PHYS_LENGTH 64 #define ADI_MAX_PHYS_LENGTH 64
@ -106,7 +106,7 @@ static struct {
*/ */
struct adi { struct adi {
struct input_dev dev; struct input_dev *dev;
int length; int length;
int ret; int ret;
int idx; int idx;
@ -215,7 +215,7 @@ static inline int adi_get_bits(struct adi *adi, int count)
static int adi_decode(struct adi *adi) static int adi_decode(struct adi *adi)
{ {
struct input_dev *dev = &adi->dev; struct input_dev *dev = adi->dev;
char *abs = adi->abs; char *abs = adi->abs;
short *key = adi->key; short *key = adi->key;
int i, t; int i, t;
@ -318,7 +318,8 @@ static void adi_init_digital(struct gameport *gameport)
for (i = 0; seq[i]; i++) { for (i = 0; seq[i]; i++) {
gameport_trigger(gameport); gameport_trigger(gameport);
if (seq[i] > 0) msleep(seq[i]); if (seq[i] > 0)
msleep(seq[i]);
if (seq[i] < 0) { if (seq[i] < 0) {
mdelay(-seq[i]); mdelay(-seq[i]);
udelay(-seq[i]*14); /* It looks like mdelay() is off by approx 1.4% */ udelay(-seq[i]*14); /* It looks like mdelay() is off by approx 1.4% */
@ -397,42 +398,46 @@ static void adi_id_decode(struct adi *adi, struct adi_port *port)
} }
} }
static void adi_init_input(struct adi *adi, struct adi_port *port, int half) static int adi_init_input(struct adi *adi, struct adi_port *port, int half)
{ {
int i, t; struct input_dev *input_dev;
char buf[ADI_MAX_NAME_LENGTH]; char buf[ADI_MAX_NAME_LENGTH];
int i, t;
if (!adi->length) return; adi->dev = input_dev = input_allocate_device();
if (!input_dev)
init_input_dev(&adi->dev); return -ENOMEM;
t = adi->id < ADI_ID_MAX ? adi->id : ADI_ID_MAX; t = adi->id < ADI_ID_MAX ? adi->id : ADI_ID_MAX;
snprintf(buf, ADI_MAX_PHYS_LENGTH, adi_names[t], adi->id); snprintf(buf, ADI_MAX_PHYS_LENGTH, adi_names[t], adi->id);
snprintf(adi->name, ADI_MAX_NAME_LENGTH, "Logitech %s", buf); snprintf(adi->name, ADI_MAX_NAME_LENGTH, "Logitech %s [%s]", buf, adi->cname);
snprintf(adi->phys, ADI_MAX_PHYS_LENGTH, "%s/input%d", port->gameport->phys, half); snprintf(adi->phys, ADI_MAX_PHYS_LENGTH, "%s/input%d", port->gameport->phys, half);
adi->abs = adi_abs[t]; adi->abs = adi_abs[t];
adi->key = adi_key[t]; adi->key = adi_key[t];
adi->dev.open = adi_open; input_dev->name = adi->name;
adi->dev.close = adi_close; input_dev->phys = adi->phys;
input_dev->id.bustype = BUS_GAMEPORT;
input_dev->id.vendor = GAMEPORT_ID_VENDOR_LOGITECH;
input_dev->id.product = adi->id;
input_dev->id.version = 0x0100;
input_dev->cdev.dev = &port->gameport->dev;
input_dev->private = port;
adi->dev.name = adi->name; input_dev->open = adi_open;
adi->dev.phys = adi->phys; input_dev->close = adi_close;
adi->dev.id.bustype = BUS_GAMEPORT;
adi->dev.id.vendor = GAMEPORT_ID_VENDOR_LOGITECH;
adi->dev.id.product = adi->id;
adi->dev.id.version = 0x0100;
adi->dev.private = port; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
adi->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++)
set_bit(adi->abs[i], adi->dev.absbit); set_bit(adi->abs[i], input_dev->absbit);
for (i = 0; i < adi->buttons; i++) for (i = 0; i < adi->buttons; i++)
set_bit(adi->key[i], adi->dev.keybit); set_bit(adi->key[i], input_dev->keybit);
return 0;
} }
static void adi_init_center(struct adi *adi) static void adi_init_center(struct adi *adi)
@ -445,17 +450,17 @@ static void adi_init_center(struct adi *adi)
for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) { for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) {
t = adi->abs[i]; t = adi->abs[i];
x = adi->dev.abs[t]; x = adi->dev->abs[t];
if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE) if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE)
x = i < adi->axes10 ? 512 : 128; x = i < adi->axes10 ? 512 : 128;
if (i < adi->axes10) if (i < adi->axes10)
input_set_abs_params(&adi->dev, t, 64, x * 2 - 64, 2, 16); input_set_abs_params(adi->dev, t, 64, x * 2 - 64, 2, 16);
else if (i < adi->axes10 + adi->axes8) else if (i < adi->axes10 + adi->axes8)
input_set_abs_params(&adi->dev, t, 48, x * 2 - 48, 1, 16); input_set_abs_params(adi->dev, t, 48, x * 2 - 48, 1, 16);
else else
input_set_abs_params(&adi->dev, t, -1, 1, 0, 0); input_set_abs_params(adi->dev, t, -1, 1, 0, 0);
} }
} }
@ -469,7 +474,8 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
int i; int i;
int err; int err;
if (!(port = kzalloc(sizeof(struct adi_port), GFP_KERNEL))) port = kzalloc(sizeof(struct adi_port), GFP_KERNEL);
if (!port)
return -ENOMEM; return -ENOMEM;
port->gameport = gameport; port->gameport = gameport;
@ -477,10 +483,8 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
gameport_set_drvdata(gameport, port); gameport_set_drvdata(gameport, port);
err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW); err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
if (err) { if (err)
kfree(port); goto fail1;
return err;
}
adi_init_digital(gameport); adi_init_digital(gameport);
adi_read_packet(port); adi_read_packet(port);
@ -490,13 +494,18 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
adi_id_decode(port->adi + i, port); adi_id_decode(port->adi + i, port);
adi_init_input(port->adi + i, port, i);
if (!port->adi[i].length)
continue;
err = adi_init_input(port->adi + i, port, i);
if (err)
goto fail2;
} }
if (!port->adi[0].length && !port->adi[1].length) { if (!port->adi[0].length && !port->adi[1].length) {
gameport_close(gameport); err = -ENODEV;
kfree(port); goto fail2;
return -ENODEV;
} }
gameport_set_poll_handler(gameport, adi_poll); gameport_set_poll_handler(gameport, adi_poll);
@ -511,12 +520,18 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
if (port->adi[i].length > 0) { if (port->adi[i].length > 0) {
adi_init_center(port->adi + i); adi_init_center(port->adi + i);
input_register_device(&port->adi[i].dev); input_register_device(port->adi[i].dev);
printk(KERN_INFO "input: %s [%s] on %s\n",
port->adi[i].name, port->adi[i].cname, gameport->phys);
} }
return 0; return 0;
fail2: for (i = 0; i < 2; i++)
if (port->adi[i].dev)
input_free_device(port->adi[i].dev);
gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL);
kfree(port);
return err;
} }
static void adi_disconnect(struct gameport *gameport) static void adi_disconnect(struct gameport *gameport)
@ -526,7 +541,7 @@ static void adi_disconnect(struct gameport *gameport)
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
if (port->adi[i].length > 0) if (port->adi[i].length > 0)
input_unregister_device(&port->adi[i].dev); input_unregister_device(port->adi[i].dev);
gameport_close(gameport); gameport_close(gameport);
gameport_set_drvdata(gameport, NULL); gameport_set_drvdata(gameport, NULL);
kfree(port); kfree(port);

View file

@ -53,11 +53,9 @@ __obsolete_setup("amijoy=");
static int amijoy_used; static int amijoy_used;
static DECLARE_MUTEX(amijoy_sem); static DECLARE_MUTEX(amijoy_sem);
static struct input_dev amijoy_dev[2]; static struct input_dev *amijoy_dev[2];
static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" }; static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
static char *amijoy_name = "Amiga joystick";
static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp) static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
{ {
int i, data = 0, button = 0; int i, data = 0, button = 0;
@ -70,15 +68,15 @@ static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
case 1: data = ~custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break; case 1: data = ~custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break;
} }
input_regs(amijoy_dev + i, fp); input_regs(amijoy_dev[i], fp);
input_report_key(amijoy_dev + i, BTN_TRIGGER, button); input_report_key(amijoy_dev[i], BTN_TRIGGER, button);
input_report_abs(amijoy_dev + i, ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1)); input_report_abs(amijoy_dev[i], ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1));
data = ~(data ^ (data << 1)); data = ~(data ^ (data << 1));
input_report_abs(amijoy_dev + i, ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1)); input_report_abs(amijoy_dev[i], ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1));
input_sync(amijoy_dev + i); input_sync(amijoy_dev[i]);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -114,39 +112,52 @@ static void amijoy_close(struct input_dev *dev)
static int __init amijoy_init(void) static int __init amijoy_init(void)
{ {
int i, j; int i, j;
int err;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++) {
if (amijoy[i]) { if (!amijoy[i])
if (!request_mem_region(CUSTOM_PHYSADDR+10+i*2, 2, continue;
"amijoy [Denise]")) {
if (i == 1 && amijoy[0]) { amijoy_dev[i] = input_allocate_device();
input_unregister_device(amijoy_dev); if (!amijoy_dev[i]) {
release_mem_region(CUSTOM_PHYSADDR+10, 2); err = -ENOMEM;
} goto fail;
return -EBUSY;
} }
amijoy_dev[i].open = amijoy_open; if (!request_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2, "amijoy [Denise]")) {
amijoy_dev[i].close = amijoy_close; input_free_device(amijoy_dev[i]);
amijoy_dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); err = -EBUSY;
amijoy_dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y); goto fail;
amijoy_dev[i].keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); }
amijoy_dev[i]->name = "Amiga joystick";
amijoy_dev[i]->phys = amijoy_phys[i];
amijoy_dev[i]->id.bustype = BUS_AMIGA;
amijoy_dev[i]->id.vendor = 0x0001;
amijoy_dev[i]->id.product = 0x0003;
amijoy_dev[i]->id.version = 0x0100;
amijoy_dev[i]->open = amijoy_open;
amijoy_dev[i]->close = amijoy_close;
amijoy_dev[i]->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
amijoy_dev[i]->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
amijoy_dev[i]->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
for (j = 0; j < 2; j++) { for (j = 0; j < 2; j++) {
amijoy_dev[i].absmin[ABS_X + j] = -1; amijoy_dev[i]->absmin[ABS_X + j] = -1;
amijoy_dev[i].absmax[ABS_X + j] = 1; amijoy_dev[i]->absmax[ABS_X + j] = 1;
} }
amijoy_dev[i].name = amijoy_name; input_register_device(amijoy_dev[i]);
amijoy_dev[i].phys = amijoy_phys[i];
amijoy_dev[i].id.bustype = BUS_AMIGA;
amijoy_dev[i].id.vendor = 0x0001;
amijoy_dev[i].id.product = 0x0003;
amijoy_dev[i].id.version = 0x0100;
input_register_device(amijoy_dev + i);
printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i);
} }
return 0; return 0;
fail: while (--i >= 0)
if (amijoy[i]) {
input_unregister_device(amijoy_dev[i]);
release_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2);
}
return err;
} }
static void __exit amijoy_exit(void) static void __exit amijoy_exit(void)
@ -155,8 +166,8 @@ static void __exit amijoy_exit(void)
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
if (amijoy[i]) { if (amijoy[i]) {
input_unregister_device(amijoy_dev + i); input_unregister_device(amijoy_dev[i]);
release_mem_region(CUSTOM_PHYSADDR+10+i*2, 2); release_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2);
} }
} }

View file

@ -111,7 +111,7 @@ static short analog_joy_btn[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN
static unsigned char analog_chf[] = { 0xf, 0x0, 0x1, 0x9, 0x2, 0x4, 0xc, 0x8, 0x3, 0x5, 0xb, 0x7, 0xd, 0xe, 0xa, 0x6 }; static unsigned char analog_chf[] = { 0xf, 0x0, 0x1, 0x9, 0x2, 0x4, 0xc, 0x8, 0x3, 0x5, 0xb, 0x7, 0xd, 0xe, 0xa, 0x6 };
struct analog { struct analog {
struct input_dev dev; struct input_dev *dev;
int mask; int mask;
short *buttons; short *buttons;
char name[ANALOG_MAX_NAME_LENGTH]; char name[ANALOG_MAX_NAME_LENGTH];
@ -182,7 +182,7 @@ static unsigned long analog_faketime = 0;
static void analog_decode(struct analog *analog, int *axes, int *initial, int buttons) static void analog_decode(struct analog *analog, int *axes, int *initial, int buttons)
{ {
struct input_dev *dev = &analog->dev; struct input_dev *dev = analog->dev;
int i, j; int i, j;
if (analog->mask & ANALOG_HAT_FCS) if (analog->mask & ANALOG_HAT_FCS)
@ -428,27 +428,30 @@ static void analog_name(struct analog *analog)
* analog_init_device() * analog_init_device()
*/ */
static void analog_init_device(struct analog_port *port, struct analog *analog, int index) static int analog_init_device(struct analog_port *port, struct analog *analog, int index)
{ {
struct input_dev *input_dev;
int i, j, t, v, w, x, y, z; int i, j, t, v, w, x, y, z;
analog_name(analog); analog_name(analog);
sprintf(analog->phys, "%s/input%d", port->gameport->phys, index); sprintf(analog->phys, "%s/input%d", port->gameport->phys, index);
analog->buttons = (analog->mask & ANALOG_GAMEPAD) ? analog_pad_btn : analog_joy_btn; analog->buttons = (analog->mask & ANALOG_GAMEPAD) ? analog_pad_btn : analog_joy_btn;
init_input_dev(&analog->dev); analog->dev = input_dev = input_allocate_device();
if (!input_dev)
return -ENOMEM;
analog->dev.name = analog->name; input_dev->name = analog->name;
analog->dev.phys = analog->phys; input_dev->phys = analog->phys;
analog->dev.id.bustype = BUS_GAMEPORT; input_dev->id.bustype = BUS_GAMEPORT;
analog->dev.id.vendor = GAMEPORT_ID_VENDOR_ANALOG; input_dev->id.vendor = GAMEPORT_ID_VENDOR_ANALOG;
analog->dev.id.product = analog->mask >> 4; input_dev->id.product = analog->mask >> 4;
analog->dev.id.version = 0x0100; input_dev->id.version = 0x0100;
analog->dev.open = analog_open; input_dev->open = analog_open;
analog->dev.close = analog_close; input_dev->close = analog_close;
analog->dev.private = port; input_dev->private = port;
analog->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = j = 0; i < 4; i++) for (i = j = 0; i < 4; i++)
if (analog->mask & (1 << i)) { if (analog->mask & (1 << i)) {
@ -461,8 +464,6 @@ static void analog_init_device(struct analog_port *port, struct analog *analog,
v = (x >> 3); v = (x >> 3);
w = (x >> 3); w = (x >> 3);
set_bit(t, analog->dev.absbit);
if ((i == 2 || i == 3) && (j == 2 || j == 3) && (z > (y >> 3))) if ((i == 2 || i == 3) && (j == 2 || j == 3) && (z > (y >> 3)))
x = y; x = y;
@ -472,11 +473,7 @@ static void analog_init_device(struct analog_port *port, struct analog *analog,
w = (x >> 4); w = (x >> 4);
} }
analog->dev.absmax[t] = (x << 1) - v; input_set_abs_params(input_dev, t, v, (x << 1) - v, port->fuzz, w);
analog->dev.absmin[t] = v;
analog->dev.absfuzz[t] = port->fuzz;
analog->dev.absflat[t] = w;
j++; j++;
} }
@ -484,41 +481,30 @@ static void analog_init_device(struct analog_port *port, struct analog *analog,
if (analog->mask & analog_exts[i]) if (analog->mask & analog_exts[i])
for (x = 0; x < 2; x++) { for (x = 0; x < 2; x++) {
t = analog_hats[j++]; t = analog_hats[j++];
set_bit(t, analog->dev.absbit); input_set_abs_params(input_dev, t, -1, 1, 0, 0);
analog->dev.absmax[t] = 1;
analog->dev.absmin[t] = -1;
} }
for (i = j = 0; i < 4; i++) for (i = j = 0; i < 4; i++)
if (analog->mask & (0x10 << i)) if (analog->mask & (0x10 << i))
set_bit(analog->buttons[j++], analog->dev.keybit); set_bit(analog->buttons[j++], input_dev->keybit);
if (analog->mask & ANALOG_BTNS_CHF) if (analog->mask & ANALOG_BTNS_CHF)
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
set_bit(analog->buttons[j++], analog->dev.keybit); set_bit(analog->buttons[j++], input_dev->keybit);
if (analog->mask & ANALOG_HBTN_CHF) if (analog->mask & ANALOG_HBTN_CHF)
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
set_bit(analog->buttons[j++], analog->dev.keybit); set_bit(analog->buttons[j++], input_dev->keybit);
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
if (analog->mask & (ANALOG_BTN_TL << i)) if (analog->mask & (ANALOG_BTN_TL << i))
set_bit(analog_pads[i], analog->dev.keybit); set_bit(analog_pads[i], input_dev->keybit);
analog_decode(analog, port->axes, port->initial, port->buttons); analog_decode(analog, port->axes, port->initial, port->buttons);
input_register_device(&analog->dev); input_register_device(analog->dev);
printk(KERN_INFO "input: %s at %s", analog->name, port->gameport->phys); return 0;
if (port->cooked)
printk(" [ADC port]\n");
else
printk(" [%s timer, %d %sHz clock, %d ns res]\n", TIME_NAME,
port->speed > 10000 ? (port->speed + 800) / 1000 : port->speed,
port->speed > 10000 ? "M" : "k",
port->speed > 10000 ? (port->loop * 1000) / (port->speed / 1000)
: (port->loop * 1000000) / port->speed);
} }
/* /*
@ -659,37 +645,41 @@ static int analog_connect(struct gameport *gameport, struct gameport_driver *drv
return - ENOMEM; return - ENOMEM;
err = analog_init_port(gameport, drv, port); err = analog_init_port(gameport, drv, port);
if (err) { if (err)
kfree(port); goto fail1;
return err;
}
err = analog_init_masks(port); err = analog_init_masks(port);
if (err) { if (err)
gameport_close(gameport); goto fail2;
gameport_set_drvdata(gameport, NULL);
kfree(port);
return err;
}
gameport_set_poll_handler(gameport, analog_poll); gameport_set_poll_handler(gameport, analog_poll);
gameport_set_poll_interval(gameport, 10); gameport_set_poll_interval(gameport, 10);
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
if (port->analog[i].mask) if (port->analog[i].mask) {
analog_init_device(port, port->analog + i, i); err = analog_init_device(port, port->analog + i, i);
if (err)
goto fail3;
}
return 0; return 0;
fail3: while (--i >= 0)
input_unregister_device(port->analog[i].dev);
fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL);
kfree(port);
return err;
} }
static void analog_disconnect(struct gameport *gameport) static void analog_disconnect(struct gameport *gameport)
{ {
int i;
struct analog_port *port = gameport_get_drvdata(gameport); struct analog_port *port = gameport_get_drvdata(gameport);
int i;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
if (port->analog[i].mask) if (port->analog[i].mask)
input_unregister_device(&port->analog[i].dev); input_unregister_device(port->analog[i].dev);
gameport_close(gameport); gameport_close(gameport);
gameport_set_drvdata(gameport, NULL); gameport_set_drvdata(gameport, NULL);
printk(KERN_INFO "analog.c: %d out of %d reads (%d%%) on %s failed\n", printk(KERN_INFO "analog.c: %d out of %d reads (%d%%) on %s failed\n",

View file

@ -44,13 +44,11 @@ MODULE_LICENSE("GPL");
#define COBRA_MAX_STROBE 45 /* 45 us max wait for first strobe */ #define COBRA_MAX_STROBE 45 /* 45 us max wait for first strobe */
#define COBRA_LENGTH 36 #define COBRA_LENGTH 36
static char* cobra_name = "Creative Labs Blaster GamePad Cobra";
static int cobra_btn[] = { BTN_START, BTN_SELECT, BTN_TL, BTN_TR, BTN_X, BTN_Y, BTN_Z, BTN_A, BTN_B, BTN_C, BTN_TL2, BTN_TR2, 0 }; static int cobra_btn[] = { BTN_START, BTN_SELECT, BTN_TL, BTN_TR, BTN_X, BTN_Y, BTN_Z, BTN_A, BTN_B, BTN_C, BTN_TL2, BTN_TR2, 0 };
struct cobra { struct cobra {
struct gameport *gameport; struct gameport *gameport;
struct input_dev dev[2]; struct input_dev *dev[2];
int reads; int reads;
int bads; int bads;
unsigned char exists; unsigned char exists;
@ -128,7 +126,7 @@ static void cobra_poll(struct gameport *gameport)
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
if (cobra->exists & r & (1 << i)) { if (cobra->exists & r & (1 << i)) {
dev = cobra->dev + i; dev = cobra->dev[i];
input_report_abs(dev, ABS_X, ((data[i] >> 4) & 1) - ((data[i] >> 3) & 1)); input_report_abs(dev, ABS_X, ((data[i] >> 4) & 1) - ((data[i] >> 3) & 1));
input_report_abs(dev, ABS_Y, ((data[i] >> 2) & 1) - ((data[i] >> 1) & 1)); input_report_abs(dev, ABS_Y, ((data[i] >> 2) & 1) - ((data[i] >> 1) & 1));
@ -159,11 +157,13 @@ static void cobra_close(struct input_dev *dev)
static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv) static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
{ {
struct cobra *cobra; struct cobra *cobra;
struct input_dev *input_dev;
unsigned int data[2]; unsigned int data[2];
int i, j; int i, j;
int err; int err;
if (!(cobra = kzalloc(sizeof(struct cobra), GFP_KERNEL))) cobra = kzalloc(sizeof(struct cobra), GFP_KERNEL);
if (!cobra)
return -ENOMEM; return -ENOMEM;
cobra->gameport = gameport; cobra->gameport = gameport;
@ -191,38 +191,46 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
gameport_set_poll_handler(gameport, cobra_poll); gameport_set_poll_handler(gameport, cobra_poll);
gameport_set_poll_interval(gameport, 20); gameport_set_poll_interval(gameport, 20);
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++) {
if ((cobra->exists >> i) & 1) { if (~(cobra->exists >> i) & 1)
continue;
cobra->dev[i] = input_dev = input_allocate_device();
if (!input_dev) {
err = -ENOMEM;
goto fail3;
}
sprintf(cobra->phys[i], "%s/input%d", gameport->phys, i); sprintf(cobra->phys[i], "%s/input%d", gameport->phys, i);
cobra->dev[i].private = cobra; input_dev->name = "Creative Labs Blaster GamePad Cobra";
cobra->dev[i].open = cobra_open; input_dev->phys = cobra->phys[i];
cobra->dev[i].close = cobra_close; input_dev->id.bustype = BUS_GAMEPORT;
input_dev->id.vendor = GAMEPORT_ID_VENDOR_CREATIVE;
input_dev->id.product = 0x0008;
input_dev->id.version = 0x0100;
input_dev->cdev.dev = &gameport->dev;
input_dev->private = cobra;
cobra->dev[i].name = cobra_name; input_dev->open = cobra_open;
cobra->dev[i].phys = cobra->phys[i]; input_dev->close = cobra_close;
cobra->dev[i].id.bustype = BUS_GAMEPORT;
cobra->dev[i].id.vendor = GAMEPORT_ID_VENDOR_CREATIVE;
cobra->dev[i].id.product = 0x0008;
cobra->dev[i].id.version = 0x0100;
cobra->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
input_set_abs_params(&cobra->dev[i], ABS_X, -1, 1, 0, 0);
input_set_abs_params(&cobra->dev[i], ABS_Y, -1, 1, 0, 0);
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
input_set_abs_params(input_dev, ABS_X, -1, 1, 0, 0);
input_set_abs_params(input_dev, ABS_Y, -1, 1, 0, 0);
for (j = 0; cobra_btn[j]; j++) for (j = 0; cobra_btn[j]; j++)
set_bit(cobra_btn[j], cobra->dev[i].keybit); set_bit(cobra_btn[j], input_dev->keybit);
input_register_device(&cobra->dev[i]); input_register_device(cobra->dev[i]);
printk(KERN_INFO "input: %s on %s\n", cobra_name, gameport->phys);
} }
return 0; return 0;
fail2: gameport_close(gameport); fail3: for (i = 0; i < 2; i++)
fail1: gameport_set_drvdata(gameport, NULL); if (cobra->dev[i])
input_unregister_device(cobra->dev[i]);
fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL);
kfree(cobra); kfree(cobra);
return err; return err;
} }
@ -234,7 +242,7 @@ static void cobra_disconnect(struct gameport *gameport)
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
if ((cobra->exists >> i) & 1) if ((cobra->exists >> i) & 1)
input_unregister_device(cobra->dev + i); input_unregister_device(cobra->dev[i]);
gameport_close(gameport); gameport_close(gameport);
gameport_set_drvdata(gameport, NULL); gameport_set_drvdata(gameport, NULL);
kfree(cobra); kfree(cobra);

View file

@ -43,25 +43,28 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver"); MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static int db9[] __initdata = { -1, 0 }; struct db9_config {
static int db9_nargs __initdata = 0; int args[2];
module_param_array_named(dev, db9, int, &db9_nargs, 0); int nargs;
};
#define DB9_MAX_PORTS 3
static struct db9_config db9[DB9_MAX_PORTS] __initdata;
module_param_array_named(dev, db9[0].args, int, &db9[0].nargs, 0);
MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)"); MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
module_param_array_named(dev2, db9[1].args, int, &db9[0].nargs, 0);
static int db9_2[] __initdata = { -1, 0 };
static int db9_nargs_2 __initdata = 0;
module_param_array_named(dev2, db9_2, int, &db9_nargs_2, 0);
MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)"); MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)");
module_param_array_named(dev3, db9[2].args, int, &db9[2].nargs, 0);
static int db9_3[] __initdata = { -1, 0 };
static int db9_nargs_3 __initdata = 0;
module_param_array_named(dev3, db9_3, int, &db9_nargs_3, 0);
MODULE_PARM_DESC(dev3, "Describes third attached device (<parport#>,<type>)"); MODULE_PARM_DESC(dev3, "Describes third attached device (<parport#>,<type>)");
__obsolete_setup("db9="); __obsolete_setup("db9=");
__obsolete_setup("db9_2="); __obsolete_setup("db9_2=");
__obsolete_setup("db9_3="); __obsolete_setup("db9_3=");
#define DB9_ARG_PARPORT 0
#define DB9_ARG_MODE 1
#define DB9_MULTI_STICK 0x01 #define DB9_MULTI_STICK 0x01
#define DB9_MULTI2_STICK 0x02 #define DB9_MULTI2_STICK 0x02
#define DB9_GENESIS_PAD 0x03 #define DB9_GENESIS_PAD 0x03
@ -87,40 +90,53 @@ __obsolete_setup("db9_3=");
#define DB9_NORMAL 0x0a #define DB9_NORMAL 0x0a
#define DB9_NOSELECT 0x08 #define DB9_NOSELECT 0x08
#define DB9_MAX_DEVICES 2
#define DB9_GENESIS6_DELAY 14 #define DB9_GENESIS6_DELAY 14
#define DB9_REFRESH_TIME HZ/100 #define DB9_REFRESH_TIME HZ/100
#define DB9_MAX_DEVICES 2
struct db9_mode_data {
const char *name;
const short *buttons;
int n_buttons;
int n_pads;
int n_axis;
int bidirectional;
int reverse;
};
struct db9 { struct db9 {
struct input_dev dev[DB9_MAX_DEVICES]; struct input_dev *dev[DB9_MAX_DEVICES];
struct timer_list timer; struct timer_list timer;
struct pardevice *pd; struct pardevice *pd;
int mode; int mode;
int used; int used;
struct semaphore sem; struct semaphore sem;
char phys[2][32]; char phys[DB9_MAX_DEVICES][32];
}; };
static struct db9 *db9_base[3]; static struct db9 *db9_base[3];
static short db9_multi_btn[] = { BTN_TRIGGER, BTN_THUMB }; static const short db9_multi_btn[] = { BTN_TRIGGER, BTN_THUMB };
static short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_MODE }; static const short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_MODE };
static short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START }; static const short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START };
static char db9_buttons[DB9_MAX_PAD] = { 0, 1, 2, 4, 0, 6, 8, 9, 1, 1, 7, 9, 9 };
static short *db9_btn[DB9_MAX_PAD] = { NULL, db9_multi_btn, db9_multi_btn, db9_genesis_btn, NULL, db9_genesis_btn,
db9_genesis_btn, db9_cd32_btn, db9_multi_btn, db9_multi_btn, db9_cd32_btn,
db9_cd32_btn, db9_cd32_btn };
static char *db9_name[DB9_MAX_PAD] = { NULL, "Multisystem joystick", "Multisystem joystick (2 fire)", "Genesis pad",
NULL, "Genesis 5 pad", "Genesis 6 pad", "Saturn pad", "Multisystem (0.8.0.2) joystick",
"Multisystem (0.8.0.2-dual) joystick", "Amiga CD-32 pad", "Saturn dpp", "Saturn dpp dual" };
static const int db9_max_pads[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 6, 1, 2, 1, 6, 12 };
static const int db9_num_axis[DB9_MAX_PAD] = { 0, 2, 2, 2, 0, 2, 2, 7, 2, 2, 2 ,7, 7 };
static const short db9_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_RZ, ABS_Z, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y }; static const short db9_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_RZ, ABS_Z, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
static const int db9_bidirectional[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0 };
static const int db9_reverse[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0 }; static const struct db9_mode_data db9_modes[] = {
{ NULL, NULL, 0, 0, 0, 0, 0 },
{ "Multisystem joystick", db9_multi_btn, 1, 1, 2, 1, 1 },
{ "Multisystem joystick (2 fire)", db9_multi_btn, 2, 1, 2, 1, 1 },
{ "Genesis pad", db9_genesis_btn, 4, 1, 2, 1, 1 },
{ NULL, NULL, 0, 0, 0, 0, 0 },
{ "Genesis 5 pad", db9_genesis_btn, 6, 1, 2, 1, 1 },
{ "Genesis 6 pad", db9_genesis_btn, 8, 1, 2, 1, 1 },
{ "Saturn pad", db9_cd32_btn, 9, 6, 7, 0, 1 },
{ "Multisystem (0.8.0.2) joystick", db9_multi_btn, 1, 1, 2, 1, 1 },
{ "Multisystem (0.8.0.2-dual) joystick", db9_multi_btn, 1, 2, 2, 1, 1 },
{ "Amiga CD-32 pad", db9_cd32_btn, 7, 1, 2, 1, 1 },
{ "Saturn dpp", db9_cd32_btn, 9, 6, 7, 0, 0 },
{ "Saturn dpp dual", db9_cd32_btn, 9, 12, 7, 0, 0 },
};
/* /*
* Saturn controllers * Saturn controllers
@ -342,7 +358,7 @@ static int db9_saturn(int mode, struct parport *port, struct input_dev *dev)
default: default:
return -1; return -1;
} }
max_pads = min(db9_max_pads[mode], DB9_MAX_DEVICES); max_pads = min(db9_modes[mode].n_pads, DB9_MAX_DEVICES);
for (tmp = 0, i = 0; i < n; i++) { for (tmp = 0, i = 0; i < n; i++) {
id = db9_saturn_read_packet(port, data, type + i, 1); id = db9_saturn_read_packet(port, data, type + i, 1);
tmp = db9_saturn_report(id, data, dev, tmp, max_pads); tmp = db9_saturn_report(id, data, dev, tmp, max_pads);
@ -354,17 +370,18 @@ static void db9_timer(unsigned long private)
{ {
struct db9 *db9 = (void *) private; struct db9 *db9 = (void *) private;
struct parport *port = db9->pd->port; struct parport *port = db9->pd->port;
struct input_dev *dev = db9->dev; struct input_dev *dev = db9->dev[0];
struct input_dev *dev2 = db9->dev[1];
int data, i; int data, i;
switch(db9->mode) { switch (db9->mode) {
case DB9_MULTI_0802_2: case DB9_MULTI_0802_2:
data = parport_read_data(port) >> 3; data = parport_read_data(port) >> 3;
input_report_abs(dev + 1, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1)); input_report_abs(dev2, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev + 1, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1)); input_report_abs(dev2, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev + 1, BTN_TRIGGER, ~data & DB9_FIRE1); input_report_key(dev2, BTN_TRIGGER, ~data & DB9_FIRE1);
case DB9_MULTI_0802: case DB9_MULTI_0802:
@ -405,7 +422,7 @@ static void db9_timer(unsigned long private)
input_report_key(dev, BTN_C, ~data & DB9_FIRE2); input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NORMAL); parport_write_control(port, DB9_NORMAL);
data=parport_read_data(port); data = parport_read_data(port);
input_report_key(dev, BTN_A, ~data & DB9_FIRE1); input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_START, ~data & DB9_FIRE2); input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
@ -414,7 +431,7 @@ static void db9_timer(unsigned long private)
case DB9_GENESIS5_PAD: case DB9_GENESIS5_PAD:
parport_write_control(port, DB9_NOSELECT); parport_write_control(port, DB9_NOSELECT);
data=parport_read_data(port); data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1)); input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1)); input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
@ -422,7 +439,7 @@ static void db9_timer(unsigned long private)
input_report_key(dev, BTN_C, ~data & DB9_FIRE2); input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NORMAL); parport_write_control(port, DB9_NORMAL);
data=parport_read_data(port); data = parport_read_data(port);
input_report_key(dev, BTN_A, ~data & DB9_FIRE1); input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_X, ~data & DB9_FIRE2); input_report_key(dev, BTN_X, ~data & DB9_FIRE2);
@ -434,7 +451,7 @@ static void db9_timer(unsigned long private)
parport_write_control(port, DB9_NOSELECT); /* 1 */ parport_write_control(port, DB9_NOSELECT); /* 1 */
udelay(DB9_GENESIS6_DELAY); udelay(DB9_GENESIS6_DELAY);
data=parport_read_data(port); data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1)); input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1)); input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
@ -443,7 +460,7 @@ static void db9_timer(unsigned long private)
parport_write_control(port, DB9_NORMAL); parport_write_control(port, DB9_NORMAL);
udelay(DB9_GENESIS6_DELAY); udelay(DB9_GENESIS6_DELAY);
data=parport_read_data(port); data = parport_read_data(port);
input_report_key(dev, BTN_A, ~data & DB9_FIRE1); input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_START, ~data & DB9_FIRE2); input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
@ -477,7 +494,7 @@ static void db9_timer(unsigned long private)
case DB9_CD32_PAD: case DB9_CD32_PAD:
data=parport_read_data(port); data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1)); input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1)); input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
@ -513,7 +530,7 @@ static int db9_open(struct input_dev *dev)
if (!db9->used++) { if (!db9->used++) {
parport_claim(db9->pd); parport_claim(db9->pd);
parport_write_data(port, 0xff); parport_write_data(port, 0xff);
if (db9_reverse[db9->mode]) { if (db9_modes[db9->mode].reverse) {
parport_data_reverse(port); parport_data_reverse(port);
parport_write_control(port, DB9_NORMAL); parport_write_control(port, DB9_NORMAL);
} }
@ -539,117 +556,160 @@ static void db9_close(struct input_dev *dev)
up(&db9->sem); up(&db9->sem);
} }
static struct db9 __init *db9_probe(int *config, int nargs) static struct db9 __init *db9_probe(int parport, int mode)
{ {
struct db9 *db9; struct db9 *db9;
const struct db9_mode_data *db9_mode;
struct parport *pp; struct parport *pp;
struct pardevice *pd;
struct input_dev *input_dev;
int i, j; int i, j;
int err;
if (config[0] < 0) if (mode < 1 || mode >= DB9_MAX_PAD || !db9_modes[mode].n_buttons) {
return NULL; printk(KERN_ERR "db9.c: Bad device type %d\n", mode);
err = -EINVAL;
if (nargs < 2) { goto err_out;
printk(KERN_ERR "db9.c: Device type must be specified.\n");
return NULL;
} }
if (config[1] < 1 || config[1] >= DB9_MAX_PAD || !db9_buttons[config[1]]) { db9_mode = &db9_modes[mode];
printk(KERN_ERR "db9.c: bad config\n");
return NULL;
}
pp = parport_find_number(config[0]); pp = parport_find_number(parport);
if (!pp) { if (!pp) {
printk(KERN_ERR "db9.c: no such parport\n"); printk(KERN_ERR "db9.c: no such parport\n");
return NULL; err = -ENODEV;
goto err_out;
} }
if (db9_bidirectional[config[1]]) { if (db9_mode[mode].bidirectional && !(pp->modes & PARPORT_MODE_TRISTATE)) {
if (!(pp->modes & PARPORT_MODE_TRISTATE)) {
printk(KERN_ERR "db9.c: specified parport is not bidirectional\n"); printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
parport_put_port(pp); err = -EINVAL;
return NULL; goto err_put_pp;
}
} }
if (!(db9 = kzalloc(sizeof(struct db9), GFP_KERNEL))) { pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
parport_put_port(pp); if (!pd) {
return NULL; printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n");
err = -EBUSY;
goto err_put_pp;
}
db9 = kzalloc(sizeof(struct db9), GFP_KERNEL);
if (!db9) {
printk(KERN_ERR "db9.c: Not enough memory\n");
err = -ENOMEM;
goto err_unreg_pardev;
} }
init_MUTEX(&db9->sem); init_MUTEX(&db9->sem);
db9->mode = config[1]; db9->pd = pd;
db9->mode = mode;
init_timer(&db9->timer); init_timer(&db9->timer);
db9->timer.data = (long) db9; db9->timer.data = (long) db9;
db9->timer.function = db9_timer; db9->timer.function = db9_timer;
db9->pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); for (i = 0; i < (min(db9_mode->n_pads, DB9_MAX_DEVICES)); i++) {
parport_put_port(pp);
if (!db9->pd) { db9->dev[i] = input_dev = input_allocate_device();
printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n"); if (!input_dev) {
kfree(db9); printk(KERN_ERR "db9.c: Not enough memory for input device\n");
return NULL; err = -ENOMEM;
goto err_free_devs;
} }
for (i = 0; i < (min(db9_max_pads[db9->mode], DB9_MAX_DEVICES)); i++) {
sprintf(db9->phys[i], "%s/input%d", db9->pd->port->name, i); sprintf(db9->phys[i], "%s/input%d", db9->pd->port->name, i);
db9->dev[i].private = db9; input_dev->name = db9_mode->name;
db9->dev[i].open = db9_open; input_dev->phys = db9->phys[i];
db9->dev[i].close = db9_close; input_dev->id.bustype = BUS_PARPORT;
input_dev->id.vendor = 0x0002;
input_dev->id.product = mode;
input_dev->id.version = 0x0100;
input_dev->private = db9;
db9->dev[i].name = db9_name[db9->mode]; input_dev->open = db9_open;
db9->dev[i].phys = db9->phys[i]; input_dev->close = db9_close;
db9->dev[i].id.bustype = BUS_PARPORT;
db9->dev[i].id.vendor = 0x0002;
db9->dev[i].id.product = config[1];
db9->dev[i].id.version = 0x0100;
db9->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (j = 0; j < db9_buttons[db9->mode]; j++) for (j = 0; j < db9_mode->n_buttons; j++)
set_bit(db9_btn[db9->mode][j], db9->dev[i].keybit); set_bit(db9_mode->buttons[j], input_dev->keybit);
for (j = 0; j < db9_num_axis[db9->mode]; j++) { for (j = 0; j < db9_mode->n_axis; j++) {
set_bit(db9_abs[j], db9->dev[i].absbit); if (j < 2)
if (j < 2) { input_set_abs_params(input_dev, db9_abs[j], -1, 1, 0, 0);
db9->dev[i].absmin[db9_abs[j]] = -1; else
db9->dev[i].absmax[db9_abs[j]] = 1; input_set_abs_params(input_dev, db9_abs[j], 1, 255, 0, 0);
} else {
db9->dev[i].absmin[db9_abs[j]] = 1;
db9->dev[i].absmax[db9_abs[j]] = 255;
db9->dev[i].absflat[db9_abs[j]] = 0;
}
}
input_register_device(db9->dev + i);
printk(KERN_INFO "input: %s on %s\n", db9->dev[i].name, db9->pd->port->name);
} }
input_register_device(input_dev);
}
parport_put_port(pp);
return db9; return db9;
err_free_devs:
while (--i >= 0)
input_unregister_device(db9->dev[i]);
kfree(db9);
err_unreg_pardev:
parport_unregister_device(pd);
err_put_pp:
parport_put_port(pp);
err_out:
return ERR_PTR(err);
}
static void __exit db9_remove(struct db9 *db9)
{
int i;
for (i = 0; i < min(db9_modes[db9->mode].n_pads, DB9_MAX_DEVICES); i++)
input_unregister_device(db9->dev[i]);
parport_unregister_device(db9->pd);
kfree(db9);
} }
static int __init db9_init(void) static int __init db9_init(void)
{ {
db9_base[0] = db9_probe(db9, db9_nargs); int i;
db9_base[1] = db9_probe(db9_2, db9_nargs_2); int have_dev = 0;
db9_base[2] = db9_probe(db9_3, db9_nargs_3); int err = 0;
if (db9_base[0] || db9_base[1] || db9_base[2]) for (i = 0; i < DB9_MAX_PORTS; i++) {
return 0; if (db9[i].nargs == 0 || db9[i].args[DB9_ARG_PARPORT] < 0)
continue;
return -ENODEV; if (db9[i].nargs < 2) {
printk(KERN_ERR "db9.c: Device type must be specified.\n");
err = -EINVAL;
break;
}
db9_base[i] = db9_probe(db9[i].args[DB9_ARG_PARPORT],
db9[i].args[DB9_ARG_MODE]);
if (IS_ERR(db9_base[i])) {
err = PTR_ERR(db9_base[i]);
break;
}
have_dev = 1;
}
if (err) {
while (--i >= 0)
db9_remove(db9_base[i]);
return err;
}
return have_dev ? 0 : -ENODEV;
} }
static void __exit db9_exit(void) static void __exit db9_exit(void)
{ {
int i, j; int i;
for (i = 0; i < 3; i++) for (i = 0; i < DB9_MAX_PORTS; i++)
if (db9_base[i]) { if (db9_base[i])
for (j = 0; j < min(db9_max_pads[db9_base[i]->mode], DB9_MAX_DEVICES); j++) db9_remove(db9_base[i]);
input_unregister_device(db9_base[i]->dev + j);
parport_unregister_device(db9_base[i]->pd);
}
} }
module_init(db9_init); module_init(db9_init);

View file

@ -41,20 +41,22 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver"); MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static int gc[] __initdata = { -1, 0, 0, 0, 0, 0 }; #define GC_MAX_PORTS 3
static int gc_nargs __initdata = 0; #define GC_MAX_DEVICES 5
module_param_array_named(map, gc, int, &gc_nargs, 0);
MODULE_PARM_DESC(map, "Describers first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
static int gc_2[] __initdata = { -1, 0, 0, 0, 0, 0 }; struct gc_config {
static int gc_nargs_2 __initdata = 0; int args[GC_MAX_DEVICES + 1];
module_param_array_named(map2, gc_2, int, &gc_nargs_2, 0); int nargs;
MODULE_PARM_DESC(map2, "Describers second set of devices"); };
static int gc_3[] __initdata = { -1, 0, 0, 0, 0, 0 }; static struct gc_config gc[GC_MAX_PORTS] __initdata;
static int gc_nargs_3 __initdata = 0;
module_param_array_named(map3, gc_3, int, &gc_nargs_3, 0); module_param_array_named(map, gc[0].args, int, &gc[0].nargs, 0);
MODULE_PARM_DESC(map3, "Describers third set of devices"); MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
module_param_array_named(map2, gc[1].args, int, &gc[1].nargs, 0);
MODULE_PARM_DESC(map2, "Describes second set of devices");
module_param_array_named(map3, gc[2].args, int, &gc[2].nargs, 0);
MODULE_PARM_DESC(map3, "Describes third set of devices");
__obsolete_setup("gc="); __obsolete_setup("gc=");
__obsolete_setup("gc_2="); __obsolete_setup("gc_2=");
@ -77,12 +79,12 @@ __obsolete_setup("gc_3=");
struct gc { struct gc {
struct pardevice *pd; struct pardevice *pd;
struct input_dev dev[5]; struct input_dev *dev[GC_MAX_DEVICES];
struct timer_list timer; struct timer_list timer;
unsigned char pads[GC_MAX + 1]; unsigned char pads[GC_MAX + 1];
int used; int used;
struct semaphore sem; struct semaphore sem;
char phys[5][32]; char phys[GC_MAX_DEVICES][32];
}; };
static struct gc *gc_base[3]; static struct gc *gc_base[3];
@ -330,7 +332,6 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES
static void gc_timer(unsigned long private) static void gc_timer(unsigned long private)
{ {
struct gc *gc = (void *) private; struct gc *gc = (void *) private;
struct input_dev *dev = gc->dev;
unsigned char data[GC_MAX_LENGTH]; unsigned char data[GC_MAX_LENGTH];
unsigned char data_psx[5][GC_PSX_BYTES]; unsigned char data_psx[5][GC_PSX_BYTES];
int i, j, s; int i, j, s;
@ -357,16 +358,16 @@ static void gc_timer(unsigned long private)
if (data[31 - j] & s) axes[1] |= 1 << j; if (data[31 - j] & s) axes[1] |= 1 << j;
} }
input_report_abs(dev + i, ABS_X, axes[0]); input_report_abs(gc->dev[i], ABS_X, axes[0]);
input_report_abs(dev + i, ABS_Y, -axes[1]); input_report_abs(gc->dev[i], ABS_Y, -axes[1]);
input_report_abs(dev + i, ABS_HAT0X, !(s & data[6]) - !(s & data[7])); input_report_abs(gc->dev[i], ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
input_report_abs(dev + i, ABS_HAT0Y, !(s & data[4]) - !(s & data[5])); input_report_abs(gc->dev[i], ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
for (j = 0; j < 10; j++) for (j = 0; j < 10; j++)
input_report_key(dev + i, gc_n64_btn[j], s & data[gc_n64_bytes[j]]); input_report_key(gc->dev[i], gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
input_sync(dev + i); input_sync(gc->dev[i]);
} }
} }
} }
@ -384,19 +385,19 @@ static void gc_timer(unsigned long private)
s = gc_status_bit[i]; s = gc_status_bit[i];
if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) { if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {
input_report_abs(dev + i, ABS_X, !(s & data[6]) - !(s & data[7])); input_report_abs(gc->dev[i], ABS_X, !(s & data[6]) - !(s & data[7]));
input_report_abs(dev + i, ABS_Y, !(s & data[4]) - !(s & data[5])); input_report_abs(gc->dev[i], ABS_Y, !(s & data[4]) - !(s & data[5]));
} }
if (s & gc->pads[GC_NES]) if (s & gc->pads[GC_NES])
for (j = 0; j < 4; j++) for (j = 0; j < 4; j++)
input_report_key(dev + i, gc_snes_btn[j], s & data[gc_nes_bytes[j]]); input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_nes_bytes[j]]);
if (s & gc->pads[GC_SNES]) if (s & gc->pads[GC_SNES])
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
input_report_key(dev + i, gc_snes_btn[j], s & data[gc_snes_bytes[j]]); input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
input_sync(dev + i); input_sync(gc->dev[i]);
} }
} }
@ -413,15 +414,15 @@ static void gc_timer(unsigned long private)
s = gc_status_bit[i]; s = gc_status_bit[i];
if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) { if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {
input_report_abs(dev + i, ABS_X, !(s & data[2]) - !(s & data[3])); input_report_abs(gc->dev[i], ABS_X, !(s & data[2]) - !(s & data[3]));
input_report_abs(dev + i, ABS_Y, !(s & data[0]) - !(s & data[1])); input_report_abs(gc->dev[i], ABS_Y, !(s & data[0]) - !(s & data[1]));
input_report_key(dev + i, BTN_TRIGGER, s & data[4]); input_report_key(gc->dev[i], BTN_TRIGGER, s & data[4]);
} }
if (s & gc->pads[GC_MULTI2]) if (s & gc->pads[GC_MULTI2])
input_report_key(dev + i, BTN_THUMB, s & data[5]); input_report_key(gc->dev[i], BTN_THUMB, s & data[5]);
input_sync(dev + i); input_sync(gc->dev[i]);
} }
} }
@ -438,44 +439,44 @@ static void gc_timer(unsigned long private)
case GC_PSX_RUMBLE: case GC_PSX_RUMBLE:
input_report_key(dev + i, BTN_THUMBL, ~data_psx[i][0] & 0x04); input_report_key(gc->dev[i], BTN_THUMBL, ~data_psx[i][0] & 0x04);
input_report_key(dev + i, BTN_THUMBR, ~data_psx[i][0] & 0x02); input_report_key(gc->dev[i], BTN_THUMBR, ~data_psx[i][0] & 0x02);
case GC_PSX_NEGCON: case GC_PSX_NEGCON:
case GC_PSX_ANALOG: case GC_PSX_ANALOG:
if(gc->pads[GC_DDR] & gc_status_bit[i]) { if (gc->pads[GC_DDR] & gc_status_bit[i]) {
for(j = 0; j < 4; j++) for(j = 0; j < 4; j++)
input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j)); input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
} else { } else {
for (j = 0; j < 4; j++) for (j = 0; j < 4; j++)
input_report_abs(dev + i, gc_psx_abs[j+2], data_psx[i][j + 2]); input_report_abs(gc->dev[i], gc_psx_abs[j+2], data_psx[i][j + 2]);
input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128); input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128); input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
} }
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j)); input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08); input_report_key(gc->dev[i], BTN_START, ~data_psx[i][0] & 0x08);
input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01); input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01);
input_sync(dev + i); input_sync(gc->dev[i]);
break; break;
case GC_PSX_NORMAL: case GC_PSX_NORMAL:
if(gc->pads[GC_DDR] & gc_status_bit[i]) { if (gc->pads[GC_DDR] & gc_status_bit[i]) {
for(j = 0; j < 4; j++) for(j = 0; j < 4; j++)
input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j)); input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
} else { } else {
input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128); input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128); input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
/* for some reason if the extra axes are left unset they drift */ /* for some reason if the extra axes are left unset they drift */
/* for (j = 0; j < 4; j++) /* for (j = 0; j < 4; j++)
input_report_abs(dev + i, gc_psx_abs[j+2], 128); input_report_abs(gc->dev[i], gc_psx_abs[j+2], 128);
* This needs to be debugged properly, * This needs to be debugged properly,
* maybe fuzz processing needs to be done in input_sync() * maybe fuzz processing needs to be done in input_sync()
* --vojtech * --vojtech
@ -483,12 +484,12 @@ static void gc_timer(unsigned long private)
} }
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j)); input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08); input_report_key(gc->dev[i], BTN_START, ~data_psx[i][0] & 0x08);
input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01); input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01);
input_sync(dev + i); input_sync(gc->dev[i]);
break; break;
@ -533,177 +534,212 @@ static void gc_close(struct input_dev *dev)
up(&gc->sem); up(&gc->sem);
} }
static struct gc __init *gc_probe(int *config, int nargs) static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
{ {
struct gc *gc; struct input_dev *input_dev;
struct parport *pp; int i;
int i, j;
if (config[0] < 0) if (!pad_type)
return NULL; return 0;
if (nargs < 2) { if (pad_type < 1 || pad_type > GC_MAX) {
printk(KERN_ERR "gamecon.c: at least one device must be specified\n"); printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", pad_type);
return NULL; return -EINVAL;
} }
pp = parport_find_number(config[0]); gc->dev[idx] = input_dev = input_allocate_device();
if (!input_dev) {
if (!pp) { printk(KERN_ERR "gamecon.c: Not enough memory for input device\n");
printk(KERN_ERR "gamecon.c: no such parport\n"); return -ENOMEM;
return NULL;
} }
if (!(gc = kzalloc(sizeof(struct gc), GFP_KERNEL))) { input_dev->name = gc_names[pad_type];
parport_put_port(pp); input_dev->phys = gc->phys[idx];
return NULL; input_dev->id.bustype = BUS_PARPORT;
} input_dev->id.vendor = 0x0001;
input_dev->id.product = pad_type;
input_dev->id.version = 0x0100;
input_dev->private = gc;
init_MUTEX(&gc->sem); input_dev->open = gc_open;
input_dev->close = gc_close;
gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
parport_put_port(pp); for (i = 0; i < 2; i++)
input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);
if (!gc->pd) { gc->pads[0] |= gc_status_bit[idx];
printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n"); gc->pads[pad_type] |= gc_status_bit[idx];
kfree(gc);
return NULL;
}
parport_claim(gc->pd); switch (pad_type) {
init_timer(&gc->timer);
gc->timer.data = (long) gc;
gc->timer.function = gc_timer;
for (i = 0; i < nargs - 1; i++) {
if (!config[i + 1])
continue;
if (config[i + 1] < 1 || config[i + 1] > GC_MAX) {
printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", config[i + 1]);
continue;
}
gc->dev[i].private = gc;
gc->dev[i].open = gc_open;
gc->dev[i].close = gc_close;
gc->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (j = 0; j < 2; j++) {
set_bit(ABS_X + j, gc->dev[i].absbit);
gc->dev[i].absmin[ABS_X + j] = -1;
gc->dev[i].absmax[ABS_X + j] = 1;
}
gc->pads[0] |= gc_status_bit[i];
gc->pads[config[i + 1]] |= gc_status_bit[i];
switch(config[i + 1]) {
case GC_N64: case GC_N64:
for (j = 0; j < 10; j++) for (i = 0; i < 10; i++)
set_bit(gc_n64_btn[j], gc->dev[i].keybit); set_bit(gc_n64_btn[i], input_dev->keybit);
for (j = 0; j < 2; j++) { for (i = 0; i < 2; i++) {
set_bit(ABS_X + j, gc->dev[i].absbit); input_set_abs_params(input_dev, ABS_X + i, -127, 126, 0, 2);
gc->dev[i].absmin[ABS_X + j] = -127; input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0);
gc->dev[i].absmax[ABS_X + j] = 126;
gc->dev[i].absflat[ABS_X + j] = 2;
set_bit(ABS_HAT0X + j, gc->dev[i].absbit);
gc->dev[i].absmin[ABS_HAT0X + j] = -1;
gc->dev[i].absmax[ABS_HAT0X + j] = 1;
} }
break; break;
case GC_SNES: case GC_SNES:
for (j = 4; j < 8; j++) for (i = 4; i < 8; i++)
set_bit(gc_snes_btn[j], gc->dev[i].keybit); set_bit(gc_snes_btn[i], input_dev->keybit);
case GC_NES: case GC_NES:
for (j = 0; j < 4; j++) for (i = 0; i < 4; i++)
set_bit(gc_snes_btn[j], gc->dev[i].keybit); set_bit(gc_snes_btn[i], input_dev->keybit);
break; break;
case GC_MULTI2: case GC_MULTI2:
set_bit(BTN_THUMB, gc->dev[i].keybit); set_bit(BTN_THUMB, input_dev->keybit);
case GC_MULTI: case GC_MULTI:
set_bit(BTN_TRIGGER, gc->dev[i].keybit); set_bit(BTN_TRIGGER, input_dev->keybit);
break; break;
case GC_PSX: case GC_PSX:
case GC_DDR: for (i = 0; i < 6; i++)
if(config[i + 1] == GC_DDR) { input_set_abs_params(input_dev, gc_psx_abs[i], 4, 252, 0, 2);
for (j = 0; j < 4; j++) for (i = 0; i < 12; i++)
set_bit(gc_psx_ddr_btn[j], gc->dev[i].keybit); set_bit(gc_psx_btn[i], input_dev->keybit);
} else {
for (j = 0; j < 6; j++) {
set_bit(gc_psx_abs[j], gc->dev[i].absbit);
gc->dev[i].absmin[gc_psx_abs[j]] = 4;
gc->dev[i].absmax[gc_psx_abs[j]] = 252;
gc->dev[i].absflat[gc_psx_abs[j]] = 2;
}
}
for (j = 0; j < 12; j++) break;
set_bit(gc_psx_btn[j], gc->dev[i].keybit);
case GC_DDR:
for (i = 0; i < 4; i++)
set_bit(gc_psx_ddr_btn[i], input_dev->keybit);
for (i = 0; i < 12; i++)
set_bit(gc_psx_btn[i], input_dev->keybit);
break; break;
} }
sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i); return 0;
}
gc->dev[i].name = gc_names[config[i + 1]]; static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
gc->dev[i].phys = gc->phys[i]; {
gc->dev[i].id.bustype = BUS_PARPORT; struct gc *gc;
gc->dev[i].id.vendor = 0x0001; struct parport *pp;
gc->dev[i].id.product = config[i + 1]; struct pardevice *pd;
gc->dev[i].id.version = 0x0100; int i;
int err;
pp = parport_find_number(parport);
if (!pp) {
printk(KERN_ERR "gamecon.c: no such parport\n");
err = -EINVAL;
goto err_out;
} }
parport_release(gc->pd); pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
if (!pd) {
printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n");
err = -EBUSY;
goto err_put_pp;
}
gc = kzalloc(sizeof(struct gc), GFP_KERNEL);
if (!gc) {
printk(KERN_ERR "gamecon.c: Not enough memory\n");
err = -ENOMEM;
goto err_unreg_pardev;
}
init_MUTEX(&gc->sem);
gc->pd = pd;
init_timer(&gc->timer);
gc->timer.data = (long) gc;
gc->timer.function = gc_timer;
for (i = 0; i < n_pads; i++) {
if (!pads[i])
continue;
sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i);
err = gc_setup_pad(gc, i, pads[i]);
if (err)
goto err_free_devs;
input_register_device(gc->dev[i]);
}
if (!gc->pads[0]) { if (!gc->pads[0]) {
printk(KERN_ERR "gamecon.c: No valid devices specified\n");
err = -EINVAL;
goto err_free_gc;
}
parport_put_port(pp);
return gc;
err_free_devs:
while (--i >= 0)
input_unregister_device(gc->dev[i]);
err_free_gc:
kfree(gc);
err_unreg_pardev:
parport_unregister_device(pd);
err_put_pp:
parport_put_port(pp);
err_out:
return ERR_PTR(err);
}
static void __exit gc_remove(struct gc *gc)
{
int i;
for (i = 0; i < GC_MAX_DEVICES; i++)
if (gc->dev[i])
input_unregister_device(gc->dev[i]);
parport_unregister_device(gc->pd); parport_unregister_device(gc->pd);
kfree(gc); kfree(gc);
return NULL;
}
for (i = 0; i < 5; i++)
if (gc->pads[0] & gc_status_bit[i]) {
input_register_device(gc->dev + i);
printk(KERN_INFO "input: %s on %s\n", gc->dev[i].name, gc->pd->port->name);
}
return gc;
} }
static int __init gc_init(void) static int __init gc_init(void)
{ {
gc_base[0] = gc_probe(gc, gc_nargs); int i;
gc_base[1] = gc_probe(gc_2, gc_nargs_2); int have_dev = 0;
gc_base[2] = gc_probe(gc_3, gc_nargs_3); int err = 0;
if (gc_base[0] || gc_base[1] || gc_base[2]) for (i = 0; i < GC_MAX_PORTS; i++) {
return 0; if (gc[i].nargs == 0 || gc[i].args[0] < 0)
continue;
return -ENODEV; if (gc[i].nargs < 2) {
printk(KERN_ERR "gamecon.c: at least one device must be specified\n");
err = -EINVAL;
break;
}
gc_base[i] = gc_probe(gc[i].args[0], gc[i].args + 1, gc[i].nargs - 1);
if (IS_ERR(gc_base[i])) {
err = PTR_ERR(gc_base[i]);
break;
}
have_dev = 1;
}
if (err) {
while (--i >= 0)
gc_remove(gc_base[i]);
return err;
}
return have_dev ? 0 : -ENODEV;
} }
static void __exit gc_exit(void) static void __exit gc_exit(void)
{ {
int i, j; int i;
for (i = 0; i < 3; i++) for (i = 0; i < GC_MAX_PORTS; i++)
if (gc_base[i]) { if (gc_base[i])
for (j = 0; j < 5; j++) gc_remove(gc_base[i]);
if (gc_base[i]->pads[0] & gc_status_bit[j])
input_unregister_device(gc_base[i]->dev + j);
parport_unregister_device(gc_base[i]->pd);
}
} }
module_init(gc_init); module_init(gc_init);

View file

@ -81,7 +81,7 @@ static short gf2k_seq_digital[] = { 590, 320, 860, 0 };
struct gf2k { struct gf2k {
struct gameport *gameport; struct gameport *gameport;
struct input_dev dev; struct input_dev *dev;
int reads; int reads;
int bads; int bads;
unsigned char id; unsigned char id;
@ -175,7 +175,7 @@ static int gf2k_get_bits(unsigned char *buf, int pos, int num, int shift)
static void gf2k_read(struct gf2k *gf2k, unsigned char *data) static void gf2k_read(struct gf2k *gf2k, unsigned char *data)
{ {
struct input_dev *dev = &gf2k->dev; struct input_dev *dev = gf2k->dev;
int i, t; int i, t;
for (i = 0; i < 4 && i < gf2k_axes[gf2k->id]; i++) for (i = 0; i < 4 && i < gf2k_axes[gf2k->id]; i++)
@ -239,13 +239,19 @@ static void gf2k_close(struct input_dev *dev)
static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
{ {
struct gf2k *gf2k; struct gf2k *gf2k;
struct input_dev *input_dev;
unsigned char data[GF2K_LENGTH]; unsigned char data[GF2K_LENGTH];
int i, err; int i, err;
if (!(gf2k = kzalloc(sizeof(struct gf2k), GFP_KERNEL))) gf2k = kzalloc(sizeof(struct gf2k), GFP_KERNEL);
return -ENOMEM; input_dev = input_allocate_device();
if (!gf2k || !input_dev) {
err = -ENOMEM;
goto fail1;
}
gf2k->gameport = gameport; gf2k->gameport = gameport;
gf2k->dev = input_dev;
gameport_set_drvdata(gameport, gf2k); gameport_set_drvdata(gameport, gf2k);
@ -295,53 +301,52 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
gf2k->length = gf2k_lens[gf2k->id]; gf2k->length = gf2k_lens[gf2k->id];
init_input_dev(&gf2k->dev); input_dev->name = gf2k_names[gf2k->id];
input_dev->phys = gf2k->phys;
input_dev->id.bustype = BUS_GAMEPORT;
input_dev->id.vendor = GAMEPORT_ID_VENDOR_GENIUS;
input_dev->id.product = gf2k->id;
input_dev->id.version = 0x0100;
input_dev->cdev.dev = &gameport->dev;
input_dev->private = gf2k;
gf2k->dev.private = gf2k; input_dev->open = gf2k_open;
gf2k->dev.open = gf2k_open; input_dev->close = gf2k_close;
gf2k->dev.close = gf2k_close; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
gf2k->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
gf2k->dev.name = gf2k_names[gf2k->id];
gf2k->dev.phys = gf2k->phys;
gf2k->dev.id.bustype = BUS_GAMEPORT;
gf2k->dev.id.vendor = GAMEPORT_ID_VENDOR_GENIUS;
gf2k->dev.id.product = gf2k->id;
gf2k->dev.id.version = 0x0100;
for (i = 0; i < gf2k_axes[gf2k->id]; i++) for (i = 0; i < gf2k_axes[gf2k->id]; i++)
set_bit(gf2k_abs[i], gf2k->dev.absbit); set_bit(gf2k_abs[i], input_dev->absbit);
for (i = 0; i < gf2k_hats[gf2k->id]; i++) { for (i = 0; i < gf2k_hats[gf2k->id]; i++) {
set_bit(ABS_HAT0X + i, gf2k->dev.absbit); set_bit(ABS_HAT0X + i, input_dev->absbit);
gf2k->dev.absmin[ABS_HAT0X + i] = -1; input_dev->absmin[ABS_HAT0X + i] = -1;
gf2k->dev.absmax[ABS_HAT0X + i] = 1; input_dev->absmax[ABS_HAT0X + i] = 1;
} }
for (i = 0; i < gf2k_joys[gf2k->id]; i++) for (i = 0; i < gf2k_joys[gf2k->id]; i++)
set_bit(gf2k_btn_joy[i], gf2k->dev.keybit); set_bit(gf2k_btn_joy[i], input_dev->keybit);
for (i = 0; i < gf2k_pads[gf2k->id]; i++) for (i = 0; i < gf2k_pads[gf2k->id]; i++)
set_bit(gf2k_btn_pad[i], gf2k->dev.keybit); set_bit(gf2k_btn_pad[i], input_dev->keybit);
gf2k_read_packet(gameport, gf2k->length, data); gf2k_read_packet(gameport, gf2k->length, data);
gf2k_read(gf2k, data); gf2k_read(gf2k, data);
for (i = 0; i < gf2k_axes[gf2k->id]; i++) { for (i = 0; i < gf2k_axes[gf2k->id]; i++) {
gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 : input_dev->absmax[gf2k_abs[i]] = (i < 2) ? input_dev->abs[gf2k_abs[i]] * 2 - 32 :
gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32; input_dev->abs[gf2k_abs[0]] + input_dev->abs[gf2k_abs[1]] - 32;
gf2k->dev.absmin[gf2k_abs[i]] = 32; input_dev->absmin[gf2k_abs[i]] = 32;
gf2k->dev.absfuzz[gf2k_abs[i]] = 8; input_dev->absfuzz[gf2k_abs[i]] = 8;
gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0; input_dev->absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0;
} }
input_register_device(&gf2k->dev); input_register_device(gf2k->dev);
printk(KERN_INFO "input: %s on %s\n", gf2k_names[gf2k->id], gameport->phys);
return 0; return 0;
fail2: gameport_close(gameport); fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL); fail1: gameport_set_drvdata(gameport, NULL);
input_free_device(input_dev);
kfree(gf2k); kfree(gf2k);
return err; return err;
} }
@ -350,7 +355,7 @@ static void gf2k_disconnect(struct gameport *gameport)
{ {
struct gf2k *gf2k = gameport_get_drvdata(gameport); struct gf2k *gf2k = gameport_get_drvdata(gameport);
input_unregister_device(&gf2k->dev); input_unregister_device(gf2k->dev);
gameport_close(gameport); gameport_close(gameport);
gameport_set_drvdata(gameport, NULL); gameport_set_drvdata(gameport, NULL);
kfree(gf2k); kfree(gf2k);

View file

@ -55,7 +55,7 @@ MODULE_LICENSE("GPL");
struct grip { struct grip {
struct gameport *gameport; struct gameport *gameport;
struct input_dev dev[2]; struct input_dev *dev[2];
unsigned char mode[2]; unsigned char mode[2];
int reads; int reads;
int bads; int bads;
@ -190,7 +190,7 @@ static void grip_poll(struct gameport *gameport)
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
dev = grip->dev + i; dev = grip->dev[i];
grip->reads++; grip->reads++;
switch (grip->mode[i]) { switch (grip->mode[i]) {
@ -297,6 +297,7 @@ static void grip_close(struct input_dev *dev)
static int grip_connect(struct gameport *gameport, struct gameport_driver *drv) static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
{ {
struct grip *grip; struct grip *grip;
struct input_dev *input_dev;
unsigned int data[GRIP_LENGTH_XT]; unsigned int data[GRIP_LENGTH_XT];
int i, j, t; int i, j, t;
int err; int err;
@ -339,48 +340,56 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
gameport_set_poll_handler(gameport, grip_poll); gameport_set_poll_handler(gameport, grip_poll);
gameport_set_poll_interval(gameport, 20); gameport_set_poll_interval(gameport, 20);
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++) {
if (grip->mode[i]) { if (!grip->mode[i])
continue;
grip->dev[i] = input_dev = input_allocate_device();
if (!input_dev) {
err = -ENOMEM;
goto fail3;
}
sprintf(grip->phys[i], "%s/input%d", gameport->phys, i); sprintf(grip->phys[i], "%s/input%d", gameport->phys, i);
grip->dev[i].private = grip; input_dev->name = grip_name[grip->mode[i]];
input_dev->phys = grip->phys[i];
input_dev->id.bustype = BUS_GAMEPORT;
input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
input_dev->id.product = grip->mode[i];
input_dev->id.version = 0x0100;
input_dev->cdev.dev = &gameport->dev;
input_dev->private = grip;
grip->dev[i].open = grip_open; input_dev->open = grip_open;
grip->dev[i].close = grip_close; input_dev->close = grip_close;
grip->dev[i].name = grip_name[grip->mode[i]]; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
grip->dev[i].phys = grip->phys[i];
grip->dev[i].id.bustype = BUS_GAMEPORT;
grip->dev[i].id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
grip->dev[i].id.product = grip->mode[i];
grip->dev[i].id.version = 0x0100;
grip->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) { for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
if (j < grip_cen[grip->mode[i]]) if (j < grip_cen[grip->mode[i]])
input_set_abs_params(&grip->dev[i], t, 14, 52, 1, 2); input_set_abs_params(input_dev, t, 14, 52, 1, 2);
else if (j < grip_anx[grip->mode[i]]) else if (j < grip_anx[grip->mode[i]])
input_set_abs_params(&grip->dev[i], t, 3, 57, 1, 0); input_set_abs_params(input_dev, t, 3, 57, 1, 0);
else else
input_set_abs_params(&grip->dev[i], t, -1, 1, 0, 0); input_set_abs_params(input_dev, t, -1, 1, 0, 0);
} }
for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++) for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
if (t > 0) if (t > 0)
set_bit(t, grip->dev[i].keybit); set_bit(t, input_dev->keybit);
printk(KERN_INFO "input: %s on %s\n", input_register_device(grip->dev[i]);
grip_name[grip->mode[i]], gameport->phys);
input_register_device(grip->dev + i);
} }
return 0; return 0;
fail2: gameport_close(gameport); fail3: for (i = 0; i < 2; i++)
fail1: gameport_set_drvdata(gameport, NULL); if (grip->dev[i])
input_unregister_device(grip->dev[i]);
fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL);
kfree(grip); kfree(grip);
return err; return err;
} }
@ -391,8 +400,8 @@ static void grip_disconnect(struct gameport *gameport)
int i; int i;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
if (grip->mode[i]) if (grip->dev[i])
input_unregister_device(grip->dev + i); input_unregister_device(grip->dev[i]);
gameport_close(gameport); gameport_close(gameport);
gameport_set_drvdata(gameport, NULL); gameport_set_drvdata(gameport, NULL);
kfree(grip); kfree(grip);

View file

@ -32,23 +32,37 @@ MODULE_LICENSE("GPL");
#define dbg(format, arg...) do {} while (0) #define dbg(format, arg...) do {} while (0)
#endif #endif
#define GRIP_MAX_PORTS 4
/* /*
* Grip multiport state * Grip multiport state
*/ */
struct grip_port {
struct input_dev *dev;
int mode;
int registered;
/* individual gamepad states */
int buttons;
int xaxes;
int yaxes;
int dirty; /* has the state been updated? */
};
struct grip_mp { struct grip_mp {
struct gameport *gameport; struct gameport *gameport;
struct input_dev dev[4]; struct grip_port *port[GRIP_MAX_PORTS];
int mode[4]; // struct input_dev *dev[4];
int registered[4]; // int mode[4];
// int registered[4];
int reads; int reads;
int bads; int bads;
/* individual gamepad states */ /* individual gamepad states */
int buttons[4]; // int buttons[4];
int xaxes[4]; // int xaxes[4];
int yaxes[4]; // int yaxes[4];
int dirty[4]; /* has the state been updated? */ // int dirty[4]; /* has the state been updated? */
}; };
/* /*
@ -85,16 +99,16 @@ struct grip_mp {
#define GRIP_MODE_GP 2 #define GRIP_MODE_GP 2
#define GRIP_MODE_C64 3 #define GRIP_MODE_C64 3
static int grip_btn_gp[] = { BTN_TR, BTN_TL, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, -1 }; static const int grip_btn_gp[] = { BTN_TR, BTN_TL, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, -1 };
static int grip_btn_c64[] = { BTN_JOYSTICK, -1 }; static const int grip_btn_c64[] = { BTN_JOYSTICK, -1 };
static int grip_abs_gp[] = { ABS_X, ABS_Y, -1 }; static const int grip_abs_gp[] = { ABS_X, ABS_Y, -1 };
static int grip_abs_c64[] = { ABS_X, ABS_Y, -1 }; static const int grip_abs_c64[] = { ABS_X, ABS_Y, -1 };
static int *grip_abs[] = { NULL, NULL, grip_abs_gp, grip_abs_c64 }; static const int *grip_abs[] = { NULL, NULL, grip_abs_gp, grip_abs_c64 };
static int *grip_btn[] = { NULL, NULL, grip_btn_gp, grip_btn_c64 }; static const int *grip_btn[] = { NULL, NULL, grip_btn_gp, grip_btn_c64 };
static char *grip_name[] = { NULL, NULL, "Gravis Grip Pad", "Commodore 64 Joystick" }; static const char *grip_name[] = { NULL, NULL, "Gravis Grip Pad", "Commodore 64 Joystick" };
static const int init_seq[] = { static const int init_seq[] = {
1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
@ -104,9 +118,9 @@ static const int init_seq[] = {
/* Maps multiport directional values to X,Y axis values (each axis encoded in 3 bits) */ /* Maps multiport directional values to X,Y axis values (each axis encoded in 3 bits) */
static int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 }; static const int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 };
static void register_slot(int i, struct grip_mp *grip); static int register_slot(int i, struct grip_mp *grip);
/* /*
* Returns whether an odd or even number of bits are on in pkt. * Returns whether an odd or even number of bits are on in pkt.
@ -353,9 +367,10 @@ static int dig_mode_start(struct gameport *gameport, u32 *packet)
static int get_and_decode_packet(struct grip_mp *grip, int flags) static int get_and_decode_packet(struct grip_mp *grip, int flags)
{ {
struct grip_port *port;
u32 packet; u32 packet;
int joytype = 0; int joytype = 0;
int slot = 0; int slot;
/* Get a packet and check for validity */ /* Get a packet and check for validity */
@ -377,6 +392,8 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags)
if ((slot < 0) || (slot > 3)) if ((slot < 0) || (slot > 3))
return flags; return flags;
port = grip->port[slot];
/* /*
* Handle "reset" packets, which occur at startup, and when gamepads * Handle "reset" packets, which occur at startup, and when gamepads
* are removed or plugged in. May contain configuration of a new gamepad. * are removed or plugged in. May contain configuration of a new gamepad.
@ -385,14 +402,14 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags)
joytype = (packet >> 16) & 0x1f; joytype = (packet >> 16) & 0x1f;
if (!joytype) { if (!joytype) {
if (grip->registered[slot]) { if (port->registered) {
printk(KERN_INFO "grip_mp: removing %s, slot %d\n", printk(KERN_INFO "grip_mp: removing %s, slot %d\n",
grip_name[grip->mode[slot]], slot); grip_name[port->mode], slot);
input_unregister_device(grip->dev + slot); input_unregister_device(port->dev);
grip->registered[slot] = 0; port->registered = 0;
} }
dbg("Reset: grip multiport slot %d\n", slot); dbg("Reset: grip multiport slot %d\n", slot);
grip->mode[slot] = GRIP_MODE_RESET; port->mode = GRIP_MODE_RESET;
flags |= IO_SLOT_CHANGE; flags |= IO_SLOT_CHANGE;
return flags; return flags;
} }
@ -402,17 +419,17 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags)
if (joytype == 0x1f) { if (joytype == 0x1f) {
int dir = (packet >> 8) & 0xf; /* eight way directional value */ int dir = (packet >> 8) & 0xf; /* eight way directional value */
grip->buttons[slot] = (~packet) & 0xff; port->buttons = (~packet) & 0xff;
grip->yaxes[slot] = ((axis_map[dir] >> 2) & 3) - 1; port->yaxes = ((axis_map[dir] >> 2) & 3) - 1;
grip->xaxes[slot] = (axis_map[dir] & 3) - 1; port->xaxes = (axis_map[dir] & 3) - 1;
grip->dirty[slot] = 1; port->dirty = 1;
if (grip->mode[slot] == GRIP_MODE_RESET) if (port->mode == GRIP_MODE_RESET)
flags |= IO_SLOT_CHANGE; flags |= IO_SLOT_CHANGE;
grip->mode[slot] = GRIP_MODE_GP; port->mode = GRIP_MODE_GP;
if (!grip->registered[slot]) { if (!port->registered) {
dbg("New Grip pad in multiport slot %d.\n", slot); dbg("New Grip pad in multiport slot %d.\n", slot);
register_slot(slot, grip); register_slot(slot, grip);
} }
@ -445,9 +462,9 @@ static int slots_valid(struct grip_mp *grip)
return 0; return 0;
for (slot = 0; slot < 4; slot++) { for (slot = 0; slot < 4; slot++) {
if (grip->mode[slot] == GRIP_MODE_RESET) if (grip->port[slot]->mode == GRIP_MODE_RESET)
invalid = 1; invalid = 1;
if (grip->mode[slot] != GRIP_MODE_NONE) if (grip->port[slot]->mode != GRIP_MODE_NONE)
active = 1; active = 1;
} }
@ -484,7 +501,7 @@ static int multiport_init(struct grip_mp *grip)
/* Get packets, store multiport state, and check state's validity */ /* Get packets, store multiport state, and check state's validity */
for (tries = 0; tries < 4096; tries++) { for (tries = 0; tries < 4096; tries++) {
if ( slots_valid(grip) ) { if (slots_valid(grip)) {
initialized = 1; initialized = 1;
break; break;
} }
@ -499,24 +516,24 @@ static int multiport_init(struct grip_mp *grip)
static void report_slot(struct grip_mp *grip, int slot) static void report_slot(struct grip_mp *grip, int slot)
{ {
struct input_dev *dev = &(grip->dev[slot]); struct grip_port *port = grip->port[slot];
int i, buttons = grip->buttons[slot]; int i;
/* Store button states with linux input driver */ /* Store button states with linux input driver */
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
input_report_key(dev, grip_btn_gp[i], (buttons >> i) & 1); input_report_key(port->dev, grip_btn_gp[i], (port->buttons >> i) & 1);
/* Store axis states with linux driver */ /* Store axis states with linux driver */
input_report_abs(dev, ABS_X, grip->xaxes[slot]); input_report_abs(port->dev, ABS_X, port->xaxes);
input_report_abs(dev, ABS_Y, grip->yaxes[slot]); input_report_abs(port->dev, ABS_Y, port->yaxes);
/* Tell the receiver of the events to process them */ /* Tell the receiver of the events to process them */
input_sync(dev); input_sync(port->dev);
grip->dirty[slot] = 0; port->dirty = 0;
} }
/* /*
@ -540,7 +557,7 @@ static void grip_poll(struct gameport *gameport)
} }
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
if (grip->dirty[i]) if (grip->port[i]->dirty)
report_slot(grip, i); report_slot(grip, i);
} }
@ -571,35 +588,43 @@ static void grip_close(struct input_dev *dev)
* Tell the linux input layer about a newly plugged-in gamepad. * Tell the linux input layer about a newly plugged-in gamepad.
*/ */
static void register_slot(int slot, struct grip_mp *grip) static int register_slot(int slot, struct grip_mp *grip)
{ {
struct grip_port *port = grip->port[slot];
struct input_dev *input_dev;
int j, t; int j, t;
grip->dev[slot].private = grip; port->dev = input_dev = input_allocate_device();
grip->dev[slot].open = grip_open; if (!input_dev)
grip->dev[slot].close = grip_close; return -ENOMEM;
grip->dev[slot].name = grip_name[grip->mode[slot]];
grip->dev[slot].id.bustype = BUS_GAMEPORT;
grip->dev[slot].id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
grip->dev[slot].id.product = 0x0100 + grip->mode[slot];
grip->dev[slot].id.version = 0x0100;
grip->dev[slot].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (j = 0; (t = grip_abs[grip->mode[slot]][j]) >= 0; j++) input_dev->name = grip_name[port->mode];
input_set_abs_params(&grip->dev[slot], t, -1, 1, 0, 0); input_dev->id.bustype = BUS_GAMEPORT;
input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
input_dev->id.product = 0x0100 + port->mode;
input_dev->id.version = 0x0100;
input_dev->cdev.dev = &grip->gameport->dev;
input_dev->private = grip;
for (j = 0; (t = grip_btn[grip->mode[slot]][j]) >= 0; j++) input_dev->open = grip_open;
input_dev->close = grip_close;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (j = 0; (t = grip_abs[port->mode][j]) >= 0; j++)
input_set_abs_params(input_dev, t, -1, 1, 0, 0);
for (j = 0; (t = grip_btn[port->mode][j]) >= 0; j++)
if (t > 0) if (t > 0)
set_bit(t, grip->dev[slot].keybit); set_bit(t, input_dev->keybit);
input_register_device(grip->dev + slot); input_register_device(port->dev);
grip->registered[slot] = 1; port->registered = 1;
if (grip->dirty[slot]) /* report initial state, if any */ if (port->dirty) /* report initial state, if any */
report_slot(grip, slot); report_slot(grip, slot);
printk(KERN_INFO "grip_mp: added %s, slot %d\n", return 0;
grip_name[grip->mode[slot]], slot);
} }
static int grip_connect(struct gameport *gameport, struct gameport_driver *drv) static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
@ -626,7 +651,7 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
goto fail2; goto fail2;
} }
if (!grip->mode[0] && !grip->mode[1] && !grip->mode[2] && !grip->mode[3]) { if (!grip->port[0]->mode && !grip->port[1]->mode && !grip->port[2]->mode && !grip->port[3]->mode) {
/* nothing plugged in */ /* nothing plugged in */
err = -ENODEV; err = -ENODEV;
goto fail2; goto fail2;
@ -646,8 +671,8 @@ static void grip_disconnect(struct gameport *gameport)
int i; int i;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
if (grip->registered[i]) if (grip->port[i]->registered)
input_unregister_device(grip->dev + i); input_unregister_device(grip->port[i]->dev);
gameport_close(gameport); gameport_close(gameport);
gameport_set_drvdata(gameport, NULL); gameport_set_drvdata(gameport, NULL);
kfree(grip); kfree(grip);

View file

@ -67,7 +67,7 @@ struct guillemot_type {
struct guillemot { struct guillemot {
struct gameport *gameport; struct gameport *gameport;
struct input_dev dev; struct input_dev *dev;
int bads; int bads;
int reads; int reads;
struct guillemot_type *type; struct guillemot_type *type;
@ -123,7 +123,7 @@ static int guillemot_read_packet(struct gameport *gameport, u8 *data)
static void guillemot_poll(struct gameport *gameport) static void guillemot_poll(struct gameport *gameport)
{ {
struct guillemot *guillemot = gameport_get_drvdata(gameport); struct guillemot *guillemot = gameport_get_drvdata(gameport);
struct input_dev *dev = &guillemot->dev; struct input_dev *dev = guillemot->dev;
u8 data[GUILLEMOT_MAX_LENGTH]; u8 data[GUILLEMOT_MAX_LENGTH];
int i; int i;
@ -179,14 +179,20 @@ static void guillemot_close(struct input_dev *dev)
static int guillemot_connect(struct gameport *gameport, struct gameport_driver *drv) static int guillemot_connect(struct gameport *gameport, struct gameport_driver *drv)
{ {
struct guillemot *guillemot; struct guillemot *guillemot;
struct input_dev *input_dev;
u8 data[GUILLEMOT_MAX_LENGTH]; u8 data[GUILLEMOT_MAX_LENGTH];
int i, t; int i, t;
int err; int err;
if (!(guillemot = kzalloc(sizeof(struct guillemot), GFP_KERNEL))) guillemot = kzalloc(sizeof(struct guillemot), GFP_KERNEL);
return -ENOMEM; input_dev = input_allocate_device();
if (!guillemot || !input_dev) {
err = -ENOMEM;
goto fail1;
}
guillemot->gameport = gameport; guillemot->gameport = gameport;
guillemot->dev = input_dev;
gameport_set_drvdata(gameport, guillemot); gameport_set_drvdata(gameport, guillemot);
@ -216,41 +222,40 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver *
gameport_set_poll_interval(gameport, 20); gameport_set_poll_interval(gameport, 20);
sprintf(guillemot->phys, "%s/input0", gameport->phys); sprintf(guillemot->phys, "%s/input0", gameport->phys);
guillemot->type = guillemot_type + i; guillemot->type = guillemot_type + i;
guillemot->dev.private = guillemot; input_dev->name = guillemot_type[i].name;
guillemot->dev.open = guillemot_open; input_dev->phys = guillemot->phys;
guillemot->dev.close = guillemot_close; input_dev->id.bustype = BUS_GAMEPORT;
input_dev->id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT;
input_dev->id.product = guillemot_type[i].id;
input_dev->id.version = (int)data[14] << 8 | data[15];
input_dev->cdev.dev = &gameport->dev;
input_dev->private = guillemot;
guillemot->dev.name = guillemot_type[i].name; input_dev->open = guillemot_open;
guillemot->dev.phys = guillemot->phys; input_dev->close = guillemot_close;
guillemot->dev.id.bustype = BUS_GAMEPORT;
guillemot->dev.id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT;
guillemot->dev.id.product = guillemot_type[i].id;
guillemot->dev.id.version = (int)data[14] << 8 | data[15];
guillemot->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++) for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++)
input_set_abs_params(&guillemot->dev, t, 0, 255, 0, 0); input_set_abs_params(input_dev, t, 0, 255, 0, 0);
if (guillemot->type->hat) { if (guillemot->type->hat) {
input_set_abs_params(&guillemot->dev, ABS_HAT0X, -1, 1, 0, 0); input_set_abs_params(input_dev, ABS_HAT0X, -1, 1, 0, 0);
input_set_abs_params(&guillemot->dev, ABS_HAT0Y, -1, 1, 0, 0); input_set_abs_params(input_dev, ABS_HAT0Y, -1, 1, 0, 0);
} }
for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++) for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++)
set_bit(t, guillemot->dev.keybit); set_bit(t, input_dev->keybit);
input_register_device(&guillemot->dev); input_register_device(guillemot->dev);
printk(KERN_INFO "input: %s ver %d.%02d on %s\n",
guillemot->type->name, data[14], data[15], gameport->phys);
return 0; return 0;
fail2: gameport_close(gameport); fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL); fail1: gameport_set_drvdata(gameport, NULL);
input_free_device(input_dev);
kfree(guillemot); kfree(guillemot);
return err; return err;
} }
@ -260,7 +265,7 @@ static void guillemot_disconnect(struct gameport *gameport)
struct guillemot *guillemot = gameport_get_drvdata(gameport); struct guillemot *guillemot = gameport_get_drvdata(gameport);
printk(KERN_INFO "guillemot.c: Failed %d reads out of %d on %s\n", guillemot->reads, guillemot->bads, guillemot->phys); printk(KERN_INFO "guillemot.c: Failed %d reads out of %d on %s\n", guillemot->reads, guillemot->bads, guillemot->phys);
input_unregister_device(&guillemot->dev); input_unregister_device(guillemot->dev);
gameport_close(gameport); gameport_close(gameport);
kfree(guillemot); kfree(guillemot);
} }

View file

@ -144,7 +144,7 @@ static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect)
int is_update; int is_update;
/* Check this effect type is supported by this device */ /* Check this effect type is supported by this device */
if (!test_bit(effect->type, iforce->dev.ffbit)) if (!test_bit(effect->type, iforce->dev->ffbit))
return -EINVAL; return -EINVAL;
/* /*
@ -152,30 +152,31 @@ static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect)
*/ */
if (effect->id == -1) { if (effect->id == -1) {
for (id=0; id < FF_EFFECTS_MAX; ++id) for (id = 0; id < FF_EFFECTS_MAX; ++id)
if (!test_and_set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags)) break; if (!test_and_set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags))
break;
if ( id == FF_EFFECTS_MAX || id >= iforce->dev.ff_effects_max) if (id == FF_EFFECTS_MAX || id >= iforce->dev->ff_effects_max)
return -ENOMEM; return -ENOMEM;
effect->id = id; effect->id = id;
iforce->core_effects[id].owner = current->pid; iforce->core_effects[id].owner = current->pid;
iforce->core_effects[id].flags[0] = (1<<FF_CORE_IS_USED); /* Only IS_USED bit must be set */ iforce->core_effects[id].flags[0] = (1 << FF_CORE_IS_USED); /* Only IS_USED bit must be set */
is_update = FALSE; is_update = FALSE;
} }
else { else {
/* We want to update an effect */ /* We want to update an effect */
if (!CHECK_OWNERSHIP(effect->id, iforce)) return -EACCES; if (!CHECK_OWNERSHIP(effect->id, iforce))
return -EACCES;
/* Parameter type cannot be updated */ /* Parameter type cannot be updated */
if (effect->type != iforce->core_effects[effect->id].effect.type) if (effect->type != iforce->core_effects[effect->id].effect.type)
return -EINVAL; return -EINVAL;
/* Check the effect is not already being updated */ /* Check the effect is not already being updated */
if (test_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags)) { if (test_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags))
return -EAGAIN; return -EAGAIN;
}
is_update = TRUE; is_update = TRUE;
} }
@ -339,15 +340,19 @@ void iforce_delete_device(struct iforce *iforce)
int iforce_init_device(struct iforce *iforce) int iforce_init_device(struct iforce *iforce)
{ {
struct input_dev *input_dev;
unsigned char c[] = "CEOV"; unsigned char c[] = "CEOV";
int i; int i;
input_dev = input_allocate_device();
if (input_dev)
return -ENOMEM;
init_waitqueue_head(&iforce->wait); init_waitqueue_head(&iforce->wait);
spin_lock_init(&iforce->xmit_lock); spin_lock_init(&iforce->xmit_lock);
init_MUTEX(&iforce->mem_mutex); init_MUTEX(&iforce->mem_mutex);
iforce->xmit.buf = iforce->xmit_data; iforce->xmit.buf = iforce->xmit_data;
iforce->dev = input_dev;
iforce->dev.ff_effects_max = 10;
/* /*
* Input device fields. * Input device fields.
@ -356,26 +361,27 @@ int iforce_init_device(struct iforce *iforce)
switch (iforce->bus) { switch (iforce->bus) {
#ifdef CONFIG_JOYSTICK_IFORCE_USB #ifdef CONFIG_JOYSTICK_IFORCE_USB
case IFORCE_USB: case IFORCE_USB:
iforce->dev.id.bustype = BUS_USB; input_dev->id.bustype = BUS_USB;
iforce->dev.dev = &iforce->usbdev->dev; input_dev->cdev.dev = &iforce->usbdev->dev;
break; break;
#endif #endif
#ifdef CONFIG_JOYSTICK_IFORCE_232 #ifdef CONFIG_JOYSTICK_IFORCE_232
case IFORCE_232: case IFORCE_232:
iforce->dev.id.bustype = BUS_RS232; input_dev->id.bustype = BUS_RS232;
iforce->dev.dev = &iforce->serio->dev; input_dev->cdev.dev = &iforce->serio->dev;
break; break;
#endif #endif
} }
iforce->dev.private = iforce; input_dev->private = iforce;
iforce->dev.name = "Unknown I-Force device"; input_dev->name = "Unknown I-Force device";
iforce->dev.open = iforce_open; input_dev->open = iforce_open;
iforce->dev.close = iforce_release; input_dev->close = iforce_release;
iforce->dev.flush = iforce_flush; input_dev->flush = iforce_flush;
iforce->dev.event = iforce_input_event; input_dev->event = iforce_input_event;
iforce->dev.upload_effect = iforce_upload_effect; input_dev->upload_effect = iforce_upload_effect;
iforce->dev.erase_effect = iforce_erase_effect; input_dev->erase_effect = iforce_erase_effect;
input_dev->ff_effects_max = 10;
/* /*
* On-device memory allocation. * On-device memory allocation.
@ -399,7 +405,8 @@ int iforce_init_device(struct iforce *iforce)
if (i == 20) { /* 5 seconds */ if (i == 20) { /* 5 seconds */
printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n"); printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n");
return -1; input_free_device(input_dev);
return -ENODEV;
} }
/* /*
@ -407,12 +414,12 @@ int iforce_init_device(struct iforce *iforce)
*/ */
if (!iforce_get_id_packet(iforce, "M")) if (!iforce_get_id_packet(iforce, "M"))
iforce->dev.id.vendor = (iforce->edata[2] << 8) | iforce->edata[1]; input_dev->id.vendor = (iforce->edata[2] << 8) | iforce->edata[1];
else else
printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet M\n"); printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet M\n");
if (!iforce_get_id_packet(iforce, "P")) if (!iforce_get_id_packet(iforce, "P"))
iforce->dev.id.product = (iforce->edata[2] << 8) | iforce->edata[1]; input_dev->id.product = (iforce->edata[2] << 8) | iforce->edata[1];
else else
printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet P\n"); printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet P\n");
@ -422,15 +429,15 @@ int iforce_init_device(struct iforce *iforce)
printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet B\n"); printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet B\n");
if (!iforce_get_id_packet(iforce, "N")) if (!iforce_get_id_packet(iforce, "N"))
iforce->dev.ff_effects_max = iforce->edata[1]; iforce->dev->ff_effects_max = iforce->edata[1];
else else
printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet N\n"); printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet N\n");
/* Check if the device can store more effects than the driver can really handle */ /* Check if the device can store more effects than the driver can really handle */
if (iforce->dev.ff_effects_max > FF_EFFECTS_MAX) { if (iforce->dev->ff_effects_max > FF_EFFECTS_MAX) {
printk(KERN_WARNING "input??: Device can handle %d effects, but N_EFFECTS_MAX is set to %d in iforce.h\n", printk(KERN_WARNING "input??: Device can handle %d effects, but N_EFFECTS_MAX is set to %d in iforce.h\n",
iforce->dev.ff_effects_max, FF_EFFECTS_MAX); iforce->dev->ff_effects_max, FF_EFFECTS_MAX);
iforce->dev.ff_effects_max = FF_EFFECTS_MAX; iforce->dev->ff_effects_max = FF_EFFECTS_MAX;
} }
/* /*
@ -453,29 +460,28 @@ int iforce_init_device(struct iforce *iforce)
*/ */
for (i = 0; iforce_device[i].idvendor; i++) for (i = 0; iforce_device[i].idvendor; i++)
if (iforce_device[i].idvendor == iforce->dev.id.vendor && if (iforce_device[i].idvendor == input_dev->id.vendor &&
iforce_device[i].idproduct == iforce->dev.id.product) iforce_device[i].idproduct == input_dev->id.product)
break; break;
iforce->type = iforce_device + i; iforce->type = iforce_device + i;
iforce->dev.name = iforce->type->name; input_dev->name = iforce->type->name;
/* /*
* Set input device bitfields and ranges. * Set input device bitfields and ranges.
*/ */
iforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF) | BIT(EV_FF_STATUS); input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF) | BIT(EV_FF_STATUS);
for (i = 0; iforce->type->btn[i] >= 0; i++) { for (i = 0; iforce->type->btn[i] >= 0; i++) {
signed short t = iforce->type->btn[i]; signed short t = iforce->type->btn[i];
set_bit(t, iforce->dev.keybit); set_bit(t, input_dev->keybit);
} }
set_bit(BTN_DEAD, iforce->dev.keybit); set_bit(BTN_DEAD, input_dev->keybit);
for (i = 0; iforce->type->abs[i] >= 0; i++) { for (i = 0; iforce->type->abs[i] >= 0; i++) {
signed short t = iforce->type->abs[i]; signed short t = iforce->type->abs[i];
set_bit(t, iforce->dev.absbit);
switch (t) { switch (t) {
@ -483,52 +489,42 @@ int iforce_init_device(struct iforce *iforce)
case ABS_Y: case ABS_Y:
case ABS_WHEEL: case ABS_WHEEL:
iforce->dev.absmax[t] = 1920; input_set_abs_params(input_dev, t, -1920, 1920, 16, 128);
iforce->dev.absmin[t] = -1920; set_bit(t, input_dev->ffbit);
iforce->dev.absflat[t] = 128;
iforce->dev.absfuzz[t] = 16;
set_bit(t, iforce->dev.ffbit);
break; break;
case ABS_THROTTLE: case ABS_THROTTLE:
case ABS_GAS: case ABS_GAS:
case ABS_BRAKE: case ABS_BRAKE:
iforce->dev.absmax[t] = 255; input_set_abs_params(input_dev, t, 0, 255, 0, 0);
iforce->dev.absmin[t] = 0;
break; break;
case ABS_RUDDER: case ABS_RUDDER:
iforce->dev.absmax[t] = 127; input_set_abs_params(input_dev, t, -128, 127, 0, 0);
iforce->dev.absmin[t] = -128;
break; break;
case ABS_HAT0X: case ABS_HAT0X:
case ABS_HAT0Y: case ABS_HAT0Y:
case ABS_HAT1X: case ABS_HAT1X:
case ABS_HAT1Y: case ABS_HAT1Y:
iforce->dev.absmax[t] = 1;
iforce->dev.absmin[t] = -1; input_set_abs_params(input_dev, t, -1, 1, 0, 0);
break; break;
} }
} }
for (i = 0; iforce->type->ff[i] >= 0; i++) for (i = 0; iforce->type->ff[i] >= 0; i++)
set_bit(iforce->type->ff[i], iforce->dev.ffbit); set_bit(iforce->type->ff[i], input_dev->ffbit);
/* /*
* Register input device. * Register input device.
*/ */
input_register_device(&iforce->dev); input_register_device(iforce->dev);
printk(KERN_DEBUG "iforce->dev.open = %p\n", iforce->dev.open); printk(KERN_DEBUG "iforce->dev->open = %p\n", iforce->dev->open);
printk(KERN_INFO "input: %s [%d effects, %ld bytes memory]\n",
iforce->dev.name, iforce->dev.ff_effects_max,
iforce->device_memory.end);
return 0; return 0;
} }

View file

@ -139,7 +139,8 @@ printk(KERN_DEBUG "iforce-packets.c: control_playback %d %d\n", id, value);
static int mark_core_as_ready(struct iforce *iforce, unsigned short addr) static int mark_core_as_ready(struct iforce *iforce, unsigned short addr)
{ {
int i; int i;
for (i=0; i<iforce->dev.ff_effects_max; ++i) {
for (i = 0; i < iforce->dev->ff_effects_max; ++i) {
if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) && if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) &&
(iforce->core_effects[i].mod1_chunk.start == addr || (iforce->core_effects[i].mod1_chunk.start == addr ||
iforce->core_effects[i].mod2_chunk.start == addr)) { iforce->core_effects[i].mod2_chunk.start == addr)) {
@ -153,7 +154,7 @@ static int mark_core_as_ready(struct iforce *iforce, unsigned short addr)
void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data, struct pt_regs *regs) void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data, struct pt_regs *regs)
{ {
struct input_dev *dev = &iforce->dev; struct input_dev *dev = iforce->dev;
int i; int i;
static int being_used = 0; static int being_used = 0;

View file

@ -131,11 +131,10 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
struct iforce *iforce; struct iforce *iforce;
int err; int err;
if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL))) iforce = kzalloc(sizeof(struct iforce), GFP_KERNEL);
if (!iforce)
return -ENOMEM; return -ENOMEM;
memset(iforce, 0, sizeof(struct iforce));
iforce->bus = IFORCE_232; iforce->bus = IFORCE_232;
iforce->serio = serio; iforce->serio = serio;
@ -148,7 +147,8 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
return err; return err;
} }
if (iforce_init_device(iforce)) { err = iforce_init_device(iforce);
if (err) {
serio_close(serio); serio_close(serio);
serio_set_drvdata(serio, NULL); serio_set_drvdata(serio, NULL);
kfree(iforce); kfree(iforce);
@ -162,7 +162,7 @@ static void iforce_serio_disconnect(struct serio *serio)
{ {
struct iforce *iforce = serio_get_drvdata(serio); struct iforce *iforce = serio_get_drvdata(serio);
input_unregister_device(&iforce->dev); input_unregister_device(iforce->dev);
serio_close(serio); serio_close(serio);
serio_set_drvdata(serio, NULL); serio_set_drvdata(serio, NULL);
kfree(iforce); kfree(iforce);

View file

@ -135,28 +135,24 @@ static int iforce_usb_probe(struct usb_interface *intf,
struct usb_host_interface *interface; struct usb_host_interface *interface;
struct usb_endpoint_descriptor *epirq, *epout; struct usb_endpoint_descriptor *epirq, *epout;
struct iforce *iforce; struct iforce *iforce;
int err = -ENOMEM;
interface = intf->cur_altsetting; interface = intf->cur_altsetting;
epirq = &interface->endpoint[0].desc; epirq = &interface->endpoint[0].desc;
epout = &interface->endpoint[1].desc; epout = &interface->endpoint[1].desc;
if (!(iforce = kmalloc(sizeof(struct iforce) + 32, GFP_KERNEL))) if (!(iforce = kzalloc(sizeof(struct iforce) + 32, GFP_KERNEL)))
goto fail; goto fail;
memset(iforce, 0, sizeof(struct iforce)); if (!(iforce->irq = usb_alloc_urb(0, GFP_KERNEL)))
if (!(iforce->irq = usb_alloc_urb(0, GFP_KERNEL))) {
goto fail; goto fail;
}
if (!(iforce->out = usb_alloc_urb(0, GFP_KERNEL))) { if (!(iforce->out = usb_alloc_urb(0, GFP_KERNEL)))
goto fail; goto fail;
}
if (!(iforce->ctrl = usb_alloc_urb(0, GFP_KERNEL))) { if (!(iforce->ctrl = usb_alloc_urb(0, GFP_KERNEL)))
goto fail; goto fail;
}
iforce->bus = IFORCE_USB; iforce->bus = IFORCE_USB;
iforce->usbdev = dev; iforce->usbdev = dev;
@ -174,7 +170,9 @@ static int iforce_usb_probe(struct usb_interface *intf,
usb_fill_control_urb(iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0), usb_fill_control_urb(iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0),
(void*) &iforce->cr, iforce->edata, 16, iforce_usb_ctrl, iforce); (void*) &iforce->cr, iforce->edata, 16, iforce_usb_ctrl, iforce);
if (iforce_init_device(iforce)) goto fail; err = iforce_init_device(iforce);
if (err)
goto fail;
usb_set_intfdata(intf, iforce); usb_set_intfdata(intf, iforce);
return 0; return 0;
@ -187,7 +185,7 @@ fail:
kfree(iforce); kfree(iforce);
} }
return -ENODEV; return err;
} }
/* Called by iforce_delete() */ /* Called by iforce_delete() */
@ -211,7 +209,7 @@ static void iforce_usb_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL); usb_set_intfdata(intf, NULL);
if (iforce) { if (iforce) {
iforce->usbdev = NULL; iforce->usbdev = NULL;
input_unregister_device(&iforce->dev); input_unregister_device(iforce->dev);
if (!open) { if (!open) {
iforce_delete_device(iforce); iforce_delete_device(iforce);

View file

@ -117,7 +117,7 @@ struct iforce_device {
}; };
struct iforce { struct iforce {
struct input_dev dev; /* Input device interface */ struct input_dev *dev; /* Input device interface */
struct iforce_device *type; struct iforce_device *type;
int bus; int bus;

View file

@ -54,7 +54,7 @@ MODULE_LICENSE("GPL");
struct interact { struct interact {
struct gameport *gameport; struct gameport *gameport;
struct input_dev dev; struct input_dev *dev;
int bads; int bads;
int reads; int reads;
unsigned char type; unsigned char type;
@ -130,7 +130,7 @@ static int interact_read_packet(struct gameport *gameport, int length, u32 *data
static void interact_poll(struct gameport *gameport) static void interact_poll(struct gameport *gameport)
{ {
struct interact *interact = gameport_get_drvdata(gameport); struct interact *interact = gameport_get_drvdata(gameport);
struct input_dev *dev = &interact->dev; struct input_dev *dev = interact->dev;
u32 data[3]; u32 data[3];
int i; int i;
@ -208,14 +208,20 @@ static void interact_close(struct input_dev *dev)
static int interact_connect(struct gameport *gameport, struct gameport_driver *drv) static int interact_connect(struct gameport *gameport, struct gameport_driver *drv)
{ {
struct interact *interact; struct interact *interact;
struct input_dev *input_dev;
__u32 data[3]; __u32 data[3];
int i, t; int i, t;
int err; int err;
if (!(interact = kzalloc(sizeof(struct interact), GFP_KERNEL))) interact = kzalloc(sizeof(struct interact), GFP_KERNEL);
return -ENOMEM; input_dev = input_allocate_device();
if (!interact || !input_dev) {
err = -ENOMEM;
goto fail1;
}
interact->gameport = gameport; interact->gameport = gameport;
interact->dev = input_dev;
gameport_set_drvdata(gameport, interact); gameport_set_drvdata(gameport, interact);
@ -249,41 +255,40 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d
interact->type = i; interact->type = i;
interact->length = interact_type[i].length; interact->length = interact_type[i].length;
interact->dev.private = interact; input_dev->name = interact_type[i].name;
interact->dev.open = interact_open; input_dev->phys = interact->phys;
interact->dev.close = interact_close; input_dev->id.bustype = BUS_GAMEPORT;
input_dev->id.vendor = GAMEPORT_ID_VENDOR_INTERACT;
input_dev->id.product = interact_type[i].id;
input_dev->id.version = 0x0100;
input_dev->private = interact;
interact->dev.name = interact_type[i].name; input_dev->open = interact_open;
interact->dev.phys = interact->phys; input_dev->close = interact_close;
interact->dev.id.bustype = BUS_GAMEPORT;
interact->dev.id.vendor = GAMEPORT_ID_VENDOR_INTERACT;
interact->dev.id.product = interact_type[i].id;
interact->dev.id.version = 0x0100;
interact->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; (t = interact_type[interact->type].abs[i]) >= 0; i++) { for (i = 0; (t = interact_type[interact->type].abs[i]) >= 0; i++) {
set_bit(t, interact->dev.absbit); set_bit(t, input_dev->absbit);
if (i < interact_type[interact->type].b8) { if (i < interact_type[interact->type].b8) {
interact->dev.absmin[t] = 0; input_dev->absmin[t] = 0;
interact->dev.absmax[t] = 255; input_dev->absmax[t] = 255;
} else { } else {
interact->dev.absmin[t] = -1; input_dev->absmin[t] = -1;
interact->dev.absmax[t] = 1; input_dev->absmax[t] = 1;
} }
} }
for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++) for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++)
set_bit(t, interact->dev.keybit); set_bit(t, input_dev->keybit);
input_register_device(&interact->dev); input_register_device(interact->dev);
printk(KERN_INFO "input: %s on %s\n",
interact_type[interact->type].name, gameport->phys);
return 0; return 0;
fail2: gameport_close(gameport); fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL); fail1: gameport_set_drvdata(gameport, NULL);
input_free_device(input_dev);
kfree(interact); kfree(interact);
return err; return err;
} }
@ -292,7 +297,7 @@ static void interact_disconnect(struct gameport *gameport)
{ {
struct interact *interact = gameport_get_drvdata(gameport); struct interact *interact = gameport_get_drvdata(gameport);
input_unregister_device(&interact->dev); input_unregister_device(interact->dev);
gameport_close(gameport); gameport_close(gameport);
gameport_set_drvdata(gameport, NULL); gameport_set_drvdata(gameport, NULL);
kfree(interact); kfree(interact);

View file

@ -49,14 +49,13 @@ MODULE_LICENSE("GPL");
static int magellan_buttons[] = { BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 }; static int magellan_buttons[] = { BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 };
static int magellan_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ }; static int magellan_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
static char *magellan_name = "LogiCad3D Magellan / SpaceMouse";
/* /*
* Per-Magellan data. * Per-Magellan data.
*/ */
struct magellan { struct magellan {
struct input_dev dev; struct input_dev *dev;
int idx; int idx;
unsigned char data[MAGELLAN_MAX_LENGTH]; unsigned char data[MAGELLAN_MAX_LENGTH];
char phys[32]; char phys[32];
@ -85,7 +84,7 @@ static int magellan_crunch_nibbles(unsigned char *data, int count)
static void magellan_process_packet(struct magellan* magellan, struct pt_regs *regs) static void magellan_process_packet(struct magellan* magellan, struct pt_regs *regs)
{ {
struct input_dev *dev = &magellan->dev; struct input_dev *dev = magellan->dev;
unsigned char *data = magellan->data; unsigned char *data = magellan->data;
int i, t; int i, t;
@ -138,9 +137,9 @@ static void magellan_disconnect(struct serio *serio)
{ {
struct magellan* magellan = serio_get_drvdata(serio); struct magellan* magellan = serio_get_drvdata(serio);
input_unregister_device(&magellan->dev);
serio_close(serio); serio_close(serio);
serio_set_drvdata(serio, NULL); serio_set_drvdata(serio, NULL);
input_unregister_device(magellan->dev);
kfree(magellan); kfree(magellan);
} }
@ -153,52 +152,48 @@ static void magellan_disconnect(struct serio *serio)
static int magellan_connect(struct serio *serio, struct serio_driver *drv) static int magellan_connect(struct serio *serio, struct serio_driver *drv)
{ {
struct magellan *magellan; struct magellan *magellan;
int i, t; struct input_dev *input_dev;
int err; int err = -ENOMEM;
int i;
if (!(magellan = kmalloc(sizeof(struct magellan), GFP_KERNEL))) magellan = kzalloc(sizeof(struct magellan), GFP_KERNEL);
return -ENOMEM; input_dev = input_allocate_device();
if (!magellan || !input_dev)
memset(magellan, 0, sizeof(struct magellan)); goto fail;
magellan->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; i < 9; i++)
set_bit(magellan_buttons[i], magellan->dev.keybit);
for (i = 0; i < 6; i++) {
t = magellan_axes[i];
set_bit(t, magellan->dev.absbit);
magellan->dev.absmin[t] = -360;
magellan->dev.absmax[t] = 360;
}
magellan->dev = input_dev;
sprintf(magellan->phys, "%s/input0", serio->phys); sprintf(magellan->phys, "%s/input0", serio->phys);
init_input_dev(&magellan->dev); input_dev->name = "LogiCad3D Magellan / SpaceMouse";
magellan->dev.private = magellan; input_dev->phys = magellan->phys;
magellan->dev.name = magellan_name; input_dev->id.bustype = BUS_RS232;
magellan->dev.phys = magellan->phys; input_dev->id.vendor = SERIO_MAGELLAN;
magellan->dev.id.bustype = BUS_RS232; input_dev->id.product = 0x0001;
magellan->dev.id.vendor = SERIO_MAGELLAN; input_dev->id.version = 0x0100;
magellan->dev.id.product = 0x0001; input_dev->cdev.dev = &serio->dev;
magellan->dev.id.version = 0x0100; input_dev->private = magellan;
magellan->dev.dev = &serio->dev;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; i < 9; i++)
set_bit(magellan_buttons[i], input_dev->keybit);
for (i = 0; i < 6; i++)
input_set_abs_params(input_dev, magellan_axes[i], -360, 360, 0, 0);
serio_set_drvdata(serio, magellan); serio_set_drvdata(serio, magellan);
err = serio_open(serio, drv); err = serio_open(serio, drv);
if (err) { if (err)
serio_set_drvdata(serio, NULL); goto fail;
input_register_device(magellan->dev);
return 0;
fail: serio_set_drvdata(serio, NULL);
input_free_device(input_dev);
kfree(magellan); kfree(magellan);
return err; return err;
}
input_register_device(&magellan->dev);
printk(KERN_INFO "input: %s on %s\n", magellan_name, serio->phys);
return 0;
} }
/* /*

View file

@ -113,7 +113,7 @@ static struct {
struct sw { struct sw {
struct gameport *gameport; struct gameport *gameport;
struct input_dev dev[4]; struct input_dev *dev[4];
char name[64]; char name[64];
char phys[4][32]; char phys[4][32];
int length; int length;
@ -301,7 +301,7 @@ static int sw_check(__u64 t)
static int sw_parse(unsigned char *buf, struct sw *sw) static int sw_parse(unsigned char *buf, struct sw *sw)
{ {
int hat, i, j; int hat, i, j;
struct input_dev *dev = sw->dev; struct input_dev *dev;
switch (sw->type) { switch (sw->type) {
@ -310,6 +310,8 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8) if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8)
return -1; return -1;
dev = sw->dev[0];
input_report_abs(dev, ABS_X, (GB( 3,3) << 7) | GB(16,7)); input_report_abs(dev, ABS_X, (GB( 3,3) << 7) | GB(16,7));
input_report_abs(dev, ABS_Y, (GB( 0,3) << 7) | GB(24,7)); input_report_abs(dev, ABS_Y, (GB( 0,3) << 7) | GB(24,7));
input_report_abs(dev, ABS_RZ, (GB(35,2) << 7) | GB(40,7)); input_report_abs(dev, ABS_RZ, (GB(35,2) << 7) | GB(40,7));
@ -335,13 +337,13 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (sw_parity(GB(i*15,15))) if (sw_parity(GB(i*15,15)))
return -1; return -1;
input_report_abs(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1)); input_report_abs(sw->dev[i], ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
input_report_abs(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1)); input_report_abs(sw->dev[i], ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
for (j = 0; j < 10; j++) for (j = 0; j < 10; j++)
input_report_key(dev + i, sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1)); input_report_key(sw->dev[i], sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1));
input_sync(dev + i); input_sync(sw->dev[i]);
} }
return 0; return 0;
@ -352,6 +354,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8) if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8)
return -1; return -1;
dev = sw->dev[0];
input_report_abs(dev, ABS_X, GB( 9,10)); input_report_abs(dev, ABS_X, GB( 9,10));
input_report_abs(dev, ABS_Y, GB(19,10)); input_report_abs(dev, ABS_Y, GB(19,10));
input_report_abs(dev, ABS_RZ, GB(36, 6)); input_report_abs(dev, ABS_RZ, GB(36, 6));
@ -372,6 +375,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8) if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8)
return -1; return -1;
dev = sw->dev[0];
input_report_abs(dev, ABS_X, GB( 0,10)); input_report_abs(dev, ABS_X, GB( 0,10));
input_report_abs(dev, ABS_Y, GB(16,10)); input_report_abs(dev, ABS_Y, GB(16,10));
input_report_abs(dev, ABS_THROTTLE, GB(32, 6)); input_report_abs(dev, ABS_THROTTLE, GB(32, 6));
@ -396,6 +400,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (!sw_parity(GB(0,33))) if (!sw_parity(GB(0,33)))
return -1; return -1;
dev = sw->dev[0];
input_report_abs(dev, ABS_RX, GB( 0,10)); input_report_abs(dev, ABS_RX, GB( 0,10));
input_report_abs(dev, ABS_RUDDER, GB(10, 6)); input_report_abs(dev, ABS_RUDDER, GB(10, 6));
input_report_abs(dev, ABS_THROTTLE, GB(16, 6)); input_report_abs(dev, ABS_THROTTLE, GB(16, 6));
@ -581,6 +586,7 @@ static int sw_guess_mode(unsigned char *buf, int len)
static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
{ {
struct sw *sw; struct sw *sw;
struct input_dev *input_dev;
int i, j, k, l; int i, j, k, l;
int err; int err;
unsigned char *buf = NULL; /* [SW_LENGTH] */ unsigned char *buf = NULL; /* [SW_LENGTH] */
@ -729,42 +735,50 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]); sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]);
sprintf(sw->phys[i], "%s/input%d", gameport->phys, i); sprintf(sw->phys[i], "%s/input%d", gameport->phys, i);
sw->dev[i].private = sw; input_dev = input_allocate_device();
if (!input_dev) {
err = -ENOMEM;
goto fail3;
}
sw->dev[i].open = sw_open; input_dev->name = sw->name;
sw->dev[i].close = sw_close; input_dev->phys = sw->phys[i];
input_dev->id.bustype = BUS_GAMEPORT;
input_dev->id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT;
input_dev->id.product = sw->type;
input_dev->id.version = 0x0100;
input_dev->cdev.dev = &gameport->dev;
input_dev->private = sw;
sw->dev[i].name = sw->name; input_dev->open = sw_open;
sw->dev[i].phys = sw->phys[i]; input_dev->close = sw_close;
sw->dev[i].id.bustype = BUS_GAMEPORT;
sw->dev[i].id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT;
sw->dev[i].id.product = sw->type;
sw->dev[i].id.version = 0x0100;
sw->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (j = 0; (bits = sw_bit[sw->type][j]); j++) { for (j = 0; (bits = sw_bit[sw->type][j]); j++) {
code = sw_abs[sw->type][j]; code = sw_abs[sw->type][j];
set_bit(code, sw->dev[i].absbit); set_bit(code, input_dev->absbit);
sw->dev[i].absmax[code] = (1 << bits) - 1; input_dev->absmax[code] = (1 << bits) - 1;
sw->dev[i].absmin[code] = (bits == 1) ? -1 : 0; input_dev->absmin[code] = (bits == 1) ? -1 : 0;
sw->dev[i].absfuzz[code] = ((bits >> 1) >= 2) ? (1 << ((bits >> 1) - 2)) : 0; input_dev->absfuzz[code] = ((bits >> 1) >= 2) ? (1 << ((bits >> 1) - 2)) : 0;
if (code != ABS_THROTTLE) if (code != ABS_THROTTLE)
sw->dev[i].absflat[code] = (bits >= 5) ? (1 << (bits - 5)) : 0; input_dev->absflat[code] = (bits >= 5) ? (1 << (bits - 5)) : 0;
} }
for (j = 0; (code = sw_btn[sw->type][j]); j++) for (j = 0; (code = sw_btn[sw->type][j]); j++)
set_bit(code, sw->dev[i].keybit); set_bit(code, input_dev->keybit);
input_register_device(sw->dev + i); dbg("%s%s [%d-bit id %d data %d]\n", sw->name, comment, m, l, k);
printk(KERN_INFO "input: %s%s on %s [%d-bit id %d data %d]\n",
sw->name, comment, gameport->phys, m, l, k); input_register_device(sw->dev[i]);
} }
return 0; return 0;
fail2: gameport_close(gameport); fail3: while (--i >= 0)
fail1: gameport_set_drvdata(gameport, NULL); input_unregister_device(sw->dev[i]);
fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL);
kfree(sw); kfree(sw);
kfree(buf); kfree(buf);
kfree(idbuf); kfree(idbuf);
@ -777,7 +791,7 @@ static void sw_disconnect(struct gameport *gameport)
int i; int i;
for (i = 0; i < sw->number; i++) for (i = 0; i < sw->number; i++)
input_unregister_device(sw->dev + i); input_unregister_device(sw->dev[i]);
gameport_close(gameport); gameport_close(gameport);
gameport_set_drvdata(gameport, NULL); gameport_set_drvdata(gameport, NULL);
kfree(sw); kfree(sw);

View file

@ -70,8 +70,7 @@ static char *spaceball_names[] = {
*/ */
struct spaceball { struct spaceball {
struct input_dev dev; struct input_dev *dev;
struct serio *serio;
int idx; int idx;
int escape; int escape;
unsigned char data[SPACEBALL_MAX_LENGTH]; unsigned char data[SPACEBALL_MAX_LENGTH];
@ -85,7 +84,7 @@ struct spaceball {
static void spaceball_process_packet(struct spaceball* spaceball, struct pt_regs *regs) static void spaceball_process_packet(struct spaceball* spaceball, struct pt_regs *regs)
{ {
struct input_dev *dev = &spaceball->dev; struct input_dev *dev = spaceball->dev;
unsigned char *data = spaceball->data; unsigned char *data = spaceball->data;
int i; int i;
@ -193,9 +192,9 @@ static void spaceball_disconnect(struct serio *serio)
{ {
struct spaceball* spaceball = serio_get_drvdata(serio); struct spaceball* spaceball = serio_get_drvdata(serio);
input_unregister_device(&spaceball->dev);
serio_close(serio); serio_close(serio);
serio_set_drvdata(serio, NULL); serio_set_drvdata(serio, NULL);
input_unregister_device(spaceball->dev);
kfree(spaceball); kfree(spaceball);
} }
@ -208,69 +207,62 @@ static void spaceball_disconnect(struct serio *serio)
static int spaceball_connect(struct serio *serio, struct serio_driver *drv) static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
{ {
struct spaceball *spaceball; struct spaceball *spaceball;
int i, t, id; struct input_dev *input_dev;
int err; int err = -ENOMEM;
int i, id;
if ((id = serio->id.id) > SPACEBALL_MAX_ID) if ((id = serio->id.id) > SPACEBALL_MAX_ID)
return -ENODEV; return -ENODEV;
if (!(spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL))) spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL);
return - ENOMEM; input_dev = input_allocate_device();
if (!spaceball || !input_dev)
goto fail;
memset(spaceball, 0, sizeof(struct spaceball)); spaceball->dev = input_dev;
sprintf(spaceball->phys, "%s/input0", serio->phys);
spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->name = spaceball_names[id];
input_dev->phys = spaceball->phys;
input_dev->id.bustype = BUS_RS232;
input_dev->id.vendor = SERIO_SPACEBALL;
input_dev->id.product = id;
input_dev->id.version = 0x0100;
input_dev->cdev.dev = &serio->dev;
input_dev->private = spaceball;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
switch (id) { switch (id) {
case SPACEBALL_4000FLX: case SPACEBALL_4000FLX:
case SPACEBALL_4000FLX_L: case SPACEBALL_4000FLX_L:
spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_9); input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_9);
spaceball->dev.keybit[LONG(BTN_A)] |= BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_MODE); input_dev->keybit[LONG(BTN_A)] |= BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_MODE);
default: default:
spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4)
| BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7) | BIT(BTN_8); | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7) | BIT(BTN_8);
case SPACEBALL_3003C: case SPACEBALL_3003C:
spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_1) | BIT(BTN_8); input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_1) | BIT(BTN_8);
} }
for (i = 0; i < 6; i++) { for (i = 0; i < 3; i++) {
t = spaceball_axes[i]; input_set_abs_params(input_dev, ABS_X + i, -8000, 8000, 8, 40);
set_bit(t, spaceball->dev.absbit); input_set_abs_params(input_dev, ABS_RX + i, -1600, 1600, 2, 8);
spaceball->dev.absmin[t] = i < 3 ? -8000 : -1600;
spaceball->dev.absmax[t] = i < 3 ? 8000 : 1600;
spaceball->dev.absflat[t] = i < 3 ? 40 : 8;
spaceball->dev.absfuzz[t] = i < 3 ? 8 : 2;
} }
spaceball->serio = serio;
spaceball->dev.private = spaceball;
sprintf(spaceball->phys, "%s/input0", serio->phys);
init_input_dev(&spaceball->dev);
spaceball->dev.name = spaceball_names[id];
spaceball->dev.phys = spaceball->phys;
spaceball->dev.id.bustype = BUS_RS232;
spaceball->dev.id.vendor = SERIO_SPACEBALL;
spaceball->dev.id.product = id;
spaceball->dev.id.version = 0x0100;
spaceball->dev.dev = &serio->dev;
serio_set_drvdata(serio, spaceball); serio_set_drvdata(serio, spaceball);
err = serio_open(serio, drv); err = serio_open(serio, drv);
if (err) { if (err)
serio_set_drvdata(serio, NULL); goto fail;
input_register_device(spaceball->dev);
return 0;
fail: serio_set_drvdata(serio, NULL);
input_free_device(input_dev);
kfree(spaceball); kfree(spaceball);
return err; return err;
}
input_register_device(&spaceball->dev);
printk(KERN_INFO "input: %s on serio%s\n",
spaceball_names[id], serio->phys);
return 0;
} }
/* /*

View file

@ -52,15 +52,13 @@ MODULE_LICENSE("GPL");
static int spaceorb_buttons[] = { BTN_TL, BTN_TR, BTN_Y, BTN_X, BTN_B, BTN_A }; static int spaceorb_buttons[] = { BTN_TL, BTN_TR, BTN_Y, BTN_X, BTN_B, BTN_A };
static int spaceorb_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ }; static int spaceorb_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
static char *spaceorb_name = "SpaceTec SpaceOrb 360 / Avenger";
/* /*
* Per-Orb data. * Per-Orb data.
*/ */
struct spaceorb { struct spaceorb {
struct input_dev dev; struct input_dev *dev;
struct serio *serio;
int idx; int idx;
unsigned char data[SPACEORB_MAX_LENGTH]; unsigned char data[SPACEORB_MAX_LENGTH];
char phys[32]; char phys[32];
@ -78,7 +76,7 @@ static unsigned char *spaceorb_errors[] = { "EEPROM storing 0 failed", "Receive
static void spaceorb_process_packet(struct spaceorb *spaceorb, struct pt_regs *regs) static void spaceorb_process_packet(struct spaceorb *spaceorb, struct pt_regs *regs)
{ {
struct input_dev *dev = &spaceorb->dev; struct input_dev *dev = spaceorb->dev;
unsigned char *data = spaceorb->data; unsigned char *data = spaceorb->data;
unsigned char c = 0; unsigned char c = 0;
int axes[6]; int axes[6];
@ -95,8 +93,8 @@ static void spaceorb_process_packet(struct spaceorb *spaceorb, struct pt_regs *r
case 'R': /* Reset packet */ case 'R': /* Reset packet */
spaceorb->data[spaceorb->idx - 1] = 0; spaceorb->data[spaceorb->idx - 1] = 0;
for (i = 1; i < spaceorb->idx && spaceorb->data[i] == ' '; i++); for (i = 1; i < spaceorb->idx && spaceorb->data[i] == ' '; i++);
printk(KERN_INFO "input: %s [%s] on %s\n", printk(KERN_INFO "input: %s [%s] is %s\n",
spaceorb_name, spaceorb->data + i, spaceorb->serio->phys); dev->name, spaceorb->data + i, spaceorb->phys);
break; break;
case 'D': /* Ball + button data */ case 'D': /* Ball + button data */
@ -123,7 +121,7 @@ static void spaceorb_process_packet(struct spaceorb *spaceorb, struct pt_regs *r
case 'E': /* Error packet */ case 'E': /* Error packet */
if (spaceorb->idx != 4) return; if (spaceorb->idx != 4) return;
printk(KERN_ERR "joy-spaceorb: Device error. [ "); printk(KERN_ERR "spaceorb: Device error. [ ");
for (i = 0; i < 7; i++) if (data[1] & (1 << i)) printk("%s ", spaceorb_errors[i]); for (i = 0; i < 7; i++) if (data[1] & (1 << i)) printk("%s ", spaceorb_errors[i]);
printk("]\n"); printk("]\n");
break; break;
@ -154,9 +152,9 @@ static void spaceorb_disconnect(struct serio *serio)
{ {
struct spaceorb* spaceorb = serio_get_drvdata(serio); struct spaceorb* spaceorb = serio_get_drvdata(serio);
input_unregister_device(&spaceorb->dev);
serio_close(serio); serio_close(serio);
serio_set_drvdata(serio, NULL); serio_set_drvdata(serio, NULL);
input_unregister_device(spaceorb->dev);
kfree(spaceorb); kfree(spaceorb);
} }
@ -169,52 +167,48 @@ static void spaceorb_disconnect(struct serio *serio)
static int spaceorb_connect(struct serio *serio, struct serio_driver *drv) static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
{ {
struct spaceorb *spaceorb; struct spaceorb *spaceorb;
int i, t; struct input_dev *input_dev;
int err; int err = -ENOMEM;
int i;
if (!(spaceorb = kmalloc(sizeof(struct spaceorb), GFP_KERNEL))) spaceorb = kzalloc(sizeof(struct spaceorb), GFP_KERNEL);
return -ENOMEM; input_dev = input_allocate_device();
if (!spaceorb || !input_dev)
memset(spaceorb, 0, sizeof(struct spaceorb)); goto fail;
spaceorb->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; i < 6; i++)
set_bit(spaceorb_buttons[i], spaceorb->dev.keybit);
for (i = 0; i < 6; i++) {
t = spaceorb_axes[i];
set_bit(t, spaceorb->dev.absbit);
spaceorb->dev.absmin[t] = -508;
spaceorb->dev.absmax[t] = 508;
}
spaceorb->serio = serio;
spaceorb->dev.private = spaceorb;
spaceorb->dev = input_dev;
sprintf(spaceorb->phys, "%s/input0", serio->phys); sprintf(spaceorb->phys, "%s/input0", serio->phys);
init_input_dev(&spaceorb->dev); input_dev->name = "SpaceTec SpaceOrb 360 / Avenger";
spaceorb->dev.name = spaceorb_name; input_dev->phys = spaceorb->phys;
spaceorb->dev.phys = spaceorb->phys; input_dev->id.bustype = BUS_RS232;
spaceorb->dev.id.bustype = BUS_RS232; input_dev->id.vendor = SERIO_SPACEORB;
spaceorb->dev.id.vendor = SERIO_SPACEORB; input_dev->id.product = 0x0001;
spaceorb->dev.id.product = 0x0001; input_dev->id.version = 0x0100;
spaceorb->dev.id.version = 0x0100; input_dev->cdev.dev = &serio->dev;
spaceorb->dev.dev = &serio->dev; input_dev->private = spaceorb;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; i < 6; i++)
set_bit(spaceorb_buttons[i], input_dev->keybit);
for (i = 0; i < 6; i++)
input_set_abs_params(input_dev, spaceorb_axes[i], -508, 508, 0, 0);
serio_set_drvdata(serio, spaceorb); serio_set_drvdata(serio, spaceorb);
err = serio_open(serio, drv); err = serio_open(serio, drv);
if (err) { if (err)
serio_set_drvdata(serio, NULL); goto fail;
input_register_device(spaceorb->dev);
return 0;
fail: serio_set_drvdata(serio, NULL);
input_free_device(input_dev);
kfree(spaceorb); kfree(spaceorb);
return err; return err;
}
input_register_device(&spaceorb->dev);
return 0;
} }
/* /*

View file

@ -48,14 +48,12 @@ MODULE_LICENSE("GPL");
#define STINGER_MAX_LENGTH 8 #define STINGER_MAX_LENGTH 8
static char *stinger_name = "Gravis Stinger";
/* /*
* Per-Stinger data. * Per-Stinger data.
*/ */
struct stinger { struct stinger {
struct input_dev dev; struct input_dev *dev;
int idx; int idx;
unsigned char data[STINGER_MAX_LENGTH]; unsigned char data[STINGER_MAX_LENGTH];
char phys[32]; char phys[32];
@ -68,7 +66,7 @@ struct stinger {
static void stinger_process_packet(struct stinger *stinger, struct pt_regs *regs) static void stinger_process_packet(struct stinger *stinger, struct pt_regs *regs)
{ {
struct input_dev *dev = &stinger->dev; struct input_dev *dev = stinger->dev;
unsigned char *data = stinger->data; unsigned char *data = stinger->data;
if (!stinger->idx) return; if (!stinger->idx) return;
@ -126,9 +124,9 @@ static void stinger_disconnect(struct serio *serio)
{ {
struct stinger *stinger = serio_get_drvdata(serio); struct stinger *stinger = serio_get_drvdata(serio);
input_unregister_device(&stinger->dev);
serio_close(serio); serio_close(serio);
serio_set_drvdata(serio, NULL); serio_set_drvdata(serio, NULL);
input_unregister_device(stinger->dev);
kfree(stinger); kfree(stinger);
} }
@ -141,53 +139,46 @@ static void stinger_disconnect(struct serio *serio)
static int stinger_connect(struct serio *serio, struct serio_driver *drv) static int stinger_connect(struct serio *serio, struct serio_driver *drv)
{ {
struct stinger *stinger; struct stinger *stinger;
int i; struct input_dev *input_dev;
int err; int err = -ENOMEM;
if (!(stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL))) stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL);
return -ENOMEM; input_dev = input_allocate_device();
if (!stinger || !input_dev)
memset(stinger, 0, sizeof(struct stinger)); goto fail;
stinger->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
stinger->dev.keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) | \
BIT(BTN_Y) | BIT(BTN_Z) | BIT(BTN_TL) | BIT(BTN_TR) | \
BIT(BTN_START) | BIT(BTN_SELECT);
stinger->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
stinger->dev = input_dev;
sprintf(stinger->phys, "%s/serio0", serio->phys); sprintf(stinger->phys, "%s/serio0", serio->phys);
init_input_dev(&stinger->dev); input_dev->name = "Gravis Stinger";
stinger->dev.name = stinger_name; input_dev->phys = stinger->phys;
stinger->dev.phys = stinger->phys; input_dev->id.bustype = BUS_RS232;
stinger->dev.id.bustype = BUS_RS232; input_dev->id.vendor = SERIO_STINGER;
stinger->dev.id.vendor = SERIO_STINGER; input_dev->id.product = 0x0001;
stinger->dev.id.product = 0x0001; input_dev->id.version = 0x0100;
stinger->dev.id.version = 0x0100; input_dev->cdev.dev = &serio->dev;
stinger->dev.dev = &serio->dev; input_dev->private = stinger;
for (i = 0; i < 2; i++) { input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
stinger->dev.absmax[ABS_X+i] = 64; input_dev->keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) |
stinger->dev.absmin[ABS_X+i] = -64; BIT(BTN_Y) | BIT(BTN_Z) | BIT(BTN_TL) | BIT(BTN_TR) |
stinger->dev.absflat[ABS_X+i] = 4; BIT(BTN_START) | BIT(BTN_SELECT);
} input_set_abs_params(input_dev, ABS_X, -64, 64, 0, 4);
input_set_abs_params(input_dev, ABS_Y, -64, 64, 0, 4);
stinger->dev.private = stinger;
serio_set_drvdata(serio, stinger); serio_set_drvdata(serio, stinger);
err = serio_open(serio, drv); err = serio_open(serio, drv);
if (err) { if (err)
serio_set_drvdata(serio, NULL); goto fail;
input_register_device(stinger->dev);
return 0;
fail: serio_set_drvdata(serio, NULL);
input_free_device(input_dev);
kfree(stinger); kfree(stinger);
return err; return err;
}
input_register_device(&stinger->dev);
printk(KERN_INFO "input: %s on %s\n", stinger_name, serio->phys);
return 0;
} }
/* /*

View file

@ -63,37 +63,70 @@ MODULE_LICENSE("GPL");
#define TMDC_ABS_HAT 4 #define TMDC_ABS_HAT 4
#define TMDC_BTN 16 #define TMDC_BTN 16
static unsigned char tmdc_byte_a[16] = { 0, 1, 3, 4, 6, 7 }; static const unsigned char tmdc_byte_a[16] = { 0, 1, 3, 4, 6, 7 };
static unsigned char tmdc_byte_d[16] = { 2, 5, 8, 9 }; static const unsigned char tmdc_byte_d[16] = { 2, 5, 8, 9 };
static signed char tmdc_abs[TMDC_ABS] = static const signed char tmdc_abs[TMDC_ABS] =
{ ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE, ABS_RX, ABS_RY, ABS_RZ }; { ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE, ABS_RX, ABS_RY, ABS_RZ };
static signed char tmdc_abs_hat[TMDC_ABS_HAT] = static const signed char tmdc_abs_hat[TMDC_ABS_HAT] =
{ ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y }; { ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
static signed char tmdc_abs_at[TMDC_ABS] = static const signed char tmdc_abs_at[TMDC_ABS] =
{ ABS_X, ABS_Y, ABS_RUDDER, -1, ABS_THROTTLE }; { ABS_X, ABS_Y, ABS_RUDDER, -1, ABS_THROTTLE };
static signed char tmdc_abs_fm[TMDC_ABS] = static const signed char tmdc_abs_fm[TMDC_ABS] =
{ ABS_RX, ABS_RY, ABS_X, ABS_Y }; { ABS_RX, ABS_RY, ABS_X, ABS_Y };
static short tmdc_btn_pad[TMDC_BTN] = static const short tmdc_btn_pad[TMDC_BTN] =
{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR }; { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR };
static short tmdc_btn_joy[TMDC_BTN] = static const short tmdc_btn_joy[TMDC_BTN] =
{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE, { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE,
BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z }; BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z };
static short tmdc_btn_fm[TMDC_BTN] = static const short tmdc_btn_fm[TMDC_BTN] =
{ BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 }; { BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 };
static short tmdc_btn_at[TMDC_BTN] = static const short tmdc_btn_at[TMDC_BTN] =
{ BTN_TRIGGER, BTN_THUMB2, BTN_PINKIE, BTN_THUMB, BTN_BASE6, BTN_BASE5, BTN_BASE4, { BTN_TRIGGER, BTN_THUMB2, BTN_PINKIE, BTN_THUMB, BTN_BASE6, BTN_BASE5, BTN_BASE4,
BTN_BASE3, BTN_BASE2, BTN_BASE }; BTN_BASE3, BTN_BASE2, BTN_BASE };
static struct { static const struct {
int x; int x;
int y; int y;
} tmdc_hat_to_axis[] = {{ 0, 0}, { 1, 0}, { 0,-1}, {-1, 0}, { 0, 1}}; } tmdc_hat_to_axis[] = {{ 0, 0}, { 1, 0}, { 0,-1}, {-1, 0}, { 0, 1}};
static const struct tmdc_model {
unsigned char id;
const char *name;
char abs;
char hats;
char btnc[4];
char btno[4];
const signed char *axes;
const short *buttons;
} tmdc_models[] = {
{ 1, "ThrustMaster Millenium 3D Inceptor", 6, 2, { 4, 2 }, { 4, 6 }, tmdc_abs, tmdc_btn_joy },
{ 3, "ThrustMaster Rage 3D Gamepad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
{ 4, "ThrustMaster Attack Throttle", 5, 2, { 4, 6 }, { 4, 2 }, tmdc_abs_at, tmdc_btn_at },
{ 8, "ThrustMaster FragMaster", 4, 0, { 8, 2 }, { 0, 0 }, tmdc_abs_fm, tmdc_btn_fm },
{ 163, "Thrustmaster Fusion GamePad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
{ 0, "Unknown %d-axis, %d-button TM device %d", 0, 0, { 0, 0 }, { 0, 0 }, tmdc_abs, tmdc_btn_joy }
};
struct tmdc_port {
struct input_dev *dev;
char name[64];
char phys[32];
int mode;
const signed char *abs;
const short *btn;
unsigned char absc;
unsigned char btnc[4];
unsigned char btno[4];
};
struct tmdc { struct tmdc {
struct gameport *gameport; struct gameport *gameport;
struct input_dev dev[2]; struct tmdc_port *port[2];
#if 0
struct input_dev *dev[2];
char name[2][64]; char name[2][64];
char phys[2][32]; char phys[2][32];
int mode[2]; int mode[2];
@ -102,6 +135,7 @@ struct tmdc {
unsigned char absc[2]; unsigned char absc[2];
unsigned char btnc[2][4]; unsigned char btnc[2][4];
unsigned char btno[2][4]; unsigned char btno[2][4];
#endif
int reads; int reads;
int bads; int bads;
unsigned char exists; unsigned char exists;
@ -156,6 +190,50 @@ static int tmdc_read_packet(struct gameport *gameport, unsigned char data[2][TMD
return (i[0] == TMDC_MAX_LENGTH) | ((i[1] == TMDC_MAX_LENGTH) << 1); return (i[0] == TMDC_MAX_LENGTH) | ((i[1] == TMDC_MAX_LENGTH) << 1);
} }
static int tmdc_parse_packet(struct tmdc_port *port, unsigned char *data)
{
int i, k, l;
if (data[TMDC_BYTE_ID] != port->mode)
return -1;
for (i = 0; i < port->absc; i++) {
if (port->abs[i] < 0)
return 0;
input_report_abs(port->dev, port->abs[i], data[tmdc_byte_a[i]]);
}
switch (port->mode) {
case TMDC_MODE_M3DI:
i = tmdc_byte_d[0];
input_report_abs(port->dev, ABS_HAT0X, ((data[i] >> 3) & 1) - ((data[i] >> 1) & 1));
input_report_abs(port->dev, ABS_HAT0Y, ((data[i] >> 2) & 1) - ( data[i] & 1));
break;
case TMDC_MODE_AT:
i = tmdc_byte_a[3];
input_report_abs(port->dev, ABS_HAT0X, tmdc_hat_to_axis[(data[i] - 141) / 25].x);
input_report_abs(port->dev, ABS_HAT0Y, tmdc_hat_to_axis[(data[i] - 141) / 25].y);
break;
}
for (k = l = 0; k < 4; k++) {
for (i = 0; i < port->btnc[k]; i++)
input_report_key(port->dev, port->btn[i + l],
((data[tmdc_byte_d[k]] >> (i + port->btno[k])) & 1));
l += port->btnc[k];
}
input_sync(port->dev);
return 0;
}
/* /*
* tmdc_poll() reads and analyzes ThrustMaster joystick data. * tmdc_poll() reads and analyzes ThrustMaster joystick data.
*/ */
@ -164,57 +242,21 @@ static void tmdc_poll(struct gameport *gameport)
{ {
unsigned char data[2][TMDC_MAX_LENGTH]; unsigned char data[2][TMDC_MAX_LENGTH];
struct tmdc *tmdc = gameport_get_drvdata(gameport); struct tmdc *tmdc = gameport_get_drvdata(gameport);
struct input_dev *dev;
unsigned char r, bad = 0; unsigned char r, bad = 0;
int i, j, k, l; int i;
tmdc->reads++; tmdc->reads++;
if ((r = tmdc_read_packet(tmdc->gameport, data)) != tmdc->exists) if ((r = tmdc_read_packet(tmdc->gameport, data)) != tmdc->exists)
bad = 1; bad = 1;
else else {
for (i = 0; i < 2; i++) {
if (r & (1 << i) & tmdc->exists) {
for (j = 0; j < 2; j++) if (tmdc_parse_packet(tmdc->port[i], data[i]))
if (r & (1 << j) & tmdc->exists) {
if (data[j][TMDC_BYTE_ID] != tmdc->mode[j]) {
bad = 1; bad = 1;
continue;
} }
dev = tmdc->dev + j;
for (i = 0; i < tmdc->absc[j]; i++) {
if (tmdc->abs[j][i] < 0) continue;
input_report_abs(dev, tmdc->abs[j][i], data[j][tmdc_byte_a[i]]);
} }
switch (tmdc->mode[j]) {
case TMDC_MODE_M3DI:
i = tmdc_byte_d[0];
input_report_abs(dev, ABS_HAT0X, ((data[j][i] >> 3) & 1) - ((data[j][i] >> 1) & 1));
input_report_abs(dev, ABS_HAT0Y, ((data[j][i] >> 2) & 1) - ( data[j][i] & 1));
break;
case TMDC_MODE_AT:
i = tmdc_byte_a[3];
input_report_abs(dev, ABS_HAT0X, tmdc_hat_to_axis[(data[j][i] - 141) / 25].x);
input_report_abs(dev, ABS_HAT0Y, tmdc_hat_to_axis[(data[j][i] - 141) / 25].y);
break;
}
for (k = l = 0; k < 4; k++) {
for (i = 0; i < tmdc->btnc[j][k]; i++)
input_report_key(dev, tmdc->btn[j][i + l],
((data[j][tmdc_byte_d[k]] >> (i + tmdc->btno[j][k])) & 1));
l += tmdc->btnc[j][k];
}
input_sync(dev);
} }
tmdc->bads += bad; tmdc->bads += bad;
@ -235,31 +277,89 @@ static void tmdc_close(struct input_dev *dev)
gameport_stop_polling(tmdc->gameport); gameport_stop_polling(tmdc->gameport);
} }
static int tmdc_setup_port(struct tmdc *tmdc, int idx, unsigned char *data)
{
const struct tmdc_model *model;
struct tmdc_port *port;
struct input_dev *input_dev;
int i, j, b = 0;
tmdc->port[idx] = port = kzalloc(sizeof (struct tmdc_port), GFP_KERNEL);
input_dev = input_allocate_device();
if (!port || !input_dev) {
kfree(port);
input_free_device(input_dev);
return -ENOMEM;
}
port->mode = data[TMDC_BYTE_ID];
for (model = tmdc_models; model->id && model->id != port->mode; model++)
/* empty */;
port->abs = model->axes;
port->btn = model->buttons;
if (!model->id) {
port->absc = data[TMDC_BYTE_DEF] >> 4;
for (i = 0; i < 4; i++)
port->btnc[i] = i < (data[TMDC_BYTE_DEF] & 0xf) ? 8 : 0;
} else {
port->absc = model->abs;
for (i = 0; i < 4; i++)
port->btnc[i] = model->btnc[i];
}
for (i = 0; i < 4; i++)
port->btno[i] = model->btno[i];
snprintf(port->name, sizeof(port->name), model->name,
port->absc, (data[TMDC_BYTE_DEF] & 0xf) << 3, port->mode);
snprintf(port->phys, sizeof(port->phys), "%s/input%d", tmdc->gameport->phys, i);
port->dev = input_dev;
input_dev->name = port->name;
input_dev->phys = port->phys;
input_dev->id.bustype = BUS_GAMEPORT;
input_dev->id.vendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
input_dev->id.product = model->id;
input_dev->id.version = 0x0100;
input_dev->cdev.dev = &tmdc->gameport->dev;
input_dev->private = tmdc;
input_dev->open = tmdc_open;
input_dev->close = tmdc_close;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; i < port->absc && i < TMDC_ABS; i++)
if (port->abs[i] >= 0)
input_set_abs_params(input_dev, port->abs[i], 8, 248, 2, 4);
for (i = 0; i < model->hats && i < TMDC_ABS_HAT; i++)
input_set_abs_params(input_dev, tmdc_abs_hat[i], -1, 1, 0, 0);
for (i = 0; i < 4; i++) {
for (j = 0; j < port->btnc[i] && j < TMDC_BTN; j++)
set_bit(port->btn[j + b], input_dev->keybit);
b += port->btnc[i];
}
input_register_device(port->dev);
return 0;
}
/* /*
* tmdc_probe() probes for ThrustMaster type joysticks. * tmdc_probe() probes for ThrustMaster type joysticks.
*/ */
static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv) static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
{ {
static struct models {
unsigned char id;
char *name;
char abs;
char hats;
char btnc[4];
char btno[4];
signed char *axes;
short *buttons;
} models[] = { { 1, "ThrustMaster Millenium 3D Inceptor", 6, 2, { 4, 2 }, { 4, 6 }, tmdc_abs, tmdc_btn_joy },
{ 3, "ThrustMaster Rage 3D Gamepad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
{ 4, "ThrustMaster Attack Throttle", 5, 2, { 4, 6 }, { 4, 2 }, tmdc_abs_at, tmdc_btn_at },
{ 8, "ThrustMaster FragMaster", 4, 0, { 8, 2 }, { 0, 0 }, tmdc_abs_fm, tmdc_btn_fm },
{ 163, "Thrustmaster Fusion GamePad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
{ 0, "Unknown %d-axis, %d-button TM device %d", 0, 0, { 0, 0 }, { 0, 0 }, tmdc_abs, tmdc_btn_joy }};
unsigned char data[2][TMDC_MAX_LENGTH]; unsigned char data[2][TMDC_MAX_LENGTH];
struct tmdc *tmdc; struct tmdc *tmdc;
int i, j, k, l, m; int i;
int err; int err;
if (!(tmdc = kzalloc(sizeof(struct tmdc), GFP_KERNEL))) if (!(tmdc = kzalloc(sizeof(struct tmdc), GFP_KERNEL)))
@ -281,68 +381,25 @@ static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
gameport_set_poll_handler(gameport, tmdc_poll); gameport_set_poll_handler(gameport, tmdc_poll);
gameport_set_poll_interval(gameport, 20); gameport_set_poll_interval(gameport, 20);
for (j = 0; j < 2; j++) for (i = 0; i < 2; i++) {
if (tmdc->exists & (1 << j)) { if (tmdc->exists & (1 << i)) {
tmdc->mode[j] = data[j][TMDC_BYTE_ID]; err = tmdc_setup_port(tmdc, i, data[i]);
if (err)
for (m = 0; models[m].id && models[m].id != tmdc->mode[j]; m++); goto fail3;
tmdc->abs[j] = models[m].axes;
tmdc->btn[j] = models[m].buttons;
if (!models[m].id) {
models[m].abs = data[j][TMDC_BYTE_DEF] >> 4;
for (k = 0; k < 4; k++)
models[m].btnc[k] = k < (data[j][TMDC_BYTE_DEF] & 0xf) ? 8 : 0;
} }
tmdc->absc[j] = models[m].abs;
for (k = 0; k < 4; k++) {
tmdc->btnc[j][k] = models[m].btnc[k];
tmdc->btno[j][k] = models[m].btno[k];
}
sprintf(tmdc->name[j], models[m].name, models[m].abs,
(data[j][TMDC_BYTE_DEF] & 0xf) << 3, tmdc->mode[j]);
sprintf(tmdc->phys[j], "%s/input%d", gameport->phys, j);
tmdc->dev[j].private = tmdc;
tmdc->dev[j].open = tmdc_open;
tmdc->dev[j].close = tmdc_close;
tmdc->dev[j].name = tmdc->name[j];
tmdc->dev[j].phys = tmdc->phys[j];
tmdc->dev[j].id.bustype = BUS_GAMEPORT;
tmdc->dev[j].id.vendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
tmdc->dev[j].id.product = models[m].id;
tmdc->dev[j].id.version = 0x0100;
tmdc->dev[j].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; i < models[m].abs && i < TMDC_ABS; i++)
if (tmdc->abs[j][i] >= 0)
input_set_abs_params(&tmdc->dev[j], tmdc->abs[j][i], 8, 248, 2, 4);
for (i = 0; i < models[m].hats && i < TMDC_ABS_HAT; i++)
input_set_abs_params(&tmdc->dev[j], tmdc_abs_hat[i], -1, 1, 0, 0);
for (k = l = 0; k < 4; k++) {
for (i = 0; i < models[m].btnc[k] && i < TMDC_BTN; i++)
set_bit(tmdc->btn[j][i + l], tmdc->dev[j].keybit);
l += models[m].btnc[k];
}
input_register_device(tmdc->dev + j);
printk(KERN_INFO "input: %s on %s\n", tmdc->name[j], gameport->phys);
} }
return 0; return 0;
fail2: gameport_close(gameport); fail3: while (--i >= 0) {
fail1: gameport_set_drvdata(gameport, NULL); if (tmdc->port[i]) {
input_unregister_device(tmdc->port[i]->dev);
kfree(tmdc->port[i]);
}
}
fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL);
kfree(tmdc); kfree(tmdc);
return err; return err;
} }
@ -352,9 +409,12 @@ static void tmdc_disconnect(struct gameport *gameport)
struct tmdc *tmdc = gameport_get_drvdata(gameport); struct tmdc *tmdc = gameport_get_drvdata(gameport);
int i; int i;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++) {
if (tmdc->exists & (1 << i)) if (tmdc->port[i]) {
input_unregister_device(tmdc->dev + i); input_unregister_device(tmdc->port[i]->dev);
kfree(tmdc->port[i]);
}
}
gameport_close(gameport); gameport_close(gameport);
gameport_set_drvdata(gameport, NULL); gameport_set_drvdata(gameport, NULL);
kfree(tmdc); kfree(tmdc);

View file

@ -42,19 +42,21 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("TurboGraFX parallel port interface driver"); MODULE_DESCRIPTION("TurboGraFX parallel port interface driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static int tgfx[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 }; #define TGFX_MAX_PORTS 3
static int tgfx_nargs __initdata = 0; #define TGFX_MAX_DEVICES 7
module_param_array_named(map, tgfx, int, &tgfx_nargs, 0);
struct tgfx_config {
int args[TGFX_MAX_DEVICES + 1];
int nargs;
};
static struct tgfx_config tgfx[TGFX_MAX_PORTS] __initdata;
module_param_array_named(map, tgfx[0].args, int, &tgfx[0].nargs, 0);
MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>"); MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>");
module_param_array_named(map2, tgfx[1].args, int, &tgfx[1].nargs, 0);
static int tgfx_2[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
static int tgfx_nargs_2 __initdata = 0;
module_param_array_named(map2, tgfx_2, int, &tgfx_nargs_2, 0);
MODULE_PARM_DESC(map2, "Describes second set of devices"); MODULE_PARM_DESC(map2, "Describes second set of devices");
module_param_array_named(map3, tgfx[2].args, int, &tgfx[2].nargs, 0);
static int tgfx_3[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
static int tgfx_nargs_3 __initdata = 0;
module_param_array_named(map3, tgfx_3, int, &tgfx_nargs_3, 0);
MODULE_PARM_DESC(map3, "Describes third set of devices"); MODULE_PARM_DESC(map3, "Describes third set of devices");
__obsolete_setup("tgfx="); __obsolete_setup("tgfx=");
@ -75,17 +77,17 @@ __obsolete_setup("tgfx_3=");
#define TGFX_TOP2 0x08 #define TGFX_TOP2 0x08
static int tgfx_buttons[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2 }; static int tgfx_buttons[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2 };
static char *tgfx_name = "TurboGraFX Multisystem joystick";
static struct tgfx { static struct tgfx {
struct pardevice *pd; struct pardevice *pd;
struct timer_list timer; struct timer_list timer;
struct input_dev dev[7]; struct input_dev *dev[TGFX_MAX_DEVICES];
char phys[7][32]; char name[TGFX_MAX_DEVICES][64];
char phys[TGFX_MAX_DEVICES][32];
int sticks; int sticks;
int used; int used;
struct semaphore sem; struct semaphore sem;
} *tgfx_base[3]; } *tgfx_base[TGFX_MAX_PORTS];
/* /*
* tgfx_timer() reads and analyzes TurboGraFX joystick data. * tgfx_timer() reads and analyzes TurboGraFX joystick data.
@ -100,7 +102,7 @@ static void tgfx_timer(unsigned long private)
for (i = 0; i < 7; i++) for (i = 0; i < 7; i++)
if (tgfx->sticks & (1 << i)) { if (tgfx->sticks & (1 << i)) {
dev = tgfx->dev + i; dev = tgfx->dev[i];
parport_write_data(tgfx->pd->port, ~(1 << i)); parport_write_data(tgfx->pd->port, ~(1 << i));
data1 = parport_read_status(tgfx->pd->port) ^ 0x7f; data1 = parport_read_status(tgfx->pd->port) ^ 0x7f;
@ -153,118 +155,165 @@ static void tgfx_close(struct input_dev *dev)
up(&tgfx->sem); up(&tgfx->sem);
} }
/* /*
* tgfx_probe() probes for tg gamepads. * tgfx_probe() probes for tg gamepads.
*/ */
static struct tgfx __init *tgfx_probe(int *config, int nargs) static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
{ {
struct tgfx *tgfx; struct tgfx *tgfx;
struct input_dev *input_dev;
struct parport *pp; struct parport *pp;
struct pardevice *pd;
int i, j; int i, j;
int err;
if (config[0] < 0) pp = parport_find_number(parport);
return NULL;
if (nargs < 2) {
printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
return NULL;
}
pp = parport_find_number(config[0]);
if (!pp) { if (!pp) {
printk(KERN_ERR "turbografx.c: no such parport\n"); printk(KERN_ERR "turbografx.c: no such parport\n");
return NULL; err = -EINVAL;
goto err_out;
} }
if (!(tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL))) { pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
parport_put_port(pp); if (!pd) {
return NULL; printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
err = -EBUSY;
goto err_put_pp;
}
tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL);
if (!tgfx) {
printk(KERN_ERR "turbografx.c: Not enough memory\n");
err = -ENOMEM;
goto err_unreg_pardev;
} }
init_MUTEX(&tgfx->sem); init_MUTEX(&tgfx->sem);
tgfx->pd = pd;
tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
parport_put_port(pp);
if (!tgfx->pd) {
printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
kfree(tgfx);
return NULL;
}
init_timer(&tgfx->timer); init_timer(&tgfx->timer);
tgfx->timer.data = (long) tgfx; tgfx->timer.data = (long) tgfx;
tgfx->timer.function = tgfx_timer; tgfx->timer.function = tgfx_timer;
tgfx->sticks = 0; for (i = 0; i < n_devs; i++) {
if (n_buttons[i] < 1)
continue;
for (i = 0; i < nargs - 1; i++) if (n_buttons[i] > 6) {
if (config[i+1] > 0 && config[i+1] < 6) { printk(KERN_ERR "turbografx.c: Invalid number of buttons %d\n", n_buttons[i]);
err = -EINVAL;
goto err_free_devs;
}
tgfx->dev[i] = input_dev = input_allocate_device();
if (!input_dev) {
printk(KERN_ERR "turbografx.c: Not enough memory for input device\n");
err = -ENOMEM;
goto err_free_devs;
}
tgfx->sticks |= (1 << i); tgfx->sticks |= (1 << i);
snprintf(tgfx->name[i], sizeof(tgfx->name[i]),
"TurboGraFX %d-button Multisystem joystick", n_buttons[i]);
snprintf(tgfx->phys[i], sizeof(tgfx->phys[i]),
"%s/input%d", tgfx->pd->port->name, i);
tgfx->dev[i].private = tgfx; input_dev->name = tgfx->name[i];
tgfx->dev[i].open = tgfx_open; input_dev->phys = tgfx->phys[i];
tgfx->dev[i].close = tgfx_close; input_dev->id.bustype = BUS_PARPORT;
input_dev->id.vendor = 0x0003;
input_dev->id.product = n_buttons[i];
input_dev->id.version = 0x0100;
sprintf(tgfx->phys[i], "%s/input0", tgfx->pd->port->name); input_dev->private = tgfx;
input_dev->open = tgfx_open;
input_dev->close = tgfx_close;
tgfx->dev[i].name = tgfx_name; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
tgfx->dev[i].phys = tgfx->phys[i]; input_set_abs_params(input_dev, ABS_X, -1, 1, 0, 0);
tgfx->dev[i].id.bustype = BUS_PARPORT; input_set_abs_params(input_dev, ABS_Y, -1, 1, 0, 0);
tgfx->dev[i].id.vendor = 0x0003;
tgfx->dev[i].id.product = config[i+1];
tgfx->dev[i].id.version = 0x0100;
tgfx->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); for (j = 0; j < n_buttons[i]; j++)
tgfx->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y); set_bit(tgfx_buttons[j], input_dev->keybit);
for (j = 0; j < config[i+1]; j++) input_register_device(tgfx->dev[i]);
set_bit(tgfx_buttons[j], tgfx->dev[i].keybit);
tgfx->dev[i].absmin[ABS_X] = -1; tgfx->dev[i].absmax[ABS_X] = 1;
tgfx->dev[i].absmin[ABS_Y] = -1; tgfx->dev[i].absmax[ABS_Y] = 1;
input_register_device(tgfx->dev + i);
printk(KERN_INFO "input: %d-button Multisystem joystick on %s\n",
config[i+1], tgfx->pd->port->name);
} }
if (!tgfx->sticks) { if (!tgfx->sticks) {
parport_unregister_device(tgfx->pd); printk(KERN_ERR "turbografx.c: No valid devices specified\n");
kfree(tgfx); err = -EINVAL;
return NULL; goto err_free_tgfx;
} }
return tgfx; return tgfx;
err_free_devs:
while (--i >= 0)
input_unregister_device(tgfx->dev[i]);
err_free_tgfx:
kfree(tgfx);
err_unreg_pardev:
parport_unregister_device(pd);
err_put_pp:
parport_put_port(pp);
err_out:
return ERR_PTR(err);
}
static void __exit tgfx_remove(struct tgfx *tgfx)
{
int i;
for (i = 0; i < TGFX_MAX_DEVICES; i++)
if (tgfx->dev[i])
input_unregister_device(tgfx->dev[i]);
parport_unregister_device(tgfx->pd);
kfree(tgfx);
} }
static int __init tgfx_init(void) static int __init tgfx_init(void)
{ {
tgfx_base[0] = tgfx_probe(tgfx, tgfx_nargs); int i;
tgfx_base[1] = tgfx_probe(tgfx_2, tgfx_nargs_2); int have_dev = 0;
tgfx_base[2] = tgfx_probe(tgfx_3, tgfx_nargs_3); int err = 0;
if (tgfx_base[0] || tgfx_base[1] || tgfx_base[2]) for (i = 0; i < TGFX_MAX_PORTS; i++) {
return 0; if (tgfx[i].nargs == 0 || tgfx[i].args[0] < 0)
continue;
return -ENODEV; if (tgfx[i].nargs < 2) {
printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
err = -EINVAL;
break;
}
tgfx_base[i] = tgfx_probe(tgfx[i].args[0], tgfx[i].args + 1, tgfx[i].nargs - 1);
if (IS_ERR(tgfx_base[i])) {
err = PTR_ERR(tgfx_base[i]);
break;
}
have_dev = 1;
}
if (err) {
while (--i >= 0)
tgfx_remove(tgfx_base[i]);
return err;
}
return have_dev ? 0 : -ENODEV;
} }
static void __exit tgfx_exit(void) static void __exit tgfx_exit(void)
{ {
int i, j; int i;
for (i = 0; i < 3; i++) for (i = 0; i < TGFX_MAX_PORTS; i++)
if (tgfx_base[i]) { if (tgfx_base[i])
for (j = 0; j < 7; j++) tgfx_remove(tgfx_base[i]);
if (tgfx_base[i]->sticks & (1 << j))
input_unregister_device(tgfx_base[i]->dev + j);
parport_unregister_device(tgfx_base[i]->pd);
}
} }
module_init(tgfx_init); module_init(tgfx_init);

View file

@ -69,8 +69,6 @@ MODULE_LICENSE("GPL");
#define TWIDJOY_MAX_LENGTH 5 #define TWIDJOY_MAX_LENGTH 5
static char *twidjoy_name = "Handykey Twiddler";
static struct twidjoy_button_spec { static struct twidjoy_button_spec {
int bitshift; int bitshift;
int bitmask; int bitmask;
@ -95,7 +93,7 @@ twidjoy_buttons[] = {
*/ */
struct twidjoy { struct twidjoy {
struct input_dev dev; struct input_dev *dev;
int idx; int idx;
unsigned char data[TWIDJOY_MAX_LENGTH]; unsigned char data[TWIDJOY_MAX_LENGTH];
char phys[32]; char phys[32];
@ -108,8 +106,7 @@ struct twidjoy {
static void twidjoy_process_packet(struct twidjoy *twidjoy, struct pt_regs *regs) static void twidjoy_process_packet(struct twidjoy *twidjoy, struct pt_regs *regs)
{ {
if (twidjoy->idx == TWIDJOY_MAX_LENGTH) { struct input_dev *dev = twidjoy->dev;
struct input_dev *dev = &twidjoy->dev;
unsigned char *data = twidjoy->data; unsigned char *data = twidjoy->data;
struct twidjoy_button_spec *bp; struct twidjoy_button_spec *bp;
int button_bits, abs_x, abs_y; int button_bits, abs_x, abs_y;
@ -136,9 +133,6 @@ static void twidjoy_process_packet(struct twidjoy *twidjoy, struct pt_regs *regs
input_report_abs(dev, ABS_Y, +abs_y); input_report_abs(dev, ABS_Y, +abs_y);
input_sync(dev); input_sync(dev);
}
return;
} }
/* /*
@ -179,9 +173,9 @@ static void twidjoy_disconnect(struct serio *serio)
{ {
struct twidjoy *twidjoy = serio_get_drvdata(serio); struct twidjoy *twidjoy = serio_get_drvdata(serio);
input_unregister_device(&twidjoy->dev);
serio_close(serio); serio_close(serio);
serio_set_drvdata(serio, NULL); serio_set_drvdata(serio, NULL);
input_unregister_device(twidjoy->dev);
kfree(twidjoy); kfree(twidjoy);
} }
@ -195,59 +189,49 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv)
{ {
struct twidjoy_button_spec *bp; struct twidjoy_button_spec *bp;
struct twidjoy *twidjoy; struct twidjoy *twidjoy;
struct input_dev *input_dev;
int err = -ENOMEM;
int i; int i;
int err;
if (!(twidjoy = kmalloc(sizeof(struct twidjoy), GFP_KERNEL))) twidjoy = kzalloc(sizeof(struct twidjoy), GFP_KERNEL);
return -ENOMEM; input_dev = input_allocate_device();
if (!twidjoy || !input_dev)
memset(twidjoy, 0, sizeof(struct twidjoy)); goto fail;
twidjoy->dev = input_dev;
sprintf(twidjoy->phys, "%s/input0", serio->phys); sprintf(twidjoy->phys, "%s/input0", serio->phys);
init_input_dev(&twidjoy->dev); input_dev->name = "Handykey Twiddler";
twidjoy->dev.name = twidjoy_name; input_dev->phys = twidjoy->phys;
twidjoy->dev.phys = twidjoy->phys; input_dev->id.bustype = BUS_RS232;
twidjoy->dev.id.bustype = BUS_RS232; input_dev->id.vendor = SERIO_TWIDJOY;
twidjoy->dev.id.vendor = SERIO_TWIDJOY; input_dev->id.product = 0x0001;
twidjoy->dev.id.product = 0x0001; input_dev->id.version = 0x0100;
twidjoy->dev.id.version = 0x0100; input_dev->cdev.dev = &serio->dev;
twidjoy->dev.dev = &serio->dev; input_dev->private = twidjoy;
twidjoy->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
input_set_abs_params(input_dev, ABS_X, -50, 50, 4, 4);
input_set_abs_params(input_dev, ABS_Y, -50, 50, 4, 4);
for (bp = twidjoy_buttons; bp->bitmask; bp++) { for (bp = twidjoy_buttons; bp->bitmask; bp++)
for (i = 0; i < bp->bitmask; i++) for (i = 0; i < bp->bitmask; i++)
set_bit(bp->buttons[i], twidjoy->dev.keybit); set_bit(bp->buttons[i], input_dev->keybit);
}
twidjoy->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
for (i = 0; i < 2; i++) {
twidjoy->dev.absmax[ABS_X+i] = 50;
twidjoy->dev.absmin[ABS_X+i] = -50;
/* TODO: arndt 20010708: Are these values appropriate? */
twidjoy->dev.absfuzz[ABS_X+i] = 4;
twidjoy->dev.absflat[ABS_X+i] = 4;
}
twidjoy->dev.private = twidjoy;
serio_set_drvdata(serio, twidjoy); serio_set_drvdata(serio, twidjoy);
err = serio_open(serio, drv); err = serio_open(serio, drv);
if (err) { if (err)
serio_set_drvdata(serio, NULL); goto fail;
input_register_device(twidjoy->dev);
return 0;
fail: serio_set_drvdata(serio, NULL);
input_free_device(input_dev);
kfree(twidjoy); kfree(twidjoy);
return err; return err;
}
input_register_device(&twidjoy->dev);
printk(KERN_INFO "input: %s on %s\n", twidjoy_name, serio->phys);
return 0;
} }
/* /*

View file

@ -47,14 +47,13 @@ MODULE_LICENSE("GPL");
#define WARRIOR_MAX_LENGTH 16 #define WARRIOR_MAX_LENGTH 16
static char warrior_lengths[] = { 0, 4, 12, 3, 4, 4, 0, 0 }; static char warrior_lengths[] = { 0, 4, 12, 3, 4, 4, 0, 0 };
static char *warrior_name = "Logitech WingMan Warrior";
/* /*
* Per-Warrior data. * Per-Warrior data.
*/ */
struct warrior { struct warrior {
struct input_dev dev; struct input_dev *dev;
int idx, len; int idx, len;
unsigned char data[WARRIOR_MAX_LENGTH]; unsigned char data[WARRIOR_MAX_LENGTH];
char phys[32]; char phys[32];
@ -67,7 +66,7 @@ struct warrior {
static void warrior_process_packet(struct warrior *warrior, struct pt_regs *regs) static void warrior_process_packet(struct warrior *warrior, struct pt_regs *regs)
{ {
struct input_dev *dev = &warrior->dev; struct input_dev *dev = warrior->dev;
unsigned char *data = warrior->data; unsigned char *data = warrior->data;
if (!warrior->idx) return; if (!warrior->idx) return;
@ -131,9 +130,9 @@ static void warrior_disconnect(struct serio *serio)
{ {
struct warrior *warrior = serio_get_drvdata(serio); struct warrior *warrior = serio_get_drvdata(serio);
input_unregister_device(&warrior->dev);
serio_close(serio); serio_close(serio);
serio_set_drvdata(serio, NULL); serio_set_drvdata(serio, NULL);
input_unregister_device(warrior->dev);
kfree(warrior); kfree(warrior);
} }
@ -146,60 +145,48 @@ static void warrior_disconnect(struct serio *serio)
static int warrior_connect(struct serio *serio, struct serio_driver *drv) static int warrior_connect(struct serio *serio, struct serio_driver *drv)
{ {
struct warrior *warrior; struct warrior *warrior;
int i; struct input_dev *input_dev;
int err; int err = -ENOMEM;
if (!(warrior = kmalloc(sizeof(struct warrior), GFP_KERNEL))) warrior = kzalloc(sizeof(struct warrior), GFP_KERNEL);
return -ENOMEM; input_dev = input_allocate_device();
if (!warrior || !input_dev)
memset(warrior, 0, sizeof(struct warrior)); goto fail;
warrior->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
warrior->dev.keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2);
warrior->dev.relbit[0] = BIT(REL_DIAL);
warrior->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y);
warrior->dev = input_dev;
sprintf(warrior->phys, "%s/input0", serio->phys); sprintf(warrior->phys, "%s/input0", serio->phys);
init_input_dev(&warrior->dev); input_dev->name = "Logitech WingMan Warrior";
warrior->dev.name = warrior_name; input_dev->phys = warrior->phys;
warrior->dev.phys = warrior->phys; input_dev->id.bustype = BUS_RS232;
warrior->dev.id.bustype = BUS_RS232; input_dev->id.vendor = SERIO_WARRIOR;
warrior->dev.id.vendor = SERIO_WARRIOR; input_dev->id.product = 0x0001;
warrior->dev.id.product = 0x0001; input_dev->id.version = 0x0100;
warrior->dev.id.version = 0x0100; input_dev->cdev.dev = &serio->dev;
warrior->dev.dev = &serio->dev; input_dev->private = warrior;
for (i = 0; i < 2; i++) { input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
warrior->dev.absmax[ABS_X+i] = -64; input_dev->keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2);
warrior->dev.absmin[ABS_X+i] = 64; input_dev->relbit[0] = BIT(REL_DIAL);
warrior->dev.absflat[ABS_X+i] = 8; input_set_abs_params(input_dev, ABS_X, -64, 64, 0, 8);
} input_set_abs_params(input_dev, ABS_Y, -64, 64, 0, 8);
input_set_abs_params(input_dev, ABS_THROTTLE, -112, 112, 0, 0);
warrior->dev.absmax[ABS_THROTTLE] = -112; input_set_abs_params(input_dev, ABS_HAT0X, -1, 1, 0, 0);
warrior->dev.absmin[ABS_THROTTLE] = 112; input_set_abs_params(input_dev, ABS_HAT0X, -1, 1, 0, 0);
for (i = 0; i < 2; i++) {
warrior->dev.absmax[ABS_HAT0X+i] = -1;
warrior->dev.absmin[ABS_HAT0X+i] = 1;
}
warrior->dev.private = warrior;
serio_set_drvdata(serio, warrior); serio_set_drvdata(serio, warrior);
err = serio_open(serio, drv); err = serio_open(serio, drv);
if (err) { if (err)
serio_set_drvdata(serio, NULL); goto fail;
input_register_device(warrior->dev);
return 0;
fail: serio_set_drvdata(serio, NULL);
input_free_device(input_dev);
kfree(warrior); kfree(warrior);
return err; return err;
}
input_register_device(&warrior->dev);
printk(KERN_INFO "input: Logitech WingMan Warrior on %s\n", serio->phys);
return 0;
} }
/* /*

View file

@ -155,10 +155,7 @@ static const char *amikbd_messages[8] = {
[7] = KERN_WARNING "amikbd: keyboard interrupt\n" [7] = KERN_WARNING "amikbd: keyboard interrupt\n"
}; };
static struct input_dev amikbd_dev; static struct input_dev *amikbd_dev;
static char *amikbd_name = "Amiga keyboard";
static char *amikbd_phys = "amikbd/input0";
static irqreturn_t amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp) static irqreturn_t amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp)
{ {
@ -176,16 +173,16 @@ static irqreturn_t amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp)
scancode = amikbd_keycode[scancode]; scancode = amikbd_keycode[scancode];
input_regs(&amikbd_dev, fp); input_regs(amikbd_dev, fp);
if (scancode == KEY_CAPSLOCK) { /* CapsLock is a toggle switch key on Amiga */ if (scancode == KEY_CAPSLOCK) { /* CapsLock is a toggle switch key on Amiga */
input_report_key(&amikbd_dev, scancode, 1); input_report_key(amikbd_dev, scancode, 1);
input_report_key(&amikbd_dev, scancode, 0); input_report_key(amikbd_dev, scancode, 0);
input_sync(&amikbd_dev);
} else { } else {
input_report_key(&amikbd_dev, scancode, down); input_report_key(amikbd_dev, scancode, down);
input_sync(&amikbd_dev);
} }
input_sync(amikbd_dev);
} else /* scancodes >= 0x78 are error codes */ } else /* scancodes >= 0x78 are error codes */
printk(amikbd_messages[scancode - 0x78]); printk(amikbd_messages[scancode - 0x78]);
@ -202,39 +199,41 @@ static int __init amikbd_init(void)
if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb")) if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb"))
return -EBUSY; return -EBUSY;
init_input_dev(&amikbd_dev); amikbd_dev = input_dev_allocate();
if (!amikbd_dev) {
printk(KERN_ERR "amikbd: not enough memory for input device\n");
release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
return -ENOMEM;
}
amikbd_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); amikbd_dev->name = "Amiga Keyboard";
amikbd_dev.keycode = amikbd_keycode; amikbd_dev->phys = "amikbd/input0";
amikbd_dev.keycodesize = sizeof(unsigned char); amikbd_dev->id.bustype = BUS_AMIGA;
amikbd_dev.keycodemax = ARRAY_SIZE(amikbd_keycode); amikbd_dev->id.vendor = 0x0001;
amikbd_dev->id.product = 0x0001;
amikbd_dev->id.version = 0x0100;
amikbd_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
amikbd_dev->keycode = amikbd_keycode;
amikbd_dev->keycodesize = sizeof(unsigned char);
amikbd_dev->keycodemax = ARRAY_SIZE(amikbd_keycode);
for (i = 0; i < 0x78; i++) for (i = 0; i < 0x78; i++)
if (amikbd_keycode[i]) if (amikbd_keycode[i])
set_bit(amikbd_keycode[i], amikbd_dev.keybit); set_bit(amikbd_keycode[i], amikbd_dev->keybit);
ciaa.cra &= ~0x41; /* serial data in, turn off TA */ ciaa.cra &= ~0x41; /* serial data in, turn off TA */
request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt); request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt);
amikbd_dev.name = amikbd_name; input_register_device(amikbd_dev);
amikbd_dev.phys = amikbd_phys;
amikbd_dev.id.bustype = BUS_AMIGA;
amikbd_dev.id.vendor = 0x0001;
amikbd_dev.id.product = 0x0001;
amikbd_dev.id.version = 0x0100;
input_register_device(&amikbd_dev);
printk(KERN_INFO "input: %s\n", amikbd_name);
return 0; return 0;
} }
static void __exit amikbd_exit(void) static void __exit amikbd_exit(void)
{ {
input_unregister_device(&amikbd_dev);
free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt); free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt);
release_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100); input_unregister_device(amikbd_dev);
release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
} }
module_init(amikbd_init); module_init(amikbd_init);

View file

@ -186,11 +186,11 @@ static struct {
struct atkbd { struct atkbd {
struct ps2dev ps2dev; struct ps2dev ps2dev;
struct input_dev *dev;
/* Written only during init */ /* Written only during init */
char name[64]; char name[64];
char phys[32]; char phys[32];
struct input_dev dev;
unsigned short id; unsigned short id;
unsigned char keycode[512]; unsigned char keycode[512];
@ -290,7 +290,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
if (!atkbd->enabled) if (!atkbd->enabled)
goto out; goto out;
input_event(&atkbd->dev, EV_MSC, MSC_RAW, code); input_event(atkbd->dev, EV_MSC, MSC_RAW, code);
if (atkbd->translated) { if (atkbd->translated) {
@ -326,10 +326,10 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
atkbd->release = 1; atkbd->release = 1;
goto out; goto out;
case ATKBD_RET_HANGUEL: case ATKBD_RET_HANGUEL:
atkbd_report_key(&atkbd->dev, regs, KEY_HANGUEL, 3); atkbd_report_key(atkbd->dev, regs, KEY_HANGUEL, 3);
goto out; goto out;
case ATKBD_RET_HANJA: case ATKBD_RET_HANJA:
atkbd_report_key(&atkbd->dev, regs, KEY_HANJA, 3); atkbd_report_key(atkbd->dev, regs, KEY_HANJA, 3);
goto out; goto out;
case ATKBD_RET_ERR: case ATKBD_RET_ERR:
printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys); printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys);
@ -345,7 +345,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
} }
if (atkbd->keycode[code] != ATKBD_KEY_NULL) if (atkbd->keycode[code] != ATKBD_KEY_NULL)
input_event(&atkbd->dev, EV_MSC, MSC_SCAN, code); input_event(atkbd->dev, EV_MSC, MSC_SCAN, code);
switch (atkbd->keycode[code]) { switch (atkbd->keycode[code]) {
case ATKBD_KEY_NULL: case ATKBD_KEY_NULL:
@ -365,7 +365,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
"to make it known.\n", "to make it known.\n",
code & 0x80 ? "e0" : "", code & 0x7f); code & 0x80 ? "e0" : "", code & 0x7f);
} }
input_sync(&atkbd->dev); input_sync(atkbd->dev);
break; break;
case ATKBD_SCR_1: case ATKBD_SCR_1:
scroll = 1 - atkbd->release * 2; scroll = 1 - atkbd->release * 2;
@ -390,7 +390,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
break; break;
default: default:
value = atkbd->release ? 0 : value = atkbd->release ? 0 :
(1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key))); (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev->key)));
switch (value) { /* Workaround Toshiba laptop multiple keypress */ switch (value) { /* Workaround Toshiba laptop multiple keypress */
case 0: case 0:
@ -398,7 +398,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
break; break;
case 1: case 1:
atkbd->last = code; atkbd->last = code;
atkbd->time = jiffies + msecs_to_jiffies(atkbd->dev.rep[REP_DELAY]) / 2; atkbd->time = jiffies + msecs_to_jiffies(atkbd->dev->rep[REP_DELAY]) / 2;
break; break;
case 2: case 2:
if (!time_after(jiffies, atkbd->time) && atkbd->last == code) if (!time_after(jiffies, atkbd->time) && atkbd->last == code)
@ -406,16 +406,16 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
break; break;
} }
atkbd_report_key(&atkbd->dev, regs, atkbd->keycode[code], value); atkbd_report_key(atkbd->dev, regs, atkbd->keycode[code], value);
} }
if (atkbd->scroll) { if (atkbd->scroll) {
input_regs(&atkbd->dev, regs); input_regs(atkbd->dev, regs);
if (click != -1) if (click != -1)
input_report_key(&atkbd->dev, BTN_MIDDLE, click); input_report_key(atkbd->dev, BTN_MIDDLE, click);
input_report_rel(&atkbd->dev, REL_WHEEL, scroll); input_report_rel(atkbd->dev, REL_WHEEL, scroll);
input_report_rel(&atkbd->dev, REL_HWHEEL, hscroll); input_report_rel(atkbd->dev, REL_HWHEEL, hscroll);
input_sync(&atkbd->dev); input_sync(atkbd->dev);
} }
atkbd->release = 0; atkbd->release = 0;
@ -463,7 +463,6 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
return 0; return 0;
case EV_REP: case EV_REP:
if (atkbd->softrepeat) return 0; if (atkbd->softrepeat) return 0;
@ -693,7 +692,7 @@ static void atkbd_disconnect(struct serio *serio)
device_remove_file(&serio->dev, &atkbd_attr_softrepeat); device_remove_file(&serio->dev, &atkbd_attr_softrepeat);
device_remove_file(&serio->dev, &atkbd_attr_softraw); device_remove_file(&serio->dev, &atkbd_attr_softraw);
input_unregister_device(&atkbd->dev); input_unregister_device(atkbd->dev);
serio_close(serio); serio_close(serio);
serio_set_drvdata(serio, NULL); serio_set_drvdata(serio, NULL);
kfree(atkbd); kfree(atkbd);
@ -701,7 +700,7 @@ static void atkbd_disconnect(struct serio *serio)
/* /*
* atkbd_set_device_attrs() initializes keyboard's keycode table * atkbd_set_keycode_table() initializes keyboard's keycode table
* according to the selected scancode set * according to the selected scancode set
*/ */
@ -737,53 +736,58 @@ static void atkbd_set_keycode_table(struct atkbd *atkbd)
static void atkbd_set_device_attrs(struct atkbd *atkbd) static void atkbd_set_device_attrs(struct atkbd *atkbd)
{ {
struct input_dev *input_dev = atkbd->dev;
int i; int i;
memset(&atkbd->dev, 0, sizeof(struct input_dev)); if (atkbd->extra)
sprintf(atkbd->name, "AT Set 2 Extra keyboard");
else
sprintf(atkbd->name, "AT %s Set %d keyboard",
atkbd->translated ? "Translated" : "Raw", atkbd->set);
init_input_dev(&atkbd->dev); sprintf(atkbd->phys, "%s/input0", atkbd->ps2dev.serio->phys);
atkbd->dev.name = atkbd->name; input_dev->name = atkbd->name;
atkbd->dev.phys = atkbd->phys; input_dev->phys = atkbd->phys;
atkbd->dev.id.bustype = BUS_I8042; input_dev->id.bustype = BUS_I8042;
atkbd->dev.id.vendor = 0x0001; input_dev->id.vendor = 0x0001;
atkbd->dev.id.product = atkbd->translated ? 1 : atkbd->set; input_dev->id.product = atkbd->translated ? 1 : atkbd->set;
atkbd->dev.id.version = atkbd->id; input_dev->id.version = atkbd->id;
atkbd->dev.event = atkbd_event; input_dev->event = atkbd_event;
atkbd->dev.private = atkbd; input_dev->private = atkbd;
atkbd->dev.dev = &atkbd->ps2dev.serio->dev; input_dev->cdev.dev = &atkbd->ps2dev.serio->dev;
atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC); input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);
if (atkbd->write) { if (atkbd->write) {
atkbd->dev.evbit[0] |= BIT(EV_LED); input_dev->evbit[0] |= BIT(EV_LED);
atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
} }
if (atkbd->extra) if (atkbd->extra)
atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) | input_dev->ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) |
BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC); BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC);
if (!atkbd->softrepeat) { if (!atkbd->softrepeat) {
atkbd->dev.rep[REP_DELAY] = 250; input_dev->rep[REP_DELAY] = 250;
atkbd->dev.rep[REP_PERIOD] = 33; input_dev->rep[REP_PERIOD] = 33;
} }
atkbd->dev.mscbit[0] = atkbd->softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN); input_dev->mscbit[0] = atkbd->softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN);
if (atkbd->scroll) { if (atkbd->scroll) {
atkbd->dev.evbit[0] |= BIT(EV_REL); input_dev->evbit[0] |= BIT(EV_REL);
atkbd->dev.relbit[0] = BIT(REL_WHEEL) | BIT(REL_HWHEEL); input_dev->relbit[0] = BIT(REL_WHEEL) | BIT(REL_HWHEEL);
set_bit(BTN_MIDDLE, atkbd->dev.keybit); set_bit(BTN_MIDDLE, input_dev->keybit);
} }
atkbd->dev.keycode = atkbd->keycode; input_dev->keycode = atkbd->keycode;
atkbd->dev.keycodesize = sizeof(unsigned char); input_dev->keycodesize = sizeof(unsigned char);
atkbd->dev.keycodemax = ARRAY_SIZE(atkbd_set2_keycode); input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
for (i = 0; i < 512; i++) for (i = 0; i < 512; i++)
if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL) if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
set_bit(atkbd->keycode[i], atkbd->dev.keybit); set_bit(atkbd->keycode[i], input_dev->keybit);
} }
/* /*
@ -796,13 +800,15 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd)
static int atkbd_connect(struct serio *serio, struct serio_driver *drv) static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
{ {
struct atkbd *atkbd; struct atkbd *atkbd;
int err; struct input_dev *dev;
int err = -ENOMEM;
if (!(atkbd = kmalloc(sizeof(struct atkbd), GFP_KERNEL))) atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL);
return - ENOMEM; dev = input_allocate_device();
if (!atkbd || !dev)
memset(atkbd, 0, sizeof(struct atkbd)); goto fail;
atkbd->dev = dev;
ps2_init(&atkbd->ps2dev, serio); ps2_init(&atkbd->ps2dev, serio);
switch (serio->id.type) { switch (serio->id.type) {
@ -828,19 +834,15 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
serio_set_drvdata(serio, atkbd); serio_set_drvdata(serio, atkbd);
err = serio_open(serio, drv); err = serio_open(serio, drv);
if (err) { if (err)
serio_set_drvdata(serio, NULL); goto fail;
kfree(atkbd);
return err;
}
if (atkbd->write) { if (atkbd->write) {
if (atkbd_probe(atkbd)) { if (atkbd_probe(atkbd)) {
serio_close(serio); serio_close(serio);
serio_set_drvdata(serio, NULL); err = -ENODEV;
kfree(atkbd); goto fail;
return -ENODEV;
} }
atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra); atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
@ -851,19 +853,9 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd->id = 0xab00; atkbd->id = 0xab00;
} }
if (atkbd->extra)
sprintf(atkbd->name, "AT Set 2 Extra keyboard");
else
sprintf(atkbd->name, "AT %s Set %d keyboard",
atkbd->translated ? "Translated" : "Raw", atkbd->set);
sprintf(atkbd->phys, "%s/input0", serio->phys);
atkbd_set_keycode_table(atkbd); atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd); atkbd_set_device_attrs(atkbd);
input_register_device(&atkbd->dev);
device_create_file(&serio->dev, &atkbd_attr_extra); device_create_file(&serio->dev, &atkbd_attr_extra);
device_create_file(&serio->dev, &atkbd_attr_scroll); device_create_file(&serio->dev, &atkbd_attr_scroll);
device_create_file(&serio->dev, &atkbd_attr_set); device_create_file(&serio->dev, &atkbd_attr_set);
@ -872,9 +864,14 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd_enable(atkbd); atkbd_enable(atkbd);
printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys); input_register_device(atkbd->dev);
return 0; return 0;
fail: serio_set_drvdata(serio, NULL);
input_free_device(dev);
kfree(atkbd);
return err;
} }
/* /*
@ -896,9 +893,9 @@ static int atkbd_reconnect(struct serio *serio)
atkbd_disable(atkbd); atkbd_disable(atkbd);
if (atkbd->write) { if (atkbd->write) {
param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0) param[0] = (test_bit(LED_SCROLLL, atkbd->dev->led) ? 1 : 0)
| (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0) | (test_bit(LED_NUML, atkbd->dev->led) ? 2 : 0)
| (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0); | (test_bit(LED_CAPSL, atkbd->dev->led) ? 4 : 0);
if (atkbd_probe(atkbd)) if (atkbd_probe(atkbd))
return -1; return -1;
@ -1008,6 +1005,7 @@ static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count) static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count)
{ {
struct input_dev *new_dev;
unsigned long value; unsigned long value;
char *rest; char *rest;
@ -1019,12 +1017,19 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
return -EINVAL; return -EINVAL;
if (atkbd->extra != value) { if (atkbd->extra != value) {
/* unregister device as it's properties will change */ /*
input_unregister_device(&atkbd->dev); * Since device's properties will change we need to
* unregister old device. But allocate new one first
* to make sure we have it.
*/
if (!(new_dev = input_allocate_device()))
return -ENOMEM;
input_unregister_device(atkbd->dev);
atkbd->dev = new_dev;
atkbd->set = atkbd_select_set(atkbd, atkbd->set, value); atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
atkbd_activate(atkbd); atkbd_activate(atkbd);
atkbd_set_device_attrs(atkbd); atkbd_set_device_attrs(atkbd);
input_register_device(&atkbd->dev); input_register_device(atkbd->dev);
} }
return count; return count;
} }
@ -1036,6 +1041,7 @@ static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count) static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count)
{ {
struct input_dev *new_dev;
unsigned long value; unsigned long value;
char *rest; char *rest;
@ -1044,12 +1050,14 @@ static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t cou
return -EINVAL; return -EINVAL;
if (atkbd->scroll != value) { if (atkbd->scroll != value) {
/* unregister device as it's properties will change */ if (!(new_dev = input_allocate_device()))
input_unregister_device(&atkbd->dev); return -ENOMEM;
input_unregister_device(atkbd->dev);
atkbd->dev = new_dev;
atkbd->scroll = value; atkbd->scroll = value;
atkbd_set_keycode_table(atkbd); atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd); atkbd_set_device_attrs(atkbd);
input_register_device(&atkbd->dev); input_register_device(atkbd->dev);
} }
return count; return count;
} }
@ -1061,6 +1069,7 @@ static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count) static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
{ {
struct input_dev *new_dev;
unsigned long value; unsigned long value;
char *rest; char *rest;
@ -1072,13 +1081,15 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
return -EINVAL; return -EINVAL;
if (atkbd->set != value) { if (atkbd->set != value) {
/* unregister device as it's properties will change */ if (!(new_dev = input_allocate_device()))
input_unregister_device(&atkbd->dev); return -ENOMEM;
input_unregister_device(atkbd->dev);
atkbd->dev = new_dev;
atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra); atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra);
atkbd_activate(atkbd); atkbd_activate(atkbd);
atkbd_set_keycode_table(atkbd); atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd); atkbd_set_device_attrs(atkbd);
input_register_device(&atkbd->dev); input_register_device(atkbd->dev);
} }
return count; return count;
} }
@ -1090,6 +1101,7 @@ static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count) static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count)
{ {
struct input_dev *new_dev;
unsigned long value; unsigned long value;
char *rest; char *rest;
@ -1101,15 +1113,16 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t
return -EINVAL; return -EINVAL;
if (atkbd->softrepeat != value) { if (atkbd->softrepeat != value) {
/* unregister device as it's properties will change */ if (!(new_dev = input_allocate_device()))
input_unregister_device(&atkbd->dev); return -ENOMEM;
input_unregister_device(atkbd->dev);
atkbd->dev = new_dev;
atkbd->softrepeat = value; atkbd->softrepeat = value;
if (atkbd->softrepeat) if (atkbd->softrepeat)
atkbd->softraw = 1; atkbd->softraw = 1;
atkbd_set_device_attrs(atkbd); atkbd_set_device_attrs(atkbd);
input_register_device(&atkbd->dev); input_register_device(atkbd->dev);
} }
return count; return count;
} }
@ -1121,6 +1134,7 @@ static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count) static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count)
{ {
struct input_dev *new_dev;
unsigned long value; unsigned long value;
char *rest; char *rest;
@ -1129,11 +1143,13 @@ static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t co
return -EINVAL; return -EINVAL;
if (atkbd->softraw != value) { if (atkbd->softraw != value) {
/* unregister device as it's properties will change */ if (!(new_dev = input_allocate_device()))
input_unregister_device(&atkbd->dev); return -ENOMEM;
input_unregister_device(atkbd->dev);
atkbd->dev = new_dev;
atkbd->softraw = value; atkbd->softraw = value;
atkbd_set_device_attrs(atkbd); atkbd_set_device_attrs(atkbd);
input_register_device(&atkbd->dev); input_register_device(atkbd->dev);
} }
return count; return count;
} }

View file

@ -70,8 +70,7 @@ static unsigned char corgikbd_keycode[NR_SCANCODES] = {
struct corgikbd { struct corgikbd {
unsigned char keycode[ARRAY_SIZE(corgikbd_keycode)]; unsigned char keycode[ARRAY_SIZE(corgikbd_keycode)];
struct input_dev input; struct input_dev *input;
char phys[32];
spinlock_t lock; spinlock_t lock;
struct timer_list timer; struct timer_list timer;
@ -147,7 +146,7 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs
spin_lock_irqsave(&corgikbd_data->lock, flags); spin_lock_irqsave(&corgikbd_data->lock, flags);
if (regs) if (regs)
input_regs(&corgikbd_data->input, regs); input_regs(corgikbd_data->input, regs);
num_pressed = 0; num_pressed = 0;
for (col = 0; col < KB_COLS; col++) { for (col = 0; col < KB_COLS; col++) {
@ -169,14 +168,14 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs
scancode = SCANCODE(row, col); scancode = SCANCODE(row, col);
pressed = rowd & KB_ROWMASK(row); pressed = rowd & KB_ROWMASK(row);
input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], pressed); input_report_key(corgikbd_data->input, corgikbd_data->keycode[scancode], pressed);
if (pressed) if (pressed)
num_pressed++; num_pressed++;
if (pressed && (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF) if (pressed && (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
&& time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) { && time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) {
input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1); input_event(corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
corgikbd_data->suspend_jiffies=jiffies; corgikbd_data->suspend_jiffies=jiffies;
} }
} }
@ -185,7 +184,7 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs
corgikbd_activate_all(); corgikbd_activate_all();
input_sync(&corgikbd_data->input); input_sync(corgikbd_data->input);
/* if any keys are pressed, enable the timer */ /* if any keys are pressed, enable the timer */
if (num_pressed) if (num_pressed)
@ -249,9 +248,9 @@ static void corgikbd_hinge_timer(unsigned long data)
if (hinge_count >= HINGE_STABLE_COUNT) { if (hinge_count >= HINGE_STABLE_COUNT) {
spin_lock_irqsave(&corgikbd_data->lock, flags); spin_lock_irqsave(&corgikbd_data->lock, flags);
input_report_switch(&corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0)); input_report_switch(corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0));
input_report_switch(&corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0)); input_report_switch(corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0));
input_sync(&corgikbd_data->input); input_sync(corgikbd_data->input);
spin_unlock_irqrestore(&corgikbd_data->lock, flags); spin_unlock_irqrestore(&corgikbd_data->lock, flags);
} }
@ -260,24 +259,22 @@ static void corgikbd_hinge_timer(unsigned long data)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int corgikbd_suspend(struct device *dev, pm_message_t state, uint32_t level) static int corgikbd_suspend(struct device *dev, pm_message_t state)
{ {
if (level == SUSPEND_POWER_DOWN) {
struct corgikbd *corgikbd = dev_get_drvdata(dev); struct corgikbd *corgikbd = dev_get_drvdata(dev);
corgikbd->suspended = 1; corgikbd->suspended = 1;
}
return 0; return 0;
} }
static int corgikbd_resume(struct device *dev, uint32_t level) static int corgikbd_resume(struct device *dev)
{ {
if (level == RESUME_POWER_ON) {
struct corgikbd *corgikbd = dev_get_drvdata(dev); struct corgikbd *corgikbd = dev_get_drvdata(dev);
/* Upon resume, ignore the suspend key for a short while */ /* Upon resume, ignore the suspend key for a short while */
corgikbd->suspend_jiffies=jiffies; corgikbd->suspend_jiffies=jiffies;
corgikbd->suspended = 0; corgikbd->suspended = 0;
}
return 0; return 0;
} }
#else #else
@ -287,16 +284,21 @@ static int corgikbd_resume(struct device *dev, uint32_t level)
static int __init corgikbd_probe(struct device *dev) static int __init corgikbd_probe(struct device *dev)
{ {
int i;
struct corgikbd *corgikbd; struct corgikbd *corgikbd;
struct input_dev *input_dev;
int i;
corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL); corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL);
if (!corgikbd) input_dev = input_allocate_device();
if (!corgikbd || !input_dev) {
kfree(corgikbd);
input_free_device(input_dev);
return -ENOMEM; return -ENOMEM;
}
dev_set_drvdata(dev,corgikbd); dev_set_drvdata(dev, corgikbd);
strcpy(corgikbd->phys, "corgikbd/input0");
corgikbd->input = input_dev;
spin_lock_init(&corgikbd->lock); spin_lock_init(&corgikbd->lock);
/* Init Keyboard rescan timer */ /* Init Keyboard rescan timer */
@ -311,28 +313,30 @@ static int __init corgikbd_probe(struct device *dev)
corgikbd->suspend_jiffies=jiffies; corgikbd->suspend_jiffies=jiffies;
init_input_dev(&corgikbd->input);
corgikbd->input.private = corgikbd;
corgikbd->input.name = "Corgi Keyboard";
corgikbd->input.dev = dev;
corgikbd->input.phys = corgikbd->phys;
corgikbd->input.id.bustype = BUS_HOST;
corgikbd->input.id.vendor = 0x0001;
corgikbd->input.id.product = 0x0001;
corgikbd->input.id.version = 0x0100;
corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
corgikbd->input.keycode = corgikbd->keycode;
corgikbd->input.keycodesize = sizeof(unsigned char);
corgikbd->input.keycodemax = ARRAY_SIZE(corgikbd_keycode);
memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode)); memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode));
for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
set_bit(corgikbd->keycode[i], corgikbd->input.keybit);
clear_bit(0, corgikbd->input.keybit);
set_bit(SW_0, corgikbd->input.swbit);
set_bit(SW_1, corgikbd->input.swbit);
input_register_device(&corgikbd->input); input_dev->name = "Corgi Keyboard";
input_dev->phys = "corgikbd/input0";
input_dev->id.bustype = BUS_HOST;
input_dev->id.vendor = 0x0001;
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
input_dev->cdev.dev = dev;
input_dev->private = corgikbd;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
input_dev->keycode = corgikbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode);
for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
set_bit(corgikbd->keycode[i], input_dev->keybit);
clear_bit(0, input_dev->keybit);
set_bit(SW_0, input_dev->swbit);
set_bit(SW_1, input_dev->swbit);
input_register_device(corgikbd->input);
mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL); mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL);
/* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
@ -349,8 +353,6 @@ static int __init corgikbd_probe(struct device *dev)
for (i = 0; i < CORGI_KEY_STROBE_NUM; i++) for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
printk(KERN_INFO "input: Corgi Keyboard Registered\n");
return 0; return 0;
} }
@ -365,7 +367,7 @@ static int corgikbd_remove(struct device *dev)
del_timer_sync(&corgikbd->htimer); del_timer_sync(&corgikbd->htimer);
del_timer_sync(&corgikbd->timer); del_timer_sync(&corgikbd->timer);
input_unregister_device(&corgikbd->input); input_unregister_device(corgikbd->input);
kfree(corgikbd); kfree(corgikbd);

View file

@ -102,7 +102,7 @@ static int ctrlclick_volume = 100; /* % */
module_param (ctrlclick_volume, int, 0); module_param (ctrlclick_volume, int, 0);
MODULE_PARM_DESC (ctrlclick_volume, "Ctrlclick volume (in %), default is 100%"); MODULE_PARM_DESC (ctrlclick_volume, "Ctrlclick volume (in %), default is 100%");
static int lk201_compose_is_alt = 0; static int lk201_compose_is_alt;
module_param (lk201_compose_is_alt, int, 0); module_param (lk201_compose_is_alt, int, 0);
MODULE_PARM_DESC (lk201_compose_is_alt, "If set non-zero, LK201' Compose key " MODULE_PARM_DESC (lk201_compose_is_alt, "If set non-zero, LK201' Compose key "
"will act as an Alt key"); "will act as an Alt key");
@ -274,7 +274,7 @@ static lk_keycode_t lkkbd_keycode[LK_NUM_KEYCODES] = {
}; };
#define CHECK_LED(LED, BITS) do { \ #define CHECK_LED(LED, BITS) do { \
if (test_bit (LED, lk->dev.led)) \ if (test_bit (LED, lk->dev->led)) \
leds_on |= BITS; \ leds_on |= BITS; \
else \ else \
leds_off |= BITS; \ leds_off |= BITS; \
@ -287,7 +287,7 @@ struct lkkbd {
lk_keycode_t keycode[LK_NUM_KEYCODES]; lk_keycode_t keycode[LK_NUM_KEYCODES];
int ignore_bytes; int ignore_bytes;
unsigned char id[LK_NUM_IGNORE_BYTES]; unsigned char id[LK_NUM_IGNORE_BYTES];
struct input_dev dev; struct input_dev *dev;
struct serio *serio; struct serio *serio;
struct work_struct tq; struct work_struct tq;
char name[64]; char name[64];
@ -423,8 +423,7 @@ lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
DBG (KERN_INFO "Got byte 0x%02x\n", data); DBG (KERN_INFO "Got byte 0x%02x\n", data);
if (lk->ignore_bytes > 0) { if (lk->ignore_bytes > 0) {
DBG (KERN_INFO "Ignoring a byte on %s\n", DBG (KERN_INFO "Ignoring a byte on %s\n", lk->name);
lk->name);
lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data; lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data;
if (lk->ignore_bytes == 0) if (lk->ignore_bytes == 0)
@ -435,14 +434,14 @@ lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
switch (data) { switch (data) {
case LK_ALL_KEYS_UP: case LK_ALL_KEYS_UP:
input_regs (&lk->dev, regs); input_regs (lk->dev, regs);
for (i = 0; i < ARRAY_SIZE (lkkbd_keycode); i++) for (i = 0; i < ARRAY_SIZE (lkkbd_keycode); i++)
if (lk->keycode[i] != KEY_RESERVED) if (lk->keycode[i] != KEY_RESERVED)
input_report_key (&lk->dev, lk->keycode[i], 0); input_report_key (lk->dev, lk->keycode[i], 0);
input_sync (&lk->dev); input_sync (lk->dev);
break; break;
case LK_METRONOME: case LK_METRONOME:
DBG (KERN_INFO "Got LK_METRONOME and don't " DBG (KERN_INFO "Got %#d and don't "
"know how to handle...\n"); "know how to handle...\n");
break; break;
case LK_OUTPUT_ERROR: case LK_OUTPUT_ERROR:
@ -482,12 +481,12 @@ lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
default: default:
if (lk->keycode[data] != KEY_RESERVED) { if (lk->keycode[data] != KEY_RESERVED) {
input_regs (&lk->dev, regs); input_regs (lk->dev, regs);
if (!test_bit (lk->keycode[data], lk->dev.key)) if (!test_bit (lk->keycode[data], lk->dev->key))
input_report_key (&lk->dev, lk->keycode[data], 1); input_report_key (lk->dev, lk->keycode[data], 1);
else else
input_report_key (&lk->dev, lk->keycode[data], 0); input_report_key (lk->dev, lk->keycode[data], 0);
input_sync (&lk->dev); input_sync (lk->dev);
} else } else
printk (KERN_WARNING "%s: Unknown key with " printk (KERN_WARNING "%s: Unknown key with "
"scancode 0x%02x on %s.\n", "scancode 0x%02x on %s.\n",
@ -605,7 +604,7 @@ lkkbd_reinit (void *data)
lk->serio->write (lk->serio, volume_to_hw (lk->bell_volume)); lk->serio->write (lk->serio, volume_to_hw (lk->bell_volume));
/* Enable/disable keyclick (and possibly set volume) */ /* Enable/disable keyclick (and possibly set volume) */
if (test_bit (SND_CLICK, lk->dev.snd)) { if (test_bit (SND_CLICK, lk->dev->snd)) {
lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK); lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK);
lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume)); lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume));
lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK); lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK);
@ -616,7 +615,7 @@ lkkbd_reinit (void *data)
} }
/* Sound the bell if needed */ /* Sound the bell if needed */
if (test_bit (SND_BELL, lk->dev.snd)) if (test_bit (SND_BELL, lk->dev->snd))
lk->serio->write (lk->serio, LK_CMD_SOUND_BELL); lk->serio->write (lk->serio, LK_CMD_SOUND_BELL);
} }
@ -627,71 +626,70 @@ static int
lkkbd_connect (struct serio *serio, struct serio_driver *drv) lkkbd_connect (struct serio *serio, struct serio_driver *drv)
{ {
struct lkkbd *lk; struct lkkbd *lk;
struct input_dev *input_dev;
int i; int i;
int err; int err;
if (!(lk = kmalloc (sizeof (struct lkkbd), GFP_KERNEL))) lk = kzalloc (sizeof (struct lkkbd), GFP_KERNEL);
return -ENOMEM; input_dev = input_allocate_device ();
if (!lk || !input_dev) {
memset (lk, 0, sizeof (struct lkkbd)); err = -ENOMEM;
goto fail;
init_input_dev (&lk->dev); }
set_bit (EV_KEY, lk->dev.evbit);
set_bit (EV_LED, lk->dev.evbit);
set_bit (EV_SND, lk->dev.evbit);
set_bit (EV_REP, lk->dev.evbit);
set_bit (LED_CAPSL, lk->dev.ledbit);
set_bit (LED_SLEEP, lk->dev.ledbit);
set_bit (LED_COMPOSE, lk->dev.ledbit);
set_bit (LED_SCROLLL, lk->dev.ledbit);
set_bit (SND_BELL, lk->dev.sndbit);
set_bit (SND_CLICK, lk->dev.sndbit);
lk->serio = serio; lk->serio = serio;
lk->dev = input_dev;
INIT_WORK (&lk->tq, lkkbd_reinit, lk); INIT_WORK (&lk->tq, lkkbd_reinit, lk);
lk->bell_volume = bell_volume; lk->bell_volume = bell_volume;
lk->keyclick_volume = keyclick_volume; lk->keyclick_volume = keyclick_volume;
lk->ctrlclick_volume = ctrlclick_volume; lk->ctrlclick_volume = ctrlclick_volume;
memcpy (lk->keycode, lkkbd_keycode, sizeof (lk_keycode_t) * LK_NUM_KEYCODES);
lk->dev.keycode = lk->keycode; strlcpy (lk->name, "DEC LK keyboard", sizeof(lk->name));
lk->dev.keycodesize = sizeof (lk_keycode_t); snprintf (lk->phys, sizeof(lk->phys), "%s/input0", serio->phys);
lk->dev.keycodemax = LK_NUM_KEYCODES;
lk->dev.event = lkkbd_event; input_dev->name = lk->name;
lk->dev.private = lk; input_dev->phys = lk->phys;
input_dev->id.bustype = BUS_RS232;
input_dev->id.vendor = SERIO_LKKBD;
input_dev->id.product = 0;
input_dev->id.version = 0x0100;
input_dev->cdev.dev = &serio->dev;
input_dev->event = lkkbd_event;
input_dev->private = lk;
set_bit (EV_KEY, input_dev->evbit);
set_bit (EV_LED, input_dev->evbit);
set_bit (EV_SND, input_dev->evbit);
set_bit (EV_REP, input_dev->evbit);
set_bit (LED_CAPSL, input_dev->ledbit);
set_bit (LED_SLEEP, input_dev->ledbit);
set_bit (LED_COMPOSE, input_dev->ledbit);
set_bit (LED_SCROLLL, input_dev->ledbit);
set_bit (SND_BELL, input_dev->sndbit);
set_bit (SND_CLICK, input_dev->sndbit);
input_dev->keycode = lk->keycode;
input_dev->keycodesize = sizeof (lk_keycode_t);
input_dev->keycodemax = LK_NUM_KEYCODES;
for (i = 0; i < LK_NUM_KEYCODES; i++)
set_bit (lk->keycode[i], input_dev->keybit);
serio_set_drvdata (serio, lk); serio_set_drvdata (serio, lk);
err = serio_open (serio, drv); err = serio_open (serio, drv);
if (err) { if (err)
serio_set_drvdata (serio, NULL); goto fail;
kfree (lk);
return err;
}
sprintf (lk->name, "DEC LK keyboard"); input_register_device (lk->dev);
sprintf (lk->phys, "%s/input0", serio->phys);
memcpy (lk->keycode, lkkbd_keycode, sizeof (lk_keycode_t) * LK_NUM_KEYCODES);
for (i = 0; i < LK_NUM_KEYCODES; i++)
set_bit (lk->keycode[i], lk->dev.keybit);
lk->dev.name = lk->name;
lk->dev.phys = lk->phys;
lk->dev.id.bustype = BUS_RS232;
lk->dev.id.vendor = SERIO_LKKBD;
lk->dev.id.product = 0;
lk->dev.id.version = 0x0100;
lk->dev.dev = &serio->dev;
input_register_device (&lk->dev);
printk (KERN_INFO "input: %s on %s, initiating reset\n", lk->name, serio->phys);
lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET); lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET);
return 0; return 0;
fail: serio_set_drvdata (serio, NULL);
input_free_device (input_dev);
kfree (lk);
return err;
} }
/* /*
@ -702,9 +700,11 @@ lkkbd_disconnect (struct serio *serio)
{ {
struct lkkbd *lk = serio_get_drvdata (serio); struct lkkbd *lk = serio_get_drvdata (serio);
input_unregister_device (&lk->dev); input_get_device (lk->dev);
input_unregister_device (lk->dev);
serio_close (serio); serio_close (serio);
serio_set_drvdata (serio, NULL); serio_set_drvdata (serio, NULL);
input_put_device (lk->dev);
kfree (lk); kfree (lk);
} }

View file

@ -37,7 +37,7 @@ static unsigned char dc_kbd_keycode[256] = {
struct dc_kbd { struct dc_kbd {
struct input_dev dev; struct input_dev *dev;
unsigned char new[8]; unsigned char new[8];
unsigned char old[8]; unsigned char old[8];
}; };
@ -46,30 +46,24 @@ struct dc_kbd {
static void dc_scan_kbd(struct dc_kbd *kbd) static void dc_scan_kbd(struct dc_kbd *kbd)
{ {
int i; int i;
struct input_dev *dev = &kbd->dev; struct input_dev *dev = kbd->dev;
for(i=0; i<8; i++) for (i = 0; i < 8; i++)
input_report_key(dev, input_report_key(dev, dc_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
dc_kbd_keycode[i+224],
(kbd->new[0]>>i)&1);
for(i=2; i<8; i++) { for (i = 2; i < 8; i++) {
if(kbd->old[i]>3&&memscan(kbd->new+2, kbd->old[i], 6)==NULL) { if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == NULL) {
if(dc_kbd_keycode[kbd->old[i]]) if (dc_kbd_keycode[kbd->old[i]])
input_report_key(dev, input_report_key(dev, dc_kbd_keycode[kbd->old[i]], 0);
dc_kbd_keycode[kbd->old[i]],
0);
else else
printk("Unknown key (scancode %#x) released.", printk("Unknown key (scancode %#x) released.",
kbd->old[i]); kbd->old[i]);
} }
if(kbd->new[i]>3&&memscan(kbd->old+2, kbd->new[i], 6)!=NULL) { if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) != NULL) {
if(dc_kbd_keycode[kbd->new[i]]) if(dc_kbd_keycode[kbd->new[i]])
input_report_key(dev, input_report_key(dev, dc_kbd_keycode[kbd->new[i]], 1);
dc_kbd_keycode[kbd->new[i]],
1);
else else
printk("Unknown key (scancode %#x) pressed.", printk("Unknown key (scancode %#x) pressed.",
kbd->new[i]); kbd->new[i]);
@ -89,43 +83,39 @@ static void dc_kbd_callback(struct mapleq *mq)
unsigned long *buf = mq->recvbuf; unsigned long *buf = mq->recvbuf;
if (buf[1] == mapledev->function) { if (buf[1] == mapledev->function) {
memcpy(kbd->new, buf+2, 8); memcpy(kbd->new, buf + 2, 8);
dc_scan_kbd(kbd); dc_scan_kbd(kbd);
} }
} }
static int dc_kbd_connect(struct maple_device *dev) static int dc_kbd_connect(struct maple_device *dev)
{ {
int i;
unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
struct dc_kbd *kbd; struct dc_kbd *kbd;
struct input_dev *input_dev;
unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
int i;
if (!(kbd = kmalloc(sizeof(struct dc_kbd), GFP_KERNEL))) dev->private_data = kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL);
return -1; input_dev = input_allocate_device();
memset(kbd, 0, sizeof(struct dc_kbd)); if (!kbd || !input_dev) {
kfree(kbd);
input_free_device(input_dev);
return -ENOMEM;
}
dev->private_data = kbd; kbd->dev = input_dev;
kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); input_dev->name = dev->product_name;
input_dev->id.bustype = BUS_MAPLE;
input_dev->private = kbd;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
for (i = 0; i < 255; i++)
set_bit(dc_kbd_keycode[i], input_dev->keybit);
clear_bit(0, input_dev->keybit);
init_input_dev(&kbd->dev); input_register_device(kbd->dev);
for (i=0; i<255; i++)
set_bit(dc_kbd_keycode[i], kbd->dev.keybit);
clear_bit(0, kbd->dev.keybit);
kbd->dev.private = kbd;
kbd->dev.name = dev->product_name;
kbd->dev.id.bustype = BUS_MAPLE;
input_register_device(&kbd->dev);
maple_getcond_callback(dev, dc_kbd_callback, 1, MAPLE_FUNC_KEYBOARD); maple_getcond_callback(dev, dc_kbd_callback, 1, MAPLE_FUNC_KEYBOARD);
printk(KERN_INFO "input: keyboard(0x%lx): %s\n", data, kbd->dev.name);
return 0; return 0;
} }
@ -134,7 +124,7 @@ static void dc_kbd_disconnect(struct maple_device *dev)
{ {
struct dc_kbd *kbd = dev->private_data; struct dc_kbd *kbd = dev->private_data;
input_unregister_device(&kbd->dev); input_unregister_device(kbd->dev);
kfree(kbd); kfree(kbd);
} }

View file

@ -57,11 +57,9 @@ static unsigned char nkbd_keycode[128] = {
KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_UP, 0 KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_UP, 0
}; };
static char *nkbd_name = "Newton Keyboard";
struct nkbd { struct nkbd {
unsigned char keycode[128]; unsigned char keycode[128];
struct input_dev dev; struct input_dev *dev;
struct serio *serio; struct serio *serio;
char phys[32]; char phys[32];
}; };
@ -73,13 +71,13 @@ static irqreturn_t nkbd_interrupt(struct serio *serio,
/* invalid scan codes are probably the init sequence, so we ignore them */ /* invalid scan codes are probably the init sequence, so we ignore them */
if (nkbd->keycode[data & NKBD_KEY]) { if (nkbd->keycode[data & NKBD_KEY]) {
input_regs(&nkbd->dev, regs); input_regs(nkbd->dev, regs);
input_report_key(&nkbd->dev, nkbd->keycode[data & NKBD_KEY], data & NKBD_PRESS); input_report_key(nkbd->dev, nkbd->keycode[data & NKBD_KEY], data & NKBD_PRESS);
input_sync(&nkbd->dev); input_sync(nkbd->dev);
} }
else if (data == 0xe7) /* end of init sequence */ else if (data == 0xe7) /* end of init sequence */
printk(KERN_INFO "input: %s on %s\n", nkbd_name, serio->phys); printk(KERN_INFO "input: %s on %s\n", nkbd->dev->name, serio->phys);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -87,62 +85,59 @@ static irqreturn_t nkbd_interrupt(struct serio *serio,
static int nkbd_connect(struct serio *serio, struct serio_driver *drv) static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
{ {
struct nkbd *nkbd; struct nkbd *nkbd;
struct input_dev *input_dev;
int err = -ENOMEM;
int i; int i;
int err;
if (!(nkbd = kmalloc(sizeof(struct nkbd), GFP_KERNEL))) nkbd = kzalloc(sizeof(struct nkbd), GFP_KERNEL);
return -ENOMEM; input_dev = input_allocate_device();
if (!nkbd || !input_dev)
memset(nkbd, 0, sizeof(struct nkbd)); goto fail;
nkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
nkbd->serio = serio; nkbd->serio = serio;
nkbd->dev = input_dev;
sprintf(nkbd->phys, "%s/input0", serio->phys);
memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode));
init_input_dev(&nkbd->dev); input_dev->name = "Newton Keyboard";
nkbd->dev.keycode = nkbd->keycode; input_dev->phys = nkbd->phys;
nkbd->dev.keycodesize = sizeof(unsigned char); input_dev->id.bustype = BUS_RS232;
nkbd->dev.keycodemax = ARRAY_SIZE(nkbd_keycode); input_dev->id.vendor = SERIO_NEWTON;
nkbd->dev.private = nkbd; input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
input_dev->cdev.dev = &serio->dev;
input_dev->private = nkbd;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
input_dev->keycode = nkbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
input_dev->keycodemax = ARRAY_SIZE(nkbd_keycode);
for (i = 0; i < 128; i++)
set_bit(nkbd->keycode[i], input_dev->keybit);
clear_bit(0, input_dev->keybit);
serio_set_drvdata(serio, nkbd); serio_set_drvdata(serio, nkbd);
err = serio_open(serio, drv); err = serio_open(serio, drv);
if (err) { if (err)
serio_set_drvdata(serio, NULL); goto fail;
input_register_device(nkbd->dev);
return 0;
fail: serio_set_drvdata(serio, NULL);
input_free_device(input_dev);
kfree(nkbd); kfree(nkbd);
return err; return err;
}
memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode));
for (i = 0; i < 128; i++)
set_bit(nkbd->keycode[i], nkbd->dev.keybit);
clear_bit(0, nkbd->dev.keybit);
sprintf(nkbd->phys, "%s/input0", serio->phys);
nkbd->dev.name = nkbd_name;
nkbd->dev.phys = nkbd->phys;
nkbd->dev.id.bustype = BUS_RS232;
nkbd->dev.id.vendor = SERIO_NEWTON;
nkbd->dev.id.product = 0x0001;
nkbd->dev.id.version = 0x0100;
nkbd->dev.dev = &serio->dev;
input_register_device(&nkbd->dev);
printk(KERN_INFO "input: %s on %s\n", nkbd_name, serio->phys);
return 0;
} }
static void nkbd_disconnect(struct serio *serio) static void nkbd_disconnect(struct serio *serio)
{ {
struct nkbd *nkbd = serio_get_drvdata(serio); struct nkbd *nkbd = serio_get_drvdata(serio);
input_unregister_device(&nkbd->dev);
serio_close(serio); serio_close(serio);
serio_set_drvdata(serio, NULL); serio_set_drvdata(serio, NULL);
input_unregister_device(nkbd->dev);
kfree(nkbd); kfree(nkbd);
} }

View file

@ -85,7 +85,7 @@ static int spitz_senses[] = {
struct spitzkbd { struct spitzkbd {
unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)]; unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)];
struct input_dev input; struct input_dev *input;
char phys[32]; char phys[32];
spinlock_t lock; spinlock_t lock;
@ -187,8 +187,7 @@ static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs
spin_lock_irqsave(&spitzkbd_data->lock, flags); spin_lock_irqsave(&spitzkbd_data->lock, flags);
if (regs) input_regs(spitzkbd_data->input, regs);
input_regs(&spitzkbd_data->input, regs);
num_pressed = 0; num_pressed = 0;
for (col = 0; col < KB_COLS; col++) { for (col = 0; col < KB_COLS; col++) {
@ -210,7 +209,7 @@ static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs
scancode = SCANCODE(row, col); scancode = SCANCODE(row, col);
pressed = rowd & KB_ROWMASK(row); pressed = rowd & KB_ROWMASK(row);
input_report_key(&spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed); input_report_key(spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed);
if (pressed) if (pressed)
num_pressed++; num_pressed++;
@ -220,15 +219,15 @@ static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs
spitzkbd_activate_all(); spitzkbd_activate_all();
input_report_key(&spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 ); input_report_key(spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 );
input_report_key(&spitzkbd_data->input, KEY_SUSPEND, pwrkey); input_report_key(spitzkbd_data->input, KEY_SUSPEND, pwrkey);
if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) { if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) {
input_event(&spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1); input_event(spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1);
spitzkbd_data->suspend_jiffies = jiffies; spitzkbd_data->suspend_jiffies = jiffies;
} }
input_sync(&spitzkbd_data->input); input_sync(spitzkbd_data->input);
/* if any keys are pressed, enable the timer */ /* if any keys are pressed, enable the timer */
if (num_pressed) if (num_pressed)
@ -259,6 +258,7 @@ static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id, struct pt_regs *reg
static void spitzkbd_timer_callback(unsigned long data) static void spitzkbd_timer_callback(unsigned long data)
{ {
struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data; struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
spitzkbd_scankeyboard(spitzkbd_data, NULL); spitzkbd_scankeyboard(spitzkbd_data, NULL);
} }
@ -298,9 +298,9 @@ static void spitzkbd_hinge_timer(unsigned long data)
if (hinge_count >= HINGE_STABLE_COUNT) { if (hinge_count >= HINGE_STABLE_COUNT) {
spin_lock_irqsave(&spitzkbd_data->lock, flags); spin_lock_irqsave(&spitzkbd_data->lock, flags);
input_report_switch(&spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0)); input_report_switch(spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
input_report_switch(&spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0)); input_report_switch(spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
input_sync(&spitzkbd_data->input); input_sync(spitzkbd_data->input);
spin_unlock_irqrestore(&spitzkbd_data->lock, flags); spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
} else { } else {
@ -309,9 +309,8 @@ static void spitzkbd_hinge_timer(unsigned long data)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int spitzkbd_suspend(struct device *dev, pm_message_t state, uint32_t level) static int spitzkbd_suspend(struct device *dev, pm_message_t state)
{ {
if (level == SUSPEND_POWER_DOWN) {
int i; int i;
struct spitzkbd *spitzkbd = dev_get_drvdata(dev); struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
spitzkbd->suspended = 1; spitzkbd->suspended = 1;
@ -320,13 +319,12 @@ static int spitzkbd_suspend(struct device *dev, pm_message_t state, uint32_t lev
enabled so we can detect a power button press for resume */ enabled so we can detect a power button press for resume */
for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++) for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++)
pxa_gpio_mode(spitz_strobes[i] | GPIO_IN); pxa_gpio_mode(spitz_strobes[i] | GPIO_IN);
}
return 0; return 0;
} }
static int spitzkbd_resume(struct device *dev, uint32_t level) static int spitzkbd_resume(struct device *dev)
{ {
if (level == RESUME_POWER_ON) {
int i; int i;
struct spitzkbd *spitzkbd = dev_get_drvdata(dev); struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
@ -336,7 +334,7 @@ static int spitzkbd_resume(struct device *dev, uint32_t level)
/* Upon resume, ignore the suspend key for a short while */ /* Upon resume, ignore the suspend key for a short while */
spitzkbd->suspend_jiffies = jiffies; spitzkbd->suspend_jiffies = jiffies;
spitzkbd->suspended = 0; spitzkbd->suspended = 0;
}
return 0; return 0;
} }
#else #else
@ -346,14 +344,21 @@ static int spitzkbd_resume(struct device *dev, uint32_t level)
static int __init spitzkbd_probe(struct device *dev) static int __init spitzkbd_probe(struct device *dev)
{ {
int i;
struct spitzkbd *spitzkbd; struct spitzkbd *spitzkbd;
struct input_dev *input_dev;
int i;
spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL); spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL);
if (!spitzkbd) if (!spitzkbd)
return -ENOMEM; return -ENOMEM;
dev_set_drvdata(dev,spitzkbd); input_dev = input_allocate_device();
if (!input_dev) {
kfree(spitzkbd);
return -ENOMEM;
}
dev_set_drvdata(dev, spitzkbd);
strcpy(spitzkbd->phys, "spitzkbd/input0"); strcpy(spitzkbd->phys, "spitzkbd/input0");
spin_lock_init(&spitzkbd->lock); spin_lock_init(&spitzkbd->lock);
@ -368,30 +373,34 @@ static int __init spitzkbd_probe(struct device *dev)
spitzkbd->htimer.function = spitzkbd_hinge_timer; spitzkbd->htimer.function = spitzkbd_hinge_timer;
spitzkbd->htimer.data = (unsigned long) spitzkbd; spitzkbd->htimer.data = (unsigned long) spitzkbd;
spitzkbd->suspend_jiffies=jiffies; spitzkbd->suspend_jiffies = jiffies;
init_input_dev(&spitzkbd->input); spitzkbd->input = input_dev;
spitzkbd->input.private = spitzkbd;
spitzkbd->input.name = "Spitz Keyboard"; input_dev->private = spitzkbd;
spitzkbd->input.dev = dev; input_dev->name = "Spitz Keyboard";
spitzkbd->input.phys = spitzkbd->phys; input_dev->phys = spitzkbd->phys;
spitzkbd->input.id.bustype = BUS_HOST; input_dev->cdev.dev = dev;
spitzkbd->input.id.vendor = 0x0001;
spitzkbd->input.id.product = 0x0001; input_dev->id.bustype = BUS_HOST;
spitzkbd->input.id.version = 0x0100; input_dev->id.vendor = 0x0001;
spitzkbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW); input_dev->id.product = 0x0001;
spitzkbd->input.keycode = spitzkbd->keycode; input_dev->id.version = 0x0100;
spitzkbd->input.keycodesize = sizeof(unsigned char);
spitzkbd->input.keycodemax = ARRAY_SIZE(spitzkbd_keycode); input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
input_dev->keycode = spitzkbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
input_dev->keycodemax = ARRAY_SIZE(spitzkbd_keycode);
memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode)); memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode));
for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++) for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++)
set_bit(spitzkbd->keycode[i], spitzkbd->input.keybit); set_bit(spitzkbd->keycode[i], input_dev->keybit);
clear_bit(0, spitzkbd->input.keybit); clear_bit(0, input_dev->keybit);
set_bit(SW_0, spitzkbd->input.swbit); set_bit(SW_0, input_dev->swbit);
set_bit(SW_1, spitzkbd->input.swbit); set_bit(SW_1, input_dev->swbit);
input_register_device(input_dev);
input_register_device(&spitzkbd->input);
mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
/* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
@ -444,7 +453,7 @@ static int spitzkbd_remove(struct device *dev)
del_timer_sync(&spitzkbd->htimer); del_timer_sync(&spitzkbd->htimer);
del_timer_sync(&spitzkbd->timer); del_timer_sync(&spitzkbd->timer);
input_unregister_device(&spitzkbd->input); input_unregister_device(spitzkbd->input);
kfree(spitzkbd); kfree(spitzkbd);

View file

@ -76,13 +76,14 @@ static unsigned char sunkbd_keycode[128] = {
struct sunkbd { struct sunkbd {
unsigned char keycode[128]; unsigned char keycode[128];
struct input_dev dev; struct input_dev *dev;
struct serio *serio; struct serio *serio;
struct work_struct tq; struct work_struct tq;
wait_queue_head_t wait; wait_queue_head_t wait;
char name[64]; char name[64];
char phys[32]; char phys[32];
char type; char type;
unsigned char enabled;
volatile s8 reset; volatile s8 reset;
volatile s8 layout; volatile s8 layout;
}; };
@ -124,10 +125,13 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio,
break; break;
default: default:
if (!sunkbd->enabled)
break;
if (sunkbd->keycode[data & SUNKBD_KEY]) { if (sunkbd->keycode[data & SUNKBD_KEY]) {
input_regs(&sunkbd->dev, regs); input_regs(sunkbd->dev, regs);
input_report_key(&sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE)); input_report_key(sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE));
input_sync(&sunkbd->dev); input_sync(sunkbd->dev);
} else { } else {
printk(KERN_WARNING "sunkbd.c: Unknown key (scancode %#x) %s.\n", printk(KERN_WARNING "sunkbd.c: Unknown key (scancode %#x) %s.\n",
data & SUNKBD_KEY, data & SUNKBD_RELEASE ? "released" : "pressed"); data & SUNKBD_KEY, data & SUNKBD_RELEASE ? "released" : "pressed");
@ -184,7 +188,7 @@ static int sunkbd_initialize(struct sunkbd *sunkbd)
sunkbd->reset = -2; sunkbd->reset = -2;
sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET); sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET);
wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
if (sunkbd->reset <0) if (sunkbd->reset < 0)
return -1; return -1;
sunkbd->type = sunkbd->reset; sunkbd->type = sunkbd->reset;
@ -213,10 +217,17 @@ static void sunkbd_reinit(void *data)
sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED); sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED);
sunkbd->serio->write(sunkbd->serio, sunkbd->serio->write(sunkbd->serio,
(!!test_bit(LED_CAPSL, sunkbd->dev.led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev.led) << 2) | (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) |
(!!test_bit(LED_COMPOSE, sunkbd->dev.led) << 1) | !!test_bit(LED_NUML, sunkbd->dev.led)); (!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) | !!test_bit(LED_NUML, sunkbd->dev->led));
sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev.snd)); sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd));
sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev.snd)); sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd));
}
static void sunkbd_enable(struct sunkbd *sunkbd, int enable)
{
serio_pause_rx(sunkbd->serio);
sunkbd->enabled = 1;
serio_continue_rx(sunkbd->serio);
} }
/* /*
@ -226,70 +237,64 @@ static void sunkbd_reinit(void *data)
static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
{ {
struct sunkbd *sunkbd; struct sunkbd *sunkbd;
struct input_dev *input_dev;
int err = -ENOMEM;
int i; int i;
int err;
if (!(sunkbd = kmalloc(sizeof(struct sunkbd), GFP_KERNEL))) sunkbd = kzalloc(sizeof(struct sunkbd), GFP_KERNEL);
return -ENOMEM; input_dev = input_allocate_device();
if (!sunkbd || !input_dev)
memset(sunkbd, 0, sizeof(struct sunkbd)); goto fail;
init_input_dev(&sunkbd->dev);
init_waitqueue_head(&sunkbd->wait);
sunkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
sunkbd->dev.ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML);
sunkbd->dev.sndbit[0] = BIT(SND_CLICK) | BIT(SND_BELL);
sunkbd->serio = serio; sunkbd->serio = serio;
sunkbd->dev = input_dev;
init_waitqueue_head(&sunkbd->wait);
INIT_WORK(&sunkbd->tq, sunkbd_reinit, sunkbd); INIT_WORK(&sunkbd->tq, sunkbd_reinit, sunkbd);
snprintf(sunkbd->phys, sizeof(sunkbd->phys), "%s/input0", serio->phys);
sunkbd->dev.keycode = sunkbd->keycode;
sunkbd->dev.keycodesize = sizeof(unsigned char);
sunkbd->dev.keycodemax = ARRAY_SIZE(sunkbd_keycode);
sunkbd->dev.event = sunkbd_event;
sunkbd->dev.private = sunkbd;
serio_set_drvdata(serio, sunkbd); serio_set_drvdata(serio, sunkbd);
err = serio_open(serio, drv); err = serio_open(serio, drv);
if (err) { if (err)
serio_set_drvdata(serio, NULL); goto fail;
kfree(sunkbd);
return err;
}
if (sunkbd_initialize(sunkbd) < 0) { if (sunkbd_initialize(sunkbd) < 0) {
serio_close(serio); serio_close(serio);
serio_set_drvdata(serio, NULL); goto fail;
kfree(sunkbd);
return -ENODEV;
} }
sprintf(sunkbd->name, "Sun Type %d keyboard", sunkbd->type); sprintf(sunkbd->name, "Sun Type %d keyboard", sunkbd->type);
memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode)); memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode));
input_dev->name = sunkbd->name;
input_dev->phys = sunkbd->phys;
input_dev->id.bustype = BUS_RS232;
input_dev->id.vendor = SERIO_SUNKBD;
input_dev->id.product = sunkbd->type;
input_dev->id.version = 0x0100;
input_dev->cdev.dev = &serio->dev;
input_dev->private = sunkbd;
input_dev->event = sunkbd_event;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
input_dev->ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML);
input_dev->sndbit[0] = BIT(SND_CLICK) | BIT(SND_BELL);
input_dev->keycode = sunkbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
input_dev->keycodemax = ARRAY_SIZE(sunkbd_keycode);
for (i = 0; i < 128; i++) for (i = 0; i < 128; i++)
set_bit(sunkbd->keycode[i], sunkbd->dev.keybit); set_bit(sunkbd->keycode[i], input_dev->keybit);
clear_bit(0, sunkbd->dev.keybit); clear_bit(0, input_dev->keybit);
sprintf(sunkbd->phys, "%s/input0", serio->phys);
sunkbd->dev.name = sunkbd->name;
sunkbd->dev.phys = sunkbd->phys;
sunkbd->dev.id.bustype = BUS_RS232;
sunkbd->dev.id.vendor = SERIO_SUNKBD;
sunkbd->dev.id.product = sunkbd->type;
sunkbd->dev.id.version = 0x0100;
sunkbd->dev.dev = &serio->dev;
input_register_device(&sunkbd->dev);
printk(KERN_INFO "input: %s on %s\n", sunkbd->name, serio->phys);
sunkbd_enable(sunkbd, 1);
input_register_device(sunkbd->dev);
return 0; return 0;
fail: serio_set_drvdata(serio, NULL);
input_free_device(input_dev);
kfree(sunkbd);
return err;
} }
/* /*
@ -299,7 +304,9 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
static void sunkbd_disconnect(struct serio *serio) static void sunkbd_disconnect(struct serio *serio)
{ {
struct sunkbd *sunkbd = serio_get_drvdata(serio); struct sunkbd *sunkbd = serio_get_drvdata(serio);
input_unregister_device(&sunkbd->dev);
sunkbd_enable(sunkbd, 0);
input_unregister_device(sunkbd->dev);
serio_close(serio); serio_close(serio);
serio_set_drvdata(serio, NULL); serio_set_drvdata(serio, NULL);
kfree(sunkbd); kfree(sunkbd);

View file

@ -56,11 +56,9 @@ static unsigned char xtkbd_keycode[256] = {
106 106
}; };
static char *xtkbd_name = "XT Keyboard";
struct xtkbd { struct xtkbd {
unsigned char keycode[256]; unsigned char keycode[256];
struct input_dev dev; struct input_dev *dev;
struct serio *serio; struct serio *serio;
char phys[32]; char phys[32];
}; };
@ -77,9 +75,9 @@ static irqreturn_t xtkbd_interrupt(struct serio *serio,
default: default:
if (xtkbd->keycode[data & XTKBD_KEY]) { if (xtkbd->keycode[data & XTKBD_KEY]) {
input_regs(&xtkbd->dev, regs); input_regs(xtkbd->dev, regs);
input_report_key(&xtkbd->dev, xtkbd->keycode[data & XTKBD_KEY], !(data & XTKBD_RELEASE)); input_report_key(xtkbd->dev, xtkbd->keycode[data & XTKBD_KEY], !(data & XTKBD_RELEASE));
input_sync(&xtkbd->dev); input_sync(xtkbd->dev);
} else { } else {
printk(KERN_WARNING "xtkbd.c: Unknown key (scancode %#x) %s.\n", printk(KERN_WARNING "xtkbd.c: Unknown key (scancode %#x) %s.\n",
data & XTKBD_KEY, data & XTKBD_RELEASE ? "released" : "pressed"); data & XTKBD_KEY, data & XTKBD_RELEASE ? "released" : "pressed");
@ -91,62 +89,60 @@ static irqreturn_t xtkbd_interrupt(struct serio *serio,
static int xtkbd_connect(struct serio *serio, struct serio_driver *drv) static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
{ {
struct xtkbd *xtkbd; struct xtkbd *xtkbd;
struct input_dev *input_dev;
int err = -ENOMEM;
int i; int i;
int err;
if (!(xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL))) xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL);
return -ENOMEM; input_dev = input_allocate_device();
if (!xtkbd || !input_dev)
memset(xtkbd, 0, sizeof(struct xtkbd)); goto fail;
xtkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
xtkbd->serio = serio; xtkbd->serio = serio;
xtkbd->dev = input_dev;
sprintf(xtkbd->phys, "%s/input0", serio->phys);
memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode));
init_input_dev(&xtkbd->dev); input_dev->name = "XT Keyboard";
xtkbd->dev.keycode = xtkbd->keycode; input_dev->phys = xtkbd->phys;
xtkbd->dev.keycodesize = sizeof(unsigned char); input_dev->id.bustype = BUS_XTKBD;
xtkbd->dev.keycodemax = ARRAY_SIZE(xtkbd_keycode); input_dev->id.vendor = 0x0001;
xtkbd->dev.private = xtkbd; input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
input_dev->cdev.dev = &serio->dev;
input_dev->private = xtkbd;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
input_dev->keycode = xtkbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
input_dev->keycodemax = ARRAY_SIZE(xtkbd_keycode);
for (i = 0; i < 255; i++)
set_bit(xtkbd->keycode[i], input_dev->keybit);
clear_bit(0, input_dev->keybit);
serio_set_drvdata(serio, xtkbd); serio_set_drvdata(serio, xtkbd);
err = serio_open(serio, drv); err = serio_open(serio, drv);
if (err) { if (err)
serio_set_drvdata(serio, NULL); goto fail;
input_register_device(xtkbd->dev);
return 0;
fail: serio_set_drvdata(serio, NULL);
input_free_device(input_dev);
kfree(xtkbd); kfree(xtkbd);
return err; return err;
}
memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode));
for (i = 0; i < 255; i++)
set_bit(xtkbd->keycode[i], xtkbd->dev.keybit);
clear_bit(0, xtkbd->dev.keybit);
sprintf(xtkbd->phys, "%s/input0", serio->phys);
xtkbd->dev.name = xtkbd_name;
xtkbd->dev.phys = xtkbd->phys;
xtkbd->dev.id.bustype = BUS_XTKBD;
xtkbd->dev.id.vendor = 0x0001;
xtkbd->dev.id.product = 0x0001;
xtkbd->dev.id.version = 0x0100;
xtkbd->dev.dev = &serio->dev;
input_register_device(&xtkbd->dev);
printk(KERN_INFO "input: %s on %s\n", xtkbd_name, serio->phys);
return 0;
} }
static void xtkbd_disconnect(struct serio *serio) static void xtkbd_disconnect(struct serio *serio)
{ {
struct xtkbd *xtkbd = serio_get_drvdata(serio); struct xtkbd *xtkbd = serio_get_drvdata(serio);
input_unregister_device(&xtkbd->dev);
serio_close(serio); serio_close(serio);
serio_set_drvdata(serio, NULL); serio_set_drvdata(serio, NULL);
input_unregister_device(xtkbd->dev);
kfree(xtkbd); kfree(xtkbd);
} }

View file

@ -24,9 +24,7 @@ MODULE_AUTHOR("Richard Zidlicky <rz@linux-m68k.org>");
MODULE_DESCRIPTION("m68k beeper driver"); MODULE_DESCRIPTION("m68k beeper driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static char m68kspkr_name[] = "m68k beeper"; static struct input_dev *m68kspkr_dev;
static char m68kspkr_phys[] = "m68k/generic";
static struct input_dev m68kspkr_dev;
static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{ {
@ -51,32 +49,34 @@ static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int
static int __init m68kspkr_init(void) static int __init m68kspkr_init(void)
{ {
if (!mach_beep){ if (!mach_beep) {
printk("%s: no lowlevel beep support\n", m68kspkr_name); printk(KERN_INFO "m68kspkr: no lowlevel beep support\n");
return -1; return -ENODEV;
} }
m68kspkr_dev.evbit[0] = BIT(EV_SND); m68kspkr_dev = input_allocate_device();
m68kspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); if (!m68kspkr_dev)
m68kspkr_dev.event = m68kspkr_event; return -ENOMEM;
m68kspkr_dev.name = m68kspkr_name; m68kspkr_dev->name = "m68k beeper";
m68kspkr_dev.phys = m68kspkr_phys; m68kspkr_dev->phys = "m68k/generic";
m68kspkr_dev.id.bustype = BUS_HOST; m68kspkr_dev->id.bustype = BUS_HOST;
m68kspkr_dev.id.vendor = 0x001f; m68kspkr_dev->id.vendor = 0x001f;
m68kspkr_dev.id.product = 0x0001; m68kspkr_dev->id.product = 0x0001;
m68kspkr_dev.id.version = 0x0100; m68kspkr_dev->id.version = 0x0100;
input_register_device(&m68kspkr_dev); m68kspkr_dev->evbit[0] = BIT(EV_SND);
m68kspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
m68kspkr_dev->event = m68kspkr_event;
printk(KERN_INFO "input: %s\n", m68kspkr_name); input_register_device(m68kspkr_dev);
return 0; return 0;
} }
static void __exit m68kspkr_exit(void) static void __exit m68kspkr_exit(void)
{ {
input_unregister_device(&m68kspkr_dev); input_unregister_device(m68kspkr_dev);
} }
module_init(m68kspkr_init); module_init(m68kspkr_init);

View file

@ -23,9 +23,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("PC Speaker beeper driver"); MODULE_DESCRIPTION("PC Speaker beeper driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static char pcspkr_name[] = "PC Speaker"; static struct input_dev *pcspkr_dev;
static char pcspkr_phys[] = "isa0061/input0";
static struct input_dev pcspkr_dev;
static DEFINE_SPINLOCK(i8253_beep_lock); static DEFINE_SPINLOCK(i8253_beep_lock);
@ -68,27 +66,29 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c
static int __init pcspkr_init(void) static int __init pcspkr_init(void)
{ {
pcspkr_dev.evbit[0] = BIT(EV_SND); pcspkr_dev = input_allocate_device();
pcspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); if (!pcspkr_dev)
pcspkr_dev.event = pcspkr_event; return -ENOMEM;
pcspkr_dev.name = pcspkr_name; pcspkr_dev->name = "PC Speaker";
pcspkr_dev.phys = pcspkr_phys; pcspkr_dev->name = "isa0061/input0";
pcspkr_dev.id.bustype = BUS_ISA; pcspkr_dev->id.bustype = BUS_ISA;
pcspkr_dev.id.vendor = 0x001f; pcspkr_dev->id.vendor = 0x001f;
pcspkr_dev.id.product = 0x0001; pcspkr_dev->id.product = 0x0001;
pcspkr_dev.id.version = 0x0100; pcspkr_dev->id.version = 0x0100;
input_register_device(&pcspkr_dev); pcspkr_dev->evbit[0] = BIT(EV_SND);
pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
pcspkr_dev->event = pcspkr_event;
printk(KERN_INFO "input: %s\n", pcspkr_name); input_register_device(pcspkr_dev);
return 0; return 0;
} }
static void __exit pcspkr_exit(void) static void __exit pcspkr_exit(void)
{ {
input_unregister_device(&pcspkr_dev); input_unregister_device(pcspkr_dev);
/* turn off the speaker */ /* turn off the speaker */
pcspkr_event(NULL, EV_SND, SND_BELL, 0); pcspkr_event(NULL, EV_SND, SND_BELL, 0);
} }

View file

@ -17,28 +17,24 @@
#endif #endif
MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
MODULE_DESCRIPTION("PC Speaker beeper driver"); MODULE_DESCRIPTION("Sparc Speaker beeper driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static unsigned long beep_iobase; static unsigned long beep_iobase;
static struct input_dev *sparcspkr_dev;
static char *sparcspkr_isa_name = "Sparc ISA Speaker";
static char *sparcspkr_ebus_name = "Sparc EBUS Speaker";
static char *sparcspkr_phys = "sparc/input0";
static struct input_dev sparcspkr_dev;
DEFINE_SPINLOCK(beep_lock); DEFINE_SPINLOCK(beep_lock);
static void __init init_sparcspkr_struct(void) static void __init init_sparcspkr_struct(void)
{ {
sparcspkr_dev.evbit[0] = BIT(EV_SND); sparcspkr_dev->evbit[0] = BIT(EV_SND);
sparcspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); sparcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
sparcspkr_dev.phys = sparcspkr_phys; sparcspkr_dev->phys = "sparc/input0";
sparcspkr_dev.id.bustype = BUS_ISA; sparcspkr_dev->id.bustype = BUS_ISA;
sparcspkr_dev.id.vendor = 0x001f; sparcspkr_dev->id.vendor = 0x001f;
sparcspkr_dev.id.product = 0x0001; sparcspkr_dev->id.product = 0x0001;
sparcspkr_dev.id.version = 0x0100; sparcspkr_dev->id.version = 0x0100;
} }
static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
@ -84,14 +80,15 @@ static int __init init_ebus_beep(struct linux_ebus_device *edev)
{ {
beep_iobase = edev->resource[0].start; beep_iobase = edev->resource[0].start;
init_sparcspkr_struct(); sparcspkr_dev = input_allocate_device();
if (!sparcspkr_dev)
return -ENOMEM;
sparcspkr_dev.name = sparcspkr_ebus_name; sparcspkr_dev->name = "Sparc EBUS Speaker";
sparcspkr_dev.event = ebus_spkr_event; sparcspkr_dev->event = ebus_spkr_event;
input_register_device(&sparcspkr_dev); input_register_device(sparcspkr_dev);
printk(KERN_INFO "input: %s\n", sparcspkr_ebus_name);
return 0; return 0;
} }
@ -137,15 +134,17 @@ static int __init init_isa_beep(struct sparc_isa_device *isa_dev)
{ {
beep_iobase = isa_dev->resource.start; beep_iobase = isa_dev->resource.start;
sparcspkr_dev = input_allocate_device();
if (!sparcspkr_dev)
return -ENOMEM;
init_sparcspkr_struct(); init_sparcspkr_struct();
sparcspkr_dev.name = sparcspkr_isa_name; sparcspkr_dev->name = "Sparc ISA Speaker";
sparcspkr_dev.event = isa_spkr_event; sparcspkr_dev->event = isa_spkr_event;
sparcspkr_dev.id.bustype = BUS_ISA;
input_register_device(&sparcspkr_dev); input_register_device(&sparcspkr_dev);
printk(KERN_INFO "input: %s\n", sparcspkr_isa_name);
return 0; return 0;
} }
#endif #endif
@ -182,7 +181,7 @@ static int __init sparcspkr_init(void)
static void __exit sparcspkr_exit(void) static void __exit sparcspkr_exit(void)
{ {
input_unregister_device(&sparcspkr_dev); input_unregister_device(sparcspkr_dev);
} }
module_init(sparcspkr_init); module_init(sparcspkr_init);

View file

@ -79,8 +79,8 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
{ {
struct alps_data *priv = psmouse->private; struct alps_data *priv = psmouse->private;
unsigned char *packet = psmouse->packet; unsigned char *packet = psmouse->packet;
struct input_dev *dev = &psmouse->dev; struct input_dev *dev = psmouse->dev;
struct input_dev *dev2 = &priv->dev2; struct input_dev *dev2 = priv->dev2;
int x, y, z, ges, fin, left, right, middle; int x, y, z, ges, fin, left, right, middle;
int back = 0, forward = 0; int back = 0, forward = 0;
@ -379,20 +379,24 @@ static int alps_reconnect(struct psmouse *psmouse)
static void alps_disconnect(struct psmouse *psmouse) static void alps_disconnect(struct psmouse *psmouse)
{ {
struct alps_data *priv = psmouse->private; struct alps_data *priv = psmouse->private;
psmouse_reset(psmouse); psmouse_reset(psmouse);
input_unregister_device(&priv->dev2); input_unregister_device(priv->dev2);
kfree(priv); kfree(priv);
} }
int alps_init(struct psmouse *psmouse) int alps_init(struct psmouse *psmouse)
{ {
struct alps_data *priv; struct alps_data *priv;
struct input_dev *dev1 = psmouse->dev, *dev2;
int version; int version;
psmouse->private = priv = kmalloc(sizeof(struct alps_data), GFP_KERNEL); psmouse->private = priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
if (!priv) dev2 = input_allocate_device();
if (!priv || !dev2)
goto init_fail; goto init_fail;
memset(priv, 0, sizeof(struct alps_data));
priv->dev2 = dev2;
if (!(priv->i = alps_get_model(psmouse, &version))) if (!(priv->i = alps_get_model(psmouse, &version)))
goto init_fail; goto init_fail;
@ -411,41 +415,39 @@ int alps_init(struct psmouse *psmouse)
if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0)) if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0))
goto init_fail; goto init_fail;
psmouse->dev.evbit[LONG(EV_KEY)] |= BIT(EV_KEY); dev1->evbit[LONG(EV_KEY)] |= BIT(EV_KEY);
psmouse->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH); dev1->keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
psmouse->dev.keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER); dev1->keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER);
psmouse->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); dev1->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
psmouse->dev.evbit[LONG(EV_ABS)] |= BIT(EV_ABS); dev1->evbit[LONG(EV_ABS)] |= BIT(EV_ABS);
input_set_abs_params(&psmouse->dev, ABS_X, 0, 1023, 0, 0); input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0);
input_set_abs_params(&psmouse->dev, ABS_Y, 0, 767, 0, 0); input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0);
input_set_abs_params(&psmouse->dev, ABS_PRESSURE, 0, 127, 0, 0); input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
if (priv->i->flags & ALPS_WHEEL) { if (priv->i->flags & ALPS_WHEEL) {
psmouse->dev.evbit[LONG(EV_REL)] |= BIT(EV_REL); dev1->evbit[LONG(EV_REL)] |= BIT(EV_REL);
psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL); dev1->relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL);
} }
if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD); dev1->keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK); dev1->keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
} }
sprintf(priv->phys, "%s/input1", psmouse->ps2dev.serio->phys); sprintf(priv->phys, "%s/input1", psmouse->ps2dev.serio->phys);
priv->dev2.phys = priv->phys; dev2->phys = priv->phys;
priv->dev2.name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; dev2->name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse";
priv->dev2.id.bustype = BUS_I8042; dev2->id.bustype = BUS_I8042;
priv->dev2.id.vendor = 0x0002; dev2->id.vendor = 0x0002;
priv->dev2.id.product = PSMOUSE_ALPS; dev2->id.product = PSMOUSE_ALPS;
priv->dev2.id.version = 0x0000; dev2->id.version = 0x0000;
priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); dev2->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y); dev2->relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); dev2->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
input_register_device(&priv->dev2); input_register_device(priv->dev2);
printk(KERN_INFO "input: %s on %s\n", priv->dev2.name, psmouse->ps2dev.serio->phys);
psmouse->protocol_handler = alps_process_byte; psmouse->protocol_handler = alps_process_byte;
psmouse->disconnect = alps_disconnect; psmouse->disconnect = alps_disconnect;
@ -455,6 +457,7 @@ int alps_init(struct psmouse *psmouse)
return 0; return 0;
init_fail: init_fail:
input_free_device(dev2);
kfree(priv); kfree(priv);
return -1; return -1;
} }

View file

@ -22,7 +22,7 @@ struct alps_model_info {
}; };
struct alps_data { struct alps_data {
struct input_dev dev2; /* Relative device */ struct input_dev *dev2; /* Relative device */
char name[32]; /* Name */ char name[32]; /* Name */
char phys[32]; /* Phys */ char phys[32]; /* Phys */
struct alps_model_info *i; /* Info */ struct alps_model_info *i; /* Info */

View file

@ -34,10 +34,7 @@ MODULE_DESCRIPTION("Amiga mouse driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static int amimouse_lastx, amimouse_lasty; static int amimouse_lastx, amimouse_lasty;
static struct input_dev amimouse_dev; static struct input_dev *amimouse_dev;
static char *amimouse_name = "Amiga mouse";
static char *amimouse_phys = "amimouse/input0";
static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp) static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
{ {
@ -62,16 +59,16 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
potgor = custom.potgor; potgor = custom.potgor;
input_regs(&amimouse_dev, fp); input_regs(amimouse_dev, fp);
input_report_rel(&amimouse_dev, REL_X, dx); input_report_rel(amimouse_dev, REL_X, dx);
input_report_rel(&amimouse_dev, REL_Y, dy); input_report_rel(amimouse_dev, REL_Y, dy);
input_report_key(&amimouse_dev, BTN_LEFT, ciaa.pra & 0x40); input_report_key(amimouse_dev, BTN_LEFT, ciaa.pra & 0x40);
input_report_key(&amimouse_dev, BTN_MIDDLE, potgor & 0x0100); input_report_key(amimouse_dev, BTN_MIDDLE, potgor & 0x0100);
input_report_key(&amimouse_dev, BTN_RIGHT, potgor & 0x0400); input_report_key(amimouse_dev, BTN_RIGHT, potgor & 0x0400);
input_sync(&amimouse_dev); input_sync(amimouse_dev);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -103,28 +100,30 @@ static int __init amimouse_init(void)
if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE)) if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE))
return -ENODEV; return -ENODEV;
amimouse_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); if (!(amimouse_dev = input_allocate_device()))
amimouse_dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); return -ENOMEM;
amimouse_dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
amimouse_dev.open = amimouse_open;
amimouse_dev.close = amimouse_close;
amimouse_dev.name = amimouse_name; amimouse_dev->name = "Amiga mouse";
amimouse_dev.phys = amimouse_phys; amimouse_dev->phys = "amimouse/input0";
amimouse_dev.id.bustype = BUS_AMIGA; amimouse_dev->id.bustype = BUS_AMIGA;
amimouse_dev.id.vendor = 0x0001; amimouse_dev->id.vendor = 0x0001;
amimouse_dev.id.product = 0x0002; amimouse_dev->id.product = 0x0002;
amimouse_dev.id.version = 0x0100; amimouse_dev->id.version = 0x0100;
input_register_device(&amimouse_dev); amimouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
amimouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
amimouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
amimouse_dev->open = amimouse_open;
amimouse_dev->close = amimouse_close;
input_register_device(amimouse_dev);
printk(KERN_INFO "input: %s at joy0dat\n", amimouse_name);
return 0; return 0;
} }
static void __exit amimouse_exit(void) static void __exit amimouse_exit(void)
{ {
input_unregister_device(&amimouse_dev); input_unregister_device(amimouse_dev);
} }
module_init(amimouse_init); module_init(amimouse_init);

View file

@ -87,7 +87,36 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)");
__obsolete_setup("inport_irq="); __obsolete_setup("inport_irq=");
static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs); static struct input_dev *inport_dev;
static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned char buttons;
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_HOLD | INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
input_regs(inport_dev, regs);
outb(INPORT_REG_X, INPORT_CONTROL_PORT);
input_report_rel(inport_dev, REL_X, inb(INPORT_DATA_PORT));
outb(INPORT_REG_Y, INPORT_CONTROL_PORT);
input_report_rel(inport_dev, REL_Y, inb(INPORT_DATA_PORT));
outb(INPORT_REG_BTNS, INPORT_CONTROL_PORT);
buttons = inb(INPORT_DATA_PORT);
input_report_key(inport_dev, BTN_MIDDLE, buttons & 1);
input_report_key(inport_dev, BTN_LEFT, buttons & 2);
input_report_key(inport_dev, BTN_RIGHT, buttons & 4);
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
input_sync(inport_dev);
return IRQ_HANDLED;
}
static int inport_open(struct input_dev *dev) static int inport_open(struct input_dev *dev)
{ {
@ -106,54 +135,9 @@ static void inport_close(struct input_dev *dev)
free_irq(inport_irq, NULL); free_irq(inport_irq, NULL);
} }
static struct input_dev inport_dev = {
.evbit = { BIT(EV_KEY) | BIT(EV_REL) },
.keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
.relbit = { BIT(REL_X) | BIT(REL_Y) },
.open = inport_open,
.close = inport_close,
.name = INPORT_NAME,
.phys = "isa023c/input0",
.id = {
.bustype = BUS_ISA,
.vendor = INPORT_VENDOR,
.product = 0x0001,
.version = 0x0100,
},
};
static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned char buttons;
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_HOLD | INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
input_regs(&inport_dev, regs);
outb(INPORT_REG_X, INPORT_CONTROL_PORT);
input_report_rel(&inport_dev, REL_X, inb(INPORT_DATA_PORT));
outb(INPORT_REG_Y, INPORT_CONTROL_PORT);
input_report_rel(&inport_dev, REL_Y, inb(INPORT_DATA_PORT));
outb(INPORT_REG_BTNS, INPORT_CONTROL_PORT);
buttons = inb(INPORT_DATA_PORT);
input_report_key(&inport_dev, BTN_MIDDLE, buttons & 1);
input_report_key(&inport_dev, BTN_LEFT, buttons & 2);
input_report_key(&inport_dev, BTN_RIGHT, buttons & 4);
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
input_sync(&inport_dev);
return IRQ_HANDLED;
}
static int __init inport_init(void) static int __init inport_init(void)
{ {
unsigned char a,b,c; unsigned char a, b, c;
if (!request_region(INPORT_BASE, INPORT_EXTENT, "inport")) { if (!request_region(INPORT_BASE, INPORT_EXTENT, "inport")) {
printk(KERN_ERR "inport.c: Can't allocate ports at %#x\n", INPORT_BASE); printk(KERN_ERR "inport.c: Can't allocate ports at %#x\n", INPORT_BASE);
@ -163,26 +147,44 @@ static int __init inport_init(void)
a = inb(INPORT_SIGNATURE_PORT); a = inb(INPORT_SIGNATURE_PORT);
b = inb(INPORT_SIGNATURE_PORT); b = inb(INPORT_SIGNATURE_PORT);
c = inb(INPORT_SIGNATURE_PORT); c = inb(INPORT_SIGNATURE_PORT);
if (( a == b ) || ( a != c )) { if (a == b || a != c) {
release_region(INPORT_BASE, INPORT_EXTENT); release_region(INPORT_BASE, INPORT_EXTENT);
printk(KERN_ERR "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE); printk(KERN_ERR "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE);
return -ENODEV; return -ENODEV;
} }
if (!(inport_dev = input_allocate_device())) {
printk(KERN_ERR "inport.c: Not enough memory for input device\n");
release_region(INPORT_BASE, INPORT_EXTENT);
return -ENOMEM;
}
inport_dev->name = INPORT_NAME;
inport_dev->phys = "isa023c/input0";
inport_dev->id.bustype = BUS_ISA;
inport_dev->id.vendor = INPORT_VENDOR;
inport_dev->id.product = 0x0001;
inport_dev->id.version = 0x0100;
inport_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
inport_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
inport_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
inport_dev->open = inport_open;
inport_dev->close = inport_close;
outb(INPORT_RESET, INPORT_CONTROL_PORT); outb(INPORT_RESET, INPORT_CONTROL_PORT);
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_BASE, INPORT_DATA_PORT); outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
input_register_device(&inport_dev); input_register_device(inport_dev);
printk(KERN_INFO "input: " INPORT_NAME " at %#x irq %d\n", INPORT_BASE, inport_irq);
return 0; return 0;
} }
static void __exit inport_exit(void) static void __exit inport_exit(void)
{ {
input_unregister_device(&inport_dev); input_unregister_device(inport_dev);
release_region(INPORT_BASE, INPORT_EXTENT); release_region(INPORT_BASE, INPORT_EXTENT);
} }

Some files were not shown because too many files have changed in this diff Show more