aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/ftdi_sio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r--drivers/usb/serial/ftdi_sio.c179
1 files changed, 140 insertions, 39 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 683304d60615..3dc3768ca71c 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -47,7 +47,7 @@
47/* 47/*
48 * Version Information 48 * Version Information
49 */ 49 */
50#define DRIVER_VERSION "v1.4.3" 50#define DRIVER_VERSION "v1.5.0"
51#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>" 51#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>"
52#define DRIVER_DESC "USB FTDI Serial Converters Driver" 52#define DRIVER_DESC "USB FTDI Serial Converters Driver"
53 53
@@ -82,7 +82,8 @@ struct ftdi_private {
82 int rx_processed; 82 int rx_processed;
83 unsigned long rx_bytes; 83 unsigned long rx_bytes;
84 84
85 __u16 interface; /* FT2232C port interface (0 for FT232/245) */ 85 __u16 interface; /* FT2232C, FT2232H or FT4232H port interface
86 (0 for FT232/245) */
86 87
87 speed_t force_baud; /* if non-zero, force the baud rate to 88 speed_t force_baud; /* if non-zero, force the baud rate to
88 this value */ 89 this value */
@@ -94,6 +95,7 @@ struct ftdi_private {
94 unsigned long tx_bytes; 95 unsigned long tx_bytes;
95 unsigned long tx_outstanding_bytes; 96 unsigned long tx_outstanding_bytes;
96 unsigned long tx_outstanding_urbs; 97 unsigned long tx_outstanding_urbs;
98 unsigned short max_packet_size;
97}; 99};
98 100
99/* struct ftdi_sio_quirk is used by devices requiring special attention. */ 101/* struct ftdi_sio_quirk is used by devices requiring special attention. */
@@ -164,6 +166,7 @@ static struct usb_device_id id_table_combined [] = {
164 { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, 166 { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
165 { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) }, 167 { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) },
166 { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, 168 { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
169 { USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },
167 { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, 170 { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
168 { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, 171 { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
169 { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) }, 172 { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) },
@@ -673,6 +676,7 @@ static struct usb_device_id id_table_combined [] = {
673 { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, 676 { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
674 { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), 677 { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
675 .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 678 .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
679 { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) },
676 { }, /* Optional parameter entry */ 680 { }, /* Optional parameter entry */
677 { } /* Terminating entry */ 681 { } /* Terminating entry */
678}; 682};
@@ -693,12 +697,13 @@ static const char *ftdi_chip_name[] = {
693 [FT232BM] = "FT232BM", 697 [FT232BM] = "FT232BM",
694 [FT2232C] = "FT2232C", 698 [FT2232C] = "FT2232C",
695 [FT232RL] = "FT232RL", 699 [FT232RL] = "FT232RL",
700 [FT2232H] = "FT2232H",
701 [FT4232H] = "FT4232H"
696}; 702};
697 703
698 704
699/* Constants for read urb and write urb */ 705/* Constants for read urb and write urb */
700#define BUFSZ 512 706#define BUFSZ 512
701#define PKTSZ 64
702 707
703/* rx_flags */ 708/* rx_flags */
704#define THROTTLED 0x01 709#define THROTTLED 0x01
@@ -715,7 +720,6 @@ static const char *ftdi_chip_name[] = {
715/* function prototypes for a FTDI serial converter */ 720/* function prototypes for a FTDI serial converter */
716static int ftdi_sio_probe(struct usb_serial *serial, 721static int ftdi_sio_probe(struct usb_serial *serial,
717 const struct usb_device_id *id); 722 const struct usb_device_id *id);
718static void ftdi_shutdown(struct usb_serial *serial);
719static int ftdi_sio_port_probe(struct usb_serial_port *port); 723static int ftdi_sio_port_probe(struct usb_serial_port *port);
720static int ftdi_sio_port_remove(struct usb_serial_port *port); 724static int ftdi_sio_port_remove(struct usb_serial_port *port);
721static int ftdi_open(struct tty_struct *tty, 725static int ftdi_open(struct tty_struct *tty,
@@ -744,6 +748,8 @@ static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base);
744static unsigned short int ftdi_232am_baud_to_divisor(int baud); 748static unsigned short int ftdi_232am_baud_to_divisor(int baud);
745static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base); 749static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base);
746static __u32 ftdi_232bm_baud_to_divisor(int baud); 750static __u32 ftdi_232bm_baud_to_divisor(int baud);
751static __u32 ftdi_2232h_baud_base_to_divisor(int baud, int base);
752static __u32 ftdi_2232h_baud_to_divisor(int baud);
747 753
748static struct usb_serial_driver ftdi_sio_device = { 754static struct usb_serial_driver ftdi_sio_device = {
749 .driver = { 755 .driver = {
@@ -772,7 +778,6 @@ static struct usb_serial_driver ftdi_sio_device = {
772 .ioctl = ftdi_ioctl, 778 .ioctl = ftdi_ioctl,
773 .set_termios = ftdi_set_termios, 779 .set_termios = ftdi_set_termios,
774 .break_ctl = ftdi_break_ctl, 780 .break_ctl = ftdi_break_ctl,
775 .shutdown = ftdi_shutdown,
776}; 781};
777 782
778 783
@@ -838,6 +843,36 @@ static __u32 ftdi_232bm_baud_to_divisor(int baud)
838 return ftdi_232bm_baud_base_to_divisor(baud, 48000000); 843 return ftdi_232bm_baud_base_to_divisor(baud, 48000000);
839} 844}
840 845
846static __u32 ftdi_2232h_baud_base_to_divisor(int baud, int base)
847{
848 static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 };
849 __u32 divisor;
850 int divisor3;
851
852 /* hi-speed baud rate is 10-bit sampling instead of 16-bit */
853 divisor3 = (base / 10 / baud) * 8;
854
855 divisor = divisor3 >> 3;
856 divisor |= (__u32)divfrac[divisor3 & 0x7] << 14;
857 /* Deal with special cases for highest baud rates. */
858 if (divisor == 1)
859 divisor = 0;
860 else if (divisor == 0x4001)
861 divisor = 1;
862 /*
863 * Set this bit to turn off a divide by 2.5 on baud rate generator
864 * This enables baud rates up to 12Mbaud but cannot reach below 1200
865 * baud with this bit set
866 */
867 divisor |= 0x00020000;
868 return divisor;
869}
870
871static __u32 ftdi_2232h_baud_to_divisor(int baud)
872{
873 return ftdi_2232h_baud_base_to_divisor(baud, 120000000);
874}
875
841#define set_mctrl(port, set) update_mctrl((port), (set), 0) 876#define set_mctrl(port, set) update_mctrl((port), (set), 0)
842#define clear_mctrl(port, clear) update_mctrl((port), 0, (clear)) 877#define clear_mctrl(port, clear) update_mctrl((port), 0, (clear))
843 878
@@ -996,6 +1031,19 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
996 baud = 9600; 1031 baud = 9600;
997 } 1032 }
998 break; 1033 break;
1034 case FT2232H: /* FT2232H chip */
1035 case FT4232H: /* FT4232H chip */
1036 if ((baud <= 12000000) & (baud >= 1200)) {
1037 div_value = ftdi_2232h_baud_to_divisor(baud);
1038 } else if (baud < 1200) {
1039 div_value = ftdi_232bm_baud_to_divisor(baud);
1040 } else {
1041 dbg("%s - Baud rate too high!", __func__);
1042 div_value = ftdi_232bm_baud_to_divisor(9600);
1043 div_okay = 0;
1044 baud = 9600;
1045 }
1046 break;
999 } /* priv->chip_type */ 1047 } /* priv->chip_type */
1000 1048
1001 if (div_okay) { 1049 if (div_okay) {
@@ -1196,14 +1244,29 @@ static void ftdi_determine_type(struct usb_serial_port *port)
1196 if (interfaces > 1) { 1244 if (interfaces > 1) {
1197 int inter; 1245 int inter;
1198 1246
1199 /* Multiple interfaces. Assume FT2232C. */ 1247 /* Multiple interfaces.*/
1200 priv->chip_type = FT2232C; 1248 if (version == 0x0800) {
1249 priv->chip_type = FT4232H;
1250 /* Hi-speed - baud clock runs at 120MHz */
1251 priv->baud_base = 120000000 / 2;
1252 } else if (version == 0x0700) {
1253 priv->chip_type = FT2232H;
1254 /* Hi-speed - baud clock runs at 120MHz */
1255 priv->baud_base = 120000000 / 2;
1256 } else
1257 priv->chip_type = FT2232C;
1258
1201 /* Determine interface code. */ 1259 /* Determine interface code. */
1202 inter = serial->interface->altsetting->desc.bInterfaceNumber; 1260 inter = serial->interface->altsetting->desc.bInterfaceNumber;
1203 if (inter == 0) 1261 if (inter == 0) {
1204 priv->interface = PIT_SIOA; 1262 priv->interface = INTERFACE_A;
1205 else 1263 } else if (inter == 1) {
1206 priv->interface = PIT_SIOB; 1264 priv->interface = INTERFACE_B;
1265 } else if (inter == 2) {
1266 priv->interface = INTERFACE_C;
1267 } else if (inter == 3) {
1268 priv->interface = INTERFACE_D;
1269 }
1207 /* BM-type devices have a bug where bcdDevice gets set 1270 /* BM-type devices have a bug where bcdDevice gets set
1208 * to 0x200 when iSerialNumber is 0. */ 1271 * to 0x200 when iSerialNumber is 0. */
1209 if (version < 0x500) { 1272 if (version < 0x500) {
@@ -1231,6 +1294,45 @@ static void ftdi_determine_type(struct usb_serial_port *port)
1231} 1294}
1232 1295
1233 1296
1297/* Determine the maximum packet size for the device. This depends on the chip
1298 * type and the USB host capabilities. The value should be obtained from the
1299 * device descriptor as the chip will use the appropriate values for the host.*/
1300static void ftdi_set_max_packet_size(struct usb_serial_port *port)
1301{
1302 struct ftdi_private *priv = usb_get_serial_port_data(port);
1303 struct usb_serial *serial = port->serial;
1304 struct usb_device *udev = serial->dev;
1305
1306 struct usb_interface *interface = serial->interface;
1307 struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc;
1308
1309 unsigned num_endpoints;
1310 int i = 0;
1311
1312 num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;
1313 dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);
1314
1315 /* NOTE: some customers have programmed FT232R/FT245R devices
1316 * with an endpoint size of 0 - not good. In this case, we
1317 * want to override the endpoint descriptor setting and use a
1318 * value of 64 for wMaxPacketSize */
1319 for (i = 0; i < num_endpoints; i++) {
1320 dev_info(&udev->dev, "Endpoint %d MaxPacketSize %d\n", i+1,
1321 interface->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
1322 ep_desc = &interface->cur_altsetting->endpoint[i].desc;
1323 if (ep_desc->wMaxPacketSize == 0) {
1324 ep_desc->wMaxPacketSize = cpu_to_le16(0x40);
1325 dev_info(&udev->dev, "Overriding wMaxPacketSize on endpoint %d\n", i);
1326 }
1327 }
1328
1329 /* set max packet size based on descriptor */
1330 priv->max_packet_size = ep_desc->wMaxPacketSize;
1331
1332 dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
1333}
1334
1335
1234/* 1336/*
1235 * *************************************************************************** 1337 * ***************************************************************************
1236 * Sysfs Attribute 1338 * Sysfs Attribute
@@ -1314,7 +1416,9 @@ static int create_sysfs_attrs(struct usb_serial_port *port)
1314 if ((!retval) && 1416 if ((!retval) &&
1315 (priv->chip_type == FT232BM || 1417 (priv->chip_type == FT232BM ||
1316 priv->chip_type == FT2232C || 1418 priv->chip_type == FT2232C ||
1317 priv->chip_type == FT232RL)) { 1419 priv->chip_type == FT232RL ||
1420 priv->chip_type == FT2232H ||
1421 priv->chip_type == FT4232H)) {
1318 retval = device_create_file(&port->dev, 1422 retval = device_create_file(&port->dev,
1319 &dev_attr_latency_timer); 1423 &dev_attr_latency_timer);
1320 } 1424 }
@@ -1333,7 +1437,9 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
1333 device_remove_file(&port->dev, &dev_attr_event_char); 1437 device_remove_file(&port->dev, &dev_attr_event_char);
1334 if (priv->chip_type == FT232BM || 1438 if (priv->chip_type == FT232BM ||
1335 priv->chip_type == FT2232C || 1439 priv->chip_type == FT2232C ||
1336 priv->chip_type == FT232RL) { 1440 priv->chip_type == FT232RL ||
1441 priv->chip_type == FT2232H ||
1442 priv->chip_type == FT4232H) {
1337 device_remove_file(&port->dev, &dev_attr_latency_timer); 1443 device_remove_file(&port->dev, &dev_attr_latency_timer);
1338 } 1444 }
1339 } 1445 }
@@ -1416,6 +1522,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
1416 usb_set_serial_port_data(port, priv); 1522 usb_set_serial_port_data(port, priv);
1417 1523
1418 ftdi_determine_type(port); 1524 ftdi_determine_type(port);
1525 ftdi_set_max_packet_size(port);
1419 read_latency_timer(port); 1526 read_latency_timer(port);
1420 create_sysfs_attrs(port); 1527 create_sysfs_attrs(port);
1421 return 0; 1528 return 0;
@@ -1485,18 +1592,6 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
1485 return 0; 1592 return 0;
1486} 1593}
1487 1594
1488/* ftdi_shutdown is called from usbserial:usb_serial_disconnect
1489 * it is called when the usb device is disconnected
1490 *
1491 * usbserial:usb_serial_disconnect
1492 * calls __serial_close for each open of the port
1493 * shutdown is called then (ie ftdi_shutdown)
1494 */
1495static void ftdi_shutdown(struct usb_serial *serial)
1496{
1497 dbg("%s", __func__);
1498}
1499
1500static void ftdi_sio_priv_release(struct kref *k) 1595static void ftdi_sio_priv_release(struct kref *k)
1501{ 1596{
1502 struct ftdi_private *priv = container_of(k, struct ftdi_private, kref); 1597 struct ftdi_private *priv = container_of(k, struct ftdi_private, kref);
@@ -1671,8 +1766,8 @@ static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
1671 if (data_offset > 0) { 1766 if (data_offset > 0) {
1672 /* Original sio needs control bytes too... */ 1767 /* Original sio needs control bytes too... */
1673 transfer_size += (data_offset * 1768 transfer_size += (data_offset *
1674 ((count + (PKTSZ - 1 - data_offset)) / 1769 ((count + (priv->max_packet_size - 1 - data_offset)) /
1675 (PKTSZ - data_offset))); 1770 (priv->max_packet_size - data_offset)));
1676 } 1771 }
1677 1772
1678 buffer = kmalloc(transfer_size, GFP_ATOMIC); 1773 buffer = kmalloc(transfer_size, GFP_ATOMIC);
@@ -1694,7 +1789,7 @@ static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
1694 if (data_offset > 0) { 1789 if (data_offset > 0) {
1695 /* Original sio requires control byte at start of 1790 /* Original sio requires control byte at start of
1696 each packet. */ 1791 each packet. */
1697 int user_pktsz = PKTSZ - data_offset; 1792 int user_pktsz = priv->max_packet_size - data_offset;
1698 int todo = count; 1793 int todo = count;
1699 unsigned char *first_byte = buffer; 1794 unsigned char *first_byte = buffer;
1700 const unsigned char *current_position = buf; 1795 const unsigned char *current_position = buf;
@@ -1775,11 +1870,6 @@ static void ftdi_write_bulk_callback(struct urb *urb)
1775 1870
1776 dbg("%s - port %d", __func__, port->number); 1871 dbg("%s - port %d", __func__, port->number);
1777 1872
1778 if (status) {
1779 dbg("nonzero write bulk status received: %d", status);
1780 return;
1781 }
1782
1783 priv = usb_get_serial_port_data(port); 1873 priv = usb_get_serial_port_data(port);
1784 if (!priv) { 1874 if (!priv) {
1785 dbg("%s - bad port private data pointer - exiting", __func__); 1875 dbg("%s - bad port private data pointer - exiting", __func__);
@@ -1790,13 +1880,18 @@ static void ftdi_write_bulk_callback(struct urb *urb)
1790 data_offset = priv->write_offset; 1880 data_offset = priv->write_offset;
1791 if (data_offset > 0) { 1881 if (data_offset > 0) {
1792 /* Subtract the control bytes */ 1882 /* Subtract the control bytes */
1793 countback -= (data_offset * DIV_ROUND_UP(countback, PKTSZ)); 1883 countback -= (data_offset * DIV_ROUND_UP(countback, priv->max_packet_size));
1794 } 1884 }
1795 spin_lock_irqsave(&priv->tx_lock, flags); 1885 spin_lock_irqsave(&priv->tx_lock, flags);
1796 --priv->tx_outstanding_urbs; 1886 --priv->tx_outstanding_urbs;
1797 priv->tx_outstanding_bytes -= countback; 1887 priv->tx_outstanding_bytes -= countback;
1798 spin_unlock_irqrestore(&priv->tx_lock, flags); 1888 spin_unlock_irqrestore(&priv->tx_lock, flags);
1799 1889
1890 if (status) {
1891 dbg("nonzero write bulk status received: %d", status);
1892 return;
1893 }
1894
1800 usb_serial_port_softint(port); 1895 usb_serial_port_softint(port);
1801} /* ftdi_write_bulk_callback */ 1896} /* ftdi_write_bulk_callback */
1802 1897
@@ -1892,7 +1987,7 @@ static void ftdi_read_bulk_callback(struct urb *urb)
1892 1987
1893 /* count data bytes, but not status bytes */ 1988 /* count data bytes, but not status bytes */
1894 countread = urb->actual_length; 1989 countread = urb->actual_length;
1895 countread -= 2 * DIV_ROUND_UP(countread, PKTSZ); 1990 countread -= 2 * DIV_ROUND_UP(countread, priv->max_packet_size);
1896 spin_lock_irqsave(&priv->rx_lock, flags); 1991 spin_lock_irqsave(&priv->rx_lock, flags);
1897 priv->rx_bytes += countread; 1992 priv->rx_bytes += countread;
1898 spin_unlock_irqrestore(&priv->rx_lock, flags); 1993 spin_unlock_irqrestore(&priv->rx_lock, flags);
@@ -1965,7 +2060,7 @@ static void ftdi_process_read(struct work_struct *work)
1965 2060
1966 need_flip = 0; 2061 need_flip = 0;
1967 for (packet_offset = priv->rx_processed; 2062 for (packet_offset = priv->rx_processed;
1968 packet_offset < urb->actual_length; packet_offset += PKTSZ) { 2063 packet_offset < urb->actual_length; packet_offset += priv->max_packet_size) {
1969 int length; 2064 int length;
1970 2065
1971 /* Compare new line status to the old one, signal if different/ 2066 /* Compare new line status to the old one, signal if different/
@@ -1980,7 +2075,7 @@ static void ftdi_process_read(struct work_struct *work)
1980 priv->prev_status = new_status; 2075 priv->prev_status = new_status;
1981 } 2076 }
1982 2077
1983 length = min_t(u32, PKTSZ, urb->actual_length-packet_offset)-2; 2078 length = min_t(u32, priv->max_packet_size, urb->actual_length-packet_offset)-2;
1984 if (length < 0) { 2079 if (length < 0) {
1985 dev_err(&port->dev, "%s - bad packet length: %d\n", 2080 dev_err(&port->dev, "%s - bad packet length: %d\n",
1986 __func__, length+2); 2081 __func__, length+2);
@@ -2011,6 +2106,7 @@ static void ftdi_process_read(struct work_struct *work)
2011 if (data[packet_offset+1] & FTDI_RS_BI) { 2106 if (data[packet_offset+1] & FTDI_RS_BI) {
2012 error_flag = TTY_BREAK; 2107 error_flag = TTY_BREAK;
2013 dbg("BREAK received"); 2108 dbg("BREAK received");
2109 usb_serial_handle_break(port);
2014 } 2110 }
2015 if (data[packet_offset+1] & FTDI_RS_PE) { 2111 if (data[packet_offset+1] & FTDI_RS_PE) {
2016 error_flag = TTY_PARITY; 2112 error_flag = TTY_PARITY;
@@ -2025,8 +2121,11 @@ static void ftdi_process_read(struct work_struct *work)
2025 /* Note that the error flag is duplicated for 2121 /* Note that the error flag is duplicated for
2026 every character received since we don't know 2122 every character received since we don't know
2027 which character it applied to */ 2123 which character it applied to */
2028 tty_insert_flip_char(tty, 2124 if (!usb_serial_handle_sysrq_char(port,
2029 data[packet_offset + i], error_flag); 2125 data[packet_offset + i]))
2126 tty_insert_flip_char(tty,
2127 data[packet_offset + i],
2128 error_flag);
2030 } 2129 }
2031 need_flip = 1; 2130 need_flip = 1;
2032 } 2131 }
@@ -2332,6 +2431,8 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)
2332 case FT232BM: 2431 case FT232BM:
2333 case FT2232C: 2432 case FT2232C:
2334 case FT232RL: 2433 case FT232RL:
2434 case FT2232H:
2435 case FT4232H:
2335 /* the 8U232AM returns a two byte value (the sio is a 1 byte 2436 /* the 8U232AM returns a two byte value (the sio is a 1 byte
2336 value) - in the same format as the data returned from the in 2437 value) - in the same format as the data returned from the in
2337 point */ 2438 point */