/*
 * CAIF USB handler
 * Copyright (C) ST-Ericsson AB 2011
 * Author:	Sjur Brendeland
 * License terms: GNU General Public License (GPL) version 2
 *
 */

#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__

#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/slab.h>
#include <linux/mii.h>
#include <linux/usb.h>
#include <linux/usb/usbnet.h>
#include <linux/etherdevice.h>
#include <net/netns/generic.h>
#include <net/caif/caif_dev.h>
#include <net/caif/caif_layer.h>
#include <net/caif/cfpkt.h>
#include <net/caif/cfcnfg.h>

MODULE_LICENSE("GPL");

#define CFUSB_PAD_DESCR_SZ 1	/* Alignment descriptor length */
#define CFUSB_ALIGNMENT 4	/* Number of bytes to align. */
#define CFUSB_MAX_HEADLEN (CFUSB_PAD_DESCR_SZ + CFUSB_ALIGNMENT-1)
#define STE_USB_VID 0x04cc	/* USB Product ID for ST-Ericsson */
#define STE_USB_PID_CAIF 0x230f	/* Product id for CAIF Modems */

struct cfusbl {
	struct cflayer layer;
	u8 tx_eth_hdr[ETH_HLEN];
};

static bool pack_added;

static int cfusbl_receive(struct cflayer *layr, struct cfpkt *pkt)
{
	u8 hpad;

	/* Remove padding. */
	cfpkt_extr_head(pkt, &hpad, 1);
	cfpkt_extr_head(pkt, NULL, hpad);
	return layr->up->receive(layr->up, pkt);
}

static int cfusbl_transmit(struct cflayer *layr, struct cfpkt *pkt)
{
	struct caif_payload_info *info;
	u8 hpad;
	u8 zeros[CFUSB_ALIGNMENT];
	struct sk_buff *skb;
	struct cfusbl *usbl = container_of(layr, struct cfusbl, layer);

	skb = cfpkt_tonative(pkt);

	skb_reset_network_header(skb);
	skb->protocol = htons(ETH_P_IP);

	info = cfpkt_info(pkt);
	hpad = (info->hdr_len + CFUSB_PAD_DESCR_SZ) & (CFUSB_ALIGNMENT - 1);

	if (skb_headroom(skb) < ETH_HLEN + CFUSB_PAD_DESCR_SZ + hpad) {
		pr_warn("Headroom to small\n");
		kfree_skb(skb);
		return -EIO;
	}
	memset(zeros, 0, hpad);

	cfpkt_add_head(pkt, zeros, hpad);
	cfpkt_add_head(pkt, &hpad, 1);
	cfpkt_add_head(pkt, usbl->tx_eth_hdr, sizeof(usbl->tx_eth_hdr));
	return layr->dn->transmit(layr->dn, pkt);
}

static void cfusbl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
			   int phyid)
{
	if (layr->up && layr->up->ctrlcmd)
		layr->up->ctrlcmd(layr->up, ctrl, layr->id);
}

static struct cflayer *cfusbl_create(int phyid, u8 ethaddr[ETH_ALEN],
				      u8 braddr[ETH_ALEN])
{
	struct cfusbl *this = kmalloc(sizeof(struct cfusbl), GFP_ATOMIC);

	if (!this) {
		pr_warn("Out of memory\n");
		return NULL;
	}
	caif_assert(offsetof(struct cfusbl, layer) == 0);

	memset(this, 0, sizeof(struct cflayer));
	this->layer.receive = cfusbl_receive;
	this->layer.transmit = cfusbl_transmit;
	this->layer.ctrlcmd = cfusbl_ctrlcmd;
	snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "usb%d", phyid);
	this->layer.id = phyid;

	/*
	 * Construct TX ethernet header:
	 *	0-5	destination address
	 *	5-11	source address
	 *	12-13	protocol type
	 */
	ether_addr_copy(&this->tx_eth_hdr[ETH_ALEN], braddr);
	ether_addr_copy(&this->tx_eth_hdr[ETH_ALEN], ethaddr);
	this->tx_eth_hdr[12] = cpu_to_be16(ETH_P_802_EX1) & 0xff;
	this->tx_eth_hdr[13] = (cpu_to_be16(ETH_P_802_EX1) >> 8) & 0xff;
	pr_debug("caif ethernet TX-header dst:%pM src:%pM type:%02x%02x\n",
			this->tx_eth_hdr, this->tx_eth_hdr + ETH_ALEN,
			this->tx_eth_hdr[12], this->tx_eth_hdr[13]);

	return (struct cflayer *) this;
}

static struct packet_type caif_usb_type __read_mostly = {
	.type = cpu_to_be16(ETH_P_802_EX1),
};

static int cfusbl_device_notify(struct notifier_block *me, unsigned long what,
				void *ptr)
{
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
	struct caif_dev_common common;
	struct cflayer *layer, *link_support;
	struct usbnet *usbnet;
	struct usb_device *usbdev;

	/* Check whether we have a NCM device, and find its VID/PID. */
	if (!(dev->dev.parent && dev->dev.parent->driver &&
	      strcmp(dev->dev.parent->driver->name, "cdc_ncm") == 0))
		return 0;

	usbnet = netdev_priv(dev);
	usbdev = usbnet->udev;

	pr_debug("USB CDC NCM device VID:0x%4x PID:0x%4x\n",
		le16_to_cpu(usbdev->descriptor.idVendor),
		le16_to_cpu(usbdev->descriptor.idProduct));

	/* Check for VID/PID that supports CAIF */
	if (!(le16_to_cpu(usbdev->descriptor.idVendor) == STE_USB_VID &&
		le16_to_cpu(usbdev->descriptor.idProduct) == STE_USB_PID_CAIF))
		return 0;

	if (what == NETDEV_UNREGISTER)
		module_put(THIS_MODULE);

	if (what != NETDEV_REGISTER)
		return 0;

	__module_get(THIS_MODULE);

	memset(&common, 0, sizeof(common));
	common.use_frag = false;
	common.use_fcs = false;
	common.use_stx = false;
	common.link_select = CAIF_LINK_HIGH_BANDW;
	common.flowctrl = NULL;

	link_support = cfusbl_create(dev->ifindex, dev->dev_addr,
					dev->broadcast);

	if (!link_support)
		return -ENOMEM;

	if (dev->num_tx_queues > 1)
		pr_warn("USB device uses more than one tx queue\n");

	caif_enroll_dev(dev, &common, link_support, CFUSB_MAX_HEADLEN,
			&layer, &caif_usb_type.func);
	if (!pack_added)
		dev_add_pack(&caif_usb_type);
	pack_added = true;

	strncpy(layer->name, dev->name,
			sizeof(layer->name) - 1);
	layer->name[sizeof(layer->name) - 1] = 0;

	return 0;
}

static struct notifier_block caif_device_notifier = {
	.notifier_call = cfusbl_device_notify,
	.priority = 0,
};

static int __init cfusbl_init(void)
{
	return register_netdevice_notifier(&caif_device_notifier);
}

static void __exit cfusbl_exit(void)
{
	unregister_netdevice_notifier(&caif_device_notifier);
	dev_remove_pack(&caif_usb_type);
}

module_init(cfusbl_init);
module_exit(cfusbl_exit);
