/******************************************************************************
 *  cxacru.c  -  driver for USB ADSL modems based on
 *               Conexant AccessRunner chipset
 *
 *  Copyright (C) 2009 Simon Arlott
 *
 *  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.
 *
 ******************************************************************************/

/* raw command access
 *
 * use to:
 *   1. read flash
 *   2. write flash
 *
 * flash writes must have 60 bytes of data,
 * because the device will continue processing
 * that data and write it to flash until it is
 * complete
 */

static ssize_t cxacru_sysfs_store_raw(struct device *dev,
	struct device_attribute *attr, const char *buf, size_t count)
{
	struct cxacru_data *instance = to_usbatm_driver_data(\
		to_usb_interface(dev));
	int len = strlen(buf);
	int ret, pos, num;
	u8 cmd = 0x80;
	__le32 data[CMD_PACKET_SIZE / 4];
	u8 resp[256];

	if (!capable(CAP_NET_ADMIN))
		return -EACCES;

	if (instance == NULL)
		return -ENODEV;

	memset(resp, 0, sizeof(resp));

	pos = 0;
	num = -1;
	while (pos < len && num < 16) {
		int tmp;
		u32 value;

		printk(KERN_INFO "cxacru-raw: %d\n", pos);
		ret = sscanf(buf + pos, "%u%n", &value, &tmp);
		printk(KERN_INFO "cxacru-raw: %d (%u %d)\n", tmp, value, ret);
		if (ret < 1)
			return -EINVAL;
		pos += tmp;

		if (num == -1) {
			cmd = value;
			num++;
		} else {
			data[num++] = cpu_to_le32(value);
		}
	}

	printk(KERN_INFO "cxacru-out: (%d)", cmd);
	for (ret = 0; ret < num; ret++)
		printk(" %08x", le32_to_cpu(data[ret]));
	printk("\n");

	ret = cxacru_cm(instance, cmd, (u8 *) data, num * 4, resp, 256);
	atm_err(instance->usbatm, "cmd %d: %d\n", cmd, ret);
	printk(KERN_INFO "cxacru-in:");
	for (ret = 0; ret < 256; ret++) {
		printk(" %02x", resp[ret]);
		if ((ret + 1) % 64 == 0) {
			printk("\n");
			printk(KERN_INFO "cxacru-in:");
		}
	}
	printk("\n");
	return len;
}
