aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/mos7720.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/mos7720.c')
-rw-r--r--drivers/usb/serial/mos7720.c134
1 files changed, 130 insertions, 4 deletions
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 2ce1a2acf1a8..e0aa031c5418 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -81,12 +81,15 @@ struct moschip_serial {
81 81
82static int debug; 82static int debug;
83 83
84static struct usb_serial_driver moschip7720_2port_driver;
85
84#define USB_VENDOR_ID_MOSCHIP 0x9710 86#define USB_VENDOR_ID_MOSCHIP 0x9710
85#define MOSCHIP_DEVICE_ID_7720 0x7720 87#define MOSCHIP_DEVICE_ID_7720 0x7720
86#define MOSCHIP_DEVICE_ID_7715 0x7715 88#define MOSCHIP_DEVICE_ID_7715 0x7715
87 89
88static const struct usb_device_id moschip_port_id_table[] = { 90static const struct usb_device_id moschip_port_id_table[] = {
89 { USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7720) }, 91 { USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7720) },
92 { USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7715) },
90 { } /* terminating entry */ 93 { } /* terminating entry */
91}; 94};
92MODULE_DEVICE_TABLE(usb, moschip_port_id_table); 95MODULE_DEVICE_TABLE(usb, moschip_port_id_table);
@@ -186,6 +189,75 @@ exit:
186} 189}
187 190
188/* 191/*
192 * mos7715_interrupt_callback
193 * this is the 7715's callback function for when we have received data on
194 * the interrupt endpoint.
195 */
196static void mos7715_interrupt_callback(struct urb *urb)
197{
198 int result;
199 int length;
200 int status = urb->status;
201 __u8 *data;
202 __u8 iir;
203
204 switch (status) {
205 case 0:
206 /* success */
207 break;
208 case -ECONNRESET:
209 case -ENOENT:
210 case -ESHUTDOWN:
211 /* this urb is terminated, clean up */
212 dbg("%s - urb shutting down with status: %d", __func__,
213 status);
214 return;
215 default:
216 dbg("%s - nonzero urb status received: %d", __func__,
217 status);
218 goto exit;
219 }
220
221 length = urb->actual_length;
222 data = urb->transfer_buffer;
223
224 /* Structure of data from 7715 device:
225 * Byte 1: IIR serial Port
226 * Byte 2: unused
227 * Byte 2: DSR parallel port
228 * Byte 4: FIFO status for both */
229
230 if (unlikely(length != 4)) {
231 dbg("Wrong data !!!");
232 return;
233 }
234
235 iir = data[0];
236 if (!(iir & 0x01)) { /* serial port interrupt pending */
237 switch (iir & 0x0f) {
238 case SERIAL_IIR_RLS:
239 dbg("Serial Port: Receiver status error or address "
240 "bit detected in 9-bit mode\n");
241 break;
242 case SERIAL_IIR_CTI:
243 dbg("Serial Port: Receiver time out");
244 break;
245 case SERIAL_IIR_MS:
246 dbg("Serial Port: Modem status change");
247 break;
248 }
249 }
250
251exit:
252 result = usb_submit_urb(urb, GFP_ATOMIC);
253 if (result)
254 dev_err(&urb->dev->dev,
255 "%s - Error %d submitting control urb\n",
256 __func__, result);
257 return;
258}
259
260/*
189 * mos7720_bulk_in_callback 261 * mos7720_bulk_in_callback
190 * this is the callback function for when we have received data on the 262 * this is the callback function for when we have received data on the
191 * bulk in endpoint. 263 * bulk in endpoint.
@@ -283,7 +355,7 @@ static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value,
283 355
284 if (value < MOS_MAX_PORT) { 356 if (value < MOS_MAX_PORT) {
285 if (product == MOSCHIP_DEVICE_ID_7715) 357 if (product == MOSCHIP_DEVICE_ID_7715)
286 value = value*0x100+0x100; 358 value = 0x0200; /* identifies the 7715's serial port */
287 else 359 else
288 value = value*0x100+0x200; 360 value = value*0x100+0x200;
289 } else { 361 } else {
@@ -319,6 +391,35 @@ out:
319 return status; 391 return status;
320} 392}
321 393
394
395/*
396 * mos77xx_probe
397 * this function installs the appropriate read interrupt endpoint callback
398 * depending on whether the device is a 7720 or 7715, thus avoiding costly
399 * run-time checks in the high-frequency callback routine itself.
400 */
401static int mos77xx_probe(struct usb_serial *serial,
402 const struct usb_device_id *id)
403{
404 if (id->idProduct == MOSCHIP_DEVICE_ID_7715)
405 moschip7720_2port_driver.read_int_callback =
406 mos7715_interrupt_callback;
407 else
408 moschip7720_2port_driver.read_int_callback =
409 mos7720_interrupt_callback;
410
411 return 0;
412}
413
414static int mos77xx_calc_num_ports(struct usb_serial *serial)
415{
416 u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
417 if (product == MOSCHIP_DEVICE_ID_7715)
418 return 1;
419
420 return 2;
421}
422
322static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port) 423static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)
323{ 424{
324 struct usb_serial *serial; 425 struct usb_serial *serial;
@@ -1495,6 +1596,7 @@ static int mos7720_startup(struct usb_serial *serial)
1495 struct usb_device *dev; 1596 struct usb_device *dev;
1496 int i; 1597 int i;
1497 char data; 1598 char data;
1599 u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
1498 1600
1499 dbg("%s: Entering ..........", __func__); 1601 dbg("%s: Entering ..........", __func__);
1500 1602
@@ -1514,6 +1616,29 @@ static int mos7720_startup(struct usb_serial *serial)
1514 1616
1515 usb_set_serial_data(serial, mos7720_serial); 1617 usb_set_serial_data(serial, mos7720_serial);
1516 1618
1619 /*
1620 * The 7715 uses the first bulk in/out endpoint pair for the parallel
1621 * port, and the second for the serial port. Because the usbserial core
1622 * assumes both pairs are serial ports, we must engage in a bit of
1623 * subterfuge and swap the pointers for ports 0 and 1 in order to make
1624 * port 0 point to the serial port. However, both moschip devices use a
1625 * single interrupt-in endpoint for both ports (as mentioned a little
1626 * further down), and this endpoint was assigned to port 0. So after
1627 * the swap, we must copy the interrupt endpoint elements from port 1
1628 * (as newly assigned) to port 0, and null out port 1 pointers.
1629 */
1630 if (product == MOSCHIP_DEVICE_ID_7715) {
1631 struct usb_serial_port *tmp = serial->port[0];
1632 serial->port[0] = serial->port[1];
1633 serial->port[1] = tmp;
1634 serial->port[0]->interrupt_in_urb = tmp->interrupt_in_urb;
1635 serial->port[0]->interrupt_in_buffer = tmp->interrupt_in_buffer;
1636 serial->port[0]->interrupt_in_endpointAddress =
1637 tmp->interrupt_in_endpointAddress;
1638 serial->port[1]->interrupt_in_urb = NULL;
1639 serial->port[1]->interrupt_in_buffer = NULL;
1640 }
1641
1517 /* we set up the pointers to the endpoints in the mos7720_open * 1642 /* we set up the pointers to the endpoints in the mos7720_open *
1518 * function, as the structures aren't created yet. */ 1643 * function, as the structures aren't created yet. */
1519 1644
@@ -1529,7 +1654,7 @@ static int mos7720_startup(struct usb_serial *serial)
1529 1654
1530 /* Initialize all port interrupt end point to port 0 int 1655 /* Initialize all port interrupt end point to port 0 int
1531 * endpoint. Our device has only one interrupt endpoint 1656 * endpoint. Our device has only one interrupt endpoint
1532 * comman to all ports */ 1657 * common to all ports */
1533 serial->port[i]->interrupt_in_endpointAddress = 1658 serial->port[i]->interrupt_in_endpointAddress =
1534 serial->port[0]->interrupt_in_endpointAddress; 1659 serial->port[0]->interrupt_in_endpointAddress;
1535 1660
@@ -1584,11 +1709,12 @@ static struct usb_serial_driver moschip7720_2port_driver = {
1584 .description = "Moschip 2 port adapter", 1709 .description = "Moschip 2 port adapter",
1585 .usb_driver = &usb_driver, 1710 .usb_driver = &usb_driver,
1586 .id_table = moschip_port_id_table, 1711 .id_table = moschip_port_id_table,
1587 .num_ports = 2, 1712 .calc_num_ports = mos77xx_calc_num_ports,
1588 .open = mos7720_open, 1713 .open = mos7720_open,
1589 .close = mos7720_close, 1714 .close = mos7720_close,
1590 .throttle = mos7720_throttle, 1715 .throttle = mos7720_throttle,
1591 .unthrottle = mos7720_unthrottle, 1716 .unthrottle = mos7720_unthrottle,
1717 .probe = mos77xx_probe,
1592 .attach = mos7720_startup, 1718 .attach = mos7720_startup,
1593 .release = mos7720_release, 1719 .release = mos7720_release,
1594 .ioctl = mos7720_ioctl, 1720 .ioctl = mos7720_ioctl,
@@ -1600,7 +1726,7 @@ static struct usb_serial_driver moschip7720_2port_driver = {
1600 .chars_in_buffer = mos7720_chars_in_buffer, 1726 .chars_in_buffer = mos7720_chars_in_buffer,
1601 .break_ctl = mos7720_break, 1727 .break_ctl = mos7720_break,
1602 .read_bulk_callback = mos7720_bulk_in_callback, 1728 .read_bulk_callback = mos7720_bulk_in_callback,
1603 .read_int_callback = mos7720_interrupt_callback, 1729 .read_int_callback = NULL /* dynamically assigned in probe() */
1604}; 1730};
1605 1731
1606static int __init moschip7720_init(void) 1732static int __init moschip7720_init(void)