/*
 * ThingM blink(1) USB RGB LED driver
 *
 * Copyright 2013-2014 Savoir-faire Linux Inc.
 *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
 *
 * 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, version 2.
 */

#include <linux/hid.h>
#include <linux/hidraw.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>

#include "hid-ids.h"

#define REPORT_ID	1
#define REPORT_SIZE	9

/* Firmware major number of supported devices */
#define THINGM_MAJOR_MK1	'1'
#define THINGM_MAJOR_MK2	'2'

struct thingm_fwinfo {
	char major;
	unsigned numrgb;
	unsigned first;
};

static const struct thingm_fwinfo thingm_fwinfo[] = {
	{
		.major = THINGM_MAJOR_MK1,
		.numrgb = 1,
		.first = 0,
	}, {
		.major = THINGM_MAJOR_MK2,
		.numrgb = 2,
		.first = 1,
	}
};

/* A red, green or blue channel, part of an RGB chip */
struct thingm_led {
	struct thingm_rgb *rgb;
	struct led_classdev ldev;
	char name[32];
};

/* Basically a WS2812 5050 RGB LED chip */
struct thingm_rgb {
	struct thingm_device *tdev;
	struct thingm_led red;
	struct thingm_led green;
	struct thingm_led blue;
	struct work_struct work;
	u8 num;
};

struct thingm_device {
	struct hid_device *hdev;
	struct {
		char major;
		char minor;
	} version;
	const struct thingm_fwinfo *fwinfo;
	struct mutex lock;
	struct thingm_rgb *rgb;
};

static int thingm_send(struct thingm_device *tdev, u8 buf[REPORT_SIZE])
{
	int ret;

	hid_dbg(tdev->hdev, "-> %d %c %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n",
			buf[0], buf[1], buf[2], buf[3], buf[4],
			buf[5], buf[6], buf[7], buf[8]);

	ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE,
			HID_FEATURE_REPORT, HID_REQ_SET_REPORT);

	return ret < 0 ? ret : 0;
}

static int thingm_recv(struct thingm_device *tdev, u8 buf[REPORT_SIZE])
{
	int ret;

	ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE,
			HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
	if (ret < 0)
		return ret;

	hid_dbg(tdev->hdev, "<- %d %c %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n",
			buf[0], buf[1], buf[2], buf[3], buf[4],
			buf[5], buf[6], buf[7], buf[8]);

	return 0;
}

static int thingm_version(struct thingm_device *tdev)
{
	u8 buf[REPORT_SIZE] = { REPORT_ID, 'v', 0, 0, 0, 0, 0, 0, 0 };
	int err;

	err = thingm_send(tdev, buf);
	if (err)
		return err;

	err = thingm_recv(tdev, buf);
	if (err)
		return err;

	tdev->version.major = buf[3];
	tdev->version.minor = buf[4];

	return 0;
}

static int thingm_write_color(struct thingm_rgb *rgb)
{
	u8 buf[REPORT_SIZE] = { REPORT_ID, 'c', 0, 0, 0, 0, 0, rgb->num, 0 };

	buf[2] = rgb->red.ldev.brightness;
	buf[3] = rgb->green.ldev.brightness;
	buf[4] = rgb->blue.ldev.brightness;

	return thingm_send(rgb->tdev, buf);
}

static void thingm_work(struct work_struct *work)
{
	struct thingm_rgb *rgb = container_of(work, struct thingm_rgb, work);

	mutex_lock(&rgb->tdev->lock);

	if (thingm_write_color(rgb))
		hid_err(rgb->tdev->hdev, "failed to write color\n");

	mutex_unlock(&rgb->tdev->lock);
}

static void thingm_led_set(struct led_classdev *ldev,
		enum led_brightness brightness)
{
	struct thingm_led *led = container_of(ldev, struct thingm_led, ldev);

	/* the ledclass has already stored the brightness value */
	schedule_work(&led->rgb->work);
}

static int thingm_init_rgb(struct thingm_rgb *rgb)
{
	const int minor = ((struct hidraw *) rgb->tdev->hdev->hidraw)->minor;
	int err;

	/* Register the red diode */
	snprintf(rgb->red.name, sizeof(rgb->red.name),
			"thingm%d:red:led%d", minor, rgb->num);
	rgb->red.ldev.name = rgb->red.name;
	rgb->red.ldev.max_brightness = 255;
	rgb->red.ldev.brightness_set = thingm_led_set;
	rgb->red.rgb = rgb;

	err = led_classdev_register(&rgb->tdev->hdev->dev, &rgb->red.ldev);
	if (err)
		return err;

	/* Register the green diode */
	snprintf(rgb->green.name, sizeof(rgb->green.name),
			"thingm%d:green:led%d", minor, rgb->num);
	rgb->green.ldev.name = rgb->green.name;
	rgb->green.ldev.max_brightness = 255;
	rgb->green.ldev.brightness_set = thingm_led_set;
	rgb->green.rgb = rgb;

	err = led_classdev_register(&rgb->tdev->hdev->dev, &rgb->green.ldev);
	if (err)
		goto unregister_red;

	/* Register the blue diode */
	snprintf(rgb->blue.name, sizeof(rgb->blue.name),
			"thingm%d:blue:led%d", minor, rgb->num);
	rgb->blue.ldev.name = rgb->blue.name;
	rgb->blue.ldev.max_brightness = 255;
	rgb->blue.ldev.brightness_set = thingm_led_set;
	rgb->blue.rgb = rgb;

	err = led_classdev_register(&rgb->tdev->hdev->dev, &rgb->blue.ldev);
	if (err)
		goto unregister_green;

	INIT_WORK(&rgb->work, thingm_work);

	return 0;

unregister_green:
	led_classdev_unregister(&rgb->green.ldev);

unregister_red:
	led_classdev_unregister(&rgb->red.ldev);

	return err;
}

static void thingm_remove_rgb(struct thingm_rgb *rgb)
{
	flush_work(&rgb->work);
	led_classdev_unregister(&rgb->red.ldev);
	led_classdev_unregister(&rgb->green.ldev);
	led_classdev_unregister(&rgb->blue.ldev);
}

static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
	struct thingm_device *tdev;
	int i, err;

	tdev = devm_kzalloc(&hdev->dev, sizeof(struct thingm_device),
			GFP_KERNEL);
	if (!tdev)
		return -ENOMEM;

	tdev->hdev = hdev;
	hid_set_drvdata(hdev, tdev);

	err = hid_parse(hdev);
	if (err)
		goto error;

	err = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
	if (err)
		goto error;

	mutex_init(&tdev->lock);

	err = thingm_version(tdev);
	if (err)
		goto stop;

	hid_dbg(hdev, "firmware version: %c.%c\n",
			tdev->version.major, tdev->version.minor);

	for (i = 0; i < ARRAY_SIZE(thingm_fwinfo) && !tdev->fwinfo; ++i)
		if (thingm_fwinfo[i].major == tdev->version.major)
			tdev->fwinfo = &thingm_fwinfo[i];

	if (!tdev->fwinfo) {
		hid_err(hdev, "unsupported firmware %c\n", tdev->version.major);
		goto stop;
	}

	tdev->rgb = devm_kzalloc(&hdev->dev,
			sizeof(struct thingm_rgb) * tdev->fwinfo->numrgb,
			GFP_KERNEL);
	if (!tdev->rgb) {
		err = -ENOMEM;
		goto stop;
	}

	for (i = 0; i < tdev->fwinfo->numrgb; ++i) {
		struct thingm_rgb *rgb = tdev->rgb + i;

		rgb->tdev = tdev;
		rgb->num = tdev->fwinfo->first + i;
		err = thingm_init_rgb(rgb);
		if (err) {
			while (--i >= 0)
				thingm_remove_rgb(tdev->rgb + i);
			goto stop;
		}
	}

	return 0;
stop:
	hid_hw_stop(hdev);
error:
	return err;
}

static void thingm_remove(struct hid_device *hdev)
{
	struct thingm_device *tdev = hid_get_drvdata(hdev);
	int i;

	for (i = 0; i < tdev->fwinfo->numrgb; ++i)
		thingm_remove_rgb(tdev->rgb + i);

	hid_hw_stop(hdev);
}

static const struct hid_device_id thingm_table[] = {
	{ HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) },
	{ }
};
MODULE_DEVICE_TABLE(hid, thingm_table);

static struct hid_driver thingm_driver = {
	.name = "thingm",
	.probe = thingm_probe,
	.remove = thingm_remove,
	.id_table = thingm_table,
};

module_hid_driver(thingm_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Vivien Didelot <vivien.didelot@savoirfairelinux.com>");
MODULE_DESCRIPTION("ThingM blink(1) USB RGB LED driver");
