/*
 *  Copyright (c) 2001-2005 Edouard TISSERANT   <edouard.tisserant@wanadoo.fr>
 *  Copyright (c) 2004-2005 Stephane VOLTZ      <svoltz@numericable.fr>
 *
 *  USB Acecad "Acecad Flair" tablet support
 *
 *  Changelog:
 *      v3.2 - Added sysfs support
 */

/*
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

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

/*
 * Version Information
 */
#define DRIVER_VERSION "v3.2"
#define DRIVER_DESC    "USB Acecad Flair tablet driver"
#define DRIVER_LICENSE "GPL"
#define DRIVER_AUTHOR  "Edouard TISSERANT <edouard.tisserant@wanadoo.fr>"

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);

#define USB_VENDOR_ID_ACECAD	0x0460
#define USB_DEVICE_ID_FLAIR	0x0004
#define USB_DEVICE_ID_302	0x0008

struct usb_acecad {
	char name[128];
	char phys[64];
	struct usb_device *usbdev;
	struct input_dev dev;
	struct urb *irq;

	signed char *data;
	dma_addr_t data_dma;
};

static void usb_acecad_irq(struct urb *urb, struct pt_regs *regs)
{
	struct usb_acecad *acecad = urb->context;
	unsigned char *data = acecad->data;
	struct input_dev *dev = &acecad->dev;
	int prox, status;

	switch (urb->status) {
		case 0:
			/* success */
			break;
		case -ECONNRESET:
		case -ENOENT:
		case -ESHUTDOWN:
			/* this urb is terminated, clean up */
			dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
			return;
		default:
			dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
			goto resubmit;
	}

	prox = (data[0] & 0x04) >> 2;
	input_report_key(dev, BTN_TOOL_PEN, prox);

	if (prox) {
		int x = data[1] | (data[2] << 8);
		int y = data[3] | (data[4] << 8);
		/* Pressure should compute the same way for flair and 302 */
		int pressure = data[5] | (data[6] << 8);
		int touch = data[0] & 0x01;
		int stylus = (data[0] & 0x10) >> 4;
		int stylus2 = (data[0] & 0x20) >> 5;
		input_report_abs(dev, ABS_X, x);
		input_report_abs(dev, ABS_Y, y);
		input_report_abs(dev, ABS_PRESSURE, pressure);
		input_report_key(dev, BTN_TOUCH, touch);
		input_report_key(dev, BTN_STYLUS, stylus);
		input_report_key(dev, BTN_STYLUS2, stylus2);
	}

	/* event termination */
	input_sync(dev);

resubmit:
	status = usb_submit_urb(urb, GFP_ATOMIC);
	if (status)
		err("can't resubmit intr, %s-%s/input0, status %d",
			acecad->usbdev->bus->bus_name, acecad->usbdev->devpath, status);
}

static int usb_acecad_open(struct input_dev *dev)
{
	struct usb_acecad *acecad = dev->private;

	acecad->irq->dev = acecad->usbdev;
	if (usb_submit_urb(acecad->irq, GFP_KERNEL))
		return -EIO;

	return 0;
}

static void usb_acecad_close(struct input_dev *dev)
{
	struct usb_acecad *acecad = dev->private;

	usb_kill_urb(acecad->irq);
}

static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *dev = interface_to_usbdev(intf);
	struct usb_host_interface *interface = intf->cur_altsetting;
	struct usb_endpoint_descriptor *endpoint;
	struct usb_acecad *acecad;
	int pipe, maxp;
	char path[64];

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

	endpoint = &interface->endpoint[0].desc;

	if (!(endpoint->bEndpointAddress & 0x80))
		return -ENODEV;

	if ((endpoint->bmAttributes & 3) != 3)
		return -ENODEV;

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

	acecad = kcalloc(1, sizeof(struct usb_acecad), GFP_KERNEL);
	if (!acecad)
		return -ENOMEM;

	acecad->data = usb_buffer_alloc(dev, 8, SLAB_KERNEL, &acecad->data_dma);
	if (!acecad->data)
		goto fail1;

	acecad->irq = usb_alloc_urb(0, GFP_KERNEL);
	if (!acecad->irq)
		goto fail2;

	if (dev->manufacturer)
		strlcpy(acecad->name, dev->manufacturer, sizeof(acecad->name));

	if (dev->product) {
		if (dev->manufacturer)
			strlcat(acecad->name, " ", sizeof(acecad->name));
		strlcat(acecad->name, dev->product, sizeof(acecad->name));
	}

	usb_make_path(dev, path, sizeof(path));
	snprintf(acecad->phys, sizeof(acecad->phys), "%s/input0", path);

	acecad->usbdev = dev;

	acecad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
	acecad->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
	acecad->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
	acecad->dev.keybit[LONG(BTN_DIGI)] = BIT(BTN_TOOL_PEN) |BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2);

	switch (id->driver_info) {
		case 0:
			acecad->dev.absmax[ABS_X] = 5000;
			acecad->dev.absmax[ABS_Y] = 3750;
			acecad->dev.absmax[ABS_PRESSURE] = 512;
			if (!strlen(acecad->name))
				snprintf(acecad->name, sizeof(acecad->name),
					"USB Acecad Flair Tablet %04x:%04x",
					dev->descriptor.idVendor, dev->descriptor.idProduct);
			break;
		case 1:
			acecad->dev.absmax[ABS_X] = 3000;
			acecad->dev.absmax[ABS_Y] = 2250;
			acecad->dev.absmax[ABS_PRESSURE] = 1024;
			if (!strlen(acecad->name))
				snprintf(acecad->name, sizeof(acecad->name),
					"USB Acecad 302 Tablet %04x:%04x",
					dev->descriptor.idVendor, dev->descriptor.idProduct);
			break;
	}

	acecad->dev.absfuzz[ABS_X] = 4;
	acecad->dev.absfuzz[ABS_Y] = 4;

	acecad->dev.private = acecad;
	acecad->dev.open = usb_acecad_open;
	acecad->dev.close = usb_acecad_close;

	acecad->dev.name = acecad->name;
	acecad->dev.phys = acecad->phys;
	acecad->dev.id.bustype = BUS_USB;
	acecad->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor);
	acecad->dev.id.product = le16_to_cpu(dev->descriptor.idProduct);
	acecad->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice);
	acecad->dev.dev = &intf->dev;

	usb_fill_int_urb(acecad->irq, dev, pipe,
			acecad->data, maxp > 8 ? 8 : maxp,
			usb_acecad_irq, acecad, endpoint->bInterval);
	acecad->irq->transfer_dma = acecad->data_dma;
	acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	input_register_device(&acecad->dev);

	printk(KERN_INFO "input: %s with packet size %d on %s\n",
		acecad->name, maxp, path);

	usb_set_intfdata(intf, acecad);

	return 0;

 fail2:	usb_buffer_free(dev, 8, acecad->data, acecad->data_dma);
 fail1:	kfree(acecad);
	return -ENOMEM;
}

static void usb_acecad_disconnect(struct usb_interface *intf)
{
	struct usb_acecad *acecad = usb_get_intfdata(intf);

	usb_set_intfdata(intf, NULL);
	if (acecad) {
		usb_kill_urb(acecad->irq);
		input_unregister_device(&acecad->dev);
		usb_free_urb(acecad->irq);
		usb_buffer_free(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma);
		kfree(acecad);
	}
}

static struct usb_device_id usb_acecad_id_table [] = {
	{ USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_FLAIR), .driver_info = 0 },
	{ USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_302),	 .driver_info = 1 },
	{ }
};

MODULE_DEVICE_TABLE(usb, usb_acecad_id_table);

static struct usb_driver usb_acecad_driver = {
	.owner =	THIS_MODULE,
	.name =		"usb_acecad",
	.probe =	usb_acecad_probe,
	.disconnect =	usb_acecad_disconnect,
	.id_table =	usb_acecad_id_table,
};

static int __init usb_acecad_init(void)
{
	int result = usb_register(&usb_acecad_driver);
	if (result == 0)
		info(DRIVER_VERSION ":" DRIVER_DESC);
	return result;
}

static void __exit usb_acecad_exit(void)
{
	usb_deregister(&usb_acecad_driver);
}

module_init(usb_acecad_init);
module_exit(usb_acecad_exit);
