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.c185
1 files changed, 155 insertions, 30 deletions
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 763e32a44be0..0d47f2c4d59f 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 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);
@@ -106,7 +109,7 @@ static void mos7720_interrupt_callback(struct urb *urb)
106 __u8 sp1; 109 __u8 sp1;
107 __u8 sp2; 110 __u8 sp2;
108 111
109 dbg("%s", " : Entering\n"); 112 dbg(" : Entering");
110 113
111 switch (status) { 114 switch (status) {
112 case 0: 115 case 0:
@@ -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.
@@ -206,7 +278,7 @@ static void mos7720_bulk_in_callback(struct urb *urb)
206 278
207 mos7720_port = urb->context; 279 mos7720_port = urb->context;
208 if (!mos7720_port) { 280 if (!mos7720_port) {
209 dbg("%s", "NULL mos7720_port pointer \n"); 281 dbg("NULL mos7720_port pointer");
210 return ; 282 return ;
211 } 283 }
212 284
@@ -218,7 +290,6 @@ static void mos7720_bulk_in_callback(struct urb *urb)
218 290
219 tty = tty_port_tty_get(&port->port); 291 tty = tty_port_tty_get(&port->port);
220 if (tty && urb->actual_length) { 292 if (tty && urb->actual_length) {
221 tty_buffer_request_room(tty, urb->actual_length);
222 tty_insert_flip_string(tty, data, urb->actual_length); 293 tty_insert_flip_string(tty, data, urb->actual_length);
223 tty_flip_buffer_push(tty); 294 tty_flip_buffer_push(tty);
224 } 295 }
@@ -275,17 +346,15 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)
275 * this function will be used for sending command to device 346 * this function will be used for sending command to device
276 */ 347 */
277static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value, 348static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value,
278 __u16 index, void *data) 349 __u16 index, u8 *data)
279{ 350{
280 int status; 351 int status;
281 unsigned int pipe; 352 u8 *buf;
282 u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); 353 u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
283 __u8 requesttype;
284 __u16 size = 0x0000;
285 354
286 if (value < MOS_MAX_PORT) { 355 if (value < MOS_MAX_PORT) {
287 if (product == MOSCHIP_DEVICE_ID_7715) 356 if (product == MOSCHIP_DEVICE_ID_7715)
288 value = value*0x100+0x100; 357 value = 0x0200; /* identifies the 7715's serial port */
289 else 358 else
290 value = value*0x100+0x200; 359 value = value*0x100+0x200;
291 } else { 360 } else {
@@ -298,27 +367,58 @@ static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value,
298 } 367 }
299 368
300 if (request == MOS_WRITE) { 369 if (request == MOS_WRITE) {
301 request = (__u8)MOS_WRITE; 370 value = value + *data;
302 requesttype = (__u8)0x40; 371 status = usb_control_msg(serial->dev,
303 value = value + (__u16)*((unsigned char *)data); 372 usb_sndctrlpipe(serial->dev, 0), MOS_WRITE,
304 data = NULL; 373 0x40, value, index, NULL, 0, MOS_WDR_TIMEOUT);
305 pipe = usb_sndctrlpipe(serial->dev, 0);
306 } else { 374 } else {
307 request = (__u8)MOS_READ; 375 buf = kmalloc(1, GFP_KERNEL);
308 requesttype = (__u8)0xC0; 376 if (!buf) {
309 size = 0x01; 377 status = -ENOMEM;
310 pipe = usb_rcvctrlpipe(serial->dev, 0); 378 goto out;
379 }
380 status = usb_control_msg(serial->dev,
381 usb_rcvctrlpipe(serial->dev, 0), MOS_READ,
382 0xc0, value, index, buf, 1, MOS_WDR_TIMEOUT);
383 *data = *buf;
384 kfree(buf);
311 } 385 }
312 386out:
313 status = usb_control_msg(serial->dev, pipe, request, requesttype,
314 value, index, data, size, MOS_WDR_TIMEOUT);
315
316 if (status < 0) 387 if (status < 0)
317 dbg("Command Write failed Value %x index %x\n", value, index); 388 dbg("Command Write failed Value %x index %x", value, index);
318 389
319 return status; 390 return status;
320} 391}
321 392
393
394/*
395 * mos77xx_probe
396 * this function installs the appropriate read interrupt endpoint callback
397 * depending on whether the device is a 7720 or 7715, thus avoiding costly
398 * run-time checks in the high-frequency callback routine itself.
399 */
400static int mos77xx_probe(struct usb_serial *serial,
401 const struct usb_device_id *id)
402{
403 if (id->idProduct == MOSCHIP_DEVICE_ID_7715)
404 moschip7720_2port_driver.read_int_callback =
405 mos7715_interrupt_callback;
406 else
407 moschip7720_2port_driver.read_int_callback =
408 mos7720_interrupt_callback;
409
410 return 0;
411}
412
413static int mos77xx_calc_num_ports(struct usb_serial *serial)
414{
415 u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
416 if (product == MOSCHIP_DEVICE_ID_7715)
417 return 1;
418
419 return 2;
420}
421
322static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port) 422static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)
323{ 423{
324 struct usb_serial *serial; 424 struct usb_serial *serial;
@@ -390,7 +490,7 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)
390 */ 490 */
391 port_number = port->number - port->serial->minor; 491 port_number = port->number - port->serial->minor;
392 send_mos_cmd(port->serial, MOS_READ, port_number, UART_LSR, &data); 492 send_mos_cmd(port->serial, MOS_READ, port_number, UART_LSR, &data);
393 dbg("SS::%p LSR:%x\n", mos7720_port, data); 493 dbg("SS::%p LSR:%x", mos7720_port, data);
394 494
395 dbg("Check:Sending Command .........."); 495 dbg("Check:Sending Command ..........");
396 496
@@ -729,7 +829,7 @@ static void mos7720_throttle(struct tty_struct *tty)
729 struct moschip_port *mos7720_port; 829 struct moschip_port *mos7720_port;
730 int status; 830 int status;
731 831
732 dbg("%s- port %d\n", __func__, port->number); 832 dbg("%s- port %d", __func__, port->number);
733 833
734 mos7720_port = usb_get_serial_port_data(port); 834 mos7720_port = usb_get_serial_port_data(port);
735 835
@@ -1208,7 +1308,7 @@ static void mos7720_set_termios(struct tty_struct *tty,
1208 return; 1308 return;
1209 } 1309 }
1210 1310
1211 dbg("%s\n", "setting termios - ASPIRE"); 1311 dbg("setting termios - ASPIRE");
1212 1312
1213 cflag = tty->termios->c_cflag; 1313 cflag = tty->termios->c_cflag;
1214 1314
@@ -1226,7 +1326,7 @@ static void mos7720_set_termios(struct tty_struct *tty,
1226 change_port_settings(tty, mos7720_port, old_termios); 1326 change_port_settings(tty, mos7720_port, old_termios);
1227 1327
1228 if (!port->read_urb) { 1328 if (!port->read_urb) {
1229 dbg("%s", "URB KILLED !!!!!\n"); 1329 dbg("URB KILLED !!!!!");
1230 return; 1330 return;
1231 } 1331 }
1232 1332
@@ -1495,6 +1595,7 @@ static int mos7720_startup(struct usb_serial *serial)
1495 struct usb_device *dev; 1595 struct usb_device *dev;
1496 int i; 1596 int i;
1497 char data; 1597 char data;
1598 u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
1498 1599
1499 dbg("%s: Entering ..........", __func__); 1600 dbg("%s: Entering ..........", __func__);
1500 1601
@@ -1514,6 +1615,29 @@ static int mos7720_startup(struct usb_serial *serial)
1514 1615
1515 usb_set_serial_data(serial, mos7720_serial); 1616 usb_set_serial_data(serial, mos7720_serial);
1516 1617
1618 /*
1619 * The 7715 uses the first bulk in/out endpoint pair for the parallel
1620 * port, and the second for the serial port. Because the usbserial core
1621 * assumes both pairs are serial ports, we must engage in a bit of
1622 * subterfuge and swap the pointers for ports 0 and 1 in order to make
1623 * port 0 point to the serial port. However, both moschip devices use a
1624 * single interrupt-in endpoint for both ports (as mentioned a little
1625 * further down), and this endpoint was assigned to port 0. So after
1626 * the swap, we must copy the interrupt endpoint elements from port 1
1627 * (as newly assigned) to port 0, and null out port 1 pointers.
1628 */
1629 if (product == MOSCHIP_DEVICE_ID_7715) {
1630 struct usb_serial_port *tmp = serial->port[0];
1631 serial->port[0] = serial->port[1];
1632 serial->port[1] = tmp;
1633 serial->port[0]->interrupt_in_urb = tmp->interrupt_in_urb;
1634 serial->port[0]->interrupt_in_buffer = tmp->interrupt_in_buffer;
1635 serial->port[0]->interrupt_in_endpointAddress =
1636 tmp->interrupt_in_endpointAddress;
1637 serial->port[1]->interrupt_in_urb = NULL;
1638 serial->port[1]->interrupt_in_buffer = NULL;
1639 }
1640
1517 /* we set up the pointers to the endpoints in the mos7720_open * 1641 /* we set up the pointers to the endpoints in the mos7720_open *
1518 * function, as the structures aren't created yet. */ 1642 * function, as the structures aren't created yet. */
1519 1643
@@ -1529,7 +1653,7 @@ static int mos7720_startup(struct usb_serial *serial)
1529 1653
1530 /* Initialize all port interrupt end point to port 0 int 1654 /* Initialize all port interrupt end point to port 0 int
1531 * endpoint. Our device has only one interrupt endpoint 1655 * endpoint. Our device has only one interrupt endpoint
1532 * comman to all ports */ 1656 * common to all ports */
1533 serial->port[i]->interrupt_in_endpointAddress = 1657 serial->port[i]->interrupt_in_endpointAddress =
1534 serial->port[0]->interrupt_in_endpointAddress; 1658 serial->port[0]->interrupt_in_endpointAddress;
1535 1659
@@ -1584,11 +1708,12 @@ static struct usb_serial_driver moschip7720_2port_driver = {
1584 .description = "Moschip 2 port adapter", 1708 .description = "Moschip 2 port adapter",
1585 .usb_driver = &usb_driver, 1709 .usb_driver = &usb_driver,
1586 .id_table = moschip_port_id_table, 1710 .id_table = moschip_port_id_table,
1587 .num_ports = 2, 1711 .calc_num_ports = mos77xx_calc_num_ports,
1588 .open = mos7720_open, 1712 .open = mos7720_open,
1589 .close = mos7720_close, 1713 .close = mos7720_close,
1590 .throttle = mos7720_throttle, 1714 .throttle = mos7720_throttle,
1591 .unthrottle = mos7720_unthrottle, 1715 .unthrottle = mos7720_unthrottle,
1716 .probe = mos77xx_probe,
1592 .attach = mos7720_startup, 1717 .attach = mos7720_startup,
1593 .release = mos7720_release, 1718 .release = mos7720_release,
1594 .ioctl = mos7720_ioctl, 1719 .ioctl = mos7720_ioctl,
@@ -1600,7 +1725,7 @@ static struct usb_serial_driver moschip7720_2port_driver = {
1600 .chars_in_buffer = mos7720_chars_in_buffer, 1725 .chars_in_buffer = mos7720_chars_in_buffer,
1601 .break_ctl = mos7720_break, 1726 .break_ctl = mos7720_break,
1602 .read_bulk_callback = mos7720_bulk_in_callback, 1727 .read_bulk_callback = mos7720_bulk_in_callback,
1603 .read_int_callback = mos7720_interrupt_callback, 1728 .read_int_callback = NULL /* dynamically assigned in probe() */
1604}; 1729};
1605 1730
1606static int __init moschip7720_init(void) 1731static int __init moschip7720_init(void)