hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// SPDX-License-Identifier: GPL-2.0
/*
 * Navman Serial USB driver
 *
 * Copyright (C) 2006 Greg Kroah-Hartman <gregkh@suse.de>
 *
 * TODO:
 *    Add termios method that uses copy_hw but also kills all echo
 *    flags as the navman is rx only so cannot echo.
 */
 
#include <linux/gfp.h>
#include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
 
static const struct usb_device_id id_table[] = {
   { USB_DEVICE(0x0a99, 0x0001) },    /* Talon Technology device */
   { USB_DEVICE(0x0df7, 0x0900) },    /* Mobile Action i-gotU */
   { },
};
MODULE_DEVICE_TABLE(usb, id_table);
 
static void navman_read_int_callback(struct urb *urb)
{
   struct usb_serial_port *port = urb->context;
   unsigned char *data = urb->transfer_buffer;
   int status = urb->status;
   int result;
 
   switch (status) {
   case 0:
       /* success */
       break;
   case -ECONNRESET:
   case -ENOENT:
   case -ESHUTDOWN:
       /* this urb is terminated, clean up */
       dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
           __func__, status);
       return;
   default:
       dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
           __func__, status);
       goto exit;
   }
 
   usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
 
   if (urb->actual_length) {
       tty_insert_flip_string(&port->port, data, urb->actual_length);
       tty_flip_buffer_push(&port->port);
   }
 
exit:
   result = usb_submit_urb(urb, GFP_ATOMIC);
   if (result)
       dev_err(&urb->dev->dev,
           "%s - Error %d submitting interrupt urb\n",
           __func__, result);
}
 
static int navman_open(struct tty_struct *tty, struct usb_serial_port *port)
{
   int result = 0;
 
   if (port->interrupt_in_urb) {
       dev_dbg(&port->dev, "%s - adding interrupt input for treo\n",
           __func__);
       result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
       if (result)
           dev_err(&port->dev,
               "%s - failed submitting interrupt urb, error %d\n",
               __func__, result);
   }
   return result;
}
 
static void navman_close(struct usb_serial_port *port)
{
   usb_kill_urb(port->interrupt_in_urb);
}
 
static int navman_write(struct tty_struct *tty, struct usb_serial_port *port,
           const unsigned char *buf, int count)
{
   /*
    * This device can't write any data, only read from the device
    */
   return -EOPNOTSUPP;
}
 
static struct usb_serial_driver navman_device = {
   .driver = {
       .owner =    THIS_MODULE,
       .name =        "navman",
   },
   .id_table =        id_table,
   .num_ports =        1,
   .open =            navman_open,
   .close =         navman_close,
   .write =         navman_write,
   .read_int_callback =    navman_read_int_callback,
};
 
static struct usb_serial_driver * const serial_drivers[] = {
   &navman_device, NULL
};
 
module_usb_serial_driver(serial_drivers, id_table);
 
MODULE_LICENSE("GPL v2");