Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Navman Serial USB driver
0004  *
0005  * Copyright (C) 2006 Greg Kroah-Hartman <gregkh@suse.de>
0006  *
0007  * TODO:
0008  *  Add termios method that uses copy_hw but also kills all echo
0009  *  flags as the navman is rx only so cannot echo.
0010  */
0011 
0012 #include <linux/gfp.h>
0013 #include <linux/kernel.h>
0014 #include <linux/tty.h>
0015 #include <linux/tty_flip.h>
0016 #include <linux/module.h>
0017 #include <linux/usb.h>
0018 #include <linux/usb/serial.h>
0019 
0020 static const struct usb_device_id id_table[] = {
0021     { USB_DEVICE(0x0a99, 0x0001) }, /* Talon Technology device */
0022     { USB_DEVICE(0x0df7, 0x0900) }, /* Mobile Action i-gotU */
0023     { },
0024 };
0025 MODULE_DEVICE_TABLE(usb, id_table);
0026 
0027 static void navman_read_int_callback(struct urb *urb)
0028 {
0029     struct usb_serial_port *port = urb->context;
0030     unsigned char *data = urb->transfer_buffer;
0031     int status = urb->status;
0032     int result;
0033 
0034     switch (status) {
0035     case 0:
0036         /* success */
0037         break;
0038     case -ECONNRESET:
0039     case -ENOENT:
0040     case -ESHUTDOWN:
0041         /* this urb is terminated, clean up */
0042         dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
0043             __func__, status);
0044         return;
0045     default:
0046         dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
0047             __func__, status);
0048         goto exit;
0049     }
0050 
0051     usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
0052 
0053     if (urb->actual_length) {
0054         tty_insert_flip_string(&port->port, data, urb->actual_length);
0055         tty_flip_buffer_push(&port->port);
0056     }
0057 
0058 exit:
0059     result = usb_submit_urb(urb, GFP_ATOMIC);
0060     if (result)
0061         dev_err(&urb->dev->dev,
0062             "%s - Error %d submitting interrupt urb\n",
0063             __func__, result);
0064 }
0065 
0066 static int navman_open(struct tty_struct *tty, struct usb_serial_port *port)
0067 {
0068     int result = 0;
0069 
0070     if (port->interrupt_in_urb) {
0071         dev_dbg(&port->dev, "%s - adding interrupt input for treo\n",
0072             __func__);
0073         result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
0074         if (result)
0075             dev_err(&port->dev,
0076                 "%s - failed submitting interrupt urb, error %d\n",
0077                 __func__, result);
0078     }
0079     return result;
0080 }
0081 
0082 static void navman_close(struct usb_serial_port *port)
0083 {
0084     usb_kill_urb(port->interrupt_in_urb);
0085 }
0086 
0087 static int navman_write(struct tty_struct *tty, struct usb_serial_port *port,
0088             const unsigned char *buf, int count)
0089 {
0090     /*
0091      * This device can't write any data, only read from the device
0092      */
0093     return -EOPNOTSUPP;
0094 }
0095 
0096 static struct usb_serial_driver navman_device = {
0097     .driver = {
0098         .owner =    THIS_MODULE,
0099         .name =     "navman",
0100     },
0101     .id_table =     id_table,
0102     .num_ports =        1,
0103     .open =         navman_open,
0104     .close =        navman_close,
0105     .write =        navman_write,
0106     .read_int_callback =    navman_read_int_callback,
0107 };
0108 
0109 static struct usb_serial_driver * const serial_drivers[] = {
0110     &navman_device, NULL
0111 };
0112 
0113 module_usb_serial_driver(serial_drivers, id_table);
0114 
0115 MODULE_LICENSE("GPL v2");