Beispiel #1
0
static ssize_t
hysdn_conf_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
{
	struct conf_writedata *cnf;
	int i;
	unsigned char ch, *cp;

	if (!count)
		return (0);	/* nothing to handle */

	if (!(cnf = file->private_data))
		return (-EFAULT);	/* should never happen */

	if (cnf->state == CONF_STATE_DETECT) {	/* auto detect cnf or pof data */
		if (copy_from_user(&ch, buf, 1))	/* get first char for detect */
			return (-EFAULT);

		if (ch == 0x1A) {
			/* we detected a pof file */
			if ((cnf->needed_size = pof_write_open(cnf->card, &cnf->pof_buffer)) <= 0)
				return (cnf->needed_size);	/* an error occurred -> exit */
			cnf->buf_size = 0;	/* buffer is empty */
			cnf->state = CONF_STATE_POF;	/* new state */
		} else {
			/* conf data has been detected */
			cnf->buf_size = 0;	/* buffer is empty */
			cnf->state = CONF_STATE_CONF;	/* requested conf data write */
			if (cnf->card->state != CARD_STATE_RUN)
				return (-ERR_NOT_BOOTED);
			cnf->conf_line[CONF_LINE_LEN - 1] = 0;	/* limit string length */
			cnf->channel = 4098;	/* default channel for output */
		}
	}			/* state was auto detect */
	if (cnf->state == CONF_STATE_POF) {	/* pof write active */
		i = cnf->needed_size - cnf->buf_size;	/* bytes still missing for write */
		if (i <= 0)
			return (-EINVAL);	/* size error handling pof */

		if (i < count)
			count = i;	/* limit requested number of bytes */
		if (copy_from_user(cnf->pof_buffer + cnf->buf_size, buf, count))
			return (-EFAULT);	/* error while copying */
		cnf->buf_size += count;

		if (cnf->needed_size == cnf->buf_size) {
			cnf->needed_size = pof_write_buffer(cnf->card, cnf->buf_size);	/* write data */
			if (cnf->needed_size <= 0) {
				cnf->card->state = CARD_STATE_BOOTERR;	/* show boot error */
				return (cnf->needed_size);	/* an error occurred */
			}
			cnf->buf_size = 0;	/* buffer is empty again */
		}
	}
	/* pof write active */
	else {			/* conf write active */

		if (cnf->card->state != CARD_STATE_RUN) {
			if (cnf->card->debug_flags & LOG_CNF_MISC)
				hysdn_addlog(cnf->card, "cnf write denied -> not booted");
			return (-ERR_NOT_BOOTED);
		}
		i = (CONF_LINE_LEN - 1) - cnf->buf_size;	/* bytes available in buffer */
		if (i > 0) {
			/* copy remaining bytes into buffer */

			if (count > i)
				count = i;	/* limit transfer */
			if (copy_from_user(cnf->conf_line + cnf->buf_size, buf, count))
				return (-EFAULT);	/* error while copying */

			i = count;	/* number of chars in buffer */
			cp = cnf->conf_line + cnf->buf_size;
			while (i) {
				/* search for end of line */
				if ((*cp < ' ') && (*cp != 9))
					break;	/* end of line found */
				cp++;
				i--;
			}	/* search for end of line */

			if (i) {
				/* delimiter found */
				*cp++ = 0;	/* string termination */
				count -= (i - 1);	/* subtract remaining bytes from count */
				while ((i) && (*cp < ' ') && (*cp != 9)) {
					i--;	/* discard next char */
					count++;	/* mark as read */
					cp++;	/* next char */
				}
				cnf->buf_size = 0;	/* buffer is empty after transfer */
				if ((i = process_line(cnf)) < 0)	/* handle the line */
					count = i;	/* return the error */
			}
			/* delimiter found */
			else {
				cnf->buf_size += count;		/* add chars to string */
				if (cnf->buf_size >= CONF_LINE_LEN - 1) {
					if (cnf->card->debug_flags & LOG_CNF_MISC)
						hysdn_addlog(cnf->card, "cnf line too long %d chars pos %d", cnf->buf_size, count);
					return (-ERR_CONF_LONG);
				}
			}	/* not delimited */

		}
		/* copy remaining bytes into buffer */
		else {
			if (cnf->card->debug_flags & LOG_CNF_MISC)
				hysdn_addlog(cnf->card, "cnf line too long");
			return (-ERR_CONF_LONG);
		}
	}			/* conf write active */

	return (count);
}				/* hysdn_conf_write */
static ssize_t
hysdn_conf_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
{
	struct conf_writedata *cnf;
	int i;
	unsigned char ch, *cp;

	if (!count)
		return (0);	/*                   */

	if (!(cnf = file->private_data))
		return (-EFAULT);	/*                     */

	if (cnf->state == CONF_STATE_DETECT) {	/*                             */
		if (copy_from_user(&ch, buf, 1))	/*                           */
			return (-EFAULT);

		if (ch == 0x1A) {
			/*                        */
			if ((cnf->needed_size = pof_write_open(cnf->card, &cnf->pof_buffer)) <= 0)
				return (cnf->needed_size);	/*                           */
			cnf->buf_size = 0;	/*                 */
			cnf->state = CONF_STATE_POF;	/*           */
		} else {
			/*                             */
			cnf->buf_size = 0;	/*                 */
			cnf->state = CONF_STATE_CONF;	/*                           */
			if (cnf->card->state != CARD_STATE_RUN)
				return (-ERR_NOT_BOOTED);
			cnf->conf_line[CONF_LINE_LEN - 1] = 0;	/*                     */
			cnf->channel = 4098;	/*                            */
		}
	}			/*                       */
	if (cnf->state == CONF_STATE_POF) {	/*                  */
		i = cnf->needed_size - cnf->buf_size;	/*                               */
		if (i <= 0)
			return (-EINVAL);	/*                         */

		if (i < count)
			count = i;	/*                                 */
		if (copy_from_user(cnf->pof_buffer + cnf->buf_size, buf, count))
			return (-EFAULT);	/*                     */
		cnf->buf_size += count;

		if (cnf->needed_size == cnf->buf_size) {
			cnf->needed_size = pof_write_buffer(cnf->card, cnf->buf_size);	/*            */
			if (cnf->needed_size <= 0) {
				cnf->card->state = CARD_STATE_BOOTERR;	/*                 */
				return (cnf->needed_size);	/*                   */
			}
			cnf->buf_size = 0;	/*                       */
		}
	}
	/*                  */
	else {			/*                   */

		if (cnf->card->state != CARD_STATE_RUN) {
			if (cnf->card->debug_flags & LOG_CNF_MISC)
				hysdn_addlog(cnf->card, "cnf write denied -> not booted");
			return (-ERR_NOT_BOOTED);
		}
		i = (CONF_LINE_LEN - 1) - cnf->buf_size;	/*                           */
		if (i > 0) {
			/*                                  */

			if (count > i)
				count = i;	/*                */
			if (copy_from_user(cnf->conf_line + cnf->buf_size, buf, count))
				return (-EFAULT);	/*                     */

			i = count;	/*                           */
			cp = cnf->conf_line + cnf->buf_size;
			while (i) {
				/*                        */
				if ((*cp < ' ') && (*cp != 9))
					break;	/*                   */
				cp++;
				i--;
			}	/*                        */

			if (i) {
				/*                 */
				*cp++ = 0;	/*                    */
				count -= (i - 1);	/*                                     */
				while ((i) && (*cp < ' ') && (*cp != 9)) {
					i--;	/*                   */
					count++;	/*              */
					cp++;	/*           */
				}
				cnf->buf_size = 0;	/*                                */
				if ((i = process_line(cnf)) < 0)	/*                 */
					count = i;	/*                  */
			}
			/*                 */
			else {
				cnf->buf_size += count;		/*                     */
				if (cnf->buf_size >= CONF_LINE_LEN - 1) {
					if (cnf->card->debug_flags & LOG_CNF_MISC)
						hysdn_addlog(cnf->card, "cnf line too long %d chars pos %d", cnf->buf_size, count);
					return (-ERR_CONF_LONG);
				}
			}	/*               */

		}
		/*                                  */
		else {
			if (cnf->card->debug_flags & LOG_CNF_MISC)
				hysdn_addlog(cnf->card, "cnf line too long");
			return (-ERR_CONF_LONG);
		}
	}			/*                   */

	return (count);
}				/*                  */