Blame view

kernel/linux-imx6_3.14.28/drivers/usb/serial/navman.c 2.82 KB
6b13f685e   김민수   BSP 최초 추가
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
116
117
118
119
120
121
122
123
  /*
   * Navman Serial USB driver
   *
   * Copyright (C) 2006 Greg Kroah-Hartman <gregkh@suse.de>
   *
   *	This program is free software; you can redistribute it and/or
   *	modify it under the terms of the GNU General Public License
   *	version 2 as published by the Free Software Foundation.
   *
   * 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
  ",
  			__func__, status);
  		return;
  	default:
  		dev_dbg(&port->dev, "%s - nonzero urb status received: %d
  ",
  			__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
  ",
  			__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
  ",
  			__func__);
  		result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
  		if (result)
  			dev_err(&port->dev,
  				"%s - failed submitting interrupt urb, error %d
  ",
  				__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");