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); } /* */