/*
 * USB Phidget MotorControl driver
 *
 * Copyright (C) 2006  Sean Young <sean@mess.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/usb.h>

#include "phidget.h"

#define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
#define DRIVER_DESC "USB PhidgetMotorControl Driver"

#define USB_VENDOR_ID_GLAB		0x06c2
#define USB_DEVICE_ID_MOTORCONTROL	0x0058

#define URB_INT_SIZE			8

static unsigned long device_no;

struct motorcontrol {
	struct usb_device *udev;
	struct usb_interface *intf;
	struct device *dev;
	int dev_no;
	u8 inputs[4];
	s8 desired_speed[2];
	s8 speed[2];
	s16 _current[2];
	s8 acceleration[2];
	struct urb *irq;
	unsigned char *data;
	dma_addr_t data_dma;

	struct delayed_work do_notify;
	unsigned long input_events;
	unsigned long speed_events;
	unsigned long exceed_events;
};

static struct usb_device_id id_table[] = {
	{ USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_MOTORCONTROL) },
	{}
};
MODULE_DEVICE_TABLE(usb, id_table);

static int set_motor(struct motorcontrol *mc, int motor)
{
	u8 *buffer;
	int speed, speed2, acceleration;
	int retval;

	buffer = kzalloc(8, GFP_KERNEL);
	if (!buffer) {
		dev_err(&mc->intf->dev, "%s - out of memory\n", __FUNCTION__);
		return -ENOMEM;
	}

	acceleration = mc->acceleration[motor] * 10;
	/* -127 <= speed <= 127 */
	speed = (mc->desired_speed[motor] * 127) / 100;
	/* -0x7300 <= speed2 <= 0x7300 */
	speed2 = (mc->desired_speed[motor] * 230 * 128) / 100;

	buffer[0] = motor;
	buffer[1] = speed;
	buffer[2] = acceleration >> 8;
	buffer[3] = acceleration;
	buffer[4] = speed2 >> 8;
	buffer[5] = speed2;

	retval = usb_control_msg(mc->udev,
			 usb_sndctrlpipe(mc->udev, 0),
			 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000);

	if (retval != 8)
		dev_err(&mc->intf->dev, "usb_control_msg returned %d\n",
				retval);
	kfree(buffer);

	return retval < 0 ? retval : 0;
}

static void motorcontrol_irq(struct urb *urb)
{
	struct motorcontrol *mc = urb->context;
	unsigned char *buffer = mc->data;
	int i, level;
	int retval;
	int status = urb->status;;

	switch (status) {
	case 0:			/* success */
		break;
	case -ECONNRESET:	/* unlink */
	case -ENOENT:
	case -ESHUTDOWN:
		return;
	/* -EPIPE:  should clear the halt */
	default:		/* error */
		goto resubmit;
	}

	/* digital inputs */
	for (i=0; i<4; i++) {
		level = (buffer[0] >> i) & 1;
		if (mc->inputs[i] != level) {
			mc->inputs[i] = level;
			set_bit(i, &mc->input_events);
		}
	}

	/* motor speed */
	if (buffer[2] == 0) {
		for (i=0; i<2; i++) {
		level = ((s8)buffer[4+i]) * 100 / 127;
			if (mc->speed[i] != level) {
				mc->speed[i] = level;
				set_bit(i, &mc->speed_events);
			}
		}
	} else {
		int index = buffer[3] & 1;

		level = ((s8)buffer[4] << 8) | buffer[5];
		level = level * 100 / 29440;
		if (mc->speed[index] != level) {
			mc->speed[index] = level;
			set_bit(index, &mc->speed_events);
		}

		level = ((s8)buffer[6] << 8) | buffer[7];
		mc->_current[index] = level * 100 / 1572;
	}

	if (buffer[1] & 1)
		set_bit(0, &mc->exceed_events);

	if (buffer[1] & 2)
		set_bit(1, &mc->exceed_events);

	if (mc->input_events || mc->exceed_events || mc->speed_events)
		schedule_delayed_work(&mc->do_notify, 0);

resubmit:
	retval = usb_submit_urb(urb, GFP_ATOMIC);
	if (retval)
		dev_err(&mc->intf->dev,
			"can't resubmit intr, %s-%s/motorcontrol0, retval %d",
			mc->udev->bus->bus_name,
			mc->udev->devpath, retval);
}

static void do_notify(struct work_struct *work)
{
	struct motorcontrol *mc =
		container_of(work, struct motorcontrol, do_notify.work);
	int i;
	char sysfs_file[8];

	for (i=0; i<4; i++) {
		if (test_and_clear_bit(i, &mc->input_events)) {
			sprintf(sysfs_file, "input%d", i);
			sysfs_notify(&mc->dev->kobj, NULL, sysfs_file);
		}
	}

	for (i=0; i<2; i++) {
		if (test_and_clear_bit(i, &mc->speed_events)) {
			sprintf(sysfs_file, "speed%d", i);
			sysfs_notify(&mc->dev->kobj, NULL, sysfs_file);
		}
	}

	for (i=0; i<2; i++) {
		if (test_and_clear_bit(i, &mc->exceed_events))
			dev_warn(&mc->intf->dev,
				"motor #%d exceeds 1.5 Amp current limit\n", i);
	}
}

#define show_set_speed(value)		\
static ssize_t set_speed##value(struct device *dev,			\
					struct device_attribute *attr,	\
					const char *buf, size_t count)	\
{									\
	struct motorcontrol *mc = dev_get_drvdata(dev);			\
	int speed;							\
	int retval;							\
									\
	if (sscanf(buf, "%d", &speed) < 1)				\
		return -EINVAL;						\
									\
	if (speed < -100 || speed > 100)				\
		return -EINVAL;						\
									\
	mc->desired_speed[value] = speed;				\
									\
	retval = set_motor(mc, value);					\
									\
	return retval ? retval : count;					\
}									\
									\
static ssize_t show_speed##value(struct device *dev,			\
					struct device_attribute *attr,	\
					char *buf)			\
{									\
	struct motorcontrol *mc = dev_get_drvdata(dev);			\
									\
	return sprintf(buf, "%d\n", mc->speed[value]);			\
}

#define speed_attr(value) 						\
	__ATTR(speed##value, S_IWUGO | S_IRUGO, 			\
		show_speed##value, set_speed##value)

show_set_speed(0);
show_set_speed(1);

#define show_set_acceleration(value)		\
static ssize_t set_acceleration##value(struct device *dev, 		\
					struct device_attribute *attr,	\
					const char *buf, size_t count)	\
{									\
	struct motorcontrol *mc = dev_get_drvdata(dev);			\
	int acceleration;						\
	int retval;							\
									\
	if (sscanf(buf, "%d", &acceleration) < 1)			\
		return -EINVAL;						\
									\
	if (acceleration < 0 || acceleration > 100)			\
		return -EINVAL;						\
									\
	mc->acceleration[value] = acceleration;				\
									\
	retval = set_motor(mc, value);					\
									\
	return retval ? retval : count;					\
}									\
									\
static ssize_t show_acceleration##value(struct device *dev,	 	\
					struct device_attribute *attr,	\
							char *buf)	\
{									\
	struct motorcontrol *mc = dev_get_drvdata(dev);			\
									\
	return sprintf(buf, "%d\n", mc->acceleration[value]);		\
}

#define acceleration_attr(value)	\
	__ATTR(acceleration##value, S_IWUGO | S_IRUGO,			\
		show_acceleration##value, set_acceleration##value)

show_set_acceleration(0);
show_set_acceleration(1);

#define show_current(value)	\
static ssize_t show_current##value(struct device *dev,			\
					struct device_attribute *attr,	\
					char *buf)			\
{									\
	struct motorcontrol *mc = dev_get_drvdata(dev);			\
									\
	return sprintf(buf, "%dmA\n", (int)mc->_current[value]);	\
}

#define current_attr(value)	\
	__ATTR(current##value, S_IRUGO, show_current##value, NULL)

show_current(0);
show_current(1);

#define show_input(value)	\
static ssize_t show_input##value(struct device *dev,			\
					struct device_attribute *attr,	\
					char *buf)			\
{									\
	struct motorcontrol *mc = dev_get_drvdata(dev);			\
									\
	return sprintf(buf, "%d\n", (int)mc->inputs[value]);		\
}

#define input_attr(value)	\
	__ATTR(input##value, S_IRUGO, show_input##value, NULL)

show_input(0);
show_input(1);
show_input(2);
show_input(3);

static struct device_attribute dev_attrs[] = {
	input_attr(0),
	input_attr(1),
	input_attr(2),
	input_attr(3),
	speed_attr(0),
	speed_attr(1),
	acceleration_attr(0),
	acceleration_attr(1),
	current_attr(0),
	current_attr(1)
};

static int motorcontrol_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *dev = interface_to_usbdev(intf);
	struct usb_host_interface *interface;
	struct usb_endpoint_descriptor *endpoint;
	struct motorcontrol *mc;
	int pipe, maxp, rc = -ENOMEM;
	int bit, value, i;

	interface = intf->cur_altsetting;
	if (interface->desc.bNumEndpoints != 1)
		return -ENODEV;

	endpoint = &interface->endpoint[0].desc;
	if (!usb_endpoint_dir_in(endpoint))
		return -ENODEV;

	/*
	 * bmAttributes
	 */
	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));

	mc = kzalloc(sizeof(*mc), GFP_KERNEL);
	if (!mc)
		goto out;

	mc->dev_no = -1;
	mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &mc->data_dma);
	if (!mc->data)
		goto out;

	mc->irq = usb_alloc_urb(0, GFP_KERNEL);
	if (!mc->irq)
		goto out;

	mc->udev = usb_get_dev(dev);
	mc->intf = intf;
	mc->acceleration[0] = mc->acceleration[1] = 10;
	INIT_DELAYED_WORK(&mc->do_notify, do_notify);
	usb_fill_int_urb(mc->irq, mc->udev, pipe, mc->data,
			maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp,
			motorcontrol_irq, mc, endpoint->bInterval);
	mc->irq->transfer_dma = mc->data_dma;
	mc->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	usb_set_intfdata(intf, mc);

	do {
		bit = find_first_zero_bit(&device_no, sizeof(device_no));
		value = test_and_set_bit(bit, &device_no);
	} while(value);
	mc->dev_no = bit;

	mc->dev = device_create(phidget_class, &mc->udev->dev, 0,
				"motorcontrol%d", mc->dev_no);
	if (IS_ERR(mc->dev)) {
		rc = PTR_ERR(mc->dev);
		mc->dev = NULL;
		goto out;
	}

	dev_set_drvdata(mc->dev, mc);

	if (usb_submit_urb(mc->irq, GFP_KERNEL)) {
		rc = -EIO;
		goto out;
	}

	for (i=0; i<ARRAY_SIZE(dev_attrs); i++) {
		rc = device_create_file(mc->dev, &dev_attrs[i]);
		if (rc)
			goto out2;
	}

	dev_info(&intf->dev, "USB PhidgetMotorControl attached\n");

	return 0;
out2:
	while (i-- > 0)
		device_remove_file(mc->dev, &dev_attrs[i]);
out:
	if (mc) {
		usb_free_urb(mc->irq);
		if (mc->data)
			usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma);
		if (mc->dev)
			device_unregister(mc->dev);
		if (mc->dev_no >= 0)
			clear_bit(mc->dev_no, &device_no);

		kfree(mc);
	}

	return rc;
}

static void motorcontrol_disconnect(struct usb_interface *interface)
{
	struct motorcontrol *mc;
	int i;

	mc = usb_get_intfdata(interface);
	usb_set_intfdata(interface, NULL);
	if (!mc)
		return;

	usb_kill_urb(mc->irq);
	usb_free_urb(mc->irq);
	usb_buffer_free(mc->udev, URB_INT_SIZE, mc->data, mc->data_dma);

	cancel_delayed_work(&mc->do_notify);

	for (i=0; i<ARRAY_SIZE(dev_attrs); i++)
		device_remove_file(mc->dev, &dev_attrs[i]);

	device_unregister(mc->dev);

	usb_put_dev(mc->udev);
	clear_bit(mc->dev_no, &device_no);
	kfree(mc);

	dev_info(&interface->dev, "USB PhidgetMotorControl detached\n");
}

static struct usb_driver motorcontrol_driver = {
	.name = "phidgetmotorcontrol",
	.probe = motorcontrol_probe,
	.disconnect = motorcontrol_disconnect,
	.id_table = id_table
};

static int __init motorcontrol_init(void)
{
	int retval = 0;

	retval = usb_register(&motorcontrol_driver);
	if (retval)
		err("usb_register failed. Error number %d", retval);

	return retval;
}

static void __exit motorcontrol_exit(void)
{
	usb_deregister(&motorcontrol_driver);
}

module_init(motorcontrol_init);
module_exit(motorcontrol_exit);

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
