[PATCH] Apple Motion Sensor driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 2 Aug 2006 21:15:20 +0200
Michael Hanselmann <linux-kernel at hansmi.ch> wrote:

> This driver adds support for the Apple Motion Sensor (AMS) as found in
> 2005 revisions of Apple PowerBooks and iBooks. It implements both the
> PMU and I?C variants. The I?C driver and mouse emulation is based on
> code by Stelian Pop <stelian at popies.net>, while the PMU driver has been
> developped by myself. HD parking support will be added later.
> 
> ...
>
> +/* There is only one motion sensor per machine */
> +struct ams ams;

That's a somewhat risky name for a global variable.

Then again, nobody else is likely to be so bold as to add another
three-character global ;)

> +/* Call with lock held! */
> +int ams_sensor_attach(void)

Which lock?

> +static int ams_i2c_cmd(enum ams_i2c_cmd cmd)
> +{
> +	s32 result;
> +	int i;
> +
> +	ams_i2c_write(AMS_COMMAND, cmd);
> +	for (i = 0; i < 10; i++) {
> +		mdelay(5);
> +		result = ams_i2c_read(AMS_COMMAND);
> +		if (result == 0 || result & 0x80)
> +			return 0;
> +	}
> +	return -1;
> +}

That's a potentially very long busy wait.

> +static void ams_i2c_set_irq(enum ams_irq reg, char enable)
> +{
> +	if (reg & AMS_IRQ_FREEFALL) {
> +		u8 val = ams_i2c_read(AMS_CTRLX);
> +		if (enable)     val |= 0x80;
> +		else            val &= ~0x80;
> +		ams_i2c_write(AMS_CTRLX, val);
> +	}
> +
> +	if (reg & AMS_IRQ_SHOCK) {
> +		u8 val = ams_i2c_read(AMS_CTRLY);
> +		if (enable)     val |= 0x80;
> +		else            val &= ~0x80;
> +		ams_i2c_write(AMS_CTRLY, val);
> +	}
> +
> +	if (reg & AMS_IRQ_GLOBAL) {
> +		u8 val = ams_i2c_read(AMS_CTRLZ);
> +		if (enable)     val |= 0x80;
> +		else            val &= ~0x80;
> +		ams_i2c_write(AMS_CTRLZ, val);
> +	}
> +}

Please, let's use

	if (a)
		b;
	else
		c;

> +/* Call with lock held! */
> +static void ams_mouse_enable(void)

Which lock?

> +{
> +	s8 x, y, z;
> +
> +	if (ams.idev)
> +		return;
> +
> +	ams_sensors(&x, &y, &z);
> +	ams.xcalib = x;
> +	ams.ycalib = y;
> +	ams.zcalib = z;
> +
> +	ams.idev = input_allocate_device();
> +	if (!ams.idev)
> +		return;
> +
> +	ams.idev->name = "Apple Motion Sensor";
> +	ams.idev->id.bustype = ams.bustype;
> +	ams.idev->id.vendor = 0;
> +	ams.idev->cdev.dev = &ams.of_dev->dev;
> +
> +	input_set_abs_params(ams.idev, ABS_X, -50, 50, 3, 0);
> +	input_set_abs_params(ams.idev, ABS_Y, -50, 50, 3, 0);
> +	input_set_abs_params(ams.idev, ABS_Z, -50, 50, 3, 0);
> +
> +	set_bit(EV_ABS, ams.idev->evbit);
> +	set_bit(EV_KEY, ams.idev->evbit);
> +
> +	if (input_register_device(ams.idev)) {
> +		input_free_device(ams.idev);
> +		ams.idev = NULL;
> +		return;
> +	}
> +
> +	ams.kthread = kthread_run(ams_mouse_kthread, NULL, "kams");
> +	if (IS_ERR(ams.kthread)) {
> +		input_unregister_device(ams.idev);
> +		ams.idev = NULL;
> +		return;

Didn't we just leak ams.idev?  Or does the disconnect handler handle that?

<goes to input_unregister_device() for the API description, comes away
discouraged>

> +		ams.idev = NULL;
> +	}
> +}
> +
> +static ssize_t ams_mouse_show_mouse(struct device *dev,
> +	struct device_attribute *attr, char *buf)
> +{
> +	return sprintf(buf, "%d\n", mouse);
> +}
> +
> +static ssize_t ams_mouse_store_mouse(struct device *dev,
> +	struct device_attribute *attr, const char *buf, size_t count)
> +{
> +	if (sscanf(buf, "%d\n", &mouse) != 1)
> +		return -EINVAL;
> +
> +	mouse = !!mouse;

That statement isn't needed.

> +	mutex_lock(&ams.lock);
> +
> +	if (mouse)
> +		ams_mouse_enable();
> +	else
> +		ams_mouse_disable();
> +
> +	mutex_unlock(&ams.lock);
> +
> +	return count;
> +}
>
> ...
>
> +/* Enables or disables the specified interrupts */
> +static void ams_pmu_set_irq(enum ams_irq reg, char enable)
> +{
> +	if (reg & AMS_IRQ_FREEFALL) {
> +		u8 val = ams_pmu_get_register(AMS_FF_ENABLE);
> +		if (enable)	val |= 0x80;
> +		else		val &= ~0x80;
> +		ams_pmu_set_register(AMS_FF_ENABLE, val);
> +	}
> +
> +	if (reg & AMS_IRQ_SHOCK) {
> +		u8 val = ams_pmu_get_register(AMS_SHOCK_ENABLE);
> +		if (enable)	val |= 0x80;
> +		else		val &= ~0x80;
> +		ams_pmu_set_register(AMS_SHOCK_ENABLE, val);
> +	}
> +
> +	if (reg & AMS_IRQ_GLOBAL) {
> +		u8 val = ams_pmu_get_register(AMS_CONTROL);
> +		if (enable)	val |= 0x80;
> +		else		val &= ~0x80;
> +		ams_pmu_set_register(AMS_CONTROL, val);
> +	}
> +}

Again - coding style is wrong.

> +/* Call with lock held! */
> +int __init ams_pmu_init(struct device_node *np)

Which lock??

> +{
> +	u32 *prop;
> +	int result;
> +
> +	mutex_lock(&ams.lock);

Obviously not that one...






[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux