spin_lock_irqsave(&line->lock, flags); /* write_room subtracts 1 for the needed NULL, so we readd it.*/
ret = LINE_BUFSIZE - (write_room(line) + 1);
spin_unlock_irqrestore(&line->lock, flags);
if (len < end) {
memcpy(line->tail, buf, len);
line->tail += len;
} else { /* The circular buffer is wrapping */
memcpy(line->tail, buf, end);
buf += end;
memcpy(line->buffer, buf, len - end);
line->tail = line->buffer + len - end;
}
return len;
}
/* *Flushestheringbuffertotheoutputchannels.Thatis,write_chanis *called,passingitline->headasbuffer,andanappropriatecount. * *Onexit,returns1whenthebufferisempty, *0whenthebufferisnotemptyonexit, *and-errnowhenanerroroccurred. *
* Must be called while holding line->lock!*/ staticint flush_buffer(struct line *line)
{ int n, count;
if ((line->buffer == NULL) || (line->head == line->tail)) return1;
if (line->tail < line->head) { /* line->buffer + LINE_BUFSIZE is the end of the buffer! */
count = line->buffer + LINE_BUFSIZE - line->head;
void line_hangup(struct tty_struct *tty)
{ struct line *line = tty->driver_data;
tty_port_hangup(&line->port);
}
void close_lines(struct line *lines, int nlines)
{ int i;
for(i = 0; i < nlines; i++)
close_chan(&lines[i]);
}
int setup_one_line(struct line *lines, int n, char *init, conststruct chan_opts *opts, char **error_out)
{ struct line *line = &lines[n]; struct tty_driver *driver = line->driver->driver; int err = -EINVAL;
if (line->port.count) {
*error_out = "Device is already open"; goto out;
}
if (!strcmp(init, "none")) { if (line->valid) {
line->valid = 0;
kfree(line->init_str);
tty_unregister_device(driver, n);
parse_chan_pair(NULL, line, n, opts, error_out);
err = 0;
}
*error_out = "configured as 'none'";
} else { char *new = kstrdup(init, GFP_KERNEL); if (!new) {
*error_out = "Failed to allocate memory"; return -ENOMEM;
} if (line->valid) {
tty_unregister_device(driver, n);
kfree(line->init_str);
}
line->init_str = new;
line->valid = 1;
err = parse_chan_pair(new, line, n, opts, error_out); if (!err) { struct device *d = tty_port_register_device(&line->port,
driver, n, NULL); if (IS_ERR(d)) {
*error_out = "Failed to register device";
err = PTR_ERR(d);
parse_chan_pair(NULL, line, n, opts, error_out);
}
} if (err) {
*error_out = "failed to parse channel pair";
line->init_str = NULL;
line->valid = 0;
kfree(new);
}
}
out: return err;
}
if (*end != '=') {
error = "Couldn't parse device number"; goto out;
} if (n >= num) {
error = "Device number out of range"; goto out;
}
conf[n] = end + 1;
} return0;
out:
printk(KERN_ERR "Failed to set up %s with " "configuration string \"%s\" : %s\n", name, init, error); return -EINVAL;
}
int line_config(struct line *lines, unsignedint num, char *str, conststruct chan_opts *opts, char **error_out)
{ char *end; int n;
if (*str == '=') {
*error_out = "Can't configure all devices from mconsole"; return -EINVAL;
}
n = simple_strtoul(str, &end, 0); if (*end++ != '=') {
*error_out = "Couldn't parse device number"; return -EINVAL;
} if (n >= num) {
*error_out = "Device number out of range"; return -EINVAL;
}
return setup_one_line(lines, n, end, opts, error_out);
}
int line_get_config(char *name, struct line *lines, unsignedint num, char *str, int size, char **error_out)
{ struct line *line; char *end; int dev, n = 0;
dev = simple_strtoul(name, &end, 0); if ((*end != '\0') || (end == name)) {
*error_out = "line_get_config failed to parse device number"; return0;
}
if ((dev < 0) || (dev >= num)) {
*error_out = "device number out of range"; return0;
}
line = &lines[dev];
if (!line->valid)
CONFIG_CHUNK(str, size, n, "none", 1); else { struct tty_struct *tty = tty_port_tty_get(&line->port); if (tty == NULL) {
CONFIG_CHUNK(str, size, n, line->init_str, 1);
} else {
n = chan_config_string(line, str, size, error_out);
tty_kref_put(tty);
}
}
return n;
}
int line_id(char **str, int *start_out, int *end_out)
{ char *end; int n;
n = simple_strtoul(*str, &end, 0); if ((*end != '\0') || (end == *str)) return -1;
int line_remove(struct line *lines, unsignedint num, int n, char **error_out)
{ if (n >= num) {
*error_out = "Device number out of range"; return -EINVAL;
} return setup_one_line(lines, n, "none", NULL, error_out);
}
int register_lines(struct line_driver *line_driver, conststruct tty_operations *ops, struct line *lines, int nlines)
{ struct tty_driver *driver; int err; int i;
driver = tty_alloc_driver(nlines, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV); if (IS_ERR(driver)) return PTR_ERR(driver);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.