diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2012-05-21 15:39:42 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2012-05-21 15:39:42 -0400 |
commit | 0ad8c6a22d03a1598f7cc6585c65354dadca62ad (patch) | |
tree | 1507deef3d55d5f3c71b2f76924fe1f6c6211905 /drivers/usb/serial | |
parent | 8527f8e2934683e53405fbe876a4e6f4a0c46eb8 (diff) | |
parent | 76e10d158efb6d4516018846f60c2ab5501900bc (diff) |
Merge tag 'v3.4' with SCSI updates, needed for subsequent firewire-sbp2 changes
Linux 3.4
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/bus.c | 5 | ||||
-rw-r--r-- | drivers/usb/serial/cp210x.c | 9 | ||||
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 36 | ||||
-rw-r--r-- | drivers/usb/serial/metro-usb.c | 6 | ||||
-rw-r--r-- | drivers/usb/serial/option.c | 1 | ||||
-rw-r--r-- | drivers/usb/serial/pl2303.c | 2 | ||||
-rw-r--r-- | drivers/usb/serial/sierra.c | 5 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 31 |
8 files changed, 45 insertions, 50 deletions
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 7f547dc3a590..ed8adb052ca7 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c | |||
@@ -60,8 +60,6 @@ static int usb_serial_device_probe(struct device *dev) | |||
60 | retval = -ENODEV; | 60 | retval = -ENODEV; |
61 | goto exit; | 61 | goto exit; |
62 | } | 62 | } |
63 | if (port->dev_state != PORT_REGISTERING) | ||
64 | goto exit; | ||
65 | 63 | ||
66 | driver = port->serial->type; | 64 | driver = port->serial->type; |
67 | if (driver->port_probe) { | 65 | if (driver->port_probe) { |
@@ -98,9 +96,6 @@ static int usb_serial_device_remove(struct device *dev) | |||
98 | if (!port) | 96 | if (!port) |
99 | return -ENODEV; | 97 | return -ENODEV; |
100 | 98 | ||
101 | if (port->dev_state != PORT_UNREGISTERING) | ||
102 | return retval; | ||
103 | |||
104 | device_remove_file(&port->dev, &dev_attr_port_number); | 99 | device_remove_file(&port->dev, &dev_attr_port_number); |
105 | 100 | ||
106 | driver = port->serial->type; | 101 | driver = port->serial->type; |
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 0310e2df59f5..ec30f95ef399 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c | |||
@@ -287,7 +287,8 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, | |||
287 | /* Issue the request, attempting to read 'size' bytes */ | 287 | /* Issue the request, attempting to read 'size' bytes */ |
288 | result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | 288 | result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), |
289 | request, REQTYPE_DEVICE_TO_HOST, 0x0000, | 289 | request, REQTYPE_DEVICE_TO_HOST, 0x0000, |
290 | port_priv->bInterfaceNumber, buf, size, 300); | 290 | port_priv->bInterfaceNumber, buf, size, |
291 | USB_CTRL_GET_TIMEOUT); | ||
291 | 292 | ||
292 | /* Convert data into an array of integers */ | 293 | /* Convert data into an array of integers */ |
293 | for (i = 0; i < length; i++) | 294 | for (i = 0; i < length; i++) |
@@ -340,12 +341,14 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, | |||
340 | result = usb_control_msg(serial->dev, | 341 | result = usb_control_msg(serial->dev, |
341 | usb_sndctrlpipe(serial->dev, 0), | 342 | usb_sndctrlpipe(serial->dev, 0), |
342 | request, REQTYPE_HOST_TO_DEVICE, 0x0000, | 343 | request, REQTYPE_HOST_TO_DEVICE, 0x0000, |
343 | port_priv->bInterfaceNumber, buf, size, 300); | 344 | port_priv->bInterfaceNumber, buf, size, |
345 | USB_CTRL_SET_TIMEOUT); | ||
344 | } else { | 346 | } else { |
345 | result = usb_control_msg(serial->dev, | 347 | result = usb_control_msg(serial->dev, |
346 | usb_sndctrlpipe(serial->dev, 0), | 348 | usb_sndctrlpipe(serial->dev, 0), |
347 | request, REQTYPE_HOST_TO_DEVICE, data[0], | 349 | request, REQTYPE_HOST_TO_DEVICE, data[0], |
348 | port_priv->bInterfaceNumber, NULL, 0, 300); | 350 | port_priv->bInterfaceNumber, NULL, 0, |
351 | USB_CTRL_SET_TIMEOUT); | ||
349 | } | 352 | } |
350 | 353 | ||
351 | kfree(buf); | 354 | kfree(buf); |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ff8605b4b4be..02e7f2d32d52 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -75,7 +75,8 @@ struct ftdi_private { | |||
75 | unsigned long last_dtr_rts; /* saved modem control outputs */ | 75 | unsigned long last_dtr_rts; /* saved modem control outputs */ |
76 | struct async_icount icount; | 76 | struct async_icount icount; |
77 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ | 77 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ |
78 | char prev_status, diff_status; /* Used for TIOCMIWAIT */ | 78 | char prev_status; /* Used for TIOCMIWAIT */ |
79 | bool dev_gone; /* Used to abort TIOCMIWAIT */ | ||
79 | char transmit_empty; /* If transmitter is empty or not */ | 80 | char transmit_empty; /* If transmitter is empty or not */ |
80 | struct usb_serial_port *port; | 81 | struct usb_serial_port *port; |
81 | __u16 interface; /* FT2232C, FT2232H or FT4232H port interface | 82 | __u16 interface; /* FT2232C, FT2232H or FT4232H port interface |
@@ -1681,6 +1682,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) | |||
1681 | init_waitqueue_head(&priv->delta_msr_wait); | 1682 | init_waitqueue_head(&priv->delta_msr_wait); |
1682 | 1683 | ||
1683 | priv->flags = ASYNC_LOW_LATENCY; | 1684 | priv->flags = ASYNC_LOW_LATENCY; |
1685 | priv->dev_gone = false; | ||
1684 | 1686 | ||
1685 | if (quirk && quirk->port_probe) | 1687 | if (quirk && quirk->port_probe) |
1686 | quirk->port_probe(priv); | 1688 | quirk->port_probe(priv); |
@@ -1839,6 +1841,9 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) | |||
1839 | 1841 | ||
1840 | dbg("%s", __func__); | 1842 | dbg("%s", __func__); |
1841 | 1843 | ||
1844 | priv->dev_gone = true; | ||
1845 | wake_up_interruptible_all(&priv->delta_msr_wait); | ||
1846 | |||
1842 | remove_sysfs_attrs(port); | 1847 | remove_sysfs_attrs(port); |
1843 | 1848 | ||
1844 | kref_put(&priv->kref, ftdi_sio_priv_release); | 1849 | kref_put(&priv->kref, ftdi_sio_priv_release); |
@@ -1982,17 +1987,19 @@ static int ftdi_process_packet(struct tty_struct *tty, | |||
1982 | N.B. packet may be processed more than once, but differences | 1987 | N.B. packet may be processed more than once, but differences |
1983 | are only processed once. */ | 1988 | are only processed once. */ |
1984 | status = packet[0] & FTDI_STATUS_B0_MASK; | 1989 | status = packet[0] & FTDI_STATUS_B0_MASK; |
1985 | if (status & FTDI_RS0_CTS) | ||
1986 | priv->icount.cts++; | ||
1987 | if (status & FTDI_RS0_DSR) | ||
1988 | priv->icount.dsr++; | ||
1989 | if (status & FTDI_RS0_RI) | ||
1990 | priv->icount.rng++; | ||
1991 | if (status & FTDI_RS0_RLSD) | ||
1992 | priv->icount.dcd++; | ||
1993 | if (status != priv->prev_status) { | 1990 | if (status != priv->prev_status) { |
1994 | priv->diff_status |= status ^ priv->prev_status; | 1991 | char diff_status = status ^ priv->prev_status; |
1995 | wake_up_interruptible(&priv->delta_msr_wait); | 1992 | |
1993 | if (diff_status & FTDI_RS0_CTS) | ||
1994 | priv->icount.cts++; | ||
1995 | if (diff_status & FTDI_RS0_DSR) | ||
1996 | priv->icount.dsr++; | ||
1997 | if (diff_status & FTDI_RS0_RI) | ||
1998 | priv->icount.rng++; | ||
1999 | if (diff_status & FTDI_RS0_RLSD) | ||
2000 | priv->icount.dcd++; | ||
2001 | |||
2002 | wake_up_interruptible_all(&priv->delta_msr_wait); | ||
1996 | priv->prev_status = status; | 2003 | priv->prev_status = status; |
1997 | } | 2004 | } |
1998 | 2005 | ||
@@ -2395,15 +2402,12 @@ static int ftdi_ioctl(struct tty_struct *tty, | |||
2395 | */ | 2402 | */ |
2396 | case TIOCMIWAIT: | 2403 | case TIOCMIWAIT: |
2397 | cprev = priv->icount; | 2404 | cprev = priv->icount; |
2398 | while (1) { | 2405 | while (!priv->dev_gone) { |
2399 | interruptible_sleep_on(&priv->delta_msr_wait); | 2406 | interruptible_sleep_on(&priv->delta_msr_wait); |
2400 | /* see if a signal did it */ | 2407 | /* see if a signal did it */ |
2401 | if (signal_pending(current)) | 2408 | if (signal_pending(current)) |
2402 | return -ERESTARTSYS; | 2409 | return -ERESTARTSYS; |
2403 | cnow = priv->icount; | 2410 | cnow = priv->icount; |
2404 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | ||
2405 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) | ||
2406 | return -EIO; /* no change => error */ | ||
2407 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | 2411 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || |
2408 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | 2412 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || |
2409 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || | 2413 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || |
@@ -2412,7 +2416,7 @@ static int ftdi_ioctl(struct tty_struct *tty, | |||
2412 | } | 2416 | } |
2413 | cprev = cnow; | 2417 | cprev = cnow; |
2414 | } | 2418 | } |
2415 | /* not reached */ | 2419 | return -EIO; |
2416 | break; | 2420 | break; |
2417 | case TIOCSERGETLSR: | 2421 | case TIOCSERGETLSR: |
2418 | return get_lsr_info(port, (struct serial_struct __user *)arg); | 2422 | return get_lsr_info(port, (struct serial_struct __user *)arg); |
diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 6e1622f2a297..08d16e8c002d 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c | |||
@@ -27,8 +27,8 @@ | |||
27 | 27 | ||
28 | /* Product information. */ | 28 | /* Product information. */ |
29 | #define FOCUS_VENDOR_ID 0x0C2E | 29 | #define FOCUS_VENDOR_ID 0x0C2E |
30 | #define FOCUS_PRODUCT_ID 0x0720 | 30 | #define FOCUS_PRODUCT_ID_BI 0x0720 |
31 | #define FOCUS_PRODUCT_ID_UNI 0x0710 | 31 | #define FOCUS_PRODUCT_ID_UNI 0x0700 |
32 | 32 | ||
33 | #define METROUSB_SET_REQUEST_TYPE 0x40 | 33 | #define METROUSB_SET_REQUEST_TYPE 0x40 |
34 | #define METROUSB_SET_MODEM_CTRL_REQUEST 10 | 34 | #define METROUSB_SET_MODEM_CTRL_REQUEST 10 |
@@ -47,7 +47,7 @@ struct metrousb_private { | |||
47 | 47 | ||
48 | /* Device table list. */ | 48 | /* Device table list. */ |
49 | static struct usb_device_id id_table[] = { | 49 | static struct usb_device_id id_table[] = { |
50 | { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID) }, | 50 | { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_BI) }, |
51 | { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) }, | 51 | { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) }, |
52 | { }, /* Terminating entry. */ | 52 | { }, /* Terminating entry. */ |
53 | }; | 53 | }; |
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 836cfa9a515f..f4465ccddc35 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -708,6 +708,7 @@ static const struct usb_device_id option_ids[] = { | |||
708 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, | 708 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, |
709 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, | 709 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, |
710 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED) }, | 710 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED) }, |
711 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED) }, | ||
711 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED3) }, | 712 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED3) }, |
712 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED4) }, | 713 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED4) }, |
713 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED5) }, | 714 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED5) }, |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index ff4a174fa5de..a1a9062954c4 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -420,7 +420,7 @@ static void pl2303_set_termios(struct tty_struct *tty, | |||
420 | control = priv->line_control; | 420 | control = priv->line_control; |
421 | if ((cflag & CBAUD) == B0) | 421 | if ((cflag & CBAUD) == B0) |
422 | priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); | 422 | priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); |
423 | else | 423 | else if ((old_termios->c_cflag & CBAUD) == B0) |
424 | priv->line_control |= (CONTROL_DTR | CONTROL_RTS); | 424 | priv->line_control |= (CONTROL_DTR | CONTROL_RTS); |
425 | if (control != priv->line_control) { | 425 | if (control != priv->line_control) { |
426 | control = priv->line_control; | 426 | control = priv->line_control; |
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index f14465a83dd1..8c8bf806f6fa 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -221,7 +221,7 @@ static const struct sierra_iface_info typeB_interface_list = { | |||
221 | }; | 221 | }; |
222 | 222 | ||
223 | /* 'blacklist' of interfaces not served by this driver */ | 223 | /* 'blacklist' of interfaces not served by this driver */ |
224 | static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11 }; | 224 | static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11, 19, 20 }; |
225 | static const struct sierra_iface_info direct_ip_interface_blacklist = { | 225 | static const struct sierra_iface_info direct_ip_interface_blacklist = { |
226 | .infolen = ARRAY_SIZE(direct_ip_non_serial_ifaces), | 226 | .infolen = ARRAY_SIZE(direct_ip_non_serial_ifaces), |
227 | .ifaceinfo = direct_ip_non_serial_ifaces, | 227 | .ifaceinfo = direct_ip_non_serial_ifaces, |
@@ -298,6 +298,9 @@ static const struct usb_device_id id_table[] = { | |||
298 | /* Sierra Wireless HSPA Non-Composite Device */ | 298 | /* Sierra Wireless HSPA Non-Composite Device */ |
299 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)}, | 299 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)}, |
300 | { USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */ | 300 | { USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */ |
301 | { USB_DEVICE(0x1199, 0x68A2), /* Sierra Wireless MC77xx in QMI mode */ | ||
302 | .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist | ||
303 | }, | ||
301 | { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ | 304 | { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ |
302 | .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist | 305 | .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist |
303 | }, | 306 | }, |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 69230f01056a..97355a15bbea 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -1059,6 +1059,12 @@ int usb_serial_probe(struct usb_interface *interface, | |||
1059 | serial->attached = 1; | 1059 | serial->attached = 1; |
1060 | } | 1060 | } |
1061 | 1061 | ||
1062 | /* Avoid race with tty_open and serial_install by setting the | ||
1063 | * disconnected flag and not clearing it until all ports have been | ||
1064 | * registered. | ||
1065 | */ | ||
1066 | serial->disconnected = 1; | ||
1067 | |||
1062 | if (get_free_serial(serial, num_ports, &minor) == NULL) { | 1068 | if (get_free_serial(serial, num_ports, &minor) == NULL) { |
1063 | dev_err(&interface->dev, "No more free serial devices\n"); | 1069 | dev_err(&interface->dev, "No more free serial devices\n"); |
1064 | goto probe_error; | 1070 | goto probe_error; |
@@ -1070,19 +1076,16 @@ int usb_serial_probe(struct usb_interface *interface, | |||
1070 | port = serial->port[i]; | 1076 | port = serial->port[i]; |
1071 | dev_set_name(&port->dev, "ttyUSB%d", port->number); | 1077 | dev_set_name(&port->dev, "ttyUSB%d", port->number); |
1072 | dbg ("%s - registering %s", __func__, dev_name(&port->dev)); | 1078 | dbg ("%s - registering %s", __func__, dev_name(&port->dev)); |
1073 | port->dev_state = PORT_REGISTERING; | ||
1074 | device_enable_async_suspend(&port->dev); | 1079 | device_enable_async_suspend(&port->dev); |
1075 | 1080 | ||
1076 | retval = device_add(&port->dev); | 1081 | retval = device_add(&port->dev); |
1077 | if (retval) { | 1082 | if (retval) |
1078 | dev_err(&port->dev, "Error registering port device, " | 1083 | dev_err(&port->dev, "Error registering port device, " |
1079 | "continuing\n"); | 1084 | "continuing\n"); |
1080 | port->dev_state = PORT_UNREGISTERED; | ||
1081 | } else { | ||
1082 | port->dev_state = PORT_REGISTERED; | ||
1083 | } | ||
1084 | } | 1085 | } |
1085 | 1086 | ||
1087 | serial->disconnected = 0; | ||
1088 | |||
1086 | usb_serial_console_init(debug, minor); | 1089 | usb_serial_console_init(debug, minor); |
1087 | 1090 | ||
1088 | exit: | 1091 | exit: |
@@ -1124,22 +1127,8 @@ void usb_serial_disconnect(struct usb_interface *interface) | |||
1124 | } | 1127 | } |
1125 | kill_traffic(port); | 1128 | kill_traffic(port); |
1126 | cancel_work_sync(&port->work); | 1129 | cancel_work_sync(&port->work); |
1127 | if (port->dev_state == PORT_REGISTERED) { | 1130 | if (device_is_registered(&port->dev)) |
1128 | |||
1129 | /* Make sure the port is bound so that the | ||
1130 | * driver's port_remove method is called. | ||
1131 | */ | ||
1132 | if (!port->dev.driver) { | ||
1133 | int rc; | ||
1134 | |||
1135 | port->dev.driver = | ||
1136 | &serial->type->driver; | ||
1137 | rc = device_bind_driver(&port->dev); | ||
1138 | } | ||
1139 | port->dev_state = PORT_UNREGISTERING; | ||
1140 | device_del(&port->dev); | 1131 | device_del(&port->dev); |
1141 | port->dev_state = PORT_UNREGISTERED; | ||
1142 | } | ||
1143 | } | 1132 | } |
1144 | } | 1133 | } |
1145 | serial->type->disconnect(serial); | 1134 | serial->type->disconnect(serial); |