text:
#include <linux/list.h>
#include <linux/rwsem.h>

#include <asm/ebcdic.h>

#include "qeth.h"
#include "qeth_mpc.h"
#include "qeth_fs.h"

/*****************************************************************************/
/*                                                                           */
/*          /sys-fs stuff UNDER DEVELOPMENT !!!                              */
/*                                                                           */
/*****************************************************************************/
//low/high watermark

static ssize_t
qeth_dev_state_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;
	if (!card)
		return -EINVAL;

	switch (card->state) {
	case CARD_STATE_DOWN:
		return sprintf(buf, "DOWN\n");
	case CARD_STATE_HARDSETUP:
		return sprintf(buf, "HARDSETUP\n");
	case CARD_STATE_SOFTSETUP:
		return sprintf(buf, "SOFTSETUP\n");
	case CARD_STATE_UP:
		if (card->lan_online)
		return sprintf(buf, "UP (LAN ONLINE)\n");
		else
			return sprintf(buf, "UP (LAN OFFLINE)\n");
	case CARD_STATE_RECOVER:
		return sprintf(buf, "RECOVER\n");
	default:
		return sprintf(buf, "UNKNOWN\n");
	}
}

static DEVICE_ATTR(state, 0444, qeth_dev_state_show, NULL);

static ssize_t
qeth_dev_chpid_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;
	if (!card)
		return -EINVAL;

	return sprintf(buf, "%02X\n", card->info.chpid);
}

static DEVICE_ATTR(chpid, 0444, qeth_dev_chpid_show, NULL);

static ssize_t
qeth_dev_if_name_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;
	if (!card)
		return -EINVAL;
	return sprintf(buf, "%s\n", QETH_CARD_IFNAME(card));
}

static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL);

static ssize_t
qeth_dev_card_type_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;
	if (!card)
		return -EINVAL;

	return sprintf(buf, "%s\n", qeth_get_cardname_short(card));
}

static DEVICE_ATTR(card_type, 0444, qeth_dev_card_type_show, NULL);

static ssize_t
qeth_dev_portno_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;
	if (!card)
		return -EINVAL;

	return sprintf(buf, "%i\n", card->info.portno);
}

static ssize_t
qeth_dev_portno_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;
	char *tmp;
	unsigned int portno;

	if (!card)
		return -EINVAL;

	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER))
		return -EPERM;

	portno = simple_strtoul(buf, &tmp, 16);
	if ((portno < 0) || (portno > MAX_PORTNO)){
		PRINT_WARN("portno 0x%X is out of range\n", portno);
		return -EINVAL;
	}

	card->info.portno = portno;
	return count;
}

static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);

static ssize_t
qeth_dev_portname_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;
	char portname[9] = {0, };

	if (!card)
		return -EINVAL;

	if (card->info.portname_required) {
		memcpy(portname, card->info.portname + 1, 8);
		EBCASC(portname, 8);
		return sprintf(buf, "%s\n", portname);
	} else
		return sprintf(buf, "no portname required\n");
}

static ssize_t
qeth_dev_portname_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;
	char *tmp;
	int i;

	if (!card)
		return -EINVAL;

	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER))
		return -EPERM;

	tmp = strsep((char **) &buf, "\n");
	if ((strlen(tmp) > 8) || (strlen(tmp) == 0))
		return -EINVAL;

	card->info.portname[0] = strlen(tmp);
	/* for beauty reasons */
	for (i = 1; i < 9; i++)
		card->info.portname[i] = ' ';
	strcpy(card->info.portname + 1, tmp);
	ASCEBC(card->info.portname + 1, 8);

	return count;
}

static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
		qeth_dev_portname_store);

static ssize_t
qeth_dev_checksum_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return sprintf(buf, "%s checksumming\n", qeth_get_checksum_str(card));
}

static ssize_t
qeth_dev_checksum_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;
	char *tmp;

	if (!card)
		return -EINVAL;

	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER))
		return -EPERM;

	tmp = strsep((char **) &buf, "\n");
	if (!strcmp(tmp, "sw_checksumming"))
		card->options.checksum_type = SW_CHECKSUMMING;
	else if (!strcmp(tmp, "hw_checksumming"))
		card->options.checksum_type = HW_CHECKSUMMING;
	else if (!strcmp(tmp, "no_checksumming"))
		card->options.checksum_type = NO_CHECKSUMMING;
	else {
		PRINT_WARN("Unknown checksumming type '%s'\n", tmp);
		return -EINVAL;
	}
	return count;
}

static DEVICE_ATTR(checksumming, 0644, qeth_dev_checksum_show,
		qeth_dev_checksum_store);

static ssize_t
qeth_dev_prioqing_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	switch (card->qdio.do_prio_queueing) {
	case QETH_PRIO_Q_ING_PREC:
		return sprintf(buf, "%s\n", "by precedence");
	case QETH_PRIO_Q_ING_TOS:
		return sprintf(buf, "%s\n", "by type of service");
	default:
		return sprintf(buf, "always queue %i\n",
			       card->qdio.default_out_queue);
	}
}

static ssize_t
qeth_dev_prioqing_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;
	char *tmp;

	if (!card)
		return -EINVAL;

	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER))
		return -EPERM;

	/* check if 1920 devices are supported ,
	 * if though we have to permit priority queueing
	 */
	if (card->qdio.no_out_queues == 1) {
		PRINT_WARN("Priority queueing disabled due "
			   "to hardware limitations!\n");
		card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
		return -EPERM;
	}

	tmp = strsep((char **) &buf, "\n");
	if (!strcmp(tmp, "prio_queueing_prec"))
		card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_PREC;
	else if (!strcmp(tmp, "prio_queueing_tos"))
		card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_TOS;
	else if (!strcmp(tmp, "no_prio_queueing:0")) {
		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
		card->qdio.default_out_queue = 0;
	} else if (!strcmp(tmp, "no_prio_queueing:1")) {
		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
		card->qdio.default_out_queue = 1;
	} else if (!strcmp(tmp, "no_prio_queueing:2")) {
		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
		card->qdio.default_out_queue = 2;
	} else if (!strcmp(tmp, "no_prio_queueing:3")) {
		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
		card->qdio.default_out_queue = 3;
	} else if (!strcmp(tmp, "no_prio_queueing")) {
		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
		card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
	} else {
		PRINT_WARN("Unknown queueing type '%s'\n", tmp);
		return -EINVAL;
	}
	return count;
}

static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show,
		qeth_dev_prioqing_store);

static ssize_t
qeth_dev_bufcnt_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return sprintf(buf, "%i\n", card->qdio.in_buf_pool.buf_count);
}

static ssize_t
qeth_dev_bufcnt_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;
	char *tmp;
	int cnt, old_cnt;
	int rc;

	if (!card)
		return -EINVAL;

	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER))
		return -EPERM;

	old_cnt = card->qdio.in_buf_pool.buf_count;
	cnt = simple_strtoul(buf, &tmp, 10);
	cnt = (cnt < QETH_IN_BUF_COUNT_MIN) ? QETH_IN_BUF_COUNT_MIN :
		((cnt > QETH_IN_BUF_COUNT_MAX) ? QETH_IN_BUF_COUNT_MAX : cnt);
	if (old_cnt != cnt) {
		if ((rc = qeth_realloc_buffer_pool(card, cnt)))
			PRINT_WARN("Error (%d) while setting "
				   "buffer count.\n", rc);
	}
	return count;
}

static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
		qeth_dev_bufcnt_store);

static inline ssize_t
qeth_dev_route_show(struct qeth_card *card, struct qeth_routing_info *route,
		    char *buf)
{
	switch (route->type) {
	case PRIMARY_ROUTER:
		return sprintf(buf, "%s\n", "primary router");
	case SECONDARY_ROUTER:
		return sprintf(buf, "%s\n", "secondary router");
	case MULTICAST_ROUTER:
		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
			return sprintf(buf, "%s\n", "multicast router+");
		else
			return sprintf(buf, "%s\n", "multicast router");
	case PRIMARY_CONNECTOR:
		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
			return sprintf(buf, "%s\n", "primary connector+");
		else
			return sprintf(buf, "%s\n", "primary connector");
	case SECONDARY_CONNECTOR:
		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
			return sprintf(buf, "%s\n", "secondary connector+");
		else
			return sprintf(buf, "%s\n", "secondary connector");
	default:
		return sprintf(buf, "%s\n", "no");
	}
}

static ssize_t
qeth_dev_route4_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_route_show(card, &card->options.route4, buf);
}

static inline ssize_t
qeth_dev_route_store(struct qeth_card *card, struct qeth_routing_info *route,
		enum qeth_prot_versions prot, const char *buf, size_t count)
{
	enum qeth_routing_types old_route_type = route->type;
	char *tmp;
	int rc;

	tmp = strsep((char **) &buf, "\n");

	if (!strcmp(tmp, "no_router")){
		route->type = NO_ROUTER;
	} else if (!strcmp(tmp, "primary_connector")) {
		route->type = PRIMARY_CONNECTOR;
	} else if (!strcmp(tmp, "secondary_connector")) {
		route->type = SECONDARY_CONNECTOR;
	} else if (!strcmp(tmp, "multicast_router")) {
		route->type = MULTICAST_ROUTER;
	} else if (!strcmp(tmp, "primary_router")) {
		route->type = PRIMARY_ROUTER;
	} else if (!strcmp(tmp, "secondary_router")) {
		route->type = SECONDARY_ROUTER;
	} else if (!strcmp(tmp, "multicast_router")) {
		route->type = MULTICAST_ROUTER;
	} else {
		PRINT_WARN("Invalid routing type '%s'.\n", tmp);
		return -EINVAL;
	}
	if (((card->state == CARD_STATE_SOFTSETUP) ||
	     (card->state == CARD_STATE_UP)) &&
	    (old_route_type != route->type)){
		if (prot == QETH_PROT_IPV4)
			rc = qeth_setrouting_v4(card);
		else if (prot == QETH_PROT_IPV6)
			rc = qeth_setrouting_v6(card);
	}
	return count;
}

static ssize_t
qeth_dev_route4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_route_store(card, &card->options.route4,
			            QETH_PROT_IPV4, buf, count);
}

static DEVICE_ATTR(route4, 0644, qeth_dev_route4_show, qeth_dev_route4_store);

#ifdef CONFIG_QETH_IPV6
static ssize_t
qeth_dev_route6_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	if (!qeth_is_supported(card, IPA_IPV6))
		return sprintf(buf, "%s\n", "n/a");

	return qeth_dev_route_show(card, &card->options.route6, buf);
}

static ssize_t
qeth_dev_route6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	if (!qeth_is_supported(card, IPA_IPV6)){
		PRINT_WARN("IPv6 not supported for interface %s.\n"
			   "Routing status no changed.\n",
			   QETH_CARD_IFNAME(card));
		return -ENOTSUPP;
	}

	return qeth_dev_route_store(card, &card->options.route6,
			            QETH_PROT_IPV6, buf, count);
}

static DEVICE_ATTR(route6, 0644, qeth_dev_route6_show, qeth_dev_route6_store);
#endif

static ssize_t
qeth_dev_add_hhlen_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return sprintf(buf, "%i\n", card->options.add_hhlen);
}

static ssize_t
qeth_dev_add_hhlen_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;
	char *tmp;
	int i;

	if (!card)
		return -EINVAL;

	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER))
		return -EPERM;

	i = simple_strtoul(buf, &tmp, 10);
	if ((i < 0) || (i > MAX_ADD_HHLEN)) {
		PRINT_WARN("add_hhlen out of range\n");
		return -EINVAL;
	}
	card->options.add_hhlen = i;

	return count;
}

static DEVICE_ATTR(add_hhlen, 0644, qeth_dev_add_hhlen_show,
		   qeth_dev_add_hhlen_store);

static ssize_t
qeth_dev_fake_ll_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return sprintf(buf, "%i\n", card->options.fake_ll? 1:0);
}

static ssize_t
qeth_dev_fake_ll_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;
	char *tmp;
	int i;

	if (!card)
		return -EINVAL;

	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER))
		return -EPERM;

	i = simple_strtoul(buf, &tmp, 16);
	if ((i != 0) && (i != 1)) {
		PRINT_WARN("fake_ll: write 0 or 1 to this file!\n");
		return -EINVAL;
	}
	card->options.fake_ll = i;
	return count;
}

static DEVICE_ATTR(fake_ll, 0644, qeth_dev_fake_ll_show,
		   qeth_dev_fake_ll_store);

static ssize_t
qeth_dev_fake_broadcast_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
}

static ssize_t
qeth_dev_fake_broadcast_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;
	char *tmp;
	int i;

	if (!card)
		return -EINVAL;

	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER))
		return -EPERM;

	i = simple_strtoul(buf, &tmp, 16);
	if ((i == 0) || (i == 1))
		card->options.fake_broadcast = i;
	else {
		PRINT_WARN("fake_broadcast: write 0 or 1 to this file!\n");
		return -EINVAL;
	}
	return count;
}

static DEVICE_ATTR(fake_broadcast, 0644, qeth_dev_fake_broadcast_show,
		   qeth_dev_fake_broadcast_store);

static ssize_t
qeth_dev_recover_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;
	char *tmp;
	int i;

	if (!card)
		return -EINVAL;

	if (card->state != CARD_STATE_UP)
		return -EPERM;

	i = simple_strtoul(buf, &tmp, 16);
	if (i == 1)
		qeth_schedule_recovery(card);

	return count;
}

static DEVICE_ATTR(recover, 0200, NULL, qeth_dev_recover_store);

static ssize_t
qeth_dev_broadcast_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
		return sprintf(buf, "n/a\n");

	return sprintf(buf, "%s\n", (card->options.broadcast_mode ==
				     QETH_TR_BROADCAST_ALLRINGS)?
		       "all rings":"local");
}

static ssize_t
qeth_dev_broadcast_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;
	char *tmp;

	if (!card)
		return -EINVAL;

	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER))
		return -EPERM;

	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR))){
		PRINT_WARN("Device is not a tokenring device!\n");
		return -EINVAL;
	}

	tmp = strsep((char **) &buf, "\n");

	if (!strcmp(tmp, "local")){
		card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL;
		return count;
	} else if (!strcmp(tmp, "all_rings")) {
		card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
		return count;
	} else {
		PRINT_WARN("broadcast_mode: invalid mode %s!\n",
			   tmp);
		return -EINVAL;
	}
	return count;
}

static DEVICE_ATTR(broadcast_mode, 0644, qeth_dev_broadcast_mode_show,
		   qeth_dev_broadcast_mode_store);

static ssize_t
qeth_dev_canonical_macaddr_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
		return sprintf(buf, "n/a\n");

	return sprintf(buf, "%i\n", (card->options.macaddr_mode ==
				     QETH_TR_MACADDR_CANONICAL)? 1:0);
}

static ssize_t
qeth_dev_canonical_macaddr_store(struct device *dev, struct device_attribute *attr, const char *buf,
				  size_t count)
{
	struct qeth_card *card = dev->driver_data;
	char *tmp;
	int i;

	if (!card)
		return -EINVAL;

	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER))
		return -EPERM;

	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR))){
		PRINT_WARN("Device is not a tokenring device!\n");
		return -EINVAL;
	}

	i = simple_strtoul(buf, &tmp, 16);
	if ((i == 0) || (i == 1))
		card->options.macaddr_mode = i?
			QETH_TR_MACADDR_CANONICAL :
			QETH_TR_MACADDR_NONCANONICAL;
	else {
		PRINT_WARN("canonical_macaddr: write 0 or 1 to this file!\n");
		return -EINVAL;
	}
	return count;
}

static DEVICE_ATTR(canonical_macaddr, 0644, qeth_dev_canonical_macaddr_show,
		   qeth_dev_canonical_macaddr_store);

static ssize_t
qeth_dev_layer2_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return sprintf(buf, "%i\n", card->options.layer2 ? 1:0);
}

static ssize_t
qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;
	char *tmp;
	int i;

	if (!card)
		return -EINVAL;
	if (card->info.type == QETH_CARD_TYPE_IQD) {
                PRINT_WARN("Layer2 on Hipersockets is not supported! \n");
                return -EPERM;
        }

	if (((card->state != CARD_STATE_DOWN) &&
	     (card->state != CARD_STATE_RECOVER)))
		return -EPERM;

	i = simple_strtoul(buf, &tmp, 16);
	if ((i == 0) || (i == 1))
		card->options.layer2 = i;
	else {
		PRINT_WARN("layer2: write 0 or 1 to this file!\n");
		return -EINVAL;
	}
	return count;
}

static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
		   qeth_dev_layer2_store);

static ssize_t
qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	switch (card->options.large_send) {
	case QETH_LARGE_SEND_NO:
		return sprintf(buf, "%s\n", "no");
	case QETH_LARGE_SEND_EDDP:
		return sprintf(buf, "%s\n", "EDDP");
	case QETH_LARGE_SEND_TSO:
		return sprintf(buf, "%s\n", "TSO");
	default:
		return sprintf(buf, "%s\n", "N/A");
	}
}

static ssize_t
qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;
	enum qeth_large_send_types type;
	int rc = 0;
	char *tmp;

	if (!card)
		return -EINVAL;
	tmp = strsep((char **) &buf, "\n");
	if (!strcmp(tmp, "no")){
		type = QETH_LARGE_SEND_NO;
	} else if (!strcmp(tmp, "EDDP")) {
		type = QETH_LARGE_SEND_EDDP;
	} else if (!strcmp(tmp, "TSO")) {
		type = QETH_LARGE_SEND_TSO;
	} else {
		PRINT_WARN("large_send: invalid mode %s!\n", tmp);
		return -EINVAL;
	}
	if (card->options.large_send == type)
		return count;
	if ((rc = qeth_set_large_send(card, type)))
		return rc;
	return count;
}

static DEVICE_ATTR(large_send, 0644, qeth_dev_large_send_show,
		   qeth_dev_large_send_store);

static ssize_t
qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value )
{

	if (!card)
		return -EINVAL;

	return sprintf(buf, "%i\n", value);
}

static ssize_t
qeth_dev_blkt_store(struct qeth_card *card, const char *buf, size_t count,
			  int *value, int max_value)
{
	char *tmp;
	int i;

	if (!card)
		return -EINVAL;

	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER))
		return -EPERM;

	i = simple_strtoul(buf, &tmp, 10);
	if (i <= max_value) {
		*value = i;
	} else {
		PRINT_WARN("blkt total time: write values between"
			   " 0 and %d to this file!\n", max_value);
		return -EINVAL;
	}
	return count;
}

static ssize_t
qeth_dev_blkt_total_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	return qeth_dev_blkt_show(buf, card, card->info.blkt.time_total);
}

static ssize_t
qeth_dev_blkt_total_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	return qeth_dev_blkt_store(card, buf, count,
				   &card->info.blkt.time_total,1000);
}

static DEVICE_ATTR(total, 0644, qeth_dev_blkt_total_show,
		   qeth_dev_blkt_total_store);

static ssize_t
qeth_dev_blkt_inter_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	return qeth_dev_blkt_show(buf, card, card->info.blkt.inter_packet);
}

static ssize_t
qeth_dev_blkt_inter_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	return qeth_dev_blkt_store(card, buf, count,
				   &card->info.blkt.inter_packet,100);
}

static DEVICE_ATTR(inter, 0644, qeth_dev_blkt_inter_show,
		   qeth_dev_blkt_inter_store);

static ssize_t
qeth_dev_blkt_inter_jumbo_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	return qeth_dev_blkt_show(buf, card,
				  card->info.blkt.inter_packet_jumbo);
}

static ssize_t
qeth_dev_blkt_inter_jumbo_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	return qeth_dev_blkt_store(card, buf, count,
				   &card->info.blkt.inter_packet_jumbo,100);
}

static DEVICE_ATTR(inter_jumbo, 0644, qeth_dev_blkt_inter_jumbo_show,
		   qeth_dev_blkt_inter_jumbo_store);

static struct device_attribute * qeth_blkt_device_attrs[] = {
	&dev_attr_total,
	&dev_attr_inter,
	&dev_attr_inter_jumbo,
	NULL,
};

static struct attribute_group qeth_device_blkt_group = {
	.name = "blkt",
	.attrs = (struct attribute **)qeth_blkt_device_attrs,
};

static struct device_attribute * qeth_device_attrs[] = {
	&dev_attr_state,
	&dev_attr_chpid,
	&dev_attr_if_name,
	&dev_attr_card_type,
	&dev_attr_portno,
	&dev_attr_portname,
	&dev_attr_checksumming,
	&dev_attr_priority_queueing,
	&dev_attr_buffer_count,
	&dev_attr_route4,
#ifdef CONFIG_QETH_IPV6
	&dev_attr_route6,
#endif
	&dev_attr_add_hhlen,
	&dev_attr_fake_ll,
	&dev_attr_fake_broadcast,
	&dev_attr_recover,
	&dev_attr_broadcast_mode,
	&dev_attr_canonical_macaddr,
	&dev_attr_layer2,
	&dev_attr_large_send,
	NULL,
};

static struct attribute_group qeth_device_attr_group = {
	.attrs = (struct attribute **)qeth_device_attrs,
};

static struct device_attribute * qeth_osn_device_attrs[] = {
	&dev_attr_state,
	&dev_attr_chpid,
	&dev_attr_if_name,
	&dev_attr_card_type,
	&dev_attr_buffer_count,
	&dev_attr_recover,
	NULL,
};

static struct attribute_group qeth_osn_device_attr_group = {
	.attrs = (struct attribute **)qeth_osn_device_attrs,
};

#define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store)			     \
struct device_attribute dev_attr_##_id = {				     \
	.attr = {.name=__stringify(_name), .mode=_mode, .owner=THIS_MODULE },\
	.show	= _show,						     \
	.store	= _store,						     \
};

int
qeth_check_layer2(struct qeth_card *card)
{
	if (card->options.layer2)
		return -EPERM;
	return 0;
}

static ssize_t
qeth_dev_ipato_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	if (qeth_check_layer2(card))
		return -EPERM;
	return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
}

static ssize_t
qeth_dev_ipato_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;
	char *tmp;

	if (!card)
		return -EINVAL;

	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER))
		return -EPERM;

	if (qeth_check_layer2(card))
		return -EPERM;

	tmp = strsep((char **) &buf, "\n");
	if (!strcmp(tmp, "toggle")){
		card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
	} else if (!strcmp(tmp, "1")){
		card->ipato.enabled = 1;
	} else if (!strcmp(tmp, "0")){
		card->ipato.enabled = 0;
	} else {
		PRINT_WARN("ipato_enable: write 0, 1 or 'toggle' to "
			   "this file\n");
		return -EINVAL;
	}
	return count;
}

static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
			qeth_dev_ipato_enable_show,
			qeth_dev_ipato_enable_store);

static ssize_t
qeth_dev_ipato_invert4_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	if (qeth_check_layer2(card))
		return -EPERM;

	return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
}

static ssize_t
qeth_dev_ipato_invert4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;
	char *tmp;

	if (!card)
		return -EINVAL;

	if (qeth_check_layer2(card))
		return -EPERM;

	tmp = strsep((char **) &buf, "\n");
	if (!strcmp(tmp, "toggle")){
		card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
	} else if (!strcmp(tmp, "1")){
		card->ipato.invert4 = 1;
	} else if (!strcmp(tmp, "0")){
		card->ipato.invert4 = 0;
	} else {
		PRINT_WARN("ipato_invert4: write 0, 1 or 'toggle' to "
			   "this file\n");
		return -EINVAL;
	}
	return count;
}

static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
			qeth_dev_ipato_invert4_show,
			qeth_dev_ipato_invert4_store);

static inline ssize_t
qeth_dev_ipato_add_show(char *buf, struct qeth_card *card,
			enum qeth_prot_versions proto)
{
	struct qeth_ipato_entry *ipatoe;
	unsigned long flags;
	char addr_str[40];
	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
	int i = 0;

	if (qeth_check_layer2(card))
		return -EPERM;

	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
	/* add strlen for "/<mask>\n" */
	entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
	spin_lock_irqsave(&card->ip_lock, flags);
	list_for_each_entry(ipatoe, &card->ipato.entries, entry){
		if (ipatoe->proto != proto)
			continue;
		/* String must not be longer than PAGE_SIZE. So we check if
		 * string length gets near PAGE_SIZE. Then we can savely display
		 * the next IPv6 address (worst case, compared to IPv4) */
		if ((PAGE_SIZE - i) <= entry_len)
			break;
		qeth_ipaddr_to_string(proto, ipatoe->addr, addr_str);
		i += snprintf(buf + i, PAGE_SIZE - i,
			      "%s/%i\n", addr_str, ipatoe->mask_bits);
	}
	spin_unlock_irqrestore(&card->ip_lock, flags);
	i += snprintf(buf + i, PAGE_SIZE - i, "\n");

	return i;
}

static ssize_t
qeth_dev_ipato_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
}

static inline int
qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto,
		  u8 *addr, int *mask_bits)
{
	const char *start, *end;
	char *tmp;
	char buffer[49] = {0, };

	start = buf;
	/* get address string */
	end = strchr(start, '/');
	if (!end || (end-start >= 49)){
		PRINT_WARN("Invalid format for ipato_addx/delx. "
			   "Use <ip addr>/<mask bits>\n");
		return -EINVAL;
	}
	strncpy(buffer, start, end - start);
	if (qeth_string_to_ipaddr(buffer, proto, addr)){
		PRINT_WARN("Invalid IP address format!\n");
		return -EINVAL;
	}
	start = end + 1;
	*mask_bits = simple_strtoul(start, &tmp, 10);

	return 0;
}

static inline ssize_t
qeth_dev_ipato_add_store(const char *buf, size_t count,
			 struct qeth_card *card, enum qeth_prot_versions proto)
{
	struct qeth_ipato_entry *ipatoe;
	u8 addr[16];
	int mask_bits;
	int rc;

	if (qeth_check_layer2(card))
		return -EPERM;
	if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits)))
		return rc;

	if (!(ipatoe = kmalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL))){
		PRINT_WARN("No memory to allocate ipato entry\n");
		return -ENOMEM;
	}
	memset(ipatoe, 0, sizeof(struct qeth_ipato_entry));
	ipatoe->proto = proto;
	memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
	ipatoe->mask_bits = mask_bits;

	if ((rc = qeth_add_ipato_entry(card, ipatoe))){
		kfree(ipatoe);
		return rc;
	}

	return count;
}

static ssize_t
qeth_dev_ipato_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
}

static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
			qeth_dev_ipato_add4_show,
			qeth_dev_ipato_add4_store);

static inline ssize_t
qeth_dev_ipato_del_store(const char *buf, size_t count,
			 struct qeth_card *card, enum qeth_prot_versions proto)
{
	u8 addr[16];
	int mask_bits;
	int rc;

	if (qeth_check_layer2(card))
		return -EPERM;
	if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits)))
		return rc;

	qeth_del_ipato_entry(card, proto, addr, mask_bits);

	return count;
}

static ssize_t
qeth_dev_ipato_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
}

static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
			qeth_dev_ipato_del4_store);

#ifdef CONFIG_QETH_IPV6
static ssize_t
qeth_dev_ipato_invert6_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	if (qeth_check_layer2(card))
		return -EPERM;

	return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
}

static ssize_t
qeth_dev_ipato_invert6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;
	char *tmp;

	if (!card)
		return -EINVAL;

	if (qeth_check_layer2(card))
		return -EPERM;

	tmp = strsep((char **) &buf, "\n");
	if (!strcmp(tmp, "toggle")){
		card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
	} else if (!strcmp(tmp, "1")){
		card->ipato.invert6 = 1;
	} else if (!strcmp(tmp, "0")){
		card->ipato.invert6 = 0;
	} else {
		PRINT_WARN("ipato_invert6: write 0, 1 or 'toggle' to "
			   "this file\n");
		return -EINVAL;
	}
	return count;
}

static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
			qeth_dev_ipato_invert6_show,
			qeth_dev_ipato_invert6_store);

static ssize_t
qeth_dev_ipato_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
}

static ssize_t
qeth_dev_ipato_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
}

static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
			qeth_dev_ipato_add6_show,
			qeth_dev_ipato_add6_store);

static ssize_t
qeth_dev_ipato_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
}

static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
			qeth_dev_ipato_del6_store);
#endif /* CONFIG_QETH_IPV6 */

static struct device_attribute * qeth_ipato_device_attrs[] = {
	&dev_attr_ipato_enable,
	&dev_attr_ipato_invert4,
	&dev_attr_ipato_add4,
	&dev_attr_ipato_del4,
#ifdef CONFIG_QETH_IPV6
	&dev_attr_ipato_invert6,
	&dev_attr_ipato_add6,
	&dev_attr_ipato_del6,
#endif
	NULL,
};

static struct attribute_group qeth_device_ipato_group = {
	.name = "ipa_takeover",
	.attrs = (struct attribute **)qeth_ipato_device_attrs,
};

static inline ssize_t
qeth_dev_vipa_add_show(char *buf, struct qeth_card *card,
			enum qeth_prot_versions proto)
{
	struct qeth_ipaddr *ipaddr;
	char addr_str[40];
	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
	unsigned long flags;
	int i = 0;

	if (qeth_check_layer2(card))
		return -EPERM;

	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
	entry_len += 2; /* \n + terminator */
	spin_lock_irqsave(&card->ip_lock, flags);
	list_for_each_entry(ipaddr, &card->ip_list, entry){
		if (ipaddr->proto != proto)
			continue;
		if (ipaddr->type != QETH_IP_TYPE_VIPA)
			continue;
		/* String must not be longer than PAGE_SIZE. So we check if
		 * string length gets near PAGE_SIZE. Then we can savely display
		 * the next IPv6 address (worst case, compared to IPv4) */
		if ((PAGE_SIZE - i) <= entry_len)
			break;
		qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str);
		i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
	}
	spin_unlock_irqrestore(&card->ip_lock, flags);
	i += snprintf(buf + i, PAGE_SIZE - i, "\n");

	return i;
}

static ssize_t
qeth_dev_vipa_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
}

static inline int
qeth_parse_vipae(const char* buf, enum qeth_prot_versions proto,
		 u8 *addr)
{
	if (qeth_string_to_ipaddr(buf, proto, addr)){
		PRINT_WARN("Invalid IP address format!\n");
		return -EINVAL;
	}
	return 0;
}

static inline ssize_t
qeth_dev_vipa_add_store(const char *buf, size_t count,
			 struct qeth_card *card, enum qeth_prot_versions proto)
{
	u8 addr[16] = {0, };
	int rc;

	if (qeth_check_layer2(card))
		return -EPERM;
	if ((rc = qeth_parse_vipae(buf, proto, addr)))
		return rc;

	if ((rc = qeth_add_vipa(card, proto, addr)))
		return rc;

	return count;
}

static ssize_t
qeth_dev_vipa_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
}

static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
			qeth_dev_vipa_add4_show,
			qeth_dev_vipa_add4_store);

static inline ssize_t
qeth_dev_vipa_del_store(const char *buf, size_t count,
			 struct qeth_card *card, enum qeth_prot_versions proto)
{
	u8 addr[16];
	int rc;

	if (qeth_check_layer2(card))
		return -EPERM;
	if ((rc = qeth_parse_vipae(buf, proto, addr)))
		return rc;

	qeth_del_vipa(card, proto, addr);

	return count;
}

static ssize_t
qeth_dev_vipa_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
}

static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
			qeth_dev_vipa_del4_store);

#ifdef CONFIG_QETH_IPV6
static ssize_t
qeth_dev_vipa_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
}

static ssize_t
qeth_dev_vipa_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
}

static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
			qeth_dev_vipa_add6_show,
			qeth_dev_vipa_add6_store);

static ssize_t
qeth_dev_vipa_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	if (qeth_check_layer2(card))
		return -EPERM;

	return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
}

static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
			qeth_dev_vipa_del6_store);
#endif /* CONFIG_QETH_IPV6 */

static struct device_attribute * qeth_vipa_device_attrs[] = {
	&dev_attr_vipa_add4,
	&dev_attr_vipa_del4,
#ifdef CONFIG_QETH_IPV6
	&dev_attr_vipa_add6,
	&dev_attr_vipa_del6,
#endif
	NULL,
};

static struct attribute_group qeth_device_vipa_group = {
	.name = "vipa",
	.attrs = (struct attribute **)qeth_vipa_device_attrs,
};

static inline ssize_t
qeth_dev_rxip_add_show(char *buf, struct qeth_card *card,
		       enum qeth_prot_versions proto)
{
	struct qeth_ipaddr *ipaddr;
	char addr_str[40];
	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
	unsigned long flags;
	int i = 0;

	if (qeth_check_layer2(card))
		return -EPERM;

	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
	entry_len += 2; /* \n + terminator */
	spin_lock_irqsave(&card->ip_lock, flags);
	list_for_each_entry(ipaddr, &card->ip_list, entry){
		if (ipaddr->proto != proto)
			continue;
		if (ipaddr->type != QETH_IP_TYPE_RXIP)
			continue;
		/* String must not be longer than PAGE_SIZE. So we check if
		 * string length gets near PAGE_SIZE. Then we can savely display
		 * the next IPv6 address (worst case, compared to IPv4) */
		if ((PAGE_SIZE - i) <= entry_len)
			break;
		qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str);
		i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
	}
	spin_unlock_irqrestore(&card->ip_lock, flags);
	i += snprintf(buf + i, PAGE_SIZE - i, "\n");

	return i;
}

static ssize_t
qeth_dev_rxip_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
}

static inline int
qeth_parse_rxipe(const char* buf, enum qeth_prot_versions proto,
		 u8 *addr)
{
	if (qeth_string_to_ipaddr(buf, proto, addr)){
		PRINT_WARN("Invalid IP address format!\n");
		return -EINVAL;
	}
	return 0;
}

static inline ssize_t
qeth_dev_rxip_add_store(const char *buf, size_t count,
			struct qeth_card *card, enum qeth_prot_versions proto)
{
	u8 addr[16] = {0, };
	int rc;

	if (qeth_check_layer2(card))
		return -EPERM;
	if ((rc = qeth_parse_rxipe(buf, proto, addr)))
		return rc;

	if ((rc = qeth_add_rxip(card, proto, addr)))
		return rc;

	return count;
}

static ssize_t
qeth_dev_rxip_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
}

static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
			qeth_dev_rxip_add4_show,
			qeth_dev_rxip_add4_store);

static inline ssize_t
qeth_dev_rxip_del_store(const char *buf, size_t count,
			struct qeth_card *card, enum qeth_prot_versions proto)
{
	u8 addr[16];
	int rc;

	if (qeth_check_layer2(card))
		return -EPERM;
	if ((rc = qeth_parse_rxipe(buf, proto, addr)))
		return rc;

	qeth_del_rxip(card, proto, addr);

	return count;
}

static ssize_t
qeth_dev_rxip_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
}

static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
			qeth_dev_rxip_del4_store);

#ifdef CONFIG_QETH_IPV6
static ssize_t
qeth_dev_rxip_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
}

static ssize_t
qeth_dev_rxip_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
}

static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
			qeth_dev_rxip_add6_show,
			qeth_dev_rxip_add6_store);

static ssize_t
qeth_dev_rxip_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct qeth_card *card = dev->driver_data;

	if (!card)
		return -EINVAL;

	return qeth_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
}

static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
			qeth_dev_rxip_del6_store);
#endif /* CONFIG_QETH_IPV6 */

static struct device_attribute * qeth_rxip_device_attrs[] = {
	&dev_attr_rxip_add4,
	&dev_attr_rxip_del4,
#ifdef CONFIG_QETH_IPV6
	&dev_attr_rxip_add6,
	&dev_attr_rxip_del6,
#endif
	NULL,
};

static struct attribute_group qeth_device_rxip_group = {
	.name = "rxip",
	.attrs = (struct attribute **)qeth_rxip_device_attrs,
};

int
qeth_create_device_attributes(struct device *dev)
{
	int ret;
	struct qeth_card *card = dev->driver_data;

	if (card->info.type == QETH_CARD_TYPE_OSN)
		return sysfs_create_group(&dev->kobj,
					  &qeth_osn_device_attr_group);

	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group)))
		return ret;
	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group))){
		sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
		return ret;
	}
	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_vipa_group))){
		sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
		sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
		return ret;
	}
	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_rxip_group))){
		sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
		sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
		sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
	}
	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group)))
		return ret;

	return ret;
}

void
qeth_remove_device_attributes(struct device *dev)
{
	struct qeth_card *card = dev->driver_data;

	if (card->info.type == QETH_CARD_TYPE_OSN)
		return sysfs_remove_group(&dev->kobj,
					  &qeth_osn_device_attr_group);

	sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
	sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
	sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
	sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
	sysfs_remove_group(&dev->kobj, &qeth_device_blkt_group);
}

/**********************/
/* DRIVER ATTRIBUTES  */
/**********************/
static ssize_t
qeth_driver_group_store(struct device_driver *ddrv, const char *buf,
			size_t count)
{
	const char *start, *end;
	char bus_ids[3][BUS_ID_SIZE], *argv[3];
	int i;
	int err;

	start = buf;
	for (i = 0; i < 3; i++) {
		static const char delim[] = { ',', ',', '\n' };
		int len;

		if (!(end = strchr(start, delim[i])))
			return -EINVAL;
		len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start);
		strncpy(bus_ids[i], start, len);
		bus_ids[i][len] = '\0';
		start = end + 1;
		argv[i] = bus_ids[i];
	}
	err = ccwgroup_create(qeth_root_dev, qeth_ccwgroup_driver.driver_id,
			&qeth_ccw_driver, 3, argv);
	if (err)
		return err;
	else
		return count;
}

static DRIVER_ATTR(group, 0200, 0, qeth_driver_group_store);

static ssize_t
qeth_driver_notifier_register_store(struct device_driver *ddrv, const char *buf,
				size_t count)
{
	int rc;
	int signum;
	char *tmp, *tmp2;

	tmp = strsep((char **) &buf, "\n");
	if (!strncmp(tmp, "unregister", 10)){
		if ((rc = qeth_notifier_unregister(current)))
			return rc;
		return count;
	}

	signum = simple_strtoul(tmp, &tmp2, 10);
	if ((signum < 0) || (signum > 32)){
		PRINT_WARN("Signal number %d is out of range\n", signum);
		return -EINVAL;
	}
	if ((rc = qeth_notifier_register(current, signum)))
		return rc;

	return count;
}

static DRIVER_ATTR(notifier_register, 0200, 0,
		   qeth_driver_notifier_register_store);

int
qeth_create_driver_attributes(void)
{
	int rc;

	if ((rc = driver_create_file(&qeth_ccwgroup_driver.driver,
				     &driver_attr_group)))
		return rc;
	return driver_create_file(&qeth_ccwgroup_driver.driver,
				  &driver_attr_notifier_register);
}

void
qeth_remove_driver_attributes(void)
{
	driver_remove_file(&qeth_ccwgroup_driver.driver,
			&driver_attr_group);
	driver_remove_file(&qeth_ccwgroup_driver.driver,
			&driver_attr_notifier_register);
}


text:
/**
 * @author Pedro Sanders
 * @since v1
 */
import Processor from 'core/processor/processor'
import ContextStorage from 'core/context_storage'
import Registry from 'registry/registry'
import RestService from 'rest/rest'
import getConfig from 'core/config_util.js'

const SipFactory = Packages.javax.sip.SipFactory
const Properties = Packages.java.util.Properties
const LogManager = Packages.org.apache.logging.log4j.LogManager
const LOG = LogManager.getLogger()
const ANSI_GREEN = "\u001B[32m"
const ANSI_YELLOW = "\u001B[33m"
const ANSI_RESET = "\u001B[0m"

export default class Server {

    constructor(locator, registrar, dataAPIs) {
        this.locator = locator
        this.registrar = registrar
        this.dataAPIs = dataAPIs
        this.contextStorage = new ContextStorage()
        this.config = getConfig()
        // Not sure if this is a good idea in terms of performance
        this.host = this.config.spec.bindAddr
    }

    buildSipProvider(transport) {
        const defListeningPoint = this.sipStack.createListeningPoint(transport[0].port, transport[0].protocol.toLowerCase())
        const sipProvider = this.sipStack.createSipProvider(defListeningPoint)

        for (const key in transport) {
            const curTransport = transport[key]
            const proto = curTransport.protocol.toLowerCase()

            if ((proto == 'wss' || proto == 'tls') && !this.config.spec.securityContext) {
                LOG.warn(ANSI_YELLOW + 'Security context could not found. Ignoring protocol: ' + proto + ANSI_RESET)
                continue;
            }

            if (curTransport.bindAddr == undefined) {
                curTransport.bindAddr = this.host
            }

            const lp = this.sipStack.createListeningPoint(curTransport.bindAddr, curTransport.port, proto)
            sipProvider.addListeningPoint(lp)

            LOG.info('Listening  on ' + ANSI_GREEN  + curTransport.bindAddr
                + ':' + curTransport.port
                    + ' [' + proto + ']'
                        + ANSI_RESET)
        }

        return sipProvider
    }

    showExternInfo() {
        if (this.config.spec.externAddr) {
            LOG.info("ExternAddr is " + ANSI_GREEN  + this.config.spec.externAddr + ANSI_RESET)

            if(this.config.spec.localnets) {
                LOG.info("Localnets  is " + ANSI_GREEN  + this.config.spec.localnets.join(",") + ANSI_RESET)
            }
        }
    }

    setup() {
        this.showExternInfo()

        if(this.config.spec.securityContext.debugging) {
            Packages.java.lang.System.setProperty('javax.net.debug', 'ssl')
        }

        const sipFactory = SipFactory.getInstance()
        sipFactory.setPathName('gov.nist')

        this.sipStack = sipFactory.createSipStack(this.getProperties())

        const sipProvider = this.buildSipProvider(this.config.spec.transport)

        this.registry = new Registry(sipProvider, this.dataAPIs)

        const processor = new Processor(sipProvider,
            this.locator,
                this.registry,
                    this.registrar, this.dataAPIs, this.contextStorage)

        sipProvider.addSipListener(processor.listener)
    }

    start()  {
        LOG.info('Starting Routr')
        this.setup()
        this.locator.start()
        this.registry.start()
        this.restService = new RestService(this, this.locator, this.registry, this.dataAPIs)
        this.restService.start()
        java.lang.Thread.sleep(java.lang.Long.MAX_VALUE)
    }

    stop() {
        LOG.info('Stopping server')
        this.restService.stop()
        this.sipStack.stop()
        this.locator.stop()
        exit(0)
    }

    getProperties() {
        const properties = new Properties()
        // See https://github.com/RestComm/jain-sip/blob/master/src/gov/nist/javax/sip/SipStackImpl.java for
        // many other options
        properties.setProperty('javax.sip.STACK_NAME', 'routr')
        // Default host
        properties.setProperty('javax.sip.IP_ADDRESS', this.host)
        properties.setProperty('javax.sip.AUTOMATIC_DIALOG_SUPPORT', 'OFF')
        // Guard against denial of service attack.
        properties.setProperty('gov.nist.javax.sip.MAX_MESSAGE_SIZE', '1048576')
        // Drop the client connection after we are done with the transaction.
        properties.setProperty('gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS', 'false')
        properties.setProperty('gov.nist.javax.sip.TRACE_LEVEL', this.config.spec.logging.traceLevel)
        properties.setProperty('gov.nist.javax.sip.MESSAGE_PROCESSOR_FACTORY', 'gov.nist.javax.sip.stack.NioMessageProcessorFactory')
        properties.setProperty('gov.nist.javax.sip.PATCH_SIP_WEBSOCKETS_HEADERS', 'false')

        // See https://groups.google.com/forum/#!topic/mobicents-public/U_c7aLAJ_MU for useful info
        if (this.config.spec.securityContext) {
            properties.setProperty('gov.nist.javax.sip.TLS_CLIENT_PROTOCOLS', this.config.spec.securityContext.client.protocols.join())
            // This must be set to 'Disabled' when using WSS
            properties.setProperty('gov.nist.javax.sip.TLS_CLIENT_AUTH_TYPE', this.config.spec.securityContext.client.authType)
            properties.setProperty('javax.net.ssl.keyStore', this.config.spec.securityContext.keyStore)
            properties.setProperty('javax.net.ssl.trustStore', this.config.spec.securityContext.trustStore)
            properties.setProperty('javax.net.ssl.keyStorePassword', this.config.spec.securityContext.keyStorePassword)
            properties.setProperty('javax.net.ssl.keyStoreType', this.config.spec.securityContext.keyStoreType)
        }
        return properties
    }

}

redpajama_set_name: RedPajamaGithub


text:
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Code generated by Microsoft (R) AutoRest Code Generator.

package com.azure.analytics.synapse.artifacts.models;

import com.azure.core.annotation.Fluent;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;

/** A copy activity Salesforce Marketing Cloud source. */
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonTypeName("SalesforceMarketingCloudSource")
@Fluent
public final class SalesforceMarketingCloudSource extends TabularSource {
    /*
     * A query to retrieve data from source. Type: string (or Expression with resultType string).
     */
    @JsonProperty(value = "query")
    private Object query;

    /**
     * Get the query property: A query to retrieve data from source. Type: string (or Expression with resultType
     * string).
     *
     * @return the query value.
     */
    public Object getQuery() {
        return this.query;
    }

    /**
     * Set the query property: A query to retrieve data from source. Type: string (or Expression with resultType
     * string).
     *
     * @param query the query value to set.
     * @return the SalesforceMarketingCloudSource object itself.
     */
    public SalesforceMarketingCloudSource setQuery(Object query) {
        this.query = query;
        return this;
    }

    /** {@inheritDoc} */
    @Override
    public SalesforceMarketingCloudSource setQueryTimeout(Object queryTimeout) {
        super.setQueryTimeout(queryTimeout);
        return this;
    }

    /** {@inheritDoc} */
    @Override
    public SalesforceMarketingCloudSource setAdditionalColumns(Object additionalColumns) {
        super.setAdditionalColumns(additionalColumns);
        return this;
    }

    /** {@inheritDoc} */
    @Override
    public SalesforceMarketingCloudSource setSourceRetryCount(Object sourceRetryCount) {
        super.setSourceRetryCount(sourceRetryCount);
        return this;
    }

    /** {@inheritDoc} */
    @Override
    public SalesforceMarketingCloudSource setSourceRetryWait(Object sourceRetryWait) {
        super.setSourceRetryWait(sourceRetryWait);
        return this;
    }

    /** {@inheritDoc} */
    @Override
    public SalesforceMarketingCloudSource setMaxConcurrentConnections(Object maxConcurrentConnections) {
        super.setMaxConcurrentConnections(maxConcurrentConnections);
        return this;
    }
}


text:
    dispatch_async(specQueue, ^{ code; })

#define VerifyAfter(timeout, mock)      \
    usleep(timeout), MKTVerify(mock)

@interface WLXCharacteristicObserver : NSObject

@property(nonatomic) NSData * data;
@property(nonatomic) NSError * error;

- (void)updatedValue:(NSData *)data error:(NSError *)error;

@end

@implementation WLXCharacteristicObserver

- (void)updatedValue:(NSData *)data error:(NSError *)error {
    self.data = data;
    self.error = error;
}

@end

SpecBegin(WLXServiceManager)

    __block id<WLXCharacteristicLocator> mockLocator;
    __block CBPeripheral * mockPeripheral;
    __block CBService * mockService;
    __block WLXCharacteristicAsyncExecutor * asyncExecutor;
    __block WLXServiceManager * serviceManager;
    __block NSNotificationCenter * notificationCenter;

    __block CBUUID * characteristicUUID;
    __block CBCharacteristic * mockCharacteristic;
    __block NSData * data;
    __block NSError * error;
    __block dispatch_queue_t specQueue;

    beforeEach(^{
        // DO NOT change this queue. It MUST be a serial queue, in order to guarantee that the tasks
        // are processed in the arrival order. This queue must be the dispatch queue used by the
        // async executor and every time we perform an operation that requires a characteristic UUID
        // and then we 'fake' a call to didXXXX method on the WLXServiceManager with MUST wrap that
        // with the ASYNC macro. That will assure that all the book keeping operation that are performed
        // async on the async executor are executed BEFORE any other operation triggered by the didXXX
        // methods. If not a determistic behavior for the spec is not guaranted.
        specQueue = dispatch_queue_create("ar.com.wolox.WLXBluetoothDevice.Specs", DISPATCH_QUEUE_SERIAL);
        characteristicUUID = [CBUUID UUIDWithString:@"68753A44-4D6F-1226-9C60-0050E4C00067"];
        CBUUID * serviceUUID = [CBUUID UUIDWithString:@"68753A44-4D6F-1226-9C60-0050E4C00068"];
        mockLocator = mockProtocol(@protocol(WLXCharacteristicLocator));
        mockPeripheral = mock([CBPeripheral class]);
        mockService = mock([CBService class]);
        mockCharacteristic = mock([CBCharacteristic class]);
        notificationCenter = [NSNotificationCenter defaultCenter];
        [MKTGiven(mockCharacteristic.UUID) willReturn:characteristicUUID];
        [MKTGiven([mockLocator characteristicFromUUID:characteristicUUID]) willReturn:mockCharacteristic];
        [MKTGiven(mockService.UUID) willReturn:serviceUUID];

        asyncExecutor = [[WLXCharacteristicAsyncExecutor alloc] initWithCharacteristicLocator:mockLocator queue:specQueue];
        serviceManager = [[WLXServiceManager alloc] initWithPeripheral:mockPeripheral
                                                               service:mockService
                                                    notificationCenter:notificationCenter
                                                                 queue:specQueue
                                                         asyncExecutor:asyncExecutor];
    });

    afterEach(^{
        mockLocator = nil;
        mockPeripheral = nil;
        mockService = nil;
        asyncExecutor = nil;
        serviceManager = nil;
        characteristicUUID = nil;
        data = nil;
        error = nil;
    });

    describe(@"#invalidated", ^{

        context(@"when the service manager has just been created", ^{

            it(@"is not invalidated", ^{
                expect(serviceManager.invalidated).to.beFalsy;
            });

        });

        context(@"when a WLXBluetoothDeviceReconnecting notification is triggered", ^{

            beforeEach(^{
                [notificationCenter postNotificationName:WLXBluetoothDeviceReconnecting object:nil];
            });

            it(@"is invalidated", ^{
                expect(serviceManager.invalidated).to.beTruthy;
            });

        });

        context(@"when a WLXBluetoothDeviceConnectionLost notification is triggered", ^{

            beforeEach(^{
                [notificationCenter postNotificationName:WLXBluetoothDeviceConnectionLost object:nil];
            });

            it(@"is invalidated", ^{
                expect(serviceManager.invalidated).to.beTruthy;
            });

        });

        context(@"when a WLXBluetoothDeviceConnectionTerminated notification is triggered", ^{

            beforeEach(^{
                [notificationCenter postNotificationName:WLXBluetoothDeviceConnectionTerminated object:nil];
            });

            it(@"is invalidated", ^{
                expect(serviceManager.invalidated).to.beTruthy;
            });

        });

    });

    describe(@"#readValueFromCharacteristic:usingBlock:", ^{

        context(@"when a nil UUID is given", ^{

            it(@"raises an exception", ^{
                expect(^{ [serviceManager readValueFromCharacteristic:nil usingBlock:^(NSError * error, NSData * data) {

                }]; }).to.raise(@"NSInternalInconsistencyException");
            });

        });

        context(@"when a nil block is given", ^{

            it(@"raises an exception", ^{
                expect(^{
                    [serviceManager readValueFromCharacteristic:characteristicUUID usingBlock:nil];
                }).to.raise(@"NSInternalInconsistencyException");
            });

        });

        context(@"when the value is successfully read", ^{

            beforeEach(^{
                data = [[NSData alloc] init];
                [MKTGiven(mockCharacteristic.value) willReturn:data];
            });

            it(@"calls the block with the read data", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager readValueFromCharacteristic:characteristicUUID usingBlock:^(NSError * error, NSData * data) {
                    [MKTVerify(mockPeripheral) readValueForCharacteristic:mockCharacteristic];
                    expect(error).to.beNil;
                    expect(data).to.equal(data);
                    done();
                }];
                ASYNC([serviceManager didUpdateValueForCharacteristic:mockCharacteristic error:nil]);
            });});

            it(@"calls the peripheral's readValueForCharacteristic", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager readValueFromCharacteristic:characteristicUUID usingBlock:^(NSError * error, NSData * data) {
                    [MKTVerify(mockPeripheral) readValueForCharacteristic:mockCharacteristic];
                    done();
                }];
                ASYNC([serviceManager didUpdateValueForCharacteristic:mockCharacteristic error:nil]);
            });});

        });

        context(@"when there is an error reading the value", ^{

            beforeEach(^{
                error = [NSError errorWithDomain:@"ar.com.wolox.Test" code:0 userInfo:nil];
            });

            it(@"call the block with an error", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager readValueFromCharacteristic:characteristicUUID usingBlock:^(NSError * error, NSData * data) {
                    [MKTVerify(mockPeripheral) readValueForCharacteristic:mockCharacteristic];
                    expect(error).notTo.beNil;
                    expect(data).to.beNil;
                    done();
                }];
                ASYNC([serviceManager didUpdateValueForCharacteristic:mockCharacteristic error:error]);
            });});

            it(@"calls the peripheral's readValueForCharacteristic", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager readValueFromCharacteristic:characteristicUUID usingBlock:^(NSError * error, NSData * data) {
                    [MKTVerify(mockPeripheral) readValueForCharacteristic:mockCharacteristic];
                    done();
                }];
                ASYNC([serviceManager didUpdateValueForCharacteristic:mockCharacteristic error:error]);
            });});

        });

        context(@"when the service manager has been invalidated", ^{

            before(^{
                [notificationCenter postNotificationName:WLXBluetoothDeviceReconnecting object:nil];
            });

            it(@"raises an exepction", ^{
                expect(^{
                    [serviceManager readValueFromCharacteristic:characteristicUUID
                                                     usingBlock:^(NSError * error, NSData * data) {}];
                }).to.raise(NSInternalInconsistencyException);
            });

        });

    });

    describe(@"#writeValue:toCharacteristic:usingBlock:", ^{

        beforeEach(^{
            data = [[NSData alloc] init];
            [MKTGiven(mockCharacteristic.value) willReturn:data];
        });

        context(@"when a nil data is given", ^{

            it(@"raises an exception", ^{
                expect(^{
                    [serviceManager writeValue:nil toCharacteristic:characteristicUUID usingBlock:^(NSError * error){}];
                }).to.raise(@"NSInternalInconsistencyException");
            });

        });

        context(@"when a nil characteristic UUID is given", ^{

            it(@"raises an exception", ^{
                expect(^{
                    [serviceManager writeValue:data toCharacteristic:nil usingBlock:^(NSError * error){}];
                }).to.raise(@"NSInternalInconsistencyException");
            });

        });

        context(@"when a nil block is given", ^{

            it(@"raises an exception", ^{
                expect(^{
                    [serviceManager writeValue:data toCharacteristic:characteristicUUID usingBlock:nil];
                }).to.raise(@"NSInternalInconsistencyException");
            });

        });

        context(@"when the characteristic's value is successfully writen", ^{

            it(@"calls the block with a nil error", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager writeValue:data toCharacteristic:characteristicUUID usingBlock:^(NSError * error) {
                    expect(error).to.beNil;
                    done();
                }];
                ASYNC([serviceManager didWriteValueForCharacteristic:mockCharacteristic error:nil]);
            });});

            it(@"calls the peripheral's writeValue:forCharacteristic:type: method", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager writeValue:data toCharacteristic:characteristicUUID usingBlock:^(NSError * error) {
                    [MKTVerify(mockPeripheral) writeValue:data forCharacteristic:mockCharacteristic type:CBCharacteristicWriteWithResponse];
                    done();
                }];
                ASYNC([serviceManager didWriteValueForCharacteristic:mockCharacteristic error:nil]);
            });});

        });

        context(@"when the characteristic's value could not be writen", ^{

            it(@"calls the block with an error", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager writeValue:data toCharacteristic:characteristicUUID usingBlock:^(NSError * error) {
                    expect(error).notTo.beNil;
                    done();
                }];
                ASYNC([serviceManager didWriteValueForCharacteristic:mockCharacteristic error:error]);
            });});

            it(@"calls the peripheral's writeValue:forCharacteristic:type: method", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager writeValue:data toCharacteristic:characteristicUUID usingBlock:^(NSError * error) {
                    [MKTVerify(mockPeripheral) writeValue:data forCharacteristic:mockCharacteristic type:CBCharacteristicWriteWithResponse];
                    done();
                }];
                ASYNC([serviceManager didWriteValueForCharacteristic:mockCharacteristic error:error]);
            });});

        });

        context(@"when the service manager has been invalidated", ^{

            before(^{
                [notificationCenter postNotificationName:WLXBluetoothDeviceReconnecting object:nil];
            });

            it(@"raises an exepction", ^{
                expect(^{
                    [serviceManager writeValue:data
                              toCharacteristic:characteristicUUID
                                    usingBlock:^(NSError * error) {}];
                }).to.raise(NSInternalInconsistencyException);
            });

        });

    });

    describe(@"#writeValue:toCharacteristic:", ^{

        beforeEach(^{
            data = [[NSData alloc] init];
            [MKTGiven(mockCharacteristic.value) willReturn:data];
        });

        context(@"when a nil data is given", ^{

            it(@"raises an exception", ^{
                expect(^{
                    [serviceManager writeValue:nil toCharacteristic:characteristicUUID];
                }).to.raise(@"NSInternalInconsistencyException");
            });

        });

        context(@"when a nil characteristic UUID is given", ^{

            it(@"raises an exception", ^{
                expect(^{
                    [serviceManager writeValue:data toCharacteristic:nil];
                }).to.raise(@"NSInternalInconsistencyException");
            });

        });

        it(@"calls the peripheral's writeValue:forCharacteristic:type: method", ^{ waitUntil(^(DoneCallback done) {
            [serviceManager writeValue:data toCharacteristic:characteristicUUID];
            ASYNC({
                [MKTVerify(mockPeripheral) writeValue:data forCharacteristic:mockCharacteristic type:CBCharacteristicWriteWithoutResponse];
                done();
            });
        });});

        context(@"when the service manager has been invalidated", ^{

            before(^{
                [notificationCenter postNotificationName:WLXBluetoothDeviceReconnecting object:nil];
            });

            it(@"raises an exepction", ^{
                expect(^{
                    [serviceManager writeValue:data
                              toCharacteristic:characteristicUUID];
                }).to.raise(NSInternalInconsistencyException);
            });

        });

    });

    describe(@"#enableNotificationsForCharacteristic:usingBlock:", ^{

        context(@"when a nil characteristic UUID is given", ^{

            it(@"raises an exception", ^{
                expect(^{
                    [serviceManager enableNotificationsForCharacteristic:nil usingBlock:^(NSError * error) {}];
                }).to.raise(@"NSInternalInconsistencyException");
            });

        });

        context(@"when a nil block is given", ^{

            it(@"raises an exception", ^{
                expect(^{
                    [serviceManager enableNotificationsForCharacteristic:characteristicUUID usingBlock:nil];
                }).to.raise(@"NSInternalInconsistencyException");
            });

        });

        context(@"when the notifications are successfully enabled", ^{

            it(@"calls the block", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager enableNotificationsForCharacteristic:characteristicUUID usingBlock:^(NSError * error) {
                    expect(error).to.beNil;
                    done();
                }];
                ASYNC([serviceManager didUpdateNotificationStateForCharacteristic:mockCharacteristic error:nil]);
            });});

            it(@"calls the peripheral's setNotifyValue:forCharacteristic method", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager enableNotificationsForCharacteristic:characteristicUUID usingBlock:^(NSError * error) {
                    [MKTVerify(mockPeripheral) setNotifyValue:YES forCharacteristic:mockCharacteristic];
                    done();
                }];
                ASYNC([serviceManager didUpdateNotificationStateForCharacteristic:mockCharacteristic error:nil]);
            });});

        });

        context(@"when the notifications could not be enabled", ^{

            it(@"calls the block witn an error", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager enableNotificationsForCharacteristic:characteristicUUID usingBlock:^(NSError * error) {
                    expect(error).notTo.beNil;
                    done();
                }];
                ASYNC([serviceManager didUpdateNotificationStateForCharacteristic:mockCharacteristic error:error]);
            });});

            it(@"calls the peripheral's setNotifyValue:forCharacteristic method", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager enableNotificationsForCharacteristic:characteristicUUID usingBlock:^(NSError * error) {
                    [MKTVerify(mockPeripheral) setNotifyValue:YES forCharacteristic:mockCharacteristic];
                    done();
                }];
                ASYNC([serviceManager didUpdateNotificationStateForCharacteristic:mockCharacteristic error:error]);
            });});

        });

        context(@"when the service manager has been invalidated", ^{

            before(^{
                [notificationCenter postNotificationName:WLXBluetoothDeviceReconnecting object:nil];
            });

            it(@"raises an exepction", ^{
                expect(^{
                    [serviceManager enableNotificationsForCharacteristic:characteristicUUID
                                                              usingBlock:^(NSError * error) {}];
                }).to.raise(NSInternalInconsistencyException);
            });

        });

    });

    describe(@"#disableNotificationsForCharacteristic:usingBlock:", ^{

        context(@"when a nil characteristic UUID is given", ^{

            it(@"raises an exception", ^{
                expect(^{
                    [serviceManager disableNotificationsForCharacteristic:nil usingBlock:^(NSError * error) {}];
                }).to.raise(@"NSInternalInconsistencyException");
            });

        });

        context(@"when a nil block is given", ^{

            it(@"raises an exception", ^{
                expect(^{
                    [serviceManager disableNotificationsForCharacteristic:characteristicUUID usingBlock:nil];
                }).to.raise(@"NSInternalInconsistencyException");
            });

        });

        context(@"when the notifications are successfully disabled", ^{

            it(@"calls the block", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager disableNotificationsForCharacteristic:characteristicUUID usingBlock:^(NSError * error) {
                    expect(error).to.beNil;
                    done();
                }];
                ASYNC([serviceManager didUpdateNotificationStateForCharacteristic:mockCharacteristic error:nil]);
            });});

            it(@"calls the peripheral's setNotifyValue:forCharacteristic method", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager disableNotificationsForCharacteristic:characteristicUUID usingBlock:^(NSError * error) {
                    [MKTVerify(mockPeripheral) setNotifyValue:NO forCharacteristic:mockCharacteristic];
                    done();
                }];
                ASYNC([serviceManager didUpdateNotificationStateForCharacteristic:mockCharacteristic error:nil]);
            });});

        });

        context(@"when the notifications could not be disabled", ^{

            it(@"calls the block with an error", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager disableNotificationsForCharacteristic:characteristicUUID usingBlock:^(NSError * error) {
                    expect(error).notTo.beNil;
                    done();
                }];
                ASYNC([serviceManager didUpdateNotificationStateForCharacteristic:mockCharacteristic error:error]);
            });});

            it(@"calls the peripheral's setNotifyValue:forCharacteristic method", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager disableNotificationsForCharacteristic:characteristicUUID usingBlock:^(NSError * error) {
                    [MKTVerify(mockPeripheral) setNotifyValue:NO forCharacteristic:mockCharacteristic];
                    done();
                }];
                ASYNC([serviceManager didUpdateNotificationStateForCharacteristic:mockCharacteristic error:error]);
            });});

        });

        context(@"when the service manager has been invalidated", ^{

            before(^{
                [notificationCenter postNotificationName:WLXBluetoothDeviceReconnecting object:nil];
            });

            it(@"raises an exepction", ^{
                expect(^{
                    [serviceManager disableNotificationsForCharacteristic:characteristicUUID
                                                               usingBlock:^(NSError * error) {}];
                }).to.raise(NSInternalInconsistencyException);
            });

        });

    });

    describe(@"#addObserverForCharacteristic:usingBlock:", ^{

        context(@"when a nil characteristic UUID is given", ^{

            it(@"raises an exception", ^{
                id block = ^(NSError * error, NSData * data) {};
                expect(^{
                    [serviceManager addObserverForCharacteristic:nil usingBlock:block];
                }).to.raise(@"NSInternalInconsistencyException");
            });

        });

        context(@"when a nil block is given", ^{

            it(@"raises an exception", ^{
                expect(^{
                    [serviceManager addObserverForCharacteristic:characteristicUUID usingBlock:nil];
                }).to.raise(@"NSInternalInconsistencyException");
            });

        });

        context(@"when a notification is received for the observed characteristic", ^{

            beforeEach(^{
                data = [[NSData alloc] init];
                [MKTGiven(mockCharacteristic.value) willReturn:data];
            });

            it(@"calls the block with the updated data", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager addObserverForCharacteristic:characteristicUUID usingBlock:^(NSError * error, NSData * aData) {
                    expect(error).to.beNil;
                    expect(aData).to.equal(data);
                    done();
                }];
                ASYNC([serviceManager didUpdateValueForCharacteristic:mockCharacteristic error:nil]);
            });});

        });

        context(@"when a notification error is received for the observed characteristic", ^{

            it(@"calls the block with an error", ^{ waitUntil(^(DoneCallback done) {
                [serviceManager addObserverForCharacteristic:characteristicUUID usingBlock:^(NSError * error, NSData * aData) {
                    expect(error).notTo.beNil;
                    expect(aData).to.beNil;
                    done();
                }];
                ASYNC([serviceManager didUpdateValueForCharacteristic:mockCharacteristic error:error]);
            });});

        });

        context(@"when the service manager has been invalidated", ^{

            before(^{
                [notificationCenter postNotificationName:WLXBluetoothDeviceReconnecting object:nil];
            });

            it(@"raises an exepction", ^{
                expect(^{
                    [serviceManager addObserverForCharacteristic:characteristicUUID
                                                      usingBlock:^(NSError * error, NSData * aData) {}];
                }).to.raise(NSInternalInconsistencyException);
            });

        });

        it(@"returns the created observer", ^{
            id block = ^(NSError * error, NSData * data) {};
            expect([serviceManager addObserverForCharacteristic:characteristicUUID usingBlock:block]).notTo.beNil;
        });

    });

    describe(@"#addObserverForCharacteristic:selector:target:", ^{

        __block WLXCharacteristicObserver * observer;

        beforeEach(^{
            observer = [[WLXCharacteristicObserver alloc] init];
        });

        afterEach(^{
            observer = nil;
        });

        context(@"when a nil characteristic UUID is given", ^{

            it(@"raises an exception", ^{
                expect(^{
                    [serviceManager addObserverForCharacteristic:nil selector:@selector(updatedValue:error:) target:observer];
                }).to.raise(@"NSInternalInconsistencyException");
            });

        });

        context(@"when a notification is received for the observed characteristic", ^{

            beforeEach(^{
                data = [[NSData alloc] init];
                [MKTGiven(mockCharacteristic.value) willReturn:data];
            });

            it(@"calls the block with the updated data", ^{
                [serviceManager addObserverForCharacteristic:characteristicUUID selector:@selector(updatedValue:error:) target:observer];
                [serviceManager didUpdateValueForCharacteristic:mockCharacteristic error:nil];
                ASYNC({
                    expect(observer.data).to.equal(data);
                    [expect(observer.error).to beNil];
                });
            });

        });

        context(@"when a notification error is received for the observed characteristic", ^{

            it(@"calls the block with an error", ^{
                [serviceManager addObserverForCharacteristic:characteristicUUID selector:@selector(updatedValue:error:) target:observer];
                [serviceManager didUpdateValueForCharacteristic:mockCharacteristic error:error];
                ASYNC({
                    [expect(observer.data).to beNil];
                    [expect(observer.error).notTo beNil];
                });
            });

        });

        context(@"when the service manager has been invalidated", ^{

            before(^{
                [notificationCenter postNotificationName:WLXBluetoothDeviceReconnecting object:nil];
            });

            it(@"raises an exepction", ^{
                expect(^{
                    [serviceManager addObserverForCharacteristic:nil
                                                        selector:@selector(updatedValue:error:)
                                                          target:observer];
                }).to.raise(NSInternalInconsistencyException);
            });

        });

        it(@"returns the created observer", ^{
            expect([serviceManager addObserverForCharacteristic:characteristicUUID selector:@selector(updatedValue:error:) target:observer]).notTo.beNil;
        });

    });

    describe(@"#removeObserver:", ^{

        __block WLXCharacteristicObserver * observer;

        beforeEach(^{
            observer = [[WLXCharacteristicObserver alloc] init];
            data = [[NSData alloc] init];
            [MKTGiven(mockCharacteristic.value) willReturn:data];
        });

        afterEach(^{
            observer = nil;
        });

        context(@"when the observer is nil", ^{

        });

        it(@"stops notifying value updates to the removed observer", ^{
            id opaqueObserver = [serviceManager addObserverForCharacteristic:characteristicUUID
                                                                    selector:@selector(updatedValue:error:)
                                                                      target:observer];
            [serviceManager removeObserver:opaqueObserver];
            [serviceManager didUpdateValueForCharacteristic:mockCharacteristic error:nil];
            usleep(100);
            expect(observer.data).to.beNil;
            expect(observer.error).to.beNil;

        });

    });

SpecEnd


text:
Setup Trix for production
#########################

********************
Install dependencies
********************
#. Python 3.6 or higher. Check your current version by running ``python --version``.
#. PIP_
#. VirtualEnv_
#. PostgreSQL server --- not needed if you just want to build the docs.

************************************************************
Create or select a user that you want to run the Trix server
************************************************************
We recommend using a normal user with no admin/root/sudo privileges to run Trix.
You should perform the rest of the steps in this guide as this new user.

********************************************
Make a directory where you will install trix
********************************************
This directory MUST NOT be served by a http server like apache. It should be a well protected
local directory only acceccible to the user running Trix. Example::

    $ mkdir ~/trixdeploy

We will refer to your trix deploy directory as ``~/trixdeploy`` for the rest of this guide.

************
Install Trix
************
::

    $ cd ~/trixdeploy
    $ virtualenv venv
    $ venv/bin/pip3 install psycopg2 dj-static trix

*********************************
Create a Django management script
*********************************
Copy this script into ``~/trixdeploy/manage.py``::

    import os
    import sys

    if __name__ == "__main__":
        os.environ["DJANGO_SETTINGS_MODULE"] = "trix_settings"
        from django.core.management import execute_from_command_line
        execute_from_command_line(sys.argv)

*********
Configure
*********
Trix is configured through a ``trix_settings.py`` file. Start by copying the following into
``~/trixdeploy/trix_settings.py``::

    from trix.project.production.settings import *
    import dj_database_url

    # Make this 50 chars and RANDOM - do not share it with anyone
    SECRET_KEY = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'

    # Database config
    DATABASE_URL = 'sqlite:///trixdb.sqlite'
    DATABASES = {'default': dj_database_url.config(default=DATABASE_URL)}

    # Set this to False to turn of debug mode in production
    DEBUG = False

****
LDAP
****
To enable LDAP authenication, ``trix_settings.py`` would need to include an authenication backend
with LDAP support, the URI for the LDAP server and its DN template, and possiblely some
`customization <https://django-auth-ldap.readthedocs.io/en/latest/authentication.html#customizing-authentication>`_
to adjust for how the usernames are stored in Trix's database.

As an example, the settings for UiO would need to adjust for the LDAP username not being a full
email adresse by overwriting ``ldap_to_django_username()`` and ``django_to_ldap_username()``
functions of ``django_auth_ldap.backend.LDAPBackend``.

Add the following to you ``trix_settings.py`` file (but adjust the DN template)::

    AUTHENTICATION_BACKENDS = [
        'trix_uio_ldap_auth.TrixUioLDAPBackend',
    ]
    AUTH_LDAP_SERVER_URI = 'ldaps://ldap.uio.no'
    AUTH_LDAP_USER_DN_TEMPLATE = 'uid=hei,cn=people,dc=uio,dc=no'

Create a ``trix_uio_ldap_auth.py`` as follows (but adjust the email suffix)::

    from django_auth_ldap.backend import LDAPBackend

    class TrixUioLDAPBackend(LDAPBackend):
        def ldap_to_django_username(self, username):
            return '{}@example.com'.format(username)

        def django_to_ldap_username(self, username):
            return username.split('@')[0]

***********
Dataporten
***********
Replacing the login with Dataporten login is relatively easy and can be done in a few steps:

#. Register a new `Dataporten Application <https://dashboard.dataporten.no/>`_. Documentation can be found in their `Dataporten docs <https://docs.feide.no/developer_oauth/register_and_manage_applications/getting_started_app_developers.html>`_. Use the redirect URL ``http://<webpage URL>:<port>/authenticate/allauth/dataporten/login/callback/``
#. Go to the superuser panel (Django admin pages) and modify Sites. There should be an example site with id 1. Either edit this site or create a new one to reflect the name of the page.
#. Create a new Social application using Dataporten as the provider. Give it a name and fill in the client id and secret key. Add the site you configured earlier.
#. If you created a new Site, add ``SITE_ID = x`` to your ``trix_settings.py`` file, where X = Site ID.
#. Add ``DATAPORTEN_LOGIN = True`` to your ``trix_settings.py`` file.
#. Login and logout should now work through Dataporten. Users will still be created and can be edited as normal.

****************
Consent template
****************
Customising the consent template is highly recommended and can be done by following these steps:

#. Create a directory for custom templates with a subfolder named ``trix_student``
#. Create a django html file called ``consent_form.django.html`` and make it look like this::

    {% extends "trix_student/consent_form_base.django.html" %}

    {% block consent_title %}
Consent title here
{% endblock %}

    {% block consent_text %}Lorem Ipsum{% endblock %}

    {# If you want to override the buttons you can add this #}
    {# {% block consent_buttons %}BUTTONS{% endblock %} #}

#. In ``trix_settings.py`` do::

    from trix.utils.template import add_custom_template

    add_custom_template('custom_template_directory/goes/here')

If you wish to disable the consent dialog completely for some reason, add ``DISABLE_CONSENT = True``
to your ``trix_settings.py`` file.

******************
Make sure it works
******************
Just to make sure everything works, run::

    $ cd ~/trixdeploy/
    $ venv/bin/python manage.py migrate

This should create a file named ``~/trixdeploy/trixdb.sqlite``. You can remove that file now - it was just for testing.

********************
Collect static files
********************
Run the following command to collect all static files (CSS, javascript, ...) for Trix::

    $ venv/bin/python manage.py collectstatic

The files are written to the ``staticfiles`` sub-directory (~/trixdeploy/staticfiles).

********************
Configure a database
********************
Configure a Postgres database by editing the ``DATABASE_URL`` setting in your ``trix_settings.py`` script.
The format is::

    DATABASE_URL = "postgres://USER:PASSWORD@HOST:PORT/NAME"

**********************
Configure a SECRET_KEY
**********************
Configure the SECRET_KEY (used for cryptographic signing) by editing the ``SECRET_KEY`` setting in your
``trix_settings.py`` script. Make it a 50 characters long random string.

******************
Disable debug mode
******************
Before running Trix in production, you **must** set ``DEBUG=False`` in ``trix_settings.py``.

.. warning::

    If you do not disable DEBUG mode in production, you database credentials and SECRET_KEY
    will be shown to any visitor when they encounter an error.

*************************
Run the production server
*************************
::

    $ DJANGO_SETTINGS_MODULE=trix_settings venv/bin/gunicorn trix.project.production.wsgi -b 0.0.0.0:8000 --workers=12 --preload

You can adjust the number of worker threads in the ``--workers`` argument,
and the port number in the ``-b`` argument. You can run this on port 80,
but if you want to have SSL support, you will need to use a HTTP proxy
server like Apache og Nginx.

.. _PIP: https://pip.pypa.io
.. _VirtualEnv: https://virtualenv.pypa.io


text:
package com.loginbox.collections;

import java.util.HashMap;

/**
 * Support tools for creating maps without syntactic noise _or_ the awful initializer hack.
 */
public final class MapLiteral {
    private MapLiteral() {
        throw new UnsupportedOperationException();
    }

    /**
     * Creates a new HashMap with the given entries. For example:
     * <pre>
     *     HashMap<Integer, String> m = hashMap(
     *         entry(1, "foo"),
     *         entry(3, "bar")
     *     );
     * </pre>
     *
     * @param entries
     *         a sequence of map entries, usually from {@link #entry}.
     * @param <K>
     *         the key type of the resulting map.
     * @param <V>
     *         the value type of the resulting map.
     * @return a map with all of the passed entries populated into it.
     */
    @SafeVarargs
    public static <K, V> HashMap<K, V> hashMap(Entry<K, V>... entries) {
        HashMap<K, V> map = new HashMap<>();
        for (Entry<K, V> entry : entries)
            entry.storeTo(map);
        return map;
    }

    public static <K, V> Entry<K, V> entry(K key, V value) {
        return new Entry<>(key, value);
    }

    public static class Entry<K, V> {
        private final K key;
        private final V value;

        private Entry(K key, V value) {
            this.key = key;
            this.value = value;
        }

        private void storeTo(HashMap<K, V> map) {
            map.put(key, value);
        }
    }
}


text:
Let's write a Helm chart for wordsmith!

We will need the YAML manifests that we wrote earlier.

Level 1: create a chart to deploy wordsmith.

Level 2: make it so that the number of replicas can be set with `--set replicas=X`.

Level 3: change the colors of the lego bricks.

(For level 3, fork the repository and use ctr.run to build images.)

See next slide if you need hints!

---

## Hints

*Scroll one slide at a time to see hints.*

--

Use `helm create` to create a new chart.

--

Delete the content of the `templates` directory and put your YAML instead.

--

Install the resulting chart. Voilà!

--

Use `{{ .Values.replicas }}` in the YAML manifest for `words`.

--

Also add `replicas: 5` to `values.yaml` to provide a default value.

---

## Changing the color

- Fork the repository

- Make sure that your fork has valid Dockerfiles

  (or identify a branch that has valid Dockerfiles)

- Use the following images:

  ctr.run/yourgithubusername/wordsmith/db:branchname

  (replace db with web and words for the other components)

- Change the images and/or CSS in `web/static`

- Commit, push, trigger a rolling update

  (`imagePullPolicy` should be `Always`, which is the default)


text:
<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Sign up</title>

    <meta name="description" content="Source code generated using layoutit.com">
    <meta name="author" content="LayoutIt!">

    <link href="css/bootstrap.min.css" rel="stylesheet">
    <link href="css/style.css" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="css/bootstrap-select.css">

				Sign Up

			<form role="form" action="" method="post" onSubmit="return chkads()" id="lf_addstu" name="lf_addstu">

						Name

					<input type="" class="form-control" id="InputUser" name="u-name">

						Password

					<input type="password" class="form-control" id="InputPassword" name="pass">

						Address

					<input type="address" class="form-control" id="InputAddress1" placeholder="Street" name="street">

          <input type="address" class="form-control" id="InputAddress1" placeholder="City" name="city">

          State
          <select class="form-control" id="state">
            <option id="al">AL</option> <option id="ak">AK</option> <option id="az">AZ</option> <option id="ar">AR</option>
            <option id="al">CA</option> <option id="ak">CO</option> <option id="az">CT</option> <option id="ar">DC</option>
            <option id="al">DE</option> <option id="ak">FL</option> <option id="az">GE</option> <option id="ar">HI</option>
          </select>

          Zip code
          <input type="address" class="form-control" id="zip" placeholder="" name="zip">

          Please specify customer kind (Home/Business)

						Home

						Business

            Marriage Status
            <select class="form-control" id="marriage">
              <option id="m0">NA</option> <option id="m1">Married</option> <option id="m2">Single</option> <option id="m3">Divorced</option>
            </select>

              Gender
              <select class="form-control" id="gender">
                <option id="g0">NA</option> <option id="g1">Female</option> <option id="g2">Male</option>
              </select>

              Age
              <input class="form-control" id="age" name="age">

              Income
              <input class="form-control" id="income" placeholder="e.g. 100,000" name="home_in">

            Business Category
            <select class="form-control" id="biz-cat">
              <option id="b0">NA</option> <option id="b1">Beauty</option> <option id="b2">Computers</option> <option id="b3">Entertainment</option>
            </select>

              Company gross anual income
              <input class="form-control" id="biz-inc" placeholder="e.g. 100,000" name="biz_in">

      <button type="submit" class="btn btn-success">
        Submit
      </button>

    </form>

        Back to home


text:
[![BCH compliance](https://bettercodehub.com/edge/badge/10533176/TafelTaferelen)]
(https://bettercodehub.com)

 ![ScreenShot](https://raw.github.com/10533176/Tafel-Taferelen/master/doc/Schermafbeelding 2017-01-27 om 14.40.46.png)

To do plan for better code:

* Viewcontroller Hoofdmenu (als eerst naam  veranderen naar engels)
  Voor het aanwezig klikken aan tafel heb ik momenteel heel veel verschillende functies, en die functies hebben ongeveer een lengte van 60 regels.
  Dit moet veel makkelijker kunnen! van het weekend hier naar kijken, mocht het mezelf niet lukken. -> Julian Slacken

* alle (voor zo ver dat logisch is) dubbele code verwijderen. Heb nu heel vaak gekopieerd en geplakt om te kijken of het werkte,
als het werkte heb ik het vervolgens nooit meer aangepast en zo laten staan

* iets bedenken waardoor ik informatie van de huidige user kan opslaan (de info die niet veranderd) scheelt met ophalen uit firebase.

* functies schrijven voor bijvoorheeld het ophalen van groepID. Doe dit nu zo een 15 x in mijn hele project en elke keer doe ik weer hetzelfde
MOET MAKKELIJKER KUNNEN

* Dus vooral belangrijk bij mij, FUNCTIES KORTER MAKEN. voor alle if else statements aparte functies maken. HOOFDMENU moet veel eenvoudiger qua code
duplicates eruit halen, en namen van functies veranderen in meer beschrijvende namen.

**VERVOLG**

Voor het verbeteren van mijn code ben ik eerst alle dubbele code uit mijn projetc gaan halen. Deze heb ik in een aparte file gezet genaamd extensions.swift. Daarna ben ik al mijn files doorgelopen en gekeken of alles wat er in staat nog nodig was. Alle variabele die ik uiteindelijk toch niet heb gebruikt heb ik weg gehaald etc.

Hierna heb ik mijn project weer door beteer code gehaald met het volgende resultaat:

 ![ScreenShot](https://raw.github.com/10533176/Tafel-Taferelen/master/doc/Schermafbeelding 2017-01-31 om 14.09.29.png)

Met als conclusie dat mijn functies nog steeds te lang zijn en simpeler moeten worden geschreven. Om dit te realiseren heb ik geprobeerd de funties die alle data ophaald uit FireBase ook in een aparte file te zetten zodat ik deze gemakkelijker in alle viewcontrollers kon aanroepen. Na dit voor een lange tijd te hebben geprobeerd kwam ik erachter dat dat ook niet de oplossing was. Dit omdat de functies al returnen voordat de waarde daadwerkelijk is opgehaald uit Firebase. Na ook nog wat te hebben geprobeerd met Completion blocks, tot de conclusie gekomen dat ik het hiermee ook niet ging redden.

Daarom uiteindelijk al mijn firebase functies opgesplits in kleinere overzichtelijker functies. Hierdoor is het voor een buitenstaander nu makkelijker mijn code te lezen en is het voor mij ook makkelijker om wanneer er iets veranderd moet worden ik niet door een functie van 60 lijnen heen moet, maar nu slechts een functie van10 lijnen code.

Na met julian mijn functies te hebben aangepast voor het aanwezig klikken op tafel (zie final report voor meer uitleg) kwam de volgende score uit bettercode:

![ScreenShot](https://raw.github.com/10533176/Tafel-Taferelen/master/doc/Schermafbeelding 2017-02-02 om 11.07.20.png)

Als laatste heb ik nog alle namen aangepast om deze meer beschrijvend en ondersteunend te maken.