Ejemplo n.º 1
0
/*****************************************************************************
 * Driver tty interface functions
 *****************************************************************************/
static int serial_open (struct tty_struct *tty, struct file * filp)
{
	struct usb_serial *serial;
	struct usb_serial_port *port;
	unsigned int portNumber;
	int retval;
	
	dbg("%s", __FUNCTION__);

	/* get the serial object associated with this tty pointer */
	serial = usb_serial_get_by_index(tty->index);
	if (!serial) {
		tty->driver_data = NULL;
		return -ENODEV;
	}

	portNumber = tty->index - serial->minor;
	port = serial->port[portNumber];
	 
	++port->open_count;

	if (port->open_count == 1) {

		/* set up our port structure making the tty driver
		 * remember our port object, and us it */
		tty->driver_data = port;
		port->tty = tty;

		/* lock this module before we call it
		 * this may fail, which means we must bail out,
		 * safe because we are called with BKL held */
		if (!try_module_get(serial->type->owner)) {
			retval = -ENODEV;
			goto bailout_kref_put;
		}

		/* only call the device specific open if this 
		 * is the first time the port is opened */
		retval = serial->type->open(port, filp);
		if (retval)
			goto bailout_module_put;
	}

	return 0;

bailout_module_put:
	module_put(serial->type->owner);
bailout_kref_put:
	kref_put(&serial->kref, destroy_serial);
	port->open_count = 0;
	return retval;
}
Ejemplo n.º 2
0
static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
{
	struct usb_serial *serial;
	int length = 0;
	int i;
	off_t begin = 0;
	char tmp[40];

	dbg("%s", __FUNCTION__);
	length += sprintf (page, "usbserinfo:1.0 driver:%s\n", DRIVER_VERSION);
	for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
		serial = usb_serial_get_by_index(i);
		if (serial == NULL)
			continue;

		length += sprintf (page+length, "%d:", i);
		if (serial->type->owner)
			length += sprintf (page+length, " module:%s", module_name(serial->type->owner));
		length += sprintf (page+length, " name:\"%s\"", serial->type->name);
		length += sprintf (page+length, " vendor:%04x product:%04x", 
				   le16_to_cpu(serial->dev->descriptor.idVendor), 
				   le16_to_cpu(serial->dev->descriptor.idProduct));
		length += sprintf (page+length, " num_ports:%d", serial->num_ports);
		length += sprintf (page+length, " port:%d", i - serial->minor + 1);

		usb_make_path(serial->dev, tmp, sizeof(tmp));
		length += sprintf (page+length, " path:%s", tmp);
			
		length += sprintf (page+length, "\n");
		if ((length + begin) > (off + count))
			goto done;
		if ((length + begin) < off) {
			begin += length;
			length = 0;
		}
		kref_put(&serial->kref, destroy_serial);
	}
	*eof = 1;
done:
	if (off >= (length + begin))
		return 0;
	*start = page + (off-begin);
	return ((count < begin+length-off) ? count : begin+length-off);
}
Ejemplo n.º 3
0
/*
 * The parsing of the command line works exactly like the
 * serial.c code, except that the specifier is "ttyUSB" instead
 * of "ttyS".
 */
static int usb_console_setup(struct console *co, char *options)
{
	struct usbcons_info *info = &usbcons_info;
	int baud = 9600;
	int bits = 8;
	int parity = 'n';
	int doflow = 0;
	int cflag = CREAD | HUPCL | CLOCAL;
	char *s;
	struct usb_serial *serial;
	struct usb_serial_port *port;
	int retval;
	struct tty_struct *tty = NULL;
	struct ktermios dummy;

	dbg("%s", __func__);

	if (options) {
		baud = simple_strtoul(options, NULL, 10);
		s = options;
		while (*s >= '0' && *s <= '9')
			s++;
		if (*s)
			parity = *s++;
		if (*s)
			bits   = *s++ - '0';
		if (*s)
			doflow = (*s++ == 'r');
	}
	
	/* Sane default */
	if (baud == 0)
		baud = 9600;

	switch (bits) {
	case 7:
		cflag |= CS7;
		break;
	default:
	case 8:
		cflag |= CS8;
		break;
	}
	switch (parity) {
	case 'o': case 'O':
		cflag |= PARODD;
		break;
	case 'e': case 'E':
		cflag |= PARENB;
		break;
	}
	co->cflag = cflag;

	/*
	 * no need to check the index here: if the index is wrong, console
	 * code won't call us
	 */
	serial = usb_serial_get_by_index(co->index);
	if (serial == NULL) {
		/* no device is connected yet, sorry :( */
		err("No USB device connected to ttyUSB%i", co->index);
		return -ENODEV;
	}

	retval = usb_autopm_get_interface(serial->interface);
	if (retval)
		goto error_get_interface;

	port = serial->port[co->index - serial->minor];
	tty_port_tty_set(&port->port, NULL);

	info->port = port;

	++port->port.count;
	if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) {
		if (serial->type->set_termios) {
			/*
			 * allocate a fake tty so the driver can initialize
			 * the termios structure, then later call set_termios to
			 * configure according to command line arguments
			 */
			tty = kzalloc(sizeof(*tty), GFP_KERNEL);
			if (!tty) {
				retval = -ENOMEM;
				err("no more memory");
				goto reset_open_count;
			}
			kref_init(&tty->kref);
			tty_port_tty_set(&port->port, tty);
			tty->driver = usb_serial_tty_driver;
			tty->index = co->index;
			if (tty_init_termios(tty)) {
				retval = -ENOMEM;
				err("no more memory");
				goto free_tty;
			}
		}

		/* only call the device specific open if this
		 * is the first time the port is opened */
		if (serial->type->open)
			retval = serial->type->open(NULL, port);
		else
			retval = usb_serial_generic_open(NULL, port);

		if (retval) {
			err("could not open USB console port");
			goto fail;
		}

		if (serial->type->set_termios) {
			tty->termios->c_cflag = cflag;
			tty_termios_encode_baud_rate(tty->termios, baud, baud);
			memset(&dummy, 0, sizeof(struct ktermios));
			serial->type->set_termios(tty, port, &dummy);

			tty_port_tty_set(&port->port, NULL);
			kfree(tty);
		}
		set_bit(ASYNCB_INITIALIZED, &port->port.flags);
	}
	/* Now that any required fake tty operations are completed restore
	 * the tty port count */
	--port->port.count;
	/* The console is special in terms of closing the device so
	 * indicate this port is now acting as a system console. */
	port->port.console = 1;

	mutex_unlock(&serial->disc_mutex);
	return retval;

 fail:
	tty_port_tty_set(&port->port, NULL);
 free_tty:
	kfree(tty);
 reset_open_count:
	port->port.count = 0;
	usb_autopm_put_interface(serial->interface);
 error_get_interface:
	usb_serial_put(serial);
	mutex_unlock(&serial->disc_mutex);
	return retval;
}
Ejemplo n.º 4
0
/*
 * The parsing of the command line works exactly like the
 * serial.c code, except that the specifier is "ttyUSB" instead
 * of "ttyS".
 */
static int usb_console_setup(struct console *co, char *options)
{
    struct usbcons_info *info = &usbcons_info;
    int baud = 9600;
    int bits = 8;
    int parity = 'n';
    int doflow = 0;
    int cflag = CREAD | HUPCL | CLOCAL;
    char *s;
    struct usb_serial *serial;
    struct usb_serial_port *port;
    int retval = 0;
    struct tty_struct *tty = NULL;
    struct ktermios *termios = NULL, dummy;

    dbg ("%s", __func__);

    if (options) {
        baud = simple_strtoul(options, NULL, 10);
        s = options;
        while (*s >= '0' && *s <= '9')
            s++;
        if (*s)
            parity = *s++;
        if (*s)
            bits   = *s++ - '0';
        if (*s)
            doflow = (*s++ == 'r');
    }

    /* build a cflag setting */
    switch (baud) {
    case 1200:
        cflag |= B1200;
        break;
    case 2400:
        cflag |= B2400;
        break;
    case 4800:
        cflag |= B4800;
        break;
    case 19200:
        cflag |= B19200;
        break;
    case 38400:
        cflag |= B38400;
        break;
    case 57600:
        cflag |= B57600;
        break;
    case 115200:
        cflag |= B115200;
        break;
    case 9600:
    default:
        cflag |= B9600;
        /*
         * Set this to a sane value to prevent a divide error
         */
        baud  = 9600;
        break;
    }
    switch (bits) {
    case 7:
        cflag |= CS7;
        break;
    default:
    case 8:
        cflag |= CS8;
        break;
    }
    switch (parity) {
    case 'o':
    case 'O':
        cflag |= PARODD;
        break;
    case 'e':
    case 'E':
        cflag |= PARENB;
        break;
    }
    co->cflag = cflag;

    /*
     * no need to check the index here: if the index is wrong, console
     * code won't call us
     */
    serial = usb_serial_get_by_index(co->index);
    if (serial == NULL) {
        /* no device is connected yet, sorry :( */
        err ("No USB device connected to ttyUSB%i", co->index);
        return -ENODEV;
    }

    port = serial->port[0];
    port->tty = NULL;

    info->port = port;

    ++port->open_count;
    if (port->open_count == 1) {
        if (serial->type->set_termios) {
            /*
             * allocate a fake tty so the driver can initialize
             * the termios structure, then later call set_termios to
             * configure according to command line arguments
             */
            tty = kzalloc(sizeof(*tty), GFP_KERNEL);
            if (!tty) {
                retval = -ENOMEM;
                err("no more memory");
                goto reset_open_count;
            }
            termios = kzalloc(sizeof(*termios), GFP_KERNEL);
            if (!termios) {
                retval = -ENOMEM;
                err("no more memory");
                goto free_tty;
            }
            memset(&dummy, 0, sizeof(struct ktermios));
            tty->termios = termios;
            port->tty = tty;
        }

        /* only call the device specific open if this
         * is the first time the port is opened */
        if (serial->type->open)
            retval = serial->type->open(port, NULL);
        else
            retval = usb_serial_generic_open(port, NULL);

        if (retval) {
            err("could not open USB console port");
            goto free_termios;
        }

        if (serial->type->set_termios) {
            termios->c_cflag = cflag;
            serial->type->set_termios(port, &dummy);

            port->tty = NULL;
            kfree(termios);
            kfree(tty);
        }
    }

    port->console = 1;
    retval = 0;

out:
    return retval;
free_termios:
    kfree(termios);
    port->tty = NULL;
free_tty:
    kfree(tty);
reset_open_count:
    port->open_count = 0;
    goto out;
}